Compare commits

...

315 Commits

Author SHA1 Message Date
Jm Casler
41dcfdd7cb Bump to 1.2.50 2021-12-29 11:20:36 -08:00
Jm Casler
fbcbc791de Merge pull request #1041 from mc-hamster/ReplyTapback
Support for replies and tap backs
2021-12-29 09:53:03 -08:00
Jm Casler
7c6d53f297 Support for replies and tap backs
https://github.com/meshtastic/Meshtastic-device/issues/1035
2021-12-29 09:25:01 -08:00
Jm Casler
68c52a8d36 updating proto submodule to latest 2021-12-29 09:22:47 -08:00
Jm Casler
759bdfd6a4 Merge pull request #1038 from mc-hamster/master
Delete build-nightly.sh - nightly build server has been decommissioned
2021-12-29 01:32:31 -08:00
Jm Casler
94aff87706 Merge pull request #1037 from mc-hamster/ChannelUtilization
Report on channel utilization on the screen and myNodeInfo
2021-12-29 01:32:22 -08:00
Jm Casler
3fdb374dce Merge branch 'meshtastic:master' into master 2021-12-29 00:52:40 -08:00
Jm Casler
6f3ffc6ef0 Delete build-nightly.sh
Nightly build server has been decomissioned.
2021-12-29 00:52:21 -08:00
Jm Casler
07adfd7543 Merge branch 'master' into ChannelUtilization 2021-12-29 00:49:35 -08:00
Jm Casler
bdacd97fea Move airtimes struct into the class 2021-12-29 00:45:36 -08:00
Jm Casler
7eb00dd5f6 Remove unknown report type 2021-12-29 00:36:54 -08:00
Jm Casler
37dec91ed9 Rename periods to log 2021-12-29 00:36:15 -08:00
Jm Casler
80d872448d Merge pull request #1036 from mc-hamster/StoreAndForward
Removed radio config that shouldn't be there.
2021-12-29 00:12:59 -08:00
Jm Casler
cea35acfa0 Merge branch 'master' into StoreAndForward 2021-12-29 00:12:52 -08:00
Jm Casler
672ea5b494 Removed radio config that shouldn't be there. 2021-12-29 00:12:32 -08:00
Jm Casler
79e75a47f6 Add channel utilization to myNodeInfo 2021-12-28 23:37:23 -08:00
Jm Casler
10dc8233ea Initial checkin for Airtime Utilization
https://github.com/meshtastic/Meshtastic-device/issues/1034
2021-12-28 23:34:49 -08:00
Jm Casler
f1c029d6da updating proto submodule to latest 2021-12-28 23:33:12 -08:00
Jm Casler
a2883789d1 updating proto submodule to latest 2021-12-28 23:29:30 -08:00
Jm Casler
c1abe84abc Merge pull request #1024 from mc-hamster/master
Attempt to update esp8266-oled-ssd1306 (Attempt didn't work, this contains cleanup)
2021-12-28 17:25:37 -08:00
Jm Casler
f3427084c2 Merge branch 'meshtastic:master' into master 2021-12-28 16:41:09 -08:00
Jm Casler
638d43a341 Roll back oled update 2021-12-28 16:40:53 -08:00
Ben Meadors
1063415292 Remove networking operations from presentation layer (#1033)
* Remove networking operations from presentation layer
2021-12-28 14:17:56 -06:00
Ben Meadors
a70b849039 Changed getMacAddr behavior (#1017) 2021-12-28 11:20:45 -06:00
Jm Casler
33769b8657 Merge pull request #1031 from linagee/master
Ham, not HAM
2021-12-27 21:34:13 -08:00
linagee
a534eae43c Grammar. 2021-12-27 21:21:56 -07:00
linagee
5a22b49a24 Ham, not HAM
Originally discovered in 1ffa55d39a

https://www.kb6nu.com/ham-ham-radio-ham-radio-amateur-radio/#:~:text=Of%20course%20either%20term%20may,be%20avoided%20at%20all%20costs.
2021-12-27 21:18:10 -07:00
riddick
06a6f75f00 Update device-install.sh (#1029)
fix for #911

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2021-12-27 18:01:21 -06:00
Thomas Göttgens
bea9dfff38 CI/CD for building on GitLab instance (#1028)
This yml is basically a wrapper for build-all.sh that makes sure the submodules are checked out and pushes a release package to the gitlab registry. Not needed for building on github!

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2021-12-27 14:25:08 -06:00
Jm Casler
2818dfc948 Merge pull request #1030 from mc-hamster/StoreAndForward
Support for MeshPacket_Delayed_DELAYED_BROADCAST
2021-12-27 10:03:36 -08:00
Jm Casler
f521878308 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-27 10:03:09 -08:00
Jm Casler
648e8bb5e1 Support for MeshPacket_Delayed_DELAYED_BROADCAST 2021-12-27 10:02:43 -08:00
Jm Casler
6907cb192e Merge pull request #1027 from mc-hamster/StoreAndForward
S&F - Add support for secondary channels that don't have their own PSK & Update broadcast address to NODENUM_BROADCAST
2021-12-26 16:20:12 -08:00
Jm Casler
988f8c4d23 Merge branch 'master' into StoreAndForward 2021-12-26 15:53:54 -08:00
Jm Casler
4a3bdb284d Merge pull request #1026 from mc-hamster/wifi
Apply formatting to wifi related sections
2021-12-26 15:53:42 -08:00
Jm Casler
efdd2ad490 Apply formatting to S&F 2021-12-26 15:51:27 -08:00
Jm Casler
228be41ba6 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-26 15:49:52 -08:00
Jm Casler
5432d3d44b Merge branch 'meshtastic:master' into wifi 2021-12-26 15:48:18 -08:00
Jm Casler
e77cbd0588 Apply formatting to wifi related sections 2021-12-26 15:46:23 -08:00
Jm Casler
072707c77e Update esp8266-oled-ssd1306 2021-12-26 09:08:49 -08:00
Jm Casler
366a028502 Remove unused comments. 2021-12-26 09:05:35 -08:00
Jm Casler
ea7bceb85b Merge pull request #1018 from joshpirihi/master
Add mqtt_username and mqtt_password user preferences
2021-12-24 22:25:10 -08:00
Jm Casler
caa4f3cd71 Merge branch 'master' into master 2021-12-24 13:52:25 -08:00
Jm Casler
521c55595a Merge pull request #1022 from mc-hamster/wifi
Cleanup comments
2021-12-24 13:51:35 -08:00
Jm Casler
a0c9d18e0d Merge branch 'wifi' of https://github.com/mc-hamster/Meshtastic-device into wifi 2021-12-24 13:08:36 -08:00
Jm Casler
0938cded58 Cleanup comments 2021-12-24 13:08:30 -08:00
Jm Casler
0ea12436b6 Merge pull request #1020 from mc-hamster/wifi
Fix for SoftAP bugs
2021-12-23 20:34:29 -08:00
Jm Casler
8e50e25eec Cleanup content handler and remove request counter. 2021-12-23 19:56:37 -08:00
Jm Casler
2d8bf4d684 Fix for SoftAP bugs 2021-12-23 18:18:07 -08:00
Joshua Pirihi
0aa4ea86a0 Add mqtt_username and mqtt_password user preferences 2021-12-24 06:17:08 +13:00
Jm Casler
d09754fbcf Add support for secondary channels that don't have their own PSK. 2021-12-21 19:28:47 -05:00
Jm Casler
a192da5cd0 Merge pull request #1010 from andrekir/backlight
add T-Echo backlight trigger
2021-12-19 19:38:28 -05:00
Jm Casler
73985c47d6 Merge branch 'master' into backlight 2021-12-19 19:34:29 -05:00
Jm Casler
476c6f25ce Merge pull request #1012 from mc-hamster/master
Update to show fixed gps alternating with location info
2021-12-19 19:34:06 -05:00
Jm Casler
836113ef8b Merge pull request #92 from syund/Show-fixed-GPS-coordinates-on-screen
Fix coordinates not displaying when fixed
2021-12-19 15:16:33 -05:00
Jm Casler
3e31d561ea Merge branch 'StoreAndForward' of https://github.com/mc-hamster/Meshtastic-device into StoreAndForward 2021-12-19 15:11:38 -05:00
Jm Casler
192feeaf0e Update broadcast address to NODENUM_BROADCAST 2021-12-19 15:11:30 -05:00
Sam
9f63a8c330 Fix coordinates not displaying when fixed 2021-12-19 14:55:57 -05:00
Jm Casler
b6d72d3248 Merge branch 'meshtastic:master' into master 2021-12-19 14:28:08 -05:00
Jm Casler
756528180e Merge pull request #978 from mc-hamster/StoreAndForward
S&F - Describe if the message is real time or delayed in MeshPacket
2021-12-19 14:27:55 -05:00
Jm Casler
8d8fece89d Update to show fixed gps alternating with location info. 2021-12-19 14:27:49 -05:00
Jm Casler
7af4a31329 Adding MeshPacket_Delayed 2021-12-19 14:02:36 -05:00
Jm Casler
2ace1f48b8 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-19 13:58:22 -05:00
Jm Casler
d1d096d52a S&F - Describe if the message is real time or delayed in MeshPacket 2021-12-19 13:58:01 -05:00
Jm Casler
3adb79bd18 updating proto submodule to latest 2021-12-19 13:54:51 -05:00
Jm Casler
34908a8f79 Merge pull request #1009 from meshtastic/nimble-lib-swap
Nimble lib swap
2021-12-18 16:30:27 -05:00
Jm Casler
9b15bb51b3 Merge pull request #1008 from mc-hamster/master
Show fixed position indicator on screen & show fixed position indicator on screen
2021-12-18 16:24:33 -05:00
Jm Casler
d7a1b9fd62 Allow hop_limit to be configured
https://github.com/meshtastic/Meshtastic-device/issues/1007
2021-12-18 16:21:12 -05:00
Ben Meadors
727dcbc809 Merge branch 'master' into nimble-lib-swap 2021-12-18 15:16:39 -06:00
Jm Casler
94e9345354 Merge branch 'meshtastic:master' into master 2021-12-18 15:53:31 -05:00
Jm Casler
4fcd82d6f5 updating proto submodule to latest 2021-12-18 15:51:44 -05:00
Andre Kirchhoff
4cd25bc755 add eink userButtonDoublePressed backlight trigger 2021-12-18 17:47:54 -03:00
Jm Casler
252820c58c Merge branch 'meshtastic:master' into master 2021-12-18 15:20:58 -05:00
Jm Casler
0e5a783c5a Show fixed position indicator on screen #866
Show fixed position indicator on screen #866
2021-12-18 15:20:17 -05:00
Jm Casler
4a053801ce Merge pull request #1005 from mc-hamster/master
Fix for "Creating SSL certificate" screen when there's no display
2021-12-18 14:49:16 -05:00
Jm Casler
e68ca88c9c Merge branch 'master' into master 2021-12-18 13:58:57 -05:00
Jm Casler
40d61543e4 Merge pull request #999 from osmanovv/ext-notify-out
Overridden default pin to use for Ext Notify Plugin (#975)
2021-12-18 13:58:10 -05:00
Jm Casler
f3fc88ac5d Test if screen address was found 2021-12-18 11:02:54 -05:00
Jm Casler
d1370071da Test that the screen object has been created 2021-12-17 15:53:23 -05:00
Jm Casler
b71051a227 Attempt to address the ssl screen crashing on AndreK's device. 2021-12-17 14:02:29 -05:00
Vladislav Osmanov
a27260a605 Overridden default pin to use for Ext Notify Plugin (#975)
In Meshtastic DIY `GPIO13` is used for `SX126X_TXEN`,
so we choose `GPIO12` as default for Ext Notification Plugin.
2021-12-17 12:13:27 +03:00
Jm Casler
5354c49c50 Bump version to 1.2.49 2021-12-16 13:53:59 -05:00
Jm Casler
3dbc31e8f3 Merge pull request #995 from mc-hamster/master
Updated formula for position plugin & Improve time to generate the SSL certificate
2021-12-15 07:22:20 -08:00
Ben Meadors
5ff6b919c6 Remove BATTERY_PIN from tlora v1 target (#996) 2021-12-15 07:50:36 -06:00
Jm Casler
62602b54f4 Improve time to generate the SSL certificate 2021-12-14 23:50:49 -05:00
Jm Casler
ee70b5996f Updated formula for position plugin 2021-12-14 22:38:54 -05:00
Ben Meadors
1f4a3085ef Peg to specific version of NimBLE Arduino 2021-12-12 07:54:29 -06:00
Ben Meadors
f119555c12 Convert to NimBLE Arduino (#985) 2021-12-12 07:44:56 -06:00
Jm Casler
2f16b3f345 Merge pull request #989 from mc-hamster/display_speed
Bug in getNumOnlineNodes #988
2021-12-11 20:10:36 -08:00
Jm Casler
1d0221e02d Merge branch 'meshtastic:master' into display_speed 2021-12-11 19:50:51 -08:00
Jm Casler
446fb857cc Bug in getNumOnlineNodes #988 2021-12-11 19:50:20 -08:00
Jm Casler
c6292679f5 Merge pull request #987 from mc-hamster/display_speed
Identify the mode on the screen with the radio conf #986
2021-12-11 19:49:06 -08:00
Jm Casler
65cc938c72 Merge branch 'display_speed' of https://github.com/mc-hamster/Meshtastic-device into display_speed 2021-12-11 19:39:37 -08:00
Jm Casler
a1f97aea77 Update Screen.cpp 2021-12-11 19:39:31 -08:00
Jm Casler
ce42707fc7 Merge branch 'meshtastic:master' into display_speed 2021-12-11 19:37:39 -08:00
Jm Casler
1ed3195194 Identify the mode on the screen with the radio conf #986 2021-12-11 19:36:58 -08:00
Jm Casler
4de89fab0d Merge pull request #984 from mc-hamster/display_speed
Make screen animations smoother (aka Scale the CPU) #983
2021-12-11 18:56:41 -08:00
Jm Casler
4fb5107298 Make screen animations smoother (aka Scale the CPU) #983 2021-12-11 18:35:28 -08:00
Jm Casler
686057a0b1 Make screen animations smoother (aka Scale the CPU) #983 2021-12-11 18:33:52 -08:00
Sacha Weatherstone
04683580ff Merge pull request #973 from Hydra-Designs/master
Split RAK-4631 targets by base board
2021-12-10 13:27:20 +10:30
Ben Meadors
66085d7447 RAK-5005 button pin mapping tweak 2021-12-09 19:59:04 -06:00
Ben Meadors
033e0e99ec Merge branch 'meshtastic:master' into master 2021-12-09 19:58:00 -06:00
Jm Casler
98d2499074 Merge pull request #981 from mc-hamster/master
Update generated protos & has_wifi #979
2021-12-09 12:13:11 -08:00
Jm Casler
3d4e4bfa50 Update generated protos & has_wifi #979
https://github.com/meshtastic/Meshtastic-device/issues/979
2021-12-09 11:47:42 -08:00
Jm Casler
9e771f14d8 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-09 11:34:28 -08:00
Jm Casler
1156a3406e updating proto submodule to latest 2021-12-09 11:23:24 -08:00
Jm Casler
0475cc93ab Update storeforward.pb.h 2021-12-08 23:56:38 -08:00
Jm Casler
8b508576ea Merge branch 'meshtastic:master' into StoreAndForward 2021-12-08 23:48:39 -08:00
Jm Casler
a96dee5beb updating proto submodule to latest 2021-12-08 23:15:08 -08:00
Jm Casler
84332c60f0 Merge branch 'master' into StoreAndForward 2021-12-08 19:42:37 -08:00
Jm Casler
61bc0e09e7 updating proto submodule to latest 2021-12-08 18:39:12 -08:00
Jm Casler
55da39823b Update S&F protobuf 2021-12-08 17:22:02 -08:00
Jm Casler
fb15898ed6 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-08 17:17:54 -08:00
Jm Casler
9fd8df3872 Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-12-08 17:13:52 -08:00
Jm Casler
2ad37e2126 updating proto submodule to latest 2021-12-08 17:13:34 -08:00
Ben Meadors
148b62c02f Merge branch 'master' into master 2021-12-08 18:11:38 -06:00
Jm Casler
098eee0062 Merge pull request #975 from Solarvortx/ExtNotify-Pin
Ext notify pin
2021-12-08 15:52:13 -08:00
Solanaceae
b6d63059bf Change EXT_NOTIFY_PIN to EXT_NOTIFY_OUT per req. 2021-12-07 21:34:10 -07:00
Solanaceae
6cfdd99fd1 Update and configure ExNotify platforms 2021-12-07 20:26:26 -07:00
Ben Meadors
c8bea4f091 Split RAK-4631 targets by base board 2021-12-07 20:42:06 -06:00
Jm Casler
084ef821b7 Merge pull request #972 from mc-hamster/master
Add calculated airtimes to myNodeInfo  … #970
2021-12-07 13:30:15 -08:00
Jm Casler
8785f2848f Merge branch 'meshtastic:master' into master 2021-12-07 13:05:26 -08:00
Jm Casler
f86e0d46b6 Add calculated airtimes to myNodeInfo
https://github.com/meshtastic/Meshtastic-device/issues/970
2021-12-07 13:04:50 -08:00
Jm Casler
41493c9e1f Merge pull request #971 from mc-hamster/master
Generated protos for Feature request: add airtime to NodeInfo #970
2021-12-07 12:11:34 -08:00
Jm Casler
67766b817c Reduce size of airtime structure for mynodeinfo 2021-12-07 11:44:48 -08:00
Jm Casler
feb1f4fb9f Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2021-12-07 11:31:53 -08:00
Jm Casler
d3dc51d102 Fix typo 2021-12-07 11:31:46 -08:00
Jm Casler
e53a6615ad Merge branch 'master' into master 2021-12-07 11:28:28 -08:00
Jm Casler
a904bb8cc5 Generated protos for Feature request: add airtime to NodeInfo #970 2021-12-07 11:26:06 -08:00
Jm Casler
d0715f85a0 Merge pull request #969 from mc-hamster/master
Feature request: add the hop limit info to range test plugin #967
2021-12-07 09:44:57 -08:00
Jm Casler
df88feba0f Feature request: add the hop limit info to range test plugin #967 2021-12-07 09:14:31 -08:00
Jm Casler
b0a6c8929c Save partial work for S&F 2021-12-06 21:01:18 -08:00
Jm Casler
9c8c419939 Merge pull request #966 from mc-hamster/StoreAndForward
Create new default channel configurations. #965
2021-12-06 15:46:12 -08:00
Jm Casler
c83ca7bfdd Merge branch 'meshtastic:master' into StoreAndForward 2021-12-06 15:04:23 -08:00
Jm Casler
f01952bd0d Create new default channel configurations. #965
Create new default channel configurations. #965
2021-12-06 15:03:35 -08:00
Jm Casler
7cb0821886 Merge pull request #964 from mc-hamster/StoreAndForward
Update Smart Position to scale based on data rate.
2021-12-06 14:54:07 -08:00
Jm Casler
bd11b7464e Merge branch 'meshtastic:master' into StoreAndForward 2021-12-06 14:46:24 -08:00
Jm Casler
f6c3ae132a Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-12-06 14:43:08 -08:00
Jm Casler
5fc9f3bfb1 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-06 14:38:18 -08:00
Jm Casler
3384c1ed1f updating proto submodule to latest 2021-12-06 14:37:47 -08:00
Jm Casler
b2e7507cd8 Merge pull request #963 from joshpirihi/master
When switching to battery, shutdown after on_battery_shutdown_after_secs
2021-12-05 22:31:58 -08:00
Jm Casler
1cb5ba38f6 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-05 22:24:59 -08:00
Jm Casler
e9653dae03 Update Smart Position to scale based on data rate. 2021-12-05 22:23:49 -08:00
Joshua Pirihi
5b34e3e1ab When switching to battery, shutdown after on_battery_shutdown_after_secs 2021-12-06 15:37:35 +13:00
Jm Casler
6b184ed448 Merge pull request #960 from mc-hamster/StoreAndForward
Add channel bitrate to myNodeInfo #959 and Update lastlat/lastlong int32 #956
2021-12-05 17:14:27 -08:00
Jm Casler
9ec3085cd5 Merge branch 'master' into StoreAndForward 2021-12-05 16:43:46 -08:00
Ben Meadors
02e3d06bcb Remove promote-release.sh from Release process (#958) 2021-12-05 18:31:36 -06:00
Jm Casler
eefef1dceb Add channel bitrate to myNodeInfo #959 2021-12-05 16:17:13 -08:00
Jm Casler
465f7a6935 Merge branch 'StoreAndForward' of https://github.com/mc-hamster/Meshtastic-device into StoreAndForward 2021-12-05 10:20:25 -08:00
Jm Casler
3da9c7b081 Update lastlat/lastlong int32 #956 2021-12-05 10:20:16 -08:00
Jm Casler
05835fd1bb Add channel bitrate to myNodeInfo #959
Add channel bitrate to myNodeInfo #959
2021-12-05 10:17:09 -08:00
Jm Casler
92ebf1bd69 Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-12-05 10:16:12 -08:00
Jm Casler
86d712ff4d updating proto submodule to latest 2021-12-05 10:15:39 -08:00
Jm Casler
068a6c0309 Merge pull request #957 from mc-hamster/StoreAndForward
Smart position sends updates too frequently. #956
2021-12-04 19:54:25 -08:00
Jm Casler
e5ff49d5aa Merge branch 'meshtastic:master' into StoreAndForward 2021-12-04 19:52:23 -08:00
Jm Casler
aaefd2c2e7 Smart position sends updates too frequently. #956 2021-12-04 19:51:54 -08:00
Jm Casler
e73f79a344 Merge pull request #955 from mc-hamster/StoreAndForward
SoftAP doesn't always start #954
2021-12-04 19:42:55 -08:00
Jm Casler
53efb9c0f6 Update StoreForwardPlugin.cpp 2021-12-04 19:29:42 -08:00
Jm Casler
9f6522a756 SoftAP doesn't always start #954 2021-12-04 19:20:20 -08:00
Jm Casler
09b467ce7c WIP for S&F. Next is to validate the stub outs work as expected. 2021-12-03 22:20:15 -08:00
Jm Casler
105c026297 Merge branch 'meshtastic:master' into StoreAndForward 2021-12-03 19:36:41 -08:00
Jm Casler
83c6d8b07e comment out AXP192_SLAVE_ADDRESS in configuration.h #952 2021-12-03 19:35:57 -08:00
Jm Casler
e19a7c73bc Merge pull request #951 from mc-hamster/StoreAndForward
Cleanup rangetestplugin #950
2021-12-03 19:27:34 -08:00
Jm Casler
23e16bfb1a Merge branch 'master' into StoreAndForward 2021-12-03 19:00:25 -08:00
Jm Casler
47e7b00000 Cleanup rangetestplugin #950 2021-12-03 18:59:10 -08:00
Jm Casler
9adbe28319 Merge pull request #949 from osmanovv/ci4diy
building `meshtastic-diy-v1` in `build-all.sh`
2021-12-03 07:48:05 -08:00
Vladislav Osmanov
d1eb314047 building meshtastic-diy-v1 in build-all.sh 2021-12-03 14:10:41 +03:00
Jm Casler
371335e6ab Update version to 1.2.48 2021-12-02 22:55:07 -08:00
Jm Casler
8bc4b581d1 Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-12-02 22:54:22 -08:00
Jm Casler
2311653ca8 updating proto submodule to latest 2021-12-02 22:53:46 -08:00
Jm Casler
040e3234fc Merge pull request #948 from Solarvortx/SX1262-Power
Sx1262 power
2021-12-02 22:53:09 -08:00
Jm Casler
62cf2adaec Merge branch 'master' into SX1262-Power 2021-12-02 22:41:09 -08:00
Sacha Weatherstone
063499ef46 Cheanup old unused files. 2021-12-03 17:28:32 +11:00
Solanaceae
b7eaeb8c31 Merge branch 'master' into SX1262-Power 2021-12-02 21:50:37 -07:00
Solanaceae
6bd495a491 OCP limit into SX126x class where it belongs. 2021-12-02 20:46:36 -07:00
Jm Casler
f09aa9bec0 Fix promote-release #947
Fix promote-release #947
2021-12-02 19:40:40 -08:00
Jm Casler
a7b3b4386f Merge pull request #946 from mc-hamster/StoreAndForward
Store and forward generated protos & add Mac config in platform.ini
2021-12-02 19:15:23 -08:00
Jm Casler
6a426d5d71 Update S&F with new object name 2021-12-02 17:27:38 -08:00
Jm Casler
0ca061a457 uncomment meshtastic-diy-v1 2021-12-02 17:20:04 -08:00
Jm Casler
f1ef1eeaff Add monitor & upload for mac (commented out) 2021-12-02 17:19:21 -08:00
Jm Casler
1175c981c0 Update generated protos for S&F 2021-12-02 17:16:39 -08:00
Jm Casler
1d3387466f Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-12-02 16:44:14 -08:00
Jm Casler
fcccddc4ad updating proto submodule to latest 2021-12-02 16:44:00 -08:00
Jm Casler
be44fa11b1 Merge pull request #944 from mc-hamster/StoreAndForward
Store and forward
2021-12-02 11:50:57 -08:00
Jm Casler
de104a2707 Merge branch 'master' into StoreAndForward 2021-12-02 09:27:42 -08:00
Ben Meadors
9d019c1a99 Adding batch script for generating uf2 files for NRF boards (#945)
* Updated generated protos

* Added uf2-converter batch for windows machines
2021-12-02 10:19:25 -06:00
Jm Casler
11d954422b Merge branch 'meshtastic:master' into StoreAndForward 2021-12-01 17:58:51 -08:00
Jm Casler
f4d348173c Refresh node info to ensure our information is current for smart position. #934 2021-12-01 17:56:47 -08:00
Jm Casler
79eb5546a1 Merge pull request #943 from mc-hamster/StoreAndForward
Little update to #934
2021-12-01 17:24:37 -08:00
Jm Casler
4f10ab8d04 Little update to #934
updated lastGpsSend
2021-12-01 17:24:01 -08:00
Solanaceae
ab0a06e536 Raising currentLimit for SX1262 2021-11-30 17:56:19 -07:00
Jm Casler
59ef28dfa7 updating proto submodule to latest 2021-11-29 21:43:46 -08:00
Jm Casler
d87106900b Merge pull request #942 from mc-hamster/OneButton
Upgrade to OneButton 2.0.3 #941
2021-11-29 09:15:57 -08:00
Jm Casler
241325d245 Upgrade to OneButton 2.0.3 #941 2021-11-29 09:09:25 -08:00
Jm Casler
0118f3991a Merge pull request #937 from Hydra-Designs/master
Automatic screen carousel behavior implementation (auto_screen_carousel_secs user preference)
2021-11-29 08:56:53 -08:00
Ben Meadors
2a617ba7b2 Upstream proto addition 2021-11-29 10:05:32 -06:00
Ben Meadors
bbf3091889 Merge branch 'master' into master 2021-11-29 09:58:16 -06:00
Jm Casler
5199b4d3c7 Merge pull request #924 from rxt1077/issue-919
ACK retried want_ack packets #919
2021-11-29 07:06:11 -08:00
Ben Meadors
99d35b175c Merge remote-tracking branch 'upstream/master' 2021-11-29 07:02:56 -06:00
Jm Casler
98d0907f4d Merge branch 'master' into issue-919 2021-11-28 22:36:41 -08:00
Jm Casler
5f6d97151c Merge pull request #940 from mc-hamster/StoreAndForward
Fix for: Wifi admin mode no longer works #939
2021-11-28 22:16:13 -08:00
Jm Casler
8cefa82ff1 Merge branch 'meshtastic:master' into StoreAndForward 2021-11-28 21:57:02 -08:00
Jm Casler
623b846713 Fix for: Wifi admin mode no longer works #939
Fix for: Wifi admin mode no longer works #939
2021-11-28 21:56:34 -08:00
Jm Casler
e791a5aa2f Merge branch 'master' into issue-919 2021-11-28 20:13:56 -08:00
Jm Casler
82332c9cd0 Merge pull request #938 from mc-hamster/StoreAndForward
Changes for S&F and Smart Positioning #934
2021-11-28 20:13:18 -08:00
Jm Casler
d5506bb33c Cleanup (Comments & Formatting) of S&F and PrositionPlugin.cpp 2021-11-28 19:41:34 -08:00
Jm Casler
937f67c4ec Check in partial work on S&F 2021-11-28 19:34:35 -08:00
Jm Casler
3ed4a1e3e1 Merge branch 'master' into StoreAndForward 2021-11-28 19:31:49 -08:00
Jm Casler
757de54a4f Merge pull request #935 from rxt1077/issue-927
#927 add SSL notification at boot
2021-11-28 19:30:29 -08:00
Jm Casler
5cf0b6b3b1 Merge branch 'StoreAndForward' of https://github.com/mc-hamster/Meshtastic-device into StoreAndForward 2021-11-28 19:27:54 -08:00
Jm Casler
809179ce0e Merge branch 'meshtastic:master' into StoreAndForward 2021-11-28 19:26:48 -08:00
Jm Casler
d7315778d6 Generated protos for S&F 2021-11-28 19:25:50 -08:00
Ben Meadors
69a2029ade Removed unnecessary debug print 2021-11-27 09:29:39 -06:00
Ben Meadors
7a649e3fc3 Regen protobufs from upstream 2021-11-27 09:16:26 -06:00
Ben Meadors
f019151e3f auto_screen_carousel_secs behavior implementation 2021-11-27 09:11:58 -06:00
Jm Casler
88fd671880 Tweaking values of Smart Position #934
Tweaking values of Smart Position #934
2021-11-26 21:26:36 -08:00
Jm Casler
d72c091ead Merge branch 'master' into issue-927 2021-11-26 19:50:40 -08:00
Jm Casler
3ec508169a Implementation of smart positioning #934
Initial check in for https://github.com/meshtastic/Meshtastic-device/issues/934
2021-11-26 19:12:00 -08:00
Jm Casler
1775770e54 Merge pull request #936 from mc-hamster/StoreAndForward
Update protobufs with the latest from meshtastic-protobufs
2021-11-26 19:09:53 -08:00
Jm Casler
f6fde55363 Update protobufs with the latest from meshtastic-protobufs 2021-11-26 18:25:08 -08:00
Jm Casler
e548de3c88 Merge branch 'master' of https://github.com/meshtastic/Meshtastic-device 2021-11-26 18:14:45 -08:00
Jm Casler
f75aac8ebf updating submodule to latest 2021-11-26 18:13:21 -08:00
Sacha Weatherstone
bc311ac9f6 Merge branch 'master' into issue-927 2021-11-27 08:59:22 +11:00
Sacha Weatherstone
d4c6007047 Merge pull request #932 from joarSv/feature/define-battery-pin-tlorav1
Define battery pin
2021-11-27 08:58:33 +11:00
Ryan Tolboom
c5f210384f add SSL notification at boot 2021-11-26 15:09:16 -05:00
Joar Svensson
d685682dd9 Define battery pin 2021-11-26 13:28:20 +01:00
Ryan Tolboom
e31f9b6e5e Merge branch 'master' into issue-919 2021-11-24 17:06:34 -05:00
Jm Casler
a56851fefa Trying again with .47 2021-11-23 12:41:51 -08:00
Jm Casler
0fc88c542f Reverting version to 47
I can't get git push root to work. Don't know why.
2021-11-23 12:39:48 -08:00
Jm Casler
16307cb67d 47c 2021-11-23 12:17:26 -08:00
Jm Casler
9f05bd11cc Update to .47b 2021-11-23 12:14:28 -08:00
Jm Casler
4b6ee2dc88 Update version to 1.2.47 2021-11-23 11:48:53 -08:00
Ryan Tolboom
a0d829a91e Merge branch 'master' into issue-919 2021-11-23 13:36:09 -05:00
Jm Casler
dbabc24d7a Merge pull request #921 from thebentern/ignore-phone-messages-screen
Ignore messages originating from phone on screen
2021-11-23 09:52:11 -08:00
Ryan Tolboom
e3ee3c411c Merge branch 'master' into issue-919 2021-11-22 23:08:06 -05:00
Jm Casler
d3e1bbf355 Merge branch 'master' into ignore-phone-messages-screen 2021-11-22 19:46:55 -08:00
Jm Casler
2fa2497ed8 Merge pull request #918 from osmanovv/llcc68
[LLCC68] module support
2021-11-22 19:46:31 -08:00
Jm Casler
a5727052bc Merge branch 'master' into llcc68 2021-11-22 19:25:52 -08:00
Jm Casler
083518c127 Merge branch 'master' into ignore-phone-messages-screen 2021-11-22 19:23:42 -08:00
Ryan Tolboom
c36b233c49 ACK retried want_ack packets 2021-11-22 21:31:12 -05:00
Jm Casler
bc7fc1285d Merge pull request #923 from mc-hamster/StoreAndForward
Store and forward - First public release!!
2021-11-22 18:11:21 -08:00
Jm Casler
9ddcc5d2ed S&F Pre-Alpha. Functional. No crashes (I hope). 2021-11-22 17:47:42 -08:00
Jm Casler
a3ce728e26 Move SerialPlugin to plugins/esp32 2021-11-22 13:18:49 -08:00
Jm Casler
cf0d9a2c86 Merge pull request #91 from mc-hamster/master
Move Serial Plugin to new location
2021-11-22 13:17:01 -08:00
Jm Casler
ec7953ccf0 Rename src/plugins/SerialPlugin.h to src/plugins/esp32/SerialPlugin.h 2021-11-22 13:15:50 -08:00
Jm Casler
44a4bde626 Rename src/plugins/SerialPlugin.cpp to src/plugins/esp32/SerialPlugin.cpp 2021-11-22 13:15:36 -08:00
Ben Meadors
5db0a57599 Ignore messages originating from phone on screen 2021-11-21 18:44:08 -06:00
Jm Casler
834f2f4160 Updates to S&F (this one doesn't work) 2021-11-21 14:43:47 -08:00
Jm Casler
4367f05b24 Applied code formatters. 2021-11-20 21:57:21 -08:00
Jm Casler
97aec5f125 Remove comments from SF 2021-11-20 21:35:13 -08:00
Jm Casler
5191fd6475 Initial demonstrable build 2021-11-20 21:21:11 -08:00
Jm Casler
32017e53f5 Formatting applied 2021-11-18 09:36:39 -08:00
Jm Casler
37aab8a42b Able to store and forward, but packets are corrupt 2021-11-18 09:35:05 -08:00
Vladislav Osmanov
bfa0307231 LLCC68 doesn't support SF12 neither the "Long Slow" channel 2021-11-18 14:46:04 +03:00
Vladislav Osmanov
8eb0d685ac [LLCC68] module support 2021-11-17 13:28:08 +03:00
Jm Casler
43e543eabc Merge pull request #89 from meshtastic/master
Update meshtastic from head
2021-11-14 18:34:38 -08:00
Sacha Weatherstone
eee6ef018c Merge pull request #917 from thebentern/add-always-powered-preference
Added is_always_powered preference
2021-11-12 01:08:39 +11:00
Sacha Weatherstone
f7da9ac071 Merge branch 'master' into add-always-powered-preference 2021-11-11 13:50:13 +11:00
Sacha Weatherstone
928198ff03 Merge pull request #915 from jacky4566/master
Add firmware update links
2021-11-11 13:49:39 +11:00
Jm Casler
0cd82507d9 Merge pull request #88 from meshtastic/master
update from head
2021-11-10 16:47:42 -08:00
Ben Meadors
2d939d26ee Renamed to is_always_powered for convention 2021-11-06 12:11:22 -05:00
Ben Meadors
d6c7ea921a Added always_powered preference 2021-11-06 10:03:10 -05:00
Jackson Wiebe
19f43689ca Merge pull request #1 from jacky4566/patch-1
Patch 1
2021-11-05 20:50:22 -06:00
Jackson Wiebe
e78e82ef42 Update README.md 2021-11-05 20:49:40 -06:00
Jackson Wiebe
fdfc600b3d Add links for update procedure
Had to reach out to discord for update instructions when they are located on the website. Adding link here for clarity.
2021-11-05 20:47:33 -06:00
Sacha Weatherstone
334e14ea4d Merge pull request #914 from a-f-G-U-C/admin-set-team
set Team field via Admin plugin
2021-11-03 06:53:11 +11:00
a-f-G-U-C
8115ee0c97 set Team field via Admin plugin 2021-11-02 13:27:56 +00:00
Sacha Weatherstone
e21cc9d479 Merge pull request #913 from Solarvortx/master
Small fix for using 62.5Khz bandwidth setting.
2021-11-02 17:29:34 +11:00
Solanaceae
d5e4ceebcc Small fix for using 62.5Khz bandwidth setting. 2021-11-01 02:31:53 -07:00
Sacha Weatherstone
51646f28ec Merge pull request #908 from a-f-G-U-C/owner-update
fix owner name update issue (off #900)
2021-10-30 13:42:25 +11:00
Sacha Weatherstone
2c5ba29648 Merge branch 'master' into owner-update 2021-10-30 10:13:10 +11:00
Sacha Weatherstone
41bed5c14d Merge pull request #902 from a-f-G-U-C/ublox-filter-dop-fix
implement fix2D and max DOP user settings
2021-10-30 10:12:36 +11:00
a-f-G-U-C
5ef9414a25 fix owner name update issue (off #900) 2021-10-29 13:28:48 +00:00
a-f-G-U-C
2ebed9cb6c update protobufs to 61bc1d0 2021-10-29 13:13:26 +00:00
a-f-G-U-C
7a1409c42a Merge branch 'master' into ublox-filter-dop-fix 2021-10-28 13:03:01 +00:00
Sacha Weatherstone
093e3e55b9 Merge pull request #906 from a-f-G-U-C/fix900-part2
further fixes for issue 900
2021-10-28 23:34:18 +11:00
a-f-G-U-C
a911515dec clean up old data during fix transition 2021-10-28 11:58:08 +00:00
a-f-G-U-C
7ecb36dbe7 Merge branch 'meshtastic:master' into ublox-filter-dop-fix 2021-10-28 11:56:11 +00:00
a-f-G-U-C
d4ea18851d update for RX_SRC_USER 2021-10-28 11:33:32 +00:00
a-f-G-U-C
646d1caf66 updatePosition process time-only message 2021-10-28 11:31:19 +00:00
a-f-G-U-C
74c138620a revert sanity check from PR 898 2021-10-28 11:25:45 +00:00
Jm Casler
3981d2e1f6 Fix for #874 - RangeTest Plugin header fields swapped for elevation and SNR (#904)
Fix for #874 - RangeTest Plugin header fields swapped for elevation and SNR
2021-10-28 15:46:20 +11:00
Jm
6ccaa64ae8 Merge branch 'master' of https://github.com/mc-hamster/Meshtastic-device 2021-10-27 20:05:51 -07:00
Jm
5dd9610d36 Fix for #874 - RangeTest Plugin header fields swapped for elevation and SNR
Fix for #874 - RangeTest Plugin header fields swapped for elevation and SNR
2021-10-27 20:05:33 -07:00
Jm Casler
d4ed7b2f73 Merge pull request #87 from meshtastic/master
Update my fork from head
2021-10-27 19:59:30 -07:00
Jm
9702dffa12 Update proto 2021-10-27 19:57:37 -07:00
Kevin Hester
e2992cd3b9 Merge branch 'master' into ublox-filter-dop-fix 2021-10-28 10:41:03 +08:00
Kevin Hester
4e5ac1ac07 Merge pull request #901 from a-f-G-U-C/rx-src-user
add the user as distinct message source - fixing #900
2021-10-28 10:40:51 +08:00
a-f-G-U-C
e89b3bd1ec implement fix2d and max DOP user settings 2021-10-27 13:30:39 +00:00
a-f-G-U-C
da9dd62a33 add the user as distinct message source 2021-10-27 13:16:51 +00:00
Sacha Weatherstone
e6b4ee8084 Merge pull request #893 from joarSv/feature/environmental-ds18b20-sensor-support
Add support for DS18B20 temperature sensor
2021-10-27 13:54:57 +11:00
Sacha Weatherstone
0133a1b293 Merge branch 'master' into feature/environmental-ds18b20-sensor-support 2021-10-27 10:23:40 +11:00
Sacha Weatherstone
543283c0f6 Merge pull request #898 from a-f-G-U-C/inpos-selfrej-nicelog
better sanity check, logging of inbound positions
2021-10-27 10:21:20 +11:00
Sacha Weatherstone
6d778cdda4 Merge branch 'master' into inpos-selfrej-nicelog 2021-10-27 06:42:13 +11:00
Sacha Weatherstone
3ffcecee6c Merge pull request #897 from a-f-G-U-C/nodedb-updatepos-atomic
implement RX_SRC_LOCAL, Position in updatePosition
2021-10-27 06:38:33 +11:00
a-f-G-U-C
24b2fd2657 better sanity check, logging of inbound positions 2021-10-26 12:41:44 +00:00
a-f-G-U-C
b74c2da530 implement RX_SRC_LOCAL, Position in updatePosition 2021-10-26 12:22:34 +00:00
Kevin Hester
26415cf8e0 Merge branch 'master' into feature/environmental-ds18b20-sensor-support 2021-10-26 02:36:50 +08:00
Sacha Weatherstone
2f7b58abaf Merge pull request #896 from a-f-G-U-C/gps-use-pos-struct
use Position struct for GPS data
2021-10-25 07:41:09 +11:00
a-f-G-U-C
ef1d52ca04 update log message, sanity check 2021-10-24 13:02:31 +00:00
a-f-G-U-C
f69c8dddad update MeshService to use Position struct 2021-10-24 12:48:48 +00:00
a-f-G-U-C
70b80e600d use Position struct for GPS data 2021-10-24 12:38:35 +00:00
Joar Svensson
90d95d8e98 Merge branch 'master' into feature/environmental-ds18b20-sensor-support 2021-10-24 11:36:10 +02:00
a-f-G-U-C
7d267e8027 update GPSStatus to use Position struct atomically (#885) 2021-10-24 11:36:18 +11:00
a-f-G-U-C
0d884d159a implement position packet optional fields (#892) 2021-10-24 11:10:36 +11:00
a-f-G-U-C
3893810b76 fix a positional timestamp reading bug (#886)
* fix a positional timestamp reading bug

* lying about fixType is no longer required
2021-10-24 10:31:44 +11:00
Joar Svensson
fff4735a15 Add support for DS18B20 temperature sensor 2021-10-23 21:10:25 +02:00
a-f-G-U-C
a914ee133c fix a rare GPS data corruption condition (#890)
* fix a rare GPS data corruption condition

* don't use hasLock to determine validity
2021-10-23 14:21:59 +11:00
a-f-G-U-C
d0fb363422 discriminate local/remote node position updates (#889) 2021-10-23 12:58:56 +11:00
a-f-G-U-C
992bbe76d7 add backward compatible position flag defaults (#884) 2021-10-23 12:12:53 +11:00
syund
6fc3c9c868 Inline pow_neg - removes build warning (#891) 2021-10-23 11:40:43 +11:00
Kevin Hester
4fb844bddd Merge pull request #869 from geeksville/dev
new release
2021-10-16 01:45:51 +08:00
Jm
1a8b128640 small change, moving it to the laptop 2021-04-16 19:44:59 -07:00
Jm Casler
a83dcbadb9 Merge pull request #84 from meshtastic/master
update from head
2021-04-16 19:33:42 -07:00
Jm Casler
a5e3f271ea Merge pull request #83 from meshtastic/master
update from head
2021-04-09 20:36:35 -07:00
95 changed files with 1792 additions and 879 deletions

View File

@@ -4,12 +4,12 @@ on:
# workflow_dispatch:
# inputs:
# Only want to be run if a new tag starting with v is pushed.
# Only want to run if version.properties is bumped in master
push:
branches:
- "!*"
tags:
- "v1*"
- master
paths:
- 'version.properties'
jobs:
release-build:
@@ -21,19 +21,15 @@ jobs:
with:
submodules: 'recursive'
# get github branch and tag names as ${{ steps.branch_name.outputs.SOURCE_TAG }}
- name: Branch name
id: branch_name
run: |
echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/}
echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/}
echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: 3.x
# Will be available in steps.version.outputs.version
- name: Get release version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
id: version
# Note: we don't use caches on release builds because we don't want to accidentally not have a virgin build machine
- name: Upgrade python tools
@@ -60,11 +56,6 @@ jobs:
tar -xf build.tar -C data/static
rm build.tar
# Will be available in steps.version.outputs.version
- name: Get version string
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
id: version
- name: Build everything
run: bin/build-all.sh
@@ -75,8 +66,7 @@ jobs:
draft: true
prerelease: true
release_name: ${{ steps.version.outputs.version }} alpha
tag_name: ${{ steps.branch_name.outputs.SOURCE_TAG }}
# was ${{ github.ref }}
tag_name: v${{ steps.version.outputs.version }}
body: |
Autogenerated by github action, developer should edit as required before publishing...
env:
@@ -100,4 +90,4 @@ jobs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: release/archive/elfs-${{ steps.version.outputs.version }}.zip
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
asset_content_type: application/zip
asset_content_type: application/zip

2
.gitignore vendored
View File

@@ -9,7 +9,7 @@ main/credentials.h
!.vscode/extensions.json
*.code-workspace
.idea/workspace.xml
.idea
.DS_Store
Thumbs.db

50
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,50 @@
image: python:latest
variables:
# make sure GitLab check out submodules
GIT_SUBMODULE_STRATEGY: recursive
stages:
- buildall
- upload
build:
stage: buildall
before_script:
# we need zip later for packaging
- "apt update;apt -y install zip"
- "pip install -U platformio"
script:
# clean up residues from previous run
- rm -rf release
- bin/build-all.sh
# This is for my local environment, if your runners are tagged differently, modify or remove
tags:
- dockerized
# The files which are to be made available in GitLab
artifacts:
paths:
- release/archive/firmware*.zip
upload:
image: curlimages/curl:latest
stage: upload
script:
- |
PACKAGE_REGISTRY_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${CI_PROJECT_NAME}/master"
cd release/archive
for f in *.zip; do
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ${f} ${PACKAGE_REGISTRY_URL}/${f}
done
echo 'Package uploaded!'
# This is for my local environment, if your runners are tagged differently, modify or remove
tags:
- dockerized

View File

@@ -1,7 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<clangFormatSettings>
<option name="ENABLED" value="true" />
</clangFormatSettings>
</code_scheme>
</component>

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

4
.idea/misc.xml generated
View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/meshtastic-esp32.iml" filepath="$PROJECT_DIR$/.idea/meshtastic-esp32.iml" />
</modules>
</component>
</project>

9
.idea/vcs.xml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/design" vcs="Git" />
<mapping directory="$PROJECT_DIR$/proto" vcs="Git" />
<mapping directory="$PROJECT_DIR$/sdk-nrfxlib" vcs="Git" />
</component>
</project>

View File

@@ -50,7 +50,8 @@
"cassert": "cpp",
"iterator": "cpp",
"shared_mutex": "cpp",
"iostream": "cpp"
"iostream": "cpp",
"esp_nimble_hci.h": "c"
},
"cSpell.words": [
"Blox",

View File

@@ -2,4 +2,10 @@
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-device)
## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project.
Update Instructions
[For ESP32 devices click here](https://meshtastic.org/docs/getting-started/flashing-esp32)
[For nRF52 devices click here](https://meshtastic.org/docs/getting-started/flashing-nrf52)
For developer information and specific building instructions, please see the [developer doccumentation](https://meshtastic.org/docs/developers)

BIN
bin/.promote-release.sh.swp Normal file

Binary file not shown.

View File

@@ -5,11 +5,11 @@ set -e
VERSION=`bin/buildinfo.py long`
SHORT_VERSION=`bin/buildinfo.py short`
BOARDS_ESP32="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7"
BOARDS_ESP32="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1"
#BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
BOARDS_NRF52="rak4631 t-echo"
BOARDS_NRF52="rak4631_5005 rak4631_19003 t-echo"
#BOARDS_NRF52=""
OUTDIR=release/latest

View File

@@ -1,38 +0,0 @@
#!/bin/bash
source ~/.bashrc
# Meshtastic Nightly Build Script.
# McHamster (jm@casler.org)
#
# This is the script that is used for the nightly build server.
#
# It's probably not useful for most people, but you may want to run your own
# nightly builds.
#
# The last line of ~/.bashrc contains an inclusion of platformio in the path.
# Without this, the build script won't run from the crontab:
#
# export PATH="$HOME/.platformio/penv/bin:$PATH"
#
# The crontab contains:
# 0 2 * * * cd ~/meshtastic/github/meshtastic && source "~/.bashrc"; ./build-nightly.sh > ~/cronout.txt 2> ~/cronout.txt
cd Meshtastic-device
git pull
bin/build-all.sh
date_stamp=$(date +'%Y-%m-%d')
cd ..
# TODO: Archive the same binaries used by the build-all script.
#zip -r meshtastic_device_nightly_${date_stamp} Meshtastic-device/release/latest/bins
cp Meshtastic-device/release/archive/`ls -t ./Meshtastic-device/release/archive/| head -1` meshtastic_device_nightly_${date_stamp}.zip
# Copy the file to the webserver
scp meshtastic_device_nightly_${date_stamp}.zip jm@10.11.12.20:/volume1/web/meshtastic/nightly_builds/
# Delete the local copy
rm meshtastic_device_nightly_${date_stamp}.zip

View File

@@ -46,10 +46,10 @@ shift "$((OPTIND-1))"
if [ -f "${FILENAME}" ]; then
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
$PYTHON -m esptool --baud 921600 erase_flash
$PYTHON -m esptool --baud 921600 write_flash 0x1000 system-info.bin
$PYTHON -m esptool --baud 921600 write_flash 0x00390000 spiffs-*.bin
$PYTHON -m esptool --baud 921600 write_flash 0x10000 ${FILENAME}
$PYTHON -m esptool erase_flash
$PYTHON -m esptool write_flash 0x1000 system-info.bin
$PYTHON -m esptool write_flash 0x00390000 spiffs-*.bin
$PYTHON -m esptool write_flash 0x10000 ${FILENAME}
else
echo "Invalid file: ${FILENAME}"
show_help

View File

@@ -6,6 +6,10 @@ VERSION=`bin/buildinfo.py long`
# Must have a V prefix to trigger github
git tag "v${VERSION}"
git push root "v${VERSION}" # push the tag
# Commented out per https://github.com/meshtastic/Meshtastic-device/issues/947
#git push root "v${VERSION}" # push the tag
git push origin "v${VERSION}" # push the tag
echo "Tag ${VERSION} pushed to github, github actions should now be building the draft release. If it seems good, click to publish it"

1
bin/regen-protos.bat Normal file
View File

@@ -0,0 +1 @@
cd proto && ..\nanopb-0.4.4\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\proto *.proto

2
bin/uf2-convert.bat Normal file
View File

@@ -0,0 +1,2 @@
@echo off
if [%1]==[] (echo "Please specify a platformio NRF target (i.e. rak4631) as the first argument.") else (python3 .\bin\uf2conv.py .\.pio\build\%1\firmware.hex -c -o .\.pio\build\%1\firmware.uf2 -f 0xADA52840)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 532 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"/></svg>

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -325,7 +325,7 @@ Items after the first final candidate release.
- add "store and forward" support for messages, or move to the DB sync model. This would allow messages to be eventually delivered even if nodes are out of contact at the moment.
- use variable length Strings in protobufs (instead of current fixed buffers). This would save lots of RAM
- use BLEDevice::setPower to lower our BLE transmit power - extra range doesn't help us, it costs amps and it increases snoopability
- make a HAM build: just a new frequency list, a bool to say 'never do encryption' and use hte callsign as that node's unique id. -from Girts
- make a Ham build: just a new frequency list, a bool to say 'never do encryption' and use the callsign as that node's unique id. -from Girts
- don't forward redundant pings or ping responses to the phone, it just wastes phone battery
- don't send location packets if we haven't moved significantly
- scrub default radio config settings for bandwidth/range/speed

View File

@@ -1,7 +0,0 @@
* install python
* install git (including git-bash)
* install platformio
* install vscode
* install https://sourceforge.net/projects/mingw-w64/ (for windows gcc/g++) - you'll need to add the bin directory to your PATH

View File

@@ -9,7 +9,7 @@
; https://docs.platformio.org/page/projectconf.html
[platformio]
;default_envs = tbeam
default_envs = tbeam
;default_envs = tbeam0.7
;default_envs = heltec-v2.0
;default_envs = tlora-v1
@@ -21,7 +21,7 @@
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
;default_envs = rak4631
;default_envs = rak4630
default_envs = meshtastic-diy-v1
;default_envs = meshtastic-diy-v1
[common]
; common is not currently used
@@ -69,7 +69,7 @@ debug_tool = jlink
lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git#35d796226b853b0c0ff818b2f1aa3d35e7296a96 ; ESP8266_SSD1306
https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
https://github.com/meshtastic/OneButton.git#3bcba9492d01e2a8a86f46700ab16f96dd2cf1f5 ; OneButton library for non-blocking button debounce
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
@@ -111,14 +111,20 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git
adafruit/DHT sensor library@^1.4.1
adafruit/Adafruit Unified Sensor@^1.1.4
paulstoffregen/OneWire@^2.3.5
robtillaart/DS18B20@^0.1.11
h2zero/NimBLE-Arduino@1.3.1
# Hmm - this doesn't work yet
# board_build.ldscript = linker/esp32.extram.bss.ld
lib_ignore = segger_rtt
lib_ignore =
segger_rtt
ESP32 BLE Arduino
platform_packages =
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#4cde0f5d412d2695184f32e8a47e9bea57b45276
; leave this commented out to avoid breaking Windows
upload_port = /dev/ttyUSB0
;upload_port = /dev/ttyUSB0
;monitor_port = /dev/ttyUSB0
;upload_port = /dev/cu.SLAB_USBtoUART
@@ -323,12 +329,21 @@ monitor_speed = 115200
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
; The very slick RAK wireless RAK 4631 / 4630 board
[env:rak4631]
[env:rak4631_5005]
extends = nrf52840_base
board = wiscore_rak4631
# add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_5005
src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
debug_tool = jlink
[env:rak4631_19003]
extends = nrf52840_base
board = wiscore_rak4631
# add our variants files to the include and src paths
# define build flags for the TFT_eSPI library
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board -D RAK_BASE_19003
src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
debug_tool = jlink
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)

2
proto

Submodule proto updated: e24fa8c6ed...1d3b4806ab

1
src/.gitignore vendored
View File

@@ -1 +0,0 @@
main.ino.cpp

View File

@@ -19,28 +19,39 @@ class GPSStatus : public Status
bool hasLock = false; // default to false, until we complete our first read
bool isConnected = false; // Do we have a GPS we are talking to
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
int32_t altitude = 0;
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
// scaling before use)
uint32_t heading = 0;
uint32_t numSatellites = 0;
Position p = Position_init_default;
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->latitude = latitude;
this->longitude = longitude;
this->altitude = altitude;
this->dop = dop;
this->heading = heading;
this->numSatellites = numSatellites;
this->p.latitude_i = latitude;
this->p.longitude_i = longitude;
this->p.altitude = altitude;
this->p.PDOP = dop;
this->p.ground_track = heading;
this->p.sats_in_view = numSatellites;
}
// preferred method
GPSStatus(bool hasLock, bool isConnected, Position pos)
: Status()
{
this->hasLock = hasLock;
this->isConnected = isConnected;
// all-in-one struct copy
this->p = pos;
}
GPSStatus(const GPSStatus &);
GPSStatus &operator=(const GPSStatus &);
@@ -56,7 +67,7 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.latitude_i;
} else {
return latitude;
return p.latitude_i;
}
}
@@ -66,7 +77,7 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.longitude_i;
} else {
return longitude;
return p.longitude_i;
}
}
@@ -76,44 +87,59 @@ class GPSStatus : public Status
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
return node->position.altitude;
} else {
return altitude;
return p.altitude;
}
}
uint32_t getDOP() const { return p.PDOP; }
uint32_t getDOP() const { return dop; }
uint32_t getHeading() const { return p.ground_track; }
uint32_t getHeading() const { return heading; }
uint32_t getNumSatellites() const { return numSatellites; }
uint32_t getNumSatellites() const { return p.sats_in_view; }
bool matches(const GPSStatus *newStatus) const
{
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->latitude != latitude ||
newStatus->longitude != longitude || newStatus->altitude != altitude || newStatus->dop != dop ||
newStatus->heading != heading || newStatus->numSatellites != numSatellites);
#if GPS_EXTRAVERBOSE
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n",
newStatus->p.pos_timestamp, p.pos_timestamp);
#endif
return (newStatus->hasLock != hasLock ||
newStatus->isConnected != isConnected ||
newStatus->p.latitude_i != p.latitude_i ||
newStatus->p.longitude_i != p.longitude_i ||
newStatus->p.altitude != p.altitude ||
newStatus->p.altitude_hae != p.altitude_hae ||
newStatus->p.PDOP != p.PDOP ||
newStatus->p.ground_track != p.ground_track ||
newStatus->p.sats_in_view != p.sats_in_view);
}
int updateStatus(const GPSStatus *newStatus)
{
// Only update the status if values have actually changed
bool isDirty;
{
isDirty = matches(newStatus);
initialized = true;
hasLock = newStatus->hasLock;
isConnected = newStatus->isConnected;
latitude = newStatus->latitude;
longitude = newStatus->longitude;
altitude = newStatus->altitude;
dop = newStatus->dop;
heading = newStatus->heading;
numSatellites = newStatus->numSatellites;
bool isDirty = matches(newStatus);
if (isDirty && p.pos_timestamp &&
(newStatus->p.pos_timestamp == p.pos_timestamp)) {
// We can NEVER be in two locations at the same time! (also PR #886)
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n");
}
initialized = true;
hasLock = newStatus->hasLock;
isConnected = newStatus->isConnected;
p = newStatus->p;
if (isDirty) {
if (hasLock)
DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%f, heading=%f, sats=%d\n", latitude * 1e-7, longitude * 1e-7,
altitude, dop * 1e-2, heading * 1e-5, numSatellites);
else
if (hasLock) {
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, sats=%d\n",
p.pos_timestamp,
p.latitude_i * 1e-7, p.longitude_i * 1e-7,
p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
p.sats_in_view);
} else
DEBUG_MSG("No GPS lock\n");
onNewStatus.notifyObservers(this);
}

View File

@@ -11,6 +11,11 @@
/// Should we behave as if we have AC power now?
static bool isPowered()
{
// Completely circumvents the battery / power sensing logic and assumes constant power source
if (radioConfig.preferences.is_always_powered) {
return true;
}
bool isRouter = radioConfig.preferences.is_router;
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
@@ -32,6 +37,14 @@ static void sdsEnter()
doDeepSleep(getPref_sds_secs() * 1000LL);
}
extern Power *power;
static void shutdownEnter()
{
DEBUG_MSG("Enter state: SHUTDOWN\n");
power->shutdown();
}
#include "error.h"
static uint32_t secsSlept;
@@ -212,6 +225,7 @@ static void bootEnter() {
DEBUG_MSG("Enter state: BOOT\n");
}
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
State stateSDS(sdsEnter, NULL, NULL, "SDS");
State stateLS(lsEnter, lsIdle, lsExit, "LS");
State stateNB(nbEnter, NULL, NULL, "NB");
@@ -255,6 +269,14 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
// Handle being told to power off
powerFSM.add_transition(&stateBOOT, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateLS, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateNB, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateDARK, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateON, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateSERIAL, &stateSHUTDOWN, EVENT_SHUTDOWN, NULL, "Shutdown");
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");

View File

@@ -19,6 +19,7 @@
#define EVENT_POWER_CONNECTED 13
#define EVENT_POWER_DISCONNECTED 14
#define EVENT_FIRMWARE_UPDATE 15 // We just received a new firmware update packet from the phone
#define EVENT_SHUTDOWN 16 //force a full shutdown now (not just sleep)
extern Fsm powerFSM;
extern State statePOWER, stateSERIAL;

View File

@@ -1,107 +1,135 @@
#include "configuration.h"
#include "airtime.h"
#include "NodeDB.h"
#include "configuration.h"
#define periodsToLog 48
AirTime *airTime;
uint32_t secondsPerPeriod = 3600;
uint32_t lastMillis = 0;
uint32_t secSinceBoot = 0;
// AirTime at;
// Don't read out of this directly. Use the helper functions.
struct airtimeStruct {
uint32_t periodTX[periodsToLog]; // AirTime transmitted
uint32_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
uint32_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
uint8_t lastPeriodIndex;
} airtimes;
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
{
// TODO: Is the airtimes array still necessary? It's now in myNodeInfo anyway
if (reportType == TX_LOG) {
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms);
airtimes.periodTX[0] = airtimes.periodTX[0] + airtime_ms;
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
} else if (reportType == RX_LOG) {
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms);
airtimes.periodRX[0] = airtimes.periodRX[0] + airtime_ms;
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms;
} else if (reportType == RX_ALL_LOG) {
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
airtimes.periodRX_ALL[0] = airtimes.periodRX_ALL[0] + airtime_ms;
} else {
DEBUG_MSG("AirTime - Unknown report time. This should never happen!!\n");
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
}
uint8_t channelUtilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
this->channelUtilization[channelUtilPeriod] = channelUtilization[channelUtilPeriod] + airtime_ms;
}
uint8_t currentPeriodIndex()
uint8_t AirTime::currentPeriodIndex()
{
return ((getSecondsSinceBoot() / secondsPerPeriod) % periodsToLog);
return ((getSecondsSinceBoot() / SECONDS_PER_PERIOD) % PERIODS_TO_LOG);
}
void airtimeRotatePeriod()
void AirTime::airtimeRotatePeriod()
{
if (airtimes.lastPeriodIndex != currentPeriodIndex()) {
if (this->airtimes.lastPeriodIndex != currentPeriodIndex()) {
DEBUG_MSG("Rotating airtimes to a new period = %u\n", currentPeriodIndex());
for (int i = periodsToLog - 2; i >= 0; --i) {
airtimes.periodTX[i + 1] = airtimes.periodTX[i];
airtimes.periodRX[i + 1] = airtimes.periodRX[i];
airtimes.periodRX_ALL[i + 1] = airtimes.periodRX_ALL[i];
}
airtimes.periodTX[0] = 0;
airtimes.periodRX[0] = 0;
airtimes.periodRX_ALL[0] = 0;
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
this->airtimes.periodRX[i + 1] = this->airtimes.periodRX[i];
this->airtimes.periodRX_ALL[i + 1] = this->airtimes.periodRX_ALL[i];
airtimes.lastPeriodIndex = currentPeriodIndex();
myNodeInfo.air_period_tx[i + 1] = myNodeInfo.air_period_tx[i];
myNodeInfo.air_period_rx[i + 1] = myNodeInfo.air_period_rx[i];
}
this->airtimes.periodTX[0] = 0;
this->airtimes.periodRX[0] = 0;
this->airtimes.periodRX_ALL[0] = 0;
myNodeInfo.air_period_tx[0] = 0;
myNodeInfo.air_period_rx[0] = 0;
this->airtimes.lastPeriodIndex = currentPeriodIndex();
}
}
uint32_t *airtimeReport(reportTypes reportType)
uint32_t *AirTime::airtimeReport(reportTypes reportType)
{
if (reportType == TX_LOG) {
return airtimes.periodTX;
return this->airtimes.periodTX;
} else if (reportType == RX_LOG) {
return airtimes.periodRX;
return this->airtimes.periodRX;
} else if (reportType == RX_ALL_LOG) {
return airtimes.periodRX_ALL;
return this->airtimes.periodRX_ALL;
}
return 0;
}
uint8_t getPeriodsToLog()
uint8_t AirTime::getPeriodsToLog()
{
return periodsToLog;
return PERIODS_TO_LOG;
}
uint32_t getSecondsPerPeriod()
uint32_t AirTime::getSecondsPerPeriod()
{
return secondsPerPeriod;
return SECONDS_PER_PERIOD;
}
uint32_t getSecondsSinceBoot()
uint32_t AirTime::getSecondsSinceBoot()
{
return secSinceBoot;
return this->secSinceBoot;
}
float AirTime::channelUtilizationPercent()
{
uint32_t sum = 0;
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
sum += this->channelUtilization[i];
// DEBUG_MSG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
}
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
}
AirTime::AirTime() : concurrency::OSThread("AirTime") {}
int32_t AirTime::runOnce()
{
//DEBUG_MSG("AirTime::runOnce()\n");
airtimeRotatePeriod();
secSinceBoot++;
/*
This actually doesn't need to be run once per second but we currently use it for the
secSinceBoot counter.
uint8_t utilPeriod = (getSecondsSinceBoot() / 10) % CHANNEL_UTILIZATION_PERIODS;
if (firstTime) {
airtimeRotatePeriod();
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
this->channelUtilization[i] = 0;
}
firstTime = false;
lastUtilPeriod = utilPeriod;
} else {
// Reset the channelUtilization window when we roll over
if (lastUtilPeriod != utilPeriod) {
lastUtilPeriod = utilPeriod;
this->channelUtilization[utilPeriod] = 0;
}
// Update channel_utilization every second.
myNodeInfo.channel_utilization = airTime->channelUtilizationPercent();
}
If we have a better counter of how long the device has been online (and not millis())
then we can change this to something less frequent. Maybe once ever 5 seconds?
*/
return (1000 * 1);
}

View File

@@ -23,21 +23,18 @@
RX_ALL_LOG - RX_LOG = Other lora radios on our frequency channel.
*/
#define CHANNEL_UTILIZATION_PERIODS 6
#define SECONDS_PER_PERIOD 3600
#define PERIODS_TO_LOG 24
enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG };
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
void airtimeRotatePeriod();
uint8_t currentPeriodIndex();
uint8_t getPeriodsToLog();
uint32_t getSecondsSinceBoot();
uint32_t *airtimeReport(reportTypes reportType);
uint32_t getSecondsPerPeriod();
class AirTime : private concurrency::OSThread
{
@@ -45,6 +42,27 @@ class AirTime : private concurrency::OSThread
AirTime();
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
float channelUtilizationPercent();
uint32_t channelUtilization[CHANNEL_UTILIZATION_PERIODS];
uint8_t currentPeriodIndex();
void airtimeRotatePeriod();
uint8_t getPeriodsToLog();
uint32_t getSecondsPerPeriod();
uint32_t getSecondsSinceBoot();
uint32_t *airtimeReport(reportTypes reportType);
private:
bool firstTime = true;
uint8_t lastUtilPeriod = 0;
uint32_t secSinceBoot = 0;
struct airtimeStruct {
uint32_t periodTX[PERIODS_TO_LOG]; // AirTime transmitted
uint32_t periodRX[PERIODS_TO_LOG]; // AirTime received and repeated (Only valid mesh packets)
uint32_t periodRX_ALL[PERIODS_TO_LOG]; // AirTime received regardless of valid mesh packet. Could include noise.
uint8_t lastPeriodIndex;
} airtimes;
protected:
virtual int32_t runOnce() override;

View File

@@ -171,7 +171,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define I2C_SCL 22
#define BUTTON_PIN 38 // The middle button GPIO on the T-Beam
#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere.
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
#define LED_INVERTED 1
#define LED_PIN 4 // Newer tbeams (1.1) have an extra led on GPIO4
@@ -213,6 +214,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define BUTTON_PIN 39
#define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
#define USE_RF95
#define LORA_DIO0 26 // a No connect on the SX1262 module
@@ -241,6 +243,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
//#define GPS_TX_PIN 12 // not connected
#define BUTTON_PIN 39 // The middle button GPIO on the T-Beam
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Plugin (#975).
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
#define LORA_RESET 23 // RST for SX1276, and for SX1262/SX1268
@@ -256,6 +259,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// supported modules list
#define USE_SX1262
#define USE_SX1268
#define USE_LLCC68
// common pinouts for SX126X modules
#define SX126X_CS 18 // NSS for SX126X
@@ -315,6 +319,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HW_VENDOR HardwareModel_HELTEC_V2_1
#define BATTERY_PIN 37 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
#endif
@@ -335,6 +340,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Plugin.
#define USE_RF95
#define LORA_DIO0 26 // a No connect on the SX1262 module

View File

@@ -202,11 +202,13 @@ void GPS::publishUpdate()
if (shouldPublish) {
shouldPublish = false;
DEBUG_MSG("publishing GPS lock=%d\n", hasLock());
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n",
p.pos_timestamp, hasValidLocation, hasLock());
// Notify any status instances that are observing us
const meshtastic::GPSStatus status =
meshtastic::GPSStatus(hasLock(), isConnected(), latitude, longitude, altitude, dop, heading, numSatellites);
meshtastic::GPSStatus(hasValidLocation, isConnected(), p);
newStatus.notifyObservers(&status);
}
}
@@ -244,6 +246,7 @@ int32_t GPS::runOnce()
bool gotLoc = lookForLocation();
if (gotLoc && !hasValidLocation) { // declare that we have location ASAP
DEBUG_MSG("hasValidLocation RISING EDGE\n");
hasValidLocation = true;
shouldPublish = true;
}
@@ -260,6 +263,10 @@ int32_t GPS::runOnce()
if (tooLong) {
// we didn't get a location during this ack window, therefore declare loss of lock
if (hasValidLocation) {
DEBUG_MSG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc);
}
p = Position_init_default;
hasValidLocation = false;
}

View File

@@ -17,6 +17,10 @@ class GPS : private concurrency::OSThread
private:
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastWhileActiveMsec = 0;
/**
* hasValidLocation - indicates that the position variables contain a complete
* GPS location, valid and fresh (< gps_update_interval + gps_attempt_time)
*/
bool hasValidLocation = false; // default to false, until we complete our first read
bool isAwake = false; // true if we want a location right now
@@ -39,14 +43,7 @@ class GPS : private concurrency::OSThread
/** If !0 we will attempt to connect to the GPS over I2C */
static uint8_t i2cAddress;
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
int32_t altitude = 0;
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
// scaling before use)
uint32_t heading = 0; // Heading of motion, in degrees * 10^-5
int32_t geoidal_height = 0; // geoidal separation, in meters!
time_t pos_timestamp = 0; // positional timestamp from GPS solution
Position p = Position_init_default;
GPS() : concurrency::OSThread("GPS") {}

View File

@@ -14,7 +14,7 @@
// Helper functions
// Raises a number to an exponent, handling negative exponents.
static double pow_neg(double base, double exponent) {
static inline double pow_neg(double base, double exponent) {
if (exponent == 0) {
return 1;
} else if (exponent > 0) {

View File

@@ -95,6 +95,17 @@ bool NMEAGPS::lookForLocation()
if (! hasLock())
return false;
#ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n",
reader.location.age(),
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
gsafixtype.age(),
#else
0,
#endif
reader.date.age(), reader.time.age());
#endif // GPS_EXTRAVERBOSE
// check if a complete GPS solution set is available for reading
// tinyGPSDatum::age() also includes isValid() test
// FIXME
@@ -105,7 +116,7 @@ bool NMEAGPS::lookForLocation()
(reader.time.age() < GPS_SOL_EXPIRY_MS) &&
(reader.date.age() < GPS_SOL_EXPIRY_MS)))
{
// DEBUG_MSG("SOME data is TOO OLD\n");
DEBUG_MSG("SOME data is TOO OLD\n");
return false;
}
@@ -113,7 +124,7 @@ bool NMEAGPS::lookForLocation()
if (! reader.location.isUpdated())
return false;
// Start reading the data
// We know the solution is fresh and valid, so just read the data
auto loc = reader.location.value();
// Some GPSes (Air530) seem to send a zero longitude when the current fix is bogus
@@ -123,27 +134,34 @@ bool NMEAGPS::lookForLocation()
return false;
}
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
// Dilution of precision (an accuracy metric) is reported in 10^2 units, so we need to scale down when we use it
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
dop = TinyGPSPlus::parseDecimal(gsapdop.value());
p.HDOP = reader.hdop.value();
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
DEBUG_MSG("PDOP=%d, HDOP=%d\n", dop, reader.hdop.value());
#else
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
dop = 1.41 * reader.hdop.value();
p.HDOP = reader.hdop.value();
p.PDOP = 1.41 * reader.hdop.value();
#endif
// Discard incomplete or erroneous readings
if (dop == 0)
if (reader.hdop.value() == 0)
return false;
latitude = toDegInt(loc.lat);
longitude = toDegInt(loc.lng);
p.latitude_i = toDegInt(loc.lat);
p.longitude_i = toDegInt(loc.lng);
geoidal_height = reader.geoidHeight.meters();
#ifdef GPS_ALTITUDE_HAE
altitude = reader.altitude.meters() + geoidal_height;
#else
altitude = reader.altitude.meters();
p.alt_geoid_sep = reader.geoidHeight.meters();
p.altitude_hae = reader.altitude.meters() + p.alt_geoid_sep;
p.altitude = reader.altitude.meters();
p.fix_quality = fixQual;
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
p.fix_type = fixType;
#endif
// positional timestamp
@@ -155,16 +173,16 @@ bool NMEAGPS::lookForLocation()
t.tm_mon = reader.date.month() - 1;
t.tm_year = reader.date.year() - 1900;
t.tm_isdst = false;
pos_timestamp = mktime(&t);
p.pos_timestamp = mktime(&t);
// Nice to have, if available
if (reader.satellites.isUpdated()) {
setNumSatellites(reader.satellites.value());
p.sats_in_view = reader.satellites.value();
}
if (reader.course.isUpdated() && reader.course.isValid()) {
if (reader.course.value() < 36000) { // sanity check
heading = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
p.ground_track = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
} else {
DEBUG_MSG("BOGUS course.value() REJECTED: %d\n",
reader.course.value());

View File

@@ -10,6 +10,8 @@
#define PDOP_INVALID 9999
// #define UBX_MODE_NMEA
extern RadioConfig radioConfig;
UBloxGPS::UBloxGPS() {}
@@ -48,12 +50,22 @@ bool UBloxGPS::setupGPS()
delay(500);
if (isConnected()) {
#ifdef UBX_MODE_NMEA
DEBUG_MSG("Connected to UBLOX GPS, downgrading to NMEA mode\n");
DEBUG_MSG("- GPS errors below are related and safe to ignore\n");
#else
DEBUG_MSG("Connected to UBLOX GPS successfully\n");
#endif
if (!setUBXMode())
RECORD_CRITICALERROR(CriticalErrorCode_UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug
#ifdef UBX_MODE_NMEA
return false;
#else
return true;
#endif
} else {
return false;
}
@@ -61,6 +73,17 @@ bool UBloxGPS::setupGPS()
bool UBloxGPS::setUBXMode()
{
#ifdef UBX_MODE_NMEA
if (_serial_gps) {
ublox.setUART1Output(COM_TYPE_NMEA, 1000);
}
if (i2cAddress) {
ublox.setI2COutput(COM_TYPE_NMEA, 1000);
}
return false; // pretend initialization failed to force NMEA mode
#endif
if (_serial_gps) {
if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API
return false;
@@ -119,7 +142,6 @@ bool UBloxGPS::factoryReset()
void UBloxGPS::whileActive()
{
ublox.flushPVT(); // reset ALL freshness flags first
ublox.getT(maxWait()); // ask for new time data - hopefully ready when we come back
// Ask for a new position fix - hopefully it will have results ready by next time
@@ -170,28 +192,32 @@ bool UBloxGPS::lookForLocation()
{
bool foundLocation = false;
// catch fixType changes here, instead of whileActive()
if (ublox.moduleQueried.fixType) {
fixType = ublox.getFixType();
}
// check if GPS has an acceptable lock
if (! hasLock()) {
return false;
}
// check if a complete GPS solution set is available for reading
// (some of these, like lat/lon are redundant and can be removed)
if ( ! (ublox.moduleQueried.latitude &&
if ( ! (ublox.moduleQueried.fixType &&
ublox.moduleQueried.latitude &&
ublox.moduleQueried.longitude &&
ublox.moduleQueried.altitude &&
ublox.moduleQueried.pDOP &&
ublox.moduleQueried.gpsiTOW))
ublox.moduleQueried.SIV &&
ublox.moduleQueried.gpsDay))
{
// Not ready? No problem! We'll try again later.
return false;
}
fixType = ublox.getFixType();
#ifdef UBLOX_EXTRAVERBOSE
DEBUG_MSG("FixType=%d\n", fixType);
#endif
// check if GPS has an acceptable lock
if (! hasLock()) {
ublox.flushPVT(); // reset ALL freshness flags
return false;
}
// read lat/lon/alt/dop data into temporary variables to avoid
// overwriting global variables with potentially invalid data
int32_t tmp_dop = ublox.getPDOP(0); // PDOP (an accuracy metric) is reported in 10^2 units so we have to scale down when we use it
@@ -199,6 +225,10 @@ bool UBloxGPS::lookForLocation()
int32_t tmp_lon = ublox.getLongitude(0);
int32_t tmp_alt_msl = ublox.getAltitudeMSL(0);
int32_t tmp_alt_hae = ublox.getAltitude(0);
int32_t max_dop = PDOP_INVALID;
if (radioConfig.preferences.gps_max_dop)
max_dop = radioConfig.preferences.gps_max_dop * 100; // scaling
// Note: heading is only currently implmented in the ublox for the 8m chipset - therefore
// don't read it here - it will generate an ignored getPVT command on the 6ms
// heading = ublox.getHeading(0);
@@ -215,41 +245,55 @@ bool UBloxGPS::lookForLocation()
time_t tmp_ts = mktime(&t);
// SIV number is nice-to-have if it's available
if (ublox.moduleQueried.SIV) {
uint16_t gSIV = ublox.getSIV(0);
setNumSatellites(gSIV);
}
// FIXME - can opportunistically attempt to set RTC from GPS timestamp?
// bogus lat lon is reported as 0 or 0 (can be bogus just for one)
// Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg!
// FIXME - NULL ISLAND is a real location on Earth!
foundLocation = (tmp_lat != 0) && (tmp_lon != 0) &&
(tmp_lat <= 900000000) && (tmp_lat >= -900000000) &&
(tmp_dop < PDOP_INVALID);
(tmp_dop < max_dop);
// only if entire dataset is valid, update globals from temp vars
if (foundLocation) {
longitude = tmp_lon;
latitude = tmp_lat;
#ifdef GPS_ALTITUDE_HAE
altitude = tmp_alt_hae / 1000;
#else
altitude = tmp_alt_msl / 1000;
p.location_source = Position_LocSource_LOCSRC_GPS_INTERNAL;
p.longitude_i = tmp_lon;
p.latitude_i = tmp_lat;
if (fixType > 2) {
// if fix is 2d, ignore altitude data
p.altitude = tmp_alt_msl / 1000;
p.altitude_hae = tmp_alt_hae / 1000;
p.alt_geoid_sep = (tmp_alt_hae - tmp_alt_msl) / 1000;
} else {
#ifdef GPS_EXTRAVERBOSE
DEBUG_MSG("no altitude data (fixType=%d)\n", fixType);
#endif
geoidal_height = (tmp_alt_hae - tmp_alt_msl) / 1000;
pos_timestamp = tmp_ts;
dop = tmp_dop;
// clean up old values in case it's a 3d-2d fix transition
p.altitude = p.altitude_hae = p.alt_geoid_sep = 0;
}
p.pos_timestamp = tmp_ts;
p.PDOP = tmp_dop;
p.fix_type = fixType;
p.sats_in_view = ublox.getSIV(0);
// In debug logs, identify position by @timestamp:stage (stage 1 = birth)
DEBUG_MSG("lookForLocation() new pos@%x:1\n", tmp_ts);
} else {
DEBUG_MSG("Invalid location discarded\n");
// INVALID solution - should never happen
DEBUG_MSG("Invalid location lat/lon/hae/dop %d/%d/%d/%d - discarded\n",
tmp_lat, tmp_lon, tmp_alt_hae, tmp_dop);
}
ublox.flushPVT(); // reset ALL freshness flags at the end
return foundLocation;
}
bool UBloxGPS::hasLock()
{
return (fixType >= 3 && fixType <= 4);
if (radioConfig.preferences.gps_accept_2d)
return (fixType >= 2 && fixType <= 4);
else
return (fixType >= 3 && fixType <= 4);
}
bool UBloxGPS::whileIdle()

View File

@@ -27,17 +27,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "NodeDB.h"
#include "Screen.h"
#include "fonts.h"
#include "gps/GeoCoord.h"
#include "gps/RTC.h"
#include "graphics/images.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "mesh/Channels.h"
#include "plugins/TextMessagePlugin.h"
#include "sleep.h"
#include "target_specific.h"
#include "utils.h"
#include "gps/GeoCoord.h"
#ifndef NO_ESP32
#include "esp_task_wdt.h"
#include "mesh/http/WiFiAPClient.h"
#endif
@@ -147,6 +149,26 @@ static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int1
drawIconScreen(region, display, state, x, y);
}
// Used on boot when a certificate is being created
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setFont(FONT_SMALL);
display->drawString(64 + x, y, "Creating SSL certificate");
#ifndef NO_ESP32
yield();
esp_task_wdt_reset();
#endif
display->setFont(FONT_SMALL);
if ((millis() / 1000) % 2) {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
} else {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
}
}
#ifdef HAS_EINK
/// Used on eink displays while in deep sleep
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
@@ -204,7 +226,11 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
display->drawString(64 + x, y, "Updating");
display->setFont(FONT_SMALL);
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait...");
if ((millis() / 1000) % 2) {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
} else {
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
}
// display->setFont(FONT_LARGE);
// display->drawString(64 + x, 26 + y, btPIN);
@@ -226,6 +252,13 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please post on\nmeshtastic.discourse.group");
}
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward plugin are enabled
static bool shouldDrawMessage(const MeshPacket *packet)
{
return packet->from != 0 && !radioConfig.preferences.range_test_plugin_enabled &&
!radioConfig.preferences.store_forward_plugin_enabled;
}
/// Draw the last text message we received
static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
@@ -402,6 +435,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
displayLine = "No GPS Lock";
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
} else {
if (gpsFormat != GpsCoordinateFormat_GpsFormatDMS) {
char coordinateLine[22];
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
@@ -411,25 +445,36 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
sprintf(coordinateLine, "%2i%1c %06i %07i", geoCoord.getUTMZone(), geoCoord.getUTMBand(),
geoCoord.getUTMEasting(), geoCoord.getUTMNorthing());
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatMGRS) { // Military Grid Reference System
sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(), geoCoord.getMGRSEast100k(),
geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(), geoCoord.getMGRSNorthing());
sprintf(coordinateLine, "%2i%1c %1c%1c %05i %05i", geoCoord.getMGRSZone(), geoCoord.getMGRSBand(),
geoCoord.getMGRSEast100k(), geoCoord.getMGRSNorth100k(), geoCoord.getMGRSEasting(),
geoCoord.getMGRSNorthing());
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOLC) { // Open Location Code
geoCoord.getOLCCode(coordinateLine);
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
} else if (gpsFormat == GpsCoordinateFormat_GpsFormatOSGR) { // Ordnance Survey Grid Reference
if (geoCoord.getOSGRE100k() == 'I' || geoCoord.getOSGRN100k() == 'I') // OSGR is only valid around the UK region
sprintf(coordinateLine, "%s", "Out of Boundary");
else
sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(),geoCoord.getOSGRN100k(),
sprintf(coordinateLine, "%1c%1c %05i %05i", geoCoord.getOSGRE100k(), geoCoord.getOSGRN100k(),
geoCoord.getOSGREasting(), geoCoord.getOSGRNorthing());
}
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
// If fixed position, display text "Fixed GPS" alternating with the coordinates.
if (radioConfig.preferences.fixed_position) {
if ((millis() / 10000) % 2) {
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
} else {
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth("Fixed GPS"))) / 2, y, "Fixed GPS");
}
} else {
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(coordinateLine))) / 2, y, coordinateLine);
}
} else {
char latLine[22];
char lonLine[22];
sprintf(latLine, "%2i° %2i' %2.4f\" %1c", geoCoord.getDMSLatDeg(), geoCoord.getDMSLatMin(), geoCoord.getDMSLatSec(),
geoCoord.getDMSLatCP());
sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(),
sprintf(lonLine, "%3i° %2i' %2.4f\" %1c", geoCoord.getDMSLonDeg(), geoCoord.getDMSLonMin(), geoCoord.getDMSLonSec(),
geoCoord.getDMSLonCP());
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(latLine))) / 2, y - FONT_HEIGHT_SMALL * 1, latLine);
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(lonLine))) / 2, y, lonLine);
@@ -574,11 +619,6 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
n = nodeDB.getNodeByIndex(nodeIndex);
}
displayedNodeNum = n->num;
// We just changed to a new node screen, ask that node for updated state if it's older than 2 minutes
if (sinceLastSeen(n) > 120) {
service.sendNetworkPing(displayedNodeNum, true);
}
}
NodeInfo *node = nodeDB.getNodeByIndex(nodeIndex);
@@ -621,7 +661,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// display direction toward node
hasNodeHeading = true;
Position &p = node->position;
float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
float d =
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
if (d < 2000)
snprintf(distStr, sizeof(distStr), "%.0f m", d);
else
@@ -629,7 +670,8 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
// FIXME, also keep the guess at the operators heading and add/substract
// it. currently we don't do this and instead draw north up only.
float bearingToOther = GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
float bearingToOther =
GeoCoord::bearing(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
headingRadian = bearingToOther - myHeading;
drawNodeHeading(display, compassX, compassY, headingRadian);
}
@@ -670,6 +712,7 @@ void _screen_header()
Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl), ui(&dispdev)
{
address_found = address;
cmdQueue.setReader(this);
}
@@ -787,6 +830,8 @@ void Screen::forceDisplay()
#endif
}
static uint32_t lastScreenTransition;
int32_t Screen::runOnce()
{
// If we don't have a screen, don't ever spend any CPU for us.
@@ -855,6 +900,11 @@ int32_t Screen::runOnce()
// oldFrameState = ui.getUiState()->frameState;
DEBUG_MSG("Setting idle framerate\n");
targetFramerate = IDLE_FRAMERATE;
#ifndef NO_ESP32
setCPUFast(false); // Turn up the CPU to improve screen animations
#endif
ui.setTargetFPS(targetFramerate);
forceDisplay();
}
@@ -863,6 +913,11 @@ int32_t Screen::runOnce()
// standard screen switching is stopped.
if (showingNormalScreen) {
// standard screen loop handling here
if (radioConfig.preferences.auto_screen_carousel_secs > 0 &&
(millis() - lastScreenTransition) > (radioConfig.preferences.auto_screen_carousel_secs * 1000)) {
DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
handleOnPress();
}
}
// DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate,
@@ -891,6 +946,18 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
screen->debugInfo.drawFrameWiFi(display, state, x, y);
}
/* show a message that the SSL cert is being built
* it is expected that this will be used during the boot phase */
void Screen::setSSLFrames()
{
if (address_found) {
// DEBUG_MSG("showing SSL frames\n");
static FrameCallback sslFrames[] = {drawSSLScreen};
ui.setFrames(sslFrames, 1);
ui.update();
}
}
// restore our regular frame list
void Screen::setFrames()
{
@@ -925,9 +992,10 @@ void Screen::setFrames()
if (myNodeInfo.error_code)
normalFrames[numframes++] = drawCriticalFaultFrame;
// If we have a text message - show it next
if (devicestate.has_rx_text_message)
// If we have a text message - show it next, unless it's a phone message and we aren't using any special plugins
if (devicestate.has_rx_text_message && shouldDrawMessage(&devicestate.rx_text_message)) {
normalFrames[numframes++] = drawTextMessageFrame;
}
// then all the nodes
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
@@ -1022,7 +1090,8 @@ void Screen::handleOnPress()
// If we are in a transition, the press must have bounced, drop it.
if (ui.getUiState()->frameState == FIXED) {
ui.nextFrame();
DEBUG_MSG("Setting LastScreenTransition\n");
lastScreenTransition = millis();
setFastFramerate();
}
}
@@ -1037,6 +1106,11 @@ void Screen::setFastFramerate()
// We are about to start a transition so speed up fps
targetFramerate = SCREEN_TRANSITION_FRAMERATE;
#ifndef NO_ESP32
setCPUFast(true); // Turn up the CPU to improve screen animations
#endif
ui.setTargetFPS(targetFramerate);
setInterval(0); // redraw ASAP
runASAP = true;
@@ -1128,7 +1202,7 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
// Number of connections to the AP. Default mmax for the esp32 is 4
// Number of connections to the AP. Default max for the esp32 is 4
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("(" + String(WiFi.softAPgetStationNum()) + "/4)"),
y + FONT_HEIGHT_SMALL * 1, "(" + String(WiFi.softAPgetStationNum()) + "/4)");
} else {
@@ -1262,7 +1336,24 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->drawString(x, y, String("USB"));
}
auto mode = "Mode " + String(channels.getPrimary().modem_config);
auto mode = "";
if (channels.getPrimary().modem_config == 0) {
mode = "ShrtSlow";
} else if (channels.getPrimary().modem_config == 1) {
mode = "ShrtFast";
} else if (channels.getPrimary().modem_config == 2) {
mode = "LngFast";
} else if (channels.getPrimary().modem_config == 3) {
mode = "LngSlow";
} else if (channels.getPrimary().modem_config == 4) {
mode = "MedSlow";
} else if (channels.getPrimary().modem_config == 5) {
mode = "MedFast";
} else {
mode = "Custom";
}
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
// Line 2
@@ -1307,11 +1398,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, uptime);
#ifndef NO_ESP32
// Show CPU Frequency.
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("CPU " + String(getCpuFrequencyMhz()) + "MHz"),
y + FONT_HEIGHT_SMALL * 1, "CPU " + String(getCpuFrequencyMhz()) + "MHz");
#endif
// Display Channel Utilization
char chUtil[13];
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil),
y + FONT_HEIGHT_SMALL * 1, chUtil);
// Line 3
if (radioConfig.preferences.gps_format != GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
@@ -1357,7 +1448,7 @@ int Screen::handleStatusUpdate(const meshtastic::Status *arg)
return 0;
}
int Screen::handleTextMessage(const MeshPacket *arg)
int Screen::handleTextMessage(const MeshPacket *packet)
{
if (showingNormalScreen) {
setFrames(); // Regen the list of screens (will show new text message)

View File

@@ -97,6 +97,8 @@ class Screen : public concurrency::OSThread
Screen(const Screen &) = delete;
Screen &operator=(const Screen &) = delete;
uint8_t address_found;
/// Initializes the UI, turns on the display, starts showing boot screen.
//
// Not thread safe - must be called before any other methods are called.
@@ -220,6 +222,9 @@ class Screen : public concurrency::OSThread
/// Used to force (super slow) eink displays to draw critical frames
void forceDisplay();
/// Draws our SSL cert screen during boot (called from WebServer)
void setSSLFrames();
protected:
/// Updates the UI.
//

View File

@@ -40,6 +40,7 @@
#include "RF95Interface.h"
#include "SX1262Interface.h"
#include "SX1268Interface.h"
#include "LLCC68Interface.h"
#ifdef NRF52_SERIES
#include "variant.h"
@@ -133,6 +134,8 @@ static int32_t ledBlinker()
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
}
uint32_t timeLastPowered = 0;
/// Wrapper to convert our powerFSM stuff into a 'thread'
class PowerFSMThread : public OSThread
{
@@ -150,6 +153,13 @@ class PowerFSMThread : public OSThread
auto state = powerFSM.getState();
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
if (powerStatus->getHasUSB()) {
timeLastPowered = millis();
} else if (radioConfig.preferences.on_battery_shutdown_after_secs > 0 &&
millis() > timeLastPowered + (1000 * radioConfig.preferences.on_battery_shutdown_after_secs)) { //shutdown after 30 minutes unpowered
powerFSM.trigger(EVENT_SHUTDOWN);
}
return 10;
}
};
@@ -272,6 +282,8 @@ class ButtonThread : public OSThread
{
#ifndef NO_ESP32
disablePin();
#elif defined(HAS_EINK)
digitalWrite(PIN_EINK_EN,digitalRead(PIN_EINK_EN) == LOW);
#endif
}
@@ -539,6 +551,19 @@ void setup()
}
#endif
#if defined(USE_LLCC68)
if (!rIf) {
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
if (!rIf->init()) {
DEBUG_MSG("Warning: Failed to find LLCC68 radio\n");
delete rIf;
rIf = NULL;
} else {
DEBUG_MSG("LLCC68 Radio init succeeded, using LLCC68 radio\n");
}
}
#endif
#ifdef USE_SIM_RADIO
if (!rIf) {
rIf = new SimRadio;
@@ -576,6 +601,14 @@ void setup()
else
router->addInterface(rIf);
// Calculate and save the bit rate to myNodeInfo
// TODO: This needs to be added what ever method changes the channel from the phone.
myNodeInfo.bitrate = (float(Constants_DATA_PAYLOAD_LEN) /
(float(rIf->getPacketTime(Constants_DATA_PAYLOAD_LEN)))
) * 1000;
DEBUG_MSG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
powerFSMthread = new PowerFSMThread();

View File

@@ -217,17 +217,23 @@ const char *Channels::getName(size_t chIndex)
else
switch (channelSettings.modem_config) {
case ChannelSettings_ModemConfig_Bw125Cr45Sf128:
channelName = "Medium";
channelName = "ShortSlow";
break;
case ChannelSettings_ModemConfig_Bw500Cr45Sf128:
channelName = "ShortFast";
break;
case ChannelSettings_ModemConfig_Bw31_25Cr48Sf512:
channelName = "LongAlt";
channelName = "LongFast";
break;
case ChannelSettings_ModemConfig_Bw125Cr48Sf4096:
channelName = "LongSlow";
break;
case ChannelSettings_ModemConfig_Bw250Cr46Sf2048:
channelName = "MediumSlow";
break;
case ChannelSettings_ModemConfig_Bw250Cr47Sf1024:
channelName = "MediumFast";
break;
default:
channelName = "Invalid";
break;

View File

@@ -17,7 +17,7 @@ ErrorCode FloodingRouter::send(MeshPacket *p)
return Router::send(p);
}
bool FloodingRouter::shouldFilterReceived(const MeshPacket *p)
bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
{
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
printPacket("Ignoring incoming msg, because we've already seen it", p);

View File

@@ -50,7 +50,7 @@ class FloodingRouter : public Router, protected PacketHistory
* Called immedately on receiption, before any further processing.
* @return true to abandon the packet
*/
virtual bool shouldFilterReceived(const MeshPacket *p);
virtual bool shouldFilterReceived(MeshPacket *p);
/**
* Look for broadcasts we need to rebroadcast

View File

@@ -3,4 +3,5 @@
// We need this declaration for proper linking in derived classes
template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;

View File

@@ -0,0 +1,9 @@
#include "configuration.h"
#include "LLCC68Interface.h"
#include "error.h"
LLCC68Interface::LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
SPIClass &spi)
: SX126xInterface(cs, irq, rst, busy, spi)
{
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include "SX126xInterface.h"
/**
* Our adapter for LLCC68 radios
* https://www.semtech.com/products/wireless-rf/lora-core/llcc68
* ⚠️⚠️⚠️
* Be aware that LLCC68 does not support Spreading Factor 12 (SF12) and will not work on the default "Long Slow" channel.
* You must change the channel if you get `Critical Error #3` with this module.
* ⚠️⚠️⚠️
*/
class LLCC68Interface : public SX126xInterface<LLCC68>
{
public:
LLCC68Interface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi);
};

View File

@@ -112,7 +112,11 @@ bool MeshService::reloadConfig()
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
void MeshService::reloadOwner()
{
// DEBUG_MSG("reloadOwner()\n");
// update our local data directly
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
assert(nodeInfoPlugin);
// update everyone else
if (nodeInfoPlugin)
nodeInfoPlugin->sendOurNodeInfo();
nodeDB.saveToDisk();
@@ -140,7 +144,7 @@ void MeshService::handleToRadio(MeshPacket &p)
// Send the packet into the mesh
sendToMesh(packetPool.allocCopy(p));
sendToMesh(packetPool.allocCopy(p), RX_SRC_USER);
bool loopback = false; // if true send any packet the phone sends back itself (for testing)
if (loopback) {
@@ -157,12 +161,12 @@ bool MeshService::cancelSending(PacketId id)
return router->cancelSending(nodeDB.getNodeNum(), id);
}
void MeshService::sendToMesh(MeshPacket *p)
void MeshService::sendToMesh(MeshPacket *p, RxSource src)
{
nodeDB.updateFrom(*p); // update our local DB for this packet (because phone might have sent position packets etc...)
// Note: We might return !OK if our fifo was full, at that point the only option we have is to drop it
router->sendLocal(p);
router->sendLocal(p, src);
}
void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
@@ -209,34 +213,39 @@ NodeInfo *MeshService::refreshMyNodeInfo()
return node;
}
int MeshService::onGPSChanged(const meshtastic::GPSStatus *unused)
int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
{
// Update our local node info with our position (even if we don't decide to update anyone else)
NodeInfo *node = refreshMyNodeInfo();
Position pos = node->position;
Position pos = Position_init_default;
if (gps->hasLock()) {
if (gps->altitude != 0)
pos.altitude = gps->altitude;
pos.latitude_i = gps->latitude;
pos.longitude_i = gps->longitude;
if (newStatus->getHasLock()) {
// load data from GPS object, will add timestamp + battery further down
pos = gps->p;
} else {
// The GPS has lost lock, if we are fixed position we should just keep using
// the old position
#if GPS_EXTRAVERBOSE
DEBUG_MSG("onGPSchanged() - lost validLocation\n");
#endif
if (radioConfig.preferences.fixed_position) {
DEBUG_MSG("WARNING: Using fixed position\n");
} else {
// throw away old position
pos.latitude_i = 0;
pos.longitude_i = 0;
pos.altitude = 0;
pos = node->position;
}
}
DEBUG_MSG("got gps notify time=%u, lat=%d, bat=%d\n", pos.time, pos.latitude_i, pos.battery_level);
// Finally add a fresh timestamp and battery level reading
// I KNOW this is redundant with refreshMyNodeInfo() above, but these are
// inexpensive nonblocking calls and can be refactored in due course
pos.time = getValidTime(RTCQualityGPS);
pos.battery_level = powerStatus->getBatteryChargePercent();
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
DEBUG_MSG("onGPSChanged() pos@%x:4, time=%u, lat=%d, bat=%d\n",
pos.pos_timestamp, pos.time, pos.latitude_i, pos.battery_level);
// Update our current position in the local DB
nodeDB.updatePosition(nodeDB.getNodeNum(), pos);
nodeDB.updatePosition(nodeDB.getNodeNum(), pos, RX_SRC_LOCAL);
return 0;
}

View File

@@ -75,7 +75,7 @@ class MeshService
/// Send a packet into the mesh - note p must have been allocated from packetPool. We will return it to that pool after
/// sending. This is the ONLY function you should use for sending messages into the mesh, because it also updates the nodedb
/// cache
void sendToMesh(MeshPacket *p);
void sendToMesh(MeshPacket *p, RxSource src = RX_SRC_LOCAL);
/** Attempt to cancel a previously sent packet from this _local_ node. Returns true if a packet was found we could cancel */
bool cancelSending(PacketId id);

View File

@@ -20,7 +20,8 @@ typedef uint32_t PacketId; // A packet sequence number
*/
enum RxSource {
RX_SRC_LOCAL, // message was generated locally
RX_SRC_RADIO // message was received from radio mesh
RX_SRC_RADIO, // message was received from radio mesh
RX_SRC_USER // message was received from end-user device
};
/**

View File

@@ -125,6 +125,11 @@ void NodeDB::installDefaultRadioConfig()
memset(&radioConfig, 0, sizeof(radioConfig));
radioConfig.has_preferences = true;
resetRadioConfig();
// for backward compat, default position flags are BAT+ALT+MSL (0x23 = 35)
radioConfig.preferences.position_flags = (PositionFlags_POS_BATTERY |
PositionFlags_POS_ALTITUDE | PositionFlags_POS_ALT_MSL);
}
void NodeDB::installDefaultChannels()
@@ -240,6 +245,10 @@ void NodeDB::init()
preferences.end();
DEBUG_MSG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
/* The ESP32 has a wifi radio. This will need to be modified at some point so
* the test isn't so simplistic.
*/
myNodeInfo.has_wifi = true;
#endif
resetRadioConfig(); // If bogus settings got saved, then fix them
@@ -424,7 +433,7 @@ uint32_t sinceLastSeen(const NodeInfo *n)
return delta;
}
#define NUM_ONLINE_SECS (60 * 2) // 2 hrs to consider someone offline
#define NUM_ONLINE_SECS (60 & 60 * 2) // 2 hrs to consider someone offline
size_t NodeDB::getNumOnlineNodes()
{
@@ -442,25 +451,42 @@ size_t NodeDB::getNumOnlineNodes()
/** Update position info for this node based on received position data
*/
void NodeDB::updatePosition(uint32_t nodeId, const Position &p)
void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
{
NodeInfo *info = getOrCreateNode(nodeId);
DEBUG_MSG("DB update position node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i);
if (src == RX_SRC_LOCAL) {
// Local packet, fully authoritative
DEBUG_MSG("updatePosition LOCAL pos@%x:5, time=%u, latI=%d, lonI=%d\n",
p.pos_timestamp, p.time, p.latitude_i, p.longitude_i);
info->position = p;
// Be careful to only update fields that have been set by the sender
// A lot of position reports don't have time populated. In that case, be careful to not blow away the time we
// recorded based on the packet rxTime
if (p.time)
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.pos_timestamp &&
!p.location_source) {
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
// (stop-gap fix for issue #900)
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
info->position.time = p.time;
if (p.battery_level)
info->position.battery_level = p.battery_level;
if (p.latitude_i || p.longitude_i) {
info->position.latitude_i = p.latitude_i;
info->position.longitude_i = p.longitude_i;
} else {
// Be careful to only update fields that have been set by the REMOTE sender
// A lot of position reports don't have time populated. In that case, be careful to not blow away the time we
// recorded based on the packet rxTime
//
// FIXME perhaps handle RX_SRC_USER separately?
DEBUG_MSG("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n",
nodeId, p.time, p.latitude_i, p.longitude_i);
// First, back up fields that we want to protect from overwrite
uint32_t tmp_time = info->position.time;
// Next, update atomically
info->position = p;
// Last, restore any fields that may have been overwritten
if (! info->position.time)
info->position.time = tmp_time;
}
if (p.altitude)
info->position.altitude = p.altitude;
info->has_position = true;
updateGUIforNode = info;
notifyObservers(true); // Force an update whether or not our node counts have changed

View File

@@ -59,7 +59,7 @@ class NodeDB
/** Update position info for this node based on received position data
*/
void updatePosition(uint32_t nodeId, const Position &p);
void updatePosition(uint32_t nodeId, const Position &p, RxSource src = RX_SRC_RADIO);
/** Update user info for this node based on received user data
*/

View File

@@ -297,6 +297,16 @@ void RadioInterface::applyModemConfig()
cr = 8;
sf = 12;
break;
case ChannelSettings_ModemConfig_Bw250Cr46Sf2048:
bw = 250;
cr = 6;
sf = 11;
break;
case ChannelSettings_ModemConfig_Bw250Cr47Sf1024:
bw = 250;
cr = 7;
sf = 10;
break;
default:
assert(0); // Unknown enum
}
@@ -307,6 +317,8 @@ void RadioInterface::applyModemConfig()
if (bw == 31) // This parameter is not an integer
bw = 31.25;
if (bw == 62) // Fix for 62.5Khz bandwidth
bw = 62.5;
}
power = channelSettings.tx_power;

View File

@@ -87,8 +87,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
* for a long time.
*/
const uint8_t syncWord = 0x2b;
float currentLimit = 100; // FIXME
float currentLimit = 100; // 100mA OCP - Should be acceptable for RFM95/SX127x chipset.
LockingModule module; // The HW interface to the radio

View File

@@ -16,8 +16,13 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
// If someone asks for acks on broadcast, we need the hop limit to be at least one, so that first node that receives our
// message will rebroadcast. But asking for hop_limit 0 in that context means the client app has no preference on hop counts
// and we want this message to get through the whole mesh, so use the default.
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0)
p->hop_limit = HOP_RELIABLE;
if (p->to == NODENUM_BROADCAST && p->hop_limit == 0) {
if (radioConfig.preferences.hop_limit && radioConfig.preferences.hop_limit <= HOP_MAX) {
p->hop_limit = (radioConfig.preferences.hop_limit >= HOP_MAX) ? HOP_MAX : radioConfig.preferences.hop_limit;
} else {
p->hop_limit = HOP_RELIABLE;
}
}
auto copy = packetPool.allocCopy(*p);
startRetransmission(copy);
@@ -26,7 +31,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
return FloodingRouter::send(p);
}
bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
bool ReliableRouter::shouldFilterReceived(MeshPacket *p)
{
// Note: do not use getFrom() here, because we want to ignore messages sent from phone
if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) {
@@ -54,6 +59,17 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
}
}
/* send acks for repeated packets that want acks and are destined for us
* this way if an ACK is dropped and a packet is resent we'll ACK the resent packet
* make sure wasSeenRecently _doesn't_ update
* finding the channel requires decoding the packet. */
if (p->want_ack && (p->to == getNodeNum()) && wasSeenRecently(p, false)) {
if (perhapsDecode(p)) {
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
DEBUG_MSG("acking a repeated want_ack packet\n");
}
}
return FloodingRouter::shouldFilterReceived(p);
}

View File

@@ -102,7 +102,7 @@ class ReliableRouter : public FloodingRouter
/**
* We hook this method so we can see packets before FloodingRouter says they should be discarded
*/
virtual bool shouldFilterReceived(const MeshPacket *p);
virtual bool shouldFilterReceived(MeshPacket *p);
/**
* Add p to the list of packets to retransmit occasionally. We will free it once we stop retransmitting.

View File

@@ -115,7 +115,11 @@ MeshPacket *Router::allocForSending()
p->which_payloadVariant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
p->from = nodeDB.getNodeNum();
p->to = NODENUM_BROADCAST;
p->hop_limit = HOP_RELIABLE;
if (radioConfig.preferences.hop_limit && radioConfig.preferences.hop_limit <= HOP_MAX) {
p->hop_limit = (radioConfig.preferences.hop_limit >= HOP_MAX) ? HOP_MAX : radioConfig.preferences.hop_limit;
} else {
p->hop_limit = HOP_RELIABLE;
}
p->id = generatePacketId();
p->rx_time =
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
@@ -145,7 +149,7 @@ void Router::setReceivedMessage()
runASAP = true;
}
ErrorCode Router::sendLocal(MeshPacket *p)
ErrorCode Router::sendLocal(MeshPacket *p, RxSource src)
{
// No need to deliver externally if the destination is the local node
if (p->to == nodeDB.getNodeNum()) {
@@ -161,7 +165,7 @@ ErrorCode Router::sendLocal(MeshPacket *p)
// If we are sending a broadcast, we also treat it as if we just received it ourself
// this allows local apps (and PCs) to see broadcasts sourced locally
if (p->to == NODENUM_BROADCAST) {
handleReceived(p, RX_SRC_LOCAL);
handleReceived(p, src);
}
return send(p);
@@ -334,9 +338,11 @@ void Router::handleReceived(MeshPacket *p, RxSource src)
if (decoded) {
// parsing was successful, queue for our recipient
if (src == RX_SRC_LOCAL)
printPacket("handleReceived(local)", p);
printPacket("handleReceived(LOCAL)", p);
else if (src == RX_SRC_USER)
printPacket("handleReceived(USER)", p);
else
printPacket("handleReceived(remote)", p);
printPacket("handleReceived(REMOTE)", p);
} else {
printPacket("packet decoding failed (no PSK?)", p);
}

View File

@@ -45,7 +45,7 @@ class Router : protected concurrency::OSThread
*
* NOTE: This method will free the provided packet (even if we return an error code)
*/
ErrorCode sendLocal(MeshPacket *p);
ErrorCode sendLocal(MeshPacket *p, RxSource src = RX_SRC_RADIO);
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
bool cancelSending(NodeNum from, PacketId id);
@@ -90,7 +90,7 @@ class Router : protected concurrency::OSThread
* Called immedately on receiption, before any further processing.
* @return true to abandon the packet
*/
virtual bool shouldFilterReceived(const MeshPacket *p) { return false; }
virtual bool shouldFilterReceived(MeshPacket *p) { return false; }
/**
* Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to

View File

@@ -29,6 +29,8 @@ class SX126xInterface : public RadioLibInterface
protected:
float currentLimit = 140; // Higher OCP limit for SX126x PA
/**
* Specific module instance
*/

