Commit 8074b54
fix: decode special log records in ReadRange without status flags (#77)
Fixes ReadRange decoding when TREND_LOG contains special log records
(e.g., `log-interrupted`, `time-change`) that don't have status flags.
## Problem
When reading a `TREND_LOG` that contains a special log record, records
after it were silently missing from the result. The issue was that
`decodeRange` unconditionally consumed the status flags bytes after the
log-datum value, but special records don't have status flags. This
caused the decoder to read into the bytes of the next record and lose
sync.
## Solution
Updated `decodeRange` in `src/lib/asn1.ts` to:
- Validate closing tag 1 before consuming it
- Check for context tag 2 presence before decoding status flags (status
flags are **optional for ALL record types** per ASHRAE 135 §12.25)
- Add support for log-status choice (context tag 0 - special records
like `log-disabled`, `buffer-purged`, `log-interrupted`)
- Add support for time-change choice (context tag 9 - clock adjustment
records)
- Add `isLogStatus`, `logStatus`, and `isTimeChange` fields to
differentiate special records
## Type Changes
- Extracted `LogRecord`, `LogStatusFlags`, `LogRecordStatusFlags`
interfaces to `types.ts`
- Updated `ReadRangeAcknowledge.values` to use `LogRecord[]` instead of
`any[]`
- Added `LogRecordValue` union type to narrow `LogRecord.value`
- Added ASHRAE 135 §12.25 standard references to code comments
## Testing
- Added unit test for special log-status records without status flags
(mixed with normal records)
- Added unit test for time-change records without status flags
- All 204 unit tests pass
- Linting passes
- Build passes
- CodeQL security scan - no issues found
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>ReadRange bug when response contains a special log
record</issue_title>
> <issue_description>Hello
>
> When reading a `TREND_LOG` that contains a special log record (e.g.
`log-interrupted`), records after it are silently missing from the
result — no error, no warning.
>
> I spent some time debugging this with Wireshark and found that the raw
UDP packet is perfectly valid and complete. The issue is in
`decodeRange`.
>
> ### What's happening
>
> Special log records don't have status flags. A normal record ends
with:
> ```
> 1f 2a 04 00 ← closing tag 1, opening tag 2, BIT_STRING, closing tag 2
> ```
> A special record ends with just:
> ```
> 1f ← closing tag 1, nothing after
> ```
>
> But `decodeRange` unconditionally consumes 2 tags after the datum
value without validating their tag numbers. So it reads into the bytes
of the next record, shifts the offset by an unpredictable amount
(depends on the byte values that follow), and loses sync for everything
after.
>
> The behavior is non-deterministic — sometimes records after the
special one are silently dropped, sometimes the buffer appears
truncated. Took a while to figure out why the same code would behave
differently depending on which records were in the response.
>
> ### Reproduction
>
> ```javascript
> const response = await client.readRange(
> { address: '10.x.x.x:47808' },
> { type: bacnet.ObjectType.TREND_LOG, instance: 100101 },
> startIndex, 20,
> {}
> );
> // response contains fewer records than expected
> // no error thrown
> // Wireshark shows the full response is received correctly
>
> Thanks so much for the patch ;-)
>
> Thomas</issue_description>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> <comment_new><author>@robertsLando</author><body>
> Hi Thomas and thanks for your issue! WOuld you like to submit a PR?
</body></comment_new>
> </comments>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #76
<!-- START COPILOT CODING AGENT TIPS -->
---
💬 Send tasks to Copilot coding agent from
[Slack](https://gh.io/cca-slack-docs) and
[Teams](https://gh.io/cca-teams-docs) to turn conversations into code.
Copilot posts an update in your thread when it's finished.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: robertsLando <11502495+robertsLando@users.noreply.github.com>1 parent 3d5d609 commit 8074b54
4 files changed
Lines changed: 402 additions & 29 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
34 | 36 | | |
35 | 37 | | |
36 | 38 | | |
| |||
2421 | 2423 | | |
2422 | 2424 | | |
2423 | 2425 | | |
| 2426 | + | |
| 2427 | + | |
| 2428 | + | |
| 2429 | + | |
| 2430 | + | |
| 2431 | + | |
| 2432 | + | |
| 2433 | + | |
2424 | 2434 | | |
2425 | 2435 | | |
2426 | 2436 | | |
2427 | 2437 | | |
2428 | | - | |
| 2438 | + | |
2429 | 2439 | | |
2430 | 2440 | | |
2431 | 2441 | | |
2432 | | - | |
| 2442 | + | |
2433 | 2443 | | |
2434 | 2444 | | |
2435 | 2445 | | |
| |||
2474 | 2484 | | |
2475 | 2485 | | |
2476 | 2486 | | |
2477 | | - | |
| 2487 | + | |
| 2488 | + | |
| 2489 | + | |
| 2490 | + | |
| 2491 | + | |
| 2492 | + | |
| 2493 | + | |
| 2494 | + | |
| 2495 | + | |
| 2496 | + | |
| 2497 | + | |
| 2498 | + | |
2478 | 2499 | | |
2479 | 2500 | | |
2480 | 2501 | | |
2481 | | - | |
| 2502 | + | |
| 2503 | + | |
| 2504 | + | |
| 2505 | + | |
| 2506 | + | |
| 2507 | + | |
| 2508 | + | |
| 2509 | + | |
| 2510 | + | |
| 2511 | + | |
| 2512 | + | |
| 2513 | + | |
| 2514 | + | |
| 2515 | + | |
| 2516 | + | |
2482 | 2517 | | |
2483 | 2518 | | |
2484 | 2519 | | |
2485 | 2520 | | |
2486 | 2521 | | |
2487 | 2522 | | |
2488 | 2523 | | |
2489 | | - | |
| 2524 | + | |
| 2525 | + | |
2490 | 2526 | | |
2491 | 2527 | | |
2492 | 2528 | | |
2493 | 2529 | | |
2494 | 2530 | | |
2495 | 2531 | | |
2496 | 2532 | | |
2497 | | - | |
| 2533 | + | |
| 2534 | + | |
2498 | 2535 | | |
2499 | 2536 | | |
2500 | 2537 | | |
2501 | 2538 | | |
2502 | | - | |
| 2539 | + | |
| 2540 | + | |
| 2541 | + | |
| 2542 | + | |
| 2543 | + | |
| 2544 | + | |
| 2545 | + | |
| 2546 | + | |
| 2547 | + | |
| 2548 | + | |
| 2549 | + | |
2503 | 2550 | | |
2504 | 2551 | | |
| 2552 | + | |
2505 | 2553 | | |
2506 | 2554 | | |
2507 | 2555 | | |
2508 | 2556 | | |
2509 | | - | |
2510 | | - | |
2511 | | - | |
| 2557 | + | |
| 2558 | + | |
| 2559 | + | |
| 2560 | + | |
2512 | 2561 | | |
2513 | 2562 | | |
2514 | 2563 | | |
2515 | | - | |
2516 | | - | |
2517 | | - | |
2518 | | - | |
2519 | | - | |
2520 | | - | |
2521 | | - | |
2522 | | - | |
2523 | | - | |
2524 | | - | |
| 2564 | + | |
| 2565 | + | |
| 2566 | + | |
| 2567 | + | |
| 2568 | + | |
| 2569 | + | |
| 2570 | + | |
| 2571 | + | |
| 2572 | + | |
| 2573 | + | |
| 2574 | + | |
| 2575 | + | |
| 2576 | + | |
| 2577 | + | |
| 2578 | + | |
| 2579 | + | |
| 2580 | + | |
| 2581 | + | |
| 2582 | + | |
| 2583 | + | |
2525 | 2584 | | |
2526 | 2585 | | |
2527 | 2586 | | |
2528 | | - | |
2529 | 2587 | | |
2530 | 2588 | | |
2531 | 2589 | | |
| |||
2535 | 2593 | | |
2536 | 2594 | | |
2537 | 2595 | | |
2538 | | - | |
| 2596 | + | |
| 2597 | + | |
2539 | 2598 | | |
2540 | | - | |
2541 | | - | |
| 2599 | + | |
| 2600 | + | |
| 2601 | + | |
| 2602 | + | |
| 2603 | + | |
| 2604 | + | |
| 2605 | + | |
| 2606 | + | |
| 2607 | + | |
| 2608 | + | |
| 2609 | + | |
| 2610 | + | |
| 2611 | + | |
| 2612 | + | |
| 2613 | + | |
| 2614 | + | |
| 2615 | + | |
| 2616 | + | |
| 2617 | + | |
| 2618 | + | |
2542 | 2619 | | |
2543 | 2620 | | |
2544 | 2621 | | |
2545 | 2622 | | |
2546 | | - | |
2547 | | - | |
| 2623 | + | |
| 2624 | + | |
| 2625 | + | |
| 2626 | + | |
2548 | 2627 | | |
2549 | 2628 | | |
2550 | 2629 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
112 | 115 | | |
113 | 116 | | |
114 | 117 | | |
| |||
170 | 173 | | |
171 | 174 | | |
172 | 175 | | |
173 | | - | |
| 176 | + | |
| 177 | + | |
174 | 178 | | |
175 | 179 | | |
176 | 180 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
742 | 742 | | |
743 | 743 | | |
744 | 744 | | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
| 752 | + | |
| 753 | + | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
| 786 | + | |
| 787 | + | |
| 788 | + | |
| 789 | + | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
745 | 816 | | |
746 | 817 | | |
747 | 818 | | |
748 | 819 | | |
749 | 820 | | |
750 | 821 | | |
751 | | - | |
| 822 | + | |
752 | 823 | | |
753 | 824 | | |
754 | 825 | | |
| |||
0 commit comments