Feat/ha integration support - #2
Conversation
HarborCameraConfig gains cert_pem/key_pem fields so consumers can pass certificate material directly instead of persisting private keys to disk. cert_path/key_path/cert_dir are now optional; the config validates that one complete pair is provided. Since ssl.SSLContext.load_cert_chain only accepts file paths, PEM data is staged in a private temp directory (0600 files) that is removed before build_ssl_context returns, so the temp-file lifecycle is fully encapsulated in the library. The ssl_context_cache is now keyed off the certificate material (SHA-256 of the PEM pair, or the path pair for path-based configs) via the new get_ssl_cache_key(), so rotated credentials never reuse a stale context. The test fixture in tests/data/certs.py is a throwaway self-signed cert generated for the suite; it is excluded from detect-private-key.
…eriod Harbor cameras frequently cycle their TCP connection, which previously caused on_connection_change to fire on every raw connect/disconnect and forced consumers to run their own grace timers. HarborMQTTClient now takes connection_grace_period (default 90 seconds, exported as DEFAULT_CONNECTION_GRACE_PERIOD) and only reports stable transitions: connects are reported immediately, while a disconnect is held back and silently dropped if the client reconnects within the window. Setting the grace period to 0 restores raw per-transition reporting. An explicit stop() skips the grace window and reports the disconnect immediately. The async callback signature is unchanged, and client.connected still reflects the raw transport state. SSL cache invalidation in the reconnect loop now goes through get_ssl_cache_key() to match the material-keyed cache.
The device reports enum-ish fields in mixed/upper case (e.g. PLAYING, GOOD). These are now normalized to stable lowercase strings before landing in HarborDeviceState.values, so consumers no longer need to lowercase them for enum options. The documented value sets are exported from the package root: SPEAKER_STATES (idle, muted, off, paused, playing, unknown) and STREAM_QUALITIES (excellent, fair, good, poor, unknown). Values outside these sets are still stored lowercased and logged as a warning once per value, so the option lists can be extended when new values appear.
|
Warning Review limit reached
Next review available in: 47 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughIntroduces PEM-string or file-path based camera certificate configuration in ChangesCamera cert/enum and MQTT debounce changes
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant Transport
participant HarborMQTTClient
participant GraceTask as _disconnect_after_grace
participant Listener as on_connection_change
Transport->>HarborMQTTClient: _set_connected(True)
HarborMQTTClient->>Listener: notify connected=True
Transport->>HarborMQTTClient: _set_connected(False)
HarborMQTTClient->>GraceTask: schedule grace period task
alt reconnect within grace period
Transport->>HarborMQTTClient: _set_connected(True)
HarborMQTTClient->>GraceTask: cancel pending task
else grace period elapses
GraceTask->>Listener: notify connected=False
end
HarborMQTTClient->>HarborMQTTClient: stop() cancels/flushes pending task
sequenceDiagram
participant Caller
participant get_ssl_context
participant get_ssl_cache_key
participant build_ssl_context
Caller->>get_ssl_context: request SSL context for camera_config
get_ssl_context->>get_ssl_cache_key: derive cache key from PEM or path material
get_ssl_context->>build_ssl_context: build on cache miss
build_ssl_context-->>get_ssl_context: SSLContext (from PEM temp files or paths)
get_ssl_context-->>Caller: cached or newly built SSLContext
Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization has reached its limit of developer seats under the Pro Plan. For new users, CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please add seats to your subscription by visiting https://app.coderabbit.ai/login.If you believe this is a mistake and have available seats, please assign one to the pull request author through the subscription management page using the link above. Comment |
There was a problem hiding this comment.
Pull request overview
Adds in-memory PEM certificate support (to avoid requiring callers to persist private keys to disk) and updates MQTT/camera behavior to better support integrations (HA) via more stable connection-state signaling and normalized camera state values.
Changes:
- Extend
HarborCameraConfigto acceptcert_pem/key_pemand validate that a complete certificate pair is provided. - Add SSL-context cache keying via certificate material (
get_ssl_cache_key) and support building anSSLContextfrom PEM strings by staging into a private temp directory. - Add debounced MQTT connection-change notifications and normalize certain camera enum state fields to lowercase, exporting known-value sets.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_mqtt.py | Adds tests for debounced connection-change reporting and stop-time disconnect flushing. |
| tests/test_config.py | Adds tests for config validation, SSL context building from PEM, and cache key behavior. |
| tests/test_camera_state.py | Adds tests ensuring camera enum state values are normalized and stable across updates. |
| tests/data/certs.py | Provides throwaway self-signed cert/key PEM fixtures for the test suite. |
| harbor/utils.py | Implements PEM-based SSL context build, private temp-file staging, and SSL cache keying by material. |
| harbor/mqtt.py | Adds connection-change debouncing and updates SSL cache invalidation logic. |
| harbor/devices/camera.py | Normalizes known enum state fields to lowercase and logs unexpected values once. |
| harbor/config.py | Makes cert path fields optional, adds PEM fields, and validates certificate-material completeness. |
| harbor/init.py | Re-exports SPEAKER_STATES and STREAM_QUALITIES. |
| .pre-commit-config.yaml | Excludes the test key fixture from detect-private-key. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Rebuild the SSL context inside the reconnect loop so cache invalidations in the error handlers actually take effect on the next attempt instead of reusing the initial context forever; unchanged material remains a cheap cache hit. - Write staged PEM temp files with explicit UTF-8 encoding and LF newlines to avoid platform-dependent newline translation on Windows. - Correct the HarborCameraConfig docstring to accurately describe the short-lived temp-file staging instead of claiming PEM data is never written to disk.
HarborCameraConfig gains cert_pem/key_pem fields so consumers can pass
certificate material directly instead of persisting private keys to
disk. cert_path/key_path/cert_dir are now optional; the config validates
that one complete pair is provided. Since ssl.SSLContext.load_cert_chain
only accepts file paths, PEM data is staged in a private temp directory
(0600 files) that is removed before build_ssl_context returns, so the
temp-file lifecycle is fully encapsulated in the library.
The ssl_context_cache is now keyed off the certificate material (SHA-256
of the PEM pair, or the path pair for path-based configs) via the new
get_ssl_cache_key(), so rotated credentials never reuse a stale context.
The test fixture in tests/data/certs.py is a throwaway self-signed cert
generated for the suite; it is excluded from detect-private-key.
Summary by CodeRabbit
New Features
Bug Fixes