pamoja.gateway
Idiomatic LoRaWAN gateway facade.
A gateway hears packets from every node in range and hands them to a network server, which
hands back the packets to transmit. The protocol between them is a plain exchange of UDP
datagrams, and this speaks it from both sides: build a datagram, encode() it onto a
socket of your own, and parse() whatever arrives.
Frequencies are in hertz, payloads are bytes rather than base64, and a reception time is a
count of microseconds, so nothing has to be formatted by hand.
Example::
from pamoja.gateway import Packet, PacketKind, Rxpk, encode
from pamoja.lora import link
heard = Rxpk(868_100_000, b"hello", link=link(7, 125_000), rssi_dbm=-35.0, snr_db=5.1)
datagram = encode(Packet(PacketKind.PUSH_DATA, 0x1234, gateway="b827ebfffe010203",
packets=[heard]))
1"""Idiomatic LoRaWAN gateway facade. 2 3A gateway hears packets from every node in range and hands them to a network server, which 4hands back the packets to transmit. The protocol between them is a plain exchange of UDP 5datagrams, and this speaks it from both sides: build a datagram, :func:`encode` it onto a 6socket of your own, and :func:`parse` whatever arrives. 7 8Frequencies are in hertz, payloads are ``bytes`` rather than base64, and a reception time is a 9count of microseconds, so nothing has to be formatted by hand. 10 11Example:: 12 13 from pamoja.gateway import Packet, PacketKind, Rxpk, encode 14 from pamoja.lora import link 15 16 heard = Rxpk(868_100_000, b"hello", link=link(7, 125_000), rssi_dbm=-35.0, snr_db=5.1) 17 datagram = encode(Packet(PacketKind.PUSH_DATA, 0x1234, gateway="b827ebfffe010203", 18 packets=[heard])) 19""" 20 21from __future__ import annotations 22 23import enum 24 25from pamoja._native import GatewayNetwork as Network 26from pamoja._native import GatewayNetworkEvent as NetworkEvent 27from pamoja._native import GatewayPacket as Packet 28from pamoja._native import GatewayRxpk as Rxpk 29from pamoja._native import GatewaySlot as Slot 30from pamoja._native import GatewayStat as Stat 31from pamoja._native import GatewayTxpk as Txpk 32from pamoja._native import gateway_acknowledgment as acknowledgment 33from pamoja._native import gateway_encode as encode 34from pamoja._native import gateway_parse as parse 35 36__all__ = [ 37 "Crc", 38 "DEFAULT_PORT", 39 "Network", 40 "NetworkEvent", 41 "Packet", 42 "PacketKind", 43 "Rxpk", 44 "Slot", 45 "Stat", 46 "TxStatus", 47 "Txpk", 48 "acknowledgment", 49 "encode", 50 "parse", 51] 52 53#: The port a packet forwarder sends to by convention, which the protocol itself does not fix. 54DEFAULT_PORT = 1700 55 56 57class PacketKind(str, enum.Enum): 58 """Which kind of datagram.""" 59 60 #: The gateway forwarding what it heard. 61 PUSH_DATA = "PushData" 62 #: The server acknowledging a PUSH_DATA. 63 PUSH_ACK = "PushAck" 64 #: The gateway holding its route open through any address translation in front of it. 65 PULL_DATA = "PullData" 66 #: The server sending a packet to transmit. 67 PULL_RESP = "PullResp" 68 #: The server acknowledging a PULL_DATA. 69 PULL_ACK = "PullAck" 70 #: The gateway reporting what became of a PULL_RESP. 71 TX_ACK = "TxAck" 72 73 74class Crc(str, enum.Enum): 75 """What the CRC of a received packet said.""" 76 77 #: The CRC checked. 78 OK = "Ok" 79 #: The CRC failed. 80 FAILED = "Failed" 81 #: The packet carried no CRC. 82 ABSENT = "Absent" 83 84 85class TxStatus(str, enum.Enum): 86 """What became of a downlink the server asked for, as the protocol names it.""" 87 88 #: It was scheduled. 89 NONE = "NONE" 90 #: It arrived too late to schedule. 91 TOO_LATE = "TOO_LATE" 92 #: Its timestamp is too far ahead. 93 TOO_EARLY = "TOO_EARLY" 94 #: Another packet was already scheduled then. 95 COLLISION_PACKET = "COLLISION_PACKET" 96 #: A beacon was already scheduled then. 97 COLLISION_BEACON = "COLLISION_BEACON" 98 #: The radio chain cannot reach that frequency. 99 TX_FREQ = "TX_FREQ" 100 #: The gateway cannot transmit at that power. 101 TX_POWER = "TX_POWER" 102 #: A GPS timestamp was asked for while the GPS is unlocked. 103 GPS_UNLOCKED = "GPS_UNLOCKED"
75class Crc(str, enum.Enum): 76 """What the CRC of a received packet said.""" 77 78 #: The CRC checked. 79 OK = "Ok" 80 #: The CRC failed. 81 FAILED = "Failed" 82 #: The packet carried no CRC. 83 ABSENT = "Absent"
What the CRC of a received packet said.
58class PacketKind(str, enum.Enum): 59 """Which kind of datagram.""" 60 61 #: The gateway forwarding what it heard. 62 PUSH_DATA = "PushData" 63 #: The server acknowledging a PUSH_DATA. 64 PUSH_ACK = "PushAck" 65 #: The gateway holding its route open through any address translation in front of it. 66 PULL_DATA = "PullData" 67 #: The server sending a packet to transmit. 68 PULL_RESP = "PullResp" 69 #: The server acknowledging a PULL_DATA. 70 PULL_ACK = "PullAck" 71 #: The gateway reporting what became of a PULL_RESP. 72 TX_ACK = "TxAck"
Which kind of datagram.
86class TxStatus(str, enum.Enum): 87 """What became of a downlink the server asked for, as the protocol names it.""" 88 89 #: It was scheduled. 90 NONE = "NONE" 91 #: It arrived too late to schedule. 92 TOO_LATE = "TOO_LATE" 93 #: Its timestamp is too far ahead. 94 TOO_EARLY = "TOO_EARLY" 95 #: Another packet was already scheduled then. 96 COLLISION_PACKET = "COLLISION_PACKET" 97 #: A beacon was already scheduled then. 98 COLLISION_BEACON = "COLLISION_BEACON" 99 #: The radio chain cannot reach that frequency. 100 TX_FREQ = "TX_FREQ" 101 #: The gateway cannot transmit at that power. 102 TX_POWER = "TX_POWER" 103 #: A GPS timestamp was asked for while the GPS is unlocked. 104 GPS_UNLOCKED = "GPS_UNLOCKED"
What became of a downlink the server asked for, as the protocol names it.
Returns the acknowledgment a server owes a datagram, or None for one that needs none.
Writes a datagram to send over a socket.
Reads a datagram that arrived.