Add Temperature to Hikvision Camera Overlay
So, this is a pretty niche solution, but I found it to be an interesting project to do.
I thought it would be cool if my outdoor Hikvision PoE cameras displayed the current temperature on the on-screen display. Currently, it just displays the date, time, and the name of the camera.
In the web interface of the camera, there is the option for custom text on the OSD, but it has to be manually updated.
My first idea was to do some packet captures to figure out what form information was being sent on this page. Perhaps I could have a script send a POST request to this page with an updated temperature value.
I fired up Wireshark, and I was able to see the custom text being sent as XML in a POST request to this page on the camera’s web interface. I tried to replicate the request using cURL, but the camera requires authentication to the page before if will accept requests. There’s no authentication sent with the POST request when updating the custom text, so it must be using cookies to keep track of authentication.
While Googling around, I came across some documentation (PDF warning) for Hikvision-CGI. This works as an API for the camera, which is exactly what I needed. I just needed to enable it on the camera and add a user before I could start using it.
So now all I needed to do was send the right data to the necessary URL according to the documentation.
curl -X PUT -d '<?xml version="1.0" encoding="UTF 8"?><TextOverlay version="1.0" xmlns="http://www.hikvision.com/ver10/XMLSchema"><id>1 </id><enabled>true</enabled><posX>624</posX> <posY>16</posY><message>80F</message> </TextOverlay>' 192.168.40.10/Video/inputs/channels/1/overlays/text/1 --user admin:password
So that took care of the biggest unknown. Now all that’s left is use an API from a weather app to pull the current temperature for my location.
I decided on ClimaCell because they offered a free API that only required an API key for authentication. The documentation isn’t exactly straightforward, but I managed to construct a request that gave me what I wanted.
curl --request GET --url 'https://api.climacell.co/v3/weather/realtime?unit_system=us&lat=40.00 &lon=-100.00&apikey=mykey&fields=temp'
{"lat":40.00,"lon":-100.00,"temp":{"value":86.45,"units":"F"}, "observation_time":{"value":"2020-08-30T20:17:03.449Z"}}
Now I just needed to make a Python script to put these together.
import requests import json params = ( ('unit_system', 'us'), ('lat', '40.00'), ('lon', '-100.00'), ('apikey', 'mykey'), ('fields', 'temp'), ) response = requests.get('https://api.climacell.co/v3/weather/realtime', params=params) temperature = json.loads(response.text) temp = str(round(temperature['temp']['value'])) xml_request = ''' <?xml version="1.0" encoding="UTF 8"?> <TextOverlay version="1.0" xmlns="http://www.hikvision.com/ver10/XMLSchema"> <id>1</id> <enabled>true</enabled> <posX>624</posX> <posY>16</posY> <message>'''+temp+'''F</message> </TextOverlay> ''' response = requests.put( 'http://192.168.40.10/Video/inputs/channels/1/overlays/text/1', headers={"Content-Type": "application/xml"}, data=xml_request, auth=('admin', 'password') ) print(response.content)
And now we put it in a cronjob to update the temperature every 5 minutes.
*/5 * * * * /usr/bin/python3 /home/admin/updateoverlay.py
I’m pretty pleased with the result and I’m glad Hikvision put in some form of an API.
Leave a Reply