Skip to content

Commit

Permalink
ANPR event switch and sensor for IPC
Browse files Browse the repository at this point in the history
  • Loading branch information
maciej-or committed Jan 12, 2025
1 parent f6dac0d commit d1bceff
Show file tree
Hide file tree
Showing 26 changed files with 1,321 additions and 1 deletion.
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
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
3 changes: 3 additions & 0 deletions tests/fixtures/devices/DS-2CD2T86G2-ISU.json
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,9 @@
]
}
}
},
"ITC/capability": {
"status_code": 403
}
}
}
Expand Down
Loading

0 comments on commit d1bceff

Please sign in to comment.