From b85ea6585d5033837c219ff37af2686b8168d749 Mon Sep 17 00:00:00 2001
From: Terra <terra@clerie.de>
Date: Sun, 24 Apr 2022 23:32:49 +0200
Subject: [PATCH] Add keys and message ID checking

---
 MultiNode/Configurator.py |  2 +-
 RasPi/Config.toml         |  7 ++++--
 RasPi/MultiNode.py        | 51 +++++++++++++++++++++++++++------------
 TODO                      |  1 -
 4 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/MultiNode/Configurator.py b/MultiNode/Configurator.py
index 954bac2..adea776 100644
--- a/MultiNode/Configurator.py
+++ b/MultiNode/Configurator.py
@@ -86,7 +86,7 @@ port.write(b"w")
 port.write(bytearray(config))
 
 server_key = 0x2e29b257521dc792
-client_key = 0x0#0x7ed64cce5b5d8e85
+client_key = 0x7ed64cce5b5d8e85
 port.write(b"k")
 port.write(struct.pack("<QQ", client_key, server_key))
 
diff --git a/RasPi/Config.toml b/RasPi/Config.toml
index c8884b3..3fdbf9b 100644
--- a/RasPi/Config.toml
+++ b/RasPi/Config.toml
@@ -3,6 +3,9 @@ address = 0x0001
 secret_key = 0x2e29b257521dc792
 time_interval = 5
 
-[node]
-address = 0x1FFF
+# Hexadecimal IDs
+[node.1FFF]
+secret_key = 0x7ed64cce5b5d8e85
+
+[node.1234]
 secret_key = 0x7ed64cce5b5d8e85
\ No newline at end of file
diff --git a/RasPi/MultiNode.py b/RasPi/MultiNode.py
index af256b3..aa9ab62 100644
--- a/RasPi/MultiNode.py
+++ b/RasPi/MultiNode.py
@@ -18,8 +18,7 @@ class MultiNode:
 	def __init__(self):
 		with open("Config.toml", "r") as config_file:
 			config = toml.loads(config_file.read())
-
-		print(config)
+			
 		self.server_address = config["server"]["address"]
 		self.server_secret_key = config["server"]["secret_key"]
 		# How often to send the time
@@ -27,6 +26,10 @@ class MultiNode:
 		self.devices = {}
 		self.last_time_message = time.time()
 
+		for node_id_str in config["node"]:
+			node_id = int(node_id_str, 16)
+			self.devices[node_id] = config["node"][node_id_str]
+
 		self.lora = LoRa(
 		    0,  # SPI channel
 		    25,  # Interrupt pin
@@ -83,15 +86,30 @@ class MultiNode:
 			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)
+		if not tx_id in self.devices:
+			with open("Config.toml", "r") as config_file:
+				config = toml.loads(config_file.read())
+				for node_id_str in config["node"]:
+					node_id = int(node_id_str, 16)
+					if not node_id in self.devices:
+						self.devices[node_id] = config["node"][node_id_str]
+			
+			if not tx_id in self.devices:
+				print(f"Error: Unrecognized device with ID {tx_id}")
+				return
+
+		hash_function = blake2s(key=self.devices[tx_id]["secret_key"].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
+		#	self.devices[tx_id] = {}
 
-		if not tx_id in self.devices:
-			self.devices[tx_id] = {}
+		if "last_message_id" in self.devices[tx_id]:
+			if msg_id <= self.devices[tx_id]["last_message_id"]:
+				print(f'Error, expected an ID larger than {self.devices[tx_id]["last_message_id"]} but got {msg_id}')
+				return
 		
 		self.devices[tx_id]["last_message_id"] = msg_id
 		self.decode_packet(self.devices[tx_id], data)
@@ -122,19 +140,20 @@ class MultiNode:
 	def print_data(self):
 		for device_id in self.devices:
 			device = self.devices[device_id]
-			print(f'Node {device_id} @ ID {device["last_message_id"]}:')
+			if "last_message_id" in device:
+				print(f'Node {device_id} @ ID {device["last_message_id"]}:')
 
-			if "status" in device:
-				print(f'\t{device["status"]["battery"]:.3f} V {device["status"]["temperature"]:.1f} °C')
+				if "status" in device:
+					print(f'\t{device["status"]["battery"]:.3f} V {device["status"]["temperature"]:.1f} °C')
 
-			if "sensors" in device:
-				for sensor in device["sensors"]:
-					if sensor["value"] == math.nan:
-						print(f'\tCH {sensor["channel"]} on Pin {sensor["pin"]}: ERROR')
-					else:
-						print(f'\tCH {sensor["channel"]} on Pin {sensor["pin"]}: {sensor["value"]:.4f} {self.sensor_type_table[sensor["type"]]}')
-			
-			print()
+				if "sensors" in device:
+					for sensor in device["sensors"]:
+						if sensor["value"] == math.nan:
+							print(f'\tCH {sensor["channel"]} on Pin {sensor["pin"]}: ERROR')
+						else:
+							print(f'\tCH {sensor["channel"]} on Pin {sensor["pin"]}: {sensor["value"]:.4f} {self.sensor_type_table[sensor["type"]]}')
+				
+				print()
 
 
 if __name__ == "__main__":
diff --git a/TODO b/TODO
index 4707e75..f2ba5db 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,3 @@
 - Add password protection to configuration
-- Webserver
 - More sensor types
 - Control of node outputs
\ No newline at end of file