12 KiB
AquaCom approved test vectors
Fixture source policy: all vectors below are derived from Technical description – AquaCom – RTU level, Rev 1.6, ITT Flygt AB, July 2004 (AquaCom_RTU_1_6_eng.pdf) — evidence class SPECIFICATION (examples printed in the authoritative document). Vectors marked (synthetic) are constructed by the project to exercise edge cases the document's examples do not cover; they are labeled SYNTHETIC_FROM_SPECIFICATION and are subordinate to the source examples in authority. Each fixture becomes an automated test on implementation; fixtures are immutable once approved (implementation specification §64).
Notation. <SOH>=01H, <STX>=02H, <CR>=0DH, _=space (20H), !W = Wait byte (DC3, 13H). Checksums are per §2.4: sum of all bytes after SOH/STX up to (excluding) #, excluding Wait bytes, in a 16-bit signed integer; the transmitted value is the absolute value. The separator space between # and the checksum, and the trailing space before CR, are included in the summed range.
Checksum convention reminder (verified by the examples below): the summed range starts after SOH/STX — i.e. at the space that follows the start byte — and ends at the space immediately before the checksum digits. 32+83+67+79+32=293 for SCO (§2.4) confirms this: leading space 32, SCO 83+67+79, trailing space 32.
1. Checksum algorithm vectors
| ID | Telegram | Documented checksum | Verified | Source |
|---|---|---|---|---|
| AQ-CK-001 | <STX> SCO _ # _ 293 <CR> |
293 | yes | §2.4 |
| AQ-CK-002 | <SOH> 9 BRK _ # _ 376 <CR> |
376 | yes | §3.4.1.2 |
| AQ-CK-003 | <SOH> 0 ALO _ # _ 364 <CR> |
364 | yes | §2.2.3.3 |
| AQ-CK-004 | <STX> NDA _ # _ 275 <CR> |
275 | yes | §3.4.12.2 |
| AQ-CK-005 | <STX> SCO _ # _ 293 <CR> (RTU→CS OK answer) |
293 | yes | §3.4.2.3 |
| AQ-CK-006 | <STX> SCE 48 _ # _ 423 <CR> |
423 | yes | §3.4.2.3 |
| AQ-CK-007 | <SOH> 9 WCA 0 3 6 17 13 59 _ # _ 1031 <CR> |
1031 | yes | §2.2.3.3 |
| AQ-CK-008 | <SOH> 9 WCA 0 3 6 17 14 0 _ # _ 970 <CR> |
970 | yes | §2.2.3.3 |
| AQ-CK-009 | <STX> ALN T 0 0 0 0 _ # _ 719 <CR> |
719 | yes | §2.2.3.3 |
| AQ-CK-010 | <STX> OK _ # _ 218 <CR> |
218 | yes | §2.2.3.1, §3.4.1.2 |
| AQ-CK-011 | <SOH> 5 WCA 0 1 4 27 10 13 _ # _ 1011 <CR> |
1011 | yes | §3.4.1.3 |
| AQ-CK-012 | <STX> ALR 111 11 1 4 27 10 13 A T 0 0 0 0 B 31 _ # _ 1922 <CR> |
1922 | yes | §3.4.1.3 |
| AQ-CK-013 | <SOH> 5 ALO _ # _ 369 <CR> |
369 | yes | §3.4.1.3 |
| AQ-CK-014 | <SOH> 9 MCC 0 1 _ # _ 525 <CR> |
525 | yes | §3.4.3.2 |
| AQ-CK-015 | <SOH> 9 SLT 0 1 _ # _ 557 <CR> |
557 | yes | §3.4.9.2 |
| AQ-CK-016 | <SOH> 2 MAS 0 1 _ # _ 532 <CR> |
532 | yes | §3.4.5.3 |
| AQ-CK-017 | <SOH> 2 MAT 7 7 81 81 82 9003 _ # _ 1194 <CR> |
1194 | yes | §3.4.6.1 |
| AQ-CK-018 | <SOH> 9 MAT 7 9001 _ # _ 700 <CR> |
700 | yes | §3.4.6.2 |
| AQ-CK-019 | <SOH> 9 WGD 01 05 02 13 38 01 05 01 _ # _ 1433 <CR> |
1433 | yes | §3.4.11.3 |
| AQ-CK-020 | <SOH> 5 WGD 01 05 02 13 10 01 05 01 _ # _ 1419 <CR> |
1419 | yes | §3.4.11.2 |
| AQ-CK-021 | <SOH> 9 WGH 01 04 30 23 30 _ # _ 1039 <CR> |
1039 | yes | §3.4.12.2 |
| AQ-CK-022 | <SOH> 9 WGH 01 05 01 03 50 _ # _ 1038 <CR> |
1038 | yes | §3.4.12.2 |
| AQ-CK-023 | <SOH> 9 WGH 01 05 01 08 10 _ # _ 1039 <CR> |
1039 | yes | §3.4.12.2 |
| AQ-CK-024 | <SOH> 9 WGH 01 05 01 08 20 _ # _ 1040 <CR> |
1040 | yes | §3.4.12.2 |
| AQ-CK-025 | <SOH> 500 WGH 99 12 31 21 40 _ # _ 1147 <CR> |
1147 | yes | §3.7 |
| AQ-CK-026 | <STX> 9_ACT_#_369_<CR> (caller-ID, literal ACT) |
369 | yes | §2.2.3.3 |
| AQ-CK-027 | <STX> ALR 9 12 3 6 17 13 58 P T 0 0 0 0 A 27 _ # _ 1867 <CR> |
1867 | yes | §2.2.3.3 |
| AQ-CK-028 | <STX> ALR 9 12 1 4 27 10 26 P T 0 0 0 0 A 27 _ # _ 1856 <CR> |
1856 | yes | §3.4.1.2 |
| AQ-CK-029 | <SOH> 9 WCA 0 1 4 27 10 27 _ # _ 1020 <CR> |
1020 | yes | §3.4.1.2 |
| AQ-CK-030 | <SOH> 86 WGS P 0 ! 1 _ # _ 785 <CR> |
785 | yes | §2.2.3.1 — confirms the 0 ! two-field form |
| AQ-CK-031 | <SOH> 901 WGS P 0 ! 11 _ # _ 878 <CR> |
878 | yes | §3.4.10.2 |
| AQ-CK-032 | <SOH> 9 WGS P 2 F 1 _ # _ 771 <CR> |
771 | yes | §3.4.10.3 |
| AQ-CK-033 | <STX> 32000 654321 03 11 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 8050 8531 8532 _ # _ 2925 <CR> |
2925 | yes | §3.6.4 (Wait-free form of the WGS-answer pair) |
| AQ-CK-034 | <STX> 32000 65!W4321 03 11!W 0 0 0 0 0!W 1 2 3 4 5!W 6 7 8 9 1!W0 8050 853!W1 8532 _ # _ 2925 <CR> |
2925 | yes | §3.6.4 (Wait-laden form; identical checksum — proves Wait exclusion) |
| AQ-CK-035 | <STX> 7 9001 _ # _ 353 <CR> |
353 | yes | §3.4.7.2 (MAT fetch answer) |
Discrepant vector (documented checksum fails recomputation; see protocol-gaps.md AQ-GAP-006):
| ID | Telegram | Documented | Recomputed | Source | Note |
|---|---|---|---|---|---|
| AQ-CK-E1 | <SOH> 9 MAT 0 1 _ # _ 557 <CR> |
557 | 540 | §3.4.7.2 | fetch request; 557 is exactly the SLT fetch checksum (copy-paste error); not approved until PDF-confirmed |
The long multi-line examples (WGS answers 7679 / 3633 / 6967 / 6968; WGH answers 6922 / 6479 / 4220; WGD answers 4984 / 5632; MCC 24268 / 28910; SLT 14331 / 15425 / 15061) are candidates for wraparound coverage (sums > 65535) but cannot be recomputed from the markdown conversion — blockquote markers, \# escapes and line-wrap artifacts survive in the conversion and alter byte sums (AQ-GAP-005). They must be transcribed from the authoritative PDF before approval; until then they are not approved fixtures, and the synthetic vectors below cover the wraparound branches.
Synthetic algorithm-branch vectors (values computed and verified against the §2.4 algorithm):
| ID | Constructed telegram | Raw sum | Expected checksum | Why |
|---|---|---|---|---|
| AQ-CK-S1 | <STX> + 200 × A + _ # _ |
13064 | 13064 | no wraparound — round-trip baseline (synthetic) |
| AQ-CK-S2 | <STX> + 806 × z + _ # _ |
98396 | 32676 | sum > 65535 (16-bit wraparound and the ≥32768 absolute-value branch: 98396 mod 65536 = 32860 → 65536−32860 = 32676) (synthetic) |
| AQ-CK-S3 | <STX> + 550 × z + _ # _ |
67164 | 1628 | wraparound without the absolute-value branch (67164 mod 65536 = 1628 < 32768) — isolates the mod-65536 step (synthetic) |
| AQ-CK-S4 | <STX> SCO !W !W _ # _ 293 <CR> |
— | 293 | Wait bytes excluded from the sum (synthetic; superseded by source vector AQ-CK-033/034, retained as an algorithm-level unit test) |
2. Framing / session vectors
| ID | Scenario | Expectation | Source |
|---|---|---|---|
| AQ-FR-001 | CS dialled, RTU answers 6×OK 2.5 s apart; CS transmits request after first OK detected | conversation proceeds; the OK sequence is aborted by the incoming request | §2.2.3 |
| AQ-FR-002 | Answer arrives with Wait bytes embedded mid-token (…65!!4321…) |
strip !W before tokenization; checksum unchanged; parser output equals the Wait-free form |
§3.6.4 |
| AQ-FR-003 | BRK sent 3×, then hang-up | no answer expected; transport closes cleanly | §3.4.13 |
| AQ-FR-004 | Inter-character gap of 1 s inside a telegram | accepted (RTU-side limit is exactly 1 s; the gateway as CS uses 4–20 s whole-telegram timeout — §2.5) | §2.5 |
| AQ-FR-005 | Telegram data length > 4000 chars | rejected by framer; diagnostic generated (protocol max) | §2.3.2 |
3. Live data vectors (WGS)
| ID | Scenario | Expected decode | Source |
|---|---|---|---|
| AQ-WGS-001 | Fixed, request 901 WGS P 0 ! 11 → answer 23400 13885 01 22 0 0 0 0 0 3 0 3 3 4800 … 7 8111 |
ver=23400, prod=13885, Nal=1, alp=22, rem=0, 21 measuring points (alp−1, hypothesis — AQ-GAP-002), then 1 alarm code (8111). Decode via Nal; cross-check alp−1 diagnostically only |
§3.4.10.2 (checksum not yet approvable — AQ-GAP-005 long example) |
| AQ-WGS-002 | Request with control command then BRK | command suppressed by gateway (control OUT-OF-SCOPE); BRK still required after command-bearing WGS per §3.4.13 | §3.4.10, §3.4.13 |
| AQ-WGS-003 | Request with dir=! (ignore) |
no command dispatched; normal status answer | §3.4.10 |
4. Historical vectors (WGH)
| ID | Scenario | Expected decode | Source |
|---|---|---|---|
| AQ-WGH-001 | Request 9 WGH 01 04 30 23 30 → first answer of §3.4.12.2 (36 blocks, checksum 6922) |
36 blocks; first 1 4 30 23 35, last 1 5 1 3 50; 7 values per block; ! separators; requires AQ-GAP-003 hypothesis wiring |
§3.4.12.2 |
| AQ-WGH-002 | Continuation: request with last received block timestamp 9 WGH 01 05 01 03 50 → next answer |
stream resumes at 1 5 1 3 55; proves the watermark-resume protocol |
§3.4.12.2 |
| AQ-WGH-003 | Final continuation 9 WGH 01 05 01 08 20 → NDA |
NDA = normal end-of-stream, not an error; synchronization interval complete |
§3.4.12.2 |
| AQ-WGH-004 | Day rollover: block 1 4 30 0 0 follows block 1 4 30 23 55 |
the 00:00 block belongs to the next day (comment: "the last block for a day is the one with time stamp 00:00") — no date-field jump; the date increments; single-digit year/month/day accepted (1–2 byte fields) |
§3.4.12.2 |
| AQ-WGH-005 | Answer with embedded Wait bytes (§3.7 form) | parse identical to Wait-free form; checksum identical (§3.6.4 pair) | §3.7, §3.6.4 |
| AQ-WGH-006 | Request whose span exceeds 6 hours or 4000 chars | RTU truncates per §3.4.12.1 limits; gateway detects truncated stream by receiving fewer blocks than the requested interval and re-requests from the last block timestamp (at-least-once; dedup by §13/§23 rules) | §3.4.12.1 (synthetic scenario, specification-derived limit) |
| AQ-WGH-007 | Scaling: CFG point Max=0.01, Min=0, Max_input=10, raw 64786 |
Scaled = Raw×(Max−Min)/Max_input + Min → 64.786 — every vector decode must apply wagon scaling per station CFG, not raw values |
§3.4.12.3 (synthetic combination of documented formula + example raw value) |
5. Report vectors (WGD)
| ID | Scenario | Expected decode | Source |
|---|---|---|---|
| AQ-WGD-001 | Request 5 WGD 01 05 02 13 10 01 05 01 → answer 0 0 0 501 501 0 0 0 1506 1506 … |
per point: seg1..seg4 + sum; 10 reporting points per §3.4.11.4 CFG; scaling formula per point | §3.4.11.2, §3.4.11.4 |
| AQ-WGD-002 | Empty report day → all-zero answer (§3.4.11.3) | 64 zero values decoded as valid (not NDA); zero is a legitimate report value | §3.4.11.3 |
| AQ-WGD-003 | NDA answer |
report data for that day does not exist; mark interval missing, do not treat as failure | §3.4.11 |
6. Simulator scenario requirements (traceability targets)
The simulator (implementation specification §49) shall be able to replay every vector above plus inject: bad checksum (failing AQ-CK verification), truncated telegram (no #/CR), over-long telegram, inter-character stall of 1.5 s (RTU-side timeout breach), mid-telegram Wait flooding, duplicate WGH blocks across two answers (dedup regression per ARCHITECTURE.md §23), conflicting block re-transmission (REJECT_CONFLICT path per §13), and station clock set to a future date (timestamp-validation diagnostics per software-specification.md §26). The simulator must not share parsing code with the production decoder (§49).
Approval state: section 1 verified rows (AQ-CK-001–035) and section 2 approved as fixtures; AQ-CK-E1 pending AQ-GAP-006 (PDF confirmation); long examples pending AQ-GAP-005 (PDF transcription); sections 3–4 blocked by AQ-GAP-002/003 for full decode assertions (framing-level assertions may proceed; Nal-based decoding is documented and unblocked). Synthetic vectors subordinate to source vectors. Update this file's approval state when gaps close — never delete vectors.