Skip to content

Merge branch 'feature/cameras' into main - #259

Merged
cleithner-comcast merged 68 commits into
mainfrom
feature/cameras
Aug 5, 2026
Merged

Merge branch 'feature/cameras' into main#259
cleithner-comcast merged 68 commits into
mainfrom
feature/cameras

Conversation

@cleithner-comcast

Copy link
Copy Markdown
Contributor

No description provided.

cleithner-comcast and others added 30 commits May 27, 2026 18:07
Adds proposal, design, specs, and tasks for the SBMD v4 runtime
migration from YAML+mapper drivers to JavaScript handler-based drivers.

Capabilities:
- sbmd-v4-runtime: core runtime (eval, registration, dispatch, result builder)
- sbmd-v4-light-driver: light driver as proof of life
- observability-metrics: lightweight metric instruments with JSON dump
- sbmd-system: factory and driver changes (modified)
- sbmd-script-execution-limits: overall timeout, max deferral depth (modified)
- Move all .sbmd v3 spec files to specs/v3-pending/
- Skip non-light integration tests (pending v4 conversion)
- Make SBMD schema validation conditional on spec files existing
- Point sbmdParserTest at v3-pending/ directory
- Implement SbmdUtils.result() mutable builder in sbmd-utils.js:
  - dataModel.updateResource() (2/3/4-arg), dataModel.setMetadata()
  - storage.setPersistentData(), storage.setTransientData()
  - device.sendCommand(), device.writeAttribute()
  - device.requestCommand(), device.readAttribute() (deferred terminals)
  - log(), success(), error()
  - Terminal sealing prevents post-terminal operations
- Add 23 ResultBuilderTest unit tests (C++ harness via mquickjs)
- All 300 unit tests pass
- Add SbmdV4Registration.h — C++ data structures for v4 driver registrations:
  SbmdV4Alias, SbmdV4Supplements, SbmdV4ResourceHandler, SbmdV4Resource,
  SbmdV4Endpoint, SbmdV4DeviceHandler, SbmdV4Registration
- Add SbmdV4Loader.h/.cpp — two-pass .sbmd.js file evaluation:
  - InjectCaptureFunction: sets up SbmdDriver() and __sbmd_registration
  - ExtractConstants: text-scans for constants: block, brace-matches,
    evaluates as object literal, produces name→value pairs
  - LoadDriver: prepends var preamble, IIFE-wraps, evaluates, extracts
    registration metadata + handler JSValues
  - Reset __sbmd_registration on error paths (prevents cross-driver leaks)
- Add 23 SbmdV4LoaderTest unit tests covering:
  - Constants extraction (basic, hex, booleans, strings, empty, non-primitive rejection)
  - Full driver loading (metadata, aliases, endpoints, resources, handlers)
  - Error cases (missing name, double SbmdDriver call, no SbmdDriver call)
  - Cross-driver isolation via IIFE wrapping
- Note: mquickjs does not support computed property names ([expr]:)
  in object literals — drivers must use string literal keys
- All 323 unit tests pass
Add SbmdV4ResultExecutor::Parse() which walks the {ops, terminal} JSValue
returned by v4 handlers and extracts it into typed C++ structures:

- ResultOp variants: UpdateResource, SetMetadata, SetPersistentData,
  SetTransientData, Log
- ResultTerminal variants: Success, Error, SendCommand, WriteAttribute,
  RequestCommand, ReadAttribute

The parser extracts options (endpointId, timedInvokeTimeoutMs) from the
nested options object, keeps TLV payloads as base64 strings for later
decoding by the execution layer, and captures deferred handler JSValues
(onResponse/onError) for requestCommand/readAttribute terminals.

Unknown op types are skipped with a warning; unknown terminal types fail
the parse.

22 new tests covering all op types, terminal types, options parsing,
deferred handler extraction, operation ordering, and edge cases.

345/345 tests passing.
…roup 5)

Add SbmdV4Driver class that manages the v4 driver lifecycle:

- Metadata-only (inactive): registration data always available, handlers
  not GC-rooted. Source text retained for re-evaluation.
- Active: re-evaluates .sbmd.js file to get fresh handler JSValues,
  GC-roots them via JS_AddGCRef with stable std::list<JSGCRef> storage.
  Handlers are callable across GC cycles.
- Deactivate: releases all GC roots via JS_DeleteGCRef, resets handler
  JSValues to JS_UNDEFINED.

13 new tests: initial state, activation, handler invocation after
activation, double activate/deactivate safety, deactivation clears
handlers, metadata preserved, re-activation, minimal driver with no
handlers.

358/358 tests passing.
… Group 6)

Add SbmdV4DispatchTable that maps incoming Matter reports to handlers:

- Resolves alias names to (clusterId, elementId) dispatch keys
- Supports three priority levels: Specific (single alias), Multi
  (multiple aliases), Wildcard (no element ID — matches any in cluster)
- Lookup returns all matching handlers in priority order
- Separate tables for attribute, event, and command handlers

Integrate dispatch tables into SbmdV4Driver:
- Built automatically during Activate() from registration aliases
- Cleared during Deactivate()
- Accessible via GetAttributeDispatch/GetEventDispatch/GetCommandDispatch

