OzWrapper.OzSigfox.OzSigfox.OzSigfox¶
- class OzWrapper.OzSigfox.OzSigfox.OzSigfox¶
Sigfox LPWAN communication wrapper backed by the iWire driver.
Encodes sensor values into two fixed-size 12-byte binary packs and transmits them sequentially over the Sigfox network via the
drivers.iWire.iWire.iWiremodule. Although it is conceptually related toSensorBase.SensorBase.GenericSensor, this class does not inherit from it; it operates as a standalone uplink worker.- Payload encoding:
pack_1(frame id0x10) carries environmental parameters packed as:p1(PM1, 2B),p2(PM2.5, 2B),temp(2B),hum(2B),uv(2B) andrain(1B). Two-byte values are scaled by10and packed big-endian unsigned (!H).pack_2(frame id0x20) carriesg1(gas, 2B),g2(gas concentration, 4B float!f),light(4B) andflood(1B).Negative values are clamped to
0before encoding to keep unsigned packing safe.
- Variables:
iwire (
drivers.iWire.iWire.iWire | None) – iWire driver instance, orNonebeforesetup()is called.isRealtime (
int) – Flag controlling which payloads to transmit.1selects only realtime payloads (d.rdatatruthy),0selects only non-realtime payloads.payloaddata (
dict | None) – Latest sensor payload dictionary pulled from the queue, orNoneif nothing has been received.pack_1 (
dict[str,list[int]]) – Primary payload register map, mapping each send-code to[byte_offset, byte_length].pack_2 (
dict[str,list[int]]) – Secondary payload register map.sigfox_pack_1 (
list[bytes]) – Primary 12-byte binary transmit buffer, prefixed with frame id0x10.sigfox_pack_2 (
list[bytes]) – Secondary 12-byte binary transmit buffer, prefixed with frame id0x20.
Example
>>> from OzWrapper.OzSigfox.OzSigfox import OzSigfox >>> sigfox = OzSigfox() >>> sigfox.setup({"gpio": {"port": "/dev/ttyAMA2", ... "baud": 115200}, ... "rcz": "6"})
Initialize the wrapper with default pack maps and frame buffers.
Sets
isRealtimeto0, clearspayloaddata, and preparespack_1/pack_2register maps plus thesigfox_pack_1/sigfox_pack_212-byte buffers with their frame-id prefix bytes (0x10/0x20).- Parameters:
None.
- Returns:
None.
- Raises:
None – Construction performs only in-memory initialization.
Example
>>> from OzWrapper.OzSigfox.OzSigfox import OzSigfox >>> sigfox = OzSigfox() >>> len(sigfox.sigfox_pack_1) 12
Note
super().__init__()is invoked to remain forward-compatible with cooperative multiple inheritance even thoughOzSigfoxcurrently has no explicit base class.- convert(val: float, points: int = 2) list[int]¶
Pack a sensor value into a list of bytes for the Sigfox payload.
The packing format is chosen by
points:1->struct.pack("!B", val)(unsigned 8-bit).2->valis multiplied by10and cast toint, then packed asstruct.pack("!H", val)(unsigned 16-bit BE).4->struct.pack("!f", val)for floats (rounded to two decimal places) orstruct.pack("!I", val)for integers (unsigned 32-bit BE).
- Parameters:
- Returns:
Sequence of integer byte values ready to be written into
sigfox_pack_1orsigfox_pack_2.- Return type:
- Raises:
struct.error – If
valdoes not fit the selected struct format (e.g. negative value with unsigned packing, or integer overflow).TypeError – If
valhas an unsupported type for the chosenpoints(e.g.points=4with a non-numeric value).
Example
>>> sigfox = OzSigfox() >>> sigfox.convert(12.5, 2) [0, 125]
- loop(sigfoxqueue: queue.Queue) None¶
Continuously consume payloads, encode them, and uplink via Sigfox.
Blocks on
sigfoxqueue.get()for each iteration. The payload is accepted only if itsd.rdataflag matchesisRealtimesemantics: realtime mode keeps payloads whererdatais truthy, non-realtime mode keeps payloads whererdatais missing or falsy. Each accepted payload is split acrosspack_1andpack_2register maps; values are clamped to>= 0, encoded viaconvert(), and copied into the corresponding offsets ofsigfox_pack_1/sigfox_pack_2. Both frames are then transmitted through thedrivers.iWire.iWire.iWiredriver with a 3-second gap between them to satisfy Sigfox duty-cycle constraints.- Parameters:
sigfoxqueue (
queue.Queue) – Inter-thread queue that yields sensor data payload dictionaries shaped like{"d": {"rdata": <int>, "<sensor-key>": <value>, ...}}.- Returns:
This method runs an infinite loop and never returns under normal operation.
- Return type:
None
- Raises:
Exception – All exceptions raised inside the loop body are caught, logged via the contextual Oizom logger, and swallowed so the worker keeps running.
Example
>>> from queue import Queue >>> q = Queue() >>> sigfox.loop(q)
Note
The
finallyclause sleeps for one second every iteration, which throttles the loop even when payloads are missing or malformed. Adjust this interval with care: Sigfox imposes strict per-day uplink quotas.
- run(sigfoxConfig: dict, sigfoxqueue: queue.Queue) None¶
Set up the Sigfox modem and start the transmit loop when enabled.
Acts as the top-level entry point used by the application bootstrap. When
sigfoxConfig['en']is1it delegates tosetup()to bring thedrivers.iWire.iWire.iWiremodem online and then hands control off toloop(). If theenflag is missing or zero the call returns immediately, leaving the Sigfox subsystem dormant.- Parameters:
sigfoxConfig (
dict) – Configuration dictionary including theenenable flag (1to start, anything else to skip) plus all keys consumed bysetup().sigfoxqueue (
queue.Queue) – Queue forwarded toloop()to supply sensor payloads.
- Returns:
None.
- Raises:
Exception – Propagates errors raised by
setup()during modem initialization;loop()internally swallows its own exceptions.
Example
>>> from queue import Queue >>> sigfox = OzSigfox() >>> sigfox.run({"en": 1, "rcz": "6"}, Queue())
Note
This method is typically invoked inside a dedicated worker thread because
loop()never returns under normal operation.
- setup(sigfoxConfig: dict) None¶
Configure and initialize the underlying iWire Sigfox modem.
Resolves the serial port, baud rate, and Sigfox RCZ (radio configuration zone) from
sigfoxConfig, falling back to defaults (/dev/ttyAMA2,115200, RCZ6). Also reads therdataflag to driveisRealtime, then constructs andrivers.iWire.iWire.iWireinstance and calls itsinitializemethod.- Parameters:
sigfoxConfig (
dict) –Configuration mapping. Supported keys:
gpio.port(str): Serial device path.gpio.baud(int): Serial baud rate.rcz(str): Sigfox radio configuration zone.rdata(int): Realtime-data flag forisRealtime.
- Returns:
None.
- Raises:
Exception – Propagates any error raised by
drivers.iWire.iWire.iWireconstruction orinitialize(e.g. serial port unavailable, modem not responding).
Example
>>> sigfox.setup({"gpio": {"port": "/dev/ttyAMA2", ... "baud": 115200}, ... "rcz": "6", ... "rdata": 0})
Note
The default RCZ of
"6"corresponds to Sigfox’s India zone; override it for deployments in other regions.
- isRealtime = 0¶
- iwire = None¶
- pack_1¶
- pack_2¶
- payloaddata = None¶
- sigfox_pack_1 = [b'\x10', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00',...¶
- sigfox_pack_2 = [b' ', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00']¶