I run ZoneMinder to monitor several cameras at home. I decided to add a PTZ camera and selected the Axis M5525-E camera for it’s relatively low cost, uses regular 802.3af POE requirements and flexibility of configuration.
Setup of the camera is straightforward and it appeared to work great inside. Once taken outside I discovered it would not focus on a distant object when zoomed in – it couldn’t focus on anything 30 or more feet away. It was as if the focus control didn’t have enough range and need to go a bit further.
After quite a bit of troubleshooting with Axis’s tech support, they were unable to resolve the issue and decided the camera was defective. Testing the camera again outside and it still not focusing, I put the dome on as it looked like it might rain. Putting the dome on allowed it to focus! I was testing with the clear dome, it’s just a clear dome right? Apparently the dome act’s as a lens, it’s not simply clear plastic. I incorrectly assumed it would work without the dome during testing.
Accessing the camera in ZoneMinder is done by setting the camera’s source path to rtsp://USER:PASSWORD@ADDRESS/axis-media/media.amp and setting capture with to 1920 and capture height to 1080. For storage, I’m using H264 camera passthrough.
Setting up PTZ control of the camera was much more difficult. Axis cameras are popular and common so control should be easy to set it up, the Control Type was set to Axis API v2 and control address of USER:PASSWORD@ADDRESS was entered. This should work, however it nothing happens when using the controls in ZM. Inspecting the the script (AxisV2.pm) it uses for control reveals how it works and the URLs fetched to execute the commands. Using URLs from the script via a browser controlled the camera without issue. So why wasn’t the script working?
To troubleshoot I created a new VM for ZoneMinder and set it up with the new PTZ. It still did not work. It was an old install that I wanted to upgrade anyway.
The problem was finally narrowed down by using tcpdump to capture what was being sent to the camera. The dump was opened in wiresharp, the request found and the follow tcp stream was used to see the HTTP request and response. It was doing an HTTP GET for “/axis-cgi/com/ptz.cgi?rpan=59”. The camera responded with HTTP/1.1 401 Unauthorized. In the request, the dump showed basic HTTP authentication was being used. A dump from a browser sending the same request, which worked, showed digest authentication. It turns out the camera does not (at least out of the box) support basic authentication.
A work-around is to set the camera to use basic authentication. This is found in the camera’s settings under system->plain config->network->http->authentication policy. Changing the policy to Basic resolved the problem. There’s an option to accept Basic and Digest, but this did not work. It comes set to Digest. Basic authentication is much less secure since it uses base64 to hash username:password and can be reversed to expose the password. The control script should be updated to support the digest authentication that these newer cameras use.