Skip to content

Capture Sec+2.0 obstruction traffic on a device: OBST_1 vs PAIR_3_RESP timing, OBST_2 semantics #28

Description

@heythisisnate

Blocks #29 (fix for #27). Both are parked until someone can capture Security+ 2.0 obstruction traffic from a live opener.

Background

The obstruction path has been reworked twice, each time trading away a signal:

  • Before Improve obstruction detection time. #21 — obstruction came only from the OBST bit in STATUS frames, applied unconditionally. Correct, but users reported it as too slow.
  • Improve obstruction detection time. #21 — added PAIR_3_RESP decode with both edges explicit: byte1 == 0x0e → obstructed, byte1 == 0x09 → cleared. The unconditional status path stayed as a backstop.
  • Use OBST events for immediate obstruction sensing. #22 — went after OBST_1, which lands earlier than PAIR_3_RESP. To stop the two mechanisms fighting it deleted the 0x09 clear branch, demoted 0x0e to only arming obst_clear_from_status, and gated the status backstop behind obstruction == MAX || obst_clear_from_status.

After #22 the state machine has no explicit "cleared" signal, so it infers one by toggling on each OBST_1 behind a 1-second debounce — and #27 is the direct result: a swallowed OBST_1 desyncs it, with no backstop left to repair it.

Separately, GDO_CMD_OBST_2 (0x085) is defined in gdo_priv.h and stringified in gdo_utils.c, but decode_packet() has never handled it. Nobody has looked at what it carries.

What we need from a device

The proposed fix (see #29) is to let each message do the one thing it's good at: OBST_1 sets obstructed, 0x0e confirms, 0x09 clears, STATUS reconciles. Two facts decide whether that design needs a debounce guard and a magic number, or whether it collapses into something simpler.

Q1 — how much latency does OBST_1 actually buy over PAIR_3_RESP 0x0e?

This is the load-bearing question. If 0x0e follows OBST_1 within tens of milliseconds, drop OBST_1 handling entirely, take both edges from PAIR_3_RESP, and no guard is needed — that's #21's design plus the restored backstop. If OBST_1 is meaningfully earlier (presumably what motivated #22), it stays as a set-only fast path and we need a guard against a clear-burst tail landing after 0x09.

Q2 — does OBST_1 fire on the clear edge, or only on the trip?

#22's comment claims "many obstruction events will be sent when a long obstruction is cleared", implying it fires on both. If it does, ordering matters: an OBST_1 arriving after 0x09 would spuriously re-assert obstructed. (An OBST_1 arriving before 0x09 is harmless — we're already obstructed, so setting obstructed is a no-op.) The guard window in Q1 only needs to cover the burst tail.

Q3 — what does OBST_2 carry?

If OBST_1/OBST_2 distinguish trip from clear, the whole edge-inference problem disappears. Its data bytes may encode state directly.

Capture plan

Log cmd, nibble, byte1, byte2 and a millisecond timestamp for every frame, then exercise:

  • Brief interruption (fast hand wave through the beam, well under 1s). Record the full frame sequence with timings.
  • Sustained interruption (box in the beam, 30s+), through trip, hold, and clear.
  • Repeated trips in quick succession, to see how bursts overlap.

From those captures, answer:

  • Q1: measured delta between OBST_1 and the following PAIR_3_RESP 0x0e.
  • Q2: does OBST_1 appear on the clear edge? Before or after 0x09? How long is the burst tail?
  • Q3: does OBST_2 ever appear, and does it correlate with trip vs. clear? What's in its data bytes?
  • Is 0x09 reliably emitted for short obstructions, or only long ones? (Use OBST events for immediate obstruction sensing. #22's "long duration" framing suggests 0x0e may be long-only — if so, what marks a short trip?)
  • Does the STATUS OBST bit ((byte1 >> 6) & 1) latch, or does it track the beam in real time? Does it lag the OBST_* messages, and by how much?
  • Cross-check the STATUS bit against whichever OBST_* / PAIR_3_RESP preceded it, to confirm it's safe to restore as an unconditional backstop.

Also worth confirming on the device

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions