Demo 07 — Line state machine and card watchdog benches
Run the conveyor logic and the multi-card failure handling with simulated parts and simulated cards — no belt, no cards, one second.
Needs: laptop, repository. Nothing else.
Bench A — the line
The state machine in vorsa/linie.py is ticked once per camera frame with the list of detected parts. The bench feeds it simulated parts with a simulated clock and asserts the whole story of a shift.
python3 tools/test_linie_fluss.py
Output we got:
Ablauf: lauf> -> pruefen| -> lauf> -> pruefen| -> lauf> -> zone| -> arm| -> lauf> -> pruefen| -> lauf> -> pruefen| -> lauf> -> stoerung| -> lauf> -> aus|
FLUSS_OK geprueft=4 gefoerdert=1
> = belt running, | = belt stopped. Read left to right: belt runs; part 1 arrives → stop, inspect → run; part 2 → stop, inspect → run; part 1 reaches pickup → stop → arm; arm done → run; part 3 → inspect; an unknown part → inspect until the 4 s timeout, booked as unknown → run; the unknown part reaches pickup → störung (belt stops, arm is never called) → a person removes it → run; line off → belt stops.
Asserted along the way: a part is not inspected twice while leaving the delivery zone; the delivery zone waits while the arm works; without recognition the belt refuses to run; the old single-shot mode still starts the belt only for a named part.
Timing constants (bench values, not tuned on the belt): stable part 0.35 s, zone free 0.6 s, unknown 1.2 s, delivery trigger 0.25 s, stable verdict 0.6 s, inspection timeout 4 s, belt timeout 45 s, arm timeout 60 s.
Bench B — the card watchdog
python3 tools/test_karten_waechter.py
Output we got:
WAECHTER_OK {0: ('gestoert', 8, 1), 1: ('gestoert', 1, 3), 2: ('gestoert', 8, 1)}
The final state is "all cards failed" because the bench ends by breaking all three. Before that it asserts: card 1 throws DMA wait completion timed out → the ensemble answers from cards 0 and 2, card 1 is marked faulty, the alarm callback fires once; during the lock-out card 1 is not queried; after the lock-out one careful retry, still broken → locked again, no second alarm; card 1 repaired → rejoins, "back" callback fires, its answer counts again; all three broken → RuntimeError: keine Karte antwortet reaches the caller. The dict shows per card: state, number of calls, number of errors.
On the machine this is what happened on 2026-09-20 (Demo 00): with the watchdog, the line would have continued on three cards with an alarm in the message book, instead of failing every five seconds.
Proves
The operational logic — the part of an inspection cell that is not "AI" and decides whether it is usable.
Does not prove
Belt timing on real hardware (guide chapter 08 and Limitations point 5).
Failure modes
None; both run in under a second with no dependencies.
Time: 1 minute.
