Skip to main content

MacCommand

Enum MacCommand 

Source
pub enum MacCommand {
Show 33 variants LinkCheckReq, LinkCheckAns { margin: u8, gateways: u8, }, LinkAdrReq { data_rate: u8, tx_power: u8, channel_mask: u16, mask_control: u8, transmissions: u8, }, LinkAdrAns { power_ack: bool, data_rate_ack: bool, channel_mask_ack: bool, }, DutyCycleReq { max_duty_cycle: u8, }, DutyCycleAns, RxParamSetupReq { rx1_offset: u8, rx2_data_rate: u8, frequency_hz: u32, }, RxParamSetupAns { rx1_offset_ack: bool, rx2_data_rate_ack: bool, channel_ack: bool, }, DevStatusReq, DevStatusAns { battery: u8, margin: i8, }, NewChannelReq { index: u8, frequency_hz: u32, max_data_rate: u8, min_data_rate: u8, }, NewChannelAns { data_rate_range_ok: bool, frequency_ok: bool, }, RxTimingSetupReq { delay: u8, }, RxTimingSetupAns, TxParamSetupReq { max_eirp: u8, uplink_dwell: bool, downlink_dwell: bool, }, TxParamSetupAns, DlChannelReq { index: u8, frequency_hz: u32, }, DlChannelAns { uplink_frequency_exists: bool, frequency_ok: bool, }, DeviceTimeReq, DeviceTimeAns { seconds: u32, fraction: u8, }, RelayConfReq { enabled: bool, cad_periodicity: u8, default_channel_index: u8, second_channel_index: u8, second_channel_data_rate: u8, second_channel_ack_offset: u8, second_channel_frequency_hz: u32, }, RelayConfAns { cad_periodicity_ack: bool, default_channel_index_ack: bool, second_channel_index_ack: bool, second_channel_data_rate_ack: bool, second_channel_ack_offset_ack: bool, second_channel_frequency_ack: bool, }, EndDeviceConfReq { relay_mode: u8, smart_enable_level: u8, back_off: u8, second_channel_index: u8, second_channel_data_rate: u8, second_channel_ack_offset: u8, second_channel_frequency_hz: u32, }, EndDeviceConfAns { second_channel_ack_offset_ack: bool, second_channel_index_ack: bool, second_channel_data_rate_ack: bool, second_channel_frequency_ack: bool, }, FilterListReq { index: u8, action: u8, eui_len: u8, eui: [u8; 16], }, FilterListAns { combined_rules_ack: bool, eui_len_ack: bool, action_ack: bool, }, UpdateUplinkListReq { index: u8, reload_rate: u8, bucket_size: u8, dev_addr: u32, wfcnt: u32, root_wor_s_key: [u8; 16], }, UpdateUplinkListAns, CtrlUplinkListReq { index: u8, action: u8, }, CtrlUplinkListAns { index_ack: bool, wfcnt: u32, }, ConfigureFwdLimitReq { reset_limit_counters: u8, join_request_reload_rate: u8, notify_reload_rate: u8, global_uplink_reload_rate: u8, overall_reload_rate: u8, join_request_bucket_size: u8, notify_bucket_size: u8, global_uplink_bucket_size: u8, overall_bucket_size: u8, }, ConfigureFwdLimitAns, NotifyNewEndDeviceReq { dev_addr: u32, rssi_dbm: i16, snr_db: i8, },
}
Expand description

One command, in either direction.

The name says which way it travels: a request goes to a device, an answer comes back.

Variants§

§

LinkCheckReq

A device asking whether the network can hear it.

§

LinkCheckAns

How well it was heard, and by how many gateways.

Fields

§margin: u8

How far above the floor the last check arrived, in dB. 255 is reserved.

§gateways: u8

How many gateways heard it.

§

LinkAdrReq

Change rate, power, and which channels may be used.

Fields

§data_rate: u8

The rate, which each region codes for itself.

§tx_power: u8

The power, as a ceiling rather than an instruction.

§channel_mask: u16

Which channels may carry an uplink, lowest channel in the lowest bit.

§mask_control: u8

Which block of sixteen channels the mask applies to.

§transmissions: u8

How many times to send an unconfirmed uplink. Zero means the device keeps one.

§

LinkAdrAns

Which parts of the request a device took.

Fields

§power_ack: bool

Whether the power was set.

§data_rate_ack: bool

Whether the rate was set.

§channel_mask_ack: bool

Whether the channel mask was usable.

§

DutyCycleReq

Hold the device to a share of the air.

Fields

§max_duty_cycle: u8

The share is one over two to this, so 0 is no limit beyond the regional one.

§

DutyCycleAns

The device took it.

§

RxParamSetupReq

Set where and how fast the second receive window listens.

Fields

§rx1_offset: u8

How far the first window’s rate sits below the uplink rate.

§rx2_data_rate: u8

The rate of the second window.

§frequency_hz: u32

The frequency of the second window, in hertz.

§

RxParamSetupAns

Which parts of that the device took.

Fields

§rx1_offset_ack: bool

Whether the offset was in range.

§rx2_data_rate_ack: bool

Whether the rate was known.

§channel_ack: bool

Whether the frequency was usable.

§

DevStatusReq

Ask a device how it is.

§

DevStatusAns

How it is.

Fields

§battery: u8

0 on external power, 1 through 254 from empty to full, 255 when it cannot tell.

§margin: i8

The signal-to-noise ratio of the last request, in dB, from -32 to 31.

§

NewChannelReq

Create a channel, or change one.

Fields

§index: u8

Which channel. The ones a region fixes cannot be changed.

§frequency_hz: u32

The center frequency in hertz. Zero switches the channel off.

§max_data_rate: u8

The fastest rate allowed on it.

§min_data_rate: u8

The slowest rate allowed on it.

§

NewChannelAns

Whether the channel could be made.

Fields

§data_rate_range_ok: bool

Whether the device can run that range of rates.

§frequency_ok: bool

Whether its radio can reach that frequency.

§

RxTimingSetupReq

Set how long after sending the device starts listening.

Fields

§delay: u8

The delay in seconds as the command codes it, which receive_delay_s reads.

§

RxTimingSetupAns

The device took it.

§

TxParamSetupReq

Set the power and dwell time a region asks for.

Fields

§max_eirp: u8

The coded power, which eirp_dbm reads.

§uplink_dwell: bool

Whether an uplink is held to 400 ms of air time.

§downlink_dwell: bool

Whether a downlink is.

§

TxParamSetupAns

The device took it.

§

DlChannelReq

Move a channel’s downlink frequency away from its uplink one.

Fields

§index: u8

Which channel.

§frequency_hz: u32

The downlink frequency in hertz.

§

DlChannelAns

Whether that could be done.

Fields

§uplink_frequency_exists: bool

Whether the channel already had an uplink frequency to pair with.

§frequency_ok: bool

Whether the radio can reach the frequency.

§

DeviceTimeReq

A device asking the network what time it is.

§

DeviceTimeAns

The time, taken as the uplink that asked finished arriving.

Fields

§seconds: u32

Seconds since the GPS epoch, which leap seconds separate from UTC.

§fraction: u8

The fraction of that second, in steps of one part in 256.

§

RelayConfReq

Start or stop a relay, and set the channels it scans.

Fields

§enabled: bool

Whether the relay runs. With it stopped, every other field is ignored.

§cad_periodicity: u8

How often the relay scans its default channel, as TS011-1.0.1 table 18 codes it.

§default_channel_index: u8

Which of the region’s relay channels is the default one, 0 or 1.

§second_channel_index: u8

Whether a second channel is set, as table 34 codes it: 0 for none, 1 for the one the next fields describe.

§second_channel_data_rate: u8

The second channel’s data rate.

§second_channel_ack_offset: u8

How far above its frequency the second channel is acknowledged, as table 35 codes it.

§second_channel_frequency_hz: u32

The second channel’s frequency in hertz.

§

RelayConfAns

Which parts of the relay configuration were valid.

Fields

§cad_periodicity_ack: bool

Whether the scan period was.

§default_channel_index_ack: bool

Whether the default channel was.

§second_channel_index_ack: bool

Whether the second channel index was.

§second_channel_data_rate_ack: bool

Whether the second channel’s data rate was.

§second_channel_ack_offset_ack: bool

Whether its acknowledgment offset was.

§second_channel_frequency_ack: bool

Whether its frequency was.

§

