Skip to content

Admit the Wired Cam C31 T817L/10031 under a HomeBase 3 (0.28.0) - #219

Merged
keesmod merged 4 commits into
mainfrom
t817l-wired-cam-c31
Oct 5, 2026
Merged

keesmod merged 4 commits into
mainfrom
t817l-wired-cam-c31

Conversation

@keesmod

@keesmod keesmod commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Client 0.28.0 for one camera report. Refs keesmod/ha-eufy-cam#136, refs #35, refs #36, refs #57.

The report

A Wired Cam C31 arrives in the inventory as T817L with device type 10031, firmware 2.1.0.3, under a T8030 on 3.8.5.2. Bridge 0.8.29 with client 0.26.0 reports unsupported_device, because the pair is not in the profile allowlist. Type 10031 is also absent from the vendored catalogue, so a profile entry alone would admit a camera without commands or detection properties.

Change

  • Vendor catalogue (vendor/src/http/types.ts): DeviceType.WIRED_CAM_C31 = 10031 with its type label. Its property map contains GenericDeviceProperties and only the motion, person, person name, pet, vehicle, sound and crying detection states. These are custom_ states, so no setting or wire parameter is claimed. Battery and availability stay null, as for the other mains indoor cameras. Commands: live start/stop and recording download/cancel only. PTZ, presets, talkback, alarm and snooze are not registered. The type is in Device.isCamera(), so a push that a T8030 relays for it takes the HomeBase camera branch of the push normalization, as for the other Indoor cameras.
  • Live branch (vendor/src/http/station.ts): Device.isWiredCamC31() joins the existing HomeBase-controlled type 31/S350 branch: CMD_SET_PAYLOAD with nested CMD_START_REALTIME_MEDIA, mChannel, ClientOS, camera_type=0, entrytype=0, both account fields, public key and codec 1/2. Without it the camera falls through to the generic payload branch without mChannel, camera_type, entrytype or accountId. Stop, snapshot, recordings and cancel use the unchanged H3 paths. Whether the C31 acknowledges the plain H3 CMD_STOP_REALTIME_MEDIA is unverified: the cited gateway sends its stop inside the same payload envelope as its start.
  • Profile (src/device-profiles.ts): exactly T817L/10031, indoor family (the matrix's rule for outdoor wired cameras), h3-or-standalone, additional-H3 media policy. A standalone C31 reports standalone_transport_unverified.

Sources

  • Eufy's product page: Wired Cam C31, 360° pan/tilt, mains power, human/vehicle/pet/sound/cry detection, compatible with HomeBase 3 and HomeBase Mini, not HomeBase 2.
  • homebridge-eufy#1027: the same pair as its own station (standalone descriptor).
  • The MIT-licensed mscodemonkey/eufy-mega-security at 7980f34: its HomeBase-attached media start sends the same fields as the selected branch, and its T817L catalogue entry records live view and snapshots through a T8030 as tested by its maintainer on 2026-09-21. No code is copied. This is cited as a third-party result.

Tests

  • test/indoor.test.mjs and test/fixtures/indoor-media.mjs add the pair to the indoor family and shared H3 media suites: IndoorCamera factory, owner/channel, null battery and availability, motion/person/pet/sound/crying/vehicle support, push correlation, standalone rejection, the complete H.264 and H.265 start envelope with mChannel, stop, recordings, snapshot, cancellation.
  • test/device-profiles.test.mjs: exact pair, rejected T817L/10035 and /96, T817L121, T817, t817l and a trailing space, H3 and standalone relationships, media admission with the reported firmware, and exactly the four registered commands.
  • test/indoor.test.mjs: a push relayed by a T8030 for type 10031 normalizes exactly like one for type 104.
  • Mutation checks: without isWiredCamC31() in the branch, T817L: exact vendor H3 command branches and channel ownership fails. Without the isCamera() entry, the push normalization test fails.
  • Local: npm test 1391 passed, format:check, check_workflows.py, check_model_matrix.py (97 enum entries, digest repinned), scripts unittest (44) and release.py check pass.

No physical C31 was used. The reporter offered hardware tests on ha-eufy-cam#136.

Dependency audit

The required dependency-security audit fails on main and on every PR since GHSA-ch52-4w7c-c8xp (high, http-cache-semantics <= 4.2.0) was published. The second commit refreshes only that lockfile entry to 4.3.0, within cacheable-request's ^4.2.0 range. It reaches the client through got, which the push service uses without a response cache. The changelog records it.

Review

Blind review round 1 found no blocking issues. Its findings (doc counts and cause wording, the isCamera() gap in push normalization, the unverified stop, source markers, rollback note) are addressed in 693abe2.

Version 0.28.0, dated changelog. Rollback: 0.27.0.

🤖 Generated with Claude Code

keesmod and others added 4 commits October 5, 2026 09:30
Refs keesmod/ha-eufy-cam#136. The reporter's C31 arrives as T817L with
type 10031 under a T8030 on 3.8.5.2 and is rejected as unsupported_device,
because type 10031 is not in the vendored catalogue.

- Vendor: DeviceType.WIRED_CAM_C31 = 10031 with its label, a property map
  with only the motion, person, person name, pet, vehicle, sound and crying
  detection states, and the four media commands. Device.isWiredCamC31()
  joins the existing HomeBase-controlled type 31/S350 live branch, which
  sends mChannel, camera_type, entrytype and both account fields.
- Profile: exactly T817L/10031, indoor family, h3-or-standalone, H3 media.
- Tests: the indoor family suite and shared H3 media suite cover the new
  pair, plus a focused profile test for rejected variants, relationships,
  media admission and the registered commands.
- Docs: INDOOR.md section with sources, model matrix rows and repinned
  catalogue digest, regenerated DEVICE_PROFILES.md, NOTICE, CHANGELOG.

No physical C31 was used.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The required dependency audit fails on main and on every PR since the
high advisory for http-cache-semantics <= 4.2.0 was published. It reaches
the client through got and cacheable-request. The lockfile now resolves
4.3.0, within cacheable-request's ^4.2.0 range. No direct dependency or
range changes. The client uses got only for the push service, without a
response cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Device.isCamera() includes WIRED_CAM_C31, so a push that a T8030 relays
  for the C31 takes the HomeBase camera branch of the push normalization
  (a, msg_type, nick_name), as for the other Indoor cameras. A test compares
  the normalized message with type 104 and fails without the entry.
- 0.28.0 markers on the station branch and the instance predicate.
- INDOOR.md: the historical nine-model statements are scoped, the cause of
  the rejection is the profile allowlist, the plain H3 stop is unverified for
  the C31 and differs from the cited gateway's stop, and the isCamera entry
  is listed. Matrix wording follows the same cause.
- CHANGELOG: push normalization, unverified stop, and the rollback note that
  0.27.0's lockfile brings back http-cache-semantics 4.2.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…al models

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@keesmod
keesmod merged commit d925487 into main Oct 5, 2026
6 checks passed
@keesmod
keesmod deleted the t817l-wired-cam-c31 branch October 5, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant