Repository navigation
Conversation
TheengsUtils::_rawToHex() formats each byte with "%02X\r", so the last sprintf writes two bytes past the 2 * size hex digits (the '\r' and the terminating null). LORAtoX() sized its buffer 2 * packetSize + 1, one byte short, overflowing the stack for every binary LoRa packet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oders Lets the LoRa gateway receive LoRaWAN devices using ABP on a single channel (e.g. Dragino sensors set to a fixed frequency and data rate), which previously could only be published as encrypted hex. - Build flag LORA_LORAWAN (ESP32): devices (DevAddr, NwkSKey, AppSKey, name, model) are declared at runtime through the "lorawan" key of the MQTTtoLORA/config command and stored in NVS with "save":true. - Uplinks from declared devices have their MIC verified, duplicate frame counters dropped and FRMPayload decrypted; they are published to LORAtoMQTT/<DEVADDR> with fcnt, fport and the decrypted payload. Other packets keep the existing raw hex behaviour. - Build flag LORA_LORAWAN_JS adds Duktape to run TTN style decoders (Decoder(bytes, port) or decodeUplink(input)) uploaded as raw scripts to <base><gateway>/LORAWANdecoder/<DEVADDR>, outside /commands/# because that subscription only accepts JSON up to JSON_MSG_BUFFER_MAX. NTP is started so decoders can timestamp with new Date(). - Optional per device "entities" declarations create Home Assistant discovery entities from the published fields. Without the flags the firmware is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds "Configure LoRaWAN" (/lw) to the configuration menu when built with LORA_LORAWAN: - list of the declared devices with their decoder status and last FCnt - add/edit form for DevAddr, name, model, session keys, Home Assistant entities (JSON) and the JavaScript decoder; stored keys are never sent back to the browser (only a hint of their last bytes), an empty key field keeps the current key - "Test decoder" runs the decoder being edited on a payload, prefilled with the last decrypted payload of the device, without saving - delete button LORAWANconfigureDevice() now reports configuration errors to the caller, decoder storage is shared between MQTT and the WebUI (LORAWANsetDecoder), and device declarations are serialized with a larger buffer so longer entity lists are not truncated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks done
The Information page builds its table by replacing JSON punctuation and
can't display nested values: the "lorawan" array of the LORA state was
shown as stray rows ("lorawan | [devaddr | ...", "fcnt_down | 12}]").
Show each device as a single row ("LoRaWAN <DEVADDR>" with its fields
joined) on that page; the MQTT state keeps the array.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description:
Lets the LoRa gateway receive LoRaWAN devices that use ABP on a single channel. Until now these were published as encrypted
hexonly. Many inexpensive sensors (Dragino LDS02, LHT65, LSN50, …) can be set to ABP on a fixed frequency and data rate, which makes them usable with a single LilyGo board and no LoRaWAN network server.Builds on #2402: its first commit is that fix. It is opt-in, and builds without the flags are unchanged (
ttgo-lora32-v21is 1,388,338 bytes with or without this PR).-DLORA_LORAWAN(ESP32 only, about 8 KB):MQTTtoLORA/configcommand, and kept in NVS with"save":true:{"lorawan":{"devaddr":"0187F184","nwkskey":"…","appskey":"…","name":"Front door","model":"LDS02"},"save":true}Devices can also be updated or removed (
"remove":true). The LoRa state message lists them, without keys.LORAtoMQTT/<DEVADDR>withfcnt,fportand the decryptedpayloadhex. Packets from other devices, or that fail the MIC check, keep the currenthexbehaviour.-DLORA_LORAWAN_JS+${libraries.duktape}(about 200 KB):Decoder(bytes, port)(v2) ordecodeUplink(input)(v3), using Duktape 2.7.0 (MIT). Decoders are published raw to<base><gateway>/LORAWANdecoder/<DEVADDR>and stored in NVS (up to 3800 bytes). This topic is deliberately outside/commands/#: that subscription only accepts JSON up toJSON_MSG_BUFFER_MAX, andcmpToMainTopic()matches by prefix. A dedicated PicoMQTT subscription with its own size limit receives the script.decoder_erroris set if the decoder fails. A fresh Duktape heap is used for each uplink, so a faulty decoder cannot leak state between uplinks.new Date()get real time. Today the clock is only set for TLS connections.Home Assistant: an optional per-device
entitieslist (key, type, device class, unit, on/off payloads) creates discovery entities from the published fields.WebUI: a new "Configure LoRaWAN" page (
/lw) is added to the configuration menu:Documentation: new section "Decoding LoRaWAN ABP devices" in
docs/use/lora.md.Tests on a LilyGo LoRa32 V2.1 (SX1276, 915 MHz), receiving a Dragino LDS02 door sensor on firmware v1.8.2 set to ABP, 903.9 MHz, DR0 (SF10/125 kHz):
{"id":"0187F184","name":"LDS02 Door Sensor","model":"LDS02","fcnt":67,"fport":10,"payload":"8C6C0100003B00000000","BAT_V":3.18,"BAT_PCNT":"88.33","DOOR_OPEN_STATUS":1,"DOOR_STATE":"open","LAST_DOOR_OPEN_DURATION":0,"UTC_TIME":"2026-10-09T06:49:17.000Z","rssi":-34,"snr":10.5,"pferror":-2435,"packetSize":23}-wremoved and-Walladded: stock env,LORA_LORAWAN, andLORA_LORAWAN+LORA_LORAWAN_JS. (The default[env]passes-w, which hides all warnings.) The new code is clang-format 9 clean.Limitations: single channel and uplink only. There is no OTAA join, no downlinks and no MAC commands. Frame counters are tracked in RAM, so after a reboot the first frame is accepted whatever its counter. Decoders run without an execution time limit, so a decoder stuck in an infinite loop would block the loop task. This was not tested.
Checklist:
🤖 Generated with Claude Code