Skip to content

Commit

Permalink
more events for : DS-KV9503-WBE1
Browse files Browse the repository at this point in the history
  • Loading branch information
pergolafabio committed Jan 19, 2024
1 parent 75fd6f2 commit e2ef3bb
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 29 deletions.
73 changes: 46 additions & 27 deletions hikvision-doorbell/src/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
NET_DVR_ACS_ALARM_INFO,
VIDEO_INTERCOM_ALARM_ALARMTYPE_DOOR_NOT_OPEN,
VIDEO_INTERCOM_EVENT_EVENTTYPE_UNLOCK_LOG,
VideoInterComAlarmType)
VideoInterComAlarmType,
VideoInterComEventType)
from sdk.acsalarminfo import (AcsAlarmInfoMajor, AcsAlarmInfoMajorAlarm, AcsAlarmInfoMajorException, AcsAlarmInfoMajorOperation, AcsAlarmInfoMajorEvent)
from typing_extensions import override
import xml.etree.ElementTree as ET
Expand Down Expand Up @@ -82,9 +83,16 @@ class DeviceTriggerMetadata(TypedDict):
VideoInterComAlarmType.BLACKLIST_ALARM: DeviceTriggerMetadata(name='smart_lock_blacklist_alarm', type='alarm', subtype='blacklist'),
VideoInterComAlarmType.SMART_LOCK_DISCONNECTED: DeviceTriggerMetadata(name='smart_lock_disconnected', type='smart lock disconnected', subtype=''),
VideoInterComAlarmType.ACCESS_CONTROL_TAMPERING_ALARM: DeviceTriggerMetadata(name='access_control_tampering_alarm', type='alarm', subtype='access control tampering'),
VideoInterComAlarmType.DOOR_OPEN_BY_EXTERNAL_FORCE: DeviceTriggerMetadata(name='door_open_by_external_force', type='alarm', subtype='door open by external force'),
}
"""Define the attributes of each DeviceTrigger entity, indexing them by the enum VideoInterComAlarmType"""

DEVICE_TRIGGERS_DEFINITIONS_EVENT: dict[VideoInterComEventType, DeviceTriggerMetadata] = {
VideoInterComEventType.AUTHENTICATION_LOG: DeviceTriggerMetadata(name='authentication_log', type='event', subtype='authentication log'),
VideoInterComEventType.MAGNETIC_DOOR_STATUS: DeviceTriggerMetadata(name='magnetic_door_status', type='event', subtype='magnetic door status'),
}
"""Define the attributes of each DeviceTrigger entity, indexing them by the enum VideoInterComEventType"""

class MQTTHandler(EventHandler):
name = 'MQTT'
_sensors: dict[Doorbell, dict[str, Discoverable[Any]]] = {}
Expand Down Expand Up @@ -284,31 +292,43 @@ async def update_door_entities(door_id: str, control_source: str):

# Wait some seconds, then turn off the switch entity (since the door relay in the doorbell is momentary)
await asyncio.sleep(2)

door_sensor.off()
if alarm_info.byEventType == VIDEO_INTERCOM_EVENT_EVENTTYPE_UNLOCK_LOG:
door_id = alarm_info.uEventInfo.struUnlockRecord.wLockID
control_source = alarm_info.uEventInfo.struUnlockRecord.controlSource()
# unlock_type = alarm_info.uEventInfo.struUnlockRecord.byUnlockType
# card_number = str(alarm_info.uEventInfo.struAuthInfo.byCardNo

# Name of the entity inside the dict array containing all the sensors
entity_id = f'door_{door_id}'
# Extract the sensor entity from the dict and cast to know type
door_sensor = cast(Switch, self._sensors[doorbell].get(entity_id))
# If the SDK returns a lock ID that is not starting from 0,
# we don't know what switch to update in HA -> trigger both of them
# Make sure the switch is back in "OFF" position in case it was trigger by the switch
if not door_sensor:
logger.warning("Received unknown lockID: {}", door_id)
# logger.debug("Changing switches back to OFF position")
num_doors = doorbell.get_num_outputs()
for door_id in range(num_doors):
await update_door_entities(door_id, control_source)
return
await update_door_entities(door_id, control_source)
else:
logger.warning("Unhandled eventType: {}", alarm_info.byEventType)
# Extract the type of event as a Python enum
try:
event_type = VideoInterComEventType(alarm_info.byEventType)
except ValueError:
logger.warning("Received unknown Event type: {}", alarm_info.byEventType)
return

match event_type:
case VideoInterComEventType.UNLOCK_LOG:
door_id = alarm_info.uEventInfo.struUnlockRecord.wLockID
control_source = alarm_info.uEventInfo.struUnlockRecord.controlSource()
# unlock_type = alarm_info.uEventInfo.struUnlockRecord.byUnlockType
# card_number = str(alarm_info.uEventInfo.struAuthInfo.byCardNo

# Name of the entity inside the dict array containing all the sensors
entity_id = f'door_{door_id}'
# Extract the sensor entity from the dict and cast to know type
door_sensor = cast(Switch, self._sensors[doorbell].get(entity_id))
# If the SDK returns a lock ID that is not starting from 0,
# we don't know what switch to update in HA -> trigger both of them
# Make sure the switch is back in "OFF" position in case it was trigger by the switch
if not door_sensor:
logger.warning("Received unknown lockID: {}", door_id)
# logger.debug("Changing switches back to OFF position")
num_doors = doorbell.get_num_outputs()
for door_id in range(num_doors):
await update_door_entities(door_id, control_source)
return
await update_door_entities(door_id, control_source)

