Compare commits

...

361 Commits

Author SHA1 Message Date
Ben Meadors
97fd5cf2ab Merge pull request #2000 from meshtastic/develop
Develop upstream
2022-11-26 19:16:24 -06:00
Ben Meadors
d13a095516 Merge pull request #1990 from GUVWAF/develop
Send 'ACK' response for handled admin message
2022-11-26 19:15:36 -06:00
Ben Meadors
4dc7d92cf1 Merge pull request #1999 from meshtastic/master
Fix conditional syntax
2022-11-26 15:09:56 -06:00
Ben Meadors
e7dbbeb606 Fix conditional syntax 2022-11-26 14:50:07 -06:00
GUVWAF
3e892fc391 Merge branch 'meshtastic:develop' into develop 2022-11-26 21:14:52 +01:00
Ben Meadors
dfec37dfd0 Merge pull request #1996 from meshtastic/master
Develop downstream
2022-11-26 12:59:54 -06:00
Ben Meadors
b82ab34f85 Merge pull request #1993 from meshtastic/potential-sx1262-fix
Don't set DIO2 switch if TXEN is defined
2022-11-26 12:59:02 -06:00
Ben Meadors
18a2cfeda4 Merge branch 'master' into potential-sx1262-fix 2022-11-26 10:18:14 -06:00
Thomas Göttgens
082aa07e7f update batch scripts to further check filename. 2022-11-26 17:00:33 +01:00
Ben Meadors
a703ab4418 Merge branch 'master' into potential-sx1262-fix 2022-11-26 09:07:59 -06:00
Thomas Göttgens
185ceac9df Merge pull request #1994 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-26 16:06:12 +01:00
caveman99
7c9cada50e [create-pull-request] automated change 2022-11-26 15:04:12 +00:00
Thomas Göttgens
a5ba3dd445 revert protobuf change to develop 2022-11-26 16:03:17 +01:00
Ben Meadors
63838a1632 Merge branch 'master' into potential-sx1262-fix 2022-11-26 08:19:13 -06:00
Ben Meadors
30d7f188e2 Merge pull request #1991 from meshtastic/develop
Merge develop to master
2022-11-26 08:18:59 -06:00
Ben Meadors
47a47f1e69 Merge branch 'master' into develop 2022-11-26 08:18:35 -06:00
Ben Meadors
daac79f314 Merge branch 'master' into potential-sx1262-fix 2022-11-26 08:13:05 -06:00
Ben Meadors
1864216e78 Merge pull request #1992 from lewisxhe/master
Fix the format of t-echo Bluetooth pairing display page
2022-11-26 08:12:55 -06:00
Ben Meadors
71c0cf9b9a Don't set DIO2 switch if TXEN is defined 2022-11-26 08:11:32 -06:00
Ben Meadors
ef87ddb798 Merge branch 'master' into master 2022-11-26 07:44:19 -06:00
Ben Meadors
711c748b44 Merge pull request #1986 from IhorNehrutsa/MESSAGES
Some DEBUG_MSG added/changed/commented.
2022-11-26 07:44:12 -06:00
lewis
6eff09a260 Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2022-11-26 21:38:07 +08:00
lewis
c5fe878a6f Fix the format of t-echo Bluetooth pairing display page 2022-11-26 21:37:32 +08:00
Thomas Göttgens
39948c76de Merge branch 'master' into develop 2022-11-26 14:19:27 +01:00
Ben Meadors
10f14d27b7 Merge branch 'master' into MESSAGES 2022-11-26 07:13:20 -06:00
Ben Meadors
5e9d722b7d Merge pull request #1987 from lewisxhe/master
Add t-echo to the operation after the flash operation fails
2022-11-26 06:59:03 -06:00
Ben Meadors
b324c04097 Merge branch 'master' into master 2022-11-26 06:44:28 -06:00
Ben Meadors
84a9d95b1f Merge branch 'master' into MESSAGES 2022-11-26 06:43:52 -06:00
lewis
cdd499f147 Add missing restart parameters 2022-11-26 12:10:10 +08:00
GUVWAF
c45a85547e Send 'ACK' response for admin message 2022-11-25 20:33:24 +01:00
GUVWAF
8815746006 Fix wrong comment 2022-11-25 20:33:23 +01:00
Garth Vander Houwen
32a1e8ef0d Create feature.yml 2022-11-25 09:44:26 -08:00
lewis
0dff4538f3 Add t-echo to the operation after the flash operation fails 2022-11-26 00:17:54 +08:00
Ihor Nehrutsa
6507683909 Squashed commit of the following:
commit c8d1bcf04fae5f7ac5b639ddd15a738045014c95
Author: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Date:   Fri Nov 25 15:11:18 2022 +0200

    Revert "variants\tbeam\variant.h: Use LORA_CS instead of RF95_NSS"

    This reverts commit 8d225ced9c.

commit 1c37097448393ea9364c2b9bf10522802c61d5c4
Author: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Date:   Fri Nov 25 15:04:09 2022 +0200

    Some little debugs added

commit f1b55e11af
Author: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Date:   Wed Nov 23 15:24:58 2022 +0200

    Update variant.h

commit 8d225ced9c
Author: Ihor Nehrutsa <Ihor.Nehrutsa@gmail.com>
Date:   Wed Nov 23 13:06:49 2022 +0200

    variants\tbeam\variant.h: Use LORA_CS instead of RF95_NSS
2022-11-25 15:17:24 +02:00
Ben Meadors
c71e32970c Merge pull request #1982 from meshtastic/master
Master to Develop
2022-11-24 08:07:24 -06:00
Thomas Göttgens
fcf21da843 one radiolib to rule them all 2022-11-24 13:55:57 +01:00
Thomas Göttgens
ab464fe038 compress better 2022-11-24 13:07:37 +01:00
Thomas Göttgens
fd546af2a5 don't package meshtasticd simulator
that saves 5 MB on every zip.
2022-11-24 12:36:47 +01:00
Thomas Göttgens
acfbe202b6 include alternative update bin without bootloader and settings 2022-11-24 12:33:19 +01:00
Thomas Göttgens
29fb283daf adaptig for #1938 2022-11-24 12:30:15 +01:00
Thomas Göttgens
51ef9b7fbe fix RP2040 and Portduino Platforms 2022-11-24 12:24:57 +01:00
Thomas Göttgens
025d2264a2 m5stack runs with native tone support now. 2022-11-24 10:44:43 +01:00
Thomas Göttgens
b2284b2097 Tone now included in arduino core for ESP32. 2022-11-24 10:30:11 +01:00
Thomas Göttgens
5f8267c956 use the buzzer for external notification module 2022-11-24 10:11:42 +01:00
Thomas Göttgens
cf783a5bae make GPS pins configurable through protos 2022-11-24 09:23:17 +01:00
Thomas Göttgens
32e5ced814 regen protos 2022-11-24 09:22:50 +01:00
Thomas Göttgens
605fadabcf Merge branch 'master' of github.com:meshtastic/firmware 2022-11-24 00:03:45 +01:00
Thomas Göttgens
e91ace7329 Merge pull request #1980 from meshtastic/master
Master Merge again
2022-11-24 00:02:35 +01:00
Thomas Göttgens
c87cd136d4 Merge pull request #1979 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-24 00:01:39 +01:00
Thomas Göttgens
0d7d59609a Remove gpio binding for notification module. 2022-11-23 23:49:29 +01:00
thebentern
75ed0e5906 [create-pull-request] automated change 2022-11-23 22:49:22 +00:00
Thomas Göttgens
8e3b500307 ---EXPERIMENTAL--- reboot the board if the NO_AP_FOUND error comes back. 2022-11-23 23:47:50 +01:00
Thomas Göttgens
d6f77bf07e Merge pull request #1978 from meshtastic/master
Master to Develop
2022-11-23 23:44:42 +01:00
Ben Meadors
65e8209d51 Merge pull request #1976 from markbirss/master
M5Stack CoreInk enable buzzer
2022-11-23 14:32:18 -06:00
Ben Meadors
aae5247caa Merge pull request #1977 from meshtastic/hotfix-reset-nodedb
Hotfix Add reset nodedb handler back
2022-11-23 14:31:50 -06:00
Ben Meadors
2fedb6b774 Add reset nodedb handler back 2022-11-23 14:12:44 -06:00
Mark Trevor Birss
02d18d4831 Merge branch 'master' into master 2022-11-23 21:53:12 +02:00
Ben Meadors
b70c2d088d Merge pull request #1975 from GUVWAF/master
Revert "Override RoutingModule's ACK if on wrong channel"
2022-11-23 13:50:42 -06:00
Mark Trevor Birss
b3c396683e Update platformio.ini 2022-11-23 21:25:19 +02:00
Mark Trevor Birss
f08874dd37 Update platformio.ini 2022-11-23 21:24:34 +02:00
Mark Trevor Birss
648054da9b Add files via upload 2022-11-23 21:19:20 +02:00
GUVWAF
70bf7c490c Revert "Override RoutingModule's ACK if on wrong channel"
This reverts commit 71c163a8ee.
2022-11-23 19:27:57 +01:00
Thomas Göttgens
adbed5de95 - fix NTP sync on connect
- disable extended GPS mode again
- add --inline-suppr to cppflags
2022-11-22 17:19:24 +01:00
Thomas Göttgens
fe989f0bff Merge pull request #1973 from meshtastic/master
Develop refresh to Master
2022-11-22 17:08:04 +01:00
Thomas Göttgens
679e346bcb change old field denominator 2022-11-22 16:47:54 +01:00
Thomas Göttgens
832439b336 strange enough _that_ suppression works 2022-11-22 15:56:13 +01:00
Thomas Göttgens
71c2af04ec why is this working on pio/windows? 2022-11-22 15:03:01 +01:00
Ben Meadors
0f4261d02f Merge pull request #1972 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-22 07:40:41 -06:00
Thomas Göttgens
23466d8eee yank that dreaded json11 - first try 2022-11-22 14:29:00 +01:00
thebentern
8edbba2180 [create-pull-request] automated change 2022-11-22 00:56:46 +00:00
Ben Meadors
5417671332 Merge pull request #1971 from GUVWAF/master
Cover two ACK/NAK edge cases for admin packets
2022-11-21 18:11:25 -06:00
Ben Meadors
35d7e11678 Merge branch 'master' into master 2022-11-21 16:36:11 -06:00
Ben Meadors
7a63ba827b Merge pull request #1965 from meshtastic/transactional-config-edits
Only save and reboot while a transaction isnt open
2022-11-21 16:12:55 -06:00
GUVWAF
71c163a8ee Override RoutingModule's ACK if on wrong channel 2022-11-21 20:43:17 +01:00
GUVWAF
5d8e661807 Send NAK on primary channel if it cannot decode it 2022-11-21 20:43:17 +01:00
Ben Meadors
24244e8474 Update AdminModule.cpp 2022-11-21 12:24:05 -06:00
Ben Meadors
fb4f9bdc40 Merge branch 'master' into transactional-config-edits 2022-11-21 12:10:49 -06:00
Ben Meadors
668c46e0cf Merge pull request #1968 from meshtastic/develop
Merge develop upstream
2022-11-21 12:10:14 -06:00
Ben Meadors
abf8fdb661 Merge branch 'master' into develop 2022-11-21 09:39:22 -06:00
Ben Meadors
a28a04b7a0 Merge pull request #1964 from meshtastic/mqtt-init-defaults
Init default mqtt configurations
2022-11-21 09:39:10 -06:00
Ben Meadors
cd9671650b Merge branch 'master' into mqtt-init-defaults 2022-11-21 09:39:05 -06:00
Ben Meadors
00bc762bf1 Merge branch 'master' into develop 2022-11-21 09:38:46 -06:00
Thomas Göttgens
9a065bce03 Merge pull request #1970 from meshtastic/caveman99-OLED-FIX
fix TLora V1 Boards Display Init
2022-11-21 16:37:55 +01:00
Thomas Göttgens
3b2b0bdc97 fix TLora V1 Boards Display Init 2022-11-21 15:50:47 +01:00
Ben Meadors
53cd6bdf15 Merge branch 'master' into develop 2022-11-21 07:35:46 -06:00
Thomas Göttgens
edc97c1c07 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-21 14:28:45 +01:00
Ben Meadors
6a24ef2263 Merge branch 'master' into transactional-config-edits 2022-11-21 07:26:18 -06:00
Ben Meadors
50ba523fb4 Merge branch 'master' into mqtt-init-defaults 2022-11-21 07:14:47 -06:00
Thomas Göttgens
a33325f90f update web server reference to latest commit 2022-11-21 13:46:22 +01:00
Thomas Göttgens
a173b7159a Merge pull request #1967 from D4rk4/SAST
Remove empty workflow file
2022-11-21 09:01:16 +01:00
Thomas Göttgens
91295d3772 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-21 08:50:53 +01:00
Dmitry Galenko
9c1c04a8db Merge branch 'master' into SAST 2022-11-21 08:14:39 +01:00
Dmitry Galenko
51d0d0d779 Fix empty workflow 2022-11-21 08:13:28 +01:00
Dmitry Galenko
9cdf627ae3 Revert "Fix empty workflow"
This reverts commit 4b9c482384.
2022-11-21 08:12:52 +01:00
Dmitry Galenko
4b9c482384 Fix empty workflow 2022-11-21 08:10:21 +01:00
Ben Meadors
b1ba807ec9 Only save and reboot while a transaction isnt open 2022-11-20 19:50:45 -06:00
Ben Meadors
c844f153e1 Merge branch 'master' into mqtt-init-defaults 2022-11-20 15:31:54 -06:00
Thomas Göttgens
4a2b02347f Keymatrix Bugfix: Allow key 3 to send associated text
Feature: setting a text "~" emulates IO5/Userbutton with keymatrix.
2022-11-20 20:59:48 +01:00
Thomas Göttgens
e8a05d1874 Merge pull request #1947 from meshtastic/bug-1821
testing issues with RAK11200/13300
2022-11-20 19:40:52 +01:00
Ben Meadors
08c4e3fbd6 Merge branch 'master' into mqtt-init-defaults 2022-11-20 12:29:47 -06:00
Ben Meadors
1c5292ac86 Init default mqtt configurations 2022-11-20 12:29:10 -06:00
Ben Meadors
aa553ea5d8 Merge pull request #1958 from D4rk4/SAST
Implement automatic static code scan with Semgrep & Flawfinder
2022-11-20 11:10:19 -06:00
Thomas Göttgens
a00bd59e27 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-20 18:03:18 +01:00
Thomas Göttgens
f02c6c49ee Merge branch 'master' into bug-1821 2022-11-20 17:26:42 +01:00
Dmitry Galenko
e54e37a600 Rename security workflows to sec_* 2022-11-20 16:17:58 +01:00
Dmitry Galenko
b95103cab0 Run flawfinder only on push to specific branch 2022-11-20 16:16:04 +01:00
Dmitry Galenko
9b43e49116 Ignore upstream defect 2022-11-20 16:14:32 +01:00
Ben Meadors
457538c8f6 Merge branch 'master' into SAST 2022-11-20 08:13:47 -06:00
Ben Meadors
da48f0704b Merge pull request #1960 from D4rk4/SEC
Security fixes
2022-11-20 08:05:04 -06:00
Dmitry Galenko
cf8d953bba Merge branch 'master' into SAST 2022-11-20 14:41:51 +01:00
Dmitry Galenko
5f2b859e38 Merge branch 'master' into SEC 2022-11-20 14:37:46 +01:00
Dmitry Galenko
3187b5abda Revert "Missed STDC_LIB_EXT1"
This reverts commit 4392df0676.
2022-11-20 14:29:05 +01:00
Ben Meadors
ce16b50d5f Change docker push critera 2022-11-20 07:05:49 -06:00
Dmitry Galenko
4295720770 Add flawfinder for cover C++ codebase 2022-11-20 13:50:38 +01:00
Dmitry Galenko
4392df0676 Missed STDC_LIB_EXT1 2022-11-20 13:27:55 +01:00
Dmitry Galenko
4ec3b025f0 look like https://sg.run/jkdn not hit us 2022-11-20 13:19:47 +01:00
Dmitry Galenko
f4704181e9 Fix potential buffer clean issue 2022-11-20 13:12:51 +01:00
Dmitry Galenko
0e04bea39e Fix for Dockerfile-related security defects and rewrite to follow best practices 2022-11-20 12:57:55 +01:00
Thomas Göttgens
b54044fd00 if we have a filename, 'address' is the line number. Don't print that in hex ;-)
If it's really a hex address, prefix it with 0x
2022-11-20 12:00:57 +01:00
Dmitry Galenko
08c69c09c8 Fix branch name 2022-11-20 11:58:15 +01:00
Dmitry Galenko
681ea420c1 Implement automatic static code scan with Semgrep 2022-11-20 10:53:11 +01:00
Sacha Weatherstone
48ea54748f Fix build instructions link 2022-11-20 06:38:17 +00:00
Ben Meadors
4b7627595a Merge branch 'master' into bug-1821 2022-11-19 20:05:03 -06:00
Ben Meadors
6299e5483b Input boards 2022-11-19 19:39:39 -06:00
Ben Meadors
6118a966a6 Move em up 2022-11-19 19:30:19 -06:00
Ben Meadors
1fac9ee1f2 More reusable workflows 2022-11-19 19:23:35 -06:00
Ben Meadors
1e06b2d51e I think understand now 2022-11-19 18:57:06 -06:00
Ben Meadors
f3a6ed9d61 Rename to action 2022-11-19 18:53:42 -06:00
Ben Meadors
f71cbb6f6e Move to actions folder 2022-11-19 18:50:50 -06:00
Ben Meadors
23ea22c741 Checkout master first 2022-11-19 18:42:27 -06:00
Ben Meadors
8be65bb0ab Move the checkout 2022-11-19 18:40:17 -06:00
Ben Meadors
57e2e75d24 Add shells 2022-11-19 18:35:00 -06:00
Ben Meadors
29cd7568f5 Try a composite action instead 2022-11-19 18:30:43 -06:00
Ben Meadors
581076a5a1 Now let's take it further 2022-11-19 18:07:07 -06:00
Ben Meadors
27401bb9b8 Remove runs-on 2022-11-19 17:48:01 -06:00
Ben Meadors
10837ce549 With block 2022-11-19 17:45:33 -06:00
Ben Meadors
1dcd411d00 Fix indention 2022-11-19 17:43:18 -06:00
Ben Meadors
0533fd9227 Uses 2022-11-19 17:35:47 -06:00
Ben Meadors
5ce7ffc888 Show contents 2022-11-19 16:51:33 -06:00
Ben Meadors
9e914de995 Try going up a dir 2022-11-19 16:46:36 -06:00
Ben Meadors
0cc653263e Indent 2022-11-19 16:39:05 -06:00
Ben Meadors
d2d2f278cf Apparently checkout before using a local workflow 2022-11-19 16:25:00 -06:00
Ben Meadors
eb34a95ab7 Why fight me? 2022-11-19 16:23:09 -06:00
Ben Meadors
eb1f6c0de6 Root path? 2022-11-19 16:13:26 -06:00
Ben Meadors
8de79e8fb6 Path 2022-11-19 16:08:11 -06:00
Ben Meadors
fe00f0c369 Uses block 2022-11-19 16:06:59 -06:00
Ben Meadors
f9ee8583b0 Merge pull request #1956 from meshtastic/docker-hub-and-ci-overhaul
Docker hub and ci overhaul
2022-11-19 16:04:21 -06:00
Ben Meadors
a4d5f8c717 Reusable workflow 2022-11-19 16:03:55 -06:00
Ben Meadors
35c50f074b Build and push to docker hub 2022-11-19 15:44:59 -06:00
Ben Meadors
dcfa226509 Remove extra git submodule update 2022-11-19 15:42:08 -06:00
Thomas Göttgens
a9fde30a58 Merge branch 'master' into bug-1821 2022-11-19 10:00:41 +01:00
Thomas Göttgens
7ceb52103e Cleaning up GPS Code a bit 2022-11-19 09:58:29 +01:00
Thomas Göttgens
8da5d37888 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-19 09:56:11 +01:00
Thomas Göttgens
95cc328b5c That wifi update didn't go down well. 2022-11-18 19:37:56 +01:00
Thomas Göttgens
990c0119a7 fix portduino - again 2022-11-18 18:22:35 +01:00
Thomas Göttgens
144afee29e trigger wifi reconnect by mqtt or ntp failures. 2022-11-18 18:03:30 +01:00
Thomas Göttgens
9665c08b59 MQTT: don't subscribe to JSON topic if JSON is disabled in config. 2022-11-17 21:14:49 +01:00
Ben Meadors
20ee6a509d Remove more targets from checks 2022-11-17 13:35:16 -06:00
Thomas Göttgens
70d44b8838 next try. 2022-11-17 20:19:11 +01:00
Thomas Göttgens
b260c8b058 tryfix wifi issues 2022-11-17 20:09:08 +01:00
Thomas Göttgens
5991b59ba3 try fixing Wifi reconnects - don't manually reconnect and set auto-reconnect at the same time. 2022-11-17 17:48:46 +01:00
Ben Meadors
bc1fed0fb4 Merge branch 'bug-1821' of https://github.com/meshtastic/firmware into bug-1821 2022-11-15 16:23:08 -06:00
Ben Meadors
b23c364fc0 Test it this way 2022-11-15 16:22:53 -06:00
Thomas Göttgens
28b428c5a0 potential fix for 13300 2022-11-15 22:54:31 +01:00
Thomas Göttgens
5bfc58ed64 testing issues with RAK11200/13300 2022-11-15 21:55:27 +01:00
Thomas Göttgens
e9a34fca7b Portduino Radiolib upstream 2022-11-15 17:01:15 +01:00
Thomas Göttgens
6ce9734ddd Merge pull request #1944 from meshtastic/master
Master Merge
2022-11-15 11:06:14 +01:00
Thomas Göttgens
d42797ffeb fix Portduino Step 1 2022-11-15 10:49:55 +01:00
Thomas Göttgens
b5ebfa9cc3 Portduino WIP 2022-11-15 07:59:01 +01:00
Thomas Göttgens
79eff42c3c Fix and Break radiolib 2022-11-14 10:53:16 +01:00
Thomas Göttgens
7022807fa3 Merge pull request #1943 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-14 10:01:13 +01:00
Thomas Göttgens
50a301899e start to sort radiolib out. If we have macros, use them! :-)
Also we need Godmode for the SX1280 for now, hopefully can revert to more sane operation.
2022-11-14 09:49:50 +01:00
thebentern
351db5f6ef [create-pull-request] automated change 2022-11-14 08:40:21 +00:00
Ben Meadors
09fe616ac5 This number is a joke 2022-11-13 18:16:40 -06:00
Ben Meadors
2d7ff39ecc Merge pull request #1942 from meshtastic/develop
Develop to Master
2022-11-13 15:42:41 -06:00
Ben Meadors
6e856efd0e Merge branch 'master' into develop 2022-11-13 14:45:48 -06:00
Ben Meadors
c3c899bc85 Upstream protos for resolving conflicts 2022-11-13 14:45:26 -06:00
Ben Meadors
916f3cac41 Sync protos 2022-11-13 14:40:18 -06:00
Ben Meadors
9b5f358823 Add new heltec targets 2022-11-13 14:30:32 -06:00
Ben Meadors
22119c272d Merge pull request #1941 from meshtastic/add-heltec-wsl
Add Heltec Wireless Stick Lite V3 support
2022-11-13 14:09:50 -06:00
Ben Meadors
8d4c526d16 Add Heltec Wireless Stick Lite V3 support 2022-11-13 13:28:02 -06:00
Ben Meadors
83aebb7a00 Merge pull request #1940 from meshtastic/add-heltec-v3
Added support for Heltec V3
2022-11-13 10:31:37 -06:00
Ben Meadors
33cd5ce6c1 Cleanup 2022-11-13 09:48:38 -06:00
Ben Meadors
f22c2e768e Reorder 2022-11-13 09:47:55 -06:00
Ben Meadors
3d7dea0606 Added support for Heltec V3 2022-11-13 09:45:16 -06:00
Thomas Göttgens
263a421c4a fix pico build 2022-11-13 15:35:18 +01:00
Thomas Göttgens
401b92bdbb reverted too much 2022-11-13 15:28:43 +01:00
Thomas Göttgens
6a696af8f6 Revert "remember which devices were scanned on which bus and set them accordingly." - this is not working at all. 2022-11-13 14:56:52 +01:00
Thomas Göttgens
037d6c253b fix portduino 2022-11-13 11:58:02 +01:00
Thomas Göttgens
b6de79b21a fix build for RP2040 which actually has 2 TwoWire interfaces. 2022-11-12 17:50:33 +01:00
Thomas Göttgens
52cf530356 missing 2 sensor changes 2022-11-12 17:18:17 +01:00
Thomas Göttgens
861ded37db remember which devices were scanned on which bus and set them accordingly. 2022-11-12 17:12:40 +01:00
Thomas Göttgens
7a67388a97 Merge branch 'master' of github.com:meshtastic/firmware into develop 2022-11-12 14:34:51 +01:00
Thomas Göttgens
4f60fad3f6 Merge pull request #1936 from lewisxhe/master
Update tbeam-s3 variant
2022-11-12 14:12:11 +01:00
lewis he
67efd8172a Merge branch 'master' into master 2022-11-12 20:11:52 +08:00
lewis
60fdf9fcb2 Place PMU initialization before scanI2Cdevice 2022-11-12 20:09:25 +08:00
Thomas Göttgens
a606e9b7b5 Merge pull request #1935 from puzzled-pancake/patch-1
Update NZ_865 to 36dBm
2022-11-12 11:55:37 +01:00
Thomas Göttgens
65197a8e48 - Add new Compass Sensor
- speed up I2C Scanning
- make adding sensors less error prone
2022-11-12 11:03:29 +01:00
lewishe
43f769ebac Resolve compilation conflicts 2022-11-12 16:01:30 +08:00
lewishe
dff6eeb90e Merge branch 'master' of https://github.com/lewisxhe/Meshtastic-device 2022-11-12 15:16:54 +08:00
lewishe
61ebdb3367 Add SD card initialization 2022-11-12 15:14:13 +08:00
lewishe
cd95d0865f Repair the sharing of Wire1 between RTC and PMU in tbeams3 2022-11-12 15:12:53 +08:00
lewishe
b68a026627 Update tbeam-s3 variant mapping 2022-11-12 14:39:42 +08:00
lewishe
68ccebafbf Add low-speed crystal initialization for ESP32S3 2022-11-12 14:38:48 +08:00
puzzled-pancake
3737252d39 Update NZ_865 to 36dBm
Updated NZ_865 to 36dBm as per:
https://rrf.rsm.govt.nz/smart-web/smart/page/-smart/domain/licence/LicenceSummary.wdk?id=219752