Fix handler declaration format in driver tests to use object form
(matching the loader's expected format).

16 new dispatch tests: empty/single/multi/wildcard lookup, priority
ordering (all three levels), unknown alias handling, event/command
dispatch, clear, multiple handlers per key, plus 3 integration tests
with the driver lifecycle.

374/374 tests passing.
…erDeviceDriver

Task Group 9: Update SpecBasedMatterDeviceDriver for v4 runtime.

SbmdV4HandlerInvoker (new):
- BuildAttributeArgs/BuildResourceArgs: construct JS args objects
- InvokeHandler: call JS handler via mquickjs, parse result chain
- ExecuteOps: execute non-terminal ops (updateResource, setMetadata, log)

SpecBasedMatterDeviceDriver changes:
- New v4 constructor taking SbmdV4Driver* (non-owning)
- All metadata methods dispatch to v4 registration when IsV4()
- AddDevice: v4 path sets V4AttributeCallback, checks prerequisites
- DoRegisterResources: v4 path iterates registration endpoints/resources
- DoRead/Write/ExecuteResource: v4 path uses HandleV4ResourceOp
- DoSynchronizeDevice: v4 path seeds via v4 seed handlers
- HandleV4AttributeReport: dispatches attribute changes through tables
- ExecuteV4Terminal: handles sendCommand/writeAttribute terminals
- CheckPrerequisitesV4: evaluates v4 resource prerequisites

MatterDevice changes:
- Added V4AttributeCallback type and SetV4AttributeCallback()
- CacheCallback::OnAttributeChanged delegates to v4 callback when set
- Added WriteAttributeFromTlv() for v4 writeAttribute terminal
- Added friend class SpecBasedMatterDeviceDriver for access

Tests: 15 new handler invoker tests, 389/389 total passing.
Task Group 10: Update SbmdFactory for v4 runtime.

SbmdFactory changes:
- Split RegisterDriversFromDirectory into RegisterV3DriversFromDirectory
  (for .sbmd files) and RegisterV4DriversFromDirectory (for .sbmd.js files)
- V4 loading pipeline: read file → SbmdV4Loader::LoadDriver → create
  SbmdV4Driver → Activate → create SpecBasedMatterDeviceDriver(v4) →
  register with MatterDriverFactory
- Factory owns SbmdV4Driver instances (stored in v4Drivers vector) to
  ensure they outlive SpecBasedMatterDeviceDriver wrappers
- V4 drivers are activated immediately at startup (all drivers active)
- File discovery uses double extension check: .js extension + .sbmd stem

Also covers deferred tasks 5.4 (factory integration) and 5.5 (activation
at startup — simplified to activate-all for now).

Tests: 4 new factory tests (file loading, driver activation, file
discovery pattern, nonexistent directory). 393/393 total passing.
Task Group 12: Light Driver Conversion

light.sbmd.js (new):
- Complete v4 light driver with constants block for all cluster/attribute/
  command/resource IDs
- 13 supported device types matching v3 driver
- Endpoint 1 with isOn (seed+write) and currentLevel (optional, seed+write)
- Attribute handlers for OnOff and CurrentLevel with TLV decoding
- Write handlers: isOn sends On/Off commands, currentLevel sends
  MoveToLevelWithOnOff with percent-to-level conversion

SbmdFactory runtime initialization:
- Added mquickjs runtime initialization (Initialize + LoadBundle +
  InjectCaptureFunction) in RegisterV4DriversFromDirectory
- Fixed deadlock: LoadBundle internally takes the JS mutex on error
  paths, so callers must not hold it across the call
- Added v4RuntimeReady flag to avoid redundant initialization

SpecBasedMatterDeviceDriver fixes:
- Fixed TLV extraction in HandleV4AttributeReport: use TLVWriter::
  CopyElement instead of GetRemainingLength() (returns 0 for cache data)
- Fixed CheckPrerequisitesV4: use strtoul instead of std::stoul to
  avoid ASAN __cxa_throw CHECK failure in ASAN-preloaded builds

CMake:
- Added .sbmd.js file installation alongside .sbmd files

Tests: 393/393 unit tests passing. 3/3 light integration tests passing.
Convert all v3 YAML-based SBMD drivers to v4 JavaScript handler format:
- temperature-sensor, humidity-sensor, contact-sensor, occupancy-sensor
- water-leak-detector, air-quality-sensor, door-lock, thermostat
- ikea-timmerflotte (vendor-specific multi-endpoint driver)

Fix caching policy inversion in SpecBasedMatterDeviceDriver: resources
without read handlers now use CACHING_POLICY_ALWAYS (subscription-driven),
resources with read handlers use CACHING_POLICY_NEVER (driver-called).

Add read handler fallback that returns cached value when no JS handler
exists (safety net for CACHING_POLICY_ALWAYS resources).

Fix multi-endpoint resource routing in ikea-timmerflotte: humidity handler
uses explicit endpoint '1' in updateResource since the humidity cluster
lives on Matter endpoint 2 but the resource is registered on endpoint 1.

Remove pytest skip markers from 6 integration test files and fix test
ordering in ikea_timmerflotte_test.py (register listeners before
commissioning).

All 393 unit tests pass. Integration tests verified:
- light: 3/3, temperature: 2/2, humidity: 2/2
- thermostat: 8/8, thermostat_with_fan: 21/21, door_lock: 7/7
- ikea_timmerflotte: 4/4
Delete v3 SBMD parser (SbmdParser.h, SbmdParser.cpp) and its unit test
(sbmdParserTest.cpp). All drivers now use v4 JavaScript format.

Delete v3-pending/ staging directory containing all 10 original .sbmd
YAML driver files, replaced by .sbmd.js equivalents in specs/.

Delete schema/ directory (v2 and v3 JSON schemas for YAML validation).

Remove v3 SbmdUtils.Response helpers (value, error, invoke, write) from
sbmd-utils.js — v4 drivers use SbmdUtils.result() builder instead.

Remove RegisterV3DriversFromDirectory from SbmdFactory and its header
declaration. Consolidate directory validation into RegisterV4Drivers.

Remove yaml-cpp dependency from core/CMakeLists.txt (was only used by
SbmdParser). Remove SBMD schema validation build target and .sbmd file
install target.

SbmdSpec.h, ScriptResult.h/.cpp, and ScriptResultTest.cpp are retained
as they are shared infrastructure used by the v4 runtime.

392 unit tests pass (1 removed: sbmdParserTest). Integration smoke test
verified.
- Rename all SbmdV4* files/classes/methods to Sbmd* (17 file renames)
- Remove all v3/v4 version prefixes from symbols, comments, and logs
- Remove duplicate v3 code paths from SpecBasedMatterDeviceDriver
- Rename SbmdSpec.h types to SbmdSpec* prefix to avoid collision
- Update unit tests to use SbmdRegistration types directly
- Delete docs/SBMD-v3-legacy.md
- Clean SBMD.md title and references

392/392 unit tests pass.
Remove the entire v3 script-based SBMD runtime:

Source files deleted:
- SbmdScript.h, SbmdSpec.h — v3 spec/script interfaces
- ScriptResult.h/.cpp — v3 result handling
- quickjs/SbmdScriptImpl.h/.cpp — QuickJS v3 engine
- mquickjs/SbmdScriptImpl.h/.cpp — mQuickJS v3 engine

MatterDevice.h/cpp changes:
- Remove all Bind*Info() methods and binding maps
- Remove HandleResource{Read,Write,Execute}() v3 paths
- Remove ReadSeedValueFromAttribute/SeedResourceFromAttribute
- Remove v3 script-based OnAttributeChanged/OnEventData paths
- Remove v3 command response mapping (MapCommandExecuteResponse)
- Update SendCommandFromTlv to take direct fields instead of SbmdCommand
- Add cachedClusterFeatureMaps member with accessor

Test files deleted:
- SbmdScriptTest.cpp (2093 lines) — v3 script engine tests
- ScriptResultTest.cpp (452 lines) — v3 result tests
- MatterDeviceTest.cpp (206 lines) — v3 event tests

Test files updated:
- MatterDeviceTestHelpers.h — remove MockSbmdScript, v3 binding helpers
- MatterDeviceEndpointMapTest.cpp — remove OnAttributeChangedFanOutTest
- CMakeLists.txt — remove deleted test targets

256/256 unit tests pass.
Implement requestCommand and readAttribute deferred terminals that park
resource operations and resume them when device responses arrive.

MatterDevice changes:
- Add SendCommandWithCallbacks() for deferred command invocation
- Extend CommandContext with deferred onResponse/onError callbacks
- Update OnResponse/OnError/OnDone to route through deferred callbacks

SpecBasedMatterDeviceDriver changes:
- Add PendingOperation struct with GC-rooted handlers, match criteria,
  overall deadline, and deferral depth counter
- Implement ExecuteRequestCommand() — sends command, parks promise,
  registers pending operation with deferred callbacks
- Implement ExecuteReadAttribute() — reads from cache, calls onResponse
  handler, continues chain
- Implement HandleDeferredCommandResponse() — encodes response TLV as
  base64, invokes onResponse handler, continues chain
- Implement HandleDeferredCommandError() — invokes onError handler
- Implement ContinueDeferredChain() — handles re-arming (new
  requestCommand/readAttribute), immediate terminals (success/error/
  sendCommand/writeAttribute), depth and deadline enforcement
- Implement CompletePendingOperation() and ReleasePendingGcRoots()

SbmdHandlerInvoker changes:
- Add BuildCommandResponseArgs() for deferred command responses
- Add BuildAttributeReadResponseArgs() for deferred attribute reads
- Add BuildDeferredErrorArgs() for timeout/error callbacks

Tests (9 new, 265/265 total):
- BuildCommandResponseArgs with data and null data
- BuildAttributeReadResponseArgs
- BuildDeferredErrorArgs (timeout and commandFailed)
- InvokeDeferredOnResponseHandler end-to-end
- InvokeDeferredOnErrorHandler end-to-end
- InvokeDeferredOnResponse returning requestCommand (chaining)
- InvokeDeferredReadAttributeResponse end-to-end
…TG6.2-6.3)

Add supplements support that pre-fetches declared attribute and resource
values before calling handler functions, delivering them as
args.supplements.attributes and args.supplements.resources.

SbmdHandlerInvoker changes:
- Add AttributeSupplementFetcher and ResourceSupplementFetcher callback
  types for testable data fetching
- Add AddSupplements() — builds args.supplements JS object from
  SbmdSupplements declarations using fetcher callbacks. Empty supplements
  are a no-op. Missing values are set to null.

SpecBasedMatterDeviceDriver changes:
- Add MakeAttrFetcher() — resolves alias names via the driver's alias
  map, reads TLV from MatterDevice data cache, returns base64-encoded
  values
- Add MakeResFetcher() — parses endpoint/resource paths, reads values
  via deviceServiceGetResourceById()
- Wire AddSupplements into all three handler invocation paths:
  InvokeSeedHandler (resource seed), HandleResourceOp (resource
  read/write/execute), HandleAttributeReport (attribute report handlers)

Unit tests (7 new, 272 total):
- AddSupplementsEmpty: no-op when supplements are empty
- AddSupplementsAttributesOnly: attribute values keyed by alias name
- AddSupplementsResourcesOnly: resource values keyed by path
- AddSupplementsBothAttributesAndResources: combined supplements
- AddSupplementsMissingValuesAreNull: unfetchable values become null
- SupplementsAccessibleFromHandler: end-to-end handler reads supplements
- SupplementsNullHandledByHandler: handler null-checks work correctly