EndDeviceConfReq

Set how an end device uses a relay.

Fields

§relay_mode: u8

Whether relaying is off (0), on (1), turned on after uplinks go unanswered (2), or left to the device (3), TS011-1.0.1 table 40.

§smart_enable_level: u8

How many unanswered uplinks turn relaying on in mode 2, as table 41 codes it.

§back_off: u8

How many wake-on-radio frames without an acknowledgment before the uplink goes anyway, 0 meaning every time, table 43.

§second_channel_index: u8

Whether a second channel is set, 0 for none and 1 for the one described.

§second_channel_data_rate: u8

The second channel’s data rate.

§second_channel_ack_offset: u8

How far above its frequency the second channel is acknowledged, table 35.

§second_channel_frequency_hz: u32

The second channel’s frequency in hertz.

§

EndDeviceConfAns

Which parts of the end device configuration were valid, TS011-1.0.1 table 45.

Fields

§second_channel_ack_offset_ack: bool

Whether the second channel’s acknowledgment offset was.

§second_channel_index_ack: bool

Whether the second channel index was.

§second_channel_data_rate_ack: bool

Whether its data rate was.

§second_channel_frequency_ack: bool

Whether its frequency was.

§

FilterListReq

Set one rule of a relay’s join request filter.

Fields

§index: u8

The rule, 0 being the action when no other rule matches.

§action: u8

No rule (0), forward (1) or filter (2), TS011-1.0.1 table 48.

§eui_len: u8

How many leading bytes of JoinEUI and DevEUI the rule matches. A length past FILTER_EUI_MAX is kept, so a relay can refuse it, but not its bytes past the sixteenth.

§eui: [u8; 16]

The leading bytes of JoinEUI then DevEUI, most significant first, as an EUI is written.

§

FilterListAns

Which parts of the filter rule were valid.

Fields

§combined_rules_ack: bool

Whether the fields together made a rule to create, change or remove.

§eui_len_ack: bool

Whether the length was.

§action_ack: bool

Whether the action was.

§

UpdateUplinkListReq

Trust an end device, so a relay verifies its wake-on-radio frames and forwards it.

Fields

§index: u8

The entry of the trusted list, 0 to 15.

§reload_rate: u8

Tokens earned an hour, 63 meaning no limit, TS011-1.0.1 table 54.

§bucket_size: u8

The bucket size multiplier, as table 55 codes it.

§dev_addr: u32

The end device’s address.

§wfcnt: u32

The next wake-on-radio frame counter the network expects from it.

§root_wor_s_key: [u8; 16]

The root relay session key the device’s wake-on-radio keys come from.

§

UpdateUplinkListAns

The relay took it.

§

CtrlUplinkListReq

Read the counter of a trusted end device, or remove it.

Fields

§index: u8

The entry of the trusted list.

§action: u8

Read (0) or remove (1), TS011-1.0.1 table 58.

§

CtrlUplinkListAns

The entry’s last valid counter.

Fields

§index_ack: bool

Whether the entry was in use.

§wfcnt: u32

The last wake-on-radio frame counter the relay accepted from it.

§

ConfigureFwdLimitReq

Set a relay’s forwarding limits, TS011-1.0.1 section 10.6.

Fields

§reset_limit_counters: u8

What happens to the token counters, as table 63 codes it.

§join_request_reload_rate: u8

Join requests forwarded an hour, 127 meaning no limit.

§notify_reload_rate: u8

New end device notifications an hour.

§global_uplink_reload_rate: u8

Uplinks forwarded an hour across every trusted end device.

§overall_reload_rate: u8

Every message the relay sends an hour.

§join_request_bucket_size: u8

The join request bucket size multiplier, table 55.

§notify_bucket_size: u8

The notification bucket size multiplier.

§global_uplink_bucket_size: u8

The global uplink bucket size multiplier.

§overall_bucket_size: u8

The overall bucket size multiplier.

§

ConfigureFwdLimitAns

The relay took it.

§

NotifyNewEndDeviceReq

A relay heard a wake-on-radio frame it could not verify.

Fields

§dev_addr: u32

The address the frame named.

§rssi_dbm: i16

The frame’s signal strength in dBm, carried from -142 to -15.

§snr_db: i8

Its signal-to-noise ratio in dB, carried from -20 to 11.

