Bayesian Binary Sensor#8810
Conversation
|
Hi @jlmcgehee21, It seems you haven't yet signed a CLA. Please do so here. Once you do that we will be able to review and accept this pull request. Thanks! |
There was a problem hiding this comment.
closing bracket does not match visual indentation
There was a problem hiding this comment.
continuation line under-indented for visual indent
There was a problem hiding this comment.
continuation line under-indented for visual indent
There was a problem hiding this comment.
continuation line under-indented for visual indent
There was a problem hiding this comment.
'homeassistant.const.CONF_ENTITY_ID' imported but unused
'homeassistant.const.CONF_TYPE' imported but unused
'homeassistant.const.ATTR_ENTITY_ID' imported but unused
Why: * It would be beneficial to leverage various sensor outputs in a Bayesian manner in order to sense more complex events. This change addresses the need by: * `BayesianBinarySensor` class in `./homeassistant/components/binary_sensor/bayesian.py` * Tests in `./tests/components/binary_sensor/test_bayesian.py` Caveats: This is my first time in this code-base. I did try to follow conventions that I was able to find, but I'm sure there will be some issues to straighten out.
There was a problem hiding this comment.
'homeassistant.const.ATTR_UNIT_OF_MEASUREMENT' imported but unused
'homeassistant.const.TEMP_CELSIUS' imported but unused
There was a problem hiding this comment.
'homeassistant.const.ATTR_UNIT_OF_MEASUREMENT' imported but unused
'homeassistant.const.TEMP_CELSIUS' imported but unused
|
Was running tests locally with I probably will need some pointers regarding whatever side effects I may be causing when running the full test suite. |
|
Love it....will be great for presence detection as well. |
|
This will be fantastic to try to infer when my apartment should go into night/sleep mode! |
| import homeassistant.helpers.config_validation as cv | ||
| from homeassistant.components.binary_sensor import (BinarySensorDevice, | ||
| PLATFORM_SCHEMA) | ||
| from homeassistant.const import (CONF_NAME, STATE_UNKNOWN, CONF_SENSOR_CLASS, |
There was a problem hiding this comment.
CONF_SENSOR_CLASS does not exists in homeassistant.const anymore
| else: | ||
| self.current_obs.pop(entity, None) | ||
|
|
||
| def __update_probability(self, prior, observation): |
There was a problem hiding this comment.
You are not using self inside the function, so the function could be extracted from the class.
We normally use only one _ in the beginning of the function name.
There was a problem hiding this comment.
Oops, was updating self.probability before a refactor. Changed to a @staticmethod to keep the namespace of the class (my usual approach), if this is not preferred, I can move outside.
This change addresses the need by: * Removing `CONF_SENSOR_CLASS` and its usage in `get_deprecated`. * Make probability update function a static method, and use single `_` to match project conventions.
| observations = config.get(CONF_OBSERVATIONS) | ||
| prior = config.get(CONF_PRIOR) | ||
| probability_threshold = config.get(CONF_PROBABILITY_THRESHOLD) | ||
| device_class = CONF_DEVICE_CLASS |
There was a problem hiding this comment.
Should this be config.get(CONF_DEVICE_CLASS) ?
|
@Danielhiversen, once I add docs in home-assistant.github.io, will this make the next release? |
MartinHjelmare
left a comment
There was a problem hiding this comment.
Cool! Some comments below.
| BayesianBinarySensor(hass, name, prior, observations, | ||
| probability_threshold, device_class) | ||
| ], True) | ||
| return True |
There was a problem hiding this comment.
setup_platform shouldn't return anything.
| vol.Optional(CONF_NAME, default=DEFAULT_NAME): | ||
| cv.string, | ||
| vol.Required(CONF_OBSERVATIONS): | ||
| vol.Schema([dict]), |
There was a problem hiding this comment.
You could add cv.ensure_list. Something like:
vol.Schema(vol.All(cv.ensure_list, [dict])),It seems the only platforms that are supported are state and numeric_state. Shouldn't we try to check that the user configures the correct platforms? Right now a bad platform will cause an uncaught error.
|
|
||
| for obs in self._observations: | ||
| entity_id = obs['entity_id'] | ||
| async_track_state_change(hass, entity_id, |
There was a problem hiding this comment.
Do this in the method async_added_to_hass which will be called when the entity is added to home assistant.
| class BayesianBinarySensor(BinarySensorDevice): | ||
| """Representation of a Bayesian sensor.""" | ||
|
|
||
| def __init__(self, hass, name, prior, observations, probability_threshold, |
There was a problem hiding this comment.
Don't pass in hass. It will be set on the entity when it has been added to home assistant.
| entity_observation.get('below'), | ||
| entity_observation.get('above'), None, | ||
| entity_observation): | ||
|
|
|
|
||
| @asyncio.coroutine | ||
| def async_update(self): | ||
| """Get the latest data and updates the states.""" |
There was a problem hiding this comment.
Write all the verbs in imperative mood: "Get... update..."
| Use Bayesian Inference to trigger a binary sensor. | ||
|
|
||
| For more details about this platform, please refer to the documentation at | ||
| https://home-assistant.io/components/sensor.bayesian_binary/ |
There was a problem hiding this comment.
https://home-assistant.io/components/binary_sensor.bayesian/
|
|
||
| prior = self.prior | ||
| for obs in self.current_obs.values(): | ||
| prior = self._update_probability(obs, prior) |
There was a problem hiding this comment.
The signature of the _update_probability method has the parameters in the reverse order of this call. Is this deliberate? I'm not very familiar with the Bayesian theory in application.
There was a problem hiding this comment.
Good catch! It actually didn't matter (and hence didn't fail my tests) because I was treating the scenario a bit naively (P(Event|False) = 1 - P(Event|True)). I thought this would be a decent first shot, but after some reflection, I preferred to allow the user to specify P(Event|False) and default to the above case if they do not.
| observations = config.get(CONF_OBSERVATIONS) | ||
| prior = config.get(CONF_PRIOR) | ||
| probability_threshold = config.get(CONF_PROBABILITY_THRESHOLD) | ||
| device_class = config.get(CONF_DEVICE_CLASS) |
There was a problem hiding this comment.
CONF_DEVICE_CLASS isn't part of your config schema.
There was a problem hiding this comment.
'homeassistant.const.CONF_STATE' imported but unused
| async_track_state_change(self.hass, entity_id, | ||
| async_threshold_sensor_state_listener) | ||
|
|
||
| def _update_current_obs(self, entity_observation, should_trigger): |
There was a problem hiding this comment.
add a function documentation. Add decorator "@callback" if they need run inside async loop or add "Async friendly" to function documentation if that dosn't matters.
There was a problem hiding this comment.
I basically adapted the binary.threshold sensor and its test for this implementation, and it seems the test is made to run in what looks like a full hass environment. With this in mind, I would guess that the @callback decorator is not needed because my tests are passing? If this is true, then appropriate solution would be to add "Async friendly" to the docstring, correct?
As a side note, the pylintrc and the travis tests both designate docstrings are only needed for public methods. For ease of contribution, would it be appropriate to include modification of these files as part of my PR in order for linting to fail if these methods have no documentation?
I appreciate the feedback, and hope to address it the best way possible.
There was a problem hiding this comment.
Good point. I make a PR to remove that from pylintrc. This small info about that function is in every case helpfull.
Yeah, the function can run async/sync. So but "Async friendly" to this function like https://github.com/home-assistant/home-assistant/blob/c56f99baafac33483dd13699993d7da4ee5d7efd/homeassistant/helpers/location.py#L11-L14.
That help to prevent on future change on that platform.
A async/sync problem is only visible on real world and not every time inside tests. It is very hard to find a problem like this.
There was a problem hiding this comment.
👍 thanks for the clarification.
| else: | ||
| self.current_obs.pop(entity, None) | ||
|
|
||
| def _process_numeric_state(self, entity_observation): |
There was a problem hiding this comment.
add a function documentation. Add decorator "@callback" if they need run inside async loop or add "Async friendly" to function documentation if that dosn't matters.
|
|
||
| self._update_current_obs(entity_observation, should_trigger) | ||
|
|
||
| def _process_state(self, entity_observation): |
There was a problem hiding this comment.
add a function documentation. Add decorator "@callback" if they need run inside async loop or add "Async friendly" to function documentation if that dosn't matters.
|
@Danielhiversen @MartinHjelmare @pvizeli hopefully I have addressed all comments/concerns. I have also added documentation, and linked to the PR in the description for this PR. Unfortunately, it seems I missed the |
|
Retrigger travis API |
|
Will this make into 0.53? |
|
Yes. |
* upstream/dev: (113 commits) Fix fitbit error when trying to access token after upgrade. (home-assistant#9183) Upgrade sendgrid to 5.0.1 (home-assistant#9215) Upgrade pyasn1 to 0.3.3 and pyasn1-modules to 0.1.1 (home-assistant#9216) directv: extended discovery via REST api, bug fix (home-assistant#8800) Bayesian Binary Sensor (home-assistant#8810) Add cloud auth support (home-assistant#9208) Abode push events and lock, cover, and switch components (home-assistant#9095) Lint Sonarr tests Upgrade pymysensors to 0.11.1 (home-assistant#9212) Refactor rfxtrx (home-assistant#9117) Issue home-assistant#6893 in rfxtrx (home-assistant#9130) Support for season sensor (home-assistant#8958) Add counter component (home-assistant#9146) Fix and optimize digitalloggers platform (home-assistant#9203) Prevent error when no forecast data was available (home-assistant#9176) Add "status" to Sonarr sensor (home-assistant#9204) fix worldtidesinfo home-assistant#9184 (home-assistant#9201) Update pushbullet.py (home-assistant#9200) Fix dht22 when no data was read initially home-assistant#8976 (home-assistant#9198) Prevent iCloud exceptions in logfile (home-assistant#9179) ...
Description:
Why:
Bayesian manner in order to sense more complex events.
This change addresses the need by:
BayesianBinarySensorclass in./homeassistant/components/binary_sensor/bayesian.py./tests/components/binary_sensor/test_bayesian.pyCaveats:
This is my first time in this code-base. I did try to follow conventions
that I was able to find, but I'm sure there will be some issues to
straighten out.
Example entry for
configuration.yaml(if applicable):Checklist:
If user exposed functionality or configuration variables are added/changed:
If the code does not interact with devices:
toxrun successfully. Your PR cannot be merged unless tests pass