1- import os
1+ """Meshtastic ESP32 Unified OTA
2+ """
3+ import os
24import hashlib
35import socket
46import logging
1113def _file_sha256 (filename : str ):
1214 """Calculate SHA256 hash of a file."""
1315 sha256_hash = hashlib .sha256 ()
14-
16+
1517 with open (filename , "rb" ) as f :
1618 for byte_block in iter (lambda : f .read (4096 ), b"" ):
1719 sha256_hash .update (byte_block )
1820
1921 return sha256_hash
2022
23+
24+ class OTAError (Exception ):
25+ """Exception for OTA errors."""
26+
27+
2128class ESP32WiFiOTA :
2229 """ESP32 WiFi Unified OTA updates."""
2330
@@ -28,21 +35,21 @@ def __init__(self, filename: str, hostname: str, port: int = 3232):
2835 self ._socket : Optional [socket .socket ] = None
2936
3037 if not os .path .exists (self ._filename ):
31- raise Exception (f"File { self ._filename } does not exist" )
38+ raise FileNotFoundError (f"File { self ._filename } does not exist" )
3239
3340 self ._file_hash = _file_sha256 (self ._filename )
3441
3542 def _read_line (self ) -> str :
3643 """Read a line from the socket."""
3744 if not self ._socket :
38- raise Exception ("Socket not connected" )
45+ raise ConnectionError ("Socket not connected" )
3946
4047 line = b""
4148 while not line .endswith (b"\n " ):
4249 char = self ._socket .recv (1 )
43-
50+
4451 if not char :
45- raise Exception ("Connection closed while waiting for response" )
52+ raise ConnectionError ("Connection closed while waiting for response" )
4653
4754 line += char
4855
@@ -78,10 +85,11 @@ def update(self, progress_callback: Optional[Callable[[int, int], None]] = None)
7885 response = self ._read_line ()
7986 if response == "OK" :
8087 break
81- elif response == "ERASING" :
88+
89+ if response == "ERASING" :
8290 logger .info ("Device is erasing flash..." )
8391 elif response .startswith ("ERR " ):
84- raise Exception (f"Device reported error: { response } " )
92+ raise OTAError (f"Device reported error: { response } " )
8593 else :
8694 logger .warning (f"Unexpected response: { response } " )
8795
@@ -105,18 +113,16 @@ def update(self, progress_callback: Optional[Callable[[int, int], None]] = None)
105113 logger .info ("Firmware sent, waiting for verification..." )
106114 while True :
107115 response = self ._read_line ()
108-
109116 if response == "OK" :
110117 logger .info ("OTA update completed successfully!" )
111118 break
112- elif response == "ACK" :
113- continue
114- elif response .startswith ("ERR " ):
115- raise Exception (f"OTA update failed: { response } " )
116- else :
119+
120+ if response .startswith ("ERR " ):
121+ raise OTAError (f"OTA update failed: { response } " )
122+ elif response != "ACK" :
117123 logger .warning (f"Unexpected final response: { response } " )
118124
119125 finally :
120126 if self ._socket :
121127 self ._socket .close ()
122- self ._socket = None
128+ self ._socket = None
0 commit comments