Implementations§

Source§

impl MacCommand

Source

pub const fn cid(&self) -> u8

The identifier this command goes out under.

§Returns

The byte, which is shared with the command answering it in the other direction.

§Examples
use pamoja_lorawan::mac::{MacCommand, CID_LINK_ADR};

let answer = MacCommand::LinkAdrAns {
    power_ack: true,
    data_rate_ack: true,
    channel_mask_ack: true,
};
assert_eq!(answer.cid(), CID_LINK_ADR, "the same byte as the request");
Source

pub const fn direction(&self) -> Direction

Which way this command travels.

§Returns

Direction::Downlink for what a network sends, Direction::Uplink for what a device answers with.

§Examples
use pamoja_lorawan::{Direction, mac::MacCommand};

assert_eq!(MacCommand::DevStatusReq.direction(), Direction::Downlink);
assert_eq!(MacCommand::LinkCheckReq.direction(), Direction::Uplink);
Source

pub const fn len(&self) -> usize

How many bytes this command takes, its identifier included.

§Returns

The length, which a reader has to know because the bytes do not carry it.

§Examples
use pamoja_lorawan::mac::MacCommand;

assert_eq!(MacCommand::LinkCheckReq.len(), 1, "the identifier and nothing else");
assert_eq!(MacCommand::DevStatusAns { battery: 200, margin: -3 }.len(), 3);
Source

pub const fn is_empty(&self) -> bool

Whether this command is only its identifier.

§Returns

Whether it carries no fields.

Source

pub fn encode(&self, out: &mut [u8]) -> Result<usize, LorawanError>

Writes this command out.

§Arguments
  • out - where to write it.
§Returns

How many bytes were written.

§Errors

LorawanError::PayloadTooLong when out is shorter than the command, and LorawanError::MalformedFrame for a frequency the field cannot hold, which is one above 1.67 GHz or one that is not a whole number of hundreds of hertz, and for a join filter longer than FILTER_EUI_MAX bytes.

§Examples
use pamoja_lorawan::mac::MacCommand;
use pamoja_lorawan::Direction;

// The network's answer to a link check: heard 20 dB above the floor by three gateways.
let mut out = [0u8; 8];
let command = MacCommand::LinkCheckAns { margin: 20, gateways: 3 };
let written = command.encode(&mut out).unwrap();

// The device reads it back from the downlink's frame options.
let (heard, taken) = MacCommand::parse(Direction::Downlink, &out[..written]).unwrap();
assert_eq!((heard, taken), (command, written));
Source

pub fn parse( direction: Direction, bytes: &[u8], ) -> Result<(MacCommand, usize), LorawanError>

Reads one command.

§Arguments
  • direction - which way the frame carrying it travels. The same identifier is a different command each way, and nothing in the bytes says which, so this is not guessed.
  • bytes - the command and whatever follows it.
§Returns

The command and how many bytes it took.

§Errors

LorawanError::FrameTooShort when the bytes stop inside the command, and LorawanError::UnknownCommand carrying the identifier when it is one this version does not know, which a caller cannot step over.

§Examples
use pamoja_lorawan::{Direction, mac::MacCommand};

// A request and its answer share an identifier, so the direction decides which one
// the same bytes are.
let mut bytes = [0u8; 2];
let request = MacCommand::DutyCycleReq { max_duty_cycle: 10 };
request.encode(&mut bytes).unwrap();

let (down, _) = MacCommand::parse(Direction::Downlink, &bytes).unwrap();
assert_eq!(down, request);

let (up, taken) = MacCommand::parse(Direction::Uplink, &bytes).unwrap();
assert_eq!(up, MacCommand::DutyCycleAns);
assert_eq!(taken, 1, "the answer has no payload, so the second byte is not its own");

Trait Implementations§

Source§

impl Clone for MacCommand

Source§

fn clone(&self) -> MacCommand

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for MacCommand

Source§

impl Debug for MacCommand

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for MacCommand

Source§

impl PartialEq for MacCommand

Source§

fn eq(&self, other: &MacCommand) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for MacCommand

Auto Trait Implementations§

Blanket Implementations§

Source§

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

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

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
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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

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

Performs the conversion.
Source§

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

Source§

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

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

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

Performs the conversion.