Skip to content

fix: make ACTIVE_COV_SUBSCRIPTIONS readable (wire decoder into ReadProperty, decode multi-entry lists) - #91

Open
chrismoorhouse wants to merge 2 commits into
bacnet-js:masterfrom
mobiusflow:fix/active-cov-subscriptions
Open

chrismoorhouse wants to merge 2 commits into
bacnet-js:masterfrom
mobiusflow:fix/active-cov-subscriptions

Conversation

@chrismoorhouse

Copy link
Copy Markdown
Contributor

Summary

Fixes #90.

Reading the Device object's ACTIVE_COV_SUBSCRIPTIONS property (152) always failed with INVALID_DECODING for two independent reasons, fixed in two commits:

  1. Wire the decoder into ReadProperty acknowledgements. decodeCovSubscription() was only reachable via bacappDecodeContextApplicationData(), which no service calls. ReadProperty.decodeAcknowledge() now decodes the list entries directly, following the same special-case pattern already used for WEEKLY_SCHEDULE, EXCEPTION_SCHEDULE, EFFECTIVE_PERIOD and DATE_LIST; decodeCovSubscription is now exported from asn1.
  2. Decode lists with more than one entry. After time-remaining [3], the decoder treated any non-closing-tag byte as the optional cov-increment [4] — but in a multi-entry list that byte is the opening tag [0] of the next subscription, so decoding failed whenever a device reported two or more subscriptions. The decoder now only consumes cov-increment when the context tag is actually 4.

Verification

  • npm run build clean
  • npm run test:unit — 204/204 pass
  • Round-trip: two subscriptions encoded back-to-back via bacappEncodeApplicationData (tag 111) decode sequentially with correct process ids, object ids and lengths
  • Tested end-to-end against an MS/TP device behind a bacnet-stack router-mstp: readProperty(..., 152) now returns the full subscription list (previously INVALID_DECODING), enabling enumeration and cleanup of stale COV subscriptions

decodeCovSubscription was only reachable via
bacappDecodeContextApplicationData, which no service calls, so reading
the Device object's ACTIVE_COV_SUBSCRIPTIONS property always failed with
INVALID_DECODING: the generic application-tag decoder cannot parse the
context-tagged BACnetCOVSubscription structure.

Decode the list entries in ReadProperty.decodeAcknowledge, following the
same pattern as the weekly/exception schedule and calendar date list
special cases, and export decodeCovSubscription from asn1.
decodeCovSubscription treated any byte after timeRemaining that was not
a closing tag as the optional covIncrement [4]. In a list with multiple
subscriptions the next byte is the opening tag [0] of the next entry,
so decoding failed with INVALID_DECODING for any device reporting more
than one active subscription. Require the context tag to actually be 4
before consuming covIncrement.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 14:07

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.

Copilot review overview

🟡 Changes recommended

Closing-tag handling, tag validation, and regression test coverage need correction.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Fixes decoding of Device ACTIVE_COV_SUBSCRIPTIONS, including multi-entry lists.

Changes:

  • Adds COV subscription handling to ReadProperty acknowledgements.
  • Exports and corrects the COV subscription decoder.
File Description
src/​lib/​services/​ReadProperty.ts Decodes COV subscription lists.
src/​lib/​asn1.ts Exports the decoder and recognizes optional COV increments.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/lib/asn1.ts
Comment on lines +1958 to 1965
if (
len < apduLen &&
!isClosingTag(buffer[offset + len]) &&
decodeIsContextTag(buffer, offset + len, 4)
) {
result = decodeTagNumberAndValue(buffer, offset + len)
len += result.len
if (result.tagNumber !== 4) return undefined
Comment on lines +259 to +260
len += result.len
}
value: result.value,
} as ApplicationData)
len += result.len
} else if (property.id === PropertyIdentifier.ACTIVE_COV_SUBSCRIPTIONS) {

This branch has not been deployed

No deployments
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.

Reading ACTIVE_COV_SUBSCRIPTIONS always fails with INVALID_DECODING (decoder unreachable + cannot decode multi-entry lists)

2 participants