6dBW = 36dBm/4watt
2022-11-12 17:55:28 +13:00
lewis he
888a8d05c4 Merge branch 'meshtastic:master' into master 2022-11-12 09:56:18 +08:00
Thomas Göttgens
f25f902c20 max power for the 1280 is +13dBm 2022-11-11 08:59:16 +01:00
Thomas Göttgens
a6ea5496b4 Fixed DIO Pin mapping. SX1280 is working 2022-11-10 23:26:31 +01:00
Thomas Göttgens
222424a80c no excuses, this was a SNAFU 2022-11-10 23:06:37 +01:00
Thomas Göttgens
74f31d7d68 Fix SX1280 init 2022-11-10 23:00:01 +01:00
Thomas Göttgens
5c59c8d701 GPS Update 2022-11-10 22:21:07 +01:00
Ben Meadors
30a87e3145 Switch to a smaller sample of devices for cppcheck 2022-11-10 07:26:28 -06:00
Thomas Göttgens
87f7a60f71 fix #1931 coordinates inserted into NMES stream 2022-11-10 13:51:22 +01:00
Thomas Göttgens
f7d8885257 update coordinates for DMS display too 2022-11-10 13:50:38 +01:00
Thomas Göttgens
77410dc3c3 Merge pull request #1932 from meshtastic/master
Master Merge
2022-11-10 11:02:38 +01:00
Thomas Göttgens
d1acf02ee8 Master Merge 2022-11-10 11:01:36 +01:00
Thomas Göttgens
de0954f307 switch to upstream Ethernet lib 2022-11-10 09:35:56 +01:00
Ben Meadors
7da1e5c3e8 Merge pull request #1930 from meshtastic/bug-1928
fix #1928 valid NMEA sentences
2022-11-09 18:06:01 -06:00
Thomas Göttgens
3c11e87197 Merge pull request #1927 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-09 23:43:35 +01:00
Thomas Göttgens
b004706eff fix #1928 valid NMEA sentences 2022-11-09 23:42:52 +01:00
thebentern
2247e71a52 [create-pull-request] automated change 2022-11-09 21:39:27 +00:00
Ben Meadors
8146e84200 Merge pull request #1926 from GUVWAF/master
Set preamble length back to 32
2022-11-09 14:29:54 -06:00
GUVWAF
1213ec2d57 Set preamble length back to 32 2022-11-09 21:21:50 +01:00
Thomas Göttgens
30b6cca366 Merge pull request #1925 from meshtastic/bug-1914
fix #1914 and clean up rangetest a bit
2022-11-09 15:14:47 +01:00
Thomas Göttgens
4dd140a887 fix #1914 and clean up rangetest a bit 2022-11-09 15:12:57 +01:00
Ben Meadors
87c555bde3 Changed retention policy 2022-11-09 14:48:53 +01:00
Ben Meadors
c4951b1236 Build cleanup and update deprecated platformio cmd 2022-11-09 14:48:53 +01:00
thebentern
0249eb1307 [create-pull-request] automated change 2022-11-09 14:48:53 +01:00
Ben Meadors
f0279e7f92 Merge pull request #1923 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-09 07:33:27 -06:00
Ben Meadors
1a50181ace Merge branch 'master' into create-pull-request/patch 2022-11-09 07:33:02 -06:00
Ben Meadors
d77bc239c1 Changed retention policy 2022-11-09 07:20:53 -06:00
Ben Meadors
cb283f4c57 Build cleanup and update deprecated platformio cmd 2022-11-09 07:14:08 -06:00
Thomas Göttgens
803858ab0a change default pins for codec2 to work on TLORA 2.1-1.8 2022-11-09 11:50:13 +01:00
thebentern
728fc8cbad [create-pull-request] automated change 2022-11-08 22:51:44 +00:00
Thomas Göttgens
ad05b91f89 Merge pull request #1922 from meshtastic/develop
fix #1916
2022-11-08 23:15:04 +01:00
Thomas Göttgens
671e6cde44 Merge branch 'master' into develop 2022-11-08 22:33:38 +01:00
Thomas Göttgens
7a3ad0afba fix #1916 2022-11-08 22:32:53 +01:00
Ben Meadors
d9f1704e36 Merge pull request #1921 from meshtastic/update-phoneapi
Updated admin module and protobufs
2022-11-08 15:32:20 -06:00
Ben Meadors
32223a818c Updated admin module and protobufs 2022-11-08 15:04:24 -06:00
Thomas Göttgens
31e13d4de3 Merge pull request #1920 from meshtastic/develop
rename wifi_mode to eth_mode
2022-11-08 21:55:06 +01:00
Thomas Göttgens
815bd6321b Merge branch 'master' into develop 2022-11-08 21:54:38 +01:00
Thomas Göttgens
9f9bd40343 rename wifi_mode to eth_mode 2022-11-08 21:53:44 +01:00
Ben Meadors
2331226bb6 Bump version 2022-11-08 07:27:48 -06:00
Ben Meadors
80ff118f0f Merge pull request #1918 from meshtastic/develop
Develop to master
2022-11-08 07:26:14 -06:00
Ben Meadors
d6eeda7136 Merge pull request #1917 from meshtastic/master
Master Rollup
2022-11-08 07:25:40 -06:00
Ben Meadors
fb92e498f0 Merge pull request #1902 from GUVWAF/develop
Change preambleLength to 8 symbols to reduce airtime
2022-11-08 07:25:02 -06:00
Ben Meadors
bf8d8886fd Merge branch 'develop' into master 2022-11-08 07:20:29 -06:00
Ben Meadors
a695726f2a Merge pull request #1912 from meshtastic/docker-compose
Added docker compose multiple nodes example
2022-11-08 07:12:36 -06:00
Ben Meadors
6dc4172110 Merge branch 'master' into docker-compose 2022-11-08 07:12:21 -06:00
Thomas Göttgens
25a9ee8eb6 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-08 13:40:07 +01:00
Ben Meadors
e122232761 Removed defunct line 2022-11-07 13:29:34 -06:00
Ben Meadors
b13eaee6b3 More fun 2022-11-07 13:28:37 -06:00
Ben Meadors
f0f5107a5d Added docker compose 4 nodes example 2022-11-06 19:22:20 -06:00
Ben Meadors
0832cc50a8 Add a docker-compose 2022-11-06 13:19:49 -06:00
Thomas Göttgens
962a3d0c55 Merge pull request #1911 from meshtastic/caveman99-patch-1
Fix assert
2022-11-06 19:06:26 +01:00
Thomas Göttgens
6934e0bce7 Fix assert 2022-11-06 18:36:17 +01:00
Ben Meadors
3492d64177 Alpine 2022-11-06 18:22:52 +01:00
Thomas Göttgens
057109dcac Reduce retention to 30 days. 2022-11-06 18:22:52 +01:00
Ben Meadors
12fa08007d Docker is back 2022-11-06 18:22:52 +01:00
Ben Meadors
3562d34555 Remove flag 2022-11-06 18:22:52 +01:00
Ben Meadors
3ca6f645d4 Portduino build flags 2022-11-06 18:22:52 +01:00
Ben Meadors
6694d31d07 Somehow I still missed one :-| 2022-11-06 18:22:52 +01:00
Ben Meadors
d15edf1955 Update NMEAWPL.h 2022-11-06 18:22:52 +01:00
Ben Meadors
e1ce037550 Update NMEAWPL.cpp 2022-11-06 18:22:52 +01:00
Ben Meadors
f9c376a524 Update NMEAWPL.cpp 2022-11-06 18:22:52 +01:00
Ben Meadors
26a907444c Fix for alpine linux builds 2022-11-06 18:22:52 +01:00
Ben Meadors
5c214bf4d8 Merge pull request #1908 from meshtastic/docker-returns
Docker is back
2022-11-06 09:31:24 -06:00
Ben Meadors
5151a5641e Merge branch 'master' into docker-returns 2022-11-06 09:31:02 -06:00
Ben Meadors
9513209b70 Alpine 2022-11-06 09:30:46 -06:00
Thomas Göttgens
f1416ac9f7 Reduce retention to 30 days. 2022-11-06 14:49:02 +01:00
Thomas Göttgens
631db56a44 Next try, plus change cppcheck defines back. 2022-11-06 14:32:02 +01:00
Thomas Göttgens
7b378d36cc try to make cppcheck happy again 2022-11-06 13:29:01 +01:00
Thomas Göttgens
8ab269e1b3 revert BME680 to default settings, they are working good. Our init was just replicating what's in the lib anyway. 2022-11-06 10:52:54 +01:00
Thomas Göttgens
7652253b8d optimize BME680 usage 2022-11-06 10:37:14 +01:00
Ben Meadors
9805319940 Docker is back 2022-11-05 21:08:29 -05:00
Ben Meadors
e1e607cba3 Remove flag 2022-11-05 19:09:04 -05:00
Ben Meadors
d74bcd3583 Portduino build flags 2022-11-05 18:21:35 -05:00
Ben Meadors
9c0483975c Somehow I still missed one :-| 2022-11-05 15:34:54 -05:00
Ben Meadors
2fb85dc129 Merge pull request #1906 from meshtastic/thebentern-patch-1
Fix for alpine linux builds
2022-11-05 15:30:10 -05:00
Ben Meadors
d641adc0fc Update NMEAWPL.h 2022-11-05 15:20:09 -05:00
Ben Meadors
a7a020f431 Update NMEAWPL.cpp 2022-11-05 15:14:08 -05:00
Ben Meadors
a08ac5a47e Update NMEAWPL.cpp 2022-11-05 15:11:11 -05:00
Ben Meadors
30e5706eaa Fix for alpine linux builds 2022-11-05 15:10:43 -05:00
Thomas Göttgens
16444c190d Ignore Band power limits for licensed HAMs 2022-11-05 20:13:47 +01:00
Thomas Göttgens
3d9633a56c Different Sensor access, should prevent overheating/wrong measurements. 2022-11-05 20:12:41 +01:00
GUVWAF
c0e630522c Merge branch 'meshtastic:develop' into develop 2022-11-05 19:09:36 +01:00
Ben Meadors
9422d31f55 Merge pull request #1905 from meshtastic/trying-again
Trying again
2022-11-05 09:35:51 -05:00
Ben Meadors
087c7c19af Update protos 2022-11-05 09:34:33 -05:00
Ben Meadors
3476b35fca Merge remote-tracking branch 'origin/master' into trying-again 2022-11-05 09:33:39 -05:00
Ben Meadors
950d5defda Master to develop (resolves conflicts) (#1903)
* Rearranging deck chairs, 900M22S working, 30S not

* We do have wire, just not where it's expected

* Put more of the module specific pins in their blocks

* tryfix compile with NO_SCREEN

* Portduino only: don't continue to try rebooting (#1887)

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>

* Support for TLORA 2.1-1.8

* Don't allow arbitrary channel name for admin (#1886)

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

* Experimental DIY nrf52840 feather support (#1884)

* Experimental DIY nrf52840 feather support

* Fix target

* sx1262 wiring

* Remove lib

* Don't consider Response as ACK for FloodingRouter (#1885)

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

* Fix feather diy (#1892)

* Fix variant

* Fix feather diy target

* [modules][external notifications] allow select channel to listen to

* Fix feather diy pin mapping (#1894)

Thanks to @markbirss

* [create-pull-request] automated change

* Override Screen Autodtect

* Maybe fix crash of this board.

* Fixes reset loop with new espressif32 platform on tlora-v2

 Sending a pulse to the OLED_RESET Pin 16 results in a reset loop using recent version of the espressif32 platform.

* Experiment with self hosted action runner

* Fix MQTT on ETH

* revert the tryfix

* Cheating

* Cleanup artifacts older than 1 month

* Update cleanup_artifacts.yml

* Update cleanup_artifacts.yml

* Update cleanup_artifacts.yml

* Delete cleanup_artifacts.yml

* fix: use RF95_IRQ for wakeup source in doLightSleep (#1899)

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>

* Update protos

* Update protos

Co-authored-by: code8buster <communismisgreat@national.shitposting.agency>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: GUVWAF <78759985+GUVWAF@users.noreply.github.com>
Co-authored-by: Mykhailo Lesyk <m@lesyk.org>
Co-authored-by: Mykhailo Lesyk <lesykm@users.noreply.github.com>
Co-authored-by: caveman99 <caveman99@users.noreply.github.com>
Co-authored-by: he-leon <he-leon@users.noreply.github.com>
Co-authored-by: Lars Weber <weber@weber-software.com>
2022-11-05 09:28:41 -05:00
Ben Meadors
c6f060a24f Add develop to CI 2022-11-05 09:21:51 -05:00
Thomas Göttgens
1716c4d6f9 Allow static IP for WLAN
and portentially fix reconnect issues
2022-11-05 15:02:06 +01:00
Ben Meadors
cda7a60734 Update protos 2022-11-05 08:43:44 -05:00
Lars Weber
ed26ab801c fix: use RF95_IRQ for wakeup source in doLightSleep (#1899)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-11-05 08:37:00 -05:00
Thomas Göttgens
8874a6e488 update protos 2022-11-05 14:18:57 +01:00
Thomas Göttgens
657ae44b6f Merge branch 'master' of github.com:meshtastic/firmware 2022-11-05 14:11:19 +01:00
Ben Meadors
01381057c5 Delete cleanup_artifacts.yml 2022-11-05 08:06:28 -05:00
Ben Meadors
3dc6ed5672 Update cleanup_artifacts.yml 2022-11-05 06:57:47 -05:00
Ben Meadors
764b48e04a Update cleanup_artifacts.yml 2022-11-05 06:47:00 -05:00
Ben Meadors
4c931967c7 Update cleanup_artifacts.yml 2022-11-05 06:44:08 -05:00
Ben Meadors
a547a791ba Cleanup artifacts older than 1 month 2022-11-05 06:42:53 -05:00
GUVWAF
176072801b Change preambleLength to 8 symbols to reduce airtime 2022-11-05 09:58:10 +01:00
Thomas Göttgens
b941c51cf7 Merge pull request #1900 from meshtastic/mqtt-eth
Mqtt eth
2022-11-04 23:13:18 +01:00
Thomas Göttgens
8a9fd6846e Merge branch 'master' into mqtt-eth 2022-11-04 22:44:42 +01:00
Ben Meadors
a49355133c Cheating 2022-11-04 14:23:22 -05:00
Thomas Göttgens
09cdc20440 manual merge of changes from Master 2022-11-04 19:56:44 +01:00
Thomas Göttgens
1c0dfe47c8 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-04 19:51:22 +01:00
Thomas Göttgens
66623693eb Merge branch 'master' into mqtt-eth 2022-11-04 19:48:57 +01:00
Thomas Göttgens
7c692444e5 revert the tryfix 2022-11-04 19:48:28 +01:00
Thomas Göttgens
4ccb4393c5 Fix MQTT on ETH 2022-11-04 19:44:45 +01:00
Ben Meadors
b2e540b114 Experiment with self hosted action runner 2022-11-04 13:43:16 -05:00
Thomas Göttgens
a5d1165c54 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-04 19:34:35 +01:00
Thomas Göttgens
aa321e06dd Merge pull request #1898 from he-leon/patch-1
Fixes reset loop with new espressif32 platform on tlora-v2
2022-11-04 19:26:16 +01:00
he-leon
8b84ac8a6c Fixes reset loop with new espressif32 platform on tlora-v2
Sending a pulse to the OLED_RESET Pin 16 results in a reset loop using recent version of the espressif32 platform.
2022-11-04 16:48:49 +01:00
Thomas Göttgens
6c07fbfc12 Merge pull request #1896 from meshtastic/oled-config
Oled config
2022-11-03 23:05:09 +01:00
Thomas Göttgens
04a478a5ad Maybe fix crash of this board. 2022-11-03 22:50:54 +01:00
Thomas Göttgens
acfa186d44 Override Screen Autodtect 2022-11-03 22:44:22 +01:00
Thomas Göttgens
3db504c470 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-03 22:38:05 +01:00
Thomas Göttgens
3e5955be44 Merge pull request #1895 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-11-03 22:36:16 +01:00
caveman99
f1afbf2c0f [create-pull-request] automated change 2022-11-03 21:35:06 +00:00
Thomas Göttgens
20c559382d Merge branch 'master' of github.com:meshtastic/firmware 2022-11-03 22:32:27 +01:00
Thomas Göttgens
a3f1c02347 Merge pull request #1882 from lesykm/ext_notification_channel
[modules][external notifications] allow select channel to listen to
2022-11-03 22:21:43 +01:00
Ben Meadors
f5945d429e Merge branch 'master' into ext_notification_channel 2022-11-03 14:29:15 -05:00
Ben Meadors
a3eced53bb Fix feather diy pin mapping (#1894)
Thanks to @markbirss
2022-11-03 14:28:49 -05:00
Thomas Göttgens
20686cc66a Show boot logo / OEM Logo longer - 5 seconds each now. 2022-11-03 09:46:32 +01:00
Thomas Göttgens
5608fa32f7 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-03 08:29:28 +01:00
Mykhailo Lesyk
a0c5defda6 Merge branch 'master' into ext_notification_channel 2022-11-02 20:34:23 -07:00
Mykhailo Lesyk
25a3a09d5f [modules][external notifications] allow select channel to listen to 2022-11-02 20:31:28 -07:00
Ben Meadors
593301146e Fix feather diy (#1892)
* Fix variant

* Fix feather diy target
2022-11-02 15:57:47 -05:00
GUVWAF
5715ddc361 Don't consider Response as ACK for FloodingRouter (#1885)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-11-02 14:32:18 -05:00
Thomas Göttgens
09ddde177c codec2 Audio Support for SX1280 (untested) 2022-11-02 18:23:41 +01:00
Ben Meadors
ef18b173cd Experimental DIY nrf52840 feather support (#1884)
* Experimental DIY nrf52840 feather support

* Fix target

* sx1262 wiring

* Remove lib
2022-11-02 18:19:09 +01:00
GUVWAF
ac4e88e0d2 Don't allow arbitrary channel name for admin (#1886)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-11-02 18:19:09 +01:00
Thomas Göttgens
3e82cd7dd4 Support for TLORA 2.1-1.8 2022-11-02 18:19:09 +01:00
GUVWAF
b1f2025558 Portduino only: don't continue to try rebooting (#1887)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-11-02 18:19:09 +01:00
Thomas Göttgens
57ca5fea81 tryfix compile with NO_SCREEN 2022-11-02 18:19:09 +01:00
code8buster
0ce018cf97 Put more of the module specific pins in their blocks 2022-11-02 18:19:09 +01:00
code8buster
15a8710e69 We do have wire, just not where it's expected 2022-11-02 18:19:09 +01:00
code8buster
cae75dcb6d Rearranging deck chairs, 900M22S working, 30S not 2022-11-02 18:19:09 +01:00
Thomas Göttgens
d5e2b70b71 Merge pull request #1888 from meshtastic/TLORA-18
Support for TLORA 2.1-1.8
2022-11-02 18:16:44 +01:00
Thomas Göttgens
05b9fd04c6 switch submodule branch to develop 2022-11-02 15:08:49 +01:00
Thomas Göttgens
4650989774 Merge branch 'master' into TLORA-18 2022-11-02 15:01:40 +01:00
Thomas Göttgens
bcc77efb88 Merge branch 'master' of github.com:meshtastic/firmware 2022-11-02 14:13:04 +01:00
Ben Meadors
39c1637030 Experimental DIY nrf52840 feather support (#1884)
* Experimental DIY nrf52840 feather support

* Fix target

* sx1262 wiring

* Remove lib
2022-11-02 07:48:14 -05:00
Ben Meadors
6d3028f213 Merge branch 'master' into TLORA-18 2022-11-02 07:20:39 -05:00
GUVWAF
b2969b2faf Don't allow arbitrary channel name for admin (#1886)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-11-02 07:18:15 -05:00
Thomas Göttgens
d07350e4a4 Merge branch 'master' into TLORA-18 2022-11-02 13:14:51 +01:00
Thomas Göttgens
12df55c3d4 Support for TLORA 2.1-1.8 2022-11-02 13:12:15 +01:00
GUVWAF
85b541bfd9 Portduino only: don't continue to try rebooting (#1887)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-11-02 06:58:14 -05:00
Thomas Göttgens
a9c6d6a80c Merge pull request #1878 from code8buster/master
Making meshtastic-dr-dev E22-900M22S/M30S work alternately
2022-11-02 10:34:08 +01:00
Thomas Göttgens
32ad8aaa4e tryfix compile with NO_SCREEN 2022-11-02 10:17:59 +01:00
code8buster
3d8e6aead2 Put more of the module specific pins in their blocks 2022-10-31 21:54:05 -04:00
code8buster
2747600a3a Merge branch 'meshtastic:master' into master 2022-11-01 01:35:34 +00:00
Thomas Göttgens
b7ef63230b new location of ota firmware 2022-10-31 14:50:31 +01:00
Ben Meadors
b4d6c8f37b Update verbiage 2022-10-31 08:32:21 -05:00
Ben Meadors
6a907348b4 Merge branch 'master' into master 2022-10-31 08:17:37 -05:00
Ben Meadors
760d463bf5 Merge branch 'master' into master 2022-10-31 06:12:16 -05:00
code8buster
8fa71afb72 We do have wire, just not where it's expected 2022-10-30 22:30:33 -04:00
code8buster
309a3d5396 Rearranging deck chairs, 900M22S working, 30S not 2022-10-30 22:28:25 -04:00
lewis he
da2279c295 Merge branch 'meshtastic:master' into master 2022-10-22 18:22:12 +08:00
lewishe
13e635b74e Add judgment on t-beam-s3-core to scanI2Cdevice in main.cpp 2022-10-10 11:50:18 +08:00
121 changed files with 3434 additions and 1157 deletions

27
.github/ISSUE_TEMPLATE/feature.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Feature Request
description: Request a new feature
title: "[Feature Request]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for your request this will not gurantee that we will implement it, but it will be reviewed.
- type: dropdown
id: soc
attributes:
label: Platform
description: What device platform will support your feature?
multiple: true
options:
- NRF52
- ESP32
validations:
required: true
- type: textarea
id: body
attributes:
label: Description
description: Please provide details about your enhancement.
validations:
required: true

41
.github/actions/setup-base/action.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: 'Setup Build Base Composite Action'
description: 'Base build actions for Meshtastic Platform IO steps'
runs:
using: "composite"
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install cppcheck
shell: bash
run: |
sudo apt-get install -y cppcheck
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
shell: bash
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
shell: bash
run: |
pio upgrade

54
.github/workflows/build_esp32.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Build ESP32
on:
workflow_call:
inputs:
board:
required: true
type: string
jobs:
build-esp32:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "meshtastic/web"
file: "build.tar"
target: "build.tar"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- name: Build ESP32
run: bin/build-esp32.sh ${{ inputs.board }}
- name: Pull OTA Firmware
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "meshtastic/firmware-ota"
file: "firmware.bin"
target: "release/bleota.bin"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get release version string
shell: bash
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.bin
release/*.elf

33
.github/workflows/build_nrf52.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Build NRF52
on:
workflow_call:
inputs:
board:
required: true
type: string
jobs:
build-nrf52:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build NRF52
run: bin/build-nrf52.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf
release/*.zip

32
.github/workflows/build_rpi2040.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Build RPI2040
on:
workflow_call:
inputs:
board:
required: true
type: string
jobs:
build-rpi2040:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Build Raspberry Pi 2040
run: ./bin/build-rpi2040.sh ${{ inputs.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf

View File

@@ -2,14 +2,14 @@ name: CI
on:
# # Triggers the workflow on push but only for the master branch
push:
branches: [master]
branches: [master, develop]
paths-ignore:
- "**.md"
- "version.properties"
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
pull_request_target:
branches: [master]
branches: [master, develop]
paths-ignore:
- "**.md"
#- "**.yml"
@@ -23,60 +23,22 @@ jobs:
matrix:
include:
- board: rak11200
- board: tlora-v2
- board: tlora-v1
- board: tlora_v1_3
- board: tlora-v2-1-1.6
- board: tbeam
- board: heltec-v1
- board: heltec-v2.0
- board: heltec-v2.1
- board: tbeam0.7
- board: meshtastic-diy-v1
- board: meshtastic-dr-dev
- board: rak4631
- board: rak4631_eink
- board: t-echo
- board: nano-g1
- board: station-g1
- board: m5stack-core
- board: m5stack-coreink
- board: tbeam-s3-core
# - board: pico
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install cppcheck
run: |
sudo apt-get install -y cppcheck
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools and install platformio
run: |
python -m pip install --upgrade pip
pip install -U platformio
- name: Upgrade platformio
run: |
pio upgrade
- uses: actions/checkout@v3
- name: Build base
id: base
uses: ./.github/actions/setup-base
- name: Check ${{ matrix.board }}
run: bin/check-all.sh ${{ matrix.board }}
@@ -95,6 +57,8 @@ jobs:
- board: heltec-v1
- board: heltec-v2.0
- board: heltec-v2.1
- board: heltec-v3
- board: heltec-wsl-v3
- board: tbeam0.7
- board: meshtastic-diy-v1
- board: meshtastic-dr-dev
@@ -103,73 +67,9 @@ jobs:
- board: m5stack-core
- board: m5stack-coreink
- board: tbeam-s3-core
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
- name: Upgrade platformio
run: |
pio upgrade
- name: Pull web ui
uses: dsaltares/fetch-gh-release-asset@master
with:
repo: "meshtastic/web"
file: "build.tar"
target: "build.tar"
token: ${{ secrets.GITHUB_TOKEN }}
- name: Unpack web ui
run: |
tar -xf build.tar -C data/static
rm build.tar
- 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 "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.bin
release/*.elf
retention-days: 90
uses: ./.github/workflows/build_esp32.yml
with:
board: ${{ matrix.board }}
build-nrf52:
strategy:
@@ -181,53 +81,10 @@ jobs:
- board: rak4631_eink
- board: t-echo
- board: pca10059_diy_eink
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
- name: Upgrade platformio
run: |
pio upgrade
- name: Build NRF52
run: bin/build-nrf52.sh ${{ matrix.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf
release/*.zip
retention-days: 90
- board: feather_diy
uses: ./.github/workflows/build_nrf52.yml
with:
board: ${{ matrix.board }}
build-rpi2040:
strategy:
@@ -236,84 +93,17 @@ jobs:
matrix:
include:
- board: pico
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
- name: Upgrade platformio
run: |
pio upgrade
- name: Build Raspberry Pi 2040
run: ./bin/build-rpi2040.sh ${{ matrix.board }}
- name: Get release version string
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- name: Store binaries as an artifact
uses: actions/upload-artifact@v3
with:
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
path: |
release/*.uf2
release/*.elf
retention-days: 90
uses: ./.github/workflows/build_rpi2040.yml
with:
board: ${{ matrix.board }}
build-native:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
submodules: "recursive"
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Cache python libs
uses: actions/cache@v3
id: cache-pip # needed in if test
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip
- name: Upgrade python tools
run: |
python -m pip install --upgrade pip
pip install -U platformio adafruit-nrfutil
pip install -U meshtastic --pre
- name: Upgrade platformio
run: |
pio upgrade
- uses: actions/checkout@v3
- name: Build base
id: base
uses: ./.github/actions/setup-base
# We now run integration test before other build steps (to quickly see runtime failures)
- name: Build for native
@@ -337,11 +127,29 @@ jobs:
with:
name: firmware-native-${{ steps.version.outputs.version }}.zip
path: |
release/meshtasticd_linux_amd64
release/device-*.sh
release/device-*.bat
retention-days: 90
- name: Docker login
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/login-action@v2
with:
username: meshtastic
password: ${{ secrets.DOCKER_TOKEN }}
- name: Docker setup
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/setup-buildx-action@v2
- name: Docker build and push
if: ${{ github.event_name == 'workflow_dispatch' }}
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: meshtastic/device-simulator:latest
after-checks:
runs-on: ubuntu-latest
needs: [check]
@@ -371,7 +179,7 @@ jobs:
id: version
- name: Move files up
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/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
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
- name: Repackage in single firmware zip
uses: actions/upload-artifact@v3
@@ -381,7 +189,6 @@ jobs:
./*.bin
./*.uf2
./firmware-*-ota.zip
./meshtasticd_linux_amd64
./device-*.sh
./device-*.bat
retention-days: 90
@@ -401,14 +208,14 @@ jobs:
chmod +x ./output/device-update.sh
- name: Zip firmware
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v3
with:
name: debug-elfs-${{ steps.version.outputs.version }}.zip
path: ./*.elf
retention-days: 90
retention-days: 30
- name: Create request artifacts
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
@@ -450,7 +257,7 @@ jobs:
chmod +x ./output/device-update.sh
- name: Zip firmware
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
- uses: actions/download-artifact@v3
with:
@@ -458,7 +265,7 @@ jobs:
path: ./elfs
- name: Zip Elfs
run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
run: zip -j -9 -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
# For diagnostics
- name: Show artifacts
@@ -470,7 +277,7 @@ jobs:
with:
draft: true
prerelease: true
release_name: Meshtastic Device ${{ steps.version.outputs.version }} Alpha
release_name: Meshtastic Firmware ${{ steps.version.outputs.version }}
tag_name: v${{ steps.version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...

View File

@@ -0,0 +1,40 @@
---
name: Flawfinder Scan
on:
push:
branches: [master, develop]
paths-ignore:
- "**.md"
- "version.properties"
jobs:
flawfinder:
runs-on: ubuntu-latest
name: Flawfinder
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
# step 2
- name: flawfinder_scan
uses: david-a-wheeler/flawfinder@2.0.19
with:
arguments: '--sarif ./'
output: 'flawfinder_report.sarif'
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v3
with:
name: flawfinder_report.sarif
path: flawfinder_report.sarif
# step 4
- name: publish code scanning alerts
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: flawfinder_report.sarif
category: flawfinder

View File

@@ -0,0 +1,44 @@
---
name: Semgrep Full Scan
on:
workflow_dispatch:
branches:
- master
schedule:
- cron: '0 1 * * 6'
jobs:
semgrep-full:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
# step 2
- name: full scan
run: |
semgrep \
--sarif --output report.sarif \
--metrics=off \
--config="p/default"
# step 3
- name: save report as pipeline artifact
uses: actions/upload-artifact@v3
with:
name: report.sarif
path: report.sarif
# step 4
- name: publish code scanning alerts
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: report.sarif
category: semgrep

View File

@@ -0,0 +1,28 @@
---
name: Semgrep Differential Scan
on:
pull_request
jobs:
semgrep-diff:
runs-on: ubuntu-latest
container:
image: returntocorp/semgrep
steps:
# step 1
- name: clone application source code
uses: actions/checkout@v3
with:
fetch-depth: 0
# step 2
- name: differential scan
run: |
semgrep scan \
--error \
--metrics=off \
--baseline-commit ${{ github.event.pull_request.base.sha }} \
--config="p/default"

2
.semgrepignore Normal file
View File

@@ -0,0 +1,2 @@
.github/workflows/main_matrix.yml
src/mesh/compression/unishox2.c

41
Dockerfile Normal file
View File

@@ -0,0 +1,41 @@
FROM debian:bullseye-slim AS builder
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
# http://bugs.python.org/issue19846
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
ENV LANG C.UTF-8
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install build deps
USER root
RUN apt-get update && \
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates
# create a non-priveleged user & group
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
USER mesh
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \
chmod +x /tmp/get-platformio.py && \
python3 /tmp/get-platformio.py && \
git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \
cd /tmp/firmware && \
chmod +x /tmp/firmware/bin/build-native.sh && \
source ~/.platformio/penv/bin/activate && \
./bin/build-native.sh
FROM frolvlad/alpine-glibc
RUN apk --update add --no-cache g++ shadow && \
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_amd64 /home/mesh/
USER mesh
WORKDIR /home/mesh
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'"
HEALTHCHECK NONE

View File

@@ -10,7 +10,7 @@
This repository contains the device firmware for the Meshtastic project.
**[Building Instructions](https://meshtastic.org/docs/developers/Firmware/build)**
**[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
**[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
## Stats

View File

@@ -31,7 +31,7 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6

View File

@@ -31,7 +31,7 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6

View File

@@ -1,5 +1,7 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base]
platform = https://github.com/meshtastic/platform-native.git#096b3c3e9c5c8e19d4c3b6cd803fffef2a9be4c5
framework = arduino
build_src_filter =
${env.build_src_filter}
-<platform/esp32/>
@@ -16,5 +18,4 @@ 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

View File

@@ -1,109 +0,0 @@
#!/usr/bin/env bash
set -e
VERSION=`bin/buildinfo.py long`
SHORT_VERSION=`bin/buildinfo.py short`
BOARDS_ESP32="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"
#BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
BOARDS_NRF52="rak4631 rak4631_eink t-echo pca10059_diy_eink"
#BOARDS_NRF52=""
OUTDIR=release/latest
# We keep all old builds (and their map files in the archive dir)
ARCHIVEDIR=release/archive
rm -f $OUTDIR/firmware*
mkdir -p $OUTDIR/bins $ARCHIVEDIR
rm -r $OUTDIR/bins/* || true
mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal
# build the named environment and copy the bins to the release directory
function do_build() {
BOARD=$1
isNrf=$3
echo "Building for $BOARD ($isNrf) with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$BOARD/firmware.*
# The shell vars the build tool expects to find
export APP_VERSION=$VERSION
basename=universal/firmware-$BOARD-$VERSION
pio run --environment $BOARD # -v
SRCELF=.pio/build/$BOARD/firmware.elf
cp $SRCELF $OUTDIR/elfs/$basename.elf
if [ "$isNrf" = "false" ]
then
echo "Copying ESP32 bin file"
SRCBIN=.pio/build/$BOARD/firmware.bin
cp $SRCBIN $OUTDIR/bins/$basename.bin
else
echo "Generating NRF52 uf2 file"
SRCHEX=.pio/build/$BOARD/firmware.hex
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/$basename.uf2 -f 0xADA52840
fi
}
function do_boards() {
declare boards=$1
declare isNrf=$2
for board in $boards; do
# Build universal
echo "about to build $board $isNrf"
do_build $board "" "$isNrf"
done
}
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
do_boards "$BOARDS_ESP32" "false"
do_boards "$BOARDS_NRF52" "true"
pio run --environment native
cp .pio/build/native/program $OUTDIR/bins/universal/meshtasticd_linux_amd64
echo "Building Filesystem for ESP32 targets"
pio run --environment tbeam -t buildfs
cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/littlefs-$VERSION.bin
# keep the bins in archive also
cp $OUTDIR/bins/universal/littlefs* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR
echo Updating android bins $OUTDIR/forandroid
rm -rf $OUTDIR/forandroid
mkdir -p $OUTDIR/forandroid
cp -a $OUTDIR/bins/universal/*.bin $OUTDIR/forandroid/
cat >$OUTDIR/curfirmwareversion.xml <<XML
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is kept in source control because it reflects the last stable
release. It is used by the android app for forcing software updates. Do not edit.
Generated by bin/buildall.sh -->
<resources>
<string name="cur_firmware_version" translatable="false">$VERSION</string>
<string name="short_firmware_version" translatable="false">$SHORT_VERSION</string>
</resources>
XML
echo Generating $ARCHIVEDIR/firmware-$VERSION.zip
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/littlefs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* $OUTDIR/bins/universal/meshtasticd* images/system-info.bin bin/device-install.* bin/device-update.*
echo Generating $ARCHIVEDIR/elfs-$VERSION.zip
rm -f $ARCHIVEDIR/elfs-$VERSION.zip
zip --junk-paths $ARCHIVEDIR/elfs-$VERSION.zip $OUTDIR/elfs/universal/firmware-*-$VERSION.*
echo BUILT ALL

View File

@@ -10,11 +10,8 @@ OUTDIR=release/
rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
platformio pkg update
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.*
@@ -32,6 +29,10 @@ echo "Copying ESP32 bin file"
SRCBIN=.pio/build/$1/firmware.factory.bin
cp $SRCBIN $OUTDIR/$basename.bin
echo "Copying ESP32 update bin file"
SRCBIN=.pio/build/$1/firmware.bin
cp $SRCBIN $OUTDIR/$basename-update.bin
echo "Building Filesystem for ESP32 targets"
pio run --environment tbeam -t buildfs
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin

View File

@@ -12,11 +12,8 @@ rm -f $OUTDIR/firmware*
mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
platformio pkg update
pio run --environment native
cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64

View File

@@ -10,11 +10,8 @@ OUTDIR=release/
rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
platformio pkg update
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.*

View File

@@ -10,11 +10,8 @@ OUTDIR=release/
rm -f $OUTDIR/firmware*
rm -r $OUTDIR/* || true
# Make sure our submodules are current
git submodule update
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
platformio lib update
platformio pkg update
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
rm -f .pio/build/$1/firmware.*

View File

@@ -26,7 +26,7 @@ IF "__%FILENAME%__" == "____" (
echo "Missing FILENAME"
goto HELP
)
IF EXIST %FILENAME% (
IF EXIST %FILENAME% IF x%FILENAME:update=%==x%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 0x00 %FILENAME%
@@ -37,6 +37,9 @@ IF EXIST %FILENAME% (
) else (
echo "Invalid file: %FILENAME%"
goto HELP
) else (
echo "Invalid file: %FILENAME%"
goto HELP
)
:EOF

View File

@@ -14,6 +14,7 @@ Flash image file to device, but first erasing and writing system information"
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The .bin file to flash. Custom to your device type and region.
EOF
}
@@ -44,7 +45,7 @@ shift "$((OPTIND-1))"
shift
}
if [ -f "${FILENAME}" ]; then
if [ -f "${FILENAME}" ] && [[ "${FILENAME}" != *"update"* ]]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
"$PYTHON" -m esptool erase_flash
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
@@ -52,8 +53,8 @@ if [ -f "${FILENAME}" ]; then
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
else
echo "Invalid file: ${FILENAME}"
show_help
echo "Invalid file: ${FILENAME}"
fi
exit 0

View File

@@ -10,7 +10,7 @@ echo.
echo -h Display this help and exit
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
echo -f FILENAME The *update.bin file to flash. Custom to your device type.
goto EOF
:GETOPTS
@@ -26,9 +26,12 @@ IF "__%FILENAME%__" == "____" (
echo "Missing FILENAME"
goto HELP
)
IF EXIST %FILENAME% (
IF EXIST %FILENAME% IF NOT x%FILENAME:update=%==x%FILENAME% (
echo Trying to flash update %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
) else (
echo "Invalid file: %FILENAME%"
goto HELP
) else (
echo "Invalid file: %FILENAME%"
goto HELP

View File

@@ -11,7 +11,8 @@ Flash image file to device, leave existing system intact."
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The .bin file to flash. Custom to your device type and region.
-f FILENAME The *update.bin file to flash. Custom to your device type.
EOF
}
@@ -42,12 +43,12 @@ shift "$((OPTIND-1))"
shift
}
if [ -f "${FILENAME}" ]; then
echo "Trying to flash update ${FILENAME}."
$PYTHON -m esptool --baud 115200 write_flash 0x00 ${FILENAME}
if [ -f "${FILENAME}" ] && [[ $FILENAME == *"update"* ]]; then
printf "Trying to flash update ${FILENAME}"
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
else
echo "Invalid file: ${FILENAME}"
show_help
echo "Invalid file: ${FILENAME}"
fi
exit 0

13
docker-compose.yml Normal file
View File

@@ -0,0 +1,13 @@
version: "3.7"
services:
meshtastic-node:
build: .
deploy:
mode: replicated
replicas: 4
networks:
- mesh
networks:
mesh:

View File

@@ -37,12 +37,24 @@ extra_scripts = bin/platformio-custom.py
; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile
; of code is a heap corruption bug!
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need.
build_flags = -Wno-missing-field-initializers
-Wno-format
-Isrc -Isrc/mesh -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
-DUSE_THREAD_NAMES
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
-DPB_ENABLE_MALLOC=1
-DRADIOLIB_EXCLUDE_CC1101
-DRADIOLIB_EXCLUDE_NRF24
-DRADIOLIB_EXCLUDE_RF69
-DRADIOLIB_EXCLUDE_SX1231
-DRADIOLIB_EXCLUDE_SI443X
-DRADIOLIB_EXCLUDE_RFM2X
-DRADIOLIB_EXCLUDE_AFSK
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
-DRADIOLIB_EXCLUDE_MORSE
-DRADIOLIB_EXCLUDE_RTTY
-DRADIOLIB_EXCLUDE_SSTV
monitor_speed = 115200
@@ -50,30 +62,29 @@ 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
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
https://github.com/meshtastic/TinyGPSPlus.git#2f0d0528d737000043e949f4c3bdfb623cf0b902
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
nanopb/Nanopb@^0.4.6
erriez/ErriezCRC32@^1.0.1
jgromes/RadioLib@^5.5.0
; Used for the code analysis in PIO Home / Inspect
check_tool = cppcheck
check_skip_packages = yes
check_flags =
--common-flag
cppcheck: --enable=--inline-suppr
-DAPP_VERSION=1.0.0
--suppressions-list=suppressions.txt
--inline-suppr
; Common settings for conventional (non Portduino) Arduino targets
[arduino_base]
framework = arduino
lib_deps =
${env.lib_deps}
; Portduino is using meshtastic fork for now
jgromes/RadioLib@5.4.1
mprograms/QMC5883LCompass@^1.1.1
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76
build_flags = ${env.build_flags} -Os
-DRADIOLIB_SPI_PARANOID=0
# -DRADIOLIB_GODMODE
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
; Common libs for communicating over TCP/IP networks such as MQTT
@@ -81,7 +92,6 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/>
lib_deps =
knolleary/PubSubClient@^2.8
arduino-libraries/NTPClient@^3.1.0
meshtastic/json11@^1.0.2
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)

View File

@@ -1,6 +1,18 @@
#include "configuration.h"
#include "FSCommon.h"
#ifdef HAS_SDCARD
#include <SPI.h>
#include <SD.h>
#ifdef SDCARD_USE_SPI1
SPIClass SPI1(HSPI);
#define SDHandler SPI1
#endif
#endif //HAS_SDCARD
bool copyFile(const char* from, const char* to)
{
@@ -169,3 +181,39 @@ void fsInit()
listDir("/", 10);
#endif
}
void setupSDCard()
{
#ifdef HAS_SDCARD
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
if (!SD.begin(SDCARD_CS, SDHandler)) {
DEBUG_MSG("No SD_MMC card detected\n");
return ;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
DEBUG_MSG("No SD_MMC card attached\n");
return ;
}
DEBUG_MSG("SD_MMC Card Type: ");
if (cardType == CARD_MMC) {
DEBUG_MSG("MMC\n");
} else if (cardType == CARD_SD) {
DEBUG_MSG("SDSC\n");
} else if (cardType == CARD_SDHC) {
DEBUG_MSG("SDHC\n");
} else {
DEBUG_MSG("UNKNOWN\n");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
DEBUG_MSG("SD Card Size: %lluMB\n", cardSize);
DEBUG_MSG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
DEBUG_MSG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
#endif
}

View File

@@ -44,3 +44,4 @@ bool copyFile(const char* from, const char* to);
bool renameFile(const char* pathFrom, const char* pathTo);
void listDir(const char * dirname, uint8_t levels, boolean del);
void rmDir(const char * dirname);
void setupSDCard();

View File

@@ -25,22 +25,6 @@ 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;
// 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()
{

View File

@@ -2,22 +2,13 @@
#include "configuration.h"
#include "NodeDB.h"
#ifndef PIN_BUZZER
// Noop methods for boards w/o buzzer
void playBeep(){};
void playStartMelody(){};
void playShutdownMelody(){};
#else
#ifdef M5STACK
#include "Speaker.h"
TONE Tone;
#else
#if !defined(ARCH_ESP32) && !defined(ARCH_RP2040) && !defined(ARCH_PORTDUINO)
#include "Tone.h"
#endif
#if !defined(ARCH_PORTDUINO)
extern "C" void delay(uint32_t dwMs);
#endif
struct ToneDuration {
int frequency_khz;
@@ -43,30 +34,25 @@ const int DURATION_1_8 = 125; // 1/8 note
const int DURATION_1_4 = 250; // 1/4 note
void playTones(const ToneDuration *tone_durations, int size) {
if (config.network.eth_enabled != true) {
#ifdef PIN_BUZZER
if (!config.device.buzzer_gpio)
config.device.buzzer_gpio = PIN_BUZZER;
#endif
if (config.device.buzzer_gpio) {
for (int i = 0; i < size; i++) {
const auto &tone_duration = tone_durations[i];
#ifdef M5STACK
Tone.tone(tone_duration.frequency_khz);
delay(tone_duration.duration_ms);
Tone.mute();
#else
tone(PIN_BUZZER, tone_duration.frequency_khz, tone_duration.duration_ms);
#endif
tone(config.device.buzzer_gpio, tone_duration.frequency_khz, tone_duration.duration_ms);
// to distinguish the notes, set a minimum time between them.
delay(1.3 * tone_duration.duration_ms);
}
}
}
#ifdef M5STACK
void playBeep() {
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}};
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
#else
void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
#endif
void playStartMelody() {
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8},
@@ -75,11 +61,9 @@ void playStartMelody() {
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
}
void playShutdownMelody() {
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

@@ -110,6 +110,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define INA_ADDR_ALTERNATE 0x41
#define QMC6310_ADDR 0x1C
#define QMI8658_ADDR 0x6B
#define QMC5883L_ADDR 0x1E
#define SHTC3_ADDR 0x70
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D

View File

@@ -12,7 +12,7 @@
void printATECCInfo()
{
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: ");
@@ -90,7 +90,7 @@ uint8_t oled_probe(byte addr)
return o_probe;
}
void scanI2Cdevice(void)
void scanI2Cdevice()
{
byte err, addr;
uint16_t registerValue = 0x00;
@@ -106,16 +106,16 @@ void scanI2Cdevice(void)
if (addr == SSD1306_ADDRESS) {
screen_found = addr;
screen_model = oled_probe(addr);
if (screen_model == 1){
if (screen_model == 1) {
DEBUG_MSG("ssd1306 display found\n");
} else if (screen_model == 2){
} else if (screen_model == 2) {
DEBUG_MSG("sh1106 display found\n");
} else {
DEBUG_MSG("unknown display found\n");
}
}
#ifndef ARCH_PORTDUINO
if (addr == ATECC608B_ADDR){
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (addr == ATECC608B_ADDR) {
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {
DEBUG_MSG("ATECC608B initialized\n");
@@ -163,50 +163,56 @@ void scanI2Cdevice(void)
DEBUG_MSG("axp192/axp2101 PMU found\n");
}
#endif
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
if (registerValue == 0x61) {
DEBUG_MSG("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr;
} else if (registerValue == 0x60) {
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
} else {
DEBUG_MSG("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr;
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
if (registerValue == 0x61) {
DEBUG_MSG("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr;
} else if (registerValue == 0x60) {
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
} else {
DEBUG_MSG("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr;
}
}
}
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xFE, 2);
DEBUG_MSG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
DEBUG_MSG("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr;
} else { // Assume INA219 if INA260 ID is not found
DEBUG_MSG("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr;
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
registerValue = getRegisterValue(addr, 0xFE, 2);
DEBUG_MSG("Register MFG_UID: 0x%x\n", registerValue);
if (registerValue == 0x5449) {
DEBUG_MSG("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr;
} else { // Assume INA219 if INA260 ID is not found
DEBUG_MSG("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr;
}
}
if (addr == MCP9808_ADDR) {
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
DEBUG_MSG("MCP9808 sensor found\n");
}
if (addr == SHTC3_ADDR) {
DEBUG_MSG("SHTC3 sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
}
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
DEBUG_MSG("LPS22HB sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
}
// High rate sensors, will be processed internally
if (addr == QMC6310_ADDR) {
DEBUG_MSG("QMC6310 Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
}
if (addr == QMI8658_ADDR) {
DEBUG_MSG("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
}
if (addr == QMC5883L_ADDR) {
DEBUG_MSG("QMC5883L Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[TelemetrySensorType_QMC5883L] = addr;
}
}
if (addr == MCP9808_ADDR) {
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);
}
@@ -218,5 +224,5 @@ void scanI2Cdevice(void)
DEBUG_MSG("%i I2C devices found\n",nDevices);
}
#else
void scanI2Cdevice(void) {}
void scanI2Cdevice() {}
#endif

View File

@@ -150,9 +150,21 @@ bool GPS::setupGPS()
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
// if the overrides are not dialled in, set them from the board definitions, if they exist
#if defined(GPS_RX_PIN)
if (!config.position.rx_gpio)
config.position.rx_gpio = GPS_RX_PIN;
#endif
#if defined(GPS_TX_PIN)
if (!config.position.tx_gpio)
config.position.tx_gpio = GPS_TX_PIN;
#endif
// ESP32 has a special set of parameters vs other arduino ports
#if defined(GPS_RX_PIN) && defined(ARCH_ESP32)
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
#if defined(ARCH_ESP32)
if(config.position.rx_gpio)
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio);
#else
_serial_gps->begin(GPS_BAUDRATE);
#endif

View File

@@ -109,7 +109,7 @@ bool NMEAGPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
fixType = atoi(gsafixtype.value()); // will set to zero if no data
DEBUG_MSG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
// DEBUG_MSG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
#endif
// check if GPS has an acceptable lock
@@ -168,7 +168,7 @@ bool NMEAGPS::lookForLocation()
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.HDOP = reader.hdop.value();
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
DEBUG_MSG("PDOP=%d, HDOP=%d\n", dop, reader.hdop.value());
// DEBUG_MSG("PDOP=%d, HDOP=%d\n", p.PDOP, p.HDOP);
#else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)

View File

@@ -1,4 +1,5 @@
#include "NMEAWPL.h"
#include "GeoCoord.h"
/* -------------------------------------------
* 1 2 3 4 5 6
@@ -15,11 +16,19 @@
* -------------------------------------------
*/
uint printWPL(char *buf, const Position &pos, const char *name)
uint32_t 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++) {
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude);
uint32_t len = sprintf(buf, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s",
geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(),
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(),
name);
uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);
@@ -50,25 +59,30 @@ uint printWPL(char *buf, const Position &pos, const char *name)
* -------------------------------------------
*/
uint printGGA(char *buf, const Position &pos)
uint32_t 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",
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude);
uint32_t len = sprintf(buf, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%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',
geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(),
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(),
pos.fix_type,
pos.sats_in_view,
pos.HDOP,
pos.altitude,
geoCoord.getAltitude(),
'M',
pos.altitude_geoidal_separation,
'M',
0,
0);
uint chk = 0;
for (uint i = 1; i < len; i++) {
uint32_t chk = 0;
for (uint32_t i = 1; i < len; i++) {
chk ^= buf[i];
}
len += sprintf(buf + len, "*%02X\r\n", chk);

View File

@@ -3,5 +3,5 @@
#include <Arduino.h>
#include "main.h"
uint printWPL(char *buf, const Position &pos, const char *name);
uint printGGA(char *buf, const Position &pos);
uint32_t printWPL(char *buf, const Position &pos, const char *name);
uint32_t printGGA(char *buf, const Position &pos);

View File

@@ -44,7 +44,11 @@ void readFromRTC()
if(rtc_found == PCF8563_RTC) {
uint32_t now = millis();
PCF8563_Class rtc;
#ifdef RTC_USE_WIRE1
rtc.begin(Wire1);
#else
rtc.begin();
#endif
auto tc = rtc.getDateTime();
tm t;
t.tm_year = tc.year - 1900;
@@ -110,7 +114,11 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
#elif defined(PCF8563_RTC)
if(rtc_found == PCF8563_RTC) {
PCF8563_Class rtc;
rtc.begin();
#ifdef RTC_USE_WIRE1
rtc.begin(Wire1);
#else
rtc.begin();
#endif
tm *t = localtime(&tv->tv_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);

View File

@@ -50,8 +50,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using namespace meshtastic; /** @todo remove */
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
namespace graphics
{
@@ -67,6 +65,8 @@ namespace graphics
static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
static uint32_t targetFramerate = IDLE_FRAMERATE;
static char btPIN[16] = "888888";
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
@@ -283,27 +283,27 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
int x_offset = display->width() / 2;
int y_offset = display->height() == 64 ? 0 : 32;
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_MEDIUM);
display->drawString(64 + x, y, "Bluetooth");
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
display->setFont(FONT_SMALL);
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM -4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
display->drawString(x_offset + x, y_offset + y, "Enter this code");
display->setFont(FONT_LARGE);
String displayPin(btPIN);
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
display->drawString(x_offset + x, y_offset + y, pin);
auto displayPin = new String(btPIN);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(12 + x, 26 + y, displayPin->substring(0, 3));
display->drawString(72 + x, 26 + y, displayPin->substring(3, 6));
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_SMALL);
char buf[30];
const char *name = "Name: ";
strcpy(buf, name);
strcat(buf, getDeviceName());
display->drawString(64 + x, 48 + y, buf);
String deviceName = "Name: ";
deviceName.concat(getDeviceName());
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
display->drawString(x_offset + x, y_offset + y, deviceName);
}
static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
@@ -538,9 +538,10 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} else {
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_DMS) {
char coordinateLine[22];
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
@@ -944,6 +945,9 @@ void Screen::setup()
// Set the utf8 conversion function
dispdev.setFontTableLookupFunction(customFontTableLookup);
if (strlen(oemStore.oem_text) > 0)
logo_timeout *= 2;
// Add frames.
static FrameCallback bootFrames[] = {drawBootScreen};
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
@@ -1012,26 +1016,28 @@ int32_t Screen::runOnce()
return RUN_SAME;
}
// Show boot screen for first 5 seconds, then switch to normal operation.
// Show boot screen for first logo_timeout seconds, then switch to normal operation.
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
static bool showingBootScreen = true;
if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) {
if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) {
DEBUG_MSG("Done with boot screen...\n");
stopBootScreen();
showingBootScreen = false;
}
// If we have an OEM Boot screen, toggle after 2,5 seconds
// If we have an OEM Boot screen, toggle after logo_timeout seconds
if (strlen(oemStore.oem_text) > 0) {
static bool showingOEMBootScreen = true;
if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) {
if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) {
DEBUG_MSG("Switch to OEM screen...\n");
// Change frames.
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
ui.setFrames(bootOEMFrames, bootOEMFrameCount);
ui.update();
#ifndef USE_EINK
ui.update();
#endif
showingOEMBootScreen = false;
}
}

View File

@@ -10,7 +10,7 @@ namespace graphics
class Screen
{
public:
Screen(char){}
explicit Screen(char){}
void onPress() {}
void setup() {}
void setOn(bool) {}

View File

@@ -37,7 +37,7 @@
#include "nimble/NimbleBluetooth.h"
#endif
#if HAS_WIFI || defined(ARCH_PORTDUINO)
#if HAS_WIFI
#include "mesh/wifi/WiFiServerAPI.h"
#include "mqtt/MQTT.h"
#endif
@@ -51,7 +51,7 @@
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "SX1281Interface.h"
#include "SX1280Interface.h"
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
#include "platform/portduino/SimRadio.h"
#endif
@@ -87,8 +87,6 @@ uint8_t kb_model;
// 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
@@ -102,7 +100,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_QMI8658+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t nodeTelemetrySensorsMap[_TelemetrySensorType_MAX + 1] = { 0 }; // one is enough, missing elements will be initialized to 0 anyway.
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
@@ -142,8 +140,9 @@ bool ButtonThread::shutdown_on_long_stop = false;
#endif
static Periodic *ledPeriodic;
static OSThread *powerFSMthread, *buttonThread;
static OSThread *powerFSMthread;
#if HAS_BUTTON
static OSThread *buttonThread;
uint32_t ButtonThread::longPressTime = 0;
#endif
@@ -246,8 +245,32 @@ void setup()
digitalWrite(PIN_3V3_EN, 1);
#endif
// Currently only the tbeam has a PMU
// PMU initialization needs to be placed before scanI2Cdevice
power = new Power();
power->setStatusHandler(powerStatus);
powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
#ifdef LILYGO_TBEAM_S3_CORE
// In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck
// PCF8563 RTC in tbeam-s3 uses Wire1 to share I2C bus
Wire1.beginTransmission(PCF8563_RTC);
if (Wire1.endTransmission() == 0){
rtc_found = PCF8563_RTC;
DEBUG_MSG("PCF8563 RTC found\n");
}
#endif
// We need to scan here to decide if we have a screen for nodeDB.init()
scanI2Cdevice();
#ifdef HAS_SDCARD
setupSDCard();
#endif
#ifdef RAK4630
// scanEInkDevice();
#endif
@@ -282,18 +305,10 @@ void setup()
playStartMelody();
// Currently only the tbeam has a PMU
power = new Power();
power->setStatusHandler(powerStatus);
powerStatus->observe(&power->newStatus);
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
// fixed screen override?
if (config.display.oled != Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;
/*
* 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
@@ -372,16 +387,15 @@ void setup()
}
#endif
#if defined(USE_SX1281) && !defined(ARCH_PORTDUINO)
#if defined(USE_SX1280) && !defined(ARCH_PORTDUINO)
if (!rIf) {
rIf = new SX1281Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find SX1281 radio\n");
DEBUG_MSG("Warning: Failed to find SX1280 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("SX1281 Radio init succeeded, using SX1281 radio\n");
rIf_wide_lora = true;
DEBUG_MSG("SX1280 Radio init succeeded, using SX1280 radio\n");
}
}
#endif

View File

@@ -6,7 +6,7 @@
#include "PowerStatus.h"
#include "graphics/Screen.h"
#include "mesh/generated/telemetry.pb.h"
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#include <SparkFun_ATECCX08a_Arduino_Library.h>
#endif
@@ -17,17 +17,16 @@ extern uint8_t kb_model;
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;
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
extern ATECCX08A atecc;
#endif
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
extern uint8_t nodeTelemetrySensorsMap[_TelemetrySensorType_MAX + 1];
extern int TCPPort; // set by Portduino

View File

@@ -29,8 +29,8 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
{
PacketId ackId = ((c && c->error_reason == Routing_Error_NONE) || !c) ? p->decoded.request_id : 0;
if (ackId && p->to != getNodeNum()) {
bool isAck = ((c && c->error_reason == Routing_Error_NONE)); // consider only ROUTING_APP message without error as ACK
if (isAck && p->to != getNodeNum()) {
// do not flood direct message that is ACKed
DEBUG_MSG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM

View File

@@ -8,6 +8,6 @@ template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;
#if !defined(ARCH_PORTDUINO)
template class SX128xInterface<SX1281>;
#if defined(RADIOLIB_GODMODE)
template class SX128xInterface<SX1280>;
#endif

View File

@@ -109,10 +109,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
/// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and it needs to
/// to be able to fetch the initial admin packets without yet knowing any channels.
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
!ch ||
strlen(ch->settings.name) > 0 ||
(strcasecmp(ch->settings.name, pi.boundChannel) == 0);
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (strcasecmp(ch->settings.name, pi.boundChannel) == 0);
if (!rxChannelOk) {
// no one should have already replied!

View File

@@ -104,16 +104,17 @@ bool MeshService::reloadConfig(int saveWhat)
}
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void MeshService::reloadOwner()
void MeshService::reloadOwner(bool shouldSave)
{
// DEBUG_MSG("reloadOwner()\n");
// update our local data directly
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
assert(nodeInfoModule);
// update everyone else
if (nodeInfoModule)
// update everyone else and save to disk
if (nodeInfoModule && shouldSave) {
nodeInfoModule->sendOurNodeInfo();
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
}
}
/**

View File

@@ -69,7 +69,7 @@ class MeshService
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();
void reloadOwner(bool shouldSave = true);
/// Called when the user wakes up our GUI, normally sends our latest location to the mesh (if we have it), otherwise at least
/// sends our owner

View File

@@ -204,6 +204,7 @@ void NodeDB::installDefaultModuleConfig()
{
DEBUG_MSG("Installing default ModuleConfig\n");
memset(&moduleConfig, 0, sizeof(ModuleConfig));
moduleConfig.version = DEVICESTATE_CUR_VER;
moduleConfig.has_mqtt = true;
moduleConfig.has_range_test = true;
@@ -213,6 +214,10 @@ void NodeDB::installDefaultModuleConfig()
moduleConfig.has_external_notification = true;
moduleConfig.has_canned_message = true;
strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(default_mqtt_address));
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(default_mqtt_username));
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(default_mqtt_password));
initModuleConfigIntervals();
}
@@ -470,6 +475,15 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
DEBUG_MSG("Error: can't rename new pref file\n");
} else {
DEBUG_MSG("Can't write prefs\n");
#ifdef ARCH_NRF52
static uint8_t failedCounter = 0;
failedCounter++;
if(failedCounter >= 2){
FSCom.format();
//After formatting, the device needs to be restarted
nodeDB.resetRadioConfig(true);
}
#endif
}
#else
DEBUG_MSG("ERROR: Filesystem not implemented\n");
@@ -741,9 +755,9 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *f
String lcd = String("Critical error ") + code + "!\n";
screen->print(lcd.c_str());
if (filename)
DEBUG_MSG("NOTE! Recording critical error %d at %s:%lx\n", code, filename, address);
DEBUG_MSG("NOTE! Recording critical error %d at %s:%lu\n", code, filename, address);
else
DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address);
DEBUG_MSG("NOTE! Recording critical error %d, address=0x%lx\n", code, address);
// Record error to DB
myNodeInfo.error_code = code;

View File

@@ -58,7 +58,7 @@ class NodeDB
void init();
/// write to flash
void saveToDisk(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS), 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
@@ -194,6 +194,10 @@ extern NodeDB nodeDB;
#define default_min_wake_secs 10
#define default_screen_on_secs 60 * 10
#define default_mqtt_address "mqtt.meshtastic.org"
#define default_mqtt_username "meshdev"
#define default_mqtt_password "large4cats"
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval)
{
if (configuredInterval > 0) return configuredInterval * 1000;

View File

@@ -249,11 +249,15 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_canned_message_tag;
fromRadioScratch.moduleConfig.payload_variant.canned_message = moduleConfig.canned_message;
break;
case ModuleConfig_audio_tag:
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_audio_tag;
fromRadioScratch.moduleConfig.payload_variant.audio = moduleConfig.audio;
break;
}
config_state++;
// Advance when we have sent all of our ModuleConfig objects
if (config_state > ModuleConfig_canned_message_tag) {
if (config_state > ModuleConfig_audio_tag) {
state = STATE_SEND_COMPLETE_ID;
config_state = 0;
}

View File

@@ -129,6 +129,7 @@ bool RF95Interface::reconfigure()
if (power > MAX_POWER) // This chip has lower power limits than some
power = MAX_POWER;
err = lora->setOutputPower(power);
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);

View File

@@ -89,7 +89,7 @@ const RegionInfo regions[] = {
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, false),
RDEF(NZ_865, 864.0f, 868.0f, 100, 0, 36, true, false, false),
/*
https://lora-alliance.org/wp-content/uploads/2020/11/lorawan_regional_parameters_v1.0.3reva_0.pdf
@@ -177,7 +177,7 @@ uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
static uint8_t bytes[MAX_RHPACKETLEN];
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader));
// Make sure enough time has elapsed for this packet to be sent and an ACK is received.
// Make sure enough time has elapsed for this packet to be sent and an ACK is received.
// DEBUG_MSG("Waiting for flooding message with airtime %d and slotTime is %d\n", packetAirtime, slotTimeMsec);
float channelUtil = airTime->channelUtilizationPercent();
uint8_t CWsize = map(channelUtil, 0, 100, CWmin, CWmax);
@@ -189,7 +189,7 @@ uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
uint32_t RadioInterface::getTxDelayMsec()
{
/** We wait a random multiple of 'slotTimes' (see definition in header file) in order to avoid collisions.
The pool to take a random multiple from is the contention window (CW), which size depends on the
The pool to take a random multiple from is the contention window (CW), which size depends on the
current channel utilization. */
float channelUtil = airTime->channelUtilizationPercent();
uint8_t CWsize = map(channelUtil, 0, 100, CWmin, CWmax);
@@ -225,7 +225,7 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
void printPacket(const char *prefix, const MeshPacket *p)
{
DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d Ch0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff,
DEBUG_MSG("%s (id=0x%08x fr=0x%02x to=0x%02x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id, p->from & 0xff, p->to & 0xff,
p->want_ack, p->hop_limit, p->channel);
if (p->which_payload_variant == MeshPacket_decoded_tag) {
auto &s = p->decoded;
@@ -365,37 +365,37 @@ void RadioInterface::applyModemConfig()
switch (loraConfig.modem_preset) {
case Config_LoRaConfig_ModemPreset_SHORT_FAST:
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 7;
break;
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 8;
break;
case Config_LoRaConfig_ModemPreset_MEDIUM_FAST:
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 9;
break;
case Config_LoRaConfig_ModemPreset_MEDIUM_SLOW:
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 10;
break;
case Config_LoRaConfig_ModemPreset_LONG_FAST:
bw = (myRegion->wideLora && rIf_wide_lora) ? 800 : 250;
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 11;
break;
case Config_LoRaConfig_ModemPreset_LONG_SLOW:
bw = (myRegion->wideLora && rIf_wide_lora) ? 400 : 125;
bw = (myRegion->wideLora) ? 406.25 : 125;
cr = 8;
sf = 12;
break;
case Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
bw = (myRegion->wideLora && rIf_wide_lora) ? 200 : 31.25;
bw = (myRegion->wideLora) ? 203.125 : 31.25;
cr = 8;
sf = 12;
break;
@@ -411,12 +411,20 @@ void RadioInterface::applyModemConfig()
bw = 31.25;
if (bw == 62) // Fix for 62.5Khz bandwidth
bw = 62.5;
if (bw == 200)
bw = 203.125;
if (bw == 400)
bw = 406.25;
if (bw == 800)
bw = 812.5;
if (bw == 1600)
bw = 1625.0;
}
power = loraConfig.tx_power;
assert(myRegion); // Should have been found in init
if ((power == 0) || (power > myRegion->powerLimit))
if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed))
power = myRegion->powerLimit;
if (power == 0)
@@ -424,7 +432,7 @@ void RadioInterface::applyModemConfig()
// Set final tx_power back onto config
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)));
@@ -441,9 +449,10 @@ void RadioInterface::applyModemConfig()
saveChannelNum(channel_num);
saveFreq(freq + config.lora.frequency_offset);
DEBUG_MSG("Radio freq=%.3f, config.lora.frequency_offset=%.3f\n", freq, config.lora.frequency_offset);
DEBUG_MSG("Set radio: region=%s, name=%s, config=%u, ch=%d, power=%d\n", myRegion->name, channelName, loraConfig.modem_preset, channel_num, power);
DEBUG_MSG("Radio myRegion->freqStart / myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd, myRegion->freqEnd - myRegion->freqStart);
DEBUG_MSG("Radio myRegion->numChannels: %d\n", numChannels);
DEBUG_MSG("Radio myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd, myRegion->freqEnd - myRegion->freqStart);
DEBUG_MSG("Radio myRegion->numChannels: %d x %.3fkHz\n", numChannels, bw);
DEBUG_MSG("Radio channel_num: %d\n", channel_num);
DEBUG_MSG("Radio frequency: %f\n", getFreq());
DEBUG_MSG("Slot time: %u msec\n", slotTimeMsec);
@@ -460,7 +469,7 @@ void RadioInterface::limitPower()
if (myRegion->powerLimit)
maxPower = myRegion->powerLimit;
if (power > maxPower) {
if ((power > maxPower) && !devicestate.owner.is_licensed) {
DEBUG_MSG("Lowering transmit power because of regulatory limits\n");
power = maxPower;
}

View File

@@ -11,17 +11,6 @@
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
#ifdef ARCH_PORTDUINO
void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes)
{
concurrency::LockGuard g(spiLock);
Module::SPItransfer(cmd, reg, dataOut, dataIn, numBytes);
}
#else
void LockingModule::SPIbeginTransaction()
{
spiLock->lock();
@@ -36,8 +25,6 @@ void LockingModule::SPIendTransaction()
Module::SPIendTransaction();
}
#endif
RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi, PhysicalLayer *_iface)
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
@@ -317,7 +304,13 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
void RadioLibInterface::handleReceiveInterrupt()
{
uint32_t xmitMsec;
assert(isReceiving);
// when this is called, we should be in receive mode - if we are not, just jump out instead of bombing. Possible Race Condition?
if (!isReceiving) {
DEBUG_MSG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode\n");
return;
}
isReceiving = false;
// read the number of actually received bytes

View File

@@ -41,12 +41,8 @@ class LockingModule : public Module
{
}
#ifdef ARCH_PORTDUINO
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) override;
#else
void SPIbeginTransaction() override;
void SPIendTransaction() override;
#endif
};
class RadioLibInterface : public RadioInterface, protected concurrency::NotifiedWorkerThread

View File

@@ -96,7 +96,11 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
if (MeshModule::currentReply)
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);
if (p->which_payload_variant == MeshPacket_decoded_tag)
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
else
// Send a 'NO_CHANNEL' error on the primary channel if want_ack packet destined for us cannot be decoded
sendAckNak(Routing_Error_NO_CHANNEL, getFrom(p), p->id, channels.getPrimaryIndex());
}
// We consider an ack to be either a !routing packet with a request ID or a routing packet with !error

View File

@@ -11,7 +11,7 @@ extern "C" {
#include "mesh/compression/unishox2.h"
}
#if HAS_WIFI
#if HAS_WIFI || HAS_ETHERNET
#include "mqtt/MQTT.h"
#endif
@@ -209,7 +209,7 @@ ErrorCode Router::send(MeshPacket *p)
if (p->which_payload_variant == MeshPacket_decoded_tag) {
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
#if HAS_WIFI
#if HAS_WIFI || HAS_ETHERNET
// check if we should send decrypted packets to mqtt
// truth table:
@@ -240,7 +240,7 @@ ErrorCode Router::send(MeshPacket *p)
return encodeResult; // FIXME - this isn't a valid ErrorCode
}
#if HAS_WIFI
#if HAS_WIFI || HAS_ETHERNET
// the packet is now encrypted.
// check if we should send encrypted packets to mqtt
if (mqtt && shouldActuallyEncrypt)

View File

@@ -12,6 +12,7 @@ SX126xInterface<T>::SX126xInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq,
SPIClass &spi)
: RadioLibInterface(cs, irq, rst, busy, spi, &lora), lora(&module)
{
DEBUG_MSG("SX126xInterface(cs=%d, irq=%d, rst=%d, busy=%d)\n", cs, irq, rst, busy);
}
/// Initialise the Driver transport hardware and software.
@@ -25,11 +26,11 @@ bool SX126xInterface<T>::init()
pinMode(SX126X_POWER_EN, OUTPUT);
#endif
#ifdef SX126X_RXEN // set not rx or tx mode
#if defined(SX126X_RXEN) && (SX126X_RXEN != RADIOLIB_NC) // set not rx or tx mode
digitalWrite(SX126X_RXEN, LOW); // Set low before becoming an output
pinMode(SX126X_RXEN, OUTPUT);
#endif
#ifdef SX126X_TXEN
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
digitalWrite(SX126X_TXEN, LOW);
pinMode(SX126X_TXEN, OUTPUT);
#endif
@@ -56,9 +57,9 @@ bool SX126xInterface<T>::init()
// \todo Display actual typename of the adapter, not just `SX126x`
DEBUG_MSG("SX126x 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);
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);
// current limit was removed from module' ctor
// override default value (60 mA)
@@ -66,10 +67,10 @@ bool SX126xInterface<T>::init()
DEBUG_MSG("Current limit set to %f\n", currentLimit);
DEBUG_MSG("Current limit set result %d\n", res);
#ifdef SX126X_TXEN
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
// 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);
res = lora.setDio2AsRfSwitch(false);
#endif
#if 0
@@ -81,11 +82,11 @@ bool SX126xInterface<T>::init()
//if(crcLSB != 0x0f)
// RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
crcLSB = 0x5a;
err = lora.writeRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
RECORD_CRITICALERROR(CriticalErrorCode_SX1262Failure);
err = lora.readRegister(SX126X_REG_CRC_POLYNOMIAL_LSB, &crcLSB, 1);
if(err != RADIOLIB_ERR_NONE)
@@ -144,8 +145,9 @@ bool SX126xInterface<T>::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
if (power > 22) // This chip has lower power limits than some
power = 22;
if (power > SX126X_MAX_POWER) // This chip has lower power limits than some
power = SX126X_MAX_POWER;
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
@@ -164,14 +166,18 @@ template<typename T>
void SX126xInterface<T>::setStandby()
{
checkNotification(); // handle any pending interrupts before we force standby
int err = lora.standby();
if (err != RADIOLIB_ERR_NONE)
DEBUG_MSG("SX126x standby failed with error %d\n", err);
assert(err == RADIOLIB_ERR_NONE);
#ifdef SX126X_RXEN // we have RXEN/TXEN control - turn off RX and TX power
#if defined(SX126X_RXEN) && (SX126X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
digitalWrite(SX126X_RXEN, LOW);
#endif
#ifdef SX126X_TXEN
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
digitalWrite(SX126X_TXEN, LOW);
#endif
@@ -196,10 +202,10 @@ void SX126xInterface<T>::addReceiveMetadata(MeshPacket *mp)
template<typename T>
void SX126xInterface<T>::configHardwareForSend()
{
#ifdef SX126X_TXEN // we have RXEN/TXEN control - turn on TX power / off RX power
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX126X_TXEN, HIGH);
#endif
#ifdef SX126X_RXEN
#if defined(SX126X_RXEN) && (SX126X_RXEN != RADIOLIB_NC)
digitalWrite(SX126X_RXEN, LOW);
#endif
@@ -218,13 +224,13 @@ void SX126xInterface<T>::startReceive()
setStandby();
#ifdef SX126X_RXEN // we have RXEN/TXEN control - turn on RX power / off TX power
#if defined(SX126X_RXEN) && (SX126X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX126X_RXEN, HIGH);
#endif
#ifdef SX126X_TXEN
#if defined(SX126X_TXEN) && (SX126X_TXEN != RADIOLIB_NC)
digitalWrite(SX126X_TXEN, LOW);
#endif
// int err = lora.startReceive();
int err = lora.startReceiveDutyCycleAuto(); // We use a 32 bit preamble so this should save some power by letting radio sit in
// standby mostly.
@@ -244,13 +250,13 @@ bool SX126xInterface<T>::isChannelActive()
// check if we can detect a LoRa preamble on the current channel
int16_t result;
setStandby();
setStandby();
result = lora.scanChannel();
if (result == RADIOLIB_PREAMBLE_DETECTED)
if (result == RADIOLIB_PREAMBLE_DETECTED)
return true;
assert(result != RADIOLIB_ERR_WRONG_MODEM);
return false;
}

View File

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

View File

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

View File

@@ -1,17 +0,0 @@
#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

@@ -2,11 +2,11 @@
#include "SX128xInterface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
#if defined(RADIOLIB_GODMODE)
// Particular boards might define a different max power based on what their hardware can do
#ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 22
#define SX128X_MAX_POWER 13
#endif
template<typename T>
@@ -61,7 +61,7 @@ bool SX128xInterface<T>::init()
#endif
if (res == RADIOLIB_ERR_NONE)
res = lora.setCRC(RADIOLIB_SX128X_LORA_CRC_ON);
res = lora.setCRC(2);
if (res == RADIOLIB_ERR_NONE)
startReceive(); // start receiving
@@ -105,8 +105,9 @@ bool SX128xInterface<T>::reconfigure()
if (err != RADIOLIB_ERR_NONE)
RECORD_CRITICALERROR(CriticalErrorCode_INVALID_RADIO_SETTING);
if (power > 22) // This chip has lower power limits than some
power = 22;
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
err = lora.setOutputPower(power);
assert(err == RADIOLIB_ERR_NONE);
@@ -218,7 +219,11 @@ bool SX128xInterface<T>::isChannelActive()
template<typename T>
bool SX128xInterface<T>::isActivelyReceiving()
{
return isChannelActive();
// return isChannelActive();
uint16_t irq = lora.getIrqStatus();
bool hasPreamble = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID);
return hasPreamble;
}
template<typename T>

View File

@@ -1,12 +1,12 @@
#pragma once
#if !defined(ARCH_PORTDUINO)
#if defined(RADIOLIB_GODMODE)
#include "RadioLibInterface.h"
/**
* \brief Adapter for SX128x radio family. Implements common logic for child classes.
* \tparam T RadioLib module type for SX128x: SX1281.
* \tparam T RadioLib module type for SX128x: SX1280.
*/
template<class T>
class SX128xInterface : public RadioLibInterface

View File

@@ -32,7 +32,8 @@ typedef enum _AdminMessage_ModuleConfigType {
AdminMessage_ModuleConfigType_STOREFORWARD_CONFIG = 3,
AdminMessage_ModuleConfigType_RANGETEST_CONFIG = 4,
AdminMessage_ModuleConfigType_TELEMETRY_CONFIG = 5,
AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6
AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG = 6,
AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7
} AdminMessage_ModuleConfigType;
/* Struct definitions */
@@ -81,10 +82,11 @@ typedef struct _AdminMessage {
ModuleConfig set_module_config;
/* Set the Canned Message Module messages text. */
char set_canned_message_module_messages[201];
/* Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins */
bool confirm_set_config;
/* Sent immediatly after a config change has been sent to ensure comms, if this is not recieved, the config will be reverted after 10 mins */
bool confirm_set_module_config;
/* Begins an edit transaction for config, module config, owner, and channel settings changes
This will delay the standard *implicit* save to the file system and subsequent reboot behavior until committed (commit_edit_settings) */
bool begin_edit_settings;
/* Commits an open transaction for any edits made to config, module config, owner, and channel settings */
bool commit_edit_settings;
/* Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again.
Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes.
If you fail to do so, the radio will assume loss of comms and revert your changes.
@@ -116,8 +118,8 @@ typedef struct _AdminMessage {
#define _AdminMessage_ConfigType_ARRAYSIZE ((AdminMessage_ConfigType)(AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
#define _AdminMessage_ModuleConfigType_MIN AdminMessage_ModuleConfigType_MQTT_CONFIG
#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG
#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_CANNEDMSG_CONFIG+1))
#define _AdminMessage_ModuleConfigType_MAX AdminMessage_ModuleConfigType_AUDIO_CONFIG
#define _AdminMessage_ModuleConfigType_ARRAYSIZE ((AdminMessage_ModuleConfigType)(AdminMessage_ModuleConfigType_AUDIO_CONFIG+1))
#ifdef __cplusplus
@@ -146,8 +148,8 @@ extern "C" {
#define AdminMessage_set_config_tag 34
#define AdminMessage_set_module_config_tag 35
#define AdminMessage_set_canned_message_module_messages_tag 36
#define AdminMessage_confirm_set_config_tag 64
#define AdminMessage_confirm_set_module_config_tag 65
#define AdminMessage_begin_edit_settings_tag 64
#define AdminMessage_commit_edit_settings_tag 65
#define AdminMessage_confirm_set_channel_tag 66
#define AdminMessage_confirm_set_radio_tag 67
#define AdminMessage_reboot_ota_seconds_tag 95
@@ -176,8 +178,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 3
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_module_config,set_module_config), 35) \
X(a, STATIC, ONEOF, STRING, (payload_variant,set_canned_message_module_messages,set_canned_message_module_messages), 36) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_config,confirm_set_config), 64) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,confirm_set_module_config,confirm_set_module_config), 65) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,begin_edit_settings,begin_edit_settings), 64) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,commit_edit_settings,commit_edit_settings), 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) \

View File

@@ -31,12 +31,6 @@ typedef enum _Config_PositionConfig_PositionFlags {
Config_PositionConfig_PositionFlags_SPEED = 512
} Config_PositionConfig_PositionFlags;
typedef enum _Config_NetworkConfig_WiFiMode {
Config_NetworkConfig_WiFiMode_CLIENT = 0,
Config_NetworkConfig_WiFiMode_ACCESS_POINT = 1,
Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN = 2
} Config_NetworkConfig_WiFiMode;
typedef enum _Config_NetworkConfig_EthMode {
Config_NetworkConfig_EthMode_DHCP = 0,
Config_NetworkConfig_EthMode_STATIC = 1
@@ -56,6 +50,12 @@ typedef enum _Config_DisplayConfig_DisplayUnits {
Config_DisplayConfig_DisplayUnits_IMPERIAL = 1
} Config_DisplayConfig_DisplayUnits;
typedef enum _Config_DisplayConfig_OledType {
Config_DisplayConfig_OledType_OLED_AUTO = 0,
Config_DisplayConfig_OledType_OLED_SSD1306 = 1,
Config_DisplayConfig_OledType_OLED_SH1106 = 2
} Config_DisplayConfig_OledType;
typedef enum _Config_LoRaConfig_RegionCode {
Config_LoRaConfig_RegionCode_UNSET = 0,
Config_LoRaConfig_RegionCode_US = 1,
@@ -100,6 +100,8 @@ typedef struct _Config_DeviceConfig {
Config_DeviceConfig_Role role;
bool serial_enabled;
bool debug_log_enabled;
uint32_t button_gpio;
uint32_t buzzer_gpio;
} Config_DeviceConfig;
typedef struct _Config_DisplayConfig {
@@ -109,6 +111,7 @@ typedef struct _Config_DisplayConfig {
bool compass_north_top;
bool flip_screen;
Config_DisplayConfig_DisplayUnits units;
Config_DisplayConfig_OledType oled;
} Config_DisplayConfig;
typedef struct _Config_LoRaConfig {
@@ -142,6 +145,8 @@ typedef struct _Config_PositionConfig {
uint32_t gps_update_interval;
uint32_t gps_attempt_time;
uint32_t position_flags;
uint32_t rx_gpio;
uint32_t tx_gpio;
} Config_PositionConfig;
typedef struct _Config_PowerConfig {
@@ -189,10 +194,6 @@ typedef struct _Config {
#define _Config_PositionConfig_PositionFlags_MAX Config_PositionConfig_PositionFlags_SPEED
#define _Config_PositionConfig_PositionFlags_ARRAYSIZE ((Config_PositionConfig_PositionFlags)(Config_PositionConfig_PositionFlags_SPEED+1))
#define _Config_NetworkConfig_WiFiMode_MIN Config_NetworkConfig_WiFiMode_CLIENT
#define _Config_NetworkConfig_WiFiMode_MAX Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN
#define _Config_NetworkConfig_WiFiMode_ARRAYSIZE ((Config_NetworkConfig_WiFiMode)(Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN+1))
#define _Config_NetworkConfig_EthMode_MIN Config_NetworkConfig_EthMode_DHCP
#define _Config_NetworkConfig_EthMode_MAX Config_NetworkConfig_EthMode_STATIC
#define _Config_NetworkConfig_EthMode_ARRAYSIZE ((Config_NetworkConfig_EthMode)(Config_NetworkConfig_EthMode_STATIC+1))
@@ -205,6 +206,10 @@ typedef struct _Config {
#define _Config_DisplayConfig_DisplayUnits_MAX Config_DisplayConfig_DisplayUnits_IMPERIAL
#define _Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((Config_DisplayConfig_DisplayUnits)(Config_DisplayConfig_DisplayUnits_IMPERIAL+1))
#define _Config_DisplayConfig_OledType_MIN Config_DisplayConfig_OledType_OLED_AUTO
#define _Config_DisplayConfig_OledType_MAX Config_DisplayConfig_OledType_OLED_SH1106
#define _Config_DisplayConfig_OledType_ARRAYSIZE ((Config_DisplayConfig_OledType)(Config_DisplayConfig_OledType_OLED_SH1106+1))
#define _Config_LoRaConfig_RegionCode_MIN Config_LoRaConfig_RegionCode_UNSET
#define _Config_LoRaConfig_RegionCode_MAX Config_LoRaConfig_RegionCode_LORA_24
#define _Config_LoRaConfig_RegionCode_ARRAYSIZE ((Config_LoRaConfig_RegionCode)(Config_LoRaConfig_RegionCode_LORA_24+1))
@@ -224,21 +229,21 @@ extern "C" {
/* Initializer values for message structs */
#define Config_init_default {0, {Config_DeviceConfig_init_default}}
#define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0}
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0}
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
#define Config_NetworkConfig_init_default {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_default}
#define Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN}
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_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, 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}
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0}
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
#define Config_NetworkConfig_init_zero {0, "", "", "", 0, _Config_NetworkConfig_EthMode_MIN, false, Config_NetworkConfig_IpV4Config_init_zero}
#define Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN}
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _Config_DisplayConfig_DisplayUnits_MIN, _Config_DisplayConfig_OledType_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, 0}}
#define Config_BluetoothConfig_init_zero {0, _Config_BluetoothConfig_PairingMode_MIN, 0}
@@ -249,12 +254,15 @@ extern "C" {
#define Config_DeviceConfig_role_tag 1
#define Config_DeviceConfig_serial_enabled_tag 2
#define Config_DeviceConfig_debug_log_enabled_tag 3
#define Config_DeviceConfig_button_gpio_tag 4
#define Config_DeviceConfig_buzzer_gpio_tag 5
#define Config_DisplayConfig_screen_on_secs_tag 1
#define Config_DisplayConfig_gps_format_tag 2
#define Config_DisplayConfig_auto_screen_carousel_secs_tag 3
#define Config_DisplayConfig_compass_north_top_tag 4
#define Config_DisplayConfig_flip_screen_tag 5
#define Config_DisplayConfig_units_tag 6
#define Config_DisplayConfig_oled_tag 7
#define Config_LoRaConfig_use_preset_tag 1
#define Config_LoRaConfig_modem_preset_tag 2
#define Config_LoRaConfig_bandwidth_tag 3
@@ -278,6 +286,8 @@ extern "C" {
#define Config_PositionConfig_gps_update_interval_tag 5
#define Config_PositionConfig_gps_attempt_time_tag 6
#define Config_PositionConfig_position_flags_tag 7
#define Config_PositionConfig_rx_gpio_tag 8
#define Config_PositionConfig_tx_gpio_tag 9
#define Config_PowerConfig_is_power_saving_tag 1
#define Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
#define Config_PowerConfig_adc_multiplier_override_tag 3
@@ -323,7 +333,9 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,bluetooth,payload_variant.bl
#define Config_DeviceConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, role, 1) \
X(a, STATIC, SINGULAR, BOOL, serial_enabled, 2) \
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 3)
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 3) \
X(a, STATIC, SINGULAR, UINT32, button_gpio, 4) \
X(a, STATIC, SINGULAR, UINT32, buzzer_gpio, 5)
#define Config_DeviceConfig_CALLBACK NULL
#define Config_DeviceConfig_DEFAULT NULL
@@ -334,7 +346,9 @@ X(a, STATIC, SINGULAR, BOOL, fixed_position, 3) \
X(a, STATIC, SINGULAR, BOOL, gps_enabled, 4) \
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 5) \
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 6) \
X(a, STATIC, SINGULAR, UINT32, position_flags, 7)
X(a, STATIC, SINGULAR, UINT32, position_flags, 7) \
X(a, STATIC, SINGULAR, UINT32, rx_gpio, 8) \
X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9)
#define Config_PositionConfig_CALLBACK NULL
#define Config_PositionConfig_DEFAULT NULL
@@ -376,7 +390,8 @@ X(a, STATIC, SINGULAR, UENUM, gps_format, 2) \
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 3) \
X(a, STATIC, SINGULAR, BOOL, compass_north_top, 4) \
X(a, STATIC, SINGULAR, BOOL, flip_screen, 5) \
X(a, STATIC, SINGULAR, UENUM, units, 6)
X(a, STATIC, SINGULAR, UENUM, units, 6) \
X(a, STATIC, SINGULAR, UENUM, oled, 7)
#define Config_DisplayConfig_CALLBACK NULL
#define Config_DisplayConfig_DEFAULT NULL
@@ -426,12 +441,12 @@ extern const pb_msgdesc_t Config_BluetoothConfig_msg;
/* Maximum encoded size of messages (where known) */
#define Config_BluetoothConfig_size 10
#define Config_DeviceConfig_size 6
#define Config_DisplayConfig_size 20
#define Config_DeviceConfig_size 18
#define Config_DisplayConfig_size 22
#define Config_LoRaConfig_size 68
#define Config_NetworkConfig_IpV4Config_size 20
#define Config_NetworkConfig_size 161
#define Config_PositionConfig_size 30
#define Config_PositionConfig_size 42
#define Config_PowerConfig_size 43
#define Config_size 164

View File

@@ -66,6 +66,9 @@ typedef struct _LocalModuleConfig {
incompatible changes This integer is set at build time and is private to
NodeDB.cpp in the device code. */
uint32_t version;
/* The part of the config that is specific to the Audio module */
bool has_audio;
ModuleConfig_AudioConfig audio;
} LocalModuleConfig;
@@ -75,9 +78,9 @@ extern "C" {
/* Initializer values for message structs */
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_NetworkConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default, false, Config_BluetoothConfig_init_default, 0}
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0}
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0, false, ModuleConfig_AudioConfig_init_default}
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_NetworkConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero, false, Config_BluetoothConfig_init_zero, 0}
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0}
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0, false, ModuleConfig_AudioConfig_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define LocalConfig_device_tag 1
@@ -96,6 +99,7 @@ extern "C" {
#define LocalModuleConfig_telemetry_tag 6
#define LocalModuleConfig_canned_message_tag 7
#define LocalModuleConfig_version_tag 8
#define LocalModuleConfig_audio_tag 9
/* Struct field encoding specification for nanopb */
#define LocalConfig_FIELDLIST(X, a) \
@@ -125,7 +129,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, store_forward, 4) \
X(a, STATIC, OPTIONAL, MESSAGE, range_test, 5) \
X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \
X(a, STATIC, SINGULAR, UINT32, version, 8)
X(a, STATIC, SINGULAR, UINT32, version, 8) \
X(a, STATIC, OPTIONAL, MESSAGE, audio, 9)
#define LocalModuleConfig_CALLBACK NULL
#define LocalModuleConfig_DEFAULT NULL
#define LocalModuleConfig_mqtt_MSGTYPE ModuleConfig_MQTTConfig
@@ -135,6 +140,7 @@ X(a, STATIC, SINGULAR, UINT32, version, 8)
#define LocalModuleConfig_range_test_MSGTYPE ModuleConfig_RangeTestConfig
#define LocalModuleConfig_telemetry_MSGTYPE ModuleConfig_TelemetryConfig
#define LocalModuleConfig_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
#define LocalModuleConfig_audio_MSGTYPE ModuleConfig_AudioConfig
extern const pb_msgdesc_t LocalConfig_msg;
extern const pb_msgdesc_t LocalModuleConfig_msg;
@@ -144,8 +150,8 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
#define LocalModuleConfig_fields &LocalModuleConfig_msg
/* Maximum encoded size of messages (where known) */
#define LocalConfig_size 359
#define LocalModuleConfig_size 270
#define LocalConfig_size 385
#define LocalModuleConfig_size 361
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -52,6 +52,8 @@ typedef enum _HardwareModel {
HardwareModel_RAK11200 = 13,
/* B&Q Consulting Nano Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:nano */
HardwareModel_NANO_G1 = 14,
/* TODO: REPLACE */
HardwareModel_TLORA_V2_1_1P8 = 15,
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
HardwareModel_STATION_G1 = 25,
/* Less common/prototype boards listed here (needs one more byte over the air) */
@@ -76,6 +78,10 @@ typedef enum _HardwareModel {
HardwareModel_DR_DEV = 41,
/* M5 esp32 based MCU modules with enclosure, TFT and LORA Shields. All Variants (Basic, Core, Fire, Core2, Paper) https://m5stack.com/ */
HardwareModel_M5STACK = 42,
/* New Heltec LoRA32 with ESP32-S3 CPU */
HardwareModel_HELTEC_V3 = 43,
/* New Heltec Wireless Stick Lite with ESP32-S3 CPU */
HardwareModel_HELTEC_WSL_V3 = 44,
/* Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. */
HardwareModel_PRIVATE_HW = 255
} HardwareModel;
@@ -499,7 +505,7 @@ typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
typedef struct _MeshPacket {
/* The sending node number.
Note: Our crypto implementation uses this field as well.
See [crypto](/docs/developers/firmware/encryption) for details.
See [crypto](/docs/overview/encryption) for details.
FIXME - really should be fixed32 instead, this encoding only hurts the ble link though. */
uint32_t from;
/* The (immediatSee Priority description for more details.y should be fixed32 instead, this encoding only
@@ -527,7 +533,7 @@ typedef struct _MeshPacket {
needs to be unique for a few minutes (long enough to last for the length of
any ACK or the completion of a mesh broadcast flood).
Note: Our crypto implementation uses this id as well.
See [crypto](/docs/developers/firmware/encryption) for details.
See [crypto](/docs/overview/encryption) for details.
FIXME - really should be fixed32 instead, this encoding only
hurts the ble link though. */
uint32_t id;

View File

@@ -12,6 +12,9 @@ PB_BIND(ModuleConfig, ModuleConfig, AUTO)
PB_BIND(ModuleConfig_MQTTConfig, ModuleConfig_MQTTConfig, AUTO)
PB_BIND(ModuleConfig_AudioConfig, ModuleConfig_AudioConfig, AUTO)
PB_BIND(ModuleConfig_SerialConfig, ModuleConfig_SerialConfig, AUTO)
@@ -34,3 +37,4 @@ PB_BIND(ModuleConfig_CannedMessageConfig, ModuleConfig_CannedMessageConfig, AUTO

View File

@@ -10,6 +10,18 @@
#endif
/* Enum definitions */
typedef enum _ModuleConfig_AudioConfig_Audio_Baud {
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT = 0,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_3200 = 1,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_2400 = 2,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1600 = 3,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1400 = 4,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1300 = 5,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_1200 = 6,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700 = 7,
ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B = 8
} ModuleConfig_AudioConfig_Audio_Baud;
typedef enum _ModuleConfig_SerialConfig_Serial_Baud {
ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT = 0,
ModuleConfig_SerialConfig_Serial_Baud_BAUD_110 = 1,
@@ -49,6 +61,14 @@ typedef enum _ModuleConfig_CannedMessageConfig_InputEventChar {
} ModuleConfig_CannedMessageConfig_InputEventChar;
/* Struct definitions */
typedef struct _ModuleConfig_AudioConfig {
bool codec2_enabled;
uint32_t mic_chan;
uint32_t amp_pin;
uint32_t ptt_pin;
ModuleConfig_AudioConfig_Audio_Baud bitrate;
} ModuleConfig_AudioConfig;
typedef struct _ModuleConfig_CannedMessageConfig {
bool rotary1_enabled;
uint32_t inputbroker_pin_a;
@@ -70,13 +90,14 @@ typedef struct _ModuleConfig_ExternalNotificationConfig {
bool active;
bool alert_message;
bool alert_bell;
bool use_pwm;
} ModuleConfig_ExternalNotificationConfig;
typedef struct _ModuleConfig_MQTTConfig {
bool enabled;
char address[32];
char username[32];
char password[32];
char username[64];
char password[64];
bool encryption_enabled;
bool json_enabled;
} ModuleConfig_MQTTConfig;
@@ -131,11 +152,17 @@ typedef struct _ModuleConfig {
ModuleConfig_TelemetryConfig telemetry;
/* TODO: REPLACE */
ModuleConfig_CannedMessageConfig canned_message;
/* TODO: REPLACE */
ModuleConfig_AudioConfig audio;
} payload_variant;
} ModuleConfig;
/* Helper constants for enums */
#define _ModuleConfig_AudioConfig_Audio_Baud_MIN ModuleConfig_AudioConfig_Audio_Baud_CODEC2_DEFAULT
#define _ModuleConfig_AudioConfig_Audio_Baud_MAX ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B
#define _ModuleConfig_AudioConfig_Audio_Baud_ARRAYSIZE ((ModuleConfig_AudioConfig_Audio_Baud)(ModuleConfig_AudioConfig_Audio_Baud_CODEC2_700B+1))
#define _ModuleConfig_SerialConfig_Serial_Baud_MIN ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT
#define _ModuleConfig_SerialConfig_Serial_Baud_MAX ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600
#define _ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((ModuleConfig_SerialConfig_Serial_Baud)(ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1))
@@ -156,22 +183,29 @@ extern "C" {
/* Initializer values for message structs */
#define ModuleConfig_init_default {0, {ModuleConfig_MQTTConfig_init_default}}
#define ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0}
#define ModuleConfig_AudioConfig_init_default {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN}
#define ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0}
#define ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0}
#define ModuleConfig_RangeTestConfig_init_default {0, 0, 0}
#define ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0}
#define ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define ModuleConfig_init_zero {0, {ModuleConfig_MQTTConfig_init_zero}}
#define ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0}
#define ModuleConfig_AudioConfig_init_zero {0, 0, 0, 0, _ModuleConfig_AudioConfig_Audio_Baud_MIN}
#define ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _ModuleConfig_SerialConfig_Serial_Mode_MIN}
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0}
#define ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
#define ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0}
#define ModuleConfig_RangeTestConfig_init_zero {0, 0, 0}
#define ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0}
#define ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
/* Field tags (for use in manual encoding/decoding) */
#define ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define ModuleConfig_AudioConfig_mic_chan_tag 2
#define ModuleConfig_AudioConfig_amp_pin_tag 3
#define ModuleConfig_AudioConfig_ptt_pin_tag 4
#define ModuleConfig_AudioConfig_bitrate_tag 5
#define ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2
#define ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3
@@ -189,6 +223,7 @@ extern "C" {
#define ModuleConfig_ExternalNotificationConfig_active_tag 4
#define ModuleConfig_ExternalNotificationConfig_alert_message_tag 5
#define ModuleConfig_ExternalNotificationConfig_alert_bell_tag 6
#define ModuleConfig_ExternalNotificationConfig_use_pwm_tag 7
#define ModuleConfig_MQTTConfig_enabled_tag 1
#define ModuleConfig_MQTTConfig_address_tag 2
#define ModuleConfig_MQTTConfig_username_tag 3
@@ -222,6 +257,7 @@ extern "C" {
#define ModuleConfig_range_test_tag 5
#define ModuleConfig_telemetry_tag 6
#define ModuleConfig_canned_message_tag 7
#define ModuleConfig_audio_tag 8
/* Struct field encoding specification for nanopb */
#define ModuleConfig_FIELDLIST(X, a) \
@@ -231,7 +267,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,external_notification,payloa
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,store_forward,payload_variant.store_forward), 4) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,range_test,payload_variant.range_test), 5) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,telemetry,payload_variant.telemetry), 6) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8)
#define ModuleConfig_CALLBACK NULL
#define ModuleConfig_DEFAULT NULL
#define ModuleConfig_payload_variant_mqtt_MSGTYPE ModuleConfig_MQTTConfig
@@ -241,6 +278,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_varia
#define ModuleConfig_payload_variant_range_test_MSGTYPE ModuleConfig_RangeTestConfig
#define ModuleConfig_payload_variant_telemetry_MSGTYPE ModuleConfig_TelemetryConfig
#define ModuleConfig_payload_variant_canned_message_MSGTYPE ModuleConfig_CannedMessageConfig
#define ModuleConfig_payload_variant_audio_MSGTYPE ModuleConfig_AudioConfig
#define ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
@@ -252,6 +290,15 @@ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6)
#define ModuleConfig_MQTTConfig_CALLBACK NULL
#define ModuleConfig_MQTTConfig_DEFAULT NULL
#define ModuleConfig_AudioConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, mic_chan, 2) \
X(a, STATIC, SINGULAR, UINT32, amp_pin, 3) \
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 4) \
X(a, STATIC, SINGULAR, UENUM, bitrate, 5)
#define ModuleConfig_AudioConfig_CALLBACK NULL
#define ModuleConfig_AudioConfig_DEFAULT NULL
#define ModuleConfig_SerialConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
X(a, STATIC, SINGULAR, BOOL, echo, 2) \
@@ -269,7 +316,8 @@ X(a, STATIC, SINGULAR, UINT32, output_ms, 2) \
X(a, STATIC, SINGULAR, UINT32, output, 3) \
X(a, STATIC, SINGULAR, BOOL, active, 4) \
X(a, STATIC, SINGULAR, BOOL, alert_message, 5) \
X(a, STATIC, SINGULAR, BOOL, alert_bell, 6)
X(a, STATIC, SINGULAR, BOOL, alert_bell, 6) \
X(a, STATIC, SINGULAR, BOOL, use_pwm, 7)
#define ModuleConfig_ExternalNotificationConfig_CALLBACK NULL
#define ModuleConfig_ExternalNotificationConfig_DEFAULT NULL
@@ -315,6 +363,7 @@ X(a, STATIC, SINGULAR, BOOL, send_bell, 11)
extern const pb_msgdesc_t ModuleConfig_msg;
extern const pb_msgdesc_t ModuleConfig_MQTTConfig_msg;
extern const pb_msgdesc_t ModuleConfig_AudioConfig_msg;
extern const pb_msgdesc_t ModuleConfig_SerialConfig_msg;
extern const pb_msgdesc_t ModuleConfig_ExternalNotificationConfig_msg;
extern const pb_msgdesc_t ModuleConfig_StoreForwardConfig_msg;
@@ -325,6 +374,7 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define ModuleConfig_fields &ModuleConfig_msg
#define ModuleConfig_MQTTConfig_fields &ModuleConfig_MQTTConfig_msg
#define ModuleConfig_AudioConfig_fields &ModuleConfig_AudioConfig_msg
#define ModuleConfig_SerialConfig_fields &ModuleConfig_SerialConfig_msg
#define ModuleConfig_ExternalNotificationConfig_fields &ModuleConfig_ExternalNotificationConfig_msg
#define ModuleConfig_StoreForwardConfig_fields &ModuleConfig_StoreForwardConfig_msg
@@ -333,14 +383,15 @@ extern const pb_msgdesc_t ModuleConfig_CannedMessageConfig_msg;
#define ModuleConfig_CannedMessageConfig_fields &ModuleConfig_CannedMessageConfig_msg
/* Maximum encoded size of messages (where known) */
#define ModuleConfig_AudioConfig_size 22
#define ModuleConfig_CannedMessageConfig_size 49
#define ModuleConfig_ExternalNotificationConfig_size 20
#define ModuleConfig_MQTTConfig_size 105
#define ModuleConfig_ExternalNotificationConfig_size 22
#define ModuleConfig_MQTTConfig_size 169
#define ModuleConfig_RangeTestConfig_size 10
#define ModuleConfig_SerialConfig_size 26
#define ModuleConfig_StoreForwardConfig_size 22
#define ModuleConfig_TelemetryConfig_size 18
#define ModuleConfig_size 107
#define ModuleConfig_size 172
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -51,6 +51,9 @@ typedef enum _PortNum {
/* Waypoint payloads.
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */
PortNum_WAYPOINT_APP = 8,
/* Audio Payloads.
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */
PortNum_AUDIO_APP = 9,
/* Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module. */
PortNum_REPLY_APP = 32,

View File

@@ -33,7 +33,9 @@ typedef enum _TelemetrySensorType {
/* 3-Axis magnetic sensor */
TelemetrySensorType_QMC6310 = 9,
/* 6-Axis inertial measurement sensor */
TelemetrySensorType_QMI8658 = 10
TelemetrySensorType_QMI8658 = 10,
/* 3-Axis magnetic sensor */
TelemetrySensorType_QMC5883L = 11
} TelemetrySensorType;
/* Struct definitions */
@@ -85,8 +87,8 @@ typedef struct _Telemetry {
/* Helper constants for enums */
#define _TelemetrySensorType_MIN TelemetrySensorType_SENSOR_UNSET
#define _TelemetrySensorType_MAX TelemetrySensorType_QMI8658
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_QMI8658+1))
#define _TelemetrySensorType_MAX TelemetrySensorType_QMC5883L
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_QMC5883L+1))
#ifdef __cplusplus

View File

@@ -12,7 +12,7 @@
#include <HTTPBodyParser.hpp>
#include <HTTPMultipartBodyParser.hpp>
#include <HTTPURLEncodedBodyParser.hpp>
#include <json11.hpp>
#include "mqtt/JSON.h"
#ifdef ARCH_ESP32
#include "esp_task_wdt.h"
@@ -246,15 +246,15 @@ void htmlDeleteDir(const char *dirname)
root.close();
}
std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname,
uint8_t levels)
JSONArray htmlListDir(const char *dirname, uint8_t levels)
{
File root = FSCom.open(dirname, FILE_O_READ);
JSONArray fileList;
if (!root) {
return NULL;
return fileList;
}
if (!root.isDirectory()) {
return NULL;
return fileList;
}
// iterate over the file list
@@ -263,19 +263,19 @@ std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *,
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
if (levels) {
#ifdef ARCH_ESP32
htmlListDir(fileList, file.path(), levels - 1);
fileList.push_back(new JSONValue(htmlListDir(file.path(), levels - 1)));
#else
htmlListDir(fileList, file.name(), levels - 1);
fileList.push_back(new JSONValue(htmlListDir(file.name(), levels - 1)));
#endif
file.close();
}
} else {
std::map<char *, char *> thisFileMap;
thisFileMap[strdup("size")] = strdup(String(file.size()).c_str());
JSONObject thisFileMap;
thisFileMap["size"] = new JSONValue((int)file.size());
#ifdef ARCH_ESP32
thisFileMap[strdup("name")] = strdup(String(file.path()).substring(1).c_str());
thisFileMap["name"] = new JSONValue(String(file.path()).substring(1).c_str());
#else
thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str());
thisFileMap["name"] = new JSONValue(String(file.name()).substring(1).c_str());
#endif
if (String(file.name()).substring(1).endsWith(".gz")) {
#ifdef ARCH_ESP32
@@ -284,9 +284,9 @@ std::vector<std::map<char *, char *>> *htmlListDir(std::vector<std::map<char *,
String modifiedFile = String(file.name()).substring(1);
#endif
modifiedFile.remove((modifiedFile.length() - 3), 3);
thisFileMap[strdup("nameModified")] = strdup(modifiedFile.c_str());
thisFileMap["nameModified"] = new JSONValue(modifiedFile.c_str());
}
fileList->push_back(thisFileMap);
fileList.push_back(new JSONValue(thisFileMap));
}
file.close();
file = root.openNextFile();
@@ -301,29 +301,31 @@ void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "GET");
using namespace json11;
auto fileList = htmlListDir(new std::vector<std::map<char *, char *>>(), "/static", 10);
auto fileList = htmlListDir("/static", 10);
// create json output structure
Json filesystemObj = Json::object{
{"total", String(FSCom.totalBytes()).c_str()},
{"used", String(FSCom.usedBytes()).c_str()},
{"free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()},
};
JSONObject filesystemObj;
filesystemObj["total"] = new JSONValue((int)FSCom.totalBytes());
filesystemObj["used"] = new JSONValue((int)FSCom.usedBytes());
filesystemObj["free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes()));
Json jsonObjInner = Json::object{{"files", Json(*fileList)}, {"filesystem", filesystemObj}};
JSONObject jsonObjInner;
jsonObjInner["files"] = new JSONValue(fileList);
jsonObjInner["filesystem"] = new JSONValue(filesystemObj);
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
JSONObject jsonObjOuter;
jsonObjOuter["data"] = new JSONValue(jsonObjInner);
jsonObjOuter["status"] = new JSONValue("ok");
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
}
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
ResourceParameters *params = req->getParams();
std::string paramValDelete;
@@ -334,15 +336,19 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
std::string pathDelete = "/" + paramValDelete;
if (FSCom.remove(pathDelete.c_str())) {
Serial.println(pathDelete.c_str());
Json jsonObjOuter = Json::object{{"status", "ok"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONObject jsonObjOuter;
jsonObjOuter["status"] = new JSONValue("ok");
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
return;
} else {
Serial.println(pathDelete.c_str());
Json jsonObjOuter = Json::object{{"status", "Error"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONObject jsonObjOuter;
jsonObjOuter["status"] = new JSONValue("Error");
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
return;
}
}
@@ -559,8 +565,6 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
void handleReport(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
ResourceParameters *params = req->getParams();
std::string content;
@@ -579,81 +583,87 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
}
// data->airtime->tx_log
std::vector<String> txLogValues;
JSONArray txLogValues;
uint32_t *logArray;
logArray = airTime->airtimeReport(TX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
txLogValues.push_back(String(tmp));
txLogValues.push_back(new JSONValue((int)logArray[i]));
}
// data->airtime->rx_log
std::vector<String> rxLogValues;
JSONArray rxLogValues;
logArray = airTime->airtimeReport(RX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
rxLogValues.push_back(String(tmp));
rxLogValues.push_back(new JSONValue((int)logArray[i]));
}
// data->airtime->rx_all_log
std::vector<String> rxAllLogValues;
JSONArray rxAllLogValues;
logArray = airTime->airtimeReport(RX_ALL_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
rxAllLogValues.push_back(String(tmp));
rxAllLogValues.push_back(new JSONValue((int)logArray[i]));
}
Json jsonObjAirtime = Json::object{
{"tx_log", Json(txLogValues)},
{"rx_log", Json(rxLogValues)},
{"rx_all_log", Json(rxAllLogValues)},
{"channel_utilization", Json(airTime->channelUtilizationPercent())},
{"utilization_tx", Json(airTime->utilizationTXPercent())},
{"seconds_since_boot", Json(int(airTime->getSecondsSinceBoot()))},
{"seconds_per_period", Json(int(airTime->getSecondsPerPeriod()))},
{"periods_to_log", Json(airTime->getPeriodsToLog())},
};
// data->airtime
JSONObject jsonObjAirtime;
jsonObjAirtime["tx_log"] = new JSONValue(txLogValues);
jsonObjAirtime["rx_log"] = new JSONValue(rxLogValues);
jsonObjAirtime["rx_all_log"] = new JSONValue(rxAllLogValues);
jsonObjAirtime["channel_utilization"] = new JSONValue(airTime->channelUtilizationPercent());
jsonObjAirtime["utilization_tx"] = new JSONValue(airTime->utilizationTXPercent());
jsonObjAirtime["seconds_since_boot"] = new JSONValue(int(airTime->getSecondsSinceBoot()));
jsonObjAirtime["seconds_per_period"] = new JSONValue(int(airTime->getSecondsPerPeriod()));
jsonObjAirtime["periods_to_log"] = new JSONValue(airTime->getPeriodsToLog());
// data->wifi
String ipStr = String(WiFi.localIP().toString());
Json jsonObjWifi = Json::object{{"rssi", String(WiFi.RSSI())}, {"ip", ipStr.c_str()}};
JSONObject jsonObjWifi;
jsonObjWifi["rssi"] = new JSONValue(WiFi.RSSI());
jsonObjWifi["ip"] = new JSONValue(WiFi.localIP().toString().c_str());
// data->memory
Json jsonObjMemory = Json::object{{"heap_total", Json(int(ESP.getHeapSize()))},
{"heap_free", Json(int(ESP.getFreeHeap()))},
{"psram_total", Json(int(ESP.getPsramSize()))},
{"psram_free", Json(int(ESP.getFreePsram()))},
{"fs_total", String(FSCom.totalBytes()).c_str()},
{"fs_used", String(FSCom.usedBytes()).c_str()},
{"fs_free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()}};
JSONObject jsonObjMemory;
jsonObjMemory["heap_total"] = new JSONValue((int)ESP.getHeapSize());
jsonObjMemory["heap_free"] = new JSONValue((int)ESP.getFreeHeap());
jsonObjMemory["psram_total"] = new JSONValue((int)ESP.getPsramSize());
jsonObjMemory["psram_free"] = new JSONValue((int)ESP.getFreePsram());
jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes());
jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes());
jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes()));
// data->power
Json jsonObjPower = Json::object{{"battery_percent", Json(powerStatus->getBatteryChargePercent())},
{"battery_voltage_mv", Json(powerStatus->getBatteryVoltageMv())},
{"has_battery", BoolToString(powerStatus->getHasBattery())},
{"has_usb", BoolToString(powerStatus->getHasUSB())},
{"is_charging", BoolToString(powerStatus->getIsCharging())}};
JSONObject jsonObjPower;
jsonObjPower["battery_percent"] = new JSONValue(powerStatus->getBatteryChargePercent());
jsonObjPower["battery_voltage_mv"] = new JSONValue(powerStatus->getBatteryVoltageMv());
jsonObjPower["has_battery"] = new JSONValue(BoolToString(powerStatus->getHasBattery()));
jsonObjPower["has_usb"] = new JSONValue(BoolToString(powerStatus->getHasUSB()));
jsonObjPower["is_charging"] = new JSONValue(BoolToString(powerStatus->getIsCharging()));
// data->device
Json jsonObjDevice = Json::object{{"reboot_counter", Json(int(myNodeInfo.reboot_count))}};
JSONObject jsonObjDevice;
jsonObjDevice["reboot_counter"] = new JSONValue((int)myNodeInfo.reboot_count);
// data->radio
Json jsonObjRadio = Json::object{{"frequency", Json(RadioLibInterface::instance->getFreq())},
{"lora_channel", Json(int(RadioLibInterface::instance->getChannelNum()))}};
JSONObject jsonObjRadio;
jsonObjRadio["frequency"] = new JSONValue(RadioLibInterface::instance->getFreq());
jsonObjRadio["lora_channel"] = new JSONValue((int)RadioLibInterface::instance->getChannelNum());
// collect data to inner data object
Json jsonObjInner = Json::object{{"airtime", jsonObjAirtime}, {"wifi", jsonObjWifi}, {"memory", jsonObjMemory},
{"power", jsonObjPower}, {"device", jsonObjDevice}, {"radio", jsonObjRadio}};
JSONObject jsonObjInner;
jsonObjInner["airtime"] = new JSONValue(jsonObjAirtime);
jsonObjInner["wifi"] = new JSONValue(jsonObjWifi);
jsonObjInner["memory"] = new JSONValue(jsonObjMemory);
jsonObjInner["power"] = new JSONValue(jsonObjPower);
jsonObjInner["device"] = new JSONValue(jsonObjDevice);
jsonObjInner["radio"] = new JSONValue(jsonObjRadio);
// create json output structure
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
JSONObject jsonObjOuter;
jsonObjOuter["data"] = new JSONValue(jsonObjInner);
jsonObjOuter["status"] = new JSONValue("ok");
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
}
/*
@@ -767,8 +777,6 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res)
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "POST");
@@ -797,15 +805,15 @@ void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
#endif
}
Json jsonObjOuter = Json::object{{"status", "ok"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONObject jsonObjOuter;
jsonObjOuter["status"] = new JSONValue("ok");
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
}
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "GET");
@@ -814,7 +822,7 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
int n = WiFi.scanNetworks();
// build list of network objects
std::vector<Json> networkObjs;
JSONArray networkObjs;
if (n > 0) {
for (int i = 0; i < n; ++i) {
char ssidArray[50];
@@ -823,8 +831,10 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
ssidString.toCharArray(ssidArray, 50);
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
Json thisNetwork = Json::object{{"ssid", ssidArray}, {"rssi", WiFi.RSSI(i)}};
networkObjs.push_back(thisNetwork);
JSONObject thisNetwork;
thisNetwork["ssid"] = new JSONValue(ssidArray);
thisNetwork["rssi"] = new JSONValue(WiFi.RSSI(i));
networkObjs.push_back(new JSONValue(thisNetwork));
}
// Yield some cpu cycles to IP stack.
// This is important in case the list is large and it takes us time to return
@@ -834,9 +844,12 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
}
// build output structure
Json jsonObjOuter = Json::object{{"data", networkObjs}, {"status", "ok"}};
JSONObject jsonObjOuter;
jsonObjOuter["data"] = new JSONValue(networkObjs);
jsonObjOuter["status"] = new JSONValue("ok");
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
JSONValue *value = new JSONValue(jsonObjOuter);
res->print(value->Stringify().c_str());
delete value;
}

View File

@@ -35,32 +35,49 @@ char ourHost[16];
bool APStartupComplete = 0;
unsigned long lastrun_ntp = 0;
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
static Periodic *wifiReconnect;
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 (config.network.wifi_enabled && needReconnect) {
if (!*wifiPsw) // Treat empty password as no password
wifiPsw = NULL;
if (*wifiName) {
needReconnect = false;
needReconnect = false;
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
// Make sure we clear old connection credentials
WiFi.disconnect(false, true);
DEBUG_MSG("... Reconnecting to WiFi access point\n");
DEBUG_MSG("... Reconnecting to WiFi access point %s\n",wifiName);
int n = WiFi.scanNetworks();
if (n > 0) {
for (int i = 0; i < n; ++i) {
DEBUG_MSG("Found WiFi network %s, signal strength %d\n", WiFi.SSID(i).c_str(), WiFi.RSSI(i));
yield();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(wifiName, wifiPsw);
} else {
DEBUG_MSG("No networks found during site survey. Rebooting MCU...\n");
screen->startRebootScreen();
rebootAtMsec = millis() + 5000;
}
}
#ifndef DISABLE_NTP
if (WiFi.isConnected()) {
if (WiFi.isConnected() && (((millis() - lastrun_ntp) > 43200000) || (lastrun_ntp == 0))) { // every 12 hours
DEBUG_MSG("Updating NTP time\n");
if (timeClient.update()) {
DEBUG_MSG("NTP Request Success - Setting RTCQualityNTP if needed\n");
@@ -70,6 +87,7 @@ static int32_t reconnectWiFi()
tv.tv_usec = 0;
perhapsSetRTC(RTCQualityNTP, &tv);
lastrun_ntp = millis();
} else {
DEBUG_MSG("NTP Update failed\n");
@@ -77,11 +95,13 @@ static int32_t reconnectWiFi()
}
#endif
return 43200 * 1000; // every 12 hours
if (config.network.wifi_enabled && !WiFi.isConnected()) {
return 1000; // check once per second
} else {
return 300000; // every 5 minutes
}
}
static Periodic *wifiReconnect;
bool isWifiAvailable()
{
@@ -95,20 +115,10 @@ bool isWifiAvailable()
// Disable WiFi
void deinitWifi()
{
/*
Note from Jm (jm@casler.org - Sept 16, 2020):
A bug in the ESP32 SDK was introduced in Oct 2019 that keeps the WiFi radio from
turning back on after it's shut off. See:
https://github.com/espressif/arduino-esp32/issues/3522
Until then, WiFi should only be allowed when there's no power
saving on the 2.4g transceiver.
*/
DEBUG_MSG("WiFi deinit\n");
if (isWifiAvailable()) {
WiFi.disconnect(true);
WiFi.mode(WIFI_MODE_NULL);
DEBUG_MSG("WiFi Turned Off\n");
// WiFi.printDiag(Serial);
@@ -169,6 +179,15 @@ bool initWifi()
WiFi.mode(WIFI_MODE_STA);
WiFi.setHostname(ourHost);
WiFi.onEvent(WiFiEvent);
WiFi.setAutoReconnect(false);
WiFi.setSleep(false);
if (config.network.eth_mode == Config_NetworkConfig_EthMode_STATIC && config.network.ipv4_config.ip != 0) {
WiFi.config(config.network.ipv4_config.ip,
config.network.ipv4_config.gateway,
config.network.ipv4_config.subnet,
config.network.ipv4_config.dns,
config.network.ipv4_config.dns); // Wifi wants two DNS servers... set both to the same value
}
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
@@ -222,9 +241,9 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
DEBUG_MSG("Disconnected from WiFi access point\n");
// Event 5
WiFi.disconnect(false, true);
needReconnect = true;
wifiReconnect->setIntervalFromNow(1000);
break;
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
DEBUG_MSG("Authentication mode of access point has changed\n");
@@ -236,6 +255,9 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case SYSTEM_EVENT_STA_LOST_IP:
DEBUG_MSG("Lost IP address and IP address is reset to 0\n");
WiFi.disconnect(false, true);
needReconnect = true;
wifiReconnect->setIntervalFromNow(1000);
break;
case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
DEBUG_MSG("WiFi Protected Setup (WPS): succeeded in enrollee mode\n");
@@ -251,8 +273,6 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case SYSTEM_EVENT_AP_START:
DEBUG_MSG("WiFi access point started\n");
onNetworkConnected();
break;
case SYSTEM_EVENT_AP_STOP:
DEBUG_MSG("WiFi access point stopped\n");

View File

@@ -13,7 +13,10 @@
#include "unistd.h"
#endif
#define DEFAULT_REBOOT_SECONDS 5
AdminModule *adminModule;
bool hasOpenEditTransaction;
/// A special reserved string to indicate strings we can not share with external nodes. We will use this 'reserved' word instead.
/// Also, to make setting work correctly, if someone tries to set a string to this reserved value we assume they don't really want
@@ -133,13 +136,23 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
case AdminMessage_factory_reset_tag: {
DEBUG_MSG("Initiating factory reset\n");
nodeDB.factoryReset();
reboot(5);
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
case AdminMessage_nodedb_reset_tag: {
} case AdminMessage_nodedb_reset_tag: {
DEBUG_MSG("Initiating node-db reset\n");
nodeDB.resetNodes();
reboot(5);
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
case AdminMessage_begin_edit_settings_tag: {
DEBUG_MSG("Beginning transaction for editing settings\n");
hasOpenEditTransaction = true;
break;
}
case AdminMessage_commit_edit_settings_tag: {
DEBUG_MSG("Committing transaction for edited settings\n");
hasOpenEditTransaction = false;
saveChanges(SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
break;
}
#ifdef ARCH_PORTDUINO
@@ -163,6 +176,12 @@ bool AdminModule::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
}
break;
}
// If asked for a response and it is not yet set, generate an 'ACK' response
if (mp.decoded.want_response && !myReply) {
myReply = allocErrorResponse(Routing_Error_NONE, &mp);
}
return handled;
}
@@ -192,9 +211,8 @@ void AdminModule::handleSetOwner(const User &o)
}
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);
service.reloadOwner(!hasOpenEditTransaction);
saveChanges(SEGMENT_DEVICESTATE);
}
}
@@ -220,7 +238,7 @@ void AdminModule::handleSetConfig(const Config &c)
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);
saveChanges(SEGMENT_DEVICESTATE, false);
break;
case Config_power_tag:
DEBUG_MSG("Setting config: Power\n");
@@ -252,9 +270,8 @@ void AdminModule::handleSetConfig(const Config &c)
config.bluetooth = c.payload_variant.bluetooth;
break;
}
service.reloadConfig(SEGMENT_CONFIG);
reboot(5);
saveChanges(SEGMENT_CONFIG);
}
void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
@@ -295,17 +312,21 @@ void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
moduleConfig.has_canned_message = true;
moduleConfig.canned_message = c.payload_variant.canned_message;
break;
case ModuleConfig_audio_tag:
DEBUG_MSG("Setting module config: Audio\n");
moduleConfig.has_audio = true;
moduleConfig.audio = c.payload_variant.audio;
break;
}
service.reloadConfig(SEGMENT_MODULECONFIG);
reboot(5);
saveChanges(SEGMENT_MODULECONFIG);
}
void AdminModule::handleSetChannel(const Channel &cc)
{
channels.setChannel(cc);
channels.onConfigChanged(); // tell the radios about this change
nodeDB.saveChannelsToDisk();
saveChanges(SEGMENT_CHANNELS, false);
}
/**
@@ -421,6 +442,11 @@ void AdminModule::handleGetModuleConfig(const MeshPacket &req, const uint32_t co
res.get_module_config_response.which_payload_variant = ModuleConfig_canned_message_tag;
res.get_module_config_response.payload_variant.canned_message = moduleConfig.canned_message;
break;
case AdminMessage_ModuleConfigType_AUDIO_CONFIG:
DEBUG_MSG("Getting module config: Audio\n");
res.get_module_config_response.which_payload_variant = ModuleConfig_audio_tag;
res.get_module_config_response.payload_variant.audio = moduleConfig.audio;
break;
}
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
@@ -469,6 +495,20 @@ void AdminModule::reboot(int32_t seconds)
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
}
void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
{
if (!hasOpenEditTransaction) {
DEBUG_MSG("Saving changes to disk\n");
service.reloadConfig(saveWhat); // Calls saveToDisk among other things
} else {
DEBUG_MSG("Delaying save of changes to disk until the open transaction is committed\n");
}
if (shouldReboot)
{
reboot(DEFAULT_REBOOT_SECONDS);
}
}
AdminModule::AdminModule() : ProtobufModule("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
{
// restrict to the admin channel for rx

View File

@@ -2,7 +2,7 @@
#include "ProtobufModule.h"
/**
* Routing module for router control messages
* Admin module for admin messages
*/
class AdminModule : public ProtobufModule<AdminMessage>
{
@@ -20,6 +20,9 @@ class AdminModule : public ProtobufModule<AdminMessage>
virtual bool handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *p) override;
private:
bool hasOpenEditTransaction = false;
void saveChanges(int saveWhat, bool shouldReboot = true);
/**
* Getters
*/

View File

@@ -176,7 +176,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
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->payload = MATRIXKEY;
this->currentMessageIndex = event->kbchar -1;
this->lastTouchMillis = millis();
validEvent = true;
@@ -246,7 +246,12 @@ int32_t CannedMessageModule::runOnce()
}
} else {
if ((this->messagesCount > this->currentMessageIndex) && (strlen(this->messages[this->currentMessageIndex]) > 0)) {
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true);
if(strcmp (this->messages[this->currentMessageIndex], "~") == 0) {
powerFSM.trigger(EVENT_PRESS);
return INT32_MAX;
} else {
sendText(NODENUM_BROADCAST, this->messages[this->currentMessageIndex], true);
}
this->runState = CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE;
} else {
DEBUG_MSG("Reset message is empty.\n");

View File

@@ -76,7 +76,7 @@ int32_t ExternalNotificationModule::runOnce()
// moduleConfig.external_notification.output_ms = 1000;
// moduleConfig.external_notification.output = 13;
if (externalCurrentState) {
if (externalCurrentState && !moduleConfig.external_notification.use_pwm) {
// If the output is turned on, turn it back off after the given period of time.
if (externalTurnedOn + (moduleConfig.external_notification.output_ms
@@ -84,13 +84,13 @@ int32_t ExternalNotificationModule::runOnce()
: EXT_NOTIFICATION_MODULE_OUTPUT_MS) <
millis()) {
DEBUG_MSG("Turning off external notification\n");
if (output != PIN_BUZZER) {
setExternalOff();
}
setExternalOff();
}
}
return (25);
if (moduleConfig.external_notification.use_pwm)
return INT32_MAX; // we don't need this thread here...
else
return 25;
}
void ExternalNotificationModule::setExternalOn()
@@ -116,9 +116,6 @@ ExternalNotificationModule::ExternalNotificationModule()
: SinglePortModule("ExternalNotificationModule", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread(
"ExternalNotificationModule")
{
// restrict to the admin channel for rx
boundChannel = Channels::gpioChannel;
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
@@ -131,7 +128,7 @@ ExternalNotificationModule::ExternalNotificationModule()
// moduleConfig.external_notification.alert_bell = 1;
// moduleConfig.external_notification.output_ms = 1000;
// moduleConfig.external_notification.output = 13;
if (moduleConfig.external_notification.enabled) {
DEBUG_MSG("Initializing External Notification Module\n");
@@ -140,14 +137,19 @@ ExternalNotificationModule::ExternalNotificationModule()
? moduleConfig.external_notification.output
: EXT_NOTIFICATION_MODULE_OUTPUT;
if (output != PIN_BUZZER) {
if (!moduleConfig.external_notification.use_pwm) {
// 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 {
config.device.buzzer_gpio = config.device.buzzer_gpio
? config.device.buzzer_gpio
: PIN_BUZZER;
// in PWM Mode we force the buzzer pin if it is set
DEBUG_MSG("Using Pin %i in PWM mode\n", config.device.buzzer_gpio);
}
} else {
DEBUG_MSG("External Notification Module Disabled\n");
@@ -168,7 +170,7 @@ 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) {
if (output != PIN_BUZZER) {
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn();
} else {
playBeep();
@@ -179,7 +181,7 @@ ProcessMessage ExternalNotificationModule::handleReceived(const MeshPacket &mp)
if (moduleConfig.external_notification.alert_message) {
DEBUG_MSG("externalNotificationModule - Notification Module\n");
if (output != PIN_BUZZER) {
if (!moduleConfig.external_notification.use_pwm) {
setExternalOn();
} else {
playBeep();

View File

@@ -19,6 +19,9 @@
#ifdef ARCH_ESP32
#include "modules/esp32/RangeTestModule.h"
#include "modules/esp32/StoreForwardModule.h"
#ifdef USE_SX1280
#include "modules/esp32/AudioModule.h"
#endif
#endif
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
#include "modules/ExternalNotificationModule.h"
@@ -65,17 +68,16 @@ void setupModules()
#endif
#ifdef ARCH_ESP32
// Only run on an esp32 based device.
/*
Maintained by MC Hamster (Jm Casler) jm@casler.org
*/
#ifdef USE_SX1280
new AudioModule();
#endif
new ExternalNotificationModule();
storeForwardModule = new StoreForwardModule();
new RangeTestModule();
#elif defined(ARCH_NRF52)
new ExternalNotificationModule();
new ExternalNotificationModule();
#endif
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra acks

View File

@@ -16,6 +16,14 @@ int32_t BME280Sensor::runOnce() {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = bme280.begin(nodeTelemetrySensorsMap[sensorType]);
bme280.setSampling( Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1, // Temp. oversampling
Adafruit_BME280::SAMPLING_X1, // Pressure oversampling
Adafruit_BME280::SAMPLING_X1, // Humidity oversampling
Adafruit_BME280::FILTER_OFF,
Adafruit_BME280::STANDBY_MS_1000);
return initI2CSensor();
}
@@ -23,6 +31,7 @@ void BME280Sensor::setup() { }
bool BME280Sensor::getMetrics(Telemetry *measurement) {
DEBUG_MSG("BME280Sensor::getMetrics\n");
bme280.takeForcedMeasurement();
measurement->variant.environment_metrics.temperature = bme280.readTemperature();
measurement->variant.environment_metrics.relative_humidity = bme280.readHumidity();
measurement->variant.environment_metrics.barometric_pressure = bme280.readPressure() / 100.0F;

View File

@@ -14,25 +14,19 @@ int32_t BME680Sensor::runOnce() {
if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = bme680.begin(nodeTelemetrySensorsMap[sensorType]);
status = bme680.begin(nodeTelemetrySensorsMap[sensorType]);
return initI2CSensor();
}
void BME680Sensor::setup()
{
// Set up oversampling and filter initialization
bme680.setTemperatureOversampling(BME680_OS_8X);
bme680.setHumidityOversampling(BME680_OS_2X);
bme680.setPressureOversampling(BME680_OS_4X);
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme680.setGasHeater(320, 150); // 320*C for 150 ms
}
void BME680Sensor::setup() { }
bool BME680Sensor::getMetrics(Telemetry *measurement) {
measurement->variant.environment_metrics.temperature = bme680.readTemperature();
measurement->variant.environment_metrics.relative_humidity = bme680.readHumidity();
measurement->variant.environment_metrics.barometric_pressure = bme680.readPressure() / 100.0F;
measurement->variant.environment_metrics.gas_resistance = bme680.readGas() / 1000.0;
bme680.performReading();
measurement->variant.environment_metrics.temperature = bme680.temperature;
measurement->variant.environment_metrics.relative_humidity = bme680.humidity;
measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F;
measurement->variant.environment_metrics.gas_resistance = bme680.gas_resistance / 1000.0;
return true;
}

View File

@@ -16,6 +16,13 @@ int32_t BMP280Sensor::runOnce() {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
}
status = bmp280.begin(nodeTelemetrySensorsMap[sensorType]);
bmp280.setSampling( Adafruit_BMP280::MODE_FORCED,
Adafruit_BMP280::SAMPLING_X1, // Temp. oversampling
Adafruit_BMP280::SAMPLING_X1, // Pressure oversampling
Adafruit_BMP280::FILTER_OFF,
Adafruit_BMP280::STANDBY_MS_1000);
return initI2CSensor();
}
@@ -23,6 +30,7 @@ void BMP280Sensor::setup() { }
bool BMP280Sensor::getMetrics(Telemetry *measurement) {
DEBUG_MSG("BMP280Sensor::getMetrics\n");
bmp280.takeForcedMeasurement();
measurement->variant.environment_metrics.temperature = bmp280.readTemperature();
measurement->variant.environment_metrics.barometric_pressure = bmp280.readPressure() / 100.0F;

View File

@@ -0,0 +1,241 @@
#include "configuration.h"
#include "AudioModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "FSCommon.h"
#include <assert.h>
/*
AudioModule
A interface to send raw codec2 audio data over the mesh network. Based on the example code from the ESP32_codec2 project.
https://github.com/deulis/ESP32_Codec2
Codec 2 is a low-bitrate speech audio codec (speech coding)
that is patent free and open source develop by David Grant Rowe.
http://www.rowetel.com/ and https://github.com/drowe67/codec2
Basic Usage:
1) Enable the module by setting audio.codec2_enabled to 1.
2) Set the pins (audio.mic_pin / audio.amp_pin) for your preferred microphone and amplifier GPIO pins.
On tbeam, recommend to use:
audio.mic_chan 6 (GPIO 34)
audio.amp_pin 14
audio.ptt_pin 39
3) Set audio.timeout to the amount of time to wait before we consider
your voice stream as "done".
4) Set audio.bitrate to the desired codec2 rate (CODEC2_3200, CODEC2_2400, CODEC2_1600, CODEC2_1400, CODEC2_1300, CODEC2_1200, CODEC2_700, CODEC2_700B)
KNOWN PROBLEMS
* Until the module is initilized by the startup sequence, the amp_pin pin is in a floating
state. This may produce a bit of "noise".
* Will not work on NRF and the Linux device targets.
*/
#define AMIC 6
#define AAMP 14
#define PTT_PIN 39
#define AUDIO_MODULE_RX_BUFFER 128
#define AUDIO_MODULE_DATA_MAX Constants_DATA_PAYLOAD_LEN
#define AUDIO_MODULE_MODE 7 // 700B
#define AUDIO_MODULE_ACK 1
#if defined(ARCH_ESP32) && defined(USE_SX1280)
AudioModule *audioModule;
ButterworthFilter hp_filter(240, 8000, ButterworthFilter::ButterworthFilter::Highpass, 1);
//int16_t 1KHz sine test tone
int16_t Sine1KHz[8] = { -21210 , -30000, -21210, 0 , 21210 , 30000 , 21210, 0 };
int Sine1KHz_index = 0;
uint8_t rx_raw_audio_value = 127;
AudioModule::AudioModule() : SinglePortModule("AudioModule", PortNum_AUDIO_APP), concurrency::OSThread("AudioModule") {
audio_fifo.init();
}
void AudioModule::run_codec2()
{
if (state == State::tx)
{
for (int i = 0; i < ADC_BUFFER_SIZE; i++)
speech[i] = (int16_t)hp_filter.Update((float)speech[i]);
codec2_encode(codec2_state, tx_encode_frame + tx_encode_frame_index, speech);
//increment the pointer where the encoded frame must be saved
tx_encode_frame_index += 8;
//If it is the 5th time then we have a ready trasnmission frame
if (tx_encode_frame_index == ENCODE_FRAME_SIZE)
{
tx_encode_frame_index = 0;
//Transmit it
sendPayload();
}
}
if (state == State::rx) //Receiving
{
//Make a cycle to get each codec2 frame from the received frame
for (int i = 0; i < ENCODE_FRAME_SIZE; i += 8)
{
//Decode the codec2 frame
codec2_decode(codec2_state, output_buffer, rx_encode_frame + i);
// Add to the audio buffer the 320 samples resulting of the decode of the codec2 frame.
for (int g = 0; g < ADC_BUFFER_SIZE; g++)
audio_fifo.put(output_buffer[g]);
}
}
state = State::standby;
}
void AudioModule::handleInterrupt()
{
audioModule->onTimer();
}
void AudioModule::onTimer()
{
if (state == State::tx) {
adc_buffer[adc_buffer_index++] = (16 * adc1_get_raw(mic_chan)) - 32768;
//If you want to test with a 1KHz tone, comment the line above and descomment the three lines below
// adc_buffer[adc_buffer_index++] = Sine1KHz[Sine1KHz_index++];
// if (Sine1KHz_index >= 8)
// Sine1KHz_index = 0;
if (adc_buffer_index == ADC_BUFFER_SIZE) {
adc_buffer_index = 0;
memcpy((void*)speech, (void*)adc_buffer, 2 * ADC_BUFFER_SIZE);
audioModule->setIntervalFromNow(0); // process buffer immediately
}
} else if (state == State::rx) {
int16_t v;
//Get a value from audio_fifo and convert it to 0 - 255 to play it in the ADC
//If none value is available the DAC will play the last one that was read, that's
//why the rx_raw_audio_value variable is a global one.
if (audio_fifo.get(&v))
rx_raw_audio_value = (uint8_t)((v + 32768) / 256);
//Play
dacWrite(moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP, rx_raw_audio_value);
}
}
int32_t AudioModule::runOnce()
{
if (moduleConfig.audio.codec2_enabled) {
if (firstTime) {
DEBUG_MSG("Initializing ADC on Channel %u\n", moduleConfig.audio.mic_chan ? moduleConfig.audio.mic_chan : AMIC);
mic_chan = moduleConfig.audio.mic_chan ? (adc1_channel_t)(int)moduleConfig.audio.mic_chan : (adc1_channel_t)AMIC;
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(mic_chan, ADC_ATTEN_DB_6);
// Start a timer at 8kHz to sample the ADC and play the audio on the DAC.
uint32_t cpufreq = getCpuFrequencyMhz();
switch (cpufreq){
case 160:
adcTimer = timerBegin(3, 1000, true); // 160 MHz / 1000 = 160KHz
break;
case 240:
adcTimer = timerBegin(3, 1500, true); // 240 MHz / 1500 = 160KHz
break;
case 320:
adcTimer = timerBegin(3, 2000, true); // 320 MHz / 2000 = 160KHz
break;
case 80:
default:
adcTimer = timerBegin(3, 500, true); // 80 MHz / 500 = 160KHz
break;
}
timerAttachInterrupt(adcTimer, &AudioModule::handleInterrupt, true);
timerAlarmWrite(adcTimer, 20, true); // Interrupts when counter == 20, 8.000 times a second
timerAlarmEnable(adcTimer);
DEBUG_MSG("Initializing DAC on Pin %u\n", moduleConfig.audio.amp_pin ? moduleConfig.audio.amp_pin : AAMP);
DEBUG_MSG("Initializing PTT on Pin %u\n", moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN);
// Configure PTT input
pinMode(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN, INPUT_PULLUP);
state = State::rx;
DEBUG_MSG("Setting up codec2 in mode %u\n", moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE);
codec2_state = codec2_create(moduleConfig.audio.bitrate ? moduleConfig.audio.bitrate : AUDIO_MODULE_MODE);
codec2_set_lpc_post_filter(codec2_state, 1, 0, 0.8, 0.2);
firstTime = 0;
} else {
// Check if we have a PTT press
if (digitalRead(moduleConfig.audio.ptt_pin ? moduleConfig.audio.ptt_pin : PTT_PIN) == LOW) {
// PTT pressed, recording
state = State::tx;
}
if (state != State::standby) {
run_codec2();
}
}
return 100;
} else {
DEBUG_MSG("Audio Module Disabled\n");
return INT32_MAX;
}
}
MeshPacket *AudioModule::allocReply()
{
auto reply = allocDataPacket(); // Allocate a packet for sending
return reply;
}
void AudioModule::sendPayload(NodeNum dest, bool wantReplies)
{
MeshPacket *p = allocReply();
p->to = dest;
p->decoded.want_response = wantReplies;
p->want_ack = AUDIO_MODULE_ACK;
p->decoded.payload.size = ENCODE_FRAME_SIZE;
memcpy(p->decoded.payload.bytes, tx_encode_frame, p->decoded.payload.size);
service.sendToMesh(p);
}
ProcessMessage AudioModule::handleReceived(const MeshPacket &mp)
{
if (moduleConfig.audio.codec2_enabled) {
auto &p = mp.decoded;
if (getFrom(&mp) != nodeDB.getNodeNum()) {
if (p.payload.size == ENCODE_FRAME_SIZE) {
memcpy(rx_encode_frame, p.payload.bytes, p.payload.size);
state = State::rx;
audioModule->setIntervalFromNow(0);
run_codec2();
} else {
DEBUG_MSG("Invalid payload size %u != %u\n", p.payload.size, ENCODE_FRAME_SIZE);
}
}
}
return ProcessMessage::CONTINUE;
}
#endif

View File

@@ -0,0 +1,68 @@
#pragma once
#include "SinglePortModule.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "NodeDB.h"
#include <Arduino.h>
#include <driver/adc.h>
#include <functional>
#if defined(ARCH_ESP32) && defined(USE_SX1280)
#include <codec2.h>
#include <ButterworthFilter.h>
#include <FastAudioFIFO.h>
#endif
#define ADC_BUFFER_SIZE 320 // 40ms of voice in 8KHz sampling frequency
#define ENCODE_FRAME_SIZE 40 // 5 codec2 frames of 8 bytes each
class AudioModule : public SinglePortModule, private concurrency::OSThread
{
#if defined(ARCH_ESP32) && defined(USE_SX1280)
bool firstTime = 1;
hw_timer_t* adcTimer = NULL;
uint16_t adc_buffer[ADC_BUFFER_SIZE] = {};
int16_t speech[ADC_BUFFER_SIZE] = {};
int16_t output_buffer[ADC_BUFFER_SIZE] = {};
unsigned char rx_encode_frame[ENCODE_FRAME_SIZE] = {};
unsigned char tx_encode_frame[ENCODE_FRAME_SIZE] = {};
int tx_encode_frame_index = 0;
FastAudioFIFO audio_fifo;
uint16_t adc_buffer_index = 0;
adc1_channel_t mic_chan = (adc1_channel_t)0;
struct CODEC2* codec2_state = NULL;
enum State
{
standby, rx, tx
};
volatile State state = State::tx;
public:
AudioModule();
/**
* Send our payload into the mesh
*/
void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
protected:
virtual int32_t runOnce() override;
static void handleInterrupt();
void onTimer();
void run_codec2();
virtual MeshPacket *allocReply() override;
/** Called to handle a particular incoming message
* @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;
#endif
};
extern AudioModule *audioModule;

View File

@@ -12,7 +12,7 @@
//#include <assert.h>
/*
As a sender, I can send packets every n-seonds. These packets include an incramented PacketID.
As a sender, I can send packets every n seconds. These packets include an incremented PacketID.
As a receiver, I can receive packets from multiple senders. These packets can be saved to the Filesystem.
*/
@@ -36,12 +36,12 @@ int32_t RangeTestModule::runOnce()
without having to configure it from the PythonAPI or WebUI.
*/
//moduleConfig.range_test.enabled = 1;
//moduleConfig.range_test.sender = 30;
// moduleConfig.range_test.enabled = 1;
// moduleConfig.range_test.sender = 30;
// moduleConfig.range_test.save = 1;
// Fixed position is useful when testing indoors.
// radioConfig.preferences.fixed_position = 1;
// config.position.fixed_position = 1;
uint32_t senderHeartbeat = moduleConfig.range_test.sender * 1000;
@@ -57,7 +57,8 @@ int32_t RangeTestModule::runOnce()
return (5000); // Sending first message 5 seconds after initilization.
} else {
DEBUG_MSG("Initializing Range Test Module -- Receiver\n");
return (500);
return (INT32_MAX);
// This thread does not need to run as a receiver
}
} else {
@@ -70,8 +71,7 @@ int32_t RangeTestModule::runOnce()
DEBUG_MSG("gpsStatus->getLongitude() %d\n", gpsStatus->getLongitude());
DEBUG_MSG("gpsStatus->getHasLock() %d\n", gpsStatus->getHasLock());
DEBUG_MSG("gpsStatus->getDOP() %d\n", gpsStatus->getDOP());
DEBUG_MSG("gpsStatus->getHasLock() %d\n", gpsStatus->getHasLock());
DEBUG_MSG("pref.fixed_position() %d\n", config.position.fixed_position);
DEBUG_MSG("fixed_position() %d\n", config.position.fixed_position);
// Only send packets if the channel is less than 25% utilized.
if (airTime->channelUtilizationPercent() < 25) {
@@ -82,11 +82,11 @@ int32_t RangeTestModule::runOnce()
return (senderHeartbeat);
} else {
// Otherwise, we're a receiver.
return (500);
return (INT32_MAX);
// This thread does not need to run as a receiver
}
// TBD
}
} else {
@@ -155,8 +155,8 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const MeshPacket &mp)
DEBUG_MSG("mp.from %d\n", mp.from);
DEBUG_MSG("mp.rx_snr %f\n", mp.rx_snr);
DEBUG_MSG("mp.hop_limit %d\n", mp.hop_limit);
DEBUG_MSG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Depricated
DEBUG_MSG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Depricated
// DEBUG_MSG("mp.decoded.position.latitude_i %d\n", mp.decoded.position.latitude_i); // Depricated
// DEBUG_MSG("mp.decoded.position.longitude_i %d\n", mp.decoded.position.longitude_i); // Depricated
DEBUG_MSG("---- Node Information of Received Packet (mp.from):\n");
DEBUG_MSG("n->user.long_name %s\n", n->user.long_name);
DEBUG_MSG("n->user.short_name %s\n", n->user.short_name);
@@ -221,6 +221,8 @@ bool RangeTestModuleRadio::appendFile(const MeshPacket &mp)
return 0;
}
FSCom.mkdir("/static");
// If the file doesn't exist, write the header.
if (!FSCom.exists("/static/rangetest.csv")) {
//--------- Write to file

241
src/mqtt/JSON.cpp Normal file
View File

@@ -0,0 +1,241 @@
/*
* File JSON.cpp part of the SimpleJSON Library - http://mjpa.in/json
*
* Copyright (C) 2010 Mike Anchor
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "JSON.h"
/**
* Blocks off the public constructor
*
* @access private
*
*/
JSON::JSON()
{
}
/**
* Parses a complete JSON encoded string
*
* @access public
*
* @param char* data The JSON text
*
* @return JSONValue* Returns a JSON Value representing the root, or NULL on error
*/
JSONValue *JSON::Parse(const char *data)
{
// Skip any preceding whitespace, end of data = no JSON = fail
if (!SkipWhitespace(&data))
return NULL;
// We need the start of a value here now...
JSONValue *value = JSONValue::Parse(&data);
if (value == NULL)
return NULL;
// Can be white space now and should be at the end of the string then...
if (SkipWhitespace(&data))
{
delete value;
return NULL;
}
// We're now at the end of the string
return value;
}
/**
* Turns the passed in JSONValue into a JSON encode string
*
* @access public
*
* @param JSONValue* value The root value
*
* @return std::string Returns a JSON encoded string representation of the given value
*/
std::string JSON::Stringify(const JSONValue *value)
{
if (value != NULL)
return value->Stringify();
else
return "";
}
/**
* Skips over any whitespace characters (space, tab, \r or \n) defined by the JSON spec
*
* @access protected
*
* @param char** data Pointer to a char* that contains the JSON text
*
* @return bool Returns true if there is more data, or false if the end of the text was reached
*/
bool JSON::SkipWhitespace(const char **data)
{
while (**data != 0 && (**data == ' ' || **data == '\t' || **data == '\r' || **data == '\n'))
(*data)++;
return **data != 0;
}
/**
* Extracts a JSON String as defined by the spec - "<some chars>"
* Any escaped characters are swapped out for their unescaped values
*
* @access protected
*
* @param char** data Pointer to a char* that contains the JSON text
* @param std::string& str Reference to a std::string to receive the extracted string
*
* @return bool Returns true on success, false on failure
*/
bool JSON::ExtractString(const char **data, std::string &str)
{
str = "";
while (**data != 0)
{
// Save the char so we can change it if need be
char next_char = **data;
// Escaping something?
if (next_char == '\\')
{
// Move over the escape char
(*data)++;
// Deal with the escaped char
switch (**data)
{
case '"': next_char = '"'; break;
case '\\': next_char = '\\'; break;
case '/': next_char = '/'; break;
case 'b': next_char = '\b'; break;
case 'f': next_char = '\f'; break;
case 'n': next_char = '\n'; break;
case 'r': next_char = '\r'; break;
case 't': next_char = '\t'; break;
case 'u':
{
// We need 5 chars (4 hex + the 'u') or its not valid
if (!simplejson_csnlen(*data, 5))
return false;
// Deal with the chars
next_char = 0;
for (int i = 0; i < 4; i++)
{
// Do it first to move off the 'u' and leave us on the
// final hex digit as we move on by one later on
(*data)++;
next_char <<= 4;
// Parse the hex digit
if (**data >= '0' && **data <= '9')
next_char |= (**data - '0');
else if (**data >= 'A' && **data <= 'F')
next_char |= (10 + (**data - 'A'));
else if (**data >= 'a' && **data <= 'f')
next_char |= (10 + (**data - 'a'));
else
{
// Invalid hex digit = invalid JSON
return false;
}
}
break;
}
// By the spec, only the above cases are allowed
default:
return false;
}
}
// End of the string?
else if (next_char == '"')
{
(*data)++;
str.reserve(); // Remove unused capacity
return true;
}
// Disallowed char?
else if (next_char < ' ' && next_char != '\t')
{
// SPEC Violation: Allow tabs due to real world cases
return false;
}
// Add the next char
str += next_char;
// Move on
(*data)++;
}
// If we're here, the string ended incorrectly
return false;
}
/**
* Parses some text as though it is an integer
*
* @access protected
*
* @param char** data Pointer to a char* that contains the JSON text
*
* @return double Returns the double value of the number found
*/
double JSON::ParseInt(const char **data)
{
double integer = 0;
while (**data != 0 && **data >= '0' && **data <= '9')
integer = integer * 10 + (*(*data)++ - '0');
return integer;
}
/**
* Parses some text as though it is a decimal
*
* @access protected
*
* @param char** data Pointer to a char* that contains the JSON text
*
* @return double Returns the double value of the decimal found
*/
double JSON::ParseDecimal(const char **data)
{
double decimal = 0.0;
double factor = 0.1;
while (**data != 0 && **data >= '0' && **data <= '9')
{
int digit = (*(*data)++ - '0');
decimal = decimal + digit * factor;
factor *= 0.1;
}
return decimal;
}

70
src/mqtt/JSON.h Normal file
View File

@@ -0,0 +1,70 @@
/*
* File JSON.h part of the SimpleJSON Library - http://mjpa.in/json
*
* Copyright (C) 2010 Mike Anchor
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _JSON_H_
#define _JSON_H_
#include <vector>
#include <string>
#include <map>
#include <cstring>
// Simple function to check a string 's' has at least 'n' characters
static inline bool simplejson_csnlen(const char *s, size_t n) {
if (s == 0)
return false;
const char *save = s;
while (n-- > 0)
{
if (*(save++) == 0) return false;
}
return true;
}
// Custom types
class JSONValue;
typedef std::vector<JSONValue*> JSONArray;
typedef std::map<std::string, JSONValue*> JSONObject;
#include "JSONValue.h"
class JSON
{
friend class JSONValue;
public:
static JSONValue* Parse(const char *data);
static std::string Stringify(const JSONValue *value);
protected:
static bool SkipWhitespace(const char **data);
static bool ExtractString(const char **data, std::string &str);
static double ParseInt(const char **data);
static double ParseDecimal(const char **data);
private:
JSON();
};
#endif

940
src/mqtt/JSONValue.cpp Normal file
View File

@@ -0,0 +1,940 @@
/*
* File JSONValue.cpp part of the SimpleJSON Library - http://mjpa.in/json
*
* Copyright (C) 2010 Mike Anchor
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <math.h>
#include "JSONValue.h"
// Macros to free an array/object
#define FREE_ARRAY(x) { JSONArray::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete *iter; } }
#define FREE_OBJECT(x) { JSONObject::iterator iter; for (iter = x.begin(); iter != x.end(); iter++) { delete (*iter).second; } }
/**
* Parses a JSON encoded value to a JSONValue object
*
* @access protected
*
* @param char** data Pointer to a char* that contains the data
*
* @return JSONValue* Returns a pointer to a JSONValue object on success, NULL on error
*/
JSONValue *JSONValue::Parse(const char **data)
{
// Is it a string?
if (**data == '"')
{
std::string str;
if (!JSON::ExtractString(&(++(*data)), str))
return NULL;
else
return new JSONValue(str);
}
// Is it a boolean?
else if ((simplejson_csnlen(*data, 4) && strncasecmp(*data, "true", 4) == 0) || (simplejson_csnlen(*data, 5) && strncasecmp(*data, "false", 5) == 0))
{
bool value = strncasecmp(*data, "true", 4) == 0;
(*data) += value ? 4 : 5;
return new JSONValue(value);
}
// Is it a null?
else if (simplejson_csnlen(*data, 4) && strncasecmp(*data, "null", 4) == 0)
{
(*data) += 4;
return new JSONValue();
}
// Is it a number?
else if (**data == '-' || (**data >= '0' && **data <= '9'))
{
// Negative?
bool neg = **data == '-';
if (neg) (*data)++;
double number = 0.0;
// Parse the whole part of the number - only if it wasn't 0
if (**data == '0')
(*data)++;
else if (**data >= '1' && **data <= '9')
number = JSON::ParseInt(data);
else
return NULL;
// Could be a decimal now...
if (**data == '.')
{
(*data)++;
// Not get any digits?
if (!(**data >= '0' && **data <= '9'))
return NULL;
// Find the decimal and sort the decimal place out
// Use ParseDecimal as ParseInt won't work with decimals less than 0.1
// thanks to Javier Abadia for the report & fix
double decimal = JSON::ParseDecimal(data);
// Save the number
number += decimal;
}
// Could be an exponent now...
if (**data == 'E' || **data == 'e')
{
(*data)++;
// Check signage of expo
bool neg_expo = false;
if (**data == '-' || **data == '+')
{
neg_expo = **data == '-';
(*data)++;
}
// Not get any digits?
if (!(**data >= '0' && **data <= '9'))
return NULL;
// Sort the expo out
double expo = JSON::ParseInt(data);
for (double i = 0.0; i < expo; i++)
number = neg_expo ? (number / 10.0) : (number * 10.0);
}
// Was it neg?
if (neg) number *= -1;
return new JSONValue(number);
}
// An object?
else if (**data == '{')
{
JSONObject object;
(*data)++;
while (**data != 0)
{
// Whitespace at the start?
if (!JSON::SkipWhitespace(data))
{
FREE_OBJECT(object);
return NULL;
}
// Special case - empty object
if (object.size() == 0 && **data == '}')
{
(*data)++;
return new JSONValue(object);
}
// We want a string now...
std::string name;
if (!JSON::ExtractString(&(++(*data)), name))
{
FREE_OBJECT(object);
return NULL;
}
// More whitespace?
if (!JSON::SkipWhitespace(data))
{
FREE_OBJECT(object);
return NULL;
}
// Need a : now
if (*((*data)++) != ':')
{
FREE_OBJECT(object);
return NULL;
}
// More whitespace?
if (!JSON::SkipWhitespace(data))
{
FREE_OBJECT(object);
return NULL;
}
// The value is here
JSONValue *value = Parse(data);
if (value == NULL)
{
FREE_OBJECT(object);
return NULL;
}
// Add the name:value
if (object.find(name) != object.end())
delete object[name];
object[name] = value;
// More whitespace?
if (!JSON::SkipWhitespace(data))
{
FREE_OBJECT(object);
return NULL;
}
// End of object?
if (**data == '}')
{
(*data)++;
return new JSONValue(object);
}
// Want a , now
if (**data != ',')
{
FREE_OBJECT(object);
return NULL;
}
(*data)++;
}
// Only here if we ran out of data
FREE_OBJECT(object);
return NULL;
}
// An array?
else if (**data == '[')
{
JSONArray array;
(*data)++;
while (**data != 0)
{
// Whitespace at the start?
if (!JSON::SkipWhitespace(data))
{
FREE_ARRAY(array);
return NULL;
}
// Special case - empty array
if (array.size() == 0 && **data == ']')
{
(*data)++;
return new JSONValue(array);
}
// Get the value
JSONValue *value = Parse(data);
if (value == NULL)
{
FREE_ARRAY(array);
return NULL;
}
// Add the value
array.push_back(value);
// More whitespace?
if (!JSON::SkipWhitespace(data))
{
FREE_ARRAY(array);
return NULL;
}
// End of array?
if (**data == ']')
{
(*data)++;
return new JSONValue(array);
}
// Want a , now
if (**data != ',')
{
FREE_ARRAY(array);
return NULL;
}
(*data)++;
}
// Only here if we ran out of data
FREE_ARRAY(array);
return NULL;
}
// Ran out of possibilites, it's bad!
else
{
return NULL;
}
}
/**
* Basic constructor for creating a JSON Value of type NULL
*
* @access public
*/
JSONValue::JSONValue(/*NULL*/)
{
type = JSONType_Null;
}
/**
* Basic constructor for creating a JSON Value of type String
*
* @access public
*
* @param char* m_char_value The string to use as the value
*/
JSONValue::JSONValue(const char *m_char_value)
{
type = JSONType_String;
string_value = new std::string(std::string(m_char_value));
}
/**
* Basic constructor for creating a JSON Value of type String
*
* @access public
*
* @param std::string m_string_value The string to use as the value
*/
JSONValue::JSONValue(const std::string &m_string_value)
{
type = JSONType_String;
string_value = new std::string(m_string_value);
}
/**
* Basic constructor for creating a JSON Value of type Bool
*
* @access public
*
* @param bool m_bool_value The bool to use as the value
*/
JSONValue::JSONValue(bool m_bool_value)
{
type = JSONType_Bool;
bool_value = m_bool_value;
}
/**
* Basic constructor for creating a JSON Value of type Number
*
* @access public
*
* @param double m_number_value The number to use as the value
*/
JSONValue::JSONValue(double m_number_value)
{
type = JSONType_Number;
number_value = m_number_value;
}
/**
* Basic constructor for creating a JSON Value of type Number
*
* @access public
*
* @param int m_integer_value The number to use as the value
*/
JSONValue::JSONValue(int m_integer_value)
{
type = JSONType_Number;
number_value = (double) m_integer_value;
}
/**
* Basic constructor for creating a JSON Value of type Array
*
* @access public
*
* @param JSONArray m_array_value The JSONArray to use as the value
*/
JSONValue::JSONValue(const JSONArray &m_array_value)
{
type = JSONType_Array;
array_value = new JSONArray(m_array_value);
}
/**
* Basic constructor for creating a JSON Value of type Object
*
* @access public
*
* @param JSONObject m_object_value The JSONObject to use as the value
*/
JSONValue::JSONValue(const JSONObject &m_object_value)
{
type = JSONType_Object;
object_value = new JSONObject(m_object_value);
}
/**
* Copy constructor to perform a deep copy of array / object values
*
* @access public
*
* @param JSONValue m_source The source JSONValue that is being copied
*/
JSONValue::JSONValue(const JSONValue &m_source)
{
type = m_source.type;
switch (type)
{
case JSONType_String:
string_value = new std::string(*m_source.string_value);
break;
case JSONType_Bool:
bool_value = m_source.bool_value;
break;
case JSONType_Number:
number_value = m_source.number_value;
break;
case JSONType_Array:
{
JSONArray source_array = *m_source.array_value;
JSONArray::iterator iter;
array_value = new JSONArray();
for (iter = source_array.begin(); iter != source_array.end(); iter++)
array_value->push_back(new JSONValue(**iter));
break;
}
case JSONType_Object:
{
JSONObject source_object = *m_source.object_value;
object_value = new JSONObject();
JSONObject::iterator iter;
for (iter = source_object.begin(); iter != source_object.end(); iter++)
{
std::string name = (*iter).first;
(*object_value)[name] = new JSONValue(*((*iter).second));
}
break;
}
case JSONType_Null:
// Nothing to do.
break;
}
}
/**
* The destructor for the JSON Value object
* Handles deleting the objects in the array or the object value
*
* @access public
*/
JSONValue::~JSONValue()
{
if (type == JSONType_Array)
{
JSONArray::iterator iter;
for (iter = array_value->begin(); iter != array_value->end(); iter++)
delete *iter;
delete array_value;
}
else if (type == JSONType_Object)
{
JSONObject::iterator iter;
for (iter = object_value->begin(); iter != object_value->end(); iter++)
{
delete (*iter).second;
}
delete object_value;
}
else if (type == JSONType_String)
{
delete string_value;
}
}
/**
* Checks if the value is a NULL
*
* @access public
*
* @return bool Returns true if it is a NULL value, false otherwise
*/
bool JSONValue::IsNull() const
{
return type == JSONType_Null;
}
/**
* Checks if the value is a String
*
* @access public
*
* @return bool Returns true if it is a String value, false otherwise
*/
bool JSONValue::IsString() const
{
return type == JSONType_String;
}
/**
* Checks if the value is a Bool
*
* @access public
*
* @return bool Returns true if it is a Bool value, false otherwise
*/
bool JSONValue::IsBool() const
{
return type == JSONType_Bool;
}
/**
* Checks if the value is a Number
*
* @access public
*
* @return bool Returns true if it is a Number value, false otherwise
*/
bool JSONValue::IsNumber() const
{
return type == JSONType_Number;
}
/**
* Checks if the value is an Array
*
* @access public
*
* @return bool Returns true if it is an Array value, false otherwise
*/
bool JSONValue::IsArray() const
{
return type == JSONType_Array;
}
/**
* Checks if the value is an Object
*
* @access public
*
* @return bool Returns true if it is an Object value, false otherwise
*/
bool JSONValue::IsObject() const
{
return type == JSONType_Object;
}
/**
* Retrieves the String value of this JSONValue
* Use IsString() before using this method.
*
* @access public
*
* @return std::string Returns the string value
*/
const std::string &JSONValue::AsString() const
{
return (*string_value);
}
/**
* Retrieves the Bool value of this JSONValue
* Use IsBool() before using this method.
*
* @access public
*
* @return bool Returns the bool value
*/
bool JSONValue::AsBool() const
{
return bool_value;
}
/**
* Retrieves the Number value of this JSONValue
* Use IsNumber() before using this method.
*
* @access public
*
* @return double Returns the number value
*/
double JSONValue::AsNumber() const
{
return number_value;
}
/**
* Retrieves the Array value of this JSONValue
* Use IsArray() before using this method.
*
* @access public
*
* @return JSONArray Returns the array value
*/
const JSONArray &JSONValue::AsArray() const
{
return (*array_value);
}
/**
* Retrieves the Object value of this JSONValue
* Use IsObject() before using this method.
*
* @access public
*
* @return JSONObject Returns the object value
*/
const JSONObject &JSONValue::AsObject() const
{
return (*object_value);
}
/**
* Retrieves the number of children of this JSONValue.
* This number will be 0 or the actual number of children
* if IsArray() or IsObject().
*
* @access public
*
* @return The number of children.
*/
std::size_t JSONValue::CountChildren() const
{
switch (type)
{
case JSONType_Array:
return array_value->size();
case JSONType_Object:
return object_value->size();
default:
return 0;
}
}
/**
* Checks if this JSONValue has a child at the given index.
* Use IsArray() before using this method.
*
* @access public
*
* @return bool Returns true if the array has a value at the given index.
*/
bool JSONValue::HasChild(std::size_t index) const
{
if (type == JSONType_Array)
{
return index < array_value->size();
}
else
{
return false;
}
}
/**
* Retrieves the child of this JSONValue at the given index.
* Use IsArray() before using this method.
*
* @access public
*
* @return JSONValue* Returns JSONValue at the given index or NULL
* if it doesn't exist.
*/
JSONValue *JSONValue::Child(std::size_t index)
{
if (index < array_value->size())
{
return (*array_value)[index];
}
else
{
return NULL;
}
}
/**
* Checks if this JSONValue has a child at the given key.
* Use IsObject() before using this method.
*
* @access public
*
* @return bool Returns true if the object has a value at the given key.
*/
bool JSONValue::HasChild(const char* name) const
{
if (type == JSONType_Object)
{
return object_value->find(name) != object_value->end();
}
else
{
return false;
}
}
/**
* Retrieves the child of this JSONValue at the given key.
* Use IsObject() before using this method.
*
* @access public
*
* @return JSONValue* Returns JSONValue for the given key in the object
* or NULL if it doesn't exist.
*/
JSONValue* JSONValue::Child(const char* name)
{
JSONObject::const_iterator it = object_value->find(name);
if (it != object_value->end())
{
return it->second;
}
else
{
return NULL;
}
}
/**
* Retrieves the keys of the JSON Object or an empty vector
* if this value is not an object.
*
* @access public
*
* @return std::vector<std::string> A vector containing the keys.
*/
std::vector<std::string> JSONValue::ObjectKeys() const
{
std::vector<std::string> keys;
if (type == JSONType_Object)
{
JSONObject::const_iterator iter = object_value->begin();
while (iter != object_value->end())
{
keys.push_back(iter->first);
iter++;
}
}
return keys;
}
/**
* Creates a JSON encoded string for the value with all necessary characters escaped
*
* @access public
*
* @param bool prettyprint Enable prettyprint
*
* @return std::string Returns the JSON string
*/
std::string JSONValue::Stringify(bool const prettyprint) const
{
size_t const indentDepth = prettyprint ? 1 : 0;
return StringifyImpl(indentDepth);
}
/**
* Creates a JSON encoded string for the value with all necessary characters escaped
*
* @access private
*
* @param size_t indentDepth The prettyprint indentation depth (0 : no prettyprint)
*
* @return std::string Returns the JSON string
*/
std::string JSONValue::StringifyImpl(size_t const indentDepth) const
{
std::string ret_string;
size_t const indentDepth1 = indentDepth ? indentDepth + 1 : 0;
std::string const indentStr = Indent(indentDepth);
std::string const indentStr1 = Indent(indentDepth1);
switch (type)
{
case JSONType_Null:
ret_string = "null";
break;
case JSONType_String:
ret_string = StringifyString(*string_value);
break;
case JSONType_Bool:
ret_string = bool_value ? "true" : "false";
break;
case JSONType_Number:
{
if (isinf(number_value) || isnan(number_value))
ret_string = "null";
else
{
std::stringstream ss;
ss.precision(15);
ss << number_value;
ret_string = ss.str();
}
break;
}
case JSONType_Array:
{
ret_string = indentDepth ? "[\n" + indentStr1 : "[";
JSONArray::const_iterator iter = array_value->begin();
while (iter != array_value->end())
{
ret_string += (*iter)->StringifyImpl(indentDepth1);
// Not at the end - add a separator
if (++iter != array_value->end())
ret_string += ",";
}
ret_string += indentDepth ? "\n" + indentStr + "]" : "]";
break;
}
case JSONType_Object:
{
ret_string = indentDepth ? "{\n" + indentStr1 : "{";
JSONObject::const_iterator iter = object_value->begin();
while (iter != object_value->end())
{
ret_string += StringifyString((*iter).first);
ret_string += ":";
ret_string += (*iter).second->StringifyImpl(indentDepth1);
// Not at the end - add a separator
if (++iter != object_value->end())
ret_string += ",";
}
ret_string += indentDepth ? "\n" + indentStr + "}" : "}";
break;
}
}
return ret_string;
}
/**
* Creates a JSON encoded string with all required fields escaped
* Works from http://www.ecma-internationl.org/publications/files/ECMA-ST/ECMA-262.pdf
* Section 15.12.3.
*
* @access private
*
* @param std::string str The string that needs to have the characters escaped
*
* @return std::string Returns the JSON string
*/
std::string JSONValue::StringifyString(const std::string &str)
{
std::string str_out = "\"";
std::string::const_iterator iter = str.begin();
while (iter != str.end())
{
char chr = *iter;
if (chr == '"' || chr == '\\' || chr == '/')
{
str_out += '\\';
str_out += chr;
}
else if (chr == '\b')
{
str_out += "\\b";
}
else if (chr == '\f')
{
str_out += "\\f";
}
else if (chr == '\n')
{
str_out += "\\n";
}
else if (chr == '\r')
{
str_out += "\\r";
}
else if (chr == '\t')
{
str_out += "\\t";
}
else if (chr < ' ' || chr > 126)
{
str_out += "\\u";
for (int i = 0; i < 4; i++)
{
int value = (chr >> 12) & 0xf;
if (value >= 0 && value <= 9)
str_out += (char)('0' + value);
else if (value >= 10 && value <= 15)
str_out += (char)('A' + (value - 10));
chr <<= 4;
}
}
else
{
str_out += chr;
}
iter++;
}
str_out += "\"";
return str_out;
}
/**
* Creates the indentation string for the depth given
*
* @access private
*
* @param size_t indent The prettyprint indentation depth (0 : no indentation)
*
* @return std::string Returns the string
*/
std::string JSONValue::Indent(size_t depth)
{
const size_t indent_step = 2;
depth ? --depth : 0;
std::string indentStr(depth * indent_step, ' ');
return indentStr;
}

95
src/mqtt/JSONValue.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* File JSONValue.h part of the SimpleJSON Library - http://mjpa.in/json
*
* Copyright (C) 2010 Mike Anchor
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _JSONVALUE_H_
#define _JSONVALUE_H_
#include <vector>
#include <string>
#include "JSON.h"
class JSON;
enum JSONType { JSONType_Null, JSONType_String, JSONType_Bool, JSONType_Number, JSONType_Array, JSONType_Object };
class JSONValue
{
friend class JSON;
public:
JSONValue(/*NULL*/);
JSONValue(const char *m_char_value);
JSONValue(const std::string &m_string_value);
JSONValue(bool m_bool_value);
JSONValue(double m_number_value);
JSONValue(int m_integer_value);
JSONValue(const JSONArray &m_array_value);
JSONValue(const JSONObject &m_object_value);
JSONValue(const JSONValue &m_source);
~JSONValue();
bool IsNull() const;
bool IsString() const;
bool IsBool() const;
bool IsNumber() const;
bool IsArray() const;
bool IsObject() const;
const std::string &AsString() const;
bool AsBool() const;
double AsNumber() const;
const JSONArray &AsArray() const;
const JSONObject &AsObject() const;
std::size_t CountChildren() const;
bool HasChild(std::size_t index) const;
JSONValue *Child(std::size_t index);
bool HasChild(const char* name) const;
JSONValue *Child(const char* name);
std::vector<std::string> ObjectKeys() const;
std::string Stringify(bool const prettyprint = false) const;
protected:
static JSONValue *Parse(const char **data);
private:
static std::string StringifyString(const std::string &str);
std::string StringifyImpl(size_t const indentDepth) const;
static std::string Indent(size_t depth);
JSONType type;
union
{
bool bool_value;
double number_value;
std::string *string_value;
JSONArray *array_value;
JSONObject *object_value;
};
};
#endif

View File

@@ -12,7 +12,7 @@
#include <WiFi.h>
#endif
#include <assert.h>
#include <json11.hpp>
#include "mqtt/JSON.h"
MQTT *mqtt;
@@ -32,19 +32,19 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
if (moduleConfig.mqtt.json_enabled && (strncmp(topic, jsonTopic.c_str(), jsonTopic.length()) == 0)) {
// check if this is a json payload message by comparing the topic start
using namespace json11;
char payloadStr[length + 1];
memcpy(payloadStr, payload, length);
payloadStr[length] = 0; // null terminated string
std::string err;
auto json = Json::parse(payloadStr, err);
if (err.empty()) {
JSONValue *json_value = JSON::Parse(payloadStr);
if (json_value != NULL) {
DEBUG_MSG("JSON Received on MQTT, parsing..\n");
// check if it is a valid envelope
if (json.object_items().count("sender") != 0 && json.object_items().count("payload") != 0 && json["type"].string_value().compare("sendtext") == 0) {
JSONObject json;
json = json_value->AsObject();
if ((json.find("sender") != json.end()) && (json.find("payload") != json.end()) && (json.find("type") != json.end()) && json["type"]->IsString() && (json["type"]->AsString().compare("sendtext") == 0)) {
// this is a valid envelope
if (json["sender"].string_value().compare(owner.id) != 0) {
std::string jsonPayloadStr = json["payload"].dump();
if (json["payload"]->IsString() && json["type"]->IsString() && (json["sender"]->AsString().compare(owner.id) != 0)) {
std::string jsonPayloadStr = json["payload"]->AsString();
DEBUG_MSG("JSON payload %s, length %u\n", jsonPayloadStr.c_str(), jsonPayloadStr.length());
// construct protobuf data packet using TEXT_MESSAGE, send it to the mesh
@@ -68,23 +68,27 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length)
// no json, this is an invalid payload
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
}
delete json_value;
} else {
pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e);
if (strcmp(e.gateway_id, owner.id) == 0)
DEBUG_MSG("Ignoring downlink message we originally sent.\n");
else {
if (e.packet) {
DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length);
MeshPacket *p = packetPool.allocCopy(*e.packet);
if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) {
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
return;
}else {
if (strcmp(e.gateway_id, owner.id) == 0)
DEBUG_MSG("Ignoring downlink message we originally sent.\n");
else {
if (e.packet) {
DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length);
MeshPacket *p = packetPool.allocCopy(*e.packet);
// ignore messages sent by us or if we don't have the channel key
if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p))
router->enqueueReceivedMessage(p);
else
packetPool.release(p);
// ignore messages sent by us or if we don't have the channel key
if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p))
router->enqueueReceivedMessage(p);
else
packetPool.release(p);
}
}
}
// make sure to free both strings and the MeshPacket (passing in NULL is acceptable)
free(e.channel_id);
free(e.gateway_id);
@@ -115,24 +119,16 @@ bool MQTT::connected()
void MQTT::reconnect()
{
if (wantsLink()) {
const char *serverAddr = "mqtt.meshtastic.org"; // default hostname
int serverPort = 1883; // default server port
const char *mqttUsername = "meshdev";
const char *mqttPassword = "large4cats";
// Defaults
int serverPort = 1883;
const char *serverAddr = default_mqtt_address;
const char *mqttUsername = default_mqtt_username;
const char *mqttPassword = default_mqtt_password;
if (*moduleConfig.mqtt.address) {
serverAddr = moduleConfig.mqtt.address; // Override the default
mqttUsername =
moduleConfig.mqtt.username; // do not use the hardcoded credentials for a custom mqtt server
serverAddr = moduleConfig.mqtt.address;
mqttUsername = moduleConfig.mqtt.username;
mqttPassword = moduleConfig.mqtt.password;
} else {
// we are using the default server. Use the hardcoded credentials by default, but allow overriding
if (*moduleConfig.mqtt.username && moduleConfig.mqtt.username[0] != '\0') {
mqttUsername = moduleConfig.mqtt.username;
}
if (*moduleConfig.mqtt.password && moduleConfig.mqtt.password[0] != '\0') {
mqttPassword = moduleConfig.mqtt.password;
}
}
String server = String(serverAddr);
@@ -145,8 +141,7 @@ void MQTT::reconnect()
}
pubSub.setServer(serverAddr, serverPort);
DEBUG_MSG("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername,
mqttPassword);
DEBUG_MSG("Connecting to MQTT server %s, port: %d, username: %s, password: %s\n", serverAddr, serverPort, mqttUsername, mqttPassword);
auto myStatus = (statusTopic + owner.id);
bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword, myStatus.c_str(), 1, true, "offline");
if (connected) {
@@ -173,9 +168,11 @@ void MQTT::sendSubscriptions()
String topic = cryptTopic + channels.getGlobalId(i) + "/#";
DEBUG_MSG("Subscribing to %s\n", topic.c_str());
pubSub.subscribe(topic.c_str(), 1); // FIXME, is QOS 1 right?
String topicDecoded = jsonTopic + channels.getGlobalId(i) + "/#";
DEBUG_MSG("Subscribing to %s\n", topicDecoded.c_str());
pubSub.subscribe(topicDecoded.c_str(), 1); // FIXME, is QOS 1 right?
if (moduleConfig.mqtt.json_enabled == true) {
String topicDecoded = jsonTopic + channels.getGlobalId(i) + "/#";
DEBUG_MSG("Subscribing to %s\n", topicDecoded.c_str());
pubSub.subscribe(topicDecoded.c_str(), 1); // FIXME, is QOS 1 right?
}
}
}
}
@@ -254,7 +251,6 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
if (moduleConfig.mqtt.json_enabled) {
// handle json topic
using namespace json11;
auto jsonString = this->downstreamPacketToJson((MeshPacket *)&mp);
if (jsonString.length() != 0) {
String topicJson = jsonTopic + channelId + "/" + owner.id;
@@ -268,12 +264,11 @@ void MQTT::onSend(const MeshPacket &mp, ChannelIndex chIndex)
// converts a downstream packet into a json message
std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
{
using namespace json11;
// the created jsonObj is immutable after creation, so
// we need to do the heavy lifting before assembling it.
String msgType;
Json msgPayload;
JSONObject msgPayload;
JSONObject jsonObj;
switch (mp->decoded.portnum) {
case PortNum_TEXT_MESSAGE_APP: {
@@ -284,17 +279,17 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
payloadStr[mp->decoded.payload.size] = 0; // null terminated string
// check if this is a JSON payload
std::string err;
auto json = Json::parse(payloadStr, err);
if (err.empty()) {
JSONValue *json_value = JSON::Parse(payloadStr);
if (json_value != NULL) {
DEBUG_MSG("text message payload is of type json\n");
// if it is, then we can just use the json object
msgPayload = json;
jsonObj["payload"] = json_value;
} else {
// if it isn't, then we need to create a json object
// with the string as the value
DEBUG_MSG("text message payload is of type plaintext\n");
msgPayload = Json::object{{"text", payloadStr}};
msgPayload["text"] = new JSONValue(payloadStr);
jsonObj["payload"] = new JSONValue(msgPayload);
}
break;
}
@@ -307,22 +302,19 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Telemetry_msg, &scratch)) {
decoded = &scratch;
if (decoded->which_variant == Telemetry_device_metrics_tag) {
msgPayload = Json::object{
{"battery_level", (int)decoded->variant.device_metrics.battery_level},
{"voltage", decoded->variant.device_metrics.voltage},
{"channel_utilization", decoded->variant.device_metrics.channel_utilization},
{"air_util_tx", decoded->variant.device_metrics.air_util_tx},
};
msgPayload["battery_level"] = new JSONValue((int)decoded->variant.device_metrics.battery_level);
msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage);
msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization);
msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx);
} else if (decoded->which_variant == Telemetry_environment_metrics_tag) {
msgPayload = Json::object{
{"temperature", decoded->variant.environment_metrics.temperature},
{"relative_humidity", decoded->variant.environment_metrics.relative_humidity},
{"barometric_pressure", decoded->variant.environment_metrics.barometric_pressure},
{"gas_resistance", decoded->variant.environment_metrics.gas_resistance},
{"voltage", decoded->variant.environment_metrics.voltage},
{"current", decoded->variant.environment_metrics.current},
};
msgPayload["temperature"] = new JSONValue(decoded->variant.environment_metrics.temperature);
msgPayload["relative_humidity"] = new JSONValue(decoded->variant.environment_metrics.relative_humidity);
msgPayload["barometric_pressure"] = new JSONValue(decoded->variant.environment_metrics.barometric_pressure);
msgPayload["gas_resistance"] = new JSONValue(decoded->variant.environment_metrics.gas_resistance);
msgPayload["voltage"] = new JSONValue(decoded->variant.environment_metrics.voltage);
msgPayload["current"] = new JSONValue(decoded->variant.environment_metrics.current);
}
jsonObj["payload"] = new JSONValue(msgPayload);
} else
DEBUG_MSG("Error decoding protobuf for telemetry message!\n");
};
@@ -336,13 +328,11 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &User_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"id", decoded->id},
{"longname", decoded->long_name},
{"shortname", decoded->short_name},
{"hardware", decoded->hw_model}
};
msgPayload["id"] = new JSONValue(decoded->id);
msgPayload["longname"] = new JSONValue(decoded->long_name);
msgPayload["shortname"] = new JSONValue(decoded->short_name);
msgPayload["hardware"] = new JSONValue(decoded->hw_model);
jsonObj["payload"] = new JSONValue(msgPayload);
} else
DEBUG_MSG("Error decoding protobuf for nodeinfo message!\n");
};
@@ -356,13 +346,12 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Position_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"time", (int)decoded->time},
{"pos_timestamp", (int)decoded->timestamp},
{"latitude_i", (int)decoded->latitude_i},
{"longitude_i", (int)decoded->longitude_i},
{"altitude", (int)decoded->altitude}
};
msgPayload["time"] = new JSONValue((int)decoded->time);
msgPayload["timestamp"] = new JSONValue((int)decoded->timestamp);
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
msgPayload["altitude"] = new JSONValue((int)decoded->altitude);
jsonObj["payload"] = new JSONValue(msgPayload);
} else {
DEBUG_MSG("Error decoding protobuf for position message!\n");
}
@@ -378,15 +367,14 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Waypoint_msg, &scratch)) {
decoded = &scratch;
msgPayload = Json::object{
{"id", (int)decoded->id},
{"name", decoded->name},
{"description", decoded->description},
{"expire", (int)decoded->expire},
{"locked", decoded->locked},
{"latitude_i", (int)decoded->latitude_i},
{"longitude_i", (int)decoded->longitude_i},
};
msgPayload["id"] = new JSONValue((int)decoded->id);
msgPayload["name"] = new JSONValue(decoded->name);
msgPayload["description"] = new JSONValue(decoded->description);
msgPayload["expire"] = new JSONValue((int)decoded->expire);
msgPayload["locked"] = new JSONValue(decoded->locked);
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
jsonObj["payload"] = new JSONValue(msgPayload);
} else {
DEBUG_MSG("Error decoding protobuf for position message!\n");
}
@@ -398,21 +386,20 @@ std::string MQTT::downstreamPacketToJson(MeshPacket *mp)
break;
}
// assemble the final jsonObj
Json jsonObj = Json::object{
{"id", Json((int)mp->id)},
{"timestamp", Json((int)mp->rx_time)},
{"to", Json((int)mp->to)},
{"from", Json((int)mp->from)},
{"channel", Json((int)mp->channel)},
{"type", msgType.c_str()},
{"sender", owner.id},
{"payload", msgPayload}
};
jsonObj["id"] = new JSONValue((int)mp->id);
jsonObj["timestamp"] = new JSONValue((int)mp->rx_time);
jsonObj["to"] = new JSONValue((int)mp->to);
jsonObj["from"] = new JSONValue((int)mp->from);
jsonObj["channel"] = new JSONValue((int)mp->channel);
jsonObj["type"] = new JSONValue(msgType.c_str());
jsonObj["sender"] = new JSONValue(owner.id);
// serialize and write it to the stream
JSONValue *value = new JSONValue(jsonObj);
std::string jsonStr = value->Stringify();
// serialize and return it
std::string jsonStr = jsonObj.dump();
DEBUG_MSG("serialized json message: %s\n", jsonStr.c_str());
delete value;
return jsonStr;
}

View File

@@ -70,6 +70,8 @@
#define HW_VENDOR HardwareModel_TLORA_V1_1P3
#elif defined(TLORA_V2_1_16)
#define HW_VENDOR HardwareModel_TLORA_V2_1_1P6
#elif defined(TLORA_V2_1_18)
#define HW_VENDOR HardwareModel_TLORA_V2_1_1P8
#elif defined(GENIEBLOCKS)
#define HW_VENDOR HardwareModel_GENIEBLOCKS
#elif defined(PRIVATE_HW)
@@ -82,6 +84,10 @@
#define HW_VENDOR HardwareModel_STATION_G1
#elif defined(DR_DEV)
#define HW_VENDOR HardwareModel_DR_DEV
#elif defined(HELTEC_V3)
#define HW_VENDOR HardwareModel_HELTEC_V3
#elif defined(HELTEC_WSL_V3)
#define HW_VENDOR HardwareModel_HELTEC_WSL_V3
#endif
//

View File

@@ -14,6 +14,7 @@
#include <driver/rtc_io.h>
#include <nvs.h>
#include <nvs_flash.h>
#include "soc/rtc.h"
NimbleBluetooth *nimbleBluetooth;
@@ -23,7 +24,7 @@ void getMacAddr(uint8_t *dmac)
}
void setBluetoothEnable(bool on) {
if (!isWifiAvailable() && config.bluetooth.enabled == true) {
if (!nimbleBluetooth) {
nimbleBluetooth = new NimbleBluetooth();
@@ -36,6 +37,44 @@ void setBluetoothEnable(bool on) {
}
}
#ifdef HAS_32768HZ
#define CALIBRATE_ONE(cali_clk) calibrate_one(cali_clk, #cali_clk)
static uint32_t calibrate_one(rtc_cal_sel_t cal_clk, const char *name)
{
const uint32_t cal_count = 1000;
// const float factor = (1 << 19) * 1000.0f; unused var?
uint32_t cali_val;
for (int i = 0; i < 5; ++i) {
cali_val = rtc_clk_cal(cal_clk, cal_count);
}
return cali_val;
}
void enableSlowCLK()
{
rtc_clk_32k_enable(true);
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
uint32_t cal_32k = CALIBRATE_ONE(RTC_CAL_32K_XTAL);
if (cal_32k == 0) {
DEBUG_MSG("32K XTAL OSC has not started up\n");
} else {
rtc_clk_slow_freq_set(RTC_SLOW_FREQ_32K_XTAL);
DEBUG_MSG("Switching RTC Source to 32.768Khz succeeded, using 32K XTAL\n");
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
}
CALIBRATE_ONE(RTC_CAL_RTC_MUX);
CALIBRATE_ONE(RTC_CAL_32K_XTAL);
if (rtc_clk_slow_freq_get() != RTC_SLOW_FREQ_32K_XTAL) {
DEBUG_MSG("Warning: Failed to switch 32K XTAL RTC source to 32.768Khz !!! \n"); return;
}
}
#endif
void esp32Setup()
{
uint32_t seed = esp_random();
@@ -83,6 +122,10 @@ void esp32Setup()
res = esp_task_wdt_add(NULL);
assert(res == ESP_OK);
#ifdef HAS_32768HZ
enableSlowCLK();
#endif
}
#if 0

View File

@@ -45,7 +45,7 @@
#define HW_VENDOR HardwareModel_T_ECHO
#elif defined(NORDIC_PCA10059)
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
#elif defined(PRIVATE_HW)
#elif defined(PRIVATE_HW) || defined(FEATHER_DIY)
#define HW_VENDOR HardwareModel_PRIVATE_HW
#else
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN

View File

@@ -13,7 +13,8 @@ void powerCommandsCheck()
#elif defined(ARCH_NRF52)
NVIC_SystemReset();
#else
DEBUG_MSG("FIXME implement reboot for this platform");
rebootAtMsec = -1;
DEBUG_MSG("FIXME implement reboot for this platform. Skipping for now.\n");
#endif
}

View File

@@ -263,8 +263,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
#ifdef BUTTON_PIN
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
#endif
#ifdef RF95_IRQ_GPIO
gpio_wakeup_enable((gpio_num_t)RF95_IRQ_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
#ifdef RF95_IRQ
gpio_wakeup_enable((gpio_num_t)RF95_IRQ, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
#endif
#ifdef PMU_IRQ
// wake due to PMU can happen repeatedly if there is no battery installed or the battery fills

View File

@@ -36,7 +36,10 @@ cstyleCast
// ignore stuff that is not ours
*:.pio/*
*:*/libdeps/*
noExplicitConstructor:*/mqtt/*
postfixOperator:*/mqtt/*
// these two caused issues
missingOverride
virtualCallInConstructor

View File

@@ -1,47 +1,55 @@
// For OLED LCD
#define I2C_SDA 21
#define I2C_SCL 22
// Initialize i2c bus on sd_dat and esp_led pins, respectively. We need a bus to not hang on boot
#define HAS_SCREEN 0
#define I2C_SDA 4
#define I2C_SCL 5
// GPS
#undef GPS_RX_PIN
#define GPS_RX_PIN NOT_A_PIN
#undef WANT_GPS
#define HAS_GPS 0
#define BUTTON_PIN 2 // The middle button GPIO on the T-Beam
#define BUTTON_PIN 13 // The middle button GPIO on the T-Beam
#define BUTTON_NEED_PULLUP
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975).
#define LORA_DIO0 -1 // a No connect on the SX1262/SX1268 module
#define LORA_RESET -1 // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO1 27 // IRQ for SX1262/SX1268 (IO26 FOR 22S)
#define LORA_DIO2 NOT_A_PIN // BUSY for SX1262/SX1268
#define LORA_DIO3 // Not connected on PCB, but internally on the SX1262/SX1268, if DIO3 is high the TXCO is enabled
#define LORA_DIO0 NOT_A_PIN // a No connect on the SX1262/SX1268 module
#define LORA_RESET NOT_A_PIN // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO3 NOT_A_PIN // Not connected on PCB, but internally on the SX1262/SX1268, if DIO3 is high the TXCO is enabled
// In transmitting, set TXEN as high communication levelRXEN pin is low level;
// In receiving, set RXEN as high communication level, TXEN is lowlevel;
// Before powering off, set TXEN、RXEN as low level.
#define LORA_RXEN 17 // Input - RF switch RX control, connecting external MCU IO, valid in high level
#define LORA_TXEN -1 // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level
/* --PINS FOR THE 900M22S
#undef RF95_SCK
#define RF95_SCK 18
#undef RF95_MISO
#define RF95_MISO 19
#undef RF95_MOSI
#define RF95_MOSI 23
// PINS FOR THE 900M22S
#define LORA_DIO1 26 // IRQ for SX1262/SX1268
#define LORA_DIO2 22 // BUSY for SX1262/SX1268
#define LORA_TXEN NOT_A_PIN // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level
#define LORA_RXEN 17 // Input - RF switch RX control, connecting external MCU IO, valid in high level
#undef RF95_NSS
#define RF95_NSS 16
*/
#define SX126X_BUSY 22
#define SX126X_CS 16
// PINS FOR THE 900M30S
#undef RF95_SCK
#define RF95_SCK 18
#undef RF95_MISO
#define RF95_MISO 19
#undef RF95_MOSI
#define RF95_MOSI 23
/*
#define LORA_DIO1 27 // IRQ for SX1262/SX1268
#define LORA_DIO2 35 // BUSY for SX1262/SX1268
#define LORA_TXEN NOT_A_PIN // Input - RF switch TX control, connecting external MCU IO or DIO2, valid in high level
#define LORA_RXEN 21 // Input - RF switch RX control, connecting external MCU IO, valid in high level
#undef RF95_NSS
#define RF95_NSS 33
#define SX126X_BUSY 35
#define SX126X_CS 33
*/
// RX/TX for RFM95/SX127x
#define RF95_RXEN LORA_RXEN
@@ -49,21 +57,15 @@
// #define RF95_TCXO <GPIO#>
// common pinouts for SX126X modules
#define SX126X_CS 33
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY 35
#define SX126X_RESET LORA_RESET
#define SX126X_RXEN LORA_RXEN
#define SX126X_TXEN LORA_TXEN
// supported modules list
#define USE_RF95 // RFM95/SX127x
//#define USE_RF95 // RFM95/SX127x
#define USE_SX1262
#define USE_SX1268
#define USE_LLCC68
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
//#define USE_SX1268
//#define USE_LLCC68
#define SX126X_E22
#endif

View File

@@ -0,0 +1,11 @@
; The very slick RAK wireless RAK 4631 / 4630 board - Unified firmware for 5005/19003, with or without OLED RAK 1921
[env:feather_diy]
extends = nrf52840_base
board = adafruit_feather_nrf52840
build_flags = ${nrf52840_base.build_flags} -Ivariants/feather_diy -Dfeather_diy
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/feather_diy>
lib_deps =
${nrf52840_base.lib_deps}
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
;upload_protocol = jlink

View File

@@ -0,0 +1,24 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "variant.h"
#include "nrf.h"
#include "wiring_constants.h"
#include "wiring_digital.h"

View File

@@ -0,0 +1,119 @@
/*
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
Copyright (c) 2016 Sandeep Mistry All right reserved.
Copyright (c) 2018, Adafruit Industries (adafruit.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _VARIANT_FEATHER_DIY_
#define _VARIANT_FEATHER_DIY_
/** Master clock frequency */
#define VARIANT_MCK (64000000ul)
#define USE_LFXO // Board uses 32khz crystal for LF
// define USE_LFRC // Board uses RC for LF
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "WVariant.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Number of pins defined in PinDescription array
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (6)
#define NUM_ANALOG_OUTPUTS (0)
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (0 + 12) //P0.12 22
#define PIN_WIRE_SCL (0 + 11) //P0.12 23
#define PIN_LED1 (32 + 15) //P1.15 3
#define PIN_LED2 (32 + 10) //P1.10 4
#define LED_BUILTIN PIN_LED1
#define LED_GREEN PIN_LED2 // Actually red
#define LED_BLUE PIN_LED1
#define LED_STATE_ON 1 // State when LED is litted
#define BUTTON_PIN (32 + 2) //P1.02 7
/*
* Serial interfaces
*/
#define PIN_SERIAL1_RX (0 + 24) //P0.24 1
#define PIN_SERIAL1_TX (0 + 25) //P0.25 0
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
#define SPI_INTERFACES_COUNT 1
#define PIN_SPI_MISO (0 + 15) //P0.15 24
#define PIN_SPI_MOSI (0 + 13) //P0.13 25
#define PIN_SPI_SCK (0 + 14) //P0.14 26
#define SS 2
#define LORA_DIO0 -1 // a No connect on the SX1262/SX1268 module
#define LORA_RESET (32 + 9) //P1.09 13 // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO1 (0 + 6) //P0.06 11 // IRQ for SX1262/SX1268
#define LORA_DIO2 (0 + 8) //P0.08 12 // BUSY for SX1262/SX1268
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262/SX1268, if DIO3 is high the TXCO is enabled
#define RF95_SCK SCK
#define RF95_MISO MI
#define RF95_MOSI MO
#define RF95_NSS SS
// enables 3.3V periphery like GPS or IO Module
#define PIN_3V3_EN (-1)
#undef USE_EINK
// supported modules list
#define USE_SX1262
// common pinouts for SX126X modules
#define SX126X_CS RF95_NSS // NSS for SX126X
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_RXEN (0 + 27) //P0.27 10
#define SX126X_TXEN (0 + 26) //P0.26 9
#ifdef EBYTE_E22
// Internally the TTGO module hooks the SX126x-DIO2 in to control the TX/RX switch
// (which is the default for the sx1262interface code)
#define SX126X_E22
#endif
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -0,0 +1,9 @@
[env:heltec-v3]
platform = https://github.com/Baptou88/platform-espressif32.git
extends = esp32_base
board = heltec_wifi_lora_32_V3
# Temporary: https://community.platformio.org/t/heltec-esp32-lora-v3-board-support/30406/2
platform_packages =
framework-arduinoespressif32@https://github.com/Baptou88/arduino-esp32.git
build_flags =
${esp32s3_base.build_flags} -D HELTEC_V3 -I variants/heltec_v3

View File

@@ -0,0 +1,32 @@
#define LED_PIN LED
#define HAS_GPS 0
#define RESET_OLED RST_OLED
#define I2C_SDA SDA_OLED // I2C pins for this board
#define I2C_SCL SCL_OLED
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0
#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define ADC_MULTIPLIER 5.22
#define USE_SX1262
#define LORA_DIO0 -1 // a No connect on the SX1262 module
#define LORA_RESET 12
#define LORA_DIO1 14 // SX1262 IRQ
#define LORA_DIO2 13 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
#define RF95_SCK 9
#define RF95_MISO 11
#define RF95_MOSI 10
#define RF95_NSS 8
#define SX126X_CS RF95_NSS
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22

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