Skip to content

feat: enhance ZCL error handling and add OTA cluster attributes and commands#172

Merged
nozols merged 5 commits intomasterfrom
feature/ota
Mar 10, 2026
Merged

feat: enhance ZCL error handling and add OTA cluster attributes and commands#172
nozols merged 5 commits intomasterfrom
feature/ota

Conversation

@nozols
Copy link
Copy Markdown
Contributor

@nozols nozols commented Mar 6, 2026

  • OTA cluster: Fully implemented lib/clusters/ota.js with all spec-defined attributes (13), commands (8 client+server), and proper response structures including variant IMAGE_BLOCK_RESPONSE with encodeMissingFieldsBehavior:
    'skip'
  • ZCL error handling: Added ZCLError class to lib/util/index.js — allows throwing errors with a ZCL status code (e.g. WAIT_FOR_DATA) that propagates to the default response frame sent back to the device
  • Frame control fix: Cluster-specific responses now correctly set clusterSpecific: true on the response frame control, preventing mis-routing on the receiving end
  • encodeMissingFieldsBehavior support: ZCLStruct options (including encodeMissingFieldsBehavior) are now forwarded when building command and response arg types in Cluster.j

@nozols nozols requested review from Copilot and removed request for Copilot March 6, 2026 09:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 expands the Zigbee OTA Upgrade cluster implementation and improves ZCL command/response handling by enabling status-aware errors and ensuring cluster-specific responses are framed correctly. It also updates type generation to better represent ZCL status enums and optional-field encoding behavior.

Changes:

  • Add ZCLError to propagate ZCL status codes into Default Response frames, plus tests for status propagation/encoding.
  • Implement the OTA cluster with spec-defined attributes/commands and support encodeMissingFieldsBehavior: 'skip' for variant/optional fields.
  • Update response framing and type-generation to account for cluster-specific responses and status enum typing.

Reviewed changes

Copilot reviewed 11 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
lib/util/index.js Introduces ZCLError for status-aware errors.
lib/Endpoint.js Encodes ZCL status into Default Response; fixes clusterSpecific bit on responses.
lib/Cluster.js Forwards encodeMissingFieldsBehavior into ZCLStruct construction.
lib/BoundCluster.js Passes response metadata through to endpoint framing.
lib/clusters/ota.js Implements OTA attributes and commands (including variant responses).
scripts/generate-types.js Enhances TS generation (status enum aliasing, optionality rules, new exports).
index.d.ts Regenerated typings including OTA + ZCLError/bind() signatures.
index.js Exports ZCLError.
test/testZCLError.js Adds tests covering Default Response status propagation/encoding.
test/ota.js Adds tests for optional/variant field encoding behavior in OTA commands.
package.json / package-lock.json Bumps @athombv/data-types to support missing-field encoding behavior.
AGENTS.md Documents conventions for optional fields and server→client command exposure.
.gitignore Ignores .envrc.
Comments suppressed due to low confidence (1)

scripts/generate-types.js:306

  • ZCLNodeEndpoint.bind() now references BoundCluster, but BoundCluster is only declared inside the later declare module "zigbee-clusters" { ... } block. In TypeScript, names declared inside a module-augmentation block are not automatically in scope for the top-level declarations in the file, so this can make the generated index.d.ts fail to type-check (Cannot find name 'BoundCluster'). Fix by declaring/exporting BoundCluster (and ZCLError if needed) in the top-level module scope before it’s referenced, or by restructuring the .d.ts to avoid mixing top-level exports with a separate declare module block.
    attributes: Array<string | number>,
    opts?: { timeout?: number }
  ): Promise<{ [x: string]: unknown }>;

  writeAttributes(attributes?: object, opts?: { timeout?: number }): Promise<unknown>;

  configureReporting(attributes?: object, opts?: { timeout?: number }): Promise<void>;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

nozols and others added 2 commits March 6, 2026 10:54
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@nozols nozols merged commit 6afae08 into master Mar 10, 2026
3 checks passed
@nozols nozols deleted the feature/ota branch March 10, 2026 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants