Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANPR event switch and sensor for IPC #286

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions custom_components/hikvision_next/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@
**ISAPI_EVENTS["pir"],
"device_class": BinarySensorDeviceClass.MOTION,
},
"anpr": {
**ISAPI_EVENTS["anpr"],
"device_class": BinarySensorDeviceClass.MOTION,
},
}
1 change: 1 addition & 0 deletions custom_components/hikvision_next/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ async def _async_get_diagnostics(
"Event/triggers/scenechangedetection-1",
"Event/notification/httpHosts",
"Streaming/channels",
"ITC/capability"
]

for endpoint in endpoints:
Expand Down
8 changes: 8 additions & 0 deletions custom_components/hikvision_next/isapi/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
EVENT_IO: Final = "io"
EVENT_SMART: Final = "smart"
EVENT_PIR: Final = "pir"
EVENT_TRAFFIC: Final = "trafic"
EVENTS = {
"motiondetection": {
"type": EVENT_BASIC,
Expand Down Expand Up @@ -69,6 +70,12 @@
"slug": "WLAlarm/PIR",
"direct_node": "PIRAlarm",
},
"anpr": {
"type": EVENT_TRAFFIC,
"label": "License Plate Recognition",
"slug": "vehicleDetect",
"direct_node": "VehicleDetectCfg",
}
}

STREAM_TYPE = {
Expand All @@ -84,6 +91,7 @@
"thermometry": "motiondetection",
"shelteralarm": "tamperdetection",
"VMDHumanVehicle": "motiondetection",
"vehicledetection": "anpr"
}

MUTEX_ALTERNATE_ID = {"motiondetection": "VMDHumanVehicle"}
23 changes: 22 additions & 1 deletion custom_components/hikvision_next/isapi/isapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
EVENT_BASIC,
EVENT_IO,
EVENT_PIR,
EVENT_TRAFFIC,
EVENTS,
EVENTS_ALTERNATE_ID,
GET,
Expand Down Expand Up @@ -114,6 +115,9 @@ async def get_hardware_info(self):
self.capabilities.output_ports = int(deep_get(capabilities, "SysCap.IOCap.IOOutputPortNums", 0))
self.capabilities.support_alarm_server = bool(await self.get_alarm_server())

itc_capability = (await self.request(GET, "ITC/capability")).get("ITCCap", {})
self.capabilities.support_anpr = str_to_bool(deep_get(itc_capability, "isSupportVehicleDetection", "false"))

# Set if NVR based on whether more than 1 supported IP or analog cameras
# Single IP camera will show 0 supported devices in total
if self.capabilities.analog_cameras_inputs + self.capabilities.digital_cameras_inputs > 1:
Expand Down Expand Up @@ -297,6 +301,13 @@ def create_event_info(event_trigger: dict):
if event := create_event_info(event_trigger):
events.append(event)

if self.capabilities.support_anpr and not self.device_info.is_nvr:
# TODO: add support for NVR
event_trigger = await self.request(GET, "Event/triggers/vehicledetection-1")
event_trigger = deep_get(event_trigger, "EventTrigger", {})
if event := create_event_info(event_trigger):
events.append(event)

