gfroerli / firmware

Firmware for the water temperature sensor project
GNU General Public License v3.0
6 stars 1 forks source link

Rethink LoRaWAN message format #79

Closed rnestler closed 3 years ago

rnestler commented 3 years ago

Currently we have a hardcoded message format that looks is just 4 little endian floats:

[T_water, T_inside, RH_inside, V_supply]

This doesn't allow any versioning or extensibility at all.

Solutions

We could add a version byte.

We could use the FPort field in the MACPayload of a LoRaWAN frame, which provides application specific values in the range of 1..223

dbrgn commented 3 years ago

I agree. I wouldn't call it "version byte", but instead "message type". This way we can both use it for new message versions as well as nodes with different sensor types.

rnestler commented 3 years ago

New format proposal:

|data_mask|data|
The data_mask has a bit set for every value that is available. This allows to send up to 8 values: bit value type
xxxxxxx1 T_water u12
xxxxxx1x T_inside u16
xxxxx1xx RH_inside u16
xxxx1xxx V_supply u12
xxx1xxxx reserved -
xx1xxxxx reserved -
x1xxxxxx reserved -
1xxxxxxx reserved -

So if we just have T_water and V_supply available we'd have the following frame:

|0b00001001|T_water|V_supply|

in code it may look like this:

struct MeasurementMessage {
    t_water: Option<U12>,
    t_inside: Option<u16>,
    rh_inside: Option<u16>,
    v_supply: Option<U12>,
}

impl MeasurementMessage {
    pub fn encode(&mut [u8]) -> u8 {
        // a bit of magic here ;)
    }
}
dbrgn commented 3 years ago

I like the mask byte! :heart:

I'd use integer types for the values though (millidegrees celsius and 0.1% RH)

rnestler commented 3 years ago

I'd use integer types for the values though (millidegrees celsius and 0.1% RH)

We could also send the raw u16 bytes and convert on the receiver to save some message space and thus power.

dbrgn commented 3 years ago

That's a good point! It's a bit less flexible (since we leak implementation details and need to update the message type if the sensor changes), but it saves airtime which is one of the most important things to optimize for.

dbrgn commented 3 years ago

Regarding crates to parse and generate non-aligned payloads:

screenshot-20200916-001824

rnestler commented 3 years ago

I was made aware by my roommate that the resolution and range we use for the sensor values are way too large :slightly_smiling_face: We could for example reduce the size even further by saying:

Than we could use an even lower resolution per sensor value.

dbrgn commented 3 years ago

@rnestler good point. Can you create a concrete proposal?

dbrgn commented 3 years ago

This is now implemented.

rnestler commented 3 years ago

Is it though? Did we also implement the versioning?

dbrgn commented 3 years ago

@rnestler

We could use the FPort field in the MACPayload of a LoRaWAN frame, which provides application specific values in the range of 1..223

I agree. I wouldn't call it "version byte", but instead "message type". This way we can both use it for new message versions as well as nodes with different sensor types.

rnestler commented 3 years ago

@dbrgn But is this done already? That we use the FPort field to distinguish?

dbrgn commented 3 years ago

Well, we do use a FPort value in the rn2xx3 branch, so I guess... yes?

We only have a single message type right now, so it doesn't matter which FPort we use :wink: Once we include the devices in the productive device group on TTN, we'll just have to ensure that it doesn't collide with the existing FPort (which is 1 I think, so we could use 2).