Also updates tasks.md checkboxes for TG3.2, TG8, TG13, TG14.
All five resources (airQuality, temperature, humidity, co2Concentration,
pm25Concentration) are populated by attribute handlers that fire when the
device data cache is primed at startup and on every subsequent attribute
report. Seed handlers are only needed for event-driven resources that
cannot be replayed from the attribute cache. Since these resources are
all attribute-driven, the seed handlers were redundant overhead.
Remove seed handlers from contact sensor, door lock, humidity sensor,
light, occupancy sensor, temperature sensor, thermostat, and water leak
detector SBMD drivers.

These resources are all populated by attribute handlers, and those
handlers are invoked when the initial device data cache is primed at
startup as well as on subsequent attribute reports. Seed handlers are
only needed for resources whose state is populated by runtime events and
cannot be reconstructed from the attribute cache.

This keeps startup initialization efficient by relying on the initial
cache processing path and avoids unnecessary placeholder or default
resource writes before real attribute values arrive.
Remove 'dynamic' and 'emitEvents' from mode arrays in all .sbmd.js specs
since these are now on by default. Authors use 'static' or 'noEvents' to
opt out.

- ConvertModesToBitmask starts with DYNAMIC|DYNAMIC_CAPABLE|EMIT_EVENTS
  set and returns std::optional<uint8_t> to reject unsupported modes
- Remove redundant mode strings from all 10 driver specs and test fixture
- Clean stale v3 reference in docs/SBMD.md and door-lock comment
…ilder extraction

Storage implementation (openspec: sbmd-storage):
- Add persistentData[] and transientData[] to SbmdSupplements struct
- Parse persistentData/transientData arrays in SbmdLoader::ExtractSupplements
- Add PersistentDataFetcher, TransientDataFetcher, TransientDataSetter typedefs
- Extend AddSupplements to build args.supplements.persistentData and
  args.supplements.transientData JS objects from fetcher callbacks
- Wire setPersistentData op to deviceServiceSetMetadata
  (URI: /devices/{uuid}/metadata/sbmd.{key})
- Implement transient storage as in-memory map with TTL-based lazy expiry
  on SpecBasedMatterDeviceDriver (per-device scoping)
- Wire setTransientData op to driver's transient store via TransientDataSetter
- Add ttlSecs (uint32_t) to SetTransientData struct and JS builder
- Remove Sbmd.getPersistentData()/getTransientData() from docs — all storage
  reads go through supplements only

updateResource metadata wiring:
- Change JS builder from op.options to op.metadata = JSON.stringify(d)
- Add std::optional<std::string> metadata to UpdateResource struct
- Parse metadata string in SbmdResultExecutor
- In ExecuteOps, parse metadata JSON string to cJSON* and pass to
  updateResource() C function for the BCoreResourceUpdatedEvent

Result builder extraction:
- Extract ResultBuilder into separate sbmd-result.js loaded after sbmd-utils.js
- Rename SbmdUtilsLoader to SbmdBundleLoader (loads both JS bundles)

SBMD.md documentation updates:
- Section 4.12: Add persistentData and transientData supplement types
- Section 5.1: Add persistentData and transientData to supplements table
- Section 7.1: Fix updateResource metadata param description
- Section 7.3: Rewrite storage section — reads via supplements, remove
  standalone getter functions, document ttlSecs on setTransientData
- Section 8: Fix handleLockAlarms example to use supplements instead of
  Sbmd.getPersistentData()

Known doc-vs-code discrepancies documented in tasks.md (items 11-19):
- requestCommand: doc shows 4-arg, code is 5-arg with separate deferred obj
- readAttribute: doc shows 3-arg, code is 4-arg with separate deferred obj
- Response callback: doc says 'handler', code uses 'onResponse'
- setMetadata: doc says 2-arg, code is 4-arg (resource field unused in C++)
- endpointId option undocumented on all device operations
- Several options documented but not implemented (timeoutMs, successValue,
  context, passthrough, matterCode)
- Sbmd.Tlv.TYPE and decodeStruct() undocumented

Tests: 154 passing (Sbmd + ResultBuilder)
…lue, and API cleanup

Wire context/matterCode through the deferred operation pipeline and clean up
the JS and C++ APIs based on doc-vs-code review (tasks 11-19).

Deferred handler context:
- requestCommand/readAttribute accept 'context' option, forwarded to
  onResponse/onError handlers as args.handlerContext
- Context JSValue is GC-rooted in PendingOperation and released on completion
- All BuildCommandResponseArgs, BuildAttributeReadResponseArgs, and
  BuildDeferredErrorArgs call sites pass context through

Error reporting:
- BuildDeferredErrorArgs accepts matterCode (int32_t), exposed as
  args.error.matterCode (number or null) in JS error handlers
- Command failure passes CHIP_ERROR code via error.AsInteger()

sendCommand successValue:
- sendCommand options accept 'successValue' string
- On successful send, sets *executeResponse optimistically (same semantics
  as .success(value))

requestCommand timeoutMs override:
- Per-operation timeoutMs overrides driver defaultTimeoutMs and system default
  for the pending operation deadline

API simplification:
- requestCommand changed from 5-arg to 4-arg form: payload is optional 3rd
  arg, options detected via 'var opts = options || payload' pattern
