Imported from kovalev-sergey/homebridge-sony-audio (
AGENTS.md). Install upstream withnpx skills add kovalev-sergey/homebridge-sony-audio. Copyright stays with the author.
AGENTS.md
Guidance for AI coding agents working in this repository.
Project
homebridge-sony-audio — a Homebridge dynamic platform plugin (TypeScript) that
discovers Sony audio devices (soundbars, AV receivers, wireless speakers) on the LAN via
SSDP and exposes them to HomeKit as a Television + TelevisionSpeaker accessory
(power, volume/mute, input source selection, remote keys).
It talks to the Sony Audio Control API over JSON-RPC-ish HTTP POST requests plus a WebSocket subscription for push notifications.
Commands
npm run build # tsc -> dist/
npm run lint # eslint src/**.ts --max-warnings=0 (must pass, zero warnings)
npm test # jest (unit tests in tests/*.spec.ts)
npm run test:coverage # jest --coverage
npm run watch # build + npm link + nodemon (rebuild & restart homebridge on src change)
npm start # build + run local homebridge in debug/insecure mode
- Unit tests live in
tests/*.spec.ts(jest + ts-jest, config injest.config.js, TS options intsconfig.spec.json). Shared fakes are intests/helpers/:logger.ts(mock HomebridgeLogger),mockHttp.ts(route-tableHttpClient),mockWs.ts(drivablewsreplacement),homebridge.ts(fakeAPI+PlatformAccessorybacked by real hap-nodejs services),hap.ts(resolves@homebridge/hap-nodejson Homebridge 2.x and falls back tohap-nodejson 1.x — always import HAP through this shim in tests) andfixtures.ts(Audio Control API payloads). - Network (
src/http.ts,ws,src/ssdp.ts) is always mocked in the device/discoverer specs;node:fs/promisesis exercised for real against aos.tmpdir()directory,http.spec.tsruns against a real localhttpserver, andssdp.spec.tsfakesdgram/osbecause multicast is not reliable in CI. tests/also contains two manual SSDP helper scripts (ssdp-client.ts,ssdp-server.ts) run ad hoc withts-node; they are not part of the jest run.ssdp-server.tsimpersonates a Sony device (answers M-SEARCH + serves a UPnP description over HTTP) so discovery can be checked end to end without hardware.- CI (
.github/workflows/build.yml) runsnpm run lint,npm testthennpm run buildon a matrix of Node 22/24 × Homebridge 1.11.x/2.3.x. - Always run
npm run lint && npm test && npm run buildbefore considering a change done.
Layout (src/)
| File | Role |
|---|---|
index.ts |
Entry point; registers the platform with Homebridge. |
settings.ts |
PLATFORM_NAME (SonyAudio) and PLUGIN_NAME constants. |
platform.ts |
SonyAudioHomebridgePlatform — cached accessory restore, discovery wiring, accessory publish/unregister. |
discoverer.ts |
Discoverer (EventEmitter) — SSDP search for urn:schemas-sony-com:service:ScalarWebAPI:1, fetches & parses device description XML, emits DiscoveryEvents.NewDeviceFound. |
ssdp.ts |
Client (EventEmitter) — minimal SSDP M-SEARCH client over node:dgram (one socket per external IPv4 interface). Replaces the node-ssdp package. |
http.ts |
HttpClient / httpGet — minimal HTTP client over node:http/node:https, reproducing the axios behaviour the plugin relied on (baseURL joining, JSON sniffing, non-2xx rejection, timeout: 0). Replaces the axios package. |
sonyDevice.ts |
SonyDevice (EventEmitter) — device model + all API calls, WebSocket notification subscriptions, emits DEVICE_EVENTS. |
sonyAudioAccessory.ts |
SonyAudioAccessory — maps SonyDevice state/events onto HAP services & characteristics. |
api.ts |
Pure declarations: request payload constants, response/notification types, API error classes. No I/O. |
sonyAudioAccessorySettings.ts |
Per-accessory persisted settings (input names / visibility) stored as JSON in Homebridge storage path via node:fs/promises. |
Data flow: Discoverer → SonyDevice → platform.publishDevice() → SonyAudioAccessory.
The SonyDevice instance is stored in PlatformAccessory<SonyDevice>.context.
Conventions
- TypeScript,
strict: truebutnoImplicitAny: false; target ES2018, CommonJS output todist/. - ESLint config in
.eslintrc: single quotes, 2-space indent, trailing commas on multiline,curlyalways,eqeqeq.no-consoleis a warning — use the HomebridgeLogger(this.log/this.platform.log) instead, neverconsole.*. - HomeKit-visible names must go through
getHomeKitName()(src/name.ts); HAP-NodeJS 2.x logs warnings for names that do not start/end with an alphanumeric character. - Lint runs with
--max-warnings=0, so warnings are effectively errors. - Files with very long import lines / API doc links start with
/* eslint-disable max-len */. - New Audio Control API calls: add the request constant and response interface to
api.ts(with a JSDoc link to the Sony docs), then a method onSonyDevice. - Keep HomeKit-facing logic in
sonyAudioAccessory.ts; keep protocol logic insonyDevice.ts. HOMEBRIDGE_SONY_AUDIO_DEVenv var is appended to the UDN when generating accessory UUIDs so a dev instance does not collide with the production one.config.schema.jsondefines the Homebridge UI config (plugin aliasSonyAudio, singular platform).- When adding support for a device model, also update the tables in
README.md.
Git flow
- Single long-lived branch:
master. Feature/fix work goes on short-lived branches merged via PR (CI runs on pushes tomasterand on PRs targetingmaster). - Dependency updates arrive as
dependabot/npm_and_yarn/*branches. - Commit messages follow Conventional Commits with these prefixes seen in history:
feat:,fix:,docs:,chore:(e.g.chore: version bump,fix: custom uuid). - Version bumps are their own commit (
chore: version bump) touchingpackage.json/package-lock.json.
Deployment flow
- Bump
versioninpackage.json(+ lock file) and commit aschore: version bump. - Merge to
master;Build and Lintworkflow must be green. - Create a GitHub release with a tag
vX.Y.Z(tags in repo:v1.0.8…v1.2.0). .github/workflows/publish.ymltriggers on release creation (orworkflow_dispatch): it re-runs lint+build on Node 22/24 against both Homebridge majors, thennpm publishto npm. Authentication uses npm trusted publishing (OIDC) — the job requestsid-token: writeand needs npm >= 11.5.1, there is noNPM_TOKENsecret, and npm attaches build provenance automatically. Publishing is gated on repo ==kovalev-sergey/homebridge-sony-audioand av*tag.prepublishOnlyrunslint+test+buildlocally as a safety net;.npmignorekeepssrc/, tests and dev config out of the published tarball (dist/is what ships).
Notes
dist/is generated — never edit it, never commit it.- Node >= 22 (
^22 || ^24 || ^26), homebridge^1.8.0 || ^2.0.0perengines. - Dependencies are intentionally lean:
ws,fast-xml-parser. Prefer Node built-ins over new packages (persistence usesnode:fs/promises, HTTP usessrc/http.tsonnode:http, discovery usessrc/ssdp.tsonnode:dgram).