Compare commits

..

346 Commits

Author SHA1 Message Date
Thomas Göttgens
05147c016c Merge pull request #1839 from meshtastic/pwm-notify
use PWM buzzer on notification module.
2022-10-22 14:25:32 +02:00
Thomas Göttgens
62b3509009 missed one 2022-10-22 14:13:45 +02:00
Thomas Göttgens
d817889255 don't depend on EXT_NOTIFY_OUT being defined. 2022-10-22 13:45:43 +02:00
Thomas Göttgens
d4ddcdd91e use PWM buzzer on notification module. To activate set moduleConfig.external_notification.output equal to the PIN_BUZZER. If another value is set, the traditional digital mode is used 2022-10-22 13:35:34 +02:00
Thomas Göttgens
0bda4c2f76 Merge pull request #1838 from meshtastic/filebrowser-fix
fix json filebrowser in web server
2022-10-22 12:35:31 +02:00
Thomas Göttgens
be8da851a6 fix json filebrowser in web server 2022-10-22 11:55:01 +02:00
Thomas Göttgens
d4459a48b9 Merge pull request #1831 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-21 09:43:30 +02:00
thebentern
197bd2c3e1 [create-pull-request] automated change 2022-10-20 22:04:56 +00:00
Ben Meadors
d4ea9568ac Save devicestate (nodedb) on position config change (#1829) 2022-10-20 13:14:53 -05:00
Ben Meadors
97968213ff Factory reset should include modules and channels (#1828) 2022-10-20 07:51:52 -05:00
Thomas Göttgens
995885962d Merge pull request #1826 from meshtastic/oem-proto
wire in OEM.proto keystore
2022-10-20 09:10:01 +02:00
Ben Meadors
ddc1928bbb Merge branch 'master' into oem-proto 2022-10-19 19:22:35 -05:00
Ben Meadors
056a93f0c9 Consolidate reboots (#1827) 2022-10-19 19:19:04 -05:00
Ben Meadors
3d9845ff6d Update checkout version and release string 2022-10-19 11:43:24 -05:00
Ben Meadors
b615463981 Update download-artifiact version 2022-10-19 11:35:25 -05:00
Ben Meadors
d3540e82ff I think these tokens are extra 2022-10-19 10:44:09 -05:00
Ben Meadors
15ec8ba6a3 Whoops 2022-10-19 08:58:14 -05:00
Ben Meadors
db12eab083 Update setup-python 2022-10-19 08:51:00 -05:00
Thomas Göttgens
7d8c77a4b2 Merge branch 'master' into oem-proto 2022-10-19 15:42:21 +02:00
Thomas Göttgens
7c8c479b96 wire in OEM.proto keystore 2022-10-19 15:39:06 +02:00
Ben Meadors
e29ae1cc91 Update upload-artifact version 2022-10-19 08:11:28 -05:00
Ben Meadors
089dd5b4d7 Update github cache action version 2022-10-19 07:38:44 -05:00
Ben Meadors
06285b599c Update deprecated ::set-output commands 2022-10-19 07:35:16 -05:00
Thomas Göttgens
1b6395b4e4 Merge pull request #1825 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-19 13:45:12 +02:00
caveman99
2236f74a55 [create-pull-request] automated change 2022-10-19 11:44:12 +00:00
Thomas Göttgens
43c9ab1faa Merge pull request #1824 from meshtastic/caveman99-patch1
Dont retransmit packets destined for ourselves.
2022-10-19 11:56:44 +02:00
Thomas Göttgens
b56f9b3b16 Dont retransmit packets destined for ourselves.
Solves assert failed: virtual ErrorCode Router::send(MeshPacket*) Router.cpp:189 (p->to != nodeDB.getNodeNum())
2022-10-19 11:44:26 +02:00
Thomas Göttgens
303396dfc3 Merge pull request #1823 from meshtastic/json-cleanup
Json cleanup
2022-10-19 11:20:24 +02:00
Thomas Göttgens
075a53ced0 Update MQTT.cpp 2022-10-19 11:04:13 +02:00
Thomas Göttgens
18ccb38824 Update MQTT.cpp 2022-10-19 11:01:23 +02:00
Thomas Göttgens
c97831963b just for good measure, correct json type field 2022-10-19 10:58:46 +02:00
Thomas Göttgens
7c3dc076d2 only convert and send JSON topics with type 'sendtext' 2022-10-19 10:54:56 +02:00
Thomas Göttgens
b859347ecd Merge pull request #1822 from meshtastic/json-cleanup
possible fix for stuck MQTT handler.
2022-10-19 00:02:00 +02:00
Thomas Göttgens
ea87193c8f possible fix for stuck MQTT handler. 2022-10-18 21:51:40 +02:00
Thomas Göttgens
c1381b9ebd Merge pull request #1818 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-18 12:21:02 +02:00
caveman99
227cd93e67 [create-pull-request] automated change 2022-10-18 10:20:06 +00:00
Thomas Göttgens
f68f8e5547 Merge pull request #1817 from meshtastic/json-cleanup
fix JSON red herring error messages and Redirectable Print's new fixed buffer
2022-10-18 11:57:11 +02:00
Thomas Göttgens
943e6f02d4 Merge branch 'master' into json-cleanup 2022-10-18 11:18:34 +02:00
Thomas Göttgens
01298a7b01 Update RedirectablePrint.cpp 2022-10-18 11:18:12 +02:00
Thomas Göttgens
46aee8274f fix JSON red herring error messages and Redirectable Print's new fixed buffer. 2022-10-18 11:16:21 +02:00
Thomas Göttgens
f76a2eeb9e Merge pull request #1816 from meshtastic/wifi-disconnect-fix
If wifi credentials ever go stale, dump them.
2022-10-18 11:15:19 +02:00
Thomas Göttgens
3b7c0be842 don't irritate people with non working options 2022-10-18 10:30:50 +02:00
Thomas Göttgens
49378a9145 If wifi credentials ever go stale, dump them.
This solves the dreaded 5 - STA_DISCONNECTED / 2 - AUTH_EXPIRE loops
2022-10-18 10:16:47 +02:00
Thomas Göttgens
139f61d03e Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 16:45:28 +02:00
Ben Meadors
f10d04591d Don't make a nested json object payload (#1815) 2022-10-17 09:09:28 -05:00
Thomas Göttgens
e65d9e8ccd Add support for SX1281 on 2.4 GHz (#1809)
* Add support for SX1281 on 2.4 GHz

* only allow wide BW settings when the right chip is detected

* portduino cannot use this chip yet as it uses an old modified version of radiolib

* missed a spot

* Attempt to supress false positive

* Attempt to supress false positive

* Trying casing from the cpp-check manual

* Trying casing from the cpp-check manual

* Inline suppr should be default but...

* Maybe casting it will make the damn thing shut up

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-10-17 08:33:41 -05:00
Ben Meadors
1fc3c0af70 Update variant.h (#1814) 2022-10-17 08:07:18 -05:00
Thomas Göttgens
e4751e34ae missed a spot 2022-10-17 10:34:43 +02:00
Thomas Göttgens
e922169e72 Merge branch 'LORA-24' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:32:35 +02:00
Thomas Göttgens
2b851ef6ae Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:32:05 +02:00
Thomas Göttgens
5f4b93aba2 portduino cannot use this chip yet as it uses an old modified version of radiolib 2022-10-17 10:31:29 +02:00
Thomas Göttgens
b66d1a5dab Merge branch 'master' into LORA-24 2022-10-17 10:05:15 +02:00
Thomas Göttgens
867525eff8 Merge pull request #1813 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-17 10:05:00 +02:00
caveman99
7dcc981a2c [create-pull-request] automated change 2022-10-17 08:04:36 +00:00
Thomas Göttgens
38fed8a61e Merge branch 'LORA-24' of github.com:meshtastic/Meshtastic-device 2022-10-17 10:00:41 +02:00
Thomas Göttgens
31c2c8a7a3 only allow wide BW settings when the right chip is detected 2022-10-17 10:00:00 +02:00
Thomas Göttgens
a081d28e36 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-17 09:45:39 +02:00
Ben Meadors
93bb4f84f9 Merge branch 'master' into LORA-24 2022-10-16 17:27:18 -05:00
github-actions[bot]
72e04edd7f [create-pull-request] automated change (#1812)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2022-10-16 17:26:55 -05:00
Ben Meadors
b0d05522c0 Make telemetry packets minimum priority (#1810) 2022-10-16 15:59:59 -05:00
Thomas Göttgens
f6119639bb Add support for SX1281 on 2.4 GHz 2022-10-16 19:07:58 +02:00
Ben Meadors
fc57a9daa4 Send environment telemetry every minute (#1808) 2022-10-16 11:36:38 -05:00
Thomas Göttgens
d8f44d7b1b Merge pull request #1807 from meshtastic/nmea-serial
Add NMEA output mode to serial module
2022-10-16 17:15:24 +02:00
Ben Meadors
efe2e90a03 Merge branch 'master' into nmea-serial 2022-10-16 09:59:30 -05:00
Ben Meadors
45f9dee89a Telemetry phone api guard (#1805)
* Delay start of telemetry modules

* Don't send unless our toPhoneQueue is empty

* Get wrecked, checks!
2022-10-16 09:58:58 -05:00
Thomas Göttgens
cc73d2c2f2 Sigh... 2022-10-16 16:51:17 +02:00
Thomas Göttgens
b1f789dddd fix cppcheck 2022-10-16 16:45:32 +02:00
Thomas Göttgens
d3e9dbf6a9 Add NMEA output mode (my own position, and other devices as waypoints) to serial module 2022-10-16 16:37:38 +02:00
Thomas Göttgens
44529620ad Merge pull request #1806 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-16 16:25:34 +02:00
caveman99
7a9673dc37 [create-pull-request] automated change 2022-10-16 14:24:27 +00:00
Thomas Göttgens
27bcf67c0c add routine to output waypoint data 2022-10-16 12:28:49 +02:00
Ben Meadors
7fde56b8ac Make telemetry logging more concise (#1804)
* Make telemetry logging more concise

* Whoops
2022-10-15 18:48:34 -05:00
Ben Meadors
6b614a2d6a Added LPS22HB (RAK-1902) sensor support (#1802) 2022-10-15 14:55:57 -05:00
Ben Meadors
1e1509fbf5 Use pio registry (#1801) 2022-10-15 12:34:52 -05:00
Ben Meadors
a3e67f8e4b SHTC3 Sensor (RAK-1901) support (#1800) 2022-10-15 09:11:05 -05:00
Ben Meadors
028b25cfe8 Change RTCQuality acceptance criteria (#1797)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-14 19:12:55 -05:00
Ben Meadors
2555e082d6 Add nrf52 to serial module registration (#1799)
* Add nrf52 to serial module registration

* Update Modules.cpp

* Update Modules.cpp

* Update Modules.cpp
2022-10-14 11:38:56 -05:00
Thomas Göttgens
f8fa721c72 Merge pull request #1798 from meshtastic/i2cscan
Scan for I2C devices twice on all CPU's
2022-10-14 15:33:46 +02:00
Thomas Göttgens
a7e0127793 scan i2c twice for all devices, not just tbeam 2022-10-13 23:46:25 +02:00
Thomas Göttgens
603f60d86a Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-13 19:13:09 +02:00
Thomas Göttgens
6febf6b17c Merge pull request #1796 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 17:58:41 +02:00
thebentern
53aaf766dd [create-pull-request] automated change 2022-10-13 14:54:05 +00:00
Thomas Göttgens
4fa8d02b08 update FromRadio UUID for nRF52 devices (#1795) 2022-10-13 09:32:54 -05:00
Thomas Göttgens
efa423c8ad update FromRadio UUID for nRF52 devices 2022-10-13 16:20:27 +02:00
Thomas Göttgens
43fb0d80f1 Merge pull request #1794 from meshtastic/canned-spice
Display looks better that way...
2022-10-13 15:56:13 +02:00
Thomas Göttgens
b25ace14e5 Update CannedMessageModule.h 2022-10-13 15:44:27 +02:00
Thomas Göttgens
8734751bc4 make screen timeout work again 2022-10-13 15:31:57 +02:00
Thomas Göttgens
5559a1edb0 Display looks better that way... 2022-10-13 15:22:57 +02:00
Thomas Göttgens
bf503354f3 Merge pull request #1792 from meshtastic/atecca
Support for ATECCA608B Cryptographic Coprocessor
2022-10-13 14:34:44 +02:00
Thomas Göttgens
7b10441a28 update raspberry pi framework some more... 2022-10-13 14:21:48 +02:00
Thomas Göttgens
994e396c00 update Raspberry Pico Framework 2022-10-13 13:57:17 +02:00
Thomas Göttgens
6e22ee9061 make nRF52 happy 2022-10-13 13:31:19 +02:00
Thomas Göttgens
b5fb0f60b0 don't compile on Portduino 2022-10-13 13:01:24 +02:00
Thomas Göttgens
a7fe69ed6b Support for ATECCA608B Cryptographic Coprocessor 2022-10-13 12:55:28 +02:00
Thomas Göttgens
7f05298172 Merge pull request #1790 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-13 08:45:13 +02:00
thebentern
92a2505056 [create-pull-request] automated change 2022-10-12 23:42:47 +00:00
Ben Meadors
aae9d2fcf6 Package ota zip in final firmware bundle 2022-10-12 13:03:19 -05:00
Ben Meadors
b59e928589 Secure DFU mode for OTA updates with pin (#1789) 2022-10-12 10:31:39 -05:00
Ben Meadors
1db08b3b0e Add pico 2022-10-12 08:06:08 -05:00
Ben Meadors
2cf3c105a1 Add DFU package for nrf52 assets to build assets 2022-10-12 08:06:08 -05:00
Ben Meadors
505e4e8176 Run dfu begin first (#1786)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-12 07:55:17 -05:00
Thomas Göttgens
49a9973548 Merge pull request #1788 from meshtastic/bug-1787
fixes #1787
2022-10-12 13:26:21 +02:00
Thomas Göttgens
18af9d734d fixes #1787 2022-10-12 13:13:02 +02:00
Ben Meadors
3e22aafea8 Change UUID for FromRadio characteristic (#1785) 2022-10-11 20:01:26 -05:00
Ben Meadors
434db4347b Send device telemetry to phone every minute (#1784) 2022-10-11 10:21:30 -05:00
Thomas Göttgens
b2c3b405b1 Merge pull request #1783 from meshtastic/ota
debug print on early boot when OTA firmware is detected.
2022-10-10 23:40:19 +02:00
Thomas Göttgens
4bc8f6a6b9 Merge branch 'master' into ota 2022-10-10 23:14:26 +02:00
Thomas Göttgens
4534d17d79 debug print on early boot when OTA firmware is detected. 2022-10-10 23:05:24 +02:00
Ben Meadors
f88dde2f60 Send channels over phoneapi on want config (#1780)
* Send channels

* Doh!

* Adjust comments

* Missed a spot

* Consolidate

* Skipped disabled ones

* Fixed bounding

* Change order

* comment out disabled check for build artefact

* Remove loop

* Off by one

* Probably should start at zero

* Zero

* Oops

* enable dubug log

* Reset to index zero

Co-authored-by: Sacha Weatherstone <sachaw100@hotmail.com>
2022-10-10 10:36:49 -05:00
Thomas Göttgens
f8982ddaf8 Best Practise Platformio 6.x dependency definitions 2022-10-10 15:42:05 +02:00
Thomas Göttgens
784cd8c6f1 Merge pull request #1768 from meshtastic/nrf52-Rollup
Nrf52 rollup
2022-10-10 15:30:45 +02:00
Thomas Göttgens
c3ab8f12cf Merge branch 'master' into nrf52-Rollup 2022-10-10 15:09:49 +02:00
Thomas Göttgens
b5adb7babc Update nrf52840.ini 2022-10-10 15:09:31 +02:00
Thomas Göttgens
62c809a596 Merge pull request #1782 from meshtastic/lora-freq-check
Lora freq check
2022-10-10 12:53:14 +02:00
Thomas Göttgens
d2fe4426c1 Revert Platform Change for now. 2022-10-10 12:32:08 +02:00
Thomas Göttgens
984f0ca12c check allowed range for lora.channel_num 2022-10-10 12:28:31 +02:00
Thomas Göttgens
9d3eba9ea4 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-10 12:15:09 +02:00
Thomas Göttgens
323f81eaba Merge branch 'master' into nrf52-Rollup 2022-10-10 12:06:44 +02:00
Thomas Göttgens
8d0e25fd82 Merge pull request #1770 from meshtastic/ota
Switch to OTA firmware
2022-10-09 11:54:16 +02:00
Thomas Göttgens
20eaddee58 - fix conditional include for nRF52 (no OTA there)
- fix compiler warning in Canned Messages
2022-10-09 11:35:19 +02:00
Thomas Göttgens
30b1bd85d9 fix build for non-esp32 2022-10-09 11:19:33 +02:00
Thomas Göttgens
09cce094d1 Merge branch 'master' into ota 2022-10-09 11:00:20 +02:00
Thomas Göttgens
33a208e3c4 Merge pull request #1777 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-09 11:00:01 +02:00
caveman99
dd4c4fba80 [create-pull-request] automated change 2022-10-09 08:55:33 +00:00
Sacha Weatherstone
a17c40ad09 Merge branch 'master' into ota 2022-10-09 16:44:24 +10:00
Sacha Weatherstone
9d73e606ac Merge pull request #1774 from meshtastic/node-db
erase oldest entry from NodeDB if it is full
2022-10-09 16:40:46 +10:00
Ben Meadors
da12360105 Merge branch 'master' into node-db 2022-10-08 13:48:35 -05:00
GUVWAF
ee1ae627a3 Model the time it is busy receiving/transmitting (#1776)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-08 12:10:50 -05:00
Thomas Göttgens
137a8dcfdf Merge pull request #1775 from meshtastic/i2cscan-fix
move and repeat i2c scan to fix BLE PIN
2022-10-08 17:52:32 +02:00
Thomas Göttgens
b2d753ed86 move and repeat i2c scan to fix BLE PIN 2022-10-08 17:36:39 +02:00
Thomas Göttgens
6e40102f26 - use bigger screen fonts on Wiphone
- erase oldest entry from NodeDB if it is full.
2022-10-08 17:07:16 +02:00
Ben Meadors
511fe23b8a Merge branch 'master' into ota 2022-10-08 08:22:16 -05:00
Thomas Göttgens
e433895873 Merge pull request #1773 from meshtastic/canned-messages
Fix another crash in Canned Messages
2022-10-08 15:09:58 +02:00
Thomas Göttgens
5572195af9 Fix another crash in Canned Messages 2022-10-08 14:52:21 +02:00
Thomas Göttgens
cb956cd35b Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-08 14:35:07 +02:00
Ben Meadors
b551c7738e Merge branch 'master' into ota 2022-10-08 07:28:35 -05:00
GUVWAF
3d45c4dbd8 Don't resend ACK if another module sent a response (#1772)
* strcmp returns zero if strings are equal

* Make debug message more clear

* Don't resend ACK if another module sent a response

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-10-08 07:27:59 -05:00
Thomas Göttgens
8681489cb7 Merge pull request #1771 from meshtastic/compass-size
Scale Compass circle to bigger screens
2022-10-08 13:22:14 +02:00
Thomas Göttgens
ed328766b2 Scale Compass circle to bigger screens 2022-10-08 12:32:48 +02:00
Thomas Göttgens
fb852ee6eb Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-08 11:25:46 +02:00
Thomas Göttgens
a6ee708b90 Merge branch 'master' into ota 2022-10-08 11:21:33 +02:00
Thomas Göttgens
c9398e7b8a - prevent crash when no messages defined
- remove debug print
2022-10-08 11:20:54 +02:00
Thomas Göttgens
b591e35442 Switch to OTA firmware 2022-10-08 11:10:29 +02:00
Thomas Göttgens
e50e15dc04 Merge pull request #1769 from meshtastic/RTC
1.0.1 RTC LIB is released on PIO Registry
2022-10-08 11:09:54 +02:00
Thomas Göttgens
d4e65d8607 1.0.1 RTC LIB is released on PIO Registry 2022-10-08 11:09:16 +02:00
Thomas Göttgens
63ced7da7c use upstream nRF52 toolkit. (TEST)
also RTC Lib 1.0.1 is finally out.
2022-10-07 20:28:20 +02:00
Thomas Göttgens
03868d05db Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-07 20:23:00 +02:00
Thomas Göttgens
186374525a Don't mix MQTT Payloads of Firmware 1.2 and 1.3/2.0 (#1767) 2022-10-07 12:54:42 -05:00
Thomas Göttgens
f116585c2a Don't mix MQTT Payloads of Firmware 1.2 and 1.3/2.0 2022-10-07 19:26:45 +02:00
Thomas Göttgens
f4945729bc Merge pull request #1766 from meshtastic/new-sounds
use F# as startup and shutdown sound triple
2022-10-07 19:16:50 +02:00
Thomas Göttgens
a3c76232c8 use F# as startup and shutdown sound triple. The existing tuuut-tut-tut was getting on my nerves 2022-10-07 19:03:49 +02:00
Thomas Göttgens
5bc41118e2 Merge pull request #1760 from meshtastic/support-rak14004
Use small font for freetext messages
2022-10-07 18:58:28 +02:00
Thomas Göttgens
9445a96b3a Merge branch 'support-rak14004' of github.com:meshtastic/Meshtastic-device 2022-10-07 18:40:51 +02:00
Thomas Göttgens
a5761069ca Finalize destination selection. Primary Channel only for now. 2022-10-07 18:40:15 +02:00
Thomas Göttgens
2d4bfe183c Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-07 16:42:29 +02:00
Ben Meadors
bf4115a80f Telemetry sensors re-map (#1765)
* Add factory erase uf2 to the release assets

* Sensors map

* Uncomment sensors
2022-10-07 08:33:07 -05:00
Ben Meadors
b2e84dfd29 Merge branch 'master' into support-rak14004 2022-10-07 06:58:08 -05:00
lewis he
004f6fa4d6 Add t-beam-s3-core onboard device support. (#1764)
* Change t-beam-s3-core pins definitions

* Add t-beam-s3-core power initialization to properly initialize the I2C device

* Add 6-axis and 3-axis sensor detection
2022-10-07 06:57:55 -05:00
Thomas Göttgens
cefd4cd647 Merge pull request #1762 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-10-06 23:15:59 +02:00
thebentern
fd2ae61e3e [create-pull-request] automated change 2022-10-06 20:53:47 +00:00
Thomas Göttgens
7cda61ca01 - preliminary work for node selection
- show sending screen on immediate click
2022-10-06 22:34:55 +02:00
Thomas Göttgens
98e1d52eaa Merge branch 'support-rak14004' of github.com:meshtastic/Meshtastic-device 2022-10-06 18:41:33 +02:00
Thomas Göttgens
1d09beb8a7 word wrap long input and fix compiler warnings 2022-10-06 18:40:31 +02:00
Thomas Göttgens
d44cce2928 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-10-06 17:24:48 +02:00
Thomas Göttgens
51b3d4d06e Merge branch 'master' into support-rak14004 2022-10-06 17:24:33 +02:00
Thomas Göttgens
a17ddaa951 Use small font for freetext messages 2022-10-06 17:24:08 +02:00
Thomas Göttgens
9bd925226c Merge pull request #1759 from meshtastic/support-rak14004
support RAK14004 in Canned Messages
2022-10-06 16:37:25 +02:00
Thomas Göttgens
e34ada3ff1 support RAK14004 in Canned Messages 2022-10-06 16:00:33 +02:00
Thomas Göttgens
1ec1ff0773 Merge pull request #1758 from andrekir/PCF8563-lib
update PCF8563_Library to 1.0.0
2022-10-06 09:12:38 +02:00
Thomas Göttgens
7f935717db Update platformio.ini 2022-10-06 08:56:02 +02:00
Thomas Göttgens
5b1d3a0c51 Update platformio.ini 2022-10-06 08:55:58 +02:00
andrekir
484f340023 update PCF8563_Library to 1.0.0 2022-10-06 01:05:21 -03:00
Ben Meadors
ab0cf025c5 Remove flag 2022-10-05 11:41:53 -05:00
Ben Meadors
b384d9ea88 Remove yml exclusion for now 2022-10-05 11:18:37 -05:00
Ben Meadors
bb2094c4de Fixed move 2022-10-05 11:11:14 -05:00
Ben Meadors
6708121ba6 Add factory erase uf2 to the release assets (#1756)
* Add factory erase uf2 to the release assets

* Copy single file

* Overwrite hopefully
2022-10-05 10:52:51 -05:00
Thomas Göttgens
46a9bb3f7d Merge pull request #1755 from meshtastic/gps-rollup
GPS Rollup, incorporates changes from @pmarches and @lewisxhe
2022-10-05 15:32:27 +02:00
Thomas Göttgens
62498d0935 GPS Rollup, incorporates changes from @pmarches and @lewisxhe 2022-10-05 14:59:07 +02:00
Thomas Göttgens
c70184fbed Merge pull request #1754 from meshtastic/issue-1707
wire in part 2 of serial mode - implements #1228
2022-10-05 13:45:11 +02:00
Thomas Göttgens
4d2cb45f9f wire in part 1 of serial mode... select if you want textmsg or own portnum via config. 2022-10-05 11:39:50 +02:00
Thomas Göttgens
e5605cc6fe Merge pull request #1753 from meshtastic/bug-1713
fix #1713
2022-10-05 10:51:56 +02:00
Thomas Göttgens
f7331a2e41 fix #1713
stop output to serial debug after config has been loaded (if serial is disabled), and only accept protobuf packets from that point on.
2022-10-05 10:33:39 +02:00
Thomas Göttgens
838271a14f Merge pull request #1751 from rjmcdougall/radiolib-5.4.0-fix
Switch to 5.4.0 using latest fix (170ce9) to error check after calibr…
2022-10-05 09:25:05 +02:00
Thomas Göttgens
b6b23907ed Merge pull request #1752 from meshtastic/flash-save
Flash saver
2022-10-05 09:12:11 +02:00
Thomas Göttgens
b240b9a088 Use the global radiolib... 2022-10-05 09:02:46 +02:00
Thomas Göttgens
b3a484f1e5 update to Radiolib 5.4.1 2022-10-05 09:01:39 +02:00
Thomas Göttgens
f3042ddf37 Update NodeDB.cpp 2022-10-05 08:56:00 +02:00
Thomas Göttgens
54816231e9 Calculate CRC32 of Protobuf and compare before save. 2022-10-05 08:52:27 +02:00
Richard McDougall
1c168d7d62 Switch to 5.4.0 using latest fix (170ce9) to error check after calibration 2022-10-04 10:52:23 -07:00
Thomas Göttgens
063c4904ff only save files when they changed - also clamp app version 2022-10-04 17:25:03 +02:00
Thomas Göttgens
fefcbb147b fix #1646 2022-10-04 15:27:18 +02:00
Thomas Göttgens
53d48e8f61 use radiolib 5.3 for now 2022-10-04 15:19:00 +02:00
Thomas Göttgens
ce5bce5cdc Merge pull request #1749 from meshtastic/flash-save
Only save the changed parts of config to disk.
2022-10-04 14:52:10 +02:00
Thomas Göttgens
3597685b23 Only save the changed parts of config to disk. 2022-10-04 14:32:07 +02:00
Thomas Göttgens
dc097c7230 Merge pull request #1729 from rjmcdougall/pcf8563rtc
Adjust year, hour, minute for PCF8563
2022-10-04 13:40:40 +02:00
Thomas Göttgens
b148781e4b Missed one. 2022-10-04 13:29:06 +02:00
Thomas Göttgens
5d8826e8ef Merge branch 'master' into pcf8563rtc 2022-10-04 13:27:49 +02:00
Thomas Göttgens
39a51c7fbb update lib to make this work 2022-10-04 13:26:20 +02:00
Thomas Göttgens
129edde338 Merge pull request #1746 from meshtastic/feature-1406
implement #1406
2022-10-04 10:01:19 +02:00
Thomas Göttgens
93cc278eee implement #1406 2022-10-04 09:47:54 +02:00
Thomas Göttgens
c34198264a Merge branch 'master' into pcf8563rtc 2022-10-04 09:38:33 +02:00
Thomas Göttgens
054b12325d Merge pull request #1745 from meshtastic/compiler-warning
fix compiler warning
2022-10-04 09:27:34 +02:00
Thomas Göttgens
0f7a126828 fix compiler warning 2022-10-04 09:11:24 +02:00
Thomas Göttgens
7ff72fb981 Merge pull request #1744 from meshtastic/dependency-scan
add versioning to all lib depends
2022-10-04 09:10:28 +02:00
Thomas Göttgens
0fe99595a9 Lib update and fix include errors 2022-10-04 08:59:03 +02:00
Thomas Göttgens
b2ff628cec add versioning to all lib depends (compatible upgrade allowed) and move as many as possible off github and into PIO registry.
Also add a script to check for lib updates (maybe in CI?)
2022-10-04 08:40:39 +02:00
Thomas Göttgens
86a3bd6db8 Merge pull request #1742 from meshtastic/bug-1740
Clean up GPS code and add some flags per #1740
2022-10-04 08:38:57 +02:00
Thomas Göttgens
73a5357d0e Brainfart. This is already km/h 2022-10-04 08:11:07 +02:00
Richard McDougall
2faf507c0d Merge branch 'meshtastic:master' into pcf8563rtc 2022-10-03 13:55:49 -07:00
Thomas Göttgens
cf124d97b8 Clean up GPS code and add some flags per #1740 2022-10-03 20:30:11 +02:00
Sacha Weatherstone
482c0766af Merge pull request #1741 from andrekir/channel_num
move channel_num to loraConfig
2022-10-03 16:34:42 +10:00
Ben Meadors
7e5a26fde5 Merge branch 'master' into channel_num 2022-10-02 19:45:32 -05:00
Ben Meadors
e85af2f732 regen protos 2022-10-02 19:45:15 -05:00
Sacha Weatherstone
4df81008bc Merge branch 'master' into channel_num 2022-10-03 10:32:56 +10:00
Ben Meadors
803dc69ccd Update radiolib 2022-10-02 09:48:48 -05:00
Thomas Göttgens
42308cca5b Merge branch 'master' into pcf8563rtc 2022-10-01 17:31:02 +02:00
Thomas Göttgens
ea991a4eee Merge pull request #1737 from GUVWAF/EnhancedSimRadio
Let SimRadio communicate via TCP
2022-10-01 17:24:26 +02:00
GUVWAF
04db2d4410 Merge branch 'EnhancedSimRadio' of https://github.com/GUVWAF/Meshtastic-device into EnhancedSimRadio 2022-10-01 17:07:59 +02:00
GUVWAF
076c1ed2ee Merge branch 'EnhancedSimRadio' of https://github.com/GUVWAF/Meshtastic-device into EnhancedSimRadio 2022-10-01 17:05:49 +02:00
Thomas Göttgens
75aa4ea325 suppress cppcheck warning 2022-10-01 17:05:04 +02:00
GUVWAF
e54be07dc0 Update include path in MeshService 2022-10-01 17:04:19 +02:00
GUVWAF
d439d00e25 Move SimRadio to platform/portduino 2022-10-01 17:03:40 +02:00
GUVWAF
c4bea793af Mark WifiServerPort constructor as explicit 2022-10-01 17:02:16 +02:00
GUVWAF
b53dcb932e Adapt conditional include 2022-10-01 17:01:25 +02:00
Thomas Göttgens
371428d6ab Fix compile error on nRF52 2022-10-01 16:41:49 +02:00
Thomas Göttgens
1970d0c00f Merge branch 'master' into EnhancedSimRadio 2022-10-01 15:59:44 +02:00
github-actions[bot]
1dd7aa935f [create-pull-request] automated change (#1738)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2022-10-01 08:47:35 -05:00
Thomas Göttgens
6b40f9d95c Unfork this lib, we're done here now. 2022-10-01 15:27:13 +02:00
Thomas Göttgens
b3717d0396 Merge branch 'master' into pcf8563rtc 2022-10-01 15:20:16 +02:00
GUVWAF
82ba95833b strcmp returns zero if strings are equal (#1736)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-10-01 08:18:25 -05:00
Thomas Göttgens
28384df702 Merge pull request #1734 from meshtastic/Build-Image
Build image
2022-10-01 15:17:41 +02:00
GUVWAF
aee06f4738 Suppress debug messages in PhoneAPI as they flood the logs when a TCP connection is open 2022-10-01 12:09:43 +02:00
GUVWAF
ab282765d4 Let SimRadio start receive a packet if its PortNum is Simulator_App 2022-10-01 12:06:59 +02:00
GUVWAF
5d464badc8 Give TCP port as argument to API server 2022-10-01 12:05:20 +02:00
GUVWAF
68282682de Use new SimRadio in main for Portduino 2022-10-01 12:03:35 +02:00
GUVWAF
2696b04138 Allow Portduino to set the TCP port 2022-10-01 12:02:29 +02:00
GUVWAF
31dc37150b Fix typo 2022-10-01 12:00:31 +02:00
GUVWAF
e66d9d0add Add content to SimRadio, similar to RadioInterface 2022-10-01 11:59:20 +02:00
GUVWAF
067bde321b Remove old SimRadio from RadioInterface 2022-10-01 11:57:27 +02:00
GUVWAF
84ec364ac2 Add enhanced SimRadio files 2022-10-01 11:56:16 +02:00
Thomas Göttgens
32990856e3 Merge branch 'master' into Build-Image 2022-10-01 10:31:59 +02:00
Thomas Göttgens
a1bd5c9ea0 Accomodate for new flash files 2022-10-01 10:31:25 +02:00
Thomas Göttgens
51f0e7879a use the right firmware artefact 2022-10-01 10:06:13 +02:00
Thomas Göttgens
0bdb90d133 remove hard to maintain system-info bootloader 2022-10-01 09:50:16 +02:00
Thomas Göttgens
e98c11ff89 The new combined firmware starts flashing at offset 0, no need to flash system-info or partitions any more. 2022-10-01 09:46:56 +02:00
andrekir
8f84d7089c move channel_num to loraConfig 2022-09-30 17:33:43 -03:00
Thomas Göttgens
b0712c4186 make other platforms happy again 2022-09-29 21:23:01 +02:00
Thomas Göttgens
8f92383ce4 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-29 17:05:11 +02:00
Thomas Göttgens
c571fc9e24 generate a monolithic flash image for the app. 2022-09-29 17:04:56 +02:00
Thomas Göttgens
05126bc6dc Merge branch 'master' into pcf8563rtc 2022-09-29 16:33:43 +02:00
Thomas Göttgens
de56a370c6 Merge pull request #1733 from meshtastic/TLORA-fix
Tlora fix
2022-09-29 13:37:51 +02:00
Thomas Göttgens
daf189bf4b Check in variant.h change 2022-09-29 13:23:23 +02:00
Thomas Göttgens
d95ec7e6b9 fix TLORA-V2.1-1.6 2022-09-29 13:21:48 +02:00
Ben Meadors
ac235bcabb Reset nodedb wiring (#1724) 2022-09-28 16:47:26 -05:00
Neil Hao
ab4b3a50ee 'battery_gauge_fix' (#1731) 2022-09-28 15:53:26 -05:00
Thomas Göttgens
7f0fb2a2b6 Move file to right spot in source tree 2022-09-28 20:13:41 +02:00
Richard McDougall
ade1edfdfc Adjust year, hour, minute for PCF8563 2022-09-27 22:51:40 -07:00
Thomas Göttgens
4723faa95f Merge pull request #1728 from meshtastic/bug-1669
fixes #1669
2022-09-27 14:15:38 +02:00
Thomas Göttgens
93f83b0fcb Merge branch 'master' into bug-1669 2022-09-27 14:03:48 +02:00
Thomas Göttgens
8f84f7c0a5 fixes #1669 2022-09-27 14:03:02 +02:00
Ben Meadors
48e4101f1c Move it 2022-09-27 06:08:24 -05:00
Thomas Göttgens
e6bb79f4c1 Merge pull request #1727 from meshtastic/ESPIDF-Littlefs
use the native littlefs builder of newer framework
2022-09-27 00:50:41 +02:00
Thomas Göttgens
0bef3464f5 Merge branch 'master' into ESPIDF-Littlefs 2022-09-27 00:50:33 +02:00
Thomas Göttgens
3c038a8c50 Update main_matrix.yml 2022-09-27 00:50:16 +02:00
Thomas Göttgens
b8eb751316 Update build-esp32.sh 2022-09-27 00:23:50 +02:00
Thomas Göttgens
5332db1eca Include OTA Firmware in Build 2022-09-27 00:21:45 +02:00
Thomas Göttgens
9deda962aa Merge branch 'master' into ESPIDF-Littlefs 2022-09-27 00:16:41 +02:00
Thomas Göttgens
c53434539b use the native littlefs builder of newer framework 2022-09-27 00:16:12 +02:00
Ben Meadors
7f179deaf3 Update build-esp32.sh 2022-09-26 16:01:28 -05:00
Ben Meadors
da29fa139f Copy the current one 2022-09-26 16:00:20 -05:00
Thomas Göttgens
1d8a562fd9 Merge pull request #1725 from meshtastic/AsyncOTA
Changes for OTA Support on ESP32
2022-09-26 22:57:48 +02:00
Thomas Göttgens
0dbf97afab Merge branch 'master' into AsyncOTA 2022-09-26 22:57:23 +02:00
Thomas Göttgens
e5720fba3e Merge pull request #1726 from meshtastic/partitions
Include partitions.bin
2022-09-26 22:56:59 +02:00
Ben Meadors
498ac00b92 Copy cpartitions.bin 2022-09-26 15:51:09 -05:00
Ben Meadors
226a2dfe04 Include partitions.bin 2022-09-26 15:48:02 -05:00
Thomas Göttgens
7e9a233296 - new Bootloader for ESP-IDF 4.2
- save partition table to device
- modify partition table for async OTA
2022-09-26 22:42:58 +02:00
Ben Meadors
ae311c838e Try to decode mqtt packets first (#1705)
* Try to decode first

* Remove GPS pins from TLoRAv1 so that it can boot

* Use release version of radio lib

* Use fixed versions of esp framework and tool chain
2022-09-25 09:39:50 -05:00
Thomas Göttgens
de769db3bc Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-23 23:29:52 +02:00
Thomas Göttgens
5fa96c7fd1 missed one, sorry 2022-09-23 23:29:32 +02:00
Thomas Göttgens
2ee0c9a67a Merge pull request #1720 from meshtastic/axe-framerate-debug
get rid of framerate debug messages
2022-09-23 23:21:21 +02:00
Thomas Göttgens
347af0210e Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-23 23:09:20 +02:00
Thomas Göttgens
d8455d687c Merge branch 'master' into axe-framerate-debug 2022-09-23 23:08:46 +02:00
Thomas Göttgens
34fef4c4e7 get rid of framerate debug messages 2022-09-23 23:07:26 +02:00
Thomas Göttgens
18bb373219 switch Bluetooth back on when wifi is disabled and bluetooth is enabled. This still had the old behaviour to check for a set ssid... (#1719) 2022-09-23 15:10:33 -05:00
Thomas Göttgens
2f74f9ca15 Merge pull request #1718 from meshtastic/ESPIDF-Rollup
Suppress compiler warning
2022-09-23 21:33:37 +02:00
Thomas Göttgens
5775c390f3 Merge branch 'master' into ESPIDF-Rollup 2022-09-23 21:19:19 +02:00
Thomas Göttgens
80826b8712 Merge pull request #1711 from meshtastic/ESPIDF-Littlefs
Filesystem fixes for LittleFS
2022-09-23 21:14:40 +02:00
Thomas Göttgens
664d18cf58 t'ell that came from? 2022-09-23 21:03:53 +02:00
Thomas Göttgens
bc2cddcb11 Filesystem abstraction would work really well, if it wasn't for crap vendor toolchains. 2022-09-23 20:43:42 +02:00
Thomas Göttgens
4949bda606 Don't delete OEM.proto on factory reset 2022-09-23 19:52:42 +02:00
Thomas Göttgens
b4f75ad042 use exception decoder 2022-09-23 19:52:07 +02:00
Thomas Göttgens
af4d11e17b fix and refactor FSCommon for new ESPIDF 2022-09-23 19:51:08 +02:00
Thomas Göttgens
e8f4a8b739 Merge branch 'master' into ESPIDF-Littlefs 2022-09-23 18:45:37 +02:00
Thomas Göttgens
fae6693f8f fix (or better suppress) another compiler warning 2022-09-23 12:37:59 +02:00
Thomas Göttgens
0646ecdec4 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-23 12:32:07 +02:00
Thomas Göttgens
544c89460f Nullify older saved proto files once more
this will be neccessary for the 1.3.42 release, since we renumbered some protos again. Subsequent additions to protos don't need this, just when we reshuffle.
2022-09-23 12:28:32 +02:00
Thomas Göttgens
15089f5b01 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-23 09:55:00 +02:00
Ben Meadors
8ef510035d Owner reboot (#1716) 2022-09-22 08:02:58 -05:00
Sacha Weatherstone
864b1f754c Merge branch 'master' into ESPIDF-Littlefs 2022-09-22 14:58:53 +10:00
Sacha Weatherstone
883a2ebac0 Merge pull request #1717 from ajmcquilkin/ajmcquilkin/imperial-screen-units
Add Support for Imperial Units on Screen
2022-09-22 13:22:22 +10:00
Adam McQuilkin
bbe5b2e42c Remove accidental whitespace changes 2022-09-21 22:48:12 -04:00
Adam McQuilkin
1b316b111f Initial commit 2022-09-21 22:37:36 -04:00
Thomas Göttgens
d0720620e8 fix compiler warning 2022-09-21 17:22:31 +02:00
Thomas Göttgens
cf4947d898 Fix build for non-ESP32 2022-09-21 17:05:10 +02:00
Thomas Göttgens
b5a8efa16b Filesystem fixes for LittleFS 2022-09-21 16:47:10 +02:00
Thomas Göttgens
b38ae783b9 Merge pull request #1706 from meshtastic/communicator
Freetext Input with CardKB
2022-09-21 16:33:49 +02:00
Thomas Göttgens
cbd8346c93 Merge branch 'master' into communicator 2022-09-21 16:10:28 +02:00
Thomas Göttgens
c0bfb979fd Merge pull request #1710 from meshtastic/serial-flush
Fix Serial comms with new framework
2022-09-21 16:01:01 +02:00
Thomas Göttgens
7c5a36ce38 Update SerialConsole.cpp 2022-09-21 15:46:56 +02:00
Thomas Göttgens
fc729b0cbb Send PROTOBUF over serial without delay 2022-09-21 15:36:17 +02:00
Thomas Göttgens
0b81a25fda Output serial console data without buffering 2022-09-21 15:34:48 +02:00
Thomas Göttgens
011db443ba Bugfixes in Freetext Module.
- work without fixed messages defined
- honour cursor position on backspace
- don't send an empty string
- compiler warnings in font engine fixed
2022-09-21 10:42:10 +02:00
Thomas Göttgens
b73e240f4d relative paths are relative 2022-09-20 16:36:50 +02:00
Thomas Göttgens
6de77ee310 use cyrillic font if defined 2022-09-20 16:30:21 +02:00
Thomas Göttgens
0a8293a2d6 Cursor editing 2022-09-20 16:21:32 +02:00
Thomas Göttgens
d0ad5dd4cf - don't swallow keystrokes
- switch back and forth between the 2 modes.
2022-09-20 14:28:42 +02:00
Thomas Göttgens
ab342ce904 Freetext Input with CardKB Take 1 - Also removes FacesKB support, this thing is ancient. 2022-09-20 13:50:18 +02:00
Thomas Göttgens
140250ef03 Merge pull request #1704 from meshtastic/ESPIDF-Rollup
ESP and TFT misc fixes
2022-09-19 17:57:12 +02:00
Thomas Göttgens
ed90275370 use double buffering on TFT screens 2022-09-19 16:57:18 +02:00
Thomas Göttgens
e8b28faaf1 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-19 16:18:16 +02:00
Thomas Göttgens
afcc7b6a56 Always use the latest framework for ESP32 2022-09-19 16:18:01 +02:00
Thomas Göttgens
e27a507a28 Merge pull request #1703 from meshtastic/ESPIDF-Rollup
Small fixes for ESP Serial Init and Power FSM debug garble.
2022-09-19 15:57:47 +02:00
Thomas Göttgens
207f701f0a Update GPS.cpp 2022-09-19 15:46:59 +02:00
Thomas Göttgens
dd8cb1c7fb Small fixes for ESP Serial Init and Power FSM debug garble. 2022-09-19 15:36:48 +02:00
Thomas Göttgens
ccf93b8c23 Merge pull request #1687 from meshtastic/ESPIDF-Rollup
use the new ESP Framework for our older boards too
2022-09-19 12:18:09 +02:00
Thomas Göttgens
4c6f3ead60 fixing I2C requests and Wifi Power Saving Modes. 2022-09-19 12:05:57 +02:00
Thomas Göttgens
2d81d359b8 Update esp32.ini
Update arch by hand
2022-09-19 09:36:13 +02:00
Thomas Göttgens
1f96d5d957 Merge branch 'master' into ESPIDF-Rollup 2022-09-19 09:33:50 +02:00
Thomas Göttgens
033f45d4da Merge pull request #1702 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-09-19 09:32:01 +02:00
thebentern
ae2c514ee7 [create-pull-request] automated change 2022-09-18 20:55:27 +00:00
Ben Meadors
e0d3ac01b0 Merge branch 'master' into ESPIDF-Rollup 2022-09-17 08:22:44 -05:00
Thomas Göttgens
7c202b6069 Merge branch 'master' into ESPIDF-Rollup 2022-09-13 19:18:20 +02:00
Ben Meadors
bfd1fecc2a Merge branch 'master' into ESPIDF-Rollup 2022-09-13 06:36:56 -05:00
Ben Meadors
ade66cd8f4 Merge branch 'master' into ESPIDF-Rollup 2022-09-12 18:07:42 -05:00
Ben Meadors
adc50f40b1 Merge branch 'master' into ESPIDF-Rollup 2022-09-12 14:56:09 -05:00
Thomas Göttgens
eac2613743 make platformio.ini even more modular 2022-09-12 14:02:21 +02:00
Thomas Göttgens
4a0c18c4cd Merge branch 'ESPIDF-Rollup' of github.com:meshtastic/Meshtastic-device 2022-09-12 13:40:52 +02:00
Thomas Göttgens
e376a3a28e just use the general toolkit 2022-09-12 13:40:20 +02:00
Thomas Göttgens
a6bdff53c9 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-12 13:25:54 +02:00
Thomas Göttgens
b5c5483ced Merge branch 'master' into ESPIDF-Rollup 2022-09-12 12:50:38 +02:00
Thomas Göttgens
cc054a13e2 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-09-12 09:25:04 +02:00
Sacha Weatherstone
c446a0f222 Merge branch 'master' into ESPIDF-Rollup 2022-09-11 10:45:27 +10:00
Thomas Göttgens
3102777a71 Update platformio.ini 2022-09-10 20:53:23 +02:00
Thomas Göttgens
ed95f382cf Merge branch 'master' into ESPIDF-Rollup 2022-09-10 20:39:54 +02:00
Sacha Weatherstone
52e4f93760 Merge branch 'master' into ESPIDF-Rollup 2022-09-10 22:13:56 +10:00
Thomas Göttgens
bf3306fbc8 use the new ESP Framework for our older boards too 2022-09-09 22:31:30 +02:00
138 changed files with 2941 additions and 1201 deletions

View File

@@ -12,7 +12,7 @@ on:
branches: [master]
paths-ignore:
- "**.md"
- "**.yml"
#- "**.yml"
workflow_dispatch:
@@ -57,12 +57,12 @@ jobs:
sudo apt-get install -y cppcheck
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
@@ -112,12 +112,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
@@ -126,12 +126,12 @@ jobs:
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil littlefs-python
pip install -U platformio adafruit-nrfutil
- name: Upgrade platformio
run: |
pio upgrade
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
@@ -147,13 +147,21 @@ jobs:
- name: Build ESP32
run: bin/build-esp32.sh ${{ matrix.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "meshtastic/Meshtastic-OTA"
file: "firmware.bin"
target: "release/bleota.bin"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
@@ -182,12 +190,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
@@ -206,16 +214,17 @@ jobs:
run: bin/build-nrf52.sh ${{ matrix.board }}
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf
release/*.zip
retention-days: 90
build-rpi2040:
@@ -236,12 +245,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
@@ -260,11 +269,11 @@ jobs:
run: ./bin/build-rpi2040.sh ${{ matrix.board }}
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
@@ -283,12 +292,12 @@ jobs:
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v1
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
@@ -318,11 +327,11 @@ jobs:
run: bin/build-native.sh
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: firmware-native-${{ steps.version.outputs.version }}.zip
path: |
@@ -351,30 +360,31 @@ jobs:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
path: ./
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Move files up
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/system-info.bin ./**/firmware*.bin ./**/*.uf2 ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: firmware-${{ steps.version.outputs.version }}
path: |
./*.bin
./*.uf2
./firmware-*-ota.zip
./meshtasticd_linux_amd64
./device-*.sh
./device-*.bat
retention-days: 90
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: firmware-${{ steps.version.outputs.version }}
path: ./output
@@ -392,7 +402,7 @@ jobs:
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip
path: ./*.elf
@@ -416,18 +426,18 @@ jobs:
needs: [gather-artifacts, after-checks]
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: firmware-${{ steps.version.outputs.version }}
path: ./output
@@ -440,7 +450,7 @@ jobs:
- name: Zip firmware
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip
path: ./elfs
@@ -458,7 +468,7 @@ jobs:
with:
draft: true
prerelease: true
release_name: Meshtastic Device ${{ steps.version.outputs.version }} alpha - Public Preview
release_name: Meshtastic Device ${{ steps.version.outputs.version }} Alpha
tag_name: v${{ steps.version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...

View File

@@ -53,7 +53,8 @@
"iostream": "cpp",
"esp_nimble_hci.h": "c",
"map": "cpp",
"random": "cpp"
"random": "cpp",
"*.tpp": "cpp"
},
"cSpell.words": [
"Blox",

53
arch/esp32/esp32.ini Normal file
View File

@@ -0,0 +1,53 @@
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
extends = arduino_base
platform = platformio/espressif32@^5.2.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 921600
debug_init_break = tbreak setup
monitor_filters = esp32_exception_decoder
board_build.filesystem = littlefs
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
h2zero/NimBLE-Arduino@^1.4.0
arduino-libraries/NTPClient@^3.1.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
lib_ignore =
segger_rtt
ESP32 BLE Arduino
; leave this commented out to avoid breaking Windows
;upload_port = /dev/ttyUSB0
;monitor_port = /dev/ttyUSB0
; Please don't delete these lines. JM uses them.
;upload_port = /dev/cu.SLAB_USBtoUART
;monitor_port = /dev/cu.SLAB_USBtoUART
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv

46
arch/esp32/esp32s3.ini Normal file
View File

@@ -0,0 +1,46 @@
[esp32s3_base]
extends = arduino_base
platform = platformio/espressif32@^5.2.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 961200
monitor_speed = 115200
debug_init_break = tbreak setup
monitor_filters = esp32_exception_decoder
board_build.filesystem = littlefs
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
h2zero/NimBLE-Arduino@^1.4.0
arduino-libraries/NTPClient@^3.1.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
lib_ignore =
segger_rtt
ESP32 BLE Arduino
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv

18
arch/nrf52/nrf52.ini Normal file
View File

@@ -0,0 +1,18 @@
[nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^9.4.0
extends = arduino_base
build_type = debug ; I'm debugging with ICE a lot now
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/nrf52
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040>
lib_ignore =
BluetoothOTA
; Note: By default no lora device is created for this build - it uses a simulated interface
[env:feather_nrf52832]
extends = nrf52_base
board = adafruit_feather_nrf52832

14
arch/nrf52/nrf52840.ini Normal file
View File

@@ -0,0 +1,14 @@
[nrf52840_base]
extends = nrf52_base
build_flags = ${nrf52_base.build_flags}
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
; Note: By default no lora device is created for this build - it uses a simulated interface
[env:nrf52840dk]
extends = nrf52840_base
board = nrf52840_dk

View File

@@ -0,0 +1,19 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
build_src_filter =
${env.build_src_filter}
-<platform/esp32/>
-<nimble/>
-<platform/nrf52/>
-<platform/stm32wl/>
-<platform/rp2040>
-<mesh/http/>
-<modules/esp32>
-<modules/Telemetry>
+<../variants/portduino>
lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
rweather/Crypto@^0.4.0
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
build_flags = ${arduino_base.build_flags} -Isrc/platform/portduino

19
arch/rp2040/rp2040.ini Normal file
View File

@@ -0,0 +1,19 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc
extends = arduino_base
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2040
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl>
lib_ignore =
BluetoothOTA
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b

18
arch/stm32/stm32wl5e.ini Normal file
View File

@@ -0,0 +1,18 @@
[stm32wl5e_base]
platform = platformio/ststm32@^15.4.1
board = generic_wl5e
framework = arduino
build_type = debug
build_flags =
${arduino_base.build_flags}
-Isrc/platform/stm32wl -g
-DHAL_SUBGHZ_MODULE_ENABLED
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
lib_deps =
${env.lib_deps}
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
lib_ignore =
mathertel/OneButton@^2.0.3

Binary file not shown.

View File

@@ -29,13 +29,11 @@ SRCELF=.pio/build/$1/firmware.elf
cp $SRCELF $OUTDIR/$basename.elf
echo "Copying ESP32 bin file"
SRCBIN=.pio/build/$1/firmware.bin
SRCBIN=.pio/build/$1/firmware.factory.bin
cp $SRCBIN $OUTDIR/$basename.bin
echo "Building Filesystem for ESP32 targets"
pio run --environment tbeam -t buildfs
cp .pio/build/tbeam/spiffs.bin $OUTDIR/littlefs-$VERSION.bin
cp images/system-info.bin $OUTDIR/system-info.bin
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR

View File

@@ -26,7 +26,9 @@ basename=firmware-$1-$VERSION
pio run --environment $1 # -v
SRCELF=.pio/build/$1/firmware.elf
DFUPKG=.pio/build/$1/firmware.zip
cp $SRCELF $OUTDIR/$basename.elf
cp $DFUPKG $OUTDIR/$basename-ota.zip
echo "Generating NRF52 uf2 file"
SRCHEX=.pio/build/$1/firmware.hex
@@ -34,3 +36,4 @@ bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
cp bin/*.uf2 $OUTDIR

23
bin/check-dependencies.sh Normal file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Note: This is a prototype for how we could add static code analysis to the CI.
set -e
if [[ $# -gt 0 ]]; then
# can override which environment by passing arg
BOARDS="$@"
else
BOARDS="rak4631 rak4631_eink t-echo pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
fi
echo "BOARDS:${BOARDS}"
CHECK=""
for BOARD in $BOARDS; do
CHECK="${CHECK} -e ${BOARD}"
done
echo $CHECK
pio pkg outdated -e $CHECK

View File

@@ -29,11 +29,11 @@ IF "__%FILENAME%__" == "____" (
IF EXIST %FILENAME% (
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
%PYTHON% -m esptool --baud 115200 erase_flash
%PYTHON% -m esptool --baud 115200 write_flash 0x1000 system-info.bin
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
for %%f in (littlefs-*.bin) do (
%PYTHON% -m esptool --baud 115200 write_flash 0x2B0000 %%f
%PYTHON% -m esptool --baud 115200 write_flash 0x300000 %%f
)
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
) else (
echo "Invalid file: %FILENAME%"
goto HELP

View File

@@ -47,9 +47,10 @@ shift "$((OPTIND-1))"
if [ -f "${FILENAME}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
"$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x1000 system-info.bin
"$PYTHON" -m esptool write_flash 0x2B0000 littlefs-*.bin
"$PYTHON" -m esptool write_flash 0x10000 ${FILENAME}
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
else
echo "Invalid file: ${FILENAME}"
show_help

View File

@@ -28,7 +28,7 @@ IF "__%FILENAME%__" == "____" (
)
IF EXIST %FILENAME% (
echo Trying to flash update %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
) else (
echo "Invalid file: %FILENAME%"
goto HELP

View File

@@ -44,7 +44,7 @@ shift "$((OPTIND-1))"
if [ -f "${FILENAME}" ]; then
echo "Trying to flash update ${FILENAME}."
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
$PYTHON -m esptool --baud 115200 write_flash 0x00 ${FILENAME}
else
echo "Invalid file: ${FILENAME}"
show_help

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env python3
import getopt
import sys
import os
from littlefs import LittleFS
from pathlib import Path
print( "Building LittleFS image..." )
argList = sys.argv[1:]
arxx = { argList[i]: argList[i+1] for i in range(0, len(argList)-1, 2) }
dataPath = arxx["-c"]
blockSize = int(arxx["-b"])
blockCount = int(arxx["-s"]) / blockSize
cwd = os.getcwd()
os.chdir(dataPath)
fileList = []
dirList = []
for (dirpath, dirnames, filenames) in os.walk('.'):
for f in filenames:
if (f[:1] != '.'):
fileList.append( os.path.join(dirpath, f) )
for d in dirnames:
if (d[:1] != '.'):
dirList.append( os.path.join(dirpath, d) )
fs = LittleFS(block_size=blockSize, block_count=blockCount) # create a 448kB partition
for curDir in dirList:
print( "Creating dir " + curDir )
fs.mkdir( curDir )
for curFile in fileList:
print( "Adding file " + curFile )
with open( curFile, 'rb' ) as f:
data = f.read()
with fs.open( curFile, 'wb') as fh:
fh.write( data )
outName = argList[-1]
os.chdir(cwd)
with open(outName, 'wb') as fh:
fh.write(fs.context.buffer)

View File

@@ -1,24 +1,70 @@
import subprocess
import configparser
import traceback
import sys
from os.path import join
from readprops import readProps
Import("env")
env.Replace( MKSPIFFSTOOL=env.get("PROJECT_DIR") + '/bin/mklittlefs.py' )
try:
import littlefs
except ImportError:
env.Execute("$PYTHONEXE -m pip install littlefs-python")
platform = env.PioPlatform()
def esp32_create_combined_bin(source, target, env):
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
print("Generating combined binary for serial flashing")
app_offset = 0x10000
new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin")
sections = env.subst(env.get("FLASH_EXTRA_IMAGES"))
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
chip = env.get("BOARD_MCU")
flash_size = env.BoardConfig().get("upload.flash_size")
flash_freq = env.BoardConfig().get("build.f_flash", '40m')
flash_freq = flash_freq.replace('000000L', 'm')
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
if flash_mode == "qio" or flash_mode == "qout":
flash_mode = "dio"
if memory_type == "opi_opi" or memory_type == "opi_qspi":
flash_mode = "dout"
cmd = [
"--chip",
chip,
"merge_bin",
"-o",
new_file_name,
"--flash_mode",
flash_mode,
"--flash_freq",
flash_freq,
"--flash_size",
flash_size,
]
print(" Offset | File")
for section in sections:
sect_adr, sect_file = section.split(" ", 1)
print(f" - {sect_adr} | {sect_file}")
cmd += [sect_adr, sect_file]
print(f" - {hex(app_offset)} | {firmware_name}")
cmd += [hex(app_offset), firmware_name]
print('Using esptool.py arguments: %s' % ' '.join(cmd))
esptool.main(cmd)
if (platform.name == "espressif32"):
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
import esptool
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
Import("projenv")
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
verObj = readProps(prefsLoc)
print("Using meshtastic platformio-custom.py, firmware version " + verObj['long'])
# print("path is" + ','.join(sys.path))
# General options that are passed to the C and C++ compilers
projenv.Append(CCFLAGS=[

Binary file not shown.

View File

@@ -1,7 +1,8 @@
# FIXME! using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
# This is a layout for 4MB of flash
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x2A0000,
spiffs, data, spiffs, 0x2B0000,0x150000,
nvs, data, nvs, 0x009000, 0x005000,
otadata, data, ota, 0x00e000, 0x002000,
app, app, ota_0, 0x010000, 0x250000,
flashApp, app, ota_1, 0x260000, 0x0A0000,
spiffs, data, spiffs, 0x300000, 0x100000,
1 # FIXME! using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
2 # This is a layout for 4MB of flash
3 # Name, Type, SubType, Offset, Size, Flags
4 nvs, data, nvs, 0x9000, 0x5000, nvs, data, nvs, 0x009000, 0x005000,
5 otadata, data, ota, 0xe000, 0x2000, otadata, data, ota, 0x00e000, 0x002000,
6 app0, app, ota_0, 0x10000, 0x2A0000, app, app, ota_0, 0x010000, 0x250000,
7 spiffs, data, spiffs, 0x2B0000,0x150000, flashApp, app, ota_1, 0x260000, 0x0A0000,
8 spiffs, data, spiffs, 0x300000, 0x100000,

View File

@@ -2,7 +2,8 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
default_envs = tbeam
;default_envs = tbeam
;default_envs = pico
;default_envs = tbeam-s3-core
;default_envs = tbeam0.7
;default_envs = heltec-v1
@@ -14,7 +15,7 @@ default_envs = tbeam
;default_envs = tlora-v2
;default_envs = tlora-v2-1-1.6
;default_envs = lora-relay-v1 # nrf board
; default_envs = t-echo
;default_envs = t-echo
;default_envs = nrf52840dk-geeksville
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
;default_envs = nano-g1
@@ -24,7 +25,9 @@ default_envs = tbeam
;default_envs = m5stack-coreink
;default_envs = rak4631
extra_configs = variants/*/platformio.ini
extra_configs =
arch/*/*.ini
variants/*/platformio.ini
[env]
extra_scripts = bin/platformio-custom.py
@@ -45,17 +48,18 @@ monitor_speed = 115200
lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/TinyGPSPlus.git
Wire ; explicitly needed here because the AXP202 library forgets to add it
SPI
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#2f0d0528d737000043e949f4c3bdfb623cf0b902
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.6
erriez/ErriezCRC32@^1.0.1
; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck
check_skip_packages = yes
check_flags =
--common-flag
cppcheck: --enable=--inline-suppr
; Common settings for conventional (non Portduino) Arduino targets
[arduino_base]
@@ -63,16 +67,18 @@ framework = arduino
lib_deps =
${env.lib_deps}
; Portduino is using meshtastic fork for now
https://github.com/jgromes/RadioLib.git
jgromes/RadioLib@5.4.1
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
build_flags = ${env.build_flags} -Os
-DRADIOLIB_SPI_PARANOID=0
# -DRADIOLIB_GODMODE
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
; Common libs for communicating over TCP/IP networks such as MQTT
[networking_base]
lib_deps =
PubSubClient
knolleary/PubSubClient@^2.8
meshtastic/json11@^1.0.2
; Common libs for environmental measurements in telemetry module
@@ -81,177 +87,11 @@ lib_deps =
lib_deps =
adafruit/Adafruit BusIO@^1.11.4
adafruit/Adafruit Unified Sensor@^1.1.4
adafruit/Adafruit BMP280 Library@^2.6.3
adafruit/Adafruit BMP280 Library@^2.6.6
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BME680 Library@^2.0.1
adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
extends = arduino_base
platform = espressif32@3.5.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 921600
debug_init_break = tbreak setup
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_flags =
${arduino_base.build_flags} -Wall -Wextra -Isrc/platform/esp32 -lnimble -std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial -DCONFIG_BT_NIMBLE_ENABLED -DCONFIG_NIMBLE_CPP_LOG_LEVEL=2 -DCONFIG_BT_NIMBLE_MAX_CCCDS=20
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git
h2zero/NimBLE-Arduino@1.4.0
arduino-libraries/NTPClient@^3.1.0
lorol/LittleFS_esp32@^1.0.6
https://github.com/lewisxhe/XPowersLib.git
lib_ignore =
segger_rtt
ESP32 BLE Arduino
platform_packages =
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#4cde0f5d412d2695184f32e8a47e9bea57b45276
; leave this commented out to avoid breaking Windows
;upload_port = /dev/ttyUSB0
;monitor_port = /dev/ttyUSB0
; Please don't delete these lines. JM uses them.
;upload_port = /dev/cu.SLAB_USBtoUART
;monitor_port = /dev/cu.SLAB_USBtoUART
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv
[nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
; platform = nordicnrf52 ;pending https://github.com/platformio/builder-framework-arduino-nrf5/pull/7
platform = https://github.com/meshtastic/platform-nordicnrf52.git#merge
extends = arduino_base
build_type = debug ; I'm debugging with ICE a lot now
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/nrf52
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040>
lib_ignore =
BluetoothOTA
[nrf52840_base]
extends = nrf52_base
build_flags = ${nrf52_base.build_flags}
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto.git
; Note: By default no lora device is created for this build - it uses a simulated interface
[env:nrf52840dk]
extends = nrf52840_base
board = nrf52840_dk
; Note: By default no lora device is created for this build - it uses a simulated interface
[env:feather_nrf52832]
extends = nrf52_base
board = adafruit_feather_nrf52832
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
extends = arduino_base
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/rp2040
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl>
lib_ignore =
BluetoothOTA
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/kokke/tiny-AES-c.git
[stm32wl5e_base]
platform = ststm32
board = generic_wl5e
framework = arduino
build_type = debug
build_flags =
${arduino_base.build_flags}
-Isrc/platform/stm32wl -g
-DHAL_SUBGHZ_MODULE_ENABLED
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
lib_deps =
${env.lib_deps}
https://github.com/jgromes/RadioLib.git
https://github.com/kokke/tiny-AES-c.git
lib_ignore =
mathertel/OneButton@^2.0.3
[esp32s3_base]
extends = arduino_base
platform = espressif32
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
upload_speed = 961200
monitor_speed = 115200
debug_init_break = tbreak setup
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
build_flags =
${arduino_base.build_flags}
-Wall
-Wextra
-Isrc/platform/esp32
-std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
-DAXP_DEBUG_PORT=Serial
-DCONFIG_BT_NIMBLE_ENABLED
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
; https://github.com/meshtastic/esp32_https_server.git
; PR has been submitted and can be deleted after merging ,https://github.com/meshtastic/esp32_https_server/pull/1
https://github.com/lewisxhe/esp32_https_server.git
h2zero/NimBLE-Arduino@1.4.0
arduino-libraries/NTPClient@^3.1.0
https://github.com/lewisxhe/XPowersLib.git
lib_ignore =
segger_rtt
ESP32 BLE Arduino
platform_packages =
framework-arduinoespressif32@ 3.20004.220825
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
board_build.partitions = partition-table.csv
adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4

View File

@@ -7,7 +7,7 @@ const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5,
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b};
const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};

View File

@@ -9,7 +9,7 @@
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
#define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
// NRF52 wants these constants as byte arrays

View File

@@ -9,13 +9,13 @@ bool copyFile(const char* from, const char* to)
File f1 = FSCom.open(from, FILE_O_READ);
if (!f1){
DEBUG_MSG("Failed to open file");
DEBUG_MSG("Failed to open source file %s\n", from);
return false;
}
File f2 = FSCom.open(to, FILE_O_WRITE);
if (!f2) {
DEBUG_MSG("Failed to open file");
DEBUG_MSG("Failed to open destination file %s\n", to);
return false;
}
@@ -33,17 +33,25 @@ bool copyFile(const char* from, const char* to)
bool renameFile(const char* pathFrom, const char* pathTo)
{
#ifdef FSCom
#ifdef ARCH_ESP32
// rename was fixed for ESP32 IDF LittleFS in April
return FSCom.rename(pathFrom, pathTo);
#else
if (copyFile(pathFrom, pathTo) && FSCom.remove(pathFrom) ) {
return true;
} else{
return false;
}
#endif
#endif
}
void listDir(const char * dirname, uint8_t levels)
void listDir(const char * dirname, uint8_t levels, boolean del = false)
{
#ifdef FSCom
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
char buffer[255];
#endif
File root = FSCom.open(dirname, FILE_O_READ);
if(!root){
return;
@@ -56,55 +64,92 @@ void listDir(const char * dirname, uint8_t levels)
while(file){
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
if(levels){
listDir(file.name(), levels -1);
#ifdef ARCH_ESP32
listDir(file.path(), levels -1, del);
if(del) {
DEBUG_MSG("Removing %s\n", file.path());
strcpy(buffer, file.path());
file.close();
FSCom.rmdir(buffer);
} else {
file.close();
}
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
listDir(file.name(), levels -1, del);
if(del) {
DEBUG_MSG("Removing %s\n", file.name());
strcpy(buffer, file.name());
file.close();
FSCom.rmdir(buffer);
} else {
file.close();
}
#else
listDir(file.name(), levels -1, del);
file.close();
#endif
}
} else {
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
#ifdef ARCH_ESP32
if(del) {
DEBUG_MSG("Deleting %s\n", file.path());
strcpy(buffer, file.path());
file.close();
FSCom.remove(buffer);
} else {
DEBUG_MSG(" %s (%i Bytes)\n", file.path(), file.size());
file.close();
}
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if(del) {
DEBUG_MSG("Deleting %s\n", file.name());
strcpy(buffer, file.name());
file.close();
FSCom.remove(buffer);
} else {
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
file.close();
}
#else
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
file.close();
#endif
}
file.close();
file = root.openNextFile();
}
file.close();
#ifdef ARCH_ESP32
if(del) {
DEBUG_MSG("Removing %s\n", root.path());
strcpy(buffer, root.path());
root.close();
FSCom.rmdir(buffer);
} else {
root.close();
}
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
if(del) {
DEBUG_MSG("Removing %s\n", root.name());
strcpy(buffer, root.name());
root.close();
FSCom.rmdir(buffer);
} else {
root.close();
}
#else
root.close();
#endif
#endif
}
void rmDir(const char * dirname)
{
#ifdef FSCom
File file = FSCom.open(dirname, FILE_O_READ);
if(!file){
return;
}
if(!file.isDirectory()){
file.close();
FSCom.remove(file.name());
// DEBUG_MSG("Remove FILE %s\n", file.name());
return;
}
file.rewindDirectory();
while (true) {
File entry = file.openNextFile();
if (!entry) {
break;
}
char dirpath[100]; // array to hold the result.
strcpy(dirpath, dirname); // copy string one into the result.
strcat(dirpath,"/"); // append string two to the result.
strcat(dirpath,entry.name()); // append string two to the result.
if(entry.isDirectory() && !String(entry.name()).endsWith(".")) {
entry.close();
// DEBUG_MSG("Descend DIR %s\n", dirpath);
rmDir(dirpath);
} else {
entry.close();
// DEBUG_MSG("Remove FILE %s\n", entry.name());
FSCom.remove(entry.name());
}
}
FSCom.rmdir(dirname);
// DEBUG_MSG("Remove DIR %s\n", dirname);
file.close();
#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
}
@@ -116,8 +161,11 @@ void fsInit()
DEBUG_MSG("ERROR filesystem mount Failed. Formatting...\n");
assert(0); // FIXME - report failure to phone
}
#ifdef ARCH_ESP32
DEBUG_MSG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
#else
DEBUG_MSG("Filesystem files:\n");
#endif
listDir("/", 10);
#endif
}

View File

@@ -23,16 +23,9 @@
#endif
#if defined(ARCH_ESP32)
#if CONFIG_IDF_TARGET_ESP32S3
#include <LittleFS.h> //esp32s3 uses the framework's built-in LittleFS
#define FSCom LittleFS
#else
// ESP32 version
#include "LITTLEFS.h"
#define FSCom LITTLEFS
#endif
#include "LittleFS.h"
#define FSCom LittleFS
#define FSBegin() FSCom.begin(true)
#define FILE_O_WRITE "w"
#define FILE_O_READ "r"
@@ -47,6 +40,7 @@ using namespace Adafruit_LittleFS_Namespace;
#endif
void fsInit();
bool copyFile(const char* from, const char* to);
bool renameFile(const char* pathFrom, const char* pathTo);
void listDir(const char * dirname, uint8_t levels);
void listDir(const char * dirname, uint8_t levels, boolean del);
void rmDir(const char * dirname);

View File

@@ -25,21 +25,21 @@ class GPSStatus : public Status
public:
GPSStatus() { statusType = STATUS_TYPE_GPS; }
// proposed for deprecation
GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
uint32_t heading, uint32_t numSatellites)
: Status()
{
this->hasLock = hasLock;
this->isConnected = isConnected;
// // proposed for deprecation
// GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
// uint32_t heading, uint32_t numSatellites)
// : Status()
// {
// this->hasLock = hasLock;
// this->isConnected = isConnected;
this->p.latitude_i = latitude;
this->p.longitude_i = longitude;
this->p.altitude = altitude;
this->p.PDOP = dop;
this->p.ground_track = heading;
this->p.sats_in_view = numSatellites;
}
// this->p.latitude_i = latitude;
// this->p.longitude_i = longitude;
// this->p.altitude = altitude;
// this->p.PDOP = dop;
// this->p.ground_track = heading;
// this->p.sats_in_view = numSatellites;
// }
// preferred method
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
@@ -114,6 +114,7 @@ class GPSStatus : public Status
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track ||
newStatus->p.ground_speed != p.ground_speed ||
newStatus->p.sats_in_view != p.sats_in_view);
}
@@ -136,9 +137,9 @@ class GPSStatus : public Status
if (isDirty) {
if (hasLock) {
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, sats=%d\n", p.timestamp,
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp,
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
p.sats_in_view);
p.ground_speed * 1e-2, p.sats_in_view);
} else
DEBUG_MSG("No GPS lock\n");
onNewStatus.notifyObservers(this);

View File

@@ -131,7 +131,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
#endif
// DEBUG_MSG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
last_read_value = scaled;
return scaled * 1000;
return scaled;
} else {
return last_read_value;
}
@@ -368,8 +368,21 @@ bool Power::axpChipInit()
#ifdef HAS_PMU
TwoWire * w = NULL;
// Use macro to distinguish which wire is used by PMU
#ifdef PMU_USE_WIRE1
w = &Wire1;
#else
w = &Wire;
#endif
/**
* It is not necessary to specify the wire pin,
* just input the wire, because the wire has been initialized in main.cpp
*/
if (!PMU) {
PMU = new XPowersAXP2101(Wire, I2C_SDA, I2C_SCL);
PMU = new XPowersAXP2101(*w);
if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP2101 power management\n");
delete PMU;
@@ -380,7 +393,7 @@ bool Power::axpChipInit()
}
if (!PMU) {
PMU = new XPowersAXP192(Wire, I2C_SDA, I2C_SCL);
PMU = new XPowersAXP192(*w);
if (!PMU->init()) {
DEBUG_MSG("Warning: Failed to find AXP192 power management\n");
delete PMU;
@@ -396,7 +409,9 @@ bool Power::axpChipInit()
* In order not to affect other devices, if the initialization of the PMU fails, Wire needs to be re-initialized once,
* if there are multiple devices sharing the bus.
* * */
Wire.begin(I2C_SDA, I2C_SCL);
#ifndef PMU_USE_WIRE1
w->begin(I2C_SDA, I2C_SCL);
#endif
return false;
}
@@ -456,6 +471,23 @@ bool Power::axpChipInit()
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
/**
* ALDO2 cannot be turned off.
* It is a necessary condition for sensor communication.
* It must be turned on to properly access the sensor and screen
* It is also responsible for the power supply of PCF8563
*/
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
// 6-axis , magnetometer ,bme280 , oled screen power channel
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
// sdcard power channle
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
// PMU->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
// PMU->enablePowerOutput(XPOWERS_DCDC4);

View File

@@ -240,7 +240,7 @@ void PowerFSM_setup()
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool hasPower = isPowered();
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower);
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout");
// wake timer expired or a packet arrived

View File

@@ -1,6 +1,7 @@
#include "configuration.h"
#include "RedirectablePrint.h"
#include "RTC.h"
#include "NodeDB.h"
#include "concurrency/OSThread.h"
// #include "wifi/WiFiServerAPI.h"
#include <assert.h>
@@ -30,7 +31,9 @@ size_t RedirectablePrint::write(uint8_t c)
// optionally send chars to TCP also
//WiFiServerPort::debugOut(c);
dest->write(c);
if (!config.has_lora || config.device.serial_enabled)
dest->write(c);
return 1; // We always claim one was written, rather than trusting what the
// serial port said (which could be zero)
}
@@ -46,6 +49,13 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
if (len < 0) return 0;
// If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the return value
if (len > sizeof(printBuf) - 1) {
len = sizeof(printBuf) - 1;
printBuf[sizeof(printBuf) - 2] = '\n';
}
len = Print::write(printBuf, len);
return len;
}
@@ -100,4 +110,4 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
}
return r;
}
}

View File

@@ -20,6 +20,9 @@ void consolePrintf(const char *format, ...)
va_start(arg, format);
console->vprintf(format, arg);
va_end(arg);
#ifdef ARCH_ESP32
console->flush();
#endif
}
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
@@ -57,10 +60,15 @@ bool SerialConsole::checkIsConnected()
*/
bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
{
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
if (!config.device.debug_log_enabled)
setDestination(&noopPrint);
canWrite = true;
// only talk to the API once the configuration has been loaded and we're sure the serial port is not disabled.
if (config.has_lora && config.device.serial_enabled) {
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
if (!config.device.debug_log_enabled)
setDestination(&noopPrint);
canWrite = true;
return StreamAPI::handleToRadio(buf, len);
}
return StreamAPI::handleToRadio(buf, len);
}else{
return false;
}
}

View File

@@ -36,6 +36,7 @@ struct ToneDuration {
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_CS4 277
const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note
@@ -65,16 +66,17 @@ void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
#endif
void playStartMelody() {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4},
{NOTE_B3, DURATION_1_8},
{NOTE_B3, DURATION_1_8}};
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8},
{NOTE_AS3, DURATION_1_8},
{NOTE_CS4, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
void playShutdownMelody() {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4},
{NOTE_G3, DURATION_1_8},
{NOTE_D3, DURATION_1_8}};
ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8},
{NOTE_AS3, DURATION_1_8},
{NOTE_FS3, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
#endif

View File

@@ -94,19 +94,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Define this if you know you have that controller or your "SSD1306" misbehaves.
//#define USE_SH1106
// Flip the screen upside down by default as it makes more sense on T-BEAM
// devices. Comment this out to not rotate screen 180 degrees.
#define SCREEN_FLIP_VERTICALLY
// Define if screen should be mirrored left to right
// #define SCREEN_MIRROR
// The m5stack I2C Keyboard (also RAK14004)
#define CARDKB_ADDR 0x5F
// The older M5 Faces I2C Keyboard
#define FACESKB_ADDR 0x88
// -----------------------------------------------------------------------------
// SENSOR
// -----------------------------------------------------------------------------
@@ -115,6 +108,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MCP9808_ADDR 0x18
#define INA_ADDR 0x40
#define INA_ADDR_ALTERNATE 0x41
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
// -----------------------------------------------------------------------------
// Security
// -----------------------------------------------------------------------------
#define ATECC608B_ADDR 0x35
// -----------------------------------------------------------------------------
// GPS

View File

@@ -9,6 +9,41 @@
#endif
#if HAS_WIRE
void printATECCInfo()
{
#ifndef ARCH_PORTDUINO
atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: ");
for (int i = 0 ; i < 9 ; i++) {
DEBUG_MSG("%02x",atecc.serialNumber[i]);
}
DEBUG_MSG(", Rev Number: ");
for (int i = 0 ; i < 4 ; i++) {
DEBUG_MSG("%02x",atecc.revisionNumber[i]);
}
DEBUG_MSG("\n");
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
if (atecc.generatePublicKey() == false) {
DEBUG_MSG("ATECC608B Error generating public key\n");
} else {
DEBUG_MSG("ATECC608B Public Key: ");
for (int i = 0 ; i < 64 ; i++) {
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]);
}
DEBUG_MSG("\n");
}
}
#endif
}
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
uint16_t value = 0x00;
Wire.beginTransmission(address);
@@ -79,6 +114,17 @@ void scanI2Cdevice(void)
DEBUG_MSG("unknown display found\n");
}
}
#ifndef ARCH_PORTDUINO
if (addr == ATECC608B_ADDR){
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {
DEBUG_MSG("ATECC608B initialized\n");
} else {
DEBUG_MSG("ATECC608B initialization failed\n");
}
printATECCInfo();
}
#endif
#ifdef RV3028_RTC
if (addr == RV3028_RTC){
rtc_found = addr;
@@ -107,10 +153,6 @@ void scanI2Cdevice(void)
kb_model = 0x00;
}
}
if (addr == FACESKB_ADDR) {
faceskb_found = addr;
DEBUG_MSG("m5 Faces found\n");
}
if (addr == ST7567_ADDRESS) {
screen_found = addr;
DEBUG_MSG("st7567 display found\n");
@@ -149,6 +191,22 @@ void scanI2Cdevice(void)
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
}
if (addr == QMC6310_ADDR) {
DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
}
if (addr == QMI8658_ADDR) {
DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
}
if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
}
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
DEBUG_MSG("LPS22HB sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
}
} else if (err == 4) {
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
}

View File

@@ -145,8 +145,8 @@ bool GPS::setupGPS()
if (_serial_gps && !didSerialInit) {
didSerialInit = true;
#if CONFIG_IDF_TARGET_ESP32S3
// In esp32s3 framework, setRxBufferSize needs to be initialized before Serial
#ifdef ARCH_ESP32
// In esp32 framework, setRxBufferSize needs to be initialized before Serial
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
@@ -157,12 +157,6 @@ bool GPS::setupGPS()
_serial_gps->begin(GPS_BAUDRATE);
#endif
#if CONFIG_IDF_TARGET_ESP32
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
#ifdef LILYGO_TBEAM_S3_CORE
/*
* T-Beam-S3-Core will be preset to use gps Probe here, and other boards will not be changed first
*/
@@ -251,86 +245,6 @@ bool GPS::setupGPS()
DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
}
}
#endif
#ifdef TTGO_T_ECHO
// Switch to 9600 baud, then close and reopen port
_serial_gps->end();
delay(250);
_serial_gps->begin(4800);
delay(250);
_serial_gps->write("$PCAS01,1*1D\r\n");
delay(250);
_serial_gps->end();
delay(250);
_serial_gps->begin(9600);
delay(250);
// Initialize the L76K Chip, use GPS + GLONASS
_serial_gps->write("$PCAS04,5*1C\r\n");
delay(250);
// only ask for RMC and GGA
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
delay(250);
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
_serial_gps->write("$PCAS11,3*1E\r\n");
delay(250);
#endif
#ifdef GPS_UBLOX
delay(250);
// Set the UART port to output NMEA only
byte _message_nmea[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x00, 0x00,
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
if (!getACK(0x06, 0x00)) {
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n");
return true;
}
// disable GGL
byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A};
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n");
return true;
}
// disable GSA
byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x41};
_serial_gps->write(_message_GSA, sizeof(_message_GSA));
if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n");
return true;
}
// disable GSV
byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x48};
_serial_gps->write(_message_GSV, sizeof(_message_GSV));
if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n");
return true;
}
// disable VTG
byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x09, 0x56};
_serial_gps->write(_message_VTG, sizeof(_message_VTG));
if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n");
return true;
}
// enable RMC
byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x54};
_serial_gps->write(_message_RMC, sizeof(_message_RMC));
if (!getACK(0x06, 0x01)) {
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n");
return true;
}
// enable GGA
byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x38};
_serial_gps->write(_message_GGA, sizeof(_message_GGA));
if (!getACK(0x06, 0x01)) DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
#endif
}
return true;
@@ -490,7 +404,6 @@ int32_t GPS::runOnce()
// if we have received valid NMEA claim we are connected
setConnected();
} else {
#if defined(LILYGO_TBEAM_S3_CORE)
if(gnssModel == GNSS_MODEL_UBLOX){
// reset the GPS on next bootup
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
@@ -499,14 +412,6 @@ int32_t GPS::runOnce()
nodeDB.saveDeviceStateToDisk();
}
}
#elif defined(GPS_UBLOX)
// reset the GPS on next bootup
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n");
devicestate.did_gps_reset = false;
nodeDB.saveDeviceStateToDisk();
}
#endif
}
// If we are overdue for an update, turn on the GPS and at least publish the current status
@@ -608,6 +513,13 @@ int GPS::prepareDeepSleep(void *unused)
GnssModel_t GPS::probe()
{
// return immediately if the model is set by the variant.h file
#ifdef GPS_UBLOX
return GNSS_MODEL_UBLOX;
#elif defined(GPS_L76K)
return GNSS_MODEL_MTK;
#else
// we use autodetect, only T-BEAM S3 for now...
uint8_t buffer[256];
/*
* The GNSS module information variable is temporarily placed inside the function body,
@@ -702,6 +614,7 @@ GnssModel_t GPS::probe()
}
return GNSS_MODEL_UBLOX;
#endif
}
#if HAS_GPS

View File

@@ -19,27 +19,21 @@ static int32_t toDegInt(RawDegrees d)
bool NMEAGPS::factoryReset()
{
/**
* First use the macro definition to distinguish,
* if there is no problem, the macro definition will be deleted
* */
#if defined(LILYGO_TBEAM_S3_CORE)
if(gnssModel == GNSS_MODEL_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);
}
#elif defined(GPS_UBLOX)
#ifdef PIN_GPS_REINIT
//The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
digitalWrite(PIN_GPS_REINIT, 0);
pinMode(PIN_GPS_REINIT, OUTPUT);
delay(150); //The L76K datasheet calls for at least 100MS delay
digitalWrite(PIN_GPS_REINIT, 1);
#endif
// 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);
#endif
return true;
}
@@ -223,13 +217,10 @@ bool NMEAGPS::lookForLocation()
}
}
/*
// REDUNDANT?
// expect gps pos lat=37.520825, lon=-122.309162, alt=158
DEBUG_MSG("new NMEA GPS pos lat=%f, lon=%f, alt=%d, dop=%g, heading=%f\n",
latitude * 1e-7, longitude * 1e-7, altitude, dop * 1e-2,
heading * 1e-5);
*/
if (reader.speed.isUpdated() && reader.speed.isValid()) {
p.ground_speed = reader.speed.kmph();
}
return true;
}

76
src/gps/NMEAWPL.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "NMEAWPL.h"
/* -------------------------------------------
* 1 2 3 4 5 6
* | | | | | |
* $--WPL,llll.ll,a,yyyyy.yy,a,c--c*hh<CR><LF>
*
* Field Number:
* 1 Latitude
* 2 N or S (North or South)
* 3 Longitude
* 4 E or W (East or West)
* 5 Waypoint name
* 6 Checksum
* -------------------------------------------
*/
uint printWPL(char *buf, const Position &pos, const char *name)
{
uint len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}
/* -------------------------------------------
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* | | | | | | | | | | | | | | |
* $--GGA,hhmmss.ss,ddmm.mm,a,ddmm.mm,a,x,xx,x.x,x.x,M,x.x,M,x.x,xxxx*hh<CR><LF>
*
* Field Number:
* 1 UTC of this position report, hh is hours, mm is minutes, ss.ss is seconds.
* 2 Latitude
* 3 N or S (North or South)
* 4 Longitude
* 5 E or W (East or West)
* 6 GPS Quality Indicator (non null)
* 7 Number of satellites in use, 00 - 12
* 8 Horizontal Dilution of precision (meters)
* 9 Antenna Altitude above/below mean-sea-level (geoid) (in meters)
* 10 Units of antenna altitude, meters
* 11 Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid
* 12 Units of geoidal separation, meters
* 13 Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used
* 14 Differential reference station ID, 0000-1023
* 15 Checksum
* -------------------------------------------
*/
uint printGGA(char *buf, const Position &pos)
{
uint len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d",
pos.time / 1000,
pos.time % 1000,
pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N',
pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E',
pos.fix_type,
pos.sats_in_view,
pos.HDOP,
pos.altitude,
'M',
pos.altitude_geoidal_separation,
'M',
0,
0);
uint chk = 0;
for (uint i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
return len;
}