# some devices do not have scenechangedetection in Event/triggers
if not [e for e in events if e.id == "scenechangedetection"]:
is_supported = str_to_bool(deep_get(system_capabilities, "SmartCap.isSupportSceneChangeDetection", False))
Expand Down Expand Up @@ -350,6 +361,9 @@ def get_event_url(self, event_id: str, channel_id: int, io_port_id: int, is_prox
elif event_type == EVENT_PIR:
# ISAPI/WLAlarm/PIR
url = slug
elif event_type == EVENT_TRAFFIC:
# /ISAPI/Traffic/channels/1/vehicleDetect
url = f"Traffic/channels/{channel_id}/{slug}"
else:
url = f"Smart/{slug}/{channel_id}"
return url
Expand Down Expand Up @@ -679,7 +693,11 @@ def parse_event_notification(xml: str) -> AlertInfo:
detection_target = deep_get(alert, "DetectionRegionList.DetectionRegionEntry.detectionTarget")
region_id = int(deep_get(alert, "DetectionRegionList.DetectionRegionEntry.regionID", 0))

if not EVENTS[event_id]:
anpr_license_plate = deep_get(alert, "ANPR.licensePlate")
anpr_confidence_level = deep_get(alert, "ANPR.confidenceLevel", 0)
anpr_direction = deep_get(alert, "ANPR.direction", "unknown")

if not EVENTS.get(event_id):
raise ValueError(f"Unsupported event {event_id}")

return AlertInfo(
Expand All @@ -690,6 +708,9 @@ def parse_event_notification(xml: str) -> AlertInfo:
mac,
region_id,
detection_target,
anpr_license_plate,
anpr_direction,
anpr_confidence_level
)

async def get_camera_image(
Expand Down
4 changes: 4 additions & 0 deletions custom_components/hikvision_next/isapi/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class AlertInfo:
mac: str = ""
region_id: int = 0
detection_target: str = field(default=None)
anpr_license_plate: str = field(default=None)
anpr_direction: str = field(default=None)
anpr_confidence_level: int = 0


@dataclass
Expand Down Expand Up @@ -102,6 +105,7 @@ class CapabilitiesInfo:
support_holiday_mode: bool = False
support_alarm_server: bool = False
support_channel_zero: bool = False
support_anpr: bool = False
support_event_mutex_checking: bool = False
input_ports: int = 0
output_ports: int = 0
Expand Down
5 changes: 5 additions & 0 deletions custom_components/hikvision_next/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ def fire_hass_event(self, alert: AlertInfo):
message["detection_target"] = alert.detection_target
message["region_id"] = alert.region_id

if alert.event_id == 'anpr':
message["anpr_license_plate"] = alert.anpr_license_plate
message["anpr_direction"] = alert.anpr_direction
message["anpr_confidence_level"] = int(alert.anpr_confidence_level)

self.hass.bus.fire(
HIKVISION_EVENT,
message,
Expand Down
6 changes: 6 additions & 0 deletions custom_components/hikvision_next/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
},
"io": {
"name": "Alarm Input {io_port_id}"
},
"anpr": {
"name": "License Plate"
}
},
"switch": {
Expand Down Expand Up @@ -89,6 +92,9 @@
},
"io": {
"name": "Alarm Input {io_port_id}"
},
"anpr": {
"name": "License Plate Recognition"
}
},
"camera": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<EventNotificationAlert version="2.0"
xmlns="http://www.hikvision.com/ver20/XMLSchema">
<ipAddress>10.2.124.188</ipAddress>
<portNo>8123</portNo>
<protocol>HTTP</protocol>
<macAddress>bc:5e:33:62:2a:5c</macAddress>
<channelID>1</channelID>
<dateTime>2023-08-11T13:49:00+01:00</dateTime>
<activePostCount>1</activePostCount>
<eventType>ANPR</eventType>
<eventState>active</eventState>
<eventDescription>ANPR</eventDescription>
<channelName>Camera 01</channelName>
<ANPR>
<country>5</country>
<licensePlate>KH35192</licensePlate>
<line>1</line>
<direction>forward</direction>
<confidenceLevel>100</confidenceLevel>
<plateType>unknown</plateType>
<plateColor>unknown</plateColor>
<licenseBright>0</licenseBright>
<dangmark>no</dangmark>
<twoWheelVehicle>no</twoWheelVehicle>
<threeWheelVehicle>no</threeWheelVehicle>
<plateCharBelieve>99,99,99,99,99,99,99</plateCharBelieve>
<vehicleType>vehicle</vehicleType>
<detectDir>8</detectDir>
<detectType>0</detectType>
<alarmDataType>0</alarmDataType>
<vehicleInfo>
<index>39</index>
<colorDepth>2</colorDepth>
<color>white</color>
<length>0</length>
<vehicleLogoRecog>1060</vehicleLogoRecog>
<vehileSubLogoRecog>0</vehileSubLogoRecog>
<vehileModel>0</vehileModel>
</vehicleInfo>
<pictureInfoList>
<pictureInfo>
<fileName>licensePlatePicture.jpg</fileName>
<type>licensePlatePicture</type>
<dataType>0</dataType>
<picRecogMode>0</picRecogMode>
<absTime>20230811134900555</absTime>
<pId>2023081113490182400fSXqc8CQHtdNG</pId>
</pictureInfo>
<pictureInfo>
<fileName>vehiclePicture.jpg</fileName>
<type>vehiclePicture</type>
<dataType>0</dataType>
<picRecogMode>0</picRecogMode>
<absTime>20230811134900555</absTime>
<plateRect>
<X>544</X>
<Y>835</Y>
<width>40</width>
<height>35</height>
</plateRect>
<pId>2023081113490182400EgqBZCXSSOD9V</pId>
</pictureInfo>
</pictureInfoList>
<originalLicensePlate>KH35192</originalLicensePlate>
<CRIndex>5</CRIndex>
<vehicleListName>otherList</vehicleListName>
<plateCategory></plateCategory>
<plateSize>0</plateSize>
</ANPR>
<UUID>20230811134901822007gWpiNIuI14ikdwfKR5eDCzuV45RubEmi88qaD5w0YTq</UUID>
<picNum>2</picNum>
<monitoringSiteID>1</monitoringSiteID>
<isDataRetransmission>false</isDataRetransmission>
<DeviceGPSInfo>
<longitudeType>E</longitudeType>
<latitudeType>N</latitudeType>
<Longitude>
<degree>7</degree>
<minute>56</minute>
<sec>9.000000</sec>
</Longitude>
<Latitude>
<degree>58</degree>
<minute>6</minute>
<sec>22.300000</sec>
</Latitude>
</DeviceGPSInfo>
</EventNotificationAlert>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<EventNotificationAlert version="2.0"
xmlns="http://www.hikvision.com/ver20/XMLSchema">
<ipAddress>10.2.124.188</ipAddress>
<portNo>8123</portNo>
<protocol>HTTP</protocol>
<macAddress>bc:5e:33:62:2a:5c</macAddress>
<channelID>1</channelID>
<dateTime>2023-08-11T14:02:35+01:00</dateTime>
<activePostCount>1</activePostCount>
<eventType>ANPR</eventType>
<eventState>active</eventState>
<eventDescription>ANPR</eventDescription>
<channelName>Camera 01</channelName>
<ANPR>
<country>0</country>
<licensePlate>unknown</licensePlate>
<line>1</line>
<direction>forward</direction>
<confidenceLevel>0</confidenceLevel>
<plateType>unknown</plateType>
<plateColor>unknown</plateColor>
<licenseBright>0</licenseBright>
<dangmark>unknown</dangmark>
<twoWheelVehicle>no</twoWheelVehicle>
<threeWheelVehicle>no</threeWheelVehicle>
<plateCharBelieve></plateCharBelieve>
<vehicleType>SUVMPV</vehicleType>
<detectDir>8</detectDir>
<detectType>0</detectType>
<alarmDataType>0</alarmDataType>
<vehicleInfo>
<index>93</index>
<colorDepth>2</colorDepth>
<color>white</color>
<length>0</length>
<vehicleLogoRecog>1036</vehicleLogoRecog>
<vehileSubLogoRecog>0</vehileSubLogoRecog>
<vehileModel>0</vehileModel>
</vehicleInfo>
<pictureInfoList>
<pictureInfo>
<fileName>vehiclePicture.jpg</fileName>
<type>vehiclePicture</type>
<dataType>0</dataType>
<picRecogMode>0</picRecogMode>
<absTime>20230811140235286</absTime>
<plateRect>
<X>0</X>
<Y>0</Y>
<width>0</width>
<height>0</height>
</plateRect>
<pId>2023081114023616000te10ogXYgHMUv</pId>
</pictureInfo>
</pictureInfoList>
<originalLicensePlate>unknown</originalLicensePlate>
<CRIndex>0</CRIndex>
<vehicleListName>otherList</vehicleListName>
<plateCategory></plateCategory>
<plateSize>0</plateSize>
</ANPR>
<UUID>2023081114023615800vefGxfobg2fpWcnGtTmw4kkii7gsXTdT58WIAeZZkGfh</UUID>
<picNum>1</picNum>
<monitoringSiteID>1</monitoringSiteID>
<isDataRetransmission>false</isDataRetransmission>
<DeviceGPSInfo>
<longitudeType>E</longitudeType>
<latitudeType>N</latitudeType>
<Longitude>
<degree>7</degree>
<minute>56</minute>
<sec>9.000000</sec>
</Longitude>
<Latitude>
<degree>58</degree>
<minute>6</minute>
<sec>22.300000</sec>
</Latitude>
</DeviceGPSInfo>
</EventNotificationAlert>
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2146G2-ISU.json
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2346G2-ISU.json
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2386G2-IU.json
Original file line number Diff line number Diff line change
Expand Up @@ -1823,6 +1823,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2443G0-IW.json
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2532F-IWS.json
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2T46G2-ISU.json
Original file line number Diff line number Diff line change
Expand Up @@ -1944,6 +1944,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
Loading
Loading