Skip to content

Commit

Permalink
Add a switch to enable/disable SmartMotionDetection
Browse files Browse the repository at this point in the history
  • Loading branch information
rroller committed Dec 26, 2021
1 parent 637eb8e commit 934341e
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 19 deletions.
37 changes: 22 additions & 15 deletions custom_components/dahua/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def __init__(self, hass: HomeAssistant, events: list, address: str, port: int, r
self.events: list = events
self._supports_coaxial_control = False
self._supports_disarming_linkage = False
self._supports_smart_motion_detection = False
self._serial_number: str
self._profile_mode = "0"
self._supports_profile_mode = False
Expand Down Expand Up @@ -216,6 +217,12 @@ async def _async_update_data(self):
except ClientError:
self._supports_disarming_linkage = False

try:
await self.client.async_get_smart_motion_detection()
self._supports_smart_motion_detection = True
except ClientError:
self._supports_smart_motion_detection = False

is_doorbell = self.is_doorbell()

if not is_doorbell:
Expand Down Expand Up @@ -260,6 +267,8 @@ async def _async_update_data(self):
coros.append(asyncio.ensure_future(self.client.async_get_disarming_linkage()))
if self._supports_coaxial_control:
coros.append(asyncio.ensure_future(self.client.async_get_coaxial_control_io_status()))
if self._supports_smart_motion_detection:
coros.append(asyncio.ensure_future(self.client.async_get_smart_motion_detection()))

# Gather results and update the data map
results = await asyncio.gather(*coros)
Expand Down Expand Up @@ -473,16 +482,12 @@ def supports_security_light(self) -> bool:
return "-AS-PV" in self.model or self.model == "AD410"

def is_doorbell(self) -> bool:
"""
Returns true if this is a doorbell (VTO)
"""
""" Returns true if this is a doorbell (VTO) """
m = self.model.upper()
return m.startswith("VTO") or m.startswith("DHI") or self.is_amcrest_doorbell()

def is_amcrest_doorbell(self) -> bool:
"""
Returns true if this is an Amcrest doorbell
"""
""" Returns true if this is an Amcrest doorbell """
return self.model.upper().startswith("AD")

def supports_infrared_light(self) -> bool:
Expand All @@ -500,21 +505,19 @@ def supports_illuminator(self) -> bool:
return not self.is_amcrest_doorbell() and "table.Lighting_V2[{0}][0][0].Mode".format(self._channel) in self.data

def is_motion_detection_enabled(self) -> bool:
"""
Returns true if motion detection is enabled for the camera
"""
""" Returns true if motion detection is enabled for the camera """
return self.data.get("table.MotionDetect[{0}].Enable".format(self._channel), "").lower() == "true"

def is_disarming_linkage_enabled(self) -> bool:
"""
Returns true if disarming linkage is enable
"""
""" Returns true if disarming linkage is enable """
return self.data.get("table.DisableLinkage.Enable", "").lower() == "true"

def is_smart_motion_detection_enabled(self) -> bool:
""" Returns true if smart motion detection is enabled """
return self.data.get("table.SmartMotionDetect[0].Enable", "").lower() == "true"

def is_siren_on(self) -> bool:
"""
Returns true if the camera siren is on
"""
""" Returns true if the camera siren is on """
return self.data.get("status.status.Speaker", "").lower() == "on"

def get_device_name(self) -> str:
Expand Down Expand Up @@ -598,6 +601,10 @@ def get_max_streams(self) -> int:
"""Returns the max number of streams supported by the device. All streams might not be enabled though"""
return self._max_streams

def supports_smart_motion_detection(self) -> bool:
""" True if smart motion detection is supported"""
return self._supports_smart_motion_detection


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Handle removal of an entry."""
Expand Down
20 changes: 17 additions & 3 deletions custom_components/dahua/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,28 @@ async def async_set_all_ivs_rules(self, channel: int, enabled: bool):
return await self.get(url, True)

async def async_set_ivs_rule(self, channel: int, index: int, enabled: bool):
"""
Sets and IVS rules to enabled or disabled
"""
""" Sets and IVS rules to enabled or disabled """
url = "/cgi-bin/configManager.cgi?action=setConfig&VideoAnalyseRule[{0}][{1}].Enable={2}".format(
channel, index, str(enabled).lower()
)
return await self.get(url, True)

async def async_enabled_smart_motion_detection(self, enabled: bool):
""" Enables or disabled smart motion detection """
url = "/cgi-bin/configManager.cgi?action=setConfig&SmartMotionDetect[0].Enable={0}".format(str(enabled).lower())
return await self.get(url, True)

async def async_get_smart_motion_detection(self) -> dict:
"""
Gets the status of smart motion detection. Example output:
table.SmartMotionDetect[0].Enable=true
table.SmartMotionDetect[0].ObjectTypes.Human=true
table.SmartMotionDetect[0].ObjectTypes.Vehicle=false
table.SmartMotionDetect[0].Sensitivity=Middle
"""
url = "/cgi-bin/configManager.cgi?action=getConfig&name=SmartMotionDetect"
return await self.get(url)

async def async_set_lighting_v1(self, channel: int, enabled: bool, brightness: int) -> dict:
""" async_get_lighting_v1 will turn the IR light (InfraRed light) on or off """
# on = Manual, off = Off
Expand Down
44 changes: 43 additions & 1 deletion custom_components/dahua/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ async def async_setup_entry(hass: HomeAssistant, entry, async_add_devices):
coordinator: DahuaDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]

# I think most cameras have a motion sensor so we'll blindly add a switch for it
devices = [DahuaMotionDetectionBinarySwitch(coordinator, entry)]
devices = [
DahuaMotionDetectionBinarySwitch(coordinator, entry),
]

# But only some cams have a siren, very few do actually
if coordinator.supports_siren():
devices.append(DahuaSirenBinarySwitch(coordinator, entry))
if coordinator.supports_smart_motion_detection():
devices.append(DahuaSmartMotionDetectionBinarySwitch(coordinator, entry))

try:
await coordinator.client.async_get_disarming_linkage()
Expand Down Expand Up @@ -114,6 +118,44 @@ def is_on(self):
return self._coordinator.is_disarming_linkage_enabled()


class DahuaSmartMotionDetectionBinarySwitch(DahuaBaseEntity, SwitchEntity):
"""Enables or disables the Smart Motion Detection option in the camera"""

async def async_turn_on(self, **kwargs): # pylint: disable=unused-argument
"""Turn on SmartMotionDetect"""
await self._coordinator.client.async_enabled_smart_motion_detection(True)
await self._coordinator.async_refresh()

async def async_turn_off(self, **kwargs): # pylint: disable=unused-argument
"""Turn off SmartMotionDetect"""
await self._coordinator.client.async_enabled_smart_motion_detection(False)
await self._coordinator.async_refresh()

@property
def name(self):
"""Return the name of the switch."""
return self._coordinator.get_device_name() + " " + "Smart Motion Detection"

@property
def unique_id(self):
"""
A unique identifier for this entity. Needs to be unique within a platform (ie light.hue). Should not be
configurable by the user or be changeable see
https://developers.home-assistant.io/docs/entity_registry_index/#unique-id-requirements
"""
return self._coordinator.get_serial_number() + "_smart_motion_detection"

@property
def icon(self):
"""Return the icon of this switch."""
return MOTION_DETECTION_ICON

@property
def is_on(self):
""" Return true if the switch is on. """
return self._coordinator.is_smart_motion_detection_enabled()


class DahuaSirenBinarySwitch(DahuaBaseEntity, SwitchEntity):
"""dahua siren switch class. Used to enable or disable camera built in sirens"""

Expand Down

0 comments on commit 934341e

Please sign in to comment.