From d755e0a83d7faa4528395ea74fcd482edb281cb8 Mon Sep 17 00:00:00 2001 From: Nick Art Date: Fri, 6 Dec 2024 18:51:33 -0500 Subject: [PATCH 1/2] Networking Restructuring Base Networking is now completely modular and separate from Smart Systems Platform, can be used with any ESP32, the ssp_networking is an add on, introducing more custom commands also specifically for the Smart Systems Platform --- software/.DS_Store | Bin 12292 -> 12292 bytes software/networking/.DS_Store | Bin 6148 -> 6148 bytes software/networking/networking.py | 450 ++++-------------- software/networking/networking_commands.py | 155 ------- software/networking/ssp_networking.py | 513 +++++++++++++++++++++ software/release/config.py | 6 +- 6 files changed, 594 insertions(+), 530 deletions(-) delete mode 100644 software/networking/networking_commands.py create mode 100644 software/networking/ssp_networking.py diff --git a/software/.DS_Store b/software/.DS_Store index a490800680382215eccfbc7ad8c87182f61f23b0..3b6d6820e63e4eec46d4c50fdbe20c8aca8ec933 100644 GIT binary patch delta 85 zcmZokXi1phdGU^hRb%wz!;$<3+)KbSdFij#Aa^7C^THw%g^U_@{y9~70?yixQF e(`FmV^K26vIyZAGw6SfD7At1l%%af?VF3Wz6dc_E delta 200 zcmZokXi1ph&uFkQU^hRb{A2+Z$<3+)KbSWgiA-VK{9N=56DKP}2}3>*=1f*oP^^dZ z7>aY!4TF>Oa|;;2;Nxr{g(RDs@8Xh_lb-|>k delta 63 zcmZoMXffEZk4;^SA&()Ip@gBFA)ld$A)6r+$WLd8XGjL}bAd1s$WLJ?p6tl3I(Z*k O+QhQyo7p-3@&f<`0uej_ diff --git a/software/networking/networking.py b/software/networking/networking.py index b1f9622..6367a4f 100644 --- a/software/networking/networking.py +++ b/software/networking/networking.py @@ -1,14 +1,10 @@ import network -import machine -from config import mysecrets, config, whitelist, i2c_dict, version, msg_codes, msg_subcodes, networking_keys import time import ubinascii -import urequests import espnow import gc import struct import json -import os class Networking: @@ -22,6 +18,11 @@ def __init__(self, infmsg=False, dbgmsg=False, errmsg=False, admin=False, initti self.dbgmsg = dbgmsg self.errmsg = errmsg self.admin = admin + self.config = {"Name": None, + "Configuration": None, + "id": None, + "Version": None, + } #Just as an example, can include more information here, but for interoperability purposes please keep the basic four attributes self._staif = network.WLAN(network.STA_IF) self._apif = network.WLAN(network.AP_IF) @@ -29,11 +30,7 @@ def __init__(self, infmsg=False, dbgmsg=False, errmsg=False, admin=False, initti self.sta = self.Sta(self, self._staif) self.ap = self.Ap(self, self._apif) self.aen = self.Aen(self) - - self.config = config - self.config["id"] = ubinascii.hexlify(machine.unique_id()).decode() - self.config["version"] = ''.join(str(value) for value in version.values()) - self.version = version + if infmsg: print(f"{(time.ticks_ms() - self.inittime) / 1000:.3f} Networking initialised and ready") @@ -42,8 +39,6 @@ def cleanup(self): self.aen.cleanup() self._staif.active(False) self._apif.active(False) - #timer.deinit() - irq_handler = None def iprint(self, message): if self.infmsg: @@ -122,17 +117,6 @@ def set_channel(self, number): self._sta.config(channel=number) self.master.dprint(f"STA channel set to {number}") - def get_joke(self): - self.master.dprint("sta.get_joke") - try: - reply = urequests.get('https://v2.jokeapi.dev/joke/Programming') - if reply.status_code == 200: - joke = reply.json() - return joke.get('setup', '') + '\n' + joke.get('delivery', joke.get('joke', '')) - except Exception as e: - self.master.eprint('Error fetching joke:', str(e)) - return None - class Ap: def __init__(self, master, _apif): self.master = master @@ -193,20 +177,13 @@ def __init__(self, master): self.received_sensor_data = {} self.received_rssi_data = {} self._irq_function = None - self._pause_function = None + self.custom_cmd = None + self.custom_inf = None + self.custom_ack = None self.boops = 0 self.ifidx = 0 # 0 sends via sta, 1 via ap # self.channel = 0 - self._whitelist = whitelist - - # Flags - self._pairing_enabled = True - self._pairing = False - self._paired = False - self._paired_macs = [] - self._running = True - self._aen.irq(self._irq) self.master.iprint("ESP-NOW initialised and ready") @@ -217,33 +194,34 @@ def cleanup(self): self._aen.active(False) # add delete buffers and stuff - def update_peer(self, peer_mac, name=None, channel=None, ifidx=None): + def update_peer(self, peer_mac, peer_config=None, channel=None, ifidx=None): self.master.dprint("aen.update_peer") if peer_mac in self._peers: try: - if name is not None: - self._peers[peer_mac]['name'] = name + if peer_config is not None: + self._peers[peer_mac].update(peer_config) if channel is not None: self._peers[peer_mac]['channel'] = channel if ifidx is not None: self._peers[peer_mac]['ifidx'] = ifidx - self.master.dprint(f"Peer {peer_mac} updated to channel {channel}, ifidx {ifidx} and name {name}") + self.master.dprint(f"Peer {peer_mac} updated to channel {channel}, ifidx {ifidx} and name {self._peers[peer_mac]['name']}") except OSError as e: self.master.eprint(f"Error updating peer {peer_mac}: {e}") return self.master.iprint(f"Peer {peer_mac} not found") - def add_peer(self, peer_mac, peer_name=None, peer_id=None, peer_configuration=None, peer_version=None, channel=None, ifidx=None): + def add_peer(self, peer_mac, peer_config=None, channel=None, ifidx=None): self.master.dprint("aen.add_peer") if peer_mac not in self._peers: try: - self._peers[peer_mac] = {'channel': channel, 'ifidx': ifidx, 'name': peer_name, 'id': peer_id, 'configuration': peer_configuration, 'version': peer_version} - self.master.dprint(f"Peer {peer_mac} added with channel {channel}, ifidx {ifidx} and name {peer_name}") + self._peers[peer_mac] = {'channel': channel, 'ifidx': ifidx} + self._peers[peer_mac].update(peer_config) + self.master.dprint(f"Peer {peer_mac} added with channel {channel}, ifidx {ifidx} and name {self._peers[peer_mac]['name']}") except OSError as e: self.master.eprint(f"Error adding peer {peer_mac}: {e}") else: self.master.dprint(f"Peer {peer_mac} already exists, updating") - self.update_peer(peer_mac, peer_name, channel, ifidx) + self.update_peer(peer_mac, peer_config, channel, ifidx) def remove_peer(self, peer_mac): self.master.dprint("aen.remove_peers") @@ -270,44 +248,39 @@ def rssi(self): return self._aen.peers_table # Send cmds - def send_command(self, msg_subkey, mac, payload=None, channel=None, ifidx=None, sudo=False): + def send_command(self, msg_code, msg_subcode, mac, payload=None, channel=None, ifidx=None): self.master.dprint("aen.send_command") - if sudo and isinstance(payload, list): - payload.append("sudo") - elif sudo and payload is None: - payload = ["sudo"] - else: - payload = [payload, "sudo"] - if (msg_key := "cmd") and msg_subkey in msg_subcodes[msg_key]: - self.master.iprint(f"Sending {msg_subkey} ({bytes([msg_subcodes[msg_key][msg_subkey]])}) command to {mac} ({self.peer_name(mac)})") - self._compose(mac, payload, msg_codes[msg_key], msg_subcodes[msg_key][msg_subkey], channel, ifidx) - else: - self.master.iprint(f"Command {msg_subkey} not found") + self._compose(mac, payload, msg_code, msg_subcode, channel, ifidx) gc.collect() - def ping(self, mac, channel=None, ifidx=None): + def ping(self, mac, channel=None, ifidx=None): #Ping self.master.dprint("aen.ping") if bool(self.ifidx): send_channel = self.master.ap.channel() else: send_channel = self.master.sta.channel() - self.send_command("Ping", mac, [send_channel, self.ifidx, self.master.config], channel, ifidx) # sends channel, ifidx and name + self.send_command(0x01, 0x10, mac, [send_channel, self.ifidx, self.master.config], channel, ifidx) # sends channel, ifidx and name - def boop(self, mac, channel=None, ifidx=None, sudo=False): + def boop(self, mac, channel=None, ifidx=None): #"RSSI/Status/Config-Boop" self.master.dprint("aen.boop") - self.send_command("RSSI/Status/Config-Boop", mac, None, channel, ifidx, sudo) + self.send_command(0x01, 0x15, mac, None, channel, ifidx) def echo(self, mac, message, channel=None, ifidx=None): self.master.dprint("aen.echo") - try: + if len(str(message)) > 241: + try: + self.master.iprint(f"Sending echo ({message}) to {mac} ({self.peer_name(mac)})") + except Exception as e: + self.master.eprint(f"Sending echo to {mac} ({self.peer_name(mac)}), but error printing message content: {e}") + else: self.master.iprint(f"Sending echo ({message}) to {mac} ({self.peer_name(mac)})") - except Exception as e: - self.master.eprint(f"Sending echo to {mac} ({self.peer_name(mac)}), but error printing message content: {e}") - self._compose(mac, message, 0x01, 0x15, channel, ifidx) + self.send_command(0x01, 0x15, mac, message, channel, ifidx) gc.collect() + def send_message(self, mac, message, channel=None, ifidx=None): + self.send(mac, message, channel, ifidx) def send(self, mac, message, channel=None, ifidx=None): - self.master.dprint("aen.message") + self.master.dprint("aen.send_message") if len(str(message)) > 241: try: self.master.iprint( @@ -319,10 +292,8 @@ def send(self, mac, message, channel=None, ifidx=None): self.master.iprint(f"Sending message ({message}) to {mac} ({self.peer_name(mac)})") self._compose(mac, message, 0x02, 0x22, channel, ifidx) gc.collect() - self.master.dprint(f"Free memory: {gc.mem_free()}") - def send_sensor(self, mac, message, channel=None, - ifidx=None): # message is a dict, key is the sensor type and the value is the sensor value + def send_data(self, mac, message, channel=None,ifidx=None): # message is a dict, key is the sensor type and the value is the sensor value, fix name!!!!!!! self.master.dprint("aen.message") try: self.master.iprint(f"Sending sensor data ({message}) to {mac} ({self.peer_name(mac)})") @@ -356,7 +327,7 @@ def _irq(self): if self.master.admin: try: self._receive() - if self._irq_function and self.check_messages() and self._running: + if self._irq_function and self.check_messages(): self._irq_function() gc.collect() return @@ -366,7 +337,7 @@ def _irq(self): raise SystemExit("Stopping networking execution. ctrl-c or ctrl-d again to stop main code") # in thonny stops library code but main code keeps running, same in terminal else: self._receive() - if self._irq_function and self.check_messages() and self._running: + if self._irq_function and self.check_messages(): self._irq_function() gc.collect() return @@ -374,6 +345,18 @@ def _irq(self): def irq(self, func): self.master.dprint("aen.irq") self._irq_function = func + + def cmd(self, func): + self.master.dprint("aen.cmd") + self.custom_cmd = func + + def inf(self, func): + self.master.dprint("aen.inf") + self.custom_inf = func + + def ack(self, func): + self.master.dprint("aen.ack") + self.custom_ack = func def _send(self, peers_mac, messages, channel, ifidx): self.master.dprint("aen._send") @@ -426,9 +409,9 @@ def _compose(self, peer_mac, payload=None, msg_type=0x02, subtype=0x22, channel= if isinstance(peer_mac, list): for peer_macs in peer_mac: if peer_macs not in self._peers: - self.add_peer(peer_macs, None, None, None, None, channel, ifidx) + self.add_peer(peer_macs, None, channel, ifidx) elif peer_mac not in self._peers: - self.add_peer(peer_mac, None, None, None, None, channel, ifidx) + self.add_peer(peer_mac, None, channel, ifidx) def __encode_payload(): self.master.dprint("aen.__encode_payload") @@ -602,21 +585,18 @@ def __process_message(sender_mac, message, receive_timestamp): return # Handle the message based on type - if msg_type == (msg_key := msg_codes["cmd"]): # Command Message + if msg_type == (msg_key := 0x01): # Command Message __handle_cmd(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload if payload else None, msg_key) - elif msg_type == (msg_key := msg_codes["inf"]): # Informational Message + elif msg_type == (msg_key := 0x02): # Informational Message __handle_inf(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload if payload else None, msg_key) - elif msg_type == (msg_key := msg_codes["ack"]): # Acknowledgement Message + elif msg_type == (msg_key := 0x03): # Acknowledgement Message __handle_ack(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload if payload else None, msg_key) else: self.master.iprint(f"Unknown message type from {sender_mac} ({self.peer_name(sender_mac)}): {message}") - def __check_authorisation(sender_mac, payload): - return sender_mac in self._whitelist or payload == "sudo" or payload[-1] == "sudo" - def __send_confirmation(msg_type, recipient_mac, msg_subkey_type, payload=None, error=None): if msg_type == "Success": self._compose(recipient_mac, [msg_subkey_type, payload], 0x03, 0x11) @@ -628,321 +608,44 @@ def __send_confirmation(msg_type, recipient_mac, msg_subkey_type, payload=None, def __handle_cmd(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload, msg_key): self.master.dprint(f"aen.__handle_cmd") payload = __decode_payload(payload_type, payload) - if (msg_subkey := "Reboot") and subtype == msg_subcodes[msg_key][msg_subkey]: # Reboot - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) - machine.reset() - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Firmware-Update") and subtype == msg_subcodes[msg_key][msg_subkey]: # Firmware-Update - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - # Insert update logic here - self.master.iprint("no update logic written just yet") - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "File-Update") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Update - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - # Insert update logic here - self.master.iprint("No update logic written just yet") - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "File-Download") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Download - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - # should return a list with a link and the list of files to download - if __check_authorisation(sender_mac, payload): - try: - # import mip - # base = payload[0] - # files_to_copy = payload[1] - # if files_to_copy is None: - # mip.install(base) - # else: - # for f in files_to_copy: - # mip.install(base + f) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Web-Repl") and subtype == msg_subcodes[msg_key][msg_subkey]: # Web-Repl - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - # should be a list with name and password - if __check_authorisation(sender_mac, payload): - try: - # add logic to connect to Wi-Fi and set up webrepl - webrepl.start() - self.master.sta.connect(payload[0], payload[1]) - link = "webrepl link" - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", link) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "File-Run") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Run - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.iprint("Execute logic not implemented") - # insert run logic here - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Set-Admin") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Admin Bool - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - self.master.iprint(f"Received Set-Admin command: self.admin set to {payload[0]}") - try: - self.master.admin = payload[0] - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Whitelist-Add") and subtype == msg_subcodes[msg_key][msg_subkey]: # Whitelist-Add - Add Admin macs to _whitelist + if (msg_subkey := "Ping") and subtype == 0x01 or subtype == 0x10: # Ping self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - self.master.iprint(f"Received add admin macs to _whitelist command, added {payload[0]} and {payload[1]}") - try: - self._whitelist.append(payload[0]) - self._whitelist.append(payload[1]) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Config-Change") and subtype == msg_subcodes[msg_key][msg_subkey]: # change config - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.config["configuration"] = payload[0] - if payload[1]: - file_path = "config.py" - with open(file_path, "r") as f: - lines = f.readlines() - with open(file_path, "w") as f: - for line in lines: - if line.startswith(' "configuration": '): - f.write(f' "configuration": "{payload[0]}",\n') - else: - f.write(line) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Name-Change") and subtype == msg_subcodes[msg_key][msg_subkey]: # change name - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.config["name"] = payload[0] - if payload[1]: - file_path = "config.py" - with open(file_path, "r") as f: - lines = f.readlines() - with open(file_path, "w") as f: - for line in lines: - if line.startswith(' "name": '): - f.write(f' "name": "{payload[0]}"\n') - else: - f.write(line) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Ping") and subtype == msg_subcodes[msg_key][msg_subkey]: # Ping - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - self.add_peer(sender_mac, payload[2]["name"], payload[2]["id"], payload[2]["configuration"], payload[2]["version"], payload[0], payload[1]) + self.add_peer(sender_mac, payload[2], payload[0], payload[1]) if bool(self.ifidx): channel = self.master.ap.channel() else: channel = self.master.sta.channel() response = [channel, self.ifidx, self.master.config, send_timestamp] self._compose(sender_mac, response, 0x03, 0x10) -# elif (msg_subkey := "Pair") and subtype == msg_subcodes[msg_key][msg_subkey]: # Pair #add something that checks that the messages are from the same mac # BREAKS NETWORK -# self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") -# if self._pairing_enabled and networking_keys["handshake_key_1"] == payload: -# self._pairing = True -# self.pair(sender_mac, networking_keys["handshake_key_2"]) -# # some timer for if key 3 is not received to reset states -# elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_2"] == payload: -# self._paired = True -# self._paired_macs.append(sender_mac) -# self.pair(sender_mac, networking_keys["handshake_key_3"]) -# # some timer that sets to false if key 4 is not received -# elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_3"] == payload: -# try: -# # Insert pairing logic here do a reverse handshake -# self._paired = True -# self._paired_macs.append(sender_mac) -# self.pair(sender_mac, networking_keys["handshake_key_4"]) -# self.master.iprint("no pairing logic written just yet") -# __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) -# except Exception as e: -# self.master.eprint(f"Error: {e} with payload: {payload}") -# __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) -# elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_3"] == payload: -# self._paired = True -# # remove timer from before -# else: -# __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", "Pairing disabled", payload) -# elif (msg_subkey := "Set-Pair") and subtype == msg_subcodes[msg_key][msg_subkey]: # Enable pairing mode -# self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") -# if __check_authorisation(sender_mac, payload): -# try: -# self._pairing_enabled = payload[0] -# __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) -# except Exception as e: -# self.master.eprint(f"Error: {e} with payload: {payload}") -# __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) -# else: -# __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "RSSI/Status/Config-Boop") and subtype == msg_subcodes[msg_key][msg_subkey]: # RSSI/Status/Config Boop + elif (msg_subkey := "RSSI/Status/Config-Boop") and subtype == 0x03 or subtype == 0x13: # RSSI/Status/Config Boop self.boops = self.boops + 1 self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)}), Received total of {self.boops} boops!") try: self._compose(sender_mac, [self.master.config, self.master.version, self.master.sta.mac, self.master.ap.mac, self.rssi()], 0x02, 0x20) # [ID, Name, Config, Version, sta mac, ap mac, rssi] except Exception as e: __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - elif (msg_subkey := "Directory-Get") and subtype == msg_subcodes[msg_key][msg_subkey]: # Get List of Files # BREAKS NETWORK - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - try: - def ___list_all_files(path): - result = [] - entries = os.listdir(path) - for entry in entries: - full_path = path + "/" + entry - try: - if os.stat(full_path)[0] & 0x4000: - result.extend(___list_all_files(full_path)) - else: - result.append(full_path) - except OSError: - # Handle inaccessible files or directories - continue - return result - - start_path = '.' - all_files = ___list_all_files(start_path) - self._compose(sender_mac, all_files, 0x02, 0x20) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - elif (msg_subkey := "Echo") and subtype == msg_subcodes[msg_key][msg_subkey]: # Echo + elif (msg_subkey := "Echo") and subtype == subtype == 0x02 or subtype == 0x15: # Echo self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)}): {__decode_payload(payload_type, payload)}") # Check i or d self._compose(sender_mac, payload, 0x03, 0x15) - elif (msg_subkey := "Resend") and subtype == msg_subcodes[msg_key][msg_subkey]: # Resend lost long messages - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - self.master.iprint("Long_sent_buffer disabled due to memory constraints") - elif (msg_subkey := "WiFi-Connect") and subtype == msg_subcodes[msg_key][msg_subkey]: # Connect to Wi-Fi - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.sta.connect(payload[0], payload[1]) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "WiFi-Disconnect") and subtype == msg_subcodes[msg_key][ - msg_subkey]: # Disconnect from Wi-Fi - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.sta.disconnect() - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "AP-Enable") and subtype == msg_subcodes[msg_key][msg_subkey]: # Enable AP - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - ssid = payload[0] - if ssid == "": - ssid = self.master.config["name"] - password = payload[1] - self.master.ap.setap(ssid, password) - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.eprint(f"Error: {e} with payload: {payload}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "AP-Disable") and subtype == msg_subcodes[msg_key][msg_subkey]: # Disable AP - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - payload = __decode_payload(payload_type, payload) # should return a list of desired name, password and max clients - if __check_authorisation(sender_mac, payload): - try: - self.master.ap.deactivate() - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - self.master.iprint(f"Error: {e}") - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Pause") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Pause - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.iprint(f"Received pause command: {payload[0]}") - self._running = False - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - if self._pause_function: - self._pause_function() # calls the custom set pause function to display a screen - while not self._running: - time.sleep(0.5) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") - elif (msg_subkey := "Resume") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Continue - self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") - if __check_authorisation(sender_mac, payload): - try: - self.master.iprint(f"Received continue command: {payload}") - self.master._running = True - __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) - except Exception as e: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) - else: - __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") else: self.master.iprint(f"Unknown command subtype from {sender_mac} ({self.peer_name(sender_mac)}): {subtype}") + if self.custom_cmd: + self.custom_cmd(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key) def __handle_inf(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload, msg_key): self.master.dprint("aen.__handle_inf") payload = __decode_payload(payload_type, payload) - if (msg_subkey := "RSSI/Status/Config-Boop") and subtype == msg_subcodes[msg_key][msg_subkey]: # RSSI/Status/Config-Boop + if (msg_subkey := "RSSI/Status/Config-Boop") and subtype == 0x00 or subtype == 0x20: # RSSI/Status/Config-Boop self.master.iprint(f"{msg_subkey} ({subtype}) data received from {sender_mac} ({self.peer_name(sender_mac)}): {payload}") self.received_rssi_data[sender_mac] = payload # __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) #confirm message recv - elif (msg_subkey := "Sensor") and subtype == msg_subcodes[msg_key][msg_subkey]: # Sensor Data + elif (msg_subkey := "Data") and subtype == 0x01 or subtype == 0x21: # Sensor Data payload["time_sent"] = send_timestamp payload["time_recv"] = receive_timestamp self.master.iprint(f"{msg_subkey} ({subtype}) data received from {sender_mac} ({self.peer_name(sender_mac)}): {payload}") self.received_sensor_data[sender_mac] = payload # __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) #confirm message recv - elif (msg_subkey := "Message") and subtype == msg_subcodes[msg_key][msg_subkey]: # Message / Other + elif (msg_subkey := "Message") and subtype == 0x02 or subtype == 0x22: # Message / Other self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}): {payload}") self._received_messages.append((sender_mac, payload, receive_timestamp)) self._received_messages_size.append(len(payload)) @@ -951,35 +654,36 @@ def __handle_inf(sender_mac, subtype, send_timestamp, receive_timestamp, payload self._received_messages.pop(0) self._received_messages_size.pop(0) # __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) #confirm message recv - elif (msg_subkey := "Directory") and subtype == msg_subcodes[msg_key][msg_subkey]: # File Directory - self.master.iprint(f"{msg_subkey} ({subtype}) data received from {sender_mac} ({self.peer_name(sender_mac)}): {payload}") - # __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) #confirm message recv else: self.master.iprint(f"Unknown info subtype from {sender_mac} ({self.peer_name(sender_mac)}): {subtype}") + if self.custom_inf: + self.custom_inf(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key) def __handle_ack(sender_mac, subtype, send_timestamp, receive_timestamp, payload_type, payload, msg_key): self.master.dprint("aen.__handle_ack") payload = __decode_payload(payload_type, payload) - if (msg_subkey := "Pong") and subtype == msg_subcodes[msg_key][msg_subkey]: # Pong - self.add_peer(sender_mac, payload[2]["name"], payload[2]["id"], payload[2]["configuration"], payload[2]["version"], payload[0], payload[1]) + if (msg_subkey := "Pong") and subtype == 0x10: # Pong + self.add_peer(sender_mac, payload[2], payload[0], payload[1]) self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}), {receive_timestamp - payload[3]}") - elif (msg_subkey := "Echo") and subtype == msg_subcodes[msg_key][msg_subkey]: # Echo + elif (msg_subkey := "Echo") and subtype == 0x15: # Echo self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}), {__decode_payload(payload_type, payload)}") - elif (msg_subkey := "Success") and subtype == msg_subcodes[msg_key][msg_subkey]: # Success + elif (msg_subkey := "Success") and subtype == 0x11: # Success # payload should return a list with a cmd type and payload - self.master.iprint(f"Cmd {msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}) for type {payload[0]} with payload {payload[1]}") + self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}) for type {payload[0]} with payload {payload[1]}") # add to ack buffer - elif (msg_subkey := "Fail") and subtype == msg_subcodes[msg_key][msg_subkey]: # Fail + elif (msg_subkey := "Fail") and subtype == 0x12: # Fail # payload should return a list with a cmd type, error and payload - self.master.iprint(f"Cmd {msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}) for type {payload[0]} with error {payload[1]} and payload {payload[2]}") + self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}) for type {payload[0]} with error {payload[1]} and payload {payload[2]}") # add to ack buffer - elif (msg_subkey := "Confirm") and subtype == msg_subcodes[msg_key][msg_subkey]: # Confirmation + elif (msg_subkey := "Confirm") and subtype == 0x13: # Confirmation # payload should return a list with message type and payload self.master.iprint(f"{msg_subkey} ({subtype}) received from {sender_mac} ({self.peer_name(sender_mac)}) for type {payload[0]} with payload {payload[1]}") # add to ack buffer else: self.master.iprint(f"Unknown ack subtype from {sender_mac} ({self.peer_name(sender_mac)}): {subtype}, Payload: {payload}") - # Insert more acknowledgement logic here and/or add message to acknowledgement buffer + if self.custom_ack: + self.custom_ack(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key) + # Insert more acknowledgement logic here and/or add message to acknowledgement buffer if self._aen.any(): for mac, data in self._aen: @@ -994,4 +698,4 @@ def __handle_ack(sender_mac, subtype, send_timestamp, receive_timestamp, payload break # message structure (what kind of message types do I need?: Command which requires me to do something (ping, pair, change state(update, code, mesh mode, run a certain file), Informational Message (Sharing Sensor Data and RSSI Data) -# | Header (1 byte) | Type (1 byte) | Subtype (1 byte) | Timestamp(ms ticks) (4 bytes) | Payload type (1) | Payload (variable) | Checksum (1 byte) | \ No newline at end of file +# | Header (1 byte) | Type (1 byte) | Subtype (1 byte) | Timestamp(ms ticks) (4 bytes) | Payload type (1) | Payload (variable) | Checksum (1 byte) | diff --git a/software/networking/networking_commands.py b/software/networking/networking_commands.py deleted file mode 100644 index 0d5b6d8..0000000 --- a/software/networking/networking_commands.py +++ /dev/null @@ -1,155 +0,0 @@ -class Commands: - def __init__(self, networking): - self.master = networking - self.aen = networking.aen - - def ping(self, mac, channel=None, ifidx=None): - self.master.dprint("net.cmd.ping") - self.aen.ping(mac, channel, ifidx) - - def echo(self, mac, message, channel=None, ifidx=None): - self.master.dprint("net.cmd.echo") - self.aen.echo(mac, message, channel, ifidx) - - def boop(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("aen.boop") - self.aen.boop(mac, channel, ifidx, sudo) - - def send(self, mac, message, channel=None, ifidx=None): - self.master.dprint("net.cmd.message") - self.aen.send(mac, message, channel, ifidx) - - def broadcast(self, message, channel=None, ifidx=None): - self.master.dprint("net.cmd.broadcast") - mac = b'\xff\xff\xff\xff\xff\xff' - self.send(mac, message, channel, ifidx) - - def send_sensor(self, mac, message, channel=None,ifidx=None): # message is a dict, key is the sensor type and the value is the sensor value - self.master.dprint("net.cmd.message") - - - - - def reboot(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.reboot") - self.aen.send_command("Reboot", mac, None, channel, ifidx, sudo) - - def firmware_update(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.firmware_update") - self.aen.send_command("Firmware-Update", mac, None, channel, ifidx, sudo) - - def file_update(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_update") - self.aen.send_command("File-Update", mac, None, channel, ifidx, sudo) - - def file_download(self, mac, link, file_list=None, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_download") - self.aen.send_command("File-Download", mac, [link, file_list], channel, ifidx, sudo) - - def web_repl(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.web_repl") - self.master.ap.set_ap(ap_name := self.master.config["name"], password := networking_keys["default_ap_key"]) - self.aen.send_command("Web-Repl", mac, [ap_name, password], channel, ifidx, sudo) - # await success message and if success False disable AP or try again - - def file_run(self, mac, filename, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_run") - self.aen.send_command("File-Run", mac, filename, channel, ifidx, sudo) - - def admin_set(self, mac, new_bool, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.admin_set") - self.aen.send_command("Admin-Set", mac, new_bool, channel, ifidx, sudo) - - def whitelist_add(self, mac, mac_list=None, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.whitelist_add") - if mac_list is not None: - mac_list = [self.master.sta.mac, self.master.ap.mac] - self.aen.send_command("Whitelist-Add", mac, mac_list, channel, ifidx, sudo) - - def config_change(self, mac, new_config, hardcode=False, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.config_change") - self.aen.send_command("Config-Change", mac, [new_config, hardcode], channel, ifidx, sudo) - - def reboot(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.reboot") - self.aen.send_command("Reboot", mac, None, channel, ifidx, sudo) - - def firmware_update(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.firmware_update") - self.aen.send_command("Firmware-Update", mac, None, channel, ifidx, sudo) - - def file_update(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_update") - self.aen.send_command("File-Update", mac, None, channel, ifidx, sudo) - - def file_download(self, mac, link, file_list=None, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_download") - self.aen.send_command("File-Download", mac, [link, file_list], channel, ifidx, sudo) - - def web_repl(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.web_repl") - self.master.ap.set_ap(ap_name := self.master.config["name"], password := networking_keys["default_ap_key"]) - self.aen.send_command("Web-Repl", mac, [ap_name, password], channel, ifidx, sudo) - # await success message and if success False disable AP or try again - - def file_run(self, mac, filename, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.file_run") - self.aen.send_command("File-Run", mac, filename, channel, ifidx, sudo) - - def admin_set(self, mac, new_bool, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.admin_set") - self.aen.send_command("Admin-Set", mac, new_bool, channel, ifidx, sudo) - - def whitelist_add(self, mac, mac_list=None, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.whitelist_add") - if mac_list is not None: - mac_list = [self.master.sta.mac, self.master.ap.mac] - self.aen.send_command("Whitelist-Add", mac, mac_list, channel, ifidx, sudo) - - def config_change(self, mac, new_config, hardcode=False, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.config_change") - self.aen.send_command("Config-Change", mac, [new_config, hardcode], channel, ifidx, sudo) - - def name_change(self, mac, new_name, hardcode=False, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.name_change") - self.aen.send_command("Name-Change", mac, [new_name, hardcode], channel, ifidx, sudo) - - def pair(self, mac, key=networking_keys["handshake_key1"], channel=None, ifidx=None): - self.master.dprint("net.cmd.pair") - self.aen.send_command("Pair", mac, key, channel, ifidx) - - def pair_enable(self, mac, pair_bool, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.pair") - self.aen.send_command("Set-Pair", mac, pair_bool, channel, ifidx, sudo) - - def directory_get(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.directory_get") - self.aen.send_command("Directory-Get", mac, None, channel, ifidx, sudo) - - # resend cmd - - def wifi_connect(self, mac, name, password, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.wifi_connect") - self.aen.send_command("Wifi-Connect", mac, [name, password], channel, ifidx, sudo) - - def wifi_disconnect(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.wifi_disconnect") - self.aen.send_command("Wifi-Disconnect", mac, None, channel, ifidx, sudo) - - def ap_enable(self, mac, name, password, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.ap_enable") - self.aen.send_command("AP-Enable", mac, [name, password], channel, ifidx, sudo) - - def ap_disable(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.ap_disable") - self.aen.send_command("AP-Disable", mac, None, channel, ifidx, sudo) - - def pause(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.pause") - self.aen.send_command("Pause", mac, None, channel, ifidx, sudo) - - def resume(self, mac, channel=None, ifidx=None, sudo=False): - self.master.dprint("net.cmd.resume") - self.aen.send_command("Resume", mac, None, channel, ifidx, sudo) - - diff --git a/software/networking/ssp_networking.py b/software/networking/ssp_networking.py new file mode 100644 index 0000000..58d34e3 --- /dev/null +++ b/software/networking/ssp_networking.py @@ -0,0 +1,513 @@ +from config import mysecrets, config, whitelist, i2c_dict, version, msg_codes, msg_subcodes, networking_keys +from networking import Networking +import ubinascii +import machine +import time +import os +import gc +import webrepl + + +class SSP_Networking: + def __init__(self, infmsg=False, dbgmsg=False, errmsg=False, admin=False, inittime=time.ticks_ms()): + if infmsg: + print(f"{(time.ticks_ms() - inittime) / 1000:.3f} Initialising Smart System Education Platform Networking") + self.networking = Networking(infmsg, dbgmsg, errmsg, admin, inittime) + config["id"] = ubinascii.hexlify(machine.unique_id()).decode() + config["version"] = ''.join(str(value) for value in version.values()) + self.networking.config = config + self.version = version + self.commands = self.Commands(self) + self.orders = self.Orders(self) + + class Commands: + def __init__(self, master): + self.master = master + + def send_command(self, msg_subkey, mac, payload=None, channel=None, ifidx=None, sudo=False): + self.master.dprint("aen.send_command") + if sudo and isinstance(payload, list): + payload.append("sudo") + elif sudo and payload is None: + payload = ["sudo"] + else: + payload = [payload, "sudo"] + if (msg_key := "cmd") and msg_subkey in msg_subcodes[msg_key]: + self.master.networking.iprint(f"Sending {msg_subkey} ({bytes([msg_subcodes[msg_key][msg_subkey]])}) command to {mac} ({self.master.networking.aen.peer_name(mac)})") + self.master.networking.aen.send_command(msg_codes[msg_key], msg_subcodes[msg_key][msg_subkey], mac, payload, channel, ifidx) + else: + self.master.iprint(f"Command {msg_subkey} not found") + gc.collect() + + def ping(self, mac, channel=None, ifidx=None): + self.master.networking.dprint("net.cmd.ping") + self.master.networking.aen.ping(mac, channel, ifidx) + + def echo(self, mac, message, channel=None, ifidx=None): + self.master.networking.dprint("net.cmd.echo") + self.master.networking.aen.echo(mac, message, channel, ifidx) + + def boop(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("aen.boop") + self.master.networking.aen.boop(mac, channel, ifidx, sudo) + + def send(self, mac, message, channel=None, ifidx=None): + self.master.networking.dprint("net.cmd.message") + self.master.networking.aen.send(mac, message, channel, ifidx) + + def broadcast(self, message, channel=None, ifidx=None): + self.master.networking.dprint("net.cmd.broadcast") + mac = b'\xff\xff\xff\xff\xff\xff' + self.send(mac, message, channel, ifidx) + + def send_data(self, mac, message, channel=None,ifidx=None): # message is a dict, key is the sensor type and the value is the sensor value + self.master.networking.dprint("net.cmd.message") + self.master.networking.aen.send_data(mac, message, channel, ifidx) + + def reboot(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.reboot") + self.master.networking.aen.send_command("Reboot", mac, None, channel, ifidx, sudo) + + def firmware_update(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.firmware_update") + self.master.networking.aen.send_command("Firmware-Update", mac, None, channel, ifidx, sudo) + + def file_update(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.file_update") + self.master.networking.aen.send_command("File-Update", mac, None, channel, ifidx, sudo) + + def file_download(self, mac, link, file_list=None, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.file_download") + self.master.networking.aen.send_command("File-Download", mac, [link, file_list], channel, ifidx, sudo) + + def web_repl(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.web_repl") + self.master.networking.ap.set_ap(ap_name := self.master.networking.config["name"], password := networking_keys["default_ap_key"]) + self.master.networking.aen.send_command("Web-Repl", mac, [ap_name, password], channel, ifidx, sudo) + # await success message and if success False disable AP or try again + + def file_run(self, mac, filename, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.file_run") + self.master.networking.aen.send_command("File-Run", mac, filename, channel, ifidx, sudo) + + def admin_set(self, mac, new_bool, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.admin_set") + self.master.networking.aen.send_command("Admin-Set", mac, new_bool, channel, ifidx, sudo) + + def whitelist_add(self, mac, mac_list=None, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.whitelist_add") + if mac_list is not None: + mac_list = [self.master.networking.sta.mac, self.master.networking.ap.mac] + self.master.networking.aen.send_command("Whitelist-Add", mac, mac_list, channel, ifidx, sudo) + + def config_change(self, mac, new_config, hardcode=False, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.config_change") + self.master.networking.aen.send_command("Config-Change", mac, [new_config, hardcode], channel, ifidx, sudo) + + def name_change(self, mac, new_name, hardcode=False, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.name_change") + self.master.networking.aen.send_command("Name-Change", mac, [new_name, hardcode], channel, ifidx, sudo) + + def pair(self, mac, key=networking_keys["handshake_key1"], channel=None, ifidx=None): + self.master.networking.dprint("net.cmd.pair") + self.master.networking.aen.send_command("Pair", mac, key, channel, ifidx) + + def pair_enable(self, mac, pair_bool, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.pair") + self.master.networking.aen.send_command("Set-Pair", mac, pair_bool, channel, ifidx, sudo) + + def directory_get(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.directory_get") + self.master.networking.aen.send_command("Directory-Get", mac, None, channel, ifidx, sudo) + + # resend cmd + + def wifi_connect(self, mac, name, password, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.wifi_connect") + self.master.networking.aen.send_command("Wifi-Connect", mac, [name, password], channel, ifidx, sudo) + + def wifi_disconnect(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.wifi_disconnect") + self.master.networking.aen.send_command("Wifi-Disconnect", mac, None, channel, ifidx, sudo) + + def ap_enable(self, mac, name, password, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.ap_enable") + self.master.networking.aen.send_command("AP-Enable", mac, [name, password], channel, ifidx, sudo) + + def ap_disable(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.ap_disable") + self.master.networking.aen.send_command("AP-Disable", mac, None, channel, ifidx, sudo) + + def pause(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.pause") + self.master.networking.aen.send_command("Pause", mac, None, channel, ifidx, sudo) + + def resume(self, mac, channel=None, ifidx=None, sudo=False): + self.master.networking.dprint("net.cmd.resume") + self.master.networking.aen.send_command("Resume", mac, None, channel, ifidx, sudo) + + + class Orders: + def __init__(self, master): + self.master = master + self.master.networking.dprint("net.cmd.orders") + self._whitelist = whitelist + + self._pause_function = None + + # Flags + self._pairing_enabled = True + self._pairing = False + self._paired = False + self._paired_macs = [] + self._running = True + + def __check_authorisation(sender_mac, payload): + return sender_mac in self._whitelist or payload == "sudo" or payload[-1] == "sudo" + + def __send_confirmation(msg_type, recipient_mac, msg_subkey_type, payload=None, error=None): + self.master.networking.dprint("net.order.__send_confirmation") + self.master.networking.aen.__send_confirmation(msg_type, recipient_mac, msg_subkey_type, payload, error) + + def custom_cmd_handler(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key): + self.master.networking.dprint("net.order.custom_cmd_handler") + if (msg_subkey := "Reboot") and subtype == msg_subcodes[msg_key][msg_subkey]: # Reboot + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) + machine.reset() + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Firmware-Update") and subtype == msg_subcodes[msg_key][msg_subkey]: # Firmware-Update + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + # Insert update logic here + self.master.iprint("no update logic written just yet") + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "File-Update") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Update + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + # Insert update logic here + self.master.iprint("No update logic written just yet") + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "File-Download") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Download + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + # should return a list with a link and the list of files to download + if __check_authorisation(sender_mac, payload): + try: + # import mip + # base = payload[0] + # files_to_copy = payload[1] + # if files_to_copy is None: + # mip.install(base) + # else: + # for f in files_to_copy: + # mip.install(base + f) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Web-Repl") and subtype == msg_subcodes[msg_key][msg_subkey]: # Web-Repl + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + # should be a list with name and password + if __check_authorisation(sender_mac, payload): + try: + # add logic to connect to Wi-Fi and set up webrepl + webrepl.start() + self.master.sta.connect(payload[0], payload[1]) + link = "webrepl link" + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", link) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "File-Run") and subtype == msg_subcodes[msg_key][msg_subkey]: # File-Run + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.iprint("Execute logic not implemented") + # insert run logic here + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Set-Admin") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Admin Bool + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + self.master.iprint(f"Received Set-Admin command: self.admin set to {payload[0]}") + try: + self.master.admin = payload[0] + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Whitelist-Add") and subtype == msg_subcodes[msg_key][ + msg_subkey]: # Whitelist-Add - Add Admin macs to _whitelist + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + self.master.iprint( + f"Received add admin macs to _whitelist command, added {payload[0]} and {payload[1]}") + try: + self._whitelist.append(payload[0]) + self._whitelist.append(payload[1]) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Config-Change") and subtype == msg_subcodes[msg_key][msg_subkey]: # change config + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.config["configuration"] = payload[0] + if payload[1]: + file_path = "config.py" + with open(file_path, "r") as f: + lines = f.readlines() + with open(file_path, "w") as f: + for line in lines: + if line.startswith(' "configuration": '): + f.write(f' "configuration": "{payload[0]}",\n') + else: + f.write(line) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Name-Change") and subtype == msg_subcodes[msg_key][msg_subkey]: # change name + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.config["name"] = payload[0] + if payload[1]: + file_path = "config.py" + with open(file_path, "r") as f: + lines = f.readlines() + with open(file_path, "w") as f: + for line in lines: + if line.startswith(' "name": '): + f.write(f' "name": "{payload[0]}"\n') + else: + f.write(line) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Ping") and subtype == msg_subcodes[msg_key][msg_subkey]: # Ping + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + self.master.networking.aen.add_peer(sender_mac, payload[2]["name"], payload[2]["id"], payload[2]["configuration"], + payload[2]["version"], payload[0], payload[1]) + if bool(self.master.networking.aen.ifidx): + channel = self.master.ap.channel() + else: + channel = self.master.sta.channel() + response = [channel, self.master.networking.aen.ifidx, self.master.config, send_timestamp] + self.master.networking.aen.send_command(0x03, 0x10, sender_mac, response) + # elif (msg_subkey := "Pair") and subtype == msg_subcodes[msg_key][msg_subkey]: # Pair #add something that checks that the messages are from the same mac # BREAKS NETWORK + # self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") + # if self._pairing_enabled and networking_keys["handshake_key_1"] == payload: + # self._pairing = True + # self.pair(sender_mac, networking_keys["handshake_key_2"]) + # # some timer for if key 3 is not received to reset states + # elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_2"] == payload: + # self._paired = True + # self._paired_macs.append(sender_mac) + # self.pair(sender_mac, networking_keys["handshake_key_3"]) + # # some timer that sets to false if key 4 is not received + # elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_3"] == payload: + # try: + # # Insert pairing logic here do a reverse handshake + # self._paired = True + # self._paired_macs.append(sender_mac) + # self.pair(sender_mac, networking_keys["handshake_key_4"]) + # self.master.iprint("no pairing logic written just yet") + # __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + # except Exception as e: + # self.master.eprint(f"Error: {e} with payload: {payload}") + # __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + # elif self._pairing_enabled and self._pairing and networking_keys["handshake_key_3"] == payload: + # self._paired = True + # # remove timer from before + # else: + # __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", "Pairing disabled", payload) + # elif (msg_subkey := "Set-Pair") and subtype == msg_subcodes[msg_key][msg_subkey]: # Enable pairing mode + # self.master.iprint(f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.peer_name(sender_mac)})") + # if __check_authorisation(sender_mac, payload): + # try: + # self._pairing_enabled = payload[0] + # __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + # except Exception as e: + # self.master.eprint(f"Error: {e} with payload: {payload}") + # __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + # else: + # __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "RSSI/Status/Config-Boop") and subtype == msg_subcodes[msg_key][ + msg_subkey]: # RSSI/Status/Config Boop + self.boops = self.boops + 1 + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)}), Received total of {self.boops} boops!") + try: + self.master.networking.aen.send_command(0x02, 0x20, sender_mac,[self.master.config, self.master.version, self.master.sta.mac, self.master.ap.mac, self.master.networking.aen.rssi()]) # [ID, Name, Config, Version, sta mac, ap mac, rssi] + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + elif (msg_subkey := "Directory-Get") and subtype == msg_subcodes[msg_key][ + msg_subkey]: # Get List of Files # BREAKS NETWORK + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + try: + def ___list_all_files(path): + result = [] + entries = os.listdir(path) + for entry in entries: + full_path = path + "/" + entry + try: + if os.stat(full_path)[0] & 0x4000: + result.extend(___list_all_files(full_path)) + else: + result.append(full_path) + except OSError: + # Handle inaccessible files or directories + continue + return result + + start_path = '.' + all_files = ___list_all_files(start_path) + self.master.networking.aen.send_command(0x02, 0x20, sender_mac, all_files) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + elif (msg_subkey := "Echo") and subtype == msg_subcodes[msg_key][msg_subkey]: # Echo + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)}): {payload}") # Check i or d + self.master.networking.aen.send_command(0x03, 0x15, sender_mac, payload) + elif (msg_subkey := "Resend") and subtype == msg_subcodes[msg_key][msg_subkey]: # Resend lost long messages + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + self.master.iprint("Long_sent_buffer disabled due to memory constraints") + elif (msg_subkey := "WiFi-Connect") and subtype == msg_subcodes[msg_key][msg_subkey]: # Connect to Wi-Fi + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.sta.connect(payload[0], payload[1]) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "WiFi-Disconnect") and subtype == msg_subcodes[msg_key][ + msg_subkey]: # Disconnect from Wi-Fi + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.sta.disconnect() + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "AP-Enable") and subtype == msg_subcodes[msg_key][msg_subkey]: # Enable AP + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + ssid = payload[0] + if ssid == "": + ssid = self.master.config["name"] + password = payload[1] + self.master.ap.setap(ssid, password) + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.eprint(f"Error: {e} with payload: {payload}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "AP-Disable") and subtype == msg_subcodes[msg_key][msg_subkey]: # Disable AP + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.ap.deactivate() + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + self.master.iprint(f"Error: {e}") + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Pause") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Pause + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.iprint(f"Received pause command: {payload[0]}") + self._running = False + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + if self._pause_function: + self._pause_function() # calls the custom set pause function to display a screen + while not self._running: + time.sleep(0.5) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + elif (msg_subkey := "Resume") and subtype == msg_subcodes[msg_key][msg_subkey]: # Set Continue + self.master.iprint( + f"{msg_subkey} ({subtype}) command received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)})") + if __check_authorisation(sender_mac, payload): + try: + self.master.iprint(f"Received continue command: {payload}") + self.master._running = True + __send_confirmation("Success", sender_mac, f"{msg_subkey} ({subtype})", payload) + except Exception as e: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, e) + else: + __send_confirmation("Fail", sender_mac, f"{msg_subkey} ({subtype})", payload, "Not authorised") + else: + self.master.iprint( + f"Unknown command subtype from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)}): {subtype}") + + def custom_inf_handler(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key): + self.master.networking.dprint("net.order.custom_inf_handler") + if (msg_subkey := "Directory") and subtype == msg_subcodes[msg_key][msg_subkey]: # File Directory + self.master.iprint(f"{msg_subkey} ({subtype}) data received from {sender_mac} ({self.master.networking.aen.peer_name(sender_mac)}): {payload}") + # __send_confirmation("Confirm", sender_mac, f"{msg_subkey} ({subtype})", payload) #confirm message recv + + + def custom_ack_handler(sender_mac, subtype, send_timestamp, receive_timestamp, payload, msg_key): + self.master.networking.dprint("net.order.custom_ack_handler") + + self.master.networking.aen.cmd(custom_cmd_handler) + self.master.networking.aen.inf(custom_inf_handler) + self.master.networking.aen.ack(custom_ack_handler) \ No newline at end of file diff --git a/software/release/config.py b/software/release/config.py index 2a004a7..4dec91c 100644 --- a/software/release/config.py +++ b/software/release/config.py @@ -1,6 +1,8 @@ config = { "name": "Nickname", - "configuration": "AM1" + "configuration": "AM1", + "id": None, + "version": None } version = {'adxl345.py': 3, 'files.py': 2, @@ -45,7 +47,7 @@ }, "inf": { "RSSI/Status/Config-Boop": 0x20, - "Sensor": 0x21, + "Data": 0x21, "Message": 0x22, "Directory": 0x23, }, From 9a70f2917ad1c280ee3613422ae6f28599846ccc Mon Sep 17 00:00:00 2001 From: Nick Art Date: Fri, 6 Dec 2024 19:06:07 -0500 Subject: [PATCH 2/2] Cleaned up and updated mains for new networking structure --- .../examples => archive}/default_main.py | 0 .../examples => archive}/pyscript_main.py | 0 software/main/.idea/.name | 2 +- .../inspectionProfiles/profiles_settings.xml | 6 ++++++ software/main/.idea/misc.xml | 7 +++++++ software/main/boot.py | 10 +++++++--- software/main/main.py | 11 ++++++++--- software/networking/.DS_Store | Bin 6148 -> 6148 bytes software/networking/README.qmd | 3 ++- software/networking/examples/.DS_Store | Bin 6148 -> 6148 bytes software/release/README.qmd | 3 ++- 11 files changed, 33 insertions(+), 9 deletions(-) rename software/{networking/examples => archive}/default_main.py (100%) rename software/{networking/examples => archive}/pyscript_main.py (100%) create mode 100644 software/main/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 software/main/.idea/misc.xml diff --git a/software/networking/examples/default_main.py b/software/archive/default_main.py similarity index 100% rename from software/networking/examples/default_main.py rename to software/archive/default_main.py diff --git a/software/networking/examples/pyscript_main.py b/software/archive/pyscript_main.py similarity index 100% rename from software/networking/examples/pyscript_main.py rename to software/archive/pyscript_main.py diff --git a/software/main/.idea/.name b/software/main/.idea/.name index 6c5d810..11a5d8e 100644 --- a/software/main/.idea/.name +++ b/software/main/.idea/.name @@ -1 +1 @@ -boot.py \ No newline at end of file +main.py \ No newline at end of file diff --git a/software/main/.idea/inspectionProfiles/profiles_settings.xml b/software/main/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/software/main/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/software/main/.idea/misc.xml b/software/main/.idea/misc.xml new file mode 100644 index 0000000..89c8a65 --- /dev/null +++ b/software/main/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/software/main/boot.py b/software/main/boot.py index fffeeb8..4b4d73d 100644 --- a/software/main/boot.py +++ b/software/main/boot.py @@ -17,7 +17,7 @@ sta.active(False) ap.active(False) -from networking import Networking +from ssp_networking import SSP_Networking #Network infmsg = False @@ -27,11 +27,12 @@ if configuration == "AM1": infmsg = True -networking = Networking(infmsg, dbgmsg, errmsg) +networking = SSP_Networking(infmsg, dbgmsg, errmsg) peer_mac = b'\xff\xff\xff\xff\xff\xff' import time +global timer print("{:.3f} Name: {}, ID: {}, Configuration: {}, Sta mac: {}, Ap mac: {}, Version: {}".format( (time.ticks_ms() - networking.inittime) / 1000, @@ -73,5 +74,8 @@ def heartbeat(timer): def deinit(): networking.cleanup() - timer.deinit() + try: + timer.deinit() + except Exception as e: + print(e) machine.reset() diff --git a/software/main/main.py b/software/main/main.py index d949e5d..8168039 100644 --- a/software/main/main.py +++ b/software/main/main.py @@ -17,7 +17,7 @@ sta.active(False) ap.active(False) -from networking import Networking +from ssp_networking import SSP_Networking #Network infmsg = False @@ -27,11 +27,12 @@ if configuration == "AM1": infmsg = True -networking = Networking(infmsg, dbgmsg, errmsg) +networking = SSP_Networking(infmsg, dbgmsg, errmsg) peer_mac = b'\xff\xff\xff\xff\xff\xff' import time +global timer print("{:.3f} Name: {}, ID: {}, Configuration: {}, Sta mac: {}, Ap mac: {}, Version: {}".format( (time.ticks_ms() - networking.inittime) / 1000, @@ -43,6 +44,7 @@ networking.config["version"] )) + def idle(): lastPressed = 0 @@ -73,7 +75,10 @@ def heartbeat(timer): def deinit(): networking.cleanup() - timer.deinit() + try: + timer.deinit() + except Exception as e: + print(e) machine.reset() def run_config_module(module_name): diff --git a/software/networking/.DS_Store b/software/networking/.DS_Store index f645cbfa257df92cbf1ecf30c3b155c16c6e7595..d5a864be0c9c713291a3d57017a1ee0ef9f57727 100644 GIT binary patch delta 43 zcmZoMXfc@J&nUPtU^g?P;AS3{kBpot#mPBI`T04FlOM2%Z2rsomT@yX$6tN`J!20z delta 32 ocmZoMXfc@J&nU1lU^g?Pz-AtnkBpn8*xoWuY>?f|&heKY0IZP;n*aa+ diff --git a/software/networking/README.qmd b/software/networking/README.qmd index 31fa77b..e9ea4bc 100644 --- a/software/networking/README.qmd +++ b/software/networking/README.qmd @@ -47,4 +47,5 @@ A short description of the directories can be found below. | examples | This directory hosts example code | Nick | | examples/example.py | This is some basic example code on how to use my networking library | Nick | | examples/long_message_example.py | This code showcases the long message capabilities built into my code. By sending multiple messages that are then stitched back together by the recipient the max payload can be increased from 241 bytes to 256 x 238 = 60928 bytes, although in reality the ESP32 boards will start running out of memory with messages above 30 kilobytes. | Nick | -| networking.py | This is the main networking code that builds on ESP-NOW. There are many prepared functionalities (and some more that I am working on), such as long message support, sending of various variable types (bytes, bytearray, dicts, lists, int, float, char, string), as well as different types of messages such as ping, echo and more. There are also various features in place to make the networking more robust. It needs config.py to function. | Nick | +| networking.py | This is the main networking code that builds on ESP-NOW. There are many prepared functionalities (and some more that I am working on), such as long message support, sending of various variable types (bytes, bytearray, dicts, lists, int, float, char, string), as well as different types of messages such as ping, echo and more. There are also various features in place to make the networking more robust. | Nick | +| ssp_networking.py | This is the SSP networking code that builds on the above networking.py. This adds even more functionality on top (many more commands) and customises certain use for the Smart Systems Platform. Needs a config.py to properly work. | Nick | diff --git a/software/networking/examples/.DS_Store b/software/networking/examples/.DS_Store index c08600879812897c238c53bf15a1f4c37a883d2a..db2e52c6ced779e86575a023d9c05182fb167765 100644 GIT binary patch delta 70 zcmZoMXfc=|#>B`mu~2NHo+2aj#DLw5%#(STk|(caYTBI7JcDIpLmlI0b`E|HpsLM< Y%-@+O^NUz=FaQA~0|V3M0Ff=s0I$LkyZ`_I delta 177 zcmZoMXfc=|#>B)qu~2NHo+2ab#DLw4m>3yZC-X2S>+>_DFr+f1F(fjSGUPCnFvK(D z0@;}ic?^0C1q_v*Ir+&+Ir&Kp3=9Gc42-gq6Bs923xH%8iW!m_ihwE$2el-Y m2Ae-J&Slxm&cV+CbP$m9oq009h$ROj&}^V0hRp#YTbKc%U@O}I diff --git a/software/release/README.qmd b/software/release/README.qmd index abe8f55..9f8142b 100644 --- a/software/release/README.qmd +++ b/software/release/README.qmd @@ -37,7 +37,8 @@ A short description of the directories can be found below. |--------------|-----------------------------------------|--------------| | release/config.py | Smart Module Configuration File | Nick | | main/main.py | Smart Module Main.py | Nick | -| networking/networking.py | This is the main networking code that builds on ESP-NOW. There are many prepared functionalities (and some more that I am working on), such as long message support, sending of various variable types (bytes, bytearray, dicts, lists, int, float, char, string), as well as different types of messages such as ping, echo and more. There are also various features in place to make the networking more robust. It needs config.py to function. | Nick | +| networking/networking.py | This is the main networking code that builds on ESP-NOW. There are many prepared functionalities (and some more that I am working on), such as long message support, sending of various variable types (bytes, bytearray, dicts, lists, int, float, char, string), as well as different types of messages such as ping, echo and more. There are also various features in place to make the networking more robust. | Nick | +| networking/ssp_networking.py | This is the ssp networking module. It needs config.py to function. | Nick | | libraries/adxl345.py | Support for the built in accelerometer https://github.com/DFRobot/micropython-dflib/blob/master/ADXL345/user_lib/ADXL345.py | Milan | | libraries/files.py | Custom save to file library | Milan | | libraries/icons.py | Icon support for the smart motor module | Milan |