Session

Struct Session 

Source
pub struct Session<A: AesProvider, S: Sha256Provider, const TX: usize = 1> { /* private fields */ }

Implementations§

Source§

impl<A: AesProvider, S: Sha256Provider, const TX: usize> Session<A, S, TX>

Source

pub fn new( config: SessionConfig, boot_status: Status, engine: CryptoEngine<A, S>, ) -> Self

boot_status is the retained hardware reset cause, reported by the first PROP_LAST_STATUS get of the first session.

Source

pub fn settings(&self) -> RadioSettings

The active radio settings.

Source

pub fn device_name(&self) -> &str

Current UTF-8 PROP_DEV_NAME value.

Source

pub fn tx_data(&self) -> &[u8]

Payload of the transmit requested by Effect::StartTransmit.

Source

pub fn tx_power(&self) -> TxPower

Power selection for the pending transmit.

Source

pub fn max_tx_power_dbm(&self) -> i8

The board’s maximum transmit power, as configured. The concrete dBm value behind TxPower::Max when a transmit is staged.

Source

pub fn tx_nocca(&self) -> bool

Whether the pending transmit requested TX_FLAG_NOCCA — skip the pre-transmit channel-activity check.

Source

pub fn has_pending_tx(&self) -> bool

Whether a transmit is awaiting Session::on_tx_result.

Source

pub fn queued_frame_count(&self) -> usize

Number of received frames currently waiting for the host.

Source

pub fn dev_domain_version(&self) -> u32

Monotonic generation of the device-domain node tables and the live device key. The firmware caches this and re-syncs the live device node’s MAC whenever it changes (device-node plan increment 3).

Identity provisioning bumps it too, even though a newly provisioned key only takes effect at the next boot (live-state-until-reboot, as with CMD_CLEAR): the old key stops being one the device claims immediately, and the node has to be told so it can stop originating traffic under it.

Source

pub fn dev_channel_keys(&self) -> impl Iterator<Item = [u8; 32]> + '_

The device identity’s provisioned channel keys (raw symmetric keys, not the derived identifiers). The firmware joins each into the device node so it processes multicast on that channel.

Source

pub fn dev_peers(&self) -> impl Iterator<Item = [u8; 32]> + '_

The device identity’s provisioned peer public keys. The firmware registers each with the device node’s MAC.

Source

pub fn repeater_enabled(&self) -> bool

PROP_MAC_REPEATER_ENABLED: whether the device node should autonomously forward overheard routable frames and advertise NodeRole::Repeater. Part of the device domain, so it changes Session::dev_domain_version and the firmware reconciles it against the live MAC on the next sync.

Source

pub fn repeater_regions(&self) -> &[u8]

PROP_MAC_REPEATER_REGIONS: the flood-forwarding region filter, in wire order — concatenated 2-octet codes, empty for no restriction. This is also exactly the Supported Regions identity option payload, so a caller advertising the device’s regions can forward these bytes unchanged.

Source

pub fn repeater_default_region(&self) -> Option<[u8; 2]>

PROP_MAC_REPEATER_DEFAULT_REGION: the code inserted into an untagged flood packet, or None to never tag.

Source

pub fn repeater_min_rssi(&self) -> Option<i16>

PROP_MAC_REPEATER_MIN_RSSI: minimum received RSSI in dBm for flood forwarding, or None for no threshold.

Source

pub fn repeater_min_snr(&self) -> Option<i8>

PROP_MAC_REPEATER_MIN_SNR: minimum received SNR in whole dB for flood forwarding, or None for no threshold.

Source

pub fn dev_key(&self) -> Option<&[u8; 32]>

The live PROP_DEV_KEY value. None once a factory reset (CMD_CLEAR + CMD_RST) completes — the firmware uses this edge to make a running device node dormant.

Source

pub fn reset(&mut self, reason: Status, emit: &mut impl FnMut(&[u8])) -> Effect

Reset all protocol state to post-reset values, announce the reset with the given reason, and return the radio effect applying the post-reset radio configuration.

Used for CMD_RST (with [Status::RESET_SOFTWARE]). With a saved snapshot the post-reset value of every saved device-domain property is its saved value — including the PHY enable state; the documented defaults apply only when nothing is saved. The host domain always returns to its documented defaults: it is never saved. Queue contents and replay baselines are discarded either way.

Source

pub fn attach(&mut self, link_secure: bool)

A host attached. Resets session state only (spec §Attach): the device and host domains — PHY configuration and enable state, device name, duty accounting, provisioning, and the inbound queue — are untouched, and nothing is emitted; the attach itself produces no notification. Accepted frames are delivered live from here on; queued frames wait for CMD_QUEUE_DRAIN.

