Skip to main content

Message

Enum Message 

Source
pub enum Message {
    Version {
        station: String,
        firmware: String,
        package: String,
        model: String,
        protocol: u32,
        features: String,
    },
    RouterConfig {
        net_id: Option<Vec<u32>>,
        join_eui: Vec<(u64, u64)>,
        region: String,
        max_eirp: f64,
        hwspec: String,
        freq_range: (u32, u32),
        data_rates: Vec<Option<(u8, u32, bool)>>,
    },
    JoinRequest {
        mhdr: u8,
        join_eui: Eui,
        dev_eui: Eui,
        dev_nonce: u16,
        mic: i32,
        data_rate: u8,
        frequency_hz: u32,
        levels: Levels,
    },
    Uplink {
        mhdr: u8,
        dev_addr: i32,
        fctrl: u8,
        fcnt: u16,
        fopts: Vec<u8>,
        fport: Option<u8>,
        payload: Vec<u8>,
        mic: i32,
        data_rate: u8,
        frequency_hz: u32,
        levels: Levels,
    },
    Proprietary {
        payload: Vec<u8>,
        data_rate: u8,
        frequency_hz: u32,
        levels: Levels,
    },
    Downlink {
        dev_eui: Eui,
        class: u8,
        diid: i64,
        pdu: Vec<u8>,
        rx_delay: Option<u8>,
        rx1: Option<(u8, u32)>,
        rx2: Option<(u8, u32)>,
        ping_slot: Option<(u8, u32)>,
        priority: u8,
        xtime: Option<i64>,
        rctx: Option<i64>,
        gpstime: Option<i64>,
    },
    Schedule {
        frames: Vec<Broadcast>,
    },
    Transmitted {
        diid: i64,
        dev_eui: Eui,
        rctx: i64,
        xtime: i64,
        txtime: f64,
        gpstime: Option<i64>,
    },
    TimeSync {
        txtime: Option<i64>,
        xtime: Option<i64>,
        gpstime: Option<i64>,
    },
    Other {
        msgtype: String,
    },
}
Expand description

Every message the websocket carries once the session is open.

Variants§

§

Version

What the station is, sent first thing after the websocket opens.

Fields

§station: String

The station software.

§firmware: String

Its firmware.

§package: String

The package it came from.

§model: String

The hardware model.

§protocol: u32

The protocol version it speaks.

§features: String

What it can do, such as gps or prod.

§

RouterConfig

How the server tells the station to configure its radios.

Fields

§net_id: Option<Vec<u32>>

The networks whose data frames the station forwards, or None to forward every network’s.

A station matches each entry against the top seven bits of a frame’s device address, so an empty list forwards no data frame at all, while None, written as null, filters nothing.

§join_eui: Vec<(u64, u64)>

The join identifier ranges whose join requests are forwarded, as inclusive pairs; an empty list filters nothing.

§region: String

The region name, such as EU868.

§max_eirp: f64

The highest radiated power the region allows, in dBm.

§hwspec: String

The concentrator the configuration is written for, such as sx1301/1.

§freq_range: (u32, u32)

The lowest and highest frequency the station may use, in hertz.

§data_rates: Vec<Option<(u8, u32, bool)>>

The data rates, indexed by data-rate number, each a spreading factor, a bandwidth in hertz, and whether it is downlink only.

A spreading factor of 0 is FSK. None is a number the table leaves undefined, which the protocol writes as a spreading factor of -1 so the entries after it keep their numbers.

§

JoinRequest

A join request the station heard.

Fields

§mhdr: u8

The MAC header byte.

§join_eui: Eui

The application the device is joining.

§dev_eui: Eui

The device asking.

§dev_nonce: u16

The nonce it used, which a server must not see twice.

§mic: i32

The message integrity code.

§data_rate: u8

The data rate it arrived at.

§frequency_hz: u32

The frequency it arrived on, in hertz.

§levels: Levels

How it was heard.

A data frame the station heard.

Fields

§mhdr: u8

The MAC header byte.

§dev_addr: i32

The device address it came from.

§fctrl: u8

The frame control byte.

§fcnt: u16

The frame counter, as the sixteen bits on the air.

§fopts: Vec<u8>

The frame options, as bytes.

§fport: Option<u8>

The port, or None for a frame carrying only options.

§payload: Vec<u8>

The encrypted payload.

§mic: i32

The message integrity code.

§data_rate: u8

The data rate it arrived at.

§frequency_hz: u32

The frequency it arrived on, in hertz.

§levels: Levels

How it was heard.

§

Proprietary

A frame this protocol does not describe, which the station heard and passes on whole.

Fields

§payload: Vec<u8>

The frame as it arrived, header and integrity code included.

§data_rate: u8

The data rate it arrived at.

§frequency_hz: u32

The frequency it arrived on, in hertz.

§levels: Levels

How it was heard.

A frame the server asks the station to transmit.

A class A frame, and a class C frame answering an uplink, are timed from that uplink’s xtime and go out in rx1 or rx2, the first preferred. A class B frame goes out at gpstime in a ping slot. A class C frame answering nothing names rx2 alone.

Fields

§dev_eui: Eui

The device it is for.

§class: u8

Which class of downlink this is: 0 for A, 1 for B, 2 for C.

§diid: i64

The identifier the transmission report carries back.

§pdu: Vec<u8>

The frame to transmit.

§rx_delay: Option<u8>

The delay before the first receive window, in seconds.

§rx1: Option<(u8, u32)>

The first window, as a data rate and a frequency in hertz.

§rx2: Option<(u8, u32)>

The second window, as a data rate and a frequency in hertz.

§ping_slot: Option<(u8, u32)>

The ping slot a class B frame goes out in, as a data rate and a frequency in hertz.

§priority: u8

How urgent it is.

§xtime: Option<i64>

The station clock the first window is counted from.

§rctx: Option<i64>

The radio context the uplink was heard on.

§gpstime: Option<i64>

When a class B frame goes out, in microseconds since the GPS epoch.

§

Schedule

Frames the server asks the station to transmit to a group at a given time.

A station reports nothing back about these, unlike a Message::Downlink.

Fields

§frames: Vec<Broadcast>

What to transmit, in the order given.

§

Transmitted

What became of a frame the station was asked to transmit.

Fields

§diid: i64

The identifier from the downlink.

§dev_eui: Eui

The device it was for.

§rctx: i64

The radio context it went out on.

§xtime: i64

The station clock it went out at.

§txtime: f64

The time it went out, in seconds.

§gpstime: Option<i64>

The GPS time, when the station has one.

§

TimeSync

The clock the two keep between them.

Fields

§txtime: Option<i64>

The station clock.

§xtime: Option<i64>

The station clock, when the server is transferring GPS time against it.

§gpstime: Option<i64>

The GPS time.

§

Other

A message this crate does not read, kept so a caller can see what arrived.

Fields

§msgtype: String

What the message called itself.

Implementations§

Source§

impl Message

Source

pub fn msgtype(&self) -> &str

Returns the word this message calls itself on the wire.

§Returns

The msgtype value, such as updf.

Source

pub fn heard( frame: &[u8], data_rate: u8, frequency_hz: u32, levels: Levels, ) -> Result<Message, ProtocolError>

Reads a frame the radio heard into the message that reports it.

A station holds no key, so nothing is verified here: the frame is split into the fields the protocol names and the server judges them. A join request becomes Message::JoinRequest and a data frame Message::Uplink.

§Arguments
  • frame - the bytes as they arrived, header through message integrity code.
  • data_rate - the data rate it arrived at.
  • frequency_hz - the frequency it arrived on, in hertz.
  • levels - how it was heard.
§Returns

The message to send up.

§Errors

Returns ProtocolError::Payload when the frame is shorter than the fields its header names, or carries a kind a station does not send up.

§Examples
use pamoja_gateway::station::{Levels, Message};
use pamoja_lorawan::{Session, Uplink};

// A node's seventh uplink, a reading on port 2, as its radio sent it.
let node = Session::new(0x2601_1BDA, [7; 16], [8; 16]);
let frame = node
    .encode_uplink(&Uplink::new(7, 2, b"21.5"))
    .expect("an uplink frame");

let heard = Message::heard(frame.as_bytes(), 5, 868_100_000, Levels::default())
    .expect("a station sends this one up");
match heard {
    Message::Uplink { dev_addr, fcnt, fport, payload, .. } => {
        assert_eq!(dev_addr as u32, node.dev_addr());
        assert_eq!(fcnt, 7);
        assert_eq!(fport, Some(2));
        assert_eq!(payload.len(), 4, "still encrypted: a station holds no key");
    }
    other => panic!("that is a data frame, not {}", other.msgtype()),
}
Source

pub fn to_json(&self) -> String

Writes the message as the websocket carries it.

§Returns

The JSON text to send.

Source

pub fn from_json(body: &[u8]) -> Result<Message, ProtocolError>

Reads a message off the websocket.

A kind this crate does not build is returned as Message::Other rather than refused, because a station and a server may each speak more than the other does.

§Arguments
  • body - the message text.
§Returns

What arrived.

§Errors

Returns ProtocolError::Payload when the body is not a JSON object, carries no message kind, or is missing an identifier the kind it names requires.

Trait Implementations§

Source§

impl Clone for Message

Source§

fn clone(&self) -> Message

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 Debug for Message

Source§

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

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

impl PartialEq for Message

Source§

fn eq(&self, other: &Message) -> 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 Message

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.