7
src/gps/NMEAWPL.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <Arduino.h>
#include "main.h"
uint printWPL(char *buf, const Position &pos, const char *name);
uint printGGA(char *buf, const Position &pos);

View File

@@ -47,8 +47,8 @@ void readFromRTC()
rtc.begin();
auto tc = rtc.getDateTime();
tm t;
t.tm_year = tc.year;
t.tm_mon = tc.month;
t.tm_year = tc.year - 1900;
t.tm_mon = tc.month - 1;
t.tm_mday = tc.day;
t.tm_hour = tc.hour;
t.tm_min = tc.minute;
@@ -112,7 +112,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
PCF8563_Class rtc;
rtc.begin();
tm *t = localtime(&tv->tv_sec);
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_hour, t->tm_min, t->tm_sec);
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
DEBUG_MSG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
}
#elif defined(ARCH_ESP32)

View File

@@ -16,7 +16,7 @@ enum RTCQuality {
RTCQualityFromNet = 2,
/// Our time is based on NTP
RTCQualityNTP= 3,
RTCQualityNTP = 3,
/// Our time is based on our own GPS
RTCQualityGPS = 4

View File

@@ -57,7 +57,6 @@ namespace graphics
// This means the *visible* area (sh1106 can address 132, but shows 128 for example)
#define IDLE_FRAMERATE 1 // in fps
#define COMPASS_DIAM 44
// DEBUG
#define NUM_EXTRA_FRAMES 3 // text message and debug frame
@@ -85,10 +84,6 @@ static char ourId[5];
// GeoCoord object for the screen
GeoCoord geoCoord;
// OEM Config File
static const char *oemConfigFile = "/prefs/oem.proto";
OEMStore oemStore;
#ifdef SHOW_REDRAWS
static bool heartbeat = false;
#endif
@@ -98,7 +93,7 @@ static uint16_t displayWidth, displayHeight;
#define SCREEN_WIDTH displayWidth
#define SCREEN_HEIGHT displayHeight
#if defined(USE_EINK) || defined(ILI9341_DRIVER)
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
@@ -117,6 +112,7 @@ static uint16_t displayWidth, displayHeight;
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
#define FONT_HEIGHT_LARGE fontHeight(FONT_LARGE)
#define getStringCenteredX(s) ((SCREEN_WIDTH - display->getStringWidth(s)) / 2)
@@ -522,6 +518,8 @@ static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GP
} else {
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
displayLine = "Altitude: " + String(geoCoord.getAltitude()) + "m";
if (config.display.units == Config_DisplayConfig_DisplayUnits_IMPERIAL)
displayLine = "Altitude: " + String(geoCoord.getAltitude() * METERS_TO_FEET) + "ft";
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
}
}
@@ -666,6 +664,26 @@ static bool hasPosition(NodeInfo *n)
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
static uint16_t getCompassDiam(OLEDDisplay *display)
{
uint16_t diam = 0;
// get the smaller of the 2 dimensions and subtract 20
if(display->getWidth() > display->getHeight()) {
diam = display->getHeight();
// if 2/3 of the other size would be smaller, use that
if (diam > (display->getWidth() * 2 / 3)) {
diam = display->getWidth() * 2 / 3;
}
} else {
diam = display->getWidth();
if (diam > (display->getHeight() * 2 / 3)) {
diam = display->getHeight() * 2 / 3;
}
}
return diam - 20;
};
/// We will skip one node - the one for us, so we just blindly loop over all
/// nodes
static size_t nodeIndex;
@@ -682,7 +700,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
for (int i = 0; i < 4; i++) {
arrowPoints[i]->rotate(headingRadian);
arrowPoints[i]->scale(COMPASS_DIAM * 0.6);
arrowPoints[i]->scale(getCompassDiam(display) * 0.6);
arrowPoints[i]->translate(compassX, compassY);
}
drawLine(display, tip, tail);
@@ -704,7 +722,7 @@ static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t com
for (int i = 0; i < 4; i++) {
// North on compass will be negative of heading
rosePoints[i]->rotate(-myHeading);
rosePoints[i]->scale(COMPASS_DIAM);
rosePoints[i]->scale(getCompassDiam(display));
rosePoints[i]->translate(compassX, compassY);
}
drawLine(display, N1, N3);
@@ -769,7 +787,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
// coordinates for the center of the compass/circle
int16_t compassX = x + SCREEN_WIDTH - COMPASS_DIAM / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
bool hasNodeHeading = false;
if (ourNode && hasPosition(ourNode)) {
@@ -783,10 +801,18 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
Position &p = node->position;
float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
if (d < 2000)
snprintf(distStr, sizeof(distStr), "%.0f m", d);
else
snprintf(distStr, sizeof(distStr), "%.1f km", d / 1000);
if (config.display.units == 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));
@@ -802,7 +828,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// Debug info for gps lock errors
// DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
display->drawCircle(compassX, compassY, COMPASS_DIAM / 2);
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
// Must be after distStr is populated
drawColumns(display, x, y, fields);
@@ -898,9 +924,6 @@ void Screen::setup()
dispdev.setDetected(screen_model);
#endif
// Load OEM config from Proto file if existent
loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
// Initialising the UI will init the display too.
ui.init();
@@ -936,8 +959,12 @@ void Screen::setup()
#ifdef SCREEN_MIRROR
dispdev.mirrorScreen();
#elif defined(SCREEN_FLIP_VERTICALLY)
dispdev.flipScreenVertically();
#else
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically flip it.
// If you have a headache now, you're welcome.
if (!config.display.flip_screen) {
dispdev.flipScreenVertically();
}
#endif
// Get our hardware ID
@@ -1071,7 +1098,6 @@ int32_t Screen::runOnce()
// otherwise that breaks animations.
if (targetFramerate != IDLE_FRAMERATE && ui.getUiState()->frameState == FIXED) {
// oldFrameState = ui.getUiState()->frameState;
DEBUG_MSG("Setting idle framerate\n");
targetFramerate = IDLE_FRAMERATE;
ui.setTargetFPS(targetFramerate);
@@ -1297,7 +1323,6 @@ void Screen::handleOnPress()
// If we are in a transition, the press must have bounced, drop it.
if (ui.getUiState()->frameState == FIXED) {
ui.nextFrame();
DEBUG_MSG("Setting LastScreenTransition\n");
lastScreenTransition = millis();
setFastFramerate();
}
@@ -1309,8 +1334,6 @@ void Screen::handleOnPress()
void Screen::setFastFramerate()
{
DEBUG_MSG("Setting fast framerate\n");
// We are about to start a transition so speed up fps
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
@@ -1635,6 +1658,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// adjust Brightness cycle trough 1 to 254 as long as attachDuringLongPress is true
void Screen::adjustBrightness()
{
if (!useDisplay)
return;
if (brightness == 254) {
brightness = 0;
} else {

View File

@@ -57,6 +57,16 @@ class Screen
#define BRIGHTNESS_DEFAULT 150
#endif
// Meters to feet conversion
#ifndef METERS_TO_FEET
#define METERS_TO_FEET 3.28
#endif
// Feet to miles conversion
#ifndef MILES_TO_FEET
#define MILES_TO_FEET 5280
#endif
namespace graphics
{
@@ -213,27 +223,29 @@ class Screen : public concurrency::OSThread
LASTCHAR = ch;
switch (last) { // conversion depending on first UTF8-character
case 0xC2: {
SKIPREST = false;
return (uint8_t)ch;
}
case 0xC3: {
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
}
// map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes
// note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306' library
// have empty chars for non-latin ASCII symbols
case 0xD0: {
SKIPREST = false;
if (ch == 129) return (uint8_t)(168); // Ё
if (ch > 143 && ch < 192) return (uint8_t)(ch + 48);
}
case 0xD1: {
SKIPREST = false;
if (ch == 145) return (uint8_t)(184); // ё
if (ch > 127 && ch < 144) return (uint8_t)(ch + 112);
}
case 0xC2: {
SKIPREST = false;
return (uint8_t)ch;
}
case 0xC3: {
SKIPREST = false;
return (uint8_t)(ch | 0xC0);
}
// map UTF-8 cyrillic chars to it Windows-1251 (CP-1251) ASCII codes
// note: in this case we must use compatible font - provided ArialMT_Plain_10/16/24 by 'ThingPulse/esp8266-oled-ssd1306' library
// have empty chars for non-latin ASCII symbols
case 0xD0: {
SKIPREST = false;
if (ch == 129) return (uint8_t)(168); // Ё
if (ch > 143 && ch < 192) return (uint8_t)(ch + 48);
break;
}
case 0xD1: {
SKIPREST = false;
if (ch == 145) return (uint8_t)(184); // ё
if (ch > 127 && ch < 144) return (uint8_t)(ch + 112);
break;
}
}
// We want to strip out prefix chars for two-byte char formats

View File

@@ -22,13 +22,23 @@ void TFTDisplay::display(void)
{
concurrency::LockGuard g(spiLock);
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint16_t y = 0; y < displayHeight; y++) {
for (uint16_t x = 0; x < displayWidth; x++) {
uint16_t x,y;
for (y = 0; y < displayHeight; y++) {
for (x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7));
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7));
if (isset != dblbuf_isset) {
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
}
}
}
// Copy the Buffer to the Back Buffer
for (y = 0; y < (displayHeight / 8); y++) {
for (x = 0; x < displayWidth; x++) {
uint16_t pos = x + y * displayWidth;
buffer_back[pos] = buffer[pos];
}
}
}

View File

@@ -1,9 +1,13 @@
#pragma once
#include "Observer.h"
#define ANYKEY 0xFF
#define MATRIXKEY 0xFE
typedef struct _InputEvent {
const char* source;
char inputEvent;
char kbchar;
} InputEvent;
class InputBroker :
public Observable<const InputEvent *>

View File

@@ -16,6 +16,5 @@ void CardKbI2cImpl::init()
return;
}
DEBUG_MSG("registerSource\n");
inputBroker->registerSource(this);
}

View File

@@ -1,20 +0,0 @@
#include "facesKbI2cImpl.h"
#include "InputBroker.h"
FacesKbI2cImpl *facesKbI2cImpl;
FacesKbI2cImpl::FacesKbI2cImpl() :
KbI2cBase("facesKB")
{
}
void FacesKbI2cImpl::init()
{
if (faceskb_found != FACESKB_ADDR)
{
// Input device is not detected.
return;
}
inputBroker->registerSource(this);
}

View File

@@ -1,20 +0,0 @@
#pragma once
#include "kbI2cBase.h"
#include "main.h"
/**
* @brief The idea behind this class to have static methods for the event handlers.
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
* Technically you can have as many rotary encoders hardver attached
* to your device as you wish, but you always need to have separate event
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
*/
class FacesKbI2cImpl :
public KbI2cBase
{
public:
FacesKbI2cImpl();
void init();
};
extern FacesKbI2cImpl *facesKbI2cImpl;

View File

@@ -3,49 +3,113 @@
#include <Wire.h>
extern uint8_t cardkb_found;
extern uint8_t kb_model;
KbI2cBase::KbI2cBase(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;
}
uint8_t read_from_14004(uint8_t reg, uint8_t *data, uint8_t length)
{
uint8_t readflag = 0;
Wire.beginTransmission(CARDKB_ADDR);
Wire.write(reg);
Wire.endTransmission(); // stop transmitting
delay(20);
Wire.requestFrom(CARDKB_ADDR, (int)length);
int i = 0;
while ( Wire.available() ) // slave may send less than requested
{
data[i++] = Wire.read(); // receive a byte as a proper uint8_t
readflag = 1;
}
return readflag;
}
void write_to_14004(uint8_t reg, uint8_t data)
{
Wire.beginTransmission(CARDKB_ADDR);
Wire.write(reg);
Wire.write(data);
Wire.endTransmission(); // stop transmitting
}
int32_t KbI2cBase::runOnce()
{
InputEvent e;
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
Wire.requestFrom(CARDKB_ADDR, 1);
while (Wire.available()) {
char c = Wire.read();
switch (c) {
case 0x1b: // ESC
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
case 0x08: // Back
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
break;
case 0xb5: // Up
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_UP;
break;
case 0xb6: // Down
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
break;
case 0xb4: // Left
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
break;
case 0xb7: // Right
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
break;
case 0x0d: // Enter
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
}
if (cardkb_found != CARDKB_ADDR){
// Input device is not detected.
return INT32_MAX;
}
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
this->notifyObservers(&e);
if (kb_model == 0x02) {
// RAK14004
uint8_t rDataBuf[8] = {0};
uint8_t PrintDataBuf = 0;
if (read_from_14004(0x01, rDataBuf, 0x04) == 1) {
for (uint8_t aCount = 0; aCount < 0x04; aCount++) {
for (uint8_t bCount = 0; bCount < 0x04; bCount++ ) {
if (((rDataBuf[aCount] >> bCount) & 0x01) == 0x01) {
PrintDataBuf = aCount * 0x04 + bCount + 1;
}
}
}
}
if (PrintDataBuf != 0) {
DEBUG_MSG("RAK14004 key 0x%x pressed\n", PrintDataBuf);
InputEvent e;
e.inputEvent = MATRIXKEY;
e.source = this->_originName;
e.kbchar = PrintDataBuf;
this->notifyObservers(&e);
}
} else {
// m5 cardkb
Wire.requestFrom(CARDKB_ADDR, 1);
while (Wire.available()) {
char c = Wire.read();
InputEvent e;
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
switch (c) {
case 0x1b: // ESC
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
case 0x08: // Back
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = c;
break;
case 0xb5: // Up
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_UP;
break;
case 0xb6: // Down
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
break;
case 0xb4: // Left
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = c;
break;
case 0xb7: // Right
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = c;
break;
case 0x0d: // Enter
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
case 0x00: //nopress
e.inputEvent = ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
default: // all other keys
e.inputEvent = ANYKEY;
e.kbchar = c;
break;
}
if (e.inputEvent != ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
this->notifyObservers(&e);
}
}
}
return 500;
}

View File

@@ -36,7 +36,7 @@
#include "nimble/NimbleBluetooth.h"
#endif
#if HAS_WIFI
#if HAS_WIFI || defined(ARCH_PORTDUINO)
#include "mesh/wifi/WiFiServerAPI.h"
#include "mqtt/MQTT.h"
#endif
@@ -45,6 +45,10 @@
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "SX1281Interface.h"
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h"
#endif
#if HAS_BUTTON
#include "ButtonThread.h"
@@ -74,12 +78,17 @@ uint8_t cardkb_found;
// 0x02 for RAK14004 and 0x00 for cardkb
uint8_t kb_model;
// The I2C address of the Faces Keyboard (if found)
uint8_t faceskb_found;
// The I2C address of the RTC Module (if found)
uint8_t rtc_found;
bool rIf_wide_lora = false;
// Keystore Chips
uint8_t keystore_found;
#ifndef ARCH_PORTDUINO
ATECCX08A atecc;
#endif
bool eink_found = true;
uint32_t serialSinceMsec;
@@ -87,7 +96,7 @@ uint32_t serialSinceMsec;
bool pmu_found;
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_LPS22+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
@@ -157,9 +166,7 @@ void setup()
#endif
#ifdef DEBUG_PORT
if (!config.has_device || config.device.serial_enabled) {
consoleInit(); // Set serial baud rate and init our mesh console
}
#endif
serialSinceMsec = millis();
@@ -216,6 +223,10 @@ void setup()
// router = new DSRRouter();
router = new ReliableRouter();
#ifdef I2C_SDA1
Wire1.begin(I2C_SDA1, I2C_SCL1);
#endif
#ifdef I2C_SDA
Wire.begin(I2C_SDA, I2C_SCL);
#elif HAS_WIRE
@@ -231,6 +242,7 @@ void setup()
delay(1);
#endif
// We need to scan here to decide if we have a screen for nodeDB.init()
scanI2Cdevice();
#ifdef RAK4630
// scanEInkDevice();
@@ -271,6 +283,12 @@ void setup()
powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
/*
* Repeat the scanning for I2C devices after power initialization or look for 'latecomers'.
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
*/
scanI2Cdevice();
// Init our SPI controller (must be before screen and lora)
initSPI();
#ifndef ARCH_ESP32
@@ -324,7 +342,7 @@ void setup()
DEBUG_MSG("GPS FactoryReset requested\n");
if (gps->factoryReset()) { // If we don't succeed try again next time
devicestate.did_gps_reset = true;
nodeDB.saveToDisk();
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
}
}
@@ -349,6 +367,20 @@ void setup()
}
#endif
#if defined(USE_SX1281) && !defined(ARCH_PORTDUINO)
if (!rIf) {
rIf = new SX1281Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find SX1281 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("SX1281 Radio init succeeded, using SX1281 radio\n");
rIf_wide_lora = true;
}
}
#endif
#if defined(USE_SX1262)
if (!rIf) {
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
@@ -388,7 +420,7 @@ void setup()
}
#endif
#if !HAS_RADIO
#ifdef ARCH_PORTDUINO
if (!rIf) {
rIf = new SimRadio;
if (!rIf->init()) {
@@ -414,7 +446,7 @@ void setup()
#endif
#ifdef ARCH_PORTDUINO
initApiServer();
initApiServer(TCPPort);
#endif
// Start airtime logger thread.

View File

@@ -6,20 +6,30 @@
#include "PowerStatus.h"
#include "graphics/Screen.h"
#include "mesh/generated/telemetry.pb.h"
#ifndef ARCH_PORTDUINO
#include <SparkFun_ATECCX08a_Arduino_Library.h>
#endif
extern uint8_t screen_found;
extern uint8_t screen_model;
extern uint8_t cardkb_found;
extern uint8_t kb_model;
extern uint8_t faceskb_found;
extern uint8_t rtc_found;
extern uint8_t keystore_found;
extern bool rIf_wide_lora;
extern bool eink_found;
extern bool pmu_found;
extern bool isCharging;
extern bool isUSBPowered;
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_LPS22+1];
#ifndef ARCH_PORTDUINO
extern ATECCX08A atecc;
#endif
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
extern int TCPPort; // set by Portduino
// Global Screen singleton.
extern graphics::Screen *screen;

View File

@@ -62,13 +62,6 @@ Channel &Channels::fixupChannel(ChannelIndex chIndex)
// Convert the old string "Default" to our new short representation
if (strcmp(channelSettings.name, "Default") == 0)
*channelSettings.name = '\0';
/* Convert any old usage of the defaultpsk into our new short representation.
if (channelSettings.psk.size == sizeof(defaultpsk) &&
memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) {
*channelSettings.psk.bytes = 1;
channelSettings.psk.size = 1;
} */
}
hashes[chIndex] = generateHash(chIndex);
@@ -124,7 +117,22 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
DEBUG_MSG("Expanding short PSK #%d\n", pskIndex);
if (pskIndex == 0)
k.length = 0; // Turn off encryption
else {
else if (oemStore.oem_aes_key.size > 1) {
// Use the OEM key
DEBUG_MSG("Using OEM Key with %d bytes\n", oemStore.oem_aes_key.size);
memcpy(k.bytes, oemStore.oem_aes_key.bytes , oemStore.oem_aes_key.size);
k.length = oemStore.oem_aes_key.size;
// Bump up the last byte of PSK as needed
uint8_t *last = k.bytes + oemStore.oem_aes_key.size - 1;
*last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK
if (k.length < 16) {
DEBUG_MSG("Warning: OEM provided a too short AES128 key - padding\n");
k.length = 16;
} else if (k.length < 32 && k.length != 16) {
DEBUG_MSG("Warning: OEM provided a too short AES256 key - padding\n");
k.length = 32;
}
} else {
memcpy(k.bytes, defaultpsk, sizeof(defaultpsk));
k.length = sizeof(defaultpsk);
// Bump up the last byte of PSK as needed

View File

@@ -1,7 +1,13 @@
#include "SX126xInterface.h"
#include "SX126xInterface.cpp"
#include "SX128xInterface.h"
#include "SX128xInterface.cpp"
// We need this declaration for proper linking in derived classes
template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;
template class SX126xInterface<LLCC68>;
#if !defined(ARCH_PORTDUINO)
template class SX128xInterface<SX1281>;
#endif

View File

@@ -112,7 +112,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
!ch ||
strlen(ch->settings.name) > 0 ||
strcmp(ch->settings.name, pi.boundChannel);
(strcasecmp(ch->settings.name, pi.boundChannel) == 0);
if (!rxChannelOk) {
// no one should have already replied!

View File

@@ -15,6 +15,7 @@ struct RegionInfo {
uint8_t powerLimit; // Or zero for not set
bool audioPermitted;
bool freqSwitching;
bool wideLora;
const char *name; // EU433 etc
};

View File

@@ -90,7 +90,7 @@ void MeshService::loop()
}
/// The radioConfig object just changed, call this to force the hw to change to the new settings
bool MeshService::reloadConfig()
bool MeshService::reloadConfig(int saveWhat)
{
// If we can successfully set this radio to these settings, save them to disk
@@ -98,7 +98,7 @@ bool MeshService::reloadConfig()
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
nodeDB.saveToDisk();
nodeDB.saveToDisk(saveWhat);
return didReset;
}
@@ -113,7 +113,7 @@ void MeshService::reloadOwner()
// update everyone else
if (nodeInfoModule)
nodeInfoModule->sendOurNodeInfo();
nodeDB.saveToDisk();
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
}
/**
@@ -123,6 +123,29 @@ void MeshService::reloadOwner()
*/
void MeshService::handleToRadio(MeshPacket &p)
{
#ifdef ARCH_PORTDUINO
// Simulates device is receiving a packet via the LoRa chip
if (p.decoded.portnum == PortNum_SIMULATOR_APP) {
// Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first
Compressed scratch;
Compressed *decoded = NULL;
if (p.which_payload_variant == MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
p.decoded.payload.size = pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &Compressed_msg, &scratch);
if (p.decoded.payload.size) {
decoded = &scratch;
// Extract the original payload and replace
memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data));
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
p.decoded.portnum = decoded->portnum;
} else
DEBUG_MSG("Error decoding protobuf for simulator message!\n");
}
// Let SimRadio receive as if it did via its LoRa chip
SimRadio::instance->startReceive(&p);
return;
}
#endif
if (p.from != 0) { // We don't let phones assign nodenums to their sent messages
DEBUG_MSG("Warning: phone tried to pick a nodenum, we don't allow that.\n");
p.from = 0;
@@ -260,3 +283,8 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
return 0;
}
bool MeshService::isToPhoneQueueEmpty()
{
return toPhoneQueue.isEmpty();
}

View File

@@ -10,6 +10,9 @@
#include "MeshTypes.h"
#include "Observer.h"
#include "PointerQueue.h"
#ifdef ARCH_PORTDUINO
#include "../platform/portduino/SimRadio.h"
#endif
/**
* Top level app for this service. keeps the mesh, the radio config and the queue of received packets.
@@ -63,7 +66,7 @@ class MeshService
/** The radioConfig object just changed, call this to force the hw to change to the new settings
* @return true if client devices should be sent a new set of radio configs
*/
bool reloadConfig();
bool reloadConfig(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void reloadOwner();
@@ -86,6 +89,8 @@ class MeshService
/// Send a packet to the phone
void sendToPhone(MeshPacket *p);
bool isToPhoneQueueEmpty();
private:
/// Called when our gps position has changed - updates nodedb and sends Location message out into the mesh
/// returns 0 to allow futher processing

View File

@@ -16,6 +16,7 @@
#include "mesh-pb-constants.h"
#include <pb_decode.h>
#include <pb_encode.h>
#include <ErriezCRC32.h>
#ifdef ARCH_ESP32
#include "mesh/http/WiFiAPClient.h"
@@ -37,6 +38,7 @@ MyNodeInfo &myNodeInfo = devicestate.my_node;
LocalConfig config;
LocalModuleConfig moduleConfig;
ChannelFile channelFile;
OEMStore oemStore;
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
* might have changed is incremented. Allows others to detect they might now be on a new channel.
@@ -128,7 +130,9 @@ bool NodeDB::factoryReset()
// second, install default state (this will deal with the duplicate mac address issue)
installDefaultDeviceState();
installDefaultConfig();
// third, write to disk
installDefaultModuleConfig();
installDefaultChannels();
// third, write everything to disk
saveToDisk();
#ifdef ARCH_ESP32
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
@@ -225,13 +229,20 @@ void NodeDB::installDefaultChannels()
channelFile.version = DEVICESTATE_CUR_VER;
}
void NodeDB::resetNodes()
{
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
saveDeviceStateToDisk();
}
void NodeDB::installDefaultDeviceState()
{
DEBUG_MSG("Installing default DeviceState\n");
memset(&devicestate, 0, sizeof(DeviceState));
*numNodes = 0; // Forget node DB
*numNodes = 0;
// init our devicestate with valid flags so protobuf writing/reading will work
devicestate.has_my_node = true;
devicestate.has_owner = true;
@@ -261,6 +272,12 @@ void NodeDB::init()
DEBUG_MSG("Initializing NodeDB\n");
loadFromDisk();
uint32_t devicestateCRC = crc32Buffer(&devicestate, sizeof(devicestate));
uint32_t configCRC = crc32Buffer(&config, sizeof(config));
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
int saveWhat = 0;
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
myNodeInfo.error_code = CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash)
@@ -298,7 +315,15 @@ void NodeDB::init()
resetRadioConfig(); // If bogus settings got saved, then fix them
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
saveToDisk();
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
saveWhat |= SEGMENT_DEVICESTATE;
if (configCRC != crc32Buffer(&config, sizeof(config)))
saveWhat |= SEGMENT_CONFIG;
if (channelFileCRC != crc32Buffer(&channelFile, sizeof(channelFile)))
saveWhat |= SEGMENT_CHANNELS;
saveToDisk(saveWhat);
}
// We reserve a few nodenums for future use
@@ -332,6 +357,8 @@ static const char *prefFileName = "/prefs/db.proto";
static const char *configFileName = "/prefs/config.proto";
static const char *moduleConfigFileName = "/prefs/module.proto";
static const char *channelFileName = "/prefs/channels.proto";
static const char *oemConfigFile = "/oem/oem.proto";
/** Load a protobuf from a file, return true for success */
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
@@ -411,6 +438,9 @@ void NodeDB::loadFromDisk()
DEBUG_MSG("Loaded saved channelFile version %d\n", channelFile.version);
}
}
if (loadProto(oemConfigFile, OEMStore_size, sizeof(OEMStore), OEMStore_fields, &oemStore))
DEBUG_MSG("Loaded OEMStore\n");
}
/** Save a protobuf from a file, return true for success */
@@ -431,7 +461,6 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
} else {
okay = true;
}
f.close();
// brief window of risk here ;-)
@@ -454,7 +483,7 @@ void NodeDB::saveChannelsToDisk()
#ifdef FSCom
FSCom.mkdir("/prefs");
#endif
saveProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile);
saveProto(channelFileName, ChannelFile_size, sizeof(channelFile), ChannelFile_fields, &channelFile);
}
}
@@ -468,34 +497,41 @@ void NodeDB::saveDeviceStateToDisk()
}
}
void NodeDB::saveToDisk()
void NodeDB::saveToDisk(int saveWhat)
{
if (!devicestate.no_save) {
#ifdef FSCom
FSCom.mkdir("/prefs");
#endif
saveProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
if (saveWhat & SEGMENT_DEVICESTATE) {
saveDeviceStateToDisk();
}
// save all config segments
config.has_device = true;
config.has_display = true;
config.has_lora = true;
config.has_position = true;
config.has_power = true;
config.has_network = true;
config.has_bluetooth = true;
saveProto(configFileName, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config);
if (saveWhat & SEGMENT_CONFIG) {
config.has_device = true;
config.has_display = true;
config.has_lora = true;
config.has_position = true;
config.has_power = true;
config.has_network = true;
config.has_bluetooth = true;
saveProto(configFileName, LocalConfig_size, sizeof(config), LocalConfig_fields, &config);
}
moduleConfig.has_canned_message = true;
moduleConfig.has_external_notification = true;
moduleConfig.has_mqtt = true;
moduleConfig.has_range_test = true;
moduleConfig.has_serial = true;
moduleConfig.has_store_forward = true;
moduleConfig.has_telemetry = true;
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig);
if (saveWhat & SEGMENT_MODULECONFIG) {
moduleConfig.has_canned_message = true;
moduleConfig.has_external_notification = true;
moduleConfig.has_mqtt = true;
moduleConfig.has_range_test = true;
moduleConfig.has_serial = true;
moduleConfig.has_store_forward = true;
moduleConfig.has_telemetry = true;
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(moduleConfig), LocalModuleConfig_fields, &moduleConfig);
}
saveChannelsToDisk();
if (saveWhat & SEGMENT_CHANNELS) {
saveChannelsToDisk();
}
} else {
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
}
@@ -671,11 +707,23 @@ NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
if (!info) {
if (*numNodes >= MAX_NUM_NODES) {
screen->print("error: node_db full!\n");
DEBUG_MSG("ERROR! could not create new node, node_db is full! (%d nodes)", *numNodes);
return NULL;
screen->print("warning: node_db full! erasing oldest entry\n");
// look for oldest node and erase it
uint32_t oldest = UINT32_MAX;
int oldestIndex = -1;
for (int i = 0; i < *numNodes; i++) {
if (nodes[i].last_heard < oldest) {
oldest = nodes[i].last_heard;
oldestIndex = i;
}
}
// Shove the remaining nodes down the chain
for (int i = oldestIndex; i < *numNodes - 1; i++) {
nodes[i] = nodes[i + 1];
}
(*numNodes)--;
}
// add the node
// add the node at the end
info = &nodes[(*numNodes)++];
// everything is missing except the nodenum

View File

@@ -13,7 +13,12 @@ DeviceState versions used to be defined in the .proto file but really only this
#define here.
*/
#define DEVICESTATE_CUR_VER 18
#define SEGMENT_CONFIG 1
#define SEGMENT_MODULECONFIG 2
#define SEGMENT_DEVICESTATE 4
#define SEGMENT_CHANNELS 8
#define DEVICESTATE_CUR_VER 19
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
extern DeviceState devicestate;
@@ -21,6 +26,7 @@ extern ChannelFile channelFile;
extern MyNodeInfo &myNodeInfo;
extern LocalConfig config;
extern LocalModuleConfig moduleConfig;
extern OEMStore oemStore;
extern User &owner;
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
@@ -52,7 +58,7 @@ class NodeDB
void init();
/// write to flash
void saveToDisk(), saveChannelsToDisk(), saveDeviceStateToDisk();
void saveToDisk(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS), saveChannelsToDisk(), saveDeviceStateToDisk();
/** Reinit radio config if needed, because either:
* a) sometimes a buggy android app might send us bogus settings or
@@ -115,7 +121,7 @@ class NodeDB
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
size_t getNumOnlineNodes();
void initConfigIntervals(), initModuleConfigIntervals();
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes();
bool factoryReset();
@@ -205,4 +211,4 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
*/
extern uint32_t radioGeneration;
#define Module_Config_size (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
#define Module_Config_size (ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + ModuleConfig_TelemetryConfig_size + ModuleConfig_size)

View File

@@ -79,17 +79,17 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
memset(&toRadioScratch, 0, sizeof(toRadioScratch));
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
switch (toRadioScratch.which_payload_variant) {
case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet);
case ToRadio_want_config_id_tag:
config_nonce = toRadioScratch.want_config_id;
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
handleStartConfig();
break;
case ToRadio_disconnect_tag:
DEBUG_MSG("Disconnecting from phone\n");
close();
break;
case ToRadio_packet_tag:
return handleToRadioPacket(toRadioScratch.packet);
case ToRadio_want_config_id_tag:
config_nonce = toRadioScratch.want_config_id;
DEBUG_MSG("Client wants config, nonce=%u\n", config_nonce);
handleStartConfig();
break;
case ToRadio_disconnect_tag:
DEBUG_MSG("Disconnecting from phone\n");
close();
break;
default:
// Ignore nop messages
// DEBUG_MSG("Error: unexpected ToRadio variant\n");
@@ -109,15 +109,17 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*
* Our sending states progress in the following sequence (the client app ASSUMES THIS SEQUENCE, DO NOT CHANGE IT):
* STATE_SEND_MY_INFO, // send our my info record
* STATE_SEND_CHANNELS
* STATE_SEND_NODEINFO, // states progress in this order as the device sends to the client
STATE_SEND_CONFIG,
STATE_SEND_MODULE_CONFIG,
STATE_SEND_COMPLETE_ID,
STATE_SEND_PACKETS // send packets or debug strings
*/
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available()) {
DEBUG_MSG("getFromRadio=not available\n");
// DEBUG_MSG("getFromRadio=not available\n");
return 0;
}
// In case we send a FromRadio packet
@@ -128,7 +130,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
case STATE_SEND_NOTHING:
DEBUG_MSG("getFromRadio=STATE_SEND_NOTHING\n");
break;
case STATE_SEND_MY_INFO:
DEBUG_MSG("getFromRadio=STATE_SEND_MY_INFO\n");
// If the user has specified they don't want our node to share its location, make sure to tell the phone
@@ -154,51 +156,63 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
// Stay in current state until done sending nodeinfos
} else {
DEBUG_MSG("Done sending nodeinfos\n");
state = STATE_SEND_CONFIG;
state = STATE_SEND_CHANNELS;
// Go ahead and send that ID right now
return getFromRadio(buf);
}
break;
}
case STATE_SEND_CHANNELS:
DEBUG_MSG("getFromRadio=STATE_SEND_CHANNELS\n");
fromRadioScratch.which_payload_variant = FromRadio_channel_tag;
fromRadioScratch.channel = channels.getByIndex(config_state);
config_state++;
// Advance when we have sent all of our Channels
if (config_state >= MAX_NUM_CHANNELS) {
state = STATE_SEND_CONFIG;
config_state = Config_device_tag;
}
break;
case STATE_SEND_CONFIG:
DEBUG_MSG("getFromRadio=STATE_SEND_CONFIG\n");
fromRadioScratch.which_payload_variant = FromRadio_config_tag;
switch (config_state) {
case Config_device_tag:
fromRadioScratch.config.which_payload_variant = Config_device_tag;
fromRadioScratch.config.payload_variant.device = config.device;
break;
case Config_position_tag:
fromRadioScratch.config.which_payload_variant = Config_position_tag;
fromRadioScratch.config.payload_variant.position = config.position;
break;
case Config_power_tag:
fromRadioScratch.config.which_payload_variant = Config_power_tag;
fromRadioScratch.config.payload_variant.power = config.power;
fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs;
break;
case Config_network_tag:
fromRadioScratch.config.which_payload_variant = Config_network_tag;
fromRadioScratch.config.payload_variant.network = config.network;
break;
case Config_display_tag:
fromRadioScratch.config.which_payload_variant = Config_display_tag;
fromRadioScratch.config.payload_variant.display = config.display;
break;
case Config_lora_tag:
fromRadioScratch.config.which_payload_variant = Config_lora_tag;
fromRadioScratch.config.payload_variant.lora = config.lora;
break;
case Config_bluetooth_tag:
fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag;
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
break;
case Config_device_tag:
fromRadioScratch.config.which_payload_variant = Config_device_tag;
fromRadioScratch.config.payload_variant.device = config.device;
break;
case Config_position_tag:
fromRadioScratch.config.which_payload_variant = Config_position_tag;
fromRadioScratch.config.payload_variant.position = config.position;
break;
case Config_power_tag:
fromRadioScratch.config.which_payload_variant = Config_power_tag;
fromRadioScratch.config.payload_variant.power = config.power;
fromRadioScratch.config.payload_variant.power.ls_secs = default_ls_secs;
break;
case Config_network_tag:
fromRadioScratch.config.which_payload_variant = Config_network_tag;
fromRadioScratch.config.payload_variant.network = config.network;
break;
case Config_display_tag:
fromRadioScratch.config.which_payload_variant = Config_display_tag;
fromRadioScratch.config.payload_variant.display = config.display;
break;
case Config_lora_tag:
fromRadioScratch.config.which_payload_variant = Config_lora_tag;
fromRadioScratch.config.payload_variant.lora = config.lora;
break;
case Config_bluetooth_tag:
fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag;
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
break;
}
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
// using to the app (so that even old phone apps work with new device loads).
config_state++;
// Advance when we have sent all of our config objects
if (config_state > Config_bluetooth_tag) {
@@ -211,37 +225,37 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
DEBUG_MSG("getFromRadio=STATE_SEND_MODULECONFIG\n");
fromRadioScratch.which_payload_variant = FromRadio_moduleConfig_tag;
switch (config_state) {
case ModuleConfig_mqtt_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_mqtt_tag;
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
break;
case ModuleConfig_serial_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_serial_tag;
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
break;
case ModuleConfig_external_notification_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_external_notification_tag;
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
break;
case ModuleConfig_range_test_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_range_test_tag;
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
break;
case ModuleConfig_telemetry_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_telemetry_tag;
fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry;
break;
case ModuleConfig_canned_message_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag;
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
break;
case ModuleConfig_mqtt_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_mqtt_tag;
fromRadioScratch.moduleConfig.payload_variant.mqtt = moduleConfig.mqtt;
break;
case ModuleConfig_serial_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_serial_tag;
fromRadioScratch.moduleConfig.payload_variant.serial = moduleConfig.serial;
break;
case ModuleConfig_external_notification_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_external_notification_tag;
fromRadioScratch.moduleConfig.payload_variant.external_notification = moduleConfig.external_notification;
break;
case ModuleConfig_range_test_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_range_test_tag;
fromRadioScratch.moduleConfig.payload_variant.range_test = moduleConfig.range_test;
break;
case ModuleConfig_telemetry_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_telemetry_tag;
fromRadioScratch.moduleConfig.payload_variant.telemetry = moduleConfig.telemetry;
break;
case ModuleConfig_canned_message_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag;
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
break;
}
config_state++;
// Advance when we have sent all of our ModuleConfig objects
if (config_state > ModuleConfig_canned_message_tag) {
state = STATE_SEND_COMPLETE_ID;
config_state = Config_device_tag;
config_state = 0;
}
break;
@@ -274,7 +288,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
if (fromRadioScratch.which_payload_variant != 0) {
// Encapsulate as a FromRadio packet
size_t numbytes = pb_encode_to_bytes(buf, FromRadio_size, FromRadio_fields, &fromRadioScratch);
// DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payloadVariant, numbytes);
DEBUG_MSG("encoding toPhone packet to phone variant=%d, %d bytes\n", fromRadioScratch.which_payload_variant, numbytes);
return numbytes;
}
@@ -282,7 +297,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
return 0;
}
void PhoneAPI::handleDisconnect()
void PhoneAPI::handleDisconnect()
{
DEBUG_MSG("PhoneAPI disconnect\n");
}
@@ -301,26 +316,25 @@ void PhoneAPI::releasePhonePacket()
bool PhoneAPI::available()
{
switch (state) {
case STATE_SEND_NOTHING:
return false;
case STATE_SEND_MY_INFO:
return true;
case STATE_SEND_CONFIG:
return true;
case STATE_SEND_MODULECONFIG:
return true;
case STATE_SEND_NODEINFO:
if (!nodeInfoForPhone)
nodeInfoForPhone = nodeDB.readNextInfo();
return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_COMPLETE_ID:
return true;
case STATE_SEND_PACKETS: {
if (!packetForPhone)
packetForPhone = service.getForPhone();
bool hasPacket = !!packetForPhone;
DEBUG_MSG("available hasPacket=%d\n", hasPacket);
return hasPacket;
case STATE_SEND_NOTHING:
return false;
case STATE_SEND_MY_INFO:
case STATE_SEND_CHANNELS:
case STATE_SEND_CONFIG:
case STATE_SEND_MODULECONFIG:
case STATE_SEND_COMPLETE_ID:
return true;
case STATE_SEND_NODEINFO:
if (!nodeInfoForPhone)
nodeInfoForPhone = nodeDB.readNextInfo();
return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_PACKETS: {
if (!packetForPhone)
packetForPhone = service.getForPhone();
bool hasPacket = !!packetForPhone;
// DEBUG_MSG("available hasPacket=%d\n", hasPacket);
return hasPacket;
}
default:
assert(0); // unexpected state - FIXME, make an error code and reboot

View File

@@ -16,13 +16,13 @@
* Eventually there should be once instance of this class for each live connection (because it has a bit of state
* for that connection)
*/
class PhoneAPI
: public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
class PhoneAPI : public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
{
enum State {
STATE_SEND_NOTHING, // Initial state, don't send anything until the client starts asking for config
STATE_SEND_MY_INFO, // send our my info record
STATE_SEND_NODEINFO, // states progress in this order as the device sends to to the client
STATE_SEND_CHANNELS, // Send all channels
STATE_SEND_CONFIG, // Replacement for the old Radioconfig
STATE_SEND_MODULECONFIG, // Send Module specific config
STATE_SEND_COMPLETE_ID,
@@ -31,7 +31,7 @@ class PhoneAPI
State state = STATE_SEND_NOTHING;
int8_t config_state = Config_device_tag;
uint8_t config_state = 0;
/**
* Each packet sent to the phone has an incrementing count

View File

@@ -6,15 +6,16 @@
#include "Router.h"
#include "assert.h"
#include "configuration.h"
#include "main.h"
#include "sleep.h"
#include <assert.h>
#include <pb_decode.h>
#include <pb_encode.h>
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching) \
#define RDEF(name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, frequency_switching, wide_lora) \
{ \
Config_LoRaConfig_RegionCode_##name, freq_start, freq_end, duty_cycle, spacing, power_limit, audio_permitted, \
frequency_switching, #name \
frequency_switching, wide_lora, #name \
}
const RegionInfo regions[] = {
@@ -22,12 +23,12 @@ const RegionInfo regions[] = {
https://link.springer.com/content/pdf/bbm%3A978-1-4842-4357-2%2F1.pdf
https://www.thethingsnetwork.org/docs/lorawan/regional-parameters/
*/
RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false),
RDEF(US, 902.0f, 928.0f, 100, 0, 30, true, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/
RDEF(EU_433, 433.0f, 434.0f, 10, 0, 12, true, false),
RDEF(EU_433, 433.0f, 434.0f, 10, 0, 12, true, false, false),
/*
https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/
@@ -43,23 +44,23 @@ const RegionInfo regions[] = {
(Please refer to section 4.21 in the following document)
https://ec.europa.eu/growth/tools-databases/tris/index.cfm/ro/search/?trisaction=search.detail&year=2021&num=528&dLang=EN
*/
RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false),
RDEF(EU_868, 869.4f, 869.65f, 10, 0, 27, false, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/
RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false),
RDEF(CN, 470.0f, 510.0f, 100, 0, 19, true, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/
RDEF(JP, 920.8f, 927.8f, 100, 0, 16, true, false),
RDEF(JP, 920.8f, 927.8f, 100, 0, 16, true, false, false),
/*
https://www.iot.org.au/wp/wp-content/uploads/2016/12/IoTSpectrumFactSheet.pdf
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
*/
RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false),
RDEF(ANZ, 915.0f, 928.0f, 100, 0, 30, true, false, false),
/*
https://digital.gov.ru/uploaded/files/prilozhenie-12-k-reshenyu-gkrch-18-46-03-1.pdf
@@ -67,38 +68,44 @@ const RegionInfo regions[] = {
Note:
- We do LBT, so 100% is allowed.
*/
RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false),
RDEF(RU, 868.7f, 869.2f, 100, 0, 20, true, false, false),
/*
???
*/
RDEF(KR, 920.0f, 923.0f, 100, 0, 0, true, false),
RDEF(KR, 920.0f, 923.0f, 100, 0, 0, true, false, false),
/*
???
*/
RDEF(TW, 920.0f, 925.0f, 100, 0, 0, true, false),
RDEF(TW, 920.0f, 925.0f, 100, 0, 0, true, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/
RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false),
RDEF(IN, 865.0f, 867.0f, 100, 0, 30, true, false, false),
/*
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752
https://iotalliance.org.nz/wp-content/uploads/sites/4/2019/05/IoT-Spectrum-in-NZ-Briefing-Paper.pdf
*/
RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, true, false),
RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 0, true, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
*/
RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false),
RDEF(TH, 920.0f, 925.0f, 100, 0, 16, true, false, false),
/*
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
*/
RDEF(LORA_24, 2400.0f, 2483.5f, 100, 0, 10, true, false, true),
/*
This needs to be last. Same as US.
*/
RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false)
RDEF(UNSET, 902.0f, 928.0f, 100, 0, 30, true, false, false)
};
@@ -354,41 +361,41 @@ void RadioInterface::applyModemConfig()
// Set up default configuration
// No Sync Words in LORA mode
Config_LoRaConfig &loraConfig = config.lora;
auto channelSettings = channels.getPrimary();
if (loraConfig.spread_factor == 0) {
switch (loraConfig.modem_preset) {
case Config_LoRaConfig_ModemPreset_SHORT_FAST:
bw = 250;
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8;
sf = 7;
break;
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
bw = 250;
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8;
sf = 8;
break;
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
bw = 250;
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8;
sf = 9;
break;
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
bw = 250;
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8;
sf = 10;
break;
case Config_LoRaConfig_ModemPreset_LONG_FAST:
bw = 250;
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
cr = 8;
sf = 11;
break;
case Config_LoRaConfig_ModemPreset_LONG_SLOW:
bw = 125;
bw = (myRegion->wideLora && rIf_wide_lora) ? 400 : 125;
cr = 8;
sf = 12;
break;
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
bw = 31.25;
bw = (myRegion->wideLora && rIf_wide_lora) ? 200 : 31.25;
cr = 8;
sf = 12;
break;
@@ -416,14 +423,14 @@ void RadioInterface::applyModemConfig()
power = 17; // Default to default power if we don't have a valid power
// Set final tx_power back onto config
loraConfig.tx_power = power;
loraConfig.tx_power = (int8_t)power; // cppcheck-suppress assignmentAddressToInteger
// Calculate the number of channels
uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000)));
// If user has manually specified a channel num, then use that, otherwise generate one by hashing the name
const char *channelName = channels.getName(channels.getPrimaryIndex());
int channel_num = channelSettings.channel_num ? channelSettings.channel_num - 1 : hash(channelName) % numChannels;
int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
// Old frequency selection formula
// float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num);
@@ -461,12 +468,6 @@ void RadioInterface::limitPower()
DEBUG_MSG("Set radio: final power level=%d\n", power);
}
ErrorCode SimRadio::send(MeshPacket *p)
{
DEBUG_MSG("SimRadio.send\n");
packetPool.release(p);
return ERRNO_OK;
}
void RadioInterface::deliverToReceiver(MeshPacket *p)
{

View File

@@ -212,11 +212,6 @@ class RadioInterface
}
};
class SimRadio : public RadioInterface
{
public:
virtual ErrorCode send(MeshPacket *p) override;
};
/// Debug printing for packets
void printPacket(const char *prefix, const MeshPacket *p);

View File

@@ -58,12 +58,12 @@ bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
* make sure wasSeenRecently _doesn't_ update
* finding the channel requires decoding the packet. */
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false)) {
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false) && !MeshModule::currentReply) {
if (perhapsDecode(p)) {
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
DEBUG_MSG("acking a repeated want_ack packet\n");
}
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE) {
} else if (wasSeenRecently(p, false) && p->hop_limit == HOP_RELIABLE && !MeshModule::currentReply && p->to != nodeDB.getNodeNum()) {
// retransmission on broadcast has hop_limit still equal to HOP_RELIABLE
DEBUG_MSG("Resending implicit ack for a repeated floodmsg\n");
MeshPacket *tosend = packetPool.allocCopy(*p);
@@ -94,7 +94,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
// - not DSR routing)
if (p->want_ack) {
if (MeshModule::currentReply)
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack\n");
DEBUG_MSG("Some other module has replied to this message, no need for a 2nd ack\n");
else
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
}

View File

@@ -0,0 +1,13 @@
#include "configuration.h"
#include "SX1281Interface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
SX1281Interface::SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: SX128xInterface(cs, irq, rst, busy, spi)
{
}
#endif

View File

@@ -0,0 +1,17 @@
#pragma once
#include "SX128xInterface.h"
/**
* Our adapter for SX1281 radios
*/
#if !defined(ARCH_PORTDUINO)
class SX1281Interface : public SX128xInterface<SX1281>
{
public:
SX1281Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
};
#endif

View File

@@ -0,0 +1,247 @@
#include "configuration.h"
#include "SX128xInterface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 22
#endif
template<typename T>
SX128xInterface<T>::SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
{
}
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
template<typename T>
bool SX128xInterface<T>::init()
{
#ifdef SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, HIGH);
pinMode(SX128X_POWER_EN, OUTPUT);
#endif
#ifdef SX128X_RXEN // set not rx or tx mode
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
pinMode(SX128X_RXEN, OUTPUT);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
pinMode(SX128X_TXEN, OUTPUT);
#endif
RadioLibInterface::init();
if (power == 0)
power = SX128X_MAX_POWER;
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
limitPower();
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
// \todo Display actual typename of the adapter, not just `SX128x`
DEBUG_MSG("SX128x init result %d\n", res);
DEBUG_MSG("Frequency set to %f\n", getFreq());
DEBUG_MSG("Bandwidth set to %f\n", bw);
DEBUG_MSG("Power output set to %d\n", power);
#ifdef SX128X_TXEN
// lora.begin sets Dio2 as RF switch control, which is not true if we are manually controlling RX and TX
if (res == RADIOLIB_ERR_NONE)
res = lora.setDio2AsRfSwitch(true);
#endif
if (res == RADIOLIB_ERR_NONE)
res = lora.setCRC(RADIOLIB_SX128X_LORA_CRC_ON);
if (res == RADIOLIB_ERR_NONE)
startReceive(); // start receiving
return res == RADIOLIB_ERR_NONE;
}
template<typename T>
bool SX128xInterface<T>::reconfigure()
{
RadioLibInterface::reconfigure();
// set mode to standby
setStandby();
// configure publicly accessible settings
int err = lora.setSpreadingFactor(sf);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
err = lora.setBandwidth(bw);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
err = lora.setCodingRate(cr);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
// Hmm - seems to lower SNR when the signal levels are high. Leaving off for now...
// TODO: Confirm gain registers are okay now
// err = lora.setRxGain(true);
// assert(err == RADIOLIB_ERR_NONE);
err = lora.setSyncWord(syncWord);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setPreambleLength(preambleLength);
assert(err == RADIOLIB_ERR_NONE);
err = lora.setFrequency(getFreq());
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
if (power > 22) // This chip has lower power limits than some
power = 22;
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
startReceive(); // restart receiving
return RADIOLIB_ERR_NONE;
}
template<typename T>
void INTERRUPT_ATTR SX128xInterface<T>::disableInterrupt()
{
lora.clearDio1Action();
}
template<typename T>
void SX128xInterface<T>::setStandby()
{
checkNotification(); // handle any pending interrupts before we force standby
int err = lora.standby();
assert(err == RADIOLIB_ERR_NONE);
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX128X_RXEN, LOW);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
#endif
isReceiving = false; // If we were receiving, not any more
disableInterrupt();
completeSending(); // If we were sending, not anymore
}
/**
* Add SNR data to received messages
*/
template<typename T>
void SX128xInterface<T>::addReceiveMetadata(MeshPacket *mp)
{
// DEBUG_MSG("PacketStatus %x\n", lora.getPacketStatus());
mp->rx_snr = lora.getSNR();
mp->rx_rssi = lround(lora.getRSSI());
}
/** We override to turn on transmitter power as needed.
*/
template<typename T>
void SX128xInterface<T>::configHardwareForSend()
{
#ifdef SX128X_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX128X_TXEN, HIGH);
#endif
#ifdef SX128X_RXEN
digitalWrite(SX128X_RXEN, LOW);
#endif
RadioLibInterface::configHardwareForSend();
}
// For power draw measurements, helpful to force radio to stay sleeping
// #define SLEEP_ONLY
template<typename T>
void SX128xInterface<T>::startReceive()
{
#ifdef SLEEP_ONLY
sleep();
#else
setStandby();
#ifdef SX128X_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX128X_RXEN, HIGH);
#endif
#ifdef SX128X_TXEN
digitalWrite(SX128X_TXEN, LOW);
#endif
int err = lora.startReceive();
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);
#endif
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
template<typename T>
bool SX128xInterface<T>::isChannelActive()
{
// check if we can detect a LoRa preamble on the current channel
int16_t result;
setStandby();
result = lora.scanChannel();
if (result == RADIOLIB_PREAMBLE_DETECTED)
return true;
assert(result != RADIOLIB_ERR_WRONG_MODEM);
return false;
}
/** Could we send right now (i.e. either not actively receving or transmitting)? */
template<typename T>
bool SX128xInterface<T>::isActivelyReceiving()
{
return isChannelActive();
}
template<typename T>
bool SX128xInterface<T>::sleep()
{
// Not keeping config is busted - next time nrf52 board boots lora sending fails tcxo related? - see datasheet
// \todo Display actual typename of the adapter, not just `SX128x`
DEBUG_MSG("SX128x entering sleep mode (FIXME, don't keep config)\n");
setStandby(); // Stop any pending operations
// turn off TCXO if it was powered
// FIXME - this isn't correct
// lora.setTCXO(0);
// put chipset into sleep mode (we've already disabled interrupts by now)
bool keepConfig = true;
lora.sleep(keepConfig); // Note: we do not keep the config, full reinit will be needed
#ifdef SX128X_POWER_EN
digitalWrite(SX128X_POWER_EN, LOW);
#endif
return true;
}
#endif

View File

@@ -0,0 +1,75 @@
#pragma once
#if !defined(ARCH_PORTDUINO)
#include "RadioLibInterface.h"
/**
* \brief Adapter for SX128x radio family. Implements common logic for child classes.
* \tparam T RadioLib module type for SX128x: SX1281.
*/
template<class T>
class SX128xInterface : public RadioLibInterface
{
public:
SX128xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
/// Initialise the Driver transport hardware and software.
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool init() override;
/// Apply any radio provisioning changes
/// Make sure the Driver is properly configured before calling init().
/// \return true if initialisation succeeded.
virtual bool reconfigure() override;
/// Prepare hardware for sleep. Call this _only_ for deep sleep, not needed for light sleep.
virtual bool sleep() override;
protected:
float currentLimit = 140; // Higher OCP limit for SX128x PA
/**
* Specific module instance
*/
T lora;
/**
* Glue functions called from ISR land
*/
virtual void disableInterrupt() override;
/**
* Enable a particular ISR callback glue function
*/
virtual void enableInterrupt(void (*callback)()) { lora.setDio1Action(callback); }
/** can we detect a LoRa preamble on the current channel? */
virtual bool isChannelActive() override;
/** are we actively receiving a packet (only called during receiving state) */
virtual bool isActivelyReceiving() override;
/**
* Start waiting to receive a message
*/
virtual void startReceive() override;
/**
* We override to turn on transmitter power as needed.
*/
virtual void configHardwareForSend() override;
/**
* Add SNR data to received messages
*/
virtual void addReceiveMetadata(MeshPacket *mp) override;
virtual void setStandby() override;
private:
};
#endif

View File

@@ -18,6 +18,9 @@ class SinglePortModule : public MeshModule
SinglePortModule(const char *_name, PortNum _ourPortNum) : MeshModule(_name), ourPortNum(_ourPortNum) {}
protected:
uint32_t max_channel_util_percent = 40;
uint32_t polite_channel_util_percent = 25;
/**
* @return true if you want to receive the specified portnum
*/

View File

@@ -103,10 +103,7 @@ void StreamAPI::emitTxBuffer(size_t len)
auto totalLen = len + HEADER_LEN;
stream->write(txBuf, totalLen);
/* for(size_t i = 0; i < totalLen; i++) {
stream->write(txBuf[i]);
// stream->flush();
} */
stream->flush();
}
}
@@ -133,4 +130,4 @@ void StreamAPI::onConnectionChanged(bool connected)
// received a packet in a while
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
}
}
}

View File

@@ -59,14 +59,12 @@ typedef struct _AdminMessage {
AdminMessage_ModuleConfigType get_module_config_request;
/* Send the current Config in the response to this message. */
ModuleConfig get_module_config_response;
/* Send all channels in the response to this message */
bool get_all_channel_request;
/* Get the Canned Message Module messages in the response to this message. */
bool get_canned_message_module_messages_request;
/* Get the Canned Message Module messages in the response to this message. */
char get_canned_message_module_messages_response[201];
/* Request the node to send device metadata (firmware, protobuf version, etc) */
uint32_t get_device_metadata_request;
bool get_device_metadata_request;
/* Device metadata response */
DeviceMetadata get_device_metadata_response;
/* Set the owner for this node */
@@ -94,6 +92,9 @@ typedef struct _AdminMessage {
bool confirm_set_channel;
/* TODO: REPLACE */
bool confirm_set_radio;
/* Tell the node to reboot into the OTA Firmware in this many seconds (or <0 to cancel reboot)
Only Implemented for ESP32 Devices. This needs to be issued to send a new main firmware via bluetooth. */
int32_t reboot_ota_seconds;
/* This message is only supported for the simulator porduino build.
If received the simulator will exit successfully. */
bool exit_simulator;
@@ -136,7 +137,6 @@ extern "C" {
#define AdminMessage_get_config_response_tag 6
#define AdminMessage_get_module_config_request_tag 7
#define AdminMessage_get_module_config_response_tag 8
#define AdminMessage_get_all_channel_request_tag 9
#define AdminMessage_get_canned_message_module_messages_request_tag 10
#define AdminMessage_get_canned_message_module_messages_response_tag 11
#define AdminMessage_get_device_metadata_request_tag 12
@@ -150,6 +150,7 @@ extern "C" {
#define AdminMessage_confirm_set_module_config_tag 65
#define AdminMessage_confirm_set_channel_tag 66
#define AdminMessage_confirm_set_radio_tag 67
#define AdminMessage_reboot_ota_seconds_tag 95
#define AdminMessage_exit_simulator_tag 96
#define AdminMessage_reboot_seconds_tag 97
#define AdminMessage_shutdown_seconds_tag 98
@@ -166,10 +167,9 @@ X(a, STATIC, ONEOF, UENUM, (payload_variant,get_config_request,get_confi
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_config_response,get_config_response), 6) \
X(a, STATIC, ONEOF, UENUM, (payload_variant,get_module_config_request,get_module_config_request), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_module_config_response,get_module_config_response), 8) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_all_channel_request,get_all_channel_request), 9) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_canned_message_module_messages_request,get_canned_message_module_messages_request), 10) \
X(a, STATIC, ONEOF, STRING, (payload_variant,get_canned_message_module_messages_response,get_canned_message_module_messages_response), 11) \
X(a, STATIC, ONEOF, UINT32, (payload_variant,get_device_metadata_request,get_device_metadata_request), 12) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_metadata_request,get_device_metadata_request), 12) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_metadata_response,get_device_metadata_response), 13) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
@@ -180,6 +180,7 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_config,confirm_s
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_module_config,confirm_set_module_config), 65) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_channel,confirm_set_channel), 66) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_radio,confirm_set_radio), 67) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_ota_seconds,reboot_ota_seconds), 95) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,exit_simulator,exit_simulator), 96) \
X(a, STATIC, ONEOF, INT32, (payload_variant,reboot_seconds,reboot_seconds), 97) \
X(a, STATIC, ONEOF, INT32, (payload_variant,shutdown_seconds,shutdown_seconds), 98) \

View File

@@ -54,7 +54,7 @@ extern const pb_msgdesc_t ChannelSet_msg;
#define ChannelSet_fields &ChannelSet_msg
/* Maximum encoded size of messages (where known) */
#define ChannelSet_size 559
#define ChannelSet_size 582
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -38,25 +38,8 @@ typedef PB_BYTES_ARRAY_T(32) ChannelSettings_psk_t;
FIXME: explain how apps use channels for security.
explain how remote settings and remote gpio are managed as an example */
typedef struct _ChannelSettings {
/* NOTE: this field is _independent_ and unrelated to the concepts in channel.proto.
this is controlling the actual hardware frequency the radio is transmitting on.
In a perfect world we would have called it something else (band?) but I forgot to make this change during the big 1.2 renaming.
Most users should never need to be exposed to this field/concept.
A channel number between 1 and 13 (or whatever the max is in the current
region). If ZERO then the rule is "use the old channel name hash based
algorithm to derive the channel number")
If using the hash algorithm the channel number will be: hash(channel_name) %
NUM_CHANNELS (Where num channels depends on the regulatory region).
NUM_CHANNELS_US is 13, for other values see MeshRadio.h in the device code.
hash a string into an integer - djb2 by Dan Bernstein. -
http://www.cse.yorku.ca/~oz/hash.html
unsigned long hash(char *str) {
unsigned long hash = 5381; int c;
while ((c = *str++) != 0)
hash = ((hash << 5) + hash) + (unsigned char) c;
return hash;
} */
uint8_t channel_num;
/* Deprecated in favor of LoraConfig.channel_num */
uint32_t channel_num;
/* A simple pre-shared key for now for crypto.
Must be either 0 bytes (no crypto), 16 bytes (AES128), or 32 bytes (AES256).
A special shorthand is used for 1 byte long psks.
@@ -163,8 +146,8 @@ extern const pb_msgdesc_t Channel_msg;
#define Channel_fields &Channel_msg
/* Maximum encoded size of messages (where known) */
#define ChannelSettings_size 59
#define Channel_size 74
#define ChannelSettings_size 62
#define Channel_size 77
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -64,7 +64,8 @@ typedef enum _Config_LoRaConfig_RegionCode {
Config_LoRaConfig_RegionCode_RU = 9,
Config_LoRaConfig_RegionCode_IN = 10,
Config_LoRaConfig_RegionCode_NZ_865 = 11,
Config_LoRaConfig_RegionCode_TH = 12
Config_LoRaConfig_RegionCode_TH = 12,
Config_LoRaConfig_RegionCode_LORA_24 = 13
} Config_LoRaConfig_RegionCode;
typedef enum _Config_LoRaConfig_ModemPreset {
@@ -108,14 +109,15 @@ typedef struct _Config_DisplayConfig {
typedef struct _Config_LoRaConfig {
bool use_preset;
Config_LoRaConfig_ModemPreset modem_preset;
uint32_t bandwidth;
uint16_t bandwidth;
uint32_t spread_factor;
uint32_t coding_rate;
uint8_t coding_rate;
float frequency_offset;
Config_LoRaConfig_RegionCode region;
uint32_t hop_limit;
bool tx_enabled;
int32_t tx_power;
int8_t tx_power;
uint16_t channel_num;
pb_size_t ignore_incoming_count;
uint32_t ignore_incoming[3];
} Config_LoRaConfig;
@@ -185,8 +187,8 @@ typedef struct _Config {
#define _Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((Config_DisplayConfig_DisplayUnits)(Config_DisplayConfig_DisplayUnits_IMPERIAL+1))
#define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_UNSET
#define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_TH
#define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_TH+1))
#define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_LORA_24
#define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_LORA_24+1))
#define _Config_LoRaConfig_ModemPreset_MIN Config_LoRaConfig_ModemPreset_LONG_FAST
#define _Config_LoRaConfig_ModemPreset_MAX Config_LoRaConfig_ModemPreset_SHORT_FAST
@@ -208,7 +210,7 @@ extern "C" {
#define Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define Config_NetworkConfig_init_default {0, _Config_NetworkConfig_WiFiMode_MIN, "", "", ""}
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN}
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, {0, 0, 0}}
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_BluetoothConfig_init_default {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
#define Config_init_zero {0, {Config_DeviceConfig_init_zero}}
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0}
@@ -216,7 +218,7 @@ extern "C" {
#define Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define Config_NetworkConfig_init_zero {0, _Config_NetworkConfig_WiFiMode_MIN, "", "", ""}
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN}
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, {0, 0, 0}}
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, {0, 0, 0}}
#define Config_BluetoothConfig_init_zero {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
/* Field tags (for use in manual encoding/decoding) */
@@ -242,6 +244,7 @@ extern "C" {
#define Config_LoRaConfig_hop_limit_tag 8
#define Config_LoRaConfig_tx_enabled_tag 9
#define Config_LoRaConfig_tx_power_tag 10
#define Config_LoRaConfig_channel_num_tag 11
#define Config_LoRaConfig_ignore_incoming_tag 103
#define Config_NetworkConfig_wifi_enabled_tag 1
#define Config_NetworkConfig_wifi_mode_tag 2
@@ -350,6 +353,7 @@ X(a, STATIC, SINGULAR, UENUM, region, 7) \
X(a, STATIC, SINGULAR, UINT32, hop_limit, 8) \
X(a, STATIC, SINGULAR, BOOL, tx_enabled, 9) \
X(a, STATIC, SINGULAR, INT32, tx_power, 10) \
X(a, STATIC, SINGULAR, UINT32, channel_num, 11) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103)
#define Config_LoRaConfig_CALLBACK NULL
#define Config_LoRaConfig_DEFAULT NULL
@@ -384,7 +388,7 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg;
#define Config_BluetoothConfig_size 10
#define Config_DeviceConfig_size 6
#define Config_DisplayConfig_size 20
#define Config_LoRaConfig_size 69
#define Config_LoRaConfig_size 68
#define Config_NetworkConfig_size 137
#define Config_PositionConfig_size 30
#define Config_PowerConfig_size 43

View File

@@ -69,6 +69,7 @@ typedef struct _DeviceState {
} DeviceState;
typedef PB_BYTES_ARRAY_T(2048) OEMStore_oem_icon_bits_t;
typedef PB_BYTES_ARRAY_T(32) OEMStore_oem_aes_key_t;
/* This can be used for customizing the firmware distribution. If populated,
show a secondary bootup screen with cuatom logo and text for 2.5 seconds. */
typedef struct _OEMStore {
@@ -82,6 +83,8 @@ typedef struct _OEMStore {
ScreenFonts oem_font;
/* Use this font for the OEM text. */
char oem_text[40];
/* The default device encryption key, 16 or 32 byte */
OEMStore_oem_aes_key_t oem_aes_key;
} OEMStore;
@@ -98,10 +101,10 @@ extern "C" {
/* Initializer values for message structs */
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}, 0}
#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, "", {0, {0}}}
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}, 0}
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, "", {0, {0}}}
/* Field tags (for use in manual encoding/decoding) */
#define ChannelFile_channels_tag 1
@@ -119,6 +122,7 @@ extern "C" {
#define OEMStore_oem_icon_bits_tag 3
#define OEMStore_oem_font_tag 4
#define OEMStore_oem_text_tag 5
#define OEMStore_oem_aes_key_tag 6
/* Struct field encoding specification for nanopb */
#define DeviceState_FIELDLIST(X, a) \
@@ -150,7 +154,8 @@ X(a, STATIC, SINGULAR, UINT32, oem_icon_width, 1) \
X(a, STATIC, SINGULAR, UINT32, oem_icon_height, 2) \
X(a, STATIC, SINGULAR, BYTES, oem_icon_bits, 3) \
X(a, STATIC, SINGULAR, UENUM, oem_font, 4) \
X(a, STATIC, SINGULAR, STRING, oem_text, 5)
X(a, STATIC, SINGULAR, STRING, oem_text, 5) \
X(a, STATIC, SINGULAR, BYTES, oem_aes_key, 6)
#define OEMStore_CALLBACK NULL
#define OEMStore_DEFAULT NULL
@@ -164,9 +169,9 @@ extern const pb_msgdesc_t OEMStore_msg;
#define OEMStore_fields &OEMStore_msg
/* Maximum encoded size of messages (where known) */
#define ChannelFile_size 614
#define ChannelFile_size 638
#define DeviceState_size 21800
#define OEMStore_size 2106
#define OEMStore_size 2140
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -144,7 +144,7 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
#define LocalModuleConfig_fields &LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define LocalConfig_size 336
#define LocalConfig_size 335
#define LocalModuleConfig_size 270
#ifdef __cplusplus

View File

@@ -4,6 +4,7 @@
#ifndef PB_MESH_PB_H_INCLUDED
#define PB_MESH_PB_H_INCLUDED
#include <pb.h>
#include "channel.pb.h"
#include "config.pb.h"
#include "module_config.pb.h"
#include "portnums.pb.h"
@@ -652,6 +653,8 @@ typedef struct _FromRadio {
bool rebooted;
/* Include module config */
ModuleConfig moduleConfig;
/* One packet is sent for each channel */
Channel channel;
};
} FromRadio;
@@ -854,6 +857,7 @@ extern "C" {
#define FromRadio_config_complete_id_tag 7
#define FromRadio_rebooted_tag 8
#define FromRadio_moduleConfig_tag 9
#define FromRadio_channel_tag 10
#define ToRadio_packet_tag 1
#define ToRadio_peer_info_tag 2
#define ToRadio_want_config_id_tag 3
@@ -1001,7 +1005,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,config,config), 5) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,log_record,log_record), 6) \
X(a, STATIC, ONEOF, UINT32, (payload_variant,config_complete_id,config_complete_id), 7) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,rebooted,rebooted), 8) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig), 9) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10)
#define FromRadio_CALLBACK NULL
#define FromRadio_DEFAULT NULL
#define FromRadio_payload_variant_packet_MSGTYPE MeshPacket
@@ -1010,6 +1015,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,moduleConfig,moduleConfig),
#define FromRadio_payload_variant_config_MSGTYPE Config
#define FromRadio_payload_variant_log_record_MSGTYPE LogRecord
#define FromRadio_payload_variant_moduleConfig_MSGTYPE ModuleConfig
#define FromRadio_payload_variant_channel_MSGTYPE Channel
#define ToRadio_FIELDLIST(X, a) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \

View File

@@ -33,7 +33,8 @@ typedef enum _ModuleConfig_SerialConfig_Serial_Mode {
ModuleConfig_SerialConfig_Serial_Mode_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Mode_SIMPLE = 1,
ModuleConfig_SerialConfig_Serial_Mode_PROTO = 2,
ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3
ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG = 3,
ModuleConfig_SerialConfig_Serial_Mode_NMEA = 4
} ModuleConfig_SerialConfig_Serial_Mode;
typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
@@ -140,8 +141,8 @@ typedef struct _ModuleConfig {
#define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
#define _ModuleConfig_SerialConfig_Serial_Mode_MIN ModuleConfig_SerialConfig_Serial_Mode_DEFAULT
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG+1))
#define _ModuleConfig_SerialConfig_Serial_Mode_MAX ModuleConfig_SerialConfig_Serial_Mode_NMEA
#define _ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Mode)(ModuleConfig_SerialConfig_Serial_Mode_NMEA+1))
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MIN ModuleConfig_CannedMessageConfig_InputEventChar_NONE
#define _ModuleConfig_CannedMessageConfig_InputEventChar_MAX ModuleConfig_CannedMessageConfig_InputEventChar_BACK

View File

@@ -74,6 +74,11 @@ typedef enum _PortNum {
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS */
PortNum_ZPS_APP = 68,
/* Used to let multiple instances of Linux native applications communicate
as if they did using their LoRa chip.
Maintained by GitHub user GUVWAF.
Project files at https://github.com/GUVWAF/Meshtasticator */
PortNum_SIMULATOR_APP = 69,
/* Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/Meshtastic-device/blob/master/bin/regen-protos.sh)) */

View File

@@ -29,7 +29,11 @@ typedef enum _TelemetrySensorType {
/* High accuracy temperature and humidity */
TelemetrySensorType_SHTC3 = 7,
/* High accuracy pressure */
TelemetrySensorType_LPS22 = 8
TelemetrySensorType_LPS22 = 8,
/* 3-Axis magnetic sensor */
TelemetrySensorType_QMC6310 = 9,
/* 6-Axis inertial measurement sensor */
TelemetrySensorType_QMI8658 = 10
} TelemetrySensorType;
/* Struct definitions */
@@ -81,8 +85,8 @@ typedef struct _Telemetry {
/* Helper constants for enums */
#define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET
#define _TelemetrySensorType_MAX TelemetrySensorType_LPS22
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_LPS22+1))
#define _TelemetrySensorType_MAX TelemetrySensorType_QMI8658
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_QMI8658+1))
#ifdef __cplusplus

View File

@@ -48,8 +48,6 @@ using namespace httpsserver;
HTTPClient httpClient;
#define DEST_FS_USES_LITTLEFS
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#define ESP_ARDUINO_VERSION ESP_ARDUINO_VERSION_VAL(1, 0, 4)
// We need to specify some content-type mapping, so the resources get delivered with the
// right content type and are displayed correctly in the browser
@@ -81,8 +79,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
ResourceNode *nodeHotspotAndroid = new ResourceNode("/generate_204", "GET", &handleHotspot);
ResourceNode *nodeAdmin = new ResourceNode("/admin", "GET", &handleAdmin);
ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings);
ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply);
// ResourceNode *nodeAdminSettings = new ResourceNode("/admin/settings", "GET", &handleAdminSettings);
// ResourceNode *nodeAdminSettingsApply = new ResourceNode("/admin/settings/apply", "POST", &handleAdminSettingsApply);
// ResourceNode *nodeAdminFs = new ResourceNode("/admin/fs", "GET", &handleFs);
// ResourceNode *nodeUpdateFs = new ResourceNode("/admin/fs/update", "POST", &handleUpdateFs);
// ResourceNode *nodeDeleteFs = new ResourceNode("/admin/fs/delete", "GET", &handleDeleteFsContent);
@@ -115,8 +113,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// secureServer->registerNode(nodeDeleteFs);
secureServer->registerNode(nodeAdmin);
// secureServer->registerNode(nodeAdminFs);
secureServer->registerNode(nodeAdminSettings);
secureServer->registerNode(nodeAdminSettingsApply);
// secureServer->registerNode(nodeAdminSettings);
// secureServer->registerNode(nodeAdminSettingsApply);
secureServer->registerNode(nodeRoot); // This has to be last
// Insecure nodes
@@ -136,8 +134,8 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
// insecureServer->registerNode(nodeDeleteFs);
insecureServer->registerNode(nodeAdmin);
// insecureServer->registerNode(nodeAdminFs);
insecureServer->registerNode(nodeAdminSettings);
insecureServer->registerNode(nodeAdminSettingsApply);
// insecureServer->registerNode(nodeAdminSettings);
// insecureServer->registerNode(nodeAdminSettingsApply);
insecureServer->registerNode(nodeRoot); // This has to be last
}
@@ -253,7 +251,7 @@ void htmlDeleteDir(const char *dirname)
std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname,
uint8_t levels)
{
File root = FSCom.open(dirname);
File root = FSCom.open(dirname, FILE_O_READ);
if (!root) {
return NULL;
}
@@ -266,14 +264,27 @@ std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *,
while (file) {
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
if (levels) {
#ifdef ARCH_ESP32
htmlListDir(fileList, file.path(), levels - 1);
#else
htmlListDir(fileList, file.name(), levels - 1);
#endif
file.close();
}
} else {
std::map<char *, char *> thisFileMap;
thisFileMap[strdup("size")] = strdup(String(file.size()).c_str());
#ifdef ARCH_ESP32
thisFileMap[strdup("name")] = strdup(String(file.path()).substring(1).c_str());
#else
thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str());
#endif
if (String(file.name()).substring(1).endsWith(".gz")) {
#ifdef ARCH_ESP32
String modifiedFile = String(file.path()).substring(1);
#else
String modifiedFile = String(file.name()).substring(1);
#endif
modifiedFile.remove((modifiedFile.length() - 3), 3);
thisFileMap[strdup("nameModified")] = strdup(modifiedFile.c_str());
}
@@ -293,7 +304,7 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Methods", "GET");
using namespace json11;
auto fileList = htmlListDir(new std::vector<std::map<char *, char *>>(), "/", 10);
auto fileList = htmlListDir(new std::vector<std::map<char *, char *>>(), "/static", 10);
// create json output structure
Json filesystemObj = Json::object{
@@ -696,8 +707,8 @@ void handleAdmin(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Methods", "GET");
res->println("<h1>Meshtastic</h1>\n");
res->println("<a href=/admin/settings>Settings</a><br>\n");
res->println("<a href=/admin/fs>Manage Web Content</a><br>\n");
// res->println("<a href=/admin/settings>Settings</a><br>\n");
// res->println("<a href=/admin/fs>Manage Web Content</a><br>\n");
res->println("<a href=/json/report>Device Report</a><br>\n");
}

View File

@@ -10,6 +10,7 @@
#include "target_specific.h"
#include <DNSServer.h>
#include <ESPmDNS.h>
#include <esp_wifi.h>
#include <WiFi.h>
#include <WiFiUdp.h>
@@ -42,40 +43,25 @@ bool APStartupComplete = 0;
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
// FIXME, veto light sleep if we have a TCP server running
#if 0
class WifiSleepObserver : public Observer<uint32_t> {
protected:
/// Return 0 if sleep is okay
virtual int onNotify(uint32_t newValue) {
}
};
static WifiSleepObserver wifiSleepObserver;
//preflightSleepObserver.observe(&preflightSleep);
#endif
static int32_t reconnectWiFi()
{
const char *wifiName = config.network.wifi_ssid;
const char *wifiPsw = config.network.wifi_psk;
if (config.network.wifi_enabled && needReconnect && !WiFi.isConnected()) {
// if (radioConfig.has_preferences && needReconnect && !WiFi.isConnected()) {
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
if (*wifiName) {
needReconnect = false;
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
DEBUG_MSG("... Reconnecting to WiFi access point\n");
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(wifiName, wifiPsw);
// Starting timeClient;
}
}
@@ -109,14 +95,9 @@ bool isSoftAPForced()
bool isWifiAvailable()
{
// If wifi status is connected, return true regardless of the radio configuration.
if (isSoftAPForced()) {
return true;
}
const char *wifiName = config.network.wifi_ssid;
if (config.network.wifi_enabled && ((config.network.wifi_ssid[0]) || forcedSoftAP)) {
if (*wifiName) {
return true;
} else {
return false;
@@ -238,10 +219,8 @@ bool initWifi(bool forceSoftAP)
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
DEBUG_MSG("MY IP AP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
#if !CONFIG_IDF_TARGET_ESP32S3
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
#endif
dnsServer.start(53, "*", apIP);
@@ -254,19 +233,14 @@ bool initWifi(bool forceSoftAP)
WiFi.setHostname(ourHost);
WiFi.onEvent(WiFiEvent);
#if !CONFIG_IDF_TARGET_ESP32S3
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
#endif
WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("\nWiFi lost connection. Reason: ");
#if CONFIG_IDF_TARGET_ESP32S3
Serial.println(info.wifi_sta_disconnected.reason);
wifiDisconnectReason = info.wifi_sta_disconnected.reason;
#else
Serial.println(info.disconnected.reason);
/*
If we are disconnected from the AP for some reason,
save the error code.
@@ -274,15 +248,9 @@ bool initWifi(bool forceSoftAP)
For a reference to the codes:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code
*/
wifiDisconnectReason = info.disconnected.reason;
#endif
wifiDisconnectReason = info.wifi_sta_disconnected.reason;
},
#if CONFIG_IDF_TARGET_ESP32S3
WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
#else
WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
#endif
DEBUG_MSG("JOINING WIFI soon: ssid=%s\n", wifiName);
wifiReconnect = new Periodic("WifiConnect", reconnectWiFi);

View File

@@ -4,11 +4,12 @@
static WiFiServerPort *apiPort;
void initApiServer()
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new WiFiServerPort();
apiPort = new WiFiServerPort(port);
DEBUG_MSG("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
@@ -56,13 +57,11 @@ void WiFiServerPort::debugOut(char c)
apiPort->openAPI->debugOut(c);
}
#define MESHTASTIC_PORTNUM 4403
WiFiServerPort::WiFiServerPort() : WiFiServer(MESHTASTIC_PORTNUM), concurrency::OSThread("ApiServer") {}
WiFiServerPort::WiFiServerPort(int port) : WiFiServer(port), concurrency::OSThread("ApiServer") {}
void WiFiServerPort::init()
{
DEBUG_MSG("API server listening on TCP port %d\n", MESHTASTIC_PORTNUM);
begin();
}
@@ -80,4 +79,4 @@ int32_t WiFiServerPort::runOnce()
}
return 100; // only check occasionally for incoming connections
}
}

View File

@@ -44,7 +44,7 @@ class WiFiServerPort : public WiFiServer, private concurrency::OSThread
WiFiServerAPI *openAPI = NULL;
public:
WiFiServerPort();
explicit WiFiServerPort(int port);
void init();
@@ -55,4 +55,4 @@ class WiFiServerPort : public WiFiServer, private concurrency::OSThread
int32_t runOnce() override;
};
void initApiServer();
void initApiServer(int port=4403);

View File

@@ -2,6 +2,9 @@
#include "Channels.h"
#include "MeshService.h"
#include "NodeDB.h"
#ifdef ARCH_ESP32
#include "BleOta.h"
#endif
#include "Router.h"
#include "configuration.h"
#include "main.h"
@@ -98,8 +101,21 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
* Other
*/
case AdminMessage_reboot_seconds_tag: {
int32_t s = r->reboot_seconds;
DEBUG_MSG("Rebooting in %d seconds\n", s);
reboot(r->reboot_seconds);
break;
}
case AdminMessage_reboot_ota_seconds_tag: {
int32_t s = r->reboot_ota_seconds;
#ifdef ARCH_ESP32
if (BleOta::getOtaAppVersion().isEmpty()) {
DEBUG_MSG("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
}else{
BleOta::switchToOtaApp();
DEBUG_MSG("Rebooting to OTA in %d seconds\n", s);
}
#else
DEBUG_MSG("Not on ESP32, scheduling regular reboot in %d seconds\n", s);
#endif
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
break;
}
@@ -117,7 +133,13 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
case AdminMessage_factory_reset_tag: {
DEBUG_MSG("Initiating factory reset\n");
nodeDB.factoryReset();
rebootAtMsec = millis() + (5 * 1000);
reboot(5);
break;
}
case AdminMessage_nodedb_reset_tag: {
DEBUG_MSG("Initiating node-db reset\n");
nodeDB.resetNodes();
reboot(5);
break;
}
#ifdef ARCH_PORTDUINO
@@ -169,13 +191,15 @@ void AdminModule::handleSetOwner(const User &o)
owner.is_licensed = o.is_licensed;
}
if (changed) // If nothing really changed, don't broadcast on the network or write to flash
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner();
DEBUG_MSG("Rebooting due to owner changes\n");
reboot(5);
}
}
void AdminModule::handleSetConfig(const Config &c)
{
bool requiresReboot = false;
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER);
bool isRegionUnset = (config.lora.region == Config_LoRaConfig_RegionCode_UNSET);
@@ -190,12 +214,13 @@ void AdminModule::handleSetConfig(const Config &c)
nodeDB.initConfigIntervals();
nodeDB.initModuleConfigIntervals();
}
requiresReboot = true;
break;
case Config_position_tag:
DEBUG_MSG("Setting config: Position\n");
config.has_position = true;
config.position = c.payload_variant.position;
// Save nodedb as well in case we got a fixed position packet
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
break;
case Config_power_tag:
DEBUG_MSG("Setting config: Power\n");
@@ -206,7 +231,6 @@ void AdminModule::handleSetConfig(const Config &c)
DEBUG_MSG("Setting config: WiFi\n");
config.has_network = true;
config.network = c.payload_variant.network;
requiresReboot = true;
break;
case Config_display_tag:
DEBUG_MSG("Setting config: Display\n");
@@ -221,23 +245,16 @@ void AdminModule::handleSetConfig(const Config &c)
config.lora.region > Config_LoRaConfig_RegionCode_UNSET) {
config.lora.tx_enabled = true;
}
requiresReboot = true;
break;
case Config_bluetooth_tag:
DEBUG_MSG("Setting config: Bluetooth\n");
config.has_bluetooth = true;
config.bluetooth = c.payload_variant.bluetooth;
requiresReboot = true;
break;
}
service.reloadConfig();
// Reboot 5 seconds after a config that requires rebooting is set
if (requiresReboot) {
DEBUG_MSG("Rebooting due to config changes\n");
screen->startRebootScreen();
rebootAtMsec = millis() + (5 * 1000);
}
service.reloadConfig(SEGMENT_CONFIG);
reboot(5);
}
void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
@@ -279,8 +296,9 @@ void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
moduleConfig.canned_message = c.payload_variant.canned_message;
break;
}
service.reloadConfig();
service.reloadConfig(SEGMENT_MODULECONFIG);
reboot(5);
}
void AdminModule::handleSetChannel(const Channel &cc)
@@ -440,6 +458,13 @@ void AdminModule::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
}
}
void AdminModule::reboot(int32_t seconds)
{
DEBUG_MSG("Rebooting in %d seconds\n", seconds);
screen->startRebootScreen();
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
}
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
{
// restrict to the admin channel for rx

View File

@@ -37,6 +37,7 @@ class AdminModule : public ProtobufModule<AdminMessage>
void handleSetConfig(const Config &c);
void handleSetModuleConfig(const ModuleConfig &c);
void handleSetChannel();
void reboot(int32_t seconds);
};
extern AdminModule *adminModule;

View File

@@ -2,18 +2,41 @@
#if HAS_SCREEN
#include "CannedMessageModule.h"
#include "FSCommon.h"
#include "NodeDB.h"
#include "MeshService.h"
#include "PowerFSM.h" // neede for button bypass
#include "mesh/generated/cannedmessages.pb.h"
// TODO: reuse defined from Screen.cpp
#ifdef OLED_RU
#include "graphics/fonts/OLEDDisplayFontsRU.h"
#endif
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
#define FONT_MEDIUM ArialMT_Plain_24
#define FONT_LARGE ArialMT_Plain_24
#else
#ifdef OLED_RU
#define FONT_SMALL ArialMT_Plain_10_RU
#else
#define FONT_SMALL ArialMT_Plain_10
#endif
#define FONT_MEDIUM ArialMT_Plain_16
#define FONT_LARGE ArialMT_Plain_24
#endif
#define fontHeight(font) ((font)[1] + 1) // height is position 1
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
#define FONT_HEIGHT_LARGE fontHeight(FONT_LARGE)
// Remove Canned message screen if no action is taken for some milliseconds
#define INACTIVATE_AFTER_MS 20000
extern uint8_t cardkb_found;
static const char *cannedMessagesConfigFile = "/prefs/cannedConf.proto";
CannedMessageModuleConfig cannedMessageModuleConfig;
@@ -30,7 +53,7 @@ CannedMessageModule::CannedMessageModule()
{
if (moduleConfig.canned_message.enabled) {
this->loadProtoForModule();
if (this->splitConfiguredMessages() <= 0) {
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found != CARDKB_ADDR)) {
DEBUG_MSG("CannedMessageModule: No messages are configured. Module is disabled\n");
this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
} else {
@@ -116,10 +139,48 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
if ((this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED)) {
powerFSM.trigger(EVENT_PRESS);
} else {
this->payload = this->runState;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_SELECT;
validEvent = true;
}
}
if (event->inputEvent == static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL)) {
DEBUG_MSG("Canned message event Cancel\n");
// emulate a timeout. Same result
this->lastTouchMillis = 0;
validEvent = true;
}
if ((event->inputEvent == static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_BACK)) ||
(event->inputEvent == static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
(event->inputEvent == static_cast<char>(ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
DEBUG_MSG("Canned message event (%x)\n",event->kbchar);
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
// pass the pressed key
this->payload = event->kbchar;
this->lastTouchMillis = millis();
validEvent = true;
}
}
if (event->inputEvent == static_cast<char>(ANYKEY)) {
DEBUG_MSG("Canned message event any key pressed\n");
// when inactive, this will switch to the freetext mode
if ((this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED)) {
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
}
// pass the pressed key
this->payload = event->kbchar;
this->lastTouchMillis = millis();
validEvent = true;
}
if (event->inputEvent == static_cast<char>(MATRIXKEY)) {
DEBUG_MSG("Canned message event Matrix key pressed\n");
// this will send the text immediately on matrix press
this->runState = CANNED_MESSAGE_RUN_STATE_ACTION_SELECT;
this->payload = event->kbchar;
this->currentMessageIndex = event->kbchar -1;
this->lastTouchMillis = millis();
validEvent = true;
}
if (validEvent) {
// Let runOnce to be called immediately.
@@ -142,7 +203,7 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
p->decoded.payload.size++;
}
DEBUG_MSG("Sending message id=%d, msg=%.*s\n", p->id, p->decoded.payload.size, p->decoded.payload.bytes);
DEBUG_MSG("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
service.sendToMesh(p);
}
@@ -151,7 +212,7 @@ int32_t CannedMessageModule::runOnce()
{
if ((!moduleConfig.canned_message.enabled) || (this->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) ||
(this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
return 30000; // TODO: should return MAX_VAL
return INT32_MAX;
}
DEBUG_MSG("Check status\n");
UIFrameEvent e = {false, true};
@@ -160,33 +221,149 @@ int32_t CannedMessageModule::runOnce()
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
e.frameChanged = true;
this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = false;
this->notifyObservers(&e);
} else if ((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) && (millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS) {
} else if (((this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) || (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT)) && ((millis() - this->lastTouchMillis) > INACTIVATE_AFTER_MS)) {
// Reset module
DEBUG_MSG("Reset due the lack of activity.\n");
DEBUG_MSG("Reset due to lack of activity.\n");
e.frameChanged = true;
this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
this->notifyObservers(&e);
} else if (this->currentMessageIndex == -1) {
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
if (this->payload == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
if (this->freetext.length() > 0) {
sendText(this->dest, this->freetext.c_str(), true);
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else {
DEBUG_MSG("Reset message is empty.\n");
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
}
} else {
if ((this->messagesCount > this->currentMessageIndex) && (strlen(this->messages[this->currentMessageIndex]) > 0)) {
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true);
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else {
DEBUG_MSG("Reset message is empty.\n");
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
}
}
e.frameChanged = true;
this->currentMessageIndex = -1;
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = false;
this->notifyObservers(&e);
return 2000;
} else if ((this->runState != CANNED_MESSAGE_RUN_STATE_FREETEXT) && (this->currentMessageIndex == -1)) {
this->currentMessageIndex = 0;
DEBUG_MSG("First touch (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
e.frameChanged = true;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_SELECT) {
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true);
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
this->currentMessageIndex = -1;
this->notifyObservers(&e);
return 2000;
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_UP) {
this->currentMessageIndex = getPrevIndex();
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
if (this->messagesCount > 0) {
this->currentMessageIndex = getPrevIndex();
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE UP (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
}
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTION_DOWN) {
this->currentMessageIndex = this->getNextIndex();
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
if (this->messagesCount > 0) {
this->currentMessageIndex = this->getNextIndex();
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = false;
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
DEBUG_MSG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
}
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
e.frameChanged = true;
switch (this->payload) {
case 0xb4: // left
if (this->destSelect){
size_t numNodes = nodeDB.getNumNodes();
if(this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i > 0) ? nodeDB.getNodeByIndex(i-1)->num : nodeDB.getNodeByIndex(numNodes-1)->num;
break;
}
}
if(this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST;
}
}else{
if (this->cursor > 0) {
this->cursor--;
}
}
break;
case 0xb7: // right
if (this->destSelect){
size_t numNodes = nodeDB.getNumNodes();
if(this->dest == NODENUM_BROADCAST) {
this->dest = nodeDB.getNodeNum();
}
for (unsigned int i = 0; i < numNodes; i++) {
if (nodeDB.getNodeByIndex(i)->num == this->dest) {
this->dest = (i < numNodes-1) ? nodeDB.getNodeByIndex(i+1)->num : nodeDB.getNodeByIndex(0)->num;
break;
}
}
if(this->dest == nodeDB.getNodeNum()) {
this->dest = NODENUM_BROADCAST;
}
}else{
if (this->cursor < this->freetext.length()) {
this->cursor++;
}
}
break;
case 0x08: // backspace
if (this->freetext.length() > 0) {
if(this->cursor == this->freetext.length()) {
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
} else {
this->freetext = this->freetext.substring(0, this->cursor - 1) + this->freetext.substring(this->cursor, this->freetext.length());
}
this->cursor--;
}
break;
case 0x09: // tab
if(this->destSelect) {
this->destSelect = false;
} else {
this->destSelect = true;
}
break;
default:
if(this->cursor == this->freetext.length()) {
this->freetext += this->payload;
} else {
this->freetext = this->freetext.substring(0, this->cursor)
+ this->payload
+ this->freetext.substring(this->cursor);
}
this->cursor += 1;
if (this->freetext.length() > Constants_DATA_PAYLOAD_LEN) {
this->cursor = Constants_DATA_PAYLOAD_LEN;
this->freetext = this->freetext.substring(0, Constants_DATA_PAYLOAD_LEN);
}
break;
}
this->lastTouchMillis = millis();
this->notifyObservers(&e);
return INACTIVATE_AFTER_MS;
}
if (this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
@@ -195,7 +372,7 @@ int32_t CannedMessageModule::runOnce()
return INACTIVATE_AFTER_MS;
}
return 30000; // TODO: should return MAX_VAL
return INT32_MAX;
}
const char *CannedMessageModule::getCurrentMessage()
@@ -210,6 +387,19 @@ const char *CannedMessageModule::getNextMessage()
{
return this->messages[this->getNextIndex()];
}
const char* CannedMessageModule::getNodeName(NodeNum node) {
if (node == NODENUM_BROADCAST){
return "Broadcast";
}else{
NodeInfo *info = nodeDB.getNode(node);
if(info != NULL) {
return info->user.long_name;
}else{
return "Unknown";
}
}
}
bool CannedMessageModule::shouldDraw()
{
if (!moduleConfig.canned_message.enabled) {
@@ -240,6 +430,8 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
{
displayedNodeNum = 0; // Not currently showing a node pane
char buffer[50];
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
@@ -247,15 +439,32 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_DISABLED) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
display->drawString(10 + x, 0 + y + 16, "Canned Message\nModule disabled.");
} else {
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
}else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y, cannedMessageModule->getPrevMessage());
display->setFont(FONT_MEDIUM);
display->drawString(0 + x, 0 + y + 8, cannedMessageModule->getCurrentMessage());
display->setFont(FONT_SMALL);
display->drawString(0 + x, 0 + y + 24, cannedMessageModule->getNextMessage());
if (this->destSelect) {
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
}
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
// used chars right aligned
sprintf(buffer, "%d left", Constants_DATA_PAYLOAD_LEN - this->freetext.length());
display->drawString(x + display->getWidth() - display->getStringWidth(buffer), y + 0, buffer);
display->setColor(WHITE);
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), cannedMessageModule->drawWithCursor(cannedMessageModule->freetext, cannedMessageModule->cursor));
} else {
if (this->messagesCount > 0) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
display->setColor(BLACK);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
display->setColor(WHITE);
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
}
}
}
@@ -281,7 +490,7 @@ bool CannedMessageModule::saveProtoForModule()
FS.mkdir("/prefs");
#endif
okay &= saveProto(cannedMessagesConfigFile, CannedMessageModuleConfig_size, sizeof(CannedMessageModuleConfig),
okay &= saveProto(cannedMessagesConfigFile, CannedMessageModuleConfig_size, sizeof(cannedMessageModuleConfig),
CannedMessageModuleConfig_fields, &cannedMessageModuleConfig);
return okay;
@@ -354,4 +563,12 @@ void CannedMessageModule::handleSetCannedMessageModuleMessages(const char *from_
}
}
String CannedMessageModule::drawWithCursor(String text, int cursor)
{
String result = text.substring(0, cursor)
+ "_"
+ text.substring(cursor);
return result;
}
#endif

View File

@@ -8,6 +8,7 @@ enum cannedMessageModuleRunState
CANNED_MESSAGE_RUN_STATE_DISABLED,
CANNED_MESSAGE_RUN_STATE_INACTIVE,
CANNED_MESSAGE_RUN_STATE_ACTIVE,
CANNED_MESSAGE_RUN_STATE_FREETEXT,
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
CANNED_MESSAGE_RUN_STATE_ACTION_UP,
@@ -34,6 +35,7 @@ class CannedMessageModule :
const char* getCurrentMessage();
const char* getPrevMessage();
const char* getNextMessage();
const char* getNodeName(NodeNum node);
bool shouldDraw();
void eventUp();
void eventDown();
@@ -42,6 +44,8 @@ class CannedMessageModule :
void handleGetCannedMessageModuleMessages(const MeshPacket &req, AdminMessage *response);
void handleSetCannedMessageModuleMessages(const char *from_msg);
String drawWithCursor(String text, int cursor);
protected:
virtual int32_t runOnce() override;
@@ -70,6 +74,11 @@ class CannedMessageModule :
int currentMessageIndex = -1;
cannedMessageModuleRunState runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
char payload = 0x00;
unsigned int cursor = 0;
String freetext = ""; // Text Buffer for Freetext Editor
bool destSelect = false; // Freetext Editor Mode
NodeNum dest = NODENUM_BROADCAST;
char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE+1];
char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT];
@@ -78,4 +87,4 @@ class CannedMessageModule :
};
extern CannedMessageModule *cannedMessageModule;
#endif
#endif

View File

@@ -3,9 +3,14 @@
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "buzz/buzz.h"
#include "configuration.h"
#include <Arduino.h>
#ifndef PIN_BUZZER
#define PIN_BUZZER false
#endif
//#include <assert.h>
/*
@@ -44,7 +49,11 @@
*/
// Default configurations
#ifdef EXT_NOTIFY_OUT
#define EXT_NOTIFICATION_MODULE_OUTPUT EXT_NOTIFY_OUT
#else
#define EXT_NOTIFICATION_MODULE_OUTPUT 0
#endif
#define EXT_NOTIFICATION_MODULE_OUTPUT_MS 1000
#define ASCII_BELL 0x07
@@ -75,7 +84,9 @@ int32_t ExternalNotificationModule::runOnce()
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
millis()) {
DEBUG_MSG("Turning off external notification\n");
setExternalOff();
if (output != PIN_BUZZER) {
setExternalOff();
}
}
}
@@ -84,27 +95,19 @@ int32_t ExternalNotificationModule::runOnce()
void ExternalNotificationModule::setExternalOn()
{
#ifdef EXT_NOTIFY_OUT
externalCurrentState = 1;
externalTurnedOn = millis();
digitalWrite((moduleConfig.external_notification.output
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT),
digitalWrite(output,
(moduleConfig.external_notification.active ? true : false));
#endif
}
void ExternalNotificationModule::setExternalOff()
{
#ifdef EXT_NOTIFY_OUT
externalCurrentState = 0;
digitalWrite((moduleConfig.external_notification.output
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT),
digitalWrite(output,
(moduleConfig.external_notification.active ? false : true));
#endif
}
// --------
@@ -116,8 +119,6 @@ ExternalNotificationModule::ExternalNotificationModule()
// restrict to the admin channel for rx
boundChannel = Channels::gpioChannel;
#ifdef EXT_NOTIFY_OUT
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
@@ -135,25 +136,27 @@ ExternalNotificationModule::ExternalNotificationModule()
DEBUG_MSG("Initializing External Notification Module\n");
// Set the direction of a pin
pinMode((moduleConfig.external_notification.output
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT),
OUTPUT);
output = moduleConfig.external_notification.output
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT;
// Turn off the pin
setExternalOff();
if (output != PIN_BUZZER) {
// Set the direction of a pin
DEBUG_MSG("Using Pin %i in digital mode\n", output);
pinMode(output, OUTPUT);
// Turn off the pin
setExternalOff();
} else{
DEBUG_MSG("Using Pin %i in PWM mode\n", output);
}
} else {
DEBUG_MSG("External Notification Module Disabled\n");
enabled = false;
}
#endif
}
ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
{
#ifdef EXT_NOTIFY_OUT
if (moduleConfig.external_notification.enabled) {
if (getFrom(&mp) != nodeDB.getNodeNum()) {
@@ -165,21 +168,28 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
DEBUG_MSG("externalNotificationModule - Notification Bell\n");
for (int i = 0; i < p.payload.size; i++) {
if (p.payload.bytes[i] == ASCII_BELL) {
setExternalOn();
if (output != PIN_BUZZER) {
setExternalOn();
} else {
playBeep();
}
}
}
}
if (moduleConfig.external_notification.alert_message) {
DEBUG_MSG("externalNotificationModule - Notification Module\n");
setExternalOn();
if (output != PIN_BUZZER) {
setExternalOn();
} else {
playBeep();
}
}
}
} else {
DEBUG_MSG("External Notification Module Disabled\n");
}
#endif
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
}

View File

@@ -12,6 +12,8 @@
*/
class ExternalNotificationModule : public SinglePortModule, private concurrency::OSThread
{
uint32_t output = 0;
public:
ExternalNotificationModule();

View File

@@ -3,7 +3,6 @@
#include "input/RotaryEncoderInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#include "input/cardKbI2cImpl.h"
#include "input/facesKbI2cImpl.h"
#include "modules/AdminModule.h"
#include "modules/CannedMessageModule.h"
#include "modules/NodeInfoModule.h"
@@ -53,8 +52,6 @@ void setupModules()
upDownInterruptImpl1->init();
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
facesKbI2cImpl = new FacesKbI2cImpl();
facesKbI2cImpl->init();
#endif
#if HAS_SCREEN
cannedMessageModule = new CannedMessageModule();
@@ -63,13 +60,15 @@ void setupModules()
new DeviceTelemetryModule();
new EnvironmentTelemetryModule();
#endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO)
new SerialModule();
#endif
#ifdef ARCH_ESP32
// Only run on an esp32 based device.
/*
Maintained by MC Hamster (Jm Casler) jm@casler.org
*/
new SerialModule();
new ExternalNotificationModule();
storeForwardModule = new StoreForwardModule();

View File

@@ -58,6 +58,8 @@ MeshPacket *PositionModule::allocReply()
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
assert(node->has_position);
node->position.seq_number++;
// configuration of POSITION packet
// consider making this a function argument?
uint32_t pos_flags = config.position.position_flags;
@@ -94,10 +96,19 @@ MeshPacket *PositionModule::allocReply()
if (pos_flags & Config_PositionConfig_PositionFlags_TIMESTAMP)
p.timestamp = node->position.timestamp;
if (pos_flags & Config_PositionConfig_PositionFlags_SEQ_NO)
p.seq_number = node->position.seq_number;
if (pos_flags & Config_PositionConfig_PositionFlags_HEADING)
p.ground_track = node->position.ground_track;
if (pos_flags & Config_PositionConfig_PositionFlags_SPEED)
p.ground_speed = node->position.ground_speed;
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
// devices can get time.
if (getRTCQuality() < RTCQualityGPS) {
if (getRTCQuality() < RTCQualityDevice) {
DEBUG_MSG("Stripping time %u from position send\n", p.time);
p.time = 0;
} else
@@ -133,7 +144,7 @@ int32_t PositionModule::runOnce()
if (lastGpsSend == 0 || (now - lastGpsSend) >= intervalMs) {
// Only send packets if the channel is less than 40% utilized.
if (airTime->channelUtilizationPercent() < 40) {
if (airTime->channelUtilizationPercent() < max_channel_util_percent) {
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
lastGpsSend = now;
@@ -154,7 +165,7 @@ int32_t PositionModule::runOnce()
} else if (config.position.position_broadcast_smart_enabled) {
// Only send packets if the channel is less than 25% utilized.
if (airTime->channelUtilizationPercent() < 25) {
if (airTime->channelUtilizationPercent() < polite_channel_util_percent) {
NodeInfo *node2 = service.refreshMyNodeInfo(); // should guarantee there is now a position

View File

@@ -2,6 +2,7 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "NMEAWPL.h"
#include "Router.h"
#include "configuration.h"
#include <Arduino.h>
@@ -27,8 +28,7 @@
TXD 15
3) Set timeout to the amount of time to wait before we consider
your packet as "done".
4) (Optional) In SerialModule.h set the port to PortNum_TEXT_MESSAGE_APP if you want to
send messages to/from the general text message channel.
4) not applicable any more
5) Connect to your device over the serial interface at 38400 8N1.
6) Send a packet up to 240 bytes in length. This will get relayed over the mesh network.
7) (Optional) Set echo to 1 and any message you send out will be echoed back
@@ -41,7 +41,7 @@
KNOWN PROBLEMS
* Until the module is initilized by the startup sequence, the TX pin is in a floating
state. Device connected to that pin may see this as "noise".
* Will not work on NRF and the Linux device targets.
* Will not work on T-Echo and the Linux device targets.
*/
@@ -61,10 +61,23 @@ SerialModule::SerialModule() : concurrency::OSThread("SerialModule") {}
char serialStringChar[Constants_DATA_PAYLOAD_LEN];
SerialModuleRadio::SerialModuleRadio() : SinglePortModule("SerialModuleRadio", PortNum_SERIAL_APP)
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
{
// restrict to the admin channel for rx
boundChannel = Channels::serialChannel;
switch (moduleConfig.serial.mode)
{
case ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
ourPortNum = PortNum_TEXT_MESSAGE_APP;
break;
case ModuleConfig_SerialConfig_Serial_Mode_NMEA:
ourPortNum = PortNum_POSITION_APP;
break;
default:
ourPortNum = PortNum_SERIAL_APP;
// restrict to the serial channel for rx
boundChannel = Channels::serialChannel;
break;
}
}
int32_t SerialModule::runOnce()
@@ -139,7 +152,9 @@ int32_t SerialModule::runOnce()
baud = 921600;
}
#ifdef ARCH_ESP32
#ifdef ARCH_ESP32
Serial2.setRxBufferSize(RX_BUFFER);
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
Serial2.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd);
@@ -159,24 +174,30 @@ int32_t SerialModule::runOnce()
Serial2.setTimeout(TIMEOUT); // Number of MS to wait to set the timeout for the string.
}
#ifdef ARCH_ESP32
Serial2.setRxBufferSize(RX_BUFFER);
#endif
serialModuleRadio = new SerialModuleRadio();
firstTime = 0;
} else {
String serialString;
while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
if (millis() - lastNmeaTime > 2000) {
lastNmeaTime = millis();
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
Serial2.printf("%s", outbuf);
}
} else {
String serialString;
serialModuleRadio->sendPayload();
while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
DEBUG_MSG("Received: %s\n", serialStringChar);
serialModuleRadio->sendPayload();
DEBUG_MSG("Received: %s\n", serialStringChar);
}
}
}
@@ -184,7 +205,7 @@ int32_t SerialModule::runOnce()
} else {
DEBUG_MSG("Serial Module Disabled\n");
return (INT32_MAX);
return INT32_MAX;
}
#else
return INT32_MAX;
@@ -244,12 +265,23 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
// DEBUG_MSG("* * Message came from the mesh\n");
// Serial2.println("* * Message came from the mesh");
Serial2.printf("%s", p.payload.bytes);
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
// TODO this needs to be implemented
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
// Decode the Payload some more
Position scratch;
Position *decoded = NULL;
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, Position_fields, &scratch)) {
decoded = &scratch;
}
// send position packet as WPL to the serial port
printWPL(outbuf, *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name);
Serial2.printf("%s", outbuf);
}
}
}

View File

@@ -4,11 +4,15 @@
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
#include "MeshModule.h"
#include "Router.h"
#include <functional>
class SerialModule : private concurrency::OSThread
{
bool firstTime = 1;
unsigned long lastNmeaTime = millis();
char outbuf[90] = "";
public:
SerialModule();
@@ -23,16 +27,12 @@ extern SerialModule *serialModule;
* Radio interface for SerialModule
*
*/
class SerialModuleRadio : public SinglePortModule
class SerialModuleRadio : public MeshModule
{
uint32_t lastRxID = 0;
char outbuf[90] = "";
public:
/*
TODO: Switch this to PortNum_SERIAL_APP once the change is able to be merged back here
from the main code.
*/
SerialModuleRadio();
/**
@@ -48,6 +48,20 @@ class SerialModuleRadio : public SinglePortModule
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
*/
virtual ProcessMessage handleReceived(const MeshPacket &mp) override;
PortNum ourPortNum;
virtual bool wantPacket(const MeshPacket *p) override { return p->decoded.portnum == ourPortNum; }
MeshPacket *allocDataPacket()
{
// Update our local node info with our position (even if we don't decide to update anyone else)
MeshPacket *p = router->allocForSending();
p->decoded.portnum = ourPortNum;
return p;
}
};
extern SerialModuleRadio *serialModuleRadio;

View File

@@ -9,19 +9,23 @@
#include "main.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include "MeshService.h"
int32_t DeviceTelemetryModule::runOnce()
{
#ifndef ARCH_PORTDUINO
if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup
firstTime = 0;
DEBUG_MSG("Device Telemetry: Initializing\n");
uint32_t now = millis();
if ((lastSentToMesh == 0 ||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval)) &&
airTime->channelUtilizationPercent() < max_channel_util_percent) {
sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
sendOurTelemetry();
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval);
return sendToPhoneIntervalMs;
#endif
}
@@ -29,14 +33,13 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
{
if (t->which_variant == Telemetry_device_metrics_tag) {
const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Device Telemetry: Received data from %s\n", sender);
DEBUG_MSG("Telemetry->time: %i\n", t->time);
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t->variant.device_metrics.air_util_tx);
DEBUG_MSG("Telemetry->battery_level: %i\n", t->variant.device_metrics.battery_level);
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t->variant.device_metrics.channel_utilization);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.device_metrics.voltage);
DEBUG_MSG("(Received from %s): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
sender,
t->variant.device_metrics.air_util_tx,
t->variant.device_metrics.channel_utilization,
t->variant.device_metrics.battery_level,
t->variant.device_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp);
@@ -45,7 +48,7 @@ bool DeviceTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Telemet
return false; // Let others look at this message also if they want
}
bool DeviceTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
Telemetry t;
@@ -57,22 +60,25 @@ bool DeviceTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
t.variant.device_metrics.channel_utilization = myNodeInfo.channel_utilization;
t.variant.device_metrics.voltage = powerStatus->getBatteryVoltageMv() / 1000.0;
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Device Telemetry: Read data\n");
DEBUG_MSG("Telemetry->time: %i\n", t.time);
DEBUG_MSG("Telemetry->air_util_tx: %f\n", t.variant.device_metrics.air_util_tx);
DEBUG_MSG("Telemetry->battery_level: %i\n", t.variant.device_metrics.battery_level);
DEBUG_MSG("Telemetry->channel_utilization: %f\n", t.variant.device_metrics.channel_utilization);
DEBUG_MSG("Telemetry->voltage: %f\n", t.variant.device_metrics.voltage);
DEBUG_MSG("(Sending): air_util_tx=%f, channel_utilization=%f, battery_level=%i, voltage=%f\n",
t.variant.device_metrics.air_util_tx,
t.variant.device_metrics.channel_utilization,
t.variant.device_metrics.battery_level,
t.variant.device_metrics.voltage);
MeshPacket *p = allocDataProtobuf(t);
p->to = dest;
p->decoded.want_response = wantReplies;
p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p);
DEBUG_MSG("Device Telemetry: Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
nodeDB.updateTelemetry(nodeDB.getNodeNum(), t, RX_SRC_LOCAL);
if (phoneOnly) {
DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;
}

View File

@@ -11,7 +11,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
DeviceTelemetryModule()
: concurrency::OSThread("DeviceTelemetryModule"), ProtobufModule("DeviceTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{
lastMeasurementPacket = nullptr;
lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
}
virtual bool wantUIFrame() { return false; }
@@ -24,9 +25,10 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
/**
* Send our Telemetry into the mesh
*/
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool phoneOnly = false);
private:
bool firstTime = 1;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
const MeshPacket *lastMeasurementPacket;
};

View File

@@ -9,6 +9,7 @@
#include "main.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include "MeshService.h"
// Sensors
#include "Sensor/BMP280Sensor.h"
@@ -17,6 +18,8 @@
#include "Sensor/MCP9808Sensor.h"
#include "Sensor/INA260Sensor.h"
#include "Sensor/INA219Sensor.h"
#include "Sensor/SHTC3Sensor.h"
#include "Sensor/LPS22HBSensor.h"
BMP280Sensor bmp280Sensor;
BME280Sensor bme280Sensor;
@@ -24,6 +27,8 @@ BME680Sensor bme680Sensor;
MCP9808Sensor mcp9808Sensor;
INA260Sensor ina260Sensor;
INA219Sensor ina219Sensor;
SHTC3Sensor shtc3Sensor;
LPS22HBSensor lps22hbSensor;
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
@@ -83,21 +88,31 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = ina260Sensor.runOnce();
if (ina219Sensor.hasSensor())
result = ina219Sensor.runOnce();
if (shtc3Sensor.hasSensor())
result = shtc3Sensor.runOnce();
if (lps22hbSensor.hasSensor()) {
result = lps22hbSensor.runOnce();
}
}
return result;
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled)
return result;
// this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval
if (!sendOurTelemetry()) {
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
uint32_t now = millis();
if ((lastSentToMesh == 0 ||
(now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval)) &&
airTime->channelUtilizationPercent() < max_channel_util_percent) {
sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
}
return getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
return sendToPhoneIntervalMs;
#endif
}
@@ -143,7 +158,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, Telemetry_fields, &lastMeasurement)) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("Environment Telemetry: unable to decode last packet");
DEBUG_MSG("Unable to decode last packet");
return;
}
@@ -168,15 +183,14 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
if (t->which_variant == Telemetry_environment_metrics_tag) {
const char *sender = getSenderShortName(mp);
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environment Telemetry: Received data from %s\n", sender);
DEBUG_MSG("Telemetry->time: %i\n", t->time);
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", t->variant.environment_metrics.barometric_pressure);
DEBUG_MSG("Telemetry->current: %f\n", t->variant.environment_metrics.current);
DEBUG_MSG("Telemetry->gas_resistance: %f\n", t->variant.environment_metrics.gas_resistance);
DEBUG_MSG("Telemetry->relative_humidity: %f\n", t->variant.environment_metrics.relative_humidity);
DEBUG_MSG("Telemetry->temperature: %f\n", t->variant.environment_metrics.temperature);
DEBUG_MSG("Telemetry->voltage: %f\n", t->variant.environment_metrics.voltage);
DEBUG_MSG("(Received from %s): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
sender,
t->variant.environment_metrics.barometric_pressure,
t->variant.environment_metrics.current,
t->variant.environment_metrics.gas_resistance,
t->variant.environment_metrics.relative_humidity,
t->variant.environment_metrics.temperature,
t->variant.environment_metrics.voltage);
lastMeasurementPacket = packetPool.allocCopy(mp);
}
@@ -184,7 +198,7 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const MeshPacket &mp, Te
return false; // Let others look at this message also if they want
}
bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies)
bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
Telemetry m;
m.time = getTime();
@@ -197,9 +211,10 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
m.variant.environment_metrics.temperature = 0;
m.variant.environment_metrics.voltage = 0;
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("Environment Telemetry: Read data\n");
if (lps22hbSensor.hasSensor())
lps22hbSensor.getMetrics(&m);
if (shtc3Sensor.hasSensor())
shtc3Sensor.getMetrics(&m);
if (bmp280Sensor.hasSensor())
bmp280Sensor.getMetrics(&m);
if (bme280Sensor.hasSensor())
@@ -213,22 +228,28 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
if (ina260Sensor.hasSensor())
ina260Sensor.getMetrics(&m);
DEBUG_MSG("Telemetry->time: %i\n", m.time);
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", m.variant.environment_metrics.barometric_pressure);
DEBUG_MSG("Telemetry->current: %f\n", m.variant.environment_metrics.current);
DEBUG_MSG("Telemetry->gas_resistance: %f\n", m.variant.environment_metrics.gas_resistance);
DEBUG_MSG("Telemetry->relative_humidity: %f\n", m.variant.environment_metrics.relative_humidity);
DEBUG_MSG("Telemetry->temperature: %f\n", m.variant.environment_metrics.temperature);
DEBUG_MSG("Telemetry->voltage: %f\n", m.variant.environment_metrics.voltage);
DEBUG_MSG("(Sending): barometric_pressure=%f, current=%f, gas_resistance=%f, relative_humidity=%f, temperature=%f, voltage=%f\n",
m.variant.environment_metrics.barometric_pressure,
m.variant.environment_metrics.current,
m.variant.environment_metrics.gas_resistance,
m.variant.environment_metrics.relative_humidity,
m.variant.environment_metrics.temperature,
m.variant.environment_metrics.voltage);
sensor_read_error_count = 0;
MeshPacket *p = allocDataProtobuf(m);
p->to = dest;
p->decoded.want_response = wantReplies;
p->decoded.want_response = false;
p->priority = MeshPacket_Priority_MIN;
lastMeasurementPacket = packetPool.allocCopy(*p);
DEBUG_MSG("Environment Telemetry: Sending packet to mesh");
service.sendToMesh(p, RX_SRC_LOCAL, true);
if (phoneOnly) {
DEBUG_MSG("Sending packet to phone\n");
service.sendToPhone(p);
} else {
DEBUG_MSG("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;
}

View File

@@ -12,7 +12,8 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
: concurrency::OSThread("EnvironmentTelemetryModule"),
ProtobufModule("EnvironmentTelemetry", PortNum_TELEMETRY_APP, &Telemetry_msg)
{
lastMeasurementPacket = nullptr;
lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
}
virtual bool wantUIFrame() override;
#if !HAS_SCREEN
@@ -30,11 +31,13 @@ class EnvironmentTelemetryModule : private concurrency::OSThread, public Protobu
/**
* Send our Telemetry into the mesh
*/
bool sendOurTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
float CelsiusToFahrenheit(float c);
bool firstTime = 1;
const MeshPacket *lastMeasurementPacket;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
uint32_t sensor_read_error_count = 0;
};

View File

@@ -0,0 +1,36 @@
#include "../mesh/generated/telemetry.pb.h"
#include "configuration.h"
#include "TelemetrySensor.h"
#include "LPS22HBSensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
LPS22HBSensor::LPS22HBSensor() :
TelemetrySensor(TelemetrySensorType_LPS22, "LPS22HB")
{
}
int32_t LPS22HBSensor::runOnce() {
DEBUG_MSG("Init sensor: %s\n", sensorName);
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = lps22hb.begin_I2C(nodeTelemetrySensorsMap[sensorType]);
return initI2CSensor();
}
void LPS22HBSensor::setup()
{
lps22hb.setDataRate(LPS22_RATE_10_HZ);
}
bool LPS22HBSensor::getMetrics(Telemetry *measurement) {
sensors_event_t temp;
sensors_event_t pressure;
lps22hb.getEvent(&pressure, &temp);
measurement->variant.environment_metrics.temperature = temp.temperature;
measurement->variant.environment_metrics.barometric_pressure = pressure.pressure;
return true;
}

View File

@@ -0,0 +1,17 @@
#include "../mesh/generated/telemetry.pb.h"
#include "TelemetrySensor.h"
#include <Adafruit_LPS2X.h>
#include <Adafruit_Sensor.h>
class LPS22HBSensor : virtual public TelemetrySensor {
private:
Adafruit_LPS22 lps22hb;
protected:
virtual void setup() override;
public:
LPS22HBSensor();
virtual int32_t runOnce() override;
virtual bool getMetrics(Telemetry *measurement) override;
};

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