link_secure states whether this transport meets its security binding for key provisioning (spec §Provisioning Security): physical possession for serial transports, an encrypted bonded LESC link for BLE. Key-bearing writes are refused while false.

Source

pub fn detach(&mut self)

The host detached. Session state is discarded; the device and host domains keep operating detached: accepted frames are queued instead of delivered (delegated acknowledgement arrives with CAP_HOST_AUTO_ACK).

Source

pub fn handle_frame( &mut self, bytes: &[u8], now_ms: u64, emit: &mut impl FnMut(&[u8]), ) -> Option<Effect>

Handle one decoded ULCP frame from the host.

Source

pub fn on_radio_rx( &mut self, data: &[u8], rssi_dbm: i16, snr_cb: i16, lqi: Option<NonZeroU8>, now_ms: u64, emit: &mut impl FnMut(&[u8]), ) -> Option<Effect>

Report a frame received on air at now_ms. While a host is attached, accepted frames are emitted live as CMD_STR_RECV (promiscuous mode bypasses filtering for live delivery only); while detached, accepted frames are placed in the inbound queue, authenticated duplicates coalesce, and a qualifying frame may produce a delegated-acknowledgement transmit effect. Ignored while the PHY is disabled or the frame exceeds the MTU (an unstorable frame is never acknowledged).

Source

pub fn on_tx_result( &mut self, outcome: TxOutcome, now_ms: u64, emit: &mut impl FnMut(&[u8]), ) -> Option<Effect>

Report completion of the transmit started by Effect::StartTransmit.

Source

