Compare commits

...
347 Commits
Author SHA1 Message Date
Thomas Göttgens 0f341a289e t2000-wip 2026-03-19 16:24:34 +01:00
f04746a928 Fix RAK4631 Ethernet gateway API connection loss after W5100S brownout (#9754)
* Fix RAK4631 Ethernet gateway API connection loss after W5100S brownout

PoE power instability can brownout the W5100S while the nRF52 MCU keeps
running, causing all chip registers (MAC, IP, sockets) to revert to
defaults. The firmware had no mechanism to detect or recover from this.

Changes:
- Detect W5100S chip reset by periodically verifying MAC address register
  in reconnectETH(); on mismatch, perform full hardware reset and
  re-initialize Ethernet interface and services
- Add deInitApiServer() for clean API server teardown during recovery
- Add ~APIServerPort destructor to prevent memory leaks
- Switch nRF52 from EthernetServer::available() to accept() to prevent
  the same connected client from being repeatedly re-reported
- Add proactive dead-connection cleanup in APIServerPort::runOnce()
- Add 15-minute TCP idle timeout to close half-open connections that
  consume limited W5100S hardware sockets

Fixes meshtastic/firmware#6970

Made-with: Cursor

* Log actual elapsed idle time instead of constant timeout value

Address Copilot review comment: log millis() - lastContactMsec to show
the real time since last client activity, rather than always logging the
TCP_IDLE_TIMEOUT_MS constant.

Made-with: Cursor

* Update src/mesh/api/ServerAPI.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Stop UDP multicast handler during W5100S brownout recovery

After a W5100S chip brownout, the udpHandler isRunning flag stays
true while the underlying socket is dead. Without calling stop(),
the subsequent start() no-ops and multicast is silently broken
after recovery.

Made-with: Cursor

* Address Copilot review: recovery flags and timeout constant

Move ethStartupComplete and ntp_renew reset to immediately after
service teardown, before Ethernet.begin(). Previously, if DHCP
failed the early return left ethStartupComplete=true, preventing
service re-initialization on subsequent retries.

Replace #define TCP_IDLE_TIMEOUT_MS with static constexpr uint32_t
for type safety and better C++ practice.

Made-with: Cursor

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-19 08:37:39 -05:00
WesselandGitHub 1be2529fb9 Enable LNA by default for Heltec v4.3 (#9906)
It should only be disabled by users that have problems with it.
2026-03-19 08:11:10 -05:00
Andrew YongandGitHub 959756abf1 fix(tlora-pager): Remove SDCARD_USE_SPI1 so SX1262 and SD card can share SPI bus (#9870)
Problem:
- Inserting a µSD card causes RadioLib to hit a critical error and reboot
- Device enters a boot loop as the SD card remains inserted

Reproduction:
- Insert a µSD card and power on
- RadioLib reports a critical error on boot
- Device reboots, repeating indefinitely

Root cause:
- On T-Lora Pager, SX1262 and the µSD slot share the same physical SPI bus
  (same SCK/MOSI/MISO pins, differentiated only by CS)
- SDCARD_USE_SPI1 is intended for boards where SD is on a separate SPI bus;
  it initializes a second ESP32 SPI peripheral (SPI3) for SD
- SPI2 is already driving those same pins for LoRa, so both controllers
  simultaneously drive the same GPIO lines, causing bus contention

Fix:
- Remove SDCARD_USE_SPI1 so both devices share a single SPI peripheral (SPI2),
  with CS pins providing device selection as intended
- Tested on a custom fork of device-ui; LoRa and SD card map tiles both work
  correctly with an SD card inserted

Signed-off-by: Andrew Yong <me@ndoo.sg>
2026-03-19 07:20:15 -05:00
c88b802e32 Remove early return during scan of BME address for BMP sensors (#9935)
* Enable pre-hop drop handling by default

* Remove early break if BME/DPS sensors are not detected at the BME address

* revert sneaky change

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-19 07:12:50 -05:00
fw190d13andGitHub 9f74fc11de hexDump: Add const to the buf parameter in hexDump. (#9944)
The function only reads the buffer, so marking it const clarifies intent
and prevents accidental modification.
2026-03-19 06:13:34 -05:00
HarukiToredaandGitHub 2ef09d17b9 BaseUI: Emote Refactoring (#9896)
* Emote refactor for BaseUI

* Trunk Check

* Copilot suggestions
2026-03-17 20:42:37 -05:00
Ben Meadors 19d070c284 Trunk 2026-03-17 14:01:53 -05:00
Ben Meadors e24db2994b Merge remote-tracking branch 'origin/master' into develop 2026-03-17 13:28:25 -05:00
b7379f1516 Update protobufs (#9930)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-03-17 13:25:47 -05:00
Jonathan BennettandGitHub fe8bfa0069 Add new RAK 13302 power curve (#9929) 2026-03-17 12:06:35 -05:00
52750927e3 Upgrade trunk (#9893)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-16 20:48:46 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3ef7a15a17 Update GxEPD2 to v1.6.8 (#9918)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-16 15:40:37 -05:00
ac7a58cd45 Fix: Traceroute through MQTT misses uplink node if MQTT is encrypted (#9798)
* Attempt to fix issue 9713

* Code formatting issue.

* Remade the fix to follow Copilot observations on PR

* Rebuild after AI and GUVWAF

* Update src/mesh/Router.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/mesh/Router.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* trunk fmt

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: GUVWAF <thijs@havinga.eu>
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
2026-03-17 06:48:29 +11:00
53c21eb30d Deprecate/block packets with a missing/invalid hop_start value (pre-hop firmware) (related to issue #7369) (#9476)
* Deprecate forwarding for invalid hop_start

* Add pre-hop packet drop policy

* Log ignored rebroadcasts for pre-hop packets

* Respect pre-hop policy ALLOW in routing gates

* Exempt local packets from pre-hop drop policy

* Format pre-hop log line

* Add MODERN_ONLY rebroadcast mode for pre-hop packets

* Simplify implementation for drop packet only behaviour

* Revert formatting-only changes

* Match ReliableRouter EOF formatting

* Make pre-hop drop a build-time flag

* Rework to compile/build flag MESHTASTIC_PREHOP_DROP

* Set MESHTASTIC_PREHOP_DROP off by default

* Inline pre-hop hop_start validity check

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jord <650645+DivineOmega@users.noreply.github.com>
2026-03-16 06:35:33 -05:00
Tom FifieldandGitHub e51e6cad84 Remove GPS Baudrate locking for Seeed Xiao S3 Kit (#9374)
The Seeed Xiao S3 Kit's default GPS is an L76K which operates at 9600 baud, so when this variant was defined that baud rate was specified.

However, this is a development board and it is expected that users can attach their own devices. This includes GPS, which may operate at a different baud rate. The current fixed baud rate prevents this, so this patch removes that setting.

This will revert to the regular automatic probe method. This will successfully detect the L76K as before (the same speed as before since 9600 baud is the first baud rate checked), but also allow other GPSes at other baud rates to be detected.

Thanks to @ScarpMarc for the report

Fixes https://github.com/meshtastic/firmware/issues/9373#issuecomment-3774802763
2026-03-16 19:28:21 +11:00
TomandGitHub 4890f7084f Add spoof detection for UDP packets in UdpMulticastHandler (#9905)
* Add spoof detection for UDP packets in UdpMulticastHandler

* Implement isFromUs function for packet origin validation

* ampersand
2026-03-14 19:34:19 -05:00
oscgonferandGitHub 3fcbfe4370 Remove a bunch of warnings in SEN5X (#9884) 2026-03-12 06:18:56 -05:00
Catalin PatuleaandBen Meadors b155a63d3b pioarduino Heltec v4: fix build due to LED_BUILTIN compile error. (#9875)
Fixes this build error:

  <command-line>: error: expected unqualified-id before '-' token
  /home/<snip>/.platformio/packages/framework-arduinoespressif32/variants/esp32s3/pins_arduino.h:15:22: note: in expansion of macro 'LED_BUILTIN'
     15 | static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED;
        |                      ^~~~~~~~~~~

More info: https://github.com/meshtastic/firmware/pull/9122#issuecomment-4028263894

The fix is consistent with variants/esp32s3/heltec_v3/platformio.ini

This commit is intentionally on the develop branch, because it's harmless to
develop branch, and makes us more ready for pioarduino when the time comes.

Heltec v4 introduced in: https://github.com/meshtastic/firmware/pull/7845

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-11 06:55:22 -05:00
Ben Meadors 60730a73c2 Initialize LoRaFEMInterface with default fem_type 2026-03-11 06:55:03 -05:00
421f9afead Automated version bumps (#9886)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-11 06:54:16 -05:00
da808cb43b Automated version bumps (#9886)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-11 06:52:18 -05:00
Ben Meadors 82580c6798 Initialize LoRaFEMInterface with default fem_type 2026-03-11 06:48:46 -05:00
429cf51539 Upgrade trunk (#9883)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-11 06:42:48 -05:00
Ben MeadorsandGitHub d9e2b12097 Experiment: C++17 support (#9874)
* Add C++17 support

* Add C++17 runtime probes and update build configurations for STM32 and Portduino

* Remove unflags

* Update C++ standard flags across the platforms

* Convert a couple of instances to structured bindings

* NRF52 platform.txt to add C++17 support

* Still need the unflags apparently

* Remove C++17 runtime probe tests from test_main.cpp

* Reconfigured doesnt need a nodiscard

* Remove nodiscard attribute from init() method in RadioInterface

* Remove mbedtls/error.h from build flags

Removed include directive for mbedtls/error.h from build flags.

* Fix IRAM overflow

* Fix IRAM overflow

* Add build flag to exclude MQTT from rak11200

* Update C++ standard from gnu17 to gnu++17
2026-03-11 06:28:24 -05:00
016e68ec53 Traffic Management Module for packet forwarding logic (#9358)
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Addition of traffic management module

* Fixing compile issues, but may still need to update protobufs.

* Fixing log2Floor in cuckoo hash function

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Adding station-g2 and portduino varients to be able to use this module.

* Spoofing from address for nodeinfo cache

* Changing name and behavior for zero_hop_telemetry / zero_hop_position

* Name change for exhausting telemetry packets and setting hop_limit to 1 so it will be 0 when sent.

* Updated hop logic, including exhaustRequested flag to bypass some checks later in the code.

* Reducing memory on nrf52 nodes further to 12 bytes per entry, 12KB total using 8 bit hashes with 0.4% collision. Probably ok. Adding portduino to the platforms that don't need to worry about memory as much.

* Fixing hopsAway for nodeinfo responses.

* traffic_management.nodeinfo_direct_response_min_hops -> traffic_management.nodeinfo_direct_response_max_hops

* Removing dry run mode

* Updates to UnifiedCacheEntry to use a common cache, created defaults for some values, reduced a couple bytes per entry by using a resolution-scale time selection based on configuration value.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Creating consistent log messages

* Remove docs/ESP32_Power_Management.md from traffic_module

* Add unit tests for Traffic Management Module functionality

* Fixing compile issues, but may still need to update protobufs.

* Adding support for traffic management in PhoneAPI.

* Making router_preserve_hops work without checking if the previous hop was a router. Also works for CLIENT_BASE.

* Enhance traffic management logging and configuration. Updated log messages in NextHopRouter and Router to include more context. Adjusted traffic management configuration checks in AdminModule and improved cache handling in TrafficManagementModule. Ensured consistent enabling of traffic management across various variants.

* Implement destructor for TrafficManagementModule and improve cache allocation handling. The destructor ensures proper deallocation of cache memory based on its allocation source (PSRAM or heap). Additionally, updated cache allocation logic to log warnings only when PSRAM allocation fails.

* Update TrafficManagementModule with enhanced comments for clarity and improve cache handling logic. Update protobuf submodule to latest commit.

* Add mock classes and unit tests for Traffic Management Module functionality.

* Refactor setup and loop functions in test_main.cpp to include extern "C" linkage

* Update comment to include reduced  memory requirements

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Re-arranging comments for programmers with the attention span of less than 5 lines of code.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in TrafficManagementModule to reflect changes in timestamp epoch handling and memory optimization details.

* bug: Use node-wide config_ok_to_mqtt setting for cached NodeInfo replies.

* Better way to handle clearing the ok_to_mqtt bit

* Add bucketing to cuckoo hashing, allowing for 95% occupied rate before major eviction problems.

* Extend nodeinfo cache for psram devices.

* Refactor traffic management to make hop exhaustion packet-scoped. Nice catch.

* Implement better position precision sanitization in TrafficManagementModule.

* Added logic in TrafficManagementModule to invalidate stale traffic state. Also, added some tests to avoid future me from creating a regression here.

* Fixing tests for native

* Enhance TrafficManagementModule to improve NodeInfo response handling and position deduplication logic. Added tests to ensure local packets bypass transit filters and that NodeInfo requests correctly update the requester information in the cache. Updated deduplication checks to prevent dropping valid position packets under certain conditions.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-11 06:12:12 -05:00
d7d08a4725 Upgrade trunk (#9877)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-10 06:26:22 -05:00
79f469ce71 pioarduino Heltec v4: fix build due to LED_BUILTIN compile error. (#9875)
Fixes this build error:

  <command-line>: error: expected unqualified-id before '-' token
  /home/<snip>/.platformio/packages/framework-arduinoespressif32/variants/esp32s3/pins_arduino.h:15:22: note: in expansion of macro 'LED_BUILTIN'
     15 | static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT + PIN_RGB_LED;
        |                      ^~~~~~~~~~~

More info: https://github.com/meshtastic/firmware/pull/9122#issuecomment-4028263894

The fix is consistent with variants/esp32s3/heltec_v3/platformio.ini

This commit is intentionally on the develop branch, because it's harmless to
develop branch, and makes us more ready for pioarduino when the time comes.

Heltec v4 introduced in: https://github.com/meshtastic/firmware/pull/7845

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-10 06:19:25 -05:00
0668b82858 Upgrade trunk (#9868)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-09 17:38:02 -05:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
0797378a4d chore(deps): update meshtastic/device-ui digest to 622b034 (#9864)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-09 17:37:48 -05:00
0501e177e9 T-mini Eink S3 Support for both InkHUD and BaseUI (#9856)
* Tmini Eink fix

* tuning

* better refresh

* Fix to lora pins to be like the original.

* Update pins_arduino.h

* removed dead flags from previous tests

* Update src/graphics/niche/Drivers/EInk/GDEW0102T4.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-09 17:37:34 -05:00
Ben MeadorsandGitHub a79b75a0d5 Update ESP8266Audio dependency to Meshtastic fork for compatibility (#9872)
* Update ESP8266Audio dependency to Meshtastic fork for compatibility

* Update ESP8266Audio dependency to Meshtastic fork for compatibility across multiple platformio.ini files
2026-03-09 17:36:18 -05:00
Ben Meadors 391928ed08 Add include directive for mbedtls error handling in build flags 2026-03-08 20:58:00 -05:00
Ben Meadors 6cbb9ab09a Gate chatty smart broadcast debug message behind GPS_DEBUG 2026-03-08 06:08:15 -05:00
AustinandGitHub f185abbcdd Debian: Extend sourcedeb cache expiration (#9858)
Addendum to PR #9791
The sourcedebs cannot currently be built offline >30 days after release. Extend the cache-expiry-mangling hack to sourcedeb packaging.
2026-03-07 19:31:41 -06:00
Ben Meadors 5d12edbe07 Add convenience userpref for disabling lora during development and testing 2026-03-07 11:13:55 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
398d1adea1 chore(deps): update meshtastic-esp32_https_server digest to b78f12c (#9851)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-07 06:51:03 -06:00
Ben Meadors 393cd96ba2 Merge remote-tracking branch 'origin/develop' 2026-03-07 06:39:08 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
6658ec2603 chore(deps): update neopixel to v1.15.4 (#9839)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 19:56:01 -06:00
pdxlocationsandGitHub b941dab900 Add APIPort to native config (#9840) 2026-03-07 08:49:26 +11:00
Ben Meadors ffe6f706f9 Merge remote-tracking branch 'origin/develop' 2026-03-06 10:48:51 -06:00
0ed537a336 Add json file rotation option (#9783)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 10:24:32 -06:00
86dad90573 Fix nRF52 AsyncUDP multicast TX/RX race condition causing garbled packets (#9765)
socketSendUDP() calls yield() while waiting for SEND_OK, allowing the
cooperative scheduler to run AsyncUDP::runOnce(). When runOnce() calls
parsePacket() on the same socket during an active send, the multicast
loopback packet arriving from the switch produces a garbled 8-byte RX
header (wrong source IP, wrong payload length), leading to protobuf
decode errors in UdpMulticastHandler.

Add a volatile isSending flag that writeTo() sets around endPacket()
(the only yield point). runOnce() checks this flag and skips
parsePacket() while a send is in progress. Loopback packets stay
buffered in the W5100S RX buffer and are read cleanly on the next
poll cycle.

Also propagate writeTo() return value in UdpMulticastHandler::onSend()
instead of unconditionally returning true.

Made-with: Cursor

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 08:38:50 -06:00
Ben MeadorsandGitHub 20db5fdbb7 Fix WisMesh Tap V2 env mess (#9734)
* Fix environment mess with wismesh tap v2

* Address feedback
2026-03-06 06:23:01 -06:00
5b1ea922f3 InkHUD: Nodelist cleanup (#9737)
* Nodelist cleanup

* Trunk fix

* getTextWidth cleanup

Updated the lambda to cache width in textW and reuse it instead of repeatedly calling getTextWidth(text) for unchanged text.

* Putting back hopAway ==0  condition as mentioned relayed signal is missleading

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 06:16:34 -06:00
5b94f580dc PPA: Remove Ubuntu 25.04, Add 26.04 (#9789)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 06:16:17 -06:00
3d524be965 Update Heltec Tracker v2 to version KCT8103L. (#9822)
* Update Heltec Tracker v2 to version KCT8103L.

* Fixed the issue of inaccurate comments.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 06:15:42 -06:00
4ec59ce75d Upgrade trunk (#9835)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-06 05:41:56 -06:00
WesselandGitHub cb28c38828 fix(t1000e): reclassify P0.04 as sensor power enable GPIO (#9826)
P0.04 is a digital power-enable pin for the NTC/LUX sensors, not an ADC
input. The old code was calling analogRead() on a floating GPIO that
happened to read ~mid-rail, coincidentally producing reasonable
temperature values.

- Rename T1000X_VCC_PIN to T1000X_SENSOR_EN_PIN and drive it HIGH in
initVariant() for both T1000-E and T1000-S variants
- Read BATTERY_PIN (with ADC_MULTIPLIER) instead, clamped to the 3.0V
LDO output (NTC_REF_VCC) for the NTC resistance calculation
2026-03-06 05:41:37 -06:00
969aefa551 Cardputer Kit (#9540)
* Cardputer Kit
BMI270 WIP

* BMI270 support

* verify that the number of bytes read matches the requested length

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* trunk'd

* remove excessive logging

* Kick the screen when unsleeping

* Update the st7789 library, and enable displayon and displayoff

* Battery detection

* Default to arrow keys and enter, while in menus.

* Enable Backlight control

* Update src/detect/ScanI2CTwoWire.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* updateState method now accepts shouldRequestFocus parameter for better maintainability

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-06 05:34:41 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3f5828c0e9 chore(deps): update docker/setup-buildx-action action to v4 (#9824)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 17:57:10 +11:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5cf365245e chore(deps): update docker/build-push-action action to v7 (#9832)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 16:28:15 +11:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
fdd17ac75c chore(deps): update docker/metadata-action action to v6 (#9833)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-06 16:27:48 +11:00
Jonathan BennettandGitHub 9e40c8893f Don't double-blink Thinknode-M1 Power LED while charging (#9829)
* Don't double-blink Thinknode-M1 Power LED while charging

* Drop Double Define
2026-03-05 20:34:31 -06:00
afd5e29bce More RAK6421 work (#9813)
* Add Portduino Enable pins

* Add hat plus custom fields

* Punt on the GPIO device detection for now

* Simplify TX_GAIN_LORA for RAK13302

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-05 08:15:33 -06:00
20f838a61e Add explicit dependency on mklittlefs. (#9708)
This fixes builds in very clean environment with default build target (e.g.
-t buildfs *not* explicitly specified).

Tested: pio run -e heltec-v3

Fixes #9035

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-05 06:55:02 -06:00
Clive BlackledgeandGitHub 58736f5184 fix: add ROUTER_LATE to rebroadcast integrity checks (#9816)
Adds ROUTER_LATE and CLIENT_BASE to preferred rebroadcaster check
(skip unsolicited NodeInfo) and prevents ROUTER_LATE from setting
rebroadcast mode to NONE, which would silently break relaying.
2026-03-05 06:23:17 -06:00
22031c5886 fix: treat ROUTER_LATE like ROUTER for power management and defaults (#9815)
ROUTER_LATE is an infrastructure relay that should use the same power
assumptions, interval defaults, and LoRa wake behavior as ROUTER.
Without this, ROUTER_LATE uses client-class defaults and will not
wake on LoRa activity from deep sleep, making it a broken relay.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-05 06:22:12 -06:00
fe4e75eb66 fix: add ROUTER_LATE and TAK_TRACKER to congestion scaling exemption (#9818)
ROUTER_LATE already has high base intervals and should not be further
scaled by congestion. TAK_TRACKER is a tracker variant that should
skip congestion scaling like TRACKER does.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-05 06:19:45 -06:00
42075da09e Upgrade trunk (#9823)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-05 06:17:41 -06:00
Clive BlackledgeandGitHub 6ba82ed5b6 fix: prevent router-like roles from auto-favoriting DM peers (#9821)
ROUTER and ROUTER_LATE should not accumulate favorites by sending DMs.
Also replaces magic number 12 with meshtastic_Config_DeviceConfig_Role_CLIENT_BASE.
2026-03-05 06:00:14 -06:00
935b0504d4 Update protobufs (#9825)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-03-05 06:00:01 -06:00
a8fed3256e fix: add ROUTER_LATE to telemetry impolite role check (#9819)
ROUTER_LATE should be treated as an impolite telemetry role like
ROUTER, responding to multi-hop broadcast requests and using
aggressive send timing without channel utilization checks.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-05 05:59:50 -06:00
Clive BlackledgeandGitHub 1626836a71 fix: add ROUTER_LATE to infrastructure init and config preservation (#9820)
ROUTER_LATE now preserves node_info_broadcast_secs during factory
reset and auto-enables Store & Forward server mode, matching ROUTER
infrastructure behavior.
2026-03-05 05:48:53 -06:00
Larry DoolittleandGitHub 66161da2a7 spelling fixes in .md files (#9810)
9 fixes across 6 files
notably includes github/pull_request_template.md
2026-03-05 08:54:57 +11:00
Ben Meadors 6bbdfe1797 Merge remote-tracking branch 'origin/develop' 2026-03-04 08:24:32 -06:00
7ea28d34b2 Add back FEM LNA mode configuration for LoRa (#9809)
* Add back FEM LNA mode configuration for LoRa

* Update src/mesh/NodeDB.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/AdminModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* copilot garbage

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-04 08:23:55 -06:00
Ben MeadorsandGitHub 65bf1630b3 Add some lora parameter clamping logic to coalesce to defaults and enforce some bounds (#9808) 2026-03-04 07:55:34 -06:00
Ben Meadors 3972fe1fd0 Merge remote-tracking branch 'origin/master' into develop 2026-03-04 07:53:12 -06:00
5ced739a57 Add heltec-v4.3 board (#9753)
* Add heltec-v4.3 board

* Modify LNA control display content

* Fix Heltec Tracker v2 FEM control

* Use trunk to fix formatting issues.

* Optimize the fem initialization control logic.

* Update src/mesh/RadioInterface.h change #ifdef to #if

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Change LORA_PA_EN to LORA_GC1109_PA_EN.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Remove the NodeDB.h include.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Change tx_gain to a const variable.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fixed the issue where ARCH_PORTDUINO lacked the NUM_PA_POINTS macro.

* Remove the comment.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Move #pragma once to the first line.

* Remove the FEM LNA control menu.

* Add description for KCT8103L.

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-04 06:27:12 -06:00
b7bf251798 Scaling tweaks (#9653)
* refactor: update throttling factor calculation and add unit tests for scaling behavior

* refactor: adjust throttling factor calculation for improved accuracy in different configurations

* Update src/mesh/Default.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/mesh/Default.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* refactor: enhance throttling factor calculation and introduce pow_of_2 utility function

* refactor: improve expected ms calculation in unit tests for Default::getConfiguredOrDefaultMsScaled

* refactor: improve scaling logic for routers and sensors in computeExpectedMs function

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-04 05:59:42 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
90742fc87e chore(deps): update dorny/test-reporter action to v2.6.0 (#9796)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-04 05:17:53 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
f7f356e2e2 chore(deps): update arduinojson to v6.21.6 (#9788)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-04 05:17:36 -06:00
1fad7facd6 Upgrade trunk (#9805)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-04 05:17:20 -06:00
AustinandGitHub 153ab81a9f Deb: Handle offline builds more gracefully (#9791) 2026-03-04 05:16:45 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
8d73d67246 chore(deps): update docker/setup-qemu-action action to v4 (#9807)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-04 05:12:32 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
0d46943bb8 chore(deps): update docker/login-action action to v4 (#9806)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-04 05:12:12 -06:00
Larry DoolittleandGitHub deb45e471c spelling fixes (#9801)
45 corrections in c++ source comments
limited to 27 files in src/gps src/graphics src/input
2026-03-04 16:36:53 +11:00
3601eabbf8 Improve resource cleanup on connection close (and make server API a unique pointer) (#9799)
* Improve resource cleanup on connection close

* Copilot had some good feedback. Let's just make the api a unique pointer

* Update src/mesh/api/ServerAPI.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Copilot stupidly suggesting we call protected methods

* Gotta do it in the superclasses as well

* Fix moar

* Refactor MQTT unit test to ensure proper subscription handling and clear side effects

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-03 13:37:15 -06:00
eb2f3cef89 Update protobufs (#9797)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-03-03 06:43:06 -06:00
85be5965b0 Upgrade trunk (#9795)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-03 05:36:09 -06:00
1e34c1ef1b Remove "x" permission bits from some source files (#9794)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-03-03 05:34:03 -06:00
Thomas GöttgensandGitHub 5f852a1c05 Add ADS1115 ADC to recognition as used on RAK6421 Hat (#9790) 2026-03-03 08:55:53 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1d90ea6f1d chore(deps): update crazy-max/ghaction-import-gpg action to v7 (#9787)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-03 08:09:40 +11:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
65eee22396 chore(deps): update github artifact actions (#9767)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-03 08:09:01 +11:00
cb938266c7 Upgrade trunk (#9785)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-03-02 06:45:53 -06:00
Clive BlackledgeandGitHub 8093e2ed5a Bug: Mqtt fix testcase due to immediately sending MapReport (#8872) (#9784)
* Add ESP32 Power Management lessons learned document

Documents our experimentation with ESP-IDF DFS and why it doesn't
work well for Meshtastic (RTOS locks, BLE locks, USB issues).

Proposes simpler alternative: manual setCpuFrequencyMhz() control
with explicit triggers for when to go fast vs slow.

* Added a lambda function to clear startup output in the MQTT unit test to ensure a clean state before and after the MQTT subscription process.
2026-03-02 06:45:42 -06:00
80af726877 avoid memory leak when possibly malformed packet received (#9781)
getByIndex allocates memory and returns dummy channel whenever
chIndex validation fails. Comment implies this may happen
when malformed packet is received. The fix changes implementation
so static dummyChannel is returned in such case.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-28 18:37:41 -06:00
Ben Meadors 3f5dc78744 Update log verbiage to remove GC1109 reference 2026-02-28 17:26:21 -06:00
563adc6aaa enhancement(mesh): remove late packets from tx queue when full (#9779)
* enhance tx queue priority management

In busy environments, especially for ROUTER_LATE role, tx queue
fills very quickly. Delayed packets became late but new packets
to be retransmitted won't be put into the tx queue as old ones
stay there for a very long time (even a minute or more). This change
makes meshtastic prioritize new packets over late packets from tx queue
and allows to remove late packet from back of tx queue when there
is no space for a new one.

* apply copilot recommendation for cast

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-28 17:17:29 -06:00
Ben Meadors 67f806b0a5 Merge remote-tracking branch 'origin/master' into develop 2026-02-28 11:08:15 -06:00
Ben Meadors c7dc536640 Merge remote-tracking branch 'origin/develop' 2026-02-28 09:39:25 -06:00
Ben MeadorsandGitHub 6920a5f8b1 Increase PSRAM malloc threshold from 256 bytes to 2048 bytes (#9758) 2026-02-28 09:34:26 -06:00
2b7a230977 Upgrade trunk (#9752)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-28 08:41:34 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1e16185fdd chore(deps): update platformio/ststm32 to v19.5.0 (#9764)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 08:41:21 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
60c2592694 chore(deps): update adafruit dps310 to v1.1.6 (#9763)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 08:41:01 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
fc0ad4956e chore(deps): update adafruit ahtx0 to v2.0.6 (#9766)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-28 08:40:15 -06:00
Ben MeadorsandGitHub 43aa90fc3f Unlock 0x8B5 register macro guard for SX162 (#9777) 2026-02-28 08:38:08 -06:00
Ben Meadors c28bdbd7e6 Fix mqtt test 2026-02-28 08:32:05 -06:00
857c7b3a3a Don't launch canned message when waking screen or silencing notification (#9762)
* Don't launch canned message when waking screen or silencing notification

* Add screen ifdefs

* Get the #if right

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-27 17:07:03 -06:00
Andrew YongandGitHub 83cac93ca8 fix(MQTT): Send first MapReport as soon as possible (#8872)
* fix(MQTT): First MapReport does not get sent

Throttle::isWithinTimespanMs(last_report_to_map, map_publish_interval_msecs) is
used to maintain the map reporting interval, but because last_report_to_map has
an initial value of 0, the map report routine does not start until the system
millis() time has passed map_publish_interval_msecs.

Fix this by adding a check that last_report_to_map is not 0.

Signed-off-by: Andrew Yong <me@ndoo.sg>

* feat(MQTT): Send MapReporting immediately upon location fix

Do not update last_report_to_map when Map Report is attempted without a valid
location, as this results in waiting up to an hour (or configured Map Report
interval).

That usually happens because most nodes do not keep GPS warm, so GPS usually
locks after the first attempt at Map Report.

This change also results in the log WARNing message getting spammed until a
location is obtained, so remove the message for now.

Signed-off-by: Andrew Yong <me@ndoo.sg>

* feat(MQTT): Throttled warning when position is not available for MapReport

Signed-off-by: Andrew Yong <me@ndoo.sg>

---------

Signed-off-by: Andrew Yong <me@ndoo.sg>
2026-02-27 05:16:55 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
d34fa3e7df chore(deps): update platformio/nordicnrf52 to v10.11.0 (#9760)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 08:11:00 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
75cb8bb5ea chore(deps): update platformio/espressif32 to v6.13.0 (#9759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 08:09:44 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2a99cc6a25 chore(deps): update adafruit mlx90614 to v2.1.6 (#9756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 08:01:28 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
b5f98d1270 chore(deps): update adafruit_tsl2561 to v1.1.3 (#9757)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-26 08:01:03 -06:00
Ben Meadors ef697319da Merge remote-tracking branch 'origin/develop' 2026-02-26 07:53:34 -06:00
Ben MeadorsandGitHub efd68f9fad Fix Bluetooth on RAK Ethernet Gateway by removing MESHTASTIC_EXCLUDE_POWER_FSM from build_flags (#9755) 2026-02-26 07:38:13 -06:00
3a74e049ab Add Transmit history persistence for respecting traffic intervals between reboots (#9748)
* Add transmit history for throttling that persists between reboots

* Fix RAK long press detection to prevent phantom shutdowns from floating pins

* Update test/test_transmit_history/test_main.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Test fixes and placeholder for content handler tests

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-25 20:41:07 -06:00
3b1b308357 platform: nrf52: Fix typo in BLEDfuSecure filename (#9709)
Change file name from BLEDfuScure.cpp to BLEDfuSecure.cpp. Fix filenames
in documentation.

Signed-off-by: Koko <github@kokosoftware.pl>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-25 18:00:02 -06:00
5a068431ed Add GPIO_DETECT_PA portduino config, and support 13302 detection with it (#9741)
* Add GPIO_DETECT_PA portduino config, and support 13302 detection with it.

* Tweak PA detect gpio to use pinMapping

* minor yaml output fixes

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-25 14:18:07 -06:00
25f086a64f Upgrade trunk (#9744)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-25 08:30:32 -06:00
Ben MeadorsandGitHub a93d4d7e9d Revert "Fix/rak3401 button (#9668)" (#9747)
This reverts commit a5523b04ef.
2026-02-25 08:26:49 -06:00
Thomas GöttgensandGitHub 54781cf51a hopefully fix remaining cppcheck issues (#9745) 2026-02-25 10:27:21 +01:00
WesselandGitHub ad7d19c317 Remove unused global rIf that shadows locals and fails cppcheck (#9743)
I noticed because my PR failed
2026-02-24 20:57:58 -06:00
Thomas Göttgens 58496e56d2 fail cppcheck on low already. Code quality for the win. 2026-02-24 22:45:38 +01:00
Ben Meadors 2c18a41613 Merge remote-tracking branch 'origin/master' into develop 2026-02-24 14:28:15 -06:00
c65eecc295 Update protobufs (#9739)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-24 14:27:23 -06:00
Ben MeadorsandGitHub cac45d9ced Align telemetry broadcast want_response behavior with traceroute (#9717)
* Align telemetry broadcast want_response behavior with traceroute

* Fixes

* Reduce side-effects by making the telemetry modules handle the ignorerequest

* Remove unnecessary ignoreRequest flag

* Try inheriting from MeshModule

* Add exclusion for sensor/router roles and add base telem module
2026-02-24 13:26:47 -06:00
WesselandGitHub 02d42f87d3 Implement 'agc' reset for SX126x & LR11x0 chip families (#9705)
* Implement 'agc' reset for SX126x chip family

There's no actual agc on SX126x chips but you can reset the analog
registers by doing a warm sleep & running calibration.

* Address PR comments & implement for LR11x0 too

* calibrate for configured frequency band

* Gate LR11X0_AGC_RESET
2026-02-24 08:03:25 -06:00
Ben Meadors 9c439f8d0a FIx loophole with telemetry coercion 2026-02-24 06:01:52 -06:00
cf998f03b6 Upgrade trunk (#9731)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-24 05:47:18 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
f9d1f2414a chore(deps): update sensorlib to v0.3.4 (#9727)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-24 05:46:27 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
13b25c0614 chore(deps): update meshtastic-st7789 digest to 9ee76d6 (#9729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-23 20:42:52 -06:00
AustinandGitHub 607b631114 meshtasticd: Add Luckfox Lyra Hat pinmaps (#9730)
Luckfox Lyra Plus + Waveshare Pi Pico Hat
Luckfox Lyra Ultra + wehooper4's "Luckfox Ultra" hat.
2026-02-23 20:42:41 -06:00
99e88bb499 Support mini ePaper S3 Kit (#9335)
* initial draft

* update DC pin

* add ADC channel

* fix e-ink display

* update GxEPD2 reference

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-23 12:08:24 -06:00
4f84cf011d Upgrade trunk (#9724)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-23 05:38:33 -06:00
oscgonferandGitHub 417ca86c30 Split module includes for AQ module (#9711) 2026-02-22 21:07:32 -06:00
renovate[bot]Thomas Göttgensrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7df37f8254 chore(deps): update radiolib to v7.6.0 (#9695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-22 18:53:33 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
0726a9f774 chore(deps): update radiolib to v7.6.0 (#9695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-22 18:46:39 +01:00
Ben Meadors f8cc1d6046 Merge remote-tracking branch 'origin/develop' 2026-02-22 06:10:05 -06:00
WesselandGitHub 9383d0bcfc Apply SX1262 register 0x8B5 patch for improved GC1109 RX sensitivity (#9571)
* Apply SX1262 register 0x8B5 patch for improved GC1109 RX sensitivity

Sets the LSB of undocumented SX1262 register 0x8B5 on Heltec V4 and
Wireless Tracker V2 boards with the GC1109 FEM. This patch was
recommended by Heltec/Semtech and tested in MeshCore PR #1398, where
it significantly reduced packet loss on the Heltec V4.

* Use higher level function

* Add .venv/ to .gitignore
2026-02-21 09:08:14 -06:00
f615990c00 Limit http connections and add free heap check before allocating for SSL (#9693)
* Reduce maximum concurrent HTTPS connections to save memory

* Add heap check and limit connections to prevent HTTPS connection related crashes

* Use Throttle::isWithinTimespanMs for overflow-safe heap warning throttle

* Update src/mesh/http/WebServer.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix double-free heap corruption and parser leak in web server handlers

- Remove double-free in handleFsBrowseStatic, handleNodes, handleScanNetworks:
  JSONValue(const JSONArray&) shallow-copies pointers, so delete value already
  recursively frees all elements. The explicit cleanup loops were deleting the
  same pointers a second time, corrupting the ESP32 heap allocator metadata.
  This is the likely root cause of #8827 (SSL setup failures after uptime).
- Fix memory leak in handleFormUpload: two early-return paths were missing
  delete parser.
- Remove unused global HTTPClient httpClient and its includes.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-21 09:06:17 -06:00
8feb34e7a8 RadioLib edge-triggered interrupts robustness (#9658)
* Fix potential race condition (read, ISR write, clear) in NotifiedWorkerThread

* Check for missed edge-triggered interrupts race condition between startReceive and enableInterrupt

* Occasionally poll to catch missed RX_DONE interrupts. (RadioLibInterface::pollMissedIrqs)

* Simplify RadioLibInterface::checkRxDoneIrqFlag()

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-21 06:14:04 -06:00
David RembaandGitHub a5523b04ef Fix/rak3401 button (#9668) 2026-02-21 09:15:22 +01:00
WesselandGitHub af518fbd2b Hold GC1109 FEM power during deep sleep for LNA RX wake (#9572)
* Hold GC1109 PA_POWER and PA_EN during deep sleep for LNA RX wake

Use rtc_gpio_hold_en to latch PA_POWER (LDO) and PA_EN (CSD) HIGH
during deep sleep so the GC1109 LNA remains powered for wake-on-packet
RX. Previously these pins used weak pull-ups which could lose state.

On deep sleep wake, skip these pins in the blanket RTC hold release and
instead release them in SX126xInterface::init() after GPIO registers are
set HIGH first, avoiding a power glitch on the GC1109.

Trade-off: ~6.5mA additional deep sleep current for significantly
improved wake-on-packet RX sensitivity (~17dB).

Reference: https://github.com/meshcore-dev/MeshCore/pull/1600

* Add LDO startup delay before GC1109 chip enable

TLV75733P LDO has ~550us startup time (datasheet tSTR). On cold boot,
wait 1ms for VBAT to stabilise before driving CSD/CPS, per GC1109
power-on sequence requirement. On deep sleep wake the LDO is held on
via RTC latch so no delay is needed.
2026-02-20 16:12:54 -06:00
Ben Meadors 8c37d6923b Add #include "RadioLibInterface.h" 2026-02-20 12:00:30 -06:00
Ben MeadorsandGitHub 299ef95f25 Revert "Add agc reset attempt (#8163)" (#9702)
This reverts commit ac611c4b62.
2026-02-20 11:25:28 -06:00
8f81b194d3 BLE Pairing fix (#9701)
* BLE Pairing fix

* gating for consistency

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-20 10:38:07 -06:00
6bc3e31537 Upgrade trunk (#9696)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-20 06:45:46 -06:00
840b29860f skip header items when enabling the InkHUD menu cursor (#9552)
* onNavUp() sets the menu cursor to the last item if not shown

* skip headers when showing the menu cursor in onNavUp() and onNavDown()

* skip headers when showing the menu cursor in onButtonShortPress()

* brace cursor incrementing

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2026-02-20 06:12:22 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
15460c8f97 Update meshtastic-GxEPD2 digest to c7eb4c3 (#9694)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-19 17:11:04 -06:00
Ben Meadors a77ac21e0d Trunk 2026-02-19 07:17:50 -06:00
Ben Meadors 2b6d8f6824 Merge branch 'develop' 2026-02-19 07:17:20 -06:00
+19 4c91beeda9 Develop to master (#9618)
* Don't ever define PIN_LED or BLE_LED_INVERTED (#9494)

* Don't ever define PIN_LED

* Deprecate BLE_LED_INVERTED

* Add StatusMessage module and config overrides (#9351)

* Add StatusMessage module and config overrides

* Trunk

* Don't reboot node simply for a StatusMessage config update

* Missed in reviews - fixing send bubble (#9505)

* Prefer EXT_PWR_DETECT pin over chargingVolt to detect power unplugged (#9511)

* Make sure we always return a value in NodeDB::restorePreferences() (#9516)

In case FScom is not defined there is no return statement. This
moves the return outside of the ifdef to make sure a defined
value is returned.

* Inkhud battery icon improvements. (#9513)

* Inkhud battery icon improvements.
Fixes the battery icon draining from the flat side towards the bump, which is backwards from general design language seen on most devices
By request of kr0n05_ on discord, adds the ability to mirror the battery icon which fixes that issue in another way, and is also a common design seen on other devices.

* Remove option for icon mirroring

* Add border + dither to battery to prevent font overlap

* Fix trunk format

* Code cleanup, courtesy of Xaositek.

* Add reply bot module with DM-only responses and rate limiting (#9456)

* Implement Meshtastic reply bot module with ping and status features

Adds a reply bot module that listens for /ping, /hello, and /test commands received via direct messages or broadcasts on the primary channel. The module always replies via direct message to the sender only, reporting hop count, RSSI, and SNR. Per-sender cooldowns are enforced to reduce network spam, and the module can be excluded at build time via a compile flag. Updates include the new module source files and required build configuration changes.

* Update ReplyBotModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/ReplyBotModule.h

Match the existing MESHTASTIC_EXCLUDE_* guard pattern so the module is excluded by default.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/ReplyBotModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Tidying up

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* HotFix for ReplyBot - Modules.cpp included and moved configuration.h (#9532)

* Undefine LED_BUILTIN (#9531)

Keep variant in sync with
https://github.com/meshtastic/firmware/commit/df40085

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* Add agc reset attempt (#8163)

* Add agc reset attempt

* Add radioLibInterface include

* Trunk

* AGC reset don't crash, don't naively call

* Update src/main.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Use Throttle function

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Remove unused hmx variable (#9529)

The variable is not used at all in the function, remove it to
silence the compiler warning.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* Rename LED_PIN to LED_POWER, move handling out of main to dedicated module (#9512)

* Rename LED_PIN to LED_POWER, move handling out of main to dedicated module

* Misc

* Remove errant endif

* Fix hop_limit upgrade detection (#9550)

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* meshtasticd: Fix install on Fedora 43 (#9556)

* RPM: Include meshtasticd-start.sh (#9561)

* Add Slash Key to VirtualKeyboard (#9563)

Addition of ? and / to the virtual Keyboard via short and long press

* Add support for CW2015 LiPo battery fuel gauge (#9564)

* Add support for CW2015 LiPo battery fuel gauge

* Address Copilot's concerns, minor fixups

* Make LED_POWER blip even in critical battery (#9545)

* Enable FORTIFY and SP for native builds (#9537)

* Enable FORITFY and NX for native builds

meshtasticd does have an executable stack and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and a non-executable stack.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

* Enable FORTIFY and NX for native builds

meshtasticd does have an executable stack and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and a non-executable stack.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

* Enable FORTIFY and SP for native builds

meshtasticd does have a stack canaries and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and stack canaries.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* Update built-in documentation for current method of implementation (#9592)

* Refactor logging in ProtobufModule to ensure message details are logged after successful decoding (#9536)

* Automated version bumps (#9604)

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* Add missing openocd_target to custom nrf52 boards (#9603)

This stops platformio complaining about `Missing target configuration for me25ls01-4y10td` etc when trying to flash with nrfutil.

* Add sdl libs for native builds (#9595)

* Add sdl libs for native builds

* Alpine try again

* fix some random compiler warnings (#9596)

* Modify the dependency library of v4-tft (#9507)

* BaseUI: Favorite Screen Signal Quality improvement (#9566)

* Favorite Signal Quality improvement

* Show Voltage if node shares it.

* Trunk Fix

* Change Favorite tittle to encase name with Asterisks

* Add Pluggin In condition for Battery Line

* Adjust getUptimeStr Prefixes

* Create isAPIConnected for SharedCommon usage

* Correct leftSideSpacing to account for isAPIConnected

---------

Co-authored-by: Jason P <applewiz@mac.com>

* ExternalNotification and StatusLED now call AmbientLighting to update… (#9554)

* ExternalNotification and StatusLED now call AmbientLighting to update RGB LEDs. Add optional heartbeat

* Don't overwrite RGB state if heartbeat is disabled.

* Use the right define

* Remove another .h and make rgb static

* move rgb objects into AmbientLighting class

* Straighten out AmbientLighting Thread object

* Use %f for floats

* Fixes on SCD4X admin comands (#9607)

* Fixes on SCD4X admin comands

* Minor fix in logs for SEN5X

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* feat/add sfa30 (#9372)

* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Initial implementation for SFA30Sensor

* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Add ScreenFonts.h

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>

* PMSA003I 1st round test

* Fix I2C scan speed

* Fix minor issues and bring back I2C SPEED def

* Remove PMSA003I library as its no longer needed

* Add functional SCD4X

* Fix screen frame for CO2

* Add admin commands to SCD4X class

* Add further admin commands and fixes.

* Remove unused I2C speed functions and cleanup

* Cleanup of SEN5X specific code added from switching branches
* Remove SCAN_I2C_CLOCK_SPEED block as its not needed
* Remove associated functions for setting I2C speed

* Unify build epoch to add flag in platformio-custom.py (#7917)

* Unify build_epoch replacement logic in platformio-custom

* Missed one

* Fix build error in rak_wismesh_tap_v2 (#7905)

In the logs was:
"No screen resolution defined in build_flags. Please define DISPLAY_SIZE."

set according to similar devices.

* Put guards in place around debug heap operations (#7955)

* Put guards in place around debug heap operations

* Add macros to clean up code

* Add pointer as well

* Cleanup

* Fix memory leak in NextHopRouter: always free packet copy when removing from pending

* Formatting

* Only queue 2 client notification

* Merge pull request #7965 from compumike/compumike/fix-nrf52-bluetooth-memory-leak

Fix memory leak in `NRF52Bluetooth`: allocate `BluetoothStatus` on stack, not heap

* Merge pull request #7964 from compumike/compumike/fix-nimble-bluetooth-memory-leak

Fix memory leak in `NimbleBluetooth`: allocate `BluetoothStatus` on stack, not heap

* Update protobufs (#7973)

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

* Trunk

* Trunk

* Static memory pool allocation (#7966)

* Static memory pool

* Initializer

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

---------

Co-authored-by: WillyJL <me@willyjl.dev>

* Portduino dynamic alloc

* Missed

* Drop the limit

* Update meshtastic-esp8266-oled-ssd1306 digest to 0cbc26b (#7977)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Fix json report crashes on esp32 (#7978)

* Tweak maximums

* Fix DRAM overflow on old esp32 targets

* Guard bad time warning logs using GPS_DEBUG (#7897)

In 2.7.7 / 2.7.8 we introduced some new checks for time accuracy.

In combination, these result in a spamming of the logs when a bad time is found

When the GPS is active, we're calling the GPS thread every 0.2secs.

So this log could be printed 4,500 times in a no-lock scenario :)

Reserve this experience for developers using GPS_DEBUG.

Fixes https://github.com/meshtastic/firmware/issues/7896

* Scale probe buffer size based on current baud rate (#7975)

* Scale probe buffer size based on current baud rate

* Throttle bad time validation logging and fix time comparison logic

* Remove comment

* Missed the other instances

* Copy pasta

* Fix GPS gm_mktime memory leak (#7981)

* Fix overflow of time value (#7984)

* Fix overflow of time value

* Revert "Fix overflow of time value"

This reverts commit 0847969201.

* That got boogered up

* Remove PMSA003 include from modules

* Add flag to exclude air quality module

* Rework PMSA003I to align with new I2C scanner

* Reworks AQ telemetry to match new dynamic allocation method
* Adds VBLE_I2C_CLOCK_SPEED build flag for sensors with different I2C speed requirements
* Reworks PMSA003I

* Move add sensor template to separate file

* Split telemetry on screen options

* Add variable I2C clock compile flag

* Added to Seeed Xiao S3 as demo

* Fix drawFrame in AQ module

* Module settings override to i2cScan module function

* Move to CAN_RECLOCK_I2C per architecture

* Add reclock function in TelemetrySensor.cpp
* Add flag in ESP32 common

* Minor fix

* Move I2C reclock function to src/detect

* Fix uninitMemberVar errors and compile issue

* Make sleep, wakeUp functions generic

* Fix STM32 builds

* Add exclude AQ sensor to builds that have environmental sensor excludes
* Add includes to AddI2CSensorTemplate.h

* SEN5X first pass

* WIP Sen5X functions

* Further (non-working) progress in SEN5X

* WIP Sen5X functions

* Changes on SEN5X library - removing pm_env as well

* Small cleanup of SEN5X sensors

* Minor change for SEN5X detection

* Remove dup code

* Enable PM sensor before sending telemetry.

This enables the PM sensor for a predefined period to allow for warmup.

Once telemetry is sent, the sensor shuts down again.

* Small cleanups in SEN5X sensor

* Add dynamic measurement interval for SEN5X

* Only disable SEN5X if enough time after reading.

* Idle for SEN5X on communication error

* Cleanup of logs and remove unnecessary delays

* Small TODO

* Settle on uint16_t for SEN5X PM data

* Make AQTelemetry sensors non-exclusive

* Implementation of cleaning in FS prefs and cleanup

* Remove unnecessary LOGS
* Add cleaning date storage in FS
* Report non-cumulative PN

* Bring back detection code for SEN5X after branch rebase

* Add placeholder for admin message

* Add VOC measurements and persistence (WIP)

* Adds VOC measurements and state
* Still not working on VOC Index persistence
* Should it stay in continuous mode?

* Add one-shot mode config flag to SEN5X

* Add nan checks on sensor data from SEN5X

* Working implementation on VOCState

* Adds initial timer for SEN55 to not sleep if VOCstate is not stable (1h)
* Adds conditions for stability and sensor state

* Fixes on VOC state and mode swtiching

* Adds a new RHT/Gas only mode, with 3600s stabilization time
* Fixes the VOCState buffer mismatch
* Fixes SEN50/54/55 model mistake

* Adapt SEN5X to new sensor list structure. Improve reclock.

* Improve reClockI2C conditions for different variants
* Add sleep, wakeUp, pendingForReady, hasSleep functions to PM sensors to save battery
* Add SEN5X

* Fix merge errors

* Small reordering in PMS class for consistency

* If one sensor fails, AQ telemetry still reports data

* Small formatting fix

* Add SEN5X to AQI in ScanI2C

* SCD4X now part of AQ module with template list

* Fixes difference between idle and sleep
* In LowPower, sleep is disabled
* Requires testing for I2C clock comms for commands

* Remove unnecessary import

* Add co2 to serialized AQ metrics

* Add SFA30 with new sensor template in AQ module

* Update library dependencies in platformio.ini

* Fix unitialized variables in SEN5X constructor

* Fix missing import

* Fix uninitMemberVars

* Fix import error for SCD4X

* Fix I2CClock logic

* Fix not reclocking back to 700000Hz

* Fix multiple sensors being read simultaneously

*  The logic in AQ module is different to the one in EnvironmentTelemetryModule.  In Env module, if any sensor fails to getMetrics, no valid flag for the module. This prevents other sensors to report data.

* Fix pending clock change in PMSA003

* Cleanup of SEN5X class

* Exclude AQ sensor from wio-e5 due to flash limitations

* Fix I2C clock change logic

* Make sure clock is always set to needed value

* Fix returns

* Fix trunk

* Fix on condition in reclock

* Fix trunk

* Final SFA30 class implementation

* Add HCHO to screen and improve logs

* Add metrics to mesh packet serializer

* Minor fixes in logs

* OCD tidy up of logs

* Fix sleep function

* Remove old I2C_CLOCK_SPEED code

---------

Co-authored-by: nikl <nikl174@mailbox.org>
Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>
Co-authored-by: Nashui-Yan <yannashui10@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: WillyJL <me@willyjl.dev>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Log rxBad PacketHeaders with more info (id, relay_node) like printPacket, so we can try to match RX errors to other packets in the logs. (#9614)

* Exclude status message module

* fix: zero entire public key array instead of only first byte (#9619)

* Update protobufs (#9621)

* Xiao NRF - define suitable i2c pins for the sub-variants (#8866)

Co-authored-by: Christian Walther <cwalther@gmx.ch>

* Update src/detect/ScanI2C.cpp

Co-authored-by: Wessel <wessel@weebl.me>

* Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp

Co-authored-by: Wessel <wessel@weebl.me>

* Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp

Co-authored-by: Wessel <wessel@weebl.me>

* Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp

Co-authored-by: Wessel <wessel@weebl.me>

* Update src/mesh/NodeDB.cpp

Co-authored-by: Wessel <wessel@weebl.me>

* convert GPS global and some new in gps.cpp to unique_ptr (#9628)

Trying this to see if anything bad happen if I were to replace most raw pointers with unique_ptr.

I didn't used std::make_unique since it is only supported in C++14 and onwards but until we update esp32 to arduino 3.x the ESP32 xtensa chips use a C++11 std.

* replace delete in RedirectablePrint.cpp with std::unique_ptr (#9642)

Is part of the unique_ptr modernization effort.

* replace delete in EInkDynamicDisplay.{cpp,h} with std::unique_ptr (#9643)

Is part of the unique_ptr modernization effort.

* Undefine LED_BUILTIN for Heltec v2 variant (#9647)

* Undefine LED_BUILTIN for Heltec v2 variant

* Undefine LED_BUILTIN for Heltec v2.1 variant

---------

Co-authored-by: Jorropo <jorropo.pgm@gmail.com>

* replace delete in RadioInterface.cpp with std::unique_ptr (#9645)

Is part of the unique_ptr modernization effort.

* fix typo in PIN_GPS_SWITCH (#9648)

Wasn't caught by CI.

* replace delete in CryptoEngine.{cpp,h} with std::unique_ptr (#9649)

Is part of the unique_ptr modernization effort.

* workaround NCP5623 and LP5562 I2C builds (#9652)

Theses two appear to be buggy on r1-neo and nomadstar meteor pro, they rely on Wire.h being included previously to their import.

Idk why other platforms using the same smart LEDs are working while theses ones don't.

This should make CI green on the dev branch.

* replace delete in AudioThread.h with std::unique_ptr (#9651)

Is part of the unique_ptr modernization effort.

* Add USB_MODE=1 for Station G2 (#9660)

* InkHUD: Favorite Map Applet (#9654)

* fix a lot of low level cppcheck warnings (#9623)

* simplify the observer pattern, since all the called functions are const getters.
* use arduino macro over std: for numerical values and refactor local variables in drawScrollbar()
* oh, so Cppcheck actually complained about const pointers not being const.
* slowly getting out of ifdef hell
* fix inkHUD warnings as well
* last 2 check warnings
* git checks should fail on low defects from now on

* Feat/add scd30 (#9609)

* Merge develop into SCD30

* Add SCD30 class

* Fix logging and admin commands

* Minor cleanup and logging improvements

* Minor formatting issue

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Improvements on setTemperature

* Fix casting float-uint16_t
* Pass 100 for resetting temperature offset

* Fix issues pointed out by copilot

* Add quick reboot to set interval quicker on scd30

* Change saveState to only happen after boot and minor log changes

* Fix missing semicolon in one shot mode log

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* fix: respect DontMqttMeBro flag regardless of channel PSK (#9626)

The previous PSK check was broken from its introduction in #4643 —
memcmp was used in boolean context without comparing to 0, inverting
the condition. Since no one noticed for over a year, the PSK-based
filtering provided no practical value. Simplifying to always respect
the sender's preference is both more correct and easier to reason about.

* our firmware action is too clever

Update pio_target and add pio_opts for checks.

* fix detection of SCD30 by checking if the size of the return from a 2 byte register read is correct (#9664)

* fix detection of SCD30 by checking if thee size of the return from a 2 byte register read is correct
fix signedness warning in PMSA003 sensor code.

* Add alternate path for LPS22HB

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* check EndTransmission for errors and compare returned length to expected value

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* #9623 resolved a local shadow of next_key by converting it to int. (#9665)

* zip a few gitrefs down (#9672)

* InkHUD: Allow non-system applets to subscribe to input events (#9514)

* Allow inkhud user applets to consume inputs with opt-in system
Adds a way for applets to subscribe to input events while keeping it off
by default to preserve compatibility and expected behaviours. Adds
example for use as well.
* Add check for nullptr on getActiveApplet uses
* Remove redundant includes
* Move subscribedInputs to protected
* More consistent naming scheme

* Fake IAQ values on Non-BSEC2 platforms like Platformio and the original ESP32 (#9663)

* BSEC2 Replacement
- add approximation for IAQ to non-BSEC2 platforms.
- Re-add this sensor to ESP32 targets, and refactor env_extra includes.
- Fix C++ 11 compatibility
* Check for gas resistance 0

* ULED_BUILTIN for 9m2ibr_aprs_lora_tracker (#9685)

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
Co-authored-by: Jason P <applewiz@mac.com>
Co-authored-by: Eric Sesterhenn <eric.sesterhenn@x41-dsec.de>
Co-authored-by: Vortetty <33466216+Vortetty@users.noreply.github.com>
Co-authored-by: Mattatat25 <108779801+mattatat25@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Max <rekin.m@gmail.com>
Co-authored-by: Colby Dillion <colby.dillion@pacshealth.com>
Co-authored-by: Austin <vidplace7@gmail.com>
Co-authored-by: Tom <116762865+NomDeTom@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Chloe Bethel <chloe@9net.org>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Quency-D <55523105+Quency-D@users.noreply.github.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
Co-authored-by: oscgonfer <oscgonfer@users.noreply.github.com>
Co-authored-by: nikl <nikl174@mailbox.org>
Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>
Co-authored-by: Nashui-Yan <yannashui10@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu>
Co-authored-by: WillyJL <me@willyjl.dev>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Wessel <wessel@weebl.me>
Co-authored-by: Christian Walther <cwalther@gmx.ch>
Co-authored-by: Jorropo <jorropo.pgm@gmail.com>
Co-authored-by: Eric Barch <ericb@ericbarch.com>
Co-authored-by: Clive Blackledge <clive@ansible.org>
2026-02-19 07:16:33 -06:00
d0cf79a991 Upgrade trunk (#9692)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-19 06:03:53 -06:00
MaxandGitHub 86986d6337 ULED_BUILTIN for 9m2ibr_aprs_lora_tracker (#9685) 2026-02-19 10:20:07 +08:00
5408e81de7 Upgrade trunk (#9683)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-18 06:44:55 -06:00
Thomas GöttgensandGitHub 178c3114d9 Fake IAQ values on Non-BSEC2 platforms like Platformio and the original ESP32 (#9663)
* BSEC2 Replacement
- add approximation for IAQ to non-BSEC2 platforms.
- Re-add this sensor to ESP32 targets, and refactor env_extra includes.
- Fix C++ 11 compatibility
* Check for gas resistance 0
2026-02-17 22:16:56 +01:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
357a33f454 chore(deps): update actions/stale action to v10.2.0 (#9669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-17 05:45:54 -06:00
harry-iii-lordandGitHub 4fccda26c6 Concurrency: Modern Periodic wrapper class. (#9501) 2026-02-17 05:44:26 -06:00
f94c01b452 Upgrade trunk (#9671)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-17 05:38:13 -06:00
VortettyandGitHub 3ca68e7788 InkHUD: Allow non-system applets to subscribe to input events (#9514)
* Allow inkhud user applets to consume inputs with opt-in system
Adds a way for applets to subscribe to input events while keeping it off
by default to preserve compatibility and expected behaviours. Adds
example for use as well.
* Add check for nullptr on getActiveApplet uses
* Remove redundant includes
* Move subscribedInputs to protected
* More consistent naming scheme
2026-02-17 11:03:26 +01:00
Thomas GöttgensandGitHub a4ba312579 zip a few gitrefs down (#9672) 2026-02-17 09:53:20 +01:00
Thomas GöttgensandGitHub a227fd7028 #9623 resolved a local shadow of next_key by converting it to int. (#9665) 2026-02-16 19:39:43 +01:00
6b44b5786e fix detection of SCD30 by checking if the size of the return from a 2 byte register read is correct (#9664)
* fix detection of SCD30 by checking if thee size of the return from a 2 byte register read is correct
fix signedness warning in PMSA003 sensor code.

* Add alternate path for LPS22HB

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* check EndTransmission for errors and compare returned length to expected value

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-16 10:07:07 -06:00
Thomas GöttgensandGitHub 5feba46b53 our firmware action is too clever
Update pio_target and add pio_opts for checks.
2026-02-16 16:39:31 +01:00
WesselandGitHub 0cbf53b7a7 fix: respect DontMqttMeBro flag regardless of channel PSK (#9626)
The previous PSK check was broken from its introduction in #4643 —
memcmp was used in boolean context without comparing to 0, inverting
the condition. Since no one noticed for over a year, the PSK-based
filtering provided no practical value. Simplifying to always respect
the sender's preference is both more correct and easier to reason about.
2026-02-16 13:49:58 +01:00
321ccbf5e2 Upgrade trunk (#9661)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-16 05:52:46 -06:00
57268bf4ea Feat/add scd30 (#9609)
* Merge develop into SCD30

* Add SCD30 class

* Fix logging and admin commands

* Minor cleanup and logging improvements

* Minor formatting issue

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Improvements on setTemperature

* Fix casting float-uint16_t
* Pass 100 for resetting temperature offset

* Fix issues pointed out by copilot

* Add quick reboot to set interval quicker on scd30

* Change saveState to only happen after boot and minor log changes

* Fix missing semicolon in one shot mode log

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-16 05:38:36 -06:00
Thomas GöttgensandGitHub 56fd9c7813 fix a lot of low level cppcheck warnings (#9623)
* simplify the observer pattern, since all the called functions are const getters.
* use arduino macro over std: for numerical values and refactor local variables in drawScrollbar()
* oh, so Cppcheck actually complained about const pointers not being const.
* slowly getting out of ifdef hell
* fix inkHUD warnings as well
* last 2 check warnings
* git checks should fail on low defects from now on
2026-02-16 12:28:07 +01:00
HarukiToredaandGitHub 32db70037d InkHUD: Favorite Map Applet (#9654) 2026-02-16 10:35:27 +01:00
Clive BlackledgeandGitHub 778823e623 Add USB_MODE=1 for Station G2 (#9660) 2026-02-16 10:16:05 +01:00
JorropoandGitHub 545826d319 replace delete in AudioThread.h with std::unique_ptr (#9651)
Is part of the unique_ptr modernization effort.
2026-02-15 06:49:16 -06:00
JorropoandGitHub dbef1de286 workaround NCP5623 and LP5562 I2C builds (#9652)
Theses two appear to be buggy on r1-neo and nomadstar meteor pro, they rely on Wire.h being included previously to their import.

Idk why other platforms using the same smart LEDs are working while theses ones don't.

This should make CI green on the dev branch.
2026-02-15 00:32:19 +01:00
JorropoandGitHub b0bd3df226 replace delete in CryptoEngine.{cpp,h} with std::unique_ptr (#9649)
Is part of the unique_ptr modernization effort.
2026-02-14 22:44:36 +01:00
JorropoandGitHub 167bcf2863 fix typo in PIN_GPS_SWITCH (#9648)
Wasn't caught by CI.
2026-02-14 22:12:31 +01:00
JorropoandGitHub ff485d5ff8 replace delete in RadioInterface.cpp with std::unique_ptr (#9645)
Is part of the unique_ptr modernization effort.
2026-02-14 21:39:26 +01:00
184e4ddd83 Undefine LED_BUILTIN for Heltec v2 variant (#9647)
* Undefine LED_BUILTIN for Heltec v2 variant

* Undefine LED_BUILTIN for Heltec v2.1 variant

---------

Co-authored-by: Jorropo <jorropo.pgm@gmail.com>
2026-02-14 21:30:16 +01:00
JorropoandGitHub aed2c7ca9b replace delete in EInkDynamicDisplay.{cpp,h} with std::unique_ptr (#9643)
Is part of the unique_ptr modernization effort.
2026-02-14 19:56:53 +01:00
JorropoandGitHub e1f9ccd337 replace delete in RedirectablePrint.cpp with std::unique_ptr (#9642)
Is part of the unique_ptr modernization effort.
2026-02-14 19:32:16 +01:00
JorropoandGitHub df14561560 convert GPS global and some new in gps.cpp to unique_ptr (#9628)
Trying this to see if anything bad happen if I were to replace most raw pointers with unique_ptr.

I didn't used std::make_unique since it is only supported in C++14 and onwards but until we update esp32 to arduino 3.x the ESP32 xtensa chips use a C++11 std.
2026-02-14 19:12:59 +01:00
Ben MeadorsandGitHub c8ff02cc35 Merge branch 'master' into develop 2026-02-13 18:09:37 -06:00
d770ef27c7 Update src/mesh/NodeDB.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-02-13 17:36:12 -06:00
71edf2fb48 Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-02-13 17:35:13 -06:00
c79e1925d9 Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-02-13 17:35:03 -06:00
3d649d518f Update src/modules/Telemetry/Sensor/SFA30Sensor.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-02-13 17:34:53 -06:00
947f8176dc Update src/detect/ScanI2C.cpp
Co-authored-by: Wessel <wessel@weebl.me>
2026-02-13 17:34:31 -06:00
d5bde83ff5 Upgrade trunk (#9631)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-13 12:29:43 -06:00
c3321771ef Xiao NRF - define suitable i2c pins for the sub-variants (#8866)
Co-authored-by: Christian Walther <cwalther@gmx.ch>
2026-02-12 20:20:54 +01:00
Ben MeadorsandGitHub b6e5534a8c Merge branch 'master' into develop 2026-02-12 13:11:48 -06:00
github-actions[bot]andGitHub f10d786d82 Update protobufs (#9621) 2026-02-12 19:15:08 +01:00
WesselandGitHub 1a7f560372 fix: zero entire public key array instead of only first byte (#9619) 2026-02-12 15:33:57 +01:00
Ben Meadors 38c7ad0ed6 Exclude status message module 2026-02-12 07:11:12 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
bcc24705a5 chore(deps): update neopixel to v1.15.4 (#9616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-12 06:10:24 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
8137200cb8 chore(deps): update sensirion core to v0.7.3 (#9613)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-12 05:59:08 -06:00
Mike RobbinsandGitHub bfbce2e314 Log rxBad PacketHeaders with more info (id, relay_node) like printPacket, so we can try to match RX errors to other packets in the logs. (#9614) 2026-02-12 05:52:24 -06:00
renovate[bot]andGitHub f86291546d chore(deps): update adafruit mpu6050 to v2.2.9 (#9611) 2026-02-12 11:20:44 +01:00
github-actions[bot]andGitHub 640dd5f7d7 Upgrade trunk (#9615) 2026-02-12 11:15:38 +01:00
+2
oscgonferGitHubniklHannes FuchsNashui-YanBen MeadorsTom FifieldMike Robbinsgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>thebenternWillyJLrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
15297cb56f feat/add sfa30 (#9372)
* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Initial implementation for SFA30Sensor

* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Add ScreenFonts.h

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>

* PMSA003I 1st round test

* Fix I2C scan speed

* Fix minor issues and bring back I2C SPEED def

* Remove PMSA003I library as its no longer needed

* Add functional SCD4X

* Fix screen frame for CO2

* Add admin commands to SCD4X class

* Add further admin commands and fixes.

* Remove unused I2C speed functions and cleanup

* Cleanup of SEN5X specific code added from switching branches
* Remove SCAN_I2C_CLOCK_SPEED block as its not needed
* Remove associated functions for setting I2C speed

* Unify build epoch to add flag in platformio-custom.py (#7917)

* Unify build_epoch replacement logic in platformio-custom

* Missed one

* Fix build error in rak_wismesh_tap_v2 (#7905)

In the logs was:
"No screen resolution defined in build_flags. Please define DISPLAY_SIZE."

set according to similar devices.

* Put guards in place around debug heap operations (#7955)

* Put guards in place around debug heap operations

* Add macros to clean up code

* Add pointer as well

* Cleanup

* Fix memory leak in NextHopRouter: always free packet copy when removing from pending

* Formatting

* Only queue 2 client notification

* Merge pull request #7965 from compumike/compumike/fix-nrf52-bluetooth-memory-leak

Fix memory leak in `NRF52Bluetooth`: allocate `BluetoothStatus` on stack, not heap

* Merge pull request #7964 from compumike/compumike/fix-nimble-bluetooth-memory-leak

Fix memory leak in `NimbleBluetooth`: allocate `BluetoothStatus` on stack, not heap

* Update protobufs (#7973)

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

* Trunk

* Trunk

* Static memory pool allocation (#7966)

* Static memory pool

* Initializer

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

---------

Co-authored-by: WillyJL <me@willyjl.dev>

* Portduino dynamic alloc

* Missed

* Drop the limit

* Update meshtastic-esp8266-oled-ssd1306 digest to 0cbc26b (#7977)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Fix json report crashes on esp32 (#7978)

* Tweak maximums

* Fix DRAM overflow on old esp32 targets

* Guard bad time warning logs using GPS_DEBUG (#7897)

In 2.7.7 / 2.7.8 we introduced some new checks for time accuracy.

In combination, these result in a spamming of the logs when a bad time is found

When the GPS is active, we're calling the GPS thread every 0.2secs.

So this log could be printed 4,500 times in a no-lock scenario :)

Reserve this experience for developers using GPS_DEBUG.

Fixes https://github.com/meshtastic/firmware/issues/7896

* Scale probe buffer size based on current baud rate (#7975)

* Scale probe buffer size based on current baud rate

* Throttle bad time validation logging and fix time comparison logic

* Remove comment

* Missed the other instances

* Copy pasta

* Fix GPS gm_mktime memory leak (#7981)

* Fix overflow of time value (#7984)

* Fix overflow of time value

* Revert "Fix overflow of time value"

This reverts commit 0847969201.

* That got boogered up

* Remove PMSA003 include from modules

* Add flag to exclude air quality module

* Rework PMSA003I to align with new I2C scanner

* Reworks AQ telemetry to match new dynamic allocation method
* Adds VBLE_I2C_CLOCK_SPEED build flag for sensors with different I2C speed requirements
* Reworks PMSA003I

* Move add sensor template to separate file

* Split telemetry on screen options

* Add variable I2C clock compile flag

* Added to Seeed Xiao S3 as demo

* Fix drawFrame in AQ module

* Module settings override to i2cScan module function

* Move to CAN_RECLOCK_I2C per architecture

* Add reclock function in TelemetrySensor.cpp
* Add flag in ESP32 common

* Minor fix

* Move I2C reclock function to src/detect

* Fix uninitMemberVar errors and compile issue

* Make sleep, wakeUp functions generic

* Fix STM32 builds

* Add exclude AQ sensor to builds that have environmental sensor excludes
* Add includes to AddI2CSensorTemplate.h

* SEN5X first pass

* WIP Sen5X functions

* Further (non-working) progress in SEN5X

* WIP Sen5X functions

* Changes on SEN5X library - removing pm_env as well

* Small cleanup of SEN5X sensors

* Minor change for SEN5X detection

* Remove dup code

* Enable PM sensor before sending telemetry.

This enables the PM sensor for a predefined period to allow for warmup.

Once telemetry is sent, the sensor shuts down again.

* Small cleanups in SEN5X sensor

* Add dynamic measurement interval for SEN5X

* Only disable SEN5X if enough time after reading.

* Idle for SEN5X on communication error

* Cleanup of logs and remove unnecessary delays

* Small TODO

* Settle on uint16_t for SEN5X PM data

* Make AQTelemetry sensors non-exclusive

* Implementation of cleaning in FS prefs and cleanup

* Remove unnecessary LOGS
* Add cleaning date storage in FS
* Report non-cumulative PN

* Bring back detection code for SEN5X after branch rebase

* Add placeholder for admin message

* Add VOC measurements and persistence (WIP)

* Adds VOC measurements and state
* Still not working on VOC Index persistence
* Should it stay in continuous mode?

* Add one-shot mode config flag to SEN5X

* Add nan checks on sensor data from SEN5X

* Working implementation on VOCState

* Adds initial timer for SEN55 to not sleep if VOCstate is not stable (1h)
* Adds conditions for stability and sensor state

* Fixes on VOC state and mode swtiching

* Adds a new RHT/Gas only mode, with 3600s stabilization time
* Fixes the VOCState buffer mismatch
* Fixes SEN50/54/55 model mistake

* Adapt SEN5X to new sensor list structure. Improve reclock.

* Improve reClockI2C conditions for different variants
* Add sleep, wakeUp, pendingForReady, hasSleep functions to PM sensors to save battery
* Add SEN5X

* Fix merge errors

* Small reordering in PMS class for consistency

* If one sensor fails, AQ telemetry still reports data

* Small formatting fix

* Add SEN5X to AQI in ScanI2C

* SCD4X now part of AQ module with template list

* Fixes difference between idle and sleep
* In LowPower, sleep is disabled
* Requires testing for I2C clock comms for commands

* Remove unnecessary import

* Add co2 to serialized AQ metrics

* Add SFA30 with new sensor template in AQ module

* Update library dependencies in platformio.ini

* Fix unitialized variables in SEN5X constructor

* Fix missing import

* Fix uninitMemberVars

* Fix import error for SCD4X

* Fix I2CClock logic

* Fix not reclocking back to 700000Hz

* Fix multiple sensors being read simultaneously

*  The logic in AQ module is different to the one in EnvironmentTelemetryModule.  In Env module, if any sensor fails to getMetrics, no valid flag for the module. This prevents other sensors to report data.

* Fix pending clock change in PMSA003

* Cleanup of SEN5X class

* Exclude AQ sensor from wio-e5 due to flash limitations

* Fix I2C clock change logic

* Make sure clock is always set to needed value

* Fix returns

* Fix trunk

* Fix on condition in reclock

* Fix trunk

* Final SFA30 class implementation

* Add HCHO to screen and improve logs

* Add metrics to mesh packet serializer

* Minor fixes in logs

* OCD tidy up of logs

* Fix sleep function

* Remove old I2C_CLOCK_SPEED code

---------

Co-authored-by: nikl <nikl174@mailbox.org>
Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>
Co-authored-by: Nashui-Yan <yannashui10@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: WillyJL <me@willyjl.dev>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-11 14:13:34 -06:00
6d299eac67 Fixes on SCD4X admin comands (#9607)
* Fixes on SCD4X admin comands

* Minor fix in logs for SEN5X

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-11 13:11:11 -06:00
Jonathan BennettandGitHub 31fe15bb73 ExternalNotification and StatusLED now call AmbientLighting to update… (#9554)
* ExternalNotification and StatusLED now call AmbientLighting to update RGB LEDs. Add optional heartbeat

* Don't overwrite RGB state if heartbeat is disabled.

* Use the right define

* Remove another .h and make rgb static

* move rgb objects into AmbientLighting class

* Straighten out AmbientLighting Thread object

* Use %f for floats
2026-02-11 12:02:22 -06:00
97983d8014 BaseUI: Favorite Screen Signal Quality improvement (#9566)
* Favorite Signal Quality improvement

* Show Voltage if node shares it.

* Trunk Fix

* Change Favorite tittle to encase name with Asterisks

* Add Pluggin In condition for Battery Line

* Adjust getUptimeStr Prefixes

* Create isAPIConnected for SharedCommon usage

* Correct leftSideSpacing to account for isAPIConnected

---------

Co-authored-by: Jason P <applewiz@mac.com>
2026-02-11 09:01:26 -06:00
Ben Meadors c366e53326 Merge branch 'master' into develop 2026-02-11 07:06:43 -06:00
Quency-DandBen Meadors 0adcadb1ce Modify the dependency library of v4-tft (#9507) 2026-02-11 07:06:15 -06:00
21d5a34fec Update protobufs (#9605)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-11 07:05:35 -06:00
Quency-DandGitHub 648148af8a Modify the dependency library of v4-tft (#9507) 2026-02-11 06:50:04 -06:00
Thomas GöttgensandBen Meadors 5b03b1fe52 fix some random compiler warnings (#9596) 2026-02-11 06:45:26 -06:00
Thomas GöttgensandGitHub f96a8593f2 fix some random compiler warnings (#9596) 2026-02-11 06:43:05 -06:00
4954723f97 Automated version bumps (#9604)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-11 06:30:05 -06:00
Chloe BethelandBen Meadors e047397642 Add missing openocd_target to custom nrf52 boards (#9603)
This stops platformio complaining about `Missing target configuration for me25ls01-4y10td` etc when trying to flash with nrfutil.
2026-02-11 06:29:55 -06:00
Jonathan BennettandGitHub 75f3d123f3 Add sdl libs for native builds (#9595)
* Add sdl libs for native builds

* Alpine try again
2026-02-11 06:29:16 -06:00
6b73ac3850 Upgrade trunk (#9599)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-11 06:24:46 -06:00
Chloe BethelandGitHub 44941b79cd Add missing openocd_target to custom nrf52 boards (#9603)
This stops platformio complaining about `Missing target configuration for me25ls01-4y10td` etc when trying to flash with nrfutil.
2026-02-11 06:22:01 -06:00
65adfa894f Automated version bumps (#9604)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-11 06:21:34 -06:00
6df0449408 Upgrade trunk (#9581)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-10 06:30:50 -06:00
TomandGitHub a092f6bb22 Refactor logging in ProtobufModule to ensure message details are logged after successful decoding (#9536) 2026-02-09 19:56:48 -06:00
Jason PandGitHub 927a4e47b8 Update built-in documentation for current method of implementation (#9592) 2026-02-09 18:56:22 -06:00
Jonathan BennettandGitHub df0ee74b30 Add battery curve for T-Beam 1 watt (#9585) 2026-02-09 17:33:06 -06:00
Ben Meadors af18f061cf Merge remote-tracking branch 'origin/master' into develop 2026-02-09 13:53:19 -06:00
139e45dff8 Update protobufs (#9588)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-09 13:52:01 -06:00
Jonathan BennettandGitHub 0df8719fc8 Temporarily un-renovate libch341 (#9587) 2026-02-09 13:30:27 -06:00
Ben Meadors b12cac3e00 Merge branch 'master' into develop 2026-02-09 12:52:22 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
28c4acf5c4 chore(deps): update gxepd2 to v1.6.7 (#9577)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-09 08:54:35 -06:00
+1
oscgonferGitHubHannes FuchsNashui-YanBen MeadorsTom FifieldMike Robbinsgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>thebenternWillyJLrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
579a0af516 feat: Add SCD4X (#7198)
* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Add ScreenFonts.h

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>

* PMSA003I 1st round test

* Fix I2C scan speed

* Fix minor issues and bring back I2C SPEED def

* Remove PMSA003I library as its no longer needed

* Add functional SCD4X

* Fix screen frame for CO2

* Add admin commands to SCD4X class

* Add further admin commands and fixes.

* Remove unused I2C speed functions and cleanup

* Cleanup of SEN5X specific code added from switching branches
* Remove SCAN_I2C_CLOCK_SPEED block as its not needed
* Remove associated functions for setting I2C speed

* Unify build epoch to add flag in platformio-custom.py (#7917)

* Unify build_epoch replacement logic in platformio-custom

* Missed one

* Fix build error in rak_wismesh_tap_v2 (#7905)

In the logs was:
"No screen resolution defined in build_flags. Please define DISPLAY_SIZE."

set according to similar devices.

* Put guards in place around debug heap operations (#7955)

* Put guards in place around debug heap operations

* Add macros to clean up code

* Add pointer as well

* Cleanup

* Fix memory leak in NextHopRouter: always free packet copy when removing from pending

* Formatting

* Only queue 2 client notification

* Merge pull request #7965 from compumike/compumike/fix-nrf52-bluetooth-memory-leak

Fix memory leak in `NRF52Bluetooth`: allocate `BluetoothStatus` on stack, not heap

* Merge pull request #7964 from compumike/compumike/fix-nimble-bluetooth-memory-leak

Fix memory leak in `NimbleBluetooth`: allocate `BluetoothStatus` on stack, not heap

* Update protobufs (#7973)

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

* Trunk

* Trunk

* Static memory pool allocation (#7966)

* Static memory pool

* Initializer

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

---------

Co-authored-by: WillyJL <me@willyjl.dev>

* Portduino dynamic alloc

* Missed

* Drop the limit

* Update meshtastic-esp8266-oled-ssd1306 digest to 0cbc26b (#7977)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Fix json report crashes on esp32 (#7978)

* Tweak maximums

* Fix DRAM overflow on old esp32 targets

* Guard bad time warning logs using GPS_DEBUG (#7897)

In 2.7.7 / 2.7.8 we introduced some new checks for time accuracy.

In combination, these result in a spamming of the logs when a bad time is found

When the GPS is active, we're calling the GPS thread every 0.2secs.

So this log could be printed 4,500 times in a no-lock scenario :)

Reserve this experience for developers using GPS_DEBUG.

Fixes https://github.com/meshtastic/firmware/issues/7896

* Scale probe buffer size based on current baud rate (#7975)

* Scale probe buffer size based on current baud rate

* Throttle bad time validation logging and fix time comparison logic

* Remove comment

* Missed the other instances

* Copy pasta

* Fix GPS gm_mktime memory leak (#7981)

* Fix overflow of time value (#7984)

* Fix overflow of time value

* Revert "Fix overflow of time value"

This reverts commit 0847969201.

* That got boogered up

* Remove PMSA003 include from modules

* Add flag to exclude air quality module

* Rework PMSA003I to align with new I2C scanner

* Reworks AQ telemetry to match new dynamic allocation method
* Adds VBLE_I2C_CLOCK_SPEED build flag for sensors with different I2C speed requirements
* Reworks PMSA003I

* Move add sensor template to separate file

* Split telemetry on screen options

* Add variable I2C clock compile flag

* Added to Seeed Xiao S3 as demo

* Fix drawFrame in AQ module

* Module settings override to i2cScan module function

* Move to CAN_RECLOCK_I2C per architecture

* Add reclock function in TelemetrySensor.cpp
* Add flag in ESP32 common

* Minor fix

* Move I2C reclock function to src/detect

* Fix uninitMemberVar errors and compile issue

* Make sleep, wakeUp functions generic

* Fix STM32 builds

* Add exclude AQ sensor to builds that have environmental sensor excludes
* Add includes to AddI2CSensorTemplate.h

* SEN5X first pass

* WIP Sen5X functions

* Further (non-working) progress in SEN5X

* WIP Sen5X functions

* Changes on SEN5X library - removing pm_env as well

* Small cleanup of SEN5X sensors

* Minor change for SEN5X detection

* Remove dup code

* Enable PM sensor before sending telemetry.

This enables the PM sensor for a predefined period to allow for warmup.

Once telemetry is sent, the sensor shuts down again.

* Small cleanups in SEN5X sensor

* Add dynamic measurement interval for SEN5X

* Only disable SEN5X if enough time after reading.

* Idle for SEN5X on communication error

* Cleanup of logs and remove unnecessary delays

* Small TODO

* Settle on uint16_t for SEN5X PM data

* Make AQTelemetry sensors non-exclusive

* Implementation of cleaning in FS prefs and cleanup

* Remove unnecessary LOGS
* Add cleaning date storage in FS
* Report non-cumulative PN

* Bring back detection code for SEN5X after branch rebase

* Add placeholder for admin message

* Add VOC measurements and persistence (WIP)

* Adds VOC measurements and state
* Still not working on VOC Index persistence
* Should it stay in continuous mode?

* Add one-shot mode config flag to SEN5X

* Add nan checks on sensor data from SEN5X

* Working implementation on VOCState

* Adds initial timer for SEN55 to not sleep if VOCstate is not stable (1h)
* Adds conditions for stability and sensor state

* Fixes on VOC state and mode swtiching

* Adds a new RHT/Gas only mode, with 3600s stabilization time
* Fixes the VOCState buffer mismatch
* Fixes SEN50/54/55 model mistake

* Adapt SEN5X to new sensor list structure. Improve reclock.

* Improve reClockI2C conditions for different variants
* Add sleep, wakeUp, pendingForReady, hasSleep functions to PM sensors to save battery
* Add SEN5X

* Fix merge errors

* Small reordering in PMS class for consistency

* If one sensor fails, AQ telemetry still reports data

* Small formatting fix

* Add SEN5X to AQI in ScanI2C

* SCD4X now part of AQ module with template list

* Fixes difference between idle and sleep
* In LowPower, sleep is disabled
* Requires testing for I2C clock comms for commands

* Remove unnecessary import

* Add co2 to serialized AQ metrics

* Update library dependencies in platformio.ini

* Fix unitialized variables in SEN5X constructor

* Fix missing import

* Fix uninitMemberVars

* Fix import error for SCD4X

* Fix I2CClock logic

* Fix not reclocking back to 700000Hz

* Fix multiple sensors being read simultaneously

*  The logic in AQ module is different to the one in EnvironmentTelemetryModule.  In Env module, if any sensor fails to getMetrics, no valid flag for the module. This prevents other sensors to report data.

* Fix pending clock change in PMSA003

* Cleanup of SEN5X class

* Exclude AQ sensor from wio-e5 due to flash limitations

* Fix I2C clock change logic

* Make sure clock is always set to needed value

* Fix returns

* Fix trunk

* Fix on condition in reclock

* Fix trunk

* Add check on polling interval of sen5x

* Add missing serializer

---------

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>
Co-authored-by: Nashui-Yan <yannashui10@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: WillyJL <me@willyjl.dev>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-09 08:39:12 -06:00
73adeee385 Enable FORTIFY and SP for native builds (#9537)
* Enable FORITFY and NX for native builds

meshtasticd does have an executable stack and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and a non-executable stack.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

* Enable FORTIFY and NX for native builds

meshtasticd does have an executable stack and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and a non-executable stack.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

* Enable FORTIFY and SP for native builds

meshtasticd does have a stack canaries and is not built with fortify, which makes exploitation of memory corruption bugs easier than it has to be. This enables fortify and stack canaries.

This gives the following improvements on Debian Trixie:

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   No canary found   NX enabled    PIE enabled     No RPATH   No RUNPATH   13516 Symbols	  No	0		17		./.pio/build/native/meshtasticd

$ checksec --file=./.pio/build/native/meshtasticd
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH	Symbols		FORTIFY	Fortified	Fortifiable	FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   13519 Symbols	  Yes	12		20		./.pio/build/native/meshtasticd

Tested with --sim mode I do not get any crashes or similar.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-08 19:48:18 -06:00
NickandGitHub bb3d6d5326 Fix embedded null byte truncation in ATAK strings (#9570) 2026-02-08 11:20:15 -06:00
+1
oscgonferGitHubHannes FuchsNashui-YanBen MeadorsTom FifieldMike Robbinsgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>thebenternWillyJLrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7cbab4838c Feat/add sen5x (#7245)
* Move PMSA003I to separate class and update AQ telemetry

* AirQualityTelemetry module not depend on PM sensor presence

* Remove commented line

* Fixes on PMS class

* Add missing warmup period to wakeUp function

* Fixes on compilation for different variants

* Add functions to check for I2C bus speed and set it

* Add ScreenFonts.h

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>

* PMSA003I 1st round test

* Fix I2C scan speed

* Fix minor issues and bring back I2C SPEED def

* Remove PMSA003I library as its no longer needed

* Remove unused I2C speed functions and cleanup

* Cleanup of SEN5X specific code added from switching branches
* Remove SCAN_I2C_CLOCK_SPEED block as its not needed
* Remove associated functions for setting I2C speed

* Unify build epoch to add flag in platformio-custom.py (#7917)

* Unify build_epoch replacement logic in platformio-custom

* Missed one

* Fix build error in rak_wismesh_tap_v2 (#7905)

In the logs was:
"No screen resolution defined in build_flags. Please define DISPLAY_SIZE."

set according to similar devices.

* Put guards in place around debug heap operations (#7955)

* Put guards in place around debug heap operations

* Add macros to clean up code

* Add pointer as well

* Cleanup

* Fix memory leak in NextHopRouter: always free packet copy when removing from pending

* Formatting

* Only queue 2 client notification

* Merge pull request #7965 from compumike/compumike/fix-nrf52-bluetooth-memory-leak

Fix memory leak in `NRF52Bluetooth`: allocate `BluetoothStatus` on stack, not heap

* Merge pull request #7964 from compumike/compumike/fix-nimble-bluetooth-memory-leak

Fix memory leak in `NimbleBluetooth`: allocate `BluetoothStatus` on stack, not heap

* Update protobufs (#7973)

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

* Trunk

* Trunk

* Static memory pool allocation (#7966)

* Static memory pool

* Initializer

* T-Lora Pager: Support LR1121 and SX1280 models (#7956)

* T-Lora Pager: Support LR1121 and SX1280 models

* Remove ifdefs

---------

Co-authored-by: WillyJL <me@willyjl.dev>

* Portduino dynamic alloc

* Missed

* Drop the limit

* Update meshtastic-esp8266-oled-ssd1306 digest to 0cbc26b (#7977)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Fix json report crashes on esp32 (#7978)

* Tweak maximums

* Fix DRAM overflow on old esp32 targets

* Guard bad time warning logs using GPS_DEBUG (#7897)

In 2.7.7 / 2.7.8 we introduced some new checks for time accuracy.

In combination, these result in a spamming of the logs when a bad time is found

When the GPS is active, we're calling the GPS thread every 0.2secs.

So this log could be printed 4,500 times in a no-lock scenario :)

Reserve this experience for developers using GPS_DEBUG.

Fixes https://github.com/meshtastic/firmware/issues/7896

* Scale probe buffer size based on current baud rate (#7975)

* Scale probe buffer size based on current baud rate

* Throttle bad time validation logging and fix time comparison logic

* Remove comment

* Missed the other instances

* Copy pasta

* Fix GPS gm_mktime memory leak (#7981)

* Fix overflow of time value (#7984)

* Fix overflow of time value

* Revert "Fix overflow of time value"

This reverts commit 0847969201.

* That got boogered up

* Remove PMSA003 include from modules

* Add flag to exclude air quality module

* Rework PMSA003I to align with new I2C scanner

* Reworks AQ telemetry to match new dynamic allocation method
* Adds VBLE_I2C_CLOCK_SPEED build flag for sensors with different I2C speed requirements
* Reworks PMSA003I

* Move add sensor template to separate file

* Split telemetry on screen options

* Add variable I2C clock compile flag

* Added to Seeed Xiao S3 as demo

* Fix drawFrame in AQ module

* Module settings override to i2cScan module function

* Move to CAN_RECLOCK_I2C per architecture

* Add reclock function in TelemetrySensor.cpp
* Add flag in ESP32 common

* Minor fix

* Move I2C reclock function to src/detect

* Fix uninitMemberVar errors and compile issue

* Make sleep, wakeUp functions generic

* Fix STM32 builds

* Add exclude AQ sensor to builds that have environmental sensor excludes
* Add includes to AddI2CSensorTemplate.h

* SEN5X first pass

* WIP Sen5X functions

* Further (non-working) progress in SEN5X

* WIP Sen5X functions

* Changes on SEN5X library - removing pm_env as well

* Small cleanup of SEN5X sensors

* Minor change for SEN5X detection

* Remove dup code

* Enable PM sensor before sending telemetry.

This enables the PM sensor for a predefined period to allow for warmup.

Once telemetry is sent, the sensor shuts down again.

* Small cleanups in SEN5X sensor

* Add dynamic measurement interval for SEN5X

* Only disable SEN5X if enough time after reading.

* Idle for SEN5X on communication error

* Cleanup of logs and remove unnecessary delays

* Small TODO

* Settle on uint16_t for SEN5X PM data

* Make AQTelemetry sensors non-exclusive

* Implementation of cleaning in FS prefs and cleanup

* Remove unnecessary LOGS
* Add cleaning date storage in FS
* Report non-cumulative PN

* Bring back detection code for SEN5X after branch rebase

* Add placeholder for admin message

* Add VOC measurements and persistence (WIP)

* Adds VOC measurements and state
* Still not working on VOC Index persistence
* Should it stay in continuous mode?

* Add one-shot mode config flag to SEN5X

* Add nan checks on sensor data from SEN5X

* Working implementation on VOCState

* Adds initial timer for SEN55 to not sleep if VOCstate is not stable (1h)
* Adds conditions for stability and sensor state

* Fixes on VOC state and mode swtiching

* Adds a new RHT/Gas only mode, with 3600s stabilization time
* Fixes the VOCState buffer mismatch
* Fixes SEN50/54/55 model mistake

* Adapt SEN5X to new sensor list structure. Improve reclock.

* Improve reClockI2C conditions for different variants
* Add sleep, wakeUp, pendingForReady, hasSleep functions to PM sensors to save battery
* Add SEN5X

* Fix merge errors

* Update library dependencies in platformio.ini

* Fix unitialized variables in SEN5X constructor

* Fix missing import

* Cleanup of SEN5X class

* Exclude AQ sensor from wio-e5 due to flash limitations

* Fix I2C clock change logic

* Fix trunk

* Fix on condition in reclock

* Add check on polling interval of sen5x

---------

Co-authored-by: Hannes Fuchs <hannes.fuchs+git@0xef.de>
Co-authored-by: Nashui-Yan <yannashui10@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Mike Robbins <mrobbins@alum.mit.edu>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: WillyJL <me@willyjl.dev>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-08 07:08:09 -06:00
Jonathan BennettandGitHub 4ce554e09d Make LED_POWER blip even in critical battery (#9545) 2026-02-08 06:49:30 -06:00
Jonathan BennettandGitHub eb145f8adc Add support for CW2015 LiPo battery fuel gauge (#9564)
* Add support for CW2015 LiPo battery fuel gauge

* Address Copilot's concerns, minor fixups
2026-02-07 22:30:14 -06:00
Jason PandGitHub a60e7cfe62 Add Slash Key to VirtualKeyboard (#9563)
Addition of ? and / to the virtual Keyboard via short and long press
2026-02-07 20:43:26 -05:00
53231ae4b1 Added toggable config and default for larger screens to enable / hide bubbles on chat messages (#9560)
* Added toggable config and default for largeer screens to enable / hide bubbles on chat messages

* Refactor message bubble rendering logic for improved layout and consistency

* Move osk_found initialization for trackball/encoder devices before module setup to fix missing keyboard for L1

* Utilize current checks for consistency

* Reverted last changes

---------

Co-authored-by: Jason P <applewiz@mac.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2026-02-07 15:41:31 -06:00
AustinandGitHub 39139cc2ea RPM: Include meshtasticd-start.sh (#9561) 2026-02-07 11:13:01 -05:00
5280caf9d8 Update protobufs (#9559)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-02-07 06:24:56 -06:00
Colby DillionandBen Meadors ba016fd91a Fix hop_limit upgrade detection (#9550)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-07 06:19:25 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
e2cf401ad3 Update meshtastic/device-ui digest to 6c75195 (#9553)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-07 06:16:30 -06:00
AustinandGitHub 4a4b1f4a87 meshtasticd: Fix install on Fedora 43 (#9556) 2026-02-06 19:36:21 -06:00
779e446d14 Fix hop_limit upgrade detection (#9550)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-06 13:00:08 -06:00
f73d18384d Upgrade trunk (#9547)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-06 06:22:34 -06:00
11bb2ee84e Upgrade trunk (#9368)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-02-05 05:53:48 -06:00
Jonathan BennettandGitHub 2361776992 Rename LED_PIN to LED_POWER, move handling out of main to dedicated module (#9512)
* Rename LED_PIN to LED_POWER, move handling out of main to dedicated module

* Misc

* Remove errant endif
2026-02-05 05:41:00 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>Ben Meadors
a324c4af10 Update meshtastic-esp8266-oled-ssd1306 digest to 21e484f (#9533)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-04 19:30:12 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5df5ab2790 Update Adafruit MPU6050 to v2.2.8 (#9534)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-04 17:19:11 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
74ea6206d9 Update NeoPixel to v1.15.3 (#9530)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-04 17:13:44 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
b238744445 Update Adafruit MPU6050 to v2.2.7 (#9525)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-02-04 17:12:01 -06:00
94b7149958 Remove unused hmx variable (#9529)
The variable is not used at all in the function, remove it to
silence the compiler warning.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-04 17:11:44 -06:00
ac611c4b62 Add agc reset attempt (#8163)
* Add agc reset attempt

* Add radioLibInterface include

* Trunk

* AGC reset don't crash, don't naively call

* Update src/main.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Use Throttle function

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-04 14:47:44 -06:00
89df5ef669 Undefine LED_BUILTIN (#9531)
Keep variant in sync with 
https://github.com/meshtastic/firmware/commit/df40085

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-04 11:15:49 -06:00
Ben MeadorsandGitHub be5f0a9ade Implement UDP multicast handler start/stop to ensure proper lifecycle (#9524)
* Implement UDP multicast handler start/stop to ensure proper lifecycle

* Add close method to AsyncUDP and improve UDP multicast handler lifecycle management

* Guard portduino
2026-02-04 11:15:38 -06:00
Jason PandGitHub bfc3eebd54 HotFix for ReplyBot - Modules.cpp included and moved configuration.h (#9532) 2026-02-04 08:56:50 -06:00
538a5f0dfc Add reply bot module with DM-only responses and rate limiting (#9456)
* Implement Meshtastic reply bot module with ping and status features

Adds a reply bot module that listens for /ping, /hello, and /test commands received via direct messages or broadcasts on the primary channel. The module always replies via direct message to the sender only, reporting hop count, RSSI, and SNR. Per-sender cooldowns are enforced to reduce network spam, and the module can be excluded at build time via a compile flag. Updates include the new module source files and required build configuration changes.

* Update ReplyBotModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/ReplyBotModule.h

Match the existing MESHTASTIC_EXCLUDE_* guard pattern so the module is excluded by default.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/modules/ReplyBotModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Tidying up

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-02-03 20:45:02 -06:00
VortettyandGitHub b7db22055d Inkhud battery icon improvements. (#9513)
* Inkhud battery icon improvements.
Fixes the battery icon draining from the flat side towards the bump, which is backwards from general design language seen on most devices
By request of kr0n05_ on discord, adds the ability to mirror the battery icon which fixes that issue in another way, and is also a common design seen on other devices.

* Remove option for icon mirroring

* Add border + dither to battery to prevent font overlap

* Fix trunk format

* Code cleanup, courtesy of Xaositek.
2026-02-03 20:02:54 -05:00
Jason PandGitHub b008c7a170 Fix config.display.use_long_node_name not saving (#9522) 2026-02-03 12:21:51 -06:00
Eric SesterhennandBen Meadors c8a9cdc148 Make sure we always return a value in NodeDB::restorePreferences() (#9516)
In case FScom is not defined there is no return statement. This
moves the return outside of the ifdef to make sure a defined
value is returned.
2026-02-03 06:23:49 -06:00
Eric SesterhennandGitHub 0703e0e6d7 Make sure we always return a value in NodeDB::restorePreferences() (#9516)
In case FScom is not defined there is no return statement. This
moves the return outside of the ifdef to make sure a defined
value is returned.
2026-02-03 06:22:33 -06:00
644fa5b54e Power off control pin on Thinknode m5 during deepsleep and add RTC (#9510)
* Power off control pin on Thinknode m5 during deepsleep

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Finish HAS_RTC cleanup

* Add RTC for Thinknode M5

* Don't double-init Wire

* Specify the RTC chip directly rather than use SensorRtcHelper.
Saves a bit of flash, and avoid mis-detection

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 06:07:33 -06:00
Jonathan BennettandGitHub f514bc230b Prefer EXT_PWR_DETECT pin over chargingVolt to detect power unplugged (#9511) 2026-02-03 00:13:49 -06:00
Jason PandGitHub 0022148323 Missed in reviews - fixing send bubble (#9505) 2026-02-01 19:10:00 -06:00
Jonathan BennettandGitHub 9d06c1bf34 Add StatusMessage module and config overrides (#9351)
* Add StatusMessage module and config overrides

* Trunk

* Don't reboot node simply for a StatusMessage config update
2026-01-31 14:55:51 -06:00
Jonathan BennettandGitHub 1d30342c00 Don't ever define PIN_LED or BLE_LED_INVERTED (#9494)
* Don't ever define PIN_LED

* Deprecate BLE_LED_INVERTED
2026-01-31 12:15:06 -06:00
Ben Meadors e9d4485bb5 Merge remote-tracking branch 'origin/develop' 2026-01-30 13:56:11 -06:00
7b03980e0a Refuse to send legacy DMs simply because the remote public key is unknown (#9485)
* Refuse to send legacy DMs simply because the remote public key is unknown

* Update src/mesh/Router.cpp - use more specific error

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/mesh/Router.cpp - more detail in warning message

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-30 13:46:24 -06:00
Ben MeadorsandGitHub 004179c045 Fix OTA filename determination to use unified format for ESP32 (#9488) 2026-01-30 13:46:11 -06:00
Jonathan BennettandGitHub 8f630bfcf3 Fix typo in LED state comment
And removed unused define
2026-01-30 12:52:17 -06:00
7bbfe99fbe Add on-screen keyboard to InkHUD (#9445)
* Added keyboard option to menu. Shows a keyboard layout but does not type.

* Keyboard types into text box and wraps.

* send FreeText messages from the send submenu

- renamed `KEYBOARD` action to `FREE_TEXT` and moved its menu location
to the send submenu
- opening the FreeText applet from the menu keeps the menu open and
disabled the timeout
- the FreeText applet writes to inkhud->freetext
- the sending a canned message checks inkhud->freetext and if it isn't
empty, sends and clears the inkhud->freetext

* Text scrolls along with input

* handle free text message completion as an event

implements `handleFreeText` and `OnFreeText()` for system applets to
interface with the FreeText Applet

The FreeText Applet generates an `OnFreeText` event when completing a
message which is handled by the first system applet with the
`handleFreeText` flag set to true.

The Menu Applet now handles this event.

* call `onFreeText` whenever the FreeText Applet exits

allows the menu to consistently restart its auto-close timeout

* Add text cursor

* Change UI to remove the header and make text box longer
Keyboard displays captial letters for legibility
Keyboard types captial letters with long press

* center FreeText keys and draw symbolic buttons

Move input field and keyboard drawing to their own functions:
- `drawInputField()`
- `drawKeyboard()`

Store the keys in a 1-dimensional array

Implement a matching array, `keyWidths`, to set key widths relative to
the font size

* Add character limit and counter

* Fix softlock when hitting character limit

* Move text box as its own menu page

* rework FreeTextApplet into KeyboardApplet

- The Keyboard Applet renders an on-screen keyboard at the lower portion
of the screen.
- Calling `inkhud->openKeyboard()` sends all the user applets to the
background and resizes the first system applet with `handleFreeText` set
to True to fit above the on-screen keyboard
- `inkhud->closeKeyboard()` reverses this layout change

* Fix input box rendering and add character limit to menu free text

* remove FREE_TEXT menu page and use the FREE_TEXT menu action solely

* force update when changing the free text message

* reorganize KeyboardApplet

- add comments after each row of `key[]` and `keyWidths[]` to preserve
formatting

- The selected key is now set using the key index directly

- rowWidths are pre-calculated in the KeyboardApplet constructor

- removed `drawKeyboard()` and implemented `drawKeyLabel()`

* implement `Renderer::clearTile()` to clear the region below a tile

* add parameter to forceUpdate() for re-rendering the full screen

setting the `all` parameter to true in `inkhud->forceUpdate()` now
causes the full screen buffer to clear an re-render. This is helpful for
when sending applets to the background and the UI needs a clean canvas.

System Applets can now set the `alwaysRender` flag true which causes it
to re-render on every screen update. This is set to true in the Battery
Icon Applet.

* clean up tile clearing loops

* implement dirty rendering to let applets draw over their previous render

- `Applet::requestUpdate()` now has an optional flag to keep the old
canvas

- If honored, the renderer calls `render(true)` which runs
`onDirtyRender()` instead of `onRender()` for said applet

- The renderer will not call a dirty render if the full screen is
getting re-rendered

* simplify arithmetic in clearTile for better understanding

* combine Applet::onRender() and Applet::onDirtyRender() into Applet::onRender(bool full)

- add new `full` parameter to onRender() in every applet. This parameter
can be ignored by most applets.

- `Applet::requestUpdate()` has an optional flag that requests a full
render by default

* implement tile and partial rendering in KeyboardApplet

* add comment for drawKeyLabel()

* improve clarity of byte operations in clearTile()

* remove typo and commented code

* fix inaccurate comments

* add null check to openKeyboard() and closeKeyboard()

---------

Co-authored-by: zeropt <ferr0fluidmann@gmail.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2026-01-30 13:35:10 -05:00
caae6bc597 Change canned message recipient's previous page to send page (#9227)
* Change canned message recipient's previous page to send page

* Set previousPage for new menu pages
Set nextPage in back MenuPages to previousPage
Removed back MenuAction

---------

Co-authored-by: zeropt <ferr0fluidmann@gmail.com>
Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2026-01-30 13:31:26 -05:00
Jonathan BennettandGitHub 200e79e800 You get an RTC, and you get an RTC! (delete HAS_RTC as it wasn't actually doing much) (#9493) 2026-01-30 11:54:49 -06:00
Ben MeadorsandGitHub c19fc62683 Merge pull request #9492 from meshtastic/master
Master to develop
2026-01-30 10:46:11 -06:00
Jonathan Bennett 4cf01e7e53 Adjust pin poweroff for Thinknode M6 2026-01-30 10:05:26 -06:00
Jonathan Bennett ad4b1d9c2b re-enable RTC support on THINKNODE M3 and M6 2026-01-30 09:50:47 -06:00
Ben Meadors 68733a6c51 Fix issue triage workflow by clarifying device log requirements and improving JSON response handling 2026-01-30 06:32:08 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
22617076f8 Update meshtastic/device-ui digest to 63967a4 (#9475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 20:19:12 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
6f5a7672b4 Update pschatzmann_arduino-audio-driver to v0.2.1 (#9398)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 20:18:34 -06:00
Ben MeadorsandGitHub e08c050720 Add custom ringtone definition for RAK4631 and enable buzzer pin (#9481) 2026-01-29 20:15:08 -06:00
Ben MeadorsandGitHub 28b4f37a93 Revert "Update libch341-spi-userspace digest to af9bc27 (#9472)" (#9483)
This reverts commit b18742c211.
2026-01-29 20:14:50 -06:00
Jonathan Bennett 5dd06edd00 Add ledOff if not defined 2026-01-29 13:24:10 -06:00
Jonathan Bennett eeb7373043 Remove errant symbol 2026-01-29 13:23:49 -06:00
Jonathan BennettandGitHub dbded86dcb More variant.h cleanup. LED_NOTIFICATION, remove dead code, etc (#9477) 2026-01-29 12:51:48 -06:00
Jonathan BennettandGitHub 45fbc0f9d3 Remove stale variant.h defines (#9470)
* Remove noop CANNED_MESSAGE_MODULE_ENABLE define

* Remove over-eager warning removal

* Remove unused LED_CONN

* Dead defines removal

* Rename oddball LED pin name

* Rename second oddball LED pin name

* Remove another dead define
2026-01-29 10:58:06 -06:00
61b39acc7d Add initial Nix shell (#8530)
* Add initial Nix shell

* Update flake.nix

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-29 10:06:58 -06:00
8af9e7fbdc enable long interleaving mode for LR11x0 and SX128x (#9399)
Using long interleaving is not a breaking change, the receiver node is able
to use the lora header to know if LI encoding is used or not and will
decode LI packets correctly.

However the problem is SX127x and other first generation LoRa IP which do not
support LI at all, for theses it is a breaking change.

HOWEVER due to the sync word bug the LR11x0 already can't talk with SX127x,
so if we enable LI on theses no one would be able to tell.
Same for SX128x altho this is because it works on 2.4Ghz which is incompatible with SX127x.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-29 06:44:17 -06:00
1f7ed6888a feat(stm32): Add Milesight GS301 Bathroom Odor Detector (#9359)
- STM32WLE5CCU6
- NFC (unsupported): NXP NT3H2211W0FTTJ (NTAG I2C plus: NFC Forum T2T with I2C interface, password protection and energy harvesting)
- Sensor (unsupported): Analog ADuCM355 (SHTC3 is connected to ADuCM355 and not directly accessible)
- Bicolor LED
- User button (presently not functional in STM32 variants)

The definitions for sensor voltage control are present but commented out to save power, due to lack of sensor support.

Powered by 4x 4000mAh RAMWAY ER18505 Li-SOCl2 batteries.

Flashing:

1. Power down device (remove batteries)
2. Connect USB-UART to J1 (USART2), pinout is below, do not connect +3V3 pin yet
3. Short BOOT pins next to J1
4. Connect +3V3 pin or insert batteries while BOOT pins are shorted
5. Use STM32CubeProgrammer, connect by UART mode
6. Load firmware .hex and download

J1 (USART2); Molex Picoblade (P=1.25mm * 4)

1. +3V3
2. PA3_USART2_RX_J1
3. PA2_USART2_TX_J1
4. GND

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-29 06:43:48 -06:00
31bf51b3f2 Add support for the hardware buttons on Bluetooth Nugget device (#9468)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-29 06:38:49 -06:00
334a4f04cd Fix logic for rak12035 sensor default config and improve messaging (#9414)
* better logic to check if the RAK12035 soil sensor is calibrated, better log messaging if either of the default values were used.

* .

* changes to how default calibration is done and a message it the default calibration is used pointing to the actual calibration sketch so the user can find it and use it to improve accuracy.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-29 06:29:15 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
b18742c211 Update libch341-spi-userspace digest to af9bc27 (#9472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-29 06:25:07 -06:00
Ben Meadors 03084f6d3b PRs with needs-review still should get bot labeled 2026-01-29 06:23:52 -06:00
Ben Meadors 94d7b71aa8 Merge branch 'develop' 2026-01-29 06:12:11 -06:00
Ben Meadors 415686dd06 Trunk 2026-01-29 05:56:19 -06:00
b2f2f6b305 Add a watchdog module to meshsolar. (#9337)
* add watchdog module

* Restore the code in power.h

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-28 20:41:27 -06:00
Jonathan Bennett df400850c1 Undefine LED_BUILTIN where needed 2026-01-28 18:56:57 -06:00
Jonathan Bennett 6ab2f02dbc re-add unintentionally removed include 2026-01-28 17:53:12 -06:00
d7d6fe7f0f Avoid short-circuit evaluation issues in Telemetry (#9467)
* Make sensors in telemetry non-definitory

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-28 17:18:42 -06:00
Ben Meadors d44ceb6eb2 Fix NimBLE deinit null check 2026-01-28 17:17:35 -06:00
Jonathan BennettandGitHub 4fd0a8276b Just set LED_BUILTIN universally to -1, as we don't use it. (#8830)
* Just set LED_BUILTIN universally to -1, as we don't use it.

* LUD_BUILTIN workarounds

* Squash the LED_BUILTINs that sneaked in

* Don't kill valid pin derfine
2026-01-28 17:09:13 -06:00
1d219a93ab Move input init to an init function in InputBroker (#9463)
* Move input init to an init function in iInputBroker

* Unbreak targets with EXCLUDE_INPUTBROKER

* Update src/input/InputBroker.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix conditional compilation for input broker

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Trunk

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 14:58:05 -06:00
f710cd6ecb Support fully direct request/responses (#9455)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-28 14:14:01 -06:00
571c1ac34c Initial serialModule cleanup (#9465)
* Initial serialModule cleanup

* Move SERIAL_PRINT_PORT definition to variant.h

* Add missed c6 check

* Update src/modules/SerialModule.cpp

Compile error for invalid SERIAL_PRINT_OBJECT value

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 14:08:32 -06:00
Ben Meadors fb635987d1 Merge remote-tracking branch 'origin/master' into develop 2026-01-28 13:31:39 -06:00
Jason PandGitHub a922751afc External Notification - handleReceived Rewrite (#9454)
* First steps in consolidating code and minimizing rewrite

* Continuing code cleanup

* Merge containsBell and !isMuted to a single code path

* Forgot about alert_message_buzzer in the cleanup

* More code refinements and cleanup

* Fix nagCycleCutoff

* CoPilot Updates
2026-01-28 11:12:02 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
c1e3f56324 Update LovyanGFX to v1.2.19 (#9405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-28 11:08:07 -06:00
d0562e1ee6 Add model workflows (#9462)
* Add GitHub workflows for issue completeness, duplicate detection, onboarding, and contribution quality checks

* Fix indentation

* Refactor GitHub workflows for issue handling

* Consolidate to two triage workflows

* Update .github/workflows/models_pr_triage.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 10:50:56 -06:00
4eb4c4b584 BaseUI Message Bubble Improvements (#9452)
* Improve Message bubbles for more distinct markers and improved layout

* Tune message bubble size and corner markers

* Finish message bubble tuning

---------

Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
2026-01-27 21:11:56 -05:00
Jonathan BennettandGitHub 69a42e1fd2 Add portduino_status, assign hardware device IDs... (#9441)
* Add portduino_status, assign hardware device IDs, and try to recover a CH341 device on a USB error

* Minor fixes suggested by Copilot
2026-01-27 18:00:20 -06:00
Jonathan BennettandGitHub fd498bebad Add support for Hackaday Communicator function keys (#9444) 2026-01-27 16:09:18 -06:00
小林andGitHub 23a8b5a66f Fix uMesh RF POWER configuration error (#9326)
* fix issue https://github.com/linser233/uMesh/issues/1

* fix issue https://github.com/linser233/uMesh/issues/1

* Update and rename lora-usb-umesh-1262.yaml to lora-usb-umesh-1262-30dbm.yaml

* Update and rename lora-usb-umesh-1268.yaml to lora-usb-umesh-1268-30dbm.yaml
2026-01-28 07:50:50 +11:00
Ben Meadors e1e8d6124d Merge branch 'master' into develop 2026-01-27 14:01:27 -06:00
Jonathan BennettandGitHub 10b2eae70c Move more code out of main-nrf52 into variant.cpp (#9450) 2026-01-27 13:56:32 -06:00
cfda9bb8ef Update protobufs (#9453)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-27 13:12:03 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
d1edd386b6 Update meshtastic/device-ui digest to 69739b8 (#9448)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-27 13:08:10 -06:00
Ben MeadorsandGitHub b6a1020fc5 Add error handling for SPI command failures in LR11x0, RF95, and SX128x interfaces (#9447) 2026-01-27 13:06:50 -06:00
Jonathan BennettandGitHub 91ad861b26 Add Thinknode M4 variant_shutdown() (#9449) 2026-01-27 09:56:56 -06:00
HarukiToredaandGitHub d54ae5dad8 InkHUD Menu improvements (#8975)
* InkHUD: Region Picker on initial setup

* Added Node Config menu with Lora Region Picker

* Role picker

* Preset Picker

* Timezone picker added

* Power save mode and bluetooth configs

* Config section Headers

* Channel Config

* Cleaning some behavior

* Add back to all Options

* Display config added

* Position Toggle added

* Network Config for ESP32

* Wifi details

* Reduce line spacing to fit more content

* Recent list with checkboxes

* Timezone labels easier to understand

* Trunk fix

* Added "Saving Changes" screen when reboot is needed

* Trunk fix

* Make Tips show after first boot if the region is Unset

* Added ResetDB and keep only favorite commands

* quick fix to joystick

* Trunk Fix

* Fix to tips to work with new joystick input

* Added ADC multiplier value display on power config

* added ADC calibration feature

* Fixed missing stray endiff

* GPS toggle now is aware if gps is present.
2026-01-27 09:11:11 -06:00
Ben Meadors c8079d4115 Metadata for heltec tracker v2 2026-01-27 08:05:36 -06:00
Andrew YongandGitHub 90778a4e78 feat(GPS): Support Softsleep with WAKE-UP pin on PA1010D (#9078)
Support softsleep by defining PIN_GPS_STANDBY on CDTop CD-PA1010D.

This differs from existing MTK GPS e.g. L76K, where pulling PIN_GPS_STANDBY (WAKE-UP pin) low is not sufficient to put the GPS module in standby.

An additional `$PMTK225,4*2F` must be sent to enter "Backup Mode", which is exited by bringing PIN_GPS_STANDBY (WAKE-UP pin) high.

Refer to datasheet[0] §1.9.3 "Backup Mode".

0: https://cdn-learn.adafruit.com/assets/assets/000/084/295/original/CD_PA1010D_Datasheet_v.03.pdf

Signed-off-by: Andrew Yong <me@ndoo.sg>
2026-01-27 06:03:31 -06:00
63a97a54e1 Fix retry_delay calculation for error responses (#9443)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-26 18:45:24 -06:00
Jonathan BennettandGitHub a2e8e232f1 Remove the unused OCV_ARRAYs and move one to a variant.h (#9442) 2026-01-26 16:58:16 -06:00
7efc3e3770 Replace strcpy with strncpy and null termination (#9436)
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2026-01-26 14:32:03 -06:00
Jonathan BennettandGitHub 3d58c6e916 Trackball revamp (#9440)
* Trackball revamp

* Use Throttle

* Volatile!
2026-01-26 14:28:05 -06:00
Jonathan BennettandGitHub c038cfe69a Move device code from main.cpp to earlyInitVariant (#9438) 2026-01-26 11:54:14 -06:00
Ben Meadors 0770f25e79 Merge remote-tracking branch 'origin/master' into develop 2026-01-26 08:56:38 -06:00
Jonathan BennettandGitHub 8a9830282a Move Lora Init code into LoraInit.cpp/h (#9435)
* Move Lora Init code into LoraInit.cpp/h

* Add missed extern definition

* More carefully check for nullptr in LoraInit.cpp

* STM32 fixes

* Add extern SPI1 for HW_SPI1_DEVICE

* Move initLora to RadioInterface.h
2026-01-25 20:54:17 -06:00
8894a0b711 Consolidate LoRa params / preset logic and fix display of preset values (#9413)
* Consolidate LoRa params / preset logic and fix display of preset values

* Move preset coercion logic to RadioInterface

* Fix some warnings

* Fix warnings

* STM32 fix

* Add unit tests

* Update src/mesh/RadioInterface.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-25 18:02:26 -06:00
57a3ff8dfc NRF52 - power management improvements (#9211)
* minor NRF52 test cleanup

* detect USB power input on ProMicro boards

* prevent booting on power failure detection

* introduce PowerHAL layer

* powerHAL basic implementation for NRF52

* prevent data saves on low power

* remove comment

* Update src/platform/nrf52/main-nrf52.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/power/PowerHAL.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update src/main.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Merge missing voltage threshold comparison

* add missing variable

* add missing function declaration

* remove debug strings

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-24 08:39:03 -06:00
6cff13623f Added Minimesh variant (#9289)
* Minimesh Lite Added

* Add Minimesh Lite NRF

* Added board_level = extra

* Fix formatting and optimize image for Minimesh Lite

* Change image

* The image has been deleted.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-24 08:38:07 -06:00
b312f226b4 Cut NRF52 bluetooth power usage (#8992)
* Improve NRF52 bluetooth power efficiency

* test T114 bad LFXO

* T1000 test

* force BLE param negotiation

* stash

* NRF52 bluetooth small cleanup

* fix potential connectivity issues

* lower BLE min interval to make iOS happy

* remove slave latency negotation

* add BLE issue comment

* code format

* Revert "code format"

This reverts commit 1f92b09d08.

* remove LFCLK debug info

* Fix

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-24 06:22:01 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
b627fa720b Update SensorLib to v0.3.4 (#9396)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:46:46 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9faf178bdc Update XPowersLib to v0.3.3 (#9354)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:45:26 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
c98f134b40 Update meshtastic-esp32_https_server digest to b0f3960 (#9393)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:39:22 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5838b26d90 Update lewisxhe-SensorLib to v0.3.4 (#9395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:39:05 -06:00
7221fc4d4b Delete unused code (#9350)
* Delete unused code

CryptoEngine::clearKeys() is not used in the code base, therefore this
cleanup removes the code. It might give casual reviewers the impression,
that keys are wiped.

Since the code uses memset() which might be optimized away by the
compiler, using the code might not even cause the memory
to be wiped.

* Update CryptoEngine.cpp

Fix stray newline, this is the only thing that I can come up with that might confuse the linter.

---------

Co-authored-by: Jason P <applewiz@mac.com>
2026-01-24 05:19:19 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
a417760887 Update meshtastic/device-ui digest to 37ad715 (#9403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:18:48 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
04d2dd3b1c Update GxEPD2 to v1.6.6 (#9412)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-24 05:16:47 -06:00
6b88d37b73 To fix the gps power rail issue on RAK 19007 when RAK12023+RAK12035 is installed (#9409)
* asked claude to fix the gps power rail issue when the io slot is in use.. this fixes the gps when both the RAK12500 GPS module and the RAK12035 soil sensor modules are being used.

* remove do { ... } while(0) from RESTORE_3V3_POWER() Macro

* remove some comments

* cleaner macro

* removed more excessive comments

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-24 05:16:36 -06:00
Ben Meadors d407ec1975 Merge remote-tracking branch 'origin/master' into develop 2026-01-24 04:47:24 -06:00
Jonathan BennettandGitHub 6d6a0734b0 Add pin sense to wake M6 on Solar Charge (#9416) 2026-01-23 15:37:16 -06:00
0157a769c3 Make BLE TX power configurable for nRF52 variants (#9232)
* Make BLE TX power configurable for nRF52 variants

* Include BLE TX power setting in T114 variant.h as tested

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-23 11:26:01 -06:00
Till MaasandGitHub 73932dd1c3 device-install: Consistently use write-flash (#8868)
* flash scripts: Unify indentation

* flash scripts: Support esptool v4 and v5

esptool v5 supports commands with dashes and deprecates commands with
underscores. Prior versions only support commands with underscores.
2026-01-23 06:05:29 -06:00
bc2abf3db4 BaseUI: Bubbles for messages (#9365)
* Message Bubbles

* Angled edges

* Proper indent for messages inside the bubble

* Fix message header line width

* Correctly calculate text width for the header and shrink Channel Name is on OLED

---------

Co-authored-by: Jason P <applewiz@mac.com>
2026-01-22 17:00:21 -06:00
073eb2c672 Automated version bumps (#9402)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-22 16:19:35 -06:00
JorropoandGitHub 4744010295 run trunk fmt -a (#9400)
* run trunk fmt -a

* fix bracket bug

This was introduced by @tedwardd and @thebentern in 021106dfe5.

See this diff:
         else
+            checkConfigPort = false;
             printf("Using config file %d\n", TCPPort);
2026-01-22 15:46:37 -06:00
d8d02cd6ec Implement setting TX_GAIN_LORA for portduino (#8501)
* Implement setting TX_GAIN_LORA for portduino

* use std::size instead of sizeof

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-01-22 07:08:43 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3e3299f549 Update meshtastic/device-ui digest to 613c095 (#9383)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-22 09:07:23 +11:00
eefc08087d Update protobufs (#9371)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2026-01-20 10:29:11 -06:00
Andrew YongandGitHub fb6d199d36 feat: Add Russell, a board designed to go Up! on a balloon (#9079)
Hardware repository: https://github.com/Meshtastic-Malaysia/russell
- Designed to mount on an ER34615/IFR32700 cell
- RAK3172 STM32WLE5CCU6 MCU + integrated SX1262 LoRa
- CDtop CD-PA1010D GPS
- Bosch Sensortec BME280 sensor
- Consonance CN3158 LiFePO4 solar charger

Signed-off-by: Andrew Yong <me@ndoo.sg>
2026-01-20 06:38:04 -06:00
fb3bf783dd Implement graduated scaling for NodeInfo send timeout based on active mesh size (#9364)
* Implement graduated scaling for NodeInfo send timeout based on active mesh size

* Shorter timeout still needed for pubkey unkown and ad-hoc send

* Update src/modules/NodeInfoModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-19 20:00:41 -06:00
Ben Meadors fc268d43d0 Add Meshtastic exclusion flags for webserver and paxcounter in platformio.ini 2026-01-19 16:57:21 -06:00
Jonathan BennettandGitHub c38aff7e52 Add interrupt for external charge detection (#9332)
Tested on Thinknode m4, m6, and T1000-e
2026-01-19 15:39:24 -06:00
Ben Meadors 7d4600f8c2 Merge branch 'master' into develop 2026-01-19 12:13:52 -06:00
Ben Meadors ff50ba4002 Remove bsec from OG ESP32 to fix DRAM overflow 2026-01-19 12:12:14 -06:00
5c401b8e34 Update protobufs (#9362)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-19 12:11:13 -06:00
Ben Meadors c96ebf15fd Merge remote-tracking branch 'origin/master' into develop 2026-01-19 07:57:36 -06:00
3e4239daf8 Upgrade trunk (#9330)
Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com>
2026-01-19 07:22:27 -06:00
Ben MeadorsandGitHub ab97c0126f Merge pull request #9355 from meshtastic/fix-bme
Untangle some BME680 ifdef spaghetti
2026-01-19 07:21:37 -06:00
d34d694731 Update protobufs (#9360)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2026-01-19 06:21:01 -06:00
Jonathan Bennett e545897d4e Untangle some BME680 ifdef spaghetti 2026-01-18 21:28:20 -06:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
caa6ec0e8a Update meshtastic/device-ui digest to 3480b73 (#9353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-19 14:28:05 +11:00
Jonathan BennettandGitHub afbd9e2180 Filter BLE updates that don't change pairing status (#9333) 2026-01-16 13:52:04 -06:00
64116cd0d3 Meshtastic OTA (moar) (#9327)
* Initial commit of combined BLE and WiFi OTA

* Incorporate ota_hash in AdminMessage protobuf

* OTA protobuf changes

* Trunk fmt

* Partition header check for OTA type

* Guards

* Guards

* Derp

* Missed one

---------

Co-authored-by: Jake-B <jake-b@users.noreply.github.com>
2026-01-15 14:36:36 -06:00
729 changed files with 21442 additions and 5101 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ ENV PIP_ROOT_USER_ACTION=ignore
RUN apt-get update && apt-get install --no-install-recommends -y \
cmake git zip libgpiod-dev libbluetooth-dev libi2c-dev \
libunistring-dev libmicrohttpd-dev libgnutls28-dev libgcrypt20-dev \
libusb-1.0-0-dev libssl-dev pkg-config libsqlite3-dev && \
libusb-1.0-0-dev libssl-dev pkg-config libsqlite3-dev libsdl2-dev && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
pip install --no-cache-dir -U \
platformio==6.1.16 \
+1
View File
@@ -0,0 +1 @@
use nix
+1 -1
View File
@@ -100,7 +100,7 @@ runs:
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}
overwrite: true
+3 -3
View File
@@ -4,16 +4,16 @@
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
is appreciated." This will allow other devs to potentially save you time by not accidentally duplicating work etc...
- Please do not check in files that don't have real changes
- Please do not reformat lines that you didn't have to change the code on
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (In beta for windows, WSL2 for the linux version),
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor along with the ['Trunk Check' extension](https://marketplace.visualstudio.com/items?itemName=trunk.io) (In beta for windows, WSL2 for the Linux version),
because it automatically follows our indentation rules and its auto reformatting will not cause spurious changes to lines.
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
- If your other co-developers have comments on your PR please tweak as needed.
- Please also enable "Allow edits by maintainers".
- Please do not submit untested code.
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and commnunity members can help test your changes.
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and community members can help test your changes.
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
## 🤝 Attestations
+2 -2
View File
@@ -42,7 +42,7 @@ jobs:
sudo mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
uses: crazy-max/ghaction-import-gpg@v7
with:
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
id: gpg
@@ -64,7 +64,7 @@ jobs:
PKG_VERSION: ${{ steps.version.outputs.deb }}
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
overwrite: true
+2 -2
View File
@@ -111,7 +111,7 @@ jobs:
echo "</details>" >> $GITHUB_STEP_SUMMARY
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
id: upload-firmware
with:
name: firmware-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
@@ -127,7 +127,7 @@ jobs:
release/device-*.bat
- name: Store manifests as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
id: upload-manifest
with:
name: manifest-${{ inputs.platform }}-${{ inputs.pio_env }}-${{ inputs.version }}
+4 -4
View File
@@ -98,7 +98,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
path: ./
pattern: firmware-*-*
@@ -111,7 +111,7 @@ jobs:
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: firmware-${{inputs.target}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -127,7 +127,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
pattern: firmware-*-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -146,7 +146,7 @@ jobs:
run: zip -j -9 -r ./firmware-${{inputs.target}}-${{ needs.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: debug-elfs-${{inputs.target}}-${{ needs.version.outputs.long }}.zip
overwrite: true
+1 -1
View File
@@ -35,8 +35,8 @@ jobs:
series:
- jammy # 22.04 LTS
- noble # 24.04 LTS
- plucky # 25.04
- questing # 25.10
- resolute # 26.04 LTS
uses: ./.github/workflows/package_ppa.yml
with:
ppa_repo: ppa:meshtastic/daily
+5 -5
View File
@@ -60,16 +60,16 @@ jobs:
- name: Docker login
if: ${{ inputs.push }}
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: meshtastic
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Docker setup
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Sanitize platform string
id: sanitize_platform
@@ -78,7 +78,7 @@ jobs:
- name: Docker tag
id: meta
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: meshtastic/meshtasticd
tags: |
@@ -86,7 +86,7 @@ jobs:
flavor: latest=false
- name: Docker build and push
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
id: docker_variant
with:
context: .
+3 -3
View File
@@ -139,14 +139,14 @@ jobs:
id: tags
- name: Docker login
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: meshtastic
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
- name: Docker meta (Debian)
id: meta_debian
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: meshtastic/meshtasticd
tags: |
@@ -167,7 +167,7 @@ jobs:
- name: Docker meta (Alpine)
id: meta_alpine
uses: docker/metadata-action@v5
uses: docker/metadata-action@v6
with:
images: meshtastic/meshtasticd
tags: |
+13 -13
View File
@@ -177,7 +177,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
path: ./
pattern: firmware-${{matrix.arch}}-*
@@ -187,7 +187,7 @@ jobs:
run: ls -R
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -205,7 +205,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -224,7 +224,7 @@ jobs:
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -250,13 +250,13 @@ jobs:
filter: blob:none # means we download all the git history but none of the commit (except ones with checkout like the head)
fetch-depth: 0
- name: Download the current manifests
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
path: ./manifests-new/
pattern: manifest-*
merge-multiple: true
- name: Upload combined manifests for later commit and global stats crunching.
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
id: upload-manifest
with:
name: manifests-${{ github.sha }}
@@ -324,14 +324,14 @@ jobs:
body: ${{ steps.release_notes.outputs.notes }}
- name: Download source deb
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
merge-multiple: true
path: ./output/debian-src
- name: Download `native-tft` pio deps
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -355,7 +355,7 @@ jobs:
}' > firmware-${{ needs.version.outputs.long }}.json
- name: Save Release manifest artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: manifest-${{ needs.version.outputs.long }}
overwrite: true
@@ -396,7 +396,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -413,7 +413,7 @@ jobs:
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -454,14 +454,14 @@ jobs:
python-version: 3.x
- name: Get firmware artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true
path: ./publish
- name: Get manifest artifact
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: manifest-${{ needs.version.outputs.long }}
path: ./publish
+9 -9
View File
@@ -147,7 +147,7 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
path: ./
pattern: firmware-${{matrix.arch}}-*
@@ -160,7 +160,7 @@ jobs:
run: mv -b -t ./ ./bin/device-*.sh ./bin/device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -176,7 +176,7 @@ jobs:
./Meshtastic_nRF52_factory_erase*.uf2
retention-days: 30
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
name: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -195,7 +195,7 @@ jobs:
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
overwrite: true
@@ -235,14 +235,14 @@ jobs:
Autogenerated by github action, developer should edit as required before publishing...
- name: Download source deb
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: firmware-debian-${{ needs.version.outputs.deb }}~UNRELEASED-src
merge-multiple: true
path: ./output/debian-src
- name: Download `native-tft` pio deps
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: platformio-deps-native-tft-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -292,7 +292,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
pattern: firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -309,7 +309,7 @@ jobs:
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ needs.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
name: debug-elfs-${{matrix.arch}}-${{ needs.version.outputs.long }}
merge-multiple: true
@@ -347,7 +347,7 @@ jobs:
with:
python-version: 3.x
- uses: actions/download-artifact@v7
- uses: actions/download-artifact@v8
with:
pattern: firmware-{${{ env.targets }}}-${{ needs.version.outputs.long }}
merge-multiple: true
+213
View File
@@ -0,0 +1,213 @@
name: Issue Triage (Models)
on:
issues:
types: [opened]
permissions:
issues: write
models: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.issue.number }}
cancel-in-progress: true
jobs:
triage:
if: ${{ github.repository == 'meshtastic/firmware' && github.event.issue.user.type != 'Bot' }}
runs-on: ubuntu-latest
steps:
# ─────────────────────────────────────────────────────────────────────────
# Step 1: Quality check (spam/AI-slop detection) - runs first, exits early if spam
# ─────────────────────────────────────────────────────────────────────────
- name: Detect spam or low-quality content
uses: actions/ai-inference@v2
id: quality
continue-on-error: true
with:
max-tokens: 20
prompt: |
Is this GitHub issue spam, AI-generated slop, or low quality?
Title: ${{ github.event.issue.title }}
Body: ${{ github.event.issue.body }}
Respond with exactly one of: spam, ai-generated, needs-review, ok
system-prompt: You detect spam and low-quality contributions. Be conservative - only flag obvious spam or AI slop.
model: openai/gpt-4o-mini
- name: Apply quality label if needed
if: steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
uses: actions/github-script@v8
env:
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
with:
script: |
const label = (process.env.QUALITY_LABEL || '').trim().toLowerCase();
const labelMeta = {
'spam': { color: 'd73a4a', description: 'Possible spam' },
'ai-generated': { color: 'fbca04', description: 'Possible AI-generated low-quality content' },
'needs-review': { color: 'f9d0c4', description: 'Needs human review' },
};
const meta = labelMeta[label];
if (!meta) return;
// Ensure label exists
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
} catch (e) {
if (e.status !== 404) throw e;
await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
}
// Apply label
await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.issue.number, labels: [label] });
// Set output to skip remaining steps
core.setOutput('is_spam', 'true');
# ─────────────────────────────────────────────────────────────────────────
# Step 2: Duplicate detection - only if not spam
# ─────────────────────────────────────────────────────────────────────────
- name: Detect duplicate issues
if: steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == ''
uses: pelikhan/action-genai-issue-dedup@bdb3b5d9451c1090ffcdf123d7447a5e7c7a2528 # v0.0.19
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# ─────────────────────────────────────────────────────────────────────────
# Step 3: Completeness check + auto-labeling (combined into one AI call)
# ─────────────────────────────────────────────────────────────────────────
- name: Determine if completeness check should be skipped
if: steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == ''
uses: actions/github-script@v8
id: check-skip
with:
script: |
const title = (context.payload.issue.title || '').toLowerCase();
const labels = (context.payload.issue.labels || []).map(label => label.name);
const hasFeatureRequest = title.includes('feature request');
const hasEnhancement = labels.includes('enhancement');
const shouldSkip = hasFeatureRequest && hasEnhancement;
core.setOutput('should_skip', shouldSkip ? 'true' : 'false');
- name: Analyze issue completeness and determine labels
if: (steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '') && steps.check-skip.outputs.should_skip != 'true'
uses: actions/ai-inference@v2
id: analysis
continue-on-error: true
with:
prompt: |
Analyze this GitHub issue for completeness and determine if it needs labels.
IMPORTANT: Distinguish between:
- Device/firmware bugs (crashes, reboots, lockups, radio/GPS/display/power issues) - these need device logs
- Build/release/packaging issues (missing files, CI failures, download problems) - these do NOT need device logs
- Documentation or website issues - these do NOT need device logs
If this is a device/firmware bug, request device logs and explain how to get them:
Web Flasher logs:
- Go to https://flasher.meshtastic.org
- Connect the device via USB and click Connect
- Open the device console/log output, reproduce the problem, then copy/download and attach/paste the logs
Meshtastic CLI logs:
- Run: meshtastic --port <serial-port> --noproto
- Reproduce the problem, then copy/paste the terminal output
Also request key context if missing: device model/variant, firmware version, region, steps to reproduce, expected vs actual.
Respond ONLY with valid JSON (no markdown, no code fences):
{"complete": true, "comment": "", "label": "none"}
OR
{"complete": false, "comment": "Your helpful comment", "label": "needs-logs"}
Use "needs-logs" ONLY if this is a device/firmware bug AND no logs are attached.
Use "needs-info" if basic info like firmware version or steps to reproduce are missing.
Use "none" if the issue is complete, is a feature request, or is a build/CI/packaging issue.
Title: ${{ github.event.issue.title }}
Body: ${{ github.event.issue.body }}
system-prompt: You are a helpful assistant that triages GitHub issues. Be conservative with labels. Only request device logs for actual device/firmware bugs, not for build/release/CI issues.
model: openai/gpt-4o-mini
- name: Process analysis result
if: (steps.quality.outputs.response == 'ok' || steps.quality.outputs.response == '') && steps.check-skip.outputs.should_skip != 'true' && steps.analysis.outputs.response != ''
uses: actions/github-script@v8
id: process
env:
AI_RESPONSE: ${{ steps.analysis.outputs.response }}
with:
script: |
let raw = (process.env.AI_RESPONSE || '').trim();
// Strip markdown code fences if present
raw = raw.replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/i, '').trim();
let complete = true;
let comment = '';
let label = 'none';
try {
const parsed = JSON.parse(raw);
complete = !!parsed.complete;
comment = (parsed.comment ?? '').toString().trim();
label = (parsed.label ?? 'none').toString().trim().toLowerCase();
} catch {
// If JSON parse fails, log warning and don't comment (avoid posting raw JSON)
console.log('Failed to parse AI response as JSON:', raw);
complete = true;
comment = '';
label = 'none';
}
// Validate label
const allowedLabels = new Set(['needs-logs', 'needs-info', 'none']);
if (!allowedLabels.has(label)) label = 'none';
// Only comment if we have a valid parsed comment (not raw JSON)
const shouldComment = !complete && comment.length > 0 && !comment.startsWith('{');
core.setOutput('should_comment', shouldComment ? 'true' : 'false');
core.setOutput('comment_body', comment);
core.setOutput('label', label);
- name: Apply triage label
if: steps.process.outputs.label != '' && steps.process.outputs.label != 'none'
uses: actions/github-script@v8
env:
LABEL_NAME: ${{ steps.process.outputs.label }}
with:
script: |
const label = process.env.LABEL_NAME;
const labelMeta = {
'needs-logs': { color: 'cfd3d7', description: 'Device logs requested for triage' },
'needs-info': { color: 'f9d0c4', description: 'More information requested for triage' },
};
const meta = labelMeta[label];
if (!meta) return;
// Ensure label exists
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
} catch (e) {
if (e.status !== 404) throw e;
await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
}
// Apply label
await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.issue.number, labels: [label] });
- name: Comment on issue
if: steps.process.outputs.should_comment == 'true'
uses: actions/github-script@v8
env:
COMMENT_BODY: ${{ steps.process.outputs.comment_body }}
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.issue.number,
body: process.env.COMMENT_BODY
});
+139
View File
@@ -0,0 +1,139 @@
name: PR Triage (Models)
on:
pull_request_target:
types: [opened]
permissions:
pull-requests: write
issues: write
models: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
triage:
if: ${{ github.repository == 'meshtastic/firmware' && github.event.pull_request.user.type != 'Bot' }}
runs-on: ubuntu-latest
steps:
# ─────────────────────────────────────────────────────────────────────────
# Step 1: Check if PR already has automation/type labels (skip if so)
# ─────────────────────────────────────────────────────────────────────────
- name: Check existing labels
uses: actions/github-script@v8
id: check-labels
with:
script: |
const skipLabels = new Set(['automation']);
const typeLabels = new Set(['bugfix', 'hardware-support', 'enhancement', 'dependencies', 'submodules', 'github_actions', 'trunk', 'cleanup']);
const prLabels = context.payload.pull_request.labels.map(l => l.name);
const shouldSkipAll = prLabels.some(l => skipLabels.has(l));
const hasTypeLabel = prLabels.some(l => typeLabels.has(l));
core.setOutput('skip_all', shouldSkipAll ? 'true' : 'false');
core.setOutput('has_type_label', hasTypeLabel ? 'true' : 'false');
# ─────────────────────────────────────────────────────────────────────────
# Step 2: Quality check (spam/AI-slop detection)
# ─────────────────────────────────────────────────────────────────────────
- name: Detect spam or low-quality content
if: steps.check-labels.outputs.skip_all != 'true'
uses: actions/ai-inference@v2
id: quality
continue-on-error: true
with:
max-tokens: 20
prompt: |
Is this GitHub pull request spam, AI-generated slop, or low quality?
Title: ${{ github.event.pull_request.title }}
Body: ${{ github.event.pull_request.body }}
Respond with exactly one of: spam, ai-generated, needs-review, ok
system-prompt: You detect spam and low-quality contributions. Be conservative - only flag obvious spam or AI slop.
model: openai/gpt-4o-mini
- name: Apply quality label if needed
if: steps.check-labels.outputs.skip_all != 'true' && steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
uses: actions/github-script@v8
id: quality-label
env:
QUALITY_LABEL: ${{ steps.quality.outputs.response }}
with:
script: |
const label = (process.env.QUALITY_LABEL || '').trim().toLowerCase();
const labelMeta = {
'spam': { color: 'd73a4a', description: 'Possible spam' },
'ai-generated': { color: 'fbca04', description: 'Possible AI-generated low-quality content' },
'needs-review': { color: 'f9d0c4', description: 'Needs human review' },
};
const meta = labelMeta[label];
if (!meta) return;
// Ensure label exists
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
} catch (e) {
if (e.status !== 404) throw e;
await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
}
// Apply label
await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, labels: [label] });
core.setOutput('is_spam', 'true');
# ─────────────────────────────────────────────────────────────────────────
# Step 3: Auto-label PR type (bugfix/hardware-support/enhancement)
# Only skip for spam/ai-generated; still classify needs-review PRs
# ─────────────────────────────────────────────────────────────────────────
- name: Classify PR for labeling
if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.quality.outputs.response != 'spam' && steps.quality.outputs.response != 'ai-generated'
uses: actions/ai-inference@v2
id: classify
continue-on-error: true
with:
max-tokens: 30
prompt: |
Classify this pull request into exactly one category.
Return exactly one of: bugfix, hardware-support, enhancement
Use bugfix if it fixes a bug, crash, or incorrect behavior.
Use hardware-support if it adds or improves support for a specific hardware device/variant.
Use enhancement if it adds a new feature, improves performance, or refactors code.
Title: ${{ github.event.pull_request.title }}
Body: ${{ github.event.pull_request.body }}
system-prompt: You classify pull requests into categories. Be conservative and pick the most appropriate single label.
model: openai/gpt-4o-mini
- name: Apply type label
if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.classify.outputs.response != ''
uses: actions/github-script@v8
env:
TYPE_LABEL: ${{ steps.classify.outputs.response }}
with:
script: |
const label = (process.env.TYPE_LABEL || '').trim().toLowerCase();
const labelMeta = {
'bugfix': { color: 'd73a4a', description: 'Bug fix' },
'hardware-support': { color: '0e8a16', description: 'Hardware support addition or improvement' },
'enhancement': { color: 'a2eeef', description: 'New feature or enhancement' },
};
const meta = labelMeta[label];
if (!meta) return;
// Ensure label exists
try {
await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
} catch (e) {
if (e.status !== 404) throw e;
await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
}
// Apply label
await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, labels: [label] });
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true
+11 -1
View File
@@ -54,9 +54,19 @@ jobs:
PLATFORMIO_LIBDEPS_DIR: pio/libdeps
PLATFORMIO_PACKAGES_DIR: pio/packages
PLATFORMIO_CORE_DIR: pio/core
PLATFORMIO_SETTING_ENABLE_TELEMETRY: 0
PLATFORMIO_SETTING_CHECK_PLATFORMIO_INTERVAL: 3650
PLATFORMIO_SETTING_CHECK_PRUNE_SYSTEM_THRESHOLD: 10240
- name: Mangle platformio cache
# Add "1" to epoch-timestamps of all downloads in the cache.
# This is a hack to prevent internet access at build-time.
run: |
cp pio/core/.cache/downloads/usage.db pio/core/.cache/downloads/usage.db.bak
jq -c 'with_entries(.value |= (. | tostring + "1" | tonumber))' pio/core/.cache/downloads/usage.db.bak > pio/core/.cache/downloads/usage.db
- name: Store binaries as an artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }}
overwrite: true
+2 -2
View File
@@ -46,7 +46,7 @@ jobs:
sudo apt-get install -y dput
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
uses: crazy-max/ghaction-import-gpg@v7
with:
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
id: gpg
@@ -60,7 +60,7 @@ jobs:
id: version
- name: Download artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
- name: Download test artifacts
if: needs.native-tests.result != 'skipped'
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true
+1 -1
View File
@@ -23,8 +23,8 @@ jobs:
series:
- jammy # 22.04 LTS
- noble # 24.04 LTS
- plucky # 25.04
- questing # 25.10
- resolute # 26.04 LTS
uses: ./.github/workflows/package_ppa.yml
with:
ppa_repo: |-
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: report.sarif
overwrite: true
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Stale PR+Issues
uses: actions/stale@v10.1.1
uses: actions/stale@v10.2.0
with:
days-before-stale: 45
stale-issue-message: This issue has not had any comment or update in the last month. If it is still relevant, please post update comments. If no comments are made, this issue will be closed automagically in 7 days.
+7 -7
View File
@@ -59,7 +59,7 @@ jobs:
id: version
- name: Save coverage information
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}
@@ -94,7 +94,7 @@ jobs:
- name: Save test results
if: always() # run this step even if previous step failed
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
overwrite: true
@@ -108,7 +108,7 @@ jobs:
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
- name: Save coverage information
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}
@@ -137,20 +137,20 @@ jobs:
id: version
- name: Download test artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
name: platformio-test-report-${{ steps.version.outputs.long }}
merge-multiple: true
- name: Test Report
uses: dorny/test-reporter@v2.5.0
uses: dorny/test-reporter@v2.6.0
with:
name: PlatformIO Tests
path: testreport.xml
reporter: java-junit
- name: Download coverage artifacts
uses: actions/download-artifact@v7
uses: actions/download-artifact@v8
with:
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}
path: code-coverage-report
@@ -163,7 +163,7 @@ jobs:
genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report
- name: Save Code Coverage Report
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: code-coverage-report-${{ steps.version.outputs.long }}
path: code-coverage-report
+4
View File
@@ -33,6 +33,7 @@ __pycache__
*~
venv/
.venv/
release/
.vscode/extensions.json
/compile_commands.json
@@ -50,3 +51,6 @@ idf_component.yml
CMakeLists.txt
/sdkconfig.*
.dummy/*
# PYTHONPATH used by the Nix shell
.python3
+14 -14
View File
@@ -4,29 +4,29 @@ cli:
plugins:
sources:
- id: trunk
ref: v1.7.4
ref: v1.7.6
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- checkov@3.2.497
- renovate@42.81.8
- prettier@3.8.0
- trufflehog@3.92.4
- checkov@3.2.508
- renovate@43.76.3
- prettier@3.8.1
- trufflehog@3.93.8
- yamllint@1.38.0
- bandit@1.9.2
- trivy@0.68.2
- bandit@1.9.4
- trivy@0.69.3
- taplo@0.10.0
- ruff@0.14.11
- isort@7.0.0
- markdownlint@0.47.0
- oxipng@10.0.0
- svgo@4.0.0
- actionlint@1.7.10
- ruff@0.15.6
- isort@8.0.1
- markdownlint@0.48.0
- oxipng@10.1.0
- svgo@4.0.1
- actionlint@1.7.11
- flake8@7.3.0
- hadolint@2.14.0
- shfmt@3.6.0
- shellcheck@0.11.0
- black@25.12.0
- black@26.3.1
- git-diff-check
- gitleaks@8.30.0
- clang-format@16.0.3
+2 -2
View File
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
curl wget g++ zip git ca-certificates pkg-config \
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
libx11-dev libinput-dev libxkbcommon-x11-dev libsqlite3-dev \
libx11-dev libinput-dev libxkbcommon-x11-dev libsqlite3-dev libsdl2-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -53,7 +53,7 @@ USER root
RUN apt-get update && apt-get --no-install-recommends -y install \
libc-bin libc6 libgpiod3 libyaml-cpp0.8 libi2c0 libuv1t64 libusb-1.0-0-dev \
liborcania2.3 libulfius2.7t64 libssl3t64 \
libx11-6 libinput10 libxkbcommon-x11-0 \
libx11-6 libinput10 libxkbcommon-x11-0 libsdl2-2.0-0 \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \
+26
View File
@@ -0,0 +1,26 @@
# Lightweight container for running native PlatformIO tests on non-Linux hosts
FROM python:3.14-slim-trixie
ENV DEBIAN_FRONTEND=noninteractive
ENV PIP_ROOT_USER_ACTION=ignore
# hadolint ignore=DL3008
RUN apt-get update && apt-get install --no-install-recommends -y \
g++ git ca-certificates pkg-config \
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
libx11-dev libinput-dev libxkbcommon-x11-dev libsqlite3-dev libsdl2-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir platformio==6.1.19 \
&& useradd --create-home --shell /usr/sbin/nologin meshtastic
WORKDIR /firmware
RUN chown -R meshtastic:meshtastic /firmware
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD platformio --version || exit 1
USER meshtastic
# Run tests by default; override with docker run args for specific filters
CMD ["platformio", "test", "-e", "coverage", "-v"]
+2 -2
View File
@@ -11,7 +11,7 @@ RUN apk --no-cache add \
bash g++ libstdc++-dev linux-headers zip git ca-certificates libbsd-dev \
libgpiod-dev yaml-cpp-dev bluez-dev \
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
libx11-dev libinput-dev libxkbcommon-dev sqlite-dev \
libx11-dev libinput-dev libxkbcommon-dev sqlite-dev sdl2-dev \
&& rm -rf /var/cache/apk/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -42,7 +42,7 @@ USER root
RUN apk --no-cache add \
shadow libstdc++ libbsd libgpiod yaml-cpp libusb \
i2c-tools libuv libx11 libinput libxkbcommon \
i2c-tools libuv libx11 libinput libxkbcommon sdl2 \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \
+1 -1
View File
@@ -23,4 +23,4 @@ for BOARD in $BOARDS; do
CHECK="${CHECK} -e ${BOARD}"
done
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt --inline-suppr" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt --inline-suppr" $CHECK --skip-packages --pattern="src/" --fail-on-defect=low --fail-on-defect=medium --fail-on-defect=high
+2
View File
@@ -187,6 +187,7 @@ Logging:
LogLevel: info # debug, info, warn, error
# TraceFile: /var/log/meshtasticd.json
# JSONFile: /packets.json # File location for JSON output of decoded packets
# JSONFileRotate: 60 # Rotate JSON file every N minutes, or 0 for no rotation
# JSONFilter: position # filter for packets to save to JSON file
# AsciiLogs: true # default if not specified is !isatty() on stdout
@@ -214,3 +215,4 @@ General:
AvailableDirectory: /etc/meshtasticd/available.d/
# MACAddress: AA:BB:CC:DD:EE:FF
# MACAddressSource: eth0
# APIPort: 4403
@@ -6,6 +6,9 @@ Lora:
Reset: 16 # IO4
Busy: 24 # IO5
# Ant_sw: 13 # IO3
Enable_Pins:
- 12
- 13
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.0
@@ -4,5 +4,8 @@ Lora:
Reset: 24 # IO4
Busy: 19 # IO5
# Ant_sw: 23 # IO3
Enable_Pins:
- 26
- 23
spidev: spidev0.1
# CS: 7
@@ -0,0 +1,16 @@
Lora:
### RAK13300in Slot 1
Module: sx1262
IRQ: 22 #IO6
Reset: 16 # IO4
Busy: 24 # IO5
# Ant_sw: 13 # IO3
Enable_Pins:
- 12
- 13
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.0
# CS: 8
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
@@ -0,0 +1,12 @@
Lora:
### RAK13300in Slot 2 pins
IRQ: 18 #IO6
Reset: 24 # IO4
Busy: 19 # IO5
# Ant_sw: 23 # IO3
Enable_Pins:
- 26
- 23
spidev: spidev0.1
# CS: 7
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
+5 -1
View File
@@ -5,7 +5,11 @@ Lora:
IRQ: 22 #IO6
Reset: 16 # IO4
Busy: 24 # IO5
# Ant_sw: 13 # IO3
Enable_Pins:
- 12
- 13
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.0
# GPIO_DETECT_PA: 13
TX_GAIN_LORA: [9, 9, 10, 11, 9, 8, 9, 10, 10, 10, 11, 12, 12, 12, 12, 12, 12, 12, 12, 10, 9, 8]
+16
View File
@@ -0,0 +1,16 @@
# For use with Armbian luckfox-lyra-ultra-w
# Enable overlay 'luckfox-lyra-ultra-w-spi0-cs0-spidev' with armbian-config
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/Luckfox%20Ultra%20Hat
# 1 Watt Lyra Ultra hat
Lora:
Module: sx1262
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
CS: 10
IRQ: 5
Busy: 11
Reset: 9
RXen: 14
spidev: spidev0.0 #pins are (CS=10, CLK=8, MOSI=6, MISO=7)
spiSpeed: 2000000
+17
View File
@@ -0,0 +1,17 @@
# For use with Armbian luckfox-lyra-ultra-w
# Enable overlay 'luckfox-lyra-ultra-w-spi0-cs0-spidev' with armbian-config
# https://github.com/wehooper4/Meshtastic-Hardware/tree/main/Luckfox%20Ultra%20Hat
# 2 Watt Lyra Ultra hat
Lora:
Module: sx1262
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
SX126X_MAX_POWER: 8
CS: 10
IRQ: 5
Busy: 11
Reset: 9
RXen: 14
spidev: spidev0.0 #pins are (CS=10, CLK=8, MOSI=6, MISO=7)
spiSpeed: 2000000
@@ -0,0 +1,25 @@
# For use with Armbian luckfox-lyra // luckfox-lyra-plus
# Enable overlay 'luckfox-lyra-plus-spi0-cs0_rmio13-spidev' with armbian-config
# Waveshare LoRa HAT for Raspberry Pi Pico
# https://www.waveshare.com/wiki/Pico-LoRa-SX1262
Lora:
Module: sx1262
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
spidev: spidev0.0
CS: # GPIO0_B5
pin: 13
gpiochip: 0
line: 13
IRQ: # GPIO1_C2
pin: 50
gpiochip: 1
line: 18
Busy: # GPIO0_B4
pin: 12
gpiochip: 0
line: 12
Reset: # GPIO0_A2
pin: 2
gpiochip: 0
line: 2
@@ -0,0 +1,22 @@
Lora:
Module: sx1262
CS: 0
IRQ: 6
Reset: 1
Busy: 4
RXen: 2
DIO2_AS_RF_SWITCH: true
spidev: ch341
USB_PID: 0x5512
USB_VID: 0x1A86
DIO3_TCXO_VOLTAGE: true
# USB_Serialnum: 12345678
SX126X_MAX_POWER: 22
# Reduce output power to improve EMI
TX_GAIN_LORA: [12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7]
# Note: This module integrates an additional PA to achieve higher output power.
# The 'power' parameter here does not represent the actual RF output.
# TX_GAIN_LORA defines the gain offset applied at each SX1262 input power step (122 dBm).
# Each array element corresponds to the additional gain when that input level is set,
# The effective RF output is: Pout ≈ Pset + TX_GAIN_LORA[index].
# Please refer to https://github.com/linser233/uMesh/blob/main/RF_Power.md for detailed information.
-15
View File
@@ -1,15 +0,0 @@
Lora:
Module: sx1262
CS: 0
IRQ: 6
Reset: 1
Busy: 4
RXen: 2
DIO2_AS_RF_SWITCH: true
spidev: ch341
USB_PID: 0x5512
USB_VID: 0x1A86
DIO3_TCXO_VOLTAGE: true
# USB_Serialnum: 12345678
SX126X_MAX_POWER: 30
# Reduce output power to improve EMI
@@ -0,0 +1,22 @@
Lora:
Module: sx1268
CS: 0
IRQ: 6
Reset: 1
Busy: 4
RXen: 2
DIO2_AS_RF_SWITCH: true
spidev: ch341
USB_PID: 0x5512
USB_VID: 0x1A86
DIO3_TCXO_VOLTAGE: true
# USB_Serialnum: 12345678
SX126X_MAX_POWER: 22
# Reduce output power to improve EMI
TX_GAIN_LORA: [12, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 8, 8, 7]
# Note: This module integrates an additional PA to achieve higher output power.
# The 'power' parameter here does not represent the actual RF output.
# TX_GAIN_LORA defines the gain offset applied at each SX1262 input power step (122 dBm).
# Each array element corresponds to the additional gain when that input level is set,
# The effective RF output is: Pout ≈ Pset + TX_GAIN_LORA[index].
# Please refer to https://github.com/linser233/uMesh/blob/main/RF_Power.md for detailed information.
-15
View File
@@ -1,15 +0,0 @@
Lora:
Module: sx1268
CS: 0
IRQ: 6
Reset: 1
Busy: 4
RXen: 2
DIO2_AS_RF_SWITCH: true
spidev: ch341
USB_PID: 0x5512
USB_VID: 0x1A86
DIO3_TCXO_VOLTAGE: true
# USB_Serialnum: 12345678
SX126X_MAX_POWER: 30
# Reduce output power to improve EMI
+2 -10
View File
@@ -156,16 +156,8 @@ IF %BPS_RESET% EQU 1 (
SET "PROGNAME=!FILENAME:.factory.bin=!"
CALL :LOG_MESSAGE DEBUG "Computed PROGNAME: !PROGNAME!"
IF "__!MCU!__" == "__esp32s3__" (
@REM We are working with ESP32-S3
SET "OTA_FILENAME=bleota-s3.bin"
) ELSE IF "__!MCU!__" == "__esp32c3__" (
@REM We are working with ESP32-C3
SET "OTA_FILENAME=bleota-c3.bin"
) ELSE (
@REM Everything else
SET "OTA_FILENAME=bleota.bin"
)
@REM Determine OTA filename based on MCU type (unified OTA format)
SET "OTA_FILENAME=mt-!MCU!-ota.bin"
CALL :LOG_MESSAGE DEBUG "Set OTA_FILENAME to: !OTA_FILENAME!"
@REM Set SPIFFS filename with "littlefs-" prefix.
+21 -14
View File
@@ -32,6 +32,19 @@ if ! command -v jq >/dev/null 2>&1; then
exit 1
fi
# esptool v5 supports commands with dashes and deprecates commands with
# underscores. Prior versions only support commands with underscores
if ${ESPTOOL_CMD} | grep --quiet write-flash
then
ESPTOOL_WRITE_FLASH=write-flash
ESPTOOL_ERASE_FLASH=erase-flash
ESPTOOL_READ_FLASH_STATUS=read-flash-status
else
ESPTOOL_WRITE_FLASH=write_flash
ESPTOOL_ERASE_FLASH=erase_flash
ESPTOOL_READ_FLASH_STATUS=read_flash_status
fi
set -e
# Usage info
@@ -83,8 +96,8 @@ while [ $# -gt 0 ]; do
done
if [[ $BPS_RESET == true ]]; then
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
exit 0
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset ${ESPTOOL_READ_FLASH_STATUS}
exit 0
fi
[ -z "$FILENAME" ] && [ -n "$1" ] && {
@@ -118,14 +131,8 @@ if [[ -f "$FILENAME" && "$FILENAME" == *.factory.bin ]]; then
exit 1
fi
# Determine OTA filename based on MCU type
if [ "$MCU" == "esp32s3" ]; then
OTAFILE=bleota-s3.bin
elif [ "$MCU" == "esp32c3" ]; then
OTAFILE=bleota-c3.bin
else
OTAFILE=bleota.bin
fi
# Determine OTA filename based on MCU type (unified OTA format)
OTAFILE="mt-${MCU}-ota.bin"
# Set SPIFFS filename with "littlefs-" prefix.
SPIFFSFILE="littlefs-${PROGNAME/firmware-/}.bin"
@@ -144,12 +151,12 @@ if [[ -f "$FILENAME" && "$FILENAME" == *.factory.bin ]]; then
fi
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
$ESPTOOL_CMD erase-flash
$ESPTOOL_CMD write-flash $FIRMWARE_OFFSET "${FILENAME}"
$ESPTOOL_CMD ${ESPTOOL_ERASE_FLASH}
$ESPTOOL_CMD ${ESPTOOL_WRITE_FLASH} $FIRMWARE_OFFSET "${FILENAME}"
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
$ESPTOOL_CMD ${ESPTOOL_WRITE_FLASH} $OTA_OFFSET "${OTAFILE}"
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
$ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
$ESPTOOL_CMD ${ESPTOOL_WRITE_FLASH} $OFFSET "${SPIFFSFILE}"
else
show_help
+13 -2
View File
@@ -20,6 +20,17 @@ else
exit 1
fi
# esptool v5 supports commands with dashes and deprecates commands with
# underscores. Prior versions only support commands with underscores
if ${ESPTOOL_CMD} | grep --quiet write-flash
then
ESPTOOL_WRITE_FLASH=write-flash
ESPTOOL_READ_FLASH_STATUS=read-flash-status
else
ESPTOOL_WRITE_FLASH=write_flash
ESPTOOL_READ_FLASH_STATUS=read_flash_status
fi
# Usage info
show_help() {
cat << EOF
@@ -69,7 +80,7 @@ done
shift "$((OPTIND-1))"
if [ "$CHANGE_MODE" = true ]; then
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset read_flash_status
$ESPTOOL_CMD --baud $RESET_BAUD --after no_reset ${ESPTOOL_READ_FLASH_STATUS}
exit 0
fi
@@ -80,7 +91,7 @@ fi
if [[ -f "$FILENAME" && "$FILENAME" != *.factory.bin ]]; then
echo "Trying to flash update ${FILENAME}"
$ESPTOOL_CMD --baud $FLASH_BAUD write-flash $UPDATE_OFFSET "${FILENAME}"
$ESPTOOL_CMD --baud $FLASH_BAUD ${ESPTOOL_WRITE_FLASH} $UPDATE_OFFSET "${FILENAME}"
else
show_help
echo "Invalid file: ${FILENAME}"
@@ -87,6 +87,15 @@
</screenshots>
<releases>
<release version="2.7.21" date="2026-03-11">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.21</url>
</release>
<release version="2.7.20" date="2026-02-11">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.20</url>
</release>
<release version="2.7.19" date="2026-01-22">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.19</url>
</release>
<release version="2.7.18" date="2026-01-02">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.18</url>
</release>
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Run native PlatformIO tests inside Docker (for macOS / non-Linux hosts).
#
# Usage:
# ./bin/test-native-docker.sh # run all native tests
# ./bin/test-native-docker.sh -f test_transmit_history # run specific test filter
# ./bin/test-native-docker.sh --rebuild # force rebuild the image
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
IMAGE_NAME="meshtastic-native-test"
REBUILD=false
EXTRA_ARGS=()
for arg in "$@"; do
if [[ "$arg" == "--rebuild" ]]; then
REBUILD=true
else
EXTRA_ARGS+=("$arg")
fi
done
if $REBUILD || ! docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
echo "Building test image (first run may take a few minutes)..."
docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/Dockerfile.test" "$ROOT_DIR"
fi
# Disable BUILD_EPOCH to avoid full rebuilds between test runs (matches CI)
sed_cmd='s/-DBUILD_EPOCH=$UNIX_TIME/#-DBUILD_EPOCH=$UNIX_TIME/'
# Default: run all tests. Pass extra args (e.g. -f test_transmit_history) through.
if [[ ${#EXTRA_ARGS[@]} -eq 0 ]]; then
CMD=("platformio" "test" "-e" "coverage" "-v")
else
CMD=("platformio" "test" "-e" "coverage" "-v" "${EXTRA_ARGS[@]}")
fi
exec docker run --rm \
-v "$ROOT_DIR:/src:ro" \
"$IMAGE_NAME" \
bash -c "rm -rf /tmp/fw-test && cp -a /src /tmp/fw-test && cd /tmp/fw-test && sed -i '${sed_cmd}' platformio.ini && ${CMD[*]}"
+2 -1
View File
@@ -32,7 +32,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Minesemi ME25LS01",
+2 -1
View File
@@ -33,7 +33,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "MeshLink",
+40
View File
@@ -0,0 +1,40 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_ESP32S3_DEV",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": ["wifi"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "LilyGo Mini-Epaper-S3 (4 MB Flash, 2MB PSRAM)",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.lilygo.cc",
"vendor": "LilyGo"
}
+51
View File
@@ -0,0 +1,51 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DMINIMESH_LITE -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "Minimesh Lite",
"mcu": "nrf52840",
"variant": "dls_Minimesh_Lite",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Minimesh Lite",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://deeplabstudio.com",
"vendor": "Deeplab Studio"
}
+2 -1
View File
@@ -32,7 +32,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "MINEWSEMI_MS24SF1_SX1262",
+2 -1
View File
@@ -32,7 +32,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "BQ nRF52840",
+2 -1
View File
@@ -33,7 +33,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "ProMicro compatible nRF52840",
+1 -1
View File
@@ -8,7 +8,7 @@
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],
+2 -1
View File
@@ -33,7 +33,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Seeed T1000-E",
+60
View File
@@ -0,0 +1,60 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_TRACKER_T2000_C -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"],
["0x2886", "0x0057"]
],
"usb_product": "T2000-BOOT",
"mcu": "nrf52840",
"variant": "Seeed_T2000-C",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "7.3.0",
"sd_fwid": "0x0123"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Seeed T2000-C",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink",
"cmsis-dap",
"blackmagic"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.seeedstudio.com/",
"vendor": "Seeed Studio"
}
+2 -1
View File
@@ -25,7 +25,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino", "freertos"],
"name": "Seeed WIO WM1110",
+2 -1
View File
@@ -32,7 +32,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Seeed WIO WM1110",
+2 -1
View File
@@ -32,7 +32,8 @@
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Seeed WIO WM1110",
+1 -1
View File
@@ -12,6 +12,6 @@ Ex:
- `logo_320x480.png`
- `logo_320x240.png`
This file is copied to `data/boot/logo.png` before filesytem image compilation.
This file is copied to `data/boot/logo.png` before filesystem image compilation.
For additional examples see the [`event/defcon33` branch](https://github.com/meshtastic/firmware/tree/event/defcon33).
+18
View File
@@ -1,3 +1,21 @@
meshtasticd (2.7.21.0) unstable; urgency=medium
* Version 2.7.21
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 11 Mar 2026 11:45:36 +0000
meshtasticd (2.7.20.0) unstable; urgency=medium
* Version 2.7.20
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Wed, 11 Feb 2026 12:19:54 +0000
meshtasticd (2.7.19.0) unstable; urgency=medium
* Version 2.7.19
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Thu, 22 Jan 2026 22:17:40 +0000
meshtasticd (2.7.18.0) unstable; urgency=medium
* Version 2.7.18
+7
View File
@@ -3,10 +3,17 @@ export DEBEMAIL="jbennett@incomsystems.biz"
export PLATFORMIO_LIBDEPS_DIR=pio/libdeps
export PLATFORMIO_PACKAGES_DIR=pio/packages
export PLATFORMIO_CORE_DIR=pio/core
export PLATFORMIO_SETTING_ENABLE_TELEMETRY=0
export PLATFORMIO_SETTING_CHECK_PLATFORMIO_INTERVAL=3650
export PLATFORMIO_SETTING_CHECK_PRUNE_SYSTEM_THRESHOLD=10240
# Download libraries to `pio`
platformio pkg install -e native-tft
platformio pkg install -e native-tft -t platformio/tool-scons@4.40502.0
# Mangle PlatformIO cache to prevent internet access at build-time
# Simply adds 1 to all expiry (epoch) timestamps, adding ~500 years to expiry date
cp pio/core/.cache/downloads/usage.db pio/core/.cache/downloads/usage.db.bak
jq -c 'with_entries(.value |= (. | tostring + "1" | tonumber))' pio/core/.cache/downloads/usage.db.bak >pio/core/.cache/downloads/usage.db
# Compress `pio` directory to prevent dh_clean from sanitizing it
tar -cf pio.tar pio/
rm -rf pio
+2 -1
View File
@@ -26,7 +26,8 @@ Build-Depends: debhelper-compat (= 13),
libx11-dev,
libinput-dev,
libxkbcommon-x11-dev,
libsqlite3-dev
libsqlite3-dev,
libsdl2-dev
Standards-Version: 4.6.2
Homepage: https://github.com/meshtastic/firmware
Rules-Requires-Root: no
+4 -1
View File
@@ -9,7 +9,10 @@
PIO_ENV:=\
PLATFORMIO_CORE_DIR=pio/core \
PLATFORMIO_LIBDEPS_DIR=pio/libdeps \
PLATFORMIO_PACKAGES_DIR=pio/packages
PLATFORMIO_PACKAGES_DIR=pio/packages \
PLATFORMIO_SETTING_ENABLE_TELEMETRY=0 \
PLATFORMIO_SETTING_CHECK_PLATFORMIO_INTERVAL=3650 \
PLATFORMIO_SETTING_CHECK_PRUNE_SYSTEM_THRESHOLD=10240
# Raspbian armhf builds should be compatible with armv6-hardfloat
# https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/#rpi1-compiler-flags
Generated
+44
View File
@@ -0,0 +1,44 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "NixOS",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "flake-compat",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1766314097,
"narHash": "sha256-laJftWbghBehazn/zxVJ8NdENVgjccsWAdAqKXhErrM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "306ea70f9eb0fb4e040f8540e2deab32ed7e2055",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}
+66
View File
@@ -0,0 +1,66 @@
{
description = "Nix flake to compile Meshtastic firmware";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
# Shim to make flake.nix work with stable Nix.
flake-compat = {
url = "github:NixOS/flake-compat";
flake = false;
};
};
outputs =
inputs:
let
lib = inputs.nixpkgs.lib;
forAllSystems =
fn:
lib.genAttrs lib.systems.flakeExposed (
system:
fn {
pkgs = import inputs.nixpkgs {
inherit system;
};
inherit system;
}
);
in
{
devShells = forAllSystems (
{ pkgs, ... }:
let
python3 = pkgs.python312.withPackages (
ps: with ps; [
google
]
);
in
{
default = pkgs.mkShell {
buildInputs = with pkgs; [
python3
platformio
];
shellHook = ''
# Set up PlatformIO to use a local core directory.
export PLATFORMIO_CORE_DIR=$PWD/.platformio
# Tell pip to put packages into $PIP_PREFIX instead of the usual
# location. This is especially necessary under NixOS to avoid having
# pip trying to write to the read-only Nix store. For more info,
# see https://wiki.nixos.org/wiki/Python
export PIP_PREFIX=$PWD/.python3
export PYTHONPATH="$PIP_PREFIX/${python3.sitePackages}"
export PATH="$PIP_PREFIX/bin:$PATH"
# Avoids reproducibility issues with some Python packages
# See https://nixos.org/manual/nixpkgs/stable/#python-setup.py-bdist_wheel-cannot-create-.whl
unset SOURCE_DATE_EPOCH
'';
};
}
);
};
}
+9 -1
View File
@@ -49,6 +49,7 @@ BuildRequires: pkgconfig(libulfius)
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(xkbcommon-x11)
BuildRequires: pkgconfig(sdl2)
# libbsd is needed on older Fedora/RHEL to provide 'strlcpy'
%if 0%{?fedora} >= 39 || 0%{?rhel} >= 10
@@ -59,8 +60,14 @@ BuildRequires: pkgconfig(libbsd-overlay)
Requires: systemd-udev
# Declare that this package provides the user/group it creates in %pre
# Required for Fedora 43+ which tracks users/groups as RPM dependencies
Provides: user(%{meshtasticd_user})
Provides: group(%{meshtasticd_user})
Provides: group(spi)
%description
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
Meshtastic daemon. Meshtastic is an off-grid
text communication platform that uses inexpensive LoRa radios.
%prep
@@ -151,6 +158,7 @@ fi
%license LICENSE
%doc README.md
%{_bindir}/meshtasticd
%{_bindir}/meshtasticd-start.sh
%dir %{_localstatedir}/lib/meshtasticd
%{_udevrulesdir}/99-meshtasticd-udev.rules
%dir %{_sysconfdir}/meshtasticd
+2 -4
View File
@@ -43,13 +43,11 @@ class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
self.enabled = self.setup_paths()
if self.config.get("env:" + self.environment, "build_type") != "debug":
print(
"""
print("""
Please build project in debug configuration to get more details about an exception.
See https://docs.platformio.org/page/projectconf/build_configurations.html
"""
)
""")
return self
+39 -16
View File
@@ -50,12 +50,15 @@ build_flags = -Wno-missing-field-initializers
-DRADIOLIB_EXCLUDE_APRS=1
-DRADIOLIB_EXCLUDE_LORAWAN=1
-DMESHTASTIC_EXCLUDE_DROPZONE=1
-DMESHTASTIC_EXCLUDE_REPLYBOT=1
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
-DMESHTASTIC_EXCLUDE_POWERMON=1
-DMESHTASTIC_EXCLUDE_STATUS=1
-D MAX_THREADS=40 ; As we've split modules, we have more threads to manage
-DLED_BUILTIN=-1
#-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now
#-D OLED_PL=1
#-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs
@@ -65,7 +68,7 @@ monitor_speed = 115200
monitor_filters = direct
lib_deps =
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/b34c6817c25d6faabb3a8a162b5d14fb75395433.zip
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/21e484f409cde18d44012caef84c244eb5ca28f3.zip
# renovate: datasource=git-refs depName=meshtastic-OneButton packageName=https://github.com/meshtastic/OneButton gitBranch=master
https://github.com/meshtastic/OneButton/archive/fa352d668c53f290cfa480a5f79ad422cd828c70.zip
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
@@ -94,7 +97,11 @@ lib_deps =
${env.lib_deps}
# renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL
end2endzone/NonBlockingRTTTL@1.4.0
build_unflags =
-std=c++11
-std=gnu++11
build_flags = ${env.build_flags} -Os
-std=gnu++17
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
; Common libs for communicating over TCP/IP networks such as MQTT
@@ -114,12 +121,12 @@ lib_deps =
[radiolib_base]
lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
jgromes/RadioLib@7.5.0
jgromes/RadioLib@7.6.0
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/5a870c623a4e9ab7a7abe3d02950536f107d1a31.zip
https://github.com/meshtastic/device-ui/archive/622b034d8791153de9d16a473723cb8625d35839.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -135,7 +142,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
adafruit/Adafruit BME280 Library@2.3.0
# renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310
adafruit/Adafruit DPS310@1.1.5
adafruit/Adafruit DPS310@1.1.6
# renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library
adafruit/Adafruit MCP9808 Library@2.0.2
# renovate: datasource=custom.pio depName=Adafruit INA260 packageName=adafruit/library/Adafruit INA260 Library
@@ -143,11 +150,11 @@ lib_deps =
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
adafruit/Adafruit INA219@1.2.3
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
adafruit/Adafruit MPU6050@2.2.6
adafruit/Adafruit MPU6050@2.2.9
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
adafruit/Adafruit LIS3DH@1.3.0
# renovate: datasource=custom.pio depName=Adafruit AHTX0 packageName=adafruit/library/Adafruit AHTX0
adafruit/Adafruit AHTX0@2.0.5
adafruit/Adafruit AHTX0@2.0.6
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
adafruit/Adafruit LSM6DS@4.7.4
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
@@ -155,7 +162,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632
emotibit/EmotiBit MLX90632@1.0.8
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
adafruit/Adafruit MLX90614 Library@2.1.5
adafruit/Adafruit MLX90614 Library@2.1.6
# renovate: datasource=git-refs depName=INA3221 packageName=https://github.com/sgtwilko/INA3221 gitBranch=FixOverflow
https://github.com/sgtwilko/INA3221/archive/bb03d7e9bfcc74fc798838a54f4f99738f29fc6a.zip
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
@@ -177,12 +184,12 @@ lib_deps =
# renovate: datasource=custom.pio depName=DFRobot_BMM150 packageName=dfrobot/library/DFRobot_BMM150
dfrobot/DFRobot_BMM150@1.0.0
# renovate: datasource=custom.pio depName=Adafruit_TSL2561 packageName=adafruit/library/Adafruit TSL2561
adafruit/Adafruit TSL2561@1.1.2
adafruit/Adafruit TSL2561@1.1.3
# renovate: datasource=custom.pio depName=BH1750_WE packageName=wollewald/library/BH1750_WE
wollewald/BH1750_WE@1.1.10
; (not included in native / portduino)
[environmental_extra]
; Common environmental sensor libraries (not included in native / portduino)
[environmental_extra_common]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
@@ -202,13 +209,29 @@ lib_deps =
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
closedcube/ClosedCube OPT3001@1.1.2
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core
sensirion/Sensirion Core@0.7.3
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
sensirion/Sensirion I2C SCD4x@1.1.0
# renovate: datasource=custom.pio depName=Sensirion I2C SFA3x packageName=sensirion/library/Sensirion I2C SFA3x
sensirion/Sensirion I2C SFA3x@1.0.0
# renovate: datasource=custom.pio depName=Sensirion I2C SCD30 packageName=sensirion/library/Sensirion I2C SCD30
sensirion/Sensirion I2C SCD30@1.0.0
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
[environmental_extra]
lib_deps =
${environmental_extra_common.lib_deps}
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.3.40408
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=custom.pio depName=Sensirion Core packageName=sensirion/library/Sensirion Core
sensirion/Sensirion Core@0.7.2
# renovate: datasource=custom.pio depName=Sensirion I2C SCD4x packageName=sensirion/library/Sensirion I2C SCD4x
sensirion/Sensirion I2C SCD4x@1.1.0
; Environmental sensors without BSEC (saves ~3.5KB DRAM for original ESP32 targets)
[environmental_extra_no_bsec]
lib_deps =
${environmental_extra_common.lib_deps}
# renovate: datasource=custom.pio depName=adafruit/Adafruit BME680 Library packageName=adafruit/library/Adafruit BME680
adafruit/Adafruit BME680 Library@^2.0.5
+12
View File
@@ -0,0 +1,12 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
nodeName = lock.nodes.root.inputs.flake-compat;
in
fetchTarball {
url =
lock.nodes.${nodeName}.locked.url
or "https://github.com/NixOS/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz";
sha256 = lock.nodes.${nodeName}.locked.narHash;
}
) { src = ./.; }).shellNix
+68 -59
View File
@@ -1,19 +1,23 @@
#ifndef AMBIENTLIGHTINGTHREAD_H
#define AMBIENTLIGHTINGTHREAD_H
#include "Observer.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
#include "sleep.h"
#ifdef HAS_NCP5623
#include <graphics/RAKled.h>
NCP5623 rgb;
#include <Wire.h>
#include <NCP5623.h>
#endif
#ifdef HAS_LP5562
#include <graphics/NomadStarLED.h>
LP5562 rgbw;
#endif
#ifdef HAS_NEOPIXEL
#include <graphics/NeoPixel.h>
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
#include <Adafruit_NeoPixel.h>
#endif
#ifdef UNPHONE
@@ -21,10 +25,24 @@ Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
extern unPhone unphone;
#endif
namespace concurrency
{
class AmbientLightingThread : public concurrency::OSThread
{
friend class StatusLEDModule; // Let the LEDStatusModule trigger the ambient lighting for notifications and battery status.
friend class ExternalNotificationModule; // Let the ExternalNotificationModule trigger the ambient lighting for notifications.
private:
#ifdef HAS_NCP5623
NCP5623 rgb;
#endif
#ifdef HAS_LP5562
LP5562 rgbw;
#endif
#ifdef HAS_NEOPIXEL
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
#endif
public:
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLighting")
{
@@ -36,14 +54,15 @@ class AmbientLightingThread : public concurrency::OSThread
moduleConfig.ambient_lighting.led_state = true;
#endif
#endif
// Uncomment to test module
// moduleConfig.ambient_lighting.led_state = true;
// moduleConfig.ambient_lighting.current = 10;
#if AMBIENT_LIGHTING_TEST
// define to enable test
moduleConfig.ambient_lighting.led_state = true;
moduleConfig.ambient_lighting.current = 10;
// Default to a color based on our node number
// moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
// moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
// moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
#endif
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
_type = type;
if (_type == ScanI2C::DeviceType::NONE) {
@@ -53,11 +72,6 @@ class AmbientLightingThread : public concurrency::OSThread
}
#endif
#ifdef HAS_RGB_LED
if (!moduleConfig.ambient_lighting.led_state) {
LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF");
disable();
return;
}
LOG_DEBUG("AmbientLighting init");
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623) {
@@ -77,7 +91,13 @@ class AmbientLightingThread : public concurrency::OSThread
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness(moduleConfig.ambient_lighting.current);
#endif
setLighting();
if (!moduleConfig.ambient_lighting.led_state) {
LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF");
disable();
return;
}
setLighting(moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
@@ -91,7 +111,8 @@ class AmbientLightingThread : public concurrency::OSThread
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
#endif
setLighting();
setLighting(moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
@@ -148,65 +169,53 @@ class AmbientLightingThread : public concurrency::OSThread
return 0;
}
void setLighting()
protected:
void setLighting(float current, uint8_t red, uint8_t green, uint8_t blue)
{
#ifdef HAS_NCP5623
rgb.setCurrent(moduleConfig.ambient_lighting.current);
rgb.setRed(moduleConfig.ambient_lighting.red);
rgb.setGreen(moduleConfig.ambient_lighting.green);
rgb.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
rgb.setCurrent(current);
rgb.setRed(red);
rgb.setGreen(green);
rgb.setBlue(blue);
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%f, red=%d, green=%d, blue=%d", current, red, green, blue);
#endif
#ifdef HAS_LP5562
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
rgbw.setRed(moduleConfig.ambient_lighting.red);
rgbw.setGreen(moduleConfig.ambient_lighting.green);
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
rgbw.setCurrent(current);
rgbw.setRed(red);
rgbw.setGreen(green);
rgbw.setBlue(blue);
LOG_DEBUG("Init LP5562 Ambient light w/ current=%f, red=%d, green=%d, blue=%d", current, red, green, blue);
#endif
#ifdef HAS_NEOPIXEL
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue),
0, NEOPIXEL_COUNT);
pixels.fill(pixels.Color(red, green, blue), 0, NEOPIXEL_COUNT);
// RadioMaster Bandit has addressable LED at the two buttons
// this allow us to set different lighting for them in variant.h file.
#ifdef RADIOMASTER_900_BANDIT
#if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX)
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
#endif
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
#endif
#endif
pixels.show();
// LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
// moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
// moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
// LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%f, red=%d, green=%d, blue=%d",
// current, red, green, blue);
#endif
#ifdef RGBLED_CA
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
analogWrite(RGBLED_RED, 255 - red);
analogWrite(RGBLED_GREEN, 255 - green);
analogWrite(RGBLED_BLUE, 255 - blue);
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", red, green, blue);
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
analogWrite(RGBLED_RED, red);
analogWrite(RGBLED_GREEN, green);
analogWrite(RGBLED_BLUE, blue);
LOG_DEBUG("Init Ambient light RGB Common Cathode w/ red=%d, green=%d, blue=%d", red, green, blue);
#endif
#ifdef UNPHONE
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
unphone.rgb(red, green, blue);
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", red, green, blue);
#endif
}
};
} // namespace concurrency
#endif // AMBIENTLIGHTINGTHREAD_H
+11 -16
View File
@@ -4,6 +4,7 @@
#include "configuration.h"
#include "main.h"
#include "sleep.h"
#include <memory>
#ifdef HAS_I2S
#include <AudioFileSourcePROGMEM.h>
@@ -29,9 +30,9 @@ class AudioThread : public concurrency::OSThread
io.digitalWrite(EXPANDS_AMP_EN, HIGH);
#endif
setCPUFast(true);
rtttlFile = new AudioFileSourcePROGMEM(data, len);
i2sRtttl = new AudioGeneratorRTTTL();
i2sRtttl->begin(rtttlFile, audioOut);
rtttlFile = std::unique_ptr<AudioFileSourcePROGMEM>(new AudioFileSourcePROGMEM(data, len));
i2sRtttl = std::unique_ptr<AudioGeneratorRTTTL>(new AudioGeneratorRTTTL());
i2sRtttl->begin(rtttlFile.get(), audioOut.get());
}
// Also handles actually playing the RTTTL, needs to be called in loop
@@ -47,14 +48,10 @@ class AudioThread : public concurrency::OSThread
{
if (i2sRtttl != nullptr) {
i2sRtttl->stop();
delete i2sRtttl;
i2sRtttl = nullptr;
}
if (rtttlFile != nullptr) {
delete rtttlFile;
rtttlFile = nullptr;
}
rtttlFile = nullptr;
setCPUFast(false);
#ifdef T_LORA_PAGER
@@ -66,16 +63,14 @@ class AudioThread : public concurrency::OSThread
{
if (i2sRtttl != nullptr) {
i2sRtttl->stop();
delete i2sRtttl;
i2sRtttl = nullptr;
}
#ifdef T_LORA_PAGER
io.digitalWrite(EXPANDS_AMP_EN, HIGH);
#endif
ESP8266SAM *sam = new ESP8266SAM;
sam->Say(audioOut, text);
delete sam;
auto sam = std::unique_ptr<ESP8266SAM>(new ESP8266SAM);
sam->Say(audioOut.get(), text);
setCPUFast(false);
#ifdef T_LORA_PAGER
io.digitalWrite(EXPANDS_AMP_EN, LOW);
@@ -96,15 +91,15 @@ class AudioThread : public concurrency::OSThread
private:
void initOutput()
{
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
audioOut = std::unique_ptr<AudioOutputI2S>(new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S));
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
audioOut->SetGain(0.2);
};
AudioGeneratorRTTTL *i2sRtttl = nullptr;
AudioOutputI2S *audioOut = nullptr;
std::unique_ptr<AudioGeneratorRTTTL> i2sRtttl = nullptr;
std::unique_ptr<AudioOutputI2S> audioOut = nullptr;
AudioFileSourcePROGMEM *rtttlFile = nullptr;
std::unique_ptr<AudioFileSourcePROGMEM> rtttlFile = nullptr;
};
#endif
+2 -10
View File
@@ -89,22 +89,14 @@ class BluetoothStatus : public Status
case ConnectionState::CONNECTED:
LOG_DEBUG("BluetoothStatus CONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, LOW);
#else
digitalWrite(BLE_LED, HIGH);
#endif
digitalWrite(BLE_LED, LED_STATE_ON);
#endif
break;
case ConnectionState::DISCONNECTED:
LOG_DEBUG("BluetoothStatus DISCONNECTED");
#ifdef BLE_LED
#ifdef BLE_LED_INVERTED
digitalWrite(BLE_LED, HIGH);
#else
digitalWrite(BLE_LED, LOW);
#endif
digitalWrite(BLE_LED, LED_STATE_OFF);
#endif
break;
}
-66
View File
@@ -1,66 +0,0 @@
#include "Led.h"
#include "PowerMon.h"
#include "main.h"
#include "power.h"
GpioVirtPin ledForceOn, ledBlink;
#if defined(LED_PIN)
// Most boards have a GPIO for LED control
static GpioHwPin ledRawHwPin(LED_PIN);
#else
static GpioVirtPin ledRawHwPin; // Dummy pin for no hardware
#endif
#if LED_STATE_ON == 0
static GpioVirtPin ledHwPin;
static GpioNotTransformer ledInverter(&ledHwPin, &ledRawHwPin);
#else
static GpioPin &ledHwPin = ledRawHwPin;
#endif
#if defined(HAS_PMU)
/**
* A GPIO controlled by the PMU
*/
class GpioPmuPin : public GpioPin
{
public:
void set(bool value)
{
if (pmu_found && PMU) {
// blink the axp led
PMU->setChargingLedMode(value ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF);
}
}
} ledPmuHwPin;
// In some cases we need to drive a PMU LED and a normal LED
static GpioSplitter ledFinalPin(&ledHwPin, &ledPmuHwPin);
#else
static GpioPin &ledFinalPin = ledHwPin;
#endif
#ifdef USE_POWERMON
/**
* We monitor changes to the LED drive output because we use that as a sanity test in our power monitor stuff.
*/
class MonitoredLedPin : public GpioPin
{
public:
void set(bool value)
{
if (powerMon) {
if (value)
powerMon->setState(meshtastic_PowerMon_State_LED_On);
else
powerMon->clearState(meshtastic_PowerMon_State_LED_On);
}
ledFinalPin.set(value);
}
} monitoredLedPin;
#else
static GpioPin &monitoredLedPin = ledFinalPin;
#endif
static GpioBinaryTransformer ledForcer(&ledForceOn, &ledBlink, &monitoredLedPin, GpioBinaryTransformer::Or);
-7
View File
@@ -1,7 +0,0 @@
#include "GpioLogic.h"
#include "configuration.h"
/**
* ledForceOn and ledForceOff both override the normal ledBlinker behavior (which is controlled by main)
*/
extern GpioVirtPin ledForceOn, ledBlink;
+217 -99
View File
@@ -1,11 +1,14 @@
/**
* @file Power.cpp
* @brief This file contains the implementation of the Power class, which is responsible for managing power-related functionality
* of the device. It includes battery level sensing, power management unit (PMU) control, and power state machine management. The
* Power class is used by the main device class to manage power-related functionality.
* @brief This file contains the implementation of the Power class, which is
* responsible for managing power-related functionality of the device. It
* includes battery level sensing, power management unit (PMU) control, and
* power state machine management. The Power class is used by the main device
* class to manage power-related functionality.
*
* The file also includes implementations of various battery level sensors, such as the AnalogBatteryLevel class, which assumes
* the battery voltage is attached via a voltage-divider to an analog input.
* The file also includes implementations of various battery level sensors, such
* as the AnalogBatteryLevel class, which assumes the battery voltage is
* attached via a voltage-divider to an analog input.
*
* This file is part of the Meshtastic project.
* For more information, see: https://meshtastic.org/
@@ -19,6 +22,7 @@
#include "configuration.h"
#include "main.h"
#include "meshUtils.h"
#include "power/PowerHAL.h"
#include "sleep.h"
#if defined(ARCH_PORTDUINO)
@@ -171,22 +175,12 @@ Power *power;
using namespace meshtastic;
#ifndef AREF_VOLTAGE
#if defined(ARCH_NRF52)
/*
* Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4,
* 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels.
*
* External Reference is VDD/4, with an adjustable gain of 1, 2 or 4, meaning
* VDD/4, VDD/2 or VDD for the ADC levels.
*
* Default settings are internal reference with 1/6 gain (GND..3.6V ADC range)
*/
#define AREF_VOLTAGE 3.6
#else
// NRF52 has AREF_VOLTAGE defined in architecture.h but
// make sure it's included. If something is wrong with NRF52
// definition - compilation will fail on missing definition
#if !defined(AREF_VOLTAGE) && !defined(ARCH_NRF52)
#define AREF_VOLTAGE 3.3
#endif
#endif
/**
* If this board has a battery level sensor, set this to a valid implementation
@@ -233,7 +227,8 @@ static void battery_adcDisable()
#endif
/**
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
* A simple battery level sensor that assumes the battery voltage is attached
* via a voltage-divider to an analog input
*/
class AnalogBatteryLevel : public HasBatteryLevel
{
@@ -311,7 +306,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
#ifndef BATTERY_SENSE_SAMPLES
#define BATTERY_SENSE_SAMPLES \
15 // Set the number of samples, it has an effect of increasing sensitivity in complex electromagnetic environment.
15 // Set the number of samples, it has an effect of increasing sensitivity in
// complex electromagnetic environment.
#endif
#ifdef BATTERY_PIN
@@ -341,7 +337,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
battery_adcDisable();
if (!initial_read_done) {
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
// Flush the smoothing filter with an ADC reading, if the reading is
// plausibly correct
if (scaled > last_read_value)
last_read_value = scaled;
initial_read_done = true;
@@ -350,8 +347,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
last_read_value += (scaled - last_read_value) * 0.5; // Virtual LPF
}
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u filtered=%u", BATTERY_PIN, raw, (uint32_t)(scaled), (uint32_t)
// (last_read_value));
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u filtered=%u",
// BATTERY_PIN, raw, (uint32_t)(scaled), (uint32_t) (last_read_value));
}
return last_read_value;
#endif // BATTERY_PIN
@@ -420,7 +417,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
/**
* return true if there is a battery installed in this unit
*/
// if we have a integrated device with a battery, we can assume that the battery is always connected
// if we have a integrated device with a battery, we can assume that the
// battery is always connected
#ifdef BATTERY_IMMUTABLE
virtual bool isBatteryConnect() override { return true; }
#elif defined(ADC_V)
@@ -441,10 +439,10 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
#endif
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
/// On some boards we don't have the power management chip (like AXPxxxx)
/// so we use EXT_PWR_DETECT GPIO pin to detect external power source
/// If we see a battery voltage higher than physics allows - assume charger is
/// pumping in power On some boards we don't have the power management chip
/// (like AXPxxxx) so we use EXT_PWR_DETECT GPIO pin to detect external power
/// source
virtual bool isVbusIn() override
{
#ifdef EXT_PWR_DETECT
@@ -461,8 +459,14 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
// if it's not HIGH - check the battery
#endif
#elif defined(MUZI_BASE)
return NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk;
// If we have an EXT_PWR_DETECT pin and it indicates no external power, believe it.
return false;
// technically speaking this should work for all(?) NRF52 boards
// but needs testing across multiple devices. NRF52 USB would not even work if
// VBUS was not properly connected and detected by the CPU
#elif defined(MUZI_BASE) || defined(PROMICRO_DIY_TCXO)
return powerHAL_isVBUSConnected();
#endif
return getBattVoltage() > chargingVolt;
}
@@ -485,8 +489,9 @@ class AnalogBatteryLevel : public HasBatteryLevel
#else
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(DISABLE_INA_CHARGING_DETECTION)
if (hasINA()) {
// get current flow from INA sensor - negative value means power flowing into the battery
// default assuming BATTERY+ <--> INA_VIN+ <--> SHUNT RESISTOR <--> INA_VIN- <--> LOAD
// get current flow from INA sensor - negative value means power flowing
// into the battery default assuming BATTERY+ <--> INA_VIN+ <--> SHUNT
// RESISTOR <--> INA_VIN- <--> LOAD
LOG_DEBUG("Using INA on I2C addr 0x%x for charging detection", config.power.device_battery_ina_address);
#if defined(INA_CHARGING_DETECTION_INVERT)
return getINACurrent() > 0;
@@ -502,8 +507,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
private:
/// If we see a battery voltage higher than physics allows - assume charger is pumping
/// in power
/// If we see a battery voltage higher than physics allows - assume charger is
/// pumping in power
/// For heltecs with no battery connected, the measured voltage is 2204, so
// need to be higher than that, in this case is 2500mV (3000-500)
@@ -512,7 +517,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
const float noBatVolt = (OCV[NUM_OCV_POINTS - 1] - 500) * NUM_CELLS;
// Start value from minimum voltage for the filter to not start from 0
// that could trigger some events.
// This value is over-written by the first ADC reading, it the voltage seems reasonable.
// This value is over-written by the first ADC reading, it the voltage seems
// reasonable.
bool initial_read_done = false;
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
uint32_t last_read_time_ms = 0;
@@ -654,7 +660,8 @@ bool Power::analogInit()
#ifdef CONFIG_IDF_TARGET_ESP32S3
// ESP32S3
else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP_FIT) {
LOG_INFO("ADC config based on Two Point values and fitting curve coefficients stored in eFuse");
LOG_INFO("ADC config based on Two Point values and fitting curve "
"coefficients stored in eFuse");
}
#endif
else {
@@ -662,13 +669,7 @@ bool Power::analogInit()
}
#endif // ARCH_ESP32
#ifdef ARCH_NRF52
#ifdef VBAT_AR_INTERNAL
analogReference(VBAT_AR_INTERNAL);
#else
analogReference(AR_INTERNAL); // 3.6V
#endif
#endif // ARCH_NRF52
// NRF52 ADC init moved to powerHAL_init in nrf52 platform
#ifndef ARCH_ESP32
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
@@ -691,7 +692,9 @@ bool Power::setup()
bool found = false;
if (axpChipInit()) {
found = true;
} else if (lipoInit()) {
} else if (cw2015Init()) {
found = true;
} else if (max17048Init()) {
found = true;
} else if (lipoChargerInit()) {
found = true;
@@ -701,11 +704,11 @@ bool Power::setup()
found = true;
} else if (analogInit()) {
found = true;
}
} else {
#ifdef NRF_APM
found = true;
found = true;
#endif
}
#ifdef EXT_PWR_DETECT
attachInterrupt(
EXT_PWR_DETECT,
@@ -723,6 +726,16 @@ bool Power::setup()
runASAP = true;
},
CHANGE);
#endif
#ifdef EXT_CHRG_DETECT
attachInterrupt(
EXT_CHRG_DETECT,
[]() {
power->setIntervalFromNow(0);
runASAP = true;
BaseType_t higherWake = 0;
},
CHANGE);
#endif
enabled = found;
low_voltage_counter = 0;
@@ -769,7 +782,8 @@ void Power::reboot()
HAL_NVIC_SystemReset();
#else
rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
LOG_WARN("FIXME implement reboot for this platform. Note that some settings "
"require a restart to be applied");
#endif
}
@@ -779,9 +793,12 @@ void Power::shutdown()
#if HAS_SCREEN
if (screen) {
#ifdef T_DECK_PRO
screen->showSimpleBanner("Device is powered off.\nConnect USB to start!", 0); // T-Deck Pro has no power button
screen->showSimpleBanner("Device is powered off.\nConnect USB to start!",
0); // T-Deck Pro has no power button
#elif defined(USE_EINK)
screen->showSimpleBanner("Shutting Down...", 2250); // dismiss after 3 seconds to avoid the banner on the sleep screen
screen->showSimpleBanner("Shutting Down...",
2250); // dismiss after 3 seconds to avoid the
// banner on the sleep screen
#else
screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
#endif
@@ -803,6 +820,9 @@ void Power::shutdown()
#endif
#ifdef PIN_LED3
ledOff(PIN_LED3);
#endif
#ifdef LED_NOTIFICATION
ledOff(LED_NOTIFICATION);
#endif
doDeepSleep(DELAY_FOREVER, true, true);
#elif defined(ARCH_PORTDUINO)
@@ -820,22 +840,26 @@ void Power::readPowerStatus()
int32_t batteryVoltageMv = -1; // Assume unknown
int8_t batteryChargePercent = -1;
OptionalBool usbPowered = OptUnknown;
OptionalBool hasBattery = OptUnknown; // These must be static because NRF_APM code doesn't run every time
OptionalBool hasBattery = OptUnknown; // These must be static because NRF_APM
// code doesn't run every time
OptionalBool isChargingNow = OptUnknown;
if (batteryLevel) {
hasBattery = batteryLevel->isBatteryConnect() ? OptTrue : OptFalse;
#ifndef NRF_APM
usbPowered = batteryLevel->isVbusIn() ? OptTrue : OptFalse;
isChargingNow = batteryLevel->isCharging() ? OptTrue : OptFalse;
#endif
if (hasBattery) {
batteryVoltageMv = batteryLevel->getBattVoltage();
// If the AXP192 returns a valid battery percentage, use it
if (batteryLevel->getBatteryPercent() >= 0) {
batteryChargePercent = batteryLevel->getBatteryPercent();
} else {
// If the AXP192 returns a percentage less than 0, the feature is either not supported or there is an error
// In that case, we compute an estimate of the charge percent based on open circuit voltage table defined
// in power.h
// If the AXP192 returns a percentage less than 0, the feature is either
// not supported or there is an error In that case, we compute an
// estimate of the charge percent based on open circuit voltage table
// defined in power.h
batteryChargePercent = clamp((int)(((batteryVoltageMv - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS)) * 1e2) /
((OCV[0] * NUM_CELLS) - (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS))),
0, 100);
@@ -843,12 +867,12 @@ void Power::readPowerStatus()
}
}
// FIXME: IMO we shouldn't be littering our code with all these ifdefs. Way better instead to make a Nrf52IsUsbPowered subclass
// (which shares a superclass with the BatteryLevel stuff)
// that just provides a few methods. But in the interest of fixing this bug I'm going to follow current
// practice.
#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates the power states. Takes 20 seconds or so to detect
// changes.
// FIXME: IMO we shouldn't be littering our code with all these ifdefs. Way
// better instead to make a Nrf52IsUsbPowered subclass (which shares a
// superclass with the BatteryLevel stuff) that just provides a few methods. But
// in the interest of fixing this bug I'm going to follow current practice.
#ifdef NRF_APM // Section of code detects USB power on the RAK4631 and updates
// the power states. Takes 20 seconds or so to detect changes.
nrfx_power_usb_state_t nrf_usb_state = nrfx_power_usbstatus_get();
// LOG_DEBUG("NRF Power %d", nrf_usb_state);
@@ -922,8 +946,9 @@ void Power::readPowerStatus()
#endif
// If we have a battery at all and it is less than 0%, force deep sleep if we have more than 10 low readings in
// a row. NOTE: min LiIon/LiPo voltage is 2.0 to 2.5V, current OCV min is set to 3100 that is large enough.
// If we have a battery at all and it is less than 0%, force deep sleep if we
// have more than 10 low readings in a row. NOTE: min LiIon/LiPo voltage
// is 2.0 to 2.5V, current OCV min is set to 3100 that is large enough.
//
if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
@@ -945,8 +970,8 @@ int32_t Power::runOnce()
readPowerStatus();
#ifdef HAS_PMU
// WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
// the IRQ status by reading the registers over I2C
// WE no longer use the IRQ line to wake the CPU (due to false wakes from
// sleep), but we do poll the IRQ status by reading the registers over I2C
if (PMU) {
PMU->getIrqStatus();
@@ -988,7 +1013,8 @@ int32_t Power::runOnce()
PMU->clearIrqStatus();
}
#endif
// Only read once every 20 seconds once the power status for the app has been initialized
// Only read once every 20 seconds once the power status for the app has been
// initialized
return (statusHandler && statusHandler->isInitialized()) ? (1000 * 20) : RUN_SAME;
}
@@ -996,10 +1022,12 @@ int32_t Power::runOnce()
* Init the power manager chip
*
* axp192 power
DCDC1 0.7-3.5V @ 1200mA max -> OLED // If you turn this off you'll lose comms to the axp192 because the OLED and the
axp192 share the same i2c bus, instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max -> ESP32 (keep this
on!) LDO1 30mA -> charges GPS backup battery // charges the tiny J13 battery by the GPS to power the GPS ram (for a couple of
days), can not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
DCDC1 0.7-3.5V @ 1200mA max -> OLED // If you turn this off you'll lose
comms to the axp192 because the OLED and the axp192 share the same i2c bus,
instead use ssd1306 sleep mode DCDC2 -> unused DCDC3 0.7-3.5V @ 700mA max ->
ESP32 (keep this on!) LDO1 30mA -> charges GPS backup battery // charges the
tiny J13 battery by the GPS to power the GPS ram (for a couple of days), can
not be turned off LDO2 200mA -> LORA LDO3 200mA -> GPS
*
*/
bool Power::axpChipInit()
@@ -1044,9 +1072,10 @@ bool Power::axpChipInit()
if (!PMU) {
/*
* In XPowersLib, if the XPowersAXPxxx object is released, Wire.end() will be called at the same time.
* In order not to affect other devices, if the initialization of the PMU fails, Wire needs to be re-initialized once,
* if there are multiple devices sharing the bus.
* In XPowersLib, if the XPowersAXPxxx object is released, Wire.end() will
* be called at the same time. In order not to affect other devices, if the
* initialization of the PMU fails, Wire needs to be re-initialized once, if
* there are multiple devices sharing the bus.
* * */
#ifndef PMU_USE_WIRE1
w->begin(I2C_SDA, I2C_SCL);
@@ -1063,8 +1092,8 @@ bool Power::axpChipInit()
PMU->enablePowerOutput(XPOWERS_LDO2);
// oled module power channel,
// disable it will cause abnormal communication between boot and AXP power supply,
// do not turn it off
// disable it will cause abnormal communication between boot and AXP power
// supply, do not turn it off
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
// enable oled power
PMU->enablePowerOutput(XPOWERS_DCDC1);
@@ -1091,7 +1120,8 @@ bool Power::axpChipInit()
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it uses an AXP2101 power chip*/
/*The alternative version of T-Beam 1.1 differs from T-Beam V1.1 in that it
* uses an AXP2101 power chip*/
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
// Unuse power channel
PMU->disablePowerOutput(XPOWERS_DCDC2);
@@ -1126,8 +1156,8 @@ bool Power::axpChipInit()
// t-beam s3 core
/**
* gnss module power channel
* The default ALDO4 is off, you need to turn on the GNSS power first, otherwise it will be invalid during
* initialization
* The default ALDO4 is off, you need to turn on the GNSS power first,
* otherwise it will be invalid during initialization
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
@@ -1177,7 +1207,8 @@ bool Power::axpChipInit()
// disable all axp chip interrupt
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
// Set the constant current charging current of AXP2101, temporarily use 500mA by default
// Set the constant current charging current of AXP2101, temporarily use
// 500mA by default
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
// Set up the charging voltage
@@ -1243,11 +1274,12 @@ bool Power::axpChipInit()
PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
}
// We can safely ignore this approach for most (or all) boards because MCU turned off
// earlier than battery discharged to 2.6V.
// We can safely ignore this approach for most (or all) boards because MCU
// turned off earlier than battery discharged to 2.6V.
//
// Unfortanly for now we can't use this killswitch for RAK4630-based boards because they have a bug with
// battery voltage measurement. Probably it sometimes drops to low values.
// Unfortunately for now we can't use this killswitch for RAK4630-based boards
// because they have a bug with battery voltage measurement. Probably it
// sometimes drops to low values.
#ifndef RAK4630
// Set PMU shutdown voltage at 2.6V to maximize battery utilization
PMU->setSysPowerDownVoltage(2600);
@@ -1266,10 +1298,12 @@ bool Power::axpChipInit()
attachInterrupt(
PMU_IRQ, [] { pmu_irq = true; }, FALLING);
// we do not look for AXPXXX_CHARGING_FINISHED_IRQ & AXPXXX_CHARGING_IRQ because it occurs repeatedly while there is
// no battery also it could cause inadvertent waking from light sleep just because the battery filled
// we don't look for AXPXXX_BATT_REMOVED_IRQ because it occurs repeatedly while no battery installed
// we don't look at AXPXXX_VBUS_REMOVED_IRQ because we don't have anything hooked to vbus
// we do not look for AXPXXX_CHARGING_FINISHED_IRQ & AXPXXX_CHARGING_IRQ
// because it occurs repeatedly while there is no battery also it could cause
// inadvertent waking from light sleep just because the battery filled we
// don't look for AXPXXX_BATT_REMOVED_IRQ because it occurs repeatedly while
// no battery installed we don't look at AXPXXX_VBUS_REMOVED_IRQ because we
// don't have anything hooked to vbus
PMU->enableIRQ(pmuIrqMask);
PMU->clearIrqStatus();
@@ -1291,7 +1325,7 @@ bool Power::axpChipInit()
/**
* Wrapper class for an I2C MAX17048 Lipo battery sensor.
*/
class LipoBatteryLevel : public HasBatteryLevel
class MAX17048BatteryLevel : public HasBatteryLevel
{
private:
MAX17048Singleton *max17048 = nullptr;
@@ -1339,18 +1373,18 @@ class LipoBatteryLevel : public HasBatteryLevel
virtual bool isCharging() override { return max17048->isBatteryCharging(); }
};
LipoBatteryLevel lipoLevel;
MAX17048BatteryLevel max17048Level;
/**
* Init the Lipo battery level sensor
*/
bool Power::lipoInit()
bool Power::max17048Init()
{
bool result = lipoLevel.runOnce();
LOG_DEBUG("Power::lipoInit lipo sensor is %s", result ? "ready" : "not ready yet");
bool result = max17048Level.runOnce();
LOG_DEBUG("Power::max17048Init lipo sensor is %s", result ? "ready" : "not ready yet");
if (!result)
return false;
batteryLevel = &lipoLevel;
batteryLevel = &max17048Level;
return true;
}
@@ -1358,7 +1392,88 @@ bool Power::lipoInit()
/**
* The Lipo battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::lipoInit()
bool Power::max17048Init()
{
return false;
}
#endif
#if !MESHTASTIC_EXCLUDE_I2C && HAS_CW2015
class CW2015BatteryLevel : public AnalogBatteryLevel
{
public:
/**
* Battery state of charge, from 0 to 100 or -1 for unknown
*/
virtual int getBatteryPercent() override
{
int data = -1;
Wire.beginTransmission(CW2015_ADDR);
Wire.write(0x04);
if (Wire.endTransmission() == 0) {
if (Wire.requestFrom(CW2015_ADDR, (uint8_t)1)) {
data = Wire.read();
}
}
return data;
}
/**
* The raw voltage of the battery in millivolts, or NAN if unknown
*/
virtual uint16_t getBattVoltage() override
{
uint16_t mv = 0;
Wire.beginTransmission(CW2015_ADDR);
Wire.write(0x02);
if (Wire.endTransmission() == 0) {
if (Wire.requestFrom(CW2015_ADDR, (uint8_t)2)) {
mv = Wire.read();
mv <<= 8;
mv |= Wire.read();
// Voltage is read in 305uV units, convert to mV
mv = mv * 305 / 1000;
}
}
return mv;
}
};
CW2015BatteryLevel cw2015Level;
/**
* Init the CW2015 battery level sensor
*/
bool Power::cw2015Init()
{
Wire.beginTransmission(CW2015_ADDR);
uint8_t getInfo[] = {0x0a, 0x00};
Wire.write(getInfo, 2);
Wire.endTransmission();
delay(10);
Wire.beginTransmission(CW2015_ADDR);
Wire.write(0x00);
bool result = false;
if (Wire.endTransmission() == 0) {
if (Wire.requestFrom(CW2015_ADDR, (uint8_t)1)) {
uint8_t data = Wire.read();
LOG_DEBUG("CW2015 init read data: 0x%x", data);
if (data == 0x73) {
result = true;
batteryLevel = &cw2015Level;
}
}
}
return result;
}
#else
/**
* The CW2015 battery level sensor is unavailable - default to AnalogBatteryLevel
*/
bool Power::cw2015Init()
{
return false;
}
@@ -1385,8 +1500,8 @@ class LipoCharger : public HasBatteryLevel
bool result = PPM->init(Wire, I2C_SDA, I2C_SCL, BQ25896_ADDR);
if (result) {
LOG_INFO("PPM BQ25896 init succeeded");
// Set the minimum operating voltage. Below this voltage, the PPM will protect
// PPM->setSysPowerDownVoltage(3100);
// Set the minimum operating voltage. Below this voltage, the PPM will
// protect PPM->setSysPowerDownVoltage(3100);
// Set input current limit, default is 500mA
// PPM->setInputCurrentLimit(800);
@@ -1409,7 +1524,8 @@ class LipoCharger : public HasBatteryLevel
PPM->enableMeasure();
// Turn on charging function
// If there is no battery connected, do not turn on the charging function
// If there is no battery connected, do not turn on the charging
// function
PPM->enableCharge();
} else {
LOG_WARN("PPM BQ25896 init failed");
@@ -1444,7 +1560,8 @@ class LipoCharger : public HasBatteryLevel
virtual int getBatteryPercent() override
{
return -1;
// return bq->getChargePercent(); // don't use BQ27220 for battery percent, it is not calibrated
// return bq->getChargePercent(); // don't use BQ27220 for battery percent,
// it is not calibrated
}
/**
@@ -1566,7 +1683,8 @@ bool Power::meshSolarInit()
#else
/**
* The meshSolar battery level sensor is unavailable - default to AnalogBatteryLevel
* The meshSolar battery level sensor is unavailable - default to
* AnalogBatteryLevel
*/
bool Power::meshSolarInit()
{
+12 -6
View File
@@ -9,13 +9,13 @@
*/
#include "PowerFSM.h"
#include "Default.h"
#include "Led.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "configuration.h"
#include "graphics/Screen.h"
#include "main.h"
#include "modules/StatusLEDModule.h"
#include "sleep.h"
#include "target_specific.h"
@@ -38,7 +38,10 @@ static bool isPowered()
return true;
#endif
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isRouter = ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)
? 1
: 0);
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
// We assume routers might be powered all the time, but from a low current (solar) source
@@ -103,7 +106,7 @@ static void lsIdle()
uint32_t sleepTime = SLEEP_TIME;
powerMon->setState(meshtastic_PowerMon_State_CPU_LightSleep);
ledBlink.set(false); // Never leave led on while in light sleep
statusLEDModule->setPowerLED(false);
esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL);
powerMon->clearState(meshtastic_PowerMon_State_CPU_LightSleep);
@@ -111,7 +114,7 @@ static void lsIdle()
case ESP_SLEEP_WAKEUP_TIMER:
// Normal case: timer expired, we should just go back to sleep ASAP
ledBlink.set(true); // briefly turn on led
statusLEDModule->setPowerLED(true);
wakeCause2 = doLightSleep(100); // leave led on for 1ms
secsSlept += sleepTime;
@@ -146,7 +149,7 @@ static void lsIdle()
}
} else {
// Time to stop sleeping!
ledBlink.set(false);
statusLEDModule->setPowerLED(false);
LOG_INFO("Reached ls_secs, service loop()");
powerFSM.trigger(EVENT_WAKE_TIMER);
}
@@ -262,7 +265,10 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup()
{
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isRouter = ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)
? 1
: 0);
bool hasPower = isPowered();
LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0);
+19 -30
View File
@@ -227,34 +227,21 @@ void RedirectablePrint::log_to_ble(const char *logLevel, const char *format, va_
isBleConnected = nrf52Bluetooth != nullptr && nrf52Bluetooth->isConnected();
#endif
if (isBleConnected) {
char *message;
size_t initialLen;
size_t len;
initialLen = strlen(format);
message = new char[initialLen + 1];
len = vsnprintf(message, initialLen + 1, format, arg);
if (len > initialLen) {
delete[] message;
message = new char[len + 1];
vsnprintf(message, len + 1, format, arg);
}
auto thread = concurrency::OSThread::currentThread;
meshtastic_LogRecord logRecord = meshtastic_LogRecord_init_zero;
logRecord.level = getLogLevel(logLevel);
strcpy(logRecord.message, message);
vsprintf(logRecord.message, format, arg);
if (thread)
strcpy(logRecord.source, thread->ThreadName.c_str());
logRecord.time = getValidTime(RTCQuality::RTCQualityDevice, true);
uint8_t *buffer = new uint8_t[meshtastic_LogRecord_size];
size_t size = pb_encode_to_bytes(buffer, meshtastic_LogRecord_size, meshtastic_LogRecord_fields, &logRecord);
auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[meshtastic_LogRecord_size]);
size_t size = pb_encode_to_bytes(buffer.get(), meshtastic_LogRecord_size, meshtastic_LogRecord_fields, &logRecord);
#ifdef ARCH_ESP32
nimbleBluetooth->sendLog(buffer, size);
nimbleBluetooth->sendLog(buffer.get(), size);
#elif defined(ARCH_NRF52)
nrf52Bluetooth->sendLog(buffer, size);
nrf52Bluetooth->sendLog(buffer.get(), size);
#endif
delete[] message;
delete[] buffer;
}
}
#else
@@ -292,8 +279,8 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
// append \n to format
size_t len = strlen(format);
char *newFormat = new char[len + 2];
strcpy(newFormat, format);
auto newFormat = std::unique_ptr<char[]>(new char[len + 2]);
strcpy(newFormat.get(), format);
newFormat[len] = '\n';
newFormat[len + 1] = '\0';
@@ -310,23 +297,18 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
va_end(arg);
}
if (portduino_config.logoutputlevel < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
delete[] newFormat;
return;
}
}
if (portduino_config.logoutputlevel < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
delete[] newFormat;
return;
} else if (portduino_config.logoutputlevel < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) {
delete[] newFormat;
return;
} else if (portduino_config.logoutputlevel < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) {
delete[] newFormat;
return;
}
#endif
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
delete[] newFormat;
return;
}
@@ -338,11 +320,19 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
#endif
va_list arg;
va_list arg_copy;
va_start(arg, format);
log_to_serial(logLevel, newFormat, arg);
log_to_syslog(logLevel, newFormat, arg);
log_to_ble(logLevel, newFormat, arg);
va_copy(arg_copy, arg);
log_to_serial(logLevel, newFormat.get(), arg_copy);
va_end(arg_copy);
va_copy(arg_copy, arg);
log_to_syslog(logLevel, newFormat.get(), arg_copy);
va_end(arg_copy);
log_to_ble(logLevel, newFormat.get(), arg);
va_end(arg);
#ifdef HAS_FREE_RTOS
@@ -352,11 +342,10 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
#endif
}
delete[] newFormat;
return;
}
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len)
void RedirectablePrint::hexDump(const char *logLevel, const unsigned char *buf, uint16_t len)
{
const char alphabet[17] = "0123456789abcdef";
log(logLevel, " +------------------------------------------------+ +----------------+");
+1 -1
View File
@@ -44,7 +44,7 @@ class RedirectablePrint : public Print
/** like printf but va_list based */
size_t vprintf(const char *logLevel, const char *format, va_list arg);
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
void hexDump(const char *logLevel, const unsigned char *buf, uint16_t len);
std::string mt_sprintf(const std::string fmt_str, ...);
+2
View File
@@ -35,6 +35,8 @@ void consoleInit()
#if defined(SERIAL_HAS_ON_RECEIVE)
// onReceive does only exist for HardwareSerial not for USB CDC serial
Port.onReceive([sc]() { sc->rxInt(); });
#else
(void)sc;
#endif
DEBUG_PORT.rpInit(); // Simply sets up semaphore
}
+4 -2
View File
@@ -76,8 +76,10 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
void NotifiedWorkerThread::checkNotification()
{
auto n = notification;
notification = 0; // clear notification
// Atomically read and clear. (This avoids a potential race condition where an interrupt handler could set a new notification
// after checkNotification reads but before it clears, which would cause us to miss that notification until the next one comes
// in.)
auto n = notification.exchange(0); // read+clear atomically: like `n = notification; notification = 0;` but interrupt-safe
if (n) {
onNotify(n);
}
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "OSThread.h"
#include <atomic>
namespace concurrency
{
@@ -13,7 +14,7 @@ class NotifiedWorkerThread : public OSThread
/**
* The notification that was most recently used to wake the thread. Read from runOnce()
*/
uint32_t notification = 0;
std::atomic<uint32_t> notification{0};
public:
NotifiedWorkerThread(const char *name) : OSThread(name) {}
+11 -6
View File
@@ -1,24 +1,29 @@
#pragma once
#include <functional>
#include <utility>
#include "concurrency/OSThread.h"
namespace concurrency
{
/**
* @brief Periodically invoke a callback. This just provides C-style callback conventions
* rather than a virtual function - FIXME, remove?
* @brief Periodically invoke a callback.
* Supports both legacy function pointers and modern callables.
*/
class Periodic : public OSThread
{
int32_t (*callback)();
public:
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
Periodic(const char *name, int32_t (*_callback)()) : OSThread(name), callback(_callback) {}
Periodic(const char *name, int32_t (*cb)()) : OSThread(name), callback(cb) {}
Periodic(const char *name, std::function<int32_t()> cb) : OSThread(name), callback(std::move(cb)) {}
protected:
int32_t runOnce() override { return callback(); }
int32_t runOnce() override { return callback ? callback() : 0; }
private:
std::function<int32_t()> callback;
};
} // namespace concurrency
+33 -18
View File
@@ -78,6 +78,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Configuration
// -----------------------------------------------------------------------------
// Pre-hop drop handling (compile-time flag).
#ifndef MESHTASTIC_PREHOP_DROP
#define MESHTASTIC_PREHOP_DROP 0
#endif
/// Convert a preprocessor name into a quoted string
#define xstr(s) ystr(s)
#define ystr(s) #s
@@ -149,16 +154,30 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TX_GAIN_LORA 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7
#endif
#ifdef USE_KCT8103L_PA
// Power Amps are often non-linear, so we can use an array of values for the power curve
#define NUM_PA_POINTS 22
#define TX_GAIN_LORA 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 10, 9, 8, 7
#endif
#ifdef RAK13302
#define NUM_PA_POINTS 22
#define TX_GAIN_LORA 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8
#endif
// Default system gain to 0 if not defined
#ifndef NUM_PA_POINTS
#define NUM_PA_POINTS 1
#endif
#ifndef TX_GAIN_LORA
#define TX_GAIN_LORA 0
#endif
#ifndef HAS_LORA_FEM
#define HAS_LORA_FEM 0
#endif
// -----------------------------------------------------------------------------
// Feature toggles
// -----------------------------------------------------------------------------
@@ -213,6 +232,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
#define SFA30_ADDR 0x5D
#define SHT31_4x_ADDR 0x44
#define SHT31_4x_ADDR_ALT 0x45
#define PMSA003I_ADDR 0x12
@@ -229,6 +249,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define NAU7802_ADDR 0x2A
#define MAX30102_ADDR 0x57
#define SCD4X_ADDR 0x62
#define CW2015_ADDR 0x62
#define MLX90614_ADDR_DEF 0x5A
#define CGRADSENS_ADDR 0x66
#define LTR390UV_ADDR 0x53
@@ -237,6 +258,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BQ27220_ADDR 0x55 // same address as TDECK_KB
#define BQ25896_ADDR 0x6B
#define LTR553ALS_ADDR 0x23
#define SEN5X_ADDR 0x69
#define SCD30_ADDR 0x61
// -----------------------------------------------------------------------------
// ACCELEROMETER
@@ -253,6 +276,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BHI260AP_ADDR 0x28
#define BMM150_ADDR 0x13
#define DA217_ADDR 0x26
#define BMI270_ADDR 0x68
#define BMI270_ADDR_ALT 0x69
// -----------------------------------------------------------------------------
// LED
@@ -386,9 +411,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef HAS_RADIO
#define HAS_RADIO 0
#endif
#ifndef HAS_RTC
#define HAS_RTC 0
#endif
#ifndef HAS_CPU_SHUTDOWN
#define HAS_CPU_SHUTDOWN 0
#endif
@@ -424,12 +446,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HAS_RGB_LED
#endif
#ifndef LED_STATE_OFF
#define LED_STATE_OFF 0
#endif
#ifndef LED_STATE_ON
#define LED_STATE_ON 1
#endif
#ifndef LED_STATE_OFF
#define LED_STATE_OFF (LED_STATE_ON ^ 1)
#endif
#ifndef ledOff
#define ledOff(pin) pinMode(pin, INPUT)
#endif
// default mapping of pins
#if defined(PIN_BUTTON2) && !defined(CANCEL_BUTTON_PIN)
@@ -445,18 +471,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#endif
// BME680 BSEC2 support detection
#if !defined(MESHTASTIC_BME680_BSEC2_SUPPORTED)
#if defined(RAK_4631) || defined(TBEAM_V10)
#define MESHTASTIC_BME680_BSEC2_SUPPORTED 1
#define MESHTASTIC_BME680_HEADER <bsec2.h>
#else
#define MESHTASTIC_BME680_BSEC2_SUPPORTED 0
#define MESHTASTIC_BME680_HEADER <Adafruit_BME680.h>
#endif // defined(RAK_4631)
#endif // !defined(MESHTASTIC_BME680_BSEC2_SUPPORTED)
// -----------------------------------------------------------------------------
// Global switches to turn off features for a minimized build
// -----------------------------------------------------------------------------
@@ -490,6 +504,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MESHTASTIC_EXCLUDE_REMOTEHARDWARE 1
#define MESHTASTIC_EXCLUDE_STOREFORWARD 1
#define MESHTASTIC_EXCLUDE_TEXTMESSAGE 1
#define MESHTASTIC_EXCLUDE_TRAFFIC_MANAGEMENT 1
#define MESHTASTIC_EXCLUDE_ATAK 1
#define MESHTASTIC_EXCLUDE_CANNEDMESSAGES 1
#define MESHTASTIC_EXCLUDE_NEIGHBORINFO 1
+5 -4
View File
@@ -37,14 +37,15 @@ ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
{
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, BMX160, STK8BAXX, ICM20948, QMA6100P, BMM150};
return firstOfOrNONE(9, types);
ScanI2C::DeviceType types[] = {MPU6050, LIS3DH, BMA423, LSM6DS3, LSM6DSOX, BMX160,
STK8BAXX, ICM20948, QMA6100P, BMM150, BMI270};
return firstOfOrNONE(11, types);
}
ScanI2C::FoundDevice ScanI2C::firstAQI() const
{
ScanI2C::DeviceType types[] = {PMSA003I, SCD4X};
return firstOfOrNONE(2, types);
ScanI2C::DeviceType types[] = {PMSA003I, SEN5X, SCD4X, SFA30};
return firstOfOrNONE(4, types);
}
ScanI2C::FoundDevice ScanI2C::firstRGBLED() const
+8 -1
View File
@@ -47,6 +47,7 @@ class ScanI2C
BMA423,
BQ24295,
LSM6DS3,
LSM6DSOX,
TCA9535,
TCA9555,
VEML7700,
@@ -88,7 +89,13 @@ class ScanI2C
BH1750,
DA217,
CHSC6X,
CST226SE
CST226SE,
BMI270,
SEN5X,
SFA30,
CW2015,
SCD30,
ADS1115
} DeviceType;
// typedef uint8_t DeviceAddress;
+148 -15
View File
@@ -1,4 +1,6 @@
#include "ScanI2CTwoWire.h"
#include "configuration.h"
#include "detect/ScanI2C.h"
#if !MESHTASTIC_EXCLUDE_I2C
@@ -8,6 +10,7 @@
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include "meshUtils.h" // vformat
#endif
bool in_array(uint8_t *array, int size, uint8_t lookfor)
@@ -114,6 +117,64 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation
return value;
}
bool ScanI2CTwoWire::i2cCommandResponseLength(ScanI2C::DeviceAddress addr, uint16_t command, uint8_t expectedLength) const
{
TwoWire *i2cBus = fetchI2CBus(addr);
i2cBus->beginTransmission(addr.address);
if (command > 0xFF) {
i2cBus->write((uint8_t)(command >> 8));
}
i2cBus->write((uint8_t)(command & 0xFF));
if (i2cBus->endTransmission() != 0) {
return false;
}
delay(20);
uint8_t received = i2cBus->requestFrom(addr.address, expectedLength);
bool match = (received == expectedLength);
while (i2cBus->available())
i2cBus->read();
return match;
}
/// for SEN5X detection
// Note, this code needs to be called before setting the I2C bus speed
// for the screen at high speed. The speed needs to be at 100kHz, otherwise
// detection will not work
String readSEN5xProductName(TwoWire *i2cBus, uint8_t address)
{
uint8_t cmd[] = {0xD0, 0x14};
uint8_t response[48] = {0};
i2cBus->beginTransmission(address);
i2cBus->write(cmd, 2);
if (i2cBus->endTransmission() != 0)
return "";
delay(20);
if (i2cBus->requestFrom(address, (uint8_t)48) != 48)
return "";
for (int i = 0; i < 48 && i2cBus->available(); ++i) {
response[i] = i2cBus->read();
}
char productName[33] = {0};
int j = 0;
for (int i = 0; i < 48 && j < 32; i += 3) {
if (response[i] >= 32 && response[i] <= 126)
productName[j++] = response[i];
else
break;
if (response[i + 1] >= 32 && response[i + 1] <= 126)
productName[j++] = response[i + 1];
else
break;
}
return String(productName);
}
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
case ADDR: \
logFoundDevice(__VA_ARGS__); \
@@ -280,7 +341,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
type = DPS310;
break;
}
break;
if (type == DPS310) {
break;
}
default:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID
switch (registerValue) {
@@ -390,8 +453,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
type = OPT3001;
logFoundDevice("OPT3001", (uint8_t)addr.address);
} else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 6) !=
0) { // unique SHT4x serial number (6 bytes inc. CRC)
} else if (i2cCommandResponseLength(addr, 0x89, 6)) { // SHT4x serial number (6 bytes inc. CRC)
type = SHT4X;
logFoundDevice("SHT4X", (uint8_t)addr.address);
} else {
@@ -416,6 +478,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
case LPS22HB_ADDR_ALT:
// SFA30 detection: send 2-byte command 0xD060 (Get Device Marking) and check for 48-byte response
if (i2cCommandResponseLength(addr, 0xD060, 48)) {
type = SFA30;
logFoundDevice("SFA30", (uint8_t)addr.address);
break;
}
// Fallback: LPS22HB detection at alternate address using WHO_AM_I register (0x0F == 0xB1)
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1);
if (registerValue == 0xB1) {
type = LPS22HB;
logFoundDevice("LPS22HB", (uint8_t)addr.address);
}
break;
SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address)
SCAN_SIMPLE_CASE(QMC6310U_ADDR, QMC6310U, "QMC6310U", (uint8_t)addr.address)
@@ -436,6 +511,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
if (registerValue == 0x6A) {
type = LSM6DS3;
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
} else if (registerValue == 0x6C) {
type = LSM6DSOX;
logFoundDevice("LSM6DSOX", (uint8_t)addr.address);
} else {
type = QMI8658;
logFoundDevice("QMI8658", (uint8_t)addr.address);
@@ -473,7 +551,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address);
case LSM6DS3_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1);
if (registerValue == 0x6A) {
type = LSM6DS3;
logFoundDevice("LSM6DS3", (uint8_t)addr.address);
} else if (registerValue == 0x6C) {
type = LSM6DSOX;
logFoundDevice("LSM6DSOX", (uint8_t)addr.address);
} else {
type = QMI8658;
logFoundDevice("QMI8658", (uint8_t)addr.address);
}
break;
SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address);
case TCA9555_ADDR:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 1);
@@ -508,6 +598,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(SCD30_ADDR, SCD30, "SCD30", (uint8_t)addr.address);
case CST328_ADDR:
// Do we have the CST328 or the CST226SE
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xAB), 1);
@@ -541,7 +632,17 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
SCAN_SIMPLE_CASE(BHI260AP_ADDR, BHI260AP, "BHI260AP", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address);
case SCD4X_ADDR: {
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x8), 1);
if (registerValue == 0x18) {
logFoundDevice("CW2015", (uint8_t)addr.address);
type = CW2015;
} else {
logFoundDevice("SCD4X", (uint8_t)addr.address);
type = SCD4X;
}
break;
}
SCAN_SIMPLE_CASE(BMM150_ADDR, BMM150, "BMM150", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
@@ -568,8 +669,8 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;
case ICM20948_ADDR: // same as BMX160_ADDR
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR
case ICM20948_ADDR: // same as BMX160_ADDR, BMI270_ADDR_ALT, and SEN5X_ADDR
case ICM20948_ADDR_ALT: // same as MPU6050_ADDR, BMI270_ADDR
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1);
#ifdef HAS_ICM20948
type = ICM20948;
@@ -580,14 +681,39 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
type = ICM20948;
logFoundDevice("ICM20948", (uint8_t)addr.address);
break;
} else if (addr.address == BMX160_ADDR) {
} else if (registerValue == 0x24) {
type = BMI270;
logFoundDevice("BMI270", (uint8_t)addr.address);
break;
} else if (registerValue == 0xD8) { // BMX160 chip ID at register 0x00
type = BMX160;
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
type = MPU6050;
logFoundDevice("MPU6050", (uint8_t)addr.address);
break;
String prod = "";
prod = readSEN5xProductName(i2cBus, addr.address);
if (prod.startsWith("SEN55")) {
type = SEN5X;
logFoundDevice("Sensirion SEN55", addr.address);
break;
} else if (prod.startsWith("SEN54")) {
type = SEN5X;
logFoundDevice("Sensirion SEN54", addr.address);
break;
} else if (prod.startsWith("SEN50")) {
type = SEN5X;
logFoundDevice("Sensirion SEN50", addr.address);
break;
}
if (addr.address == BMX160_ADDR) {
type = BMX160;
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
type = MPU6050;
logFoundDevice("MPU6050", (uint8_t)addr.address);
break;
}
}
break;
@@ -616,11 +742,18 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
if (len == 5 && memcmp(expectedInfo, info, len) == 0) {
LOG_INFO("NXP SE050 crypto chip found");
type = NXP_SE050;
} else {
LOG_INFO("FT6336U touchscreen found");
type = FT6336U;
break;
}
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x01), 2);
if (registerValue == 0x8583 || registerValue == 0x8580) {
type = ADS1115;
logFoundDevice("ADS1115 ADC", (uint8_t)addr.address);
break;
}
LOG_INFO("FT6336U touchscreen found");
type = FT6336U;
break;
}
+2
View File
@@ -55,6 +55,8 @@ class ScanI2CTwoWire : public ScanI2C
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth, bool) const;
bool i2cCommandResponseLength(DeviceAddress addr, uint16_t command, uint8_t expectedLength) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
static void logFoundDevice(const char *device, uint8_t address);
+31
View File
@@ -0,0 +1,31 @@
#include "reClockI2C.h"
#include "ScanI2CTwoWire.h"
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, bool force)
{
uint32_t currentClock = 0;
/* See https://github.com/arduino/Arduino/issues/11457
Currently, only ESP32 can getClock()
While all cores can setClock()
https://github.com/sandeepmistry/arduino-nRF5/blob/master/libraries/Wire/Wire.h#L50
https://github.com/earlephilhower/arduino-pico/blob/master/libraries/Wire/src/Wire.h#L60
https://github.com/stm32duino/Arduino_Core_STM32/blob/main/libraries/Wire/src/Wire.h#L103
For cases when I2C speed is different to the ones defined by sensors (see defines in sensor classes)
we need to reclock I2C and set it back to the previous desired speed.
Only for cases where we can know OR predefine the speed, we can do this.
*/
// TODO add getClock function or return a predefined clock speed per variant?
#ifdef CAN_RECLOCK_I2C
currentClock = i2cBus->getClock();
#endif
if ((currentClock != desiredClock) || force) {
LOG_DEBUG("Changing I2C clock to %u", desiredClock);
i2cBus->setClock(desiredClock);
}
return currentClock;
}
+7 -37
View File
@@ -1,41 +1,11 @@
#ifdef CAN_RECLOCK_I2C
#ifndef RECLOCK_I2C_
#define RECLOCK_I2C_
#include "ScanI2CTwoWire.h"
#include <Wire.h>
#include <stdint.h>
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus)
{
uint32_t reClockI2C(uint32_t desiredClock, TwoWire *i2cBus, bool force);
uint32_t currentClock;
/* See https://github.com/arduino/Arduino/issues/11457
Currently, only ESP32 can getClock()
While all cores can setClock()
https://github.com/sandeepmistry/arduino-nRF5/blob/master/libraries/Wire/Wire.h#L50
https://github.com/earlephilhower/arduino-pico/blob/master/libraries/Wire/src/Wire.h#L60
https://github.com/stm32duino/Arduino_Core_STM32/blob/main/libraries/Wire/src/Wire.h#L103
For cases when I2C speed is different to the ones defined by sensors (see defines in sensor classes)
we need to reclock I2C and set it back to the previous desired speed.
Only for cases where we can know OR predefine the speed, we can do this.
*/
#ifdef ARCH_ESP32
currentClock = i2cBus->getClock();
#elif defined(ARCH_NRF52)
// TODO add getClock function or return a predefined clock speed per variant?
return 0;
#elif defined(ARCH_RP2040)
// TODO add getClock function or return a predefined clock speed per variant
return 0;
#elif defined(ARCH_STM32WL)
// TODO add getClock function or return a predefined clock speed per variant
return 0;
#else
return 0;
#endif
if (currentClock != desiredClock) {
LOG_DEBUG("Changing I2C clock to %u", desiredClock);
i2cBus->setClock(desiredClock);
}
return currentClock;
}
#endif
+22 -18
View File
@@ -52,7 +52,7 @@ SerialUART *GPS::_serial_gps = &GPS_SERIAL_PORT;
HardwareSerial *GPS::_serial_gps = nullptr;
#endif
GPS *gps = nullptr;
std::unique_ptr<GPS> gps = nullptr;
static GPSUpdateScheduling scheduling;
@@ -93,7 +93,7 @@ static const char *getGPSPowerStateString(GPSPowerState state)
#ifdef PIN_GPS_SWITCH
// If we have a hardware switch, define a periodic watcher outside of the GPS runOnce thread, since this can be sleeping
// idefinitely
// indefinitely
int lastState = LOW;
bool firstrun = true;
@@ -127,7 +127,7 @@ static int32_t gpsSwitch()
return 1000;
}
static concurrency::Periodic *gpsPeriodic;
static std::unique_ptr<concurrency::Periodic> gpsPeriodic;
#endif
static void UBXChecksum(uint8_t *message, size_t length)
@@ -586,14 +586,14 @@ bool GPS::setup()
_serial_gps->write("$PMTK301,2*2E\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
// Set the intial configuration of the device - these _should_ work for most AT6558 devices
// Set the initial configuration of the device - these _should_ work for most AT6558 devices
msglen = makeCASPacket(0x06, 0x07, sizeof(_message_CAS_CFG_NAVX_CONF), _message_CAS_CFG_NAVX_CONF);
_serial_gps->write(UBXscratch, msglen);
if (getACKCas(0x06, 0x07, 250) != GNSS_RESPONSE_OK) {
LOG_WARN("ATGM336H: Could not set Config");
}
// Set the update frequence to 1Hz
// Set the update frequency to 1Hz
msglen = makeCASPacket(0x06, 0x04, sizeof(_message_CAS_CFG_RATE_1HZ), _message_CAS_CFG_RATE_1HZ);
_serial_gps->write(UBXscratch, msglen);
if (getACKCas(0x06, 0x04, 250) != GNSS_RESPONSE_OK) {
@@ -700,7 +700,7 @@ bool GPS::setup()
} else { // 8,9
LOG_INFO("GPS+SBAS+GLONASS+Galileo configured");
}
// Documentation say, we need wait atleast 0.5s after reconfiguration of GNSS module, before sending next
// Documentation say, we need wait at least 0.5s after reconfiguration of GNSS module, before sending next
// commands for the M8 it tends to be more... 1 sec should be enough ;>)
delay(1000);
}
@@ -733,7 +733,7 @@ bool GPS::setup()
SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersave for GPS", 500);
SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500);
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
// For M8 we want to enable NMEA version 4.10 so we can see the additional sats.
if (gnssModel == GNSS_MODEL_UBLOX8) {
clearBuffer();
SEND_UBX_PACKET(0x06, 0x17, _message_NMEA, "enable NMEA 4.10", 500);
@@ -905,6 +905,12 @@ void GPS::writePinStandby(bool standby)
// Write and log
pinMode(PIN_GPS_STANDBY, OUTPUT);
digitalWrite(PIN_GPS_STANDBY, val);
// Enter backup mode on PA1010D; TODO: may be applicable to other MTK GPS too
if (IS_ONE_OF(gnssModel, GNSS_MODEL_MTK_PA1010D)) {
_serial_gps->write("$PMTK225,4*2F\r\n");
}
#ifdef GPS_DEBUG
LOG_DEBUG("Pin STANDBY %s", val == HIGH ? "HI" : "LOW");
#endif
@@ -1205,7 +1211,7 @@ int32_t GPS::runOnce()
return disable(); // This should trigger when we have a fixed position, and get that first position
// 9600bps is approx 1 byte per msec, so considering our buffer size we never need to wake more often than 200ms
// if not awake we can run super infrquently (once every 5 secs?) to see if we need to wake.
// if not awake we can run super infrequently (once every 5 secs?) to see if we need to wake.
return (powerState == GPS_ACTIVE) ? GPS_THREAD_INTERVAL : 5000;
}
@@ -1479,7 +1485,7 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
if (bufferSize > 2048)
bufferSize = 2048;
char *response = new char[bufferSize](); // Dynamically allocate based on baud rate
auto response = std::unique_ptr<char[]>(new char[bufferSize]); // Dynamically allocate based on baud rate
uint16_t responseLen = 0;
unsigned long start = millis();
while (millis() - start < timeout) {
@@ -1495,19 +1501,18 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
if (c == ',' || (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n')) {
// check if we can see our chips
for (const auto &chipInfo : responseMap) {
if (strstr(response, chipInfo.detectionString.c_str()) != nullptr) {
if (strstr(response.get(), chipInfo.detectionString.c_str()) != nullptr) {
#ifdef GPS_DEBUG
LOG_DEBUG(response);
LOG_DEBUG(response.get());
#endif
LOG_INFO("%s detected", chipInfo.chipName.c_str());
delete[] response; // Cleanup before return
return chipInfo.driver;
}
}
}
if (responseLen >= 2 && response[responseLen - 2] == '\r' && response[responseLen - 1] == '\n') {
#ifdef GPS_DEBUG
LOG_DEBUG(response);
LOG_DEBUG(response.get());
#endif
// Reset the response buffer for the next potential message
responseLen = 0;
@@ -1516,13 +1521,12 @@ GnssModel_t GPS::getProbeResponse(unsigned long timeout, const std::vector<ChipI
}
}
#ifdef GPS_DEBUG
LOG_DEBUG(response);
LOG_DEBUG(response.get());
#endif
delete[] response; // Cleanup before return
return GNSS_MODEL_UNKNOWN; // Return unknown on timeout
}
GPS *GPS::createGps()
std::unique_ptr<GPS> GPS::createGps()
{
int8_t _rx_gpio = config.position.rx_gpio;
int8_t _tx_gpio = config.position.tx_gpio;
@@ -1547,7 +1551,7 @@ GPS *GPS::createGps()
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
return nullptr;
GPS *new_gps = new GPS;
auto new_gps = std::unique_ptr<GPS>(new GPS());
new_gps->rx_gpio = _rx_gpio;
new_gps->tx_gpio = _tx_gpio;
@@ -1575,7 +1579,7 @@ GPS *GPS::createGps()
#ifdef PIN_GPS_SWITCH
// toggle GPS via external GPIO switch
pinMode(PIN_GPS_SWITCH, INPUT);
gpsPeriodic = new concurrency::Periodic("GPSSwitch", gpsSwitch);
gpsPeriodic = std::unique_ptr<concurrency::Periodic>(new concurrency::Periodic("GPSSwitch", gpsSwitch));
#endif
// Currently disabled per issue #525 (TinyGPS++ crash bug)
+4 -2
View File
@@ -2,6 +2,8 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_GPS
#include <memory>
#include "GPSStatus.h"
#include "GpioLogic.h"
#include "Observer.h"
@@ -118,7 +120,7 @@ class GPS : private concurrency::OSThread
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
static GPS *createGps();
static std::unique_ptr<GPS> createGps();
// Wake the GPS hardware - ready for an update
void up();
@@ -256,5 +258,5 @@ class GPS : private concurrency::OSThread
uint8_t fixeddelayCtr = 0;
};
extern GPS *gps;
extern std::unique_ptr<GPS> gps;
#endif // Exclude GPS
+5 -5
View File
@@ -12,7 +12,7 @@ GeoCoord::GeoCoord(int32_t lat, int32_t lon, int32_t alt) : _latitude(lat), _lon
GeoCoord::GeoCoord(float lat, float lon, int32_t alt) : _altitude(alt)
{
// Change decimial representation to int32_t. I.e., 12.345 becomes 123450000
// Change decimal representation to int32_t. I.e., 12.345 becomes 123450000
_latitude = int32_t(lat * 1e+7);
_longitude = int32_t(lon * 1e+7);
GeoCoord::setCoords();
@@ -20,7 +20,7 @@ GeoCoord::GeoCoord(float lat, float lon, int32_t alt) : _altitude(alt)
GeoCoord::GeoCoord(double lat, double lon, int32_t alt) : _altitude(alt)
{
// Change decimial representation to int32_t. I.e., 12.345 becomes 123450000
// Change decimal representation to int32_t. I.e., 12.345 becomes 123450000
_latitude = int32_t(lat * 1e+7);
_longitude = int32_t(lon * 1e+7);
GeoCoord::setCoords();
@@ -467,10 +467,10 @@ int32_t GeoCoord::bearingTo(const GeoCoord &pointB)
}
/**
* Create a new point bassed on the passed in poin
* Create a new point based on the passed-in point
* Ported from http://www.edwilliams.org/avform147.htm#LL
* @param bearing
* The bearing in raidans
* The bearing in radians
* @param range_meters
* range in meters
* @return GeoCoord object of point at bearing and range from initial point
@@ -593,4 +593,4 @@ double GeoCoord::toRadians(double deg)
double GeoCoord::toDegrees(double r)
{
return r * 180 / PI;
}
}
+14 -13
View File
@@ -72,11 +72,13 @@ RTCSetResult readFromRTC()
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) {
SensorPCF8563 rtc;
#elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
SensorPCF85063 rtc;
#endif
uint32_t now = millis();
SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
@@ -221,7 +223,7 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
// This delta value works on all platforms
timeStartMsec = now;
zeroOffsetSecs = tv->tv_sec;
// If this platform has a setable RTC, set it
// If this platform has a settable RTC, set it
#ifdef RV3028_RTC
if (rtc_found.address == RV3028_RTC) {
Melopero_RV3028 rtc;
@@ -240,10 +242,12 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) {
SensorPCF8563 rtc;
#elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
SensorPCF85063 rtc;
#endif
SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
@@ -276,11 +280,7 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
settimeofday(tv, NULL);
#endif
// nrf52 doesn't have a readable RTC (yet - software not written)
#if HAS_RTC
readFromRTC();
#endif
return RTCSetResultSuccess;
} else {
return RTCSetResultNotSet; // RTC was already set with a higher quality time
@@ -312,7 +312,7 @@ const char *RtcName(RTCQuality quality)
* @param t The time to potentially set the RTC to.
* @return True if the RTC was set to the provided time, false otherwise.
*/
RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t)
RTCSetResult perhapsSetRTC(RTCQuality q, const struct tm &t)
{
/* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
@@ -397,12 +397,12 @@ uint32_t getValidTime(RTCQuality minQuality, bool local)
return (currentQuality >= minQuality) ? getTime(local) : 0;
}
time_t gm_mktime(struct tm *tm)
time_t gm_mktime(const struct tm *tm)
{
#if !MESHTASTIC_EXCLUDE_TZ
time_t result = 0;
// First, get us to the start of tm->year, by calcuating the number of days since the Unix epoch.
// First, get us to the start of tm->year, by calculating the number of days since the Unix epoch.
int year = 1900 + tm->tm_year; // tm_year is years since 1900
int year_minus_one = year - 1;
int days_before_this_year = 0;
@@ -413,8 +413,8 @@ time_t gm_mktime(struct tm *tm)
days_before_this_year -= 719162; // (1969 * 365 + 1969 / 4 - 1969 / 100 + 1969 / 400);
// Now, within this tm->year, compute the days *before* this tm->month starts.
int days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // non-leap year
int days_this_year_before_this_month = days_before_month[tm->tm_mon]; // tm->tm_mon is 0..11
static const int days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; // non-leap year
int days_this_year_before_this_month = days_before_month[tm->tm_mon]; // tm->tm_mon is 0..11
// If this is a leap year, and we're past February, add a day:
if (tm->tm_mon >= 2 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) {
@@ -435,6 +435,7 @@ time_t gm_mktime(struct tm *tm)
return result;
#else
return mktime(tm);
struct tm tmCopy = *tm;
return mktime(&tmCopy);
#endif
}
+2 -2
View File
@@ -41,7 +41,7 @@ extern uint32_t lastSetFromPhoneNtpOrGps;
/// If we haven't yet set our RTC this boot, set it from a GPS derived time
RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpdate = false);
RTCSetResult perhapsSetRTC(RTCQuality q, struct tm &t);
RTCSetResult perhapsSetRTC(RTCQuality q, const struct tm &t);
/// Return a string name for the quality
const char *RtcName(RTCQuality quality);
@@ -54,7 +54,7 @@ uint32_t getValidTime(RTCQuality minQuality, bool local = false);
RTCSetResult readFromRTC();
time_t gm_mktime(struct tm *tm);
time_t gm_mktime(const struct tm *tm);
#define SEC_PER_DAY 86400
#define SEC_PER_HOUR 3600
+1 -1
View File
@@ -37,7 +37,7 @@ static const uint8_t _message_CAS_CFG_RATE_1HZ[] = {
// CFG-NAVX (0x06, 0x07)
// Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system
// Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
// Quirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable
// and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used.
static const uint8_t _message_CAS_CFG_NAVX_CONF[] = {
0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings
+6 -6
View File
@@ -57,7 +57,7 @@ static const uint8_t _message_CFG_PM2[] PROGMEM = {
0x00, 0x00, 0x00, 0x00 // 0x64, 0x40, 0x01, 0x00 // reserved 11
};
// Constallation setup, none required for Neo-6
// Constellation setup, none required for Neo-6
// For Neo-7 GPS & SBAS
static const uint8_t _message_GNSS_7[] = {
@@ -157,7 +157,7 @@ static const uint8_t _message_NAVX5[] = {
0x00, 0x00, 0x00, 0x00, // Reserved 9
0x00, // Reserved 10
0x00, // Reserved 11
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
0x00, // usePPP (Precise Point Positioning) (0 = false, 1 = true)
0x01, // useAOP (AssistNow Autonomous configuration) = 1 (enabled)
0x00, // Reserved 12
0x00, // Reserved 13
@@ -185,7 +185,7 @@ static const uint8_t _message_NAVX5_8[] = {
0x00, // Reserved 4
0x00, 0x00, // Reserved 5
0x00, 0x00, // Reserved 6
0x00, // usePPP (Precice Point Positioning) (0 = false, 1 = true)
0x00, // usePPP (Precise Point Positioning) (0 = false, 1 = true)
0x01, // aopCfg (AssistNow Autonomous configuration) = 1 (enabled)
0x00, 0x00, // Reserved 7
0x00, 0x00, // aopOrbMaxErr = 0 to reset to firmware default
@@ -314,7 +314,7 @@ static const uint8_t _message_DISABLE_TXT_INFO[] = {
// This command applies to M8 products
static const uint8_t _message_PMS[] = {
0x00, // Version (0)
0x03, // Power setup value 3 = Agresssive 1Hz
0x03, // Power setup value 3 = Agressive 1Hz
0x00, 0x00, // period: not applicable, set to 0
0x00, 0x00, // onTime: not applicable, set to 0
0x00, 0x00 // reserved, generated by u-center
@@ -337,7 +337,7 @@ static const uint8_t _message_SAVE_10[] = {
// As the M10 has no flash, the best we can do to preserve the config is to set it in RAM and BBR.
// BBR will survive a restart, and power off for a while, but modules with small backup
// batteries or super caps will not retain the config for a long power off time.
// for all configurations using sleep / low power modes, V_BCKP needs to be hooked to permanent power for fast aquisition after
// for all configurations using sleep / low power modes, V_BCKP needs to be hooked to permanent power for fast acquisition after
// sleep
// VALSET Commands for M10
@@ -462,7 +462,7 @@ Default GNSS configuration is: GPS, Galileo, BDS B1l, with QZSS and SBAS enabled
The PMREQ puts the receiver to sleep and wakeup re-acquires really fast and seems to not need
the PM config. Lets try without it.
PMREQ sort of works with SBAS, but the awake time is too short to re-acquire any SBAS sats.
The defination of "Got Fix" doesn't seem to include SBAS. Much more too this...
The definition of "Got Fix" doesn't seem to include SBAS. Much more too this...
Even if it was, it can take minutes (up to 12.5),
even under good sat visibility conditions to re-acquire the SBAS data.
+11 -2
View File
@@ -101,7 +101,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
return true;
}
// End the update process - virtual method, overriden in derived class
// End the update process - virtual method, overridden in derived class
void EInkDisplay::endUpdate()
{
// Power off display hardware, then deep-sleep (Except Wireless Paper V1.1, no deep-sleep)
@@ -143,6 +143,10 @@ bool EInkDisplay::connect()
#ifdef ELECROW_ThinkNode_M1
// ThinkNode M1 has a hardware dimmable backlight. Start enabled
digitalWrite(PIN_EINK_EN, HIGH);
#elif defined(MINI_EPAPER_S3)
// T-Mini Epaper S3 requires panel power rail enabled before SPI transfer.
digitalWrite(PIN_EINK_EN, HIGH);
delay(10);
#else
digitalWrite(PIN_EINK_EN, LOW);
#endif
@@ -202,7 +206,8 @@ bool EInkDisplay::connect()
}
#elif defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || \
defined(CROWPANEL_ESP32S3_5_EPAPER) || defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER)
defined(CROWPANEL_ESP32S3_5_EPAPER) || defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) || \
defined(MINI_EPAPER_S3)
{
// Start HSPI
hspi = new SPIClass(HSPI);
@@ -216,9 +221,13 @@ bool EInkDisplay::connect()
// Init GxEPD2
adafruitDisplay->init();
#if defined(MINI_EPAPER_S3)
adafruitDisplay->setRotation(3);
#else
adafruitDisplay->setRotation(3);
#if defined(CROWPANEL_ESP32S3_5_EPAPER) || defined(CROWPANEL_ESP32S3_4_EPAPER)
adafruitDisplay->setRotation(0);
#endif
#endif
}
#elif defined(PCA10059) || defined(ME25LS01)
+2 -1
View File
@@ -89,7 +89,8 @@ class EInkDisplay : public OLEDDisplay
// If display uses HSPI
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0) || defined(HELTEC_VISION_MASTER_E213) || \
defined(HELTEC_VISION_MASTER_E290) || defined(TLORA_T3S3_EPAPER) || defined(CROWPANEL_ESP32S3_5_EPAPER) || \
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) || defined(ELECROW_ThinkNode_M5)
defined(CROWPANEL_ESP32S3_4_EPAPER) || defined(CROWPANEL_ESP32S3_2_EPAPER) || defined(ELECROW_ThinkNode_M5) || \
defined(MINI_EPAPER_S3)
SPIClass *hspi = NULL;
#endif

Some files were not shown because too many files have changed in this diff Show More