diff --git a/README.md b/README.md index 14d2c3f..d8cdb5e 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ ## How to install 1. Clone repository into $HASS_HOME/custom_components/iq_notify. -2. Restart Home Assistant -3. Update your configuration.yaml - example below +2. Restart Home Assistant. +3. Update your configuration.yaml - example below. The contents of this repository should be in a directory named `iq_notify` inside `custom_components` of your Home Assistant. @@ -12,13 +12,14 @@ Therefore you must have access to your Home Assistant files, no Add-on avilable. ## How can you notify? -* Notify only people present at home. (`only_home`) -* Notify only people away from home. (`only_away`) -* Notify people that just arrived home. (`just_arrived`) -* Notify people that just left home. (`just_left`) -* Notify people that are present at home for particular time. (`staying_home`) -* Notify people that are away from home for particular time. (`staying_away`) -* Try to notify people at home, but if none – notify people away. (`only_home_then_away`) +- Notify only people present at home. (`only_home`) +- Notify only people away from home. (`only_away`) +- Notify people that just arrived home. (`just_arrived`) +- Notify people that just left home. (`just_left`) +- Notify people that are present at home for particular time. (`staying_home`) +- Notify people that are away from home for particular time. (`staying_away`) +- Try to notify people at home, but if none – notify people away. (`only_home_then_away`) +- Try to notify people that just left home, but if none – notify people away. (`just_left_then_away`) ## Configuration reference @@ -29,9 +30,9 @@ notify: time: 2 # time offset in which we assume someone "just left/arrived" or "is staying" pairs: # a list of presence entities are corresponding notify services - entity: binary_sensor.presence_person1 # presence entity id #1 - service: person1_iphone # notify service to use for above entity, without domain (notify.) - - entity: device_tracker.person2 # presence entity id #2 - service: person2_phone # notify service to use for above entity, without domain (notify.) + service: person1_iphone # notify service to use for above entity, without domain (notify.) + - entity: device_tracker.person2 # presence entity id #2 + service: person2_phone # notify service to use for above entity, without domain (notify.) ``` > `time` (defaults to 2) @@ -41,7 +42,7 @@ notify: > `entity` (required) > > ID of any entity that state for "present" is `on` or `home` and `off` or `not_home` for "away". -> Can be `input_boolean`, `binary_sensor `, `group`, `switch`, `device_tracker` etc. +> Can be `input_boolean`, `binary_sensor`, `group`, `switch`, `device_tracker` etc. > `service` (required) > @@ -52,15 +53,15 @@ notify: ##### Send notification only to people that are present at home. ```yaml -- alias: 'Notify: on garbage disposal' +- alias: "Notify: on garbage disposal" trigger: platform: state entity_id: calendar.garbage_disposal - to: 'on' + to: "on" condition: condition: state entity_id: binary_sensor.people_present - state: 'on' + state: "on" action: - service: notify.iphones data: @@ -76,28 +77,27 @@ If there is someone present – notify people that are present that today is the ```yaml automation: - -- alias: 'Alarm: arm away when everyone left' - trigger: - platform: state - entity_id: binary_sensor.people_present - to: 'off' - action: - - service: alarm_control_panel.alarm_arm_away - entity_id: alarm_control_panel.alarm - -- alias: 'Alarm: send notification on arming' - trigger: - - platform: state - entity_id: alarm_control_panel.alarm - to: 'armed_away' - action: - - service: notify.iphones - data: - title: Alarm - message: Alarm has been armed. + - alias: "Alarm: arm away when everyone left" + trigger: + platform: state + entity_id: binary_sensor.people_present + to: "off" + action: + - service: alarm_control_panel.alarm_arm_away + entity_id: alarm_control_panel.alarm + + - alias: "Alarm: send notification on arming" + trigger: + - platform: state + entity_id: alarm_control_panel.alarm + to: "armed_away" + action: + - service: notify.iphones data: - mode: just_left + title: Alarm + message: Alarm has been armed. + data: + mode: just_left ``` First automation tracks if everyone left home. If so – arms the alarm. After alarm is armed – second notification notifies only the person who "just left" that the alarm was armed successfully. The last person is responsible for arming the alarm. @@ -106,20 +106,19 @@ First automation tracks if everyone left home. If so – arms the alarm. After a ```yaml automation: - -- alias: 'Door: remind on garage door kept opened' - trigger: - platform: state - entity_id: binary_sensor.garage_door_contact - to: 'on' - for: '00:05:00' - action: - - service: notify.iphones - data: - title: Garage door - message: Garage door kept opened for 5mins. + - alias: "Door: remind on garage door kept opened" + trigger: + platform: state + entity_id: binary_sensor.garage_door_contact + to: "on" + for: "00:05:00" + action: + - service: notify.iphones data: - mode: only_home_then_away + title: Garage door + message: Garage door kept opened for 5mins. + data: + mode: only_home_then_away ``` -Will let know inmates that are home about the door that are not closed, but should be. They are home so they can close it. Otherwise if no one is home – let everyone know, because it might be a security breach. +Will let users that are home know about the door that is left open. If no one is home, let everyone know (because it might be a security breach). diff --git a/notify.py b/notify.py index be5f456..6f173fa 100644 --- a/notify.py +++ b/notify.py @@ -21,16 +21,35 @@ CONF_TIME = 'time' CONF_MODE = 'mode' -DEFAULT_TIME = 2 # minutes +DEFAULT_TIME = 2 # minutes + +# send notification to all, default +MODE_ALL = 'all' + +# send notification to only present users +MODE_ONLY_HOME = 'only_home' + +# send notification to only away users +MODE_ONLY_AWAY = 'only_away' + +# send notification to users that arrived in last CONF_TIME +MODE_JUST_ARRIVED = 'just_arrived' + +# send notification to users that left in last CONF_TIME +MODE_JUST_LEFT = 'just_left' + +# send notification to present users that are present for at least CONF_TIME +MODE_STAYING_HOME = 'staying_home' + +# send notification to away users that are away for at least CONF_TIME +MODE_STAYING_AWAY = 'staying_away' + +# try to send notification to present but if no one present - send to away users +MODE_ONLY_HOME_THEN_AWAY = 'only_home_then_away' + +# try to send notification to users that left in last CONF_TIME but if that includes no one - send to away users +MODE_JUST_LEFT_THEN_AWAY = 'just_left_then_away' -MODE_ALL = 'all' # send notification to all, default -MODE_ONLY_HOME = 'only_home' # send notification to only present inmates -MODE_ONLY_AWAY = 'only_away' # send notification to only away inmates -MODE_JUST_ARRIVED = 'just_arrived' # send notification to inmates that arrived in last CONF_TIME -MODE_JUST_LEFT = 'just_left' # send notification to inmates that left in last CONF_TIME -MODE_STAYING_HOME = 'staying_home' # send notification to present inmates that are present for at least CONF_TIME -MODE_STAYING_AWAY = 'staying_away' # send notification to away inmates that are away for at least CONF_TIME -MODE_ONLY_HOME_THEN_AWAY = 'only_home_then_away' # try to send notification to present but if no one present - send to away inmates PAIRS_CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_PAIR_ENTITY): cv.string, @@ -42,15 +61,17 @@ vol.Optional(CONF_TIME, default=DEFAULT_TIME): cv.positive_int }) + def get_service(hass, config, discovery_info=None): """Get the notification service.""" - _LOGGER.debug('Setting up iq_notify platform...'); + _LOGGER.debug('Setting up iq_notify platform...') pairs = config[CONF_PAIRS] time = config[CONF_TIME] return IqNotify(pairs, time) + class IqNotify(BaseNotificationService): def __init__(self, pairs, time): @@ -76,16 +97,26 @@ def send_message(self, message="", **kwargs): time = data.get(CONF_TIME) data.pop(CONF_TIME) - _LOGGER.debug('IqNotify: using mode: ' + mode); + _LOGGER.debug('IqNotify: using mode: ' + mode + ' and message: ' + message) - # Check if there's anyone home (for MODE_ONLY_HOME_THEN_AWAY) + looking_since = dt_util.utcnow() - timedelta(minutes=time) + + # Check if anyone is home (for MODE_ONLY_HOME_THEN_AWAY) or just left (for MODE_JUST_LEFT_THEN_AWAY) anyone_home = False + anyone_just_left = False for pair in self._pairs: entity = pair.get(CONF_PAIR_ENTITY) if entity in self.hass.states._states: - cur_state = self.hass.states.get(entity).state + state = self.hass.states.get(entity) + cur_state = state.state + state_since = state.last_changed + + if cur_state == STATE_ON or cur_state == STATE_HOME: anyone_home = True + elif looking_since < state_since: + anyone_just_left = True + service_data = kwargs # Append message @@ -95,7 +126,6 @@ def send_message(self, message="", **kwargs): print(service_data) - looking_since = dt_util.utcnow() - timedelta(minutes=time) # Check and notify each entity for pair in self._pairs: @@ -106,34 +136,53 @@ def send_message(self, message="", **kwargs): state = self.hass.states.get(entity) cur_state = state.state state_since = state.last_changed - _LOGGER.debug('Entity: ' + entity + ' current state: ' + str(cur_state) + ' since: ' + str(state_since)) - + + if cur_state == STATE_ON or cur_state == STATE_HOME: + user_is_home = True + else: + user_is_home = False + notify = False - + if mode == MODE_ALL: notify = True - elif mode == MODE_ONLY_HOME and (cur_state == STATE_ON or cur_state == STATE_HOME): + elif mode == MODE_ONLY_HOME and user_is_home: notify = True - elif mode == MODE_ONLY_AWAY and (cur_state == STATE_OFF or cur_state == STATE_NOT_HOME): + elif mode == MODE_ONLY_AWAY and not user_is_home: notify = True - elif mode == MODE_JUST_ARRIVED and (cur_state == STATE_ON or cur_state == STATE_HOME): + elif mode == MODE_JUST_ARRIVED and user_is_home: if looking_since < state_since: notify = True - elif mode == MODE_JUST_LEFT and (cur_state == STATE_OFF or cur_state == STATE_NOT_HOME): + elif mode == MODE_JUST_LEFT and not user_is_home: if looking_since < state_since: notify = True - elif mode == MODE_STAYING_HOME and (cur_state == STATE_ON or cur_state == STATE_HOME): + elif mode == MODE_STAYING_HOME and user_is_home: if looking_since > state_since: notify = True - elif mode == MODE_STAYING_AWAY and (cur_state == STATE_OFF or cur_state == STATE_NOT_HOME): + elif mode == MODE_STAYING_AWAY and not user_is_home: if looking_since > state_since: notify = True elif mode == MODE_ONLY_HOME_THEN_AWAY: if not anyone_home: notify = True - elif anyone_home and (cur_state == STATE_ON or cur_state == STATE_HOME): + elif anyone_home and user_is_home: notify = True + elif mode == MODE_JUST_LEFT_THEN_AWAY: + if not user_is_home: + if not anyone_just_left: + notify = True + elif anyone_just_left: + if looking_since < state_since: + notify = True + + _LOGGER.debug('\nentity: ' + entity) + _LOGGER.debug('cur_state: ' + str(cur_state)) + _LOGGER.debug('looking_since: ' + str(looking_since)) + _LOGGER.debug('state_since: ' + str(state_since)) + _LOGGER.debug('looking_since < state_since: ' + str(looking_since < state_since)) + _LOGGER.debug('user_is_home: ' + str(user_is_home)) + _LOGGER.debug('anyone_just_left: ' + str(anyone_just_left)) if notify: self.hass.services.call('notify', service, service_data) - _LOGGER.info('Notifying notify.' + service + ' via ' + mode + ' mode'); + _LOGGER.info('Notifying notify.' + service + ' via ' + mode + ' mode' + '\n');