pub trait DeviceEnv {
Show 31 methods
// Required methods
async fn persist_snapshot(&mut self, bytes: &[u8]) -> Result<(), ()>;
async fn clear_snapshot(&mut self) -> Result<(), ()>;
async fn persist_identity(&mut self, bytes: &[u8]) -> Result<(), ()>;
async fn clear_identity(&mut self) -> Result<(), ()>;
fn fill_secret(&mut self, secret: &mut [u8; 32]) -> Result<(), ()>;
async fn apply_pairing_pin(&mut self, pin: Option<u32>) -> bool;
async fn factory_reset(&mut self) -> !;
async fn reboot(&mut self) -> !;
fn set_advertising_allowed(&mut self, allowed: bool);
async fn publish_device_name(&mut self, name: &str);
fn publish_dev_domain(&mut self, snapshot: DevDomainSnapshot);
// Provided methods
async fn older_snapshot(&mut self, out: &mut [u8]) -> Option<usize> { ... }
fn report_snapshot_rejected(&mut self, fell_back: bool) { ... }
async fn clear_counters(&mut self) { ... }
async fn sample_battery(&mut self) -> Result<BatteryStatus, ()> { ... }
async fn sample_illuminance(&mut self) -> Option<u32> { ... }
async fn battery_event(&mut self) -> BatteryStatus { ... }
async fn publish_event(&mut self) -> PublishEvent { ... }
async fn read_time(&mut self) -> Option<u32> { ... }
async fn apply_time(&mut self, epoch: Option<u32>) { ... }
async fn sample_gnss(&mut self) -> Result<GnssSnapshot, ()> { ... }
async fn sign_identity(&mut self, out: &mut [u8]) -> Option<usize> { ... }
async fn clear_ble_bonds(&mut self) -> bool { ... }
async fn set_ble_pairing(&mut self, open: bool) -> bool { ... }
fn set_alert(&mut self, state: AlertState) { ... }
fn gnss_switched(&mut self, enabled: bool) { ... }
fn set_ble_enabled(&mut self, enabled: bool) { ... }
fn request_attention(&mut self) { ... }
fn clear_attention(&mut self) { ... }
fn note_transmit_load(&mut self) { ... }
fn trace(&mut self, args: Arguments<'_>) { ... }
}Expand description
Board couplings of the session driver. Everything the loop needs from
the platform, expressed as one trait so the driver itself stays free
of HAL types and cfg board forks. Hooks a board doesn’t have keep
their no-op defaults (e.g. only the T-1000E implements the attention
indicator and transmit-load hooks today).
Required Methods§
Sourceasync fn persist_snapshot(&mut self, bytes: &[u8]) -> Result<(), ()>
async fn persist_snapshot(&mut self, bytes: &[u8]) -> Result<(), ()>
Durably persist the encoded protocol snapshot (CMD_SAVE / host wipe).
Sourceasync fn clear_snapshot(&mut self) -> Result<(), ()>
async fn clear_snapshot(&mut self) -> Result<(), ()>
Tombstone the snapshot journal (CMD_CLEAR).
Sourceasync fn persist_identity(&mut self, bytes: &[u8]) -> Result<(), ()>
async fn persist_identity(&mut self, bytes: &[u8]) -> Result<(), ()>
Durably persist the encoded device identity.
Sourceasync fn clear_identity(&mut self) -> Result<(), ()>
async fn clear_identity(&mut self) -> Result<(), ()>
Tombstone the identity journal (CMD_CLEAR).
Sourcefn fill_secret(&mut self, secret: &mut [u8; 32]) -> Result<(), ()>
fn fill_secret(&mut self, secret: &mut [u8; 32]) -> Result<(), ()>
Fill secret from the platform’s cryptographic RNG. Fails closed:
an error refuses identity generation rather than degrading.
Sourceasync fn apply_pairing_pin(&mut self, pin: Option<u32>) -> bool
async fn apply_pairing_pin(&mut self, pin: Option<u32>) -> bool
Apply a PROP_BLE_PAIRING_PIN write against the bond journal and
the live BLE stack; true when it took effect.
Sourceasync fn factory_reset(&mut self) -> !
async fn factory_reset(&mut self) -> !
CMD_FACTORY_RESET: erase EVERY piece of persistent state the
platform owns — saved snapshot, device identity, frame-counter
boundaries, BLE bonds, pairing PIN, and any other journal — then
reboot. Never returns: the reset discards in-RAM state and the
board comes back factory-fresh. Unlike
clear_ble_bonds it need not empty the
live BLE stack, because the reboot reloads bonds from the
now-erased journal.
Sourceasync fn reboot(&mut self) -> !
async fn reboot(&mut self) -> !
CMD_REBOOT: restart the hardware, keeping every persisted
journal intact. Never returns. Only reached on a board whose
SessionConfig::reboot advertises the capability, so there is no
default — a board that sets the flag owes an implementation.
A board with a mesh node owes it two courtesies before the reset
(device_node::quiesce_for_reboot provides both): airing the MAC
acknowledgment of the frame that carried the command — a
reset-class command is answered by that acknowledgment and
nothing else — and forcing the frame-counter boundaries to
durable storage. Skipping the flush re-opens the replay window
the command was admitted through, and the administrator’s
retries of that same command are then accepted again after boot:
one reboot per retry.
Sourcefn set_advertising_allowed(&mut self, allowed: bool)
fn set_advertising_allowed(&mut self, allowed: bool)
Publish the transport-arbitration advertising policy (a wired
attach suppresses BLE advertising). Diagnostic builds may
deliberately ignore allowed.
Sourceasync fn publish_device_name(&mut self, name: &str)
async fn publish_device_name(&mut self, name: &str)
Publish the session’s device name to the board’s consumers (advertising data, device node, UI).
Sourcefn publish_dev_domain(&mut self, snapshot: DevDomainSnapshot)
fn publish_dev_domain(&mut self, snapshot: DevDomainSnapshot)
Deliver a device-domain mirror to the board’s device node.
Provided Methods§
Sourceasync fn older_snapshot(&mut self, out: &mut [u8]) -> Option<usize>
async fn older_snapshot(&mut self, out: &mut [u8]) -> Option<usize>
Copy the newest committed snapshot generation strictly older than
the one last handed to the driver into out, returning its
length.
Called only after a payload is rejected, so the cost is paid on a boot that is already going wrong. Implementations re-scan the journal rather than retaining a runner-up, keeping the mount path’s “never buffers a second copy” discipline. The default refuses, which makes rejection terminal for boards whose journal cannot walk back.
Sourcefn report_snapshot_rejected(&mut self, fell_back: bool)
fn report_snapshot_rejected(&mut self, fell_back: bool)
A stored snapshot was rejected at boot. Boards with an indicator surface it locally: the host-visible report reaches nobody on an unattended repeater, which is exactly the deployment this matters for.
Sourceasync fn clear_counters(&mut self)
async fn clear_counters(&mut self)
Drop persisted frame-counter boundaries after a successful identity clear. Boards without a device node keep the default.
Sourceasync fn sample_battery(&mut self) -> Result<BatteryStatus, ()>
async fn sample_battery(&mut self) -> Result<BatteryStatus, ()>
One fresh battery measurement (Effect::SampleBattery). Only
emitted when the board’s SessionConfig::battery advertises
fields, so the default refuses.
Sourceasync fn sample_illuminance(&mut self) -> Option<u32>
async fn sample_illuminance(&mut self) -> Option<u32>
One fresh ambient light measurement in millilux
(Effect::SampleIlluminance). Only emitted on a board whose
SessionConfig::illuminance is set, so the default reports nothing.
None is a legitimate answer — the sensor exists but could not be
read — and reaches the host as the empty value rather than an error.
Sourceasync fn battery_event(&mut self) -> BatteryStatus
async fn battery_event(&mut self) -> BatteryStatus
Wait for a battery measurement the board considers worth
announcing, for publication as an unsolicited PROP_BATTERY
(Session::publish_battery).
The board owns the whole policy: the sampling cadence, the charge-state edges, and which changes matter. It is the only layer that sees every sample, so filtering there keeps the session free of cached readings and keeps this hook’s contract simple — every value it yields is published.
Cancellation-safe: the driver drops and re-creates this future on
every other loop iteration, so an implementation must not lose an
update it was cancelled on (an embassy_sync::watch::Watch
receiver behaves correctly here; a bare Signal does not).
The default never completes, so boards without battery push add nothing to the select.
Sourceasync fn publish_event(&mut self) -> PublishEvent
async fn publish_event(&mut self) -> PublishEvent
Wait for anything the board wants to publish unasked, across every property it pushes.
This is the driver’s single select arm for device-initiated
publication. The default delegates to
battery_event, so a board that pushes only
battery measurements implements that and nothing else. A board that
also pushes time or position overrides this instead and selects
over its own sources — which it can do without fighting the
borrow checker, since those are its own fields rather than three
&mut self calls.
Cancellation-safe on the same terms as
battery_event.
Sourceasync fn read_time(&mut self) -> Option<u32>
async fn read_time(&mut self) -> Option<u32>
Read the platform wall clock (Effect::ReadTime): Unix seconds,
or None when the device does not know what time it is.
Not knowing is the honest answer for a board that has never had a
fix and was never told, and it is what stops a display from
showing a clock. The default is exactly that, so a board without
CAP_TIME never has to implement it.
Sourceasync fn apply_time(&mut self, epoch: Option<u32>)
async fn apply_time(&mut self, epoch: Option<u32>)
Apply a PROP_TIME write (Effect::ApplyTime): set the wall
clock, or return it to not knowing.
A manual set outranks every receiver-derived one, so this applies
regardless of PROP_GNSS_TIME_TRUST.
Sourceasync fn sample_gnss(&mut self) -> Result<GnssSnapshot, ()>
async fn sample_gnss(&mut self) -> Result<GnssSnapshot, ()>
Sample the receiver’s current view of position and constellation
(Effect::SampleGnss). Only emitted on a board whose
SessionConfig::gnss advertises the capability, so the default
refuses.
Sourceasync fn sign_identity(&mut self, out: &mut [u8]) -> Option<usize>
async fn sign_identity(&mut self, out: &mut [u8]) -> Option<usize>
Build and sign the device identity’s node-identity blob into
out (Effect::SignIdentity), returning its length.
The board owns both halves the session does not: the signing key, and the advertised profile the Identity Request responder uses. Boards without a device node keep the default, which refuses.
Sourceasync fn clear_ble_bonds(&mut self) -> bool
async fn clear_ble_bonds(&mut self) -> bool
CMD_BLE_CLEAR_BONDS: delete every stored bond, the pairing PIN,
and the pairing lockout, then open a pairing window. true once
the deletion is durable.
Unlike the factory reset below, this runs with the board still up, so the live BLE stack has to be emptied alongside the journal — a bond forgotten on flash but still held in RAM would keep working until the next boot. Boards that do not manage their own bonds never see this and keep the default, which refuses.
Sourceasync fn set_ble_pairing(&mut self, open: bool) -> bool
async fn set_ble_pairing(&mut self, open: bool) -> bool
A PROP_BLE_PAIRING write: open (or renew) the pairing window, or
close it. false when the requested state cannot be entered —
only ever an open the board must refuse, because it is locked out
after repeated pairing failures or its Bluetooth is off; a close
always succeeds.
Sourcefn set_alert(&mut self, state: AlertState)
fn set_alert(&mut self, state: AlertState)
Start or stop the board’s locate indication (PROP_ALERT).
Carries the authoritative state and is called for every
transition — host write, local cancellation, and deadline — so an
implementation can treat it as idempotent and needs no notion of
why the alert ended. AlertState::Locate must override a local
silence setting without clearing it (spec §PROP_ALERT); boards
without CAP_ALERT never see this and keep the default.
Sourcefn gnss_switched(&mut self, enabled: bool)
fn gnss_switched(&mut self, enabled: bool)
The receiver switch was flipped at the device, and is now
enabled.
Only for the local gesture: a host write already knows what it asked for, and a board that indicated one would announce the phone’s own settings screen back at it. Carries the resulting state rather than the fact of a press, because “on” and “off” are what the operator needs told apart.
Sourcefn set_ble_enabled(&mut self, enabled: bool)
fn set_ble_enabled(&mut self, enabled: bool)
Make the Bluetooth transport reachable, or stop it being so.
Called from the device-domain mirror rather than from any one
gesture, so it arrives for a host write, a boot restore, a
CMD_RST and a menu entry alike — and arrives again whenever
anything else in the domain moves. Implementations must therefore
be idempotent, and boards without CAP_BLE never see anything
but the default.
Disabled means unreachable, not powered down: dropping the attached host and stopping advertising is what a user turns this off for, and a stack that cannot be torn down at runtime is no reason to refuse them that.
Sourcefn request_attention(&mut self)
fn request_attention(&mut self)
A covered frame was queued for an attached-or-future host (T-1000E: request the attention LED).
Sourcefn clear_attention(&mut self)
fn clear_attention(&mut self)
The host-facing queue drained to empty (T-1000E: clear it).
Sourcefn note_transmit_load(&mut self)
fn note_transmit_load(&mut self)
A transmit is about to start; boards with a battery-level estimator mark the load spike.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.