Open seederp2p opened 8 months ago
gonna close for now, too bad you couldnt use the addon , would be much better
nice :-) i hope the script doesnt hammer your device with that 1 sec, i hope it keeps stable
Yep. I'll monitor that :)
Hi!
For your information, there's a different approach possible! :)
You can go to Configuration -> Network Service -> HTTP -> HTTP Listening and configure an endpoint to receive the event payloads such as:
{
"ipAddress": "whatever",
"portNo": 80,
"protocol": "HTTP",
"dateTime": "2024-08-26T12:32:28+01:00",
"activePostCount": 1,
"eventType": "AccessControllerEvent",
"eventState": "active",
"eventDescription": "Access Controller Event",
"AccessControllerEvent": {
"deviceName": "DS-K1T502DBFWX-C",
"majorEventType": 5,
"subEventType": 21,
"reportChannel": 5,
"cardReaderKind": 1,
"doorNo": 1,
"serialNo": 257,
"currentEvent": true,
"frontSerialNo": 256,
"hasRecord": false
}
}
However I found out that this is not going to support calls to HTTPS service as it looks like the device won't support nothing higher than TLS 1.0. However you can create a "proxy service" inside your network with simple HTTP port 80 that can forward that to your HA Webhook. Example:
<?php
// Define the path to the file where the payload will be saved for debugging
$file = 'payload.txt';
// URL of the Home Assistant webhook (hidden for security)
$webhook_url = 'YOUR_WEBHOOK_URL_HERE';
// Check if the request method is POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Capture the payload from the event_log field
$event_log = isset($_POST['event_log']) ? $_POST['event_log'] : null;
// If the event_log field exists, process it
if ($event_log) {
// Convert the event_log to an array if it's in JSON format
if (is_string($event_log)) {
$event_log = json_decode($event_log, true);
}
// Initialize a variable for the event name
$event_name = "Irrelevant Event";
// Check if the major and minor fields exist and process the event
if (isset($event_log['AccessControllerEvent']['majorEventType']) && $event_log['AccessControllerEvent']['majorEventType'] === 5) {
$minor = $event_log['AccessControllerEvent']['subEventType'];
if ($minor === 22) {
$event_name = "Door Closed";
} elseif ($minor === 38) {
$event_name = "Digital Authentication";
}
}
// Rebuild the payload with the event name
$new_payload = array("last_event" => $event_name);
// Optional: Save the received payload and the (relevant) payload to be sent locally for debugging
$debug_info = "Received Payload:\n" . json_encode($event_log, JSON_PRETTY_PRINT) . "\n\n";
// Check if the event is relevant before sending it to Home Assistant
if ($event_name !== "Irrelevant Event") {
// Add the payload sent to the log
$debug_info .= "Payload Sent:\n" . json_encode($new_payload, JSON_PRETTY_PRINT) . "\n\n";
// Send the new payload to the Home Assistant webhook using cURL
$ch = curl_init($webhook_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($new_payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute the request and capture the response
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check if the request was successful
if ($http_code == 200) {
echo "Payload successfully sent to Home Assistant.";
} else {
echo "Failed to send payload to Home Assistant. HTTP Code: $http_code";
}
} else {
// If the event is not relevant, only log the information
$debug_info .= "No payload sent (Irrelevant Event).\n\n";
echo "Irrelevant event. No payload sent.";
}
// Write all debugging information to the file
file_put_contents($file, $debug_info . str_repeat("-", 20) . "\n", FILE_APPEND);
} else {
echo "event_log field not found in the request.";
}
} else {
echo "Unsupported request method.";
}
?>
In this little script I'm just using the events for finger print and door closing.
then create something like this in your HA:
template:
- trigger:
- platform: webhook
webhook_id: hikvision
local_only: true
sensor:
- name: "your-door"
state: "{{ trigger.json.last_event }}"
ah, thats cool indeed,
=> Configuration -> Network Service -> HTTP -> HTTP Listening
is that something you can configure on the Hikvison device? seems i dont have that on my DS-KD8003 ... Where can you find it? can you make a screenshot?
This is maybe an idea to implement in the addon, to support thos devices
ah, thats cool indeed,
=> Configuration -> Network Service -> HTTP -> HTTP Listening
is that something you can configure on the Hikvison device? seems i dont have that on my DS-KD8003 ... Where can you find it? can you make a screenshot?
This is maybe an idea to implement in the addon, to support thos devices
Yep!
Take a look:
However, as I said, it looks like it doesn't support nothing higher than TLS 1.0, so we should send this to a "proxy" listener in HTTP that maybe can then forward to the HA webhook (or to a listener in your integration).
Also, If you want to open the door on this device you can do that by:
curl -i --digest -u 'admin:whatever' -X PUT -d '<RemoteControlDoor><cmd>open</cmd></RemoteControlDoor>' http://you.r.i.p/ISAPI/AccessControl/RemoteControl/door/1
yeah, that door open command is indeed also part of the addon i dont have that http listener setting :-( , not easy to develop if i cant test :-(
yeah, that door open command is indeed also part of the addon i dont have that http listener setting :-( , not easy to develop if i cant test :-(
Basically the Device start sending payloads whenever ANY event occurs.
Something like:
{
"ipAddress": "whatever",
"portNo": 80,
"protocol": "HTTP",
"dateTime": "2024-08-26T12:32:28+01:00",
"activePostCount": 1,
"eventType": "AccessControllerEvent",
"eventState": "active",
"eventDescription": "Access Controller Event",
"AccessControllerEvent": {
"deviceName": "DS-K1T502DBFWX-C",
"majorEventType": 5,
"subEventType": 21,
"reportChannel": 5,
"cardReaderKind": 1,
"doorNo": 1,
"serialNo": 257,
"currentEvent": true,
"frontSerialNo": 256,
"hasRecord": false
}
}
The code numbers are the same as in the ISAPI documentation...
So for instance, a Fingerprint read is major event 5 and minor (or subevent) 38.
Door locked is major 5 and minor (or subevent) 22
should be easy, i have the issue open again , gonna make a feature reques from it ... maybe in future when i have some time :-)
should be easy, i have the issue open again , gonna make a feature reques from it ... maybe in future when i have some time :-)
sure!
Please let me know if you need any data from the device or a beta tester ;)
FYI, when you restart the hikvision device it won't start using the HTTP Listener automatically (!!!!).
In fact after you reboot, when you access your /ISAPI/Event/notification/httpHosts/1 you'll see:
<HttpHostNotification xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
<id>1</id>
<url>/HA/proxy.php</url>
<protocolType>HTTP</protocolType>
<parameterFormatType/>
<addressingFormatType>ipaddress</addressingFormatType>
<ipAddress>whatever</ipAddress>
<portNo>80</portNo>
<httpAuthenticationMethod/>
<SubscribeEvent>
<heartbeat>30</heartbeat>
<eventMode>all</eventMode>
</SubscribeEvent>
</HttpHostNotification>
Unless you save again your configuration OR you send the proper payload to the ISAPI it won't send any alerts!
After you save again you'll see this:
<HttpHostNotification xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
<id>1</id>
<url>/HA/proxy.php</url>
<protocolType>HTTP</protocolType>
<parameterFormatType/>
<addressingFormatType>ipaddress</addressingFormatType>
<ipAddress>whatever</ipAddress>
<portNo>80</portNo>
<httpAuthenticationMethod/>
<SubscribeEvent>
<heartbeat>30</heartbeat>
<eventMode>all</eventMode>
<EventList>
<Event>
<type>AccessControllerEvent</type>
<minorAlarm/>
<minorException/>
<minorOperation/>
<minorEvent/>
<pictureURLType>binary</pictureURLType>
</Event>
</EventList>
</SubscribeEvent>
</HttpHostNotification>
Notice the EventList that is now present!
You can also achieve the same result by running something like:
curl -i --digest -u 'admin:whatever' -X PUT -d '<HttpHostNotification xmlns="http://www.isapi.org/ver20/XMLSchema" version="2.0">
<id>1</id>
<url>/HA/proxy.php</url>
<protocolType>HTTP</protocolType>
<parameterFormatType/>
<addressingFormatType>ipaddress</addressingFormatType>
<ipAddress>whatever</ipAddress>
<portNo>80</portNo>
<httpAuthenticationMethod/>
<SubscribeEvent>
<heartbeat>30</heartbeat>
<eventMode>all</eventMode>
<EventList>
<Event>
<type>AccessControllerEvent</type>
<minorAlarm/>
<minorException/>
<minorOperation/>
<minorEvent/>
<pictureURLType>binary</pictureURLType>
</Event>
</EventList>
</SubscribeEvent>
</HttpHostNotification>' \
http://whatever/ISAPI/Event/notification/httpHosts/1
Please remind that it will spit all the missed events, so you should be careful. Maybe handlind event dates so you won't trigger any action based on a past event...
hmm, maybe thats a firmware bug ?
hmm, maybe thats a firmware bug ?
Very likely... :) but we can't rely on hikvision to fix this ... ahaha
I don't even have a proper contact to escalate this... so we can overcome by creating a mechanism that PUT de needed XML payload so the listener is active again (for instance after a reboot).
Then you just need to handle the dates between the payloads that hikvision send vs the current time of the system.
My example:
<?php
// Define the path to the file where the payload will be saved for debugging
$file = 'payload.txt';
// Home Assistant webhook URL
$webhook_url = 'YOUR_HIDDEN_URL_HERE';
// Check if the request method is POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Capture the payload from the event_log field
$event_log = isset($_POST['event_log']) ? $_POST['event_log'] : null;
// If the event_log field exists, process it
if ($event_log) {
// Convert event_log to an array if it's in JSON format
if (is_string($event_log)) {
$event_log = json_decode($event_log, true);
}
// Check if the dateTime field exists in the payload
if (isset($event_log['dateTime'])) {
// Convert the payload dateTime and the current system time to timestamps
$payload_time = strtotime($event_log['dateTime']);
$current_time = time();
// Calculate the difference in seconds between the payload time and the current time
$time_difference = abs($current_time - $payload_time);
// If the difference is greater than 10 seconds, consider the event as irrelevant
if ($time_difference > 10) {
// Capture the current system date and time
$system_time = date('Y-m-d H:i:s');
// Message indicating that the event is outside the time tolerance, including the system date and time
$message = "Payload is outside the time tolerance (system date: $system_time).";
echo $message;
// Log the debug information in the file
$debug_info = "$message\nPayload Received:\n" . json_encode($event_log, JSON_PRETTY_PRINT) . "\n\n";
file_put_contents($file, $debug_info . str_repeat("-", 20) . "\n", FILE_APPEND);
exit;
}
} else {
echo "dateTime field not found in the payload.";
exit;
}
// Initialize the variable for the event name
$event_name = "Irrelevant Event";
// Check if the major and minor fields exist and process the event
if ($event_log['AccessControllerEvent']['majorEventType'] === 5) {
$minor = $event_log['AccessControllerEvent']['subEventType'];
if ($minor === 22) {
$event_name = "Door Closure";
} elseif ($minor === 38) {
$event_name = "Digital Authentication";
}
}
// Reconstruct the payload with the event name
$new_payload = array("last_event" => $event_name);
// Optionally: Save the received payload and the (if relevant) payload to be sent locally for debugging
$debug_info = "Payload Received:\n" . json_encode($event_log, JSON_PRETTY_PRINT) . "\n\n";
// Check if the event is relevant before sending it to Home Assistant
if ($event_name !== "Irrelevant Event") {
// Add the sent payload to the log
$debug_info .= "Payload Sent:\n" . json_encode($new_payload, JSON_PRETTY_PRINT) . "\n\n";
// Send the new payload to the Home Assistant webhook using cURL
$ch = curl_init($webhook_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($new_payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute the request and capture the response
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check if the request was successful
if ($http_code == 200) {
echo "Payload successfully sent to Home Assistant.";
} else {
echo "Failed to send payload to Home Assistant. HTTP Code: $http_code";
}
} else {
// If the event is not relevant, just log the information
$debug_info .= "No payload sent (Irrelevant Event).\n\n";
echo "Irrelevant event. No payload sent.";
}
// Log all the debug information in the file
file_put_contents($file, $debug_info . str_repeat("-", 20) . "\n", FILE_APPEND);
} else {
echo "event_log field not found in the request.";
}
} else {
echo "Request method not supported.";
}
?>
What happened?
I'm trying to add my DS-K1T502DBFWX-C without success.
Add-on
Hikvision Doorbell
What version of the add-on are you running?
3.0.12
Installation type
Home Assistant add-on
Relevant log output
Relevant configuration
No response
Anything else?
No response