Skip to content

Conversation

@jescarri
Copy link
Owner

CLI Tool to trigger upgrdade

go run main.go update-device --private-key /home/jescarri/tmp/key.secret --version=220 --device-name testdev1k --mqtt-broker XXXXXXXXX:1883 --mqtt-username XXXXXXX --mqtt-password XXXXXX --url https://github.com/jescarri/lora-node/releases/download/220/firmware-220.bin
Processing firmware update for device: testdev1k
Firmware URL: https://github.com/jescarri/lora-node/releases/download/220/firmware-220.bin
Version: 220
Downloading firmware to calculate MD5...
Calculating MD5 sum...
MD5 sum: 041408a0c4c0ed5e2ad0e848b6a3c5d1
Shortening URL...
Shortened URL: https://tinyurl.com/28tsogdh
Loading private key...
Signature data: https://tinyurl.com/28tsogdh041408a0c4c0ed5e2ad0e848b6a3c5d1
Signing data...
JSON payload: {"u":"https://tinyurl.com/28tsogdh","v":"220","m":"041408a0c4c0ed5e2ad0e848b6a3c5d1","s":"r2d67mx+pKOEpsLu4Uk64ShtVQZu5DehS6Hse2gOwJTVn5owXHw03ZQ3jWjTPtzpWS5kGEgOWPhLdNSpgT9aBQ=="}
Chunking payload...
Payload chunked into 4 chunks
Connecting to MQTT broker...
Publishing to topic: ttn/soil-conditions/devices/testdev1k/down/push
Publishing 4 chunks as single TTN message
Firmware update payload published successfully!

Node Processing the OTA Upgrade:

[OTA] JSON parsed successfully. Triggering firmware update.
[DEBUG] Raw JSON string: {"u":"https://tinyurl.com/28tsogdh","v":"220","m":"041408a0c4c0ed5e2ad0e848b6a3c5d1","s":"r2d67mx+pKOEpsLu4Uk64ShtVQZu5DehS6Hse2gOwJTVn5owXHw03ZQ3jWjTPtzpWS5kGEgOWPhLdNSpgT9aBQ=="}
[DEBUG] JSON length: 180
[DEBUG] Extracted URL (from 'u'): https://tinyurl.com/28tsogdh
OTA in progress: true
Verifying signature for message: https://tinyurl.com/28tsogdh041408a0c4c0ed5e2ad0e848b6a3c5d1
Signature (base64): r2d67mx+pKOEpsLu4Uk64ShtVQZu5DehS6Hse2gOwJTVn5owXHw03ZQ3jWjTPtzpWS5kGEgOWPhLdNSpgT9aBQ==
Public key: a206eb8f630dbe913481fee5e91b19cd338247187bea975187b545b178ade8c1
Signature verification successful
Signature verification successful
Starting WiFi setup for OTA download...
SSID from settings: 'XXXXXXXXX' (length: 12)
Password from settings: '[CONFIGURED]' (length: 19)
Enabling WiFi in STA mode...
Connecting to WiFi SSID: XXXXXXX
Connecting to WiFi...
SUCCESS: WiFi connected!
IP Address: 192.168.2.53
Gateway: 192.168.2.1
DNS: 10.10.20.2
Signal strength: -58 dBm
=== Memory Status Before OTA ===
Free heap: 159244 bytes
Largest free block: 110580 bytes
Free PSRAM: 0 bytes
Sketch size: 1340496 bytes
Free sketch space: 1966080 bytes
Flash chip size: 4194304 bytes
Starting OTA download from: https://tinyurl.com/28tsogdh
Expected MD5: 041408a0c4c0ed5e2ad0e848b6a3c5d1
Preparing for OTA - forcing garbage collection...
Final memory check - Free heap: 156776 bytes
Starting HTTPUpdate.update()...
Added x-MD5 header: 041408a0c4c0ed5e2ad0e848b6a3c5d1
HTTPUpdate started
OTA Progress: 0/1217312 bytes (0.0%)
OTA Progress: 102400/1217312 bytes (8.4%)
OTA Progress: 266240/1217312 bytes (21.9%)
OTA Progress: 430080/1217312 bytes (35.3%)
OTA Progress: 585728/1217312 bytes (48.1%)
OTA Progress: 651264/1217312 bytes (53.5%)
OTA Progress: 765952/1217312 bytes (62.9%)
OTA Progress: 921600/1217312 bytes (75.7%)
OTA Progress: 1077248/1217312 bytes (88.5%)
OTA Progress: 1171456/1217312 bytes (96.2%)
OTA Progress: 1217312/1217312 bytes (100.0%)
OTA Progress: 1217312/1217312 bytes (100.0%)
HTTPUpdate finished
OTA update completed successfully!
Firmware updated, ready to reboot
Firmware update completed successfully - rebooting
OTA in progress: false
ets Jul 29 2019 12:21:46

jescarri added 18 commits July 22, 2025 16:20
- Updated MQTT package to use proper TTN downlinks array format instead of single downlink_message
- Modified TTNMessage struct to support multiple downlinks with incrementing f_port numbers
- Added PublishChunks method to handle multiple chunks in a single MQTT message
- Updated tests to validate new chunked message structure
- Ensured chunk size respects 51-byte TTN limit
- Fixed CLI to use new chunked publishing method

