支持的功能:
- 支持光照度条件, 环境光足够亮就不开灯, 例如阳台灯
- 支持多个 sensor 共同触发, 例如卫生间可以放两个人体传感器, 玄关可以放一个门窗传感器+人体传感器
- 支持只关不开(厕所排气扇场景)或者只开不关(不知道为啥要这样, 你想到了告诉我)
- 支持延时关闭, 根据自身情况设定, 规避人体传感器不灵敏的问题
这个功能不适合经常有人呆着的地方, 比如书房, 卧室, 客厅.
| hallway_motion_lights: | |
| module: motion_lights | |
| class: MotionLights | |
| sensor_list: | |
| - binary_sensor.door_window_sensor_158d0001191793 | |
| - binary_sensor.motion_sensor_158d0001296340 | |
| entity_on: group.hallway_lights | |
| entity_off: group.hallway_lights | |
| delay: 5 | |
| inside_restroom_motion_lights: | |
| module: motion_lights | |
| class: MotionLights | |
| sensor_list: | |
| - binary_sensor.motion_sensor_158d0002231dad | |
| - binary_sensor.motion_sensor_158d000224f8df | |
| entity_on: switch.wall_switch_ln_left_158d00022a8a9d | |
| entity_off: switch.wall_switch_ln_left_158d00022a8a9d | |
| illumination_sensor: sensor.illumination_158d000224f8df | |
| illumination_throttle: 300 | |
| delay: 300 | |
| outside_restroom_motion_lights: | |
| module: motion_lights | |
| class: MotionLights | |
| sensor_list: | |
| - binary_sensor.motion_sensor_158d000211a0c9 | |
| entity_on: switch.wall_switch_ln_right_158d00022a83d4 | |
| entity_off: switch.wall_switch_ln_right_158d00022a83d4 | |
| delay: 180 | |
| inside_restroom_fan: | |
| module: motion_lights | |
| class: MotionLights | |
| delay: 120 | |
| sensor_list: | |
| - binary_sensor.motion_sensor_158d0002231dad | |
| - binary_sensor.motion_sensor_158d000224f8df | |
| entity_off: switch.wall_switch_ln_right_158d00022a8a9d | |
| outside_restroom_fan: | |
| module: motion_lights | |
| class: MotionLights | |
| delay: 120 | |
| sensor_list: | |
| - binary_sensor.motion_sensor_158d000211a0c9 | |
| entity_off: switch.wall_switch_ln_left_158d00022a83d4 |
| import appdaemon.plugins.hass.hassapi as hass | |
| # | |
| # App to turn lights on when motion detected then off again after a delay | |
| # | |
| # Use with constrints to activate only for the hours of darkness | |
| # | |
| # Args: | |
| # | |
| # sensor_list: binary_sensors to listen on, each sensor turn "on" will action on the switch | |
| # entity_on : entity to turn on when any sensor of sensor_list turned on, can be a light, script, scene or anything else that can be turned on | |
| # entity_off : entity to turn off when all sensor of sensor_list turned off , can be a light, script, scene or anything else that can be turned off | |
| # delay: amount of time after turning on to turn off again. If not specified defaults to 60 seconds. | |
| # illumination_sensor: illumination sensor to depends on | |
| # illumination_throttle: turn on switch if illumination_sensor state is below this config value, default is 500 | |
| # | |
| # Release Notes | |
| # | |
| # Version 1.1: | |
| # Add ability for other apps to cancel the timer | |
| # | |
| # Version 1.0: | |
| # Initial Version | |
| class MotionLights(hass.Hass): | |
| def initialize(self): | |
| self.handle = None | |
| # Subscribe to sensors | |
| for _sensor in self.args['sensor_list']: | |
| self.listen_state(self.state_cb_sensor, _sensor) | |
| if self.entity_off: | |
| self.listen_state(self.state_cb_count_down_when_on, | |
| self.entity_off) | |
| self._start_turn_off_timer() | |
| def state_cb_sensor(self, entity, attribute, old, new, kwargs): | |
| if new == 'on': | |
| if not self.can_turn_entity_on: | |
| return | |
| self.log("turn on entity %s because of sensor %s state %s" % | |
| (self.entity_on, entity, new)) | |
| self.turn_on(self.entity_on) | |
| self._start_turn_off_timer() | |
| if new == "off": | |
| if not self.can_turn_entity_off: | |
| return | |
| self.log("%s turn %s" % (entity, new)) | |
| self._start_turn_off_timer() | |
| @property | |
| def illumination_switch(self): | |
| """光照条件开关 | |
| 配置 illumination_sensor 后启用 | |
| 光照临界值 illumination_throttle 默认 500 | |
| Returns: | |
| Boolean -- True 时可以开灯 | |
| """ | |
| if self.illumination_sensor_state is None: | |
| return True | |
| self.log("illumination state %s, throttle %s" % | |
| (self.illumination_sensor_state, self.illumination_throttle)) | |
| return self.illumination_sensor_state < self.illumination_throttle | |
| @property | |
| def illumination_throttle(self): | |
| """光照阈值, 超过时不满足开灯条件.""" | |
| return float(self.args.get('illumination_throttle', 500)) | |
| @property | |
| def illumination_sensor_state(self): | |
| if 'illumination_sensor' in self.args: | |
| illum_state = self.get_state(self.args['illumination_sensor']) | |
| try: | |
| return float(illum_state) | |
| except ValueError: | |
| return 0 | |
| return None | |
| @property | |
| def delay(self): | |
| if "delay" in self.args: | |
| return self.args['delay'] | |
| elif "delay_entity" in self.args: | |
| return int(self.get_state(self.args["delay_entity"])) | |
| return 30 | |
| def state_cb_count_down_when_on(self, entity, attribute, old, new, kwargs): | |
| if new == "on": | |
| self.log("%s turn %s, start timer" % (entity, new)) | |
| self._start_turn_off_timer() | |
| def _start_turn_off_timer(self): | |
| if not self.entity_off: | |
| return | |
| self.log("start count down %s seconds to turn off %s" % | |
| (self.delay, self.entity_off)) | |
| self.cancel() | |
| self.handle = self.run_in(self._turn_off_entity, self.delay) | |
| self.log("start timer %s" % self.handle) | |
| def _turn_off_entity(self, kwargs): | |
| if self.can_turn_entity_off: | |
| self.log("Turning {} off".format(self.entity_off)) | |
| self.turn_off(self.entity_off) | |
| def _turn_on_entity(self): | |
| if not self.entity_on: | |
| return | |
| if self.can_turn_entity_on: | |
| self.turn_on(self.entity_on) | |
| def cancel(self): | |
| if self.handle is not None: | |
| self.log("cancel timer %s" % self.handle) | |
| self.cancel_timer(self.handle) | |
| self.handle = None | |
| @property | |
| def entity_off(self): | |
| return self.args.get("entity_off") | |
| @property | |
| def entity_on(self): | |
| return self.args.get("entity_on") | |
| @property | |
| def can_turn_entity_off(self): | |
| if not self.entity_off: | |
| return False | |
| if self.get_state(self.entity_off) == "off": | |
| return False | |
| all_sensor_is_off = all([ | |
| self.get_state(entity_id) == "off" | |
| for entity_id in self.args['sensor_list'] | |
| ]) | |
| return all_sensor_is_off | |
| @property | |
| def can_turn_entity_on(self): | |
| if not self.entity_on: | |
| return False | |
| if self.get_state(self.entity_on) == "on": | |
| return False | |
| return self.illumination_switch | |