Max lora payload Exception
This commit is contained in:
+33
-16
@@ -20,6 +20,8 @@ else:
|
|||||||
class BaseLoraDevice:
|
class BaseLoraDevice:
|
||||||
"""Base class providing automatic ACK generation, retries, and duplicate filtering."""
|
"""Base class providing automatic ACK generation, retries, and duplicate filtering."""
|
||||||
|
|
||||||
|
MAX_PAYLOAD_SIZE = 222 # Maximum safe LoRa payload size in bytes
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.processed_msg_ids = set()
|
self.processed_msg_ids = set()
|
||||||
self.received_acks = set()
|
self.received_acks = set()
|
||||||
@@ -225,6 +227,13 @@ if IS_MICROPYTHON:
|
|||||||
payload = payload.encode('utf-8')
|
payload = payload.encode('utf-8')
|
||||||
|
|
||||||
paquet_physique = bytes([group]) + payload
|
paquet_physique = bytes([group]) + payload
|
||||||
|
|
||||||
|
if len(paquet_physique) > self.MAX_PAYLOAD_SIZE:
|
||||||
|
raise ValueError(
|
||||||
|
f"[LoRa SPI] Payload exceeds MTU limit: {len(paquet_physique)} bytes "
|
||||||
|
f"(max allowed: {self.MAX_PAYLOAD_SIZE} bytes)."
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.lora.send(paquet_physique)
|
self.lora.send(paquet_physique)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -290,18 +299,19 @@ else:
|
|||||||
# Initial configuration
|
# Initial configuration
|
||||||
self.configure(freq=868.1, sf=7, bw=125)
|
self.configure(freq=868.1, sf=7, bw=125)
|
||||||
|
|
||||||
def _send_at_cmd(self, cmd, wait_time=0.3):
|
def _send_at_cmd(self, cmd, timeout=1.5):
|
||||||
"""Sends AT command, draining unread serial noise first."""
|
"""Sends AT command and reads response until line received or timeout."""
|
||||||
# Drain any lingering lines (like 'Rssi= -4' or incoming data)
|
|
||||||
if self.ser.in_waiting > 0:
|
|
||||||
self.ser.read_all()
|
|
||||||
|
|
||||||
self.ser.write(f"{cmd}\r\n".encode('utf-8'))
|
self.ser.write(f"{cmd}\r\n".encode('utf-8'))
|
||||||
time.sleep(wait_time)
|
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
resp = ""
|
resp = ""
|
||||||
while self.ser.in_waiting > 0:
|
while (time.time() - start) < timeout:
|
||||||
resp += self.ser.readline().decode('utf-8', errors='ignore')
|
if self.ser.in_waiting > 0:
|
||||||
|
line = self.ser.readline().decode('utf-8', errors='ignore')
|
||||||
|
resp += line
|
||||||
|
if "OK" in line or "ERROR" in line or "AT_BUSY" in line:
|
||||||
|
break
|
||||||
|
time.sleep(0.02)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def configure(self, freq=868.1, sf=7, bw=125):
|
def configure(self, freq=868.1, sf=7, bw=125):
|
||||||
@@ -312,14 +322,14 @@ else:
|
|||||||
|
|
||||||
# Parameters: Freq, SF, BW, CR(0=4/5), Preamble(8), Header(1=Explicit), CRC(1=ON), IQ(0=Standard), NetMode(0=P2P), Power(14), SyncWord(18=0x12), Format(0), Type(1)
|
# Parameters: Freq, SF, BW, CR(0=4/5), Preamble(8), Header(1=Explicit), CRC(1=ON), IQ(0=Standard), NetMode(0=P2P), Power(14), SyncWord(18=0x12), Format(0), Type(1)
|
||||||
at_cfg_cmd = f"AT+CFG={freq_hz},{sf},{bw_code},0,8,1,1,0,0,14,18,0,1"
|
at_cfg_cmd = f"AT+CFG={freq_hz},{sf},{bw_code},0,8,1,1,0,0,14,18,0,1"
|
||||||
self._send_at_cmd(at_cfg_cmd, wait_time=0.2)
|
self._send_at_cmd(at_cfg_cmd, timeout=0.2)
|
||||||
|
|
||||||
# Fallback standalone commands
|
# Fallback standalone commands
|
||||||
self._send_at_cmd("AT+SYNCWORD=18", wait_time=0.1)
|
self._send_at_cmd("AT+SYNCWORD=18", timeout=0.1)
|
||||||
self._send_at_cmd("AT+PRECV=65535", wait_time=0.1)
|
self._send_at_cmd("AT+PRECV=65535", timeout=0.1)
|
||||||
self.ser.reset_input_buffer()
|
self.ser.reset_input_buffer()
|
||||||
|
|
||||||
def send(self, payload, group=None):
|
def send(self, payload, group=None, retries=0):
|
||||||
"""Encodes payload into a HEX string and transmits via 4-parameter AT+SEND."""
|
"""Encodes payload into a HEX string and transmits via 4-parameter AT+SEND."""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if group is None:
|
if group is None:
|
||||||
@@ -331,14 +341,20 @@ else:
|
|||||||
if isinstance(payload, str):
|
if isinstance(payload, str):
|
||||||
payload = payload.encode('utf-8')
|
payload = payload.encode('utf-8')
|
||||||
|
|
||||||
|
if len(payload) > self.MAX_PAYLOAD_SIZE:
|
||||||
|
raise ValueError(
|
||||||
|
f"[LoRa Serial] Payload exceeds MTU limit: {len(payload)} bytes "
|
||||||
|
f"(max allowed: {self.MAX_PAYLOAD_SIZE} bytes)."
|
||||||
|
)
|
||||||
|
|
||||||
hex_payload = payload.hex()
|
hex_payload = payload.hex()
|
||||||
|
|
||||||
log(f"[RPi LoRa Serial] Transmitting HEX string: {hex_payload}")
|
log(f"[RPi LoRa Serial] Transmitting HEX string: {hex_payload}")
|
||||||
|
|
||||||
# Format: AT+SEND=<group>,<payload_string>,<confirm>,<retries>
|
# Format: AT+SEND=<group>,<payload_string>,<confirm>,<retries>
|
||||||
cmd = f"AT+SEND={group},{hex_payload},0,3"
|
cmd = f"AT+SEND={group},{hex_payload},0,{retries}"
|
||||||
|
|
||||||
resp = self._send_at_cmd(cmd, wait_time=0.3)
|
resp = self._send_at_cmd(cmd, timeout=0.3)
|
||||||
log(f"[RPi LoRa Serial] AT+SEND response: {resp}")
|
log(f"[RPi LoRa Serial] AT+SEND response: {resp}")
|
||||||
|
|
||||||
def receive_packet(self, timeout_ms=500):
|
def receive_packet(self, timeout_ms=500):
|
||||||
@@ -424,4 +440,5 @@ class LoraCommands:
|
|||||||
PING = "ping"
|
PING = "ping"
|
||||||
COOKING_STATE_UPDATE = "cooking_state_update"
|
COOKING_STATE_UPDATE = "cooking_state_update"
|
||||||
TOGGLE_PAUSE = "toggle_pause"
|
TOGGLE_PAUSE = "toggle_pause"
|
||||||
TOGGLE_DEFROST = "toggle_defrost"
|
TOGGLE_DEFROST = "toggle_defrost"
|
||||||
|
NEW_ALERT = "new_alert"
|
||||||
Reference in New Issue
Block a user