Flow: ESL Hardware Lifecycle¶
Trigger: A link.v2 DTO is created for a barcode (onboarding begins), or the physical ESL communicates / stops communicating with the gateway
Key services: link-registry, pricer-server
Key DTOs: storeesl, storeeslstatus, link.v2, eslimage
This flow describes the complete operational lifecycle of an Electronic Shelf Label from the moment it is first associated with an item through its normal operation, temporary disconnection, intentional removal, and final deletion from the platform. The lifecycle is driven by two separate concerns that are deliberately kept in separate DTOs (per ADR-006):
storeesl— the logical identity and rendering anchor. Owned and written by link-registry. Exists while the ESL is part of the store's active label population.storeeslstatus— the physical communication state. Owned and exclusively written by pricer-server. Reflects what pricer-server observes from the RF/IR network in real time.
This split keeps the owner-equals-writer invariant clean. Rendering services depend on storeesl without coupling to hardware state; pricer-server can update communication state at high frequency without touching the link/rendering data model. The deletion of an ESL is a multi-step coordination between the two writers.
Roles in the lifecycle¶
| Service | Writes | Role |
|---|---|---|
link-registry |
storeesl, link.v2 |
Creates storeesl when the first link.v2 is written for a barcode. Watches storeeslstatus and deletes storeesl when it sees a terminal state (LOST / OFFBOARDED). |
pricer-server |
storeeslstatus |
Sole writer of storeeslstatus. Drives all state transitions from RF/IR feedback held in its internal per-ESL state DB. Deletes storeeslstatus only after the parent storeesl is gone. |
pricer-server |
(consumer) eslimage, storeesl |
Subscribes to eslimage directly via CQS to transmit images, and to storeesl to register/unregister devices and to detect the deletion that triggers the storeeslstatus cleanup. |
State machine¶
Authoritative state list and transitions are in esl-status.md (in-repo handover) and reflected on storeeslstatus.
stateDiagram-v2
[*] --> ONBOARDING : link.v2 created for barcode\n(link-registry writes storeesl;\npricer-server starts pairing)
ONBOARDING --> OK : Handshake OK\n(pricer-server writes status OK)
ONBOARDING --> ONBOARDING_PENDING : Pairing timeout
OK --> UPDATING : Image/flash queued
UPDATING --> OK : ACK received
UPDATING --> ROAMING : Delivery timeout
ROAMING --> OK : Device responds
ROAMING --> LOST : 30 days unreachable\n(firmware auto-reset)
ONBOARDING_PENDING --> LOST : 30 days
ONBOARDING_PENDING --> OFFBOARDING_PENDING : New reason
OK --> OFFBOARDING : Operator offboard\n(reachable)
OFFBOARDING --> OFFBOARDED : ACK
OFFBOARDING --> OFFBOARDING_PENDING : Timeout
OFFBOARDING_PENDING --> ROAMING : Image/flash cancels offboard
OFFBOARDING_PENDING --> LOST : 30 days
LOST --> [*] : storeesl deleted →\nstoreeslstatus deleted
OFFBOARDED --> [*] : storeesl deleted →\nstoreeslstatus deleted
Walkthrough: onboarding → operation → terminal cleanup¶
1. Onboarding¶
A first link.v2 is created for a barcode (see Item–ESL Linking). link-registry writes the storeesl DTO. pricer-server's storeesl CQS subscription fires; it registers the device in its internal DB and begins pairing over RF/IR. pricer-server writes storeeslstatus with state ONBOARDING.
- Handshake OK →
storeeslstatus.state = OK. - Timeout →
storeeslstatus.state = ONBOARDING_PENDING; retries continue.
2. Steady state and image delivery¶
When eslimage is written (by eslimage-merger), pricer-server consumes it via CQS, reads the bytes from LFS, applies rotation, and transmits.
- On queue/transmit: pricer-server writes
storeeslstatus.state = UPDATING. - On ACK: back to
OK. pricer-server also updates non-state telemetry on the same DTO (battery, firmware, IR diagnostics). - On delivery timeout:
ROAMING. The previously delivered image remains on the e-ink display (non-volatile).
3. Terminal cleanup cascade¶
When the ESL is permanently gone — either operator-initiated (OFFBOARDED) or firmware-initiated factory reset after 30 days unreachable (LOST) — the cleanup is a three-step cascade across the two writers:
- pricer-server writes terminal status.
storeeslstatus.state = LOSTorOFFBOARDED. The internal state DB records the terminal event. - link-registry deletes
storeesl. ItsstoreeslstatusCQS subscription fires; it sees the terminal state and deletes the correspondingstoreesl. Any remaininglink.v2records for that barcode are also cleaned up. - pricer-server deletes
storeeslstatus. ItsstoreeslCQS subscription fires on the deletion in step 2; it then deletes thestoreeslstatusit wrote in step 1 and removes the device from its internal DB.
pricer-server never deletes storeeslstatus on its own initiative; the parent storeesl deletion is the sole trigger. This keeps the status DTO visible to other consumers (dashboards, link-registry) during the cleanup window.
sequenceDiagram
participant PS as pricer-server
participant DTOflow
participant LR as link-registry
Note over PS: ESL reaches terminal condition<br/>(operator offboard or 30-day timeout)
PS->>DTOflow: PUT storeeslstatus<br/>state = LOST / OFFBOARDED
DTOflow-->>LR: CQS: storeeslstatus changed
LR->>DTOflow: Read storeeslstatus → terminal
LR->>DTOflow: DELETE storeesl<br/>(and any remaining link.v2)
DTOflow-->>PS: CQS: storeesl deleted
PS->>DTOflow: DELETE storeeslstatus
Note over PS,DTOflow: Cascade complete;<br/>no DTOs remain for this barcode
Roaming and queued updates¶
While an ESL is ROAMING, item updates and design changes continue to drive the upstream pipeline normally — studio-link-evaluator, studio-renderer, eslimage-merger and eslimage all keep producing the latest image. pricer-server stores the latest pending image in its internal DB; when the device re-appears it delivers the most recent image and writes storeeslstatus.state = OK. There is no separate retry queue at the DTO level — pricer-server is the queue.
Related flows¶
- Item–ESL Linking — the
storeeslDTO created in step 3 of that flow is the anchor for this entire lifecycle; theONBOARDINGstate begins there. - Item Update — during
ROAMING, accumulated image updates are delivered when the ESL returns toOK. - ECC Rendering Pipeline — the parallel image-producing path; lifecycle of the ESL itself is identical regardless of which renderer produced the image.