diff --git a/README.md b/README.md index 1d8d803..158f9df 100644 --- a/README.md +++ b/README.md @@ -65,4 +65,12 @@ Like above, but also writes all captured packets individually to a specified dir ```sh loramon /dev/ttyUSB0 --freq 868000000 --bw 125000 --sf 7 --cr 5 -C -W capturedir +``` + +### Sniff implicit header mode packets + +If you want to sniff LoRa packets with implicit header mode, use the --implicit option along with the length in bytes of the expected packet. This mode needs an RNode with a firmware version of at least 1.17. + +```sh +loramon /dev/ttyUSB0 --freq 868000000 --bw 125000 --sf 7 --cr 5 -C -W capturedir --implicit 12 ``` \ No newline at end of file diff --git a/loramon/loramon.py b/loramon/loramon.py index 5133369..eba6b41 100755 --- a/loramon/loramon.py +++ b/loramon/loramon.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 from time import sleep import argparse import threading @@ -48,6 +49,7 @@ class KISS(): CMD_RADIO_STATE = 0x06 CMD_RADIO_LOCK = 0x07 CMD_DETECT = 0x08 + CMD_IMPLICIT = 0x09 CMD_PROMISC = 0x0E CMD_READY = 0x0F CMD_STAT_RX = 0x21 @@ -114,6 +116,8 @@ class RNode(): self.r_lock = None self.r_stat_rssi = 0 self.r_stat_snr = 0 + self.r_implicit_length = 0 + self.rssi_offset = 157 self.sf = None @@ -121,6 +125,7 @@ class RNode(): self.txpower = None self.frequency = None self.bandwidth = None + self.implicit_length = 0 self.detected = None @@ -253,6 +258,10 @@ class RNode(): self.r_cr = byte RNS.log("Radio reporting coding rate is "+str(self.r_cr)) self.updateBitrate() + elif (command == KISS.CMD_IMPLICIT): + self.r_implicit_length = byte + if self.r_implicit_length != 0: + RNS.log("Radio in implicit header mode, listening for packets with a length of "+str(self.r_implicit_length)+" bytes") elif (command == KISS.CMD_RADIO_STATE): self.r_state = byte elif (command == KISS.CMD_RADIO_LOCK): @@ -317,6 +326,7 @@ class RNode(): self.setTXPower() self.setSpreadingFactor() self.setCodingRate() + self.setImplicitLength() self.setRadioState(KISS.RADIO_STATE_ON) def setFrequency(self): @@ -367,6 +377,15 @@ class RNode(): if written != len(kiss_command): raise IOError("An IO error occurred while configuring coding rate for "+self(str)) + def setImplicitLength(self): + if self.implicit_length != 0: + length = KISS.escape(bytes([self.implicit_length])) + + kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_IMPLICIT])+length+bytes([KISS.FEND]) + written = self.serial.write(kiss_command) + if written != len(kiss_command): + raise IOError("An IO error occurred while configuring implicit header mode for "+self(str)) + def setRadioState(self, state): kiss_command = bytes([KISS.FEND])+bytes([KISS.CMD_RADIO_STATE])+bytes([state])+bytes([KISS.FEND]) written = self.serial.write(kiss_command) @@ -430,6 +449,7 @@ def main(): parser.add_argument("--txp", action="store", metavar="dBm", type=int, default=None, help="TX power in dBm") parser.add_argument("--sf", action="store", metavar="factor", type=int, default=None, help="Spreading factor") parser.add_argument("--cr", action="store", metavar="rate", type=int, default=None, help="Coding rate") + parser.add_argument("--implicit", action="store", metavar="length", type=int, default=None, help="Packet length in implicit header mode") parser.add_argument("port", nargs="?", default=None, help="Serial port where RNode is attached", type=str) args = parser.parse_args() @@ -529,6 +549,11 @@ def main(): print("Coding rate:\t\t", end=' ') rnode.cr = int(input()) + if args.implicit: + rnode.implicit_length = args.implicit + else: + rnode.implicit_length = 0 + rnode.initRadio() rnode.setPromiscuousMode(True) sleep(0.5) diff --git a/setup.py b/setup.py index 455b734..393e17f 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r") as fh: setuptools.setup( name="loramon", - version="0.9.4", + version="0.9.5", author="Mark Qvist", author_email="mark@unsigned.io", description="LoRa packet sniffer for RNode hardware",