- readAttribute changed from 4-arg to 3-arg form (options as 3rd arg)
- setMetadata changed from 4-arg to 2-arg form: setMetadata(name, value)
- Removed passthrough option from requestCommand (code, docs, specs)
- Removed timeoutMs from sendCommand/writeAttribute (deferred to future)
- Removed Sbmd.Tlv.decodeStruct() alias (use decode() directly)
- Fixed response handler args: args.command -> args.response for command
  response handlers (unsolicited command handlers keep args.command)
- Updated defaultTimeoutMs description to scope to deferred operations only

Documentation (SBMD.md):
- Updated section 6.2 example with args.response.data and handlerContext usage
- Fixed all response handler references (args.command -> args.response)
- Removed passthrough from options tables and runtime behavior descriptions
- Updated requestCommand/writeAttribute options tables

Tests:
- Added 9 new unit tests: ParseSendCommandWithSuccessValue,
  ParseRequestCommandWithContext, ParseReadAttributeWithContext,
  BuildCommandResponseArgsWithHandlerContext,
  BuildAttributeReadResponseArgsWithHandlerContext,
  BuildDeferredErrorArgsWithMatterCode,
  BuildDeferredErrorArgsMatterCodeNullWhenNotProvided,
  BuildDeferredErrorArgsWithHandlerContext,
  InvokeDeferredOnResponseHandlerWithContext
- All 163 tests passing
…MD handlers

Add the callback infrastructure and dispatch logic for events and unsolicited
commands, completing the pipeline from Matter SDK callbacks through to SBMD
handler invocation.

Event dispatch (full pipeline):
- Add EventCallback typedef + SetEventCallback() + eventCallback member to
  MatterDevice, mirroring the existing AttributeCallback pattern
- Wire MatterDevice::CacheCallback::OnEventData to call eventCallback instead
  of being a logging-only stub
- SpecBasedMatterDeviceDriver::AddDevice sets the event callback alongside the
  existing attribute callback
- Add HandleEvent() which mirrors HandleAttributeReport: looks up handlers via
  GetEventDispatch().Lookup(), base64-encodes TLV, builds args, invokes JS
  handlers, and executes result ops

Unsolicited command dispatch:
- Add HandleCommand() to SpecBasedMatterDeviceDriver for dispatching commands
  that arrive without a matching pending requestCommand
- HandleCommand receives pre-encoded TLV base64 so it can be called from the
  deferred response fallback path (to be wired in a follow-up)

JS args builders (SbmdHandlerInvoker):
- Add BuildEventArgs(): creates args.event = { clusterId, eventId, tlvBase64 }
- Add BuildCommandArgs(): creates args.command = { clusterId, commandId, tlvBase64 }
- Both follow the same pattern as BuildAttributeArgs

Unit tests (6 new, 169 total passing):
- BuildEventArgsHasEventFields, BuildEventArgsEmptyTlv, InvokeEventHandler
- BuildCommandArgsHasCommandFields, BuildCommandArgsEmptyTlv, InvokeCommandHandler
…prehensive tests

Add server-side incoming command support via Matter's CommandHandlerInterface,
allowing SBMD drivers to handle truly unsolicited commands (as opposed to
deferred command responses which already worked via requestCommand).

CommandHandlerInterface infrastructure (MatterDevice):
- CommandCallback typedef and SetCommandCallback() for routing incoming
  commands from the Matter SDK to the SBMD dispatch pipeline
- IncomingCommandHandler inner class implementing chip::app::CommandHandlerInterface,
  registered per-cluster with CommandHandlerInterfaceRegistry
- RegisterIncomingCommandHandler(clusterId) creates and registers a handler
  for a specific cluster; UnregisterIncomingCommandHandlers() cleans up all
  handlers (called from destructor)
- InvokeCommand() delegates to commandCallback and responds with Status::Success

SbmdDispatchTable (SbmdDispatch.h/cpp):
- GetRegisteredClusterIds() returns all unique cluster IDs with at least one
  handler registered, used to know which clusters need CommandHandlerInterface
  instances

SpecBasedMatterDeviceDriver wiring:
- AddDevice now sets commandCallback that base64-encodes TLV and calls
  HandleCommand(), then iterates GetCommandDispatch().GetRegisteredClusterIds()
  to register IncomingCommandHandler for each cluster

Test infrastructure:
- Created testing/resources/sbmd-specs/ for contrived test-only .sbmd.js drivers
- Added command-echo.sbmd.js test driver exercising specific, multi-alias,
  and wildcard command handlers with timeout configuration
- Wired test specs directory into integration test environment via semicolon-
  delimited _sbmd_dirs in base_environment_orchestrator.py
- Added SbmdHandlerInvoker.cpp to testSbmdDispatch CMake target (+ C API stubs)

Unit tests added (26 new tests, 195 total):
- SbmdDispatchTableTest: 5 tests for GetRegisteredClusterIds (empty, specific,
  wildcard, mixed, cleared-after-clear)
- SbmdDispatchDriverTest: 5 tests for command dispatch integration
  (CommandDispatchBuiltOnActivation, CommandDispatchClearedOnDeactivation,
  CommandHandlerInvocation with BuildCommandArgs round-trip,
  CommandWildcardDispatch priority ordering, AllThreeDispatchTables)
- SbmdDriverTest: 7 tests for command handler lifecycle and timeout config
  (CommandHandlerCallableAfterActivation, CommandHandlersUndefinedAfterDeactivation,
  DefaultTimeoutMsParsedFromMatterBlock, DefaultTimeoutMsAbsentWhenNotSpecified,
  ReportingIntervalsParsed, HandlerWithTimedInvokeTimeout,
  HandlerWithDeferredTimeoutAndTimedInvoke, HandlerWithDeferredReadAttributeTimeout)