View File

@@ -4,9 +4,9 @@
#ifndef PB_ADMIN_PB_H_INCLUDED
#define PB_ADMIN_PB_H_INCLUDED
#include <pb.h>
#include "mesh.pb.h"
#include "radioconfig.pb.h"
#include "channel.pb.h"
#include "radioconfig.pb.h"
#include "mesh.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
@@ -23,6 +23,8 @@ typedef struct _AdminMessage {
RadioConfig get_radio_response;
uint32_t get_channel_request;
Channel get_channel_response;
bool get_owner_request;
User get_owner_response;
bool confirm_set_channel;
bool confirm_set_radio;
bool exit_simulator;
@@ -47,6 +49,8 @@ extern "C" {
#define AdminMessage_get_radio_response_tag 5
#define AdminMessage_get_channel_request_tag 6
#define AdminMessage_get_channel_response_tag 7
#define AdminMessage_get_owner_request_tag 8
#define AdminMessage_get_owner_response_tag 9
#define AdminMessage_confirm_set_channel_tag 32
#define AdminMessage_confirm_set_radio_tag 33
#define AdminMessage_exit_simulator_tag 34
@@ -61,6 +65,8 @@ X(a, STATIC, ONEOF, BOOL, (variant,get_radio_request,get_radio_request)
X(a, STATIC, ONEOF, MESSAGE, (variant,get_radio_response,get_radio_response), 5) \
X(a, STATIC, ONEOF, UINT32, (variant,get_channel_request,get_channel_request), 6) \
X(a, STATIC, ONEOF, MESSAGE, (variant,get_channel_response,get_channel_response), 7) \
X(a, STATIC, ONEOF, BOOL, (variant,get_owner_request,get_owner_request), 8) \
X(a, STATIC, ONEOF, MESSAGE, (variant,get_owner_response,get_owner_response), 9) \
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_channel,confirm_set_channel), 32) \
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_radio,confirm_set_radio), 33) \
X(a, STATIC, ONEOF, BOOL, (variant,exit_simulator,exit_simulator), 34) \
@@ -72,6 +78,7 @@ X(a, STATIC, ONEOF, INT32, (variant,reboot_seconds,reboot_seconds), 35)
#define AdminMessage_variant_set_channel_MSGTYPE Channel
#define AdminMessage_variant_get_radio_response_MSGTYPE RadioConfig
#define AdminMessage_variant_get_channel_response_MSGTYPE Channel
#define AdminMessage_variant_get_owner_response_MSGTYPE User
extern const pb_msgdesc_t AdminMessage_msg;
@@ -79,7 +86,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
#define AdminMessage_fields &AdminMessage_msg
/* Maximum encoded size of messages (where known) */
#define AdminMessage_size 407
#define AdminMessage_size 529
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -14,7 +14,9 @@ typedef enum _ChannelSettings_ModemConfig {
ChannelSettings_ModemConfig_Bw125Cr45Sf128 = 0,
ChannelSettings_ModemConfig_Bw500Cr45Sf128 = 1,
ChannelSettings_ModemConfig_Bw31_25Cr48Sf512 = 2,
ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3
ChannelSettings_ModemConfig_Bw125Cr48Sf4096 = 3,
ChannelSettings_ModemConfig_Bw250Cr46Sf2048 = 4,
ChannelSettings_ModemConfig_Bw250Cr47Sf1024 = 5
} ChannelSettings_ModemConfig;
typedef enum _Channel_Role {
@@ -49,8 +51,8 @@ typedef struct _Channel {
/* Helper constants for enums */
#define _ChannelSettings_ModemConfig_MIN ChannelSettings_ModemConfig_Bw125Cr45Sf128
#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw125Cr48Sf4096
#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw125Cr48Sf4096+1))
#define _ChannelSettings_ModemConfig_MAX ChannelSettings_ModemConfig_Bw250Cr47Sf1024
#define _ChannelSettings_ModemConfig_ARRAYSIZE ((ChannelSettings_ModemConfig)(ChannelSettings_ModemConfig_Bw250Cr47Sf1024+1))
#define _Channel_Role_MIN Channel_Role_DISABLED
#define _Channel_Role_MAX Channel_Role_SECONDARY

View File

@@ -4,8 +4,8 @@
#ifndef PB_DEVICEONLY_PB_H_INCLUDED
#define PB_DEVICEONLY_PB_H_INCLUDED
#include <pb.h>
#include "mesh.pb.h"
#include "channel.pb.h"
#include "mesh.pb.h"
#include "radioconfig.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
@@ -125,7 +125,7 @@ extern const pb_msgdesc_t ChannelFile_msg;
/* Maximum encoded size of messages (where known) */
#define LegacyRadioConfig_size 4
#define LegacyRadioConfig_LegacyPreferences_size 2
#define DeviceState_size 10054
#define DeviceState_size 9967
#define ChannelFile_size 832
#ifdef __cplusplus

View File

@@ -27,7 +27,7 @@ PB_BIND(MeshPacket, MeshPacket, 2)
PB_BIND(NodeInfo, NodeInfo, AUTO)
PB_BIND(MyNodeInfo, MyNodeInfo, AUTO)
PB_BIND(MyNodeInfo, MyNodeInfo, 2)
PB_BIND(LogRecord, LogRecord, AUTO)
@@ -51,3 +51,5 @@ PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO)

View File

@@ -33,6 +33,24 @@ typedef enum _HardwareModel {
HardwareModel_DIY_V1 = 39
} HardwareModel;
typedef enum _Team {
Team_CLEAR = 0,
Team_CYAN = 1,
Team_WHITE = 2,
Team_YELLOW = 3,
Team_ORANGE = 4,
Team_MAGENTA = 5,
Team_RED = 6,
Team_MAROON = 7,
Team_PURPLE = 8,
Team_DARK_BLUE = 9,
Team_BLUE = 10,
Team_TEAL = 11,
Team_GREEN = 12,
Team_DARK_GREEN = 13,
Team_BROWN = 14
} Team;
typedef enum _Constants {
Constants_Unused = 0,
Constants_DATA_PAYLOAD_LEN = 237
@@ -92,6 +110,12 @@ typedef enum _MeshPacket_Priority {
MeshPacket_Priority_MAX = 127
} MeshPacket_Priority;
typedef enum _MeshPacket_Delayed {
MeshPacket_Delayed_NO_DELAY = 0,
MeshPacket_Delayed_DELAYED_BROADCAST = 1,
MeshPacket_Delayed_DELAYED_DIRECT = 2
} MeshPacket_Delayed;
typedef enum _LogRecord_Level {
LogRecord_Level_UNSET = 0,
LogRecord_Level_CRITICAL = 50,
@@ -131,9 +155,16 @@ typedef struct _MyNodeInfo {
uint32_t error_address;
uint32_t error_count;
uint32_t reboot_count;
float bitrate;
uint32_t message_timeout_msec;
uint32_t min_app_version;
uint32_t max_channels;
pb_size_t air_period_tx_count;
uint32_t air_period_tx[24];
pb_size_t air_period_rx_count;
uint32_t air_period_rx[24];
bool has_wifi;
float channel_utilization;
} MyNodeInfo;
typedef struct _Position {
@@ -158,11 +189,6 @@ typedef struct _Position {
uint32_t fix_type;
uint32_t sats_in_view;
uint32_t sensor_id;
uint32_t heading;
int32_t roll;
int32_t pitch;
uint32_t air_speed;
uint32_t ground_distance_cm;
uint32_t pos_next_update;
uint32_t pos_seq_number;
} Position;
@@ -184,6 +210,10 @@ typedef struct _User {
pb_byte_t macaddr[6];
HardwareModel hw_model;
bool is_licensed;
Team team;
uint32_t tx_power_dbm;
uint32_t ant_gain_dbi;
uint32_t ant_azimuth;
} User;
typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t;
@@ -203,6 +233,9 @@ typedef struct _MeshPacket {
bool want_ack;
MeshPacket_Priority priority;
int32_t rx_rssi;
MeshPacket_Delayed delayed;
uint32_t reply_id;
bool is_tapback;
} MeshPacket;
typedef struct _NodeInfo {
@@ -253,6 +286,10 @@ typedef struct _ToRadio {
#define _HardwareModel_MAX HardwareModel_DIY_V1
#define _HardwareModel_ARRAYSIZE ((HardwareModel)(HardwareModel_DIY_V1+1))
#define _Team_MIN Team_CLEAR
#define _Team_MAX Team_BROWN
#define _Team_ARRAYSIZE ((Team)(Team_BROWN+1))
#define _Constants_MIN Constants_Unused
#define _Constants_MAX Constants_DATA_PAYLOAD_LEN
#define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1))
@@ -277,6 +314,10 @@ typedef struct _ToRadio {
#define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX
#define _MeshPacket_Priority_ARRAYSIZE ((MeshPacket_Priority)(MeshPacket_Priority_MAX+1))
#define _MeshPacket_Delayed_MIN MeshPacket_Delayed_NO_DELAY
#define _MeshPacket_Delayed_MAX MeshPacket_Delayed_DELAYED_DIRECT
#define _MeshPacket_Delayed_ARRAYSIZE ((MeshPacket_Delayed)(MeshPacket_Delayed_DELAYED_DIRECT+1))
#define _LogRecord_Level_MIN LogRecord_Level_UNSET
#define _LogRecord_Level_MAX LogRecord_Level_CRITICAL
#define _LogRecord_Level_ARRAYSIZE ((LogRecord_Level)(LogRecord_Level_CRITICAL+1))
@@ -287,26 +328,26 @@ extern "C" {
#endif
/* Initializer values for message structs */
#define Position_init_default {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0}
#define Position_init_default {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_default {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
#define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define Routing_init_default {0, {RouteDiscovery_init_default}}
#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0}
#define MeshPacket_init_default {0, 0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0}
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0}
#define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
#define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN}
#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}}
#define ToRadio_init_default {0, {MeshPacket_init_default}}
#define ToRadio_PeerInfo_init_default {0, 0}
#define Position_init_zero {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0}
#define Position_init_zero {0, 0, 0, 0, 0, _Position_LocSource_MIN, _Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0, _Team_MIN, 0, 0, 0}
#define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
#define Routing_init_zero {0, {RouteDiscovery_init_zero}}
#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0, 0}
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0}
#define MeshPacket_init_zero {0, 0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN, 0, _MeshPacket_Delayed_MIN, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0}
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0}
#define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0}
#define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN}
#define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}}
#define ToRadio_init_zero {0, {MeshPacket_init_zero}}
@@ -333,9 +374,14 @@ extern "C" {
#define MyNodeInfo_error_address_tag 8
#define MyNodeInfo_error_count_tag 9
#define MyNodeInfo_reboot_count_tag 10
#define MyNodeInfo_bitrate_tag 11
#define MyNodeInfo_message_timeout_msec_tag 13
#define MyNodeInfo_min_app_version_tag 14
#define MyNodeInfo_max_channels_tag 15
#define MyNodeInfo_air_period_tx_tag 16
#define MyNodeInfo_air_period_rx_tag 17
#define MyNodeInfo_has_wifi_tag 18
#define MyNodeInfo_channel_utilization_tag 19
#define Position_latitude_i_tag 1
#define Position_longitude_i_tag 2
#define Position_altitude_tag 3
@@ -357,11 +403,6 @@ extern "C" {
#define Position_fix_type_tag 23
#define Position_sats_in_view_tag 24
#define Position_sensor_id_tag 25
#define Position_heading_tag 30
#define Position_roll_tag 31
#define Position_pitch_tag 32
#define Position_air_speed_tag 33
#define Position_ground_distance_cm_tag 34
#define Position_pos_next_update_tag 40
#define Position_pos_seq_number_tag 41
#define RouteDiscovery_route_tag 2
@@ -373,6 +414,10 @@ extern "C" {
#define User_macaddr_tag 4
#define User_hw_model_tag 6
#define User_is_licensed_tag 7
#define User_team_tag 8
#define User_tx_power_dbm_tag 10
#define User_ant_gain_dbi_tag 11
#define User_ant_azimuth_tag 12
#define MeshPacket_from_tag 1
#define MeshPacket_to_tag 2
#define MeshPacket_channel_tag 3
@@ -385,6 +430,9 @@ extern "C" {
#define MeshPacket_want_ack_tag 11
#define MeshPacket_priority_tag 12
#define MeshPacket_rx_rssi_tag 13
#define MeshPacket_delayed_tag 15
#define MeshPacket_reply_id_tag 16
#define MeshPacket_is_tapback_tag 17
#define NodeInfo_num_tag 1
#define NodeInfo_user_tag 2
#define NodeInfo_position_tag 3
@@ -428,11 +476,6 @@ X(a, STATIC, SINGULAR, UINT32, fix_quality, 22) \
X(a, STATIC, SINGULAR, UINT32, fix_type, 23) \
X(a, STATIC, SINGULAR, UINT32, sats_in_view, 24) \
X(a, STATIC, SINGULAR, UINT32, sensor_id, 25) \
X(a, STATIC, SINGULAR, UINT32, heading, 30) \
X(a, STATIC, SINGULAR, SINT32, roll, 31) \
X(a, STATIC, SINGULAR, SINT32, pitch, 32) \
X(a, STATIC, SINGULAR, UINT32, air_speed, 33) \
X(a, STATIC, SINGULAR, UINT32, ground_distance_cm, 34) \
X(a, STATIC, SINGULAR, UINT32, pos_next_update, 40) \
X(a, STATIC, SINGULAR, UINT32, pos_seq_number, 41)
#define Position_CALLBACK NULL
@@ -444,7 +487,11 @@ X(a, STATIC, SINGULAR, STRING, long_name, 2) \
X(a, STATIC, SINGULAR, STRING, short_name, 3) \
X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) \
X(a, STATIC, SINGULAR, UENUM, hw_model, 6) \
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7)
X(a, STATIC, SINGULAR, BOOL, is_licensed, 7) \
X(a, STATIC, SINGULAR, UENUM, team, 8) \
X(a, STATIC, SINGULAR, UINT32, tx_power_dbm, 10) \
X(a, STATIC, SINGULAR, UINT32, ant_gain_dbi, 11) \
X(a, STATIC, SINGULAR, UINT32, ant_azimuth, 12)
#define User_CALLBACK NULL
#define User_DEFAULT NULL
@@ -484,7 +531,10 @@ X(a, STATIC, SINGULAR, FLOAT, rx_snr, 8) \
X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \
X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \
X(a, STATIC, SINGULAR, UENUM, priority, 12) \
X(a, STATIC, SINGULAR, INT32, rx_rssi, 13)
X(a, STATIC, SINGULAR, INT32, rx_rssi, 13) \
X(a, STATIC, SINGULAR, UENUM, delayed, 15) \
X(a, STATIC, SINGULAR, FIXED32, reply_id, 16) \
X(a, STATIC, SINGULAR, BOOL, is_tapback, 17)
#define MeshPacket_CALLBACK NULL
#define MeshPacket_DEFAULT NULL
#define MeshPacket_payloadVariant_decoded_MSGTYPE Data
@@ -511,9 +561,14 @@ X(a, STATIC, SINGULAR, UENUM, error_code, 7) \
X(a, STATIC, SINGULAR, UINT32, error_address, 8) \
X(a, STATIC, SINGULAR, UINT32, error_count, 9) \
X(a, STATIC, SINGULAR, UINT32, reboot_count, 10) \
X(a, STATIC, SINGULAR, FLOAT, bitrate, 11) \
X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 13) \
X(a, STATIC, SINGULAR, UINT32, min_app_version, 14) \
X(a, STATIC, SINGULAR, UINT32, max_channels, 15)
X(a, STATIC, SINGULAR, UINT32, max_channels, 15) \
X(a, STATIC, REPEATED, UINT32, air_period_tx, 16) \
X(a, STATIC, REPEATED, UINT32, air_period_rx, 17) \
X(a, STATIC, SINGULAR, BOOL, has_wifi, 18) \
X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 19)
#define MyNodeInfo_CALLBACK NULL
#define MyNodeInfo_DEFAULT NULL
@@ -584,17 +639,17 @@ extern const pb_msgdesc_t ToRadio_PeerInfo_msg;
#define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg
/* Maximum encoded size of messages (where known) */
#define Position_size 188
#define User_size 76
#define Position_size 153
#define User_size 96
#define RouteDiscovery_size 40
#define Routing_size 42
#define Data_size 260
#define MeshPacket_size 309
#define NodeInfo_size 285
#define MyNodeInfo_size 101
#define MeshPacket_size 320
#define NodeInfo_size 270
#define MyNodeInfo_size 451
#define LogRecord_size 81
#define FromRadio_size 318
#define ToRadio_size 312
#define FromRadio_size 460
#define ToRadio_size 323
#define ToRadio_PeerInfo_size 8
#ifdef __cplusplus

View File

@@ -24,6 +24,7 @@ typedef enum _PortNum {
PortNum_STORE_FORWARD_APP = 65,
PortNum_RANGE_TEST_APP = 66,
PortNum_ENVIRONMENTAL_MEASUREMENT_APP = 67,
PortNum_ZPS_APP = 68,
PortNum_PRIVATE_APP = 256,
PortNum_ATAK_FORWARDER = 257,
PortNum_MAX = 511

View File

@@ -80,7 +80,8 @@ typedef enum _PositionFlags {
} PositionFlags;
typedef enum _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType {
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0,
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20 = 1
} RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType;
/* Struct definitions */
@@ -100,6 +101,7 @@ typedef struct _RadioConfig_UserPreferences {
bool wifi_ap_mode;
RegionCode region;
ChargeCurrent charge_current;
bool position_broadcast_smart;
LocationSharing location_share;
GpsOperation gps_operation;
uint32_t gps_update_interval;
@@ -112,6 +114,8 @@ typedef struct _RadioConfig_UserPreferences {
char mqtt_server[32];
bool mqtt_disabled;
GpsCoordinateFormat gps_format;
bool gps_accept_2d;
uint32_t gps_max_dop;
bool factory_reset;
bool debug_log_enabled;
pb_size_t ignore_incoming_count;
@@ -132,6 +136,8 @@ typedef struct _RadioConfig_UserPreferences {
uint32_t range_test_plugin_sender;
bool range_test_plugin_save;
uint32_t store_forward_plugin_records;
uint32_t store_forward_plugin_history_return_max;
uint32_t store_forward_plugin_history_return_window;
bool environmental_measurement_plugin_measurement_enabled;
bool environmental_measurement_plugin_screen_enabled;
uint32_t environmental_measurement_plugin_read_error_count_threshold;
@@ -141,7 +147,14 @@ typedef struct _RadioConfig_UserPreferences {
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType environmental_measurement_plugin_sensor_type;
uint32_t environmental_measurement_plugin_sensor_pin;
bool store_forward_plugin_enabled;
bool store_forward_plugin_heartbeat;
uint32_t position_flags;
bool is_always_powered;
uint32_t auto_screen_carousel_secs;
uint32_t on_battery_shutdown_after_secs;
uint32_t hop_limit;
char mqtt_username[32];
char mqtt_password[32];
} RadioConfig_UserPreferences;
typedef struct _RadioConfig {
@@ -176,8 +189,8 @@ typedef struct _RadioConfig {
#define _PositionFlags_ARRAYSIZE ((PositionFlags)(PositionFlags_POS_TIMESTAMP+1))
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MAX RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_ARRAYSIZE ((RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType)(RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11+1))
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MAX RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20
#define _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_ARRAYSIZE ((RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType)(RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20+1))
#ifdef __cplusplus
@@ -186,9 +199,9 @@ extern "C" {
/* Initializer values for message structs */
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", ""}
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _LocationSharing_MIN, _GpsOperation_MIN, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", ""}
/* Field tags (for use in manual encoding/decoding) */
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
@@ -206,6 +219,7 @@ extern "C" {
#define RadioConfig_UserPreferences_wifi_ap_mode_tag 14
#define RadioConfig_UserPreferences_region_tag 15
#define RadioConfig_UserPreferences_charge_current_tag 16
#define RadioConfig_UserPreferences_position_broadcast_smart_tag 17
#define RadioConfig_UserPreferences_location_share_tag 32
#define RadioConfig_UserPreferences_gps_operation_tag 33
#define RadioConfig_UserPreferences_gps_update_interval_tag 34
@@ -218,6 +232,8 @@ extern "C" {
#define RadioConfig_UserPreferences_mqtt_server_tag 42
#define RadioConfig_UserPreferences_mqtt_disabled_tag 43
#define RadioConfig_UserPreferences_gps_format_tag 44
#define RadioConfig_UserPreferences_gps_accept_2d_tag 45
#define RadioConfig_UserPreferences_gps_max_dop_tag 46
#define RadioConfig_UserPreferences_factory_reset_tag 100
#define RadioConfig_UserPreferences_debug_log_enabled_tag 101
#define RadioConfig_UserPreferences_ignore_incoming_tag 103
@@ -237,6 +253,8 @@ extern "C" {
#define RadioConfig_UserPreferences_range_test_plugin_sender_tag 133
#define RadioConfig_UserPreferences_range_test_plugin_save_tag 134
#define RadioConfig_UserPreferences_store_forward_plugin_records_tag 137
#define RadioConfig_UserPreferences_store_forward_plugin_history_return_max_tag 138
#define RadioConfig_UserPreferences_store_forward_plugin_history_return_window_tag 139
#define RadioConfig_UserPreferences_environmental_measurement_plugin_measurement_enabled_tag 140
#define RadioConfig_UserPreferences_environmental_measurement_plugin_screen_enabled_tag 141
#define RadioConfig_UserPreferences_environmental_measurement_plugin_read_error_count_threshold_tag 142
@@ -246,7 +264,14 @@ extern "C" {
#define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_type_tag 146
#define RadioConfig_UserPreferences_environmental_measurement_plugin_sensor_pin_tag 147
#define RadioConfig_UserPreferences_store_forward_plugin_enabled_tag 148
#define RadioConfig_UserPreferences_store_forward_plugin_heartbeat_tag 149
#define RadioConfig_UserPreferences_position_flags_tag 150
#define RadioConfig_UserPreferences_is_always_powered_tag 151
#define RadioConfig_UserPreferences_auto_screen_carousel_secs_tag 152
#define RadioConfig_UserPreferences_on_battery_shutdown_after_secs_tag 153
#define RadioConfig_UserPreferences_hop_limit_tag 154
#define RadioConfig_UserPreferences_mqtt_username_tag 155
#define RadioConfig_UserPreferences_mqtt_password_tag 156
#define RadioConfig_preferences_tag 1
/* Struct field encoding specification for nanopb */
@@ -272,6 +297,7 @@ X(a, STATIC, SINGULAR, STRING, wifi_password, 13) \
X(a, STATIC, SINGULAR, BOOL, wifi_ap_mode, 14) \
X(a, STATIC, SINGULAR, UENUM, region, 15) \
X(a, STATIC, SINGULAR, UENUM, charge_current, 16) \
X(a, STATIC, SINGULAR, BOOL, position_broadcast_smart, 17) \
X(a, STATIC, SINGULAR, UENUM, location_share, 32) \
X(a, STATIC, SINGULAR, UENUM, gps_operation, 33) \
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 34) \
@@ -284,6 +310,8 @@ X(a, STATIC, SINGULAR, FLOAT, frequency_offset, 41) \
X(a, STATIC, SINGULAR, STRING, mqtt_server, 42) \
X(a, STATIC, SINGULAR, BOOL, mqtt_disabled, 43) \
X(a, STATIC, SINGULAR, UENUM, gps_format, 44) \
X(a, STATIC, SINGULAR, BOOL, gps_accept_2d, 45) \
X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 46) \
X(a, STATIC, SINGULAR, BOOL, factory_reset, 100) \
X(a, STATIC, SINGULAR, BOOL, debug_log_enabled, 101) \
X(a, STATIC, REPEATED, UINT32, ignore_incoming, 103) \
@@ -303,6 +331,8 @@ X(a, STATIC, SINGULAR, BOOL, range_test_plugin_enabled, 132) \
X(a, STATIC, SINGULAR, UINT32, range_test_plugin_sender, 133) \
X(a, STATIC, SINGULAR, BOOL, range_test_plugin_save, 134) \
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_records, 137) \
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_history_return_max, 138) \
X(a, STATIC, SINGULAR, UINT32, store_forward_plugin_history_return_window, 139) \
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_measurement_enabled, 140) \
X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_screen_enabled, 141) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_read_error_count_threshold, 142) \
@@ -312,7 +342,14 @@ X(a, STATIC, SINGULAR, BOOL, environmental_measurement_plugin_display_fare
X(a, STATIC, SINGULAR, UENUM, environmental_measurement_plugin_sensor_type, 146) \
X(a, STATIC, SINGULAR, UINT32, environmental_measurement_plugin_sensor_pin, 147) \
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_enabled, 148) \
X(a, STATIC, SINGULAR, UINT32, position_flags, 150)
X(a, STATIC, SINGULAR, BOOL, store_forward_plugin_heartbeat, 149) \
X(a, STATIC, SINGULAR, UINT32, position_flags, 150) \
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 151) \
X(a, STATIC, SINGULAR, UINT32, auto_screen_carousel_secs, 152) \
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 153) \
X(a, STATIC, SINGULAR, UINT32, hop_limit, 154) \
X(a, STATIC, SINGULAR, STRING, mqtt_username, 155) \
X(a, STATIC, SINGULAR, STRING, mqtt_password, 156)
#define RadioConfig_UserPreferences_CALLBACK NULL
#define RadioConfig_UserPreferences_DEFAULT NULL
@@ -324,8 +361,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
/* Maximum encoded size of messages (where known) */
#define RadioConfig_size 404
#define RadioConfig_UserPreferences_size 401
#define RadioConfig_size 526
#define RadioConfig_UserPreferences_size 523
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -0,0 +1,22 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.4 */
#include "storeforward.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
PB_BIND(StoreAndForward, StoreAndForward, AUTO)
PB_BIND(StoreAndForward_Statistics, StoreAndForward_Statistics, AUTO)
PB_BIND(StoreAndForward_History, StoreAndForward_History, AUTO)
PB_BIND(StoreAndForward_Heartbeat, StoreAndForward_Heartbeat, AUTO)

View File

@@ -0,0 +1,163 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.4 */
#ifndef PB_STOREFORWARD_PB_H_INCLUDED
#define PB_STOREFORWARD_PB_H_INCLUDED
#include <pb.h>
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Enum definitions */
typedef enum _StoreAndForward_RequestResponse {
StoreAndForward_RequestResponse_UNSET = 0,
StoreAndForward_RequestResponse_ROUTER_ERROR = 1,
StoreAndForward_RequestResponse_ROUTER_HEARTBEAT = 2,
StoreAndForward_RequestResponse_ROUTER_PING = 3,
StoreAndForward_RequestResponse_ROUTER_PONG = 4,
StoreAndForward_RequestResponse_ROUTER_BUSY = 5,
StoreAndForward_RequestResponse_ROUTER_HISTORY = 6,
StoreAndForward_RequestResponse_CLIENT_ERROR = 101,
StoreAndForward_RequestResponse_CLIENT_HISTORY = 102,
StoreAndForward_RequestResponse_CLIENT_STATS = 103,
StoreAndForward_RequestResponse_CLIENT_PING = 104,
StoreAndForward_RequestResponse_CLIENT_PONG = 105,
StoreAndForward_RequestResponse_CLIENT_ABORT = 106
} StoreAndForward_RequestResponse;
/* Struct definitions */
typedef struct _StoreAndForward_Heartbeat {
uint32_t period;
uint32_t secondary;
} StoreAndForward_Heartbeat;
typedef struct _StoreAndForward_History {
uint32_t history_messages;
uint32_t window;
uint32_t last_request;
} StoreAndForward_History;
typedef struct _StoreAndForward_Statistics {
uint32_t messages_total;
uint32_t messages_saved;
uint32_t messages_max;
uint32_t up_time;
uint32_t requests;
uint32_t requests_history;
bool heartbeat;
uint32_t return_max;
uint32_t return_window;
} StoreAndForward_Statistics;
typedef struct _StoreAndForward {
StoreAndForward_RequestResponse rr;
bool has_stats;
StoreAndForward_Statistics stats;
bool has_history;
StoreAndForward_History history;
bool has_heartbeat;
StoreAndForward_Heartbeat heartbeat;
} StoreAndForward;
/* Helper constants for enums */
#define _StoreAndForward_RequestResponse_MIN StoreAndForward_RequestResponse_UNSET
#define _StoreAndForward_RequestResponse_MAX StoreAndForward_RequestResponse_CLIENT_ABORT
#define _StoreAndForward_RequestResponse_ARRAYSIZE ((StoreAndForward_RequestResponse)(StoreAndForward_RequestResponse_CLIENT_ABORT+1))
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define StoreAndForward_init_default {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_default, false, StoreAndForward_History_init_default, false, StoreAndForward_Heartbeat_init_default}
#define StoreAndForward_Statistics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define StoreAndForward_History_init_default {0, 0, 0}
#define StoreAndForward_Heartbeat_init_default {0, 0}
#define StoreAndForward_init_zero {_StoreAndForward_RequestResponse_MIN, false, StoreAndForward_Statistics_init_zero, false, StoreAndForward_History_init_zero, false, StoreAndForward_Heartbeat_init_zero}
#define StoreAndForward_Statistics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
#define StoreAndForward_History_init_zero {0, 0, 0}
#define StoreAndForward_Heartbeat_init_zero {0, 0}
/* Field tags (for use in manual encoding/decoding) */
#define StoreAndForward_Heartbeat_period_tag 1
#define StoreAndForward_Heartbeat_secondary_tag 2
#define StoreAndForward_History_history_messages_tag 1
#define StoreAndForward_History_window_tag 2
#define StoreAndForward_History_last_request_tag 3
#define StoreAndForward_Statistics_messages_total_tag 1
#define StoreAndForward_Statistics_messages_saved_tag 2
#define StoreAndForward_Statistics_messages_max_tag 3
#define StoreAndForward_Statistics_up_time_tag 4
#define StoreAndForward_Statistics_requests_tag 5
#define StoreAndForward_Statistics_requests_history_tag 6
#define StoreAndForward_Statistics_heartbeat_tag 7
#define StoreAndForward_Statistics_return_max_tag 8
#define StoreAndForward_Statistics_return_window_tag 9
#define StoreAndForward_rr_tag 1
#define StoreAndForward_stats_tag 2
#define StoreAndForward_history_tag 3
#define StoreAndForward_heartbeat_tag 4
/* Struct field encoding specification for nanopb */
#define StoreAndForward_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UENUM, rr, 1) \
X(a, STATIC, OPTIONAL, MESSAGE, stats, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, history, 3) \
X(a, STATIC, OPTIONAL, MESSAGE, heartbeat, 4)
#define StoreAndForward_CALLBACK NULL
#define StoreAndForward_DEFAULT NULL
#define StoreAndForward_stats_MSGTYPE StoreAndForward_Statistics
#define StoreAndForward_history_MSGTYPE StoreAndForward_History
#define StoreAndForward_heartbeat_MSGTYPE StoreAndForward_Heartbeat
#define StoreAndForward_Statistics_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, messages_total, 1) \
X(a, STATIC, SINGULAR, UINT32, messages_saved, 2) \
X(a, STATIC, SINGULAR, UINT32, messages_max, 3) \
X(a, STATIC, SINGULAR, UINT32, up_time, 4) \
X(a, STATIC, SINGULAR, UINT32, requests, 5) \
X(a, STATIC, SINGULAR, UINT32, requests_history, 6) \
X(a, STATIC, SINGULAR, BOOL, heartbeat, 7) \
X(a, STATIC, SINGULAR, UINT32, return_max, 8) \
X(a, STATIC, SINGULAR, UINT32, return_window, 9)
#define StoreAndForward_Statistics_CALLBACK NULL
#define StoreAndForward_Statistics_DEFAULT NULL
#define StoreAndForward_History_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, history_messages, 1) \
X(a, STATIC, SINGULAR, UINT32, window, 2) \
X(a, STATIC, SINGULAR, UINT32, last_request, 3)
#define StoreAndForward_History_CALLBACK NULL
#define StoreAndForward_History_DEFAULT NULL
#define StoreAndForward_Heartbeat_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, period, 1) \
X(a, STATIC, SINGULAR, UINT32, secondary, 2)
#define StoreAndForward_Heartbeat_CALLBACK NULL
#define StoreAndForward_Heartbeat_DEFAULT NULL
extern const pb_msgdesc_t StoreAndForward_msg;
extern const pb_msgdesc_t StoreAndForward_Statistics_msg;
extern const pb_msgdesc_t StoreAndForward_History_msg;
extern const pb_msgdesc_t StoreAndForward_Heartbeat_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define StoreAndForward_fields &StoreAndForward_msg
#define StoreAndForward_Statistics_fields &StoreAndForward_Statistics_msg
#define StoreAndForward_History_fields &StoreAndForward_History_msg
#define StoreAndForward_Heartbeat_fields &StoreAndForward_Heartbeat_msg
/* Maximum encoded size of messages (where known) */
#define StoreAndForward_size 88
#define StoreAndForward_Statistics_size 50
#define StoreAndForward_History_size 18
#define StoreAndForward_Heartbeat_size 12
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -53,19 +53,6 @@ char contentTypes[][2][32] = {{".txt", "text/plain"}, {".html", "text/html"}
// Our API to handle messages to and from the radio.
HttpAPI webAPI;
uint32_t numberOfRequests = 0;
uint32_t timeSpeedUp = 0;
uint32_t getTimeSpeedUp()
{
return timeSpeedUp;
}
void setTimeSpeedUp()
{
timeSpeedUp = millis();
}
void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
{
@@ -87,7 +74,7 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
ResourceNode *nodeJsonReport = new ResourceNode("/json/report", "GET", &handleReport);
ResourceNode *nodeJsonSpiffsBrowseStatic = new ResourceNode("/json/spiffs/browse/static", "GET", &handleSpiffsBrowseStatic);
ResourceNode *nodeJsonDelete = new ResourceNode("/json/spiffs/delete/static", "DELETE", &handleSpiffsDeleteStatic);
ResourceNode *nodeRoot = new ResourceNode("/*", "GET", &handleStatic);
// Secure nodes
@@ -105,8 +92,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
secureServer->registerNode(nodeJsonReport);
secureServer->registerNode(nodeRoot);
secureServer->addMiddleware(&middlewareSpeedUp240);
// Insecure nodes
insecureServer->registerNode(nodeAPIv1ToRadioOptions);
insecureServer->registerNode(nodeAPIv1ToRadio);
@@ -121,43 +106,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
insecureServer->registerNode(nodeJsonDelete);
insecureServer->registerNode(nodeJsonReport);
insecureServer->registerNode(nodeRoot);
insecureServer->addMiddleware(&middlewareSpeedUp160);
}
void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next)
{
// We want to print the response status, so we need to call next() first.
next();
// Phone (or other device) has contacted us over WiFi. Keep the radio turned on.
// TODO: This should go into its own middleware layer separate from the speedup.
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
setCpuFrequencyMhz(240);
setTimeSpeedUp();
numberOfRequests++;
}
void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next)
{
// We want to print the response status, so we need to call next() first.
next();
// Phone (or other device) has contacted us over WiFi. Keep the radio turned on.
// TODO: This should go into its own middleware layer separate from the speedup.
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
// If the frequency is 240mhz, we have recently gotten a HTTPS request.
// In that case, leave the frequency where it is and just update the
// countdown timer (timeSpeedUp).
if (getCpuFrequencyMhz() != 240) {
setCpuFrequencyMhz(160);
}
setTimeSpeedUp();
numberOfRequests++;
}
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
@@ -227,7 +175,6 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS");
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
if (req->getMethod() == "OPTIONS") {
res->setStatusCode(204); // Success with no content
// res->print(""); @todo remove
@@ -336,7 +283,6 @@ void handleStatic(HTTPRequest *req, HTTPResponse *res)
std::string filename = "/static/" + parameter1;
std::string filenameGzip = "/static/" + parameter1 + ".gz";
// Try to open the file from SPIFFS
File file;
@@ -403,10 +349,6 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
DEBUG_MSG("Form Upload - Disabling keep-alive\n");
res->setHeader("Connection", "close");
DEBUG_MSG("Form Upload - Set frequency to 240mhz\n");
// The upload process is very CPU intensive. Let's speed things up a bit.
setCpuFrequencyMhz(240);
// First, we need to check the encoding of the form that we have received.
// The browser will set the Content-Type request header, so we can use it for that purpose.
// Then we select the body parser based on the encoding.
@@ -560,12 +502,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
res->print("\"tx_log\": [");
logArray = airtimeReport(TX_LOG);
for (int i = 0; i < getPeriodsToLog(); i++) {
logArray = airTime->airtimeReport(TX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != getPeriodsToLog() - 1) {
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
}
@@ -573,12 +515,12 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
res->println("],");
res->print("\"rx_log\": [");
logArray = airtimeReport(RX_LOG);
for (int i = 0; i < getPeriodsToLog(); i++) {
logArray = airTime->airtimeReport(RX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != getPeriodsToLog() - 1) {
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
}
@@ -586,26 +528,25 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
res->println("],");
res->print("\"rx_all_log\": [");
logArray = airtimeReport(RX_ALL_LOG);
for (int i = 0; i < getPeriodsToLog(); i++) {
logArray = airTime->airtimeReport(RX_ALL_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != getPeriodsToLog() - 1) {
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
}
res->println("],");
res->printf("\"seconds_since_boot\": %u,\n", getSecondsSinceBoot());
res->printf("\"seconds_per_period\": %u,\n", getSecondsPerPeriod());
res->printf("\"periods_to_log\": %u\n", getPeriodsToLog());
res->printf("\"seconds_since_boot\": %u,\n", airTime->getSecondsSinceBoot());
res->printf("\"seconds_per_period\": %u,\n", airTime->getSecondsPerPeriod());
res->printf("\"periods_to_log\": %u\n", airTime->getPeriodsToLog());
res->println("},");
res->println("\"wifi\": {");
res->printf("\"web_request_count\": %d,\n", numberOfRequests);
res->println("\"rssi\": " + String(WiFi.RSSI()) + ",");
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
@@ -736,15 +677,11 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
for (int i = 0; i < n; ++i) {
char ssidArray[50];
String ssidString = String(WiFi.SSID(i));
// String ssidString = String(WiFi.SSID(i)).toCharArray(ssidArray, WiFi.SSID(i).length());
ssidString.replace("\"", "\\\"");
ssidString.toCharArray(ssidArray, 50);
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
// res->println("{\"ssid\": \"%s\",\"rssi\": -75}, ", String(WiFi.SSID(i).c_str() );
res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i));
// WiFi.RSSI(i)
if (i != n - 1) {
res->printf(",");
}

View File

@@ -18,10 +18,6 @@ void handleReport(HTTPRequest *req, HTTPResponse *res);
void middlewareSpeedUp240(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
uint32_t getTimeSpeedUp();
void setTimeSpeedUp();
// Interface to the PhoneAPI to access the protobufs with messages
class HttpAPI : public PhoneAPI
{

View File

@@ -3,6 +3,4 @@
#define BoolToString(x) ((x) ? "true" : "false")
void replaceAll(std::string &str, const std::string &from, const std::string &to);

View File

@@ -1,6 +1,9 @@
#include "mesh/http/WebServer.h"
#include "NodeDB.h"
#include "graphics/Screen.h"
#include "main.h"
#include "mesh/http/WiFiAPClient.h"
#include "sleep.h"
#include <HTTPBodyParser.hpp>
#include <HTTPMultipartBodyParser.hpp>
#include <HTTPURLEncodedBodyParser.hpp>
@@ -56,20 +59,10 @@ static void handleWebResponse()
// will be ignored by the NRF boards.
handleDNSResponse();
if(secureServer)
if (secureServer)
secureServer->loop();
insecureServer->loop();
}
/*
Slow down the CPU if we have not received a request within the last few
seconds.
*/
if (millis() - getTimeSpeedUp() >= (25 * 1000)) {
setCpuFrequencyMhz(80);
setTimeSpeedUp();
}
}
}
@@ -77,13 +70,13 @@ static void taskCreateCert(void *parameter)
{
prefs.begin("MeshtasticHTTPS", false);
// Delete the saved certs
if (0) {
DEBUG_MSG("Deleting any saved SSL keys ...\n");
// prefs.clear();
prefs.remove("PK");
prefs.remove("cert");
}
#if 0
// Delete the saved certs (used in debugging)
DEBUG_MSG("Deleting any saved SSL keys ...\n");
// prefs.clear();
prefs.remove("PK");
prefs.remove("cert");
#endif
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
@@ -102,16 +95,10 @@ static void taskCreateCert(void *parameter)
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
// DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes");
// for (int i = 0; i < cert->getPKLength(); i++)
// Serial.print(cert->getPKData()[i], HEX);
// Serial.println();
DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
// for (int i = 0; i < cert->getCertLength(); i++)
// Serial.print(cert->getCertData()[i], HEX);
// Serial.println();
} else {
DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n");
yield();
cert = new SSLCert();
@@ -123,22 +110,12 @@ static void taskCreateCert(void *parameter)
if (createCertResult != 0) {
DEBUG_MSG("Creating the certificate failed\n");
// Serial.printf("Creating the certificate failed. Error Code = 0x%02X, check SSLCert.hpp for details",
// createCertResult);
// while (true)
// delay(500);
} else {
DEBUG_MSG("Creating the certificate was successful\n");
DEBUG_MSG("Created Private Key: %d Bytes\n", cert->getPKLength());
// for (int i = 0; i < cert->getPKLength(); i++)
// Serial.print(cert->getPKData()[i], HEX);
// Serial.println();
DEBUG_MSG("Created Certificate: %d Bytes\n", cert->getCertLength());
// for (int i = 0; i < cert->getCertLength(); i++)
// Serial.print(cert->getCertData()[i], HEX);
// Serial.println();
prefs.putBytes("PK", (uint8_t *)cert->getPKData(), cert->getPKLength());
prefs.putBytes("cert", (uint8_t *)cert->getCertData(), cert->getCertLength());
@@ -153,6 +130,7 @@ static void taskCreateCert(void *parameter)
void createSSLCert()
{
bool runLoop = false;
if (isWifiAvailable() && !isCertReady) {
// Create a new process just to handle creating the cert.
@@ -160,17 +138,29 @@ void createSSLCert()
// jm@casler.org (Oct 2020)
xTaskCreate(taskCreateCert, /* Task function. */
"createCert", /* String with name of task. */
16384, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */
16, /* Priority of the task. */
NULL); /* Task handle. */
// 16384, /* Stack size in bytes. */
8192, /* Stack size in bytes. */
NULL, /* Parameter passed as input of the task */
16, /* Priority of the task. */
NULL); /* Task handle. */
DEBUG_MSG("Waiting for SSL Cert to be generated.\n");
while (!isCertReady) {
DEBUG_MSG(".");
delay(1000);
yield();
esp_task_wdt_reset();
if ((millis() / 500) % 2) {
if (runLoop) {
DEBUG_MSG(".");
yield();
esp_task_wdt_reset();
if (millis() / 1000 >= 3) {
screen->setSSLFrames();
}
}
runLoop = false;
} else {
runLoop = true;
}
}
DEBUG_MSG("SSL Cert Ready!\n");
}
@@ -193,51 +183,17 @@ void initWebServer()
{
DEBUG_MSG("Initializing Web Server ...\n");
#if 0
// this seems to be a copypaste dup of taskCreateCert
prefs.begin("MeshtasticHTTPS", false);
size_t pkLen = prefs.getBytesLength("PK");
size_t certLen = prefs.getBytesLength("cert");
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
if (pkLen && certLen) {
uint8_t *pkBuffer = new uint8_t[pkLen];
prefs.getBytes("PK", pkBuffer, pkLen);
uint8_t *certBuffer = new uint8_t[certLen];
prefs.getBytes("cert", certBuffer, certLen);
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
// DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes");
// for (int i = 0; i < cert->getPKLength(); i++)
// Serial.print(cert->getPKData()[i], HEX);
// Serial.println();
DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
// for (int i = 0; i < cert->getCertLength(); i++)
// Serial.print(cert->getCertData()[i], HEX);
// Serial.println();
} else {
DEBUG_MSG("Web Server started without SSL keys! How did this happen?\n");
}
#endif
// We can now use the new certificate to setup our server as usual.
secureServer = new HTTPSServer(cert);
insecureServer = new HTTPServer();
registerHandlers(insecureServer, secureServer);
if(secureServer) {
if (secureServer) {
DEBUG_MSG("Starting Secure Web Server...\n");
secureServer->start();
}
DEBUG_MSG("Starting Insecure Web Server...\n");
DEBUG_MSG("Starting Insecure Web Server...\n");
insecureServer->start();
if (insecureServer->isRunning()) {
DEBUG_MSG("Web Servers Ready! :-) \n");

View File

@@ -15,7 +15,6 @@ class WebServerThread : private concurrency::OSThread
WebServerThread();
protected:
virtual int32_t runOnce();
};

View File

@@ -57,7 +57,7 @@ static int32_t reconnectWiFi()
if (*wifiName) {
needReconnect = false;
DEBUG_MSG("... Reconnecting to WiFi access point");
DEBUG_MSG("... Reconnecting to WiFi access point\n");
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(wifiName, wifiPsw);
}
@@ -103,6 +103,8 @@ void deinitWifi()
saving on the 2.4g transceiver.
*/
DEBUG_MSG("WiFi deinit\n");
if (isWifiAvailable()) {
WiFi.mode(WIFI_MODE_NULL);
DEBUG_MSG("WiFi Turned Off\n");
@@ -140,6 +142,14 @@ static void onNetworkConnected()
// Startup WiFi
bool initWifi(bool forceSoftAP)
{
if (forceSoftAP) {
DEBUG_MSG("WiFi ... Forced AP Mode\n");
} else if (radioConfig.preferences.wifi_ap_mode) {
DEBUG_MSG("WiFi ... AP Mode\n");
} else {
DEBUG_MSG("WiFi ... Client Mode\n");
}
forcedSoftAP = forceSoftAP;
if ((radioConfig.has_preferences && radioConfig.preferences.wifi_ssid[0]) || forceSoftAP) {
@@ -152,30 +162,28 @@ bool initWifi(bool forceSoftAP)
wifiPsw = NULL;
if (*wifiName || forceSoftAP) {
if (forceSoftAP) {
DEBUG_MSG("Forcing SoftAP\n");
const char *softAPssid = "meshtasticAdmin";
const char *softAPpasswd = "12345678";
if (radioConfig.preferences.wifi_ap_mode || forceSoftAP) {
IPAddress apIP(192, 168, 42, 1);
WiFi.onEvent(WiFiEvent);
WiFi.mode(WIFI_AP);
if (forcedSoftAP) {
const char *softAPssid = "meshtasticAdmin";
const char *softAPpasswd = "12345678";
DEBUG_MSG("Starting (Forced) WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
} else {
DEBUG_MSG("Starting WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
}
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", softAPssid, WiFi.softAP(softAPssid, softAPpasswd));
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
DEBUG_MSG("MY IP AP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
dnsServer.start(53, "*", apIP);
} else if (radioConfig.preferences.wifi_ap_mode) {
IPAddress apIP(192, 168, 42, 1);
WiFi.onEvent(WiFiEvent);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
DEBUG_MSG("STARTING WIFI AP: ssid=%s, ok=%d\n", wifiName, WiFi.softAP(wifiName, wifiPsw));
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.softAPIP().toString().c_str());
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
dnsServer.start(53, "*", apIP);
@@ -184,14 +192,13 @@ bool initWifi(bool forceSoftAP)
getMacAddr(dmac);
sprintf(ourHost, "Meshtastic-%02x%02x", dmac[4], dmac[5]);
Serial.println(ourHost);
WiFi.mode(WIFI_MODE_STA);
WiFi.setHostname(ourHost);
WiFi.onEvent(WiFiEvent);
// esp_wifi_set_ps(WIFI_PS_NONE); // Disable power saving
// WiFiEventId_t eventID = WiFi.onEvent(
// This is needed to improve performance.
esp_wifi_set_ps(WIFI_PS_NONE); // Disable radio power saving
WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
Serial.print("\nWiFi lost connection. Reason: ");
@@ -250,7 +257,7 @@ static void WiFiEvent(WiFiEvent_t event)
DEBUG_MSG("Authentication mode of access point has changed\n");
break;
case SYSTEM_EVENT_STA_GOT_IP:
DEBUG_MSG("Obtained IP address: \n");
DEBUG_MSG("Obtained IP address: ");
Serial.println(WiFi.localIP());
onNetworkConnected();
break;
@@ -271,7 +278,7 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case SYSTEM_EVENT_AP_START:
DEBUG_MSG("WiFi access point started\n");
Serial.println(WiFi.softAPIP());
onNetworkConnected();
break;
case SYSTEM_EVENT_AP_STOP:
@@ -305,7 +312,7 @@ static void WiFiEvent(WiFiEvent_t event)
DEBUG_MSG("Ethernet disconnected\n");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
DEBUG_MSG("Obtained IP address\n");
DEBUG_MSG("Obtained IP address (SYSTEM_EVENT_ETH_GOT_IP)\n");
break;
default:
break;
@@ -314,7 +321,7 @@ static void WiFiEvent(WiFiEvent_t event)
void handleDNSResponse()
{
if (radioConfig.preferences.wifi_ap_mode) {
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
dnsServer.processNextRequest();
}
}

View File

@@ -21,4 +21,3 @@ void handleDNSResponse();
bool isSoftAPForced();
uint8_t getWifiDisconnectReason();

View File

@@ -68,9 +68,22 @@ 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";
if (*radioConfig.preferences.mqtt_server)
if (*radioConfig.preferences.mqtt_server) {
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
mqttUsername = radioConfig.preferences.mqtt_username; //do not use the hardcoded credentials for a custom mqtt server
mqttPassword = radioConfig.preferences.mqtt_password;
} else {
//we are using the default server. Use the hardcoded credentials by default, but allow overriding
if (*radioConfig.preferences.mqtt_username && radioConfig.preferences.mqtt_username[0] != '\0') {
mqttUsername = radioConfig.preferences.mqtt_username;
}
if (*radioConfig.preferences.mqtt_password && radioConfig.preferences.mqtt_password[0] != '\0') {
mqttPassword = radioConfig.preferences.mqtt_password;
}
}
String server = String(serverAddr);
int delimIndex = server.indexOf(':');
@@ -82,9 +95,9 @@ void MQTT::reconnect()
}
pubSub.setServer(serverAddr, serverPort);
DEBUG_MSG("Connecting to MQTT server %s, port: %d\n", serverAddr, serverPort);
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, "meshdev", "large4cats", myStatus.c_str(), 1, true, "offline");
bool connected = pubSub.connect(owner.id, mqttUsername, mqttPassword, myStatus.c_str(), 1, true, "offline");
if (connected) {
DEBUG_MSG("MQTT connected\n");
enabled = true; // Start running background process again

View File

@@ -11,7 +11,6 @@
#include "services/gap/ble_svc_gap.h"
#include "services/gatt/ble_svc_gatt.h"
#include "sleep.h"
#include <Arduino.h>
#include <WiFi.h>
#ifndef NO_ESP32
@@ -557,7 +556,7 @@ void setBluetoothEnable(bool on)
bluetoothOn = on;
if (on) {
if (!initWifi(0)) // if we are using wifi, don't turn on bluetooth also
if (! isWifiAvailable() )
{
Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap());
// ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );

View File

@@ -1,6 +1,5 @@
#pragma once
#include <Arduino.h>
#include <functional>
/// We only allow one BLE connection at a time

View File

@@ -3,7 +3,6 @@
#include "configuration.h"
#include "nimble/BluetoothUtil.h"
#include "nimble/NimbleDefs.h"
#include <Arduino.h>
// This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in
// proccess at once

View File

@@ -11,7 +11,6 @@
#include "host/ble_uuid.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include <Arduino.h>
#ifdef __cplusplus
extern "C" {

View File

@@ -38,18 +38,13 @@ void __attribute__((noreturn)) __assert_func(const char *file, int line, const c
void getMacAddr(uint8_t *dmac)
{
ble_gap_addr_t addr;
if (sd_ble_gap_addr_get(&addr) == NRF_SUCCESS) {
memcpy(dmac, addr.addr, 6);
} else {
const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR;
dmac[5] = src[0];
dmac[4] = src[1];
dmac[3] = src[2];
dmac[2] = src[3];
dmac[1] = src[4];
dmac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack
}
const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR;
dmac[5] = src[0];
dmac[4] = src[1];
dmac[3] = src[2];
dmac[2] = src[3];
dmac[1] = src[4];
dmac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack
}
static void initBrownout()

View File

@@ -137,10 +137,15 @@ void AdminPlugin::handleSetOwner(const User &o)
strcpy(owner.id, o.id);
}
if (owner.is_licensed != o.is_licensed) {
changed = true;
changed = 1;
owner.is_licensed = o.is_licensed;
}
if ((!changed || o.team) && (owner.team != o.team)) {
changed = 1;
owner.team = o.team;
}
if (changed) // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner();
}

View File

@@ -44,7 +44,7 @@
*/
// Default configurations
#define EXT_NOTIFICATION_PLUGIN_OUTPUT 13
#define EXT_NOTIFICATION_PLUGIN_OUTPUT EXT_NOTIFY_OUT
#define EXT_NOTIFICATION_PLUGIN_OUTPUT_MS 1000
#define ASCII_BELL 0x07
@@ -84,21 +84,25 @@ int32_t ExternalNotificationPlugin::runOnce()
void ExternalNotificationPlugin::setExternalOn()
{
#ifdef EXT_NOTIFY_OUT
externalCurrentState = 1;
externalTurnedOn = millis();
digitalWrite((radioConfig.preferences.ext_notification_plugin_output ? radioConfig.preferences.ext_notification_plugin_output
: EXT_NOTIFICATION_PLUGIN_OUTPUT),
(radioConfig.preferences.ext_notification_plugin_active ? true : false));
#endif
}
void ExternalNotificationPlugin::setExternalOff()
{
#ifdef EXT_NOTIFY_OUT
externalCurrentState = 0;
digitalWrite((radioConfig.preferences.ext_notification_plugin_output ? radioConfig.preferences.ext_notification_plugin_output
: EXT_NOTIFICATION_PLUGIN_OUTPUT),
(radioConfig.preferences.ext_notification_plugin_active ? false : true));
#endif
}
// --------
@@ -111,6 +115,7 @@ ExternalNotificationPlugin::ExternalNotificationPlugin()
boundChannel = Channels::gpioChannel;
#ifndef NO_ESP32
#ifdef EXT_NOTIFY_OUT
/*
Uncomment the preferences below if you want to use the plugin
@@ -140,12 +145,14 @@ ExternalNotificationPlugin::ExternalNotificationPlugin()
DEBUG_MSG("External Notification Plugin Disabled\n");
enabled = false;
}
#endif
#endif
}
ProcessMessage ExternalNotificationPlugin::handleReceived(const MeshPacket &mp)
{
#ifndef NO_ESP32
#ifdef EXT_NOTIFY_OUT
if (radioConfig.preferences.ext_notification_plugin_enabled) {
@@ -173,6 +180,7 @@ ProcessMessage ExternalNotificationPlugin::handleReceived(const MeshPacket &mp)
} else {
DEBUG_MSG("External Notification Plugin Disabled\n");
}
#endif
#endif

View File

@@ -5,12 +5,11 @@
#include "plugins/RemoteHardwarePlugin.h"
#include "plugins/ReplyPlugin.h"
#include "plugins/TextMessagePlugin.h"
#include "plugins/SerialPlugin.h"
#include "plugins/TextMessagePlugin.h"
#include "plugins/RoutingPlugin.h"
#include "plugins/AdminPlugin.h"
#ifndef NO_ESP32
#include "plugins/SerialPlugin.h"
#include "plugins/esp32/SerialPlugin.h"
#include "plugins/esp32/EnvironmentalMeasurementPlugin.h"
#include "plugins/esp32/RangeTestPlugin.h"
#include "plugins/esp32/StoreForwardPlugin.h"

View File

@@ -1,9 +1,10 @@
#include "configuration.h"
#include "PositionPlugin.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "gps/GeoCoord.h"
PositionPlugin *positionPlugin;
@@ -18,6 +19,24 @@ bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, Position *pptr
{
auto p = *pptr;
// If inbound message is a replay (or spoof!) of our own messages, we shouldn't process
// (why use second-hand sources for our own data?)
// FIXME this can in fact happen with packets sent from EUD (src=RX_SRC_USER)
// to set fixed location, EUD-GPS location or just the time (see also issue #900)
if (nodeDB.getNodeNum() == getFrom(&mp)) {
DEBUG_MSG("Incoming update from MYSELF\n");
// DEBUG_MSG("Ignored an incoming update from MYSELF\n");
// return false;
}
// Log packet size and list of fields
DEBUG_MSG("POSITION node=%08x l=%d %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", getFrom(&mp), mp.decoded.payload.size,
p.latitude_i ? "LAT " : "", p.longitude_i ? "LON " : "", p.altitude ? "MSL " : "", p.altitude_hae ? "HAE " : "",
p.alt_geoid_sep ? "GEO " : "", p.PDOP ? "PDOP " : "", p.HDOP ? "HDOP " : "", p.VDOP ? "VDOP " : "",
p.sats_in_view ? "SIV " : "", p.fix_quality ? "FXQ " : "", p.fix_type ? "FXT " : "", p.pos_timestamp ? "PTS " : "",
p.time ? "TIME " : "", p.battery_level ? "BAT " : "");
if (p.time) {
struct timeval tv;
uint32_t secs = p.time;
@@ -38,7 +57,44 @@ MeshPacket *PositionPlugin::allocReply()
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
assert(node->has_position);
Position p = node->position;
// configuration of POSITION packet
// consider making this a function argument?
uint32_t pos_flags = radioConfig.preferences.position_flags;
// Populate a Position struct with ONLY the requested fields
Position p = Position_init_default; // Start with an empty structure
// lat/lon are unconditionally included - IF AVAILABLE!
p.latitude_i = node->position.latitude_i;
p.longitude_i = node->position.longitude_i;
p.time = node->position.time;
if (pos_flags & PositionFlags_POS_BATTERY)
p.battery_level = node->position.battery_level;
if (pos_flags & PositionFlags_POS_ALTITUDE) {
if (pos_flags & PositionFlags_POS_ALT_MSL)
p.altitude = node->position.altitude;
else
p.altitude_hae = node->position.altitude_hae;
if (pos_flags & PositionFlags_POS_GEO_SEP)
p.alt_geoid_sep = node->position.alt_geoid_sep;
}
if (pos_flags & PositionFlags_POS_DOP) {
if (pos_flags & PositionFlags_POS_HVDOP) {
p.HDOP = node->position.HDOP;
p.VDOP = node->position.VDOP;
} else
p.PDOP = node->position.PDOP;
}
if (pos_flags & PositionFlags_POS_SATINVIEW)
p.sats_in_view = node->position.sats_in_view;
if (pos_flags & PositionFlags_POS_TIMESTAMP)
p.pos_timestamp = node->position.pos_timestamp;
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS to include the time, so that gpsless
@@ -69,18 +125,63 @@ void PositionPlugin::sendOurPosition(NodeNum dest, bool wantReplies)
int32_t PositionPlugin::runOnce()
{
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
//radioConfig.preferences.position_broadcast_smart = true;
// We limit our GPS broadcasts to a max rate
uint32_t now = millis();
if (lastGpsSend == 0 || now - lastGpsSend >= getPref_position_broadcast_secs() * 1000) {
lastGpsSend = now;
lastGpsLatitude = node->position.latitude_i;
lastGpsLongitude = node->position.longitude_i;
// If we changed channels, ask everyone else for their latest info
bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration;
DEBUG_MSG("Sending position to mesh (wantReplies=%d)\n", requestReplies);
DEBUG_MSG("Sending pos@%x:6 to mesh (wantReplies=%d)\n", node->position.pos_timestamp, requestReplies);
sendOurPosition(NODENUM_BROADCAST, requestReplies);
} else if (radioConfig.preferences.position_broadcast_smart == true) {
NodeInfo *node = service.refreshMyNodeInfo(); // should guarantee there is now a position
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
// The minimum distance to travel before we are able to send a new position packet.
const uint32_t distanceTravelMinimum = 30;
// The minimum time that would pass before we are able to send a new position packet.
const uint32_t timeTravelMinimum = 30;
// Determine the distance in meters between two points on the globe
float distance = GeoCoord::latLongToMeter(lastGpsLatitude * 1e-7, lastGpsLongitude * 1e-7,
node->position.latitude_i * 1e-7, node->position.longitude_i * 1e-7);
// Yes, this has a bunch of magic numbers. Sorry. This is to make the scale non-linear.
const float distanceTravelMath = 1203 / (sqrt( pow(myNodeInfo.bitrate, 1.5) / 1.1 ) ) ;
uint32_t distanceTravel = (distanceTravelMath >= distanceTravelMinimum) ? distanceTravelMath : distanceTravelMinimum;
// Yes, this has a bunch of magic numbers. Sorry.
uint32_t timeTravel = ((1500 / myNodeInfo.bitrate) >= timeTravelMinimum) ? (1500 / myNodeInfo.bitrate) : timeTravelMinimum;
// If the distance traveled since the last update is greater than 100 meters
// and it's been at least 60 seconds since the last update
if ((abs(distance) >= distanceTravel) &&
(now - lastGpsSend >= timeTravel * 1000)
) {
bool requestReplies = currentGeneration != radioGeneration;
currentGeneration = radioGeneration;
DEBUG_MSG("Sending smart pos@%x:6 to mesh (wantReplies=%d, dt=%d, tt=%d)\n", node->position.pos_timestamp, requestReplies, distanceTravel, timeTravel);
sendOurPosition(NODENUM_BROADCAST, requestReplies);
/* Update lastGpsSend to now. This means if the device is stationary, then
getPref_position_broadcast_secs will still apply.
*/
lastGpsSend = now;
}
}
}
return 5000; // to save power only wake for our callback occasionally

View File

@@ -13,6 +13,10 @@ class PositionPlugin : public ProtobufPlugin<Position>, private concurrency::OST
/// We limit our GPS broadcasts to a max rate
uint32_t lastGpsSend = 0;
// Store the latest good lat / long
int32_t lastGpsLatitude = 0;
int32_t lastGpsLongitude = 0;
/// We force a rebroadcast if the radio settings change
uint32_t currentGeneration = 0;

View File

@@ -1,20 +1,23 @@
#include "EnvironmentalMeasurementPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "main.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include <DHT.h>
#include <DS18B20.h>
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include <OneWire.h>
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 // Some sensors (the DHT11) have a minimum required duration between read attempts
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
#ifdef HAS_EINK
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16
@@ -31,123 +34,136 @@
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
int32_t EnvironmentalMeasurementPlugin::runOnce() {
int32_t EnvironmentalMeasurementPlugin::runOnce()
{
#ifndef NO_ESP32 // this only works on ESP32 devices
/*
Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI.
*/
/*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5;
radioConfig.preferences.environmental_measurement_plugin_update_interval = 30;
radioConfig.preferences.environmental_measurement_plugin_update_interval = 600;
radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60;
radioConfig.preferences.environmental_measurement_plugin_display_farenheit = true;
radioConfig.preferences.environmental_measurement_plugin_display_farenheit = false;
radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13;
radioConfig.preferences.environmental_measurement_plugin_sensor_type = RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11;*/
radioConfig.preferences.environmental_measurement_plugin_sensor_type =
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20;
*/
if (! (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled ||
radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) {
// If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return (INT32_MAX);
}
if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup
firstTime = 0;
if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) {
DEBUG_MSG("EnvironmentalMeasurement: Initializing\n");
// it's possible to have this plugin enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
switch(radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin,DHT11);
this->dht->begin();
this->dht->read();
DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n",radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin, DHT11);
this->dht->begin();
this->dht->read();
DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n",
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
oneWire = new OneWire(radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
ds18b20 = new DS18B20(oneWire);
this->ds18b20->begin();
this->ds18b20->setResolution(12);
this->ds18b20->requestTemperatures();
DEBUG_MSG("EnvironmentalMeasurement: Opened DS18B20 on pin: %d\n",
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break;
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break;
}
// begin reading measurements from the sensor
// DHT have a max read-rate of 1HZ, so we should wait at least 1 second
// after initializing the sensor before we try to read from it.
// returning the interval here means that the next time OSThread
// calls our plugin, we'll run the other branch of this if statement
// and actually do a "sendOurEnvironmentalMeasurement()"
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
return (INT32_MAX);
}
else {
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
} else {
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) {
// if we somehow got to a second run of this plugin with measurement disabled, then just wait forever
// I can't imagine we'd ever get here though.
return (INT32_MAX);
}
// this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval
if(sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold)
{
if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0 ) {
DEBUG_MSG(
"EnvironmentalMeasurement: TEMPORARILY DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in %d seconds\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold,
radioConfig.preferences.environmental_measurement_plugin_recovery_interval);
sensor_read_error_count = 0;
return(radioConfig.preferences.environmental_measurement_plugin_recovery_interval*1000);
if (sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold) {
if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0) {
DEBUG_MSG("EnvironmentalMeasurement: TEMPORARILY DISABLED; The "
"environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in "
"%d seconds\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold,
radioConfig.preferences.environmental_measurement_plugin_recovery_interval);
sensor_read_error_count = 0;
return (radioConfig.preferences.environmental_measurement_plugin_recovery_interval * 1000);
}
DEBUG_MSG(
"EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Reads will not be retried until after device reset\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold);
return(INT32_MAX);
DEBUG_MSG("EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has "
"been exceed: %d. Reads will not be retried until after device reset\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold);
return (INT32_MAX);
} else if (sensor_read_error_count > 0) {
DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count, sensor_read_error_count, sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold -
sensor_read_error_count);
}
else if (sensor_read_error_count > 0){
DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold-sensor_read_error_count);
}
if (!sendOurEnvironmentalMeasurement() ){
// if we failed to read the sensor, then try again
if (!sendOurEnvironmentalMeasurement()) {
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
// return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
}
}
// The return of runOnce is an int32 representing the desired number of
// miliseconds until the function should be called again by the
// The return of runOnce is an int32 representing the desired number of
// miliseconds until the function should be called again by the
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return(radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000);
return (radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000);
#endif
}
bool EnvironmentalMeasurementPlugin::wantUIFrame() {
bool EnvironmentalMeasurementPlugin::wantUIFrame()
{
return radioConfig.preferences.environmental_measurement_plugin_screen_enabled;
}
String GetSenderName(const MeshPacket &mp) {
String GetSenderName(const MeshPacket &mp)
{
String sender;
auto node = nodeDB.getNode(getFrom(&mp));
if (node){
if (node) {
sender = node->user.short_name;
}
else {
} else {
sender = "UNK";
}
return sender;
}
uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) {
uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp)
{
uint32_t now = getTime();
uint32_t last_seen = mp->rx_time;
@@ -156,15 +172,13 @@ uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) {
delta = 0;
return delta;
}
float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c) {
return (c*9)/5 + 32;
float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c)
{
return (c * 9) / 5 + 32;
}
void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_LEFT);
@@ -173,21 +187,16 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
if (lastMeasurementPacket == nullptr) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement");
//DEBUG_MSG("EnvironmentalMeasurement: No previous measurement; not drawing frame\n");
return;
}
EnvironmentalMeasurement lastMeasurement;
uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket);
String lastSender = GetSenderName(*lastMeasurementPacket);
auto &p = lastMeasurementPacket->decoded;
if (!pb_decode_from_bytes(p.payload.bytes,
p.payload.size,
EnvironmentalMeasurement_fields,
&lastMeasurement)) {
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, EnvironmentalMeasurement_fields, &lastMeasurement)) {
display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("EnvironmentalMeasurement: unable to decode last packet");
@@ -195,20 +204,23 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
}
display->setFont(FONT_SMALL);
String last_temp = String(lastMeasurement.temperature,0) +"°C";
if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit){
last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature),0) +"°F";;
String last_temp = String(lastMeasurement.temperature, 0) + "°C";
if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit) {
last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature), 0) + "°F";
;
}
display->drawString(x, y += fontHeight(FONT_MEDIUM), lastSender+": "+last_temp +"/"+ String(lastMeasurement.relative_humidity,0) + "%("+String(agoSecs)+"s)");
display->drawString(x, y += fontHeight(FONT_MEDIUM),
lastSender + ": " + last_temp + "/" + String(lastMeasurement.relative_humidity, 0) + "%(" +
String(agoSecs) + "s)");
}
bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p)
{
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
return false;
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled ||
radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) {
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
return false;
}
String sender = GetSenderName(mp);
@@ -230,13 +242,32 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("EnvironmentalMeasurement: Read data\n");
if (!this->dht->read(true)){
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
if (!this->dht->read(true)) {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
break;
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
if (this->ds18b20->isConversionComplete()) {
m.temperature = this->ds18b20->getTempC();
m.relative_humidity = 0; // This sensor is temperature only
this->ds18b20->requestTemperatures();
break;
} else {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return false;
}
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity);
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature);
@@ -250,4 +281,3 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
service.sendToMesh(p);
return true;
}

View File

@@ -1,15 +1,20 @@
#pragma once
#include "ProtobufPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include "ProtobufPlugin.h"
#include <DHT.h>
#include <DS18B20.h>
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
#include <DHT.h>
#include <OneWire.h>
class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public ProtobufPlugin<EnvironmentalMeasurement>
{
public:
EnvironmentalMeasurementPlugin(): concurrency::OSThread("EnvironmentalMeasurementPlugin"), ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg) {
lastMeasurementPacket = nullptr;
EnvironmentalMeasurementPlugin()
: concurrency::OSThread("EnvironmentalMeasurementPlugin"),
ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg)
{
lastMeasurementPacket = nullptr;
}
virtual bool wantUIFrame();
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@@ -24,11 +29,13 @@ class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public Pro
* Send our EnvironmentalMeasurement into the mesh
*/
bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
float CelsiusToFarenheit(float c);
bool firstTime = 1;
DHT* dht;
DHT *dht;
OneWire *oneWire;
DS18B20 *ds18b20;
const MeshPacket *lastMeasurementPacket;
uint32_t sensor_read_error_count = 0;
};

View File

@@ -48,9 +48,6 @@ int32_t RangeTestPlugin::runOnce()
if (radioConfig.preferences.range_test_plugin_enabled) {
if (firstTime) {
// Interface with the serial peripheral from in here.
rangeTestPluginRadio = new RangeTestPluginRadio();
firstTime = 0;
@@ -130,27 +127,21 @@ ProcessMessage RangeTestPluginRadio::handleReceived(const MeshPacket &mp)
if (radioConfig.preferences.range_test_plugin_enabled) {
auto &p = mp.decoded;
// DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
// nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes);
/*
auto &p = mp.decoded;
DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes);
*/
if (getFrom(&mp) != nodeDB.getNodeNum()) {
// DEBUG_MSG("* * Message came from the mesh\n");
// Serial2.println("* * Message came from the mesh");
// Serial2.printf("%s", p.payload.bytes);
/*
*/
NodeInfo *n = nodeDB.getNode(getFrom(&mp));
if (radioConfig.preferences.range_test_plugin_save) {
appendFile(mp);
}
/*
NodeInfo *n = nodeDB.getNode(getFrom(&mp));
DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("p.payload.bytes \"%s\"\n", p.payload.bytes);
DEBUG_MSG("p.payload.size %d\n", p.payload.size);
@@ -158,12 +149,12 @@ ProcessMessage RangeTestPluginRadio::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);
// DEBUG_MSG("n->user.macaddr %X\n", n->user.macaddr);
DEBUG_MSG("n->user.macaddr %X\n", n->user.macaddr);
DEBUG_MSG("n->has_position %d\n", n->has_position);
DEBUG_MSG("n->position.latitude_i %d\n", n->position.latitude_i);
DEBUG_MSG("n->position.longitude_i %d\n", n->position.longitude_i);
@@ -174,6 +165,7 @@ ProcessMessage RangeTestPluginRadio::handleReceived(const MeshPacket &mp)
DEBUG_MSG("gpsStatus->getHasLock() %d\n", gpsStatus->getHasLock());
DEBUG_MSG("gpsStatus->getDOP() %d\n", gpsStatus->getDOP());
DEBUG_MSG("-----------------------------------------\n");
*/
}
} else {
@@ -237,7 +229,7 @@ bool RangeTestPluginRadio::appendFile(const MeshPacket &mp)
// Print the CSV header
if (fileToWrite.println(
"time,from,sender name,sender lat,sender long,rx lat,rx long,rx snr,rx elevation,distance,payload")) {
"time,from,sender name,sender lat,sender long,rx lat,rx long,rx elevation,rx snr,distance,hop limit,payload")) {
DEBUG_MSG("File was written\n");
} else {
DEBUG_MSG("File write failed\n");
@@ -257,9 +249,6 @@ bool RangeTestPluginRadio::appendFile(const MeshPacket &mp)
struct timeval tv;
if (!gettimeofday(&tv, NULL)) {
long hms = tv.tv_sec % SEC_PER_DAY;
// hms += tz.tz_dsttime * SEC_PER_HOUR;
// hms -= tz.tz_minuteswest * SEC_PER_MIN;
// mod `hms` to ensure in positive range of [0...SEC_PER_DAY)
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
// Tear apart hms into h:m:s
@@ -290,9 +279,10 @@ bool RangeTestPluginRadio::appendFile(const MeshPacket &mp)
fileToAppend.printf("0,");
}
fileToAppend.printf("%d,", mp.hop_limit); // Packet Hop Limit
// TODO: If quotes are found in the payload, it has to be escaped.
fileToAppend.printf("\"%s\"\n", p.payload.bytes);
fileToAppend.close();
return 1;

View File

@@ -50,4 +50,4 @@ class SerialPluginRadio : public SinglePortPlugin
virtual ProcessMessage handleReceived(const MeshPacket &mp);
};
extern SerialPluginRadio *serialPluginRadio;
extern SerialPluginRadio *serialPluginRadio;

View File

@@ -5,14 +5,12 @@
#include "Router.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
#include "mesh/generated/storeforward.pb.h"
#include "plugins/PluginDev.h"
#include <Arduino.h>
#include <iterator>
#include <map>
#define STOREFORWARD_MAX_PACKETS 0
#define STOREFORWARD_SEND_HISTORY_PERIOD 10 * 60
#define STOREFORWARD_SEND_HISTORY_MAX 0
StoreForwardPlugin *storeForwardPlugin;
int32_t StoreForwardPlugin::runOnce()
@@ -23,22 +21,30 @@ int32_t StoreForwardPlugin::runOnce()
if (radioConfig.preferences.store_forward_plugin_enabled) {
if (radioConfig.preferences.is_router) {
// Maybe some cleanup functions?
this->historyReport();
return (60 * 1000);
if (this->busy) {
// Send out the message queue.
// DEBUG_MSG("--- --- --- In busy loop 1 %d\n", this->packetHistoryTXQueue_index);
storeForwardPlugin->sendPayload(this->busyTo, this->packetHistoryTXQueue_index);
if (this->packetHistoryTXQueue_index == packetHistoryTXQueue_size) {
strcpy(this->routerMessage, "** S&F - Done");
storeForwardPlugin->sendMessage(this->busyTo, this->routerMessage);
// DEBUG_MSG("--- --- --- In busy loop - Done \n");
this->packetHistoryTXQueue_index = 0;
this->busy = false;
} else {
this->packetHistoryTXQueue_index++;
}
}
DEBUG_MSG("SF myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
return (this->packetTimeMax);
} else {
/*
* If the plugin is turned on and is_router is not enabled, then we'll send a heartbeat every
* few minutes.
*
* This behavior is expected to change. It's only here until we come up with something better.
*/
DEBUG_MSG("Store & Forward Plugin - Disabled (is_router = false)\n");
DEBUG_MSG("Store & Forward Plugin - Sending heartbeat\n");
storeForwardPlugin->sendPayload();
return (4 * 60 * 1000);
return (INT32_MAX);
}
} else {
@@ -51,6 +57,9 @@ int32_t StoreForwardPlugin::runOnce()
return (INT32_MAX);
}
/*
Create our data structure in the PSRAM.
*/
void StoreForwardPlugin::populatePSRAM()
{
/*
@@ -65,12 +74,16 @@ void StoreForwardPlugin::populatePSRAM()
DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram());
// Use a maximum of half the available PSRAM unless otherwise specified.
uint32_t numberOfPackets =
STOREFORWARD_MAX_PACKETS ? STOREFORWARD_MAX_PACKETS : ((ESP.getPsramSize() / 2) / sizeof(PacketHistoryStruct));
this->packetHistoryTXQueue =
static_cast<PacketHistoryStruct *>(ps_calloc(this->historyReturnMax, sizeof(PacketHistoryStruct)));
/* Use a maximum of 2/3 the available PSRAM unless otherwise specified.
Note: This needs to be done after every thing that would use PSRAM
*/
uint32_t numberOfPackets = (this->records ? this->records : (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct)));
// this->packetHistory = (PacketHistoryStruct *)ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct));
this->packetHistory = static_cast<PacketHistoryStruct *>(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct)));
DEBUG_MSG("After PSRAM initilization:\n");
DEBUG_MSG(" Total heap: %d\n", ESP.getHeapSize());
@@ -78,34 +91,13 @@ void StoreForwardPlugin::populatePSRAM()
DEBUG_MSG(" Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG(" Free PSRAM: %d\n", ESP.getFreePsram());
DEBUG_MSG("Store and Forward Stats:\n");
DEBUG_MSG(" numberOfPackets - %u\n", numberOfPackets);
}
// We saw a node.
void StoreForwardPlugin::sawNode(uint32_t whoWeSaw, uint32_t sawSecAgo)
{
if (radioConfig.preferences.is_router) {
// If node has been away for more than 10 minutes, send the node the last 10 minutes of
// messages
if (sawSecAgo > STOREFORWARD_SEND_HISTORY_PERIOD) {
// Node has been away for a while.
storeForwardPlugin->historySend(STOREFORWARD_SEND_HISTORY_PERIOD, whoWeSaw);
}
}
DEBUG_MSG(" numberOfPackets for packetHistory - %u\n", numberOfPackets);
}
void StoreForwardPlugin::historyReport()
{
DEBUG_MSG("Iterating through the message history...\n");
DEBUG_MSG("Message history contains %u records\n", this->packetHistoryCurrent);
uint32_t startTimer = millis();
for (int i = 0; i < this->packetHistoryCurrent; i++) {
if (this->packetHistory[i].time) {
// DEBUG_MSG("... time-%u to-0x%08x\n", this->packetHistory[i].time, this->packetHistory[i].to & 0xffffffff);
}
}
DEBUG_MSG("StoreForwardPlugin::historyReport runtime - %u ms\n", millis() - startTimer);
}
/*
@@ -113,31 +105,79 @@ void StoreForwardPlugin::historyReport()
*/
void StoreForwardPlugin::historySend(uint32_t msAgo, uint32_t to)
{
// Send "Welcome back"
this->sendPayloadWelcome(to, false);
for (int i = 0; i < this->packetHistoryCurrent; i++) {
if (this->packetHistory[i].time) {
// DEBUG_MSG("... time-%u to-0x%08x\n", this->packetHistory[i].time, this->packetHistory[i].to & 0xffffffff);
}
// uint32_t packetsSent = 0;
uint32_t queueSize = storeForwardPlugin->historyQueueCreate(msAgo, to);
if (queueSize) {
snprintf(this->routerMessage, 80, "** S&F - Sending %d message(s)", queueSize);
storeForwardPlugin->sendMessage(to, this->routerMessage);
this->busy = true; // runOnce() will pickup the next steps once busy = true.
this->busyTo = to;
} else {
strcpy(this->routerMessage, "** S&F - No history to send");
storeForwardPlugin->sendMessage(to, this->routerMessage);
}
}
void StoreForwardPlugin::historyAdd(const MeshPacket *mp)
uint32_t StoreForwardPlugin::historyQueueCreate(uint32_t msAgo, uint32_t to)
{
auto &p = mp;
static uint8_t bytes[MAX_RHPACKETLEN];
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
assert(numbytes <= MAX_RHPACKETLEN);
// uint32_t packetHistoryTXQueueIndex = 0;
DEBUG_MSG("MP numbytes %u\n", numbytes);
this->packetHistoryTXQueue_size = 0;
for (int i = 0; i < this->packetHistoryCurrent; i++) {
/*
DEBUG_MSG("SF historyQueueCreate\n");
DEBUG_MSG("SF historyQueueCreate - time %d\n", this->packetHistory[i].time);
DEBUG_MSG("SF historyQueueCreate - millis %d\n", millis());
DEBUG_MSG("SF historyQueueCreate - math %d\n", (millis() - msAgo));
*/
if (this->packetHistory[i].time && (this->packetHistory[i].time < (millis() - msAgo))) {
DEBUG_MSG("SF historyQueueCreate - Time matches - ok\n");
/*
Copy the messages that were received by the router in the last msAgo
to the packetHistoryTXQueue structure.
TODO: The condition (this->packetHistory[i].to & NODENUM_BROADCAST) == to) is not tested since
I don't have an easy way to target a specific user. Will need to do this soon.
*/
if ((this->packetHistory[i].to & NODENUM_BROADCAST) == NODENUM_BROADCAST ||
((this->packetHistory[i].to & NODENUM_BROADCAST) == to)) {
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].time = this->packetHistory[i].time;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].to = this->packetHistory[i].to;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].from = this->packetHistory[i].from;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].channel = this->packetHistory[i].channel;
this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload_size = this->packetHistory[i].payload_size;
memcpy(this->packetHistoryTXQueue[this->packetHistoryTXQueue_size].payload, this->packetHistory[i].payload,
Constants_DATA_PAYLOAD_LEN);
this->packetHistoryTXQueue_size++;
DEBUG_MSG("PacketHistoryStruct time=%d\n", this->packetHistory[i].time);
DEBUG_MSG("PacketHistoryStruct msg=%.*s\n", this->packetHistory[i].payload);
// DEBUG_MSG("PacketHistoryStruct msg=%.*s\n", this->packetHistoryTXQueue[packetHistoryTXQueueIndex].payload);
}
}
}
return this->packetHistoryTXQueue_size;
}
void StoreForwardPlugin::historyAdd(const MeshPacket &mp)
{
auto &p = mp.decoded;
// destination, source, bytes
// memcpy(p->encrypted.bytes, bytes, numbytes);
memcpy(this->packetHistory[this->packetHistoryCurrent].bytes, bytes, MAX_RHPACKETLEN);
this->packetHistory[this->packetHistoryCurrent].time = millis();
this->packetHistory[this->packetHistoryCurrent].to = mp->to;
this->packetHistory[this->packetHistoryCurrent].to = mp.to;
this->packetHistory[this->packetHistoryCurrent].channel = mp.channel;
this->packetHistory[this->packetHistoryCurrent].from = mp.from;
this->packetHistory[this->packetHistoryCurrent].payload_size = p.payload.size;
memcpy(this->packetHistory[this->packetHistoryCurrent].payload, p.payload.bytes, Constants_DATA_PAYLOAD_LEN);
this->packetHistoryCurrent++;
}
@@ -147,48 +187,47 @@ MeshPacket *StoreForwardPlugin::allocReply()
return reply;
}
void StoreForwardPlugin::sendPayload(NodeNum dest, bool wantReplies)
void StoreForwardPlugin::sendPayload(NodeNum dest, uint32_t packetHistory_index)
{
DEBUG_MSG("Sending S&F Payload\n");
MeshPacket *p = allocReply();
p->to = dest;
p->decoded.want_response = wantReplies;
p->from = this->packetHistoryTXQueue[packetHistory_index].from;
p->channel = this->packetHistoryTXQueue[packetHistory_index].channel;
p->want_ack = true;
// Let's assume that if the router received the S&F request that the client is in range.
// TODO: Make this configurable.
p->want_ack = false;
static char heartbeatString[20];
snprintf(heartbeatString, sizeof(heartbeatString), "1");
p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, "1", 1);
p->decoded.payload.size =
this->packetHistoryTXQueue[packetHistory_index].payload_size; // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, this->packetHistoryTXQueue[packetHistory_index].payload,
this->packetHistoryTXQueue[packetHistory_index].payload_size);
service.sendToMesh(p);
}
void StoreForwardPlugin::sendPayloadWelcome(NodeNum dest, bool wantReplies)
void StoreForwardPlugin::sendMessage(NodeNum dest, char *str)
{
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("Sending S&F Welcome Message\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
DEBUG_MSG("*********************************\n");
MeshPacket *p = allocReply();
p->to = dest;
p->decoded.want_response = wantReplies;
p->want_ack = true;
// FIXME - Determine if the delayed packet is broadcast or delayed. For now, assume
// everything is broadcast.
p->delayed = MeshPacket_Delayed_DELAYED_BROADCAST;
p->decoded.portnum = PortNum_TEXT_MESSAGE_APP;
// Let's assume that if the router received the S&F request that the client is in range.
// TODO: Make this configurable.
p->want_ack = false;
static char heartbeatString[80];
snprintf(heartbeatString, sizeof(heartbeatString), "Welcome back to the mesh. We have not seen you in x minutes!");
p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size);
p->decoded.payload.size = strlen(str); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, str, strlen(str));
service.sendToMesh(p);
// HardwareMessage_init_default
}
ProcessMessage StoreForwardPlugin::handleReceived(const MeshPacket &mp)
@@ -196,15 +235,38 @@ ProcessMessage StoreForwardPlugin::handleReceived(const MeshPacket &mp)
#ifndef NO_ESP32
if (radioConfig.preferences.store_forward_plugin_enabled) {
DEBUG_MSG("--- S&F Received something\n");
auto &p = mp.decoded;
// The router node should not be sending messages as a client.
if (getFrom(&mp) != nodeDB.getNodeNum()) {
printPacket("----- PACKET FROM RADIO -----", &mp);
// uint32_t sawTime = storeForwardPlugin->sawNode(getFrom(&mp) & 0xffffffff);
// DEBUG_MSG("We last saw this node (%u), %u sec ago\n", mp.from & 0xffffffff, (millis() - sawTime) / 1000);
DEBUG_MSG(" -------------- ");
if (mp.decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
DEBUG_MSG("Packet came from - PortNum_TEXT_MESSAGE_APP\n");
storeForwardPlugin->historyAdd(&mp);
if ((p.payload.bytes[0] == 'S') && (p.payload.bytes[1] == 'F') && (p.payload.bytes[2] == 0x00)) {
DEBUG_MSG("--- --- --- Request to send\n");
// Send the last 60 minutes of messages.
if (this->busy) {
strcpy(this->routerMessage, "** S&F - Busy. Try again shortly.");
storeForwardPlugin->sendMessage(getFrom(&mp), this->routerMessage);
} else {
storeForwardPlugin->historySend(1000 * 60, getFrom(&mp));
}
} else if ((p.payload.bytes[0] == 'S') && (p.payload.bytes[1] == 'F') && (p.payload.bytes[2] == 'm') &&
(p.payload.bytes[3] == 0x00)) {
strcpy(this->routerMessage, "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789012345678901234567890123456789"
"01234567890123456789012345678901234567890123456789012345678901234567890123456");
storeForwardPlugin->sendMessage(getFrom(&mp), this->routerMessage);
} else {
storeForwardPlugin->historyAdd(mp);
}
} else if (mp.decoded.portnum == PortNum_STORE_FORWARD_APP) {
} else {
DEBUG_MSG("Packet came from an unknown port %u\n", mp.decoded.portnum);
@@ -220,22 +282,107 @@ ProcessMessage StoreForwardPlugin::handleReceived(const MeshPacket &mp)
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
}
ProcessMessage StoreForwardPlugin::handleReceivedProtobuf(const MeshPacket &mp, StoreAndForward *p)
{
if (!radioConfig.preferences.store_forward_plugin_enabled) {
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
return ProcessMessage::CONTINUE;
}
if (mp.decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
DEBUG_MSG("Packet came from an PortNum_TEXT_MESSAGE_APP port %u\n", mp.decoded.portnum);
return ProcessMessage::CONTINUE;
} else if (mp.decoded.portnum == PortNum_STORE_FORWARD_APP) {
DEBUG_MSG("Packet came from an PortNum_STORE_FORWARD_APP port %u\n", mp.decoded.portnum);
} else {
DEBUG_MSG("Packet came from an UNKNOWN port %u\n", mp.decoded.portnum);
return ProcessMessage::CONTINUE;
}
switch (p->rr) {
case StoreAndForward_RequestResponse_CLIENT_ERROR:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_CLIENT_ERROR\n");
break;
case StoreAndForward_RequestResponse_CLIENT_HISTORY:
DEBUG_MSG("StoreAndForward_RequestResponse_CLIENT_HISTORY\n");
// Send the last 60 minutes of messages.
if (this->busy) {
strcpy(this->routerMessage, "** S&F - Busy. Try again shortly.");
storeForwardPlugin->sendMessage(getFrom(&mp), this->routerMessage);
} else {
storeForwardPlugin->historySend(1000 * 60, getFrom(&mp));
}
break;
case StoreAndForward_RequestResponse_CLIENT_PING:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_CLIENT_PING\n");
break;
case StoreAndForward_RequestResponse_CLIENT_PONG:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_CLIENT_PONG\n");
break;
case StoreAndForward_RequestResponse_CLIENT_STATS:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_CLIENT_STATS\n");
break;
case StoreAndForward_RequestResponse_ROUTER_BUSY:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_BUSY\n");
break;
case StoreAndForward_RequestResponse_ROUTER_ERROR:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_ERROR\n");
break;
case StoreAndForward_RequestResponse_ROUTER_HEARTBEAT:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_HEARTBEAT\n");
break;
case StoreAndForward_RequestResponse_ROUTER_PING:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_PING\n");
break;
case StoreAndForward_RequestResponse_ROUTER_PONG:
// Do nothing
DEBUG_MSG("StoreAndForward_RequestResponse_ROUTER_PONG\n");
break;
default:
assert(0); // unexpected state - FIXME, make an error code and reboot
}
return ProcessMessage::STOP; // There's no need for others to look at this message.
}
StoreForwardPlugin::StoreForwardPlugin()
: SinglePortPlugin("StoreForwardPlugin", PortNum_STORE_FORWARD_APP), concurrency::OSThread("StoreForwardPlugin")
: SinglePortPlugin("StoreForwardPlugin", PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("StoreForwardPlugin")
{
#ifndef NO_ESP32
isPromiscuous = true; // Brown chicken brown cow
/*
Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI.
*/
if (StoreForward_Dev) {
/*
Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI.
*/
radioConfig.preferences.store_forward_plugin_enabled = 1;
radioConfig.preferences.is_router = 1;
radioConfig.preferences.is_always_powered = 1;
}
if (radioConfig.preferences.store_forward_plugin_enabled) {
@@ -248,7 +395,28 @@ StoreForwardPlugin::StoreForwardPlugin()
// Do the startup here
// Maximum number of records to return.
if (radioConfig.preferences.store_forward_plugin_history_return_max)
this->historyReturnMax = radioConfig.preferences.store_forward_plugin_history_return_max;
// Maximum time window for records to return (in minutes)
if (radioConfig.preferences.store_forward_plugin_history_return_window)
this->historyReturnWindow = radioConfig.preferences.store_forward_plugin_history_return_window;
// Maximum number of records to store in memory
if (radioConfig.preferences.store_forward_plugin_records)
this->records = radioConfig.preferences.store_forward_plugin_records;
// Maximum number of records to store in memory
if (radioConfig.preferences.store_forward_plugin_heartbeat)
this->heartbeat = radioConfig.preferences.store_forward_plugin_heartbeat;
// Popupate PSRAM with our data structures.
this->populatePSRAM();
// this->packetTimeMax = 2000;
// DEBUG_MSG("SF Time to Transmit maxPacketSize (%d bytes) %d ms\n", maxPacketSize, this->packetTimeMax);
} else {
DEBUG_MSG("Device has less than 1M of PSRAM free. Aborting startup.\n");
DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n");
@@ -265,4 +433,4 @@ StoreForwardPlugin::StoreForwardPlugin()
}
}
#endif
}
}

View File

@@ -2,6 +2,8 @@
#include "SinglePortPlugin.h"
#include "concurrency/OSThread.h"
#include "mesh/generated/storeforward.pb.h"
#include "configuration.h"
#include <Arduino.h>
#include <functional>
@@ -9,19 +11,31 @@
struct PacketHistoryStruct {
uint32_t time;
uint32_t to;
uint32_t from;
uint8_t channel;
bool ack;
uint8_t bytes[MAX_RHPACKETLEN];
uint8_t payload[Constants_DATA_PAYLOAD_LEN];
pb_size_t payload_size;
};
class StoreForwardPlugin : public SinglePortPlugin, private concurrency::OSThread
{
bool firstTime = 1;
// bool firstTime = 1;
bool busy = 0;
uint32_t busyTo;
char routerMessage[80];
uint32_t receivedRecord[50][2] = {{0}};
PacketHistoryStruct *packetHistory;
uint32_t packetHistoryCurrent = 0;
PacketHistoryStruct *packetHistoryTXQueue;
uint32_t packetHistoryTXQueue_size;
uint32_t packetHistoryTXQueue_index = 0;
uint32_t packetTimeMax = 2000;
public:
StoreForwardPlugin();
@@ -29,54 +43,43 @@ class StoreForwardPlugin : public SinglePortPlugin, private concurrency::OSThrea
Update our local reference of when we last saw that node.
@return 0 if we have never seen that node before otherwise return the last time we saw the node.
*/
void sawNode(uint32_t whoWeSaw, uint32_t sawSecAgo);
void historyAdd(const MeshPacket *mp);
void historyAdd(const MeshPacket &mp);
void historyReport();
void historySend(uint32_t msAgo, uint32_t to);
void populatePSRAM();
uint32_t historyQueueCreate(uint32_t msAgo, uint32_t to);
/**
* Send our payload into the mesh
*/
void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
void sendPayloadWelcome(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
void sendPayload(NodeNum dest = NODENUM_BROADCAST, uint32_t packetHistory_index = 0);
void sendMessage(NodeNum dest, char *str);
virtual MeshPacket *allocReply();
/*
Override the wantPortnum method.
*/
virtual bool wantPortnum(PortNum p) { return true; };
private:
// Nothing here
void populatePSRAM();
// S&F Defaults
uint32_t historyReturnMax = 250; // 250 records
uint32_t historyReturnWindow = 240; // 4 hours
uint32_t records = 0; // Calculated
bool heartbeat = false; // No heartbeat.
protected:
virtual int32_t runOnce();
/** Called to handle a particular incoming message
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for it
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
it
*/
virtual ProcessMessage handleReceived(const MeshPacket &mp);
virtual ProcessMessage handleReceivedProtobuf(const MeshPacket &mp, StoreAndForward *p);
};
extern StoreForwardPlugin *storeForwardPlugin;
/*
* Radio interface for StoreForwardPlugin
*
*/
/*
class StoreForwardPluginRadio : public SinglePortPlugin
{
// uint32_t lastRxID;
public:
StoreForwardPluginRadio() : SinglePortPlugin("StoreForwardPluginRadio", PortNum_STORE_FORWARD_APP) {}
// StoreForwardPluginRadio() : SinglePortPlugin("StoreForwardPluginRadio", PortNum_TEXT_MESSAGE_APP) {}
void sendPayloadHeartbeat(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
protected:
virtual MeshPacket *allocReply2();
};
extern StoreForwardPluginRadio *storeForwardPluginRadio;
*/
extern StoreForwardPlugin *storeForwardPlugin;

View File

@@ -14,6 +14,7 @@
#include "rom/rtc.h"
#include <driver/rtc_io.h>
#include <driver/uart.h>
#include "mesh/http/WiFiAPClient.h"
#include "nimble/BluetoothUtil.h"
@@ -48,6 +49,22 @@ RTC_DATA_ATTR int bootCount = 0;
void setCPUFast(bool on)
{
#ifndef NO_ESP32
if (isWifiAvailable()) {
/*
*
* There's a newly introduced bug in the espressif framework where WiFi is
* unstable when the frequency is less than 240mhz.
*
* This mostly impacts WiFi AP mode but we'll bump the frequency for
* all WiFi use cases.
* (Added: Dec 23, 2021 by Jm Casler)
*/
DEBUG_MSG("Setting CPU to 240mhz because WiFi is in use.\n");
setCpuFrequencyMhz(240);
return;
}
setCpuFrequencyMhz(on ? 240 : 80);
#endif
}

View File

@@ -58,11 +58,16 @@ extern "C" {
/*
* Buttons
*/
#define PIN_BUTTON1 11
#ifdef RAK_BASE_5005
#define PIN_BUTTON1 9 // Pin for button on E-ink button module or IO expansion
#define BUTTON_NEED_PULLUP
#endif
#define PIN_BUTTON2 12
#define PIN_BUTTON3 24
#define PIN_BUTTON4 25
/*
* Analog pins
*/
@@ -147,7 +152,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
SW1 <-> P0.01 (Arduino GPIO number 1)
A0 <-> P0.04/AIN2 (Arduino Analog A2
A1 <-> P0.31/AIN7 (Arduino Analog A7
SPI_CS <-> P0.26 (Arduino GPIO number 26)
SPI_CS <-> P0.26 (Arduino GPIO number 26)
*/
// RAK4630 LoRa module
@@ -169,8 +174,11 @@ static const uint8_t SCK = PIN_SPI_SCK;
// #define PIN_GPS_RESET (34)
#define PIN_GPS_EN (34)
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
#ifdef RAK_BASE_5005
#define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN PIN_SERIAL1_TX
#endif
// Battery
// The battery sense is hooked to pin A0 (5)

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 1
minor = 2
build = 46
build = 50