run 16
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.pyc
|
||||
11
captures/rcp-hostid-a0-0080.txt
Normal file
11
captures/rcp-hostid-a0-0080.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
17:59:32.142 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
17:59:32.142 RX group=1 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
17:59:33.412 TX group=1 frame=2 len=006 00 00 A0 00 80 7A
|
||||
17:59:33.412 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
17:59:33.412 RX group=1 frame=2 raw 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5
|
||||
Anomalies: 1
|
||||
11
captures/rcp-hostid-a0-20d0.txt
Normal file
11
captures/rcp-hostid-a0-20d0.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 20 D0 0A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
17:59:47.538 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
17:59:47.538 RX group=1 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
17:59:48.803 TX group=1 frame=2 len=006 00 00 A0 20 D0 0A
|
||||
17:59:48.803 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 1: got 00, heartbeat offset 3 expected 80
|
||||
17:59:48.803 RX group=1 frame=2 raw 00 00 00 00 80 DA 07 80 E8 48 3A 47 07 80 E8 48 3A 47 07 80 E8 48 3A 47 07 80 E8 48 3A 47 07 80 E8 48 3A 47
|
||||
Anomalies: 1
|
||||
11
captures/rcp-hostid-a0-4030.txt
Normal file
11
captures/rcp-hostid-a0-4030.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 40 30 8A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:00:05.990 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:00:05.990 RX group=1 frame=1 heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
18:00:07.259 TX group=1 frame=2 len=006 00 00 A0 40 30 8A
|
||||
18:00:07.259 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
18:00:07.259 RX group=1 frame=2 raw 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB
|
||||
Anomalies: 1
|
||||
11
captures/rcp-hostid-a0-6030.txt
Normal file
11
captures/rcp-hostid-a0-6030.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 60 30 AA
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:00:30.467 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:00:30.467 RX group=1 frame=1 heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
18:00:31.737 TX group=1 frame=2 len=006 00 00 A0 60 30 AA
|
||||
18:00:31.737 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
18:00:31.737 RX group=1 frame=2 raw 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB 07 80 68 58 26 CB
|
||||
Anomalies: 1
|
||||
15
captures/rcp-hostid-announce-90-then-a0.txt
Normal file
15
captures/rcp-hostid-announce-90-then-a0.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 90 00 80 4A
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:00:45.254 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:00:45.254 RX group=1 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:00:46.313 TX group=1 frame=2 len=006 00 00 90 00 80 4A
|
||||
18:00:46.313 RX group=1 frame=2 ANOMALY 30 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
18:00:46.313 RX group=1 frame=2 raw 07 80 64 40 30 C9 07 80 64 40 30 C9 07 80 64 40 30 C9 07 80 64 40 30 C9 07 80 64 40 30 C9
|
||||
18:00:47.371 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:00:47.371 RX group=1 frame=3 ANOMALY 30 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 0 expected 00
|
||||
18:00:47.371 RX group=1 frame=3 raw 07 80 64 40 30 C9 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA
|
||||
Anomalies: 2
|
||||
14
captures/rcp-hostid-announce-9f-then-a0.txt
Normal file
14
captures/rcp-hostid-announce-9f-then-a0.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 9F 00 80 45
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:01:04.213 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:01:04.213 RX group=1 frame=1 ANOMALY 18 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 0 expected 00
|
||||
18:01:04.213 RX group=1 frame=1 raw 07 80 40 40 30 ED 00 00 00 00 80 DA 00 00 00 00 80 DA
|
||||
18:01:05.268 TX group=1 frame=2 len=006 00 00 9F 00 80 45
|
||||
18:01:05.268 RX group=1 frame=2 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:01:06.328 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:01:06.328 RX group=1 frame=3 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
14
captures/rcp-hostid-announce-af-then-a0.txt
Normal file
14
captures/rcp-hostid-announce-af-then-a0.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 AF 00 80 75
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:01:22.379 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:01:22.379 RX group=1 frame=1 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
18:01:23.438 TX group=1 frame=2 len=006 00 00 AF 00 80 75
|
||||
18:01:23.438 RX group=1 frame=2 ANOMALY 32 RX bytes; first mismatch at byte 0: got 00, heartbeat offset 4 expected 80
|
||||
18:01:23.438 RX group=1 frame=2 raw 00 00 07 80 0D 04 AB 7F 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA
|
||||
18:01:24.493 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:01:24.493 RX group=1 frame=3 heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
14
captures/rcp-hostid-announce-b7-then-a0.txt
Normal file
14
captures/rcp-hostid-announce-b7-then-a0.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 B7 00 80 6D
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:01:39.295 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:01:39.295 RX group=1 frame=1 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
18:01:40.351 TX group=1 frame=2 len=006 00 00 B7 00 80 6D
|
||||
18:01:40.351 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 1: got 00, heartbeat offset 3 expected 80
|
||||
18:01:40.351 RX group=1 frame=2 raw 00 00 00 00 80 DA 07 80 1B 08 D6 18 07 80 1B 08 D6 18 07 80 1B 08 D6 18 07 80 1B 08 D6 18 07 80 1B 08 D6 18
|
||||
18:01:41.409 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:01:41.409 RX group=1 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
15
captures/rcp-hostid-announce-bb-then-a0.txt
Normal file
15
captures/rcp-hostid-announce-bb-then-a0.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 BB 00 80 61
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:01:53.451 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:01:53.451 RX group=1 frame=1 heartbeat-compatible RX: 12 bytes, offset 0, 2 frames + 0 bytes
|
||||
18:01:54.508 TX group=1 frame=2 len=006 00 00 BB 00 80 61
|
||||
18:01:54.508 RX group=1 frame=2 ANOMALY 30 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
18:01:54.508 RX group=1 frame=2 raw 07 80 37 10 2C D6 07 80 37 10 2C D6 07 80 37 10 2C D6 07 80 37 10 2C D6 07 80 37 10 2C D6
|
||||
18:01:55.566 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:01:55.566 RX group=1 frame=3 ANOMALY 30 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 0 expected 00
|
||||
18:01:55.566 RX group=1 frame=3 raw 07 80 37 10 2C D6 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA
|
||||
Anomalies: 2
|
||||
13
captures/rcp-hostid-announce-ff-then-a0.txt
Normal file
13
captures/rcp-hostid-announce-ff-then-a0.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Sequence probe: 3 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 FF 00 80 25
|
||||
FRAME 3: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:02:08.775 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:02:08.775 RX group=1 frame=1 heartbeat-compatible RX: 12 bytes, offset 0, 2 frames + 0 bytes
|
||||
18:02:09.829 TX group=1 frame=2 len=006 00 00 FF 00 80 25
|
||||
18:02:09.829 RX group=1 frame=2 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:10.885 TX group=1 frame=3 len=006 00 00 A0 00 80 7A
|
||||
18:02:10.885 RX group=1 frame=3 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
Anomalies: 0
|
||||
20
captures/rcp-hostid-capblock-a-family.txt
Normal file
20
captures/rcp-hostid-capblock-a-family.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Sequence probe: 5 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 00 80 7A
|
||||
FRAME 3: 00 00 A1 00 80 7B
|
||||
FRAME 4: 00 00 A4 00 80 7E
|
||||
FRAME 5: 00 00 A5 00 80 7F
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:02:32.900 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:02:32.900 RX group=1 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:33.775 TX group=1 frame=2 len=006 00 00 A0 00 80 7A
|
||||
18:02:33.775 RX group=1 frame=2 ANOMALY 24 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
18:02:33.775 RX group=1 frame=2 raw 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5
|
||||
18:02:34.650 TX group=1 frame=3 len=006 00 00 A1 00 80 7B
|
||||
18:02:34.650 RX group=1 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:35.525 TX group=1 frame=4 len=006 00 00 A4 00 80 7E
|
||||
18:02:35.525 RX group=1 frame=4 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:36.399 TX group=1 frame=5 len=006 00 00 A5 00 80 7F
|
||||
18:02:36.399 RX group=1 frame=5 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
20
captures/rcp-hostid-capblock-b-family.txt
Normal file
20
captures/rcp-hostid-capblock-b-family.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Sequence probe: 5 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 B0 00 80 6A
|
||||
FRAME 3: 00 00 B1 00 80 6B
|
||||
FRAME 4: 00 00 B8 00 80 62
|
||||
FRAME 5: 00 00 BC 00 80 66
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
18:02:48.308 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:02:48.308 RX group=1 frame=1 heartbeat-compatible RX: 12 bytes, offset 0, 2 frames + 0 bytes
|
||||
18:02:49.181 TX group=1 frame=2 len=006 00 00 B0 00 80 6A
|
||||
18:02:49.181 RX group=1 frame=2 ANOMALY 30 RX bytes; first mismatch at byte 6: got 07, heartbeat offset 0 expected 00
|
||||
18:02:49.181 RX group=1 frame=2 raw 00 00 00 00 80 DA 07 80 EC 40 30 41 07 80 EC 40 30 41 07 80 EC 40 30 41 07 80 EC 40 30 41
|
||||
18:02:50.055 TX group=1 frame=3 len=006 00 00 B1 00 80 6B
|
||||
18:02:50.055 RX group=1 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:50.925 TX group=1 frame=4 len=006 00 00 B8 00 80 62
|
||||
18:02:50.925 RX group=1 frame=4 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:02:51.800 TX group=1 frame=5 len=006 00 00 BC 00 80 66
|
||||
18:02:51.800 RX group=1 frame=5 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
11
captures/rcp-hostid-prefix-0000-a0.txt
Normal file
11
captures/rcp-hostid-prefix-0000-a0.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
17:58:03.154 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
17:58:03.154 RX group=1 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
17:58:04.426 TX group=1 frame=2 len=006 00 00 A0 00 80 7A
|
||||
17:58:04.426 RX group=1 frame=2 ANOMALY 36 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
17:58:04.426 RX group=1 frame=2 raw 07 80 E8 40 30 45 07 80 E8 40 30 45 07 80 E8 40 30 45 07 80 E8 40 30 45 07 80 E8 40 30 45 07 80 E8 40 30 45
|
||||
Anomalies: 1
|
||||
10
captures/rcp-hostid-prefix-0080-a0.txt
Normal file
10
captures/rcp-hostid-prefix-0080-a0.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 80 A0 00 80 FA
|
||||
BASELINE heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
17:58:30.063 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
17:58:30.063 RX group=1 frame=1 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
17:58:31.333 TX group=1 frame=2 len=006 00 80 A0 00 80 FA
|
||||
17:58:31.333 RX group=1 frame=2 heartbeat-compatible RX: 19 bytes, offset 0, 3 frames + 1 bytes
|
||||
Anomalies: 0
|
||||
10
captures/rcp-hostid-prefix-8000-a0.txt
Normal file
10
captures/rcp-hostid-prefix-8000-a0.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Sequence probe: 2 frames x 1 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 80 00 A0 00 80 FA
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/1
|
||||
17:58:56.577 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
17:58:56.577 RX group=1 frame=1 heartbeat-compatible RX: 19 bytes, offset 0, 3 frames + 1 bytes
|
||||
17:58:57.850 TX group=1 frame=2 len=006 80 00 A0 00 80 FA
|
||||
17:58:57.850 RX group=1 frame=2 heartbeat-compatible RX: 23 bytes, offset 1, 3 frames + 5 bytes
|
||||
Anomalies: 0
|
||||
25
captures/rcp-hostid-repeat-a0.txt
Normal file
25
captures/rcp-hostid-repeat-a0.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
Sequence probe: 2 frames x 3 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 A0 00 80 7A
|
||||
BASELINE heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
BEGIN group 1/3
|
||||
18:03:49.510 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:49.510 RX group=1 frame=1 heartbeat-compatible RX: 13 bytes, offset 0, 2 frames + 1 bytes
|
||||
18:03:50.564 TX group=1 frame=2 len=006 00 00 A0 00 80 7A
|
||||
18:03:50.564 RX group=1 frame=2 ANOMALY 35 RX bytes; first mismatch at byte 0: got 00, heartbeat offset 4 expected 80
|
||||
18:03:50.564 RX group=1 frame=2 raw 00 00 00 80 DA 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5
|
||||
GROUP 1 TAIL ANOMALY 18 RX bytes; first mismatch at byte 0: got 07, heartbeat offset 3 expected 00
|
||||
GROUP 1 TAIL raw 07 80 68 40 30 C5 07 80 68 40 30 C5 07 80 68 40 30 C5
|
||||
BEGIN group 2/3
|
||||
18:03:53.892 TX group=2 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:53.892 RX group=2 frame=1 heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
18:03:54.952 TX group=2 frame=2 len=006 00 00 A0 00 80 7A
|
||||
18:03:54.952 RX group=2 frame=2 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
GROUP 2 TAIL heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 3/3
|
||||
18:03:58.282 TX group=3 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:58.282 RX group=3 frame=1 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:03:59.339 TX group=3 frame=2 len=006 00 00 A0 00 80 7A
|
||||
18:03:59.339 RX group=3 frame=2 heartbeat-compatible RX: 30 bytes, offset 0, 5 frames + 0 bytes
|
||||
GROUP 3 TAIL heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
Anomalies: 2
|
||||
31
captures/rcp-hostid-repeat-b0-b1.txt
Normal file
31
captures/rcp-hostid-repeat-b0-b1.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
Sequence probe: 3 frames x 3 group(s) on COM5 at 38400 8N1
|
||||
FRAME 1: 00 00 00 00 80 DA
|
||||
FRAME 2: 00 00 B0 00 80 6A
|
||||
FRAME 3: 00 00 B1 00 80 6B
|
||||
BASELINE heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
BEGIN group 1/3
|
||||
18:03:14.221 TX group=1 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:14.221 RX group=1 frame=1 heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
18:03:15.095 TX group=1 frame=2 len=006 00 00 B0 00 80 6A
|
||||
18:03:15.095 RX group=1 frame=2 ANOMALY 32 RX bytes; first mismatch at byte 0: got 00, heartbeat offset 4 expected 80
|
||||
18:03:15.095 RX group=1 frame=2 raw 00 00 07 80 6C 40 30 C1 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA 00 00 00 00 80 DA
|
||||
18:03:15.972 TX group=1 frame=3 len=006 00 00 B1 00 80 6B
|
||||
18:03:15.972 RX group=1 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
GROUP 1 TAIL heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
BEGIN group 2/3
|
||||
18:03:19.123 TX group=2 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:19.123 RX group=2 frame=1 heartbeat-compatible RX: 36 bytes, offset 0, 6 frames + 0 bytes
|
||||
18:03:19.995 TX group=2 frame=2 len=006 00 00 B0 00 80 6A
|
||||
18:03:19.995 RX group=2 frame=2 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:03:20.868 TX group=2 frame=3 len=006 00 00 B1 00 80 6B
|
||||
18:03:20.868 RX group=2 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
GROUP 2 TAIL heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
BEGIN group 3/3
|
||||
18:03:24.018 TX group=3 frame=1 len=006 00 00 00 00 80 DA
|
||||
18:03:24.018 RX group=3 frame=1 heartbeat-compatible RX: 36 bytes, offset 0, 6 frames + 0 bytes
|
||||
18:03:24.891 TX group=3 frame=2 len=006 00 00 B0 00 80 6A
|
||||
18:03:24.891 RX group=3 frame=2 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
18:03:25.767 TX group=3 frame=3 len=006 00 00 B1 00 80 6B
|
||||
18:03:25.767 RX group=3 frame=3 heartbeat-compatible RX: 24 bytes, offset 0, 4 frames + 0 bytes
|
||||
GROUP 3 TAIL heartbeat-compatible RX: 18 bytes, offset 0, 3 frames + 0 bytes
|
||||
Anomalies: 1
|
||||
@@ -3609,3 +3609,271 @@ Interpretation:
|
||||
- Best current model: these are legitimate outer-table queries whose returned
|
||||
payload can still depend on selector context, prior sequence, or exactly when
|
||||
in the panel's internal state machine they are sampled.
|
||||
|
||||
## Host Identity / Capability Exchange Lead Ladder
|
||||
|
||||
Goal:
|
||||
|
||||
- Test whether the CCU is expected to identify itself before asking for
|
||||
capability/state blocks.
|
||||
- Separate "query selector/page" behavior from "host identity/session setup"
|
||||
behavior.
|
||||
- Check whether a short query burst behaves more like a capability poll than a
|
||||
single one-shot request.
|
||||
|
||||
Tooling:
|
||||
|
||||
- Use `scripts/serial_sequence_probe.py` for fixed multi-frame sequences where
|
||||
the canonical primer stays constant and only later frames vary.
|
||||
- Use `scripts/serial_primer_candidate_sweep.py` when only a simple
|
||||
`primer -> candidate` pair is needed.
|
||||
|
||||
### Test HI1: Prefix Variation On A Stable Query
|
||||
|
||||
Keep the known-good primer fixed and vary only the prefix bytes of the `A0`
|
||||
query frame. If the response changes, the host prefix bytes may carry CCU
|
||||
identity, addressing, or mode information rather than being ignored padding.
|
||||
|
||||
Power-cycle before each run.
|
||||
|
||||
```powershell
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0000-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 80 A0 00 80 FA" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0080-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "80 00 A0 00 80 FA" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-8000-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "07 80 A0 00 80 FD" --read-after-frame 1.2 --log captures/rcp-hostid-prefix-0780-a0.txt
|
||||
```
|
||||
|
||||
What to watch for:
|
||||
|
||||
- Same `A0` block as baseline: prefix bytes probably are not the missing host
|
||||
identity on their own.
|
||||
- Different structured block: prefix bytes likely select host identity, page,
|
||||
or role.
|
||||
- Heartbeat only: that prefix pair may be invalid or reserved.
|
||||
|
||||
### Test HI2: State/Value Variation On A Stable Query
|
||||
|
||||
Keep the canonical prefix and command byte, but vary the state/value fields on
|
||||
the `A0` query. This checks whether the host is supposed to present status or
|
||||
capability bits in fields that we have mostly left at `00 80`.
|
||||
|
||||
Power-cycle before each run.
|
||||
|
||||
```powershell
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-0080.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 20 D0 0A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-20d0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 40 30 8A" --read-after-frame 1.2 --log captures/rcp-hostid-a0-4030.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 60 30 AA" --read-after-frame 1.2 --log captures/rcp-hostid-a0-6030.txt
|
||||
```
|
||||
|
||||
What to watch for:
|
||||
|
||||
- Same `A0` block every time: host state/value fields may be ignored here.
|
||||
- Different block family or different returned value bytes: these fields may be
|
||||
host-presented capability/status bits.
|
||||
- LCD/LED changes without a different serial block: possible session-state side
|
||||
effect rather than a simple table read.
|
||||
|
||||
### Test HI3: Primer -> Host-Announce -> Query
|
||||
|
||||
Try likely selector/identity-looking bytes as a middle frame before the stable
|
||||
`A0` query. This is the direct "CCU says who it is first" test.
|
||||
|
||||
Power-cycle before each run.
|
||||
|
||||
```powershell
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 90 00 80 4A" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-90-then-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 9F 00 80 45" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-9f-then-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 AF 00 80 75" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-af-then-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B7 00 80 6D" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-b7-then-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 BB 00 80 61" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-bb-then-a0.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 FF 00 80 25" --frame "00 00 A0 00 80 7A" --read-after-frame 1.0 --log captures/rcp-hostid-announce-ff-then-a0.txt
|
||||
```
|
||||
|
||||
What to watch for:
|
||||
|
||||
- Middle frame gets heartbeat only, third frame still returns plain `A0` block:
|
||||
the announce byte probably is not sufficient.
|
||||
- Middle frame changes the later `A0` response: strong evidence for a
|
||||
host-identity/selector stage.
|
||||
- Middle frame alone produces a new block: it may itself be a readable
|
||||
capability/identity query rather than a pure host announce.
|
||||
|
||||
### Test HI4: Capability-Poll Block
|
||||
|
||||
Send a short family of related queries as if a CCU is polling multiple
|
||||
capability blocks in one startup pass. This checks whether the panel expects a
|
||||
cluster of reads instead of one isolated query.
|
||||
|
||||
Power-cycle before each run.
|
||||
|
||||
```powershell
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --frame "00 00 A1 00 80 7B" --frame "00 00 A4 00 80 7E" --frame "00 00 A5 00 80 7F" --read-after-frame 0.8 --log captures/rcp-hostid-capblock-a-family.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 B1 00 80 6B" --frame "00 00 B8 00 80 62" --frame "00 00 BC 00 80 66" --read-after-frame 0.8 --log captures/rcp-hostid-capblock-b-family.txt
|
||||
```
|
||||
|
||||
What to watch for:
|
||||
|
||||
- Only the first query in the block responds: the one-shot model still dominates.
|
||||
- Later queries also respond once the family is polled as a burst: this would be
|
||||
a major new lead toward CCU-style startup behavior.
|
||||
- A later query changes the LCD or LEDs even if the first one looks ordinary:
|
||||
still worth treating as a lead.
|
||||
|
||||
### Test HI5: Repeated Poll Group
|
||||
|
||||
Repeat the same short poll group with a gap, to test whether the panel wants
|
||||
periodic polling or whether only the first startup block matters.
|
||||
|
||||
Power-cycle before each run.
|
||||
|
||||
```powershell
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 B0 00 80 6A" --frame "00 00 B1 00 80 6B" --repeat 3 --repeat-interval 1.5 --read-after-frame 0.8 --read-after-group 0.8 --log captures/rcp-hostid-repeat-b0-b1.txt
|
||||
python scripts/serial_sequence_probe.py --port COM5 --prompt --frame "00 00 00 00 80 DA" --frame "00 00 A0 00 80 7A" --repeat 3 --repeat-interval 1.5 --read-after-frame 1.0 --read-after-group 0.8 --log captures/rcp-hostid-repeat-a0.txt
|
||||
```
|
||||
|
||||
What to watch for:
|
||||
|
||||
- Only group 1 responds: startup window or latch behavior still dominates.
|
||||
- Later groups begin to respond too: periodic polling may be part of the
|
||||
expected CCU session.
|
||||
- A later group changes visible state even with similar serial output: possible
|
||||
session-timer or keepalive behavior.
|
||||
|
||||
Recommended order:
|
||||
|
||||
1. `HI3` because it most directly tests the "CCU identifies itself first"
|
||||
hypothesis.
|
||||
2. `HI4` because a capability-poll burst is a plausible Sony startup pattern.
|
||||
3. `HI1` and `HI2` if the first two stay flat and we need to isolate which host
|
||||
fields matter.
|
||||
|
||||
### 2026-05-13 Host Identity / Capability Result
|
||||
|
||||
Captures:
|
||||
|
||||
- `captures/rcp-hostid-prefix-0000-a0.txt`
|
||||
- `captures/rcp-hostid-prefix-0080-a0.txt`
|
||||
- `captures/rcp-hostid-prefix-8000-a0.txt`
|
||||
- `captures/rcp-hostid-a0-0080.txt`
|
||||
- `captures/rcp-hostid-a0-20d0.txt`
|
||||
- `captures/rcp-hostid-a0-4030.txt`
|
||||
- `captures/rcp-hostid-a0-6030.txt`
|
||||
- `captures/rcp-hostid-announce-90-then-a0.txt`
|
||||
- `captures/rcp-hostid-announce-9f-then-a0.txt`
|
||||
- `captures/rcp-hostid-announce-af-then-a0.txt`
|
||||
- `captures/rcp-hostid-announce-b7-then-a0.txt`
|
||||
- `captures/rcp-hostid-announce-bb-then-a0.txt`
|
||||
- `captures/rcp-hostid-announce-ff-then-a0.txt`
|
||||
- `captures/rcp-hostid-capblock-a-family.txt`
|
||||
- `captures/rcp-hostid-capblock-b-family.txt`
|
||||
- `captures/rcp-hostid-repeat-a0.txt`
|
||||
- `captures/rcp-hostid-repeat-b0-b1.txt`
|
||||
|
||||
Not run / no capture present:
|
||||
|
||||
- `captures/rcp-hostid-prefix-0780-a0.txt`
|
||||
|
||||
#### HI1: Prefix Variation On `A0`
|
||||
|
||||
Observed result:
|
||||
|
||||
| Query frame after primer | Result |
|
||||
| --- | --- |
|
||||
| `00 00 A0 00 80 7A` | conflicting captures: one run returned `07 80 E8 40 30 45`, another returned `07 80 68 40 30 C5` |
|
||||
| `00 80 A0 00 80 FA` | heartbeat only |
|
||||
| `80 00 A0 00 80 FA` | heartbeat only |
|
||||
| `07 80 A0 00 80 FD` | not run |
|
||||
|
||||
Read:
|
||||
|
||||
- Nonzero host prefix bytes did not help. The tested `00 80` and `80 00`
|
||||
prefixes suppressed the `A0` response entirely.
|
||||
- The plain `00 00` prefix remains the only confirmed working host prefix for
|
||||
`A0`, although the returned block still varies across runs.
|
||||
|
||||
#### HI2: State/Value Variation On `A0`
|
||||
|
||||
Observed result:
|
||||
|
||||
| Query frame after primer | Observed RCP response |
|
||||
| --- | --- |
|
||||
| `00 00 A0 00 80 7A` | `07 80 68 40 30 C5` repeated |
|
||||
| `00 00 A0 20 D0 0A` | `07 80 E8 48 3A 47` repeated |
|
||||
| `00 00 A0 40 30 8A` | `07 80 68 58 26 CB` repeated |
|
||||
| `00 00 A0 60 30 AA` | `07 80 68 58 26 CB` repeated |
|
||||
|
||||
Read:
|
||||
|
||||
- This is the strongest new lead in the set.
|
||||
- The `A0` response is not fixed: the host `state/value` fields clearly affect
|
||||
the returned block.
|
||||
- That strongly supports the idea that these fields are carrying host-presented
|
||||
status, selector, or capability information, not just filler.
|
||||
|
||||
#### HI3: Primer -> Host-Announce -> `A0`
|
||||
|
||||
Observed result:
|
||||
|
||||
| Sequence | Middle-frame result | Later `A0` result |
|
||||
| --- | --- | --- |
|
||||
| `00 -> 90 -> A0` | `07 80 64 40 30 C9` repeated | no clean `A0`; only one more `07 80 64 40 30 C9` then heartbeat |
|
||||
| `00 -> 9F -> A0` | heartbeat only after `9F` | heartbeat only after `A0`; a prior anomaly `07 80 40 40 30 ED` appeared immediately after the primer |
|
||||
| `00 -> AF -> A0` | `07 80 0D 04 AB 7F` visible with a leading heartbeat fragment | heartbeat only after `A0` |
|
||||
| `00 -> B7 -> A0` | `07 80 1B 08 D6 18` repeated | heartbeat only after `A0` |
|
||||
| `00 -> BB -> A0` | `07 80 37 10 2C D6` repeated | no clean `A0`; only one more `07 80 37 10 2C D6` then heartbeat |
|
||||
| `00 -> FF -> A0` | heartbeat only | heartbeat only |
|
||||
|
||||
Read:
|
||||
|
||||
- The "announce" bytes behaved more like readable/query commands than like a
|
||||
host identity banner the panel accepts and then builds on.
|
||||
- In most runs, the middle frame consumed the one-shot response opportunity and
|
||||
the following `A0` did not produce its own block.
|
||||
- So far this argues against a simple three-step handshake of
|
||||
`primer -> host identity -> query`.
|
||||
|
||||
#### HI4: Capability-Poll Block
|
||||
|
||||
Observed result:
|
||||
|
||||
| Block | Result |
|
||||
| --- | --- |
|
||||
| `00 -> A0 -> A1 -> A4 -> A5` | only `A0` responded (`07 80 68 40 30 C5`); `A1`, `A4`, and `A5` were heartbeat only |
|
||||
| `00 -> B0 -> B1 -> B8 -> BC` | only `B0` responded (`07 80 EC 40 30 41` with a leading heartbeat fragment); `B1`, `B8`, and `BC` were heartbeat only |
|
||||
|
||||
Read:
|
||||
|
||||
- A burst of related readable queries did not unlock later responses in the same
|
||||
startup pass.
|
||||
- The one-shot model still dominates: first successful readable query responds,
|
||||
later ones in the burst are suppressed.
|
||||
|
||||
#### HI5: Repeated Poll Group
|
||||
|
||||
Observed result:
|
||||
|
||||
| Repeated group | Result |
|
||||
| --- | --- |
|
||||
| `00 -> A0`, repeated 3 times | only group 1 produced `07 80 68 40 30 C5`; groups 2 and 3 were heartbeat only |
|
||||
| `00 -> B0 -> B1`, repeated 3 times | only group 1 `B0` produced a response; later groups were heartbeat only and `B1` never responded |
|
||||
|
||||
Read:
|
||||
|
||||
- Periodic polling without a power cycle did not open a sustained session.
|
||||
- The panel still behaves like it offers one early readable response block, then
|
||||
falls back to heartbeat-only behavior.
|
||||
|
||||
Overall interpretation:
|
||||
|
||||
- The cleanest new evidence is that host `state/value` fields matter a lot for
|
||||
at least the `A0` family.
|
||||
- The tested nonzero prefixes do not look like a missing CCU identity by
|
||||
themselves.
|
||||
- Candidate "announce" bytes mostly act like ordinary readable/query selectors,
|
||||
not like a reusable host identity stage.
|
||||
- Capability-poll bursts and repeated poll groups did not create a multi-query
|
||||
session.
|
||||
- Best current model: the startup exchange probably does involve host-presented
|
||||
status or selector bits, but the currently tested sequences still land in a
|
||||
one-shot query regime rather than an active maintained session.
|
||||
|
||||
238
scripts/serial_sequence_probe.py
Normal file
238
scripts/serial_sequence_probe.py
Normal file
@@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Send arbitrary RCP-TX7 host frame sequences and classify RX windows.
|
||||
|
||||
This helper is meant for exploratory multi-frame tests such as:
|
||||
|
||||
primer -> announce/selector -> query
|
||||
primer -> short query block
|
||||
repeated pseudo-keepalive groups
|
||||
|
||||
Each transmitted frame can be followed by a small read window so responses can
|
||||
be attributed to a specific host frame more easily than in a long raw capture.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import datetime as dt
|
||||
import sys
|
||||
import time
|
||||
|
||||
try:
|
||||
import serial
|
||||
except ImportError:
|
||||
print(
|
||||
"Missing dependency: pyserial\n"
|
||||
"Install it with: python -m pip install pyserial",
|
||||
file=sys.stderr,
|
||||
)
|
||||
raise SystemExit(2)
|
||||
|
||||
|
||||
HEARTBEAT = bytes.fromhex("00 00 00 00 80 DA")
|
||||
|
||||
|
||||
def parse_hex_bytes(text: str) -> bytes:
|
||||
normalized = text.replace(",", " ").replace("0x", "").replace("0X", "")
|
||||
parts = normalized.split()
|
||||
if not parts:
|
||||
raise argparse.ArgumentTypeError("hex frame cannot be empty")
|
||||
try:
|
||||
values = [int(part, 16) for part in parts]
|
||||
except ValueError as exc:
|
||||
raise argparse.ArgumentTypeError(f"invalid hex byte list: {text}") from exc
|
||||
if any(value < 0 or value > 0xFF for value in values):
|
||||
raise argparse.ArgumentTypeError("hex values must be bytes")
|
||||
return bytes(values)
|
||||
|
||||
|
||||
def hex_preview(data: bytes) -> str:
|
||||
return " ".join(f"{byte:02X}" for byte in data)
|
||||
|
||||
|
||||
def ascii_preview(data: bytes) -> str:
|
||||
return "".join(chr(byte) if 32 <= byte <= 126 else "." for byte in data)
|
||||
|
||||
|
||||
def make_logger(path: str | None):
|
||||
log_file = open(path, "a", encoding="utf-8") if path else None
|
||||
|
||||
def emit(line: str) -> None:
|
||||
print(line)
|
||||
if log_file:
|
||||
log_file.write(line + "\n")
|
||||
log_file.flush()
|
||||
|
||||
return emit, log_file
|
||||
|
||||
|
||||
def heartbeat_offset(data: bytes) -> int | None:
|
||||
if not data:
|
||||
return 0
|
||||
for offset in range(len(HEARTBEAT)):
|
||||
if all(byte == HEARTBEAT[(offset + index) % len(HEARTBEAT)] for index, byte in enumerate(data)):
|
||||
return offset
|
||||
return None
|
||||
|
||||
|
||||
def first_mismatch(data: bytes, offset: int) -> tuple[int, int, int] | None:
|
||||
for index, byte in enumerate(data):
|
||||
expected = HEARTBEAT[(offset + index) % len(HEARTBEAT)]
|
||||
if byte != expected:
|
||||
return index, byte, expected
|
||||
return None
|
||||
|
||||
|
||||
def classify_rx(data: bytes) -> tuple[bool, str]:
|
||||
if not data:
|
||||
return False, "no RX bytes"
|
||||
|
||||
offset = heartbeat_offset(data)
|
||||
if offset is not None:
|
||||
full = len(data) // len(HEARTBEAT)
|
||||
extra = len(data) % len(HEARTBEAT)
|
||||
return False, f"heartbeat-compatible RX: {len(data)} bytes, offset {offset}, {full} frames + {extra} bytes"
|
||||
|
||||
best_offset = min(
|
||||
range(len(HEARTBEAT)),
|
||||
key=lambda candidate: sum(
|
||||
byte != HEARTBEAT[(candidate + index) % len(HEARTBEAT)]
|
||||
for index, byte in enumerate(data)
|
||||
),
|
||||
)
|
||||
mismatch = first_mismatch(data, best_offset)
|
||||
if mismatch is None:
|
||||
return False, "heartbeat-compatible RX"
|
||||
|
||||
index, byte, expected = mismatch
|
||||
return (
|
||||
True,
|
||||
f"ANOMALY {len(data)} RX bytes; first mismatch at byte {index}: "
|
||||
f"got {byte:02X}, heartbeat offset {best_offset} expected {expected:02X}",
|
||||
)
|
||||
|
||||
|
||||
def read_window(ser: serial.Serial, duration: float) -> bytes:
|
||||
stop_at = time.monotonic() + duration
|
||||
data = bytearray()
|
||||
while time.monotonic() < stop_at:
|
||||
chunk = ser.read(128)
|
||||
if chunk:
|
||||
data.extend(chunk)
|
||||
return bytes(data)
|
||||
|
||||
|
||||
def emit_rx(emit, label: str, data: bytes, ascii_mode: bool) -> bool:
|
||||
is_anomaly, note = classify_rx(data)
|
||||
emit(f"{label} {note}")
|
||||
if data and ascii_mode:
|
||||
emit(f"{'':14} ASCII {ascii_preview(data)}")
|
||||
if is_anomaly:
|
||||
emit(f"{label} raw {hex_preview(data)}")
|
||||
return is_anomaly
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Send an arbitrary host frame sequence and classify RX after each step."
|
||||
)
|
||||
parser.add_argument("--port", required=True, help="serial port, for example COM5")
|
||||
parser.add_argument("--baud", type=int, default=38400)
|
||||
parser.add_argument("--timeout", type=float, default=0.03)
|
||||
parser.add_argument("--log", help="append probe log to this file")
|
||||
parser.add_argument("--ascii", action="store_true")
|
||||
parser.add_argument("--prompt", action="store_true", help="pause before starting so you can power-cycle or prepare the panel")
|
||||
parser.add_argument("--pre-read", type=float, default=3.0, help="seconds to observe baseline heartbeat before the first frame")
|
||||
parser.add_argument("--delay", type=float, default=0.0, help="extra delay after prompt/baseline before the first frame")
|
||||
parser.add_argument(
|
||||
"--frame",
|
||||
type=parse_hex_bytes,
|
||||
action="append",
|
||||
required=True,
|
||||
help="hex frame to send; repeat the flag to build a sequence",
|
||||
)
|
||||
parser.add_argument("--frame-interval", type=float, default=0.05, help="delay between consecutive frames in the same group")
|
||||
parser.add_argument("--read-after-frame", type=float, default=0.8, help="seconds to read/classify after each frame")
|
||||
parser.add_argument("--repeat", type=int, default=1, help="how many times to send the full frame group")
|
||||
parser.add_argument("--repeat-interval", type=float, default=0.0, help="delay between repeated frame groups")
|
||||
parser.add_argument("--read-after-group", type=float, default=0.0, help="extra seconds to read/classify after each full group")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
emit, log_file = make_logger(args.log)
|
||||
|
||||
try:
|
||||
with serial.Serial(
|
||||
port=args.port,
|
||||
baudrate=args.baud,
|
||||
bytesize=serial.EIGHTBITS,
|
||||
parity=serial.PARITY_NONE,
|
||||
stopbits=serial.STOPBITS_ONE,
|
||||
timeout=args.timeout,
|
||||
write_timeout=1.0,
|
||||
rtscts=False,
|
||||
dsrdtr=False,
|
||||
xonxoff=False,
|
||||
) as ser:
|
||||
emit(
|
||||
f"Sequence probe: {len(args.frame)} frames x {args.repeat} group(s) "
|
||||
f"on {ser.port} at {ser.baudrate} 8N1"
|
||||
)
|
||||
for index, frame in enumerate(args.frame, start=1):
|
||||
emit(f"FRAME {index}: {hex_preview(frame)}")
|
||||
|
||||
if args.prompt:
|
||||
input("Prepare/power-cycle RCP, wait for heartbeat, then press Enter: ")
|
||||
|
||||
ser.reset_input_buffer()
|
||||
emit_rx(emit, "BASELINE", read_window(ser, args.pre_read), args.ascii)
|
||||
|
||||
if args.delay > 0:
|
||||
time.sleep(args.delay)
|
||||
|
||||
anomaly_count = 0
|
||||
for group_index in range(1, args.repeat + 1):
|
||||
if group_index > 1 and args.repeat_interval > 0:
|
||||
time.sleep(args.repeat_interval)
|
||||
|
||||
emit(f"BEGIN group {group_index}/{args.repeat}")
|
||||
for frame_index, frame in enumerate(args.frame, start=1):
|
||||
stamp = dt.datetime.now().strftime("%H:%M:%S.%f")[:-3]
|
||||
emit(
|
||||
f"{stamp} TX group={group_index} frame={frame_index} "
|
||||
f"len={len(frame):03d} {hex_preview(frame)}"
|
||||
)
|
||||
ser.write(frame)
|
||||
ser.flush()
|
||||
|
||||
if args.read_after_frame > 0:
|
||||
label = f"{stamp} RX group={group_index} frame={frame_index}"
|
||||
if emit_rx(emit, label, read_window(ser, args.read_after_frame), args.ascii):
|
||||
anomaly_count += 1
|
||||
|
||||
if frame_index < len(args.frame) and args.frame_interval > 0:
|
||||
time.sleep(args.frame_interval)
|
||||
|
||||
if args.read_after_group > 0:
|
||||
label = f"GROUP {group_index} TAIL"
|
||||
if emit_rx(emit, label, read_window(ser, args.read_after_group), args.ascii):
|
||||
anomaly_count += 1
|
||||
|
||||
emit(f"Anomalies: {anomaly_count}")
|
||||
except KeyboardInterrupt:
|
||||
emit("Stopped.")
|
||||
return 0
|
||||
except serial.SerialException as exc:
|
||||
print(f"Serial error: {exc}", file=sys.stderr)
|
||||
return 1
|
||||
finally:
|
||||
if log_file:
|
||||
log_file.close()
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user