The message format now correctly generates:
{
  "downlinks": [
    {"f_port": 1, "frm_payload": "...", "priority": "NORMAL"},
    {"f_port": 2, "frm_payload": "...", "priority": "NORMAL"}
  ]
}

Instead of the incorrect single downlink_message format.
The previous base64_decode implementation had critical flaws:
- Incorrect loop logic causing buffer overruns
- Did not properly handle padding characters (=)
- Would fail to decode standard base64 strings correctly

This fix:
- Properly handles base64 padding
- Correctly bounds-checks array access
- Follows standard base64 decoding algorithm
- Should resolve Ed25519 signature verification failures

Resolves the signature verification issue where chunked MQTT
payloads were successfully received but signatures failed
to verify due to incorrect base64 decoding of the signature.
The device was crashing with task watchdog timeout during firmware
download because the WiFi task would take too long without resetting
the watchdog timer.

This fix:
- Adds esp_task_wdt_reset() calls every 512 bytes during download
- Includes progress reporting every 10KB
- Should prevent watchdog timeouts during large firmware downloads

The signature verification is now working correctly with the previous
base64 decoder fix.
The HTTPClient was not following redirects from URL shorteners like
TinyURL, causing it to try to download the redirect HTML page instead
of the actual firmware binary.

This fix:
- Enables HTTPC_STRICT_FOLLOW_REDIRECTS
- Sets redirect limit to 10 hops
- Adds better logging of HTTP responses and redirects
- Should resolve watchdog timeouts caused by downloading wrong content

This addresses the issue where signature verification succeeds but
firmware download fails due to redirect handling.
The device was crashing without showing any WiFi connection attempts,
suggesting potential issues with WiFi setup or settings retrieval.

This fix adds:
- Detailed logging of WiFi credentials from settings
- Proper WiFi state reset before attempting connection
- Extended connection timeout (30 attempts vs 20)
- WiFi status codes and connection details logging
- Regular watchdog resets during WiFi connection attempts
- Network information display upon successful connection
- Better error reporting for troubleshooting

This should help identify whether the issue is:
1. Missing WiFi credentials in settings
2. WiFi connection failure
3. Network connectivity problems
4. Or other issues causing the watchdog timeout
The watchdog crash was happening right after WiFi.mode(WIFI_STA)
because LoRaWAN (LMIC) and WiFi were conflicting for radio resources.

This fix:
- Includes proper LMIC headers and references
- Suspends LMIC operations before enabling WiFi
- Sets OP_SHUTDOWN flag to temporarily disable LMIC
- Clears any pending sendjob callbacks
- Allows clean transition from LoRaWAN to WiFi mode

This should resolve the immediate crash after 'Enabling WiFi in STA mode'
and allow the WiFi connection to proceed normally.
- Replace stack-allocated 4KB buffer with heap-allocated 2KB buffer to prevent stack overflow
- Increase watchdog reset frequency from 2s to 1s during OTA downloads
- Add proper memory cleanup and error handling for heap-allocated buffer
- Update documentation to reflect stack overflow prevention measures
- Resolves Guru Meditation Error: Stack canary watchpoint triggered
- Add explicit HTTP timeout configuration (30s total, 15s connection)
- Add internet connectivity test before OTA download using httpbin.org
- Improve timeout handling for better network reliability
- Add diagnostic output for troubleshooting network issues
- Maintain graceful failure handling with proper error reporting
- Add JSON string and length debug output
- Add extracted URL debug output
- Help identify where URL truncation is occurring
- Temporary debug code to resolve parsing discrepancy
- Increase OTA_MAX_CHUNKS from 20 to 30
- Increase OTA_CHUNK_SIZE from 70 to 100 bytes
- Add debug output to track chunk reception and assembly
- This should resolve JSON truncation issues during OTA updates
- Replace custom HTTP download implementation with ESP32's built-in HTTPUpdate library
- Add automatic HTTPS support with certificate validation bypass for simplicity
- Implement built-in MD5 verification via x-MD5 header
- Add comprehensive progress monitoring with watchdog management
- Improve error handling and cleanup
- Enable strict HTTP redirect following
- Remove large buffer allocation - HTTPUpdate handles streaming internally
- Update documentation to reflect HTTPUpdate integration improvements

This change significantly improves OTA reliability by leveraging the well-tested
ESP32 HTTPUpdate library while maintaining our existing MD5-based integrity checking
and Ed25519 signature verification for security.
- Add comprehensive memory diagnostics before OTA starts
- Check for minimum 32KB heap memory before attempting OTA
- Add try-catch error handling around HTTPUpdate.update() call
- Force memory cleanup with delay before OTA start
- Add detailed memory status logging for debugging
- Improve error reporting for OTA partition erase failures

This addresses potential flash erase crashes by ensuring sufficient memory
is available and providing better error handling during the OTA process.
- Replace huge_app.csv with min_spiffs.csv partition table
- Provides dual app partitions (app0/app1) required for OTA updates
- Each app partition: 1.875MB (sufficient for ~1.33MB firmware)
- Fixes esp_flash_erase_region crashes due to single app partition
- Current firmware: 67.8% of available app partition space
- Increase flash size limit from 1.3MB to 1.8MB (90% of 1.875MB app partition)
- Accounts for min_spiffs.csv partition table with dual OTA app partitions
- Current firmware (~1.34MB) now passes size checks with headroom
- Updated all three pipeline stages: branch, main, and release
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jul 24, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@jescarri jescarri merged commit 98a9678 into main Jul 24, 2025
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants