zm-py 0.5.5
Breaking Changes
- Python 3.13+ required (was 3.11+). HA core already requires 3.13.
- requests floor raised to >=2.32.2 (was >=2.0).
- Monitor.function no longer triggers an API call.
The property now reads from cached data instead of calling
update_monitor() on every access. Callers that relied on the
implicit refresh (notably HA's switch.py) must call
monitor.update_monitor() before reading function.
Bug Fixes
- Fix is_recording returning wrong value on most ZM versions.
Now uses version-aware alarm state tables instead of hardcoded
STATE_ALARM=3. - Fix is_available returning True when Monitor_Status is
missing (ZM < 1.32.3). Now correctly returns False. - Fix is_available failing on string "1" result from CakePHP.
- Fix stale JWT token causing 401 on retry. Token is cleared
before re-auth. - Fix login() leaking ConnectionError/Timeout to callers.
Now caught internally, returns False. - Fix wasted login() call on final retry attempt.
- Fix set_active_state() failing on state names with special
characters. Now URL-encoded. - Fix PTZ move_monitor() silently swallowing exceptions.
ControlTypeError/MonitorControlTypeError now propagate. - Fix PTZ missing verify_ssl passthrough.
- Fix _zm_request() returning None on retry exhaustion.
Now returns {} (both falsy, but consistent). - Harden error logging with method, URL, and status code.
New Features
- Multi-server support: Server class with per-monitor URL
routing via get_zms_url_for_monitor() and
get_server_url_for_monitor(). - ZM 1.37+ fields: Version-aware function getter/setter
reads decomposed Capturing/Analysing/Recording columns.
New capturing, analysing, recording properties. - set_force_alarm_state(): Trigger or cancel alarms via API.
- stream_scale / stream_maxfps: New client params injected
into all monitor image URLs. - update_all_monitors(): Bulk refresh in a single API call.
- get_event_counts(): Centralized event counting with 1s
cache shared across monitors per poll cycle. - zm_version property: Server version discovered at login.
Performance
- Connection pooling via requests.Session.
- 1s TTL caches on update_monitor(), RunState.active, and
get_event_counts() to eliminate redundant API calls within a
single HA poll cycle. - Precomputed URLs and cached alarm state lookups.
Infrastructure
- 318 unit tests, full E2E test suite.
- mypy strict mode (no ignore_errors).
- Consolidated tox/lint config.
Upgrade Notes for Home Assistant Integration
The Monitor.function property no longer performs hidden I/O.
HA's switch.py should call monitor.update_monitor() in its
update() method before reading monitor.function. The
sensor.py platform is minimally affected since is_available
(called in the same update() cycle) triggers the refresh.
The login() exception handling change makes HA's
except RequestsConnectionError in init.py dead code —
harmless but can be cleaned up.