- SbmdLoaderTest: 2 tests for timeout defaults (DefaultTimeoutAbsentWhenNotSpecified,
  ReportingDefaultsToZeroWhenAbsent)
- SbmdResultExecutorTest: 6 tests for timeout parsing permutations
  (ParseSendCommandTimedInvokeOnly, ParseRequestCommandWithTimedInvoke,
  ParseRequestCommandNoTimeoutMs, ParseReadAttributeNoTimeoutMs,
  ParseRequestCommandWithEndpoint, ParseReadAttributeWithEndpoint)
The seed handler for the locked resource was removed in 735d697 under
the assumption that RegenerateAttributeReport() would populate the
value from the attribute cache at commission time. However,
RegenerateAttributeReport() is scheduled asynchronously via
PlatformMgr().ScheduleWork() and runs AFTER deviceServiceDeviceFound()
returns — which is after the DEVICE_ADDED event has already been
emitted. This left the locked resource with a null value at the moment
clients first observe it.

Restore the seed handler so the locked resource is initialized to
'true' synchronously inside DoRegisterDriverResources, before
DEVICE_ADDED fires. The LockState attribute handler continues to keep
the resource current via subscription reports after commission.

Also fix stale test docstrings that referenced a removed v3 seedFrom
mapper mechanism and a nonexistent LockOperation event handler.
Change driverVersion from a semver-style string ('1.0.0') to a plain
uint32_t integer (1) across the entire SBMD system:

- SbmdRegistration.h: std::string → uint32_t
- SbmdLoader.cpp: GetStringProp → GetUint32Prop, update log format
- All 10 production .sbmd.js specs and 1 test spec: '1.0.0' → 1
- All unit test inline driver sources: "1.0" → 1
- Test assertions: string comparison → unsigned integer comparison
cleithner-comcast and others added 12 commits July 10, 2026 15:48
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Resolved all conflicts in favor of main (theirs) — main contains the SBMD v4 refactor which supersedes the older implementation on this branch.
…lback (#246)

Add a `kLargePayloadWithMRPFallback` transport capability that prefers a
TCP session
for large payloads (e.g. WebRTC SDP) and transparently falls back to
MRP/UDP for peers
without TCP support. Use it as the default for all controller
connections.

- Patch the Matter library: add the capability and its SessionManager/
OperationalSessionSetup handling, default GetConnectedDevice to it, and
fall back to
  UDP (with a log) when the active TCP connection pool is full.
- Allow large-payload CommandSender buffers when the session supports
them.
- Initiate GetConnectedDevice synchronously on the Matter thread in
ConnectAndExecute.
- Log the GetConnectedDevice error in DeviceDataCache.
- Raise CHIP_CONFIG_MAX_ACTIVE_TCP_CONNECTIONS from 4 to 50.
Add a 'volatile' resource mode that disables value caching
(CACHING_POLICY_NEVER) so updateResource emits an event on every call,
even when the value is unchanged. This supports event-only signaling
resources where identical values must each be delivered as distinct
events (e.g. repeated 'failed' notifications across sessions), which the
default cached behavior would suppress.

Wire it through the JSON schema, the script type definitions, and the
SBMD driver's caching-policy selection.
Add end-to-end support for a Matter WebRTC camera device driver.

- Add the WebRTCTransportRequestor cluster (Offer/Answer/ICECandidates/End
  commands, CurrentSessions attribute) to the Barton Matter library, defined
  in barton-library.zap and declared as an external cluster; the generated
  barton-library.matter is regenerated from the ZAP via the SDK generator.
- Configure a WebRTC requestor node and grant commissioned peers CASE/operate
  access to the requestor cluster via a shared ACL helper (refactored from the
  OTA-requestor-specific helper). Treat ACL entries with no targets as granting
  all clusters, per CHIP ACL semantics.
- Add the SBMD camera driver spec (camera.sbmd.js) with an abstract camera
  session endpoint and a WebRTC signaling endpoint (offer/answer/ICE resources
  and incoming command handlers), using the volatile mode for the event-only
  webrtcError resource.
- Restrict SBMD attribute/event/command handlers to alias binding (remove the
  inline clusterId form). This is a breaking schema change.
- De-version the SBMD schema surface: a single sbmd-spec-schema.json (no
  version in the filename), the validator renamed validate_sbmd_specs.py, and
  version history tracked in schema/CHANGELOG.md; schemaVersion is still
  validated against the schema's expected version. Update the schema, type
  definitions, specs, and docs.
- Add unit tests for the camera WebRTC driver, and extract the shared,
  driver-agnostic SBMD test harness (SbmdDriverTestBase) used by both the
  camera and handler-invoker tests.
# Conflicts:
#	docker/version
InvokeExecuteHandler/InvokeCommandHandler captured a raw JSValue handler
and then built args/supplements, which allocate and can relocate the
handler under mquickjs's moving GC, leaving the snapshot stale and making
JS_Call dispatch through a null pointer (SEGV). Root the handler in a
SafeJSValue and pass Get() at the call, mirroring production's Fn() usage.
Add a 'cs' camera stream command to the reference app that acts as the
in-container WebRTC peer to a Matter camera and serves the decoded
stream.

- cameraWebrtcClient: webrtcbin peer (host-only ICE), SDP offer/answer,
trickle ICE, H.264 passthrough muxed to fragmented MP4, connectivity
watchdog, and a keyframe (RTCP PLI) burst worker to start playback
quickly.
- cameraMediaServer: a small HTTP server that serves the live fragmented
MP4 to a browser via a Media Source Extensions player, replaying a
cached init segment to late joiners.
- cameraCategory / cameraDeviceSession: drive the Matter WebRTC
signaling handshake and route media to a file (file://) or the HTTP
server.
- Timestamp emitOutput/emitError and drain log/command output on a
dedicated thread so the prompt stays intact during blocking commands.
- Gate the command behind the BCORE_REFERENCE_CAMERA_SUPPORT CMake
option (enabled in the dev Linux platform); add the GStreamer stack to
the image and forward the stream port in the devcontainer.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Commit the OpenSpec artifacts for the camera / WebRTC work.

- Archive the `webrtc-endpoint-and-camera-stream-command` and
`camera-session-status-redesign` changes.
- Sync their deltas into the main specs:
- new `camera-session-lifecycle` (abstract endpoint, `stream` returns
`{protocol, entryPoint}`, no `sessionStatus`)
- `webrtc-signaling-endpoint` (five resources incl. `volatile`
`webrtcError`; `End`/async failures emit `webrtcError`; `sessionStatus`
requirement removed)
- `camera-stream-reference-command` (`--out <uri>` record/serve,
passthrough pipeline serving fragmented MP4 to a browser via MSE,
host-only ICE, connectivity timeout, updated build deps)
  - `sbmd-v4-runtime` (add the `volatile` resource mode)
# Conflicts:
#	core/test/CMakeLists.txt
#	docker/version
The main-merge that introduced SBMD runtime observability added
${SBMD_METRICS_SRC}/${SBMD_OBS_NOOP_SRC} (and BartonCommon::xhConcurrent) to the
other SBMD test targets but missed testSbmdCameraWebrtc, so it failed to link
(undefined MQuickJsRuntimeMetrics::* / observability* symbols).
…256)

The ep/webrtc negotiationRole resource is the camera's data model, so it
now reports the CAMERA's WebRTC role — offerer when the camera generates
the offer (SolicitOffer flow), answerer when it answers the client's
offer (ProvideOffer flow) — instead of the role the client must take. An
intrinsic cameraIsOfferer() predicate drives both the reported role and
the (unchanged) Matter flow selection. The reference app inverts the
reported value to choose its own role.

The Matter signaling sequence is unchanged. Driver, reference app, the
camera unit test (adds NegotiationRoleReportsCameraRole), and the
webrtc-signaling- endpoint / camera-stream-reference-command specs are
updated to the camera perspective; archives the openspec change.
@cleithner-comcast

Copy link
Copy Markdown
Contributor Author

Strategy is merge commit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges the feature/cameras branch into main, bringing in Matter/WebRTC camera-streaming support (requestor cluster + large-payload transport handling), SBMD schema updates (v5.0), reference-app camera streaming (GStreamer) behind a build flag, plus related CI/devcontainer/Docker and test-harness updates.

Changes:

  • Add WebRTC Transport Requestor cluster + camera-stream reference command support (GStreamer) and associated specs/docs.
  • Improve Matter transport/session behavior for large payloads (prefer TCP with fallback) and raise TCP connection limits.
  • Update SBMD to schema v5.0 (schema file + docs + typings), refactor SBMD unit-test support, and update validation wiring.

Reviewed changes

Copilot reviewed 76 out of 77 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
third_party/matter/barton-library/patches/0003-transport-add-kLargePayloadWithMRPFallback-capabilit.patch Adds a new transport payload capability and TCP→UDP fallback behavior in upstream Matter patchset.
third_party/matter/barton-library/linux/BartonProjectConfig.h.in Raises active TCP connection cap to match endpoint pool.
third_party/matter/barton-library/barton-common/BUILD.gn Adds external cluster for WebRTC Transport Requestor.
third_party/matter/barton-library/barton-common/barton-library.zap Adds WebRTC Transport Requestor cluster definition to ZAP output.
third_party/matter/barton-library/barton-common/barton-library.matter Extends Matter data model (WebRTC cluster definitions and endpoint wiring).
testing/resources/sbmd-specs/deferred-command-test.sbmd.js Minor JS cleanup in SBMD test driver (ternary formatting).
scripts/ci/validate_sbmd_v4_specs.py Removes old v4-only SBMD validator script.
reference/src/cameraWebrtcClient.h Adds GStreamer-backed WebRTC client API for camera streaming.
reference/src/cameraMediaServer.h Adds minimal HTTP media server interface for streaming fragmented MP4.
reference/src/cameraDeviceSession.h Adds camera session orchestration API over Barton resources.
reference/src/cameraDeviceSession.c Implements camera session lifecycle + signaling event handling via BCoreClient.
reference/src/cameraCategory.h Adds camera command category interface for reference app.
reference/src/barton-core-reference-io.c Improves prompt/log interleaving with a dedicated drain thread + terminal locking and timestamped output.
reference/src/barton-core-reference-app.c Registers the camera command category behind BCORE_REFERENCE_CAMERA_SUPPORT.
reference/CMakeLists.txt Adds BCORE_REFERENCE_CAMERA_SUPPORT option and links GStreamer/GIO when enabled.
openspec/specs/webrtc-signaling-endpoint/spec.md Adds/updates WebRTC signaling endpoint requirements (camera-perspective role semantics).
openspec/specs/sbmd-v4-runtime/spec.md Specifies volatile mode semantics for SBMD runtime (unconditional event emission).
openspec/specs/camera-stream-reference-command/spec.md Specifies the cameraStream/cs reference command behavior and lifecycle.
openspec/specs/camera-session-lifecycle/spec.md Specifies abstract camera endpoint lifecycle and stream return shape {protocol, entryPoint}.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/tasks.md Archives implementation tasks for negotiation-role contract inversion.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/specs/webrtc-signaling-endpoint/spec.md Archives delta spec for camera-perspective negotiation role.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/specs/camera-stream-reference-command/spec.md Archives delta spec for reference command role inversion.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/proposal.md Archives proposal for negotiation-role inversion.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/design.md Archives design notes for negotiation-role inversion.
openspec/changes/archive/2026-08-03-negotiation-role-camera-perspective/.openspec.yaml Archives OpenSpec metadata for the change.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/tasks.md Archives tasks for sessionStatus removal + webrtcError + volatile mode.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/specs/webrtc-signaling-endpoint/spec.md Archives delta spec for webrtcError and signaling error delivery.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/specs/sbmd-v4-runtime/spec.md Archives delta spec describing volatile resource mode.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/specs/camera-stream-reference-command/spec.md Archives delta spec updates for the reference streaming command.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/specs/camera-session-lifecycle/spec.md Archives delta spec for camera session lifecycle changes.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/proposal.md Archives proposal for camera session status redesign.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/design.md Archives design notes for sessionStatus removal and error propagation.
openspec/changes/archive/2026-07-16-camera-session-status-redesign/.openspec.yaml Archives OpenSpec metadata for the change.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/tasks.md Archives tasks for initial WebRTC endpoint + camera stream command.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/specs/webrtc-signaling-endpoint/spec.md Archives initial WebRTC endpoint spec delta.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/specs/camera-stream-reference-command/spec.md Archives initial reference command spec delta.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/proposal.md Archives proposal for initial WebRTC endpoint + command.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/design.md Archives design notes for the initial WebRTC endpoint/command work.
openspec/changes/archive/2026-07-13-webrtc-endpoint-and-camera-stream-command/.openspec.yaml Archives OpenSpec metadata for the change.
docs/SBMD.md Updates SBMD documentation to schema v5.0 and “aliases-only” handler binding.
docker/version Bumps docker image version.
docker/Dockerfile Adds GStreamer packages and builds Matter camera sample/controller binaries into the image.
core/test/src/SbmdHandlerInvokerTest.cpp Refactors tests onto shared SBMD test base/harness.
core/test/src/SbmdDriverTestSupport.cpp Adds shared SBMD C-stub recording implementation for tests.
core/test/src/SbmdDriverTestBase.h Adds shared SBMD test fixture utilities and assertion helpers.
core/test/CMakeLists.txt Wires new SBMD camera test and shared SBMD test support source.
core/src/subsystems/matter/Matter.h Refactors ACL helper declarations and formatting.
core/src/subsystems/matter/Matter.cpp Adds cluster-host detection, WebRTC ACL configuration, and related ACL helper refactor.
core/src/subsystems/matter/DeviceDataCache.cpp Improves connection error reporting and forwards subscription-established callback.
core/deviceDrivers/matter/sbmd/specs/water-leak-detector.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/thermostat.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/temperature-sensor.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/occupancy-sensor.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/light.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/ikea-timmerflotte.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/humidity-sensor.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/door-lock.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/contact-sensor.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/specs/air-quality-sensor.sbmd.js Updates SBMD driver schemaVersion to 5.0.
core/deviceDrivers/matter/sbmd/SpecBasedMatterDeviceDriver.cpp Adds support for volatile and accepts default-on modes as no-ops.
core/deviceDrivers/matter/sbmd/scriptCommon/sbmd-script.d.ts Updates typings for schema v5.0 and “aliases-only” handler definitions.
core/deviceDrivers/matter/sbmd/schema/sbmd-spec-schema.json Renames/updates schema to v5.0, adds volatile, and enforces mutually-exclusive mode pairs.
core/deviceDrivers/matter/sbmd/schema/CHANGELOG.md Adds v5.0 changelog entries (schema file naming, aliases-only, volatile, mode constraints).
core/deviceDrivers/matter/MatterDeviceDriver.cpp Makes connection initiation ordering deterministic via RunOnMatterSync.
core/deviceDrivers/matter/MatterDevice.cpp Enables large-payload command sending based on session capabilities and improves TLV error logs.
core/CMakeLists.txt Updates SBMD schema validation target to use the new validator script name.
config/cmake/platforms/dev/linux.cmake Enables camera stream support by default on dev linux platform.
api/c/src/barton-core-client.c Adds observability include (currently duplicated).
.github/skills/validate-sbmd/SKILL.md Updates skill instructions for new validator/schema file names.
.devcontainer/devcontainer.json Forwards camera media server port and sets env for X11 + GStreamer sink selection.

Comment thread api/c/src/barton-core-client.c
Comment thread core/src/subsystems/matter/Matter.h
Time-to-ready in CI lands at ~5.0-5.05s (SBMD driver load is the long
pole), so the 5s wait_for_client_to_be_ready timeout flakes. Bump to 10s.
Copilot AI review requested due to automatic review settings August 5, 2026 16:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 77 out of 78 changed files in this pull request and generated no new comments.

Suppressed comments (1)

api/c/src/barton-core-client.c:43

  • observability/observability.h is included twice, which is redundant and can slow compilation / increase include-order brittleness.
#include "icTypes/icLinkedList.h"
#include "observability/observability.h"
#include "icTypes/icLinkedListFuncs.h"
#include "observability/observability.h"

@cleithner-comcast
cleithner-comcast merged commit de70289 into main Aug 5, 2026
13 checks passed
@cleithner-comcast
cleithner-comcast deleted the feature/cameras branch August 5, 2026 18:24
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants