RFM69-keten

We kunnen de IoT-knopen met RFM69-radio’s niet direct op het internet aansluiten: we gebruiken een gateway als tussenstation. Deze zorgt onder andere voor de protocol-conversie tussen het RFM69-protocol en het IP-protocol.

RFM-protocol

Zoals gezegd gebruiken we de RFM69-radio voor pakket-communicatie in de 868MHz-band. De RFM69-radio is niet erg geschikt voor de IP-protocollen. We gebruiken een eigen RFM-protocol. Dit wordt geïmplementeerd door de library myRF69.h.

../_images/rfm69-hardware-packet-format.png

(uit RFM69HCW-datasheet, p. 52)

Een RFM69-pakket bevatten de volgende onderdelen:

header:met preamble en sync-word, geeft het begin van het pakket aan en bevat de subnetwerk-code;
length:de lengte van de payload, inclusief de lengte- en destination bytes;
destination:netwerk-adres (0..63) van de bestemming;
origin(*):netwerk-adres (0..63) van de afzender;
payload:de data die getransporteerd moet worden; de payload wordt versleuteld verstuurd (AES-128 code)
checksum (CRC):cyclic redundancy check, om te controleren of de payload niet beschadigd is;

(*) De origin is geen onderdeel van het hardware-protocol. Dit is toegevoegd door het software-protocol (myRF69.h). Bits 6..7 bevatten enkele flags. Bits 0..5 bevatten het origin-address.

De adressen 0, 61, 62, 63 hebben een speciale betekenis:

  • 0: broadcast
  • 61: send-only node
  • 62: reserved
  • 63: receive-all

Opmerking: er kunnen meerdere “send-only” nodes zijn: omdat deze geen berichten ontvangen hoeven deze ook geen eigen adres te hebben.

Payload-formaat

Het formaat voor de payload kunnen we zelf bepalen. In verband met toekomstige uitbreidingen, en het gebruik van meerdere formaten en protocollen, gebruiken we het eerste byte van de payload (na de origin) om het payload-formaat aan te geven. Het specifieke formaat bepaalt het gebruik van rest van de payload. De volgende formaten zijn in gebruik:

  • 1: JSON
  • 2: LPP (gevolgd door: IoT-knoop-ID (2 bytes), en een reeks items zoals hieronder beschreven).

Cayenne LPP formaat

Voor de payload gebruiken we een binair formaat, om de pakketten klein te houden. We kunnen hiervoor onze eigen conventies gebruiken, maar het is handiger om aan te sluiten bij conventies die elders gebruikt worden.

We gebruiken het Cayenne Low Power Payload (LPP) formaat, zoals beschreven in: https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload. Deze zijn gebaseerd op de IPSO-conventies, zie: https://github.com/AllSmartObjects/smartobject/blob/master/docs/templates.md

De payload bestaat uit een reeks items, waarbij elk item bestaat uit:

  • channel (1 byte): identificeert de sensor of actuator van de IoT-knoop;
  • type (1 byte): type van de sensor/waarde, bijv. “temperatuur”’‘
  • value (1 of meer bytes): de sensordata.

Enkele voorbeelden van veel-voorkomende types sensordata:

LPP types
Sensor Naam Type Hex Bytes Resolutie
Digitale input dIn 0 0 1 1
Digitale output dOut 1 1 1 1
Analoge input aIn 2 2 2 0.01 Signed
Analoge output aOut 3 3 2 0.01 Signed
Lichtniveau illuminance 101 65 2 1 Lux Unsigned
Aanwezigheid presence 102 66 1 1
Temperatuur temperature 103 67 2 0.1 °C Signed
Rel. Luchtvochtigheid humidity 104 68 1 0.5% Unsigned
Luchtdruk barometer 115 73 2 0.1 hPa Unsigned

Opmerkingen:

Te doen

  • kun je in een CSV-tabel meerdere sub-rijen hebben?
  • Vraag: wat betekent hier die MSB???
  • Vraag: hoe sluit je deze reeks af? is er daarvoor een speciaal type? Of gebruik je daarvoor de lengte van de payload?

Opmerking/vraag: in de downlink-berichten is er geen type-veld; en de data zijn altijd twee bytes??? In dat geval is er wel een afsluiter?

Door deze afspraken kunnen we voor veel voorkomende sensoren en actuatoren automatisch een dashboard aanmaken, uit een binaire payload of uit de JSON-versie daarvan.

Een JSON-formaat bij het Cayenne LPP-formaat

Voorbeelden:

{"0": {"temperature": 123},
 "1": {"humidity": 456}
}

(NB: de vraag is ook welk formaat bij de verdere behandeling handig is. In het geval van IPSO kun je bijv. bij temperatuur ook eenheden opgeven; dan ligt een formaat: "temperature": {"value": 123, ...} voor de hand. Maar het lijkt niet lastig om dit evt. uit te breiden.)

Encryptie

De payload wordt versleuteld verstuurd. Deze versleuteling betreft alleen het verkeer tussen de IoT-knoop en de gateway. In de gateway zelf is de payload niet versleuteld. (We zouden evt. nog een end-to-end encryptie kunnen toevoegen, zoals in het geval van LoRa.)

Adressering

Het RFM-protocol gebruikt lokale RFM-netwerk-adressen. Dit zijn waarden in het bereik 1..60. Voor het toepassingsprotocol gebruiken we een MQTT formaat, met (o.a.) de topics node/ID/sensors en node/ID/actuators. Hierin is ID de identificatie van de IoT-knoop; voorlopig gebruiken we daarvoor een 16-bits waarde, genoteerd als een hexadecimaal getal.

De gateway moet een RFM-adres omzetten in een IoT-knoop-ID, en omgekeerd.

We gebruiken hiervoor de volgende aanpak:

  • het RFM-netwerk-adres en de IoT-knoop-ID worden statisch toegewezen; we configureren deze in het programma van de betreffende knoop;
  • een IoT-knoop stuurt in elk (uplink) bericht de eigen IoT-knoop-ID;
  • de gateway houdt (in een tabel) bij, welk RFM-netwerk-adres hoort bij welke IoT-knoop;
  • in het geval van een downlink-bericht bepaalt de gateway uit deze tabel wat het RFM-netwerk-adres is bij de gegeven IoT-knoop-ID.