Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #50 from nick2k3/master
Browse files Browse the repository at this point in the history
Add motion detection setting capabilities
  • Loading branch information
fwestenberg authored Jul 12, 2020
2 parents 6afbb39 + 211c927 commit 1b4494d
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 1 deletion.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@ switch:
{% else %}
mdi:flashlight-off
{% endif %}
camera_frontdoor_motion_detection:
value_template: "{{ is_state_attr('camera.frontdoor', 'motion_detection_enabled', true) }}"
turn_on:
service: camera.enable_motion_detection
data:
entity_id: camera.frontdoor
turn_off:
service: camera.disable_motion_detection
data:
entity_id: camera.frontdoor
icon_template: >-
{% if is_state_attr('camera.frontdoor', 'motion_detection_enabled', true) %}
mdi:motion-sensor
{% else %}
mdi:motion-sensor-off
{% endif %}
```
2. Restart Home Assistant.
Expand All @@ -148,6 +165,7 @@ entities:
- switch.camera_frontdoor_ir_lights
- switch.camera_frontdoor_email
- switch.camera_frontdoor_ftp
- switch.camera_frontdoor_motion_detection
- binary_sensor.motion_frontdoor
```
Expand Down
45 changes: 44 additions & 1 deletion custom_components/reolink_dev/ReolinkPyPi/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def __init__(self, ip, channel):
self._rtspport = None
self._rtmpport = None
self._ptzpresets = dict()
self._motion_detection_state = None

def session_active(self):
return self._token is not None
Expand All @@ -41,7 +42,11 @@ async def get_settings(self):
{"cmd": "GetEmail", "action": 1, "param": param_channel},
{"cmd": "GetIrLights", "action": 1, "param": param_channel},
{"cmd": "GetRec", "action": 1, "param": param_channel},
{"cmd": "GetPtzPreset", "action": 1, "param": param_channel}]
{"cmd": "GetPtzPreset", "action": 1, "param": param_channel},
{"cmd": "GetAlarm","action":1,"param":{"Alarm":{"channel": self._channel ,"type":"md"}}}]
# the call must be like this:
#[{"cmd":"GetAlarm","action":1,"param":{"Alarm":{"channel":0,"type":"md"}}}]
#so we cannot use param_channel

param = {"token": self._token}
response = await self.send(body, param)
Expand Down Expand Up @@ -101,6 +106,14 @@ async def get_settings(self):
_LOGGER.debug(f"Got preset {preset_name} with ID {preset_id}")
else:
_LOGGER.debug(f"Preset is not enabled: {preset}")

elif data["cmd"] == "GetAlarm":
self._motion_detection_settings = data
self._pippo = data
if (data["value"]["Alarm"]["enable"] == 1):
self._motion_detection_state = True
else:
self._motion_detection_state = False
except:
continue

Expand Down Expand Up @@ -181,6 +194,11 @@ def last_motion(self):
def ptzpresets(self):
return self._ptzpresets

@property
def motion_detection_state(self):
"""Camera motion detection setting status."""
return self._motion_detection_state

async def login(self, username, password):
body = [{"cmd": "Login", "action": 0, "param": {"User": {"userName": username, "password": password}}}]
param = {"cmd": "Login", "token": "null"}
Expand Down Expand Up @@ -312,6 +330,31 @@ async def set_recording(self, enabled):
_LOGGER.error(f"Error translating Recording response to json")
return False

async def set_motion_detection(self, enabled):
await self.get_settings()

if not self._motion_detection_settings:
_LOGGER.error("Error while fetching current motion detection settings")
return

if enabled == True:
newValue = 1
else:
newValue = 0

body = [{"cmd":"SetAlarm","action":0,"param": self._motion_detection_settings["value"] }]
body[0]["param"]["Alarm"]["enable"] = newValue
response = await self.send(body, {"cmd": "SetAlarm", "token": self._token} )
try:
json_data = json.loads(response)
if json_data[0]["value"]["rspCode"] == 200:
return True
else:
return False
except:
_LOGGER.error(f"Error translating Recording response to json")
return False

