Go-posix-time and onvif-cam-poll
Here is a short text about how I got started with using Go and ONVIF for my camera projects. I started working with the Go programming language about a year and a half ago. I was intrigued by how easy it was to create a simple script or small application and deploy it. The style is terse and C-like. Finally, it gives the user the ability to ignore the Object Oriented paradigm in favor of speed of development. This made it a great language for DevOps and system programming.
I had been working on my own open source project for recording and monitoring motion events on IP and USB cameras. I was very glad when I learned about the ONVIF standard. IP Cameras that followed the standard exposed a SOAP service. It was possible to operate any feature on the camera with web service calls. For example, I could record and use other features like motion detection, snapshots and transmitting voice data to the camera speaker.
Tracking motion with GO and ONVIF
I wanted to create a script that would poll an ONIVF-compliant camera for motion events. It should report any events it discovered to my Slack workspace via a webhook. That way I would get a notification on my smartphone. I could avoid paying for a 3rd party push service like Firebase or Twillio. The cloud functions on those cameras required a monthly subscription payment. All of my data would reside in the vendors cloud. This way I could cut costs and keep my data safe. I would stop communication between the camera and the cloud on my home router.
Golang was the ideal choice for the job. Others had already written ONVIF client libraries. In addition, it was easy to code my own functions if needed. Systemd would provide restart and basic monitoring of the process.
The end product of these plans was the onvif-cam-poll repository on GitHub. I added the official Slack client library a little later. It facilitates posting of the actual snapshot directly to the slack channel through a bot token. Previous efforts relied on google drive. I would store the picture there and post the link to slack. Posting the picture directly was much more user friendly.
Clock drift
A side effect of cutting the camera off from the internet was clock drift. The is because the camera could not use an NTP server to sync its system clock. The system clock was used to add timestamps to the video. As the cameras were cheap, the system clocks were not very reliable. Even a day in isolation could yield a drift of more than 30 minutes.
My solution to this issue was to use my local Raspberry Pi 4 server. It was already polling for motion events. Now it would also set the system clock on the camera in regular intervals. ONVIF provided an API method to do that. There was one issue. The timezone format was nothing like what I had ever encountered before – the POSIX time zone format. It is a string that includes both the standard zone and its DST variant (if applicable). Finally, it specifies the dates when the zone shift would happen.
Go 1.19 and POSIX time
The good news was that the release of Go version 1.19 exposed the ZoneBounds struct. This struct contained information as to when the DST shift occurred. Now it became possible to program the formatting of Go time struct to comply to the POSIX time format. Finally, I created my first public Go package on GitHub called go-posix-time.
It was a great learning experience on the Go package system. On one hand,a simple process like this provides a low barrier to entry into the packing system. On the other hand, it left users of the package vulnerable to its loss if the public Git repository was also removed. For enterprise projects I would recommend using a proxy repository that would go to Git once per version and serve a stashed copy after that.
Ivan Šarić
Related Posts:
Filed under: open-source - @ 2022-12-18 15:41
Tags: clock-drift, golang, motion-detection, onvif, posix