Compare commits

...

173 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
81 changed files with 2288 additions and 789 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

@@ -23,52 +23,22 @@ jobs:
matrix:
include:
- board: rak11200
- board: tlora-v1
- board: tlora-v2-1-1.6
- board: tbeam
- board: heltec-v2.1
- board: meshtastic-diy-v1
- board: rak4631
- board: t-echo
- board: nano-g1
- board: station-g1
- 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 }}
@@ -97,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/firmware-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: 30
uses: ./.github/workflows/build_esp32.yml
with:
board: ${{ matrix.board }}
build-nrf52:
strategy:
@@ -176,53 +82,9 @@ jobs:
- board: t-echo
- board: pca10059_diy_eink
- board: feather_diy
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: 30
uses: ./.github/workflows/build_nrf52.yml
with:
board: ${{ matrix.board }}
build-rpi2040:
strategy:
@@ -231,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: 30
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
@@ -332,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: 30
- 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]
@@ -366,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
@@ -376,7 +189,6 @@ jobs:
./*.bin
./*.uf2
./firmware-*-ota.zip
./meshtasticd_linux_amd64
./device-*.sh
./device-*.bat
retention-days: 90
@@ -396,7 +208,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
- name: Repackage in single elfs zip
uses: actions/upload-artifact@v3
@@ -445,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:
@@ -453,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

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"

1
.gitmodules vendored
View File

@@ -1,4 +1,3 @@
[submodule "protobufs"]
path = protobufs
url = https://github.com/meshtastic/protobufs.git
branch = develop

2
.semgrepignore Normal file
View File

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

View File

@@ -1,15 +1,41 @@
FROM debian:bullseye-slim AS builder
RUN apt-get update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install wget python3 g++ zip python3-venv git vim
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -O get-platformio.py; chmod +x get-platformio.py
RUN python3 get-platformio.py
RUN git clone https://github.com/meshtastic/firmware --recurse-submodules
RUN cd firmware
RUN chmod +x ./firmware/bin/build-native.sh
RUN . ~/.platformio/penv/bin/activate; cd firmware; sh ./bin/build-native.sh
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
WORKDIR /root/
COPY --from=builder /firmware/release/meshtasticd_linux_amd64 ./
RUN apk --update add --no-cache g++
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'"
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

@@ -10,9 +10,6 @@ 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 pkg update
@@ -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,9 +12,6 @@ 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 pkg update

View File

@@ -10,9 +10,6 @@ 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 pkg update

View File

@@ -10,9 +10,6 @@ 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 pkg update

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

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
@@ -54,6 +66,7 @@ lib_deps =
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
@@ -61,20 +74,17 @@ check_skip_packages = yes
check_flags =
-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
@@ -82,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

@@ -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

@@ -12,7 +12,7 @@
void printATECCInfo()
{
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
atecc.readConfigZone(false);
DEBUG_MSG("ATECC608B Serial Number: ");
@@ -114,7 +114,7 @@ void scanI2Cdevice()
DEBUG_MSG("unknown display found\n");
}
}
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
if (addr == ATECC608B_ADDR) {
keystore_found = addr;
if (atecc.begin(keystore_found) == true) {

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

@@ -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)

View File

@@ -140,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
@@ -269,7 +270,7 @@ void setup()
#ifdef HAS_SDCARD
setupSDCard();
#endif
#ifdef RAK4630
// scanEInkDevice();
#endif
@@ -303,11 +304,11 @@ void setup()
nodeDB.init();
playStartMelody();
// fixed screen override?
if (config.display.oled != Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;
// Init our SPI controller (must be before screen and lora)
initSPI();
#ifndef ARCH_ESP32

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
@@ -22,7 +22,7 @@ extern bool pmu_found;
extern bool isCharging;
extern bool isUSBPowered;
#ifndef ARCH_PORTDUINO
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
extern ATECCX08A atecc;
#endif

View File

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

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

@@ -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

@@ -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;
@@ -432,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)));
@@ -449,8 +449,9 @@ 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->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());

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)

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

@@ -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

@@ -2,7 +2,7 @@
#include "SX1280Interface.h"
#include "error.h"
#if !defined(ARCH_PORTDUINO)
#if defined(RADIOLIB_GODMODE)
SX1280Interface::SX1280Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)

View File

@@ -6,7 +6,7 @@
* Our adapter for SX1280 radios
*/
#if !defined(ARCH_PORTDUINO)
#if defined(RADIOLIB_GODMODE)
class SX1280Interface : public SX128xInterface<SX1280>
{

View File

@@ -2,7 +2,7 @@
#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
@@ -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,6 +1,6 @@
#pragma once
#if !defined(ARCH_PORTDUINO)
#if defined(RADIOLIB_GODMODE)
#include "RadioLibInterface.h"

View File

@@ -82,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.
@@ -147,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
@@ -177,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

@@ -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 {
@@ -143,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 {
@@ -225,8 +229,8 @@ 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}
@@ -234,8 +238,8 @@ extern "C" {
#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}
@@ -250,6 +254,8 @@ 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
@@ -280,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
@@ -325,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
@@ -336,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
@@ -429,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_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

@@ -150,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 361
#define LocalModuleConfig_size 294
#define LocalConfig_size 385
#define LocalModuleConfig_size 361
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -90,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;
@@ -184,7 +185,7 @@ extern "C" {
#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}
@@ -193,7 +194,7 @@ extern "C" {
#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}
@@ -222,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
@@ -314,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
@@ -382,13 +385,13 @@ extern const pb_msgdesc_t 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

@@ -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,7 +179,7 @@ bool initWifi()
WiFi.mode(WIFI_MODE_STA);
WiFi.setHostname(ourHost);
WiFi.onEvent(WiFiEvent);
WiFi.setAutoReconnect(true);
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,
@@ -231,7 +241,9 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
DEBUG_MSG("Disconnected from WiFi access point\n");
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");
@@ -243,7 +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");
@@ -259,7 +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)
@@ -302,15 +319,14 @@ void AdminModule::handleSetModuleConfig(const ModuleConfig &c)
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);
}
/**
@@ -479,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()
@@ -129,11 +129,6 @@ ExternalNotificationModule::ExternalNotificationModule()
// moduleConfig.external_notification.output_ms = 1000;
// moduleConfig.external_notification.output = 13;
if (moduleConfig.external_notification.alert_message) {
// restrict to the gpio channel for rx
boundChannel = Channels::gpioChannel;
}
if (moduleConfig.external_notification.enabled) {
DEBUG_MSG("Initializing External Notification Module\n");
@@ -142,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");
@@ -170,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();
@@ -181,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

@@ -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);

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,6 +68,7 @@ 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 {
if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) {
DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length);
@@ -118,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);
@@ -148,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) {
@@ -176,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?
}
}
}
}
@@ -257,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;
@@ -271,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: {
@@ -287,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;
}
@@ -310,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");
};
@@ -339,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");
};
@@ -359,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");
}
@@ -381,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");
}
@@ -401,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

@@ -24,7 +24,7 @@ void getMacAddr(uint8_t *dmac)
}
void setBluetoothEnable(bool on) {
if (!isWifiAvailable() && config.bluetooth.enabled == true) {
if (!nimbleBluetooth) {
nimbleBluetooth = new NimbleBluetooth();

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,33 +0,0 @@
#include "Speaker.h"
TONE::TONE(void) {
_volume = 5;
_begun = false;
}
void TONE::begin() {
_begun = true;
ledcSetup(TONE_PIN_CHANNEL, 0, 13);
ledcAttachPin(PIN_BUZZER, TONE_PIN_CHANNEL);
}
void TONE::end() {
mute();
ledcDetachPin(PIN_BUZZER);
_begun = false;
}
void TONE::tone(uint16_t frequency) {
if(!_begun) begin();
ledcWriteTone(TONE_PIN_CHANNEL, frequency);
ledcWrite(TONE_PIN_CHANNEL, 0x400 >> _volume);
}
void TONE::setVolume(uint8_t volume) {
_volume = 11 - volume;
}
void TONE::mute() {
ledcWriteTone(TONE_PIN_CHANNEL, 0);
digitalWrite(PIN_BUZZER, 0);
}

View File

@@ -1,30 +0,0 @@
#ifndef _SPEAKER_H_
#define _SPEAKER_H_
#include "configuration.h"
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#include "esp32-hal-dac.h"
#ifdef __cplusplus
}
#endif /* __cplusplus */
class TONE {
public:
TONE(void);
void begin();
void end();
void mute();
void tone(uint16_t frequency);
void setVolume(uint8_t volume);
private:
uint8_t _volume;
bool _begun;
bool speaker_on;
};
#endif

View File

@@ -6,7 +6,6 @@ monitor_port = COM8
monitor_filters = esp32_exception_decoder
build_src_filter =
${esp32_base.build_src_filter}
+<../variants/m5stack_core>
build_flags =
${esp32_base.build_flags} -I variants/m5stack_core
-DILI9341_DRIVER

View File

@@ -11,7 +11,6 @@
#define BUTTON_PIN 38
#define PIN_BUZZER 25
#define TONE_PIN_CHANNEL 0
#undef RF95_SCK
#undef RF95_MISO

View File

@@ -1,18 +1,25 @@
[env:m5stack-coreink]
extends = esp32_base
board = m5stack-coreink
build_src_filter =
${esp32_base.build_src_filter}
build_flags =
${esp32_base.build_flags} -D M5_COREINK -I variants/m5stack_coreink
${esp32_base.build_flags} -I variants/m5stack_coreink
;-D RADIOLIB_VERBOSE
-Ofast
-D__MCUXPRESSO
-DEPD_HEIGHT=200
-DEPD_WIDTH=200
-DUSER_SETUP_LOADED
-DM5_COREINK
-DM5STACK
lib_deps =
${esp32_base.lib_deps}
zinggjm/GxEPD2@^1.4.9
lewisxhe/PCF8563_Library@^1.0.1
lib_ignore =
m5stack-coreink
monitor_filters = esp32_exception_decoder
board_build.f_cpu = 240000000L
upload_protocol = esptool
upload_port = /dev/ttyACM*
upload_port = /dev/ttyACM0

View File

@@ -1,34 +1,39 @@
#define I2C_SDA 21 //-1
#define I2C_SCL 22 //-1
#define I2C_SDA 21
#define I2C_SCL 22
//#define LED_PIN 10
// LED?
#define LED_INVERTED 0
#define LED_PIN 10
#include "pcf8563.h"
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define BUTTON_NEED_PULLUP
#define BUTTON_PIN 5
#define HAS_RTC 1
//Wheel
// Down 37
// Push 38
// Up 39
// Top Physical Button 5
#define BUTTON_NEED_PULLUP
#define BUTTON_PIN 5
//BUZZER
#define PIN_BUZZER 2
#undef RF95_SCK
#undef RF95_MISO
#undef RF95_MOSI
#undef RF95_NSS
#define USE_RF95
#define RF95_SCK 18 //13
#define RF95_MISO 34 //26
#define RF95_MOSI 23 //25
#define RF95_SCK 18
#define RF95_MISO 34
#define RF95_MOSI 23
#define RF95_NSS 14
#define LORA_DIO0 25 //32 now moved from ext port
#define LORA_RESET 26 //33 now moved from ext port
#define LORA_DIO0 25
#define LORA_RESET 26
#define LORA_DIO1 RADIOLIB_NC
#define LORA_DIO2 RADIOLIB_NC
@@ -39,12 +44,10 @@
#define USE_EINK
//https://docs.m5stack.com/en/core/coreink
//https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/coreink/coreink_sch.pdf
#define PIN_EINK_EN -1
#define PIN_EINK_CS 9 // EPD_CS
#define PIN_EINK_BUSY 4 // EPD_BUSY
#define PIN_EINK_EN -1 // N/C
#define PIN_EINK_CS 9 // EPD_CS
#define PIN_EINK_BUSY 4 // EPD_BUSY
#define PIN_EINK_DC 15 // EPD_D/C
#define PIN_EINK_RES -1 // Connected to GPIO0 but no needed !!!! maybe causing issue ?
#define PIN_EINK_SCLK 18 // EPD_SCLK
#define PIN_EINK_RES -1 // Connected but not needed
#define PIN_EINK_SCLK 18 // EPD_SCLK
#define PIN_EINK_MOSI 23 // EPD_MOSI
#define HAS_RTC 1

View File

@@ -1,16 +1,22 @@
[env:native]
platform = https://github.com/meshtastic/platform-native.git
extends = portduino_base
build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino
framework = arduino
board = cross_platform
lib_deps = ${portduino_base.lib_deps}
build_src_filter = ${portduino_base.build_src_filter}
; The Portduino based sim environment on top of a linux OS and touching linux hardware devices
[env:linux]
platform = https://github.com/meshtastic/platform-native.git
extends = portduino_base
build_flags = ${portduino_base.build_flags} -O0 -lgpiod -I variants/portduino
framework = arduino
board = linux_hardware
lib_deps = ${portduino_base.lib_deps}
build_src_filter = ${portduino_base.build_src_filter}
; The Portduino based sim environment on top of a linux OS and touching linux hardware devices
[env:linux-arm]
extends = portduino_base
build_flags = ${portduino_base.build_flags} -O0 -lgpiod -I variants/portduino
board = linux_arm
lib_deps = ${portduino_base.lib_deps}
build_src_filter = ${portduino_base.build_src_filter}

View File

@@ -23,16 +23,3 @@
// HOPE RFM90 does not have a TCXO therefore not SX126X_E22
#endif
// Temporary shim for radio lib macros until we upgrade to upstream for portduino
#define RADIOLIB_PREAMBLE_DETECTED PREAMBLE_DETECTED
#define RADIOLIB_ERR_NONE ERR_NONE
#define RADIOLIB_ERR_WRONG_MODEM ERR_WRONG_MODEM
#define RADIOLIB_SX126X_IRQ_HEADER_VALID SX126X_IRQ_HEADER_VALID
#define RADIOLIB_SX126X_LORA_CRC_ON SX126X_LORA_CRC_ON
#define RADIOLIB_SX127X_REG_TCXO SX127X_REG_TCXO
#define RADIOLIB_SX127X_REG_MODEM_STAT SX127X_REG_MODEM_STAT
#define RADIOLIB_SX127X_SYNC_WORD SX127X_SYNC_WORD
#define RADIOLIB_SX127X_MASK_IRQ_FLAG_VALID_HEADER SX127X_MASK_IRQ_FLAG_VALID_HEADER

View File

@@ -59,11 +59,11 @@ static const uint8_t SCK = 33;
// https://docs.rakwireless.com/Product-Categories/WisBlock/RAK13300/
#define LORA_DIO0 -1 // a No connect on the SX1262/SX1268 module
#define LORA_RESET WB_IO4 // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO1 WB_IO6 // IRQ for SX1262/SX1268
#define LORA_DIO2 WB_IO5 // 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 LORA_DIO0 RADIOLIB_NC // a No connect on the SX1262/SX1268 module
#define LORA_RESET WB_IO4 // RST for SX1276, and for SX1262/SX1268
#define LORA_DIO1 WB_IO6 // IRQ for SX1262/SX1268
#define LORA_DIO2 WB_IO5 // BUSY for SX1262/SX1268
#define LORA_DIO3 RADIOLIB_NC // Not connected on PCB, but internally on the TTGO SX1262/SX1268, if DIO3 is high the TXCO is enabled
#undef RF95_SCK
#define RF95_SCK SCK
@@ -75,10 +75,9 @@ static const uint8_t SCK = 33;
#define RF95_NSS SS
#define USE_SX1262
#define SX126X_CS (SS)// NSS for SX126X
#define SX126X_DIO1 (LORA_DIO1)
#define SX126X_BUSY (LORA_DIO2)
#define SX126X_RESET (LORA_RESET)
#define SX126X_TXEN (-1)
#define SX126X_RXEN (WB_IO3)
#define SX126X_CS SS// NSS for SX126X
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_POWER_EN WB_IO3
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3

View File

@@ -205,7 +205,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define RV3028_RTC (uint8_t) 0b1010010
// RAK18001 Buzzer in Slot C
#define PIN_BUZZER 21 // IO3 is PWM2
// #define PIN_BUZZER 21 // IO3 is PWM2
// NEW: set this via protobuf instead!
// Battery
// The battery sense is hooked to pin A0 (5)

View File

@@ -12,7 +12,7 @@
// TTGO uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
// not found then probe for SX1262
#define USE_RF95
#define USE_RF95 // RFM95/SX127x
#define USE_SX1262
#define USE_SX1268

View File

@@ -6,7 +6,7 @@
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
// #define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
#define LED_PIN 2 // If defined we will blink this LED
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
#define BUTTON_NEED_PULLUP

View File

@@ -5,4 +5,4 @@ lib_deps =
${esp32_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1
build_flags =
${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18
${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18 -D RADIOLIB_GODMODE

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 0
build = 3
build = 6