Major session of local-OCF reverse engineering against the NV7000BS
oven and DV5000T dryer. Surfaces a working set of HA entities for the
oven and resolves several Samsung-quirk regressions in the bridge's
write path.
Key behavioural fixes:
- OBSERVE registrations now use single-byte tokens. Samsung RT-OCF
silently drops registrations with TKL>1; same 4-byte tokens work
fine for GET/POST. Symptom was that writes returned 2.04 but the
appliance never pushed state changes.
- Per-session random starting tokens + MID. Samsung retains observer
state across DTLS reconnects from the same cert; reusing tokens on
reconnect silently no-ops.
- OBSERVE deregister sent on DtlsCoapSession.close(), with a stop-
watcher thread in PushBridge.session_once() so SIGINT/SIGTERM
actually reaches close() instead of hanging in sess.join().
- pyOpenSSL is not thread-safe — reader-loop conn.* calls now hold
the same _send_lock the sender uses, dispatching decrypted packets
outside the lock so the auto-ACK send doesn't deadlock.
- Periodic CoAP Ping (RFC 7252 §4.4) keepalive to keep DTLS warm.
- Post-write Block2 fetchback REMOVED. It was the root cause of
every "setpoint/operationTime/modes revert ~3s after write"
symptom — Samsung's stack treats a read on a freshly-written
resource as a signal to invalidate that write. OBSERVE pushes
keep HA in sync without the verification GET.
HA-facing changes (oven):
- New entities: Lamp (light), Sound (switch), Fast preheat, Natural
steam, Setpoint (number), Cook time (number), Stop cycle (button).
- Cooking mode surfaced as a read-only sensor — the oven owns the
modes field once a cycle is active and rolls local writes back.
- Cook time writes operationTime + remainingTime on
/operational/state/vs/0 (discovered via OBSERVE capture of
SmartThings mid-cycle changes — UpperTimerSet on /mode/vs/0
options is vestigial and doesn't drive the running cycle).
- New cycle_active MQTT availability topic. Writes the oven only
honours mid-cycle (setpoint, cook time, fast preheat, natural
steam, stop) gate on it via avail_with_cycle / avail_with_remote_
and_cycle. Sound + Lamp remain always-available.
- Cycle Start deliberately NOT exposed. Every byte-level approxi-
mation of SmartThings's working start sequence is rejected at
the firmware level. Empty discovery payloads remove the previous
Start button and Cooking-mode select cleanly from HA.
Diagnostics:
- DEBUG_BRIDGE=1 env var enables verbose tracing (rx CON/NON/ACK/
RST per frame, full link-tree dump at seed, /oic/res directory,
REP changes on /operational/state, /oven, /power, mode options).
Quiet in production.