From 1676bb8596d79bde7e159c002150300d486b25e4 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Mon, 15 Aug 2022 18:04:06 -0700 Subject: [PATCH 001/130] Update JoinAcceptPayload.py --- LoRaWAN/JoinAcceptPayload.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LoRaWAN/JoinAcceptPayload.py b/LoRaWAN/JoinAcceptPayload.py index 36afa39..7d4be95 100644 --- a/LoRaWAN/JoinAcceptPayload.py +++ b/LoRaWAN/JoinAcceptPayload.py @@ -56,7 +56,7 @@ def decrypt_payload(self, key, direction, mic): a += self.encrypted_payload a += mic - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) self.payload = cipher.encrypt(bytes(a))[:-4] self.appnonce = self.payload[:3] @@ -75,7 +75,7 @@ def encrypt_payload(self, key, direction, mhdr): a += self.to_clear_raw() a += self.compute_mic(key, direction, mhdr) - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) return list(map(int, cipher.decrypt(bytes(a)))) def derive_nwskey(self, key, devnonce): @@ -85,7 +85,7 @@ def derive_nwskey(self, key, devnonce): a += devnonce a += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) return list(map(int, cipher.encrypt(bytes(a)))) def derive_appskey(self, key, devnonce): @@ -95,5 +95,5 @@ def derive_appskey(self, key, devnonce): a += devnonce a += [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) return list(map(int, cipher.encrypt(bytes(a)))) From 3f99224ac60a12de4a39d6a77ab3ee8781bbe016 Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 10:39:33 -0700 Subject: [PATCH 002/130] iterate on helium - add python requirements for more sane installability - replace frame.py with writing to frame.txt - use dotenv and environment vars for keys.py - read in "hex strings" for keys.py, and read in `[1,2,3]` style arrays for the OTAA keys - some more crypto/AES fixups for pycryptodome - add [EOL at EOF](https://thoughtbot.com/blog/no-newline-at-end-of-file) These changes are only tested with rssi_helium.py and otaa_helium.py. --- .gitignore | 3 ++- LoRaWAN/DataPayload.py | 4 ++-- README.md | 34 ++++++++++++++++++++++++++++++---- frame.py | 1 - keys.py | 17 +++++++++++++++++ otaa_helium.py | 1 + requirements.txt | 4 ++++ rssi_helium.py | 23 +++++++++++++++++------ 8 files changed, 73 insertions(+), 14 deletions(-) delete mode 100644 frame.py create mode 100644 keys.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index f5000dc..ed11a67 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.pyc -keys.py +.env +frame.txt diff --git a/LoRaWAN/DataPayload.py b/LoRaWAN/DataPayload.py index 6a35513..5ff8d41 100644 --- a/LoRaWAN/DataPayload.py +++ b/LoRaWAN/DataPayload.py @@ -56,7 +56,7 @@ def decrypt_payload(self, key, direction, mic): a += [0x00] a += [i+1] - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) s = cipher.encrypt(bytes(a)) padded_payload = [] @@ -84,7 +84,7 @@ def encrypt_payload(self, key, direction, data): a += [0x00] a += [i+1] - cipher = AES.new(bytes(key)) + cipher = AES.new(bytes(key), AES.MODE_ECB) s = cipher.encrypt(bytes(a)) padded_payload = [] diff --git a/README.md b/README.md index 03075e1..07a2386 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,39 @@ This fork adds support for the Adafruit LoRA Radio Bonnet with OLED - RFM95W @ 9 It also allows you to connect as a client to the Helium Network. -You must create a device on the Helium Console at https://console.helium.com/ - -You need to rename "keys_example.py" to "keys.py" and enter you device information from the Helium Console. ## Installation -To register a device and get a device ID you need to run otaa_helium.py and stores the results in keys.py. + +After forking the repo, install the python libs: + + pip3 install -r requirements.txt + +## Credentials + +The keys can be added to a `./.env` file: + +``` +deveui = 1234ASD432 +appeui = 234ASD4321 +appkey = 34ASD43210 + +devaddr = [00,11,22] +nwskey = [11,22,33] +appskey = [22,33,44] +``` + +They can also be passed as environment variables: + +``` +deveui=1234ASD432 python3 rssi_helium.py +``` + +## Registration + +You must create a device on the Helium Console at https://console.helium.com/ + +After copying the device credentials (the first three in the `.env` file, above), run otaa_helium.py, which will get the final three credentials for the `.env` file. Then you can run tx_helium.py to send messages by specifying the msg and the frame like this: diff --git a/frame.py b/frame.py deleted file mode 100644 index 61c3e5f..0000000 --- a/frame.py +++ /dev/null @@ -1 +0,0 @@ -frame = 1 \ No newline at end of file diff --git a/keys.py b/keys.py new file mode 100644 index 0000000..3752139 --- /dev/null +++ b/keys.py @@ -0,0 +1,17 @@ +import dotenv +import json +import os + +# puts the keys from .env file into the environment, +# so this can be configured from a file or env vars. +dotenv.load_dotenv() + +# Get these values from console.helium.com under Device Details. +deveui = bytes.fromhex(os.environ.get('deveui')) +appeui = bytes.fromhex(os.environ.get('appeui')) +appkey = bytes.fromhex(os.environ.get('appkey')) + +# Fill in these values when you activate the device with otaa_helium.py. +devaddr = json.loads(os.environ.get('devaddr', '[]')) +nwskey = json.loads(os.environ.get('nwskey', '[]')) +appskey = json.loads(os.environ.get('appskey', '[]')) diff --git a/otaa_helium.py b/otaa_helium.py index a02701d..84e169f 100644 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + import sys from time import sleep from SX127x.LoRa import * diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1e482f9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pycryptodome +adafruit_blinka +adafruit-circuitpython-ssd1306 +python-dotenv diff --git a/rssi_helium.py b/rssi_helium.py index dc8554b..18847b3 100644 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -14,12 +14,14 @@ from digitalio import DigitalInOut, Direction, Pull import board import busio +import os +import re import RPi.GPIO as GPIO import helium import keys -import frame +#import frame # Button A btnA = DigitalInOut(board.D5) @@ -106,7 +108,8 @@ def on_rx_done(self): def increment(self): self.tx_counter += 1 - data_file = open("frame.py", "w") + + data_file = open("frame.txt", "w") data_file.write( 'frame = {}\n'.format(self.tx_counter)) data_file.close() @@ -180,8 +183,16 @@ def on_tx_done(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) -def init(frame): +def init(): lora = LoRaWANotaa(False) + + frame = 0 + if os.path.exists('frame.txt'): + with open('frame.txt') as df: + for line in df: + if m := re.match('^frame\s*=\s*(\d+)', line): + frame = int(m.group(1)) + lora.set_frame(frame) try: @@ -197,7 +208,7 @@ def init(frame): def main(): - global frame + #global frame global msg # parser = argparse.ArgumentParser(add_help=True, description="Trasnmit a LoRa msg") # parser.add_argument("--frame", help="Message frame") @@ -206,7 +217,7 @@ def main(): # frame = int(args.frame) # msg = args.msg msg = 'Test' - init(frame.frame) + init() if __name__ == "__main__": - main() \ No newline at end of file + main() From bc6e05adcfe8e2f42fad0e55a5cd0c4b3d04498d Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 11:01:38 -0700 Subject: [PATCH 003/130] remove globals, wire msg properly --- rssi_helium.py | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 18847b3..b4c0fcd 100644 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + import sys import argparse from time import sleep @@ -21,7 +22,6 @@ import helium import keys -#import frame # Button A btnA = DigitalInOut(board.D5) @@ -55,9 +55,6 @@ width = display.width height = display.height -global msg -msg = 'Test' - class LoRaWANotaa(LoRa): def __init__(self, verbose = False): super(LoRaWANotaa, self).__init__(verbose) @@ -110,12 +107,10 @@ def increment(self): self.tx_counter += 1 data_file = open("frame.txt", "w") - data_file.write( - 'frame = {}\n'.format(self.tx_counter)) + data_file.write(f'frame = {{self.tx_counter}}\n') data_file.close() - def tx(self, conf=True): - global msg + def tx(self, msg, conf=True): if conf: data = MHDR.CONF_DATA_UP print('Sending confirmed data up.') @@ -132,16 +127,16 @@ def tx(self, conf=True): else: print('Sending without Ack') lorawan.create(data, {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))}) - print("tx: {}".format(lorawan.to_raw())) + print(f"tx: {lorawan.to_raw()}") self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) display.fill(0) display.text('Transmit!', 0, 0, 1) display.show() - def start(self): + def start(self, msg): self.setup_tx() - self.tx() + self.tx(msg) while True: sleep(.1) if not btnB.value: @@ -183,7 +178,7 @@ def on_tx_done(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) -def init(): +def init(msg): lora = LoRaWANotaa(False) frame = 0 @@ -197,7 +192,7 @@ def init(): try: print("Sending LoRaWAN tx\n") - lora.start() + lora.start(msg) except KeyboardInterrupt: sys.stdout.flush() print("\nKeyboardInterrupt") @@ -208,16 +203,12 @@ def init(): def main(): - #global frame - global msg # parser = argparse.ArgumentParser(add_help=True, description="Trasnmit a LoRa msg") # parser.add_argument("--frame", help="Message frame") # parser.add_argument("--msg", help="tokens file") # args = parser.parse_args() # frame = int(args.frame) - # msg = args.msg - msg = 'Test' - init() + init('test') if __name__ == "__main__": main() From 3ba13800bcd513b8990691a0976418a0e3654183 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 11:09:35 -0700 Subject: [PATCH 004/130] Update rssi_helium.py --- rssi_helium.py | 77 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index dc8554b..eb769f9 100644 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 +import json import sys import argparse +import datetime from time import sleep from SX127x.LoRa import * from SX127x.LoRaArgumentParser import LoRaArgumentParser @@ -14,6 +16,7 @@ from digitalio import DigitalInOut, Direction, Pull import board import busio +import shortuuid import RPi.GPIO as GPIO @@ -48,20 +51,27 @@ display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) # Clear the display. display.fill(0) -display.text('LoRA!', 0, 0, 1) +display.text("Test is ready to start!", 0, 0, 1) +display.text('Push Left Button', 0, 10, 1) +display.text('To start test.', 0, 20, 1) display.show() width = display.width height = display.height -global msg -msg = 'Test' +#global msg +global test_status +test_status = {"running_ping": False, "ping_count": 0, "last_ping_time": None} +#msg = 'None' class LoRaWANotaa(LoRa): - def __init__(self, verbose = False): + def __init__(self, verbose = False, ack=True): super(LoRaWANotaa, self).__init__(verbose) - self.ack = False + self.iter = 0 + self.uuid = shortuuid.uuid() + self.ack = ack def on_rx_done(self): + global test_status self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) print("Raw payload: {}".format(payload)) @@ -69,9 +79,10 @@ def on_rx_done(self): lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) + test_status["last_ping_time"] = decoded.split(" ")[1] + test_status["ping_count"] += 1 print("Decoded: {}".format(decoded)) print("\n") - if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: print("Unconfirmed data down.") downlink = decoded @@ -99,9 +110,9 @@ def on_rx_done(self): s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() s += " rssi_value %d\n" % self.get_rssi_value() s += " msg: %s" % downlink - display.fill(0) - display.text(s, 0, 0, 1) - display.show() + #display.fill(0) + #display.text(s, 0, 0, 1) + #display.show() print(s) def increment(self): @@ -112,7 +123,8 @@ def increment(self): data_file.close() def tx(self, conf=True): - global msg + #global msg + msg = json.dumps({"i": self.iter, "s": self.uuid}) if conf: data = MHDR.CONF_DATA_UP print('Sending confirmed data up.') @@ -132,21 +144,36 @@ def tx(self, conf=True): print("tx: {}".format(lorawan.to_raw())) self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) - display.fill(0) - display.text('Transmit!', 0, 0, 1) - display.show() + # display.fill(0) + # display.text('Transmit!', 0, 0, 1) + # display.show() def start(self): - self.setup_tx() - self.tx() + global test_status + last_test = None while True: sleep(.1) - if not btnB.value: + display.fill(0) + display.text("Test is "+str(test_status["running_ping"]), 0, 0, 1) + display.text('Time: '+str(test_status["last_ping_time"]), 0, 10, 1) + display.text('Total Pings: '+str(test_status["ping_count"]), 0, 20, 1) + display.show() + if test_status["running_ping"] and not last_test or (last_test and (datetime.datetime.now() - last_test).seconds > 5): self.setup_tx() - self.tx() + self.tx(False) + self.iter = self.iter+1 + last_test = datetime.datetime.now() + if not btnA.value: + test_status["running_ping"] = True + if not btnB.value: + test_status["running_ping"] = False if not btnC.value: - self.setup_tx() - self.tx(False) + display.fill(0) + display.text("Test is shut down!", 0, 0, 1) + display.text('Must restart PI to', 0, 10, 1) + display.text('restart test.', 0, 20, 1) + display.show() + raise KeyboardInterrupt def set_frame(self,frame): self.tx_counter = frame @@ -176,16 +203,15 @@ def on_tx_done(self): self.set_sync_word(0x34) self.set_rx_crc(False) self.set_invert_iq(1) - self.reset_ptr_rx() self.set_mode(MODE.RXCONT) def init(frame): - lora = LoRaWANotaa(False) + lora = LoRaWANotaa(False, True) lora.set_frame(frame) try: - print("Sending LoRaWAN tx\n") + print("Starting\n") lora.start() except KeyboardInterrupt: sys.stdout.flush() @@ -198,15 +224,14 @@ def init(frame): def main(): global frame - global msg + #global msg + global test_status # parser = argparse.ArgumentParser(add_help=True, description="Trasnmit a LoRa msg") # parser.add_argument("--frame", help="Message frame") # parser.add_argument("--msg", help="tokens file") # args = parser.parse_args() # frame = int(args.frame) - # msg = args.msg - msg = 'Test' init(frame.frame) if __name__ == "__main__": - main() \ No newline at end of file + main() From 960febfedbb88bcb39a45c7287c88068067eb5f1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:31:47 -0700 Subject: [PATCH 005/130] updates --- rssi_helium.py | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) mode change 100644 => 100755 rssi_helium.py diff --git a/rssi_helium.py b/rssi_helium.py old mode 100644 new mode 100755 index f659a6e..de70ef3 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -75,7 +75,6 @@ def on_rx_done(self): self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) print("Raw payload: {}".format(payload)) - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) @@ -101,18 +100,12 @@ def on_rx_done(self): else: print("Other packet.") downlink = '' - - self.set_mode(MODE.STDBY) - s = '' s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() s += " rssi_value %d\n" % self.get_rssi_value() s += " msg: %s" % downlink - #display.fill(0) - #display.text(s, 0, 0, 1) - #display.show() print(s) def increment(self): @@ -132,24 +125,22 @@ def tx(self, msg, conf=True): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, package))} if self.ack: print('Sending with Ack') - lorawan.create(data, {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg)), 'ack':True}) + lorawan.create(data, dict(**base, **{'ack':True})) self.ack = False else: print('Sending without Ack') - lorawan.create(data, {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))}) + lorawan.create(data, base) print(f"tx: {lorawan.to_raw()}") self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) - # display.fill(0) - # display.text('Transmit!', 0, 0, 1) - # display.show() def start(self, msg): - msg = json.dumps({"i": self.iter, "s": self.uuid}) + package = json.dumps({"i": self.iter, "s": self.uuid, "m": msg}) self.setup_tx() - self.tx(msg) + self.tx(package) while True: sleep(.1) display.fill(0) @@ -159,7 +150,7 @@ def start(self, msg): display.show() if test_status["running_ping"] and not last_test or (last_test and (datetime.datetime.now() - last_test).seconds > 5): self.setup_tx() - self.tx(False) + self.tx(msg, False) self.iter = self.iter+1 last_test = datetime.datetime.now() if not btnA.value: @@ -205,7 +196,7 @@ def on_tx_done(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) -def init(msg): +def init(msg=None): lora = LoRaWANotaa(False) frame = 0 @@ -230,13 +221,7 @@ def init(msg): def main(): - # parser = argparse.ArgumentParser(add_help=True, description="Trasnmit a LoRa msg") - # parser.add_argument("--frame", help="Message frame") - # parser.add_argument("--msg", help="tokens file") - # args = parser.parse_args() - # frame = int(args.frame) - init('test') - init(frame.frame) + init() if __name__ == "__main__": main() From 0f5ed59409bd6e2e8cceb62ff6f6400b339d59ea Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:48:19 -0700 Subject: [PATCH 006/130] updates --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index de70ef3..6d73c96 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -125,7 +125,7 @@ def tx(self, msg, conf=True): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, package))} + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: print('Sending with Ack') lorawan.create(data, dict(**base, **{'ack':True})) From 2588c91af58ded9c97cf2280a5e898f795a6bd7d Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:49:31 -0700 Subject: [PATCH 007/130] updates --- rssi_helium.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 6d73c96..4538aca 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -59,16 +59,14 @@ width = display.width height = display.height -#global msg -global test_status -test_status = {"running_ping": False, "ping_count": 0, "last_ping_time": None} -#msg = 'None' class LoRaWANotaa(LoRa): def __init__(self, verbose = False, ack=True): super(LoRaWANotaa, self).__init__(verbose) self.iter = 0 self.uuid = shortuuid.uuid() self.ack = ack + self.test_status = {"running_ping": False, "ping_count": 0, "last_ping_time": None} + self.last_test = 0 def on_rx_done(self): global test_status @@ -148,7 +146,7 @@ def start(self, msg): display.text('Time: '+str(test_status["last_ping_time"]), 0, 10, 1) display.text('Total Pings: '+str(test_status["ping_count"]), 0, 20, 1) display.show() - if test_status["running_ping"] and not last_test or (last_test and (datetime.datetime.now() - last_test).seconds > 5): + if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): self.setup_tx() self.tx(msg, False) self.iter = self.iter+1 From 9bab489882d132aa2844853a793a1dddef7628c4 Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 19:49:02 -0700 Subject: [PATCH 008/130] add shortuuid to reqs --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 1e482f9..49e59a1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ pycryptodome adafruit_blinka adafruit-circuitpython-ssd1306 python-dotenv +shortuuid From 581ad72c4ce1dd7634d0d009528cb9a71f2af3ce Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:51:03 -0700 Subject: [PATCH 009/130] more rssi hacking --- rssi_helium.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 4538aca..ebcd359 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -69,15 +69,14 @@ def __init__(self, verbose = False, ack=True): self.last_test = 0 def on_rx_done(self): - global test_status self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) - test_status["last_ping_time"] = decoded.split(" ")[1] - test_status["ping_count"] += 1 + self.test_status["last_ping_time"] = decoded.split(" ")[1] + self.test_status["ping_count"] += 1 print("Decoded: {}".format(decoded)) print("\n") if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: @@ -142,9 +141,9 @@ def start(self, msg): while True: sleep(.1) display.fill(0) - display.text("Test is "+str(test_status["running_ping"]), 0, 0, 1) - display.text('Time: '+str(test_status["last_ping_time"]), 0, 10, 1) - display.text('Total Pings: '+str(test_status["ping_count"]), 0, 20, 1) + display.text("Test is "+str(self.test_status["running_ping"]), 0, 0, 1) + display.text('Time: '+str(self.test_status["last_ping_time"]), 0, 10, 1) + display.text('Total Pings: '+str(self.test_status["ping_count"]), 0, 20, 1) display.show() if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): self.setup_tx() @@ -152,9 +151,9 @@ def start(self, msg): self.iter = self.iter+1 last_test = datetime.datetime.now() if not btnA.value: - test_status["running_ping"] = True + self.test_status["running_ping"] = True if not btnB.value: - test_status["running_ping"] = False + self.test_status["running_ping"] = False if not btnC.value: display.fill(0) display.text("Test is shut down!", 0, 0, 1) From 8e14e5628dd41d72d94e894e406ec2da5e1426c4 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:53:48 -0700 Subject: [PATCH 010/130] update to store generic last message --- rssi_helium.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index ebcd359..ee412b5 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -65,7 +65,7 @@ def __init__(self, verbose = False, ack=True): self.iter = 0 self.uuid = shortuuid.uuid() self.ack = ack - self.test_status = {"running_ping": False, "ping_count": 0, "last_ping_time": None} + self.test_status = {"running_ping": False, "ping_count": 0, "last_message": None} self.last_test = 0 def on_rx_done(self): @@ -75,7 +75,7 @@ def on_rx_done(self): lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) - self.test_status["last_ping_time"] = decoded.split(" ")[1] + self.test_status["last_message"] = decoded self.test_status["ping_count"] += 1 print("Decoded: {}".format(decoded)) print("\n") From 97273b3b406e55d38db12e4ccc3a4a28ff57a140 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:54:52 -0700 Subject: [PATCH 011/130] update to store generic last message --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index ee412b5..367574d 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -142,7 +142,7 @@ def start(self, msg): sleep(.1) display.fill(0) display.text("Test is "+str(self.test_status["running_ping"]), 0, 0, 1) - display.text('Time: '+str(self.test_status["last_ping_time"]), 0, 10, 1) + display.text('Time: '+str(self.test_status["last_message"]), 0, 10, 1) display.text('Total Pings: '+str(self.test_status["ping_count"]), 0, 20, 1) display.show() if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): From 0782eee99117507843c4e3fe0911838154d9bed9 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:57:05 -0700 Subject: [PATCH 012/130] more hacking on iteration --- rssi_helium.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 367574d..e8d4ec4 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -122,6 +122,7 @@ def tx(self, msg, conf=True): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + list(map(ord, msg)) base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: print('Sending with Ack') @@ -137,7 +138,6 @@ def tx(self, msg, conf=True): def start(self, msg): package = json.dumps({"i": self.iter, "s": self.uuid, "m": msg}) self.setup_tx() - self.tx(package) while True: sleep(.1) display.fill(0) @@ -147,7 +147,7 @@ def start(self, msg): display.show() if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): self.setup_tx() - self.tx(msg, False) + self.tx(package, False) self.iter = self.iter+1 last_test = datetime.datetime.now() if not btnA.value: From a5e4e1ae4acaf0027ee9b2d1fe5e7e9d6376a42d Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:58:05 -0700 Subject: [PATCH 013/130] more hacking on iteration --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index e8d4ec4..fbacd80 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -147,7 +147,7 @@ def start(self, msg): display.show() if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): self.setup_tx() - self.tx(package, False) + self.tx(package, True) self.iter = self.iter+1 last_test = datetime.datetime.now() if not btnA.value: From ec33b59922ef03b2d3e3381aa98ff163ac786f41 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 19:59:59 -0700 Subject: [PATCH 014/130] more hacking on iteration --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index fbacd80..e227625 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -194,7 +194,7 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def init(msg=None): - lora = LoRaWANotaa(False) + lora = LoRaWANotaa(True) frame = 0 if os.path.exists('frame.txt'): From daaec65dde67f4f10c44f331115069334d8f3ee9 Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 19:56:35 -0700 Subject: [PATCH 015/130] watch for missing keys --- keys.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/keys.py b/keys.py index 3752139..fda4056 100644 --- a/keys.py +++ b/keys.py @@ -7,9 +7,12 @@ dotenv.load_dotenv() # Get these values from console.helium.com under Device Details. -deveui = bytes.fromhex(os.environ.get('deveui')) -appeui = bytes.fromhex(os.environ.get('appeui')) -appkey = bytes.fromhex(os.environ.get('appkey')) +deveui = bytes.fromhex(os.environ.get('deveui', '')) +appeui = bytes.fromhex(os.environ.get('appeui', '')) +appkey = bytes.fromhex(os.environ.get('appkey', '')) + +if not (deveui and appeui and appkey): + raise RuntimeError("sorry, need device keys before running.") # Fill in these values when you activate the device with otaa_helium.py. devaddr = json.loads(os.environ.get('devaddr', '[]')) From 9e5b32ccb90cf5b821572b508a03127200667b60 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:02:20 -0700 Subject: [PATCH 016/130] more hacking on iteration --- rssi_helium.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index e227625..b34aaae 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -122,7 +122,6 @@ def tx(self, msg, conf=True): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - list(map(ord, msg)) base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: print('Sending with Ack') @@ -149,7 +148,7 @@ def start(self, msg): self.setup_tx() self.tx(package, True) self.iter = self.iter+1 - last_test = datetime.datetime.now() + self.last_test = datetime.datetime.now() if not btnA.value: self.test_status["running_ping"] = True if not btnB.value: From a299f40e4e63db963b614e51c3b9edf533e85455 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:04:42 -0700 Subject: [PATCH 017/130] more hacking on iteration --- rssi_helium.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index b34aaae..1940b27 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -123,13 +123,14 @@ def tx(self, msg, conf=True): lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - if self.ack: - print('Sending with Ack') - lorawan.create(data, dict(**base, **{'ack':True})) - self.ack = False - else: - print('Sending without Ack') - lorawan.create(data, base) + lorawan.create(data, dict(**base, **{'ack':True})) + # if self.ack: + # print('Sending with Ack') + # + # self.ack = False + # else: + # print('Sending without Ack') + # lorawan.create(data, base) print(f"tx: {lorawan.to_raw()}") self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) @@ -193,7 +194,7 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def init(msg=None): - lora = LoRaWANotaa(True) + lora = LoRaWANotaa(False) frame = 0 if os.path.exists('frame.txt'): From 1d1d527aa5d3221bc2bae1861256f0c21a62909e Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 20:05:53 -0700 Subject: [PATCH 018/130] fix output fail, ensure it's a digit while we're here --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index 1940b27..700c5b1 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -109,7 +109,7 @@ def increment(self): self.tx_counter += 1 data_file = open("frame.txt", "w") - data_file.write(f'frame = {{self.tx_counter}}\n') + data_file.write(f'frame = {self.tx_counter:d}\n') data_file.close() def tx(self, msg, conf=True): From e8a33ee442c2ba4785b079a1c2a6b74a11200be0 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:18:29 -0700 Subject: [PATCH 019/130] no idea --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index 700c5b1..7077bb7 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -122,7 +122,7 @@ def tx(self, msg, conf=True): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, "blah"))} lorawan.create(data, dict(**base, **{'ack':True})) # if self.ack: # print('Sending with Ack') From b6c5e70b4f13a9677d52fe1a17a7cff2d79dbe66 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:20:02 -0700 Subject: [PATCH 020/130] no idea --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index 7077bb7..738d933 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -112,7 +112,7 @@ def increment(self): data_file.write(f'frame = {self.tx_counter:d}\n') data_file.close() - def tx(self, msg, conf=True): + def tx(self, msg, conf=False): if conf: data = MHDR.CONF_DATA_UP print('Sending confirmed data up.') From f95c3e15bc919ba64c842797735d9ac73ce36eaa Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:20:40 -0700 Subject: [PATCH 021/130] no idea --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index 738d933..ba91780 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -147,7 +147,7 @@ def start(self, msg): display.show() if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): self.setup_tx() - self.tx(package, True) + self.tx(package) self.iter = self.iter+1 self.last_test = datetime.datetime.now() if not btnA.value: From 8709cce4b5c5b0acdf85a62e52ab91af5b190bfe Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:21:38 -0700 Subject: [PATCH 022/130] no idea --- rssi_helium.py | 1 + 1 file changed, 1 insertion(+) diff --git a/rssi_helium.py b/rssi_helium.py index ba91780..27b0df8 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -137,6 +137,7 @@ def tx(self, msg, conf=False): def start(self, msg): package = json.dumps({"i": self.iter, "s": self.uuid, "m": msg}) + import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() while True: sleep(.1) From 49ac7444510250e15b6b3e0095bbf02909e55156 Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 20:22:10 -0700 Subject: [PATCH 023/130] ping on startup, move 'send' to actual location, simpler conditional, make last_test always a datestamp --- rssi_helium.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 27b0df8..1f876ef 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + import json import sys import argparse @@ -60,13 +61,13 @@ height = display.height class LoRaWANotaa(LoRa): - def __init__(self, verbose = False, ack=True): + def __init__(self, verbose = False, ack=True, start_ping=False): super(LoRaWANotaa, self).__init__(verbose) self.iter = 0 self.uuid = shortuuid.uuid() self.ack = ack - self.test_status = {"running_ping": False, "ping_count": 0, "last_message": None} - self.last_test = 0 + self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} + self.last_test = datetime.datetime.fromtimestamp(0) def on_rx_done(self): self.clear_irq_flags(RxDone=1) @@ -146,8 +147,10 @@ def start(self, msg): display.text('Time: '+str(self.test_status["last_message"]), 0, 10, 1) display.text('Total Pings: '+str(self.test_status["ping_count"]), 0, 20, 1) display.show() - if self.test_status["running_ping"] and not self.last_test or (self.last_test and (datetime.datetime.now() - self.last_test).seconds > 5): + + if self.test_status["running_ping"] and (datetime.datetime.now() - self.last_test).seconds > 5: self.setup_tx() + print("Sending LoRaWAN tx\n") self.tx(package) self.iter = self.iter+1 self.last_test = datetime.datetime.now() @@ -194,8 +197,8 @@ def on_tx_done(self): self.reset_ptr_rx() self.set_mode(MODE.RXCONT) -def init(msg=None): - lora = LoRaWANotaa(False) +def init(msg=None, start_ping=False): + lora = LoRaWANotaa(False, start_ping=start_ping) frame = 0 if os.path.exists('frame.txt'): @@ -207,7 +210,6 @@ def init(msg=None): lora.set_frame(frame) try: - print("Sending LoRaWAN tx\n") lora.start(msg) except KeyboardInterrupt: sys.stdout.flush() @@ -219,7 +221,10 @@ def init(msg=None): def main(): - init() + start_ping = False + if len(sys.argv) > 1 and sys.argv[1] == 'start': + start_ping = True + init(start_ping=start_ping) if __name__ == "__main__": main() From d57f7dde744d3f41f232de47ee2d2368678e045e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:50:29 -0700 Subject: [PATCH 024/130] updates --- rssi_helium.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 1f876ef..fb3a989 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -123,15 +123,14 @@ def tx(self, msg, conf=False): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, "blah"))} - lorawan.create(data, dict(**base, **{'ack':True})) - # if self.ack: - # print('Sending with Ack') - # - # self.ack = False - # else: - # print('Sending without Ack') - # lorawan.create(data, base) + if self.ack: + print('Sending with Ack') + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + lorawan.create(data, dict(**base, **{'ack':True})) + self.ack = False + else: + print('Sending without Ack') + lorawan.create(data, base) print(f"tx: {lorawan.to_raw()}") self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) From 9dcad9c439ac1ab360dd6356b009e81dce165265 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sat, 20 Aug 2022 20:51:51 -0700 Subject: [PATCH 025/130] updates --- rssi_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rssi_helium.py b/rssi_helium.py index fb3a989..0976333 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -123,9 +123,9 @@ def tx(self, msg, conf=False): self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: print('Sending with Ack') - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} lorawan.create(data, dict(**base, **{'ack':True})) self.ack = False else: From 74725eee48344d5f428c540e28ab4d2f400e254e Mon Sep 17 00:00:00 2001 From: tedder Date: Sat, 20 Aug 2022 21:55:07 -0700 Subject: [PATCH 026/130] reformat; move code.interact to an argument; enable confirm (wasn't getting 'acknowledge' after 'uplink') --- rssi_helium.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/rssi_helium.py b/rssi_helium.py index 0976333..1efcbc3 100755 --- a/rssi_helium.py +++ b/rssi_helium.py @@ -91,19 +91,19 @@ def on_rx_done(self): elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: print("Confirmed data down.") self.ack = True - downlink = decoded + downlink = decoded elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: print("Confirmed data up.") - downlink = decoded + downlink = decoded else: print("Other packet.") downlink = '' self.set_mode(MODE.STDBY) s = '' - s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() - s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() - s += " rssi_value %d\n" % self.get_rssi_value() - s += " msg: %s" % downlink + s += f" pkt_snr_value {self.get_pkt_snr_value():.2f}\n" + s += f" pkt_rssi_value {self.get_pkt_rssi_value():d}\n" + s += f" rssi_value {self.get_rssi_value():d}\n" + s += f" msg: {downlink}" print(s) def increment(self): @@ -119,7 +119,7 @@ def tx(self, msg, conf=False): print('Sending confirmed data up.') else: data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') + print('Sending unconfirmed data up.') self.increment() lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) @@ -137,7 +137,6 @@ def tx(self, msg, conf=False): def start(self, msg): package = json.dumps({"i": self.iter, "s": self.uuid, "m": msg}) - import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() while True: sleep(.1) @@ -149,8 +148,8 @@ def start(self, msg): if self.test_status["running_ping"] and (datetime.datetime.now() - self.last_test).seconds > 5: self.setup_tx() - print("Sending LoRaWAN tx\n") - self.tx(package) + print("Sending LoRaWAN tx with conf\n") + self.tx(package, conf=True) self.iter = self.iter+1 self.last_test = datetime.datetime.now() if not btnA.value: @@ -180,15 +179,15 @@ def setup_tx(self): self.set_sync_word(0x34) self.set_rx_crc(True) self.set_invert_iq(0) - assert(self.get_agc_auto_on() == 1) + assert(self.get_agc_auto_on() == 1) def on_tx_done(self): self.clear_irq_flags(TxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) - self.set_freq(helium.DOWNFREQ) + self.set_freq(helium.DOWNFREQ) self.set_bw(9) - self.set_spreading_factor(7) + self.set_spreading_factor(7) self.set_pa_config(pa_select=1) self.set_sync_word(0x34) self.set_rx_crc(False) @@ -221,8 +220,10 @@ def init(msg=None, start_ping=False): def main(): start_ping = False - if len(sys.argv) > 1 and sys.argv[1] == 'start': + if 'start' in sys.argv: start_ping = True + if 'debug' in sys.argv: + import code;code.interact(local=dict(globals(), **locals())) init(start_ping=start_ping) if __name__ == "__main__": From b02c8b7d3cd218db55ac6cd842c38ac9a47d5216 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:15:00 -0700 Subject: [PATCH 027/130] refactor to make helium more independent module --- helium_lora.py | 177 ++++++++++++++++++++++++++++++++++++++ otaa_helium.py | 2 +- rssi_helium.py | 229 ------------------------------------------------- run.py | 63 ++++++++++++++ 4 files changed, 241 insertions(+), 230 deletions(-) create mode 100755 helium_lora.py mode change 100644 => 100755 otaa_helium.py delete mode 100755 rssi_helium.py create mode 100644 run.py diff --git a/helium_lora.py b/helium_lora.py new file mode 100755 index 0000000..3ea500c --- /dev/null +++ b/helium_lora.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 + +import json +import datetime +from time import sleep +from SX127x.LoRa import LoRa +from SX127x.board_config_ada import BOARD +import LoRaWAN +from LoRaWAN.MHDR import MHDR +import os +import re +import shortuuid + +import helium +import keys + +class HeliumLoRa(LoRa): + def __init__(self, verbose = False, ack=True, start_ping=False): + super(HeliumaLoRa, self).__init__(verbose) + self.iter = 0 + self.uuid = shortuuid.uuid() + self.ack = ack + self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} + self.last_tx = datetime.datetime.fromtimestamp(0) + self.last_message = None + self.transact_timeout = 5 + self.is_otaaing = False + + def otaa(self): + self.is_otaaing = True + lorawan = LoRaWAN.new(keys.appkey) + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + sleep(10) + + def on_rx_done(self): + self.clear_irq_flags(RxDone=1) + payload = self.read_payload(nocheck=True) + if self.is_otaaing: + self.set_mode(MODE.SLEEP) + self.get_all_registers() + print(self) + lorawan = LoRaWAN.new([], keys.appkey) + lorawan.read(payload) + print(lorawan.get_payload()) + print(lorawan.get_mhdr().get_mversion()) + if lorawan.get_mhdr().get_mtype() == MHDR.JOIN_ACCEPT: + print("Got LoRaWAN join accept. Paste these values into keys.py") + print(lorawan.valid_mic()) + devaddr = lorawan.get_devaddr() + print("devaddr = {devaddr}".format()) + nwskey = lorawan.derive_nwskey(devnonce) + print("nwskey = {nwskey}".format()) + appskey = lorawan.derive_appskey(devnonce) + print("appskey = {appskey}".format()) + print("\n") + self.is_otaaing = False + return devaddr, nwskey, appskey + else: + print("Raw payload: {}".format(payload)) + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + decoded = "".join(list(map(chr, lorawan.get_payload()))) + self.last_message = decoded + self.test_status["last_message"] = decoded + self.test_status["ping_count"] += 1 + print("Decoded: {}".format(decoded)) + print("\n") + if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: + print("Unconfirmed data down.") + downlink = decoded + res = lorawan.mac_payload.get_fhdr().get_fctrl() + if 0x20 & res != 0: # Check Ack bit. + print("Server ack") + if len(downlink) == 0: + downlink = "Server ack" + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: + print("Confirmed data down.") + self.ack = True + downlink = decoded + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: + print("Confirmed data up.") + downlink = decoded + else: + print("Other packet.") + downlink = '' + self.set_mode(MODE.STDBY) + s = '' + s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() + s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() + s += " rssi_value %d\n" % self.get_rssi_value() + s += " msg: %s" % downlink + print(s) + + def increment(self): + self.tx_counter += 1 + data_file = open("frame.txt", "w") + data_file.write(f'frame = {self.tx_counter:d}\n') + data_file.close() + + def tx(self, msg, conf=False): + if conf: + data = MHDR.CONF_DATA_UP + print('Sending confirmed data up.') + else: + data = MHDR.UNCONF_DATA_UP + print('Sending unconfirmed data up.') + self.increment() + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + if self.ack: + print('Sending with Ack') + lorawan.create(data, dict(**base, **{'ack':True})) + self.ack = False + else: + print('Sending without Ack') + lorawan.create(data, base) + print(f"tx: {lorawan.to_raw()}") + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + + def set_frame(self,frame): + self.tx_counter = frame + + def setup_tx(self): + # Setup + self.clear_irq_flags(RxDone=1) + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([1,0,0,0,0,0]) + self.set_freq(helium.UPFREQ) + self.set_bw(7) + self.set_spreading_factor(7) + self.set_pa_config(max_power=0x0F, output_power=0x0E) + self.set_sync_word(0x34) + self.set_rx_crc(True) + self.set_invert_iq(0) + assert(self.get_agc_auto_on() == 1) + + def on_tx_done(self): + self.clear_irq_flags(TxDone=1) + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([0,0,0,0,0,0]) + self.set_freq(helium.DOWNFREQ) + self.set_bw(9) + self.set_spreading_factor(7) + self.set_pa_config(pa_select=1) + self.set_sync_word(0x34) + self.set_rx_crc(False) + self.set_invert_iq(1) + self.reset_ptr_rx() + self.set_mode(MODE.RXCONT) + + def transact(self, msg): + self.setup_tx() + self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) + self.iter = self.iter+1 + self.last_tx = datetime.datetime.now() + while self.last_message is None and (datetime.datetime.now() - self.last_test).seconds > self.transact_timeout: + sleep(0.1) + return self.last_message + + def stop(self): + self.set_mode(MODE.SLEEP) + BOARD.teardown() + + @classmethod + def init(cls, start_ping=False): + BOARD.setup() + lora = cls(False, start_ping=start_ping) + frame = 0 + if os.path.exists('frame.txt'): + with open('frame.txt') as df: + for line in df: + if m := re.match('^frame\s*=\s*(\d+)', line): + frame = int(m.group(1)) + lora.set_frame(frame) + return lora diff --git a/otaa_helium.py b/otaa_helium.py old mode 100644 new mode 100755 index 84e169f..7995f92 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -14,7 +14,7 @@ BOARD.setup() parser = LoRaArgumentParser("LoRaWAN sender") -class LoRaWANotaa(LoRa): +class HeliumOTAA(HeliumLoRa): def __init__(self, verbose = False): super(LoRaWANotaa, self).__init__(verbose) diff --git a/rssi_helium.py b/rssi_helium.py deleted file mode 100755 index 0976333..0000000 --- a/rssi_helium.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python3 - -import json -import sys -import argparse -import datetime -from time import sleep -from SX127x.LoRa import * -from SX127x.LoRaArgumentParser import LoRaArgumentParser -from SX127x.board_config_ada import BOARD -import LoRaWAN -from LoRaWAN.MHDR import MHDR -from random import randrange -import reset_ada -# Import the SSD1306 module. -import adafruit_ssd1306 -from digitalio import DigitalInOut, Direction, Pull -import board -import busio -import os -import re -import shortuuid - -import RPi.GPIO as GPIO - -import helium -import keys - -# Button A -btnA = DigitalInOut(board.D5) -btnA.direction = Direction.INPUT -btnA.pull = Pull.UP - -# Button B -btnB = DigitalInOut(board.D6) -btnB.direction = Direction.INPUT -btnB.pull = Pull.UP - -# Button C -btnC = DigitalInOut(board.D12) -btnC.direction = Direction.INPUT -btnC.pull = Pull.UP - -BOARD.setup() -parser = LoRaArgumentParser("LoRaWAN sender") - - -# Create the I2C interface. -i2c = busio.I2C(board.SCL, board.SDA) - -# 128x32 OLED Display -reset_pin = DigitalInOut(board.D4) -display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) -# Clear the display. -display.fill(0) -display.text("Test is ready to start!", 0, 0, 1) -display.text('Push Left Button', 0, 10, 1) -display.text('To start test.', 0, 20, 1) -display.show() -width = display.width -height = display.height - -class LoRaWANotaa(LoRa): - def __init__(self, verbose = False, ack=True, start_ping=False): - super(LoRaWANotaa, self).__init__(verbose) - self.iter = 0 - self.uuid = shortuuid.uuid() - self.ack = ack - self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} - self.last_test = datetime.datetime.fromtimestamp(0) - - def on_rx_done(self): - self.clear_irq_flags(RxDone=1) - payload = self.read_payload(nocheck=True) - print("Raw payload: {}".format(payload)) - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - lorawan.read(payload) - decoded = "".join(list(map(chr, lorawan.get_payload()))) - self.test_status["last_message"] = decoded - self.test_status["ping_count"] += 1 - print("Decoded: {}".format(decoded)) - print("\n") - if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: - print("Unconfirmed data down.") - downlink = decoded - res = lorawan.mac_payload.get_fhdr().get_fctrl() - if 0x20 & res != 0: # Check Ack bit. - print("Server ack") - if len(downlink) == 0: - downlink = "Server ack" - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: - print("Confirmed data down.") - self.ack = True - downlink = decoded - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: - print("Confirmed data up.") - downlink = decoded - else: - print("Other packet.") - downlink = '' - self.set_mode(MODE.STDBY) - s = '' - s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() - s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() - s += " rssi_value %d\n" % self.get_rssi_value() - s += " msg: %s" % downlink - print(s) - - def increment(self): - self.tx_counter += 1 - - data_file = open("frame.txt", "w") - data_file.write(f'frame = {self.tx_counter:d}\n') - data_file.close() - - def tx(self, msg, conf=False): - if conf: - data = MHDR.CONF_DATA_UP - print('Sending confirmed data up.') - else: - data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') - self.increment() - - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - if self.ack: - print('Sending with Ack') - lorawan.create(data, dict(**base, **{'ack':True})) - self.ack = False - else: - print('Sending without Ack') - lorawan.create(data, base) - print(f"tx: {lorawan.to_raw()}") - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - - def start(self, msg): - package = json.dumps({"i": self.iter, "s": self.uuid, "m": msg}) - import code;code.interact(local=dict(globals(), **locals())) - self.setup_tx() - while True: - sleep(.1) - display.fill(0) - display.text("Test is "+str(self.test_status["running_ping"]), 0, 0, 1) - display.text('Time: '+str(self.test_status["last_message"]), 0, 10, 1) - display.text('Total Pings: '+str(self.test_status["ping_count"]), 0, 20, 1) - display.show() - - if self.test_status["running_ping"] and (datetime.datetime.now() - self.last_test).seconds > 5: - self.setup_tx() - print("Sending LoRaWAN tx\n") - self.tx(package) - self.iter = self.iter+1 - self.last_test = datetime.datetime.now() - if not btnA.value: - self.test_status["running_ping"] = True - if not btnB.value: - self.test_status["running_ping"] = False - if not btnC.value: - display.fill(0) - display.text("Test is shut down!", 0, 0, 1) - display.text('Must restart PI to', 0, 10, 1) - display.text('restart test.', 0, 20, 1) - display.show() - raise KeyboardInterrupt - - def set_frame(self,frame): - self.tx_counter = frame - - def setup_tx(self): - # Setup - self.clear_irq_flags(RxDone=1) - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium.UPFREQ) - self.set_bw(7) - self.set_spreading_factor(7) - self.set_pa_config(max_power=0x0F, output_power=0x0E) - self.set_sync_word(0x34) - self.set_rx_crc(True) - self.set_invert_iq(0) - assert(self.get_agc_auto_on() == 1) - - def on_tx_done(self): - self.clear_irq_flags(TxDone=1) - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([0,0,0,0,0,0]) - self.set_freq(helium.DOWNFREQ) - self.set_bw(9) - self.set_spreading_factor(7) - self.set_pa_config(pa_select=1) - self.set_sync_word(0x34) - self.set_rx_crc(False) - self.set_invert_iq(1) - self.reset_ptr_rx() - self.set_mode(MODE.RXCONT) - -def init(msg=None, start_ping=False): - lora = LoRaWANotaa(False, start_ping=start_ping) - - frame = 0 - if os.path.exists('frame.txt'): - with open('frame.txt') as df: - for line in df: - if m := re.match('^frame\s*=\s*(\d+)', line): - frame = int(m.group(1)) - - lora.set_frame(frame) - - try: - lora.start(msg) - except KeyboardInterrupt: - sys.stdout.flush() - print("\nKeyboardInterrupt") - finally: - sys.stdout.flush() - lora.set_mode(MODE.SLEEP) - BOARD.teardown() - - -def main(): - start_ping = False - if len(sys.argv) > 1 and sys.argv[1] == 'start': - start_ping = True - init(start_ping=start_ping) - -if __name__ == "__main__": - main() diff --git a/run.py b/run.py new file mode 100644 index 0000000..1122071 --- /dev/null +++ b/run.py @@ -0,0 +1,63 @@ +import adafruit_ssd1306 +from digitalio import DigitalInOut, Direction, Pull +import board +import busio + +from helium_lora import HeliumLoRa + +# Button A +btnA = DigitalInOut(board.D5) +btnA.direction = Direction.INPUT +btnA.pull = Pull.UP + +# Button B +btnB = DigitalInOut(board.D6) +btnB.direction = Direction.INPUT +btnB.pull = Pull.UP + +# Button C +btnC = DigitalInOut(board.D12) +btnC.direction = Direction.INPUT +btnC.pull = Pull.UP + +# Create the I2C interface. +i2c = busio.I2C(board.SCL, board.SDA) + +# 128x32 OLED Display +reset_pin = DigitalInOut(board.D4) +display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) +# Clear the display. +display.fill(0) +display.text("Test is ready to start!", 0, 0, 1) +display.text('Push Left Button', 0, 10, 1) +display.text('To start test.', 0, 20, 1) +display.show() +width = display.width +height = display.height + +def run(): + lora = HeliumLoRa.init() + if not keys.nwskey: + devaddr, nwskey, appskey = lora.otaa() + while True: + sleep(.1) + display.fill(0) + display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) + display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) + display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) + display.show() + if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: + lora.transact("Test") + if not btnA.value: + lora.test_status["running_ping"] = True + if not btnB.value: + lora.test_status["running_ping"] = False + if not btnC.value: + display.fill(0) + display.text("Test is shut down!", 0, 0, 1) + display.text('Must restart PI to', 0, 10, 1) + display.text('restart test.', 0, 20, 1) + display.show() + raise KeyboardInterrupt + +run() \ No newline at end of file From e6794ffe6b250a80aaf847b5e2ab31e0fc8129bb Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:24:59 -0700 Subject: [PATCH 028/130] updates --- helium_lora.py | 2 +- run.py | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 3ea500c..8092bde 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -16,7 +16,7 @@ class HeliumLoRa(LoRa): def __init__(self, verbose = False, ack=True, start_ping=False): - super(HeliumaLoRa, self).__init__(verbose) + super(HeliumLoRa, self).__init__(verbose) self.iter = 0 self.uuid = shortuuid.uuid() self.ack = ack diff --git a/run.py b/run.py index 1122071..3575213 100644 --- a/run.py +++ b/run.py @@ -27,11 +27,6 @@ reset_pin = DigitalInOut(board.D4) display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) # Clear the display. -display.fill(0) -display.text("Test is ready to start!", 0, 0, 1) -display.text('Push Left Button', 0, 10, 1) -display.text('To start test.', 0, 20, 1) -display.show() width = display.width height = display.height From 3c8ed0b5672628e78b5c61de2da1d34da6cac990 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:26:23 -0700 Subject: [PATCH 029/130] updates --- helium_lora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_lora.py b/helium_lora.py index 8092bde..99e3fcf 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -3,7 +3,7 @@ import json import datetime from time import sleep -from SX127x.LoRa import LoRa +from SX127x.LoRa import LoRa, MODE from SX127x.board_config_ada import BOARD import LoRaWAN from LoRaWAN.MHDR import MHDR From 9124faf75020c98e961f6e9673d65f23f492522e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:29:14 -0700 Subject: [PATCH 030/130] updates --- helium_lora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_lora.py b/helium_lora.py index 99e3fcf..887922e 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -155,7 +155,7 @@ def transact(self, msg): self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) self.iter = self.iter+1 self.last_tx = datetime.datetime.now() - while self.last_message is None and (datetime.datetime.now() - self.last_test).seconds > self.transact_timeout: + while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: sleep(0.1) return self.last_message From 6af5066ad4059e3dc39d3b27c9edefffa1c2ce14 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:39:44 -0700 Subject: [PATCH 031/130] updates --- helium_lora.py | 7 +++++-- run.py | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 887922e..bef5b79 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 +import os +import re import json import datetime from time import sleep +from random import randrange + from SX127x.LoRa import LoRa, MODE from SX127x.board_config_ada import BOARD import LoRaWAN from LoRaWAN.MHDR import MHDR -import os -import re import shortuuid import helium @@ -29,6 +31,7 @@ def __init__(self, verbose = False, ack=True, start_ping=False): def otaa(self): self.is_otaaing = True lorawan = LoRaWAN.new(keys.appkey) + devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) diff --git a/run.py b/run.py index 3575213..035e9cc 100644 --- a/run.py +++ b/run.py @@ -1,3 +1,5 @@ +import time + import adafruit_ssd1306 from digitalio import DigitalInOut, Direction, Pull import board @@ -35,7 +37,7 @@ def run(): if not keys.nwskey: devaddr, nwskey, appskey = lora.otaa() while True: - sleep(.1) + time.sleep(.1) display.fill(0) display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) From 846b5119861238346c38ed355ddda0a3c75f837a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:46:26 -0700 Subject: [PATCH 032/130] Updates --- helium_lora.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index bef5b79..446ee7f 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -59,7 +59,7 @@ def on_rx_done(self): print("appskey = {appskey}".format()) print("\n") self.is_otaaing = False - return devaddr, nwskey, appskey + self.otaa_result = [devaddr, nwskey, appskey] else: print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) @@ -127,17 +127,24 @@ def set_frame(self,frame): def setup_tx(self): # Setup - self.clear_irq_flags(RxDone=1) + if not self.is_otaaing: + self.clear_irq_flags(RxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) self.set_freq(helium.UPFREQ) - self.set_bw(7) + if not self.is_otaaing: + self.set_bw(7) + else: + self.set_pa_config(pa_select=1) self.set_spreading_factor(7) self.set_pa_config(max_power=0x0F, output_power=0x0E) self.set_sync_word(0x34) self.set_rx_crc(True) - self.set_invert_iq(0) - assert(self.get_agc_auto_on() == 1) + if not self.is_otaaing: + self.set_invert_iq(0) + else: + self.get_all_registers() + assert(self.get_agc_auto_on() == 1) def on_tx_done(self): self.clear_irq_flags(TxDone=1) From fffd3927828c4edde1dc34d8b010baa2ce121a10 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:48:53 -0700 Subject: [PATCH 033/130] updates --- helium_lora.py | 4 ++-- run.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 446ee7f..54d764e 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -174,9 +174,9 @@ def stop(self): BOARD.teardown() @classmethod - def init(cls, start_ping=False): + def init(cls, verbose=False, ack=True, start_ping=False): BOARD.setup() - lora = cls(False, start_ping=start_ping) + lora = cls(verbose, ack, start_ping) frame = 0 if os.path.exists('frame.txt'): with open('frame.txt') as df: diff --git a/run.py b/run.py index 035e9cc..292d80d 100644 --- a/run.py +++ b/run.py @@ -31,7 +31,8 @@ # Clear the display. width = display.width height = display.height - +lora = HeliumLoRa.init(True) +lora.otaa() def run(): lora = HeliumLoRa.init() if not keys.nwskey: From dc8944fe50235239599b971f68442277de1bd912 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:51:15 -0700 Subject: [PATCH 034/130] updates --- helium_lora.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/helium_lora.py b/helium_lora.py index 54d764e..7421717 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -29,6 +29,7 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): + self.tx_counter = 1 self.is_otaaing = True lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] @@ -36,6 +37,7 @@ def otaa(self): self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) + self.set_mode(MODE.SLEEP) def on_rx_done(self): self.clear_irq_flags(RxDone=1) From ffb2431ee02c6b94b59070b0adc76f498f39db51 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:56:45 -0700 Subject: [PATCH 035/130] updates --- helium_lora.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 7421717..57f8b0a 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -29,8 +29,8 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): - self.tx_counter = 1 self.is_otaaing = True + import code;code.interact(local=dict(globals(), **locals())) lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) @@ -175,15 +175,17 @@ def stop(self): self.set_mode(MODE.SLEEP) BOARD.teardown() - @classmethod - def init(cls, verbose=False, ack=True, start_ping=False): - BOARD.setup() - lora = cls(verbose, ack, start_ping) + def init_frame(self): frame = 0 if os.path.exists('frame.txt'): with open('frame.txt') as df: for line in df: if m := re.match('^frame\s*=\s*(\d+)', line): frame = int(m.group(1)) - lora.set_frame(frame) + self.set_frame(frame) + + @classmethod + def init(cls, verbose=False, ack=True, start_ping=False): + BOARD.setup() + lora = cls(verbose, ack, start_ping) return lora From 2f1324a92824664bca0f87c13ddc6c500b75cb86 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 11:59:31 -0700 Subject: [PATCH 036/130] updates --- otaa_helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/otaa_helium.py b/otaa_helium.py index 7995f92..84e169f 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -14,7 +14,7 @@ BOARD.setup() parser = LoRaArgumentParser("LoRaWAN sender") -class HeliumOTAA(HeliumLoRa): +class LoRaWANotaa(LoRa): def __init__(self, verbose = False): super(LoRaWANotaa, self).__init__(verbose) From fe448ec00e1edabd77c41b12765ffa5a5599e9c8 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:05:09 -0700 Subject: [PATCH 037/130] updates --- otaa_helium.py | 55 ++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/otaa_helium.py b/otaa_helium.py index 84e169f..492df11 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -74,31 +74,34 @@ def start(self): # self.set_mode(MODE.TX) -devnonce = [randrange(256), randrange(256)] -lora = LoRaWANotaa(True) - -# Setup -lora.set_mode(MODE.SLEEP) -lora.set_dio_mapping([1,0,0,0,0,0]) -lora.set_freq(helium.UPFREQ) -lora.set_pa_config(pa_select=1) -lora.set_spreading_factor(7) -lora.set_pa_config(max_power=0x0F, output_power=0x0E) -lora.set_sync_word(0x34) -lora.set_rx_crc(True) -lora.get_all_registers() -print(lora) -assert(lora.get_agc_auto_on() == 1) - -try: - print("Sending LoRaWAN join request\n") - lora.start() +def main(): + devnonce = [randrange(256), randrange(256)] + lora = LoRaWANotaa(True) + # Setup lora.set_mode(MODE.SLEEP) + lora.set_dio_mapping([1,0,0,0,0,0]) + lora.set_freq(helium.UPFREQ) + lora.set_pa_config(pa_select=1) + lora.set_spreading_factor(7) + lora.set_pa_config(max_power=0x0F, output_power=0x0E) + lora.set_sync_word(0x34) + lora.set_rx_crc(True) + lora.get_all_registers() print(lora) -except KeyboardInterrupt: - sys.stdout.flush() - print("\nKeyboardInterrupt") -finally: - sys.stdout.flush() - lora.set_mode(MODE.SLEEP) - BOARD.teardown() + assert(lora.get_agc_auto_on() == 1) + try: + print("Sending LoRaWAN join request\n") + lora.start() + lora.set_mode(MODE.SLEEP) + print(lora) + except KeyboardInterrupt: + sys.stdout.flush() + print("\nKeyboardInterrupt") + finally: + sys.stdout.flush() + lora.set_mode(MODE.SLEEP) + BOARD.teardown() + +if __name__ == "__main__": + main() + From 782ac6ffd63ccc9521981ab07633c9d7856c8440 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:06:07 -0700 Subject: [PATCH 038/130] updates --- otaa_helium.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/otaa_helium.py b/otaa_helium.py index 492df11..ceef85b 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -61,7 +61,7 @@ def on_tx_done(self): def start(self): self.tx_counter = 1 - + devnonce = [randrange(256), randrange(256)] lorawan = LoRaWAN.new(keys.appkey) lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) @@ -75,7 +75,6 @@ def start(self): def main(): - devnonce = [randrange(256), randrange(256)] lora = LoRaWANotaa(True) # Setup lora.set_mode(MODE.SLEEP) From ac49e3b828d41d9a6fac34479989a33736f078d9 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:08:21 -0700 Subject: [PATCH 039/130] updates --- otaa_helium.py | 56 ++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/otaa_helium.py b/otaa_helium.py index ceef85b..84e169f 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -61,7 +61,7 @@ def on_tx_done(self): def start(self): self.tx_counter = 1 - devnonce = [randrange(256), randrange(256)] + lorawan = LoRaWAN.new(keys.appkey) lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) @@ -74,33 +74,31 @@ def start(self): # self.set_mode(MODE.TX) -def main(): - lora = LoRaWANotaa(True) - # Setup +devnonce = [randrange(256), randrange(256)] +lora = LoRaWANotaa(True) + +# Setup +lora.set_mode(MODE.SLEEP) +lora.set_dio_mapping([1,0,0,0,0,0]) +lora.set_freq(helium.UPFREQ) +lora.set_pa_config(pa_select=1) +lora.set_spreading_factor(7) +lora.set_pa_config(max_power=0x0F, output_power=0x0E) +lora.set_sync_word(0x34) +lora.set_rx_crc(True) +lora.get_all_registers() +print(lora) +assert(lora.get_agc_auto_on() == 1) + +try: + print("Sending LoRaWAN join request\n") + lora.start() lora.set_mode(MODE.SLEEP) - lora.set_dio_mapping([1,0,0,0,0,0]) - lora.set_freq(helium.UPFREQ) - lora.set_pa_config(pa_select=1) - lora.set_spreading_factor(7) - lora.set_pa_config(max_power=0x0F, output_power=0x0E) - lora.set_sync_word(0x34) - lora.set_rx_crc(True) - lora.get_all_registers() print(lora) - assert(lora.get_agc_auto_on() == 1) - try: - print("Sending LoRaWAN join request\n") - lora.start() - lora.set_mode(MODE.SLEEP) - print(lora) - except KeyboardInterrupt: - sys.stdout.flush() - print("\nKeyboardInterrupt") - finally: - sys.stdout.flush() - lora.set_mode(MODE.SLEEP) - BOARD.teardown() - -if __name__ == "__main__": - main() - +except KeyboardInterrupt: + sys.stdout.flush() + print("\nKeyboardInterrupt") +finally: + sys.stdout.flush() + lora.set_mode(MODE.SLEEP) + BOARD.teardown() From e19a31f797fd04defa2af5856f8017f966bfda3a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:35:53 -0700 Subject: [PATCH 040/130] updates --- helium_lora.py | 7 +++---- otaa_helium.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 57f8b0a..5247280 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -128,9 +128,7 @@ def set_frame(self,frame): self.tx_counter = frame def setup_tx(self): - # Setup - if not self.is_otaaing: - self.clear_irq_flags(RxDone=1) + # Setup self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) self.set_freq(helium.UPFREQ) @@ -156,7 +154,8 @@ def on_tx_done(self): self.set_bw(9) self.set_spreading_factor(7) self.set_pa_config(pa_select=1) - self.set_sync_word(0x34) + if not self.is_otaaing: + self.set_sync_word(0x34) self.set_rx_crc(False) self.set_invert_iq(1) self.reset_ptr_rx() diff --git a/otaa_helium.py b/otaa_helium.py index 84e169f..9d2696f 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -101,4 +101,4 @@ def start(self): finally: sys.stdout.flush() lora.set_mode(MODE.SLEEP) - BOARD.teardown() + BOARD.teardown() \ No newline at end of file From 5c50f0e2b09af5cd0d599e6d7471a4df093e51cf Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:37:37 -0700 Subject: [PATCH 041/130] updates --- helium_lora.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 5247280..5309890 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -30,7 +30,6 @@ def __init__(self, verbose = False, ack=True, start_ping=False): def otaa(self): self.is_otaaing = True - import code;code.interact(local=dict(globals(), **locals())) lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) @@ -40,6 +39,7 @@ def otaa(self): self.set_mode(MODE.SLEEP) def on_rx_done(self): + import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) if self.is_otaaing: @@ -147,19 +147,28 @@ def setup_tx(self): assert(self.get_agc_auto_on() == 1) def on_tx_done(self): - self.clear_irq_flags(TxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) - self.set_freq(helium.DOWNFREQ) - self.set_bw(9) - self.set_spreading_factor(7) - self.set_pa_config(pa_select=1) - if not self.is_otaaing: - self.set_sync_word(0x34) - self.set_rx_crc(False) self.set_invert_iq(1) self.reset_ptr_rx() + self.set_freq(helium.DOWNFREQ)#915) + self.set_spreading_factor(7)#12) + self.set_bw(9) #500Khz + self.set_rx_crc(False)#TRUE self.set_mode(MODE.RXCONT) + # self.clear_irq_flags(TxDone=1) + # self.set_mode(MODE.SLEEP) + # self.set_dio_mapping([0,0,0,0,0,0]) + # self.set_freq(helium.DOWNFREQ) + # self.set_bw(9) + # self.set_spreading_factor(7) + # self.set_pa_config(pa_select=1) + # if not self.is_otaaing: + # self.set_sync_word(0x34) + # self.set_rx_crc(False) + # self.set_invert_iq(1) + # self.reset_ptr_rx() + # self.set_mode(MODE.RXCONT) def transact(self, msg): self.setup_tx() From 5a729831435b6e6a8fb4030089db4f24cc79c6e8 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:37:49 -0700 Subject: [PATCH 042/130] updates --- run.py | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/run.py b/run.py index 292d80d..08ebb00 100644 --- a/run.py +++ b/run.py @@ -33,29 +33,29 @@ height = display.height lora = HeliumLoRa.init(True) lora.otaa() -def run(): - lora = HeliumLoRa.init() - if not keys.nwskey: - devaddr, nwskey, appskey = lora.otaa() - while True: - time.sleep(.1) - display.fill(0) - display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) - display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) - display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) - display.show() - if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: - lora.transact("Test") - if not btnA.value: - lora.test_status["running_ping"] = True - if not btnB.value: - lora.test_status["running_ping"] = False - if not btnC.value: - display.fill(0) - display.text("Test is shut down!", 0, 0, 1) - display.text('Must restart PI to', 0, 10, 1) - display.text('restart test.', 0, 20, 1) - display.show() - raise KeyboardInterrupt - -run() \ No newline at end of file +# def run(): +# lora = HeliumLoRa.init() +# if not keys.nwskey: +# devaddr, nwskey, appskey = lora.otaa() +# while True: +# time.sleep(.1) +# display.fill(0) +# display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) +# display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) +# display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) +# display.show() +# if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: +# lora.transact("Test") +# if not btnA.value: +# lora.test_status["running_ping"] = True +# if not btnB.value: +# lora.test_status["running_ping"] = False +# if not btnC.value: +# display.fill(0) +# display.text("Test is shut down!", 0, 0, 1) +# display.text('Must restart PI to', 0, 10, 1) +# display.text('restart test.', 0, 20, 1) +# display.show() +# raise KeyboardInterrupt +# +# run() \ No newline at end of file From fbcdce420cbf57b35ee5ca9270cf09e005a9d7b5 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:39:53 -0700 Subject: [PATCH 043/130] updates --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index 08ebb00..c5d9270 100644 --- a/run.py +++ b/run.py @@ -31,7 +31,7 @@ # Clear the display. width = display.width height = display.height -lora = HeliumLoRa.init(True) +lora = HeliumLoRa.init(True, True, True) lora.otaa() # def run(): # lora = HeliumLoRa.init() From a2e016f84a381897814f110083ddddc952ded9aa Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:42:06 -0700 Subject: [PATCH 044/130] updates --- helium_lora.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 5309890..0644755 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -15,7 +15,7 @@ import helium import keys - +BOARD.setup() class HeliumLoRa(LoRa): def __init__(self, verbose = False, ack=True, start_ping=False): super(HeliumLoRa, self).__init__(verbose) @@ -29,6 +29,7 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): + print(self) self.is_otaaing = True lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] @@ -36,6 +37,7 @@ def otaa(self): self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) + print(self) self.set_mode(MODE.SLEEP) def on_rx_done(self): @@ -194,6 +196,5 @@ def init_frame(self): @classmethod def init(cls, verbose=False, ack=True, start_ping=False): - BOARD.setup() lora = cls(verbose, ack, start_ping) return lora From 9a7aa125eca3a3ebb1ab41bf97214fd6019ffee8 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:43:49 -0700 Subject: [PATCH 045/130] updates --- helium_lora.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 0644755..d46c203 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -131,21 +131,32 @@ def set_frame(self,frame): def setup_tx(self): # Setup + # self.set_mode(MODE.SLEEP) + # self.set_dio_mapping([1,0,0,0,0,0]) + # self.set_freq(helium.UPFREQ) + # if not self.is_otaaing: + # self.set_bw(7) + # else: + # self.set_pa_config(pa_select=1) + # self.set_spreading_factor(7) + # self.set_pa_config(max_power=0x0F, output_power=0x0E) + # self.set_sync_word(0x34) + # self.set_rx_crc(True) + # if not self.is_otaaing: + # self.set_invert_iq(0) + # else: + # self.get_all_registers() + # assert(self.get_agc_auto_on() == 1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) self.set_freq(helium.UPFREQ) - if not self.is_otaaing: - self.set_bw(7) - else: - self.set_pa_config(pa_select=1) + self.set_pa_config(pa_select=1) self.set_spreading_factor(7) self.set_pa_config(max_power=0x0F, output_power=0x0E) self.set_sync_word(0x34) self.set_rx_crc(True) - if not self.is_otaaing: - self.set_invert_iq(0) - else: - self.get_all_registers() + self.get_all_registers() + print(self) assert(self.get_agc_auto_on() == 1) def on_tx_done(self): From cf932b104bde8bd4062c965e3ecba730920aa979 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:44:41 -0700 Subject: [PATCH 046/130] updates --- helium_lora.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/helium_lora.py b/helium_lora.py index d46c203..9fa5768 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -160,6 +160,10 @@ def setup_tx(self): assert(self.get_agc_auto_on() == 1) def on_tx_done(self): + self.clear_irq_flags(TxDone=1) + print("TxDone") + + self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) self.set_invert_iq(1) From 5f033377729ded4dba4493b314ae8bbcac139eb4 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:45:47 -0700 Subject: [PATCH 047/130] updates --- helium_lora.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 9fa5768..416f333 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -29,17 +29,28 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): - print(self) - self.is_otaaing = True + self.tx_counter = 1 + lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) + self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) - print(self) - self.set_mode(MODE.SLEEP) - + + # def otaa(self): + # print(self) + # self.is_otaaing = True + # lorawan = LoRaWAN.new(keys.appkey) + # devnonce = [randrange(256), randrange(256)] + # lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) + # self.write_payload(lorawan.to_raw()) + # self.set_mode(MODE.TX) + # sleep(10) + # print(self) + # self.set_mode(MODE.SLEEP) + # def on_rx_done(self): import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) From e0e7b01650d5ad899e23d7f656b7fd73ffbd8068 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:47:11 -0700 Subject: [PATCH 048/130] updates --- run.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run.py b/run.py index c5d9270..fc61684 100644 --- a/run.py +++ b/run.py @@ -1,6 +1,7 @@ import time import adafruit_ssd1306 +from SX127x.LoRa import LoRa, MODE from digitalio import DigitalInOut, Direction, Pull import board import busio @@ -33,6 +34,8 @@ height = display.height lora = HeliumLoRa.init(True, True, True) lora.otaa() +lora.set_mode(MODE.SLEEP) +print(lora) # def run(): # lora = HeliumLoRa.init() # if not keys.nwskey: From a5d58b44290626c82daf3e8e42eb99f84ee06377 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:49:35 -0700 Subject: [PATCH 049/130] updates --- run.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index fc61684..b34767f 100644 --- a/run.py +++ b/run.py @@ -33,9 +33,18 @@ width = display.width height = display.height lora = HeliumLoRa.init(True, True, True) -lora.otaa() -lora.set_mode(MODE.SLEEP) -print(lora) +try: + print("Sending LoRaWAN join request\n") + lora.start() + lora.set_mode(MODE.SLEEP) + print(lora) +except KeyboardInterrupt: + sys.stdout.flush() + print("\nKeyboardInterrupt") +finally: + sys.stdout.flush() + lora.set_mode(MODE.SLEEP) + BOARD.teardown() # def run(): # lora = HeliumLoRa.init() # if not keys.nwskey: From f7e52cda23e82ac6f8ec54a28a7abbf8e9f0fefe Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:49:48 -0700 Subject: [PATCH 050/130] updates --- run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run.py b/run.py index b34767f..3df5a50 100644 --- a/run.py +++ b/run.py @@ -1,3 +1,4 @@ +import sys import time import adafruit_ssd1306 From fbbd46c3661dd9640fc4aeea45df0240a6f765f7 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:50:14 -0700 Subject: [PATCH 051/130] updates --- run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run.py b/run.py index 3df5a50..bdeb122 100644 --- a/run.py +++ b/run.py @@ -4,6 +4,7 @@ import adafruit_ssd1306 from SX127x.LoRa import LoRa, MODE from digitalio import DigitalInOut, Direction, Pull +from SX127x.board_config_ada import BOARD import board import busio From 3aa28415220b4b3213da8d76f4ff4a5fb911c462 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:50:38 -0700 Subject: [PATCH 052/130] updates --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index bdeb122..52d77ed 100644 --- a/run.py +++ b/run.py @@ -37,7 +37,7 @@ lora = HeliumLoRa.init(True, True, True) try: print("Sending LoRaWAN join request\n") - lora.start() + lora.otaa() lora.set_mode(MODE.SLEEP) print(lora) except KeyboardInterrupt: From 4cb8e3e26a39fa3912a98c807b508f4772c4e183 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:53:01 -0700 Subject: [PATCH 053/130] updates --- helium_lora.py | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 416f333..0dc9d4e 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -52,7 +52,6 @@ def otaa(self): # self.set_mode(MODE.SLEEP) # def on_rx_done(self): - import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) if self.is_otaaing: @@ -116,27 +115,27 @@ def increment(self): data_file.write(f'frame = {self.tx_counter:d}\n') data_file.close() - def tx(self, msg, conf=False): - if conf: - data = MHDR.CONF_DATA_UP - print('Sending confirmed data up.') - else: - data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') - self.increment() - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - if self.ack: - print('Sending with Ack') - lorawan.create(data, dict(**base, **{'ack':True})) - self.ack = False - else: - print('Sending without Ack') - lorawan.create(data, base) - print(f"tx: {lorawan.to_raw()}") - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - + # def tx(self, msg, conf=False): + # if conf: + # data = MHDR.CONF_DATA_UP + # print('Sending confirmed data up.') + # else: + # data = MHDR.UNCONF_DATA_UP + # print('Sending unconfirmed data up.') + # self.increment() + # lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + # base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + # if self.ack: + # print('Sending with Ack') + # lorawan.create(data, dict(**base, **{'ack':True})) + # self.ack = False + # else: + # print('Sending without Ack') + # lorawan.create(data, base) + # print(f"tx: {lorawan.to_raw()}") + # self.write_payload(lorawan.to_raw()) + # self.set_mode(MODE.TX) + # def set_frame(self,frame): self.tx_counter = frame @@ -173,8 +172,6 @@ def setup_tx(self): def on_tx_done(self): self.clear_irq_flags(TxDone=1) print("TxDone") - - self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) self.set_invert_iq(1) From 648f46137e4df74833962749884c932079c7c2e1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:54:52 -0700 Subject: [PATCH 054/130] updates --- helium_lora.py | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 0dc9d4e..e60b923 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -29,6 +29,7 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): + self.setup_tx() self.tx_counter = 1 lorawan = LoRaWAN.new(keys.appkey) @@ -115,27 +116,27 @@ def increment(self): data_file.write(f'frame = {self.tx_counter:d}\n') data_file.close() - # def tx(self, msg, conf=False): - # if conf: - # data = MHDR.CONF_DATA_UP - # print('Sending confirmed data up.') - # else: - # data = MHDR.UNCONF_DATA_UP - # print('Sending unconfirmed data up.') - # self.increment() - # lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - # base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - # if self.ack: - # print('Sending with Ack') - # lorawan.create(data, dict(**base, **{'ack':True})) - # self.ack = False - # else: - # print('Sending without Ack') - # lorawan.create(data, base) - # print(f"tx: {lorawan.to_raw()}") - # self.write_payload(lorawan.to_raw()) - # self.set_mode(MODE.TX) - # + def tx(self, msg, conf=False): + if conf: + data = MHDR.CONF_DATA_UP + print('Sending confirmed data up.') + else: + data = MHDR.UNCONF_DATA_UP + print('Sending unconfirmed data up.') + self.increment() + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + if self.ack: + print('Sending with Ack') + lorawan.create(data, dict(**base, **{'ack':True})) + self.ack = False + else: + print('Sending without Ack') + lorawan.create(data, base) + print(f"tx: {lorawan.to_raw()}") + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + def set_frame(self,frame): self.tx_counter = frame From 5d5d0d5034301bf5de7601d347754be847dca082 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:56:34 -0700 Subject: [PATCH 055/130] updates --- helium_lora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_lora.py b/helium_lora.py index e60b923..7cc89f2 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -31,7 +31,6 @@ def __init__(self, verbose = False, ack=True, start_ping=False): def otaa(self): self.setup_tx() self.tx_counter = 1 - lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) @@ -53,6 +52,7 @@ def otaa(self): # self.set_mode(MODE.SLEEP) # def on_rx_done(self): + import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) if self.is_otaaing: From ff84ea80ca7465a476dc5565179ce6ea2aea5a3e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:58:59 -0700 Subject: [PATCH 056/130] updates --- helium_lora.py | 2 ++ otaa_helium.py | 4 +--- run.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index 7cc89f2..20ca863 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -52,6 +52,7 @@ def otaa(self): # self.set_mode(MODE.SLEEP) # def on_rx_done(self): + print("RxDone") import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) @@ -221,4 +222,5 @@ def init_frame(self): @classmethod def init(cls, verbose=False, ack=True, start_ping=False): lora = cls(verbose, ack, start_ping) + self.init_frame() return lora diff --git a/otaa_helium.py b/otaa_helium.py index 9d2696f..370bdf0 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -46,8 +46,6 @@ def on_rx_done(self): def on_tx_done(self): self.clear_irq_flags(TxDone=1) print("TxDone") - - self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) self.set_invert_iq(1) @@ -101,4 +99,4 @@ def start(self): finally: sys.stdout.flush() lora.set_mode(MODE.SLEEP) - BOARD.teardown() \ No newline at end of file + BOARD.teardown() diff --git a/run.py b/run.py index 52d77ed..d9532b8 100644 --- a/run.py +++ b/run.py @@ -38,6 +38,7 @@ try: print("Sending LoRaWAN join request\n") lora.otaa() + time.sleep(10) lora.set_mode(MODE.SLEEP) print(lora) except KeyboardInterrupt: From fce53e0027ae34a938012cc920a44979467d1755 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 12:59:29 -0700 Subject: [PATCH 057/130] updates --- helium_lora.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_lora.py b/helium_lora.py index 20ca863..c1255a0 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -222,5 +222,5 @@ def init_frame(self): @classmethod def init(cls, verbose=False, ack=True, start_ping=False): lora = cls(verbose, ack, start_ping) - self.init_frame() + lora.init_frame() return lora From 9b5ab5f7702186324e037ed680c8d099d3e2bc7b Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:01:41 -0700 Subject: [PATCH 058/130] updates --- helium_lora.py | 1 - otaa_helium.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index c1255a0..a9d9bc4 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -30,7 +30,6 @@ def __init__(self, verbose = False, ack=True, start_ping=False): def otaa(self): self.setup_tx() - self.tx_counter = 1 lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) diff --git a/otaa_helium.py b/otaa_helium.py index 370bdf0..ad2e4db 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -58,8 +58,6 @@ def on_tx_done(self): def start(self): - self.tx_counter = 1 - lorawan = LoRaWAN.new(keys.appkey) lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) From 1f247f2aa52bb33b02a487424f6459988d475134 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:03:40 -0700 Subject: [PATCH 059/130] updates --- helium_lora.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index a9d9bc4..f51656e 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -29,26 +29,17 @@ def __init__(self, verbose = False, ack=True, start_ping=False): self.is_otaaing = False def otaa(self): + print(self) + self.is_otaaing = True self.setup_tx() lorawan = LoRaWAN.new(keys.appkey) devnonce = [randrange(256), randrange(256)] lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) - self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) - - # def otaa(self): - # print(self) - # self.is_otaaing = True - # lorawan = LoRaWAN.new(keys.appkey) - # devnonce = [randrange(256), randrange(256)] - # lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) - # self.write_payload(lorawan.to_raw()) - # self.set_mode(MODE.TX) - # sleep(10) - # print(self) - # self.set_mode(MODE.SLEEP) + print(self) + self.set_mode(MODE.SLEEP) # def on_rx_done(self): print("RxDone") From f483fdd80c0cd5fde44d240a6f909a6c9ace98d9 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:04:29 -0700 Subject: [PATCH 060/130] updates --- helium_lora.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/helium_lora.py b/helium_lora.py index f51656e..9251fa3 100755 --- a/helium_lora.py +++ b/helium_lora.py @@ -38,9 +38,7 @@ def otaa(self): self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) - print(self) - self.set_mode(MODE.SLEEP) - # + def on_rx_done(self): print("RxDone") import code;code.interact(local=dict(globals(), **locals())) From e01f325e57e1aa2d1bfb7c59ef25185fd29d2663 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:12:22 -0700 Subject: [PATCH 061/130] updates --- helium_authenticator.py | 66 ++++++++++++++ run.py | 1 - transactor.py | 189 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 1 deletion(-) create mode 100755 helium_authenticator.py create mode 100755 transactor.py diff --git a/helium_authenticator.py b/helium_authenticator.py new file mode 100755 index 0000000..cbd434e --- /dev/null +++ b/helium_authenticator.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 + +import sys +from time import sleep +from SX127x.LoRa import * +from SX127x.LoRaArgumentParser import LoRaArgumentParser +from SX127x.board_config_ada import BOARD +import LoRaWAN +from LoRaWAN.MHDR import MHDR +from random import randrange +import reset_ada +import helium +import keys + +BOARD.setup() +class HeliumAuthenticator(LoRa): + def __init__(self, verbose = False): + super(LoRaWANotaa, self).__init__(verbose) + self.authenticated = False + self.devaddr = None + self.nwskey = None + self.appskey = None + + def on_rx_done(self): + self.clear_irq_flags(RxDone=1) + payload = self.read_payload(nocheck=True) + self.set_mode(MODE.SLEEP) + self.get_all_registers() + lorawan = LoRaWAN.new([], keys.appkey) + lorawan.read(payload) + if lorawan.get_mhdr().get_mtype() == MHDR.JOIN_ACCEPT: + self.devaddr = lorawan.get_devaddr() + self.nwskey = lorawan.derive_nwskey(devnonce) + self.appskey = lorawan.derive_appskey(devnonce) + self.authenticated = True + + def on_tx_done(self): + self.clear_irq_flags(TxDone=1) + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([0,0,0,0,0,0]) + self.set_invert_iq(1) + self.reset_ptr_rx() + self.set_freq(helium.DOWNFREQ)#915) + self.set_spreading_factor(7)#12) + self.set_bw(9) #500Khz + self.set_rx_crc(False)#TRUE + self.set_mode(MODE.RXCONT) + + def setup_tx(self): + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([1,0,0,0,0,0]) + self.set_freq(helium.UPFREQ) + self.set_pa_config(pa_select=1) + self.set_spreading_factor(7) + self.set_pa_config(max_power=0x0F, output_power=0x0E) + self.set_sync_word(0x34) + self.set_rx_crc(True) + self.get_all_registers() + assert(self.get_agc_auto_on() == 1) + + def start(self): + lorawan = LoRaWAN.new(keys.appkey) + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': [randrange(256), randrange(256)]}) + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + sleep(10) diff --git a/run.py b/run.py index d9532b8..52d77ed 100644 --- a/run.py +++ b/run.py @@ -38,7 +38,6 @@ try: print("Sending LoRaWAN join request\n") lora.otaa() - time.sleep(10) lora.set_mode(MODE.SLEEP) print(lora) except KeyboardInterrupt: diff --git a/transactor.py b/transactor.py new file mode 100755 index 0000000..4df6590 --- /dev/null +++ b/transactor.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 + +import os +import re +import json +import datetime +from time import sleep +from random import randrange + +from SX127x.LoRa import LoRa, MODE +from SX127x.board_config_ada import BOARD +import LoRaWAN +from LoRaWAN.MHDR import MHDR +import shortuuid + +import helium +import keys +BOARD.setup() +class HeliumTransactor(LoRa): + def __init__(self, verbose = False, ack=True, start_ping=False): + super(HeliumLoRa, self).__init__(verbose) + self.iter = 0 + self.uuid = shortuuid.uuid() + self.ack = ack + self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} + self.last_tx = datetime.datetime.fromtimestamp(0) + self.last_message = None + self.transact_timeout = 5 + self.is_otaaing = False + + def otaa(self): + print(self) + self.is_otaaing = True + self.setup_tx() + lorawan = LoRaWAN.new(keys.appkey) + devnonce = [randrange(256), randrange(256)] + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + sleep(10) + + def on_rx_done(self): + print("Raw payload: {}".format(payload)) + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + decoded = "".join(list(map(chr, lorawan.get_payload()))) + self.last_message = decoded + self.test_status["last_message"] = decoded + self.test_status["ping_count"] += 1 + print("Decoded: {}".format(decoded)) + print("\n") + if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: + print("Unconfirmed data down.") + downlink = decoded + res = lorawan.mac_payload.get_fhdr().get_fctrl() + if 0x20 & res != 0: # Check Ack bit. + print("Server ack") + if len(downlink) == 0: + downlink = "Server ack" + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: + print("Confirmed data down.") + self.ack = True + downlink = decoded + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: + print("Confirmed data up.") + downlink = decoded + else: + print("Other packet.") + downlink = '' + self.set_mode(MODE.STDBY) + s = '' + s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() + s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() + s += " rssi_value %d\n" % self.get_rssi_value() + s += " msg: %s" % downlink + print(s) + + def increment(self): + self.tx_counter += 1 + data_file = open("frame.txt", "w") + data_file.write(f'frame = {self.tx_counter:d}\n') + data_file.close() + + def tx(self, msg, conf=False): + if conf: + data = MHDR.CONF_DATA_UP + print('Sending confirmed data up.') + else: + data = MHDR.UNCONF_DATA_UP + print('Sending unconfirmed data up.') + self.increment() + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + if self.ack: + print('Sending with Ack') + lorawan.create(data, dict(**base, **{'ack':True})) + self.ack = False + else: + print('Sending without Ack') + lorawan.create(data, base) + print(f"tx: {lorawan.to_raw()}") + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + + def set_frame(self,frame): + self.tx_counter = frame + + def setup_tx(self): + # Setup + # self.set_mode(MODE.SLEEP) + # self.set_dio_mapping([1,0,0,0,0,0]) + # self.set_freq(helium.UPFREQ) + # if not self.is_otaaing: + # self.set_bw(7) + # else: + # self.set_pa_config(pa_select=1) + # self.set_spreading_factor(7) + # self.set_pa_config(max_power=0x0F, output_power=0x0E) + # self.set_sync_word(0x34) + # self.set_rx_crc(True) + # if not self.is_otaaing: + # self.set_invert_iq(0) + # else: + # self.get_all_registers() + # assert(self.get_agc_auto_on() == 1) + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([1,0,0,0,0,0]) + self.set_freq(helium.UPFREQ) + self.set_pa_config(pa_select=1) + self.set_spreading_factor(7) + self.set_pa_config(max_power=0x0F, output_power=0x0E) + self.set_sync_word(0x34) + self.set_rx_crc(True) + self.get_all_registers() + print(self) + assert(self.get_agc_auto_on() == 1) + + def on_tx_done(self): + self.clear_irq_flags(TxDone=1) + print("TxDone") + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([0,0,0,0,0,0]) + self.set_invert_iq(1) + self.reset_ptr_rx() + self.set_freq(helium.DOWNFREQ)#915) + self.set_spreading_factor(7)#12) + self.set_bw(9) #500Khz + self.set_rx_crc(False)#TRUE + self.set_mode(MODE.RXCONT) + # self.clear_irq_flags(TxDone=1) + # self.set_mode(MODE.SLEEP) + # self.set_dio_mapping([0,0,0,0,0,0]) + # self.set_freq(helium.DOWNFREQ) + # self.set_bw(9) + # self.set_spreading_factor(7) + # self.set_pa_config(pa_select=1) + # if not self.is_otaaing: + # self.set_sync_word(0x34) + # self.set_rx_crc(False) + # self.set_invert_iq(1) + # self.reset_ptr_rx() + # self.set_mode(MODE.RXCONT) + + def transact(self, msg): + self.setup_tx() + self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) + self.iter = self.iter+1 + self.last_tx = datetime.datetime.now() + while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: + sleep(0.1) + return self.last_message + + def stop(self): + self.set_mode(MODE.SLEEP) + BOARD.teardown() + + def init_frame(self): + frame = 0 + if os.path.exists('frame.txt'): + with open('frame.txt') as df: + for line in df: + if m := re.match('^frame\s*=\s*(\d+)', line): + frame = int(m.group(1)) + self.set_frame(frame) + + @classmethod + def init(cls, verbose=False, ack=True, start_ping=False): + lora = cls(verbose, ack, start_ping) + lora.init_frame() + return lora From 25f414d2003cd8cd0acee48f2edba713a9c3ab96 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:12:55 -0700 Subject: [PATCH 062/130] updates --- helium_authenticator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index cbd434e..9192c16 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -15,7 +15,7 @@ BOARD.setup() class HeliumAuthenticator(LoRa): def __init__(self, verbose = False): - super(LoRaWANotaa, self).__init__(verbose) + super(HeliumAuthenticator, self).__init__(verbose) self.authenticated = False self.devaddr = None self.nwskey = None From 4457e335fbdd5061721974549375a03d7eb407fa Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:14:37 -0700 Subject: [PATCH 063/130] updates --- helium_authenticator.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/helium_authenticator.py b/helium_authenticator.py index 9192c16..c50ce06 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -22,17 +22,33 @@ def __init__(self, verbose = False): self.appskey = None def on_rx_done(self): + print("RxDone") + self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) + print(payload) self.set_mode(MODE.SLEEP) self.get_all_registers() + print(self) lorawan = LoRaWAN.new([], keys.appkey) lorawan.read(payload) + print(lorawan.get_payload()) + print(lorawan.get_mhdr().get_mversion()) + if lorawan.get_mhdr().get_mtype() == MHDR.JOIN_ACCEPT: self.devaddr = lorawan.get_devaddr() self.nwskey = lorawan.derive_nwskey(devnonce) self.appskey = lorawan.derive_appskey(devnonce) self.authenticated = True + print("Got LoRaWAN join accept. Paste these values into keys.py") + print(lorawan.valid_mic()) + print("devaddr = {}".format(lorawan.get_devaddr())) + print("nwskey = {}".format(lorawan.derive_nwskey(devnonce))) + print("appskey = {}".format(lorawan.derive_appskey(devnonce))) + print("\n") + sys.exit(0) + + print("Got LoRaWAN message continue listen for join accept") def on_tx_done(self): self.clear_irq_flags(TxDone=1) From 0f7095a229026784e0dc0913f8346bbc46e7a3c0 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:16:45 -0700 Subject: [PATCH 064/130] updates --- helium_authenticator.py | 1 + run.py | 137 +++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 58 deletions(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index c50ce06..a76394d 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -75,6 +75,7 @@ def setup_tx(self): assert(self.get_agc_auto_on() == 1) def start(self): + self.setup_tx() lorawan = LoRaWAN.new(keys.appkey) lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': [randrange(256), randrange(256)]}) self.write_payload(lorawan.to_raw()) diff --git a/run.py b/run.py index 52d77ed..73fbbd6 100644 --- a/run.py +++ b/run.py @@ -1,43 +1,13 @@ -import sys -import time - -import adafruit_ssd1306 from SX127x.LoRa import LoRa, MODE -from digitalio import DigitalInOut, Direction, Pull from SX127x.board_config_ada import BOARD -import board -import busio - -from helium_lora import HeliumLoRa - -# Button A -btnA = DigitalInOut(board.D5) -btnA.direction = Direction.INPUT -btnA.pull = Pull.UP +from helium_authenticator import HeliumAuthenticator -# Button B -btnB = DigitalInOut(board.D6) -btnB.direction = Direction.INPUT -btnB.pull = Pull.UP +lora = HeliumAuthenticator(True) -# Button C -btnC = DigitalInOut(board.D12) -btnC.direction = Direction.INPUT -btnC.pull = Pull.UP -# Create the I2C interface. -i2c = busio.I2C(board.SCL, board.SDA) - -# 128x32 OLED Display -reset_pin = DigitalInOut(board.D4) -display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) -# Clear the display. -width = display.width -height = display.height -lora = HeliumLoRa.init(True, True, True) try: print("Sending LoRaWAN join request\n") - lora.otaa() + lora.start() lora.set_mode(MODE.SLEEP) print(lora) except KeyboardInterrupt: @@ -47,29 +17,80 @@ sys.stdout.flush() lora.set_mode(MODE.SLEEP) BOARD.teardown() -# def run(): -# lora = HeliumLoRa.init() -# if not keys.nwskey: -# devaddr, nwskey, appskey = lora.otaa() -# while True: -# time.sleep(.1) -# display.fill(0) -# display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) -# display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) -# display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) -# display.show() -# if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: -# lora.transact("Test") -# if not btnA.value: -# lora.test_status["running_ping"] = True -# if not btnB.value: -# lora.test_status["running_ping"] = False -# if not btnC.value: -# display.fill(0) -# display.text("Test is shut down!", 0, 0, 1) -# display.text('Must restart PI to', 0, 10, 1) -# display.text('restart test.', 0, 20, 1) -# display.show() -# raise KeyboardInterrupt + +# +# import sys +# import time +# +# import adafruit_ssd1306 +# from SX127x.LoRa import LoRa, MODE +# from digitalio import DigitalInOut, Direction, Pull +# from SX127x.board_config_ada import BOARD +# import board +# import busio +# +# from helium_lora import HeliumLoRa +# +# # Button A +# btnA = DigitalInOut(board.D5) +# btnA.direction = Direction.INPUT +# btnA.pull = Pull.UP +# +# # Button B +# btnB = DigitalInOut(board.D6) +# btnB.direction = Direction.INPUT +# btnB.pull = Pull.UP +# +# # Button C +# btnC = DigitalInOut(board.D12) +# btnC.direction = Direction.INPUT +# btnC.pull = Pull.UP +# +# # Create the I2C interface. +# i2c = busio.I2C(board.SCL, board.SDA) # -# run() \ No newline at end of file +# # 128x32 OLED Display +# reset_pin = DigitalInOut(board.D4) +# display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) +# # Clear the display. +# width = display.width +# height = display.height +# lora = HeliumLoRa.init(True, True, True) +# try: +# print("Sending LoRaWAN join request\n") +# lora.otaa() +# lora.set_mode(MODE.SLEEP) +# print(lora) +# except KeyboardInterrupt: +# sys.stdout.flush() +# print("\nKeyboardInterrupt") +# finally: +# sys.stdout.flush() +# lora.set_mode(MODE.SLEEP) +# BOARD.teardown() +# # def run(): +# # lora = HeliumLoRa.init() +# # if not keys.nwskey: +# # devaddr, nwskey, appskey = lora.otaa() +# # while True: +# # time.sleep(.1) +# # display.fill(0) +# # display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) +# # display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) +# # display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) +# # display.show() +# # if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: +# # lora.transact("Test") +# # if not btnA.value: +# # lora.test_status["running_ping"] = True +# # if not btnB.value: +# # lora.test_status["running_ping"] = False +# # if not btnC.value: +# # display.fill(0) +# # display.text("Test is shut down!", 0, 0, 1) +# # display.text('Must restart PI to', 0, 10, 1) +# # display.text('restart test.', 0, 20, 1) +# # display.show() +# # raise KeyboardInterrupt +# # +# # run() \ No newline at end of file From a308be63da47e25900d9b228c7c2b3eb81189187 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:19:25 -0700 Subject: [PATCH 065/130] updates --- helium_authenticator.py | 11 ++++++----- run.py | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index a76394d..ead5e3b 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -20,6 +20,7 @@ def __init__(self, verbose = False): self.devaddr = None self.nwskey = None self.appskey = None + self.devnonce = [randrange(256), randrange(256)] def on_rx_done(self): print("RxDone") @@ -37,14 +38,14 @@ def on_rx_done(self): if lorawan.get_mhdr().get_mtype() == MHDR.JOIN_ACCEPT: self.devaddr = lorawan.get_devaddr() - self.nwskey = lorawan.derive_nwskey(devnonce) - self.appskey = lorawan.derive_appskey(devnonce) + self.nwskey = lorawan.derive_nwskey(self.devnonce) + self.appskey = lorawan.derive_appskey(self.devnonce) self.authenticated = True print("Got LoRaWAN join accept. Paste these values into keys.py") print(lorawan.valid_mic()) print("devaddr = {}".format(lorawan.get_devaddr())) - print("nwskey = {}".format(lorawan.derive_nwskey(devnonce))) - print("appskey = {}".format(lorawan.derive_appskey(devnonce))) + print("nwskey = {}".format(lorawan.derive_nwskey(self.devnonce))) + print("appskey = {}".format(lorawan.derive_appskey(self.devnonce))) print("\n") sys.exit(0) @@ -77,7 +78,7 @@ def setup_tx(self): def start(self): self.setup_tx() lorawan = LoRaWAN.new(keys.appkey) - lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': [randrange(256), randrange(256)]}) + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': self.devnonce}) self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) diff --git a/run.py b/run.py index 73fbbd6..0adcbfe 100644 --- a/run.py +++ b/run.py @@ -1,3 +1,4 @@ +import sys from SX127x.LoRa import LoRa, MODE from SX127x.board_config_ada import BOARD from helium_authenticator import HeliumAuthenticator From fa347a3f977529692a3724a9b7725a15fc7fca96 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 13:21:52 -0700 Subject: [PATCH 066/130] updates --- helium_authenticator.py | 26 ++++++++++++++++++-------- run.py | 20 +------------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index ead5e3b..3ef14fd 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -41,14 +41,6 @@ def on_rx_done(self): self.nwskey = lorawan.derive_nwskey(self.devnonce) self.appskey = lorawan.derive_appskey(self.devnonce) self.authenticated = True - print("Got LoRaWAN join accept. Paste these values into keys.py") - print(lorawan.valid_mic()) - print("devaddr = {}".format(lorawan.get_devaddr())) - print("nwskey = {}".format(lorawan.derive_nwskey(self.devnonce))) - print("appskey = {}".format(lorawan.derive_appskey(self.devnonce))) - print("\n") - sys.exit(0) - print("Got LoRaWAN message continue listen for join accept") def on_tx_done(self): @@ -82,3 +74,21 @@ def start(self): self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) + + @classmethod + def authenticate(cls): + lora = cls(True) + try: + print("Sending LoRaWAN join request\n") + lora.start() + lora.set_mode(MODE.SLEEP) + print(lora) + except KeyboardInterrupt: + sys.stdout.flush() + print("\nKeyboardInterrupt") + finally: + sys.stdout.flush() + lora.set_mode(MODE.SLEEP) + BOARD.teardown() + return {"devaddr": lora.devaddr, "nwskey": lora.nwskey, "appskey": lora.appskey} + \ No newline at end of file diff --git a/run.py b/run.py index 0adcbfe..747768f 100644 --- a/run.py +++ b/run.py @@ -1,23 +1,5 @@ -import sys -from SX127x.LoRa import LoRa, MODE -from SX127x.board_config_ada import BOARD from helium_authenticator import HeliumAuthenticator - -lora = HeliumAuthenticator(True) - - -try: - print("Sending LoRaWAN join request\n") - lora.start() - lora.set_mode(MODE.SLEEP) - print(lora) -except KeyboardInterrupt: - sys.stdout.flush() - print("\nKeyboardInterrupt") -finally: - sys.stdout.flush() - lora.set_mode(MODE.SLEEP) - BOARD.teardown() +print(HeliumAuthenticator.authenticate()) # # import sys From ee1b6d315d5723f0541846796f661b123e18fec4 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:38:46 -0700 Subject: [PATCH 067/130] updates --- helium.py | 11 ++- helium_authenticator.py | 6 +- helium_helper.py | 2 + helium_transactor.py | 158 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 helium_helper.py create mode 100755 helium_transactor.py diff --git a/helium.py b/helium.py index bb349a8..e0b1d50 100644 --- a/helium.py +++ b/helium.py @@ -1,2 +1,9 @@ -UPFREQ = 903.9 -DOWNFREQ = 923.3 \ No newline at end of file +from helium_authenticator import HeliumAuthenticator +from helium_transactor import HeliumTransactor +print(HeliumAuthenticator.authenticate()) + +class Helium: + + @classmethod + def run() + if HeliumAuthenticator.authenticate() \ No newline at end of file diff --git a/helium_authenticator.py b/helium_authenticator.py index 3ef14fd..7f2c986 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -9,7 +9,7 @@ from LoRaWAN.MHDR import MHDR from random import randrange import reset_ada -import helium +import helium_helper import keys BOARD.setup() @@ -49,7 +49,7 @@ def on_tx_done(self): self.set_dio_mapping([0,0,0,0,0,0]) self.set_invert_iq(1) self.reset_ptr_rx() - self.set_freq(helium.DOWNFREQ)#915) + self.set_freq(helium_helper.DOWNFREQ)#915) self.set_spreading_factor(7)#12) self.set_bw(9) #500Khz self.set_rx_crc(False)#TRUE @@ -58,7 +58,7 @@ def on_tx_done(self): def setup_tx(self): self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium.UPFREQ) + self.set_freq(helium_helper.UPFREQ) self.set_pa_config(pa_select=1) self.set_spreading_factor(7) self.set_pa_config(max_power=0x0F, output_power=0x0E) diff --git a/helium_helper.py b/helium_helper.py new file mode 100644 index 0000000..bb349a8 --- /dev/null +++ b/helium_helper.py @@ -0,0 +1,2 @@ +UPFREQ = 903.9 +DOWNFREQ = 923.3 \ No newline at end of file diff --git a/helium_transactor.py b/helium_transactor.py new file mode 100755 index 0000000..5513117 --- /dev/null +++ b/helium_transactor.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 + +import os +import re +import json +import datetime +from time import sleep +from random import randrange + +from SX127x.LoRa import LoRa, MODE +from SX127x.board_config_ada import BOARD +import LoRaWAN +from LoRaWAN.MHDR import MHDR +import shortuuid + +import helium_helper +import keys +BOARD.setup() +class HeliumTransactor(LoRa): + def __init__(self, verbose = False, ack=True, start_ping=False): + super(HeliumLoRa, self).__init__(verbose) + self.iter = 0 + self.uuid = shortuuid.uuid() + self.ack = ack + self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} + self.last_tx = datetime.datetime.fromtimestamp(0) + self.last_message = None + self.transact_timeout = 5 + self.is_otaaing = False + + def otaa(self): + print(self) + self.is_otaaing = True + self.setup_tx() + lorawan = LoRaWAN.new(keys.appkey) + devnonce = [randrange(256), randrange(256)] + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + sleep(10) + + def on_rx_done(self): + print("Raw payload: {}".format(payload)) + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + decoded = "".join(list(map(chr, lorawan.get_payload()))) + self.last_message = decoded + self.test_status["last_message"] = decoded + self.test_status["ping_count"] += 1 + print("Decoded: {}".format(decoded)) + print("\n") + if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: + print("Unconfirmed data down.") + downlink = decoded + res = lorawan.mac_payload.get_fhdr().get_fctrl() + if 0x20 & res != 0: # Check Ack bit. + print("Server ack") + if len(downlink) == 0: + downlink = "Server ack" + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: + print("Confirmed data down.") + self.ack = True + downlink = decoded + elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: + print("Confirmed data up.") + downlink = decoded + else: + print("Other packet.") + downlink = '' + self.set_mode(MODE.STDBY) + s = '' + s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() + s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() + s += " rssi_value %d\n" % self.get_rssi_value() + s += " msg: %s" % downlink + print(s) + + def increment(self): + self.tx_counter += 1 + data_file = open("frame.txt", "w") + data_file.write(f'frame = {self.tx_counter:d}\n') + data_file.close() + + def tx(self, msg, conf=False): + if conf: + data = MHDR.CONF_DATA_UP + print('Sending confirmed data up.') + else: + data = MHDR.UNCONF_DATA_UP + print('Sending unconfirmed data up.') + self.increment() + lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + if self.ack: + print('Sending with Ack') + lorawan.create(data, dict(**base, **{'ack':True})) + self.ack = False + else: + print('Sending without Ack') + lorawan.create(data, base) + print(f"tx: {lorawan.to_raw()}") + self.write_payload(lorawan.to_raw()) + self.set_mode(MODE.TX) + + def set_frame(self,frame): + self.tx_counter = frame + + def setup_tx(self): + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([1,0,0,0,0,0]) + self.set_freq(helium_helper.UPFREQ) + self.set_pa_config(pa_select=1) + self.set_spreading_factor(7) + self.set_pa_config(max_power=0x0F, output_power=0x0E) + self.set_sync_word(0x34) + self.set_rx_crc(True) + self.get_all_registers() + assert(self.get_agc_auto_on() == 1) + + def on_tx_done(self): + self.clear_irq_flags(TxDone=1) + self.set_mode(MODE.SLEEP) + self.set_dio_mapping([0,0,0,0,0,0]) + self.set_freq(helium_helper.DOWNFREQ) + self.set_bw(9) + self.set_spreading_factor(7) + self.set_pa_config(pa_select=1) + self.set_rx_crc(False) + self.set_invert_iq(1) + self.reset_ptr_rx() + self.set_mode(MODE.RXCONT) + + def transact(self, msg): + self.setup_tx() + self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) + self.iter = self.iter+1 + self.last_tx = datetime.datetime.now() + while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: + sleep(0.1) + return self.last_message + + def stop(self): + self.set_mode(MODE.SLEEP) + BOARD.teardown() + + def init_frame(self): + frame = 0 + if os.path.exists('frame.txt'): + with open('frame.txt') as df: + for line in df: + if m := re.match('^frame\s*=\s*(\d+)', line): + frame = int(m.group(1)) + self.set_frame(frame) + + @classmethod + def init(cls, verbose=False, ack=True, start_ping=False): + lora = cls(verbose, ack, start_ping) + lora.init_frame() + return lora From 9fd0704f7c0b0afcb23c72900a0e117abb96b798 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:56:25 -0700 Subject: [PATCH 068/130] updates --- helium.py | 27 +++++++-- helium_transactor.py | 18 +----- keys.py | 34 ++++++++--- run.py | 140 +++++++++++++++++++------------------------ 4 files changed, 112 insertions(+), 107 deletions(-) diff --git a/helium.py b/helium.py index e0b1d50..32e678f 100644 --- a/helium.py +++ b/helium.py @@ -1,9 +1,26 @@ +import requests from helium_authenticator import HeliumAuthenticator -from helium_transactor import HeliumTransactor +from helium_transactor import keys, HeliumTransactor print(HeliumAuthenticator.authenticate()) class Helium: - - @classmethod - def run() - if HeliumAuthenticator.authenticate() \ No newline at end of file + def authenticate(self): + authentication = HeliumAuthenticator.authenticate() + keys.write(dict(**self.keys, **authentication)) + return authentication + + def register_device(self): + # if we have never seen the device, build some ... machinery and APIs etc to register this device. + # response = requests.get("http://somewebsite.com/register_device.json"+some_authentication_information) + return None + + def __init__(self): + self.keys = keys.get_keys() + if not self.keys.get("deveui"): + self.register_device() + if not self.keys.get("nwskey"): + self.authenticate() + helium_keys = passed_keys or keys.get_keys() + self.ht = HeliumTransactor(verbose, helium_keys) + + \ No newline at end of file diff --git a/helium_transactor.py b/helium_transactor.py index 5513117..54d31e8 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -17,27 +17,15 @@ import keys BOARD.setup() class HeliumTransactor(LoRa): - def __init__(self, verbose = False, ack=True, start_ping=False): + def __init__(self, verbose=False, keys=keys.get_keys()): super(HeliumLoRa, self).__init__(verbose) self.iter = 0 self.uuid = shortuuid.uuid() - self.ack = ack - self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} + self.ack = True + self.test_status = {"ping_count": 0, "last_message": None} self.last_tx = datetime.datetime.fromtimestamp(0) self.last_message = None self.transact_timeout = 5 - self.is_otaaing = False - - def otaa(self): - print(self) - self.is_otaaing = True - self.setup_tx() - lorawan = LoRaWAN.new(keys.appkey) - devnonce = [randrange(256), randrange(256)] - lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - sleep(10) def on_rx_done(self): print("Raw payload: {}".format(payload)) diff --git a/keys.py b/keys.py index fda4056..353a9af 100644 --- a/keys.py +++ b/keys.py @@ -7,14 +7,30 @@ dotenv.load_dotenv() # Get these values from console.helium.com under Device Details. -deveui = bytes.fromhex(os.environ.get('deveui', '')) -appeui = bytes.fromhex(os.environ.get('appeui', '')) -appkey = bytes.fromhex(os.environ.get('appkey', '')) - -if not (deveui and appeui and appkey): - raise RuntimeError("sorry, need device keys before running.") +key_path = os.environ.get('key_path', 'keys.json') +filekeys = json.loads(open('keys.json').read()) +deveui = bytes.fromhex(os.environ.get('deveui', filekeys.get('deveui', ''))) +appeui = bytes.fromhex(os.environ.get('appeui', filekeys.get('appeui', ''))) +appkey = bytes.fromhex(os.environ.get('appkey', filekeys.get('appkey', ''))) # Fill in these values when you activate the device with otaa_helium.py. -devaddr = json.loads(os.environ.get('devaddr', '[]')) -nwskey = json.loads(os.environ.get('nwskey', '[]')) -appskey = json.loads(os.environ.get('appskey', '[]')) +devaddr = json.loads(os.environ.get('devaddr', filekeys.get('devaddr', '[]'))) +nwskey = json.loads(os.environ.get('nwskey', filekeys.get('nwskey', '[]'))) +appskey = json.loads(os.environ.get('appskey', filekeys.get('appskey', '[]'))) + +def get_keys(): + return { + "deveui": deveui, + "appeui": appeui, + "appkey": appkey, + "devaddr": devaddr, + "nwskey": nwskey, + "appskey": appskey, + + } + +def write(keys, path=key_path): + f = open(path, 'w') + f.write(json.dumps(keys)) + f.close() + \ No newline at end of file diff --git a/run.py b/run.py index 747768f..e723f59 100644 --- a/run.py +++ b/run.py @@ -1,79 +1,63 @@ -from helium_authenticator import HeliumAuthenticator -print(HeliumAuthenticator.authenticate()) +import sys +import time +import datetime -# -# import sys -# import time -# -# import adafruit_ssd1306 -# from SX127x.LoRa import LoRa, MODE -# from digitalio import DigitalInOut, Direction, Pull -# from SX127x.board_config_ada import BOARD -# import board -# import busio -# -# from helium_lora import HeliumLoRa -# -# # Button A -# btnA = DigitalInOut(board.D5) -# btnA.direction = Direction.INPUT -# btnA.pull = Pull.UP -# -# # Button B -# btnB = DigitalInOut(board.D6) -# btnB.direction = Direction.INPUT -# btnB.pull = Pull.UP -# -# # Button C -# btnC = DigitalInOut(board.D12) -# btnC.direction = Direction.INPUT -# btnC.pull = Pull.UP -# -# # Create the I2C interface. -# i2c = busio.I2C(board.SCL, board.SDA) -# -# # 128x32 OLED Display -# reset_pin = DigitalInOut(board.D4) -# display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) -# # Clear the display. -# width = display.width -# height = display.height -# lora = HeliumLoRa.init(True, True, True) -# try: -# print("Sending LoRaWAN join request\n") -# lora.otaa() -# lora.set_mode(MODE.SLEEP) -# print(lora) -# except KeyboardInterrupt: -# sys.stdout.flush() -# print("\nKeyboardInterrupt") -# finally: -# sys.stdout.flush() -# lora.set_mode(MODE.SLEEP) -# BOARD.teardown() -# # def run(): -# # lora = HeliumLoRa.init() -# # if not keys.nwskey: -# # devaddr, nwskey, appskey = lora.otaa() -# # while True: -# # time.sleep(.1) -# # display.fill(0) -# # display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) -# # display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) -# # display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) -# # display.show() -# # if lora.test_status["running_ping"] and (datetime.datetime.now() - lora.last_test).seconds > 5: -# # lora.transact("Test") -# # if not btnA.value: -# # lora.test_status["running_ping"] = True -# # if not btnB.value: -# # lora.test_status["running_ping"] = False -# # if not btnC.value: -# # display.fill(0) -# # display.text("Test is shut down!", 0, 0, 1) -# # display.text('Must restart PI to', 0, 10, 1) -# # display.text('restart test.', 0, 20, 1) -# # display.show() -# # raise KeyboardInterrupt -# # -# # run() \ No newline at end of file +import adafruit_ssd1306 +from SX127x.LoRa import LoRa, MODE +from digitalio import DigitalInOut, Direction, Pull +from SX127x.board_config_ada import BOARD +import board +import busio + +from helium import Helium +# Button A +btnA = DigitalInOut(board.D5) +btnA.direction = Direction.INPUT +btnA.pull = Pull.UP + +# Button B +btnB = DigitalInOut(board.D6) +btnB.direction = Direction.INPUT +btnB.pull = Pull.UP + +# Button C +btnC = DigitalInOut(board.D12) +btnC.direction = Direction.INPUT +btnC.pull = Pull.UP + +# Create the I2C interface. +i2c = busio.I2C(board.SCL, board.SDA) + +# 128x32 OLED Display +reset_pin = DigitalInOut(board.D4) +display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) +# Clear the display. +width = display.width +height = display.height + +def run(): + helium = Helium() + running_ping = False + last_test = datetime.datetime.fromtimestamp(0) + while True: + time.sleep(.1) + display.fill(0) + display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) + display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) + display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) + display.show() + if running_ping and (datetime.datetime.now() - last_test).seconds > 5: + helium.transact("Test") + if not btnA.value: + running_ping = True + if not btnB.value: + running_ping = False + if not btnC.value: + display.fill(0) + display.text("Test is shut down!", 0, 0, 1) + display.text('Must restart PI to', 0, 10, 1) + display.text('restart test.', 0, 20, 1) + display.show() + raise KeyboardInterrupt + +run() \ No newline at end of file From fde444482fbb99dda28eb97ccc45cd3086678963 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:57:23 -0700 Subject: [PATCH 069/130] updates --- keys.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/keys.py b/keys.py index 353a9af..ba74a39 100644 --- a/keys.py +++ b/keys.py @@ -8,7 +8,11 @@ # Get these values from console.helium.com under Device Details. key_path = os.environ.get('key_path', 'keys.json') -filekeys = json.loads(open('keys.json').read()) +if os.path.exists(key_path): + filekeys = json.loads(open(key_path).read()) +else: + filekeys = {} + deveui = bytes.fromhex(os.environ.get('deveui', filekeys.get('deveui', ''))) appeui = bytes.fromhex(os.environ.get('appeui', filekeys.get('appeui', ''))) appkey = bytes.fromhex(os.environ.get('appkey', filekeys.get('appkey', ''))) From a32a8e2579b11c029aeb426eeb0d1f789cc0c34f Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:57:59 -0700 Subject: [PATCH 070/130] updates --- helium.py | 1 - 1 file changed, 1 deletion(-) diff --git a/helium.py b/helium.py index 32e678f..64c5c86 100644 --- a/helium.py +++ b/helium.py @@ -1,7 +1,6 @@ import requests from helium_authenticator import HeliumAuthenticator from helium_transactor import keys, HeliumTransactor -print(HeliumAuthenticator.authenticate()) class Helium: def authenticate(self): From 280722bcb62dd0da72d048ca5a098a340b2b0a79 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:58:39 -0700 Subject: [PATCH 071/130] updates --- helium.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium.py b/helium.py index 64c5c86..388b1ae 100644 --- a/helium.py +++ b/helium.py @@ -13,7 +13,7 @@ def register_device(self): # response = requests.get("http://somewebsite.com/register_device.json"+some_authentication_information) return None - def __init__(self): + def __init__(self, passed_keys=None, verbose=False): self.keys = keys.get_keys() if not self.keys.get("deveui"): self.register_device() From fc47b5130c7931a19c6131668bf8c9d2fe9df3e2 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 14:59:21 -0700 Subject: [PATCH 072/130] updates --- helium_transactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index 54d31e8..cd1c868 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -18,7 +18,7 @@ BOARD.setup() class HeliumTransactor(LoRa): def __init__(self, verbose=False, keys=keys.get_keys()): - super(HeliumLoRa, self).__init__(verbose) + super(HeliumTransactor, self).__init__(verbose) self.iter = 0 self.uuid = shortuuid.uuid() self.ack = True From 64364700634a1b0a338d31b5763d4eebb513ef43 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:01:51 -0700 Subject: [PATCH 073/130] updates --- helium.py | 5 ++++- run.py | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/helium.py b/helium.py index 388b1ae..50375d0 100644 --- a/helium.py +++ b/helium.py @@ -12,7 +12,10 @@ def register_device(self): # if we have never seen the device, build some ... machinery and APIs etc to register this device. # response = requests.get("http://somewebsite.com/register_device.json"+some_authentication_information) return None - + + def get_last_message(self): + return self.ht.last_message + def __init__(self, passed_keys=None, verbose=False): self.keys = keys.get_keys() if not self.keys.get("deveui"): diff --git a/run.py b/run.py index e723f59..d2fc73c 100644 --- a/run.py +++ b/run.py @@ -39,15 +39,17 @@ def run(): helium = Helium() running_ping = False last_test = datetime.datetime.fromtimestamp(0) + ping_count = 0 while True: time.sleep(.1) display.fill(0) - display.text("Test is "+str(lora.test_status["running_ping"]), 0, 0, 1) - display.text('Time: '+str(lora.test_status["last_message"]), 0, 10, 1) - display.text('Total Pings: '+str(lora.test_status["ping_count"]), 0, 20, 1) + display.text("Test is "+str(running_ping), 0, 0, 1) + display.text('Time: '+str(helium.get_last_message()), 0, 10, 1) + display.text('Total Pings: '+str(ping_count), 0, 20, 1) display.show() if running_ping and (datetime.datetime.now() - last_test).seconds > 5: helium.transact("Test") + ping_count += 1 if not btnA.value: running_ping = True if not btnB.value: From 3216c844a1df9e3b866d507e6272ec11e5ba2faf Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:46:20 -0700 Subject: [PATCH 074/130] updates --- helium.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/helium.py b/helium.py index 50375d0..7a2853d 100644 --- a/helium.py +++ b/helium.py @@ -16,6 +16,9 @@ def register_device(self): def get_last_message(self): return self.ht.last_message + def transact(self, msg): + return self.ht.transact(msg) + def __init__(self, passed_keys=None, verbose=False): self.keys = keys.get_keys() if not self.keys.get("deveui"): From aa64bfc313f535c8fd961efb802647ffadb0171e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:48:41 -0700 Subject: [PATCH 075/130] updates --- helium.py | 2 +- helium_transactor.py | 4 ++-- run.py | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/helium.py b/helium.py index 7a2853d..03a027b 100644 --- a/helium.py +++ b/helium.py @@ -26,6 +26,6 @@ def __init__(self, passed_keys=None, verbose=False): if not self.keys.get("nwskey"): self.authenticate() helium_keys = passed_keys or keys.get_keys() - self.ht = HeliumTransactor(verbose, helium_keys) + self.ht = HeliumTransactor.init(verbose, helium_keys) \ No newline at end of file diff --git a/helium_transactor.py b/helium_transactor.py index cd1c868..b221027 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -140,7 +140,7 @@ def init_frame(self): self.set_frame(frame) @classmethod - def init(cls, verbose=False, ack=True, start_ping=False): - lora = cls(verbose, ack, start_ping) + def init(cls, verbose=False, keys=keys.get_keys()): + lora = cls(verbose, keys) lora.init_frame() return lora diff --git a/run.py b/run.py index d2fc73c..445add2 100644 --- a/run.py +++ b/run.py @@ -10,6 +10,8 @@ import busio from helium import Helium +helium = Helium() +helium.transact("Test") # Button A btnA = DigitalInOut(board.D5) btnA.direction = Direction.INPUT @@ -37,6 +39,7 @@ def run(): helium = Helium() + helium.transact("Test") running_ping = False last_test = datetime.datetime.fromtimestamp(0) ping_count = 0 From 0398e810a5e59ca65b4755ea5be6ce0ae5c1a39a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:50:18 -0700 Subject: [PATCH 076/130] updates --- helium_transactor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helium_transactor.py b/helium_transactor.py index b221027..f8640e2 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -118,6 +118,7 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def transact(self, msg): + import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) self.iter = self.iter+1 From 6db76799acb8c22903561d4b0818fa92ed287e70 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:54:17 -0700 Subject: [PATCH 077/130] updates --- helium_authenticator.py | 2 +- helium_transactor.py | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index 7f2c986..ceb9759 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -12,7 +12,6 @@ import helium_helper import keys -BOARD.setup() class HeliumAuthenticator(LoRa): def __init__(self, verbose = False): super(HeliumAuthenticator, self).__init__(verbose) @@ -77,6 +76,7 @@ def start(self): @classmethod def authenticate(cls): + BOARD.setup() lora = cls(True) try: print("Sending LoRaWAN join request\n") diff --git a/helium_transactor.py b/helium_transactor.py index f8640e2..dc26f58 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -15,7 +15,6 @@ import helium_helper import keys -BOARD.setup() class HeliumTransactor(LoRa): def __init__(self, verbose=False, keys=keys.get_keys()): super(HeliumTransactor, self).__init__(verbose) @@ -26,10 +25,11 @@ def __init__(self, verbose=False, keys=keys.get_keys()): self.last_tx = datetime.datetime.fromtimestamp(0) self.last_message = None self.transact_timeout = 5 + self.keys = keys def on_rx_done(self): print("Raw payload: {}".format(payload)) - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) + lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) decoded = "".join(list(map(chr, lorawan.get_payload()))) self.last_message = decoded self.test_status["last_message"] = decoded @@ -76,8 +76,8 @@ def tx(self, msg, conf=False): data = MHDR.UNCONF_DATA_UP print('Sending unconfirmed data up.') self.increment() - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) + base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: print('Sending with Ack') lorawan.create(data, dict(**base, **{'ack':True})) @@ -142,6 +142,7 @@ def init_frame(self): @classmethod def init(cls, verbose=False, keys=keys.get_keys()): + BOARD.setup() lora = cls(verbose, keys) lora.init_frame() return lora From 6b1bee3d5807d20bc63497ad0d9e759f67902fbf Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:57:44 -0700 Subject: [PATCH 078/130] updates --- helium.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/helium.py b/helium.py index 03a027b..8e015ee 100644 --- a/helium.py +++ b/helium.py @@ -5,7 +5,10 @@ class Helium: def authenticate(self): authentication = HeliumAuthenticator.authenticate() - keys.write(dict(**self.keys, **authentication)) + cur_keys = self.keys + for k,v in authentication.items(): + cur_keys[k] = v + keys.write(cur_keys) return authentication def register_device(self): From 4b08aa22c48a6cceb7089046db381491e0517595 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 15:59:24 -0700 Subject: [PATCH 079/130] updates --- helium.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helium.py b/helium.py index 8e015ee..03fb2f1 100644 --- a/helium.py +++ b/helium.py @@ -5,6 +5,7 @@ class Helium: def authenticate(self): authentication = HeliumAuthenticator.authenticate() + import code;code.interact(local=dict(globals(), **locals())) cur_keys = self.keys for k,v in authentication.items(): cur_keys[k] = v From a89fbbf14a8377f69e93342c081d08a1dd7eb02d Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:04:58 -0700 Subject: [PATCH 080/130] updates --- helium_authenticator.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/helium_authenticator.py b/helium_authenticator.py index ceb9759..d5ad81a 100755 --- a/helium_authenticator.py +++ b/helium_authenticator.py @@ -13,13 +13,14 @@ import keys class HeliumAuthenticator(LoRa): - def __init__(self, verbose = False): + def __init__(self, verbose=False, keys=keys.get_keys()): super(HeliumAuthenticator, self).__init__(verbose) self.authenticated = False self.devaddr = None self.nwskey = None self.appskey = None self.devnonce = [randrange(256), randrange(256)] + self.keys = keys def on_rx_done(self): print("RxDone") @@ -30,7 +31,7 @@ def on_rx_done(self): self.set_mode(MODE.SLEEP) self.get_all_registers() print(self) - lorawan = LoRaWAN.new([], keys.appkey) + lorawan = LoRaWAN.new([], self.keys["appkey"]) lorawan.read(payload) print(lorawan.get_payload()) print(lorawan.get_mhdr().get_mversion()) @@ -68,8 +69,8 @@ def setup_tx(self): def start(self): self.setup_tx() - lorawan = LoRaWAN.new(keys.appkey) - lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': self.devnonce}) + lorawan = LoRaWAN.new(self.keys["appkey"]) + lorawan.create(MHDR.JOIN_REQUEST, {'deveui': self.keys["deveui"], 'appeui': self.keys["appeui"], 'devnonce': self.devnonce}) self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) sleep(10) From ab1868740d87c9a0cf9de3eea340323f8df66424 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:06:18 -0700 Subject: [PATCH 081/130] updates --- otaa_helium.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/otaa_helium.py b/otaa_helium.py index ad2e4db..116269b 100755 --- a/otaa_helium.py +++ b/otaa_helium.py @@ -9,7 +9,7 @@ from LoRaWAN.MHDR import MHDR from random import randrange import reset_ada -import helium +import helium_helper import keys BOARD.setup() @@ -50,7 +50,7 @@ def on_tx_done(self): self.set_dio_mapping([0,0,0,0,0,0]) self.set_invert_iq(1) self.reset_ptr_rx() - self.set_freq(helium.DOWNFREQ)#915) + self.set_freq(helium_helper.DOWNFREQ)#915) self.set_spreading_factor(7)#12) self.set_bw(9) #500Khz self.set_rx_crc(False)#TRUE @@ -76,7 +76,7 @@ def start(self): # Setup lora.set_mode(MODE.SLEEP) lora.set_dio_mapping([1,0,0,0,0,0]) -lora.set_freq(helium.UPFREQ) +lora.set_freq(helium_helper.UPFREQ) lora.set_pa_config(pa_select=1) lora.set_spreading_factor(7) lora.set_pa_config(max_power=0x0F, output_power=0x0E) From 877d84d22b11cc3f377a3e6df8bb071b40ea54f3 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:16:53 -0700 Subject: [PATCH 082/130] updates --- keys.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/keys.py b/keys.py index ba74a39..f45191d 100644 --- a/keys.py +++ b/keys.py @@ -34,7 +34,13 @@ def get_keys(): } def write(keys, path=key_path): + writable_keys = {} + for k,v in keys.items(): + if type(k) == bytes: + writable_keys[k] = cur_keys['deveui'].hex() + else: + writable_keys[k] = v f = open(path, 'w') - f.write(json.dumps(keys)) + f.write(json.dumps(writable_keys)) f.close() \ No newline at end of file From 4637abf38c99183f3975892d3cb81deed9164a6f Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:18:46 -0700 Subject: [PATCH 083/130] updates --- helium.py | 1 - keys.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/helium.py b/helium.py index 03fb2f1..8e015ee 100644 --- a/helium.py +++ b/helium.py @@ -5,7 +5,6 @@ class Helium: def authenticate(self): authentication = HeliumAuthenticator.authenticate() - import code;code.interact(local=dict(globals(), **locals())) cur_keys = self.keys for k,v in authentication.items(): cur_keys[k] = v diff --git a/keys.py b/keys.py index f45191d..7292e94 100644 --- a/keys.py +++ b/keys.py @@ -34,6 +34,7 @@ def get_keys(): } def write(keys, path=key_path): + import code;code.interact(local=dict(globals(), **locals())) writable_keys = {} for k,v in keys.items(): if type(k) == bytes: From e71677454a3665e3ff43ed2d1a9ddfa5fc7cfd86 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:20:43 -0700 Subject: [PATCH 084/130] updates --- keys.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keys.py b/keys.py index 7292e94..d6acca7 100644 --- a/keys.py +++ b/keys.py @@ -37,8 +37,8 @@ def write(keys, path=key_path): import code;code.interact(local=dict(globals(), **locals())) writable_keys = {} for k,v in keys.items(): - if type(k) == bytes: - writable_keys[k] = cur_keys['deveui'].hex() + if type(v) == bytes: + writable_keys[k] = keys[k].hex() else: writable_keys[k] = v f = open(path, 'w') From b50123a8525e0d6e3a90ede5b32219ea95fee02e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:22:29 -0700 Subject: [PATCH 085/130] updates --- helium_transactor.py | 1 - keys.py | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index dc26f58..f235bfa 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -118,7 +118,6 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def transact(self, msg): - import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) self.iter = self.iter+1 diff --git a/keys.py b/keys.py index d6acca7..6caa871 100644 --- a/keys.py +++ b/keys.py @@ -9,7 +9,11 @@ # Get these values from console.helium.com under Device Details. key_path = os.environ.get('key_path', 'keys.json') if os.path.exists(key_path): - filekeys = json.loads(open(key_path).read()) + contents = open(key_path).read() + if contents: + filekeys = json.loads(contents) + else: + filekeys = {} else: filekeys = {} @@ -34,7 +38,6 @@ def get_keys(): } def write(keys, path=key_path): - import code;code.interact(local=dict(globals(), **locals())) writable_keys = {} for k,v in keys.items(): if type(v) == bytes: From 603a8620c4d654e15915cb91d8cca7fd6adc76dd Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:23:13 -0700 Subject: [PATCH 086/130] updates --- keys.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keys.py b/keys.py index 6caa871..fbae677 100644 --- a/keys.py +++ b/keys.py @@ -43,7 +43,7 @@ def write(keys, path=key_path): if type(v) == bytes: writable_keys[k] = keys[k].hex() else: - writable_keys[k] = v + writable_keys[k] = json.dumps(v) f = open(path, 'w') f.write(json.dumps(writable_keys)) f.close() From 027a0427657c74585159436d1b4a3411a0e3a373 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:25:15 -0700 Subject: [PATCH 087/130] updates --- helium_transactor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index f235bfa..74083a3 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -118,8 +118,9 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def transact(self, msg): + import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() - self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) + self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg}), True) self.iter = self.iter+1 self.last_tx = datetime.datetime.now() while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: From a2b6566d68d7101090e5c043ed28e0cc542b9a91 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:27:26 -0700 Subject: [PATCH 088/130] updates --- helium_transactor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index 74083a3..51f0536 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -118,12 +118,11 @@ def on_tx_done(self): self.set_mode(MODE.RXCONT) def transact(self, msg): - import code;code.interact(local=dict(globals(), **locals())) self.setup_tx() self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg}), True) self.iter = self.iter+1 self.last_tx = datetime.datetime.now() - while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: + while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds < self.transact_timeout: sleep(0.1) return self.last_message From 85a10a6c9d3290146ca3b955dd585c61f0c4c476 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:28:36 -0700 Subject: [PATCH 089/130] updates --- helium_transactor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/helium_transactor.py b/helium_transactor.py index 51f0536..3c72779 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -28,6 +28,9 @@ def __init__(self, verbose=False, keys=keys.get_keys()): self.keys = keys def on_rx_done(self): + import code;code.interact(local=dict(globals(), **locals())) + self.clear_irq_flags(RxDone=1) + payload = self.read_payload(nocheck=True) print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) decoded = "".join(list(map(chr, lorawan.get_payload()))) From d910028adfb6110deab8fe81ba8020cf63a57636 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:29:29 -0700 Subject: [PATCH 090/130] updates --- helium_transactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index 3c72779..a227184 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -28,9 +28,9 @@ def __init__(self, verbose=False, keys=keys.get_keys()): self.keys = keys def on_rx_done(self): - import code;code.interact(local=dict(globals(), **locals())) self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) + import code;code.interact(local=dict(globals(), **locals())) print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) decoded = "".join(list(map(chr, lorawan.get_payload()))) From a97bedcf04016646ff44870236e3010bf19bdc4c Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:31:45 -0700 Subject: [PATCH 091/130] updates --- run.py | 129 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/run.py b/run.py index 445add2..b0b80be 100644 --- a/run.py +++ b/run.py @@ -1,68 +1,69 @@ -import sys -import time -import datetime - -import adafruit_ssd1306 -from SX127x.LoRa import LoRa, MODE -from digitalio import DigitalInOut, Direction, Pull -from SX127x.board_config_ada import BOARD -import board -import busio - from helium import Helium helium = Helium() helium.transact("Test") -# Button A -btnA = DigitalInOut(board.D5) -btnA.direction = Direction.INPUT -btnA.pull = Pull.UP - -# Button B -btnB = DigitalInOut(board.D6) -btnB.direction = Direction.INPUT -btnB.pull = Pull.UP - -# Button C -btnC = DigitalInOut(board.D12) -btnC.direction = Direction.INPUT -btnC.pull = Pull.UP - -# Create the I2C interface. -i2c = busio.I2C(board.SCL, board.SDA) - -# 128x32 OLED Display -reset_pin = DigitalInOut(board.D4) -display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) -# Clear the display. -width = display.width -height = display.height - -def run(): - helium = Helium() - helium.transact("Test") - running_ping = False - last_test = datetime.datetime.fromtimestamp(0) - ping_count = 0 - while True: - time.sleep(.1) - display.fill(0) - display.text("Test is "+str(running_ping), 0, 0, 1) - display.text('Time: '+str(helium.get_last_message()), 0, 10, 1) - display.text('Total Pings: '+str(ping_count), 0, 20, 1) - display.show() - if running_ping and (datetime.datetime.now() - last_test).seconds > 5: - helium.transact("Test") - ping_count += 1 - if not btnA.value: - running_ping = True - if not btnB.value: - running_ping = False - if not btnC.value: - display.fill(0) - display.text("Test is shut down!", 0, 0, 1) - display.text('Must restart PI to', 0, 10, 1) - display.text('restart test.', 0, 20, 1) - display.show() - raise KeyboardInterrupt -run() \ No newline at end of file +# import sys +# import time +# import datetime +# +# import adafruit_ssd1306 +# from SX127x.LoRa import LoRa, MODE +# from digitalio import DigitalInOut, Direction, Pull +# from SX127x.board_config_ada import BOARD +# import board +# import busio +# +# # Button A +# btnA = DigitalInOut(board.D5) +# btnA.direction = Direction.INPUT +# btnA.pull = Pull.UP +# +# # Button B +# btnB = DigitalInOut(board.D6) +# btnB.direction = Direction.INPUT +# btnB.pull = Pull.UP +# +# # Button C +# btnC = DigitalInOut(board.D12) +# btnC.direction = Direction.INPUT +# btnC.pull = Pull.UP +# +# # Create the I2C interface. +# i2c = busio.I2C(board.SCL, board.SDA) +# +# # 128x32 OLED Display +# reset_pin = DigitalInOut(board.D4) +# display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) +# # Clear the display. +# width = display.width +# height = display.height +# +# def run(): +# helium = Helium() +# helium.transact("Test") +# running_ping = False +# last_test = datetime.datetime.fromtimestamp(0) +# ping_count = 0 +# while True: +# time.sleep(.1) +# display.fill(0) +# display.text("Test is "+str(running_ping), 0, 0, 1) +# display.text('Time: '+str(helium.get_last_message()), 0, 10, 1) +# display.text('Total Pings: '+str(ping_count), 0, 20, 1) +# display.show() +# if running_ping and (datetime.datetime.now() - last_test).seconds > 5: +# helium.transact("Test") +# ping_count += 1 +# if not btnA.value: +# running_ping = True +# if not btnB.value: +# running_ping = False +# if not btnC.value: +# display.fill(0) +# display.text("Test is shut down!", 0, 0, 1) +# display.text('Must restart PI to', 0, 10, 1) +# display.text('restart test.', 0, 20, 1) +# display.show() +# raise KeyboardInterrupt +# +# run() \ No newline at end of file From 045af0d0d7c687f91f195201a6fbfd2a51cffe4b Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:32:30 -0700 Subject: [PATCH 092/130] updates --- helium_transactor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index a227184..72ec42d 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -30,10 +30,11 @@ def __init__(self, verbose=False, keys=keys.get_keys()): def on_rx_done(self): self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) - import code;code.interact(local=dict(globals(), **locals())) print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) decoded = "".join(list(map(chr, lorawan.get_payload()))) + print(decoded) + import code;code.interact(local=dict(globals(), **locals())) self.last_message = decoded self.test_status["last_message"] = decoded self.test_status["ping_count"] += 1 From 44b7a40ce4273c8d2e462abb32812f3328fe78f1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:34:29 -0700 Subject: [PATCH 093/130] updates --- helium_transactor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helium_transactor.py b/helium_transactor.py index 72ec42d..2bb2074 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -33,6 +33,7 @@ def on_rx_done(self): print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) decoded = "".join(list(map(chr, lorawan.get_payload()))) + lorawan.read(payload) print(decoded) import code;code.interact(local=dict(globals(), **locals())) self.last_message = decoded From bf46466ce4d7324db0b4434358b2461676ea273a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:34:49 -0700 Subject: [PATCH 094/130] updates --- helium_transactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index 2bb2074..b575aef 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -32,8 +32,8 @@ def on_rx_done(self): payload = self.read_payload(nocheck=True) print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) - decoded = "".join(list(map(chr, lorawan.get_payload()))) lorawan.read(payload) + decoded = "".join(list(map(chr, lorawan.get_payload()))) print(decoded) import code;code.interact(local=dict(globals(), **locals())) self.last_message = decoded From b6ab8ac80e1405f94bd7f12107295127be2324b5 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:35:20 -0700 Subject: [PATCH 095/130] updates --- helium_transactor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index b575aef..e65eb7e 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -35,7 +35,6 @@ def on_rx_done(self): lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) print(decoded) - import code;code.interact(local=dict(globals(), **locals())) self.last_message = decoded self.test_status["last_message"] = decoded self.test_status["ping_count"] += 1 From 97972bb93ce460640200ec0955b128bef6ddfabf Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:37:15 -0700 Subject: [PATCH 096/130] updates --- helium_transactor.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index e65eb7e..ce3923e 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -34,8 +34,6 @@ def on_rx_done(self): lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) - print(decoded) - self.last_message = decoded self.test_status["last_message"] = decoded self.test_status["ping_count"] += 1 print("Decoded: {}".format(decoded)) @@ -51,19 +49,19 @@ def on_rx_done(self): elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: print("Confirmed data down.") self.ack = True - downlink = decoded + downlink = decoded elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: print("Confirmed data up.") - downlink = decoded + downlink = decoded else: print("Other packet.") downlink = '' self.set_mode(MODE.STDBY) s = '' - s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() - s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() - s += " rssi_value %d\n" % self.get_rssi_value() - s += " msg: %s" % downlink + s += f" pkt_snr_value {self.get_pkt_snr_value():.2f}\n" + s += f" pkt_rssi_value {self.get_pkt_rssi_value():d}\n" + s += f" rssi_value {self.get_rssi_value():d}\n" + s += f" msg: {downlink}" print(s) def increment(self): @@ -97,25 +95,28 @@ def set_frame(self,frame): self.tx_counter = frame def setup_tx(self): + # Setup + self.clear_irq_flags(RxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium_helper.UPFREQ) - self.set_pa_config(pa_select=1) + self.set_freq(helium.UPFREQ) + self.set_bw(7) self.set_spreading_factor(7) self.set_pa_config(max_power=0x0F, output_power=0x0E) self.set_sync_word(0x34) self.set_rx_crc(True) - self.get_all_registers() + self.set_invert_iq(0) assert(self.get_agc_auto_on() == 1) def on_tx_done(self): self.clear_irq_flags(TxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) - self.set_freq(helium_helper.DOWNFREQ) + self.set_freq(helium.DOWNFREQ) self.set_bw(9) self.set_spreading_factor(7) self.set_pa_config(pa_select=1) + self.set_sync_word(0x34) self.set_rx_crc(False) self.set_invert_iq(1) self.reset_ptr_rx() From d1240028a94de8633a83c009e0f6d53ca96fd79e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:37:38 -0700 Subject: [PATCH 097/130] updates --- helium_transactor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index ce3923e..9a5cc61 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -99,7 +99,7 @@ def setup_tx(self): self.clear_irq_flags(RxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium.UPFREQ) + self.set_freq(helium_helper.UPFREQ) self.set_bw(7) self.set_spreading_factor(7) self.set_pa_config(max_power=0x0F, output_power=0x0E) @@ -112,7 +112,7 @@ def on_tx_done(self): self.clear_irq_flags(TxDone=1) self.set_mode(MODE.SLEEP) self.set_dio_mapping([0,0,0,0,0,0]) - self.set_freq(helium.DOWNFREQ) + self.set_freq(helium_helper.DOWNFREQ) self.set_bw(9) self.set_spreading_factor(7) self.set_pa_config(pa_select=1) From d328203e41c33377530585e1e276e3ae2c2b274c Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:38:00 -0700 Subject: [PATCH 098/130] updates --- run.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/run.py b/run.py index b0b80be..bcf2eab 100644 --- a/run.py +++ b/run.py @@ -1,6 +1,7 @@ from helium import Helium helium = Helium() -helium.transact("Test") +while True: + helium.transact("Test") # import sys # import time From 04ad7278f87a3baa15ec7edc9a5963d6ff2bcf3a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:40:55 -0700 Subject: [PATCH 099/130] updates --- helium_transactor.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index 9a5cc61..a3451e9 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -21,7 +21,6 @@ def __init__(self, verbose=False, keys=keys.get_keys()): self.iter = 0 self.uuid = shortuuid.uuid() self.ack = True - self.test_status = {"ping_count": 0, "last_message": None} self.last_tx = datetime.datetime.fromtimestamp(0) self.last_message = None self.transact_timeout = 5 @@ -34,8 +33,7 @@ def on_rx_done(self): lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) - self.test_status["last_message"] = decoded - self.test_status["ping_count"] += 1 + self.last_message = decoded print("Decoded: {}".format(decoded)) print("\n") if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: @@ -127,9 +125,13 @@ def transact(self, msg): self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg}), True) self.iter = self.iter+1 self.last_tx = datetime.datetime.now() - while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds < self.transact_timeout: - sleep(0.1) - return self.last_message + while (datetime.datetime.now() - self.last_tx).seconds < self.transact_timeout: + if self.last_message is None: + sleep(0.1) + else: + message = self.last_message + self.last_message = None + return message def stop(self): self.set_mode(MODE.SLEEP) From 9a146f9f581cf177d4702fa00c9fd40959f30ce9 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 16:41:51 -0700 Subject: [PATCH 100/130] updates --- helium_transactor.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index a3451e9..03785b9 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -29,38 +29,24 @@ def __init__(self, verbose=False, keys=keys.get_keys()): def on_rx_done(self): self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) - print("Raw payload: {}".format(payload)) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) decoded = "".join(list(map(chr, lorawan.get_payload()))) self.last_message = decoded - print("Decoded: {}".format(decoded)) - print("\n") if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: - print("Unconfirmed data down.") downlink = decoded res = lorawan.mac_payload.get_fhdr().get_fctrl() if 0x20 & res != 0: # Check Ack bit. - print("Server ack") if len(downlink) == 0: downlink = "Server ack" elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: - print("Confirmed data down.") self.ack = True downlink = decoded elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: - print("Confirmed data up.") downlink = decoded else: - print("Other packet.") downlink = '' self.set_mode(MODE.STDBY) - s = '' - s += f" pkt_snr_value {self.get_pkt_snr_value():.2f}\n" - s += f" pkt_rssi_value {self.get_pkt_rssi_value():d}\n" - s += f" rssi_value {self.get_rssi_value():d}\n" - s += f" msg: {downlink}" - print(s) def increment(self): self.tx_counter += 1 @@ -71,21 +57,16 @@ def increment(self): def tx(self, msg, conf=False): if conf: data = MHDR.CONF_DATA_UP - print('Sending confirmed data up.') else: data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') self.increment() lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: - print('Sending with Ack') lorawan.create(data, dict(**base, **{'ack':True})) self.ack = False else: - print('Sending without Ack') lorawan.create(data, base) - print(f"tx: {lorawan.to_raw()}") self.write_payload(lorawan.to_raw()) self.set_mode(MODE.TX) From 83f762530eb5c06397c77b95615b4b36f3ef9cb8 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:25:28 -0700 Subject: [PATCH 101/130] updates --- gps.py | 12 +++++ gps_simpletest.py | 109 ++++++++++++++++++++++++++++++++++++++++++++++ run.py | 75 ++++--------------------------- 3 files changed, 129 insertions(+), 67 deletions(-) create mode 100644 gps.py create mode 100644 gps_simpletest.py diff --git a/gps.py b/gps.py new file mode 100644 index 0000000..b044d12 --- /dev/null +++ b/gps.py @@ -0,0 +1,12 @@ +import os +import serial +import adafruit_gps +uart = serial.Serial(os.popen("ls /dev/ttyUSB*").read().strip(), baudrate=9600, timeout=10) +gps = adafruit_gps.GPS(uart, debug=False) +gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') +gps.send_command(b'PMTK220,2000') +last_print = time.monotonic() +def get_gps_data(): + gps.update() + if gps.has_fix: + return {"lat": gps.latitude, "lon": gps.longitude, "speed": gps.speed_knots, "alt": gps.altitude_m} diff --git a/gps_simpletest.py b/gps_simpletest.py new file mode 100644 index 0000000..b5bc841 --- /dev/null +++ b/gps_simpletest.py @@ -0,0 +1,109 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +# Simple GPS module demonstration. +# Will wait for a fix and print a message every second with the current location +# and other details. +import time +import board +import busio + +import adafruit_gps + +# Create a serial connection for the GPS connection using default speed and +# a slightly higher timeout (GPS modules typically update once a second). +# These are the defaults you should use for the GPS FeatherWing. +# For other boards set RX = GPS module TX, and TX = GPS module RX pins. +# uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10) + +# for a computer, use the pyserial library for uart access +import serial +uart = serial.Serial("/dev/ttyUSB1", baudrate=9600, timeout=10) + +# If using I2C, we'll create an I2C interface to talk to using default pins +# i2c = board.I2C() + +# Create a GPS module instance. +gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial +# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface + +# Initialize the GPS module by changing what data it sends and at what rate. +# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and +# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust +# the GPS module behavior: +# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf + +# Turn on the basic GGA and RMC info (what you typically want) +gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") +# Turn on just minimum info (RMC only, location): +# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +# Turn off everything: +# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +# Turn on everything (not all of it is parsed!) +# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') + +# Set update rate to once a second (1hz) which is what you typically want. +gps.send_command(b"PMTK220,1000") +# Or decrease to once every two seconds by doubling the millisecond value. +# Be sure to also increase your UART timeout above! +# gps.send_command(b'PMTK220,2000') +# You can also speed up the rate, but don't go too fast or else you can lose +# data during parsing. This would be twice a second (2hz, 500ms delay): +# gps.send_command(b'PMTK220,500') + +# Main loop runs forever printing the location, etc. every second. +last_print = time.monotonic() +while True: + # Make sure to call gps.update() every loop iteration and at least twice + # as fast as data comes from the GPS unit (usually every second). + # This returns a bool that's true if it parsed new data (you can ignore it + # though if you don't care and instead look at the has_fix property). + gps.update() + # Every second print out current location details if there's a fix. + current = time.monotonic() + if current - last_print >= 1.0: + last_print = current + if not gps.has_fix: + # Try again if we don't have a fix yet. + print("Waiting for fix...") + continue + # We have a fix! (gps.has_fix is true) + # Print out details about the fix like location, date, etc. + print("=" * 40) # Print a separator line. + print( + "Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format( + gps.timestamp_utc.tm_mon, # Grab parts of the time from the + gps.timestamp_utc.tm_mday, # struct_time object that holds + gps.timestamp_utc.tm_year, # the fix time. Note you might + gps.timestamp_utc.tm_hour, # not get all data like year, day, + gps.timestamp_utc.tm_min, # month! + gps.timestamp_utc.tm_sec, + ) + ) + print("Latitude: {0:.6f} degrees".format(gps.latitude)) + print("Longitude: {0:.6f} degrees".format(gps.longitude)) + print( + "Precise Latitude: {:2.}{:2.4f} degrees".format( + gps.latitude_degrees, gps.latitude_minutes + ) + ) + print( + "Precise Longitude: {:2.}{:2.4f} degrees".format( + gps.longitude_degrees, gps.longitude_minutes + ) + ) + print("Fix quality: {}".format(gps.fix_quality)) + # Some attributes beyond latitude, longitude and timestamp are optional + # and might not be present. Check if they're None before trying to use! + if gps.satellites is not None: + print("# satellites: {}".format(gps.satellites)) + if gps.altitude_m is not None: + print("Altitude: {} meters".format(gps.altitude_m)) + if gps.speed_knots is not None: + print("Speed: {} knots".format(gps.speed_knots)) + if gps.track_angle_deg is not None: + print("Track angle: {} degrees".format(gps.track_angle_deg)) + if gps.horizontal_dilution is not None: + print("Horizontal dilution: {}".format(gps.horizontal_dilution)) + if gps.height_geoid is not None: + print("Height geoid: {} meters".format(gps.height_geoid)) \ No newline at end of file diff --git a/run.py b/run.py index bcf2eab..62e3043 100644 --- a/run.py +++ b/run.py @@ -1,70 +1,11 @@ +import json from helium import Helium +from gps import get_gps_data helium = Helium() +helium.transact("Test") while True: - helium.transact("Test") - -# import sys -# import time -# import datetime -# -# import adafruit_ssd1306 -# from SX127x.LoRa import LoRa, MODE -# from digitalio import DigitalInOut, Direction, Pull -# from SX127x.board_config_ada import BOARD -# import board -# import busio -# -# # Button A -# btnA = DigitalInOut(board.D5) -# btnA.direction = Direction.INPUT -# btnA.pull = Pull.UP -# -# # Button B -# btnB = DigitalInOut(board.D6) -# btnB.direction = Direction.INPUT -# btnB.pull = Pull.UP -# -# # Button C -# btnC = DigitalInOut(board.D12) -# btnC.direction = Direction.INPUT -# btnC.pull = Pull.UP -# -# # Create the I2C interface. -# i2c = busio.I2C(board.SCL, board.SDA) -# -# # 128x32 OLED Display -# reset_pin = DigitalInOut(board.D4) -# display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) -# # Clear the display. -# width = display.width -# height = display.height -# -# def run(): -# helium = Helium() -# helium.transact("Test") -# running_ping = False -# last_test = datetime.datetime.fromtimestamp(0) -# ping_count = 0 -# while True: -# time.sleep(.1) -# display.fill(0) -# display.text("Test is "+str(running_ping), 0, 0, 1) -# display.text('Time: '+str(helium.get_last_message()), 0, 10, 1) -# display.text('Total Pings: '+str(ping_count), 0, 20, 1) -# display.show() -# if running_ping and (datetime.datetime.now() - last_test).seconds > 5: -# helium.transact("Test") -# ping_count += 1 -# if not btnA.value: -# running_ping = True -# if not btnB.value: -# running_ping = False -# if not btnC.value: -# display.fill(0) -# display.text("Test is shut down!", 0, 0, 1) -# display.text('Must restart PI to', 0, 10, 1) -# display.text('restart test.', 0, 20, 1) -# display.show() -# raise KeyboardInterrupt -# -# run() \ No newline at end of file + gps_data = get_gps_data() + response = {} + if gps_data: + response = helium.transact(json.dumps(gps_data)) + time.sleep(response.get("next_ping_at", 10)) From 2c23d6a3b5b4270a8667e7e364181d18143cdbf5 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:28:01 -0700 Subject: [PATCH 102/130] updates --- helium_transactor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/helium_transactor.py b/helium_transactor.py index 03785b9..ed9c202 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -31,6 +31,7 @@ def on_rx_done(self): payload = self.read_payload(nocheck=True) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) + print(decoded) decoded = "".join(list(map(chr, lorawan.get_payload()))) self.last_message = decoded if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: From fe38680898a1b64fb8ade2c357524f6871761edd Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:28:19 -0700 Subject: [PATCH 103/130] updates --- gps.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gps.py b/gps.py index b044d12..5eb6f87 100644 --- a/gps.py +++ b/gps.py @@ -1,6 +1,7 @@ import os import serial import adafruit_gps +import time uart = serial.Serial(os.popen("ls /dev/ttyUSB*").read().strip(), baudrate=9600, timeout=10) gps = adafruit_gps.GPS(uart, debug=False) gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') From db67fe3f9b6d6211316b36a204d30025298362d1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:28:47 -0700 Subject: [PATCH 104/130] updates --- helium_transactor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index ed9c202..425db84 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -31,8 +31,8 @@ def on_rx_done(self): payload = self.read_payload(nocheck=True) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) - print(decoded) decoded = "".join(list(map(chr, lorawan.get_payload()))) + print(decoded) self.last_message = decoded if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: downlink = decoded From 897a37e4b7d52f92d8f465109744368b38b46253 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:31:41 -0700 Subject: [PATCH 105/130] updates --- helium_transactor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index 425db84..da4bc57 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -30,7 +30,8 @@ def on_rx_done(self): self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) - lorawan.read(payload) + gz = lorawan.read(payload) + print(gz) decoded = "".join(list(map(chr, lorawan.get_payload()))) print(decoded) self.last_message = decoded From 70dfd61fe5cd75821aadbeba9b2172f3cbe92a59 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:32:21 -0700 Subject: [PATCH 106/130] updates --- helium_transactor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/helium_transactor.py b/helium_transactor.py index da4bc57..2095ffb 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -32,7 +32,9 @@ def on_rx_done(self): lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) gz = lorawan.read(payload) print(gz) - decoded = "".join(list(map(chr, lorawan.get_payload()))) + gz = lorawan.get_payload() + print(gz) + decoded = "".join(list(map(chr, gz))) print(decoded) self.last_message = decoded if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: From 053aaf51cad6574ff4f023d2454a2a4100097176 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:33:11 -0700 Subject: [PATCH 107/130] updates --- helium_transactor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index 2095ffb..a14f668 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -30,8 +30,7 @@ def on_rx_done(self): self.clear_irq_flags(RxDone=1) payload = self.read_payload(nocheck=True) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) - gz = lorawan.read(payload) - print(gz) + lorawan.read(payload) gz = lorawan.get_payload() print(gz) decoded = "".join(list(map(chr, gz))) From d9fca815b0bd29819fe6f6b33b5efcc21fa0f9f5 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:33:22 -0700 Subject: [PATCH 108/130] updates --- run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run.py b/run.py index 62e3043..5aa14c3 100644 --- a/run.py +++ b/run.py @@ -1,3 +1,4 @@ +import time import json from helium import Helium from gps import get_gps_data From 6813b2670ae87f81d6177370f4d7b381d8d3d5d1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:41:03 -0700 Subject: [PATCH 109/130] updates --- helium_transactor.py | 2 +- run.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index a14f668..7a5690e 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -64,7 +64,7 @@ def tx(self, msg, conf=False): data = MHDR.UNCONF_DATA_UP self.increment() lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) - base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} + base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, "test"))} if self.ack: lorawan.create(data, dict(**base, **{'ack':True})) self.ack = False diff --git a/run.py b/run.py index 5aa14c3..b520be2 100644 --- a/run.py +++ b/run.py @@ -3,7 +3,7 @@ from helium import Helium from gps import get_gps_data helium = Helium() -helium.transact("Test") +helium.transact({"balh": 1}) while True: gps_data = get_gps_data() response = {} From 99e158d20a6201b78aa092e6d9f319e00dab942a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 17:46:42 -0700 Subject: [PATCH 110/130] updates --- helium_transactor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/helium_transactor.py b/helium_transactor.py index 7a5690e..0997330 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -31,11 +31,11 @@ def on_rx_done(self): payload = self.read_payload(nocheck=True) lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) lorawan.read(payload) - gz = lorawan.get_payload() - print(gz) - decoded = "".join(list(map(chr, gz))) - print(decoded) - self.last_message = decoded + decoded = "".join(list(map(chr, lorawan.get_payload()))) + try: + self.last_message = json.loads(decoded) + except: + self.last_message = decoded if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: downlink = decoded res = lorawan.mac_payload.get_fhdr().get_fctrl() @@ -64,7 +64,7 @@ def tx(self, msg, conf=False): data = MHDR.UNCONF_DATA_UP self.increment() lorawan = LoRaWAN.new(self.keys["nwskey"], self.keys["appskey"]) - base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, "test"))} + base = {'devaddr': self.keys["devaddr"], 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} if self.ack: lorawan.create(data, dict(**base, **{'ack':True})) self.ack = False From 1d8ae3dee8dc343ef6e23b8fda9e331022bec297 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 18:04:19 -0700 Subject: [PATCH 111/130] updates --- run.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index b520be2..f42407a 100644 --- a/run.py +++ b/run.py @@ -3,10 +3,13 @@ from helium import Helium from gps import get_gps_data helium = Helium() -helium.transact({"balh": 1}) -while True: +def fire_ping(): gps_data = get_gps_data() response = {} if gps_data: - response = helium.transact(json.dumps(gps_data)) + response = helium.transact(json.dumps(gps_data)) or {} + return response + +while True: + response = fire_ping() time.sleep(response.get("next_ping_at", 10)) From 5e8476b1225e7989b37c4b0cbf00b8d432455ca0 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Sun, 21 Aug 2022 18:04:25 -0700 Subject: [PATCH 112/130] updates --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 07a2386..7801724 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +#RPI install routine +``` +sudo apt-get install -y tmux htop +sudo pip3 install adafruit-circuitpython-ssd1306 +sudo pip3 install adafruit-circuitpython-framebuf +sudo pip3 install adafruit-circuitpython-rfm9x +sudo pip3 install adafruit-circuitpython-gps +sudo pip3 install pycryptodome +sudo pip3 install shortuuid +sudo pip3 install python-dotenv +sudo apt-get install gpsd gpsd-clients +git clone git@github.com:DGaffney/LoRaWAN.git +``` + # LoRaWAN This is a LoRaWAN v1.0 implementation in python. From d4c7d543ce4c4059251ec05deeda3839bc36236c Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 12:33:11 -0700 Subject: [PATCH 113/130] more safety checks --- run.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/run.py b/run.py index f42407a..4c389c9 100644 --- a/run.py +++ b/run.py @@ -2,14 +2,23 @@ import json from helium import Helium from gps import get_gps_data -helium = Helium() def fire_ping(): gps_data = get_gps_data() - response = {} - if gps_data: - response = helium.transact(json.dumps(gps_data)) or {} - return response + return helium.transact(json.dumps(gps_data or {})) or {} + +helium = None +while not helium: + try: + helium = Helium() + except: + helium = None + time.sleep(5) while True: - response = fire_ping() - time.sleep(response.get("next_ping_at", 10)) + try: + response = fire_ping() + print(response) + time.sleep(response.get("next_ping_at", 10)) + except: + print("oops") + time.sleep(10) From b1d75e58d1ae4e2af861aa853df192767830e013 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 12:48:51 -0700 Subject: [PATCH 114/130] back to defaults --- gps.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gps.py b/gps.py index 5eb6f87..202988e 100644 --- a/gps.py +++ b/gps.py @@ -4,9 +4,8 @@ import time uart = serial.Serial(os.popen("ls /dev/ttyUSB*").read().strip(), baudrate=9600, timeout=10) gps = adafruit_gps.GPS(uart, debug=False) -gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') -gps.send_command(b'PMTK220,2000') -last_print = time.monotonic() +gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") +gps.send_command(b"PMTK220,1000") def get_gps_data(): gps.update() if gps.has_fix: From 92163330fc31f8afc3708e31a8d64f084258cf1e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 13:25:40 -0700 Subject: [PATCH 115/130] updates --- gps.py | 17 ++++++----------- requirements.txt | 1 + 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/gps.py b/gps.py index 202988e..c28bde6 100644 --- a/gps.py +++ b/gps.py @@ -1,12 +1,7 @@ -import os -import serial -import adafruit_gps -import time -uart = serial.Serial(os.popen("ls /dev/ttyUSB*").read().strip(), baudrate=9600, timeout=10) -gps = adafruit_gps.GPS(uart, debug=False) -gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") -gps.send_command(b"PMTK220,1000") +from gpsdclient import GPSDClient + +client = GPSDClient(host="127.0.0.1") def get_gps_data(): - gps.update() - if gps.has_fix: - return {"lat": gps.latitude, "lon": gps.longitude, "speed": gps.speed_knots, "alt": gps.altitude_m} + for result in client.dict_stream(convert_datetime=True): + if result["class"] == "TPV": + return {"lat": result.get("lat"), "lon": result.get("lon"), "speed": result.get("speed"), "alt": result.get("alt")} diff --git a/requirements.txt b/requirements.txt index 49e59a1..1deb752 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ adafruit_blinka adafruit-circuitpython-ssd1306 python-dotenv shortuuid +gpsdclient \ No newline at end of file From 3267728721acd4474e079a3373e9b60125773ebd Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 13:27:16 -0700 Subject: [PATCH 116/130] updates --- gps.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gps.py b/gps.py index c28bde6..a6f1bbf 100644 --- a/gps.py +++ b/gps.py @@ -1,7 +1,10 @@ +import datetime from gpsdclient import GPSDClient client = GPSDClient(host="127.0.0.1") -def get_gps_data(): +def get_gps_data(transact_timeout=10): + start = datetime.datetime.now() for result in client.dict_stream(convert_datetime=True): + (datetime.datetime.now() - start).seconds < transact_timeout if result["class"] == "TPV": return {"lat": result.get("lat"), "lon": result.get("lon"), "speed": result.get("speed"), "alt": result.get("alt")} From 2ffb8a5de978ccb3ae19dcadeb290fe35c603e59 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 13:34:20 -0700 Subject: [PATCH 117/130] updates --- run.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/run.py b/run.py index 4c389c9..69c32d5 100644 --- a/run.py +++ b/run.py @@ -2,18 +2,15 @@ import json from helium import Helium from gps import get_gps_data +get_gps_data() def fire_ping(): gps_data = get_gps_data() - return helium.transact(json.dumps(gps_data or {})) or {} - -helium = None -while not helium: - try: - helium = Helium() - except: - helium = None - time.sleep(5) + response = {} + if gps_data: + response = helium.transact(json.dumps(gps_data or {})) or {} + return response +helium = Helium() while True: try: response = fire_ping() From 5cfd08ef489e0ecf9e529402c9b031a1bcbab781 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 23 Aug 2022 13:42:20 -0700 Subject: [PATCH 118/130] updates --- helium.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/helium.py b/helium.py index 8e015ee..26fb6c9 100644 --- a/helium.py +++ b/helium.py @@ -1,15 +1,23 @@ +import time import requests from helium_authenticator import HeliumAuthenticator from helium_transactor import keys, HeliumTransactor class Helium: def authenticate(self): - authentication = HeliumAuthenticator.authenticate() - cur_keys = self.keys - for k,v in authentication.items(): - cur_keys[k] = v - keys.write(cur_keys) - return authentication + try_count = 0 + while try_count < 5: + try: + authentication = HeliumAuthenticator.authenticate() + cur_keys = self.keys + for k,v in authentication.items(): + cur_keys[k] = v + keys.write(cur_keys) + except: + print("Failed Auth") + try_count += 1 + time.sleep(3) + return authentication def register_device(self): # if we have never seen the device, build some ... machinery and APIs etc to register this device. From ae76422e847a43c0b04b3f2c262b3931d3841ddb Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Wed, 24 Aug 2022 12:14:50 -0700 Subject: [PATCH 119/130] tighten package --- helium_lora.py | 214 ------------------------------------------- helium_transactor.py | 4 +- run.py | 8 +- transactor.py | 189 -------------------------------------- 4 files changed, 8 insertions(+), 407 deletions(-) delete mode 100755 helium_lora.py delete mode 100755 transactor.py diff --git a/helium_lora.py b/helium_lora.py deleted file mode 100755 index 9251fa3..0000000 --- a/helium_lora.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env python3 - -import os -import re -import json -import datetime -from time import sleep -from random import randrange - -from SX127x.LoRa import LoRa, MODE -from SX127x.board_config_ada import BOARD -import LoRaWAN -from LoRaWAN.MHDR import MHDR -import shortuuid - -import helium -import keys -BOARD.setup() -class HeliumLoRa(LoRa): - def __init__(self, verbose = False, ack=True, start_ping=False): - super(HeliumLoRa, self).__init__(verbose) - self.iter = 0 - self.uuid = shortuuid.uuid() - self.ack = ack - self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} - self.last_tx = datetime.datetime.fromtimestamp(0) - self.last_message = None - self.transact_timeout = 5 - self.is_otaaing = False - - def otaa(self): - print(self) - self.is_otaaing = True - self.setup_tx() - lorawan = LoRaWAN.new(keys.appkey) - devnonce = [randrange(256), randrange(256)] - lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - sleep(10) - - def on_rx_done(self): - print("RxDone") - import code;code.interact(local=dict(globals(), **locals())) - self.clear_irq_flags(RxDone=1) - payload = self.read_payload(nocheck=True) - if self.is_otaaing: - self.set_mode(MODE.SLEEP) - self.get_all_registers() - print(self) - lorawan = LoRaWAN.new([], keys.appkey) - lorawan.read(payload) - print(lorawan.get_payload()) - print(lorawan.get_mhdr().get_mversion()) - if lorawan.get_mhdr().get_mtype() == MHDR.JOIN_ACCEPT: - print("Got LoRaWAN join accept. Paste these values into keys.py") - print(lorawan.valid_mic()) - devaddr = lorawan.get_devaddr() - print("devaddr = {devaddr}".format()) - nwskey = lorawan.derive_nwskey(devnonce) - print("nwskey = {nwskey}".format()) - appskey = lorawan.derive_appskey(devnonce) - print("appskey = {appskey}".format()) - print("\n") - self.is_otaaing = False - self.otaa_result = [devaddr, nwskey, appskey] - else: - print("Raw payload: {}".format(payload)) - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - decoded = "".join(list(map(chr, lorawan.get_payload()))) - self.last_message = decoded - self.test_status["last_message"] = decoded - self.test_status["ping_count"] += 1 - print("Decoded: {}".format(decoded)) - print("\n") - if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: - print("Unconfirmed data down.") - downlink = decoded - res = lorawan.mac_payload.get_fhdr().get_fctrl() - if 0x20 & res != 0: # Check Ack bit. - print("Server ack") - if len(downlink) == 0: - downlink = "Server ack" - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: - print("Confirmed data down.") - self.ack = True - downlink = decoded - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: - print("Confirmed data up.") - downlink = decoded - else: - print("Other packet.") - downlink = '' - self.set_mode(MODE.STDBY) - s = '' - s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() - s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() - s += " rssi_value %d\n" % self.get_rssi_value() - s += " msg: %s" % downlink - print(s) - - def increment(self): - self.tx_counter += 1 - data_file = open("frame.txt", "w") - data_file.write(f'frame = {self.tx_counter:d}\n') - data_file.close() - - def tx(self, msg, conf=False): - if conf: - data = MHDR.CONF_DATA_UP - print('Sending confirmed data up.') - else: - data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') - self.increment() - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - if self.ack: - print('Sending with Ack') - lorawan.create(data, dict(**base, **{'ack':True})) - self.ack = False - else: - print('Sending without Ack') - lorawan.create(data, base) - print(f"tx: {lorawan.to_raw()}") - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - - def set_frame(self,frame): - self.tx_counter = frame - - def setup_tx(self): - # Setup - # self.set_mode(MODE.SLEEP) - # self.set_dio_mapping([1,0,0,0,0,0]) - # self.set_freq(helium.UPFREQ) - # if not self.is_otaaing: - # self.set_bw(7) - # else: - # self.set_pa_config(pa_select=1) - # self.set_spreading_factor(7) - # self.set_pa_config(max_power=0x0F, output_power=0x0E) - # self.set_sync_word(0x34) - # self.set_rx_crc(True) - # if not self.is_otaaing: - # self.set_invert_iq(0) - # else: - # self.get_all_registers() - # assert(self.get_agc_auto_on() == 1) - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium.UPFREQ) - self.set_pa_config(pa_select=1) - self.set_spreading_factor(7) - self.set_pa_config(max_power=0x0F, output_power=0x0E) - self.set_sync_word(0x34) - self.set_rx_crc(True) - self.get_all_registers() - print(self) - assert(self.get_agc_auto_on() == 1) - - def on_tx_done(self): - self.clear_irq_flags(TxDone=1) - print("TxDone") - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([0,0,0,0,0,0]) - self.set_invert_iq(1) - self.reset_ptr_rx() - self.set_freq(helium.DOWNFREQ)#915) - self.set_spreading_factor(7)#12) - self.set_bw(9) #500Khz - self.set_rx_crc(False)#TRUE - self.set_mode(MODE.RXCONT) - # self.clear_irq_flags(TxDone=1) - # self.set_mode(MODE.SLEEP) - # self.set_dio_mapping([0,0,0,0,0,0]) - # self.set_freq(helium.DOWNFREQ) - # self.set_bw(9) - # self.set_spreading_factor(7) - # self.set_pa_config(pa_select=1) - # if not self.is_otaaing: - # self.set_sync_word(0x34) - # self.set_rx_crc(False) - # self.set_invert_iq(1) - # self.reset_ptr_rx() - # self.set_mode(MODE.RXCONT) - - def transact(self, msg): - self.setup_tx() - self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) - self.iter = self.iter+1 - self.last_tx = datetime.datetime.now() - while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: - sleep(0.1) - return self.last_message - - def stop(self): - self.set_mode(MODE.SLEEP) - BOARD.teardown() - - def init_frame(self): - frame = 0 - if os.path.exists('frame.txt'): - with open('frame.txt') as df: - for line in df: - if m := re.match('^frame\s*=\s*(\d+)', line): - frame = int(m.group(1)) - self.set_frame(frame) - - @classmethod - def init(cls, verbose=False, ack=True, start_ping=False): - lora = cls(verbose, ack, start_ping) - lora.init_frame() - return lora diff --git a/helium_transactor.py b/helium_transactor.py index 0997330..cbf22ed 100755 --- a/helium_transactor.py +++ b/helium_transactor.py @@ -106,7 +106,9 @@ def on_tx_done(self): def transact(self, msg): self.setup_tx() - self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg}), True) + self.tx(msg, True) + # Full package - too heavy: + # self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg}), True) self.iter = self.iter+1 self.last_tx = datetime.datetime.now() while (datetime.datetime.now() - self.last_tx).seconds < self.transact_timeout: diff --git a/run.py b/run.py index 69c32d5..73dcb5b 100644 --- a/run.py +++ b/run.py @@ -2,12 +2,13 @@ import json from helium import Helium from gps import get_gps_data -get_gps_data() def fire_ping(): gps_data = get_gps_data() response = {} if gps_data: - response = helium.transact(json.dumps(gps_data or {})) or {} + #response = helium.transact(json.dumps(gps_data or {})) or {} + if gps_data["lat"] and gps_data["lon"]: + response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))) return response helium = Helium() @@ -15,7 +16,8 @@ def fire_ping(): try: response = fire_ping() print(response) - time.sleep(response.get("next_ping_at", 10)) + time.sleep(int(response or "10")) + #time.sleep(response.get("next_ping_at", 10)) except: print("oops") time.sleep(10) diff --git a/transactor.py b/transactor.py deleted file mode 100755 index 4df6590..0000000 --- a/transactor.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python3 - -import os -import re -import json -import datetime -from time import sleep -from random import randrange - -from SX127x.LoRa import LoRa, MODE -from SX127x.board_config_ada import BOARD -import LoRaWAN -from LoRaWAN.MHDR import MHDR -import shortuuid - -import helium -import keys -BOARD.setup() -class HeliumTransactor(LoRa): - def __init__(self, verbose = False, ack=True, start_ping=False): - super(HeliumLoRa, self).__init__(verbose) - self.iter = 0 - self.uuid = shortuuid.uuid() - self.ack = ack - self.test_status = {"running_ping": start_ping, "ping_count": 0, "last_message": None} - self.last_tx = datetime.datetime.fromtimestamp(0) - self.last_message = None - self.transact_timeout = 5 - self.is_otaaing = False - - def otaa(self): - print(self) - self.is_otaaing = True - self.setup_tx() - lorawan = LoRaWAN.new(keys.appkey) - devnonce = [randrange(256), randrange(256)] - lorawan.create(MHDR.JOIN_REQUEST, {'deveui': keys.deveui, 'appeui': keys.appeui, 'devnonce': devnonce}) - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - sleep(10) - - def on_rx_done(self): - print("Raw payload: {}".format(payload)) - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - decoded = "".join(list(map(chr, lorawan.get_payload()))) - self.last_message = decoded - self.test_status["last_message"] = decoded - self.test_status["ping_count"] += 1 - print("Decoded: {}".format(decoded)) - print("\n") - if lorawan.get_mhdr().get_mtype() == MHDR.UNCONF_DATA_DOWN: - print("Unconfirmed data down.") - downlink = decoded - res = lorawan.mac_payload.get_fhdr().get_fctrl() - if 0x20 & res != 0: # Check Ack bit. - print("Server ack") - if len(downlink) == 0: - downlink = "Server ack" - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_DOWN: - print("Confirmed data down.") - self.ack = True - downlink = decoded - elif lorawan.get_mhdr().get_mtype() == MHDR.CONF_DATA_UP: - print("Confirmed data up.") - downlink = decoded - else: - print("Other packet.") - downlink = '' - self.set_mode(MODE.STDBY) - s = '' - s += " pkt_snr_value %f\n" % self.get_pkt_snr_value() - s += " pkt_rssi_value %d\n" % self.get_pkt_rssi_value() - s += " rssi_value %d\n" % self.get_rssi_value() - s += " msg: %s" % downlink - print(s) - - def increment(self): - self.tx_counter += 1 - data_file = open("frame.txt", "w") - data_file.write(f'frame = {self.tx_counter:d}\n') - data_file.close() - - def tx(self, msg, conf=False): - if conf: - data = MHDR.CONF_DATA_UP - print('Sending confirmed data up.') - else: - data = MHDR.UNCONF_DATA_UP - print('Sending unconfirmed data up.') - self.increment() - lorawan = LoRaWAN.new(keys.nwskey, keys.appskey) - base = {'devaddr': keys.devaddr, 'fcnt': self.tx_counter, 'data': list(map(ord, msg))} - if self.ack: - print('Sending with Ack') - lorawan.create(data, dict(**base, **{'ack':True})) - self.ack = False - else: - print('Sending without Ack') - lorawan.create(data, base) - print(f"tx: {lorawan.to_raw()}") - self.write_payload(lorawan.to_raw()) - self.set_mode(MODE.TX) - - def set_frame(self,frame): - self.tx_counter = frame - - def setup_tx(self): - # Setup - # self.set_mode(MODE.SLEEP) - # self.set_dio_mapping([1,0,0,0,0,0]) - # self.set_freq(helium.UPFREQ) - # if not self.is_otaaing: - # self.set_bw(7) - # else: - # self.set_pa_config(pa_select=1) - # self.set_spreading_factor(7) - # self.set_pa_config(max_power=0x0F, output_power=0x0E) - # self.set_sync_word(0x34) - # self.set_rx_crc(True) - # if not self.is_otaaing: - # self.set_invert_iq(0) - # else: - # self.get_all_registers() - # assert(self.get_agc_auto_on() == 1) - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([1,0,0,0,0,0]) - self.set_freq(helium.UPFREQ) - self.set_pa_config(pa_select=1) - self.set_spreading_factor(7) - self.set_pa_config(max_power=0x0F, output_power=0x0E) - self.set_sync_word(0x34) - self.set_rx_crc(True) - self.get_all_registers() - print(self) - assert(self.get_agc_auto_on() == 1) - - def on_tx_done(self): - self.clear_irq_flags(TxDone=1) - print("TxDone") - self.set_mode(MODE.SLEEP) - self.set_dio_mapping([0,0,0,0,0,0]) - self.set_invert_iq(1) - self.reset_ptr_rx() - self.set_freq(helium.DOWNFREQ)#915) - self.set_spreading_factor(7)#12) - self.set_bw(9) #500Khz - self.set_rx_crc(False)#TRUE - self.set_mode(MODE.RXCONT) - # self.clear_irq_flags(TxDone=1) - # self.set_mode(MODE.SLEEP) - # self.set_dio_mapping([0,0,0,0,0,0]) - # self.set_freq(helium.DOWNFREQ) - # self.set_bw(9) - # self.set_spreading_factor(7) - # self.set_pa_config(pa_select=1) - # if not self.is_otaaing: - # self.set_sync_word(0x34) - # self.set_rx_crc(False) - # self.set_invert_iq(1) - # self.reset_ptr_rx() - # self.set_mode(MODE.RXCONT) - - def transact(self, msg): - self.setup_tx() - self.tx(json.dumps({"i": self.iter, "s": self.uuid, "m": msg})) - self.iter = self.iter+1 - self.last_tx = datetime.datetime.now() - while self.last_message is None and (datetime.datetime.now() - self.last_tx).seconds > self.transact_timeout: - sleep(0.1) - return self.last_message - - def stop(self): - self.set_mode(MODE.SLEEP) - BOARD.teardown() - - def init_frame(self): - frame = 0 - if os.path.exists('frame.txt'): - with open('frame.txt') as df: - for line in df: - if m := re.match('^frame\s*=\s*(\d+)', line): - frame = int(m.group(1)) - self.set_frame(frame) - - @classmethod - def init(cls, verbose=False, ack=True, start_ping=False): - lora = cls(verbose, ack, start_ping) - lora.init_frame() - return lora From 1effea03fd50f24a0f107b0f55dfb828163d856d Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 15:29:37 -0700 Subject: [PATCH 120/130] updates --- gps.py | 16 ++++++++++++++++ run.py | 11 ++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/gps.py b/gps.py index a6f1bbf..7242502 100644 --- a/gps.py +++ b/gps.py @@ -1,3 +1,4 @@ +from math import sin, cos, sqrt, atan2, radians import datetime from gpsdclient import GPSDClient @@ -8,3 +9,18 @@ def get_gps_data(transact_timeout=10): (datetime.datetime.now() - start).seconds < transact_timeout if result["class"] == "TPV": return {"lat": result.get("lat"), "lon": result.get("lon"), "speed": result.get("speed"), "alt": result.get("alt")} + + +def get_dist(lat1,lon1,lat2,lon2): + # approximate radius of earth in km + R = 6373.0 + lat1 = radians(lat1) + lon1 = radians(lon1) + lat2 = radians(lat2) + lon2 = radians(lon2) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 + c = 2 * atan2(sqrt(a), sqrt(1 - a)) + distance = R * c + return distance \ No newline at end of file diff --git a/run.py b/run.py index 73dcb5b..800e26f 100644 --- a/run.py +++ b/run.py @@ -1,20 +1,21 @@ import time import json from helium import Helium -from gps import get_gps_data -def fire_ping(): +from gps import get_gps_data, get_dist +def fire_ping(last_gps): gps_data = get_gps_data() response = {} - if gps_data: + if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05: #response = helium.transact(json.dumps(gps_data or {})) or {} if gps_data["lat"] and gps_data["lon"]: response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))) - return response + return response, gps_data helium = Helium() +last_gps = {} while True: try: - response = fire_ping() + response, last_gps = fire_ping() print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) From 72463461164db031831dbfd72b359c8e73e3127c Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 15:31:27 -0700 Subject: [PATCH 121/130] updates --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index 800e26f..1a45836 100644 --- a/run.py +++ b/run.py @@ -15,7 +15,7 @@ def fire_ping(last_gps): last_gps = {} while True: try: - response, last_gps = fire_ping() + response, last_gps = fire_ping(last_gps) print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) From 1b1b0106eaf31e276fed87c1fe36ad0d0af005bb Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 17:04:18 -0700 Subject: [PATCH 122/130] updates --- run.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/run.py b/run.py index 1a45836..44a3c54 100644 --- a/run.py +++ b/run.py @@ -2,13 +2,33 @@ import json from helium import Helium from gps import get_gps_data, get_dist +import logging +import sys + +logger = logging.getLogger() +logger.setLevel(logging.INFO) +formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s', + '%m-%d-%Y %H:%M:%S') +file_handler = logging.FileHandler('/home/pi/run.log') +file_handler.setLevel(logging.DEBUG) +file_handler.setFormatter(formatter) + +logger.addHandler(file_handler) + def fire_ping(last_gps): + logging.info('Last GPS was '+str(last_gps)) gps_data = get_gps_data() + logging.info('Latest GPS is '+str(gps_date)) response = {} if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05: + logging.info('Wont send ping') #response = helium.transact(json.dumps(gps_data or {})) or {} if gps_data["lat"] and gps_data["lon"]: + logging.info('Beginning Ping') response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))) + logging.info('Ping response was '+str(response)) + else: + logging.info('Will send ping') return response, gps_data helium = Helium() From f0e7e940ff1c84f701398e7fd79260f897098715 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 17:05:18 -0700 Subject: [PATCH 123/130] updates --- run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.py b/run.py index 44a3c54..7dabc43 100644 --- a/run.py +++ b/run.py @@ -18,7 +18,7 @@ def fire_ping(last_gps): logging.info('Last GPS was '+str(last_gps)) gps_data = get_gps_data() - logging.info('Latest GPS is '+str(gps_date)) + logging.info('Latest GPS is '+str(gps_data)) response = {} if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05: logging.info('Wont send ping') From 203e93368ef364f10103c46763714b777493c457 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 17:06:53 -0700 Subject: [PATCH 124/130] updates --- run.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index 7dabc43..a1afec7 100644 --- a/run.py +++ b/run.py @@ -14,6 +14,13 @@ file_handler.setFormatter(formatter) logger.addHandler(file_handler) +def handle_exception(exc_type, exc_value, exc_traceback): + if issubclass(exc_type, KeyboardInterrupt): + sys.__excepthook__(exc_type, exc_value, exc_traceback) + return + logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback)) + +sys.excepthook = handle_exception def fire_ping(last_gps): logging.info('Last GPS was '+str(last_gps)) @@ -21,14 +28,14 @@ def fire_ping(last_gps): logging.info('Latest GPS is '+str(gps_data)) response = {} if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05: - logging.info('Wont send ping') + logging.info('Will send ping') #response = helium.transact(json.dumps(gps_data or {})) or {} if gps_data["lat"] and gps_data["lon"]: logging.info('Beginning Ping') response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))) logging.info('Ping response was '+str(response)) else: - logging.info('Will send ping') + logging.info('Wont send ping') return response, gps_data helium = Helium() @@ -39,6 +46,6 @@ def fire_ping(last_gps): print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) - except: + except e: print("oops") time.sleep(10) From 9151e95cfed666656a30d425b2ff8bda0dcbcf7e Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 17:10:18 -0700 Subject: [PATCH 125/130] updates --- run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index a1afec7..2cbb125 100644 --- a/run.py +++ b/run.py @@ -27,7 +27,7 @@ def fire_ping(last_gps): gps_data = get_gps_data() logging.info('Latest GPS is '+str(gps_data)) response = {} - if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05: + if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and (get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05): logging.info('Will send ping') #response = helium.transact(json.dumps(gps_data or {})) or {} if gps_data["lat"] and gps_data["lon"]: @@ -46,6 +46,6 @@ def fire_ping(last_gps): print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) - except e: + except: print("oops") time.sleep(10) From 4338e0f3c2d6cf5b7544c285c40dba96251aa03a Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Thu, 25 Aug 2022 17:10:40 -0700 Subject: [PATCH 126/130] updates --- gps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gps.py b/gps.py index 7242502..78bd710 100644 --- a/gps.py +++ b/gps.py @@ -23,4 +23,4 @@ def get_dist(lat1,lon1,lat2,lon2): a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) distance = R * c - return distance \ No newline at end of file + return distance or 10000 \ No newline at end of file From a8ffe0d4be757784b180302a5a4c612a01cc9fad Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Fri, 26 Aug 2022 08:00:57 -0700 Subject: [PATCH 127/130] updates --- gps.py | 26 +++++++++++++++++++++++++- run.py | 19 +++++++++---------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/gps.py b/gps.py index 78bd710..60c9c4f 100644 --- a/gps.py +++ b/gps.py @@ -21,6 +21,30 @@ def get_dist(lat1,lon1,lat2,lon2): dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 + print(a) + if not a: + return 0 c = 2 * atan2(sqrt(a), sqrt(1 - a)) distance = R * c - return distance or 10000 \ No newline at end of file + return distance + +def should_send_gps(new, old, last_sent_at): + if last_sent_at is None: + return True + if not new: + return False + if new and not old: + return True + if new.get("lat") is not None and new.get("lon") is not None and None in [old.get("lat"), old.get("lon")]: + return True + if None not in [new["lat"], new["lon"], old["lat"], old["lon"]]: + distance = get_dist(new["lat"], new["lon"], old["lat"], old["lon"]) + if distance < 0.05: + if (datetime.datetime.now() - last_sent_at).seconds > 60*5: + return True + else: + return False + else: + return True + else: + return False diff --git a/run.py b/run.py index 2cbb125..69c9523 100644 --- a/run.py +++ b/run.py @@ -1,7 +1,7 @@ import time import json from helium import Helium -from gps import get_gps_data, get_dist +from gps import get_gps_data, get_dist, should_send_gps import logging import sys @@ -22,27 +22,26 @@ def handle_exception(exc_type, exc_value, exc_traceback): sys.excepthook = handle_exception -def fire_ping(last_gps): +def fire_ping(last_gps, last_sent_at): logging.info('Last GPS was '+str(last_gps)) gps_data = get_gps_data() logging.info('Latest GPS is '+str(gps_data)) response = {} - if gps_data and not last_gps or (last_gps.get("lat") and last_gps.get("lon") and gps_data.get("lat") and gps_data.get("lon") and (get_dist(gps_data["lat"], gps_data["lon"], last_gps["lat"], last_gps["lon"])) > 0.05): + if should_send_gps(gps_data, last_gps, last_sent_at): logging.info('Will send ping') - #response = helium.transact(json.dumps(gps_data or {})) or {} - if gps_data["lat"] and gps_data["lon"]: - logging.info('Beginning Ping') - response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))) - logging.info('Ping response was '+str(response)) + response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))+","+str(int(gps_data["speed"] or 0))) + last_sent_at = datetime.datetime.now() + logging.info('Ping response was '+str(response)) else: logging.info('Wont send ping') - return response, gps_data + return response, gps_data, last_sent_at helium = Helium() last_gps = {} +last_sent_at = None while True: try: - response, last_gps = fire_ping(last_gps) + response, last_gps, last_sent_at = fire_ping(last_gps, last_sent_at) print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) From e359db661be0f3a6e33ea04f97b28603a51a68c1 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Fri, 26 Aug 2022 08:04:36 -0700 Subject: [PATCH 128/130] updates --- run.py | 1 + 1 file changed, 1 insertion(+) diff --git a/run.py b/run.py index 69c9523..deac5cd 100644 --- a/run.py +++ b/run.py @@ -1,3 +1,4 @@ +import datetime import time import json from helium import Helium From a86eb2464d516d715dde285ddd6d8b364e5c0590 Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Fri, 26 Aug 2022 11:31:46 -0700 Subject: [PATCH 129/130] updates --- run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run.py b/run.py index deac5cd..9f9c260 100644 --- a/run.py +++ b/run.py @@ -32,10 +32,11 @@ def fire_ping(last_gps, last_sent_at): logging.info('Will send ping') response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))+","+str(int(gps_data["speed"] or 0))) last_sent_at = datetime.datetime.now() + last_gps = gps_data logging.info('Ping response was '+str(response)) else: logging.info('Wont send ping') - return response, gps_data, last_sent_at + return response, last_gps, last_sent_at helium = Helium() last_gps = {} @@ -43,7 +44,6 @@ def fire_ping(last_gps, last_sent_at): while True: try: response, last_gps, last_sent_at = fire_ping(last_gps, last_sent_at) - print(response) time.sleep(int(response or "10")) #time.sleep(response.get("next_ping_at", 10)) except: From e27741fb9974f56599b9802da3704d53d61404fe Mon Sep 17 00:00:00 2001 From: Devin Gaffney Date: Tue, 30 Aug 2022 17:32:31 -0700 Subject: [PATCH 130/130] updates --- run.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/run.py b/run.py index 9f9c260..3db302b 100644 --- a/run.py +++ b/run.py @@ -31,9 +31,10 @@ def fire_ping(last_gps, last_sent_at): if should_send_gps(gps_data, last_gps, last_sent_at): logging.info('Will send ping') response = helium.transact(str(round(gps_data["lat"], 5))+","+str(round(gps_data["lon"], 5))+","+str(int(gps_data["speed"] or 0))) - last_sent_at = datetime.datetime.now() - last_gps = gps_data - logging.info('Ping response was '+str(response)) + if response == 10: + last_sent_at = datetime.datetime.now() + last_gps = gps_data + logging.info('Ping response was '+str(response)) else: logging.info('Wont send ping') return response, last_gps, last_sent_at