Validate a local plugin build with Homebridge
Use this procedure after an implementation passes its hermetic contracts. Live validation supplements the test suite; it does not replace it and must not introduce real device or account data into the repository, issue tracker, or shared logs.
1. Record the build under test
From the plugin checkout:
pwd
git status --short --branch
git rev-parse HEAD
node --version
npm run verifyConfirm that pwd is the checkout Homebridge actually loads. If the service uses a global install, inspect the package path before replacing anything:
npm root --global
npm list --global @homebridge-plugins/homebridge-eufy-security --depth=0Do not infer the loaded version from the source checkout alone. The startup log must identify the plugin version after restart.
2. Restart Homebridge
Run these commands as the account that owns the Homebridge service and storage directory:
hb-service restart
hb-service viewhb-service restart performs a normal service restart. hb-service view shows a bounded recent log window and returns, which is preferable for a repeatable check. Use the streaming view only while actively reproducing a problem:
hb-service logsStop the streaming view with Ctrl+C; this does not stop Homebridge.
If restart fails, inspect service state before retrying:
systemctl status homebridge --no-pager
journalctl --unit homebridge --since "10 minutes ago" --no-pagerThe service name can differ on non-default installations. Pass the same --service-name value used when that Homebridge service was installed.
3. Check the Homebridge log
After restart, verify all of the following in hb-service view:
- Homebridge starts without an uncaught exception or plugin load error.
- The expected Homebridge Eufy version is loaded once.
- The runtime reaches
ready, or reports one explicit actionable condition. - No second SDK owner, repeated authentication loop, or accessory registration loop appears.
- The expected accessory containers are restored without duplicate registrations.
Do not paste complete logs into an issue. Record timestamps and retain only the smallest allowlisted, redacted excerpt needed to explain a failure.
4. Check the plugin JSONL log
The default V5 plugin log is relative to the Homebridge storage directory:
homebridge-eufy/logs/homebridge-eufy.jsonlFor the standard Linux service storage root, inspect a bounded recent section with:
tail -n 100 /var/lib/homebridge/homebridge-eufy/logs/homebridge-eufy.jsonlFollow it only during a short reproduction interval:
tail -f /var/lib/homebridge/homebridge-eufy/logs/homebridge-eufy.jsonlStop following with Ctrl+C. Rotated archives are in the same directory and should remain local unless a maintainer requests a specific bounded excerpt. The JSONL log can contain support-sensitive diagnostic context even though output is allowlisted; redact serials, device names, account IDs, addresses, URLs, tokens, keys, and session material before sharing anything.
5. Run an observation-first fleet check
Use a synthetic alias in notes rather than a real device name or serial. For each selected camera:
- Confirm the accessory appears once and its existing identity is retained.
- Open the live view and record whether first video arrives, its orientation, and approximate startup time.
- Verify video with normal source audio, then verify a camera known to provide no audio still shows uninterrupted video.
- Leave the view open long enough to cross one source GOP and one RTCP interval.
- Change Home app orientation or quality only if needed to cause a normal reconfigure request; verify the session remains usable.
- Close the view and verify the source and FFmpeg processes stop without repeated cleanup errors.
- Check both
hb-service viewand the bounded plugin JSONL interval for one start and one stop, with no sensitive payload or raw media output.
Opening a live stream wakes some battery cameras and consumes a bounded media budget. Do not toggle lights, alarms, locks, arming state, microphone settings, or other persistent controls unless that operation class has separate explicit approval.
6. Drive the same paths without a Home app
The harnesses in scripts/ pair a real HAP controller against a dedicated Homebridge instance, so live camera acceptance does not depend on adding a bridge in the Home app. Each script documents its own prerequisites and options in its file header; all of them need a Homebridge instance that is not paired to any controller and a hap-controller module installed outside this repository.
| Script | What it qualifies |
|---|---|
live-hap-snapshot-check.mjs | HomeKit snapshot requests, retained image policy, and on-disk modes |
live-hap-stream-check.mjs | Negotiated live streaming, measured on the decrypted wire |
live-hap-repeated-start-check.mjs | Repeated cold-start comparison with bounded lifecycle attribution |
live-hap-codec-matrix-check.mjs | One session per advertised profile and level, judged for exact coded fidelity |
live-hap-prepared-session-check.mjs | What a prepared session that never starts holds, and what releases it |
live-hap-disabled-camera-check.mjs | Live view, snapshots, and recovery for a camera that is turned off |
live-hap-operating-mode-check.mjs | The camera operating mode service, and camera-active carried to power |
live-hap-capture.mjs | One MP4 and still per camera when a maintainer must look at a frame |
live-hksv-check.mjs | Negotiated HomeKit Secure Video output, measured on the adapted fragments |
live-talkback-check.mjs | Audible return audio, one SDK handle, and isolated outbound media |
7. Record the result safely
Record only:
- commit and package version;
- Node.js, Homebridge, and plugin versions;
- synthetic camera alias and broad power class, such as wired or battery;
- observation class, such as H.264 video, H.265 video, audio present, or audio absent;
- timestamps, pass or fail, and an allowlisted condition code;
- whether Homebridge and plugin logs were checked.
Never record real serials, device names, addresses, account identifiers, tokens, keys, raw frames, or complete logs.