Compare commits

...

72 Commits

Author SHA1 Message Date
Kevin Hester
0e9ed1e82f Merge pull request #183 from geeksville/dev
Dev
2020-06-15 07:19:45 -07:00
geeksville
02ce0558b9 Merge remote-tracking branch 'root/master' into dev 2020-06-15 07:13:34 -07:00
geeksville
63110f0134 Merge remote-tracking branch 'mine/dev' into dev 2020-06-15 07:12:31 -07:00
geeksville
d8db4449be 0.7.6 2020-06-15 07:04:03 -07:00
geeksville
fda98bbf58 oops BLE auth should not change 2020-06-14 15:52:06 -07:00
geeksville
aadba1f694 add printPacket for debug printing packets 2020-06-14 15:30:42 -07:00
geeksville
2c8d152885 Use old style (pre BLE 4.2) pairing, it seems more reliable 2020-06-14 15:30:21 -07:00
Kevin Hester
e80de4eba0 Merge pull request #179 from geeksville/dev
omg so good
2020-06-13 16:55:32 -07:00
geeksville
e382a181f7 Merge remote-tracking branch 'root/master' into dev 2020-06-13 16:50:01 -07:00
Kevin Hester
85f69cb908 Merge branch 'master' into dev 2020-06-13 16:49:44 -07:00
geeksville
112a94e572 0.7.5 2020-06-13 16:48:34 -07:00
geeksville
13307c502f misc debug output 2020-06-13 16:29:53 -07:00
geeksville
8a1754efe8 leave the software update service off for now - no one is using ityet 2020-06-13 11:36:45 -07:00
geeksville
8caa075bc6 used fixed pool allocator for now - since that's how we've been testing 2020-06-13 11:05:36 -07:00
geeksville
d5deb49d20 use executeDelete to prevent leaking BLE handles 2020-06-13 11:05:13 -07:00
geeksville
575a15e135 remove more dead rev1 protocol code 2020-06-13 08:29:41 -07:00
geeksville
dc7469c64b useful bluetooth debugging output 2020-06-13 08:29:25 -07:00
geeksville
f54b18f733 each tx packet might have a retransmission/ack copy, make pool bigger 2020-06-13 08:27:44 -07:00
geeksville
db66e4dc00 ensure we never get null from malloc 2020-06-13 08:27:25 -07:00
geeksville
47e614c7d6 fix #172
We need our own branch because we need this fix and associated pullrequest
https://github.com/espressif/arduino-esp32/pull/4085
2020-06-13 08:26:48 -07:00
geeksville
03cb3c2145 basic stack debugging - we are okay for now 2020-06-12 16:37:03 -07:00
geeksville
a8d4b5479d don't start the BLE update service for now - the android side isn't ready 2020-06-12 15:48:24 -07:00
geeksville
de37e1bbab todo notes 2020-06-12 15:40:36 -07:00
geeksville
f0b8f10665 Fix #149: Use a simple heap allocator for now, after 1.0 we can go to
fixed sized pools to protect against fragmentation.
2020-06-12 12:11:18 -07:00
geeksville
88b91de197 Prepare to make MemoryDynamic 2020-06-12 11:56:13 -07:00
Kevin Hester
f22bb34c07 Merge pull request #173 from geeksville/master
todo updates
2020-06-12 09:09:19 -07:00
Kevin Hester
2d1cb7a43a Merge branch 'master' into master 2020-06-12 09:02:11 -07:00
geeksville
dc169675e2 Update TODO list 2020-06-12 09:01:28 -07:00
geeksville
99f8253637 protobuf updates 2020-06-12 08:59:48 -07:00
Kevin Hester
f3244caac1 Merge pull request #171 from geeksville/master
doc updates
2020-06-11 21:19:58 -07:00
geeksville
6edaadf5d8 Update BLE docs 2020-06-11 21:14:53 -07:00
geeksville
1f668046a0 if we can't sleep, at least have the processor block for 100ms 2020-06-10 18:23:20 -07:00
Kevin Hester
cb2aa3b29f Merge pull request #168 from geeksville/usb
misc bug fixes, see below
2020-06-10 15:38:45 -07:00
geeksville
8ccd59a7d8 Fix #115: wake from light sleep if a character arrives on the serial port
Note - we do this not by using the uart wake feature, but by the lower
power GPIO edge feature.  Recommend sending "Z" 0x5A - because that has
many edges.  Send the character 4 times to make sure the device is awake
2020-06-10 15:36:38 -07:00
geeksville
ddfdae64bf Fix #167 while in light sleep, allow loop() to still run occasionally 2020-06-10 14:11:56 -07:00
geeksville
21a90a42e5 move flutter ideas into own project 2020-06-10 14:02:53 -07:00
geeksville
712d6e5c1e Merge remote-tracking branch 'root/master' into usb 2020-06-09 18:24:05 -07:00
geeksville
00d55c9daa require min app version 172 2020-06-09 18:20:06 -07:00
geeksville
a05e45f84b make txQueue private 2020-06-09 15:47:05 -07:00
Kevin Hester
e650033f2c Merge pull request #166 from geeksville/usb
Changes to support USB
2020-06-09 11:52:48 -07:00
geeksville
846fc14b4a 0.7.4 2020-06-09 10:35:13 -07:00
geeksville
a8a5e036f5 turn off serial debug output once we are using the protocol on the stream 2020-06-09 10:35:06 -07:00
geeksville
009f05b61d temp workaround for sleep bug #167 2020-06-09 06:38:09 -07:00
geeksville
d8a6f82459 Merge remote-tracking branch 'root/master' into usb 2020-06-08 16:42:45 -07:00
Kevin Hester
185fe8520a Merge pull request #164 from rradar/patch-1
Update build-instructions.md to use code tags
2020-06-08 16:42:31 -07:00
geeksville
ce9bac34d6 add a new SERIAL psm state, to ensure device doesn't sleep while
connected to the phone over USB.

In support of

https://github.com/meshtastic/Meshtastic-Android/issues/38
2020-06-08 16:37:49 -07:00
Kevin Hester
e80673ed15 Merge branch 'master' into patch-1 2020-06-08 16:32:43 -07:00
geeksville
bdbaf9c655 remove old BLE api 2020-06-08 16:08:02 -07:00
geeksville
7473a6c27a unify activity detection in PhoneAPI, turn off BLE API while serial API in use 2020-06-08 16:06:59 -07:00
Kevin Hester
4919129bbc Merge pull request #165 from slavino/patch-1
Update README.md
2020-06-08 13:53:12 -07:00
Slavomir Hustaty
a02175cec0 Update README.md
https://www.everythingrf.com/community/lora-frequency-in-europe

The LoRa Alliance has defined two frequency bands for the usage of LoRa technology in Europe. These bands are EU433 from 433.05 to 434.79 MHz and EU863 from 863 to 870 MHz.

EU433 (433.05 to 434.79 MHz)

The end devices in EU433 band operate from 433.05 to 434.79 MHz and use a channel data structure to support at least 16 channels.

and so on...
https://lora-alliance.org/sites/default/files/2018-04/lorawantm_regional_parameters_v1.1rb_-_final.pdf
2020-06-08 21:34:02 +02:00
rradar
63affdd2e7 Update build-instructions.md to use code tags
Update build-instructions.md to make (more) use of code tags
2020-06-08 10:55:03 +01:00
Kevin Hester
351687e5cd Merge pull request #160 from geeksville/longaddr
PROTOCOL CHANGE! activate 32 bit nodenums/packetids
2020-06-07 22:23:31 -07:00
geeksville
739f497bbd Merge branch 'master' into longaddr 2020-06-07 22:16:43 -07:00
geeksville
2d2ed591e9 set num_bits for nodenum and packet id after loading save file 2020-06-07 22:12:06 -07:00
geeksville
871a85d688 force all devices to discard old settings 2020-06-07 17:22:07 -07:00
geeksville
a5f05019db fix build instructions 2020-06-06 14:30:15 -07:00
geeksville
e124d2094f PROTOCOL CHANGE! activate 32 bit nodenums/packetids 2020-06-06 13:16:36 -07:00
Kevin Hester
5d874cd43b Merge pull request #159 from geeksville/master
hotfix release for reboot bug
2020-06-06 08:48:14 -07:00
geeksville
9f6cdadd3e Merge remote-tracking branch 'root/master' 2020-06-06 08:43:10 -07:00
geeksville
6a3853ef35 0.6.8 2020-06-06 08:33:20 -07:00
geeksville
9ea65c6793 Fix #153 - details below
Somehow nodenum was getting reset to zero (and saved to flash - which is
bad because it makes the failure permanent).  So I've changed nodenum
selection to occur after we load the saved preferences (and we try to keep
nodenum stable in that case).

I'm puzzled as to how it ever got set to zero (unless there *shudder*
is some errant pointer that clobbered it).  But next week I'm turning
4 byte nodenums back on, which will make this moot - because they
will always be based on macaddr and the current process where nodes
haggle with the mesh to pick a unique one-byte nodenum will be gone.
2020-06-06 08:30:01 -07:00
geeksville
8d14e97dfa oops - we were not saving radio state 2020-06-06 08:07:21 -07:00
Kevin Hester
420b7d48d9 Merge pull request #157 from geeksville/master
update webpage
2020-06-05 11:38:17 -07:00
geeksville
5915669f6f Merge remote-tracking branch 'root/master' 2020-06-05 11:33:58 -07:00
geeksville
52b01db306 announce beta 2020-06-05 11:33:19 -07:00
Kevin Hester
a0d6ecb331 Merge pull request #156 from geeksville/master
minor
2020-06-05 11:09:00 -07:00
geeksville
0271b02d50 Merge remote-tracking branch 'root/master' 2020-06-05 11:06:40 -07:00
geeksville
9f61c78c0e doc merge 2020-06-05 11:05:36 -07:00
geeksville
4b5cfaf9ba changes from bringing up PPR 2020-06-05 11:00:18 -07:00
Kevin Hester
c014c1bafe Merge pull request #155 from geeksville/master
now in beta
2020-06-04 11:28:39 -07:00
geeksville
96594516af now in beta 2020-06-04 11:25:06 -07:00
46 changed files with 595 additions and 610 deletions

View File

@@ -4,7 +4,7 @@ This is the device side code for the [meshtastic.org](https://www.meshtastic.org
![Continuous Integration](https://github.com/meshtastic/Meshtastic-esp32/workflows/Continuous%20Integration/badge.svg)
Meshtastic is a project that lets you use
Meshtastic is a project that lets you use
inexpensive GPS mesh radios as an extensible, super long battery life mesh GPS communicator. These radios are great for hiking, skiing, paragliding -
essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other
members and any text messages sent to your group chat.
@@ -14,30 +14,33 @@ will optionally work with your phone, but no phone is required.
Typical time between recharging the radios should be about eight days.
This project is currently early-alpha, but if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
This project is is currently in beta-testing - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the chat.
## Supported hardware
We currently support three models of radios.
- TTGO T-Beam
- [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (Recommended)
- [T-Beam V1.0 w/ NEO-6M](https://www.aliexpress.com/item/33050391850.html)
- 3D printable cases
- [T-Beam V0](https://www.thingiverse.com/thing:3773717)
- [T-Beam V1](https://www.thingiverse.com/thing:3830711)
- [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (Recommended)
- [T-Beam V1.0 w/ NEO-6M](https://www.aliexpress.com/item/33050391850.html)
- 3D printable cases
- [T-Beam V0](https://www.thingiverse.com/thing:3773717)
- [T-Beam V1](https://www.thingiverse.com/thing:3830711)
- [TTGO LORA32](https://www.aliexpress.com/item/4000211331316.html) - No GPS
- [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/) - No GPS
- [3D Printable case](https://www.thingiverse.com/thing:3125854)
- [3D Printable case](https://www.thingiverse.com/thing:3125854)
**Make sure to get the frequency for your country**
- US/JP/AU/NZ - 915MHz
- CN - 470MHz
- EU - 870MHz
- US/JP/AU/NZ - 915MHz
- CN - 470MHz
- EU - 868MHz, 433MHz
Getting a version that includes a screen is optional, but highly recommended.
## Firmware Installation
@@ -57,7 +60,7 @@ Please post comments on our [group chat](https://meshtastic.discourse.group/) if
7. Browse to the previously downloaded firmware and select the correct firmware based on the board type, country and frequency.
8. Select Flash ESP.
9. Once complete, “Done! Flashing is complete!” will be shown.
10. Debug messages sent from the Meshtastic device can be viewed with a terminal program such as [PuTTY](https://www.putty.org/) (Windows only). Within PuTTY, click “Serial”, enter the “Serial line” com port (can be found at step 4), enter “Speed” as 921600, then click “Open”.
10. Debug messages sent from the Meshtastic device can be viewed with a terminal program such as [PuTTY](https://www.putty.org/) (Windows only). Within PuTTY, click “Serial”, enter the “Serial line” com port (can be found at step 4), enter “Speed” as 921600, then click “Open”.
### Installing from a commandline
@@ -87,10 +90,10 @@ Hard resetting via RTS pin...
```
5. cd into the directory where the release zip file was expanded.
6. Install the correct firmware for your board with `device-install.sh firmware-_board_-_country_.bin`.
- Example: `./device-install.sh firmware-HELTEC-US-0.0.3.bin`.
6. Install the correct firmware for your board with `device-install.sh firmware-_board_-_country_.bin`.
- Example: `./device-install.sh firmware-HELTEC-US-0.0.3.bin`.
7. To update run `device-update.sh firmware-_board_-_country_.bin`
- Example: `./device-update.sh firmware-HELTEC-US-0.0.3.bin`.
- Example: `./device-update.sh firmware-HELTEC-US-0.0.3.bin`.
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run `esptool.py --baud 921600 write_flash 0x10000 firmware-_board_-_country_-_version_.bin`. This will be faster, also all of your current preferences will be preserved.
@@ -165,12 +168,7 @@ Hard resetting via RTS pin...
# Meshtastic Android app
The source code for the (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android).
Alpha test builds available by opting into our alpha test group. See (www.meshtastic.org) for instructions.
If you don't want to live on the 'bleeding edge' you can opt-in to the beta-test or use the released version:
[![Download at https://play.google.com/store/apps/details?id=com.geeksville.mesh](https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png)](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub%26utm_medium%3Desp32-readme%26utm_campaign%3Dmeshtastic-esp32%2520readme%26anid%3Dadmob&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)
The companion (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android). You can also download it on Google Play.
# Python API

0
bin/nrf52-gdbserver.sh Normal file → Executable file
View File

View File

@@ -1,3 +1,3 @@
export VERSION=0.6.7
export VERSION=0.7.6

View File

@@ -1,6 +1,6 @@
# What is Meshtastic?
Meshtastic is a project that lets you use
Meshtastic is a project that lets you use
inexpensive (\$30 ish) GPS radios as an extensible, long battery life, secure, mesh GPS communicator. These radios are great for hiking, skiing, paragliding - essentially any hobby where you don't have reliable internet access. Each member of your private mesh can always see the location and distance of all other members and any text messages sent to your group chat.
The radios automatically create a mesh to forward packets as needed, so everyone in the group can receive messages from even the furthest member. The radios will optionally work with your phone, but no phone is required.
@@ -24,14 +24,14 @@ Not all of these features are fully implemented yet - see **important** disclaim
- Very long battery life (should be about eight days with the beta software)
- Built in GPS and [LoRa](https://en.wikipedia.org/wiki/LoRa) radio, but we manage the radio automatically for you
- Long range - a few miles per node but each node will forward packets as needed
- Secure - channels are encrypted by AES256 (But see important disclaimers below wrt this feature)
- Shows direction and distance to all members of your channel
- Directed or broadcast text messages for channel members
- Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor
- Communication API for bluetooth devices (such as our Android app) to use the mesh. So if you have some application that needs long range low power networking, this might work for you.
- Eventually (within a couple of months) we should have a modified version of Signal that works with this project.
- Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers.
- Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
This project is currently in early alpha - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
This project is currently in beta testing but it is fairly stable and feature complete - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [forum](https://meshtastic.discourse.group/).
@@ -39,6 +39,7 @@ This software is 100% open source and developed by a group of hobbyist experimen
Note: Updates are happening almost daily, only major updates are listed below. For more details see our forum.
- 06/04/2020 - 0.6.7 Beta releases of both the application and the device code are released. Features are fairly solid now with a sizable number of users.
- 04/28/2020 - 0.6.0 [Python API](https://pypi.org/project/meshtastic/) released. Makes it easy to use meshtastic devices as "zero config / just works" mesh transport adapters for other projects.
- 04/20/2020 - 0.4.3 Pretty solid now both for the android app and the device code. Many people have donated translations and code. Probably going to call it a beta soon.
- 03/03/2020 - 0.0.9 of the Android app and device code is released. Still an alpha but fairly functional.

View File

@@ -1,205 +1,77 @@
# High priority
Items to complete soon (next couple of alpha releases).
- why is the net so chatty now?
- modem sleep should work if we lower serial rate to 115kb?
- device wakes, turns BLE on and phone doesn't notice (while phone was sitting in auto-connect)
- E22 bringup
- encryption review findings writeup
- lower wait_bluetooth_secs to 30 seconds once we have the GPS power on (but GPS in sleep mode) across light sleep. For the time
being I have it set at 2 minutes to ensure enough time for a GPS lock from scratch.
- turn on modem-sleep mode - https://github.com/espressif/arduino-esp32/issues/1142#issuecomment-512428852
last EDF release in arduino is: https://github.com/espressif/arduino-esp32/commit/1977370e6fc069e93ffd8818798fbfda27ae7d99
IDF release/v3.3 46b12a560
IDF release/v3.3 367c3c09c
https://docs.espressif.com/projects/esp-idf/en/release-v3.3/get-started/linux-setup.html
kevinh@kevin-server:~/development/meshtastic/esp32-arduino-lib-builder$ python /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/esp-idf/components/esptool_py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/build/bootloader/bootloader.bin
cp -a out/tools/sdk/* components/arduino/tools/sdk
cp -ar components/arduino/* ~/.platformio/packages/framework-arduinoespressif32@src-fba9d33740f719f712e9f8b07da6ea13/
# Medium priority
Items to complete before the first beta release.
- Use 32 bits for message IDs
- Use fixed32 for node IDs
- Remove the "want node" node number arbitration process
- Don't store position packets in the to phone fifo if we are disconnected. The phone will get that info for 'free' when it
fetches the fresh nodedb.
- Use the RFM95 sequencer to stay in idle mode most of the time, then automatically go to receive mode and automatically go from transmit to receive mode. See 4.2.8.2 of manual.
- possibly switch to https://github.com/SlashDevin/NeoGPS for gps comms
- good source of battery/signal/gps icons https://materialdesignicons.com/
- research and implement better mesh algorithm - investigate changing routing to https://github.com/sudomesh/LoRaLayer2 ?
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/
- use fuse bits to store the board type and region. So one load can be used on all boards
- the BLE stack is leaking about 200 bytes each time we go to light sleep
- turn on watchdog timer (because lib code seems buggy)
- show battery level as % full
- rx signal measurements -3 marginal, -9 bad, 10 great, -10 means almost unusable. So scale this into % signal strength. preferably as a graph, with an X indicating loss of comms.
- assign every "channel" a random shared 8 bit sync word (per 4.2.13.6 of datasheet) - use that word to filter packets before even checking CRC. This will ensure our CPU will only wake for packets on our "channel"
- Note: we do not do address filtering at the chip level, because we might need to route for the mesh
is in cleartext (so that nodes will route for other radios that are cryptoed with a key we don't know)
- add frequency hopping, dependent on the gps time, make the switch moment far from the time anyone is going to be transmitting
- share channel settings over Signal (or qr code) by embedding an an URL which is handled by the MeshUtil app.
- publish update articles on the web
# Pre-beta priority
During the beta timeframe the following improvements 'would be nice' (and yeah - I guess some of these items count as features, but it is a hobby project ;-) )
During the beta timeframe the following improvements 'would be nice'
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
for it (because it will redownload the nodedb when it comes back)
- Figure out why the RF95 ISR is never seeing RH_RF95_VALID_HEADER, so it is not protecting our rx packets from getting stomped on by sends
- fix the frequency error reading in the RF95 RX code (can't do floating point math in an ISR ;-)
- See CustomRF95::send and fix the problem of dropping partially received packets if we want to start sending
- make sure main cpu is not woken for packets with bad crc or not addressed to this node - do that in the radio hw
- triple check fcc compliance
- finish DSR for unicast
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though.
- pick channel center frequency based on channel name? "dolphin" would hash to 900Mhz, "cat" to 905MHz etc? allows us to hide the concept of channel # from hte user.
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
- make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired
- if radio params change fundamentally, discard the nodedb
- reneable the bluetooth battery level service on the T-BEAM, because we can read battery level there
# Spinoff project ideas
- an open source version of https://www.burnair.ch/skynet/
- a paragliding app like http://airwhere.co.uk/
- a version with a solar cell for power, just mounted high to permanently provide routing for nodes in a valley. Someone just pointed me at disaster.radio
- How do avalanche beacons work? Could this do that as well? possibly by using beacon mode feature of the RF95?
- provide generalized (but slow) internet message forwarding servie if one of our nodes has internet connectivity
- re-enable the bluetooth battery level service on the T-BEAM
- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors
- provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ]
# Low priority
Items after the first final candidate release.
- use variable length arduino Strings in protobufs (instead of current fixed buffers)
- Change back to using a fixed sized MemoryPool rather than MemoryDynamic (see bug #149)
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
for it (because it will redownload the nodedb when it comes back)
- add frequency hopping, dependent on the gps time, make the switch moment far from the time anyone is going to be transmitting
- assign every "channel" a random shared 8 bit sync word (per 4.2.13.6 of datasheet) - use that word to filter packets before even checking CRC. This will ensure our CPU will only wake for packets on our "channel"
- the BLE stack is leaking about 200 bytes each time we go to light sleep
- use fuse bits to store the board type and region. So one load can be used on all boards
- Don't store position packets in the to phone fifo if we are disconnected. The phone will get that info for 'free' when it
fetches the fresh nodedb.
- Use the RFM95 sequencer to stay in idle mode most of the time, then automatically go to receive mode and automatically go from transmit to receive mode. See 4.2.8.2 of manual.
- Use fixed32 for node IDs, packetIDs, successid, failid, and lat/lon - will require all nodes to be updated, but make messages slightly smaller.
- 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 an install script to let novices install software on their boards
- use std::map<NodeInfo\*, std::string> in node db
- make a HAM build: yep - that's a great idea. I'll add it to the TODO. should be pretty painless - 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 hte 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
- use https://platformio.org/lib/show/1260/OneButton if necessary
- don't send location packets if we haven't moved
- don't send location packets if we haven't moved significantly
- scrub default radio config settings for bandwidth/range/speed
- answer to pings (because some other user is looking at our nodeinfo) with our latest location (not a stale location)
- show radio and gps signal strength as an image
- only BLE advertise for a short time after the screen is on and button pressed - to save power and prevent people for sniffing for our BT app.
- make mesh aware network timing state machine (sync wake windows to gps time)
- make mesh aware network timing state machine (sync wake windows to gps time) - this can save LOTS of battery
- split out the software update utility so other projects can use it. Have the appload specify the URL for downloads.
- read the PMU battery fault indicators and blink/led/warn user on screen
- the AXP debug output says it is trying to charge at 700mA, but the max I've seen is 180mA, so AXP registers probably need to be set to tell them the circuit can only provide 300mAish max. So that the low charge rate kicks in faster and we don't wear out batteries.
- increase the max charging rate a bit for 18650s, currently it limits to 180mA (at 4V). Work backwards from the 500mA USB limit (at 5V) and let the AXP charge at that rate.
- discard very old nodedb records (> 1wk)
- using the genpartitions based table doesn't work on TTGO so for now I stay with my old memory map
- We let anyone BLE scan for us (FIXME, perhaps only allow that until we are paired with a phone and configured)
- use two different buildenv flags for ttgo vs lora32. https://docs.platformio.org/en/latest/ide/vscode.html#key-bindings
- sim gps data for testing nodes that don't have hardware
- do debug serial logging to android over bluetooth
- break out my bluetooth OTA software as a seperate library so others can use it
- Heltec LoRa32 has 8MB flash, use a bigger partition table if needed - TTGO is 4MB but has PSRAM
- add a watchdog timer
- handle millis() rollover in GPS.getTime - otherwise we will break after 50 days
- report esp32 device code bugs back to the mothership via android
- change BLE bonding to something more secure. see comment by pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND)
# Done
# Spinoff project ideas
- change the partition table to take advantage of the 4MB flash on the wroom: http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
- wrap in nice MeshRadio class
- add mesh send & rx
- make message send from android go to service, then to mesh radio
- make message receive from radio go through to android
- test loopback tx/rx path code without using radio
- notify phone when rx packets arrive, currently the phone polls at startup only
- figure out if we can use PA_BOOST - yes, it seems to be on both boards
- implement new ble characteristics
- have MeshService keep a node DB by sniffing user messages
- have a state machine return the correct FromRadio packet to the phone, it isn't always going to be a MeshPacket. Do a notify on fromnum to force the radio to read our state machine generated packets
- send my_node_num when phone sends WantsNodes
- have meshservice periodically send location data on mesh (if device has a GPS)
- implement getCurrentTime() - set based off gps but then updated locally
- make default owner record have valid usernames
- message loop between node 0x28 and 0x7c
- check in my radiolib fixes
- figure out what is busted with rx
- send our owner info at boot, reply if we see anyone send theirs
- add manager layers
- confirm second device receives that gps message and updates device db
- send correct hw vendor in the bluetooth info - needed so the android app can update different radio models
- correctly map nodeids to nodenums, currently we just do a proof of concept by always doing a broadcast
- add interrupt detach/sleep mode config to lora radio so we can enable deepsleep without panicing
- make jtag work on second board
- implement regen owner and radio prefs
- use a better font
- make nice screens (boot, about to sleep, debug info (gps signal, #people), latest text, person info - one frame per person on network)
- turn framerate from ui->state.frameState to 1 fps (or less) unless in transition
- switch to my gui layout manager
- make basic gui. different screens: debug, one page for each user in the user db, last received text message
- make button press cycle between screens
- save our node db on entry to sleep
- fix the logo
- sent/received packets (especially if a node was just reset) have variant of zero sometimes - I think there is a bug (race-condtion?) in the radio send/rx path.
- DONE dynamic nodenum assignment tasks
- make jtag debugger id stable: https://askubuntu.com/questions/49910/how-to-distinguish-between-identical-usb-to-serial-adapters
- reported altitude is crap
- good tips on which bands might be more free https://github.com/TheThingsNetwork/ttn/issues/119
- finish power measurements (GPS on during sleep vs LCD on during sleep vs LORA on during sleep) and est battery life
- make screen sleep behavior work
- make screen advance only when a new node update arrives, a new text arrives or the user presses a button, turn off screen after a while
- after reboot, channel number is getting reset to zero! fix!
- send user and location events much less often
- send location (or if not available user) when the user wakes the device from display sleep (both for testing and to improve user experience)
- make real implementation of getNumOnlineNodes
- very occasionally send our position and user packet based on the schedule in the radio info (if for nothing else so that other nodes update last_seen)
- show real text info on the text screen
- apply radio settings from android land
- cope with nodes that have 0xff or 0x00 as the last byte of their mac
- allow setting full radio params from android
- add receive timestamps to messages, inserted by esp32 when message is received but then shown on the phone
- update build to generate both board types
- have node info screen show real info (including distance and heading)
- blink the power led less often
- have radiohead ISR send messages to RX queue directly, to allow that thread to block until we have something to send
- move lora rx/tx to own thread and block on IO
- keep our pseudo time moving forward even if we enter deep sleep (use esp32 rtc)
- for non GPS equipped devices, set time from phone
- GUI on oled hangs for a few seconds occasionally, but comes back
- update local GPS position (but do not broadcast) at whatever rate the GPS is giving it
- don't send our times to other nodes
- don't trust times from other nodes
- draw compass rose based off local walking track
- add requestResponse optional bool - use for location broadcasts when sending tests
- post sample video to signal forum
- support non US frequencies
- send pr https://github.com/ThingPulse/esp8266-oled-ssd1306 to tell them about this project
- document rules for sleep wrt lora/bluetooth/screen/gps. also: if I have text messages (only) for the phone, then give a few seconds in the hopes BLE can get it across before we have to go back to sleep.
- wake from light sleep as needed for our next scheduled periodic task (needed for gps position broadcasts etc)
- turn bluetooth off based on our sleep policy
- blink LED while in LS sleep mode
- scrolling between screens based on press is busted
- Use Neo-M8M API to put it in sleep mode (on hold until my new boards arrive)
- update the prebuilt bins for different regulatory regions
- don't enter NB state if we've recently talked to the phone (to prevent breaking syncing or bluetooth sw update)
- have sw update prevent BLE sleep
- manually delete characteristics/descs
- leave lora receiver always on
- protobufs are sometimes corrupted after sleep!
- stay awake while charging
- check gps battery voltage
- if a position report includes ground truth time and we don't have time yet, set our clock from that. It is better than nothing.
- retest BLE software update for both board types
- report on wikifactory
- send note to the guy who designed the cases
- turn light sleep on aggressively (while lora is on but BLE off)
- Use the Periodic class for both position and user periodic broadcasts
- don't treat north as up, instead adjust shown bearings for our guess at the users heading (i.e. subtract one from the other)
- sendToMesh can currently block for a long time, instead have it just queue a packet for a radio freertos thread
- don't even power on bluetooth until we have some data to send to the android phone. Most of the time we should be sleeping in a lowpower "listening for lora" only mode. Once we have some packets for the phone, then power on bluetooth
until the phone pulls those packets. Ever so often power on bluetooth just so we can see if the phone wants to send some packets. Possibly might need ULP processor to help with this wake process.
- do hibernation mode to get power draw down to 2.5uA https://lastminuteengineers.com/esp32-sleep-modes-power-consumption/
- fix GPS.zeroOffset calculation it is wrong
- (needs testing) fixed the following during a plane flight:
Have state machine properly enter deep sleep based on loss of mesh and phone comms.
Default to enter deep sleep if no LORA received for two hours (indicates user has probably left the mesh).
- (fixed I think) text messages are not showing on local screen if screen was on
- add links to todos
- link to the kanban page
- add a getting started page
- finish mesh alg reeval
- ublox gps parsing seems a little buggy (we shouldn't be sending out read solution commands, the device is already broadcasting them)
- turn on gps https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example18_PowerSaveMode/Example18_PowerSaveMode.ino
- switch gps to 38400 baud https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library/blob/master/examples/Example11_ResetModule/Example2_FactoryDefaultsviaSerial/Example2_FactoryDefaultsviaSerial.ino
- Use Neo-M8M API to put it in sleep mode
- use gps sleep mode instead of killing its power (to allow fast position when we wake)
- enable fast lock and low power inside the gps chip
- Make a FAQ
- add a SF12 transmit option for _super_ long range
- figure out why this fixme is needed: "FIXME, disable wake due to PMU because it seems to fire all the time?"
- "AXP192 interrupt is not firing, remove this temporary polling of battery state"
- make debug info screen show real data (including battery level & charging) - close corresponding github issue
- remeasure wake time power draws now that we run CPU down at 80MHz
- an open source version of https://www.burnair.ch/skynet/
- a paragliding app like http://airwhere.co.uk/
- How do avalanche beacons work? Could this do that as well? possibly by using beacon mode feature of the RF95?

View File

@@ -10,19 +10,28 @@ This device will work with any MTU size, but it is highly recommended that you c
This is the main bluetooth service for the device and provides the API your app should use to get information about the mesh, send packets or provision the radio.
For a reference implementation of a client that uses this service see [RadioInterfaceService](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt). Typical flow when
a phone connects to the device should be the following:
For a reference implementation of a client that uses this service see [RadioInterfaceService](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt).
Typical flow when a phone connects to the device should be the following (if you want to watch this flow from the python app just run "meshtastic --debug --info" - the flow over BLE is identical):
- There are only three relevant endpoints (and they have built in BLE documentation - so use a BLE tool of your choice to watch them): FromRadio, FromNum (sends notifies when new data is available in FromRadio) and ToRadio
- SetMTU size to 512
- Write a ToRadio.startConfig protobuf to the "ToRadio" endpoint" - this tells the radio you are a new connection and you need the entire NodeDB sent down.
- Read repeatedly from the "FromRadio" endpoint. Each time you read you will get back a FromRadio protobuf (see Meshtatastic-protobuf). Keep reading from this endpoint until you get back and empty buffer.
- See below for the expected sequence for your initial download.
- After the initial download, you should subscribe for BLE "notify" on the "FromNum" endpoint. If a notification arrives, that means there are now one or more FromRadio packets waiting inside FromRadio. Read from FromRadio until you get back an empty packet.
- Any time you want to send packets to the radio, you should write a ToRadio packet into ToRadio.
Expected sequence for initial download:
- After your send startConfig, you will receive a series of FromRadio packets. The sequence of these packets will be as follows (but you are best not counting on this, instead just update your model for whatever packet you receive - based on looking at the type)
- Read a RadioConfig from "radio" - used to get the channel and radio settings
- Read (and write if incorrect) a User from "user" - to get the username for this node
- Read a User from "user" - to get the username for this node
- Read a MyNodeInfo from "mynode" to get information about this local device
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
- Read from "nodeinfo" until it returns empty to build the phone's copy of the current NodeDB for the mesh
- Read from "fromradio" until it returns empty to get any messages that arrived for this node while the phone was away
- Subscribe to notify on "fromnum" to get notified whenever the device has a new received packet
- Read that new packet from "fromradio"
- Whenever the phone has a packet to send write to "toradio"
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
- Read a endConfig packet that indicates that the entire state you need has been sent.
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away
For definitions (and documentation) on FromRadio, ToRadio, MyNodeInfo, NodeInfo and User protocol buffers see [mesh.proto](https://github.com/meshtastic/Meshtastic-protobufs/blob/master/mesh.proto)

View File

@@ -6,10 +6,11 @@ in these instructions I describe use of their command line tool.
1. Purchase a suitable radio (see above)
2. Install [PlatformIO](https://platformio.org/platformio-ide)
3. Download this git repo and cd into it
4. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with "hw_version" and instructions are provided above that line. Options are provided for EU433, EU835, CN, JP and US. Pull-requests eagerly accepted for other countries.
5. Plug the radio into your USB port
6. Type "pio run --environment XXX -t upload" (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either tbeam, heltec, ttgo-lora32-v1, ttgo-lora32-v2).
7. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
4. Run `git submodule update --init --recursive` to pull in dependencies this project needs.
5. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with `hw_version` and instructions are provided above that line. Options are provided for `EU433`, `EU835`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries.
6. Plug the radio into your USB port
7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tbeam`, `heltec`, `ttgo-lora32-v1`, `ttgo-lora32-v2`).
8. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
## Decoding stack traces

View File

@@ -34,7 +34,4 @@ Note that for both stategies, sizes are measured in blocks and that an AES block
## Remaining todo
- Make the packet numbers 32 bit
- Confirm the packet #s are stored in flash across deep sleep (and otherwise in in RAM)
- Have the app change the crypto key when the user generates a new channel
- Implement for NRF52 [NRF52](https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.0.0/lib_crypto_aes.html#sub_aes_ctr)

View File

@@ -40,7 +40,6 @@ Needed to be fully functional at least at the same level of the ESP32 boards. At
## Items to be 'feature complete'
- change packet numbers to be 32 bits
- check datasheet about sx1262 temperature compensation
- enable brownout detection and watchdog
- stop polling for GPS characters, instead stay blocked on read in a thread
@@ -60,8 +59,6 @@ Needed to be fully functional at least at the same level of the ESP32 boards. At
Nice ideas worth considering someday...
- Use flego to me an iOS/linux app? https://felgo.com/doc/qt/qtbluetooth-index/ or
- Use flutter to make an iOS/linux app? https://github.com/Polidea/FlutterBleLib
- enable monitor mode debugging (need to use real jlink): https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
- Improve efficiency of PeriodicTimer by only checking the next queued timer event, and carefully sorting based on schedule
- make a Mfg Controller and device under test classes as examples of custom app code for third party devs. Make a post about this. Use a custom payload type code. Have device under test send a broadcast with max hopcount of 0 for the 'mfgcontroller' payload type. mfg controller will read SNR and reply. DOT will declare failure/success and switch to the regular app screen.
@@ -128,6 +125,7 @@ Nice ideas worth considering someday...
- scheduleOSCallback doesn't work yet - it is way too fast (causes rapid polling of busyTx, high power draw etc...)
- find out why we reboot while debugging - it was bluetooth/softdevice
- make a file system implementation (preferably one that can see the files the bootloader also sees) - preferably https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/libraries/InternalFileSytem/examples/Internal_ReadWrite/Internal_ReadWrite.ino else use https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v15.3.0/lib_fds_usage.html?cp=7_5_0_3_55_3
- change packet numbers to be 32 bits
```

View File

@@ -36,6 +36,10 @@ From lower to higher power consumption.
onEntry: setBluetoothOn(true), screen.setOn(true)
onExit: screen.setOn(false)
- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off
onEntry: setBluetooth off, screen on
onExit:
## Behavior
### events that increase CPU activity
@@ -51,9 +55,11 @@ From lower to higher power consumption.
- While in DARK/ON: If we receive EVENT_BLUETOOTH_PAIR we transition to ON and start our screen_on_secs timeout
- While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown)
- While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts)
- while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial
### events that decrease cpu activity
- While in SERIAL: if SERIAL_DISCONNECTED, go to NB
- While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess
- While in ON: If it has been more than screen_on_secs since a press, lower to DARK
- While in DARK: If time since last contact by our phone exceeds phone_timeout_secs (15 minutes), we transition down into NB mode

View File

@@ -6,8 +6,8 @@
# mon exec SetMonModeDebug=1
# mon exec SetMonModeVTableAddr=0x26000
echo setting RTTAddr
eval "monitor exec SetRTTAddr %p", &_SEGGER_RTT
# echo setting RTTAddr
# eval "monitor exec SetRTTAddr %p", &_SEGGER_RTT
# the jlink debugger seems to want a pause after reset before we tell it to start running
define restart

View File

@@ -22,8 +22,6 @@ default_envs = tbeam ; Note: the github actions CI test build can't yet build NR
; HW_VERSION (default emptystring)
[env]
platform = espressif32
framework = arduino
; customize the partition table
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
@@ -79,6 +77,8 @@ lib_deps =
; Common settings for ESP targes, mixin with extends = esp32_base
[esp32_base]
platform = espressif32
framework = arduino
src_filter =
${env.src_filter} -<nrf52/>
upload_speed = 921600
@@ -86,6 +86,8 @@ debug_init_break = tbreak setup
build_flags =
${env.build_flags} -Wall -Wextra -Isrc/esp32
lib_ignore = segger_rtt
platform_packages =
framework-arduinoespressif32 @ https://github.com/meshtastic/arduino-esp32.git
; The 1.0 release of the TBEAM board
[env:tbeam]

2
proto

Submodule proto updated: 9d083d5d4f...e7f181ef6f

View File

@@ -26,60 +26,73 @@ static void sdsEnter()
#include "error.h"
static uint32_t secsSlept;
static void lsEnter()
{
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", radioConfig.preferences.ls_secs);
screen.setOn(false);
secsSlept = 0; // How long have we been sleeping this time
DEBUG_MSG("lsEnter end\n");
}
static void lsIdle()
{
DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", radioConfig.preferences.ls_secs);
#ifndef NO_ESP32
uint32_t secsSlept = 0;
esp_sleep_source_t wakeCause = ESP_SLEEP_WAKEUP_UNDEFINED;
bool reached_ls_secs = false;
while (!reached_ls_secs) {
// Do we have more sleeping to do?
if (secsSlept < radioConfig.preferences.ls_secs) {
// Briefly come out of sleep long enough to blink the led once every few seconds
uint32_t sleepTime = 5;
uint32_t sleepTime = 30;
setLed(false); // Never leave led on while in light sleep
wakeCause = doLightSleep(sleepTime * 1000LL);
if (wakeCause != ESP_SLEEP_WAKEUP_TIMER)
break;
// If some other service would stall sleep, don't let sleep happen yet
if (doPreflightSleep()) {
setLed(false); // Never leave led on while in light sleep
wakeCause = doLightSleep(sleepTime * 1000LL);
setLed(true); // briefly turn on led
doLightSleep(1);
if (wakeCause != ESP_SLEEP_WAKEUP_TIMER)
break;
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
// Normal case: timer expired, we should just go back to sleep ASAP
secsSlept += sleepTime;
reached_ls_secs = secsSlept >= radioConfig.preferences.ls_secs;
}
setLed(false);
setLed(true); // briefly turn on led
wakeCause = doLightSleep(1); // leave led on for 1ms
if (reached_ls_secs) {
// stay in LS mode but let loop check whatever it wants
DEBUG_MSG("reached ls_secs, servicing loop()\n");
} else {
DEBUG_MSG("wakeCause %d\n", wakeCause);
secsSlept += sleepTime;
// DEBUG_MSG("sleeping, flash led!\n");
}
if (wakeCause == ESP_SLEEP_WAKEUP_UART) {
// Not currently used (because uart triggers in hw have problems)
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
} else {
// We woke for some other reason (button press, uart, device interrupt)
// uint64_t status = esp_sleep_get_ext1_wakeup_status();
DEBUG_MSG("wakeCause %d\n", wakeCause);
#ifdef BUTTON_PIN
bool pressed = !digitalRead(BUTTON_PIN);
bool pressed = !digitalRead(BUTTON_PIN);
#else
bool pressed = false;
bool pressed = false;
#endif
if (pressed) // If we woke because of press, instead generate a PRESS event.
{
powerFSM.trigger(EVENT_PRESS);
if (pressed) // If we woke because of press, instead generate a PRESS event.
{
powerFSM.trigger(EVENT_PRESS);
} else {
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
powerFSM.trigger(EVENT_WAKE_TIMER);
}
}
} else {
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
powerFSM.trigger(EVENT_WAKE_TIMER);
// Someone says we can't sleep now, so just save some power by sleeping the CPU for 100ms or so
delay(100);
}
} else {
// Time to stop sleeping!
setLed(false);
DEBUG_MSG("reached ls_secs, servicing loop()\n");
powerFSM.trigger(EVENT_WAKE_TIMER);
}
#endif
}
@@ -104,6 +117,12 @@ static void darkEnter()
screen.setOn(false);
}
static void serialEnter()
{
setBluetoothEnable(false);
screen.setOn(true);
}
static void onEnter()
{
screen.setOn(true);
@@ -133,6 +152,7 @@ State stateSDS(sdsEnter, NULL, NULL, "SDS");
State stateLS(lsEnter, lsIdle, lsExit, "LS");
State stateNB(nbEnter, NULL, NULL, "NB");
State stateDARK(darkEnter, NULL, NULL, "DARK");
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
State stateBOOT(bootEnter, NULL, NULL, "BOOT");
State stateON(onEnter, NULL, NULL, "ON");
Fsm powerFSM(&stateBOOT);
@@ -148,7 +168,7 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
// Handle press events
// Handle press events - note: we ignore button presses when in API mode
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
powerFSM.add_transition(&stateNB, &stateON, EVENT_PRESS, NULL, "Press");
powerFSM.add_transition(&stateDARK, &stateON, EVENT_PRESS, NULL, "Press");
@@ -160,6 +180,7 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateNB, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateDARK, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateON, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateSERIAL, &stateSDS, EVENT_LOW_BATTERY, NULL, "LowBat");
powerFSM.add_transition(&stateDARK, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
powerFSM.add_transition(&stateON, &stateON, EVENT_BLUETOOTH_PAIR, NULL, "Bluetooth pairing");
@@ -173,6 +194,13 @@ void PowerFSM_setup()
powerFSM.add_transition(&stateDARK, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text");
powerFSM.add_transition(&stateON, &stateON, EVENT_RECEIVED_TEXT_MSG, NULL, "Received text"); // restarts the sleep timer
powerFSM.add_transition(&stateLS, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
powerFSM.add_transition(&stateNB, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
powerFSM.add_transition(&stateDARK, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
powerFSM.add_transition(&stateON, &stateSERIAL, EVENT_SERIAL_CONNECTED, NULL, "serial API");
powerFSM.add_transition(&stateSERIAL, &stateNB, EVENT_SERIAL_DISCONNECTED, NULL, "serial disconnect");
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");

View File

@@ -14,6 +14,8 @@
#define EVENT_NODEDB_UPDATED 8 // NodeDB has a big enough change that we think you should turn on the screen
#define EVENT_CONTACT_FROM_PHONE 9 // the phone just talked to us over bluetooth
#define EVENT_LOW_BATTERY 10 // Battery is critically low, go to sleep
#define EVENT_SERIAL_CONNECTED 11
#define EVENT_SERIAL_DISCONNECTED 12
extern Fsm powerFSM;

View File

@@ -1,4 +1,5 @@
#include "SerialConsole.h"
#include "PowerFSM.h"
#include "configuration.h"
#include <Arduino.h>
@@ -26,12 +27,19 @@ void SerialConsole::init()
*/
void SerialConsole::handleToRadio(const uint8_t *buf, size_t len)
{
// Note: for the time being we could _allow_ debug printing to keep going out the console
// I _think_ this is okay because we currently only print debug msgs from loop() and we are only
// dispatching serial protobuf msgs from loop() as well. When things are more threaded in the future this
// will need to change.
// setDestination(&noopPrint);
// Turn off debug serial printing once the API is activated, because other threads could print and corrupt packets
setDestination(&noopPrint);
canWrite = true;
StreamAPI::handleToRadio(buf, len);
}
/// Hookable to find out when connection changes
void SerialConsole::onConnectionChanged(bool connected)
{
if (connected) { // To prevent user confusion, turn off bluetooth while using the serial port api
powerFSM.trigger(EVENT_SERIAL_CONNECTED);
} else {
powerFSM.trigger(EVENT_SERIAL_DISCONNECTED);
}
}

View File

@@ -26,6 +26,10 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
RedirectablePrint::write('\r');
return RedirectablePrint::write(c);
}
protected:
/// Hookable to find out when connection changes
virtual void onConnectionChanged(bool connected);
};
extern SerialConsole console;

View File

@@ -1,4 +1,5 @@
#include "WorkerThread.h"
#include "debug.h"
#include <assert.h>
void Thread::start(const char *name, size_t stackSize, uint32_t priority)
@@ -16,6 +17,15 @@ void WorkerThread::doRun()
{
while (!wantExit) {
block();
#ifdef DEBUG_STACK
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10 * 1000L) {
lastPrint = millis();
meshtastic::printThreadInfo("net");
}
#endif
loop();
}
}
@@ -28,8 +38,6 @@ void NotifiedWorkerThread::notify(uint32_t v, eNotifyAction action)
xTaskNotify(taskHandle, v, action);
}
void NotifiedWorkerThread::block()
{
xTaskNotifyWait(0, // don't clear notification on entry

View File

@@ -15,6 +15,8 @@ class Thread
virtual ~Thread() { vTaskDelete(taskHandle); }
uint32_t getStackHighwaterMark() { return uxTaskGetStackHighWaterMark(taskHandle); }
protected:
/**
* The method that will be called when start is called.

View File

@@ -258,7 +258,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef NO_ESP32
#define USE_SEGGER
#else
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32
#endif
#ifdef USE_SEGGER
#include "SEGGER_RTT.h"
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)

View File

@@ -30,8 +30,6 @@ class TotalSizeCharacteristic : public CallbackCharacteristic
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
LockGuard g(updateLock);
// Check if there is enough to OTA Update
uint32_t len = getValue32(c, 0);
@@ -67,8 +65,6 @@ class DataCharacteristic : public CallbackCharacteristic
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
LockGuard g(updateLock);
std::string value = c->getValue();
uint32_t len = value.length();
@@ -92,8 +88,6 @@ class CRC32Characteristic : public CallbackCharacteristic
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
LockGuard g(updateLock);
uint32_t expectedCRC = getValue32(c, 0);
uint32_t actualCRC = crc.finalize();

View File

@@ -8,54 +8,6 @@
SimpleAllocator btPool;
/**
* Create standard device info service
**/
BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendor, std::string swVersion,
std::string hwVersion = "")
{
BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC));
BLECharacteristic *swC =
new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
BLECharacteristic *mfC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ);
// BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR),
// BLECharacteristic::PROPERTY_READ);
/*
* Mandatory characteristic for device info service?
BLECharacteristic *m_pnpCharacteristic = m_deviceInfoService->createCharacteristic(ESP_GATT_UUID_PNP_ID,
BLECharacteristic::PROPERTY_READ);
uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version;
uint8_t pnp[] = { sig, (uint8_t) (vid >> 8), (uint8_t) vid, (uint8_t) (pid >> 8), (uint8_t) pid, (uint8_t) (version >>
8), (uint8_t) version }; m_pnpCharacteristic->setValue(pnp, sizeof(pnp));
*/
swC->setValue(swVersion);
deviceInfoService->addCharacteristic(addBLECharacteristic(swC));
mfC->setValue(hwVendor);
deviceInfoService->addCharacteristic(addBLECharacteristic(mfC));
if (!hwVersion.empty()) {
BLECharacteristic *hwvC =
new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_HW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
hwvC->setValue(hwVersion);
deviceInfoService->addCharacteristic(addBLECharacteristic(hwvC));
}
// SerialNumberCharacteristic.setValue("FIXME");
// deviceInfoService->addCharacteristic(&SerialNumberCharacteristic);
// m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29,
// BLECharacteristic::PROPERTY_READ); m_manufacturerCharacteristic->setValue(name);
/* add these later?
ESP_GATT_UUID_SYSTEM_ID
*/
// caller must call service->start();
return deviceInfoService;
}
bool _BLEClientConnected = false;
class MyServerCallbacks : public BLEServerCallbacks
@@ -106,6 +58,54 @@ void addWithDesc(BLEService *service, BLECharacteristic *c, const char *descript
addBLEDescriptor(desc);
}
/**
* Create standard device info service
**/
BLEService *createDeviceInfomationService(BLEServer *server, std::string hwVendor, std::string swVersion,
std::string hwVersion = "")
{
BLEService *deviceInfoService = server->createService(BLEUUID((uint16_t)ESP_GATT_UUID_DEVICE_INFO_SVC));
BLECharacteristic *swC =
new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_SW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
BLECharacteristic *mfC = new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_MANU_NAME), BLECharacteristic::PROPERTY_READ);
// BLECharacteristic SerialNumberCharacteristic(BLEUUID((uint16_t) ESP_GATT_UUID_SERIAL_NUMBER_STR),
// BLECharacteristic::PROPERTY_READ);
/*
* Mandatory characteristic for device info service?
BLECharacteristic *m_pnpCharacteristic = m_deviceInfoService->createCharacteristic(ESP_GATT_UUID_PNP_ID,
BLECharacteristic::PROPERTY_READ);
uint8_t sig, uint16_t vid, uint16_t pid, uint16_t version;
uint8_t pnp[] = { sig, (uint8_t) (vid >> 8), (uint8_t) vid, (uint8_t) (pid >> 8), (uint8_t) pid, (uint8_t) (version >>
8), (uint8_t) version }; m_pnpCharacteristic->setValue(pnp, sizeof(pnp));
*/
swC->setValue(swVersion);
deviceInfoService->addCharacteristic(addBLECharacteristic(swC));
mfC->setValue(hwVendor);
deviceInfoService->addCharacteristic(addBLECharacteristic(mfC));
if (!hwVersion.empty()) {
BLECharacteristic *hwvC =
new BLECharacteristic(BLEUUID((uint16_t)ESP_GATT_UUID_HW_VERSION_STR), BLECharacteristic::PROPERTY_READ);
hwvC->setValue(hwVersion);
deviceInfoService->addCharacteristic(addBLECharacteristic(hwvC));
}
// SerialNumberCharacteristic.setValue("FIXME");
// deviceInfoService->addCharacteristic(&SerialNumberCharacteristic);
// m_manufacturerCharacteristic = m_deviceInfoService->createCharacteristic((uint16_t) 0x2a29,
// BLECharacteristic::PROPERTY_READ); m_manufacturerCharacteristic->setValue(name);
/* add these later?
ESP_GATT_UUID_SYSTEM_ID
*/
// caller must call service->start();
return deviceInfoService;
}
static BLECharacteristic *batteryLevelC;
/**
@@ -223,11 +223,15 @@ void deinitBLE()
pServer->getAdvertising()->stop();
destroyUpdateService();
if (pUpdate != NULL) {
destroyUpdateService();
pUpdate->stop(); // we delete them below
pUpdate->executeDelete();
}
pUpdate->stop();
pDevInfo->stop();
pUpdate->stop(); // we delete them below
pDevInfo->executeDelete();
// First shutdown bluetooth
BLEDevice::deinit(false);
@@ -235,14 +239,16 @@ void deinitBLE()
// do not delete this - it is dynamically allocated, but only once - statically in BLEDevice
// delete pServer->getAdvertising();
delete pUpdate;
if (pUpdate != NULL)
delete pUpdate;
delete pDevInfo;
delete pServer;
batteryLevelC = NULL; // Don't let anyone generate bogus notifies
for (int i = 0; i < numChars; i++)
for (int i = 0; i < numChars; i++) {
delete chars[i];
}
numChars = 0;
for (int i = 0; i < numDescs; i++)
@@ -276,15 +282,19 @@ BLEServer *initBLE(StartBluetoothPinScreenCallback startBtPinScreen, StopBluetoo
// We now let users create the battery service only if they really want (not all devices have a battery)
// BLEService *pBattery = createBatteryService(pServer);
// #define BLE_SOFTWARE_UPDATE
#ifdef BLE_SOFTWARE_UPDATE
pUpdate = createUpdateService(pServer, hwVendor, swVersion,
hwVersion); // We need to advertise this so our android ble scan operation can see it
pUpdate->start();
#endif
// It seems only one service can be advertised - so for now don't advertise our updater
// pServer->getAdvertising()->addServiceUUID(pUpdate->getUUID());
// start all our services (do this after creating all of them)
pDevInfo->start();
pUpdate->start();
// FIXME turn on this restriction only after the device is paired with a phone
// advert->setScanFilter(false, true); // We let anyone scan for us (FIXME, perhaps only allow that until we are paired with a
@@ -293,7 +303,11 @@ BLEServer *initBLE(StartBluetoothPinScreenCallback startBtPinScreen, StopBluetoo
static BLESecurity security; // static to avoid allocs
BLESecurity *pSecurity = &security;
pSecurity->setCapability(ESP_IO_CAP_OUT);
// FIXME - really should be ESP_LE_AUTH_REQ_SC_BOND but it seems there is a bug right now causing that bonding info to be lost
// occasionally?
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
return pServer;

View File

@@ -1,33 +1,12 @@
#pragma once
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
#include "BLECharacteristic.h"
/**
* This mixin just lets the power management state machine know the phone is still talking to us
*/
class BLEKeepAliveCallbacks : public BLECharacteristicCallbacks
{
public:
void onRead(BLECharacteristic *c)
{
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
}
void onWrite(BLECharacteristic *c)
{
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
}
};
#include "PowerFSM.h" // FIXME - someday I want to make this OTA thing a separate lb at at that point it can't touch this
/**
* A characterstic with a set of overridable callbacks
*/
class CallbackCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks
class CallbackCharacteristic : public BLECharacteristic, public BLECharacteristicCallbacks
{
public:
CallbackCharacteristic(const char *uuid, uint32_t btprops)
: BLECharacteristic(uuid, btprops)
{
setCallbacks(this);
}
public:
CallbackCharacteristic(const char *uuid, uint32_t btprops) : BLECharacteristic(uuid, btprops) { setCallbacks(this); }
};

View File

@@ -23,9 +23,6 @@ static CallbackCharacteristic *meshFromNumCharacteristic;
BLEService *meshService;
// If defined we will also support the old API
#define SUPPORT_OLD_BLE_API
class BluetoothPhoneAPI : public PhoneAPI
{
/**
@@ -44,150 +41,6 @@ class BluetoothPhoneAPI : public PhoneAPI
BluetoothPhoneAPI *bluetoothPhoneAPI;
class ProtobufCharacteristic : public CallbackCharacteristic
{
const pb_msgdesc_t *fields;
void *my_struct;
public:
ProtobufCharacteristic(const char *uuid, uint32_t btprops, const pb_msgdesc_t *_fields, void *_my_struct)
: CallbackCharacteristic(uuid, btprops), fields(_fields), my_struct(_my_struct)
{
setCallbacks(this);
}
void onRead(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onRead(c);
size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), fields, my_struct);
DEBUG_MSG("pbread from %s returns %d bytes\n", c->getUUID().toString().c_str(), numbytes);
c->setValue(trBytes, numbytes);
}
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
writeToDest(c, my_struct);
}
protected:
/// like onWrite, but we provide an different destination to write to, for use by subclasses that
/// want to optionally ignore parts of writes.
/// returns true for success
bool writeToDest(BLECharacteristic *c, void *dest)
{
// dumpCharacteristic(pCharacteristic);
std::string src = c->getValue();
DEBUG_MSG("pbwrite to %s of %d bytes\n", c->getUUID().toString().c_str(), src.length());
return pb_decode_from_bytes((const uint8_t *)src.c_str(), src.length(), fields, dest);
}
};
#ifdef SUPPORT_OLD_BLE_API
class NodeInfoCharacteristic : public BLECharacteristic, public BLEKeepAliveCallbacks
{
public:
NodeInfoCharacteristic()
: BLECharacteristic("d31e02e0-c8ab-4d3f-9cc9-0b8466bdabe8",
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ)
{
setCallbacks(this);
}
void onRead(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onRead(c);
const NodeInfo *info = nodeDB.readNextInfo();
if (info) {
DEBUG_MSG("Sending nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s\n", info->num, info->position.time, info->user.id,
info->user.long_name);
size_t numbytes = pb_encode_to_bytes(trBytes, sizeof(trBytes), NodeInfo_fields, info);
c->setValue(trBytes, numbytes);
} else {
c->setValue(trBytes, 0); // Send an empty response
DEBUG_MSG("Done sending nodeinfos\n");
}
}
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
DEBUG_MSG("Reset nodeinfo read pointer\n");
nodeDB.resetReadPointer();
}
};
// wrap our protobuf version with something that forces the service to reload the config
class RadioCharacteristic : public ProtobufCharacteristic
{
public:
RadioCharacteristic()
: ProtobufCharacteristic("b56786c8-839a-44a1-b98e-a1724c4a0262",
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ, RadioConfig_fields,
&radioConfig)
{
}
void onRead(BLECharacteristic *c)
{
DEBUG_MSG("Reading radio config, sdsecs %u\n", radioConfig.preferences.sds_secs);
ProtobufCharacteristic::onRead(c);
}
void onWrite(BLECharacteristic *c)
{
DEBUG_MSG("Writing radio config\n");
ProtobufCharacteristic::onWrite(c);
bluetoothPhoneAPI->handleSetRadio(radioConfig);
}
};
// wrap our protobuf version with something that forces the service to reload the owner
class OwnerCharacteristic : public ProtobufCharacteristic
{
public:
OwnerCharacteristic()
: ProtobufCharacteristic("6ff1d8b6-e2de-41e3-8c0b-8fa384f64eb6",
BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_READ, User_fields, &owner)
{
}
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(
c); // NOTE: We do not call the standard ProtobufCharacteristic superclass, because we want custom write behavior
static User o; // if the phone doesn't set ID we are careful to keep ours, we also always keep our macaddr
if (writeToDest(c, &o)) {
bluetoothPhoneAPI->handleSetOwner(o);
}
}
};
class MyNodeInfoCharacteristic : public ProtobufCharacteristic
{
public:
MyNodeInfoCharacteristic()
: ProtobufCharacteristic("ea9f3f82-8dc4-4733-9452-1f6da28892a2", BLECharacteristic::PROPERTY_READ, MyNodeInfo_fields,
&myNodeInfo)
{
}
void onRead(BLECharacteristic *c)
{
// update gps connection state
myNodeInfo.has_gps = gps->isConnected;
ProtobufCharacteristic::onRead(c);
myNodeInfo.error_code = 0; // The phone just read us, so throw it away
myNodeInfo.error_address = 0;
}
};
#endif
class ToRadioCharacteristic : public CallbackCharacteristic
{
@@ -196,9 +49,6 @@ class ToRadioCharacteristic : public CallbackCharacteristic
void onWrite(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onWrite(c);
DEBUG_MSG("Got on write\n");
bluetoothPhoneAPI->handleToRadio(c->getData(), c->getValue().length());
}
};
@@ -212,7 +62,6 @@ class FromRadioCharacteristic : public CallbackCharacteristic
void onRead(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onRead(c);
size_t numBytes = bluetoothPhoneAPI->getFromRadio(trBytes);
// Someone is going to read our value as soon as this callback returns. So fill it with the next message in the queue
@@ -236,11 +85,7 @@ class FromNumCharacteristic : public CallbackCharacteristic
// observe(&service.fromNumChanged);
}
void onRead(BLECharacteristic *c)
{
BLEKeepAliveCallbacks::onRead(c);
DEBUG_MSG("FIXME implement fromnum read\n");
}
void onRead(BLECharacteristic *c) { DEBUG_MSG("FIXME implement fromnum read\n"); }
};
/*
@@ -263,12 +108,6 @@ BLEService *createMeshBluetoothService(BLEServer *server)
addWithDesc(service, meshFromNumCharacteristic, "fromRadio");
addWithDesc(service, new ToRadioCharacteristic, "toRadio");
addWithDesc(service, new FromRadioCharacteristic, "fromNum");
#ifdef SUPPORT_OLD_BLE_API
addWithDesc(service, new MyNodeInfoCharacteristic, "myNode");
addWithDesc(service, new RadioCharacteristic, "radio");
addWithDesc(service, new OwnerCharacteristic, "owner");
addWithDesc(service, new NodeInfoCharacteristic, "nodeinfo");
#endif
meshFromNumCharacteristic->addDescriptor(addBLEDescriptor(new BLE2902())); // Needed so clients can request notification
@@ -292,6 +131,7 @@ void stopMeshBluetoothService()
{
assert(meshService);
meshService->stop();
meshService->executeDelete();
}
void destroyMeshBluetoothService()

View File

@@ -4,6 +4,7 @@
#include "configuration.h"
#include "main.h"
#include "power.h"
#include "sleep.h"
#include "target_specific.h"
bool bluetoothOn;
@@ -154,12 +155,31 @@ void axp192Init()
}
#endif
/*
static void printBLEinfo() {
int dev_num = esp_ble_get_bond_device_num();
esp_ble_bond_dev_t *dev_list = (esp_ble_bond_dev_t *)malloc(sizeof(esp_ble_bond_dev_t) * dev_num);
esp_ble_get_bond_device_list(&dev_num, dev_list);
for (int i = 0; i < dev_num; i++) {
// esp_ble_remove_bond_device(dev_list[i].bd_addr);
}
} */
void esp32Setup()
{
uint32_t seed = esp_random();
DEBUG_MSG("Setting random seed %u\n", seed);
randomSeed(seed); // ESP docs say this is fairly random
DEBUG_MSG("Total heap: %d\n", ESP.getHeapSize());
DEBUG_MSG("Free heap: %d\n", ESP.getFreeHeap());
DEBUG_MSG("Total PSRAM: %d\n", ESP.getPsramSize());
DEBUG_MSG("Free PSRAM: %d\n", ESP.getFreePsram());
// enableModemSleep();
#ifdef AXP192_SLAVE_ADDRESS
axp192Init();
#endif

View File

@@ -33,6 +33,7 @@
#include "power.h"
// #include "rom/rtc.h"
#include "DSRRouter.h"
#include "debug.h"
#include "main.h"
#include "screen.h"
#include "sleep.h"
@@ -282,6 +283,8 @@ void loop()
DEBUG_PORT.loop(); // Send/receive protobufs over the serial port
#endif
// heap_caps_check_integrity_all(true); // FIXME - disable this expensive check
#ifndef NO_ESP32
esp32Loop();
#endif
@@ -314,6 +317,14 @@ void loop()
showingBootScreen = false;
}
#ifdef DEBUG_STACK
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 10 * 1000L) {
lastPrint = millis();
meshtastic::printThreadInfo("main");
}
#endif
// Update the screen last, after we've figured out what to show.
screen.debug()->setNodeNumbersStatus(nodeDB.getNumOnlineNodes(), nodeDB.getNumNodes());
screen.debug()->setChannelNameStatus(channelSettings.name);

View File

@@ -5,12 +5,80 @@
#include "PointerQueue.h"
template <class T> class Allocator
{
public:
virtual ~Allocator() {}
/// Return a queable object which has been prefilled with zeros. Panic if no buffer is available
/// Note: this method is safe to call from regular OR ISR code
T *allocZeroed()
{
T *p = allocZeroed(0);
assert(p); // FIXME panic instead
return p;
}
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you probably
/// don't want this version).
T *allocZeroed(TickType_t maxWait)
{
T *p = alloc(maxWait);
if (p)
memset(p, 0, sizeof(T));
return p;
}
/// Return a queable object which is a copy of some other object
T *allocCopy(const T &src, TickType_t maxWait = portMAX_DELAY)
{
T *p = alloc(maxWait);
assert(p);
if (p)
*p = src;
return p;
}
/// Return a buffer for use by others
virtual void release(T *p) = 0;
protected:
// Alloc some storage
virtual T *alloc(TickType_t maxWait) = 0;
};
/**
* An allocator that just uses regular free/malloc
*/
template <class T> class MemoryDynamic : public Allocator<T>
{
public:
/// Return a buffer for use by others
virtual void release(T *p)
{
assert(p);
free(p);
}
protected:
// Alloc some storage
virtual T *alloc(TickType_t maxWait)
{
T *p = (T *)malloc(sizeof(T));
assert(p);
return p;
}
};
/**
* A pool based allocator
*
* Eventually this routine will even be safe for ISR use...
*/
template <class T> class MemoryPool
template <class T> class MemoryPool : public Allocator<T>
{
PointerQueue<T> dead;
@@ -30,39 +98,8 @@ template <class T> class MemoryPool
~MemoryPool() { delete[] buf; }
/// Return a queable object which has been prefilled with zeros. Panic if no buffer is available
/// Note: this method is safe to call from regular OR ISR code
T *allocZeroed()
{
T *p = allocZeroed(0);
assert(p); // FIXME panic instead
return p;
}
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you probably
/// don't want this version).
T *allocZeroed(TickType_t maxWait)
{
T *p = dead.dequeuePtr(maxWait);
if (p)
memset(p, 0, sizeof(T));
return p;
}
/// Return a queable object which is a copy of some other object
T *allocCopy(const T &src, TickType_t maxWait = portMAX_DELAY)
{
T *p = dead.dequeuePtr(maxWait);
if (p)
*p = src;
return p;
}
/// Return a buffer for use by others
void release(T *p)
virtual void release(T *p)
{
assert(dead.enqueue(p, 0));
assert(p >= buf &&
@@ -78,4 +115,9 @@ template <class T> class MemoryPool
(size_t)(p - buf) <
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
}
protected:
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you
/// probably don't want this version).
virtual T *alloc(TickType_t maxWait) { return dead.dequeuePtr(maxWait); }
};

View File

@@ -86,12 +86,14 @@ void MeshService::sendOurOwner(NodeNum dest, bool wantReplies)
const MeshPacket *MeshService::handleFromRadioUser(const MeshPacket *mp)
{
bool wasBroadcast = mp->to == NODENUM_BROADCAST;
bool isCollision = mp->from == myNodeInfo.my_node_num;
// we win if we have a lower macaddr
bool weWin = memcmp(&owner.macaddr, &mp->decoded.user.macaddr, sizeof(owner.macaddr)) < 0;
// Disable this collision testing if we use 32 bit nodenums
bool isCollision = (sizeof(NodeNum) == 1) && (mp->from == myNodeInfo.my_node_num);
if (isCollision) {
// we win if we have a lower macaddr
bool weWin = memcmp(&owner.macaddr, &mp->decoded.user.macaddr, sizeof(owner.macaddr)) < 0;
if (weWin) {
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
@@ -158,7 +160,7 @@ int MeshService::handleFromRadio(const MeshPacket *mp)
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
if (mp) {
DEBUG_MSG("Forwarding to phone, from=0x%x, rx_time=%u\n", mp->from, mp->rx_time);
printPacket("Forwarding to phone", mp);
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
fromNum++;

View File

@@ -6,8 +6,8 @@
#include "mesh.pb.h"
#include <Arduino.h>
typedef uint8_t NodeNum;
typedef uint8_t PacketId; // A packet sequence number
typedef uint32_t NodeNum;
typedef uint32_t PacketId; // A packet sequence number
#define NODENUM_BROADCAST (sizeof(NodeNum) == 4 ? UINT32_MAX : UINT8_MAX)
#define ERRNO_OK 0
@@ -29,4 +29,4 @@ typedef uint8_t PacketId; // A packet sequence number
typedef int ErrorCode;
/// Alloc and free packets to our global, ISR safe pool
extern MemoryPool<MeshPacket> packetPool;
extern Allocator<MeshPacket> &packetPool;

View File

@@ -30,7 +30,7 @@ DeviceState versions used to be defined in the .proto file but really only this
#define here.
*/
#define DEVICESTATE_CUR_VER 8
#define DEVICESTATE_CUR_VER 10
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
#ifndef NO_ESP32
@@ -101,10 +101,12 @@ void NodeDB::resetRadioConfig()
crypto->setKey(channelSettings.psk.size, channelSettings.psk.bytes);
// temp hack for quicker testing
/*
radioConfig.preferences.screen_on_secs = 30;
radioConfig.preferences.wait_bluetooth_secs = 30;
radioConfig.preferences.position_broadcast_secs = 15;
radioConfig.preferences.position_broadcast_secs = 6 * 60;
radioConfig.preferences.ls_secs = 60;
*/
}
@@ -114,7 +116,6 @@ void NodeDB::init()
devicestate.has_my_node = true;
devicestate.has_radio = true;
devicestate.has_owner = true;
devicestate.has_radio = false;
devicestate.radio.has_channel_settings = true;
devicestate.radio.has_preferences = true;
devicestate.node_db_count = 0;
@@ -124,10 +125,8 @@ void NodeDB::init()
// default to no GPS, until one has been found by probing
myNodeInfo.has_gps = false;
myNodeInfo.node_num_bits = sizeof(NodeNum) * 8;
myNodeInfo.packet_id_bits = sizeof(PacketId) * 8;
myNodeInfo.message_timeout_msec = FLOOD_EXPIRE_TIME;
myNodeInfo.min_app_version = 167;
myNodeInfo.min_app_version = 172;
generatePacketId(); // FIXME - ugly way to init current_packet_id;
// Init our blank owner info to reasonable defaults
@@ -135,18 +134,13 @@ void NodeDB::init()
sprintf(owner.id, "!%02x%02x%02x%02x%02x%02x", ourMacAddr[0], ourMacAddr[1], ourMacAddr[2], ourMacAddr[3], ourMacAddr[4],
ourMacAddr[5]);
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
// Set default owner name
pickNewNodeNum(); // Note: we will repick later, just in case the settings are corrupted, but we need a valid
// owner.short_name now
sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]);
// Crummy guess at our nodenum
pickNewNodeNum();
sprintf(owner.short_name, "?%02X", myNodeInfo.my_node_num & 0xff);
// Include our owner in the node db under our nodenum
NodeInfo *info = getOrCreateNode(getNodeNum());
info->user = owner;
info->has_user = true;
if (!FSBegin()) // FIXME - do this in main?
{
DEBUG_MSG("ERROR filesystem mount Failed\n");
@@ -157,6 +151,20 @@ void NodeDB::init()
loadFromDisk();
// saveToDisk();
// We set node_num and packet_id _after_ loading from disk, because we always want to use the values this
// rom was compiled for, not what happens to be in the save file.
myNodeInfo.node_num_bits = sizeof(NodeNum) * 8;
myNodeInfo.packet_id_bits = sizeof(PacketId) * 8;
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
pickNewNodeNum();
// Include our owner in the node db under our nodenum
NodeInfo *info = getOrCreateNode(getNodeNum());
info->user = owner;
info->has_user = true;
// We set these _after_ loading from disk - because they come from the build and are more trusted than
// what is stored in flash
strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region));
@@ -176,9 +184,12 @@ void NodeDB::init()
*/
void NodeDB::pickNewNodeNum()
{
// Pick an initial nodenum based on the macaddr
NodeNum r = sizeof(NodeNum) == 1 ? ourMacAddr[5]
: ((ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]);
NodeNum r = myNodeInfo.my_node_num;
// If we don't have a nodenum at app - pick an initial nodenum based on the macaddr
if (r == 0)
r = sizeof(NodeNum) == 1 ? ourMacAddr[5]
: ((ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]);
if (r == NODENUM_BROADCAST || r < NUM_RESERVED)
r = NUM_RESERVED; // don't pick a reserved node number
@@ -247,15 +258,18 @@ void NodeDB::saveToDisk()
if (!pb_encode(&stream, DeviceState_fields, &devicestate)) {
DEBUG_MSG("Error: can't write protobuf %s\n", PB_GET_ERROR(&stream));
// FIXME - report failure to phone
f.close();
} else {
// Success - replace the old file
f.close();
// brief window of risk here ;-)
if (!FS.remove(preffile))
DEBUG_MSG("Warning: Can't remove old pref file\n");
if (!FS.rename(preftmp, preffile))
DEBUG_MSG("Error: can't rename new pref file\n");
}
f.close();
// brief window of risk here ;-)
if (!FS.remove(preffile))
DEBUG_MSG("Warning: Can't remove old pref file\n");
if (!FS.rename(preftmp, preffile))
DEBUG_MSG("Error: can't rename new pref file\n");
} else {
DEBUG_MSG("ERROR: can't write prefs\n"); // FIXME report to app
}

View File

@@ -2,8 +2,6 @@
#include "configuration.h"
#include "mesh-pb-constants.h"
PacketHistory::PacketHistory()
{
recentPackets.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation
@@ -48,7 +46,7 @@ bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
r.sender = p->from;
r.rxTimeMsec = now;
recentPackets.push_back(r);
DEBUG_MSG("Adding packet record for fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
printPacket("Adding packet record", p);
}
return false;

View File

@@ -1,6 +1,8 @@
#include "PhoneAPI.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RadioInterface.h"
#include <assert.h>
PhoneAPI::PhoneAPI()
@@ -14,16 +16,35 @@ void PhoneAPI::init()
observe(&service.fromNumChanged);
}
void PhoneAPI::checkConnectionTimeout()
{
if (isConnected) {
bool newConnected = (millis() - lastContactMsec < radioConfig.preferences.phone_timeout_secs * 1000L);
if (!newConnected) {
isConnected = false;
onConnectionChanged(isConnected);
}
}
}
/**
* Handle a ToRadio protobuf
*/
void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
{
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); // As long as the phone keeps talking to us, don't let the radio go to sleep
lastContactMsec = millis();
if (!isConnected) {
isConnected = true;
onConnectionChanged(isConnected);
}
// return (lastContactMsec != 0) &&
if (pb_decode_from_bytes(buf, bufLength, ToRadio_fields, &toRadioScratch)) {
switch (toRadioScratch.which_variant) {
case ToRadio_packet_tag: {
// If our phone is sending a position, see if we can use it to set our RTC
MeshPacket &p = toRadioScratch.variant.packet;
printPacket("PACKET FROM PHONE", &p);
service.handleToRadio(p);
break;
}
@@ -71,8 +92,12 @@ void PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength)
*/
size_t PhoneAPI::getFromRadio(uint8_t *buf)
{
if (!available())
if (!available()) {
DEBUG_MSG("getFromRadio, !available\n");
return false;
} else {
DEBUG_MSG("getFromRadio, state=%d\n", state);
}
// In case we send a FromRadio packet
memset(&fromRadioScratch, 0, sizeof(fromRadioScratch));
@@ -227,6 +252,9 @@ void PhoneAPI::handleToRadioPacket(MeshPacket *p) {}
/// If the mesh service tells us fromNum has changed, tell the phone
int PhoneAPI::onNotify(uint32_t newValue)
{
checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this
// from idle)
if (state == STATE_SEND_PACKETS || state == STATE_LEGACY) {
DEBUG_MSG("Telling client we have new packets %u\n", newValue);
onNowHasData(newValue);

View File

@@ -50,6 +50,11 @@ class PhoneAPI
/// Use to ensure that clients don't get confused about old messages from the radio
uint32_t config_nonce = 0;
/** the last msec we heard from the client on the other side of this link */
uint32_t lastContactMsec = 0;
bool isConnected = false;
public:
PhoneAPI();
@@ -85,6 +90,12 @@ class PhoneAPI
/// Our fromradio packet while it is being assembled
FromRadio fromRadioScratch;
/// Hookable to find out when connection changes
virtual void onConnectionChanged(bool connected) {}
/// If we haven't heard from the other side in a while then say not connected
void checkConnectionTimeout();
/**
* Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies)
*/

View File

@@ -24,7 +24,53 @@ separated by 2.16 MHz with respect to the adjacent channels. Channel zero starts
// 1kb was too small
#define RADIO_STACK_SIZE 4096
RadioInterface::RadioInterface() : txQueue(MAX_TX_QUEUE)
void printPacket(const char *prefix, const MeshPacket *p)
{
DEBUG_MSG("%s (id=0x%08x Fr0x%02x To0x%02x, WantAck%d, HopLim%d", prefix, p->id, p->from & 0xff, p->to & 0xff, p->want_ack,
p->hop_limit);
if (p->which_payload == MeshPacket_decoded_tag) {
auto &s = p->decoded;
switch (s.which_payload) {
case SubPacket_data_tag:
DEBUG_MSG(" Payload:Data");
break;
case SubPacket_position_tag:
DEBUG_MSG(" Payload:Position");
break;
case SubPacket_user_tag:
DEBUG_MSG(" Payload:User");
break;
case 0:
DEBUG_MSG(" Payload:None");
break;
default:
DEBUG_MSG(" Payload:%d", s.which_payload);
break;
}
if (s.want_response)
DEBUG_MSG(" WANTRESP");
if (s.source != 0)
DEBUG_MSG(" source=%08x", s.source);
if (s.dest != 0)
DEBUG_MSG(" dest=%08x", s.dest);
if (s.which_ack == SubPacket_success_id_tag)
DEBUG_MSG(" successId=%08x", s.ack.success_id);
else if (s.which_ack == SubPacket_fail_id_tag)
DEBUG_MSG(" failId=%08x", s.ack.fail_id);
} else {
DEBUG_MSG(" encrypted");
}
if (p->rx_time != 0) {
DEBUG_MSG(" rxtime=%u", p->rx_time);
}
DEBUG_MSG(")\n");
}
RadioInterface::RadioInterface()
{
assert(sizeof(PacketHeader) == 4 || sizeof(PacketHeader) == 16); // make sure the compiler did what we expected

View File

@@ -59,7 +59,6 @@ class RadioInterface : protected NotifiedWorkerThread
protected:
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
PointerQueue<MeshPacket> txQueue;
uint32_t lastTxStart = 0L;
/**
@@ -163,3 +162,6 @@ class SimRadio : public RadioInterface
/// \return true if initialisation succeeded.
virtual bool init() { return true; }
};
/// Debug printing for packets
void printPacket(const char *prefix, const MeshPacket *p);

View File

@@ -114,8 +114,8 @@ bool RadioLibInterface::canSendImmediately()
/// bluetooth comms code. If the txmit queue is empty it might return an error
ErrorCode RadioLibInterface::send(MeshPacket *p)
{
DEBUG_MSG("enqueuing for send on mesh fr=0x%x,to=0x%x,id=%d (txGood=%d,rxGood=%d,rxBad=%d)\n", p->from, p->to, p->id, txGood,
rxGood, rxBad);
printPacket("enqueuing for send", p);
DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad);
ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN;
if (res != ERRNO_OK) { // we weren't able to queue it, so we must drop it to prevent leaks
@@ -134,7 +134,7 @@ bool RadioLibInterface::canSleep()
{
bool res = txQueue.isEmpty();
if (!res) // only print debug messages if we are vetoing sleep
DEBUG_MSG("radio wait to sleep, txEmpty=%d\n", txQueue.isEmpty());
DEBUG_MSG("radio wait to sleep, txEmpty=%d\n", res);
return res;
}
@@ -173,11 +173,13 @@ void RadioLibInterface::loop()
case ISR_TX:
handleTransmitInterrupt();
startReceive();
// DEBUG_MSG("tx complete - starting timer\n");
startTransmitTimer();
break;
case ISR_RX:
handleReceiveInterrupt();
startReceive();
// DEBUG_MSG("rx complete - starting timer\n");
startTransmitTimer();
break;
case TRANSMIT_DELAY_COMPLETED:
@@ -192,6 +194,8 @@ void RadioLibInterface::loop()
assert(txp);
startSend(txp);
}
} else {
// DEBUG_MSG("done with txqueue\n");
}
break;
default:
@@ -216,7 +220,7 @@ void RadioLibInterface::startTransmitTimer(bool withDelay)
uint32_t delay =
!withDelay ? 1 : random(MIN_TX_WAIT_MSEC, MAX_TX_WAIT_MSEC); // See documentation for loop() wrt these values
// DEBUG_MSG("xmit timer %d\n", delay);
// DEBUG_MSG("delaying %u\n", delay);
setPeriod(delay);
}
}
@@ -233,7 +237,7 @@ void RadioLibInterface::completeSending()
{
if (sendingPacket) {
txGood++;
DEBUG_MSG("Completed sending to=0x%x, id=%u\n", sendingPacket->to, sendingPacket->id);
printPacket("Completed sending", sendingPacket);
// We are done sending that packet, release it
packetPool.release(sendingPacket);
@@ -287,7 +291,7 @@ void RadioLibInterface::handleReceiveInterrupt()
memcpy(mp->encrypted.bytes, payload, payloadLen);
mp->encrypted.size = payloadLen;
DEBUG_MSG("Lora RX interrupt from=0x%x, id=%u\n", mp->from, mp->id);
printPacket("Lora RX", mp);
deliverToReceiver(mp);
}
@@ -297,7 +301,7 @@ void RadioLibInterface::handleReceiveInterrupt()
/** start an immediate transmit */
void RadioLibInterface::startSend(MeshPacket *txp)
{
DEBUG_MSG("Starting low level send from=0x%x, to=0x%x, id=%u, want_ack=%d\n", txp->from, txp->to, txp->id, txp->want_ack);
printPacket("Starting low level send", txp);
setStandby(); // Cancel any already in process receives
size_t numbytes = beginSending(txp);

View File

@@ -29,6 +29,8 @@ class RadioLibInterface : public RadioInterface, private PeriodicTask
*/
uint32_t rxBad = 0, rxGood = 0, txGood = 0;
PointerQueue<MeshPacket> txQueue = PointerQueue<MeshPacket>(MAX_TX_QUEUE);
protected:
float bw = 125;
uint8_t sf = 9;

View File

@@ -27,7 +27,7 @@ ErrorCode ReliableRouter::send(MeshPacket *p)
bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
{
if (p->to == NODENUM_BROADCAST && p->from == getNodeNum()) {
DEBUG_MSG("Received someone rebroadcasting for us fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
printPacket("Rx someone rebroadcasting for us", p);
// We are seeing someone rebroadcast one of our broadcast attempts.
// If this is the first time we saw this, cancel any retransmissions we have queued up and generate an internal ack for

View File

@@ -19,11 +19,15 @@
4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big
// I think this is right, one packet for each of the three fifos + one packet being currently assembled for TX or RX
// And every TX packet might have a retransmission packet or an ack alive at any moment
#define MAX_PACKETS \
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + MAX_TX_QUEUE + \
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + 2 * MAX_TX_QUEUE + \
2) // max number of packets which can be in flight (either queued from reception or queued for sending)
MemoryPool<MeshPacket> packetPool(MAX_PACKETS);
static MemoryPool<MeshPacket> staticPool(MAX_PACKETS);
// static MemoryDynamic<MeshPacket> staticPool;
Allocator<MeshPacket> &packetPool = staticPool;
/**
* Constructor
@@ -56,8 +60,11 @@ PacketId generatePacketId()
if (!didInit) {
didInit = true;
i = random(0, numPacketId +
1); // pick a random initial sequence number at boot (to prevent repeated reboots always starting at 0)
// pick a random initial sequence number at boot (to prevent repeated reboots always starting at 0)
// Note: we mask the high order bit to ensure that we never pass a 'negative' number to random
i = random(numPacketId & 0x7fffffff);
DEBUG_MSG("Initial packet id %u, numPacketId %u\n", i, numPacketId);
}
i++;
@@ -143,8 +150,8 @@ ErrorCode Router::send(MeshPacket *p)
*/
void Router::sniffReceived(const MeshPacket *p)
{
DEBUG_MSG("FIXME-update-db Sniffing packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
// FIXME, update nodedb
DEBUG_MSG("FIXME-update-db Sniffing packet\n");
// FIXME, update nodedb here for any packet that passes through us
}
bool Router::perhapsDecode(MeshPacket *p)
@@ -195,7 +202,7 @@ void Router::handleReceived(MeshPacket *p)
sniffReceived(p);
if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) {
DEBUG_MSG("Notifying observers of received packet fr=0x%x,to=0x%x,id=%d\n", p->from, p->to, p->id);
printPacket("Delivering rx packet", p);
notifyPacketReceived.notifyObservers(p);
}
}

View File

@@ -9,6 +9,7 @@ void StreamAPI::loop()
{
writeStream();
readStream();
checkConnectionTimeout();
}
/**

View File

@@ -9,7 +9,7 @@
PB_BIND(Position, Position, AUTO)
PB_BIND(Data, Data, 2)
PB_BIND(Data, Data, AUTO)
PB_BIND(User, User, AUTO)

View File

@@ -47,7 +47,7 @@ typedef struct _ChannelSettings {
char name[12];
} ChannelSettings;
typedef PB_BYTES_ARRAY_T(251) Data_payload_t;
typedef PB_BYTES_ARRAY_T(240) Data_payload_t;
typedef struct _Data {
Data_Type typ;
Data_payload_t payload;
@@ -586,20 +586,20 @@ extern const pb_msgdesc_t ManufacturingData_msg;
/* Maximum encoded size of messages (where known) */
#define Position_size 39
#define Data_size 256
#define Data_size 245
#define User_size 72
#define RouteDiscovery_size 88
#define SubPacket_size 285
#define MeshPacket_size 324
#define SubPacket_size 274
#define MeshPacket_size 313
#define ChannelSettings_size 60
#define RadioConfig_size 157
#define RadioConfig_UserPreferences_size 93
#define NodeInfo_size 132
#define MyNodeInfo_size 110
#define DeviceState_size 15463
#define DeviceState_size 15100
#define DebugString_size 258
#define FromRadio_size 333
#define ToRadio_size 327
#define FromRadio_size 322
#define ToRadio_size 316
/* ManufacturingData_size depends on runtime parameters */
#ifdef __cplusplus

View File

@@ -33,4 +33,18 @@ class UC1701Spi : public OLEDDisplay
void display(void) {}
private:
};
};
#include "variant.h"
#include <UC1701.h>
static UC1701 lcd(PIN_SPI_SCK, PIN_SPI_MOSI, ERC12864_CS, ERC12864_CD);
void testLCD() {
// PCD8544-compatible displays may have a different resolution...
lcd.begin();
// Write a piece of text on the first line...
lcd.setCursor(0, 0);
lcd.print("Hello, World!");
}

View File

@@ -14,6 +14,7 @@
#include "esp_pm.h"
#include "rom/rtc.h"
#include <driver/rtc_io.h>
#include <driver/uart.h>
#include "BluetoothUtil.h"
@@ -111,8 +112,7 @@ void initDeepSleep()
#endif
}
/// return true if sleep is allowed
static bool doPreflightSleep()
bool doPreflightSleep()
{
if (preflightSleep.notifyObservers(NULL) != 0)
return false; // vetoed
@@ -129,6 +129,7 @@ static void waitEnterSleep()
if (millis() - now > 30 * 1000) { // If we wait too long just report an error and go to sleep
recordCriticalError(ErrSleepEnterWait);
ESP.restart(); // FIXME - for now we just restart, need to fix bug #167
break;
}
}
@@ -256,6 +257,17 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
#endif
#ifdef SERIAL0_RX_GPIO
// We treat the serial port as a GPIO for a fast/low power way of waking, if we see a rising edge that means
// someone started to send something
// Alas - doesn't work reliably, instead need to use the uart specific version (which burns a little power)
// FIXME: gpio 3 is RXD for serialport 0 on ESP32
// Send a few Z characters to wake the port
gpio_wakeup_enable((gpio_num_t)SERIAL0_RX_GPIO, GPIO_INTR_LOW_LEVEL);
// uart_set_wakeup_threshold(UART_NUM_0, 3);
// esp_sleep_enable_uart_wakeup(0);
#endif
#ifdef BUTTON_PIN
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
#endif
@@ -279,7 +291,7 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
}
#endif
#if 0
// not legal on the stock android ESP build
/**
@@ -294,8 +306,8 @@ void enableModemSleep()
static esp_pm_config_esp32_t config; // filled with zeros because bss
config.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
config.min_freq_mhz = 10; // 10Mhz is minimum recommended
config.min_freq_mhz = 20; // 10Mhz is minimum recommended
config.light_sleep_enable = false;
DEBUG_MSG("Sleep request result %x\n", esp_pm_configure(&config));
}
#endif

View File

@@ -19,6 +19,9 @@ void initDeepSleep();
void setCPUFast(bool on);
void setLed(bool ledOn);
/** return true if sleep is allowed right now */
bool doPreflightSleep();
extern int bootCount;
// is bluetooth sw currently running?
@@ -31,4 +34,6 @@ extern Observable<void *> preflightSleep;
extern Observable<void *> notifySleep;
/// Called to tell observers we are now entering (deep) sleep and you should prepare. Must return 0
extern Observable<void *> notifyDeepSleep;
extern Observable<void *> notifyDeepSleep;
void enableModemSleep();

View File

@@ -132,7 +132,7 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define SX1262_CS (10)
#define SX1262_DIO1 (20)
#define SX1262_DIO2 (26)
#define SX1262_BUSY (18)
#define SX1262_BUSY (31) // Supposed to be P0.18 but because of reworks, now on P0.31 (18)
#define SX1262_RESET (17)
// #define SX1262_ANT_SW (32 + 10)
#define SX1262_RXEN (22)