case _:
"""Generic event: create the device trigger entity according to the information inside the DEVICE_TRIGGERS_DEFINITIONS dict"""

logger.info("Video intercom event {} detected on {}", event_type.name, doorbell._config.name)
self.handle_device_trigger(doorbell, DEVICE_TRIGGERS_DEFINITIONS_EVENT[event_type])

@override
async def video_intercom_alarm(
Expand Down Expand Up @@ -419,9 +439,8 @@ def handle_device_trigger(self, doorbell: Doorbell, trigger: DeviceTriggerMetada
# Cast to know type DeviceTrigger
device_trigger = cast(DeviceTrigger, device_trigger)
# Trigger the event
logger.debug("Invoking device trigger {}", trigger)
logger.info("Invoking device trigger automation{}", trigger)

# Serialize the payload, if provided as part of the trigger
json_payload = json.dumps(trigger['payload']) if trigger.get('payload') else None
device_trigger.trigger(json_payload)
#device_trigger.trigger()
device_trigger.trigger(json_payload)
34 changes: 32 additions & 2 deletions hikvision-doorbell/src/sdk/hcnetsdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,16 +146,36 @@
VIDEO_INTERCOM_ALARM_ALARMTYPE_ACCESS_CONTROL_MODULE_ANTI_TAMPERING_ALARM = 16
VIDEO_INTERCOM_ALARM_ALARMTYPE_DOORBELL_RINGING = 17
VIDEO_INTERCOM_ALARM_ALARMTYPE_DISMISS_INCOMING_CALL = 18
VIDEO_INTERCOM_ALARM_ALARMTYPE_SOS_CANCELLED = 19
VIDEO_INTERCOM_ALARM_ALARMTYPE_NO_MASK_ALARM = 20
VIDEO_INTERCOM_ALARM_ALARMTYPE_FIRE_INPUT_ALARM = 21
VIDEO_INTERCOM_ALARM_ALARMTYPE_FIRE_INPUT_RESTORED = 22
VIDEO_INTERCOM_ALARM_ALARMTYPE_DOOR_OPEN_BY_EXTERNAL_FORCE = 23
VIDEO_INTERCOM_ALARM_ALARMTYPE_TOILET_ALARM = 24
VIDEO_INTERCOM_ALARM_ALARMTYPE_TOILET_ALARM_CANCELLED = 25
VIDEO_INTERCOM_ALARM_ALARMTYPE_DRESSING_REMINDER = 26
VIDEO_INTERCOM_ALARM_ALARMTYPE_FACE_TEMPERATURE_ALARM = 27
VIDEO_INTERCOM_ALARM_ALARMTYPE_DRESSING_REMINDER_CANCELLED = 28

VIDEO_INTERCOM_EVENT_EVENTTYPE_UNLOCK_LOG = 1
VIDEO_INTERCOM_EVENT_EVENTTYPE_ANNOUNCEMENT_READING_RECEIPT = 2
VIDEO_INTERCOM_EVENT_EVENTTYPE_AUTHENTICATION_LOG = 3
VIDEO_INTERCOM_EVENT_EVENTTYPE_ILLEGAL_CARD_SWIPING_EVENT = 5
VIDEO_INTERCOM_EVENT_EVENTTYPE_DOOR_STATION_ISSUED_CARD_LOG = 6
VIDEO_INTERCOM_EVENT_EVENTTYPE_MASK_DETECT_EVENT = 7
VIDEO_INTERCOM_EVENT_EVENTTYPE_MAGNETIC_DOOR_STATUS = 8

###########################################
# Enums

class VideoInterComEventType(IntEnum):
UNLOCK_LOG = 1
ANNOUNCEMENT_READING_RECEIPT = 2
AUTHENTICATION_LOG = 3
ILLEGAL_CARD_SWIPING_EVENT = 5
DOOR_STATION_ISSUED_CARD_LOG = 6
MASK_DETECT_EVENT = 7
MAGNETIC_DOOR_STATUS = 8

class VideoInterComAlarmType(IntEnum):
ZONE_ALARM = 1
Expand All @@ -176,8 +196,18 @@ class VideoInterComAlarmType(IntEnum):
ACCESS_CONTROL_TAMPERING_ALARM = 16 # Access control security module tamper alarm
DOORBELL_RINGING = 17
DISMISS_INCOMING_CALL = 18


SOS_CANCELLED = 19
NO_MASK_ALARM = 20
FIRE_INPUT_ALARM = 21
FIRE_INPUT_RESTORED = 22
DOOR_OPEN_BY_EXTERNAL_FORCE = 23
TOILET_ALARM = 24
TOILET_ALARM_CANCELLED = 25
DRESSING_REMINDER = 26
FACE_TEMPERATURE_ALARM = 27
DRESSING_REMINDER_CANCELLED = 28


class DeviceCapabilityType(Enum):
DEVICE_VIDEOPIC_ABILITY = 0x00e
DEVICE_NETAPP_ABILITY = 0x00d
Expand Down

0 comments on commit e2ef3bb

Please sign in to comment.