diff --git a/README.md b/README.md index c55d302..9f26014 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,15 @@ It exposes through device discovery a `service` and a `device` with components f - `homeassistant/device/amcrest-service` - service config - `homeassistant/device/amcrest-[SERIAL_NUMBER]` per camera, with components: -- `event` - most all "other" events, not exposed below -- `camera` - a snapshot is saved every SNAPSHOT_UPDATE_INTERVAL (also based on how often camera saves snapshot image), also an "eventshot" is stored at the time an "event" is triggered in the camera. This is collected by filename, when the Amcrest camera logs a snapshot was saved because of an event (rather than just a routine timed snapshot) -- `doorbell` - doorbell status (if AD110 or AD410) -- `human` - human detection (if AD410) -- `motion` - motion events (if supported) -- `config` - device configuration information -- `storage` - storage stats -- `privacy_mode` - see (and set) the privacy mode of the camere +- `event` - most all "other" events, not exposed below +- `camera` - a snapshot is saved every SNAPSHOT_UPDATE_INTERVAL (also based on how often camera saves snapshot image), also an "eventshot" is stored at the time an "event" is triggered in the camera. This is collected by filename, when the Amcrest camera logs a snapshot was saved because of an event (rather than just a routine timed snapshot) +- `doorbell` - doorbell status (if AD110 or AD410) +- `human` - human detection (if AD410) +- `motion` - motion events (if supported) +- `config` - device configuration information +- `storage` - storage stats +- `privacy_mode` - get (and set) the privacy mode switch of the camera +- `motion_detection` - get (and set) the motion detection switch of the camera ## Snapshots/Eventshots plus Home Assistant Area Cards diff --git a/VERSION b/VERSION index a9d1caa..1c21be8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.99.23 +0.99.24 diff --git a/amcrest_api.py b/amcrest_api.py index e04454e..e4729a3 100644 --- a/amcrest_api.py +++ b/amcrest_api.py @@ -139,7 +139,7 @@ class AmcrestAPI(object): return privacy_mode except CommError as err: - self.logger.error(f'Failed to communicate with device ({device_id}) for privacy mode') + self.logger.error(f'Failed to communicate with device ({device_id}) to get privacy mode') def set_privacy_mode(self, device_id, switch): device = self.devices[device_id] @@ -147,7 +147,27 @@ class AmcrestAPI(object): try: return device["camera"].set_privacy(switch).strip() except CommError as err: - self.logger.error(f'Failed to communicate with device ({device_id})') + self.logger.error(f'Failed to communicate with device ({device_id}) to set privacy mode') + + # Motion detection config --------------------------------------------------------------------- + + def get_motion_detection(self, device_id): + device = self.devices[device_id] + + try: + motion_detection = device["camera"].is_motion_detector_on() + + return motion_detection + except CommError as err: + self.logger.error(f'Failed to communicate with device ({device_id}) to get motion detection') + + def set_motion_detection(self, device_id, switch): + device = self.devices[device_id] + + try: + return device["camera"].set_motion_detection(switch) + except CommError as err: + self.logger.error(f'Failed to communicate with device ({device_id}) to set motion detections') # Snapshots ----------------------------------------------------------------------------------- @@ -166,7 +186,7 @@ class AmcrestAPI(object): else: self.logger.info(f'Skipped snapshot from ({device_id}) because "privacy mode" is ON') except CommError as err: - self.logger.error(f'Failed to communicate with device ({device_id})') + self.logger.error(f'Failed to communicate with device ({device_id}) to get snapshot') def get_snapshot(self, device_id): return self.devices[device_id]['snapshot'] if 'snapshot' in self.devices[device_id] else None diff --git a/amcrest_mqtt.py b/amcrest_mqtt.py index c4a6458..182022e 100644 --- a/amcrest_mqtt.py +++ b/amcrest_mqtt.py @@ -481,6 +481,19 @@ class AmcrestMqtt(object): } device_states['privacy_mode'] = None + components[self.get_slug(device_id, 'motion_detection')] = { + 'name': 'Motion detection', + 'platform': 'switch', + 'payload_on': 'on', + 'payload_off': 'off', + 'device_class': 'switch', + 'icon': 'mdi:motion-sensor', + 'state_topic': self.get_discovery_topic(device_id, 'motion_detection'), + 'command_topic': self.get_command_topic(device_id, 'motion_detection'), + 'unique_id': self.get_slug(device_id, 'motion_detection'), + } + device_states['motion_detection'] = None + components[self.get_slug(device_id, 'motion')] = { 'name': 'Motion', 'platform': 'binary_sensor', @@ -576,7 +589,7 @@ class AmcrestMqtt(object): device_states = self.states[device_id] device_states['state']['last_update'] = str(datetime.now(ZoneInfo(self.timezone))) - for topic in ['state','storage','motion','human','doorbell','event','recording','privacy_mode']: + for topic in ['state','storage','motion','human','doorbell','event','recording','privacy_mode','motion_detection']: if topic in device_states: payload = json.dumps(device_states[topic]) if isinstance(device_states[topic], dict) else device_states[topic] self.mqttc.publish(self.get_discovery_topic(device_id, topic), payload, qos=self.mqtt_config['qos'], retain=True) @@ -601,18 +614,22 @@ class AmcrestMqtt(object): if not self.running: break device_states = self.states[device_id] - # update the privacy mode setting + # update the privacy mode switch # we don't need to verify this often since events should let us know privacy_mode = self.amcrestc.get_privacy_mode(device_id) if privacy_mode is not None: device_states['privacy_mode'] = 'on' if privacy_mode == True else 'off' + # update the motion detection switch + motion_detection = self.amcrestc.get_motion_detection(device_id) + device_states['motion_detection'] = 'on' if motion_detection == True else 'off' + storage = self.amcrestc.get_storage_stats(device_id) if storage is not None: device_states['storage'] = storage - self.publish_service_state() - self.publish_device_state(device_id) + self.publish_service_state() + self.publish_device_state(device_id) def refresh_snapshot_all_devices(self): self.logger.info(f'Collecting snapshots for all devices (every {self.snapshot_update_interval} sec)') @@ -675,6 +692,18 @@ class AmcrestMqtt(object): self.publish_device_state(device_id) else: self.logger.error(f'Setting PRIVACY_MODE failed: {repr(response)}') + elif 'motion_detection' in data: + set_motion_detection_to = False if data['motion_detection'] == 'off' else True + self.logger.info(f'Setting MOTION_DETECTION to {set_motion_detection_to} for {self.get_device_name(device_id)}') + + response = self.amcrestc.set_motion_detection(device_id, set_motion_detection_to) + + # if Amcrest device was good with that command, lets update state and then MQTT + if response == True: + device_states['motion_detection'] = data['motion_detection'] + self.publish_device_state(device_id) + else: + self.logger.error(f'Setting MOTION_DETECTION failed: {repr(response)}') else: self.logger.error(f'We got a command ({data}), but do not know what to do')