* fix: schedule ONVIF subscription renewal for short and unreported lifetimes refs #5179 The Beward camera from #5165 grants a 60 second subscription and its RenewResponse carries no TerminationTime. Three things combined so that ZM renewed after every PullMessages that returned messages (61 renewals in 74 seconds of the reporter's log): - The renewal was scheduled a fixed ONVIF_RENEWAL_ADVANCE_SECONDS (60) before termination, which for a 60 second subscription is its creation time. ONVIFNextRenewalTime() now uses the smaller of that advance and half the remaining lifetime. - Renew() only logged a missing TerminationTime and left next_renewal_time in the past. assume_renewal_times() now schedules from the lifetime we asked for, capped at what the camera last granted (ONVIFAssumedLifetime()), so this camera renews every 30 seconds. - IsRenewalNeeded() was only checked after a response carrying messages, so a camera quiet for longer than its subscription was never renewed. It is now also checked after an empty (SOAP_EOF) poll. Since renewal is now checked after every poll, a camera that answers Renew with ActionNotSupported has renewal disabled rather than being asked again on each poll, matching the existing handling of unusable TerminationTimes. Tests cover the renewal time for long, short and very short subscriptions, and the assumed lifetime with no, smaller and larger previously granted lifetimes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: only disable ONVIF renewal for ActionNotSupported, keep sub-second grants refs #5179 Review follow-ups on the renewal scheduling change: - Renew() treated soap->error == 12 as ActionNotSupported, but 12 is gSOAP's generic SOAP_FAULT. With renewal now disabled on that path, a NotAuthorized or InvalidArgVal fault from Renew would have stopped renewal for good while marking the subscription healthy. ONVIFIsActionNotSupported() checks the fault subcode and string for ActionNotSupported (wsa: or ter:); any other fault now takes the existing cleanup and re-subscribe path. - granted_lifetime truncated the remaining time to whole seconds. A termination less than a second away stored 0, which reads as "never reported", so the next Renew without a TerminationTime assumed the full requested 300 seconds. ONVIFGrantedLifetime() rounds up instead. Tests cover ActionNotSupported subcodes and strings against other faults and non-fault results, and the granted lifetime for whole, fractional and sub-second remainders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: count an assumed ONVIF renewal lifetime from the request, not the response refs #5179 When a RenewResponse has no TerminationTime, assume_renewal_times() started the assumed lifetime when the response arrived, but the camera counts it from when it received the request. A slow response pushed the deadline and the next renewal later by the response time: with subscription_timeout=10 and a 6 second response, the camera's deadline was request+10 but the renewal was scheduled for request+11. In absolute renewal mode it also ignored the exact deadline that was sent. Renew() now records the time just before building the request and the deadline it asks for: request time plus subscription_timeout, or the absolute whole-second time it sends. ONVIFAssumedTermination() replaces ONVIFAssumedLifetime() and returns that deadline, capped at request time plus the lifetime the camera last granted. The renewal is scheduled from the request time; if the response arrived after it, it is already due and the next poll renews. Tests cover no, smaller and larger previous grants, an absolute deadline kept exactly, and the slow-response case from review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
ZoneMinder
All documentation for ZoneMinder is now online at https://zoneminder.readthedocs.org
Overview
ZoneMinder is an integrated set of applications which provide a complete surveillance solution allowing capture, analysis, recording and monitoring of any CCTV or security cameras attached to a Linux based machine. It is designed to run on distributions which support the Video For Linux (V4L) interface and has been tested with video cameras attached to BTTV cards, various USB cameras and also supports most IP network cameras.
Contacting the Development Team
Before creating an issue in our github forum, please read our posting rules: https://github.com/ZoneMinder/ZoneMinder/wiki/Github-Posting-Rules
Our Dockerfile has moved
Please file issues against the ZoneMinder Dockerfile here: https://github.com/ZoneMinder/zmdockerfiles
Installation Methods
Install from a Package Repository
This is the recommended method to install ZoneMinder onto your system. ZoneMinder packages are maintained for the following distros:
- Ubuntu via Isaac Connor's PPA
- Debian from their default repository
- RHEL/CentOS and clones via RPM Fusion
- Fedora via RPM Fusion
- OpenSuse via third party repository
- Mageia from their default repository
- Arch via the AUR
- Gentoo via Portage Overlays
If a repository that hosts ZoneMinder packages is not available for your distro, then you are encouraged to build your own package, rather than build from source. While each distro is different in ways that set it apart from all the others, they are often similar enough to allow you to adapt another distro's package building instructions to your own.
Building from Source is Discouraged
Historically, installing ZoneMinder onto your system required building from source code by issuing the traditional configure, make, make install commands. To get ZoneMinder to build, all of its dependencies had to be determined and installed beforehand. Init and logrotate scripts had to be manually copied into place following the build. Optional packages such as jscalendar and Cambozola had to be manually installed. Uninstalls could leave stale files around, which could cause problems during an upgrade. Speaking of upgrades, when it comes time to upgrade all these manual steps must be repeated again.
Better methods exist today that do much of this for you. The current development team, along with other volunteers, have taken great strides in providing the resources necessary to avoid building from source.
Building a ZoneMinder Package
Building ZoneMinder into a package is not any harder than building from source. As a matter of fact, if you have successfully built ZoneMinder from source in the past, then you may find these steps to be easier.
When building a package, it is best to do this work in a separate environment, dedicated to development purposes. This could be as simple as creating a virtual machine, using Docker, or using mock. All it takes is one “Oops” to regret doing this work on your production server.
Lastly, if you desire to build a development snapshot from the master branch, it is recommended you first build your package using an official release of ZoneMinder. This will help identify whether any problems you may encounter are caused by the build process or is a new issue in the master branch.
Please visit our ReadtheDocs site for distro specific instructions.
Package Maintainers
Many of the ZoneMinder configuration variable default values are not configurable at build time through autotools or cmake. A new tool called zmeditconfigdata.sh has been added to allow package maintainers to manipulate any variable stored in ConfigData.pm without patching the source.
For example, let's say I have created a new ZoneMinder package that contains the cambozola javascript file. However by default cambozola support is turned off. To fix that, add this to the packaging script:
./utils/zmeditconfigdata.sh ZM_OPT_CAMBOZOLA yes
Note that zmeditconfigdata.sh is intended to be called, from the root build folder, prior to running cmake or configure.
Docker
Docker is a system to run applications inside isolated containers. ZoneMinder, and the ZM webserver, will run using the Dockerfile contained in this repository. However, there is still work needed to ensure that the main ZM features work properly and are documented.
Contribution Model and Development
- Source hosted at GitHub
- Report issues at GitHub Issues
- Questions/feature requests in Slack or forums
Pull requests are very welcome! If you would like to contribute, please follow the following steps. While step 3 is optional, it is preferred.
- Fork the repo
- Open an issue at our GitHub Issues Tracker. Follow the issue template to describe the bug or security issue you found. Please note feature requests or questions should be posted in our user forum or Slack channel.
- Create your feature branch (
git checkout -b 456-my-new-feature) - Commit your changes (
git commit -am 'Added some feature') It is preferred that you 'commit early and often' instead of bunching all changes into a single commit. - Push your branch to your fork on github (
git push origin 456-my-new-feature) - Create new Pull Request
- The team will then review, discuss and hopefully merge your changes.