async def send(self, body, param, stream=False):
if (self._token is None and
(body is None or body[0]["cmd"] != "Login")):
Expand Down
41 changes: 41 additions & 0 deletions custom_components/reolink_dev/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
SERVICE_DISABLE_IR_LIGHTS = 'disable_ir_lights'
SERVICE_ENABLE_RECORDING = 'enable_recording'
SERVICE_DISABLE_RECORDING = 'disable_recording'
SERVICE_ENABLE_MOTION_DETECTION = 'enable_motion_detection'
SERVICE_DISABLE_MOTION_DETECTION = 'disable_motion_detection'

DEFAULT_BRAND = 'Reolink'
DOMAIN_DATA = 'reolink_devices'
Expand Down Expand Up @@ -141,6 +143,25 @@ def handler_disable_recording(call):
entity.disable_recording()
hass.services.async_register(DOMAIN, SERVICE_DISABLE_RECORDING, handler_disable_recording)

# Event enable motion detection
def handler_enable_motion_detection(call):
component = hass.data.get(DOMAIN)
entity = component.get_entity(call.data.get(ATTR_ENTITY_ID))

if entity:
entity.enable_motion_detection()
hass.services.async_register(DOMAIN, SERVICE_ENABLE_RECORDING, handler_enable_motion_detection)

# Event disable recording
def handler_disable_motion_detection(call):
component = hass.data.get(DOMAIN)
entity = component.get_entity(call.data.get(ATTR_ENTITY_ID))

if entity:
entity.disable_motion_detection()
hass.services.async_register(DOMAIN, SERVICE_DISABLE_RECORDING, handler_disable_motion_detection)


class ReolinkCamera(Camera):
"""An implementation of a Reolink IP camera."""

Expand All @@ -167,6 +188,7 @@ def __init__(self, hass, session, host, username, password, stream, protocol, ch
self._ir_state = None
self._recording_state = None
self._ptzpresets = dict()
self._motion_detection_state = None
self._state = STATE_IDLE

self._hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, self.disconnect)
Expand All @@ -187,6 +209,7 @@ def state_attributes(self):
attrs["ir_lights_enabled"] = self._ir_state
attrs["recording_enabled"] = self._recording_state
attrs["ptzpresets"] = self._ptzpresets
attrs["motion_detection_enabled"] = self._motion_detection_state

return attrs

Expand Down Expand Up @@ -230,6 +253,11 @@ def ptzpresets(self):
"""Camera PTZ presets list."""
return self._ptzpresets

@property
def motion_detection_state(self):
"""Camera motion detection setting status."""
return self._motion_detection_state

async def stream_source(self):
"""Return the source of the stream."""
if self._protocol == "rtsp":
Expand Down Expand Up @@ -314,6 +342,18 @@ def disable_recording(self):
self._recording_state = False
self._hass.states.set(self.entity_id, self.state, self.state_attributes)

def enable_motion_detection(self):
"""Enable motion_detecion."""
if asyncio.run_coroutine_threadsafe(self._reolinkSession.set_motion_detection(True), self.hass.loop).result():
self._motion_detection_state = True
self._hass.states.set(self.entity_id, self.state, self.state_attributes)

def disable_motion_detection(self):
"""Disable motion detecion."""
if asyncio.run_coroutine_threadsafe(self._reolinkSession.set_motion_detection(False), self.hass.loop).result():
self._motion_detection_state = False
self._hass.states.set(self.entity_id, self.state, self.state_attributes)

async def update_motion_state(self):
await self._reolinkSession.get_motion_state()

Expand All @@ -332,6 +372,7 @@ async def update_status(self):
self._ir_state = self._reolinkSession.ir_state
self._recording_state = self._reolinkSession.recording_state
self._ptzpresets = self._reolinkSession.ptzpresets
self._motion_detection_state = self._reolinkSession.motion_detection_state

async def async_update(self):
"""Update the data from the camera."""
Expand Down
14 changes: 14 additions & 0 deletions custom_components/reolink_dev/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,17 @@ disable_recording:
entity_id:
description: Name of the Reolink camera entity to set.
example: 'camera.frontdoor'

enable_motion_detection:
description: Enable the motion detection of the Reolink camera.
fields:
entity_id:
description: Name of the Reolink camera entity to set.
example: 'camera.frontdoor'

disable_motion_detection:
description: Disable the motion detection of the Reolink camera.
fields:
entity_id:
description: Name of the Reolink camera entity to set.
example: 'camera.frontdoor'

0 comments on commit 1b4494d

Please sign in to comment.