From c30441a9f61b887ad17288e0d705dce1adbcf76d Mon Sep 17 00:00:00 2001
From: Terra <terra@clerie.de>
Date: Sun, 24 Apr 2022 03:41:28 +0200
Subject: [PATCH] more init

---
 .gitignore         |  1 +
 PyRH               |  1 -
 RasPi              |  1 -
 RasPi/Config.toml  |  7 +++++
 RasPi/MultiNode.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++
 RasPi/RXTest.py    | 55 +++++++++++++++++++++++++++++++++++
 6 files changed, 134 insertions(+), 2 deletions(-)
 create mode 100644 .gitignore
 delete mode 120000 PyRH
 delete mode 120000 RasPi
 create mode 100644 RasPi/Config.toml
 create mode 100644 RasPi/MultiNode.py
 create mode 100644 RasPi/RXTest.py

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c18dd8d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/PyRH b/PyRH
deleted file mode 120000
index c13d270..0000000
--- a/PyRH
+++ /dev/null
@@ -1 +0,0 @@
-/mnt/ssh/multinode/PyRH
\ No newline at end of file
diff --git a/RasPi b/RasPi
deleted file mode 120000
index 5785649..0000000
--- a/RasPi
+++ /dev/null
@@ -1 +0,0 @@
-/mnt/ssh/multinode/RasPi
\ No newline at end of file
diff --git a/RasPi/Config.toml b/RasPi/Config.toml
new file mode 100644
index 0000000..f7aead3
--- /dev/null
+++ b/RasPi/Config.toml
@@ -0,0 +1,7 @@
+[server]
+address = 0x0001
+secret_key = 0x2e29b257521dc792
+
+[node]
+address = 0x1FFF
+secret_key = 0x7ed64cce5b5d8e85
\ No newline at end of file
diff --git a/RasPi/MultiNode.py b/RasPi/MultiNode.py
new file mode 100644
index 0000000..53f2523
--- /dev/null
+++ b/RasPi/MultiNode.py
@@ -0,0 +1,71 @@
+from enum import IntEnum
+import struct
+from pyblake2 import blake2s
+import time
+import toml
+
+HASH_LENGTH = 8
+
+with open("Config.toml", "r") as config_file:
+    config = toml.loads(config_file.read())
+
+print(config)
+devices = {}
+
+
+class MessageType(IntEnum):
+    DeviceStatus = 1
+    SensorStatus = 2
+
+
+def decode_packet(data):
+    packet_type = data[0]
+
+    # match packet_type:
+    #    case MessageType.DeviceStatus:
+
+    if packet_type == MessageType.DeviceStatus:
+        return {"Battery voltage": struct.unpack('<f', data[1:5])[0]}
+
+    if packet_type == MessageType.SensorStatus:
+        channels_raw = struct.unpack('<H', data[1:3])[0]
+        channels = []
+        for i in range(16):
+            if (channels_raw >> i) & 1:
+                channels.append(i)
+        
+        sensor_data = []
+        for i in range(len(channels)):
+            offset = i * 6
+            sensor_data.append({
+                "channel": channels[i],
+                "type": data[3 + offset],
+                "pin": data[4 + offset],
+                "value": struct.unpack('<f', data[5 + offset : 9 + offset])[0]
+            })
+        return sensor_data
+
+
+def process_packet(payload):
+    rx_id = int.from_bytes(payload.message[0:2], byteorder="little")
+    tx_id = int.from_bytes(payload.message[2:4], byteorder="little")
+    msg_id = int.from_bytes(payload.message[4:8], byteorder="little")
+    length = payload.message[8]
+    data = payload.message[9: 9 + length]
+    data_hash = payload.message[9 + length: 9 + length + HASH_LENGTH]
+
+    if len(payload.message) != length + 9 + HASH_LENGTH:
+        print(
+            f"Invalid length! Expected {length + 9 + HASH_LENGTH} actual {len(payload.message)}")
+        return
+
+    hash_function = blake2s(key=0x0.to_bytes(8, "little"), digest_size=8)
+    hash_function.update(payload.message[: -HASH_LENGTH])
+
+    if hash_function.digest() != data_hash:
+        print(
+            f"Hash doesn't match! Expected {hash_function.digest()} got {data_hash}")
+        return
+
+    # print(f"{tx_id} #{msg_id}: {decode_packet(data):.3f} V, {payload.rssi} dB(?) RSSI, {payload.snr} dB(?) SNR {(time.clock_gettime_ns(0)) / 1e9}")
+    print(f"{tx_id} #{msg_id}: {data.hex()} {decode_packet(data)}, {payload.rssi} dB(?) RSSI, {payload.snr} dB(?) SNR {(time.clock_gettime_ns(0)) / 1e9}")
diff --git a/RasPi/RXTest.py b/RasPi/RXTest.py
new file mode 100644
index 0000000..a93dbb8
--- /dev/null
+++ b/RasPi/RXTest.py
@@ -0,0 +1,55 @@
+from pyLoraRFM9x import LoRa, ModemConfig
+import MultiNode
+
+#class MessageType(IntEnum):
+#    DeviceStatus = 1;
+#
+#def decode_packet(data):
+#    packet_type = data[0]
+#    
+#    #match packet_type:
+#    #    case MessageType.DeviceStatus:
+#    
+#    if packet_type == MessageType.DeviceStatus:
+#        return struct.unpack('f', data[1:5])[0]
+
+# This is our callback function that runs when a message is received
+def on_recv(payload):
+    #print("From:", payload.header_from)
+    #print("Received:", payload.message)
+    #print("RSSI: {}; SNR: {}".format(payload.rssi, payload.snr))
+    MultiNode.process_packet(payload)
+    #print(payload.message.hex())
+    #rx_id = int.from_bytes(payload.message[0:2], byteorder="little")
+    #tx_id = int.from_bytes(payload.message[2:4], byteorder="little")
+    #msg_id = int.from_bytes(payload.message[4:8], byteorder="little")
+    #length = payload.message[8]
+    #data = payload.message[9 : 9 + length]
+    #data_hash = payload.message[9 + length : 9 + length + HASH_LENGTH]
+    #
+    #if len(payload.message) != length + 9 + HASH_LENGTH:
+    #    print(f"Invalid length! Expected {length + 9 + HASH_LENGTH} actual {len(payload.message)}")
+    #    return
+    #
+    #hash_function = blake2s(key=0x0.to_bytes(8, "little"), digest_size=8)
+    #hash_function.update(payload.message[: -HASH_LENGTH])
+#
+    #if hash_function.digest() != data_hash:
+    #    print(f"Hash doesn't match! Expected {hash_function.digest()} got {data_hash}")
+    #    return
+    
+    #print(f"Received {struct.unpack('f', data[1:])[0]:.3f} V from {tx_id} with destination {rx_id} and {payload.rssi} dB(?) RSSI and {payload.snr} dB(?) SNR")
+    #print(f"{tx_id} #{msg_id}: {decode_packet(data):.3f} V, {payload.rssi} dB(?) RSSI, {payload.snr} dB(?) SNR {(time.clock_gettime_ns(0) - start_time) / 1e9}")
+
+
+# Use chip select 1. GPIO pin 5 will be used for interrupts and set reset pin to 25
+# The address of this device will be set to 2
+lora = LoRa(0, 25, 255, reset_pin = 22, modem_config=ModemConfig.Bw125Cr45Sf128, tx_power=14, freq=868, acks=False)#, receive_all=True)
+lora.cad_timeout = 1
+lora.on_recv = on_recv
+lora.set_mode_rx()
+
+import time
+
+while True:
+    time.sleep(0.5)
\ No newline at end of file