Compare commits

..

111 Commits

Author SHA1 Message Date
vidplace7
6a39d72e91 Dayton Hamvention 2025 userPrefs 2025-05-11 13:13:10 -04:00
renovate[bot]
c2a38357f1 chore(deps): update meshtastic/device-ui digest to 09b1780 (#6782)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-10 14:54:58 +02:00
github-actions[bot]
3aee4bfc6b Upgrade trunk (#6758)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-10 19:01:03 +08:00
Ben Meadors
981ecfdb61 Add client notification before role based power saving (sleep) (#6759)
* Add client notification before role based power saving (sleep)

* Unsigned
2025-05-07 21:20:32 -05:00
Tom
ca9bf6b31a Update XIAO_NRF_KIT RXEN Pin definition (#6717)
The XIAO NRF kit comes with a hat which has a slightly different pinout than the one supplied with the XIAO S3. At the last update, the RXEN pin was not moved with the rest.
2025-05-07 21:20:15 -05:00
renovate[bot]
ff2a12d579 chore(deps): update adafruit bme280 to v2.3.0 (#6708)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-08 08:32:01 +08:00
Jonathan Bennett
3a6fc668d8 20948 compass support (#6707)
* Add __has_include blocks for sensors

* Put BMP and BME back in the right sensors

* Split environmental_base to environmental_extra, to compile the working sensor libs for Native

* Remove hard-coded checks for ARCH_PORTDUINO

* Un-clobber bmx160

* Move BusIO to environmental_extra due to Armv7 compile error

* Move to forked BusIO for the moment

* Switch to Meshtastic ICM-20948 lib for Portduino support

* Use 20948 for compass direction

* Compass is more than just RAK4631

* Cleanup for 20948 compass

* use Meshtastic branch of 20948 lib

* Check for HAS_SCREEN for showing calibration screen

* No accelerometerThread on STM32
2025-05-07 18:38:42 -05:00
renovate[bot]
b657ba1abb chore(deps): update sparkfun 9dof imu breakout icm 20948 to v1.3.2 (#6761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 13:27:44 -05:00
Ben Meadors
6f256c06f6 Fix warning 2025-05-07 09:26:10 -05:00
Benjamin Faershtein
86217111b2 Update SECURITY.md (#6757) 2025-05-07 06:28:18 -05:00
Austin
57d6c1fa85 Fix event templates (names, PSKs) (#6753) 2025-05-06 18:05:22 -04:00
Austin
62421a83fd Fix EVENT_MODE on mqttless targets (#6750) 2025-05-06 13:12:25 -04:00
Austin
867f50ab11 Don't run test-native for event firmwares (#6749) 2025-05-06 12:03:01 -05:00
renovate[bot]
1e81ebed06 chore(deps): update meshtastic/device-ui digest to 35576e1 (#6747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 11:14:45 -05:00
github-actions[bot]
dd2cf633b0 Upgrade trunk (#6745)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-06 11:09:25 -05:00
github-actions[bot]
fdbe16f650 Bump release version (#6743)
* automated bumps

* Bump org.meshtastic.meshtasticd, fix GHA

---------

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: vidplace7 <vidplace7@gmail.com>
2025-05-06 11:09:14 -05:00
Austin
a2903921cd Renovate: fix device-ui match (#6748) 2025-05-06 11:09:01 -05:00
Austin
2d6181fca0 update bosch bsec2 (#6727)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-05 06:03:36 -05:00
github-actions[bot]
a32e45f8f2 Upgrade trunk (#6737)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-05 05:16:51 -05:00
Austin
055fdcb7f6 Renovate: Add changelogs for device-ui, cleanup (#6733) 2025-05-05 08:08:39 +08:00
Austin
8bb1f3e869 Update template for event userprefs (#6720) 2025-05-04 13:18:48 -05:00
github-actions[bot]
d75c91a760 [create-pull-request] automated change (#6732)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-04 08:39:59 -05:00
renovate[bot]
9d31d9f43b chore(deps): update meshtastic-device-ui digest to b9e2ad1 (#6729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-03 22:18:39 +02:00
Austin
152b8b1b02 Revert "router: on linux add a mutex around the queue (#6709)" (#6726)
This reverts commit 987623567a.
2025-05-02 13:53:25 -04:00
todd-herbert
10693c4569 Lock SPI bus while in use by InkHUD (#6719)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-02 06:20:56 -05:00
renovate[bot]
7da8aea1df chore(deps): update meshtastic-device-ui digest to aa38459 (#6706)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 06:16:53 -05:00
github-actions[bot]
baae2503d5 Upgrade trunk to 1.22.15 (#6608)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-02 16:24:21 +08:00
Ferdia McKeogh
947191a797 Add PA1010D GPS support (#6691) 2025-05-02 10:11:09 +08:00
Jorropo
987623567a router: on linux add a mutex around the queue (#6709)
UDP reception happens on an other thread, avoid data races and potential data corruption issues.
2025-05-01 06:32:20 -05:00
Manuel
a8ab6e82e6 MUI framebuffer support (#6703)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-30 20:50:30 -05:00
todd-herbert
5c005aaed5 Restore InkHUD to defaults on factory reset (#6637)
* Erase InkHUD settings on factory reset

* Documentation

* Captialn't
Lower case m. Also move the include statement to .cpp, because it doesn't really need to be in the .h
2025-05-01 12:28:05 +12:00
renovate[bot]
f9fbc3ff86 Update platform-native digest to 622341c (#6702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 15:55:13 -05:00
renovate[bot]
124f4daa71 Update meshtastic-device-ui digest to 33aa689 (#6705)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 22:14:38 +02:00
renovate[bot]
00e2ac33ad Update platform-native digest to e19f77e (#6701)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 06:24:47 -05:00
Jonathan Bennett
845088e45b Add 100 msecond delay in tft_task_handler when deviceScreen is null (#6695)
* Add 100 msecond delay in tft_task_handler when deviceScreen is null, to fix 100% usage bug

* move portduino tft task creation into tftSetup

* remove superfluous check

* update platform-native commit

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2025-04-30 06:17:24 -05:00
Ben Meadors
e0b1fdb5e8 Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5 (#6699)
* Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5.

* Update src/mesh/PhoneAPI.cpp

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

* Doot

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-30 06:08:10 -05:00
Jorropo
a7ef9e9c08 udp-multicast: remove the thread from the multicast thread API (#6685)
* udp-multicast: remove the thread from the multicast thread API

The whole API is parallel & asynchronous we don't need to start a thread ourself,
the implementation probably does when we call start listening already.

* Take copilot advice and call it a handler

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-30 05:52:42 -05:00
Austin
216fbf2343 Update 'Adafruit BusIO' to 1.17.1 (#6694) 2025-04-29 19:24:00 -04:00
Jorropo
635de2d229 udp-multicast: bump platform-native to fix UDP read of unitialized memory bug (#6686)
* udp-multicast: bump platform-native to fix UDP read of unitialized memory bug

Fixes: #6683

* Update portduino.ini

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-29 06:31:53 -05:00
Colin
72eae42b81 PMSA003I: add support for driving SET pin low while not actively taking a telemetry reading (#6569)
* support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading

* add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp

* fix typos, use arduino gpio defines instead of magic numbers

* support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading

* add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp

* fix typos, use arduino gpio defines instead of magic numbers

* RAK4631: add PMSA003I_ENABLE_PIN define

* fix indentation

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-29 06:31:01 -05:00
renovate[bot]
b4e8f7dbb6 Update Adafruit BusIO digest to 159f86a (#6681)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 20:32:19 -05:00
Jonathan Bennett
473ef1bc03 Step one of Linux Sensor support (#6673)
* First addition of __has_include for sensor support

* Add __has_include blocks for sensors

* Put BMP and BME back in the right sensors

* Make TelemetrySensor::setup() a pure virtual finction

* Split environmental_base to environmental_extra, to compile the working sensor libs for Native

* Remove hard-coded checks for ARCH_PORTDUINO

* Un-clobber bmx160

* Move BusIO to environmental_extra due to Armv7 compile error

* Move to forked BusIO for the moment

* Enable HAS_SENSOR for Portduino

* Move back to Adafruit BusIO after patch
2025-04-28 18:35:13 -05:00
renovate[bot]
ca8c177363 Update meshtastic-device-ui digest to 8113d4f (#6677)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 08:24:00 +10:00
Kalle Lilja
77e6868d5d Fix create pull request (#6680)
* add base property

* bump to 2.6.7 - manual

* disable pip version check
2025-04-28 15:47:09 -05:00
Ben Meadors
54c1423039 Use the last GOOD version 2025-04-26 06:17:08 -05:00
Austin
03f19bca0e Downgrade web to 2.5.4 (#6669) 2025-04-25 11:30:20 -05:00
todd-herbert
89df9d7686 Fix WiPhone variant.h (#6664) 2025-04-24 20:40:48 -05:00
renovate[bot]
45fcd479f6 Update meshtastic-device-ui digest to 189ed6c (#6657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 20:50:35 +02:00
GUVWAF
b1e35cd8b3 Fix preamble detected IRQ flag (#6653) 2025-04-22 14:21:29 -05:00
todd-herbert
70ced735d9 Correct a typing error in InkHUD display driver (#6651)
* Fix LCMEN2R13EFC1 LUT
A typing error when the driver was initially created.

* Spelling..
2025-04-22 06:25:53 -05:00
Manuel
24e9539d40 remove buzzer (#6652) 2025-04-22 06:25:07 -05:00
Austin
72dd5bd88d Publish firmware all together (#6642) 2025-04-20 16:31:47 -04:00
Austin
8812eadd44 Revert "Add IP Address Frame (#6615)" (#6639)
This reverts commit 5d48d2c0a7.
2025-04-20 09:49:21 -05:00
Ben Meadors
48dc0e014c Revert "Lib Update (#6510)" (#6640)
This reverts commit e2f6600cb9.
2025-04-20 09:48:07 -05:00
Austin
e03f3de185 Build and deploy event firmwares (#6628) 2025-04-20 09:45:58 -05:00
Nivek-domo
5d48d2c0a7 Add IP Address Frame (#6615)
* Update Screen.cpp

add ip on screen if has ethernet pcb like w5500 spi

* Run Trunk Format and Translate Comments FR->EN

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2025-04-20 20:06:39 +10:00
Nivek-domo
2b57ffafd7 Rak13800 Ethernet works on rak11310 too
we can use rak13800 on rak11310 too
2025-04-20 18:51:01 +10:00
renovate[bot]
a30f431b6a Update Kongduino-Adafruit_nRFCrypto digest to 5f838d2 (#6634)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-19 18:49:05 +02:00
Austin
916afb5098 appdata.xml: Add date to all releases (#6632) 2025-04-19 10:56:41 -04:00
Austin
d26b50b78c docker alpine: Add available.d config templates (#6631) 2025-04-19 00:29:59 -04:00
Austin
c6e5ec055f RPM: Build native-tft target (#6613) 2025-04-19 10:48:32 +10:00
renovate[bot]
5ab1db0142 chore(deps): update meshtastic-device-ui digest to 65eb74f (#6624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-18 09:36:23 -05:00
Austin
64a1cd3f99 Docker is fun (#6623) 2025-04-18 10:29:39 -04:00
Austin
9da141aa8c Add TFT docker builds (for CI) (#6614) 2025-04-18 07:27:38 -05:00
todd-herbert
74b3dc34e4 Fix crash when clearing NRF52 BLE bonds (#6609)
* Fix crash before clearing BLE bonds

* Prevent clients re-pairing BLE during factory reset
Clients seem able to re-pair BLE after clearing bonds during factory reset, even after advertising disabled. This seems to primarily occur on Android devices, which seem to more actively maintain the BLE connection.
As a workaround, `NRF52Bluetooth::shutdown` swaps the BLE pairing callback to one which actively rejects new connections.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-17 17:11:42 -05:00
Thomas Göttgens
e2f6600cb9 Lib Update (#6510)
* Lib Update

Draft because PIN display doesn't work yet.

* pin entry still no worky

* Fix for missing PIN code issue (#6574)

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Alexander Begoon <alex@begoonlab.tech>
2025-04-17 15:58:28 -05:00
Thomas Göttgens
ef14967fbf Crowpanel 2.4,2.8 and 3.5 support (#6355)
Co-authored-by: mverch67 <manuel.verch@gmx.de>
2025-04-17 16:03:37 +02:00
github-actions[bot]
c177c6d655 [create-pull-request] automated change (#6610)
Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com>
2025-04-17 05:33:42 -05:00
Benjamin Kyd
a36f21b29a Fix compiler error in PowerFSM when WiFi is excluded (#6603) 2025-04-17 11:36:19 +02:00
dylanli
d74359abf0 add support for Seeed solar panel (#6597)
* add seeed_solar_node

* fix RF_SW problem

* fix IIC problem

* Update Button redefination

* Add on-board flash pin defination

* fix missing a ','

* update seeed sorlar panel defination

* fix word spell

* fix upstream change

* fix upstream change

* fix upstream change

* fix formate

* Restore the FLASH definition that was deleted by mistake and pull down the CS pin to ensure low power consumption

* fix led defination conflict

* Delete lib/device-ui directory

* Restore protobufs submodule

---------

Co-authored-by: WayenWeng <jinyuan.weng@seeed.cc>
2025-04-17 16:11:17 +10:00
Benjamin Kyd
5fd64d4114 Fix uninitialised memory read (adminModule) (#6605) 2025-04-16 14:42:08 -05:00
github-actions[bot]
816d948ee5 Upgrade trunk (#6592)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-04-16 06:15:33 -05:00
Niklas
e0dafc3618 fix: set upload_speed for tlora_v1 (#6601) 2025-04-16 06:15:16 -05:00
Mark Trevor Birss
4a9a59342a Create lora-piggystick-lr1121.yaml (#6600) 2025-04-16 11:23:52 +02:00
Austin
5699d8632e Debian: use native-tft compile target (#6580) 2025-04-16 11:21:31 +02:00
Aaron.Lee
e5cd0d613c Make startup screen show the short ID (#6591)
* Update the short ID show on the boot up screen function
2025-04-16 11:20:12 +02:00
Benjamin Kyd
64c8bde04a Update platformio.ini to exclude unused modules from t1000-e (#6584)
* Update platformio.ini to exclude unused modules
* Add No EXT GPIO flag and also correct some exclusions in main
* CANNEDMSG != CANNEDMESSAGES
* Remove NO_EXT_GPIO
2025-04-16 10:12:23 +02:00
github-actions[bot]
4477031971 [create-pull-request] automated change (#6599) 2025-04-16 09:46:06 +02:00
Niklas
1138f74e2c fix: set upload_speed for tlora_v1_3 & tlora_v2_1_16 (#6595) 2025-04-15 20:39:13 -05:00
todd-herbert
cf5c8de92e Fix spurious button presses on some T-Echos (#6590)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-15 20:33:44 -05:00
Kalle Lilja
7e8294dfad FlatHub: bump metainfo.xml on release (#6578)
* add bump_metainfo.py

* bump org.meshtastic.meshtasticd.metainfo.xml on release

* update bump-version job to trigger on published

* use defusedxml.ElementTree parse

* move bump_metainfo, use requirements.txt

* add bin/bump_metainfo/requirements.txt to renovate

* Switch to short version string

* Bump version.properties to 2.6.6

* change version format

* remove url

* Add url back in

* Update url format

* manual add 2.6.6

* consolidate into one PR

* update run steps

* add ability to add date if missing

* update pull request title

* add comments

* remove quote changes

---------

Co-authored-by: Austin <vidplace7@gmail.com>
2025-04-15 18:57:21 -04:00
Tom Fifield
98411d408a Trunk fixes for heltec mesh pocket. (#6588)
https://github.com/meshtastic/firmware/pull/6533 was merged
without running trunk. This patch fixes the newly introduced
trunk errors.
2025-04-15 16:37:09 -05:00
Ben Meadors
040a34fca8 Switch to actually maintained thingsboard pubsubclient (#5204)
* Switch to actually maintained thingsboard pubsubclient

* .0

* TBPubSubClient

* SetBufferSize is split into Send and Receive.

* Update TBPubSubClient to 2.11

* Update platformio.ini

Co-authored-by: Austin <vidplace7@gmail.com>

* Re-add setBufferSize fix

---------

Co-authored-by: Tom Fifield <tom@tomfifield.net>
Co-authored-by: Austin <vidplace7@gmail.com>
2025-04-15 10:50:24 -05:00
renovate[bot]
ecd9f015d8 chore(deps): update meshtastic-device-ui digest to da8fb5e (#6593)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 06:41:52 -05:00
github-actions[bot]
4e30023a4b [create-pull-request] automated change (#6589)
Co-authored-by: fifieldt <1287116+fifieldt@users.noreply.github.com>
2025-04-15 06:41:33 -05:00
Aaron.Lee
b46aad85cc Add new hardware: Heltec MeshPocket (#6533)
* Add Heltec MeshPocket.

* MeshPocket source code update

* Optimiz code for refresh border during full update.

* Update Heltec MeshPocket json file info.
2025-04-15 13:34:30 +10:00
renovate[bot]
c4dc3472ac chore(deps): update meshtastic-device-ui digest to 3fde170 (#6586)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 01:09:32 +02:00
github-actions[bot]
28e62e53e5 Upgrade trunk (#6581)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-04-14 07:50:09 -05:00
renovate[bot]
3eb845eaae chore(deps): update meshtastic-device-ui digest to 3cdb8a6 (#6572)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 19:28:37 -05:00
renovate[bot]
e4c2730f71 chore(deps): update meshtastic-device-ui digest to 13f69c5 (#6567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 19:47:36 +02:00
Austin
e7d0837d01 Add Meshtastic Linux desktop metadata (#6568) 2025-04-11 15:54:53 -05:00
Tavis
e7ce910c3b Add generic thread module (#5484)
* compiling, untested

* use INCLUDE not EXLUDE for option to include module

* protobuf update

* working genericthread module

Update protobufs

* use EXCLUDE style instead of INCLUDE

* Update Modules.cpp

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-11 19:38:44 +02:00
github-actions[bot]
e957009019 Upgrade trunk (#6564)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-04-11 07:48:13 -05:00
Kevin Jahaziel Leon Morales
7079f538ed feat: Add Electronic Cats variant for Catsniffer (#6483)
* feat: Add Electronic Cats variant for catsniffer
* fix: Trunk fmt
* fix: Variant error
2025-04-11 13:26:30 +02:00
Ken Piper
baa05aacf5 fix: Correct underlying cause of T-Watch not functioning when set to a 16MB filesystem (#6563)
* Fix maximum flash size in T-Watch S3 board definition
* Revert "Fix: T-Watch-S3 has 8MB Flash (#6407)"
This reverts commit 769f0623be.
2025-04-11 13:04:37 +02:00
Austin
4ef9eae695 Portduino: Set C standard to 17 (#6561) 2025-04-11 13:02:55 +02:00
renovate[bot]
854d74f8db chore(deps): update meshtastic-device-ui digest to acf343b (#6559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-10 22:18:42 +02:00
Austin
91f38797a8 Don't renovate toolchain-gccarmnoneeabi (#6554) 2025-04-09 19:23:15 -05:00
todd-herbert
06ce6f3e8a fix: remove redundant GPS code targeting Heltec T114 (#6497) 2025-04-10 09:48:40 +10:00
Austin
3694805938 renovate: Link PIO deps to PlatformIO page (#6548) 2025-04-10 08:40:14 +10:00
renovate[bot]
5c13f3451c chore(deps): update meshtastic-device-ui digest to 9345b03 (#6552)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 16:10:01 -05:00
Austin
1008a08c99 Revert "chore(deps): update platformio/toolchain-gccarmnoneeabi to v1.140201.…"
This reverts commit 1888342a57.
2025-04-09 17:07:14 -04:00
renovate[bot]
e98da27446 chore(deps): update ubuntu to v24 (#6541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 13:38:21 -05:00
renovate[bot]
daa03aba30 chore(deps): update meshtastic-esp32_https_server digest to 896f177 (#6542)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 13:02:42 -05:00
renovate[bot]
456f94511f chore(deps): update libch341-spi-userspace digest to af9bc27 (#6539)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 12:57:43 -05:00
renovate[bot]
1888342a57 chore(deps): update platformio/toolchain-gccarmnoneeabi to v1.140201.0 (#6546)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 12:57:21 -05:00
renovate[bot]
8e40d88e24 chore(deps): update platform-native digest to 46f509b (#6540)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 12:56:36 -05:00
renovate[bot]
0d8e39cc2a chore(deps): update ntpclient to v3.2.1 (#6545)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-09 12:46:58 -05:00
Austin
78fa4c5c70 Setup RenovateBot (#6535) 2025-04-09 12:31:40 -05:00
todd-herbert
536b6d87c6 InkHUD support for LilyGo T3S3 E-Paper (#6503)
* Purge an incomplete E-Ink driver

* Use the deep-sleep mode of SSD16XX E-Ink displays

* TwoButton doesn't need to store pin mode

* Fix false positive button presses after light sleep

* E-Ink driver for DEPG0213BNS800

* InkHUD support for LilyGo T3S3 E-paper

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-09 10:41:51 -05:00
Andrik45719
5256ae90dc DIY v1/v1_1 add TCXO_OPTIONAL make it so that the firmware can try both TCXO and XTAL (#6534)
* EBYTE_E22 TCXO_OPTIONAL

* EBYTE_E22

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-09 10:40:38 -05:00
257 changed files with 3667 additions and 587 deletions

View File

@@ -1,29 +0,0 @@
#trunk-ignore-all(yamllint/quoted-strings): required by dependabot syntax check
version: 2
updates:
- package-ecosystem: docker
directory: /.devcontainer
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
- package-ecosystem: docker
directory: /
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
- package-ecosystem: gitsubmodule
directory: /
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
ignore:
- dependency-name: protobufs
- package-ecosystem: github-actions
directory: /.github/workflows
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific

View File

@@ -26,6 +26,11 @@ on:
required: false
type: boolean
default: false
pio_env:
description: PlatformIO environment to build
required: false
type: string
default: native
outputs:
digest:
description: Digest of built image
@@ -90,3 +95,5 @@ jobs:
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job
platforms: ${{ inputs.platform }}
build-args: |
PIO_ENV=${{ inputs.pio_env }}

View File

@@ -5,14 +5,20 @@ concurrency:
on:
# # Triggers the workflow on push but only for the master branch
push:
branches: [master, develop]
branches:
- master
- develop
- event/*
paths-ignore:
- "**.md"
- version.properties
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
pull_request_target:
branches: [master, develop]
branches:
- master
- develop
- event/*
paths-ignore:
- "**.md"
#- "**.yml"
@@ -32,12 +38,12 @@ jobs:
name: Checkout base
- id: jsonStep
run: |
if [[ "${{ github.head_ref }}" == "" ]]; then
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
else
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
fi
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS"
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
outputs:
esp32: ${{ steps.jsonStep.outputs.esp32 }}
@@ -143,9 +149,10 @@ jobs:
secrets: inherit
test-native:
if: ${{ !contains(github.ref_name, 'event/') }}
uses: ./.github/workflows/test_native.yml
docker-debian-amd64:
docker-deb-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -153,7 +160,16 @@ jobs:
runs-on: ubuntu-24.04
push: false
docker-alpine-amd64:
docker-deb-amd64-tft:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
pio_env: native-tft
docker-alp-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
@@ -161,7 +177,16 @@ jobs:
runs-on: ubuntu-24.04
push: false
docker-debian-arm64:
docker-alp-amd64-tft:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
pio_env: native-tft
docker-deb-arm64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -169,7 +194,7 @@ jobs:
runs-on: ubuntu-24.04-arm
push: false
docker-debian-armv7:
docker-deb-armv7:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -177,17 +202,6 @@ jobs:
runs-on: ubuntu-24.04-arm
push: false
after-checks:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
needs: [check]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
gather-artifacts:
permissions:
contents: write
@@ -332,7 +346,7 @@ jobs:
merge-multiple: true
path: ./output/pio-deps-native-tft
- name: Zip linux sources
- name: Zip Linux sources
working-directory: output
run: |
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
@@ -342,7 +356,9 @@ jobs:
- name: Display structure of downloaded files
run: ls -lR
- name: Add linux sources to release
- name: Add Linux sources to GtiHub Release
# Only run when targeting master branch with workflow_dispatch
if: ${{ github.ref_name == 'master' }}
run: |
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip
@@ -400,9 +416,53 @@ jobs:
- name: Display structure of downloaded files
run: ls -lR
- name: Add bins and debug elfs to release
- name: Add bins and debug elfs to GitHub Release
# Only run when targeting master branch with workflow_dispatch
if: ${{ github.ref_name == 'master' }}
run: |
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-firmware:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [release-firmware]
env:
targets: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,stm32
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- uses: actions/download-artifact@v4
with:
pattern: firmware-{${{ env.targets }}}-${{ steps.version.outputs.long }}
merge-multiple: true
path: ./publish
- name: Publish firmware to meshtastic.github.io
uses: peaceiris/actions-gh-pages@v4
env:
# On event/* branches, use the event name as the destination prefix
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
with:
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
external_repository: meshtastic/meshtastic.github.io
publish_branch: master
publish_dir: ./publish
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }}
keep_files: true
user_name: github-actions[bot]
user_email: github-actions[bot]@users.noreply.github.com
commit_message: ${{ steps.version.outputs.long }}
enable_jekyll: true

View File

@@ -46,11 +46,14 @@ jobs:
# Create a PR to bump version when a release is Published
bump-version:
if: ${{ github.event.release.published }}
if: github.event.action == 'published'
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -60,32 +63,44 @@ jobs:
with:
python-version: 3.x
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
id: version
env:
BUILD_LOCATION: local
- name: Bump version.properties
run: >-
bin/bump_version.py
run: |
# Bump version.properties
chmod +x ./bin/bump_version.py
./bin/bump_version.py
- name: Get new release version string
run: |
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
id: new_version
- name: Ensure debian deps are installed
shell: bash
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y devscripts
- name: Update debian changelog
run: >-
debian/ci_changelog.sh
run: |
# Update debian changelog
chmod +x ./debian/ci_changelog.sh
./debian/ci_changelog.sh
- name: Create version.properties pull request
- name: Bump org.meshtastic.meshtasticd.metainfo.xml
run: |
# Bump org.meshtastic.meshtasticd.metainfo.xml
pip install -r bin/bump_metainfo/requirements.txt -q
chmod +x ./bin/bump_metainfo/bump_metainfo.py
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}"
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
- name: Create Bumps pull request
uses: peter-evans/create-pull-request@v7
with:
title: Bump version.properties
base: ${{ github.event.repository.default_branch }}
title: Bump release version
commit-message: automated bumps
add-paths: |
version.properties
debian/changelog
bin/org.meshtastic.meshtasticd.metainfo.xml

View File

@@ -13,7 +13,7 @@ permissions:
jobs:
semgrep-full:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
container:
image: semgrep/semgrep

View File

@@ -6,7 +6,7 @@ permissions: read-all
jobs:
semgrep-diff:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
container:
image: semgrep/semgrep

View File

@@ -1,24 +1,25 @@
version: 0.1
cli:
version: 1.22.12
version: 1.22.15
plugins:
sources:
- id: trunk
ref: v1.6.7
ref: v1.6.8
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- renovate@40.0.6
- prettier@3.5.3
- trufflehog@3.88.23
- yamllint@1.37.0
- trufflehog@3.88.28
- yamllint@1.37.1
- bandit@1.8.3
- terrascan@1.19.9
- trivy@0.61.0
- trivy@0.62.1
- taplo@0.9.3
- ruff@0.11.4
- ruff@0.11.8
- isort@6.0.1
- markdownlint@0.44.0
- oxipng@9.1.4
- oxipng@9.1.5
- svgo@3.3.2
- actionlint@1.7.7
- flake8@7.2.0
@@ -27,7 +28,7 @@ lint:
- shellcheck@0.10.0
- black@25.1.0
- git-diff-check
- gitleaks@8.24.2
- gitleaks@8.25.1
- clang-format@16.0.3
ignore:
- linters: [ALL]

View File

@@ -1,20 +1,21 @@
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
# trunk-ignore-all(trivy/DS002): We must run as root for this container
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-bookworm AS builder
ARG PIO_ENV=native
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
# Install Dependencies
ENV PIP_ROOT_USER_ACTION=ignore
RUN apt-get update && apt-get install --no-install-recommends -y \
curl wget g++ zip git ca-certificates \
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 pkg-config \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
libx11-dev libinput-dev libxkbcommon-x11-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -24,7 +25,7 @@ WORKDIR /tmp/firmware
COPY . /tmp/firmware
# Build
RUN bash ./bin/build-native.sh && \
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
# Fetch web assets
@@ -44,7 +45,9 @@ ENV TZ=Etc/UTC
USER root
RUN apt-get update && apt-get --no-install-recommends -y install \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev \
liborcania2.3 libulfius2.7 libssl3 \
libx11-6 libinput10 libxkbcommon-x11-0 \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \

View File

@@ -4,8 +4,8 @@
| Firmware Version | Supported |
| ---------------- | ------------------ |
| 2.5.x | :white_check_mark: |
| <= 2.4.x | :x: |
| 2.6.x | :white_check_mark: |
| <= 2.5.x | :x: |
## Reporting a Vulnerability

View File

@@ -1,15 +1,16 @@
# trunk-ignore-all(trivy/DS002): We must run as root for this container
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-alpine3.21 AS builder
ARG PIO_ENV=native
ENV PIP_ROOT_USER_ACTION=ignore
RUN apk --no-cache add \
bash g++ libstdc++-dev linux-headers zip git ca-certificates 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 \
&& rm -rf /var/cache/apk/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -21,7 +22,7 @@ COPY . /tmp/firmware
# Add `argp` for musl
ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
RUN bash ./bin/build-native.sh && \
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
# ##### PRODUCTION BUILD #############
@@ -33,11 +34,16 @@ USER root
RUN apk --no-cache add \
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
libx11 libinput libxkbcommon \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \
&& mkdir -p /etc/meshtasticd/ssl
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d
WORKDIR /var/lib/meshtasticd
VOLUME /var/lib/meshtasticd

View File

@@ -2,7 +2,9 @@
[esp32_base]
extends = arduino_base
custom_esp32_kind = esp32
platform = platformio/espressif32@6.10.0
platform =
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
platformio/espressif32@6.10.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
@@ -44,13 +46,20 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.zip
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@^1.4.3
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
lewisxhe/XPowersLib@^0.2.7
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
lib_ignore =
segger_rtt

View File

@@ -1,6 +1,8 @@
[esp32c6_base]
extends = esp32_base
platform = https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
platform =
# Do not renovate until we have switched to pioarduino tagged builds
https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
build_flags =
${arduino_base.build_flags}
-Wall
@@ -23,10 +25,14 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
lewisxhe/XPowersLib@^0.2.7
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
build_src_filter =
${esp32_base.build_src_filter} -<mesh/http>

View File

@@ -16,4 +16,4 @@ build_flags =
lib_ignore =
${esp32_base.lib_ignore}
NimBLE-Arduino
libpax
libpax

View File

@@ -3,4 +3,3 @@ extends = esp32_base
custom_esp32_kind = esp32s3
monitor_speed = 115200

View File

@@ -1,10 +1,14 @@
[nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^10.8.0
platform =
# renovate: datasource=custom.pio depName=platformio/nordicnrf52 packageName=platformio/platform/nordicnrf52
platformio/nordicnrf52@^10.8.0
extends = arduino_base
platform_packages =
; our custom Git version until they merge our PR
# TODO renovate
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf
; Don't renovate toolchain-gccarmnoneeabi
platformio/toolchain-gccarmnoneeabi@~1.90301.0
build_type = debug
@@ -24,8 +28,9 @@ build_src_filter =
lib_deps=
${arduino_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
lib_ignore =
BluetoothOTA
lvgl
lvgl

View File

@@ -6,7 +6,9 @@ build_flags = ${nrf52_base.build_flags}
lib_deps =
${nrf52_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip
${environmental_extra.lib_deps}
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.

View File

@@ -1,6 +1,8 @@
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
[portduino_base]
platform = https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip
framework = arduino
build_src_filter =
@@ -15,18 +17,19 @@ build_src_filter =
+<mesh/raspihttp/>
-<mesh/eth/>
-<modules/esp32>
-<modules/Telemetry/EnvironmentTelemetry.cpp>
-<modules/Telemetry/AirQualityTelemetry.cpp>
-<modules/Telemetry/Sensor>
+<../variants/portduino>
lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
${environmental_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@^1.2.0
https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip
# renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main
https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip
build_flags =
${arduino_base.build_flags}
@@ -42,4 +45,7 @@ build_flags =
-lyaml-cpp
-li2c
-luv
-std=gnu17
-std=c++17
lib_ignore = Adafruit NeoPixel

View File

@@ -1,8 +1,13 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform =
# TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
platform_packages =
# TODO renovate
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -23,5 +28,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0

View File

@@ -1,8 +1,13 @@
; Common settings for rp2040 Processor based targets
; Common settings for rp2350 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform =
# TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
platform_packages =
# TODO renovate
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -20,5 +25,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0

View File

@@ -1,7 +1,11 @@
[stm32_base]
extends = arduino_base
platform = ststm32
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
platform =
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
platformio/ststm32@19.1.0
platform_packages =
# TODO renovate
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
extra_scripts =
${env.extra_scripts}
post:extra_scripts/extra_stm32.py
@@ -35,6 +39,7 @@ debug_tool = stlink
lib_deps =
${env.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=git-refs depName=caveman99-stm32-Crypto packageName=https://github.com/caveman99/Crypto gitBranch=main
https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip
lib_ignore =

View File

@@ -15,6 +15,7 @@ platformioFailed() {
VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short)
PIO_ENV=${1:-native}
OUTDIR=release/
@@ -24,7 +25,7 @@ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
pio pkg update --environment native || platformioFailed
pio run --environment native || platformioFailed
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
pio pkg update --environment "$PIO_ENV" || platformioFailed
pio run --environment "$PIO_ENV" || platformioFailed
cp ".pio/build/$PIO_ENV/program" "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/native-install.* $OUTDIR

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import argparse
import xml.etree.ElementTree as ET
from defusedxml.ElementTree import parse
from datetime import datetime, timezone
# Indent by 2 spaces to align with xml formatting.
def indent(elem, level=0):
i = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
for child in elem:
indent(child, level + 1)
if not child.tail or not child.tail.strip():
child.tail = i
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def main():
parser = argparse.ArgumentParser(
description="Prepend new release entry to metainfo.xml file.")
parser.add_argument("--file", help="Path to the metainfo.xml file",
default="org.meshtastic.meshtasticd.metainfo.xml")
parser.add_argument("version", help="Version string (e.g. 2.6.4)")
parser.add_argument("--date", help="Release date (YYYY-MM-DD), defaults to today",
default=datetime.now(timezone.utc).date().isoformat())
args = parser.parse_args()
tree = parse(args.file)
root = tree.getroot()
releases = root.find('releases')
if releases is None:
raise RuntimeError("<releases> element not found in XML.")
existing_versions = {
release.get('version'): release
for release in releases.findall('release')
}
existing_release = existing_versions.get(args.version)
if existing_release is not None:
if not existing_release.get('date'):
print(f"Version {args.version} found without date. Adding date...")
existing_release.set('date', args.date)
else:
print(
f"Version {args.version} is already present with date, skipping insertion.")
else:
new_release = ET.Element('release', {
'version': args.version,
'date': args.date
})
url = ET.SubElement(new_release, 'url', {'type': 'details'})
url.text = f"https://github.com/meshtastic/firmware/releases?q=tag%3Av{args.version}"
releases.insert(0, new_release)
indent(releases, level=1)
releases.tail = "\n"
print(f"Inserted new release: {args.version}")
tree.write(args.file, encoding='UTF-8', xml_declaration=True)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1 @@
defusedxml==0.7.1

View File

@@ -0,0 +1,11 @@
Lora:
Module: lr1121
CS: 0
IRQ: 6
Reset: 2
Busy: 4
spidev: ch341
DIO3_TCXO_VOLTAGE: 1.8
# USB_Serialnum: 12345678
USB_PID: 0x5512
USB_VID: 0x1A86

View File

@@ -17,8 +17,8 @@ SET "LOGCOUNTER=0"
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
SET "C3=esp32c3"
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core t-watch-s3 tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite"
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
GOTO getopts
:help

View File

@@ -22,7 +22,6 @@ BIGDB_8MB=(
"icarus"
"seeed-xiao-s3"
"tbeam-s3-core"
"t-watch-s3"
"tracksenger"
)
BIGDB_16MB=(
@@ -34,6 +33,7 @@ BIGDB_16MB=(
"m5stack-cores3"
"station-g2"
"t-eth-elite"
"t-watch-s3"
)
S3_VARIANTS=(
"s3"

View File

@@ -0,0 +1,8 @@
[Desktop Entry]
Name=Meshtastic
Comment=Meshtastic App
Exec=meshtasticd
Icon=org.meshtastic.meshtasticd
Terminal=true
Type=Application
Categories=Network;Chat;HamRadio;

View File

@@ -0,0 +1,106 @@
<?xml version='1.0' encoding='UTF-8'?>
<component type="desktop-application">
<id>org.meshtastic.meshtasticd</id>
<name>Meshtastic</name>
<summary>Decentralized mesh communication</summary>
<metadata_license>CC-BY-4.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<developer id="org.meshtastic">
<name>Meshtastic</name>
</developer>
<description>
<p>
Meshtastic is an open source project for creating off-grid, affordable, and resilient communication with LoRa mesh networks.
</p>
</description>
<launchable type="desktop-id">org.meshtastic.meshtasticd.desktop</launchable>
<categories>
<category>Network</category>
<category>Chat</category>
<category>HamRadio</category>
</categories>
<keywords>
<keyword>mesh</keyword>
<keyword>LoRa</keyword>
</keywords>
<recommends>
<control>keyboard</control>
<control>pointing</control>
<control>touch</control>
</recommends>
<requires>
<display_length compare="ge">360</display_length>
</requires>
<branding>
<color type="primary" scheme_preference="light">#97be89</color>
<color type="primary" scheme_preference="dark">#206538</color>
</branding>
<content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
<content_attribute id="social-location">intense</content_attribute>
</content_rating>
<url type="bugtracker">https://github.com/meshtastic/firmware/issues</url>
<url type="homepage">https://meshtastic.org/</url>
<url type="donation">https://opencollective.com/meshtastic</url>
<url type="faq">https://meshtastic.org/docs/software/linux/usage/</url>
<url type="vcs-browser">https://github.com/meshtastic/firmware/</url>
<screenshots>
<screenshot type="default">
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_home_dashboard_dark.webp</image>
<caption>Home Dashboard</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_initial_boot.webp</image>
<caption>Setup</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_node_list_dark.webp</image>
<caption>Nodes List</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_list_dark.webp</image>
<caption>Chats List</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_message_dark.webp</image>
<caption>Messages</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_map_dark.webp</image>
<caption>Map</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_settings_dark.webp</image>
<caption>Settings</caption>
</screenshot>
</screenshots>
<releases>
<release version="2.6.8" date="2025-05-05">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8</url>
</release>
<release version="2.6.7" date="2025-04-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7</url>
</release>
<release version="2.6.6" date="2025-04-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6</url>
</release>
<release version="2.6.5" date="2025-03-30">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5</url>
</release>
<release version="2.6.4" date="2025-03-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4</url>
</release>
</releases>
</component>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512" height="512" viewBox="0 0 512 512" xml:space="preserve">
<desc>Created with Fabric.js 4.6.0</desc>
<defs>
</defs>
<g transform="matrix(1 0 0 1 256 256)" id="xYQ9Gk9Jwpgj_HMOXB3F_" >
<path style="stroke: rgb(213,130,139); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(103,234,148); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-256, -256)" d="M 0 0 L 512 0 L 512 512 L 0 512 z" stroke-linecap="round" />
</g>
<g transform="matrix(1.79 0 0 1.79 313.74 258.36)" id="1xBsk2n9FZp60Rz1O-ceJ" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-250.97, -362.41)" d="M 250.908 330.267 L 193.126 415.005 L 180.938 406.694 L 244.802 313.037 C 246.174 311.024 248.453 309.819 250.889 309.816 C 253.326 309.814 255.606 311.015 256.982 313.026 L 320.994 406.536 L 308.821 414.869 L 250.908 330.267 Z" stroke-linecap="round" />
</g>
<g transform="matrix(1.81 0 0 1.81 145 256.15)" id="KxN7E9YpbyPgz0S4z4Cl6" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-115.14, -528.06)" d="M 87.642 581.398 L 154.757 482.977 L 142.638 474.713 L 75.523 573.134 L 87.642 581.398 Z" stroke-linecap="round" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1 +1 @@
2.6.0
2.5.3

View File

@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [["0x2886", "0x0059"]],
"usb_product": "XIAO-BOOT",
"mcu": "nrf52840",
"variant": "Seeed_Solar_Node",
"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_Solar_Node",
"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/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html",
"vendor": "Seeed Studio"
}

43
boards/crowpanel.json Normal file
View File

@@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "ESP32-S3-WROOM-1-N16R8"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "ESP32-S3-WROOM-1-N16R8 (16 MB Flash, 8 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 524288,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"monitor": {
"speed": 115200
},
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
"vendor": "Espressif"
}

View File

@@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "HT-n5262",
"mcu": "nrf52840",
"variant": "heltec_mesh_pocket",
"variants_dir": "variants",
"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",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Heltec nrf (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://heltec.org/project/meshpocket/",
"vendor": "Heltec"
}

View File

@@ -24,16 +24,16 @@
"mcu": "esp32s3",
"variant": "t-watch-s3"
},
"connectivity": ["wifi", "bluetooth"],
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino"],
"name": "LilyGo T-Watch 2020 V3",
"upload": {
"flash_size": "8MB",
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"maximum_size": 16777216,
"require_upload_port": true,
"use_1200bps_touch": true,
"wait_for_upload_port": true,

BIN
data/boot/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

8
debian/changelog vendored
View File

@@ -1,9 +1,13 @@
meshtasticd (2.5.22.0) UNRELEASED; urgency=medium
meshtasticd (2.6.8.0) UNRELEASED; urgency=medium
[ Austin Lane ]
* Initial packaging
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
-- Austin Lane <github-actions[bot]@users.noreply.github.com> Wed, 05 Feb 2025 01:10:33 +0000
[ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Tue, 06 May 2025 01:32:49 +0000

View File

@@ -5,8 +5,8 @@ export PLATFORMIO_PACKAGES_DIR=pio/packages
export PLATFORMIO_CORE_DIR=pio/core
# Download libraries to `pio`
platformio pkg install -e native
platformio pkg install -e native -t platformio/tool-scons@4.40502.0
platformio pkg install -e native-tft
platformio pkg install -e native-tft -t platformio/tool-scons@4.40502.0
# Compress `pio` directory to prevent dh_clean from sanitizing it
tar -cf pio.tar pio/
rm -rf pio

5
debian/control vendored
View File

@@ -21,7 +21,10 @@ Build-Depends: debhelper-compat (= 13),
openssl,
libssl-dev,
libulfius-dev,
liborcania-dev
liborcania-dev,
libx11-dev,
libinput-dev,
libxkbcommon-x11-dev
Standards-Version: 4.6.2
Homepage: https://github.com/meshtastic/firmware
Rules-Requires-Root: no

View File

@@ -1,8 +1,8 @@
.pio/build/native/meshtasticd usr/sbin
.pio/build/native-tft/meshtasticd usr/sbin
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/meshtasticd.service lib/systemd/system
bin/meshtasticd.service lib/systemd/system
web/* usr/share/meshtasticd/web
web/* usr/share/meshtasticd/web

4
debian/rules vendored
View File

@@ -26,7 +26,7 @@ override_dh_auto_build:
mkdir -p web && tar -xf web.tar -C web
gunzip web/ -r
# Build with platformio
$(PIO_ENV) platformio run -e native
$(PIO_ENV) platformio run -e native-tft
# Move the binary and default config to the correct name
mv .pio/build/native/program .pio/build/native/meshtasticd
mv .pio/build/native-tft/program .pio/build/native-tft/meshtasticd
cp bin/config-dist.yaml bin/config.yaml

View File

@@ -42,6 +42,10 @@ BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(liborcania)
BuildRequires: pkgconfig(libyder)
BuildRequires: pkgconfig(libulfius)
# TFT components:
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(xkbcommon-x11)
%description
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
@@ -55,12 +59,12 @@ tar -xf %{SOURCE1} -C web
gzip -dr web
%build
# Use the “native” environment from platformio to build a Linux binary
platformio run -e native
# Use the “native-tft” environment from platformio to build a Linux binary
platformio run -e native-tft
%install
mkdir -p %{buildroot}%{_sbindir}
install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml

View File

@@ -50,18 +50,26 @@ build_flags = -Wno-missing-field-initializers
-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
#-DBUILD_EPOCH=$UNIX_TIME
#-D OLED_PL=1
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/0119501e9983bd894830b02f545c377ee08d66fe.zip
# renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton
mathertel/OneButton@2.6.1
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip
# renovate: datasource=git-refs depName=meshtastic-ArduinoThread packageName=https://github.com/meshtastic/ArduinoThread gitBranch=master
https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip
# renovate: datasource=custom.pio depName=Nanopb packageName=nanopb/library/Nanopb
nanopb/Nanopb@0.4.91
# renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32
erriez/ErriezCRC32@1.0.1
; Used for the code analysis in PIO Home / Inspect
@@ -77,6 +85,7 @@ check_flags =
framework = arduino
lib_deps =
${env.lib_deps}
# renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL
end2endzone/NonBlockingRTTTL@1.3.0
build_flags = ${env.build_flags} -Os
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
@@ -84,57 +93,99 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/nic
; Common libs for communicating over TCP/IP networks such as MQTT
[networking_base]
lib_deps =
knolleary/PubSubClient@2.8
arduino-libraries/NTPClient@3.1.0
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
thingsboard/TBPubSubClient@2.12.1
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
arduino-libraries/NTPClient@3.2.1
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
arcao/Syslog@2.0.0
[radiolib_base]
lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
jgromes/RadioLib@7.1.2
[device-ui_base]
lib_deps =
https://github.com/meshtastic/device-ui/archive/56ef8db7eb4dda44dc0c1ec5828044debbbc6d33.zip
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/09b1780c8f944cffbc18a8ec5713cdfe03278503.zip
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
[environmental_base]
lib_deps =
adafruit/Adafruit BusIO@1.17.0
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
adafruit/Adafruit BusIO@1.17.1
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
adafruit/Adafruit Unified Sensor@1.1.15
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
adafruit/Adafruit BMP280 Library@2.6.8
# renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library
adafruit/Adafruit BMP085 Library@1.2.4
adafruit/Adafruit BME280 Library@2.2.4
adafruit/Adafruit BMP3XX Library@2.1.6
# 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
# 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
adafruit/Adafruit INA260 Library@1.5.2
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
adafruit/Adafruit INA219@1.2.3
adafruit/Adafruit MAX1704X@1.0.3
adafruit/Adafruit SHTC3 Library@1.0.1
adafruit/Adafruit LPS2X@2.0.6
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor
adafruit/Adafruit PM25 AQI Sensor@1.2.0
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
adafruit/Adafruit MPU6050@2.2.6
# 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
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
adafruit/Adafruit LSM6DS@4.7.4
adafruit/Adafruit VEML7700 Library@2.1.6
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
adafruit/Adafruit TSL2591 Library@1.4.5
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0
ClosedCube OPT3001@1.1.2
# 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
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip
boschsensortec/BME68x Sensor Library@1.1.40407
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.2.40408
# renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
mprograms/QMC5883LCompass@1.2.3
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
robtillaart/INA226@0.6.4
; Health Sensor Libraries
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
; (not included in native / portduino)
[environmental_extra]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.1
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
ClosedCube OPT3001@1.1.2
# renovate: datasource=git-refs depName=Bosch BSEC2 packageName=https://github.com/meshtastic/Bosch-BSEC2-Library gitBranch=extra_script
https://github.com/meshtastic/Bosch-BSEC2-Library/archive/e16952dfe5addd4287e1eb8c4f6ecac0fa3dd3de.zip
# 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

79
renovate.json Normal file
View File

@@ -0,0 +1,79 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
":dependencyDashboard",
":semanticCommitTypeAll(chore)",
":ignoreModulesAndTests",
"group:recommended",
"replacements:all",
"workarounds:all"
],
"forkProcessing": "enabled",
"ignoreDeps": ["protobufs"],
"git-submodules": {
"enabled": true
},
"pip_requirements": {
"fileMatch": ["bin/bump_metainfo/requirements.txt"]
},
"commitMessageTopic": "{{depName}}",
"labels": ["dependencies"],
"customDatasources": {
"pio": {
"description": "PlatformIO Registry",
"defaultRegistryUrlTemplate": "https://api.registry.platformio.org/v3/packages/{{packageName}}",
"format": "json",
"transformTemplates": [
"{\"releases\": [$map($.versions, function($v) { { \"version\": $v.name, \"releaseTimestamp\": $v.released_at } })], \"homepage\": $encodeUrl($join([\"https://registry.platformio.org/\",$.type,\"/\",$.owner.username,\"/\",$.name])) }"
]
}
},
"customManagers": [
{
"customType": "regex",
"description": "Match meshtastic/web version",
"fileMatch": ["bin/web.version"],
"matchStrings": ["(?<currentValue>.+)$"],
"datasourceTemplate": "github-releases",
"depNameTemplate": "meshtastic/web",
"versioningTemplate": "semver-coerced"
},
{
"customType": "regex",
"description": "Match normal PIO dependencies",
"fileMatch": [".*\\.ini$"],
"matchStrings": [
"# renovate: datasource=(?<datasource>.*?)(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?.+?@(?<currentValue>.+?)\\s"
],
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
},
{
"customType": "regex",
"description": "Match PIO zipped dependencies with github tag ref",
"fileMatch": [".*\\.ini$"],
"matchStrings": [
"# renovate: datasource=github-tags(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?https:\/\/.+?archive\/(?<currentValue>.+?).zip\\s"
],
"datasourceTemplate": "github-tags",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
},
{
"customType": "regex",
"description": "Match PIO zipped dependencies with git commit ref",
"fileMatch": [".*\\.ini$"],
"matchStrings": [
"# renovate: datasource=git-refs(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\sgitBranch=(?<gitBranch>.+?)\\s+?https:\/\/.+?archive\/(?<currentDigest>.+?).zip\\s"
],
"datasourceTemplate": "git-refs",
"currentValueTemplate": "{{{gitBranch}}}",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}"
}
],
"packageRules": [
{
"matchDepNames": ["meshtastic/device-ui"],
"reviewers": ["mverch67"],
"changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}"
}
]
}

View File

@@ -255,7 +255,7 @@ int32_t ButtonThread::runOnce()
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
#if defined(RAK_4631)
#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
case 5:
if (accelerometerThread) {

View File

@@ -12,13 +12,14 @@
#include "SPILock.h"
#include "configuration.h"
#ifdef HAS_SDCARD
// Software SPI is used by MUI so disable SD card here until it's also implemented
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
#include <SD.h>
#include <SPI.h>
#ifdef SDCARD_USE_SPI1
SPIClass SPI1(HSPI);
#define SDHandler SPI1
SPIClass SPI_HSPI(HSPI);
#define SDHandler SPI_HSPI
#else
#define SDHandler SPI
#endif
@@ -306,7 +307,7 @@ void fsInit()
*/
void setupSDCard()
{
#ifdef HAS_SDCARD
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
concurrency::LockGuard g(spiLock);
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {

View File

@@ -76,23 +76,47 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if __has_include(<Adafruit_INA219.h>)
INA219Sensor ina219Sensor;
INA226Sensor ina226Sensor;
INA260Sensor ina260Sensor;
INA3221Sensor ina3221Sensor;
#else
NullSensor ina219Sensor;
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if __has_include(<INA226.h>)
INA226Sensor ina226Sensor;
#else
NullSensor ina226Sensor;
#endif
#if __has_include(<Adafruit_INA260.h>)
INA260Sensor ina260Sensor;
#else
NullSensor ina260Sensor;
#endif
#if __has_include(<INA3221.h>)
INA3221Sensor ina3221Sensor;
#else
NullSensor ina3221Sensor;
#endif
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL)
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
#include <utility>
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
#if __has_include(<Adafruit_MAX1704X.h>)
MAX17048Sensor max17048Sensor;
#else
NullSensor max17048Sensor;
#endif
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT
RAK9154Sensor rak9154Sensor;
#endif
@@ -203,7 +227,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
*/
virtual int getBatteryPercent() override
{
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return rak9154Sensor.getBusBatteryPercent();
}
@@ -248,15 +272,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasRAK()) {
return getRAKVoltage();
}
#endif
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
return getINAVoltage();
}
@@ -426,8 +448,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// we can't be smart enough to say 'full'?
virtual bool isCharging() override
{
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \
!defined(HAS_PMU)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
}
@@ -435,7 +456,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
#ifdef EXT_CHRG_DETECT
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
#else
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) && \
!defined(DISABLE_INA_CHARGING_DETECTION)
if (hasINA()) {
// get current flow from INA sensor - negative value means power flowing into the battery
@@ -450,6 +471,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
return isBatteryConnect() && isVbusIn();
#endif
#endif
// by default, we check the battery voltage only
return isVbusIn();
}
private:
@@ -480,7 +503,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {

View File

@@ -19,7 +19,7 @@
#include "sleep.h"
#include "target_specific.h"
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
#if HAS_WIFI && !defined(ARCH_PORTDUINO) || defined(MESHTASTIC_EXCLUDE_WIFI)
#include "mesh/wifi/WiFiAPClient.h"
#endif
@@ -269,9 +269,6 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup()
{
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
bool hasPower = isPowered();
LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0);
@@ -383,6 +380,12 @@ void PowerFSM_setup()
// See: https://github.com/meshtastic/firmware/issues/1071
// Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated
// through the modules
#if HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) {
powerFSM.add_timed_transition(&stateNB, &stateLS,
Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL,
@@ -400,7 +403,9 @@ void PowerFSM_setup()
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
NULL, "Screen-on timeout");
}
#else
#endif // HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
#else // (not) ARCH_ESP32
// If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
@@ -409,4 +414,4 @@ void PowerFSM_setup()
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state
}
#endif
#endif

View File

@@ -570,6 +570,19 @@ bool GPS::setup()
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
_serial_gps->write("$PMTK886,1*29\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1010D) {
// PA1010D is used in the Pimoroni GPS board.
// Enable all constellations.
_serial_gps->write("$PMTK353,1,1,1,1,1*2A\r\n");
// Above command will reset the GPS and takes longer before it will accept new commands
delay(1000);
// Only ask for RMC and GGA (GNRMC and GNGGA)
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
delay(250);
// Enable SBAS / WAAS
_serial_gps->write("$PMTK301,2*2E\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1616S) {
// PA1616S is used in some GPS breakout boards from Adafruit
// PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here.
@@ -810,13 +823,6 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
powerState = newState;
LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
#ifdef HELTEC_MESH_NODE_T114
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
_serial_gps->begin(serialSpeeds[speedSelect]);
} else if ((newState == GPS_OFF || newState == GPS_HARDSLEEP) && (oldState != GPS_OFF && oldState != GPS_HARDSLEEP)) {
_serial_gps->end();
}
#endif
switch (newState) {
case GPS_ACTIVE:
case GPS_IDLE:
@@ -1245,9 +1251,11 @@ GnssModel_t GPS::probe(int serialSpeed)
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
{"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B},
{"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}};
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};

View File

@@ -27,6 +27,7 @@ typedef enum {
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B,
GNSS_MODEL_MTK_PA1010D,
GNSS_MODEL_MTK_PA1616S,
GNSS_MODEL_AG3335,
GNSS_MODEL_AG3352,

View File

@@ -181,7 +181,6 @@ bool EInkDisplay::connect()
// Start HSPI
hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
// VExt already enabled in setup()
// RTC GPIO hold disabled in setup()
@@ -218,6 +217,21 @@ bool EInkDisplay::connect()
adafruitDisplay->setRotation(1);
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
}
#elif defined(HELTEC_MESH_POCKET)
{
spi1 = &SPI1;
spi1->begin();
// VExt already enabled in setup()
// RTC GPIO hold disabled in setup()
// Create GxEPD2 objects
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *spi1);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// Init GxEPD2
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
}
#endif
return true;

View File

@@ -73,6 +73,10 @@ class EInkDisplay : public OLEDDisplay
SPIClass *hspi = NULL;
#endif
#if defined(HELTEC_MESH_POCKET)
SPIClass *spi1 = NULL;
#endif
private:
// FIXME quick hack to limit drawing to a very slow rate
uint32_t lastDrawMsec = 0;

View File

@@ -1104,7 +1104,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
char usersString[20];
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
@@ -1545,7 +1545,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \
defined(RAK14014) || defined(HX8357_CS)
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
@@ -1751,7 +1751,7 @@ void Screen::setup()
// flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) {
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
#elif defined(USE_ST7789)
static_cast<ST7789Spi *>(dispdev)->flipScreenVertically();
@@ -1796,7 +1796,9 @@ void Screen::setup()
powerStatusObserver.observe(&powerStatus->onNewStatus);
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
#if !MESHTASTIC_EXCLUDE_ADMIN
adminMessageObserver.observe(adminModule);
#endif
if (textMessageModule)
textMessageObserver.observe(textMessageModule);
if (inputBroker)
@@ -2490,7 +2492,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
@@ -2502,7 +2504,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
@@ -2517,7 +2519,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
} else {
// TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
@@ -2838,9 +2840,6 @@ int Screen::handleInputEvent(const InputEvent *event)
int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
{
// Note: only selected admin messages notify this observer
// If you wish to handle a new type of message, you should modify AdminModule.cpp first
switch (arg->which_payload_variant) {
// Node removed manually (i.e. via app)
case meshtastic_AdminMessage_remove_by_nodenum_tag:
@@ -2857,4 +2856,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN

View File

@@ -65,8 +65,8 @@
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) || \
defined(ILI9488_CS) && !defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28

View File

@@ -120,6 +120,303 @@ static void rak14014_tpIntHandle(void)
_rak14014_touch_int = true;
}
#elif defined(ST72xx_DE)
#include <LovyanGFX.hpp>
#include <TCA9534.h>
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
TCA9534 ioex;
class LGFX : public lgfx::LGFX_Device
{
lgfx::Bus_RGB _bus_instance;
lgfx::Panel_RGB _panel_instance;
lgfx::Touch_GT911 _touch_instance;
public:
const uint16_t screenWidth = TFT_WIDTH;
const uint16_t screenHeight = TFT_HEIGHT;
bool init_impl(bool use_reset, bool use_clear) override
{
ioex.attach(Wire);
ioex.setDeviceAddress(0x18);
ioex.config(1, TCA9534::Config::OUT);
ioex.config(2, TCA9534::Config::OUT);
ioex.config(3, TCA9534::Config::OUT);
ioex.config(4, TCA9534::Config::OUT);
ioex.output(1, TCA9534::Level::H);
ioex.output(3, TCA9534::Level::L);
ioex.output(4, TCA9534::Level::H);
pinMode(1, OUTPUT);
digitalWrite(1, LOW);
ioex.output(2, TCA9534::Level::L);
delay(20);
ioex.output(2, TCA9534::Level::H);
delay(100);
pinMode(1, INPUT);
return LGFX_Device::init_impl(use_reset, use_clear);
}
LGFX(void)
{
{
auto cfg = _panel_instance.config();
cfg.memory_width = screenWidth;
cfg.memory_height = screenHeight;
cfg.panel_width = screenWidth;
cfg.panel_height = screenHeight;
cfg.offset_x = 0;
cfg.offset_y = 0;
cfg.offset_rotation = 0;
_panel_instance.config(cfg);
}
{
auto cfg = _panel_instance.config_detail();
cfg.use_psram = 0;
_panel_instance.config_detail(cfg);
}
{
auto cfg = _bus_instance.config();
cfg.panel = &_panel_instance;
cfg.pin_d0 = ST72xx_B0; // B0
cfg.pin_d1 = ST72xx_B1; // B1
cfg.pin_d2 = ST72xx_B2; // B2
cfg.pin_d3 = ST72xx_B3; // B3
cfg.pin_d4 = ST72xx_B4; // B4
cfg.pin_d5 = ST72xx_G0; // G0
cfg.pin_d6 = ST72xx_G1; // G1
cfg.pin_d7 = ST72xx_G2; // G2
cfg.pin_d8 = ST72xx_G3; // G3
cfg.pin_d9 = ST72xx_G4; // G4
cfg.pin_d10 = ST72xx_G5; // G5
cfg.pin_d11 = ST72xx_R0; // R0
cfg.pin_d12 = ST72xx_R1; // R1
cfg.pin_d13 = ST72xx_R2; // R2
cfg.pin_d14 = ST72xx_R3; // R3
cfg.pin_d15 = ST72xx_R4; // R4
cfg.pin_henable = ST72xx_DE;
cfg.pin_vsync = ST72xx_VSYNC;
cfg.pin_hsync = ST72xx_HSYNC;
cfg.pin_pclk = ST72xx_PCLK;
cfg.freq_write = 13000000;
#ifdef ST7265_HSYNC_POLARITY
cfg.hsync_polarity = ST7265_HSYNC_POLARITY;
cfg.hsync_front_porch = ST7265_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = ST7265_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = ST7265_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = ST7265_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = ST7265_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = ST7265_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = ST7265_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = ST7265_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
#ifdef ST7262_HSYNC_POLARITY
cfg.hsync_polarity = ST7262_HSYNC_POLARITY;
cfg.hsync_front_porch = ST7262_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = ST7262_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = ST7262_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = ST7262_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = ST7262_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = ST7262_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = ST7262_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = ST7262_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
#ifdef SC7277_HSYNC_POLARITY
cfg.hsync_polarity = SC7277_HSYNC_POLARITY;
cfg.hsync_front_porch = SC7277_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = SC7277_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = SC7277_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = SC7277_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = SC7277_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = SC7277_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = SC7277_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = SC7277_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
_bus_instance.config(cfg);
}
_panel_instance.setBus(&_bus_instance);
{
auto cfg = _touch_instance.config();
cfg.x_min = 0;
cfg.x_max = TFT_WIDTH;
cfg.y_min = 0;
cfg.y_max = TFT_HEIGHT;
cfg.pin_int = -1;
cfg.pin_rst = -1;
cfg.bus_shared = true;
cfg.offset_rotation = 0;
cfg.i2c_port = 0;
cfg.i2c_addr = 0x5D;
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#elif defined(ILI9488_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ILI9488 driver chip
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ILI9488 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_GT911 _touch_instance;
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
// configure SPI
cfg.spi_host = ILI9488_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = ILI9488_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = ILI9488_SDA; // Set SPI MOSI pin number
cfg.pin_miso = ILI9488_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = ILI9488_RS; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{ // Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
cfg.pin_cs = ILI9488_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable)
// The following setting values are general initial values for each panel, so please comment out any
// unknown items and try them.
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
// ST7735 or ILI9163.
// cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
// cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
_panel_instance.config(cfg);
}
#ifdef ILI9488_BL
// Set the backlight control
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
cfg.pin_bl = ILI9488_BL; // Pin number to which the backlight is connected
cfg.invert = false; // true to invert the brightness of the backlight
// cfg.freq = 44100; // PWM frequency of backlight
// cfg.pwm_channel = 1; // PWM channel number to use
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
#endif
#if HAS_TOUCHSCREEN
// Configure settings for touch screen control.
{
auto cfg = _touch_instance.config();
cfg.pin_cs = -1;
cfg.x_min = 0;
cfg.x_max = TFT_HEIGHT - 1;
cfg.y_min = 0;
cfg.y_max = TFT_WIDTH - 1;
cfg.pin_int = SCREEN_TOUCH_INT;
#ifdef SCREEN_TOUCH_RST
cfg.pin_rst = SCREEN_TOUCH_RST;
#endif
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
// cfg.freq = 2500000;
// I2C
cfg.i2c_port = TOUCH_I2C_PORT;
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
#ifdef SCREEN_TOUCH_USE_I2C1
cfg.pin_sda = I2C_SDA1;
cfg.pin_scl = I2C_SCL1;
#else
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
#endif
// cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#elif defined(ST7789_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
@@ -129,7 +426,7 @@ class LGFX : public lgfx::LGFX_Device
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
#if HAS_TOUCHSCREEN
#ifdef T_WATCH_S3
#if defined(T_WATCH_S3) || defined(ELECROW)
lgfx::Touch_FT5x06 _touch_instance;
#else
lgfx::Touch_GT911 _touch_instance;
@@ -171,16 +468,22 @@ class LGFX : public lgfx::LGFX_Device
// The following setting values are general initial values for each panel, so please comment out any
// unknown items and try them.
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
@@ -217,6 +520,9 @@ class LGFX : public lgfx::LGFX_Device
cfg.y_min = 0;
cfg.y_max = TFT_WIDTH - 1;
cfg.pin_int = SCREEN_TOUCH_INT;
#ifdef SCREEN_TOUCH_RST
cfg.pin_rst = SCREEN_TOUCH_RST;
#endif
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
// cfg.freq = 2500000;
@@ -640,7 +946,7 @@ static LGFX *tft = nullptr;
#endif
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
#include "SPILock.h"
#include "TFTDisplay.h"
#include <SPI.h>

View File

@@ -21,7 +21,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};

View File

@@ -1 +0,0 @@
#include "./DEPG0154BNS800.h"

View File

@@ -1,34 +0,0 @@
/*
E-Ink display driver
- DEPG0154BNS800
- Manufacturer: DKE
- Size: 1.54 inch
- Resolution: 152px x 152px
- Flex connector marking: FPC7525
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class DEPG0154BNS800 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 152;
static constexpr uint32_t height = 152;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL);
public:
DEPG0154BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,132 @@
#include "./DEPG0213BNS800.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Describes the operation performed when a "fast refresh" is performed
// Source: Modified from GxEPD2 (GxEPD2_213_BN)
static const uint8_t LUT_FAST[] = {
// 1 2 3
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2B (Existing black pixels)
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2W (New white pixels)
0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2B (New black pixels)
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2W (Existing white pixels)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VCOM
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 1. Any pixels changing W2B or B2W. Two medium taps.
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2. All pixels. One short tap.
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3. Cooldown
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, //
};
// How strongly the pixels are pulled and pushed
void DEPG0213BNS800::configVoltages()
{
switch (updateType) {
case FAST:
// Reference: display datasheet, GxEPD1
sendCommand(0x03); // Gate voltage
sendData(0x17); // VGH: 20V
// Reference: display datasheet, GxEPD1
sendCommand(0x04); // Source voltage
sendData(0x41); // VSH1: 15V
sendData(0x00); // VSH2: NA
sendData(0x32); // VSL: -15V
// GxEPD1 sets this at -1.2V, but that seems to be drive the pixels very hard
sendCommand(0x2C); // VCOM voltage
sendData(0x08); // VCOM: -0.2V
break;
case FULL:
default:
// From OTP memory
break;
}
}
// Load settings about how the pixels are moved from old state to new state during a refresh
// - manually specified,
// - or with stored values from displays OTP memory
void DEPG0213BNS800::configWaveform()
{
switch (updateType) {
case FAST:
sendCommand(0x3C); // Border waveform:
sendData(0x80); // VSS
sendCommand(0x32); // Write LUT register from MCU:
sendData(LUT_FAST, sizeof(LUT_FAST)); // (describes operation for a FAST refresh)
break;
case FULL:
default:
// From OTP memory
break;
}
}
// Describes the sequence of events performed by the displays controller IC during a refresh
// Includes "power up", "load settings from memory", "update the pixels", etc
void DEPG0213BNS800::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xCF); // Differential, use manually loaded waveform
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Non-differential, load waveform from OTP
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void DEPG0213BNS800::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 500); // At least 500ms, then poll every 50ms
case FULL:
default:
return beginPolling(100, 3500); // At least 3500ms, then poll every 100ms
}
}
// For this display, we do not need to re-write the new image.
// We're overriding SSD16XX::finalizeUpdate to make this small optimization.
// The display does also work just fine with the generic SSD16XX method, though.
void DEPG0213BNS800::finalizeUpdate()
{
// Put a copy of the image into the "old memory".
// Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place
// We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc.
if (updateType != FULL) {
// writeNewImage(); // Not required for this display
writeOldImage();
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,44 @@
/*
E-Ink display driver
- DEPG0213BNS800
- Manufacturer: DKE
- Size: 2.13 inch
- Resolution: 122px x 250px
- Flex connector marking: FPC-7528B
Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs.
DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead.
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class DEPG0213BNS800 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
DEPG0213BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
protected:
void configVoltages() override;
void configWaveform() override;
void configUpdateSequence() override;
void detachFromUpdate() override;
void finalizeUpdate() override; // Only overriden for a slight optimization
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -116,5 +116,10 @@ void DEPG0290BNS800::finalizeUpdate()
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,68 @@
#include "./LCMEN2R13ECC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Map the display controller IC's output to the connected panel
void LCMEN2R13ECC1::configScanning()
{
// "Driver output control"
sendCommand(0x01);
sendData(0xF9);
sendData(0x00);
sendData(0x00);
// To-do: delete this method?
// Values set here might be redundant: F9, 00, 00 seems to be default
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
// the controller IC's OTP memory, when the update procedure begins.
void LCMEN2R13ECC1::configWaveform()
{
switch (updateType) {
case FAST:
sendCommand(0x3C); // Border waveform:
sendData(0x85);
break;
case FULL:
default:
// From OTP memory
break;
}
}
void LCMEN2R13ECC1::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Will load LUT from OTP memory
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void LCMEN2R13ECC1::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 800); // At least 500ms for fast refresh
case FULL:
default:
return beginPolling(100, 2500); // At least 2 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,41 @@
/*
E-Ink display driver
- SSD1680
- Manufacturer: WISEVAST
- Size: 2.13 inch
- Resolution: 122px x 255px
- Flex connector marking: Soldering connector, no connector is needed
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class LCMEN2R13ECC1 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
protected:
virtual void configScanning() override;
virtual void configWaveform() override;
virtual void configUpdateSequence() override;
void detachFromUpdate() override;
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -1,9 +1,11 @@
#include "./LCMEN2R13EFC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./LCMEN2R13EFC1.h"
#include <assert.h>
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
// Look up table: fast refresh, common electrode
@@ -42,11 +44,10 @@ static const uint8_t LUT_FAST_BW[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
};
// Look up table: fash refresh, pixels which change from white to black
// Look up table: fast refresh, pixels which change from white to black
static const uint8_t LUT_FAST_WB[] = {
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x43, 0x02, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
@@ -55,7 +56,7 @@ static const uint8_t LUT_FAST_WB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
};
// Look up table: fash refresh, pixels which remain black
// Look up table: fast refresh, pixels which remain black
static const uint8_t LUT_FAST_BB[] = {
0x01, 0x06, 0x03, 0x42, 0x41, 0x01, 0x01, //
0x01, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, //
@@ -151,6 +152,9 @@ void LCMEN213EFC1::reset()
void LCMEN213EFC1::sendCommand(const uint8_t command)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -158,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::sendData(uint8_t data)
@@ -167,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data)
void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -184,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::configFull()

View File

@@ -1,6 +1,9 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./SSD16XX.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX)
@@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::sendData(uint8_t data)
@@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::configFullscreen()
@@ -242,5 +255,18 @@ void SSD16XX::finalizeUpdate()
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
// Enter a lower-power state
// May only save a few µA..
void SSD16XX::deepSleep()
{
sendCommand(0x10); // Enter deep sleep
sendData(0x01); // Mode 1: preserve image RAM
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -44,6 +44,7 @@ class SSD16XX : public EInk
virtual void detachFromUpdate();
virtual bool isUpdateDone() override;
virtual void finalizeUpdate() override;
virtual void deepSleep();
protected:
uint8_t bufferOffsetX = 0; // In bytes. Panel x=0 does not always align with controller x=0. Quirky internal wiring?

View File

@@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations
#include "configuration.h"
#include "SPILock.h"
#include "SafeFile.h"
namespace NicheGraphics
@@ -46,6 +47,9 @@ template <typename T> class FlashData
public:
static bool load(T *data, const char *label)
{
// Take firmware's SPI lock
concurrency::LockGuard guard(spiLock);
// Set false if we run into issues
bool okay = true;
@@ -103,14 +107,18 @@ template <typename T> class FlashData
return okay;
}
// Save module's custom data (settings?) to flash. Does use protobufs
// Save module's custom data (settings?) to flash. Doesn't use protobufs
// Takes the firmware's SPI lock, in case the files are stored on SD card
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
static void save(T *data, const char *label)
{
// Get a filename based on the label
std::string filename = getFilename(label);
#ifdef FSCom
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
@@ -119,10 +127,10 @@ template <typename T> class FlashData
// Calculate a hash of the data
uint32_t hash = getHash(data);
spiLock->lock();
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
// f.flush();
spiLock->unlock();
bool writeSucceeded = f.close();
@@ -135,6 +143,32 @@ template <typename T> class FlashData
}
};
// Erase contents of the NicheGraphics data directory
inline void clearFlashData()
{
// Take firmware's SPI lock, in case the files are stored on SD card
concurrency::LockGuard guard(spiLock);
#ifdef FSCom
File dir = FSCom.open("/NicheGraphics"); // Open the directory
File file = dir.openNextFile(); // Attempt to open the first file in the directory
// While the directory still contains files
while (file) {
std::string path = "/NicheGraphics/";
path += file.name();
LOG_DEBUG("Erasing %s", path.c_str());
file.close();
FSCom.remove(path.c_str());
file = dir.openNextFile();
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
} // namespace NicheGraphics
#endif

View File

@@ -11,10 +11,19 @@ InkHUD::LogoApplet::LogoApplet() : concurrency::OSThread("LogoApplet")
OSThread::setIntervalFromNow(8 * 1000UL);
OSThread::enabled = true;
textLeft = "";
textRight = "";
textTitle = xstr(APP_VERSION_SHORT);
fontTitle = fontSmall;
// During onboarding, show the default short name as well as the version string
// This behavior assists manufacturers during mass production, and should not be modified without good reason
if (!settings->tips.safeShutdownSeen) {
fontTitle = fontLarge;
textLeft = xstr(APP_VERSION_SHORT);
textRight = owner.short_name;
textTitle = "Meshtastic";
} else {
fontTitle = fontSmall;
textLeft = "";
textRight = "";
textTitle = xstr(APP_VERSION_SHORT);
}
bringToForeground();
// This is then drawn with a FULL refresh by Renderer::begin

View File

@@ -3,11 +3,13 @@
#include "./Events.h"
#include "RTC.h"
#include "modules/AdminModule.h"
#include "modules/TextMessageModule.h"
#include "sleep.h"
#include "./Applet.h"
#include "./SystemApplet.h"
#include "graphics/niche/FlashData.h"
using namespace NicheGraphics;
@@ -25,6 +27,9 @@ void InkHUD::Events::begin()
deepSleepObserver.observe(&notifyDeepSleep);
rebootObserver.observe(&notifyReboot);
textMessageObserver.observe(textMessageModule);
#if !MESHTASTIC_EXCLUDE_ADMIN
adminMessageObserver.observe(adminModule);
#endif
#ifdef ARCH_ESP32
lightSleepObserver.observe(&notifyLightSleep);
#endif
@@ -117,8 +122,13 @@ int InkHUD::Events::beforeReboot(void *unused)
sa->onReboot();
}
inkhud->persistence->saveSettings();
inkhud->persistence->saveLatestMessage();
// Save settings to flash, or erase if factory reset in progress
if (!eraseOnReboot) {
inkhud->persistence->saveSettings();
inkhud->persistence->saveLatestMessage();
} else {
NicheGraphics::clearFlashData();
}
// Note: no forceUpdate call here
// We don't have any final screen to draw, although LogoApplet::onReboot did already display a "rebooting" screen
@@ -171,6 +181,23 @@ int InkHUD::Events::onReceiveTextMessage(const meshtastic_MeshPacket *packet)
return 0; // Tell caller to continue notifying other observers. (No reason to abort this event)
}
int InkHUD::Events::onAdminMessage(const meshtastic_AdminMessage *message)
{
switch (message->which_payload_variant) {
// Factory reset
// Two possible messages. One preserves BLE bonds, other wipes. Both should clear InkHUD data.
case meshtastic_AdminMessage_factory_reset_device_tag:
case meshtastic_AdminMessage_factory_reset_config_tag:
eraseOnReboot = true;
break;
default:
break;
}
return 0; // Tell caller to continue notifying other observers. (No reason to abort this event)
}
#ifdef ARCH_ESP32
// Callback for lightSleepObserver
// Make sure the display is not partway through an update when we begin light sleep

View File

@@ -33,6 +33,7 @@ class Events
int beforeDeepSleep(void *unused); // Prepare for shutdown
int beforeReboot(void *unused); // Prepare for reboot
int onReceiveTextMessage(const meshtastic_MeshPacket *packet); // Store most recent text message
int onAdminMessage(const meshtastic_AdminMessage *message); // Handle incoming admin messages
#ifdef ARCH_ESP32
int beforeLightSleep(void *unused); // Prepare for light sleep
#endif
@@ -52,10 +53,17 @@ class Events
CallbackObserver<Events, const meshtastic_MeshPacket *> textMessageObserver =
CallbackObserver<Events, const meshtastic_MeshPacket *>(this, &Events::onReceiveTextMessage);
// Get notified of incoming admin messages, and handle any which are relevant to InkHUD
CallbackObserver<Events, const meshtastic_AdminMessage *> adminMessageObserver =
CallbackObserver<Events, const meshtastic_AdminMessage *>(this, &Events::onAdminMessage);
#ifdef ARCH_ESP32
// Get notified when the system is entering light sleep
CallbackObserver<Events, void *> lightSleepObserver = CallbackObserver<Events, void *>(this, &Events::beforeLightSleep);
#endif
// If set, InkHUD's data will be erased during onReboot
bool eraseOnReboot = false;
};
} // namespace NicheGraphics::InkHUD

View File

@@ -22,6 +22,8 @@ InkHUD::MessageStore::MessageStore(std::string label)
}
// Write the contents of the MessageStore::messages object to flash
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally
void InkHUD::MessageStore::saveToFlash()
{
assert(!filename.empty());
@@ -29,7 +31,9 @@ void InkHUD::MessageStore::saveToFlash()
#ifdef FSCom
// Make the directory, if doesn't already exist
// This is the same directory accessed by NicheGraphics::FlashData
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
// Open or create the file
// No "full atomic": don't save then rename
@@ -37,6 +41,9 @@ void InkHUD::MessageStore::saveToFlash()
LOG_INFO("Saving messages in %s", filename.c_str());
// Take firmware's SPI Lock while writing
spiLock->lock();
// 1st byte: how many messages will be written to store
f.write(messages.size());
@@ -51,6 +58,9 @@ void InkHUD::MessageStore::saveToFlash()
LOG_DEBUG("Wrote message %u, length %u, text \"%s\"", (uint32_t)i, min(MAX_MESSAGE_SIZE, m.text.size()), m.text.c_str());
}
// Release firmware's SPI lock, because SafeFile::close needs it
spiLock->unlock();
bool writeSucceeded = f.close();
if (!writeSucceeded) {
@@ -63,6 +73,7 @@ void InkHUD::MessageStore::saveToFlash()
// Attempt to load the previous contents of the MessageStore:message deque from flash.
// Filename is controlled by the "label" parameter
// Takes the firmware's SPI lock during FS operations. Implemented for consistency, but only relevant when using SD card.
void InkHUD::MessageStore::loadFromFlash()
{
// Hopefully redundant. Initial intention is to only load / save once per boot.
@@ -70,6 +81,9 @@ void InkHUD::MessageStore::loadFromFlash()
#ifdef FSCom
// Take the firmware's SPI Lock, in case filesystem is on SD card
concurrency::LockGuard guard(spiLock);
// Check that the file *does* actually exist
if (!FSCom.exists(filename.c_str())) {
LOG_WARN("'%s' not found. Using default values", filename.c_str());

View File

@@ -502,6 +502,10 @@ Applets themselves do also listen separately for various events, but for the pur
Button input is sometimes handled by a system applet. `InkHUD::Events` determines whether the button should be handled by a specific system applet, or should instead trigger a default behavior
#### Factory Reset
The Events class handles the admin messages(s) which trigger factory reset. We set `Events::eraseOnReboot = true`, which causes `Events::onReboot` to erase the contents of InkHUD's data directory. We do this because some applets (e.g. ThreadedMessageApplet) save their own data to flash, so if we erased earlier, that data would get re-written during reboot.
---
### `InkHUD::Applet`

View File

@@ -98,9 +98,8 @@ void TwoButton::setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup)
assert(whichButton < 2);
buttons[whichButton].pin = pin;
buttons[whichButton].activeLogic = LOW; // Unimplemented
buttons[whichButton].mode = internalPullup ? INPUT_PULLUP : INPUT;
pinMode(buttons[whichButton].pin, buttons[whichButton].mode);
pinMode(buttons[whichButton].pin, internalPullup ? INPUT_PULLUP : INPUT);
}
void TwoButton::setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs)
@@ -182,7 +181,7 @@ void TwoButton::isrSecondary()
void TwoButton::startThread()
{
if (!OSThread::enabled) {
OSThread::setInterval(50);
OSThread::setInterval(10);
OSThread::enabled = true;
}
}
@@ -299,7 +298,9 @@ int TwoButton::afterLightSleep(esp_sleep_wakeup_cause_t cause)
// Manually trigger the button-down ISR
// - during light sleep, our ISR is disabled
// - if light sleep ends by button press, pretend our own ISR caught it
if (cause == ESP_SLEEP_WAKEUP_GPIO)
// - need to manually confirm by reading pin ourselves, to avoid occasional false positives
// (false positive only when using internal pullup resistors?)
if (cause == ESP_SLEEP_WAKEUP_GPIO && digitalRead(buttons[0].pin) == buttons[0].activeLogic)
isrPrimary();
return 0; // Indicates success

View File

@@ -35,7 +35,7 @@ class TwoButton : protected concurrency::OSThread
static TwoButton *getInstance(); // Create or get the singleton instance
void start(); // Start handling button input
void stop(); // Stop handling button input (disconnect ISRs for sleep)
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPulldown = false);
void setWiring(uint8_t whichButton, uint8_t pin, bool internalPullup = false);
void setTiming(uint8_t whichButton, uint32_t debounceMs, uint32_t longpressMs);
void setHandlerDown(uint8_t whichButton, Callback onDown);
void setHandlerUp(uint8_t whichButton, Callback onUp);
@@ -65,7 +65,6 @@ class TwoButton : protected concurrency::OSThread
// Per-button config
uint8_t pin = 0xFF; // 0xFF: unset
bool activeLogic = LOW; // Active LOW by default. Currently unimplemented.
uint8_t mode = INPUT; // Whether to use internal pull up / pull down resistors
uint32_t debounceLength = 50; // Minimum length for shortpress, in ms
uint32_t longpressLength = 500; // How long after button down to fire longpress, in ms
volatile State state = State::REST; // Internal state

View File

@@ -11,6 +11,7 @@
#ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h"
#include <thread>
#endif
DeviceScreen *deviceScreen = nullptr;
@@ -26,12 +27,10 @@ CallbackObserver<DeviceScreen, esp_sleep_wakeup_cause_t> endSleepObserver =
void tft_task_handler(void *param = nullptr)
{
while (true) {
if (deviceScreen) {
spiLock->lock();
deviceScreen->task_handler();
spiLock->unlock();
deviceScreen->sleep();
}
spiLock->lock();
deviceScreen->task_handler();
spiLock->unlock();
deviceScreen->sleep();
}
}
@@ -44,10 +43,10 @@ void tftSetup(void)
#else
if (settingsMap[displayPanel] != no_screen) {
DisplayDriverConfig displayConfig;
static char *panels[] = {"NOSCREEN", "X11", "ST7789", "ST7735", "ST7735S", "ST7796",
"ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S",
"ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"};
#ifdef USE_X11
#if defined(USE_X11)
if (settingsMap[displayPanel] == x11) {
if (settingsMap[displayWidth] && settingsMap[displayHeight])
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth],
@@ -55,6 +54,14 @@ void tftSetup(void)
else
displayConfig.device(DisplayDriverConfig::device_t::X11);
} else
#elif defined(USE_FRAMEBUFFER)
if (settingsMap[displayPanel] == fb) {
if (settingsMap[displayWidth] && settingsMap[displayHeight])
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth],
(uint16_t)settingsMap[displayHeight]);
else
displayConfig.device(DisplayDriverConfig::device_t::FB);
} else
#endif
{
displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT)
@@ -116,11 +123,15 @@ void tftSetup(void)
}
#endif
if (deviceScreen) {
#ifdef ARCH_ESP32
tftSleepObserver.observe(&notifyLightSleep);
endSleepObserver.observe(&notifyLightSleepEnd);
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
tftSleepObserver.observe(&notifyLightSleep);
endSleepObserver.observe(&notifyLightSleepEnd);
xTaskCreatePinnedToCore(tft_task_handler, "tft", 10240, NULL, 1, NULL, 0);
#elif defined(ARCH_PORTDUINO)
std::thread *tft_task = new std::thread([] { tft_task_handler(); });
#endif
}
}
#endif

View File

@@ -105,7 +105,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
#include "AmbientLightingThread.h"
#include "PowerFSMThread.h"
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
AccelerometerThread *accelerometerThread = nullptr;
#endif
@@ -115,13 +115,17 @@ AccelerometerThread *accelerometerThread = nullptr;
AudioThread *audioThread = nullptr;
#endif
#ifdef USE_PCA9557
PCA9557 IOEXP;
#endif
#if HAS_TFT
extern void tftSetup(void);
#endif
#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastThread.h"
UdpMulticastThread *udpThread = nullptr;
#include "mesh/udp/UdpMulticastHandler.h"
UdpMulticastHandler *udpHandler = nullptr;
#endif
#if defined(TCXO_OPTIONAL)
@@ -133,6 +137,10 @@ void setupNicheGraphics();
#include "nicheGraphics.h"
#endif
#if defined(HW_SPI1_DEVICE) && defined(ARCH_ESP32)
SPIClass SPI1(HSPI);
#endif
using namespace concurrency;
volatile static const char slipstreamTZString[] = {USERPREFS_TZ_STRING};
@@ -364,9 +372,11 @@ void setup()
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
#endif
#if !HAS_TFT
meshtastic_Config_DisplayConfig_OledType screen_model =
meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64;
#endif
#ifdef USE_SEGGER
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
@@ -595,6 +605,7 @@ void setup()
}
#endif
#if !HAS_TFT
auto screenInfo = i2cScanner->firstScreen();
screen_found = screenInfo.type != ScanI2C::DeviceType::NONE ? screenInfo.address : ScanI2C::ADDRESS_NONE;
@@ -612,6 +623,7 @@ void setup()
screen_model = meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
}
}
#endif
#define UPDATE_FROM_SCANNER(FIND_FN)
@@ -680,7 +692,7 @@ void setup()
}
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if !defined(ARCH_STM32WL)
auto acc_info = i2cScanner->firstAccelerometer();
accelerometer_found = acc_info.type != ScanI2C::DeviceType::NONE ? acc_info.address : accelerometer_found;
LOG_DEBUG("acc_info = %i", acc_info.type);
@@ -779,9 +791,11 @@ void setup()
else
playStartMelody();
#if !HAS_TFT
// fixed screen override?
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;
#endif
#if defined(USE_SH1107)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
@@ -793,7 +807,7 @@ void setup()
#endif
#if !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if !defined(ARCH_STM32WL)
if (acc_info.type != ScanI2C::DeviceType::NONE) {
accelerometerThread = new AccelerometerThread(acc_info.type);
}
@@ -837,10 +851,16 @@ void setup()
#elif !defined(ARCH_ESP32) // ARCH_RP2040
SPI.begin();
#else
// ESP32
// ESP32
#if defined(HW_SPI1_DEVICE)
SPI1.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
LOG_DEBUG("SPI1.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
SPI1.setFrequency(4000000);
#else
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
LOG_DEBUG("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
SPI.setFrequency(4000000);
#endif
#endif
// Initialize the screen first so we can show the logo while we start up everything else.
@@ -898,12 +918,12 @@ void setup()
#ifdef HAS_UDP_MULTICAST
LOG_DEBUG("Start multicast thread");
udpThread = new UdpMulticastThread();
udpHandler = new UdpMulticastHandler();
#ifdef ARCH_PORTDUINO
// FIXME: portduino does not ever call onNetworkConnected so call it here because I don't know what happen if I call
// onNetworkConnected there
if (config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->start();
udpHandler->start();
}
#endif
#endif
@@ -934,7 +954,7 @@ void setup()
// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789)
defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS)
screen->setup();
#elif defined(ARCH_PORTDUINO)
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
@@ -1280,7 +1300,12 @@ void setup()
LOG_DEBUG("Free heap : %7d bytes", ESP.getFreeHeap());
LOG_DEBUG("Free PSRAM : %7d bytes", ESP.getFreePsram());
#endif
#if !defined(ARCH_STM32WL)
if (accelerometerThread)
accelerometerThread->calibrate(30);
#endif
}
#endif
uint32_t rebootAtMsec; // If not zero we will reboot at this time (used to reboot shortly after the update completes)
uint32_t shutdownAtMsec; // If not zero we will shutdown at this time (used to shutdown from python or mobile client)
@@ -1310,7 +1335,7 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_AUDIO_CONFIG;
#endif
// Option to explicitly include canned messages for edge cases, e.g. niche graphics
#if (!HAS_SCREEN && NO_EXT_GPIO) && !MESHTASTIC_INCLUDE_CANNEDMSG
#if (!HAS_SCREEN || NO_EXT_GPIO) || MESHTASTIC_EXCLUDE_CANNEDMESSAGES
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_CANNEDMSG_CONFIG;
#endif
#if NO_EXT_GPIO
@@ -1318,11 +1343,11 @@ extern meshtastic_DeviceMetadata getDeviceMetadata()
#endif
// Only edge case here is if we apply this a device with built in Accelerometer and want to detect interrupts
// We'll have to macro guard against those targets potentially
#if NO_EXT_GPIO
#if NO_EXT_GPIO || MESHTASTIC_EXCLUDE_DETECTIONSENSOR
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_DETECTIONSENSOR_CONFIG;
#endif
// If we don't have any GPIO and we don't have GPS, no purpose in having serial config
#if NO_EXT_GPIO && NO_GPS
// If we don't have any GPIO and we don't have GPS OR we don't want too - no purpose in having serial config
#if NO_EXT_GPIO && NO_GPS || MESHTASTIC_EXCLUDE_SERIAL
deviceMetadata.excluded_modules |= meshtastic_ExcludedModules_SERIAL_CONFIG;
#endif
#ifndef ARCH_ESP32

View File

@@ -51,14 +51,14 @@ extern AudioThread *audioThread;
#endif
#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastThread.h"
extern UdpMulticastThread *udpThread;
#include "mesh/udp/UdpMulticastHandler.h"
extern UdpMulticastHandler *udpHandler;
#endif
// Global Screen singleton.
extern graphics::Screen *screen;
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
extern AccelerometerThread *accelerometerThread;
#endif

View File

@@ -345,7 +345,7 @@ void Channels::setChannel(const meshtastic_Channel &c)
bool Channels::anyMqttEnabled()
{
#if USERPREFS_EVENT_MODE
#if USERPREFS_EVENT_MODE && !MESHTASTIC_EXCLUDE_MQTT
// Don't publish messages on the public MQTT broker if we are in event mode
if (mqtt && mqtt->isUsingDefaultServer()) {
return false;

View File

@@ -6,6 +6,7 @@
#define ONE_MINUTE_MS 60 * 1000
#define THIRTY_SECONDS_MS 30 * 1000
#define FIVE_SECONDS_MS 5 * 1000
#define TEN_SECONDS_MS 10 * 1000
#define min_default_telemetry_interval_secs 30 * 60
#define default_gps_update_interval IF_ROUTER(ONE_DAY, 2 * 60)

View File

@@ -247,8 +247,8 @@ template <typename T> void LR11x0Interface<T>::startReceive()
lora.setPreambleLength(preambleLength); // Solve RX ack fail after direct message sent. Not sure why this is needed.
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
int err =
lora.startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
assert(err == RADIOLIB_ERR_NONE);
RadioLibInterface::startReceive();

View File

@@ -450,7 +450,6 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
nvs_flash_erase();
#endif
#ifdef ARCH_NRF52
Bluefruit.begin();
LOG_INFO("Clear bluetooth bonds!");
bond_print_list(BLE_GAP_ROLE_PERIPH);
bond_print_list(BLE_GAP_ROLE_CENTRAL);
@@ -584,7 +583,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
defined(ELECROW)) && \
HAS_TFT
// switch BT off by default; use TFT programming mode or hotkey to enable
config.bluetooth.enabled = false;
@@ -595,7 +595,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.bluetooth.fixed_pin = defaultBLEPin;
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \
defined(HX8357_CS) || defined(USE_ST7789)
defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS)
bool hasScreen = true;
#ifdef HELTEC_MESH_NODE_T114
uint32_t st7789_id = get_st7789_id(ST7789_NSS, ST7789_SCK, ST7789_SDA, ST7789_RS, ST7789_RESET);
@@ -689,7 +689,7 @@ void NodeDB::initConfigIntervals()
config.display.screen_on_secs = default_screen_on_secs;
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014)
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(UNPHONE) || defined(MESH_TAB) || defined(RAK14014) || defined(ELECROW)
config.power.is_power_saving = true;
config.display.screen_on_secs = 30;
config.power.wait_bluetooth_secs = 30;

View File

@@ -649,8 +649,10 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id);
return false;
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
} else if (IS_ONE_OF(meshtastic_PortNum_POSITION_APP, meshtastic_PortNum_WAYPOINT_APP, meshtastic_PortNum_ALERT_APP) &&
lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], TEN_SECONDS_MS)) {
// TODO: [Issue #6700] Make this rate limit throttling scale up / down with the preset
LOG_WARN("Rate limit portnum %d", p.decoded.portnum);
meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id);

View File

@@ -210,6 +210,14 @@ bool RadioLibInterface::canSleep()
return res;
}
/** Allow other firmware components to ask whether we are currently sending a packet
Initially implemented to protect T-Echo's capacitive touch button from spurious presses during tx
*/
bool RadioLibInterface::isSending()
{
return sendingPacket != NULL;
}
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
bool RadioLibInterface::cancelSending(NodeNum from, PacketId id)
{

View File

@@ -16,6 +16,9 @@
#define RADIOLIB_PIN_TYPE uint32_t
// In addition to the default Rx flags, we need the PREAMBLE_DETECTED flag to detect whether we are actively receiving
#define MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS (RADIOLIB_IRQ_RX_DEFAULT_FLAGS | (1 << RADIOLIB_IRQ_PREAMBLE_DETECTED))
/**
* We need to override the RadioLib ArduinoHal class to add mutex protection for SPI bus access
*/
@@ -132,6 +135,11 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
*/
virtual bool isActivelyReceiving() = 0;
/** Are we are currently sending a packet?
* This method is public, intending to expose this information to other firmware components
*/
virtual bool isSending();
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
virtual bool cancelSending(NodeNum from, PacketId id) override;

View File

@@ -293,8 +293,8 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
}
#if HAS_UDP_MULTICAST
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->onSend(const_cast<meshtastic_MeshPacket *>(p));
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p));
}
#endif

View File

@@ -277,8 +277,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
setStandby();
// We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly.
// Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS);
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR("SX126X startReceiveDutyCycleAuto %s%d", radioLibErr, err);
assert(err == RADIOLIB_ERR_NONE);

View File

@@ -260,8 +260,7 @@ template <typename T> void SX128xInterface<T>::startReceive()
#endif
#endif
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS | RADIOLIB_IRQ_PREAMBLE_DETECTED);
int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, MESHTASTIC_RADIOLIB_IRQ_RX_FLAGS);
if (err != RADIOLIB_ERR_NONE)
LOG_ERROR("SX128X startReceive %s%d", radioLibErr, err);

View File

@@ -43,7 +43,7 @@ template <class T, class U> class APIServerPort : public U, private concurrency:
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
*/
T *openAPI = NULL;
#if RAK_4631
#if defined(RAK_4631) || defined(RAK11310)
// Track wait time for RAK13800 Ethernet requests
int32_t waitTime = 100;
#endif

View File

@@ -239,6 +239,14 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_HELTEC_SENSOR_HUB = 92,
/* Reserved Fried Chicken ID for future use */
meshtastic_HardwareModel_RESERVED_FRIED_CHICKEN = 93,
/* Heltec Magnetic Power Bank with Meshtastic compatible */
meshtastic_HardwareModel_HELTEC_MESH_POCKET = 94,
/* Seeed Solar Node */
meshtastic_HardwareModel_SEEED_SOLAR_NODE = 95,
/* NomadStar Meteor Pro https://nomadstar.ch/ */
meshtastic_HardwareModel_NOMADSTAR_METEOR_PRO = 96,
/* Elecrow CrowPanel Advance models, ESP32-S3 and TFT with SX1262 radio plugin */
meshtastic_HardwareModel_CROWPANEL = 97,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */

View File

@@ -79,7 +79,10 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode {
/* NMEA messages specifically tailored for CalTopo */
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_CALTOPO = 5,
/* Ecowitt WS85 weather station */
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6,
/* VE.Direct is a serial protocol used by Victron Energy products
https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable */
meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7
} meshtastic_ModuleConfig_SerialConfig_Serial_Mode;
/* TODO: REPLACE */
@@ -467,8 +470,8 @@ extern "C" {
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85+1))
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT
#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT+1))
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE
#define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK

View File

@@ -13,12 +13,11 @@
#endif // HAS_ETHERNET
#define UDP_MULTICAST_DEFAUL_PORT 4403 // Default port for UDP multicast is same as TCP api server
#define UDP_MULTICAST_THREAD_INTERVAL_MS 15000
class UdpMulticastThread : public concurrency::OSThread
class UdpMulticastHandler final
{
public:
UdpMulticastThread() : OSThread("UdpMulticast") { udpIpAddress = IPAddress(224, 0, 0, 69); }
UdpMulticastHandler() { udpIpAddress = IPAddress(224, 0, 0, 69); }
void start()
{
@@ -71,14 +70,6 @@ class UdpMulticastThread : public concurrency::OSThread
return true;
}
protected:
int32_t runOnce() override
{
canSleep = true;
// TODO: Implement nodeinfo broadcast
return UDP_MULTICAST_THREAD_INTERVAL_MS;
}
private:
IPAddress udpIpAddress;
AsyncUDP udp;

View File

@@ -133,8 +133,8 @@ static void onNetworkConnected()
}
#if HAS_UDP_MULTICAST
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->start();
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpHandler->start();
}
#endif
}

View File

@@ -38,7 +38,7 @@
#include "modules/PositionModule.h"
#endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#if !defined(ARCH_STM32WL) && !MESHTASTIC_EXCLUDE_I2C
#include "motion/AccelerometerThread.h"
#endif
@@ -284,7 +284,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
case meshtastic_AdminMessage_remove_by_nodenum_tag: {
LOG_INFO("Client received remove_nodenum command");
nodeDB->removeNodeByNum(r->remove_by_nodenum);
this->notifyObservers(r); // Observed by screen
break;
}
case meshtastic_AdminMessage_set_favorite_node_tag: {
@@ -444,6 +443,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
}
// Allow any observers (e.g. the UI) to respond to this event
notifyObservers(r);
return handled;
}

View File

@@ -0,0 +1,28 @@
#include "GenericThreadModule.h"
#include "MeshService.h"
#include "configuration.h"
#include <Arduino.h>
/*
Generic Thread Module allows for the execution of custom code at a set interval.
*/
GenericThreadModule *genericThreadModule;
GenericThreadModule::GenericThreadModule() : concurrency::OSThread("GenericThreadModule") {}
int32_t GenericThreadModule::runOnce()
{
bool enabled = true;
if (!enabled)
return disable();
if (firstTime) {
// do something the first time we run
firstTime = 0;
LOG_INFO("first time GenericThread running");
}
LOG_INFO("GenericThread executing");
return (my_interval);
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include "MeshModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
#include <functional>
class GenericThreadModule : private concurrency::OSThread
{
bool firstTime = 1;
public:
GenericThreadModule();
protected:
unsigned int my_interval = 10000; // interval in millisconds
virtual int32_t runOnce() override;
};
extern GenericThreadModule *genericThreadModule;

View File

@@ -65,6 +65,10 @@
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY
#include "modules/Telemetry/PowerTelemetry.h"
#endif
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
#include "modules/GenericThreadModule.h"
#endif
#ifdef ARCH_ESP32
#if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO
#include "modules/esp32/AudioModule.h"
@@ -131,6 +135,9 @@ void setupModules()
#if !MESHTASTIC_EXCLUDE_DROPZONE
dropzoneModule = new DropzoneModule();
#endif
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
new GenericThreadModule();
#endif
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
// to a global variable.
@@ -249,4 +256,4 @@ void setupModules()
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
// acks
routingModule = new RoutingModule();
}
}

View File

@@ -370,9 +370,16 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TRACKER,
meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) &&
config.power.is_power_saving) {
LOG_DEBUG("Start next execution in 5s, then sleep");
meshtastic_ClientNotification *notification = clientNotificationPool.allocZeroed();
notification->level = meshtastic_LogRecord_Level_INFO;
notification->time = getValidTime(RTCQualityFromNet);
sprintf(notification->message, "Sending position and sleeping for %us interval in a moment",
Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs) /
1000U);
service->sendClientNotification(notification);
sleepOnNextExecution = true;
setIntervalFromNow(5000);
LOG_DEBUG("Start next execution in 5s, then sleep");
setIntervalFromNow(FIVE_SECONDS_MS);
}
}

View File

@@ -513,7 +513,7 @@ void SerialModule::processWXSerial()
// Extract the current line
char line[meshtastic_Constants_DATA_PAYLOAD_LEN];
memset(line, '\0', sizeof(line));
if (lineEnd - lineStart < sizeof(line) - 1) {
if ((size_t)(lineEnd - lineStart) < sizeof(line) - 1) {
memcpy(line, &serialBytes[lineStart], lineEnd - lineStart);
ParsedLine parsed = parseLine(line);

View File

@@ -1,6 +1,6 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h")
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "AirQualityTelemetry.h"
@@ -14,6 +14,13 @@
#include "main.h"
#include <Throttle.h>
#ifndef PMSA003I_WARMUP_MS
// from the PMSA003I datasheet:
// "Stable data should be got at least 30 seconds after the sensor wakeup
// from the sleep mode because of the fans performance."
#define PMSA003I_WARMUP_MS 30000
#endif
int32_t AirQualityTelemetryModule::runOnce()
{
/*
@@ -34,6 +41,13 @@ int32_t AirQualityTelemetryModule::runOnce()
if (moduleConfig.telemetry.air_quality_enabled) {
LOG_INFO("Air quality Telemetry: init");
#ifdef PMSA003I_ENABLE_PIN
// put the sensor to sleep on startup
pinMode(PMSA003I_ENABLE_PIN, OUTPUT);
digitalWrite(PMSA003I_ENABLE_PIN, LOW);
#endif /* PMSA003I_ENABLE_PIN */
if (!aqi.begin_I2C()) {
#ifndef I2C_NO_RESCAN
LOG_WARN("Could not establish i2c connection to AQI sensor. Rescan");
@@ -63,21 +77,45 @@ int32_t AirQualityTelemetryModule::runOnce()
if (!moduleConfig.telemetry.air_quality_enabled)
return disable();
if (((lastSentToMesh == 0) ||
!Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.air_quality_interval,
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
airTime->isTxAllowedAirUtil()) {
sendTelemetry();
lastSentToMesh = millis();
} else if (service->isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
switch (state) {
#ifdef PMSA003I_ENABLE_PIN
case State::IDLE:
// sensor is in standby; fire it up and sleep
LOG_DEBUG("runOnce(): state = idle");
digitalWrite(PMSA003I_ENABLE_PIN, HIGH);
state = State::ACTIVE;
return PMSA003I_WARMUP_MS;
#endif /* PMSA003I_ENABLE_PIN */
case State::ACTIVE:
// sensor is already warmed up; grab telemetry and send it
LOG_DEBUG("runOnce(): state = active");
if (((lastSentToMesh == 0) ||
!Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.air_quality_interval,
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
airTime->isTxAllowedChannelUtil(config.device.role != meshtastic_Config_DeviceConfig_Role_SENSOR) &&
airTime->isTxAllowedAirUtil()) {
sendTelemetry();
lastSentToMesh = millis();
} else if (service->isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
#ifdef PMSA003I_ENABLE_PIN
// put sensor back to sleep
digitalWrite(PMSA003I_ENABLE_PIN, LOW);
state = State::IDLE;
#endif /* PMSA003I_ENABLE_PIN */
return sendToPhoneIntervalMs;
default:
return disable();
}
}
return sendToPhoneIntervalMs;
}
bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)

View File

@@ -1,6 +1,6 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include("Adafruit_PM25AQI.h")
#pragma once
#include "../mesh/generated/meshtastic/telemetry.pb.h"
@@ -23,6 +23,14 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf
setIntervalFromNow(10 * 1000);
aqi = Adafruit_PM25AQI();
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
#ifdef PMSA003I_ENABLE_PIN
// the PMSA003I sensor uses about 300mW on its own; support powering it off when it's not actively taking
// a reading
state = State::IDLE;
#else
state = State::ACTIVE;
#endif
}
protected:
@@ -42,6 +50,12 @@ class AirQualityTelemetryModule : private concurrency::OSThread, public Protobuf
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
enum State {
IDLE = 0,
ACTIVE = 1,
};
State state;
Adafruit_PM25AQI aqi;
PM25_AQI_Data data = {0};
bool firstTime = true;

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