Skip to content

storeeslstatus

Version: v1 Scope: singleton per store ESL (one per physical ESL, keyed as a child of the storeesl path) Owning service: pricer-server

The storeeslstatus DTO records the real-time operational and lifecycle state of an individual ESL as reported by pricer-server (the on-premise gateway that drives the radio/IR network). It is intentionally kept separate from storeesl because its write frequency and write ownership differ fundamentally: pricer-server updates this record continuously as the device communicates, whereas storeesl is a relatively static configuration record owned by link-registry. Separating them keeps the writer-equals-owner invariant clean and lets consumers subscribe to status changes independently of configuration changes (see ADR-006).

In addition to the lifecycle state, this DTO embeds battery information, update timestamps, hardware properties, and (for IR devices) routing diagnostics — all data that PricerServer derives from device communication and that would otherwise need a secondary lookup.

ID pattern

t/{tenantid}/s/{storeid}/esls/{barcode}/status

  • t/{tenantid}/s/{storeid}/esls/{barcode} — the storeesl this status belongs to
  • /status — singleton suffix; there is exactly one status record per storeesl

Schema

Top-level fields

Field Type Description
id string Primary ID; follows the pattern above
state State (enum) Current operational and lifecycle state; see state machine below
battery BatteryProperties Battery level, state, and timestamps
last_display_update Timestamp When the display last received and acknowledged an image update
last_ok_at Timestamp Last time the device was in OK state with a confirmed up-to-date image
state_changed_at Timestamp When the current state was first entered
first_onboarded_at Timestamp When the ESL first successfully completed onboarding; not reset on subsequent re-onboardings
device_properties DeviceProperties Hardware-level properties as last reported by the device
ir_properties IrProperties IR-specific communication status; absent for non-IR devices

State enum — lifecycle states

Value Code Description
STATE_UNSPECIFIED 0 Default/unset; should not appear in practice
ONBOARDING 1 Pairing in progress; device is reachable and work is underway. Entry point for all new ESLs
ONBOARDING_PENDING 2 Pairing in progress but device timed out; reachable status unknown. Reached only via timeout from ONBOARDING
OK 3 Fully operational: device is onboarded and its display shows the latest image
UPDATING 4 An image or flash command has been queued and is in progress
ROAMING 5 Device timed out during an update; PricerServer is periodically retrying. Reached only via timeout from UPDATING
LOST 6 Device has been unreachable beyond the auto-reset threshold (30 days). Terminal: link-registry deletes the storeesl upon seeing this, which triggers PS to delete this DTO
OFFBOARDING 7 Offboard command queued; device is reachable and work is underway. May transition to UPDATING if a new image arrives before offboard executes
OFFBOARDING_PENDING 8 Offboard command queued but device timed out. May transition back to ROAMING if a new image/flash cancels the offboard
OFFBOARDED 9 Device successfully offboarded. Terminal: same cleanup flow as LOST
FAILED 10 Device is in a failed state, typically due to a configuration error

State machine transitions

[*] ──────────────────────────────────────────── ONBOARDING
ONBOARDING         ──(timeout)──────────────────► ONBOARDING_PENDING
ONBOARDING         ──(handshake OK)─────────────► OK
ONBOARDING_PENDING ──(30 days)──────────────────► LOST
ONBOARDING_PENDING ──(new reason)───────────────► OFFBOARDING_PENDING
OK                 ──(image/flash queued)────────► UPDATING
UPDATING           ──(ack received)─────────────► OK
UPDATING           ──(timeout)──────────────────► ROAMING
ROAMING            ──(device responds)──────────► OK
ROAMING            ──(30 days)──────────────────► LOST
ROAMING            ──(new reason)───────────────► OFFBOARDING_PENDING
OFFBOARDING_PENDING──(image/flash cancels)───────► ROAMING
OFFBOARDING_PENDING──(30 days)──────────────────► LOST
LOST               ──(terminal)─────────────────► [storeesl deleted → DTO deleted]
OFFBOARDED         ──(terminal)─────────────────► [storeesl deleted → DTO deleted]

The "30-day threshold" applies uniformly to ONBOARDING_PENDING, ROAMING, and OFFBOARDING_PENDING: if the device has been unreachable for 30 days, the firmware performs an automatic factory reset (the device and the gateway mutually forget each other), and the state transitions to LOST.

BatteryProperties message

Field Type Description
battery_state BatteryState (enum) Current battery state
battery_state_changed_at Timestamp When the battery state last changed
battery_first_low_at Timestamp Set on the first transition to LOW; cleared when battery recovers

BatteryState values: BATTERY_STATE_UNSPECIFIED (0), OK (1), LOW (2), UNKNOWN (3 — not yet reported by device)

DeviceProperties message

Field Type Description
firmware_version string Firmware version as reported by the device. Example: "3.4.2"
hardware_revision string Hardware revision as reported by the device. Example: "3"
encryption_state EncryptionState (enum) Encryption state of the device communication channel

EncryptionState values: ENCRYPTION_STATE_UNSPECIFIED (0), ENABLED (1), DISABLED (2), ACTIVATING (3), DEACTIVATING (4), ROTATING (5)

IrProperties message

Only populated for IR-based devices; absent for RF and other protocols.

Field Type Description
home_transceiver string Current home transceiver for this device. Example: "A1"
last_trx_list string Last known transceiver route; diagnostic use. Example: "A1,A2,B3"
roam_status RoamStatus Roaming diagnostics; only meaningful when state = ROAMING

RoamStatus fields: roam_level (RoamLevel enum), roam_sweep (uint32 — retry sweeps since roaming began), roaming_since (Timestamp)

RoamLevel values: ROAM_LEVEL_UNSPECIFIED (0), FAST (1 — recently missed), NORMAL (2 — extended), SLOW (3 — critical, auto-reset imminent)

Why it is a separate DTO (ADR-006)

PricerServer writes the status record at high frequency as devices communicate — potentially multiple times per minute per device in a large store. The storeesl record is a configuration record written by link-registry when a device is assigned to a store, and changes infrequently. Merging the two would cause:

  1. Write ownership conflicts — two services would write to the same DTO key with incompatible cadences and partial updates.
  2. Consumer coupling — services like studio-renderer that only care about esltype_id would receive floods of irrelevant status updates.
  3. Deletion race — the deletion flow requires link-registry to react to specific terminal states (LOST, OFFBOARDED) in the status record; a single merged record would create a circular dependency between the deleter and the deleted.

Keeping them separate allows each service to own exactly its slice of the data, and allows the deletion flow to be expressed cleanly: PS writes terminal state → link-registry deletes storeesl → that deletion signals PS to delete the status DTO.

Consumed by

Service Why
link-registry Watches for LOST and OFFBOARDED states to trigger storeesl deletion and lifecycle cleanup
(internal dashboards) Surfaces battery, firmware, and connectivity state for store operations teams

Deletion cascade

pricer-server is the sole writer of storeeslstatus and is also responsible for deleting it — but only as the last step of the lifecycle:

  1. pricer-server PUTs storeeslstatus with state = LOST or OFFBOARDED.
  2. link-registry deletes the parent storeesl.
  3. pricer-server observes the storeesl deletion and then deletes the corresponding storeeslstatus.

This ordering keeps the status DTO available to consumers throughout the terminal-cleanup window, and avoids leaving an orphaned status record when the ESL itself is gone.

  • storeesl — the ESL registration record; parent of this status path
  • store — the store this ESL and its status belong to