pub fn respond_rssi( &mut self, tid: u8, rssi: Result<i16, ()>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred PROP_PHY_RSSI read requested via Effect::SampleRssi. rssi is the sampled value in dBm, or Err if the radio read failed. Quote the same tid the effect carried.

Source

pub fn respond_identity_blob( &mut self, tid: u8, blob: Result<&[u8], ()>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred PROP_IDENT read requested via Effect::SignIdentity. blob is the complete signed node-identity payload — the canonical unsigned encoding followed by its 64-octet detached signature — or Err if it could not be produced. Quote the same tid the effect carried.

Source

pub fn ident_role(&self) -> Option<u8>

PROP_IDENT_ROLE: the advertised ROLE byte, or None to let the device derive it from its live forwarding state.

Source

pub fn ident_mobile(&self) -> bool

PROP_IDENT_MOBILE: whether the device identity advertises the MOB capability bit.

Source

pub fn dev_discoverable(&self) -> bool

PROP_DEV_DISCOVERABLE: whether the device identity answers Identity Requests.

Source

pub fn advert_interval_s(&self) -> u32

PROP_ADVERT_INTERVAL: seconds between unsolicited advertisements, 0 for none.

Source

pub fn beacon_interval_s(&self) -> u32

PROP_BEACON_INTERVAL: seconds between unsolicited beacons, 0 for none.

Source

pub fn startup_beacon(&self) -> bool

PROP_STARTUP_BEACON: whether one beacon goes out at bring-up.

Source

pub fn tz_offset_min(&self) -> i16

PROP_TZ_OFFSET: minutes east of UTC.

Source

pub fn gnss_enabled(&self) -> bool

PROP_GNSS_ENABLED: whether the receiver should be powered.

Always false on a board without CAP_GNSS, so a platform can act on it without first asking whether it has a receiver.

Source

pub fn gnss_ident_update(&self) -> bool

PROP_GNSS_IDENT_UPDATE: whether fixes refresh the advertised node identity’s location.

Source

pub fn gnss_ident_precision(&self) -> u8

PROP_GNSS_IDENT_PRECISION: the precision the advertised location is clamped to.

Source

pub fn gnss_time_trust(&self) -> bool

PROP_GNSS_TIME_TRUST: whether receiver-derived time may set the wall clock.

Source

pub fn alert(&self) -> AlertState

PROP_ALERT: what the device is currently doing to draw attention to itself.

Source

pub fn alert_deadline_ms(&self) -> Option<u64>

When the running alert gives itself up, as a monotonic millisecond deadline on the caller’s clock, or None when no alert is running.

The driver arms a timer on this and calls Session::poll_alert when it fires. Enforcing the bound centrally is what keeps the spec’s “a device MUST bound how long it will remain in ALERT_LOCATE” from being a promise each board has to remember to keep.

Source

pub fn poll_alert( &mut self, now_ms: u64, emit: &mut impl FnMut(&[u8]), ) -> Option<Effect>

Expire a running alert whose deadline has passed, returning the effect that stops the board’s indication.

Safe to call at any time: it does nothing until the deadline is actually reached, so a driver that polls it on every loop iteration behaves identically to one that arms a precise timer.

Source

pub fn cancel_alert(&mut self, emit: &mut impl FnMut(&[u8])) -> Option<Effect>

Cancel a running alert from the device itself — the button press of whoever found the radio.

Returns the effect that stops the indication, or None when no alert was running (so a board can use the return to decide whether the press was consumed).

Source

pub fn toggle_gnss(&mut self, emit: &mut impl FnMut(&[u8])) -> Option<bool>

Flip PROP_GNSS_ENABLED from the device itself — a button on a board that offers the receiver as a user-facing switch.

Returns the new state, or None on a device without CAP_GNSS (so a board can report a press unconditionally). No effect is returned: the switch reaches the platform through the device-domain mirror, the same path a host write, a boot restore and a CMD_RST all take.

The transition is announced like any the host did not command. PROP_GNSS_ENABLED is not otherwise an asynchronous property — nothing else moves it behind the host’s back — but a switch the operator can reach is exactly a thing that does.

Source

pub fn publish_battery( &mut self, sample: BatteryStatus, emit: &mut impl FnMut(&[u8]), ) -> bool

Publish an unsolicited PROP_BATTERY snapshot (spec §PROP_BATTERY, Asynchronous Updates: Yes).

The platform decides when a measurement is worth announcing — it owns the sampling cadence and the charge-state edges, and it is the only layer that sees every sample. This publishes what it hands over, so the session keeps its rule that it never caches a reading: nothing here can answer a later CMD_PROP_GET.

Returns whether a frame was emitted. Nothing is published while no host is attached (there is nobody to notify), and a snapshot populating a field the configured BatteryFields never claimed is dropped rather than sent — an unsolicited notification has no transaction to fail. A snapshot that merely omits an advertised field is published as-is: absence is how the device says the value is not knowable right now.

Source

pub fn respond_battery( &mut self, tid: u8, sample: Result<BatteryStatus, ()>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred PROP_BATTERY read requested via Effect::SampleBattery. sample is the platform’s snapshot, or Err if the measurement failed. Quote the same tid the effect carried.

A snapshot populating a field the configured BatteryFields never claimed is refused as STATUS_FAILURE; one that omits an advertised field is answered as-is, since a field the platform cannot currently substantiate is reported by its absence.

Source

pub fn respond_illuminance( &mut self, tid: u8, millilux: Option<u32>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred PROP_ILLUMINANCE read requested via Effect::SampleIlluminance. millilux is the measurement, or None when the sensor could not be read. Quote the same tid the effect carried.

A failed read is the empty value rather than an error status: the property is a measurement, and “no reading right now” is the same answer PROP_TIME gives for a clock that has never been set.

Source

pub fn respond_time( &mut self, tid: u8, epoch: Option<u32>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred PROP_TIME read requested via Effect::ReadTime. epoch is the platform’s wall clock in Unix seconds, or None when the device does not know what time it is. Quote the same tid the effect carried.

Not knowing is a legitimate answer, not a failure: it is reported as the empty value, which is precisely what tells a host — and a device’s own display — that there is no clock to show.

Source

pub fn publish_time( &mut self, epoch: Option<u32>, emit: &mut impl FnMut(&[u8]), ) -> bool

Publish an unsolicited PROP_TIME (spec §PROP_TIME, Asynchronous Updates: Yes).

The platform decides what is worth announcing — it owns the clock and is the only layer that sees every source that touches it. A clock going from unknown to known is the announcement that matters most; a fresh fix agreeing with the clock to the second is not.

Returns whether a frame was emitted; nothing is published while no host is attached.

Source

pub fn respond_gnss( &mut self, tid: u8, key: u32, sample: Result<GnssSnapshot, ()>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred positioning read requested via Effect::SampleGnss. sample is the receiver’s current view, or Err if it could not be obtained. Quote the same tid and key the effect carried.

A receiver that is off or still searching is not a failure — it reports [GnssSnapshot::SEARCHING], which answers zero for the facts it is sure of and empty for the position it does not have.

Source

pub fn publish_gnss( &mut self, key: u32, snapshot: &GnssSnapshot, emit: &mut impl FnMut(&[u8]), ) -> bool

Publish one positioning property as an unsolicited CMD_PROP_IS (spec §PROP_GNSS_LOCATION / §PROP_GNSS_FIX, Asynchronous Updates: Yes).

The platform decides the cadence, as it does for PROP_BATTERY: it sees every sentence the receiver produces and is the only layer that can tell a meaningful change from a jittering last digit.

Returns whether a frame was emitted. key must be a positioning property; anything else, and any publication while no host is attached, is dropped.

Source

pub fn drain_step(&mut self, now_ms: u64, emit: &mut impl FnMut(&[u8])) -> bool

Advance the drain started by Effect::DrainQueue one step, emitting either the next covered frame (oldest first, as CMD_STR_RECV with buffered metadata) or, once the covered set is exhausted, the completion status. Returns true while another call is needed; flush the transport between calls.

Source

pub fn encode_snapshot(&self, out: &mut [u8]) -> Option<usize>

Encode the current device and host domains as a snapshot for Effect::SaveSnapshot. out must hold SNAPSHOT_MAX bytes.

Source

pub fn restore_at_boot(&mut self, bytes: &[u8]) -> Result<Effect, SnapshotError>

Restore a stored snapshot at boot, before any host command is processed. On success the saved configuration is applied — the returned effect re-enables the PHY if it was enabled when saved, and detached operation (filtering, queueing, delegation) begins immediately.

The payload is decoded and validated into a candidate state first and committed in one step, so a malformed option arriving late in the decode cannot leave the device half-configured. On rejection nothing is modified and the caller should offer the next-older committed generation; see [Session::note_snapshot_ rejected] for what the device reports when none decodes.

Source

pub fn note_snapshot_rejected(&mut self)

Record that a stored generation was rejected at boot.

Called once per rejected generation. If a later, older generation restores, PROP_SAVED reports SavedStatus::Fallback — the device is working but running on stale configuration, which is both more actionable and more urgent than “something was wrong”. If none restores it reports SavedStatus::Unreadable, which a host can tell apart from “nothing saved”.

Source

pub fn saved_status(&self) -> SavedStatus

What PROP_SAVED reports (spec §Saved State).

Source

pub fn respond_save( &mut self, tid: u8, result: Result<(), ()>, emit: &mut impl FnMut(&[u8]), )

Complete the durable write requested via Effect::SaveSnapshot, quoting the same tid. On Ok the captured state becomes the post-reset baseline; on Err the previous snapshot (if any) must have been left intact by the caller and remains in effect.

Source

pub fn note_snapshot_saved(&mut self)

Note that the live state was persisted without a host having asked — a device-initiated save, such as a switch the operator flipped at the board.

Required after any such write. The session answers CMD_RST and CMD_RESTORE from its own copy of the snapshot rather than by re-reading flash, so a save it was not told about would leave the device restoring the values it had at boot and silently undoing what the operator did.

Source

pub fn respond_clear( &mut self, tid: u8, result: Result<(), ()>, emit: &mut impl FnMut(&[u8]), )

Complete the durable erase requested via Effect::ClearSaved, quoting the same tid. Live state is unaffected either way: the live device identity in particular remains in effect until the CMD_RST that completes a factory reset.

Source

pub fn identity_request(&self) -> Option<IdentitySource>

The staged PROP_DEV_PRIVATE_KEY provisioning awaiting Effect::ProvisionIdentity execution.

Source

pub fn respond_identity( &mut self, tid: u8, result: Result<[u8; 32], ()>, emit: &mut impl FnMut(&[u8]), )

Complete the device-identity provisioning requested via Effect::ProvisionIdentity, quoting the same tid. result carries the new identity’s public key once the keypair is durably stored — success is announced as CMD_PROP_IS for PROP_DEV_KEY and the private key is never emitted (spec §PROP_DEV_PRIVATE_KEY). On Ok the new identity is adopted even if the transaction was abandoned by a detach: the durable write already happened, and flash is the source of truth.

Source

pub fn set_boot_identity(&mut self, public_key: [u8; 32])

Install the independently persisted device identity’s public key at boot, before any host command: the post-reset value of PROP_DEV_KEY is the persisted identity, snapshot or not.

Source

pub fn respond_pin_set( &mut self, tid: u8, result: Result<(), ()>, emit: &mut impl FnMut(&[u8]), )

Complete a deferred write of the write-only BLE pairing PIN.

Auto Trait Implementations§

§

impl<A, S, const TX: usize> Freeze for Session<A, S, TX>
where A: Freeze, S: Freeze,

§

impl<A, S, const TX: usize = 1> !RefUnwindSafe for Session<A, S, TX>

§

impl<A, S, const TX: usize> Send for Session<A, S, TX>
where A: Send, S: Send,

§

impl<A, S, const TX: usize> Sync for Session<A, S, TX>
where A: Sync, S: Sync,

§

impl<A, S, const TX: usize> Unpin for Session<A, S, TX>
where A: Unpin, S: Unpin,

§

impl<A, S, const TX: usize = 1> !UnwindSafe for Session<A, S, TX>

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.