Compare commits

...
Author SHA1 Message Date
Ben Meadors bf958ed01d Update version.properties 2025-02-24 10:23:24 -06:00
Austin c93728eb75 Debian: Ensure deps exist for changelog bump (#6145) 2025-02-24 09:16:18 -06:00
dependabot[bot] 01c717a41d Bump actions/stale from 9.0.0 to 9.1.0 in /.github/workflows (#6143)
Bumps [actions/stale](https://github.com/actions/stale) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 22:35:14 +08:00
github-actions[bot] 7061fd1f16 Upgrade trunk (#6139) 2025-02-24 11:12:18 +01:00
Tom Fifield 7d8e0ede6c Reduce some log levels. (#6127)
This patch takes a few LOG_INFO messages and turns them into
LOG_DEBUG. The logs appear to be mostly useful to developers, rather
than end users and as such placing them at INFO level is too high a
priority.
2025-02-23 06:14:37 -06:00
github-actions[bot]andthebentern efca2b5849 [create-pull-request] automated change (#6122)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-02-22 11:19:07 -06:00
GUVWAF cfcd9cc210 Revert "Rak4631 remove spi1 (#6042)" (#6121)
This reverts commit 9b46cb4ef0.
2025-02-22 08:03:05 -06:00
Tom Fifield fe1ced7480 GPS Factory Reset no longer needed. (#6116)
In 2020 there was a bad batch of tbeams whose ubloxen went a little
loopy. We factory reset them to bring them sane again.

It's now 2025, the problem with tbeam is long fixed, and this is not
necessary for any other devices we're aware of. Removing the function to
make our code more maintainable.

There is an associated protobuf entry did_gps_reset that we might be able
to re-purpose for something else, or remove in 3.0.
2025-02-21 16:53:46 -06:00
Austin 3787cf7803 meshtasticd deb: Build armv6-compatible binary (#6104) 2025-02-21 09:55:38 +08:00
Ben Meadors 1be28520a7 Perhaps fix TXCO reports on pro-micro (#6110)
* Perhaps fix TXCO reports on pro-micro

* Missed one
2025-02-21 08:30:09 +08:00
GUVWAF 4942c7b71f Fix PowerTelemetry initialization (#6106) 2025-02-20 15:28:01 -06:00
GUVWAF 4709d21df8 Ignore and disallow multi-hop traceroutes destined to broadcast address (#6109)
* Ignore traceroutes destined to broadcast address

* Disallow multi-hop traceroute request to broadcast address

* Allow zero-hop broadcast requests
2025-02-20 14:34:09 -06:00
Tom Fifield ec0eafedab Move variant-specific lines back to variant (#6044)
Last release a change introduced different branching functions in
gps.cpp based on the model of a device. This makes the code less
readable and introduces the potential for bugs.

This patch creates a new variable, GPS_PROBETRIES that can be set
in variant.h of devices that will control how many times we will
probe for GPS presence. It sets up the T1000-E to use this variable
and cleans the code in gps.c
2025-02-20 07:48:37 -06:00
rostekus 994e22aba9 feat: added BMP-390 support to the BMP-3xx sensors (#6103) 2025-02-20 21:36:49 +08:00
Mictronics 9930bba3f5 Add Pico2W variant including Wifi support. (#6062) 2025-02-20 10:56:34 +01:00
Austin f1dc1b309a PIO: Cleanup dependency naming (#6090) 2025-02-19 18:14:54 -06:00
Austin 337265a07f Trunk: Another annotation attempt (#6100) 2025-02-20 07:43:23 +08:00
Sebastian Muszynski bb73555209 Expose INA219 measurement as battery voltage for Seeed Xiao ESP32S3 (#6070)
* Expose INA219 measurement as battery voltage for Seeed Xiao ESP32S3

* Define BATTERY_PIN and don't block a random GPIO
2025-02-19 06:36:59 -06:00
Tom Fifield 93c64cb442 Dependencies: minor version updates (#6045)
platformio/espressif32@6.9.0 --> 6.10.0
lewisxhe/XPowersLib@^0.2.6 --> 0.2.7
platformio/framework-arduinoststm32@~Oct 2024 --> 4.20900.0
zinggjm/GxEPD2@^1.4.9 --> 1.6.2
tool-esptoolpy@^1.40500.0 --> 1.40801.0

Used platformio tool to check, kept to minor version updates,
checked release notes for any breaking changes.
2025-02-19 06:32:38 -06:00
Austin 5da5803c4c Trunk: Annotate PRs and Auto-Upgrade (#6091) 2025-02-19 06:14:46 -06:00
Ikko Eltociear Ashimine 79b3a1e60e chore: update unishox2.h (#6092)
occuring -> occurring
2025-02-19 12:58:41 +01:00
rcarteraz 191ca8ce12 update readme add logo image (#6088) 2025-02-18 15:56:13 -06:00
noahhaon c67aa25d19 Add missing traceroute fields to serialized JSON output (#6087) 2025-02-18 13:25:55 -06:00
Eric Severance 3b0232de1b Validate MQTT config by testing a connection (#6076) 2025-02-17 15:03:44 -06:00
7eb77276cd Add support for new NRF52 board, MeshLink (#5736)
* Add support for MeshLink

* Updated, enabled watchdog and added button definition

* added eink variant and removed some compile errors

* Small board json file edit

* Finally got trunk working (somehow?), this is just cleanup with trunk fmt

* Various improvements and cleanup. Removed the use of PIN_3V3_En and defined a specific WD_EN pin instead for better clarity. Will do a bit more testing asap to make sure everything still works as intended :)

* Enable on-board QSPI Flash

* run trunk fmt with clang-format

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Austin <vidplace7@gmail.com>
2025-02-16 19:49:17 -06:00
Eric SeveranceandBen Meadors 7648391f91 Reject invalid configuration for the default MQTT server (#6066)
* Sanity check configuration for the default MQTT server

* Skip for MESHTASTIC_EXCLUDE_MQTT

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-02-16 07:15:30 -06:00
porkcube 4407d9e040 assigning SDA/SCL so it actually works 8| (#6065) 2025-02-16 06:39:48 -06:00
GUVWAFandBen Meadors 27fea5fc07 Fix STM32WL TCXO setting; enable logs and modules (#6063)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-02-15 09:06:10 -06:00
Michael Gjelsø 2f6cd02111 Typo for Bandit button LEDs (#6053)
Changed Button 2 LED index define from BUTTON1_COLOR_INDEX to correct BUTTON2_COLOR_INDEX
2025-02-15 08:06:41 -06:00
GUVWAF 8c9947b05c Allow NeighborInfo on non-default frequency slot (#6061) 2025-02-15 07:55:51 -06:00
Eric SeveranceandBen Meadors 50b7d6a0f7 Establish MQTT connection only from MQTT::runOnce (#6057)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-02-14 20:32:41 -06:00
Eric Severance c83ffd4911 Consider the MQTT TLS remote IP when enabled. (#6058) 2025-02-14 19:19:50 -06:00
Woutvstk 9b46cb4ef0 Rak4631 remove spi1 (#6042)
* Removed non-existant SPI1 interface on rak4631

* trunk fmt
2025-02-14 12:53:22 -06:00
porkcubeandBen Meadors 01935ea35e Add XIAO nRF52840 + Wio SX1262 DIY Variant (#5976)
* added xiao nRF52840 + xiao wio sx1262 DIY variant

* fix path / make buildy buildy

* pcf cruft from personal hw

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-02-14 06:50:28 -06:00
Austin 495f69cf90 Trunk: Trailing commas begone! (#6038) 2025-02-12 08:57:23 +08:00
Manuel eb650a6adb set TCXO to 2.4V (#6036) 2025-02-11 10:34:37 -06:00
nwilde1590 7fdd262d55 Added custom OCV array values for T1000-E (#6031) 2025-02-11 14:02:21 +08:00
Austin d1fa27d353 small fix: don't junk the zip for pio-deps (#6029) 2025-02-10 20:35:06 -06:00
Austin 8427072d79 meshtasticd: include .hidden (.git) dirs in pio-deps (#6028) 2025-02-10 18:58:02 -05:00
github-actions[bot]andthebentern 4e2b47cc67 [create-pull-request] automated change (#6027)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-02-10 15:02:42 -06:00
Jason PandBen Meadors da1d78c882 Add support for 12- and 24-hour clock, Minor Settings Frame Adjustment (#5988)
* 12- or 24-hour clock work in progress

* 12- and 24-hour added to Settings Frame. Also some adjustments to screen layout.

* Updated Uptime wording to be "Up" to fit within screen real estate

* Removed label from uptime to conserve additional space

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-02-10 14:30:43 -06:00
Austin 7c4bf38647 meshtasticd flatpak: Include pio deps with release (#6025) 2025-02-10 14:29:16 -06:00
Mark Trevor Birss 96262b106c Revert "Create display-x11.yaml (#6021)" (#6022)
This reverts commit 39e45d90e1.
2025-02-10 11:53:58 +02:00
Mark Trevor Birss 39e45d90e1 Create display-x11.yaml (#6021) 2025-02-10 09:59:13 +02:00
ChangYanChu d70a9392af improve UTF-8 string handling in JSONValue (#6011)
```text
feat(json): improve UTF-8 string handling in JSONValue

- Add proper UTF-8 multi-byte character sequence handling
- Add boundary checks for UTF-8 sequences
- Keep original code structure and flow
- Add detailed comments for UTF-8 processing logic

This change improves the robustness of JSON string handling
while maintaining compatibility with existing code.
2025-02-08 20:03:44 +08:00
dylanliandWayenWeng 4e8c4f0d55 T1000-E hardware updates and GPS positioning accuracy optimisation (#6003)
* T1000-E button setting update

* T1000-E GNSS lock error fix

* T1000-E GNSS improve detection success

---------

Co-authored-by: WayenWeng <jinyuan.weng@seeed.cc>
2025-02-07 10:02:56 +02:00
lizthedeveloper 4a6a0efcfd log the nonce value at DEBUG instead of INFO (#6001)
you're leaking the nonce to stdout, if your logs are routed to a folder, this logs the nonce every time, leading to replay attack surface area being higher. Changed to debug.
2025-02-07 08:29:48 +08:00
github-actions[bot]andthebentern cb0519dd9c [create-pull-request] automated change (#5989)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-02-06 14:11:32 -06:00
Manuel 9db51a72a4 Fix T-Deck/T-Watch no BT (#5998)
fixes #5997
2025-02-06 14:11:17 -06:00
TomandTom 64def246ee Corrected some misinformation (#5995)
Change the module text too soon , before it had chance to reach a final conclusion.

Co-authored-by: Tom <116762865+Nestpebble@users.noreply.github.com>
2025-02-06 11:36:04 +08:00
Austin 1c8eb7ece3 meshtasticd: Fix web download location (#5993) 2025-02-05 15:19:22 -06:00
Austin 447533aae5 meshtasticd-debian: Remove existing deb builds (#5792)
Replaced with OpenSUSE Build Service
https://build.opensuse.org/project/show/network:Meshtastic
2025-02-04 07:38:54 -05:00
github-actions[bot]andthebentern 1b457bcfbb [create-pull-request] automated change (#5985)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-02-03 20:47:51 -06:00
Thomas Göttgens ed07cc067a Merge branch 'master' of https://github.com/meshtastic/firmware 2025-02-03 16:48:23 +01:00
Thomas Göttgens a3a295488c add firmware build script for use with docker 2025-02-03 16:48:10 +01:00
Thomas Göttgens 5c17afb2ac Clean up some legacy macro definitions (#5983) 2025-02-03 09:36:05 -06:00
Tom Fifield 8cacdb65d6 Fix INA226 Sensor Voltage Readings (#5972)
They were off by a factor of 1000 due to the difference between
Volts and MilliVolts, as reported by @morcant .

Fixes https://github.com/meshtastic/firmware/issues/5969
2025-02-03 08:39:42 -06:00
Tom 3a34f8beaf E80 promicro update (#5967)
* add readme and update rfswitch

* Updated readme to include all data from Ebyte

* Added results from switch testing & notes thereon

* fixed picture

* Whoops!

Forgot to uncomment some settings from test.

* Update readme.md

* Delete variants/diy/nrf52_promicro_diy_tcxo/E80_RSSI_per_case.png

* Add webp image to appease trunk

* Update readme.md

* Trunky trunk trunk

* Clang and the trunk is done
2025-02-03 20:16:35 +08:00
GUVWAF d740934278 Don't rate-limit position requests for Lost and Found role (#5981) 2025-02-03 19:24:47 +08:00
Woutvstk b370717dcd Add bearing to other node on device screen in text (#5968)
* Merge branch 'store-and-forward' of https://github.com/Woutvstk/meshtastic_firmware into store-and-forward

* also show bearing to a waypoint in text on screen
2025-02-03 13:43:32 +08:00
Chloe Bethel d9534cfc9d Remove unused usages of #include <iostream> to save Flash (#5978)
Saves ~100KB on wio-e5, which was previously at 99% Flash usage
2025-02-03 11:31:54 +08:00
Austin 4c0e0b8471 Portduino: Set Web SSL Cert / Key paths from yaml (#5961) 2025-02-01 16:58:58 +08:00
Ben Meadors b5cad2b65e Fix negative decimal value detection in userPrefs (#5963) 2025-01-29 20:52:24 -06:00
Jason P cd8592ef4a Fixes #5766 Updated MQTT privateCidrRanges to add Tailscale (#5957) 2025-01-29 06:14:43 -06:00
Austin 78da8f6fc4 Portduino: Allow limiting TX Power from yaml (#5954) 2025-01-29 12:51:26 +01:00
Tom Fifield 6a12760c3d Fix off-by-one error with log writes (#5959)
As reported by @jstockdale, when writing coloured logs we were
writing the full string, including a null terminator. This caused
issues for programs consuming our logs. The fix as identified is
not to write the null.

Fixes https://github.com/meshtastic/firmware/issues/5945
2025-01-28 19:57:52 -06:00
Thomas Göttgens 30a31a3a13 Oem logo (#5939)
* reinstate oemlogo, add to userPrefs.jsonc

* disable from default build
2025-01-28 08:38:22 -06:00
Manuel 2d42e1b2bc fix: TCXO_OPTIONAL featuring SenseCAP Indicator (V1/V2) (#5948)
* fix TCXO_OPTIONAL

* fix LOG_WARN

* fix lora.begin() returns -707

* trunk fmt
2025-01-27 14:00:12 -06:00
GUVWAFandBen Meadors 4747e73f37 Space out periodic broadcasts of modules automatically (#5931)
* Space out periodic broadcasts of modules automatically

* Add warning for function usage

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-26 13:59:59 -06:00
Aleksey Vasilenko 10d553087c Add missing build_unflags (#5941)
Fixes 'undefined reference to app_main' build error for
my_esp32s3_diy_eink and my_esp32s3_diy_oled variants.
2025-01-26 16:54:26 +08:00
Ben Meadors 7649e70585 Revert "No focus on new messages if auto-carousel is off (#5881)" (#5936)
This reverts commit 0f981153eb.
2025-01-25 12:01:25 -06:00
GUVWAF a14346bc4f Rate limit position replies to three minutes (#5932) 2025-01-25 09:24:24 -06:00
github-actions[bot]andthebentern fd56995764 [create-pull-request] automated change (#5928)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-25 07:53:24 -06:00
github-actions[bot]andthebentern 4c97351187 [create-pull-request] automated change (#5926)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-24 18:52:17 -06:00
Tom Fifieldandvirgil 3298df953a Fixed the issue that the wifi configuration saved to RAM did not take effect. (#5925)
Co-authored-by: virgil <virgil.wang.cj@gmail.com>
2025-01-24 07:30:18 -06:00
Ben Meadors d1f7739bbe Peg NRF52 arduino to meshtastic fork with LFE bluetooth fix (#5924) 2025-01-23 19:56:59 -06:00
Ben Meadors 0d860882a8 NRF52 - Remove file totally before opening write (#5916)
* Remove prefs first

* Remove file first

* Remove truncate

* No longer needed

* Missed a param

* That wasn't supposed to be there

* Remove vestigal lfs assert

* Durr
2025-01-23 19:12:20 -06:00
Austin 3b40fe9805 Docker: Switch tags to newline-seperated (#5919) 2025-01-24 09:03:03 +11:00
Austin 8e8b22edb0 Debian: Switch OBS repo to network:Meshtastic (#5912) 2025-01-22 11:09:29 -06:00
Austin 01892cbd1e Docker: tag intermediate containers (#5910) 2025-01-22 08:55:57 -06:00
Thomas Göttgens 7fb22cf678 ignore platformio core files when building in place 2025-01-22 14:11:58 +01:00
Eric Severance fdc87d492c Add quotes around ${platformio.build_dir} (#5906)
Fixes #5898 (hopefully)
2025-01-22 19:45:34 +11:00
Austin 0fdbf70452 Small fix: Correctly pass secrets in Docker builds (#5905) 2025-01-22 14:26:10 +11:00
Austin 71591fb06a Build docker images with other linux (#5837) 2025-01-21 18:53:32 -06:00
Austin 9041af365d Move OpenWRT configs to subdir (#5902) 2025-01-21 16:18:40 -06:00
GUVWAF f87c370123 Fix possible memory leak for ROUTER_LATE (#5901) 2025-01-21 18:11:37 +01:00
Eric SeveranceandBen Meadors c4fcbad372 Reboot before formatting LittleFS (#5900)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-20 11:43:35 -06:00
isseysandei 0f981153eb No focus on new messages if auto-carousel is off (#5881)
* no focus on messages if screen carousel is disabled

* trunk + comment

* compacted the nested if using ternary operator

* trunk
2025-01-20 10:47:47 -06:00
Mark Trevor Birss c1beb44678 Create BananaPi-BPI-R4-sx1262.yaml (#5897) 2025-01-20 13:20:59 +02:00
Thomas Göttgens 973b453d43 Update RAK2560 code (#5844)
* * Update RAK9154 sensor to tx remote power telemetry
* remove uf2 script, pio run does that inline
* move sensor module to correct position
* disable LED and Accelerometer code on rak2560
* trunk fmt
* mention epaper variant
* attention, revert, revert
* Enable Environment Telemetry of these values
* fix float values
2025-01-20 09:34:54 +01:00
Ben Meadors 950341d1f9 Alert app messages should be treated as text (#5878) 2025-01-18 08:15:06 -06:00
Thomas Göttgens b353bcc04a fix detection of lark weather station and add rain sensor (#5874)
* fix detection of lark weather station
* fix unit tests and add support for Dfrobot rain gauge
* fix name display on bootup
* fix gauge init logic
* trunk fmt
2025-01-18 14:10:13 +01:00
github-actions[bot]andcaveman99 c4051c1a7b [create-pull-request] automated change (#5877)
Co-authored-by: caveman99 <25002+caveman99@users.noreply.github.com>
2025-01-18 13:32:09 +01:00
Austin 2262d77be4 Small fix: Reference COPR group correctly (@) (#5872) 2025-01-17 12:27:49 +08:00
Austin 9566d6ffd4 COPR: Switch to forked GitHub Action (#5871) 2025-01-16 20:21:52 -06:00
e466bf2475 Slight rework of CH341 HAL (#5848)
* Rework of CH341 HAL

* Applied trunk fmt

* revert serial reading

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2025-01-16 19:38:58 -06:00
Eric SeveranceandBen Meadors b0fe5ef8ba Initial commit of a fuzzer for Meshtastic (#5790)
* Initial commit of a fuzzer for Meshtastic.

* Use a max of 5 for the phone queues

* Only write files to the temp dir

* Limitless queue + fuzzer = lots of ram :)

* Use $PIO_ENV for path to program

* spelling: s/is/to/

* Use loopCanSleep instead of a lock in Router

* realHardware allows full use of a CPU core

* Ignore checkov CKV_DOCKER_2 & CKV_DOCKER_3

* Add Atak seed

* Fix lint issues in build.sh

* Use exception to exit from portduino_main

* Separate build & source files into $WORK & $SRC

* Use an ephemeral port for the API server

* Include CXXFLAGS in the link step

* Read all shared libraries

* Use a separate work directory for each sanitizer

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-16 18:42:21 -06:00
Vít HolásekandBen Meadors f132158c3e Fixed localization on bigger screens (#5695)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-16 18:39:39 -06:00
SignalMedicandHuston Hedinger 8179e61fdc changed GPS buad rate to 9600 (#5786)
Co-authored-by: Huston Hedinger <1875033+hdngr@users.noreply.github.com>
2025-01-16 17:26:02 -06:00
danwelch3andBen Meadors a085614aaa Initiate magnetometer based compass calibration from button presses (#5553)
* Initiate magenetometer based compass calibration from button presses

- only active for BMX160 accelerometers on RAK_4631
- replace automatic calibration on power on with button triggered
  calibration
- set 5 presses to trigger 30s calibration
- set 6 presses to trigger 60s calibration (useful if unit is not
  handheld, ie vehicle mounted)
- show calibration time remaining on calibration alert screen

* Fix non RAK 4631 builds

- exclude changes from non RAK 4631 builds
- remove calls to screen when not present

* Fix build on RAK4631_eth_gw

- exclude all compass heading updates on variant without screen

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-16 17:22:27 -06:00
Ben Meadors 7acd72ede1 Cleanup unique id 2025-01-16 16:00:23 -06:00
Austin 7ba593432e COPR: Switch from hook to copr_cli (#5864) 2025-01-16 15:51:18 -06:00
todd-herbert a48df91737 Canned messages: allow GPIO0 with "scan and select" input (#5838)
* Allow GPIO0; check for conflict with user button

* Guard for no BUTTON_PIN; handle portduino

* Portduino settings: attempt two
We don't really need to #include radio code here just to check if the pin is RADIOLIB_NC. We're only interested if scanAndSelect pin matches user button pin, but they won't match if user button is RADIOLIB_NC.

* Portduino attempt 3: glue
2025-01-16 06:38:22 -06:00
github-actions[bot]andthebentern 262f1d25a2 [create-pull-request] automated change (#5860)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-16 06:15:17 -06:00
todd-herbert 4cd2ba5479 More lines of environmental telemetry on-screen (#5853) 2025-01-16 23:23:57 +13:00
todd-herbert f9876cfe9c Wait for disconnection (#5859) 2025-01-15 07:19:51 -06:00
Ben Meadors 85de193845 Fix NRF52 default append write mode of files (#5858)
* Fix NRF52 default append write mode of files

* Inside the lock
2025-01-15 06:46:12 -06:00
Ben Meadors fb2c008c89 Update version.properties 2025-01-14 18:55:02 -06:00
Austin dd9ab7f0e1 Small Fix: Release_Channels permissions (#5852) 2025-01-14 15:17:54 +08:00
github-actions[bot]andthebentern 729c39fb86 [create-pull-request] automated change (#5849)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-13 19:18:34 -06:00
isseysandei 038430db23 Environmental sensors page scrolling (#5847)
* env scrolling first iteration

* ran trunk
2025-01-14 09:00:00 +08:00
Ben Meadors d5cd6f87a0 Kablammo 2025-01-13 12:15:27 -06:00
Austin de42d96adf Actions: Fix issues with new Release process (#5845) 2025-01-13 10:46:07 -06:00
Ben Meadors e2dd845051 Fix devicestate protobuf / filesize allocation (#5835) 2025-01-13 08:30:20 -06:00
github-actions[bot]andthebentern 6366633cd4 [create-pull-request] automated change (#5841)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-13 07:05:59 -06:00
Ben Meadors 1c0f43c8e2 NRF52 SafeFile should not remove / rename files (#5840) 2025-01-13 06:28:18 -06:00
isseysandei 89a9e0b99d Added illuminance sensors to the node's environmental sensor page (#5832)
* illuminance sensors added

* added white_lux to debug
2025-01-13 16:39:01 +08:00
Austin 4dc8d6e400 Fix daily packaging perms (#5836) 2025-01-13 13:20:22 +08:00
Austin e0f97c9306 rpkg Fedora packaging (#5735) 2025-01-13 12:24:05 +08:00
Jonathan Bennett 6b1c01ce02 Trunk n stuff (#5833)
* Trunk

* Allow new gpio syntax with defaults

* Exit on pin init failure
2025-01-12 15:10:50 -06:00
70296b47bc Multi gpiochip support for native environment (#5743)
* For each GPIO PIN, allow to specify gpiochip and line

* Added support for LLCC68 in native env.

* Removed one if by employing &&

* Fix for log, as std::string and not const char*

* Remove CH341 flag, enabling it for all LoRa chips

* Provide a default example

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2025-01-12 13:40:25 -06:00
Erayd 0cf4a2951a Bugfix for low-priority packet replacement when TX queue is full (#5827)
* Correct function comment

* Enqueue the intended packet, not the pointer to what we just dropped!

* Add some log output when we drop packets due to a full queue

* Make it clear when a non-late packet is dropped

* Remove from queue before release, not after

* Erase dropped packet from queue

* Declared type

* Log TX queue length after every send

* Fix operand order

* Add worst-case cap on TX delay vs current time
2025-01-12 12:05:51 -06:00
Eric Severance 124936b6cf Avoid a potential NULL pointer reference in nrf52/BluetoothPhoneAPI (#5830) 2025-01-12 12:05:04 -06:00
Tom FifieldandManuel fd60c9b3be Upgrade to LovyanGFX 1.2 (#5677)
* [WIP] Attempt upgrade to LovyanGFX 1.1.16

This is the version most used by the TFT branch.

I wonder if this will work with our existing code? :)

* Update Portduino to LovyanGFX 1.20.0

Manuel says it's good to go.

* Update unPhone platformio.ini

---------

Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
2025-01-12 15:16:26 +08:00
And137 a0a4c5bc79 Support for Polish fonts on E-Ink devices, Polish fonts retouch, fixed Czech/Slovak OLED/E-Ink double space bug (#5821)
* Added support for Polish fonts for E-Ink devices

* Added support for Polish fonts for E-Ink devices FIX

* Polilsh E-Ink/OLED font retouch, fixed Czech/Slovak font double space bug

* Fixed platformio.ini uncommented flag
2025-01-12 14:30:58 +08:00
Eric Severance 0fe8d4ccc7 Run the AddressSanitizer during tests (#5815)
* Run the AddressSanitizer during tests

* Show details for test failures
2025-01-12 13:51:43 +08:00
DarkZeros 00fdf2c9aa Heltec Wireless Stick Lite V1/V2 support (#5808)
* I only have the V2.1 version, not sure if
  the HW is same with V1, or V2. Given the few
  resources I could find I think it is.
* ADC / Battery measure and TX/RX are working
2025-01-12 13:17:40 +08:00
Eric Severance 253ab458ef Add lsb-release on the github runner (#5825) 2025-01-11 22:29:24 -06:00
Eric Severance b4a4d2db4e Cache Python & PlatformIO dependencies (#5822) 2025-01-11 19:40:39 -06:00
GUVWAF 6b8cf164e9 Save some flash usage on STM32WL (#5819) 2025-01-11 07:20:32 -06:00
GUVWAF 812aa35f09 Enable Tx interrupt immediately after startTransmit() (#5820) 2025-01-11 07:19:17 -06:00
Eric Severance e7802d960f Manage when destructor is called for native HttpAPI (#5807) 2025-01-11 06:15:50 -06:00
Tom Fifieldandmverch67 077ee02426 Cherry-pick: Meshtab streamline and rotation fixes (#5812)
* mesh-tab: streamline target definitions

* mesh-tab: fix touch rotation 4.0 inch display

* Mesh-Tab platformio: 4.0inch: increase SPI frequency to max

* mesh-tab: fix rotation for 3.5 IPS capacitive display

* mesh-tab: fix rotation for 3.2 IPS capacitive display

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2025-01-11 05:52:28 -06:00
Tom Fifield 46ea39af45 Quote filename in device-install.sh (#5814)
Without these quotes, a filename with spaces would be interpreted as
different arguments.

Thanks to @Hnikar-az for the report.

fixes https://github.com/meshtastic/firmware/issues/5795
2025-01-11 10:10:04 +01:00
Thomas Göttgens 25a5f178e1 remove ethernet code from this variant, remove unused radio chip code (#5810)
* remove ethernet code from this variant, remove unused radio chip code

* remove ethernet lib too, pin onewire library to release hash
2025-01-11 10:43:48 +08:00
Austin c144ee77a7 GitHub Actions: Fix meshtastic display issue in logs (#5811) 2025-01-10 19:46:12 -06:00
Austin b62bdbc46a meshtasticd-debian: Auto-Publish to OBS (#5791) 2025-01-11 09:03:29 +08:00
Ben Meadors f18a92e8c5 Don't check for node channels on broadcast address (#5804) 2025-01-10 18:46:26 +08:00
Bernd Giesecke 2e44de262e Add GPS capability to RAK2560 (RAKwireless WisMesh Hub) (#5797)
* Add GPS to RAK2560

* Add GPS to RAK2560
2025-01-09 19:20:38 -06:00
Eric Severance 1d756ae574 Fix potential memory leak in AtakPluginModule (#5803) 2025-01-10 08:25:25 +08:00
Austin 8aac9f2e8e GH Actions: Update Release action, clarify versioning (#5794) 2025-01-08 20:43:24 -06:00
Ben Meadors 33e5a04508 Don't update to the latest ref on non-master branches 2025-01-07 20:02:47 -06:00
Austin 6cf3485d07 meshtasticd-debian: Fix versioning compliance, add OBS (#5785) 2025-01-07 17:16:56 -06:00
9421eba027 Fix build for Pico2 RP2350 platform. (#5783)
* Fix LED pinout for T-Echo board marked v1.0, date 2021-6-28

* Merge PR #420

* Fixed double and missing Default class.

* Use correct format specifier and fixed typo.

* Removed duplicate code.

* Fix error: #if with no expression

* Fix warning: extra tokens at end of #endif directive.

* Fix antenna switching logic. Complementary-pin control logic is required on the rp2040-lora board.

* Fix deprecated macros.

* Set RP2040 in dormant mode when deep sleep is triggered.

* Fix array out of bounds read.

* Admin key count needs to be set otherwise the key will be zero loaded after reset.

* Don't reset the admin key size when loading defaults. Preserve an existing key in config if possible.

* Remove log spam when reading INA voltage sensor.

* Remove static declaration for admin keys from userPrefs.h. Load hard coded admin keys in case config file has empty slots.

* Removed newlines from log.

* Fix issue #5665.

* Fix build for Pico2 RP2350 platform.

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
2025-01-07 09:57:42 -06:00
Eric Severance 27fbfd03d6 Add unit tests for MQTT (#5724)
* Add unit tests for MQTT

* Test received fields
2025-01-07 07:10:42 -06:00
Marco Veneziano 353740623f Increase esp32c3 stability over wifi (#5774)
* Increase esp32c3 stability over wifi

* only apply the fix on esp32c3 based nodes
2025-01-07 07:09:51 -06:00
Austin cdcbf4c615 Small fix: debian, curl follow redirs (#5780) 2025-01-07 10:51:50 +08:00
Jonathan Bennett 395469d20a As Per XKCD #1168 2025-01-06 19:59:02 -06:00
Austin 86170171a7 meshtasticd-debian: Include web components (#5778) 2025-01-06 19:25:05 -06:00
Austin 57766d47a8 GitHub Actions: Trigger PPA stable builds upon release (#5777) 2025-01-06 18:45:59 -06:00
Austin e5dbcf5bce meshtasticd-debian: parameterize target PPA (#5776) 2025-01-06 16:20:05 -06:00
Jonathan Bennett 4c3a3ca47d Specify the *correct* scons version 2025-01-06 13:02:53 -06:00
Jonathan Bennett 78371dfdb7 Add PPA to nightly 2025-01-06 12:26:17 -06:00
Jonathan Bennett ca32889893 Specify scons version 2025-01-06 12:23:08 -06:00
Thomas Göttgens 35cd600c54 update to 7.1.2 and remove the obsolete default_envs. (#5771) 2025-01-06 17:08:12 +01:00
isseysandeiandBuildTools 70076a4b27 Improved Power Telemetry page readability even more (#5770)
* increased buffer size to 1024

* better readability

* better readability 2

---------

Co-authored-by: BuildTools <unconfigured@null.spigotmc.org>
2025-01-06 09:14:52 -06:00
Jonathan Bennett f1a8900288 Don't push to PPA for every commit 2025-01-05 23:50:32 -06:00
Jonathan Bennett 16bc89ea57 Explicitly install tools-scons 2025-01-05 22:23:34 -06:00
Jonathan Bennett 6edf74e8f1 Tab not spaces 2025-01-05 19:58:34 -06:00
Jonathan Bennett 7f280dd556 Hide pio folder in a tarball to preserve .git folders 2025-01-05 19:38:08 -06:00
Jonathan Bennett 2396aa77ca don't run the clean step 2025-01-05 19:03:44 -06:00
Jonathan Bennett d3cbbfd345 Try adding tar-ignore to preserve .git directories 2025-01-05 18:59:14 -06:00
isseysandei c003ab0eee Improved readability of Power Telemetry page (#5746)
* increased buffer size to 1024

* better readability
2025-01-05 18:58:10 -06:00
Ben Meadors 4fcf7fe027 Revert "Explicitly set CAD symbols, improve slot time calculation and adjust …" (#5765)
This reverts commit 9cc79b1d1e.
2025-01-05 18:55:55 -06:00
GUVWAFandBen Meadors 9cc79b1d1e Explicitly set CAD symbols, improve slot time calculation and adjust CW size accordingly (#5749)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-01-05 18:55:20 -06:00
Austin 403fa15a3f meshtasticd-debian: Include run in version (#5762) 2025-01-05 15:55:04 -06:00
Austin b0087fd328 meshtasticd-debian: Include core_dir in sdeb (#5761) 2025-01-05 15:26:31 -06:00
Austin fb74e1d182 meshtasticd-debian: set PLATFORMIO_CORE_DIR (#5760) 2025-01-05 15:00:01 -06:00
Austin 29a7866fc1 Use jbennett for gpg email (#5759) 2025-01-05 14:26:56 -06:00
Austin 2f552d15e5 meshtasticd-debian: Cleanup debian versioning (#5758) 2025-01-05 14:14:47 -06:00
Austin 892e0922ff meshtastic-debian: --create requires missing changelog (#5757) 2025-01-05 13:37:15 -06:00
Austin d21d6c1301 meshtasticd-debian: Build multiple series (#5756) 2025-01-05 13:24:05 -06:00
github-actions[bot]andthebentern 031aecac66 [create-pull-request] automated change (#5755)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-01-05 13:14:56 -06:00
Austin 7c10caa78b meshtastic-debian: publish with dput (#5753) 2025-01-05 12:31:01 -06:00
Austin 5196ee39cb meshtasticd: debian checkout to subdir (#5752) 2025-01-05 11:44:05 -06:00
Austin 02a5a91da0 meshtasticd debian: secrets perms (#5751) 2025-01-05 11:30:43 -06:00
Austin b2a89b8136 meshtasticd: gpg tomfoolery (#5750) 2025-01-05 11:06:00 -06:00
Austin 15019e8663 meshtasticd: deps for debian_build_src (#5748) 2025-01-05 10:37:38 -06:00
Austin 35814fd4bc meshtasticd debian: split libs for PPA (#5745) 2025-01-05 10:22:11 -06:00
Jonathan Bennett 6aabbedc00 Last Ditch effort for PPA build 2025-01-04 15:41:49 -06:00
Jonathan Bennett eb72ee0fc1 don't use "source" for deb builds 2025-01-04 14:51:36 -06:00
Jonathan Bennett 7480378aed Update debian build rules 2025-01-04 14:37:13 -06:00
Jonathan Bennett 7c21d7761c Move the RFM9x to config.available (#5742) 2025-01-04 14:12:54 -06:00
Austin 2c654454cf meshtasticd debian source package (#5741) 2025-01-04 13:39:37 -06:00
Alex Markley 9afadde2f4 Add support for LS20031 GPS module. (#5718)
Hardware documentation referenced:
- https://cdn.sparkfun.com/datasheets/GPS/LS20030~3_datasheet_v1.3.pdf
- https://cdn-shop.adafruit.com/datasheets/PMTK%20command%20packet-Complete-C39-A01.pdf
2025-01-04 07:00:39 +08:00
isseysandei 66a961cb75 increased buffer size to 1024 (#5733) 2025-01-03 11:35:34 -06:00
e1aaafb77a Cherrypick "add more locking for shared SPI devices (#5595) " (#5728)
* add more locking for shared SPI devices (#5595)

* add more locking for shared SPI devices
* call initSPI before the lock is used
* remove old one
* don't double lock
* Add missing unlock
* More missing unlocks
* Add locks to SafeFile, remove from `readcb`, introduce some LockGuards
* fix lock in setupSDCard()
* pull radiolib trunk with SPI-CS fixes
* change ContentHandler to Constructor type locks, where applicable

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: GUVWAF <thijs@havinga.eu>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>

* mesh-tab: lower I2C touch frequency

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: GUVWAF <thijs@havinga.eu>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
2025-01-03 10:05:26 +08:00
9d710041c4 Add MESHTASTIC_EXCLUDE_SOCKETAPI (#5729)
MESHTASTIC_EXCLUDE_SOCKETAPI disables the API Server when set.

Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: GUVWAF <thijs@havinga.eu>
2025-01-03 09:01:10 +08:00
Eric Severance b41efc17ba Disable BUILD_EPOCH for unit tests (#5723) 2025-01-02 10:32:38 -06:00
Thomas Göttgens 9bda080e3d evaluate GPS_THREAD_INTERVAL after variant file (#5722) 2025-01-02 16:05:12 +01:00
Eric Severance 9f7cbf1b4f MQTT unit test can inject WiFiClient (#5716) 2025-01-02 19:32:39 +08:00
Eric Severance 93e2bc7058 Use relative paths in coverage info files (#5721) 2025-01-02 14:53:07 +08:00
Eric Severance 7a1c32b89a test_native.yaml checks out code for the PR. (#5720) 2025-01-02 12:41:13 +08:00
Eric Severance 88d8ab53c8 Disable coverage generation (#5719)
* Disable coverage generation

* Comment a bit more of the report generation
2025-01-02 11:37:11 +08:00
Eric Severance 183f68ba00 Run tests as part of the main CI (#5712)
* Create an shared action to install native dependecies

* Create a workflow for running native tests

* Artifact names contain version

* Add test-native to main_matrix.yml

* No permission are required for test_native.yml

* Add permissions for dorny/test-reporter

* No permissions when running tests

* s/Generate Reports/Generate Test Reports/
2025-01-01 19:26:12 -06:00
Eric Severance 9f32995d7f Implement MeshModule destructor (#5714) 2025-01-01 19:25:01 -06:00
Eric Severance c2c06ed0ad Move DecodedServiceEnvelope into its own file (#5715) 2025-01-02 08:40:14 +08:00
Jonathan Bennett 9abd07bb05 Set ch341 MAD Address via sprintf formatting (#5713) 2025-01-01 09:06:38 +11:00
Tom Fifield fdcc0e12aa Minor TFT branch synch (#5706) 2024-12-31 10:15:01 -06:00
Thomas Göttgens 8b34c4ff05 fix misc cppcheck things and compile time warnings (#5710) 2024-12-31 15:58:59 +01:00
Bernd Giesecke 9af8c58c40 Add Ethernet RAK13800 support to RAK11310 (#5707) 2024-12-31 13:36:49 +01:00
Jonathan BennettandTom Fifield 58ebd5bcdb Actually use the MAC address from a ch341 (#5704)
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2024-12-31 17:46:03 +11:00
Tom Fifieldandmverch67 d1e5be515a cherry-pick: disable BT when TFT in use (#5705)
* disable BT when TFT in use

* add comment BT disable

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2024-12-30 20:00:37 -06:00
Tom Fifield f9e71c3fb9 Remove an \n (#5703) 2024-12-30 19:01:21 -06:00
Tom Fifieldandmverch67 bfcfca2e46 add spi_host + missing rotation (#5691)
Co-authored-by: mverch67 <manuel.verch@gmx.de>
2024-12-30 18:18:29 -06:00
Thomas Göttgens a2a6b236b7 support indicator sensors through Rp2040 serial (#5696)
* support indicator sensors through Rp2040 serial

* disable excessive debug printing
2024-12-30 21:28:31 +01:00
Tom Fifieldandmverch67 3c7053c66a reference seeed indicator fix commit arduino-esp32 (#5692)
Co-authored-by: mverch67 <manuel.verch@gmx.de>
2024-12-29 15:23:46 +11:00
Tom Fifield e45c0e4d40 Minor cppcheck fixes (#5689)
* In graphics/Screen.cpp, a copy/paste error to do with hearts
* In mesh/http/ContentHandler.cpp, an unused variable
* in mqtt/MQTT.cpp, remove unneded logic " '!A || (A && B)' is equivalent to '!A || B'"
2024-12-28 18:56:05 -06:00
Jonathan Bennett 57a9a5ca21 Another Valgrind fix (#5690) 2024-12-28 18:48:54 -06:00
github-actions[bot]andthebentern 6749367a73 [create-pull-request] automated change (#5686)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2024-12-28 18:23:56 -06:00
Jonathan Bennett a8e2446f00 Initialize array to 0s (#5688) 2024-12-29 11:05:25 +11:00
261 changed files with 7771 additions and 2563 deletions
+52
View File
@@ -0,0 +1,52 @@
# This container is used to build Meshtastic with the libraries required by the fuzzer.
# ClusterFuzzLite starts the container, runs the build.sh script, and then exits.
# As this is not a long running service, health-checks are not required. ClusterFuzzLite
# also only works if the user remains unchanged from the base image (it expects to run
# as root).
# trunk-ignore-all(trivy/DS026): No healthcheck is needed for this builder container
# trunk-ignore-all(checkov/CKV_DOCKER_2): No healthcheck is needed for this builder container
# trunk-ignore-all(checkov/CKV_DOCKER_3): We must run as root for this container
# 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
FROM gcr.io/oss-fuzz-base/base-builder:v1
ENV PIP_ROOT_USER_ACTION=ignore
# trunk-ignore(hadolint/DL3008): apt packages are not pinned.
# trunk-ignore(terrascan/AC_DOCKER_0002): apt packages are not pinned.
RUN apt-get update && apt-get install --no-install-recommends -y \
cmake git zip libgpiod-dev libbluetooth-dev libi2c-dev \
libunistring-dev libmicrohttpd-dev libgnutls28-dev libgcrypt20-dev \
libusb-1.0-0-dev libssl-dev pkg-config && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
pip install --no-cache-dir -U \
platformio==6.1.16 \
grpcio-tools==1.68.1 \
meshtastic==2.5.9
# Ugly hack to avoid clang detecting a conflict between the math "log" function and the "log" function in framework-portduino/cores/portduino/logging.h
RUN sed -i -e 's/__MATHCALL_VEC (log,, (_Mdouble_ __x));//' /usr/include/x86_64-linux-gnu/bits/mathcalls.h
# A few dependencies are too old on the base-builder image. More recent versions are built from source.
WORKDIR $SRC
RUN git config --global advice.detachedHead false && \
git clone --depth 1 --branch 0.8.0 https://github.com/jbeder/yaml-cpp.git && \
git clone --depth 1 --branch v2.3.3 https://github.com/babelouest/orcania.git && \
git clone --depth 1 --branch v1.4.20 https://github.com/babelouest/yder.git && \
git clone --depth 1 --branch v2.7.15 https://github.com/babelouest/ulfius.git
COPY ./.clusterfuzzlite/build.sh $SRC/
WORKDIR $SRC/firmware
COPY . $SRC/firmware/
# https://docs.platformio.org/en/latest/envvars.html
ENV PLATFORMIO_CORE_DIR=$SRC/pio/core \
PLATFORMIO_LIBDEPS_DIR=$SRC/pio/libdeps \
PLATFORMIO_PACKAGES_DIR=$SRC/pio/packages \
PLATFORMIO_SETTING_ENABLE_CACHE=No \
PIO_ENV=buildroot
RUN platformio pkg install --environment $PIO_ENV
+59
View File
@@ -0,0 +1,59 @@
# ClusterFuzzLite for Meshtastic
This directory contains the fuzzer implementation for Meshtastic using the ClusterFuzzLite framework.
See the [ClusterFuzzLite documentation](https://google.github.io/clusterfuzzlite/) for more details.
## Running locally
ClusterFuzzLite uses the OSS-Fuzz toolchain. To build the fuzzer manually, first grab a copy of OSS-Fuzz.
```shell
git clone https://github.com/google/oss-fuzz.git
cd oss-fuzz
```
To build the fuzzer, run:
```shell
python3 infra/helper.py build_image --external $PATH_TO_MESHTASTIC_FIRMWARE_DIRECTORY
python3 infra/helper.py build_fuzzers --external $PATH_TO_MESHTASTIC_FIRMWARE_DIRECTORY --sanitizer address
```
To run the fuzzer, run:
```shell
python3 infra/helper.py run_fuzzer --external --corpus-dir=<path-to-temp-corpus-dir> $PATH_TO_MESHTASTIC_FIRMWARE_DIRECTORY router_fuzzer
```
More background on these commands can be found in the
[ClusterFuzzLite documentation](https://google.github.io/clusterfuzzlite/build-integration/#testing-locally).
## router_fuzzer.cpp
This fuzzer submits MeshPacket protos to the `Router::enqueueReceivedMessage` method. It takes the binary
data from the fuzzer and decodes that data to a MeshPacket using nanopb. A few fields in
the MeshPacket are modified by the fuzzer.
- If the `to` field is 0, it will be replaced with the NodeID of the running node.
- If the `from` field is 0, it will be replaced with the NodeID of the running node.
- If the `id` field is 0, it will be replaced with an incrementing counter value.
- If the `pki_encrypted` field is true, the `public_key` field will be populated with the first admin key.
The `router_fuzzer_seed_corpus.py` file contains a list of MeshPackets. It is run from inside build.sh and
writes the binary MeshPacket protos to files. These files are use used by the fuzzer as its initial seed data,
helping the fuzzer to start off with a few known inputs.
### Interpreting a fuzzer crash
If the fuzzer crashes, it'll write the input bytes used for the test case to a file and notify about the
location of that file. The contents of the file are a binary serialized MeshPacket protobuf. The following
snippet of Python code can be used to parse the file into a human readable form.
```python
from meshtastic.protobuf import mesh_pb2
mesh_pb2.MeshPacket.FromString(open("crash-XXXX-file", "rb").read())
```
Consider adding any such crash results to the `router_fuzzer_seed_corpus.py` file to ensure there a isn't
a future regression for that crash test case.
+71
View File
@@ -0,0 +1,71 @@
#!/bin/bash -eu
# Build Meshtastic and a few needed dependencies using clang++
# and the OSS-Fuzz required build flags.
env
cd "$SRC"
NPROC=$(nproc || echo 1)
LDFLAGS=-lpthread cmake -S "$SRC/yaml-cpp" -B "$WORK/yaml-cpp/$SANITIZER" \
-DBUILD_SHARED_LIBS=OFF
cmake --build "$WORK/yaml-cpp/$SANITIZER" -j "$NPROC"
cmake --install "$WORK/yaml-cpp/$SANITIZER" --prefix /usr
cmake -S "$SRC/orcania" -B "$WORK/orcania/$SANITIZER" \
-DBUILD_STATIC=ON
cmake --build "$WORK/orcania/$SANITIZER" -j "$NPROC"
cmake --install "$WORK/orcania/$SANITIZER" --prefix /usr
cmake -S "$SRC/yder" -B "$WORK/yder/$SANITIZER" \
-DBUILD_STATIC=ON -DWITH_JOURNALD=OFF
cmake --build "$WORK/yder/$SANITIZER" -j "$NPROC"
cmake --install "$WORK/yder/$SANITIZER" --prefix /usr
cmake -S "$SRC/ulfius" -B "$WORK/ulfius/$SANITIZER" \
-DBUILD_STATIC=ON -DWITH_JANSSON=OFF -DWITH_CURL=OFF -DWITH_WEBSOCKET=OFF
cmake --build "$WORK/ulfius/$SANITIZER" -j "$NPROC"
cmake --install "$WORK/ulfius/$SANITIZER" --prefix /usr
cd "$SRC/firmware"
PLATFORMIO_EXTRA_SCRIPTS=$(echo -e "pre:.clusterfuzzlite/platformio-clusterfuzzlite-pre.py\npost:.clusterfuzzlite/platformio-clusterfuzzlite-post.py")
STATIC_LIBS=$(pkg-config --libs --static libulfius openssl libgpiod yaml-cpp bluez --silence-errors)
export PLATFORMIO_EXTRA_SCRIPTS
export STATIC_LIBS
export PLATFORMIO_WORKSPACE_DIR="$WORK/pio/$SANITIZER"
export TARGET_CC=$CC
export TARGET_CXX=$CXX
export TARGET_LD=$CXX
export TARGET_AR=llvm-ar
export TARGET_AS=llvm-as
export TARGET_OBJCOPY=llvm-objcopy
export TARGET_RANLIB=llvm-ranlib
mkdir -p "$OUT/lib"
cp .clusterfuzzlite/*_fuzzer.options "$OUT/"
for f in .clusterfuzzlite/*_fuzzer.cpp; do
fuzzer=$(basename "$f" .cpp)
cp -f "$f" src/fuzzer.cpp
pio run -vvv --environment "$PIO_ENV"
program="$PLATFORMIO_WORKSPACE_DIR/build/$PIO_ENV/program"
cp "$program" "$OUT/$fuzzer"
# Copy shared libraries used by the fuzzer.
read -d '' -ra shared_libs < <(ldd "$program" | sed -n 's/[^=]\+=> \([^ ]\+\).*/\1/p') || true
cp -f "${shared_libs[@]}" "$OUT/lib/"
# Build the initial fuzzer seed corpus.
corpus_name="${fuzzer}_seed_corpus"
corpus_generator="$PWD/.clusterfuzzlite/${corpus_name}.py"
if [[ -f $corpus_generator ]]; then
mkdir "$corpus_name"
pushd "$corpus_name"
python3 "$corpus_generator"
popd
zip -D "$OUT/${corpus_name}.zip" "$corpus_name"/*
fi
done
@@ -0,0 +1,35 @@
"""PlatformIO build script (post: runs after other Meshtastic scripts)."""
import os
import shlex
from SCons.Script import DefaultEnvironment
env = DefaultEnvironment()
# Remove any static libraries from the LIBS environment. Static libraries are
# handled in platformio-clusterfuzzlite-pre.py.
static_libs = set(lib[2:] for lib in shlex.split(os.getenv("STATIC_LIBS")))
env.Replace(
LIBS=[
lib for lib in env["LIBS"] if not (isinstance(lib, str) and lib in static_libs)
],
)
# FrameworkArduino/portduino/main.cpp contains the "main" function the binary.
# The fuzzing framework also provides a "main" function and needs to be run
# before Meshtastic is started. We rename the "main" function for Meshtastic to
# "portduino_main" here so that it can be called inside the fuzzer.
env.AddPostAction(
"$BUILD_DIR/FrameworkArduino/portduino/main.cpp.o",
env.VerboseAction(
" ".join(
[
"$OBJCOPY",
"--redefine-sym=main=portduino_main",
"$BUILD_DIR/FrameworkArduino/portduino/main.cpp.o",
]
),
"Renaming main symbol to portduino_main",
),
)
@@ -0,0 +1,52 @@
"""PlatformIO build script (pre: runs before other Meshtastic scripts).
ClusterFuzzLite executes in a different container from the build. During the build,
attempt to link statically to as many dependencies as possible. For dependencies that
do not have static libraries, the shared library files are copied to the output
directory by the build.sh script.
"""
import glob
import os
import shlex
from SCons.Script import DefaultEnvironment, Literal
env = DefaultEnvironment()
cxxflags = shlex.split(os.getenv("CXXFLAGS"))
sanitizer_flags = shlex.split(os.getenv("SANITIZER_FLAGS"))
lib_fuzzing_engine = shlex.split(os.getenv("LIB_FUZZING_ENGINE"))
statics = glob.glob("/usr/lib/lib*.a") + glob.glob("/usr/lib/*/lib*.a")
no_static = set(("-ldl",))
def replaceStatic(lib):
"""Replace -l<libname> with the static .a file for the library."""
if not lib.startswith("-l") or lib in no_static:
return lib
static_name = f"/lib{lib[2:]}.a"
static = [s for s in statics if s.endswith(static_name)]
if len(static) == 1:
return static[0]
return lib
# Setup the environment for building with Clang and the OSS-Fuzz required build flags.
env.Append(
CFLAGS=os.getenv("CFLAGS"),
CXXFLAGS=cxxflags,
LIBSOURCE_DIRS=["/usr/lib/x86_64-linux-gnu"],
LINKFLAGS=cxxflags
+ sanitizer_flags
+ lib_fuzzing_engine
+ ["-stdlib=libc++", "-std=c++17"],
_LIBFLAGS=[replaceStatic(s) for s in shlex.split(os.getenv("STATIC_LIBS"))]
+ [
"/usr/lib/x86_64-linux-gnu/libunistring.a", # Needs to be at the end.
# Find the shared libraries in a subdirectory named lib
# within the same directory as the binary.
Literal("-Wl,-rpath,$ORIGIN/lib"),
"-Wl,-z,origin",
],
)
+1
View File
@@ -0,0 +1 @@
language: c++
+206
View File
@@ -0,0 +1,206 @@
// Fuzzer implementation that sends MeshPackets to Router::enqueueReceivedMessage.
#include <condition_variable>
#include <cstdlib>
#include <mutex>
#include <pb_decode.h>
#include <stdexcept>
#include <string>
#include <thread>
#include "PortduinoGPIO.h"
#include "PortduinoGlue.h"
#include "PowerFSM.h"
#include "mesh/MeshTypes.h"
#include "mesh/NodeDB.h"
#include "mesh/Router.h"
#include "mesh/TypeConversions.h"
#include "mesh/mesh-pb-constants.h"
namespace
{
constexpr uint32_t nodeId = 0x12345678;
// Set to true when lateInitVariant finishes. Used to ensure lateInitVariant was called during startup.
bool hasBeenConfigured = false;
// These are used to block the Arduino loop() function until a fuzzer input is ready. This is
// an optimization that prevents a sleep from happening before the loop is run. The Arduino loop
// function calls loopCanSleep() before sleeping. loopCanSleep is implemented here in the fuzzer
// and blocks until runLoopOnce() is called to signal for the loop to run.
bool fuzzerRunning = false; // Set to true once LLVMFuzzerTestOneInput has started running.
bool loopCanRun = true; // The main Arduino loop() can run when this is true.
bool loopIsWaiting = false; // The main Arduino loop() is waiting to be signaled to run.
bool loopShouldExit = false; // Indicates that the main Arduino thread should exit by throwing ShouldExitException.
std::mutex loopLock;
std::condition_variable loopCV;
std::thread meshtasticThread;
// This exception is thrown when the portuino main thread should exit.
class ShouldExitException : public std::runtime_error
{
public:
using std::runtime_error::runtime_error;
};
// Start the loop for one test case and wait till the loop has completed. This ensures fuzz
// test cases do not overlap with one another. This helps the fuzzer attribute a crash to the
// single, currently running, test case.
void runLoopOnce()
{
realHardware = true; // Avoids delay(100) within portduino/main.cpp
std::unique_lock<std::mutex> lck(loopLock);
fuzzerRunning = true;
loopCanRun = true;
loopCV.notify_one();
loopCV.wait(lck, [] { return !loopCanRun && loopIsWaiting; });
}
} // namespace
// Called in the main Arduino loop function to determine if the loop can delay/sleep before running again.
// We use this as a way to block the loop from sleeping and to start the loop function immediately when a
// fuzzer input is ready.
bool loopCanSleep()
{
std::unique_lock<std::mutex> lck(loopLock);
loopIsWaiting = true;
loopCV.notify_one();
loopCV.wait(lck, [] { return loopCanRun || loopShouldExit; });
loopIsWaiting = false;
if (loopShouldExit)
throw ShouldExitException("exit");
if (!fuzzerRunning)
return true; // The loop can sleep before the fuzzer starts.
loopCanRun = false; // Only run the loop once before waiting again.
return false;
}
// Called just prior to starting Meshtastic. Allows for setting config values before startup.
void lateInitVariant()
{
settingsMap[logoutputlevel] = level_error;
channelFile.channels[0] = meshtastic_Channel{
.has_settings = true,
.settings =
meshtastic_ChannelSettings{
.psk = {.size = 1, .bytes = {/*defaultpskIndex=*/1}},
.name = "LongFast",
.uplink_enabled = true,
.has_module_settings = true,
.module_settings = {.position_precision = 16},
},
.role = meshtastic_Channel_Role_PRIMARY,
};
config.security.admin_key[0] = {
.size = 32,
.bytes = {0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a,
0x4c, 0xf6, 0x1a, 0x96, 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c},
};
config.security.admin_key_count = 1;
config.lora.region = meshtastic_Config_LoRaConfig_RegionCode_US;
moduleConfig.has_mqtt = true;
moduleConfig.mqtt = meshtastic_ModuleConfig_MQTTConfig{
.enabled = true,
.proxy_to_client_enabled = true,
};
moduleConfig.has_store_forward = true;
moduleConfig.store_forward = meshtastic_ModuleConfig_StoreForwardConfig{
.enabled = true,
.history_return_max = 4,
.history_return_window = 600,
.is_server = true,
};
meshtastic_Position fixedGPS = meshtastic_Position{
.has_latitude_i = true,
.latitude_i = static_cast<uint32_t>(1 * 1e7),
.has_longitude_i = true,
.longitude_i = static_cast<uint32_t>(3 * 1e7),
.has_altitude = true,
.altitude = 64,
.location_source = meshtastic_Position_LocSource_LOC_MANUAL,
};
nodeDB->setLocalPosition(fixedGPS);
config.has_position = true;
config.position.fixed_position = true;
meshtastic_NodeInfoLite *info = nodeDB->getMeshNode(nodeDB->getNodeNum());
info->has_position = true;
info->position = TypeConversions::ConvertToPositionLite(fixedGPS);
hasBeenConfigured = true;
}
extern "C" {
int portduino_main(int argc, char **argv); // Renamed "main" function from Meshtastic binary.
// Start Meshtastic in a thread and wait till it has reached the ON state.
int LLVMFuzzerInitialize(int *argc, char ***argv)
{
settingsMap[maxtophone] = 5;
meshtasticThread = std::thread([program = *argv[0]]() {
char nodeIdStr[12];
strcpy(nodeIdStr, std::to_string(nodeId).c_str());
int argc = 7;
char *argv[] = {program, "-d", "/tmp/meshtastic", "-h", nodeIdStr, "-p", "0", nullptr};
try {
portduino_main(argc, argv);
} catch (const ShouldExitException &) {
}
});
std::atexit([] {
{
const std::lock_guard<std::mutex> lck(loopLock);
loopShouldExit = true;
loopCV.notify_one();
}
meshtasticThread.join();
});
// Wait for startup.
for (int i = 1; i < 20; ++i) {
if (powerFSM.getState() == &stateON) {
assert(hasBeenConfigured);
assert(router);
assert(nodeDB);
return 0;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 1;
}
// This is the main entrypoint for the fuzzer (the fuzz target). The fuzzer will provide an array of bytes to be
// interpreted by this method. To keep things simple, the bytes are interpreted as a binary serialized MeshPacket
// proto. Any crashes discovered by the fuzzer will be written to a file. Unserialize that file to print the MeshPacket
// that caused the failure.
//
// This guide provides best practices for writing a fuzzer target.
// https://github.com/google/fuzzing/blob/master/docs/good-fuzz-target.md
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t length)
{
meshtastic_MeshPacket p = meshtastic_MeshPacket_init_default;
pb_istream_t stream = pb_istream_from_buffer(data, length);
// Ignore any inputs that fail to decode or have fields set that are not transmitted over LoRa.
if (!pb_decode(&stream, &meshtastic_MeshPacket_msg, &p) || p.rx_time || p.rx_snr || p.priority || p.rx_rssi || p.delayed ||
p.public_key.size || p.next_hop || p.relay_node || p.tx_after)
return -1; // Reject: The input will not be added to the corpus.
if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
meshtastic_Data d;
stream = pb_istream_from_buffer(p.decoded.payload.bytes, p.decoded.payload.size);
if (!pb_decode(&stream, &meshtastic_Data_msg, &d))
return -1; // Reject: The input will not be added to the corpus.
}
// Provide default values for a few fields so the fuzzer doesn't need to guess them.
if (p.from == 0)
p.from = nodeDB->getNodeNum();
if (p.to == 0)
p.to = nodeDB->getNodeNum();
static uint32_t packetId = 0;
if (p.id == 0)
p.id == ++packetId;
if (p.pki_encrypted && config.security.admin_key_count)
memcpy(&p.public_key, &config.security.admin_key[0], sizeof(p.public_key));
router->enqueueReceivedMessage(packetPool.allocCopy(p));
runLoopOnce();
return 0; // Accept: The input may be added to the corpus.
}
}
+2
View File
@@ -0,0 +1,2 @@
[libfuzzer]
max_len=256
@@ -0,0 +1,168 @@
"""Generate an initial set of MeshPackets.
The fuzzer uses these MeshPackets as an initial seed of test candidates.
It's also good to add any previously discovered crash test cases to this list
to avoid future regressions.
If left unset, the following values will be automatically set by the fuzzer.
- to: automatically set to the running node's NodeID
- from: automatically set to the running node's NodeID
- id: automatically set to the value of an incrementing counter
Additionally, if `pki_encrypted` is populated in the packet, the first admin key
will be copied into the `public_key` field.
"""
import base64
from meshtastic import BROADCAST_NUM
from meshtastic.protobuf import (
admin_pb2,
atak_pb2,
mesh_pb2,
portnums_pb2,
telemetry_pb2,
)
def From(node: int = 9):
"""Return a dict suitable for **kwargs for populating the 'from' field.
'from' is a reserved keyword in Python. It can't be used directly as an
argument to the MeshPacket constructor. Rather **From() can be used as
the final argument to provide the from node as a **kwarg.
Defaults to 9 if no value is provided.
"""
return {"from": node}
packets = (
(
"position",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.POSITION_APP,
payload=mesh_pb2.Position(
latitude_i=int(1 * 1e7),
longitude_i=int(2 * 1e7),
altitude=5,
precision_bits=32,
).SerializeToString(),
),
to=BROADCAST_NUM,
**From(),
),
),
(
"telemetry",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.TELEMETRY_APP,
payload=telemetry_pb2.Telemetry(
time=1736192207,
device_metrics=telemetry_pb2.DeviceMetrics(
battery_level=101,
channel_utilization=8,
air_util_tx=2,
uptime_seconds=42,
),
).SerializeToString(),
),
to=BROADCAST_NUM,
**From(),
),
),
(
"text",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.TEXT_MESSAGE_APP,
payload=b"Hello world",
),
to=BROADCAST_NUM,
**From(),
),
),
(
"user",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.NODEINFO_APP,
payload=mesh_pb2.User(
id="!00000009",
long_name="Node 9",
short_name="N9",
macaddr=b"\x00\x00\x00\x00\x00\x09",
hw_model=mesh_pb2.HardwareModel.RAK4631,
public_key=base64.b64decode(
"L0ih/6F41itofdE8mYyHk1SdfOJ/QRM1KQ+pO4vEEjQ="
),
).SerializeToString(),
),
**From(),
),
),
(
"traceroute",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.TRACEROUTE_APP,
payload=mesh_pb2.RouteDiscovery(
route=[10],
).SerializeToString(),
),
**From(),
),
),
(
"routing",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.ROUTING_APP,
payload=mesh_pb2.Routing(
error_reason=mesh_pb2.Routing.NO_RESPONSE,
).SerializeToString(),
),
**From(),
),
),
(
"admin",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.ADMIN_APP,
payload=admin_pb2.AdminMessage(
get_owner_request=True,
).SerializeToString(),
),
pki_encrypted=True,
**From(),
),
),
(
"atak",
mesh_pb2.MeshPacket(
decoded=mesh_pb2.Data(
portnum=portnums_pb2.PortNum.ATAK_PLUGIN,
payload=atak_pb2.TAKPacket(
is_compressed=True,
# Note, the strings are not valid for a compressed message, but will
# give the fuzzer a starting point.
contact=atak_pb2.Contact(
callsign="callsign", device_callsign="device_callsign"
),
chat=atak_pb2.GeoChat(
message="message", to="to", to_callsign="to_callsign"
),
).SerializeToString(),
),
**From(),
),
),
)
for name, packet in packets:
with open(f"{name}.MeshPacket", "wb") as f:
f.write(packet.SerializeToString())
+1
View File
@@ -0,0 +1 @@
.gitignore
+8 -2
View File
@@ -68,6 +68,12 @@ runs:
sed -i '/DDEBUG_HEAP/d' ${INI_FILE}
done
- name: PlatformIO ${{ inputs.arch }} download cache
uses: actions/cache@v4
with:
path: ~/.platformio/.cache
key: pio-cache-${{ inputs.arch }}-${{ hashFiles('.github/actions/**', '**.ini') }}
- name: Build ${{ inputs.board }}
shell: bash
run: ${{ inputs.build-script-path }} ${{ inputs.board }}
@@ -83,13 +89,13 @@ runs:
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
name: firmware-${{ inputs.arch }}-${{ inputs.board }}-${{ steps.version.outputs.long }}.zip
overwrite: true
path: |
${{ inputs.artifact-paths }}
+5 -8
View File
@@ -20,19 +20,16 @@ runs:
shell: bash
run: |
sudo apt-get -y update --fix-missing
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev lsb-release
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
# - name: Cache python libs
# uses: actions/cache@v4
# id: cache-pip # needed in if test
# with:
# path: ~/.cache/pip
# key: ${{ runner.os }}-pip
cache: pip
cache-dependency-path: |
.github/actions/**
**.ini
- name: Upgrade python tools
shell: bash
+14
View File
@@ -0,0 +1,14 @@
name: Setup native build
description: Install libraries needed for building the Native/Portduino build
runs:
using: composite
steps:
- name: Setup base
id: base
uses: ./.github/actions/setup-base
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

+72
View File
@@ -0,0 +1,72 @@
name: Build Debian Source Package
on:
workflow_call:
secrets:
PPA_GPG_PRIVATE_KEY:
required: true
inputs:
series:
description: Ubuntu/Debian series to target
required: true
type: string
build_location:
description: Location where build will execute
required: true
type: string
permissions:
contents: write
packages: write
jobs:
build-debian-src:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
path: meshtasticd
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install deps
shell: bash
working-directory: meshtasticd
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y software-properties-common build-essential devscripts equivs
sudo add-apt-repository ppa:meshtastic/build-tools -y
sudo apt-get update -y --fix-missing
sudo mk-build-deps --install --remove --tool='apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes' debian/control
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
id: gpg
- name: Get release version string
working-directory: meshtasticd
run: |
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
env:
BUILD_LOCATION: ${{ inputs.build_location }}
id: version
- name: Fetch libdeps, package debian source
working-directory: meshtasticd
run: debian/ci_pack_sdeb.sh
env:
SERIES: ${{ inputs.series }}
GPG_KEY_ID: ${{ steps.gpg.outputs.keyid }}
PKG_VERSION: ${{ steps.version.outputs.deb }}
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
overwrite: true
path: |
meshtasticd_${{ steps.version.outputs.deb }}*
-51
View File
@@ -1,51 +0,0 @@
name: Build Docker
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-native:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Docker login
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/login-action@v3
with:
username: meshtastic
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
- name: Docker setup
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/setup-buildx-action@v3
- name: Docker build and push tagged versions
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: meshtastic/meshtasticd:${{ steps.version.outputs.version }}
- name: Docker build and push
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: meshtastic/meshtasticd:latest
-52
View File
@@ -1,52 +0,0 @@
name: Build Native
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-native:
runs-on: ubuntu-latest
steps:
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get update --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Native
run: bin/build-native.sh
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-native-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/meshtasticd_linux_x86_64
bin/config-dist.yaml
-52
View File
@@ -1,52 +0,0 @@
name: Build Raspbian
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-raspbian:
runs-on: [self-hosted, linux, ARM64]
steps:
- name: Install libbluetooth
shell: bash
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Raspbian
run: bin/build-native.sh
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/meshtasticd_linux_aarch64
bin/config-dist.yaml
@@ -1,52 +0,0 @@
name: Build Raspbian Arm
on: workflow_call
permissions:
contents: write
packages: write
jobs:
build-raspbian-armv7l:
runs-on: [self-hosted, linux, ARM]
steps:
- name: Install libbluetooth
shell: bash
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Raspbian
run: bin/build-native.sh
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
overwrite: true
path: |
release/meshtasticd_linux_armv7l
bin/config-dist.yaml
+51
View File
@@ -0,0 +1,51 @@
name: Daily Packaging
on:
schedule:
- cron: 0 9 * * *
workflow_dispatch:
push:
branches:
- master
paths:
- debian/**
- "*.rpkg"
- .github/workflows/nightly_packaging.yml
- .github/workflows/build_debian_src.yml
- .github/workflows/package_ppa.yml
- .github/workflows/package_obs.yml
- .github/workflows/hook_copr.yml
permissions:
contents: write
packages: write
jobs:
docker-multiarch:
uses: ./.github/workflows/docker_manifest.yml
with:
release_channel: daily
secrets: inherit
package-ppa:
strategy:
fail-fast: false
matrix:
series: [plucky, oracular, noble, jammy]
uses: ./.github/workflows/package_ppa.yml
with:
ppa_repo: ppa:meshtastic/daily
series: ${{ matrix.series }}
secrets: inherit
package-obs:
uses: ./.github/workflows/package_obs.yml
with:
obs_project: network:Meshtastic:daily
series: unstable
secrets: inherit
hook-copr:
uses: ./.github/workflows/hook_copr.yml
with:
copr_project: daily
secrets: inherit
+92
View File
@@ -0,0 +1,92 @@
name: Build Docker
# Build Docker image, push untagged (digest-only)
on:
workflow_call:
secrets:
DOCKER_FIRMWARE_TOKEN:
required: false # Only required for push
inputs:
distro:
description: Distro to target
required: true
type: string
# choices: [debian, alpine]
platform:
description: Platform to target
required: true
type: string
runs-on:
description: Runner to use
required: true
type: string
push:
description: Push images to registry
required: false
type: boolean
default: false
outputs:
digest:
description: Digest of built image
value: ${{ jobs.docker-build.outputs.digest }}
permissions:
contents: write
packages: write
jobs:
docker-build:
outputs:
digest: ${{ steps.docker_variant.outputs.digest }}
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Docker login
if: ${{ inputs.push }}
uses: docker/login-action@v3
with:
username: meshtastic
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Docker setup
uses: docker/setup-buildx-action@v3
- name: Sanitize platform string
id: sanitize_platform
# Replace slashes with underscores
run: echo "cleaned_platform=${{ inputs.platform }}" | sed 's/\//_/g' >> $GITHUB_OUTPUT
- name: Docker tag
id: meta
uses: docker/metadata-action@v5
with:
images: meshtastic/meshtasticd
tags: |
GHA-${{ steps.version.outputs.long }}-${{ inputs.distro }}-${{ steps.sanitize_platform.outputs.cleaned_platform }}
flavor: latest=false
- name: Docker build and push
uses: docker/build-push-action@v6
id: docker_variant
with:
context: .
file: |
${{ contains(inputs.distro, 'debian') && './Dockerfile' || contains(inputs.distro, 'alpine') && './alpine.Dockerfile' }}
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job
platforms: ${{ inputs.platform }}
+186
View File
@@ -0,0 +1,186 @@
name: Build Docker Multi-Arch Manifest
on:
workflow_call:
secrets:
DOCKER_FIRMWARE_TOKEN:
required: true
inputs:
release_channel:
description: Release channel to target
required: true
type: string
permissions:
contents: write
packages: write
jobs:
docker-debian-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/amd64
runs-on: ubuntu-24.04
push: true
secrets: inherit
docker-debian-arm64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/arm64
runs-on: ubuntu-24.04-arm
push: true
secrets: inherit
docker-debian-armv7:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/arm/v7
runs-on: ubuntu-24.04-arm
push: true
secrets: inherit
docker-alpine-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/amd64
runs-on: ubuntu-24.04
push: true
secrets: inherit
docker-alpine-arm64:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/arm64
runs-on: ubuntu-24.04-arm
push: true
secrets: inherit
docker-alpine-armv7:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/arm/v7
runs-on: ubuntu-24.04-arm
push: true
secrets: inherit
docker-manifest:
needs:
# Debian
- docker-debian-amd64
- docker-debian-arm64
- docker-debian-armv7
# Alpine
- docker-alpine-amd64
- docker-alpine-arm64
- docker-alpine-armv7
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
id: version
- name: Enumerate tags
shell: python
run: |
import os
short = "${{ steps.version.outputs.short }}"
long = "${{ steps.version.outputs.long }}"
release_channel = "${{ inputs.release_channel }}"
tags = {
"beta": {
"debian": [
f"{short}", f"{long}", f"{short}-beta", f"{long}-beta", "beta", "latest",
f"{short}-debian", f"{long}-debian", f"{short}-beta-debian", f"{long}-beta-debian", "beta-debian"
],
"alpine": [
f"{short}-alpine", f"{long}-alpine", f"{short}-beta-alpine", f"{long}-beta-alpine", "beta-alpine"
]
},
"alpha": {
"debian": [
f"{short}-alpha", f"{long}-alpha", "alpha",
f"{short}-alpha-debian", f"{long}-alpha-debian", "alpha-debian"
],
"alpine": [
f"{short}-alpha-alpine", f"{long}-alpha-alpine", "alpha-alpine"
]
},
"daily": {
"debian": ["daily", "daily-debian"],
"alpine": ["daily-alpine"]
}
}
with open(os.environ["GITHUB_OUTPUT"], "a") as fh:
fh.write("debian<<EOF\n")
fh.write("\n".join(tags[release_channel]["debian"]))
fh.write("\nEOF\n")
fh.write("alpine<<EOF\n")
fh.write("\n".join(tags[release_channel]["alpine"]))
fh.write("\nEOF\n")
id: tags
- name: Docker login
uses: docker/login-action@v3
with:
username: meshtastic
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
- name: Docker meta (Debian)
id: meta_debian
uses: docker/metadata-action@v5
with:
images: meshtastic/meshtasticd
tags: |
${{ steps.tags.outputs.debian }}
flavor: latest=false
- name: Create Docker manifest (Debian)
id: manifest_debian
uses: int128/docker-manifest-create-action@v2
with:
tags: |
${{ steps.meta_debian.outputs.tags }}
push: true
sources: |
meshtastic/meshtasticd@${{ needs.docker-debian-amd64.outputs.digest }}
meshtastic/meshtasticd@${{ needs.docker-debian-arm64.outputs.digest }}
meshtastic/meshtasticd@${{ needs.docker-debian-armv7.outputs.digest }}
- name: Docker meta (Alpine)
id: meta_alpine
uses: docker/metadata-action@v5
with:
images: meshtastic/meshtasticd
tags: |
${{ steps.tags.outputs.alpine }}
- name: Create Docker manifest (Alpine)
id: manifest_alpine
uses: int128/docker-manifest-create-action@v2
with:
tags: |
${{ steps.meta_alpine.outputs.tags }}
push: true
sources: |
meshtastic/meshtasticd@${{ needs.docker-alpine-amd64.outputs.digest }}
meshtastic/meshtasticd@${{ needs.docker-alpine-arm64.outputs.digest }}
meshtastic/meshtasticd@${{ needs.docker-alpine-armv7.outputs.digest }}
+38
View File
@@ -0,0 +1,38 @@
name: Trigger COPR build
on:
workflow_call:
secrets:
COPR_API_CONFIG:
inputs:
copr_project:
description: COPR project to target
required: true
type: string
permissions:
contents: write
packages: write
jobs:
build-copr-hook:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{ github.ref }}
repository: ${{ github.repository }}
- name: Trigger COPR build
uses: vidplace7/copr-build@main
id: copr_build
env:
COPR_API_TOKEN_CONFIG: ${{ secrets.COPR_API_CONFIG }}
with:
owner: "@meshtastic"
package-name: meshtasticd
project-name: ${{ inputs.copr_project }}
git-remote: "${{ github.server_url }}/${{ github.repository }}.git"
committish: ${{ github.sha }}
+107 -86
View File
@@ -128,20 +128,54 @@ jobs:
with:
board: ${{ matrix.board }}
package-raspbian:
uses: ./.github/workflows/package_raspbian.yml
package-raspbian-armv7l:
uses: ./.github/workflows/package_raspbian_armv7l.yml
package-native:
uses: ./.github/workflows/package_amd64.yml
build-docker:
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: ./.github/workflows/build_docker.yml
build-debian-src:
uses: ./.github/workflows/build_debian_src.yml
with:
series: UNRELEASED
build_location: local
secrets: inherit
package-pio-deps-native:
uses: ./.github/workflows/package_pio_deps.yml
with:
pio_env: native
secrets: inherit
test-native:
uses: ./.github/workflows/test_native.yml
docker-debian-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
docker-alpine-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
docker-debian-arm64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/arm64
runs-on: ubuntu-24.04-arm
push: false
docker-debian-armv7:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/arm/v7
runs-on: ubuntu-24.04-arm
push: false
after-checks:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
@@ -189,7 +223,7 @@ jobs:
run: ls -R
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Move files up
@@ -198,7 +232,7 @@ jobs:
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v4
with:
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
overwrite: true
path: |
./firmware-*.bin
@@ -215,7 +249,7 @@ jobs:
- uses: actions/download-artifact@v4
with:
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
merge-multiple: true
path: ./output
@@ -229,12 +263,12 @@ jobs:
chmod +x ./output/device-update.sh
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v4
with:
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
overwrite: true
path: ./*.elf
retention-days: 30
@@ -242,8 +276,8 @@ jobs:
- uses: scruplelesswizard/comment-artifact@main
if: ${{ github.event_name == 'pull_request' }}
with:
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip. This artifact will be available for 90 days from creation"
name: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
description: "Download firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip. This artifact will be available for 90 days from creation"
github-token: ${{ secrets.GITHUB_TOKEN }}
release-artifacts:
@@ -252,12 +286,9 @@ jobs:
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
needs:
[
gather-artifacts,
package-raspbian,
package-raspbian-armv7l,
package-native,
]
- gather-artifacts
- build-debian-src
- package-pio-deps-native
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -268,73 +299,76 @@ jobs:
python-version: 3.x
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
id: version
env:
BUILD_LOCATION: local
- name: Create release
uses: actions/create-release@v1
uses: softprops/action-gh-release@v2
id: create_release
with:
draft: true
prerelease: true
release_name: Meshtastic Firmware ${{ steps.version.outputs.version }} Alpha
tag_name: v${{ steps.version.outputs.version }}
name: Meshtastic Firmware ${{ steps.version.outputs.long }} Alpha
tag_name: v${{ steps.version.outputs.long }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Download deb files
- name: Download source deb
uses: actions/download-artifact@v4
with:
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
pattern: firmware-debian-${{ steps.version.outputs.deb }}~UNRELEASED-src
merge-multiple: true
path: ./output
path: ./output/debian-src
- name: Download native pio deps
uses: actions/download-artifact@v4
with:
pattern: platformio-deps-native-${{ steps.version.outputs.long }}
merge-multiple: true
path: ./output/pio-deps-native
- name: Zip linux sources
working-directory: output
run: |
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
zip -9 -r ./platformio-deps-native-${{ steps.version.outputs.long }}.zip ./pio-deps-native
# For diagnostics
- name: Display structure of downloaded files
run: ls -lR
- name: Add raspbian aarch64 .deb
uses: actions/upload-release-asset@v1
- name: Add linux sources to release
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-${{ steps.version.outputs.long }}.zip
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
asset_content_type: application/vnd.debian.binary-package
- name: Add raspbian armv7l .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
asset_content_type: application/vnd.debian.binary-package
- name: Add raspbian amd64 .deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
asset_content_type: application/vnd.debian.binary-package
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Bump version.properties
run: >-
bin/bump_version.py
- 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
- name: Create version.properties pull request
uses: peter-evans/create-pull-request@v7
with:
title: Bump version.properties
add-paths: |
version.properties
debian/changelog
release-firmware:
strategy:
@@ -354,12 +388,12 @@ jobs:
python-version: 3.x
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- uses: actions/download-artifact@v4
with:
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}
pattern: firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}
merge-multiple: true
path: ./output
@@ -372,37 +406,24 @@ jobs:
chmod +x ./output/device-update.sh
- name: Zip firmware
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./output
run: zip -j -9 -r ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./output
- uses: actions/download-artifact@v4
with:
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
merge-multiple: true
path: ./elfs
- name: Zip firmware
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip ./elfs
- name: Zip debug elfs
run: zip -j -9 -r ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip ./elfs
# For diagnostics
- name: Display structure of downloaded files
run: ls -lR
- name: Add bins to release
uses: actions/upload-release-asset@v1
- name: Add bins and debug elfs to release
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: ${{ github.token }}
with:
upload_url: ${{needs.release-artifacts.outputs.upload_url}}
asset_path: ./firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
asset_name: firmware-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
- name: Add debug elfs to release
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{needs.release-artifacts.outputs.upload_url}}
asset_path: ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
asset_name: debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+20 -2
View File
@@ -4,9 +4,11 @@ on:
- cron: 0 8 * * 1-5
workflow_dispatch: {}
permissions: read-all
jobs:
trunk_check:
name: Trunk Check Upload
name: Trunk Check and Upload
runs-on: ubuntu-latest
steps:
@@ -14,6 +16,22 @@ jobs:
uses: actions/checkout@v4
- name: Trunk Check
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
uses: trunk-io/trunk-action@v1
with:
trunk-token: ${{ secrets.TRUNK_TOKEN }}
trunk_upgrade:
# See: https://github.com/trunk-io/trunk-action/blob/v1/readme.md#automatic-upgrades
name: Trunk Upgrade (PR)
runs-on: ubuntu-latest
permissions:
contents: write # For trunk to create PRs
pull-requests: write # For trunk to create PRs
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Trunk Upgrade
uses: trunk-io/trunk-action/upgrade@v1
with:
base: master
-90
View File
@@ -1,90 +0,0 @@
name: Package Native
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
packages: write
jobs:
build-native:
uses: ./.github/workflows/build_native.yml
package-native:
runs-on: ubuntu-22.04
needs: build-native
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-native-${{ steps.version.outputs.version }}.zip
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/DEBIAN
mkdir -p .debpkg/usr/share/meshtasticd/web
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
mkdir -p .debpkg/etc/meshtasticd/config.d
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/meshtasticd/web/ -r
cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
chmod +x .debpkg/usr/sbin/meshtasticd
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
chmod +x .debpkg/DEBIAN/conffiles
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
chmod +x .debpkg/DEBIAN/preinst
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
chmod +x .debpkg/DEBIAN/postinst
- uses: jiro4989/build-deb-action@v3
with:
package: meshtasticd
package_root: .debpkg
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: amd64
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v4
with:
name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
overwrite: true
path: |
./*.deb
+110
View File
@@ -0,0 +1,110 @@
name: Package for OpenSUSE Build Service
on:
workflow_call:
secrets:
OBS_PASSWORD:
required: true
PPA_GPG_PRIVATE_KEY:
required: true
inputs:
obs_project:
description: Meshtastic OBS project to target
required: true
type: string
series:
description: Debian series to target
required: true
type: string
permissions:
contents: write
packages: write
jobs:
build-debian-src:
uses: ./.github/workflows/build_debian_src.yml
secrets: inherit
with:
series: ${{ inputs.series }}
build_location: obs
package-obs:
runs-on: ubuntu-24.04
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
path: meshtasticd
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install OpenSUSE Build Service deps
shell: bash
run: |
echo 'deb http://download.opensuse.org/repositories/openSUSE:/Tools/xUbuntu_24.04/ /' | sudo tee /etc/apt/sources.list.d/openSUSE:Tools.list
curl -fsSL https://download.opensuse.org/repositories/openSUSE:Tools/xUbuntu_24.04/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/openSUSE_Tools.gpg > /dev/null
sudo apt-get update -y --fix-missing
sudo apt-get install -y osc
- name: Get release version string
working-directory: meshtasticd
run: |
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
env:
BUILD_LOCATION: obs
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true
- name: Display structure of downloaded files
run: ls -lah
- name: Configure osc
env:
OBS_USERNAME: meshtastic
run: |
# Setup OpenSUSE Build Service credentials
mkdir -p ~/.config/osc
echo "[general]" > ~/.config/osc/oscrc
echo "apiurl=https://api.opensuse.org" >> ~/.config/osc/oscrc
echo "[https://api.opensuse.org]" >> ~/.config/osc/oscrc
echo "user=${{ env.OBS_USERNAME }}" >> ~/.config/osc/oscrc
echo "pass=${{ secrets.OBS_PASSWORD }}" >> ~/.config/osc/oscrc
echo "credentials_mgr_class=osc.credentials.PlaintextConfigFileCredentialsManager" >> ~/.config/osc/oscrc
# Create a temporary directory for osc checkout
mkdir -p osc
# Intentionally fail if credentials are invalid
# Update secrets if this returns `401`
- name: Verify OBS authentication
run: osc token
- name: Upload package to OBS
shell: bash
working-directory: osc
env:
OBS_PROJECT: ${{ inputs.obs_project }}
OBS_PACKAGE: meshtasticd
run: |
# Initialize the package in the current directory
osc checkout --output-dir . $OBS_PROJECT $OBS_PACKAGE
# Remove the existing package files
rm -rf *.dsc *.tar.xz
# Copy new package files to the directory
cp $GITHUB_WORKSPACE/*.dsc .
cp $GITHUB_WORKSPACE/*.tar.xz .
# Add/Remove the files
osc addremove
# Commit changes and push to OpenSUSE Build Service
osc commit -m "GitHub Actions: ${{ steps.version.outputs.deb }}~${{ inputs.series }}"
+65
View File
@@ -0,0 +1,65 @@
name: Package PlatformIO Library Dependencies
# trunk-ignore-all(checkov/CKV_GHA_7): Allow workflow_dispatch inputs for testing
on:
workflow_call:
inputs:
pio_env:
description: PlatformIO environment to target
required: true
type: string
workflow_dispatch:
inputs:
pio_env:
description: PlatformIO environment to target
required: true
type: string
permissions:
contents: write
packages: write
jobs:
pkg-pio-libdeps:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Install deps
shell: bash
run: |
pip install platformio
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Fetch libdeps
shell: bash
run: |-
platformio pkg install -e ${{ inputs.pio_env }}
platformio pkg install -e ${{ inputs.pio_env }} -t platformio/tool-scons@4.40502.0
env:
PLATFORMIO_LIBDEPS_DIR: pio/libdeps
PLATFORMIO_PACKAGES_DIR: pio/packages
PLATFORMIO_CORE_DIR: pio/core
- name: Store binaries as an artifact
uses: actions/upload-artifact@v4
with:
name: platformio-deps-${{ inputs.pio_env }}-${{ steps.version.outputs.long }}
overwrite: true
include-hidden-files: true
path: |
pio/*
+74
View File
@@ -0,0 +1,74 @@
name: Package for Launchpad PPA
on:
workflow_call:
secrets:
PPA_GPG_PRIVATE_KEY:
required: true
inputs:
ppa_repo:
description: Meshtastic PPA to target
required: true
type: string
series:
description: Ubuntu series to target
required: true
type: string
permissions:
contents: write
packages: write
jobs:
build-debian-src:
uses: ./.github/workflows/build_debian_src.yml
secrets: inherit
with:
series: ${{ inputs.series }}
build_location: ppa
package-ppa:
runs-on: ubuntu-24.04
needs: build-debian-src
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
path: meshtasticd
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install deps
shell: bash
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y dput
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.PPA_GPG_PRIVATE_KEY }}
id: gpg
- name: Get release version string
working-directory: meshtasticd
run: |
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
env:
BUILD_LOCATION: ppa
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-debian-${{ steps.version.outputs.deb }}~${{ inputs.series }}-src
merge-multiple: true
- name: Display structure of downloaded files
run: ls -lah
- name: Publish with dput
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
run: |
dput ${{ inputs.ppa_repo }} meshtasticd_${{ steps.version.outputs.deb }}~${{ inputs.series }}_source.changes
-90
View File
@@ -1,90 +0,0 @@
name: Package Raspbian
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
packages: write
jobs:
build-raspbian:
uses: ./.github/workflows/build_raspbian.yml
package-raspbian:
runs-on: ubuntu-22.04
needs: build-raspbian
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/DEBIAN
mkdir -p .debpkg/usr/share/meshtasticd/web
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
mkdir -p .debpkg/etc/meshtasticd/config.d
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/meshtasticd/web/ -r
cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
chmod +x .debpkg/usr/sbin/meshtasticd
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
chmod +x .debpkg/DEBIAN/conffiles
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
chmod +x .debpkg/DEBIAN/preinst
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
chmod +x .debpkg/DEBIAN/postinst
- uses: jiro4989/build-deb-action@v3
with:
package: meshtasticd
package_root: .debpkg
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: arm64
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v4
with:
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
overwrite: true
path: |
./*.deb
@@ -1,90 +0,0 @@
name: Package Raspbian
on:
workflow_call:
workflow_dispatch:
permissions:
contents: write
packages: write
jobs:
build-raspbian_armv7l:
uses: ./.github/workflows/build_raspbian_armv7l.yml
package-raspbian_armv7l:
runs-on: ubuntu-22.04
needs: build-raspbian_armv7l
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: meshtastic/web
file: build.tar
target: build.tar
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
merge-multiple: true
- name: Display structure of downloaded files
run: ls -R
- name: build .debpkg
run: |
mkdir -p .debpkg/DEBIAN
mkdir -p .debpkg/usr/share/meshtasticd/web
mkdir -p .debpkg/usr/sbin
mkdir -p .debpkg/etc/meshtasticd
mkdir -p .debpkg/etc/meshtasticd/config.d
mkdir -p .debpkg/etc/meshtasticd/available.d
mkdir -p .debpkg/usr/lib/systemd/system/
tar -xf build.tar -C .debpkg/usr/share/meshtasticd/web
shopt -s dotglob nullglob
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then mv .debpkg/usr/share/meshtasticd/web/build/* .debpkg/usr/share/meshtasticd/web/; fi
if [ -d .debpkg/usr/share/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/meshtasticd/web/build; fi
if [ -d .debpkg/usr/share/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/meshtasticd/web/.DS_Store; fi
gunzip .debpkg/usr/share/meshtasticd/web/ -r
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r
chmod +x .debpkg/usr/sbin/meshtasticd
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
chmod +x .debpkg/DEBIAN/conffiles
# Transition /usr/share/doc/meshtasticd to /usr/share/meshtasticd
echo "rm -rf /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/preinst
chmod +x .debpkg/DEBIAN/preinst
echo "ln -sf /usr/share/meshtasticd /usr/share/doc/meshtasticd" > .debpkg/DEBIAN/postinst
chmod +x .debpkg/DEBIAN/postinst
- uses: jiro4989/build-deb-action@v3
with:
package: meshtasticd
package_root: .debpkg
maintainer: Jonathan Bennett
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
arch: armhf
depends: libyaml-cpp0.7, openssl, libulfius2.7, libi2c0
desc: Native Linux Meshtastic binary.
- uses: actions/upload-artifact@v4
with:
name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
overwrite: true
path: |
./*.deb
+45
View File
@@ -0,0 +1,45 @@
name: Trigger release workflows upon Publish
on:
release:
types: [published, released]
permissions:
contents: write
packages: write
jobs:
build-docker:
uses: ./.github/workflows/docker_manifest.yml
with:
release_channel: |-
${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
secrets: inherit
package-ppa:
strategy:
fail-fast: false
matrix:
series: [plucky, oracular, noble, jammy]
uses: ./.github/workflows/package_ppa.yml
with:
ppa_repo: |-
ppa:meshtastic/${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
series: ${{ matrix.series }}
secrets: inherit
package-obs:
uses: ./.github/workflows/package_obs.yml
with:
obs_project: |-
network:Meshtastic:${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
series: |-
${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
secrets: inherit
hook-copr:
uses: ./.github/workflows/hook_copr.yml
with:
copr_project: |-
${{ contains(github.event.release.name, 'Beta') && 'beta' || contains(github.event.release.name, 'Alpha') && 'alpha' }}
secrets: inherit
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
steps:
- name: Stale PR+Issues
uses: actions/stale@v9.0.0
uses: actions/stale@v9.1.0
with:
exempt-issue-labels: pinned,3.0
exempt-pr-labels: pinned,3.0
+169
View File
@@ -0,0 +1,169 @@
name: Run Tests on Native platform
on:
workflow_call:
workflow_dispatch:
permissions: {}
env:
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
jobs:
simulator-tests:
name: Native Simulator Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
submodules: recursive
- name: Setup native build
id: base
uses: ./.github/actions/setup-native
- name: Install simulator dependencies
run: pip install -U dotmap
# We now run integration test before other build steps (to quickly see runtime failures)
- name: Build for native/coverage
run: platformio run -e coverage
- name: Capture initial coverage information
shell: bash
run: |
sudo apt-get install -y lcov
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info
sed -i -e "s#${PWD}#.#" coverage_base.info # Make paths relative.
- name: Integration test
run: |
.pio/build/coverage/program &
PID=$!
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
echo "Simulator started, launching python test..."
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
wait
- name: Capture coverage information
if: always() # run this step even if previous step failed
run: |
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info
sed -i -e "s#${PWD}#.#" coverage_integration.info # Make paths relative.
- name: Get release version string
if: always() # run this step even if previous step failed
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Save coverage information
uses: actions/upload-artifact@v4
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-simulator-test-${{ steps.version.outputs.long }}.zip
overwrite: true
path: ./coverage_*.info
platformio-tests:
name: Native PlatformIO Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
submodules: recursive
- name: Setup native build
id: base
uses: ./.github/actions/setup-native
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
# Disable (comment-out) BUILD_EPOCH. It causes a full rebuild between tests and resets the
# coverage information each time.
- name: Disable BUILD_EPOCH
run: sed -i 's/-DBUILD_EPOCH=$UNIX_TIME/#-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
- name: PlatformIO Tests
run: platformio test -e coverage -v --junit-output-path testreport.xml
- name: Save test results
if: always() # run this step even if previous step failed
uses: actions/upload-artifact@v4
with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
overwrite: true
path: ./testreport.xml
- name: Capture coverage information
if: always() # run this step even if previous step failed
run: |
sudo apt-get install -y lcov
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info
sed -i -e "s#${PWD}#.#" coverage_tests.info # Make paths relative.
- name: Save coverage information
uses: actions/upload-artifact@v4
if: always() # run this step even if previous step failed
with:
name: lcov-coverage-info-native-platformio-tests-${{ steps.version.outputs.long }}.zip
overwrite: true
path: ./coverage_*.info
generate-reports:
name: Generate Test Reports
runs-on: ubuntu-latest
permissions: # Needed for dorny/test-reporter.
contents: read
actions: read
checks: write
needs:
- simulator-tests
- platformio-tests
if: always()
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Download test artifacts
uses: actions/download-artifact@v4
with:
name: platformio-test-report-${{ steps.version.outputs.long }}.zip
merge-multiple: true
- name: Test Report
uses: dorny/test-reporter@v1.9.1
with:
name: PlatformIO Tests
path: testreport.xml
reporter: java-junit
- name: Download coverage artifacts
uses: actions/download-artifact@v4
with:
pattern: lcov-coverage-info-native-*-${{ steps.version.outputs.long }}.zip
path: code-coverage-report
merge-multiple: true
- name: Generate Code Coverage Report
run: |
sudo apt-get install -y lcov
lcov --quiet --add-tracefile code-coverage-report/coverage_base.info --add-tracefile code-coverage-report/coverage_integration.info --add-tracefile code-coverage-report/coverage_tests.info --output-file code-coverage-report/coverage_src.info
genhtml --quiet --legend --prefix "${PWD}" code-coverage-report/coverage_src.info --output-directory code-coverage-report
- name: Save Code Coverage Report
uses: actions/upload-artifact@v4
with:
name: code-coverage-report-${{ steps.version.outputs.long }}.zip
path: code-coverage-report
+2 -73
View File
@@ -6,79 +6,8 @@ on:
workflow_dispatch: {}
jobs:
test-simulator:
runs-on: ubuntu-latest
env:
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
steps:
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get update --fix-missing
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev libi2c-dev
sudo apt-get install -y lcov
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil dotmap
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade
- name: Build Native
run: bin/build-native.sh
# We now run integration test before other build steps (to quickly see runtime failures)
- name: Build for native/coverage
run: |
platformio run -e coverage
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --initial --output-file coverage_base.info
- name: Integration test
run: |
.pio/build/coverage/program &
PID=$!
timeout 20 bash -c "until ls -al /proc/$PID/fd | grep socket; do sleep 1; done"
echo "Simulator started, launching python test..."
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
wait
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name integration --output-file coverage_integration.info
- name: PlatformIO Tests
run: |
platformio test -e coverage --junit-output-path testreport.xml
lcov ${{ env.LCOV_CAPTURE_FLAGS }} --test-name tests --output-file coverage_tests.info
- name: Test Report
uses: dorny/test-reporter@v1.9.1
if: success() || failure() # run this step even if previous step failed
with:
name: PlatformIO Tests
path: testreport.xml
reporter: java-junit
- name: Generate Code Coverage Report
run: |
lcov --quiet --add-tracefile coverage_base.info --add-tracefile coverage_integration.info --add-tracefile coverage_tests.info --output-file coverage_src.info
mkdir code-coverage-report
genhtml --quiet --legend --prefix "${PWD}" coverage_src.info --output-directory code-coverage-report
mv coverage_*.info code-coverage-report
- name: Save Code Coverage Report
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
path: code-coverage-report
native-tests:
uses: ./.github/workflows/test_native.yml
hardware-tests:
runs-on: test-runner
+26
View File
@@ -0,0 +1,26 @@
name: Annotate PR with trunk issues
# See: https://github.com/trunk-io/trunk-action/blob/v1/readme.md#getting-inline-annotations-for-fork-prs
on:
workflow_run:
workflows: [Pull Request] # Name from `trunk_check.yml`
types: [completed]
permissions: read-all
jobs:
trunk_check:
name: Trunk Code Quality Annotate
runs-on: ubuntu-latest
permissions:
checks: write # For trunk to post annotations
contents: read # For repo checkout
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Trunk Check
uses: trunk-io/trunk-action@v1
with:
post-annotations: true
@@ -20,3 +20,5 @@ jobs:
- name: Trunk Check
uses: trunk-io/trunk-action@v1
with:
save-annotations: true
+5 -1
View File
@@ -22,12 +22,16 @@ jobs:
- name: Run Trunk Fmt
run: trunk fmt
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Commit and push changes
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "Add firmware version ${{ steps.version.outputs.version }}"
git commit -m "Add firmware version ${{ steps.version.outputs.long }}"
git push
- name: Comment on PR
+1
View File
@@ -12,6 +12,7 @@ jobs:
submodules: true
- name: Update submodule
if: ${{ github.ref == 'refs/heads/master' }}
run: |
git submodule update --remote protobufs
+8 -1
View File
@@ -1,4 +1,8 @@
.pio
pio
pio.tar
web
web.tar
# ignore vscode IDE settings files
.vscode/*
@@ -8,6 +12,9 @@
*.code-workspace
.idea
.platformio
.local
.cache
.DS_Store
Thumbs.db
@@ -30,4 +37,4 @@ release/
.vscode/extensions.json
/compile_commands.json
src/mesh/raspihttp/certificate.pem
src/mesh/raspihttp/private_key.pem
src/mesh/raspihttp/private_key.pem
+10
View File
@@ -0,0 +1,10 @@
{
"overrides": [
{
"files": "userPrefs.jsonc",
"options": {
"trailingComma": "none"
}
}
]
}
+15 -17
View File
@@ -1,37 +1,35 @@
version: 0.1
cli:
version: 1.22.8
version: 1.22.10
plugins:
sources:
- id: trunk
ref: v1.6.6
ref: v1.6.7
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- prettier@3.4.2
- trufflehog@3.86.1
- prettier@3.5.1
- trufflehog@3.88.12
- yamllint@1.35.1
- bandit@1.8.0
- checkov@3.2.334
- bandit@1.8.3
- checkov@3.2.372
- terrascan@1.19.9
- trivy@0.58.0
#- trufflehog@3.63.2-rc0
- trivy@0.59.1
- taplo@0.9.3
- ruff@0.8.3
- isort@5.13.2
- markdownlint@0.43.0
- oxipng@9.1.3
- ruff@0.9.7
- isort@6.0.0
- markdownlint@0.44.0
- oxipng@9.1.4
- svgo@3.3.2
- actionlint@1.7.4
- flake8@7.1.1
- actionlint@1.7.7
- flake8@7.1.2
- hadolint@2.12.1-beta
- shfmt@3.6.0
- shellcheck@0.10.0
- black@24.10.0
- black@25.1.0
- git-diff-check
- gitleaks@8.21.2
- gitleaks@8.24.0
- clang-format@16.0.3
#- prettier@3.3.3
ignore:
- linters: [ALL]
paths:
+2 -1
View File
@@ -38,7 +38,8 @@ USER root
RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libulfius2.7 libusb-1.0-0-dev liborcania2.3 libssl3 && \
apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d
&& 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/
+26 -5
View File
@@ -1,4 +1,7 @@
# Meshtastic Firmware
<div align="center" markdown="1">
<img src=".github/meshtastic_logo.png" alt="Meshtastic Logo" width="80"/>
<h1>Meshtastic Firmware</h1>
![GitHub release downloads](https://img.shields.io/github/downloads/meshtastic/firmware/total)
[![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/firmware/main_matrix.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/firmware/actions/workflows/ci.yml)
@@ -6,13 +9,31 @@
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/)
[![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
<a href="https://trendshift.io/repositories/5524" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5524" alt="meshtastic%2Ffirmware | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
</div>
<div align="center">
<a href="https://meshtastic.org">Website</a>
-
<a href="https://meshtastic.org/docs/">Documentation</a>
</div>
## Overview
This repository contains the device firmware for the Meshtastic project.
This repository contains the official device firmware for Meshtastic, an open-source LoRa mesh networking project designed for long-range, low-power communication without relying on internet or cellular infrastructure. The firmware supports various hardware platforms, including ESP32, nRF52, RP2040/RP2350, and Linux-based devices.
- **[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
- **[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
Meshtastic enables text messaging, location sharing, and telemetry over a decentralized mesh network, making it ideal for outdoor adventures, emergency preparedness, and remote operations.
### Get Started
- 🔧 **[Building Instructions](https://meshtastic.org/docs/development/firmware/build)** – Learn how to compile the firmware from source.
- ⚡ **[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)** – Install or update the firmware on your device.
Join our community and help improve Meshtastic! 🚀
## Stats
![Alt](https://repobeats.axiom.co/api/embed/a92f097d9197ae853e780ec53d7d126e545629ab.svg "Repobeats analytics image")
![Alt](https://repobeats.axiom.co/api/embed/8025e56c482ec63541593cc5bd322c19d5c0bdcf.svg "Repobeats analytics image")
+2 -1
View File
@@ -29,7 +29,8 @@ USER root
RUN apk add libstdc++ libgpiod yaml-cpp libusb i2c-tools \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d
&& mkdir -p /etc/meshtasticd/config.d \
&& mkdir -p /etc/meshtasticd/ssl
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
WORKDIR /var/lib/meshtasticd
+4 -4
View File
@@ -2,7 +2,7 @@
[esp32_base]
extends = arduino_base
custom_esp32_kind = esp32
platform = platformio/espressif32@6.9.0
platform = platformio/espressif32@6.10.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
@@ -45,9 +45,9 @@ lib_deps =
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.2
h2zero/NimBLE-Arduino@^1.4.3
https://github.com/dbinfrago/libpax.git#3cdc0371c375676a97967547f4065607d4c53fd1
lewisxhe/XPowersLib@^0.2.6
lewisxhe/XPowersLib@^0.2.7
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0
@@ -65,4 +65,4 @@ lib_ignore =
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv
board_build.partitions = partition-table.csv
+2 -2
View File
@@ -24,7 +24,7 @@ lib_deps =
${networking_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
lewisxhe/XPowersLib@^0.2.6
lewisxhe/XPowersLib@^0.2.7
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
rweather/Crypto@^0.4.0
@@ -38,4 +38,4 @@ lib_ignore =
NonBlockingRTTTL
NimBLE-Arduino
libpax
+2 -2
View File
@@ -4,8 +4,8 @@ platform = platformio/nordicnrf52@^10.7.0
extends = arduino_base
platform_packages =
; our custom Git version until they merge our PR
framework-arduinoadafruitnrf52 @ https://github.com/geeksville/Adafruit_nRF52_Arduino.git
toolchain-gccarmnoneeabi@~1.90301.0
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino.git#e13f5820002a4fb2a5e6754b42ace185277e5adf
platformio/toolchain-gccarmnoneeabi@~1.90301.0
build_type = debug
build_flags =
+2 -2
View File
@@ -25,7 +25,7 @@ lib_deps =
${networking_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
https://github.com/lovyan03/LovyanGFX.git#1401c28a47646fe00538d487adcb2eb3c72de805
lovyan03/LovyanGFX@^1.2.0
https://github.com/pine64/libch341-spi-userspace#a9b17e3452f7fb747000d9b4ad4409155b39f6ef
build_flags =
@@ -40,4 +40,4 @@ build_flags =
-lgpiod
-lyaml-cpp
-li2c
-std=c++17
-std=c++17
+5 -6
View File
@@ -1,18 +1,17 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
${arduino_base.build_flags} -Wno-unused-variable -Wcast-align
-Isrc/platform/rp2xx0
-D__PLAT_RP2040__
# -D _POSIX_THREADS
-D__PLAT_RP2350__
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp> -<platform/rp2xx0/pico_sleep> -<platform/rp2xx0/hardware_rosc>
lib_ignore =
BluetoothOTA
+10 -4
View File
@@ -1,7 +1,7 @@
[stm32_base]
extends = arduino_base
platform = ststm32
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#ea74156acd823b6d14739f389e6cdc648f8ee36e
platform = platformio/ststm32
platform_packages = platformio/framework-arduinoststm32@^4.20900.0
build_type = release
@@ -11,9 +11,15 @@ build_flags =
${arduino_base.build_flags}
-flto
-Isrc/platform/stm32wl -g
-DMESHTASTIC_MINIMIZE_BUILD
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
-DMESHTASTIC_EXCLUDE_INPUTBROKER
-DMESHTASTIC_EXCLUDE_I2C
-DMESHTASTIC_EXCLUDE_POWERMON
-DMESHTASTIC_EXCLUDE_SCREEN
-DMESHTASTIC_EXCLUDE_MQTT
-DMESHTASTIC_EXCLUDE_BLUETOOTH
-DMESHTASTIC_EXCLUDE_PKI
-DMESHTASTIC_EXCLUDE_GPS
-DDEBUG_MUTE
; -DVECT_TAB_OFFSET=0x08000000
-DconfigUSE_CMSIS_RTOS_V2=1
; -DSPI_MODE_0=SPI_MODE0
+1
View File
@@ -0,0 +1 @@
config.yaml
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
sed -i 's/#-DBUILD_EPOCH=$UNIX_TIME/-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
export PIP_BREAK_SYSTEM_PACKAGES=1
if (echo $2 | grep -q "esp32"); then
bin/build-esp32.sh $1
elif (echo $2 | grep -q "nrf52"); then
bin/build-nrf52.sh $1
elif (echo $2 | grep -q "stm32"); then
bin/build-stm32.sh $1
elif (echo $2 | grep -q "rpi2040"); then
bin/build-rpi2040.sh $1
else
echo "Unknown target $2"
exit 1
fi
+46 -7
View File
@@ -12,12 +12,6 @@ Lora:
# IRQ: 17
# Reset: 22
# Module: RF95 # Adafruit RFM9x
# Reset: 25
# CS: 7
# IRQ: 22
# Busy: 23
# Module: RF95 # Elecrow Lora RFM95 IOT https://www.elecrow.com/lora-rfm95-iot-board-for-rpi.html
# Reset: 22
# CS: 7
@@ -29,6 +23,47 @@ Lora:
# Busy: 20
# Reset: 18
### The Radxa Zero 3E/W employs multiple gpio chips.
### Each gpio pin must be unique, but can be assigned to a specific gpio chip and line.
### In case solely a no. is given, the default gpio chip and pin == line will be employed.
###
# Module: sx1262 # Radxa Zero 3E/W + Ebyte E22-900M30S
# DIO2_AS_RF_SWITCH: true
# DIO3_TCXO_VOLTAGE: 1.8
# CS: # NSS PIN_24 -> chip 4, line 22
# pin: 24
# gpiochip: 4
# line: 22
# SCK: # SCK PIN_23 -> chip 4, line 18
# pin: 23
# gpiochip: 4
# line: 18
# Busy: # BUSY PIN_29 -> chip 3!, line 11
# pin: 29
# gpiochip: 3
# line: 11
# MOSI: # MOSI PIN_19 -> chip 4, line 19
# pin: 19
# gpiochip: 4
# line: 19
# MISO: # MISO PIN_21 -> chip 4, line 21
# pin: 21
# gpiochip: 4
# line: 21
# Reset: # NRST PIN_27 -> chip 4, line 10
# pin: 27
# gpiochip: 4
# line: 10
# IRQ: # DIO1 PIN_28 -> chip 4, line 11
# pin: 28
# gpiochip: 4
# line: 11
# RXen: # RXEN PIN_22 -> chip 3!, line 17
# pin: 22
# gpiochip: 3
# line: 17
# TXen: RADIOLIB_NC # TXEN no PIN, no line, fallback to default gpio chip
# Module: sx1268 # SX1268-based modules, tested with Ebyte E22 400M33S
# CS: 21
# IRQ: 16
@@ -43,9 +78,11 @@ Lora:
# TXen: x # TX and RX enable pins
# RXen: x
# SX126X_MAX_POWER: 8 # Limit the output power to 8 dBm, useful for amped nodes
# spiSpeed: 2000000
### Set gpio chip to use in /dev/. Defaults to 0.
### Set default/fallback gpio chip to use in /dev/. Defaults to 0.
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
# gpiochip: 4
@@ -147,6 +184,8 @@ Logging:
Webserver:
# Port: 443 # Port for Webserver & Webservices
# RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
# SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present
# SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present
General:
MaxNodes: 200
@@ -0,0 +1,9 @@
Lora:
Module: sx1262 # BananaPi-BPI-R4 SPI via 26p GPIO Header
## CS: 28
IRQ: 50
Busy: 62
Reset: 51
spidev: spidev1.0
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
+5
View File
@@ -0,0 +1,5 @@
# Module: RF95 # Adafruit RFM9x
# Reset: 25
# CS: 7
# IRQ: 22
# Busy: 23
+3
View File
@@ -7,3 +7,6 @@ Lora:
TXen: 13
RXen: 12
DIO3_TCXO_VOLTAGE: true
# Only for E22-900M33S:
# Limit the output power to 8 dBm
# SX126X_MAX_POWER: 8
+1 -1
View File
@@ -73,7 +73,7 @@ shift "$((OPTIND - 1))"
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
$ESPTOOL_CMD erase_flash
$ESPTOOL_CMD write_flash 0x00 ${FILENAME}
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
# Account for S3 board's different OTA partition
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
+1 -1
View File
@@ -102,7 +102,7 @@ pref_flags = []
for pref in userPrefs:
if userPrefs[pref].startswith("{"):
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
elif userPrefs[pref].replace(".", "").isdigit():
elif userPrefs[pref].lstrip("-").replace(".", "").isdigit():
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
elif userPrefs[pref] == "true" or userPrefs[pref] == "false":
pref_flags.append("-D" + pref + "=" + userPrefs[pref])
+8 -5
View File
@@ -1,6 +1,8 @@
import configparser
import subprocess
import os
run_number = os.getenv('GITHUB_RUN_NUMBER', '0')
build_location = os.getenv('BUILD_LOCATION', 'local')
def readProps(prefsLoc):
"""Read the version of our project as a string"""
@@ -11,6 +13,7 @@ def readProps(prefsLoc):
verObj = dict(
short="{}.{}.{}".format(version["major"], version["minor"], version["build"]),
long="unset",
deb="unset",
)
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
@@ -27,16 +30,16 @@ def readProps(prefsLoc):
# if isDirty:
# # short for 'dirty', we want to keep our verstrings source for protobuf reasons
# suffix = sha + "-d"
verObj["long"] = "{}.{}.{}.{}".format(
version["major"], version["minor"], version["build"], suffix
)
verObj["long"] = "{}.{}".format(verObj["short"], suffix)
verObj["deb"] = "{}.{}~{}{}".format(verObj["short"], run_number, build_location, sha)
except:
# print("Unexpected error:", sys.exc_info()[0])
# traceback.print_exc()
verObj["long"] = verObj["short"]
verObj["deb"] = "{}.{}~{}".format(verObj["short"], run_number, build_location)
# print("firmware version " + verStr)
return verObj
# print("path is" + ','.join(sys.path))
# print("path is" + ','.join(sys.path))
+12
View File
@@ -0,0 +1,12 @@
function meshtastic_version {
meshtastic_version=$(python3 bin/buildinfo.py short)
echo -n "$meshtastic_version"
}
function git_commits_num {
total_commits=$(git rev-list --all --count)
echo -n "$total_commits"
}
function git_commit_sha {
commit_sha=$(git rev-parse --short HEAD)
echo -n "$commit_sha"
}
+52
View File
@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DMESHLINK -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x00B3"],
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "MeshLink",
"mcu": "nrf52840",
"variant": "meshlink",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"name": "MeshLink",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.loraitalia.it",
"vendor": "LoraItalia"
}
+6
View File
@@ -0,0 +1,6 @@
.debhelper
debhelper-build-stamp
meshtasticd
files
meshtasticd.substvars
meshtasticd.postrm.debhelper
+9
View File
@@ -0,0 +1,9 @@
meshtasticd (2.5.22.0) UNRELEASED; urgency=medium
* 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
Vendored Executable
+7
View File
@@ -0,0 +1,7 @@
#!/usr/bin/bash
export DEBEMAIL="github-actions[bot]@users.noreply.github.com"
PKG_VERSION=$(python3 bin/buildinfo.py short)
dch --newversion "$PKG_VERSION.0" \
--distribution UNRELEASED \
"GitHub Actions Automatic version bump"
Vendored Executable
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/bash
export DEBEMAIL="jbennett@incomsystems.biz"
export PLATFORMIO_LIBDEPS_DIR=pio/libdeps
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
# Compress `pio` directory to prevent dh_clean from sanitizing it
tar -cf pio.tar pio/
rm -rf pio
# Download the latest meshtastic/web release build.tar to `web.tar`
curl -L https://github.com/meshtastic/web/releases/latest/download/build.tar -o web.tar
package=$(dpkg-parsechangelog --show-field Source)
rm -rf debian/changelog
dch --create --distribution "$SERIES" --package "$package" --newversion "$PKG_VERSION~$SERIES" \
"GitHub Actions Automatic packaging for $PKG_VERSION~$SERIES"
# Build the source deb
debuild -S -nc -k"$GPG_KEY_ID"
+33
View File
@@ -0,0 +1,33 @@
Source: meshtasticd
Section: misc
Priority: optional
Maintainer: Austin Lane <vidplace7@gmail.com>
Build-Depends: debhelper-compat (= 13),
lsb-release,
tar,
gzip,
platformio,
python3-protobuf,
python3-grpcio,
git,
g++,
pkg-config,
libyaml-cpp-dev,
libgpiod-dev,
libbluetooth-dev,
libusb-1.0-0-dev,
libi2c-dev,
openssl,
libssl-dev,
libulfius-dev,
liborcania-dev
Standards-Version: 4.6.2
Homepage: https://github.com/meshtastic/firmware
Rules-Requires-Root: no
Package: meshtasticd
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: Meshtastic daemon for communicating with Meshtastic devices
Meshtastic is an off-grid text communication platform that uses inexpensive
LoRa radios.
+5
View File
@@ -0,0 +1,5 @@
etc/meshtasticd
etc/meshtasticd/config.d
etc/meshtasticd/available.d
usr/share/meshtasticd/web
etc/meshtasticd/ssl
+8
View File
@@ -0,0 +1,8 @@
.pio/build/native/meshtasticd usr/sbin
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/meshtasticd.service lib/systemd/system
web/* usr/share/meshtasticd/web
Vendored Executable
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/make -f
# export DH_VERBOSE = 1
# Use the "dh" sequencer
%:
dh $@
# https://docs.platformio.org/en/latest/envvars.html
PIO_ENV:=\
PLATFORMIO_CORE_DIR=pio/core \
PLATFORMIO_LIBDEPS_DIR=pio/libdeps \
PLATFORMIO_PACKAGES_DIR=pio/packages
# Raspbian armhf builds should be compatible with armv6-hardfloat
# https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/#rpi1-compiler-flags
ifneq (,$(findstring Raspbian,$(shell lsb_release -is)))
ifeq ($(DEB_BUILD_ARCH),armhf)
PIO_ENV+=\
PLATFORMIO_BUILD_FLAGS="-mfloat-abi=hard -mfpu=vfp -march=armv6zk"
endif
endif
override_dh_auto_build:
# Extract tarballs within source deb
tar -xf pio.tar
mkdir -p web && tar -xf web.tar -C web
gunzip web/ -r
# Build with platformio
$(PIO_ENV) platformio run -e native
# Move the binary and default config to the correct name
mv .pio/build/native/program .pio/build/native/meshtasticd
cp bin/config-dist.yaml bin/config.yaml
+1
View File
@@ -0,0 +1 @@
3.0 (native)
+2
View File
@@ -0,0 +1,2 @@
pio.tar
web.tar
+1
View File
@@ -0,0 +1 @@
extend-diff-ignore = "\.pio"
+94
View File
@@ -0,0 +1,94 @@
# meshtasticd spec file for RPM-based distributions
#
# Build locally with:
# ```
# sudo dnf install rpkg-util
# rpkg local
# ```
#
# See:
# - https://docs.pagure.org/rpkg-util/v3/index.html
# - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/
Name: meshtasticd
# Version Ex: 2.5.19
Version: {{{ meshtastic_version }}}
# Release Ex: 9127.daily.gitd7f5f620.fc41
Release: {{{ git_commits_num }}}%{?copr_projectname:.%{copr_projectname}}.git{{{ git_commit_sha }}}%{?dist}
VCS: {{{ git_dir_vcs }}}
Summary: Meshtastic daemon for communicating with Meshtastic devices
License: GPL-3.0
URL: https://github.com/meshtastic/firmware
Source0: {{{ git_dir_pack }}}
Source1: https://github.com/meshtastic/web/releases/latest/download/build.tar
BuildRequires: systemd-rpm-macros
BuildRequires: python3-devel
BuildRequires: platformio
BuildRequires: python3dist(protobuf)
BuildRequires: python3dist(grpcio[protobuf])
BuildRequires: python3dist(grpcio-tools)
BuildRequires: git-core
BuildRequires: gcc-c++
BuildRequires: pkgconfig(yaml-cpp)
BuildRequires: pkgconfig(libgpiod)
BuildRequires: pkgconfig(bluez)
BuildRequires: pkgconfig(libusb-1.0)
BuildRequires: libi2c-devel
# Web components:
BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(liborcania)
BuildRequires: pkgconfig(libyder)
BuildRequires: pkgconfig(libulfius)
%description
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
text communication platform that uses inexpensive LoRa radios.
%prep
{{{ git_dir_setup_macro }}}
# Unpack the web files
mkdir -p web
tar -xf %{SOURCE1} -C web
gzip -dr web
%build
# Use the “native” environment from platformio to build a Linux binary
platformio run -e native
%install
mkdir -p %{buildroot}%{_sbindir}
install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d
cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
# Install the web files under /usr/share/meshtasticd/web
mkdir -p %{buildroot}%{_datadir}/meshtasticd/web
cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
# Install default SSL storage directory (for web)
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
%files
%license LICENSE
%doc README.md
%{_sbindir}/meshtasticd
%dir %{_sysconfdir}/meshtasticd
%dir %{_sysconfdir}/meshtasticd/config.d
%dir %{_sysconfdir}/meshtasticd/available.d
%config(noreplace) %{_sysconfdir}/meshtasticd/config.yaml
%config %{_sysconfdir}/meshtasticd/available.d/*
%{_unitdir}/meshtasticd.service
%dir %{_datadir}/meshtasticd
%dir %{_datadir}/meshtasticd/web
%{_datadir}/meshtasticd/web/*
%dir %{_sysconfdir}/meshtasticd/ssl
%changelog
%autochangelog
+7 -41
View File
@@ -3,42 +3,7 @@
[platformio]
default_envs = tbeam
;default_envs = pico
;default_envs = tbeam-s3-core
;default_envs = tbeam0.7
;default_envs = heltec-v1
;default_envs = heltec-v2_0
;default_envs = heltec-v2_1
;default_envs = heltec-wireless-tracker
;default_envs = chatter2
;default_envs = tlora-v1
;default_envs = tlora_v1_3
;default_envs = tlora-v2
;default_envs = tlora-v2-1-1_6
;default_envs = tlora-v2-1-1_6-tcxo
;default_envs = tlora-v3-3-0-tcxo
;default_envs = tlora-t3s3-v1
;default_envs = t-echo
;default_envs = canaryone
;default_envs = native
;default_envs = nano-g1
;default_envs = pca10059_diy_eink
;default_envs = meshtastic-diy-v1
;default_envs = meshtastic-diy-v1_1
;default_envs = meshtastic-dr-dev
;default_envs = m5stack-coreink
;default_envs = rak4631
;default_envs = rak4631_eth_gw
;default_envs = rak2560
;default_envs = rak_wismeshtap
;default_envs = wio-e5
;default_envs = radiomaster_900_bandit_nano
;default_envs = radiomaster_900_bandit_micro
;default_envs = radiomaster_900_bandit
;default_envs = heltec_vision_master_t190
;default_envs = heltec_vision_master_e213
;default_envs = heltec_vision_master_e290
;default_envs = heltec_mesh_node_t114
extra_configs =
arch/*/*.ini
variants/*/platformio.ini
@@ -55,7 +20,7 @@ extra_scripts = bin/platformio-custom.py
build_flags = -Wno-missing-field-initializers
-Wno-format
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
-Isrc -Isrc/mesh -Isrc/mesh/generated -Isrc/gps -Isrc/buzz -Wl,-Map,"${platformio.build_dir}"/output.map
-DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1
@@ -84,7 +49,7 @@ build_flags = -Wno-missing-field-initializers
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
#-DBUILD_EPOCH=$UNIX_TIME
;-D OLED_PL
#-D OLED_PL=1
monitor_speed = 115200
monitor_filters = direct
@@ -94,7 +59,7 @@ lib_deps =
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
nanopb/Nanopb@0.4.9
nanopb/Nanopb@0.4.91
erriez/ErriezCRC32@1.0.1
; Used for the code analysis in PIO Home / Inspect
@@ -123,7 +88,7 @@ lib_deps =
[radiolib_base]
lib_deps =
jgromes/RadioLib@7.1.0
jgromes/RadioLib@7.1.2
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
@@ -161,7 +126,8 @@ lib_deps =
mprograms/QMC5883LCompass@1.2.3
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d
https://github.com/DFRobot/DFRobot_RainfallSensor#38fea5e02b40a5430be6dab39a99a6f6347d667e
robtillaart/INA226@0.6.0
; Health Sensor Libraries
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
+2
View File
@@ -0,0 +1,2 @@
[rpkg]
user_macros = "${git_props:root}/bin/rpkg.macros"
+1 -1
View File
@@ -153,7 +153,7 @@ class AmbientLightingThread : public concurrency::OSThread
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
#endif
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
pixels.fill(BUTTON2_COLOR, BUTTON1_COLOR_INDEX, 1);
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
#endif
#endif
pixels.show();
+14
View File
@@ -190,6 +190,20 @@ int32_t ButtonThread::runOnce()
case 4:
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
#if defined(RAK_4631)
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
case 5:
if (accelerometerThread) {
accelerometerThread->calibrate(30);
}
break;
// 6 clicks: start accelerometer/magenetometer calibration for 60 seconds
case 6:
if (accelerometerThread) {
accelerometerThread->calibrate(60);
}
break;
#endif
// No valid multipress action
default:
+24 -20
View File
@@ -9,6 +9,7 @@
*
*/
#include "FSCommon.h"
#include "SPILock.h"
#include "configuration.h"
#ifdef HAS_SDCARD
@@ -48,24 +49,6 @@ void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
}
#endif
bool lfs_assert_failed =
false; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our modified lfs_util.h)
extern "C" void lfs_assert(const char *reason)
{
LOG_ERROR("LFS assert: %s", reason);
lfs_assert_failed = true;
#ifndef ARCH_PORTDUINO
#ifdef FSCom
// CORRUPTED FILESYSTEM. This causes bootloop so
// might as well try formatting now.
LOG_ERROR("Trying FSCom.format()");
FSCom.format();
#endif
#endif
}
/**
* @brief Copies a file from one location to another.
*
@@ -102,6 +85,8 @@ bool copyFile(const char *from, const char *to)
return true;
#elif defined(FSCom)
// take SPI Lock
concurrency::LockGuard g(spiLock);
unsigned char cbuffer[16];
File f1 = FSCom.open(from, FILE_O_READ);
@@ -145,16 +130,23 @@ bool renameFile(const char *pathFrom, const char *pathTo)
return false;
}
#elif defined(FSCom)
#ifdef ARCH_ESP32
// take SPI Lock
spiLock->lock();
// rename was fixed for ESP32 IDF LittleFS in April
return FSCom.rename(pathFrom, pathTo);
bool result = FSCom.rename(pathFrom, pathTo);
spiLock->unlock();
return result;
#else
// copyFile does its own locking.
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom)) {
return true;
} else {
return false;
}
#endif
#endif
}
@@ -164,6 +156,7 @@ bool renameFile(const char *pathFrom, const char *pathTo)
* @brief Get the list of files in a directory.
*
* This function returns a list of files in a directory. The list includes the full path of each file.
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
*
* @param dirname The name of the directory.
* @param levels The number of levels of subdirectories to list.
@@ -192,7 +185,7 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
file.close();
}
} else {
meshtastic_FileInfo fileInfo = {"", file.size()};
meshtastic_FileInfo fileInfo = {"", static_cast<uint32_t>(file.size())};
#ifdef ARCH_ESP32
strcpy(fileInfo.file_name, file.path());
#else
@@ -212,6 +205,7 @@ std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
/**
* Lists the contents of a directory.
* We can't use SPILOCK here because of recursion. Callers of this function should use SPILOCK.
*
* @param dirname The name of the directory to list.
* @param levels The number of levels of subdirectories to list.
@@ -325,18 +319,27 @@ void listDir(const char *dirname, uint8_t levels, bool del)
void rmDir(const char *dirname)
{
#ifdef FSCom
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
listDir(dirname, 10, true);
#elif defined(ARCH_NRF52)
// nRF52 implementation of LittleFS has a recursive delete function
FSCom.rmdir_r(dirname);
#endif
#endif
}
/**
* Some platforms (nrf52) might need to do an extra step before FSBegin().
*/
__attribute__((weak, noinline)) void preFSBegin() {}
void fsInit()
{
#ifdef FSCom
concurrency::LockGuard g(spiLock);
preFSBegin();
if (!FSBegin()) {
LOG_ERROR("Filesystem mount failed");
// assert(0); This auto-formats the partition, so no need to fail here.
@@ -356,6 +359,7 @@ void fsInit()
void setupSDCard()
{
#ifdef HAS_SDCARD
concurrency::LockGuard g(spiLock);
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
if (!SD.begin(SDCARD_CS, SDHandler)) {
+1 -4
View File
@@ -57,7 +57,4 @@ bool renameFile(const char *pathFrom, const char *pathTo);
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
void listDir(const char *dirname, uint8_t levels, bool del = false);
void rmDir(const char *dirname);
void setupSDCard();
extern bool lfs_assert_failed; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our
// modified lfs_util.h)
void setupSDCard();
+6 -4
View File
@@ -87,7 +87,7 @@ MAX17048Sensor max17048Sensor;
#endif
#endif
#if HAS_RAKPROT && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO)
RAK9154Sensor rak9154Sensor;
#endif
@@ -243,7 +243,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasRAK()) {
return getRAKVoltage();
}
@@ -406,7 +407,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// we can't be smart enough to say 'full'?
virtual bool isCharging() override
{
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \
!defined(HAS_PMU)
if (hasRAK()) {
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
}
@@ -447,7 +449,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
float last_read_value = (OCV[NUM_OCV_POINTS - 1] * NUM_CELLS);
uint32_t last_read_time_ms = 0;
#if defined(HAS_RAKPROT)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT)
uint16_t getRAKVoltage() { return rak9154Sensor.getBusVoltageMv(); }
+11 -11
View File
@@ -79,17 +79,17 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
}
if (color && logLevel != nullptr) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
Print::write("\u001b[34m", 6);
Print::write("\u001b[34m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
Print::write("\u001b[32m", 6);
Print::write("\u001b[32m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
Print::write("\u001b[33m", 6);
Print::write("\u001b[33m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
Print::write("\u001b[31m", 6);
Print::write("\u001b[31m", 5);
}
len = Print::write(printBuf, len);
if (color && logLevel != nullptr) {
Print::write("\u001b[0m", 5);
Print::write("\u001b[0m", 4);
}
return len;
}
@@ -107,15 +107,15 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
// include the header
if (color) {
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
Print::write("\u001b[34m", 6);
Print::write("\u001b[34m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
Print::write("\u001b[32m", 6);
Print::write("\u001b[32m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
Print::write("\u001b[33m", 6);
Print::write("\u001b[33m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
Print::write("\u001b[31m", 6);
Print::write("\u001b[31m", 5);
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0)
Print::write("\u001b[35m", 6);
Print::write("\u001b[35m", 5);
}
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
@@ -393,4 +393,4 @@ std::string RedirectablePrint::mt_sprintf(const std::string fmt_str, ...)
break;
}
return std::string(formatted.get());
}
}
+21 -9
View File
@@ -5,6 +5,12 @@
// Only way to work on both esp32 and nrf52
static File openFile(const char *filename, bool fullAtomic)
{
concurrency::LockGuard g(spiLock);
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
#ifdef ARCH_NRF52
FSCom.remove(filename);
return FSCom.open(filename, FILE_O_WRITE);
#endif
if (!fullAtomic)
FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists)
@@ -12,8 +18,6 @@ static File openFile(const char *filename, bool fullAtomic)
filenameTmp += ".tmp";
// clear any previous LFS errors
lfs_assert_failed = false;
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
}
@@ -53,14 +57,23 @@ bool SafeFile::close()
if (!f)
return false;
spiLock->lock();
f.close();
spiLock->unlock();
#ifdef ARCH_NRF52
return true;
#endif
if (!testReadback())
return false;
// brief window of risk here ;-)
if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) {
LOG_ERROR("Can't remove old pref file");
return false;
{ // Scope for lock
concurrency::LockGuard g(spiLock);
// brief window of risk here ;-)
if (fullAtomic && FSCom.exists(filename.c_str()) && !FSCom.remove(filename.c_str())) {
LOG_ERROR("Can't remove old pref file");
return false;
}
}
String filenameTmp = filename;
@@ -76,8 +89,7 @@ bool SafeFile::close()
/// Read our (closed) tempfile back in and compare the hash
bool SafeFile::testReadback()
{
bool lfs_failed = lfs_assert_failed;
lfs_assert_failed = false;
concurrency::LockGuard g(spiLock);
String filenameTmp = filename;
filenameTmp += ".tmp";
@@ -99,7 +111,7 @@ bool SafeFile::testReadback()
return false;
}
return !lfs_failed;
return true;
}
#endif
+1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "FSCommon.h"
#include "SPILock.h"
#include "configuration.h"
#ifdef FSCom
+9 -7
View File
@@ -145,6 +145,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define OPT3001_ADDR_ALT 0x44
#define MLX90632_ADDR 0x3A
#define DFROBOT_LARK_ADDR 0x42
#define DFROBOT_RAIN_ADDR 0x1d
#define NAU7802_ADDR 0x2A
#define MAX30102_ADDR 0x57
#define MLX90614_ADDR_DEF 0x5A
@@ -178,13 +179,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TCA9535_ADDR 0x20
#define TCA9555_ADDR 0x26
// -----------------------------------------------------------------------------
// GPS
// -----------------------------------------------------------------------------
#ifndef GPS_THREAD_INTERVAL
#define GPS_THREAD_INTERVAL 200
#endif
// -----------------------------------------------------------------------------
// Touchscreen
// -----------------------------------------------------------------------------
@@ -206,6 +200,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define VEXT_ON_VALUE LOW
#endif
// -----------------------------------------------------------------------------
// GPS
// -----------------------------------------------------------------------------
#ifndef GPS_BAUDRATE
#define GPS_BAUDRATE 9600
#define GPS_BAUDRATE_FIXED 0
@@ -213,6 +211,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define GPS_BAUDRATE_FIXED 1
#endif
#ifndef GPS_THREAD_INTERVAL
#define GPS_THREAD_INTERVAL 200
#endif
/* Step #2: follow with defines common to the architecture;
also enable HAS_ option not specifically disabled by variant.h */
#include "architecture.h"
+1
View File
@@ -66,6 +66,7 @@ class ScanI2C
CGRADSENS,
INA226,
NXP_SE050,
DFROBOT_RAIN,
} DeviceType;
// typedef uint8_t DeviceAddress;
+19 -4
View File
@@ -84,23 +84,33 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const
return o_probe;
}
uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation &registerLocation,
ScanI2CTwoWire::ResponseWidth responseWidth) const
ScanI2CTwoWire::ResponseWidth responseWidth, bool zeropad = false) const
{
uint16_t value = 0x00;
TwoWire *i2cBus = fetchI2CBus(registerLocation.i2cAddress);
i2cBus->beginTransmission(registerLocation.i2cAddress.address);
i2cBus->write(registerLocation.registerAddress);
if (zeropad) {
// Lark Commands need the argument list length in 2 bytes.
i2cBus->write((int)0);
i2cBus->write((int)0);
}
i2cBus->endTransmission();
delay(20);
i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth);
if (i2cBus->available() == 2) {
if (i2cBus->available() > 1) {
// Read MSB, then LSB
value = (uint16_t)i2cBus->read() << 8;
value |= i2cBus->read();
} else if (i2cBus->available()) {
value = i2cBus->read();
}
// Drain excess bytes
for (uint8_t i = 0; i < responseWidth - 1; i++) {
if (i2cBus->available())
i2cBus->read();
}
return value;
}
@@ -234,6 +244,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("BMP-388", (uint8_t)addr.address);
type = BMP_3XX;
break;
case 0x60: // BMP-390 should be 0x60
logFoundDevice("BMP-390", (uint8_t)addr.address);
type = BMP_3XX;
break;
case 0x58: // BMP-280 should be 0x58
default:
logFoundDevice("BMP-280", (uint8_t)addr.address);
@@ -286,7 +300,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
RESPONSE_PAYLOAD 0x01
RESPONSE_PAYLOAD+1 0x00
*/
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2);
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 6, true);
LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue);
if (registerValue == 0x5305) {
logFoundDevice("DFRobot Lark", (uint8_t)addr.address);
@@ -402,6 +416,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
#endif
@@ -510,4 +525,4 @@ void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address)
{
LOG_INFO("%s found at address 0x%x", device, address);
}
#endif
#endif
+1 -1
View File
@@ -53,7 +53,7 @@ class ScanI2CTwoWire : public ScanI2C
concurrency::Lock lock;
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const;
uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth, bool) const;
DeviceType probeOLED(ScanI2C::DeviceAddress) const;
+27 -87
View File
@@ -35,7 +35,11 @@ template <typename T, std::size_t N> std::size_t array_count(const T (&)[N])
}
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
#if defined(RAK2560)
HardwareSerial *GPS::_serial_gps = &Serial2;
#else
HardwareSerial *GPS::_serial_gps = &Serial1;
#endif
#elif defined(ARCH_RP2040)
SerialUART *GPS::_serial_gps = &Serial1;
#else
@@ -44,8 +48,6 @@ HardwareSerial *GPS::_serial_gps = nullptr;
GPS *gps = nullptr;
static const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
static GPSUpdateScheduling scheduling;
/// Multiple GPS instances might use the same serial port (in sequence), but we can
@@ -433,6 +435,10 @@ static const int serialSpeeds[3] = {9600, 115200, 38400};
static const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE};
#endif
#ifndef GPS_PROBETRIES
#define GPS_PROBETRIES 2
#endif
/**
* @brief Setup the GPS based on the model detected.
* We detect the GPS by cycling through a set of baud rates, first common then rare.
@@ -445,7 +451,18 @@ bool GPS::setup()
if (!didSerialInit) {
int msglen = 0;
if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) {
if (probeTries < 2) {
#ifdef TRACKER_T1000_E
// add power up/down strategy, improve ag3335 detection success
digitalWrite(PIN_GPS_EN, LOW);
delay(500);
digitalWrite(GPS_VRTC_EN, LOW);
delay(1000);
digitalWrite(GPS_VRTC_EN, HIGH);
delay(500);
digitalWrite(PIN_GPS_EN, HIGH);
delay(1000);
#endif
if (probeTries < GPS_PROBETRIES) {
LOG_DEBUG("Probe for GPS at %d", serialSpeeds[speedSelect]);
gnssModel = probe(serialSpeeds[speedSelect]);
if (gnssModel == GNSS_MODEL_UNKNOWN) {
@@ -456,7 +473,7 @@ bool GPS::setup()
}
}
// Rare Serial Speeds
if (probeTries == 2) {
if (probeTries == GPS_PROBETRIES) {
LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]);
gnssModel = probe(rareSerialSpeeds[speedSelect]);
if (gnssModel == GNSS_MODEL_UNKNOWN) {
@@ -768,6 +785,9 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
setPowerPMU(true); // Power (PMU): on
writePinStandby(false); // Standby (pin): awake (not standby)
setPowerUBLOX(true); // Standby (UBLOX): awake
#ifdef GNSS_AIROHA
lastFixStartMsec = 0;
#endif
break;
case GPS_SOFTSLEEP:
@@ -1017,14 +1037,6 @@ int32_t GPS::runOnce()
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
return disable();
}
// ONCE we will factory reset the GPS for bug #327
if (!devicestate.did_gps_reset) {
LOG_WARN("GPS FactoryReset requested");
if (gps->factoryReset()) { // If we don't succeed try again next time
devicestate.did_gps_reset = true;
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
}
}
GPSInitFinished = true;
publishUpdate();
}
@@ -1037,24 +1049,6 @@ int32_t GPS::runOnce()
if (whileActive()) {
// if we have received valid NMEA claim we are connected
setConnected();
} else {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) &&
IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9,
GNSS_MODEL_UBLOX10)) {
// reset the GPS on next bootup
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
LOG_DEBUG("GPS is not found, try factory reset on next boot");
devicestate.did_gps_reset = false;
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
}
}
}
// At least one GPS has a bad habit of losing its mind from time to time
if (rebootsSeen > 2) {
rebootsSeen = 0;
LOG_DEBUG("Would normally factoryReset()");
// gps->factoryReset();
}
// If we're due for an update, wake the GPS
@@ -1190,6 +1184,8 @@ GnssModel_t GPS::probe(int serialSpeed)
PROBE_SIMPLE("L76B", "$PMTK605*31", "Quectel-L76B", GNSS_MODEL_MTK_L76B, 500);
PROBE_SIMPLE("PA1616S", "$PMTK605*31", "1616S", GNSS_MODEL_MTK_PA1616S, 500);
PROBE_SIMPLE("LS20031", "$PMTK605*31", "MC-1513", GNSS_MODEL_LS20031, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
UBXChecksum(cfg_rate, sizeof(cfg_rate));
clearBuffer();
@@ -1387,62 +1383,6 @@ static int32_t toDegInt(RawDegrees d)
return r;
}
bool GPS::factoryReset()
{
#ifdef PIN_GPS_REINIT
// The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
pinMode(PIN_GPS_REINIT, OUTPUT);
digitalWrite(PIN_GPS_REINIT, 0);
delay(150); // The L76K datasheet calls for at least 100MS delay
digitalWrite(PIN_GPS_REINIT, 1);
#endif
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
byte _message_reset1[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
} else if (gnssModel == GNSS_MODEL_MTK) {
// send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements)
LOG_INFO("GNSS Factory Reset via PCAS10,3");
_serial_gps->write("$PCAS10,3*1F\r\n");
delay(100);
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
LOG_INFO("Factory Reset via CAS-CFG-RST");
uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY);
_serial_gps->write(UBXscratch, msglen);
delay(100);
} else {
// fire this for good measure, if we have an L76B - won't harm other devices.
_serial_gps->write("$PMTK104*37\r\n");
// No PMTK_ACK for this command.
delay(100);
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's
// UBLOX. Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
_serial_gps->write(_message_reset, sizeof(_message_reset));
}
delay(1000);
return true;
}
/**
* Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations
@@ -1750,4 +1690,4 @@ void GPS::toggleGpsMode()
enable();
}
}
#endif // Exclude GPS
#endif // Exclude GPS
+3 -4
View File
@@ -29,7 +29,8 @@ typedef enum {
GNSS_MODEL_MTK_L76B,
GNSS_MODEL_MTK_PA1616S,
GNSS_MODEL_AG3335,
GNSS_MODEL_AG3352
GNSS_MODEL_AG3352,
GNSS_MODEL_LS20031
} GnssModel_t;
typedef enum {
@@ -100,8 +101,6 @@ class GPS : private concurrency::OSThread
// Empty the input buffer as quickly as possible
void clearBuffer();
virtual bool factoryReset();
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
static GPS *createGps();
@@ -239,4 +238,4 @@ class GPS : private concurrency::OSThread
};
extern GPS *gps;
#endif // Exclude GPS
#endif // Exclude GPS
+9
View File
@@ -140,6 +140,15 @@ bool EInkDisplay::connect()
adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(MESHLINK)
{
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);
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(RAK4630) || defined(MAKERPYTHON)
{
if (eink_found) {
+2 -2
View File
@@ -238,7 +238,7 @@ void EInkDynamicDisplay::checkRateLimiting()
// Skip update: too soon for BACKGROUND
if (frameFlags == BACKGROUND) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_BACKGROUND_SEC * 1000)) {
if (Throttle::isWithinTimespanMs(previousRunMs, 30000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FULL;
return;
@@ -251,7 +251,7 @@ void EInkDynamicDisplay::checkRateLimiting()
// Skip update: too soon for RESPONSIVE
if (frameFlags & RESPONSIVE) {
if (Throttle::isWithinTimespanMs(previousRunMs, EINK_LIMIT_RATE_RESPONSIVE_SEC * 1000)) {
if (Throttle::isWithinTimespanMs(previousRunMs, 1000)) {
refresh = SKIPPED;
reason = EXCEEDED_RATELIMIT_FAST;
LOG_DEBUG("refresh=SKIPPED, reason=EXCEEDED_RATELIMIT_FAST, frameFlags=0x%x", frameFlags);
+122 -31
View File
@@ -123,7 +123,7 @@ static bool heartbeat = false;
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
/// Check if the display can render a string (detect special chars; emoji)
// Check if the display can render a string (detect special chars; emoji)
static bool haveGlyphs(const char *str)
{
#if defined(OLED_PL) || defined(OLED_UA) || defined(OLED_RU) || defined(OLED_CS)
@@ -162,11 +162,7 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
display->setFont(FONT_MEDIUM);
display->setTextAlignment(TEXT_ALIGN_LEFT);
#ifdef USERPREFS_SPLASH_TITLE
const char *title = USERPREFS_SPLASH_TITLE;
#else
const char *title = "meshtastic.org";
#endif
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);
@@ -185,6 +181,56 @@ static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDispl
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
}
#ifdef USERPREFS_OEM_TEXT
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
static const uint8_t xbm[] = USERPREFS_OEM_IMAGE_DATA;
display->drawXbm(x + (SCREEN_WIDTH - USERPREFS_OEM_IMAGE_WIDTH) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - USERPREFS_OEM_IMAGE_HEIGHT) / 2 + 2, USERPREFS_OEM_IMAGE_WIDTH,
USERPREFS_OEM_IMAGE_HEIGHT, xbm);
switch (USERPREFS_OEM_FONT_SIZE) {
case 0:
display->setFont(FONT_SMALL);
break;
case 2:
display->setFont(FONT_LARGE);
break;
default:
display->setFont(FONT_MEDIUM);
break;
}
display->setTextAlignment(TEXT_ALIGN_LEFT);
const char *title = USERPREFS_OEM_TEXT;
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
display->setFont(FONT_SMALL);
// Draw region in upper left
if (upperMsg)
display->drawString(x + 0, y + 0, upperMsg);
// Draw version and shortname in upper right
char buf[25];
snprintf(buf, sizeof(buf), "%s\n%s", xstr(APP_VERSION_SHORT), haveGlyphs(owner.short_name) ? owner.short_name : "");
display->setTextAlignment(TEXT_ALIGN_RIGHT);
display->drawString(x + SCREEN_WIDTH, y + 0, buf);
screen->forceDisplay();
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
}
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
// Draw region in upper left
const char *region = myRegion ? myRegion->name : NULL;
drawOEMIconScreen(region, display, state, x, y);
}
#endif
void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
{
uint16_t x_offset = display->width() / 2;
@@ -1015,7 +1061,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - devil_height) / 2 + 2 + 5, devil_width, devil_height, devil);
} else if (strcmp(msg, "♥️") == 0 || strcmp(msg, "\U0001F9E1") == 0 || strcmp(msg, "\U00002763") == 0 ||
strcmp(msg, "\U00002764") == 0 || strcmp(msg, "\U0001F495") == 0 || strcmp(msg, "\U0001F496") == 0 ||
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F496") == 0) {
strcmp(msg, "\U0001F497") == 0 || strcmp(msg, "\U0001F498") == 0) {
display->drawXbm(x + (SCREEN_WIDTH - heart_width) / 2,
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - heart_height) / 2 + 2 + 5, heart_width, heart_height, heart);
} else {
@@ -1400,9 +1446,9 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
static char distStr[20];
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
strncpy(distStr, "? mi", sizeof(distStr)); // might not have location data
strncpy(distStr, "? mi ?°", sizeof(distStr)); // might not have location data
} else {
strncpy(distStr, "? km", sizeof(distStr));
strncpy(distStr, "? km ?°", sizeof(distStr));
}
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
const char *fields[] = {username, lastStr, signalStr, distStr, NULL};
@@ -1435,18 +1481,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
if (d < (2 * MILES_TO_FEET))
snprintf(distStr, sizeof(distStr), "%.0f ft", d * METERS_TO_FEET);
else
snprintf(distStr, sizeof(distStr), "%.1f mi", d * METERS_TO_FEET / MILES_TO_FEET);
} else {
if (d < 2000)
snprintf(distStr, sizeof(distStr), "%.0f m", d);
else
snprintf(distStr, sizeof(distStr), "%.1f km", d / 1000);
}
float bearingToOther =
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
// If the top of the compass is a static north then bearingToOther can be drawn on the compass directly
@@ -1454,6 +1488,22 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
if (!config.display.compass_north_top)
bearingToOther -= myHeading;
screen->drawNodeHeading(display, compassX, compassY, compassDiam, bearingToOther);
float bearingToOtherDegrees = (bearingToOther < 0) ? bearingToOther + 2 * PI : bearingToOther;
bearingToOtherDegrees = bearingToOtherDegrees * 180 / PI;
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
if (d < (2 * MILES_TO_FEET))
snprintf(distStr, sizeof(distStr), "%.0fft %.0f°", d * METERS_TO_FEET, bearingToOtherDegrees);
else
snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET,
bearingToOtherDegrees);
} else {
if (d < 2000)
snprintf(distStr, sizeof(distStr), "%.0fm %.0f°", d, bearingToOtherDegrees);
else
snprintf(distStr, sizeof(distStr), "%.1fkm %.0f°", d / 1000, bearingToOtherDegrees);
}
}
}
if (!hasNodeHeading) {
@@ -1506,7 +1556,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
#elif defined(USE_ST7567)
dispdev = new ST7567Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif ARCH_PORTDUINO
#elif ARCH_PORTDUINO && !HAS_TFT
if (settingsMap[displayPanel] != no_screen) {
LOG_DEBUG("Make TFTDisplay!");
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
@@ -1658,6 +1708,10 @@ void Screen::setup()
// Set the utf8 conversion function
dispdev->setFontTableLookupFunction(customFontTableLookup);
#ifdef USERPREFS_OEM_TEXT
logo_timeout *= 2; // Double the time if we have a custom logo
#endif
// Add frames.
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
@@ -1803,6 +1857,22 @@ int32_t Screen::runOnce()
showingBootScreen = false;
}
#ifdef USERPREFS_OEM_TEXT
static bool showingOEMBootScreen = true;
if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) {
LOG_INFO("Switch to OEM screen...");
// Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
ui->setFrames(bootOEMFrames, bootOEMFrameCount);
ui->update();
#ifndef USE_EINK
ui->update();
#endif
showingOEMBootScreen = false;
}
#endif
#ifndef DISABLE_WELCOME_UNSET
if (showingNormalScreen && config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
setWelcomeFrames();
@@ -2578,13 +2648,12 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->drawString(x + 1, y, String("USB"));
}
auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true);
// auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, true);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
if (config.display.heading_bold)
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
// display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
// if (config.display.heading_bold)
// display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
// Line 2
uint32_t currentMillis = millis();
uint32_t seconds = currentMillis / 1000;
uint32_t minutes = seconds / 60;
@@ -2597,6 +2666,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->setColor(WHITE);
// Setup string to assemble analogClock string
std::string analogClock = "";
// Show uptime as days, hours, minutes OR seconds
std::string uptime = screen->drawTimeDelta(days, hours, minutes, seconds);
@@ -2613,17 +2685,36 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
char timebuf[10];
snprintf(timebuf, sizeof(timebuf), " %02d:%02d:%02d", hour, min, sec);
uptime += timebuf;
char timebuf[12];
if (config.display.use_12h_clock) {
std::string meridiem = "am";
if (hour >= 12) {
if (hour > 12)
hour -= 12;
meridiem = "pm";
}
if (hour == 00) {
hour = 12;
}
snprintf(timebuf, sizeof(timebuf), "%d:%02d:%02d%s", hour, min, sec, meridiem.c_str());
} else {
snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d", hour, min, sec);
}
analogClock += timebuf;
}
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime.c_str());
// Line 1
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(uptime.c_str()), y, uptime.c_str());
// Line 2
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, analogClock.c_str());
// Display Channel Utilization
char chUtil[13];
snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
#if HAS_GPS
if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
// Line 3
@@ -2756,4 +2847,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
+6
View File
@@ -278,6 +278,10 @@ class Screen : public concurrency::OSThread
bool hasHeading() { return hasCompass; }
long getHeading() { return compassHeading; }
void setEndCalibration(uint32_t _endCalibrationAt) { endCalibrationAt = _endCalibrationAt; }
uint32_t getEndCalibration() { return endCalibrationAt; }
// functions for display brightness
void increaseBrightness();
void decreaseBrightness();
@@ -673,6 +677,8 @@ class Screen : public concurrency::OSThread
bool hasCompass = false;
float compassHeading;
uint32_t endCalibrationAt;
/// Holds state for debug information
DebugInfo debugInfo;
+50 -38
View File
@@ -16,49 +16,61 @@
#include "graphics/fonts/OLEDDisplayFontsCS.h"
#endif
#ifdef OLED_PL
#define FONT_SMALL_LOCAL ArialMT_Plain_10_PL
#else
#ifdef OLED_RU
#define FONT_SMALL_LOCAL ArialMT_Plain_10_RU
#else
#ifdef OLED_UA
#define FONT_SMALL_LOCAL ArialMT_Plain_10_UA // Height: 13
#else
#ifdef OLED_CS
#define FONT_SMALL_LOCAL ArialMT_Plain_10_CS
#else
#define FONT_SMALL_LOCAL ArialMT_Plain_10 // Height: 13
#endif
#endif
#endif
#endif
#ifdef OLED_PL
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_PL // Height: 19
#else
#ifdef OLED_UA
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_UA // Height: 19
#else
#ifdef OLED_CS
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16_CS
#else
#define FONT_MEDIUM_LOCAL ArialMT_Plain_16 // Height: 19
#endif
#endif
#endif
#ifdef OLED_PL
#define FONT_LARGE_LOCAL ArialMT_Plain_24_PL // Height: 28
#else
#ifdef OLED_UA
#define FONT_LARGE_LOCAL ArialMT_Plain_24_UA // Height: 28
#else
#ifdef OLED_CS
#define FONT_LARGE_LOCAL ArialMT_Plain_24_CS // Height: 28
#else
#define FONT_LARGE_LOCAL ArialMT_Plain_24 // Height: 28
#endif
#endif
#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)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28
#define FONT_LARGE FONT_LARGE_LOCAL // Height: 28
#else
#ifdef OLED_PL
#define FONT_SMALL ArialMT_Plain_10_PL
#else
#ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU
#else
#ifdef OLED_UA
#define FONT_SMALL ArialMT_Plain_10_UA // Height: 13
#else
#ifdef OLED_CS
#define FONT_SMALL ArialMT_Plain_10_CS
#else
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
#endif
#endif
#endif
#endif
#ifdef OLED_UA
#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19
#else
#ifdef OLED_CS
#define FONT_MEDIUM ArialMT_Plain_16_CS
#else
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
#endif
#endif
#ifdef OLED_UA
#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28
#else
#ifdef OLED_CS
#define FONT_LARGE ArialMT_Plain_24_CS // Height: 28
#else
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
#endif
#endif
#define FONT_SMALL FONT_SMALL_LOCAL // Height: 13
#define FONT_MEDIUM FONT_MEDIUM_LOCAL // Height: 19
#define FONT_LARGE FONT_LARGE_LOCAL // Height: 28
#endif
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
+19 -8
View File
@@ -352,7 +352,7 @@ static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_LCD *_panel_instance;
lgfx::Panel_Device *_panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::ITouch *_touch_instance;
@@ -366,10 +366,21 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance = new lgfx::Panel_ST7735;
else if (settingsMap[displayPanel] == st7735s)
_panel_instance = new lgfx::Panel_ST7735S;
else if (settingsMap[displayPanel] == st7796)
_panel_instance = new lgfx::Panel_ST7796;
else if (settingsMap[displayPanel] == ili9341)
_panel_instance = new lgfx::Panel_ILI9341;
else if (settingsMap[displayPanel] == ili9342)
_panel_instance = new lgfx::Panel_ILI9342;
else if (settingsMap[displayPanel] == ili9488)
_panel_instance = new lgfx::Panel_ILI9488;
else if (settingsMap[displayPanel] == hx8357d)
_panel_instance = new lgfx::Panel_HX8357D;
else {
_panel_instance = new lgfx::Panel_NULL;
LOG_ERROR("Unknown display panel configured!");
}
auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0;
buscfg.spi_host = settingsMap[displayspidev];
@@ -383,12 +394,12 @@ class LGFX : public lgfx::LGFX_Device
LOG_DEBUG("Height: %d, Width: %d ", settingsMap[displayHeight], settingsMap[displayWidth]);
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = settingsMap[displayReset];
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
_panel_instance->config(cfg);
@@ -410,7 +421,7 @@ class LGFX : public lgfx::LGFX_Device
touch_cfg.y_max = settingsMap[displayWidth] - 1;
touch_cfg.pin_int = settingsMap[touchscreenIRQ];
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;
touch_cfg.offset_rotation = settingsMap[touchscreenRotate];
if (settingsMap[touchscreenI2CAddr] != -1) {
touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr];
} else {
+3 -3
View File
@@ -7,7 +7,7 @@ const uint8_t ArialMT_Plain_10_CS[] PROGMEM = {
0x20, // First char: 32
0xE0, // Number of chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x0A, // 32
0xFF, 0xFF, 0x00, 0x03, // 32
0x00, 0x00, 0x04, 0x03, // 33
0x00, 0x04, 0x05, 0x04, // 34
0x00, 0x09, 0x09, 0x06, // 35
@@ -453,7 +453,7 @@ const uint8_t ArialMT_Plain_16_CS[] PROGMEM = {
0x20, // First char: 32
0xE0, // Number of chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x10, // 32
0xFF, 0xFF, 0x00, 0x04, // 32
0x00, 0x00, 0x08, 0x04, // 33
0x00, 0x08, 0x0D, 0x06, // 34
0x00, 0x15, 0x1A, 0x0A, // 35
@@ -1036,7 +1036,7 @@ const uint8_t ArialMT_Plain_24_CS[] PROGMEM = {
0x20, // First char: 32
0xE0, // Number of chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x18, // 32
0xFF, 0xFF, 0x00, 0x06, // 32
0x00, 0x00, 0x13, 0x06, // 33
0x00, 0x13, 0x1A, 0x08, // 34
0x00, 0x2D, 0x33, 0x0E, // 35

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