Compare commits
40 Commits
evo-build-
...
v1.11.0_0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4ee93aceb | ||
|
|
46a9164622 | ||
|
|
ca5a8ecb16 | ||
|
|
7682f1085c | ||
|
|
c9d6927d26 | ||
|
|
0b947f9d1b | ||
|
|
1798e44f01 | ||
|
|
4fd7aa6ce8 | ||
|
|
94d44eb47c | ||
|
|
f8f9cddb47 | ||
|
|
6b52fb3230 | ||
|
|
a93527a474 | ||
|
|
9b08a9bd93 | ||
|
|
27c92d2fe9 | ||
|
|
e563529cc5 | ||
|
|
09a20d72e7 | ||
|
|
2228214ded | ||
|
|
2bcc9c10d2 | ||
|
|
14f00fe688 | ||
|
|
ce3b6e67f9 | ||
|
|
922e378be5 | ||
|
|
3a497a4b99 | ||
|
|
5871c69f6f | ||
|
|
802de27e03 | ||
|
|
1f5659dd26 | ||
|
|
cae37d8892 | ||
|
|
6d3219329f | ||
|
|
9405e8bee3 | ||
|
|
8b68b5a689 | ||
|
|
b2dcb06197 | ||
|
|
da5dbcd274 | ||
|
|
3e3fa5b443 | ||
|
|
f5f5886327 | ||
|
|
6ee0b85195 | ||
|
|
86225cd24a | ||
|
|
f594f2c7e6 | ||
|
|
3dc04deabf | ||
|
|
c8a6bcf57f | ||
|
|
4e886bfa90 | ||
|
|
816d4e2fa3 |
15
README.md
15
README.md
@@ -97,10 +97,10 @@ Here are some general principals you should try to adhere to:
|
|||||||
|
|
||||||
There are a number of fairly major features in the pipeline, with no particular time-frames attached yet. In very rough chronological order:
|
There are a number of fairly major features in the pipeline, with no particular time-frames attached yet. In very rough chronological order:
|
||||||
- [X] Companion radio: UI redesign
|
- [X] Companion radio: UI redesign
|
||||||
- [ ] Repeater + Room Server: add ACL's (like Sensor Node has)
|
- [X] Repeater + Room Server: add ACL's (like Sensor Node has)
|
||||||
- [ ] Standardise Bridge mode for repeaters
|
- [X] Standardise Bridge mode for repeaters
|
||||||
- [ ] Repeater/Bridge: Standardise the Transport Codes for zoning/filtering
|
- [ ] Repeater/Bridge: Standardise the Transport Codes for zoning/filtering
|
||||||
- [ ] Core + Repeater: enhanced zero-hop neighbour discovery
|
- [X] Core + Repeater: enhanced zero-hop neighbour discovery
|
||||||
- [ ] Core: round-trip manual path support
|
- [ ] Core: round-trip manual path support
|
||||||
- [ ] Companion + Apps: support for multiple sub-meshes (and 'off-grid' client repeat mode)
|
- [ ] Companion + Apps: support for multiple sub-meshes (and 'off-grid' client repeat mode)
|
||||||
- [ ] Core + Apps: support for LZW message compression
|
- [ ] Core + Apps: support for LZW message compression
|
||||||
@@ -113,12 +113,3 @@ There are a number of fairly major features in the pipeline, with no particular
|
|||||||
- Report bugs and request features on the [GitHub Issues](https://github.com/ripplebiz/MeshCore/issues) page.
|
- Report bugs and request features on the [GitHub Issues](https://github.com/ripplebiz/MeshCore/issues) page.
|
||||||
- Find additional guides and components on [my site](https://buymeacoffee.com/ripplebiz).
|
- Find additional guides and components on [my site](https://buymeacoffee.com/ripplebiz).
|
||||||
- Join [MeshCore Discord](https://discord.gg/BMwCtwHj5V) to chat with the developers and get help from the community.
|
- Join [MeshCore Discord](https://discord.gg/BMwCtwHj5V) to chat with the developers and get help from the community.
|
||||||
|
|
||||||
## RAK Wireless Board Support in PlatformIO
|
|
||||||
|
|
||||||
Before building/flashing the RAK4631 targets in this project, there is, unfortunately, some patching you have to do to your platformIO packages to make it work. There is a guide here on the process:
|
|
||||||
[RAK Wireless: How to Perform Installation of Board Support Package in PlatformIO](https://learn.rakwireless.com/hc/en-us/articles/26687276346775-How-To-Perform-Installation-of-Board-Support-Package-in-PlatformIO)
|
|
||||||
|
|
||||||
After building, you will need to convert the output firmware.hex file into a .uf2 file you can copy over to your RAK4631 device (after doing a full erase) by using the command `uf2conv.py -f 0xADA52840 -c firmware.hex` with the python script available from:
|
|
||||||
[GitHub: Microsoft - uf2](https://github.com/Microsoft/uf2/blob/master/utils/uf2conv.py)
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"arduino": {
|
|
||||||
"ldscript": "nrf52840_s140_v6.ld"
|
|
||||||
},
|
|
||||||
"core": "nRF5",
|
|
||||||
"cpu": "cortex-m4",
|
|
||||||
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
|
||||||
"f_cpu": "64000000L",
|
|
||||||
"hwids": [
|
|
||||||
[
|
|
||||||
"0x239A",
|
|
||||||
"0x8029"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"0x239A",
|
|
||||||
"0x0029"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"0x239A",
|
|
||||||
"0x002A"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"0x239A",
|
|
||||||
"0x802A"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"usb_product": "WisCore RAK3401 Board",
|
|
||||||
"mcu": "nrf52840",
|
|
||||||
"variant": "WisCore_RAK3401_Board",
|
|
||||||
"bsp": {
|
|
||||||
"name": "adafruit"
|
|
||||||
},
|
|
||||||
"softdevice": {
|
|
||||||
"sd_flags": "-DS140",
|
|
||||||
"sd_name": "s140",
|
|
||||||
"sd_version": "6.1.1",
|
|
||||||
"sd_fwid": "0x00B6"
|
|
||||||
},
|
|
||||||
"bootloader": {
|
|
||||||
"settings_addr": "0xFF000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"connectivity": [
|
|
||||||
"bluetooth"
|
|
||||||
],
|
|
||||||
"debug": {
|
|
||||||
"jlink_device": "nRF52840_xxAA",
|
|
||||||
"svd_path": "nrf52840.svd"
|
|
||||||
},
|
|
||||||
"frameworks": [
|
|
||||||
"arduino"
|
|
||||||
],
|
|
||||||
"name": "WisCore RAK3401 Board",
|
|
||||||
"upload": {
|
|
||||||
"maximum_ram_size": 248832,
|
|
||||||
"maximum_size": 815104,
|
|
||||||
"speed": 115200,
|
|
||||||
"protocol": "nrfutil",
|
|
||||||
"protocols": [
|
|
||||||
"jlink",
|
|
||||||
"nrfjprog",
|
|
||||||
"nrfutil",
|
|
||||||
"stlink"
|
|
||||||
],
|
|
||||||
"use_1200bps_touch": true,
|
|
||||||
"require_upload_port": true,
|
|
||||||
"wait_for_upload_port": true
|
|
||||||
},
|
|
||||||
"url": "https://www.rakwireless.com",
|
|
||||||
"vendor": "RAKwireless"
|
|
||||||
}
|
|
||||||
163
docs/faq.md
163
docs/faq.md
@@ -26,6 +26,10 @@ author: https://github.com/LitBomb<!-- omit from toc -->
|
|||||||
- [3.2. Q: Do I need to set the location for a repeater?](#32-q-do-i-need-to-set-the-location-for-a-repeater)
|
- [3.2. Q: Do I need to set the location for a repeater?](#32-q-do-i-need-to-set-the-location-for-a-repeater)
|
||||||
- [3.3. Q: What is the password to administer a repeater or a room server?](#33-q-what-is-the-password-to-administer-a-repeater-or-a-room-server)
|
- [3.3. Q: What is the password to administer a repeater or a room server?](#33-q-what-is-the-password-to-administer-a-repeater-or-a-room-server)
|
||||||
- [3.4. Q: What is the password to join a room server?](#34-q-what-is-the-password-to-join-a-room-server)
|
- [3.4. Q: What is the password to join a room server?](#34-q-what-is-the-password-to-join-a-room-server)
|
||||||
|
- [3.5. Q: Can I retrieve a repeater's private key or set a repeater's private key?](#35-q-can-i-retrieve-a-repeaters-private-key-or-set-a-repeaters-private-key)
|
||||||
|
- [3.6. Q: The first byte of my repeater's public key collides with an exisitng repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?](#36-q-the-first-byte-of-my-repeaters-public-key-collides-with-an-exisitng-repeater-on-the-mesh--how-do-i-get-a-new-private-key-with-a-matching-public-key-that-has-its-first-byte-of-my-choosing)
|
||||||
|
- [3.7. Q: My repeater maybe suffering from deafness due to high power interference near my mesh's frequency, it is not hearing other in-range MeshCore radios. what can I do?](#37-q-my-repeater-maybe-suffering-from-deafness-due-to-high-power-interference-near-my-meshs-frequency-it-is-not-hearing-other-in-range-meshcore-radios--what-can-i-do)
|
||||||
|
- [3.8 Q: How do I make my repeater an observer on the mesh](#38-q-how-do-i-make-my-repeater-an-observer-on-the-mesh)
|
||||||
- [4. T-Deck Related](#4-t-deck-related)
|
- [4. T-Deck Related](#4-t-deck-related)
|
||||||
- [4.1. Q: Is there a user guide for T-Deck, T-Pager, T-Watch, or T-Display Pro?](#41-q-is-there-a-user-guide-for-t-deck-t-pager-t-watch-or-t-display-pro)
|
- [4.1. Q: Is there a user guide for T-Deck, T-Pager, T-Watch, or T-Display Pro?](#41-q-is-there-a-user-guide-for-t-deck-t-pager-t-watch-or-t-display-pro)
|
||||||
- [4.2. Q: What are the steps to get a T-Deck into DFU (Device Firmware Update) mode?](#42-q-what-are-the-steps-to-get-a-t-deck-into-dfu-device-firmware-update-mode)
|
- [4.2. Q: What are the steps to get a T-Deck into DFU (Device Firmware Update) mode?](#42-q-what-are-the-steps-to-get-a-t-deck-into-dfu-device-firmware-update-mode)
|
||||||
@@ -61,22 +65,31 @@ author: https://github.com/LitBomb<!-- omit from toc -->
|
|||||||
- [5.14.3. Python MeshCore](#5143-python-meshcore)
|
- [5.14.3. Python MeshCore](#5143-python-meshcore)
|
||||||
- [5.14.4. meshcore-cli](#5144-meshcore-cli)
|
- [5.14.4. meshcore-cli](#5144-meshcore-cli)
|
||||||
- [5.14.5. meshcore.js](#5145-meshcorejs)
|
- [5.14.5. meshcore.js](#5145-meshcorejs)
|
||||||
|
- [5.14.6. pyMC\_core](#5146-pymc_core)
|
||||||
|
- [5.14.7. MeshCore Packet Decoder](#5147-meshcore-packet-decoder)
|
||||||
|
- [5.14.8. meshcore-pi](#5148-meshcore-pi)
|
||||||
|
- [5.14.9. pyMC\_Repeater](#5149-pymc_repeater)
|
||||||
|
- [5.15. Q: Are there client applications for Windows or Mac?](#515-q-are-there-client-applications-for-windows-or-mac)
|
||||||
|
- [5.16. Q: Are there any resources that compare MeshCore to other LoRa systems?](#516-q-are-there-any-resources-that-compare-meshcore-to-other-lora-systems)
|
||||||
- [6. Troubleshooting](#6-troubleshooting)
|
- [6. Troubleshooting](#6-troubleshooting)
|
||||||
- [6.1. Q: My client says another client or a repeater or a room server was last seen many, many days ago.](#61-q-my-client-says-another-client-or-a-repeater-or-a-room-server-was-last-seen-many-many-days-ago)
|
- [6.1. Q: My client says another client or a repeater or a room server was last seen many, many days ago.](#61-q-my-client-says-another-client-or-a-repeater-or-a-room-server-was-last-seen-many-many-days-ago)
|
||||||
- [6.2. Q: A repeater or a client or a room server I expect to see on my discover list (on T-Deck) or contact list (on a smart device client) are not listed.](#62-q-a-repeater-or-a-client-or-a-room-server-i-expect-to-see-on-my-discover-list-on-t-deck-or-contact-list-on-a-smart-device-client-are-not-listed)
|
- [6.2. Q: A repeater or a client or a room server I expect to see on my discover list (on T-Deck) or contact list (on a smart device client) are not listed.](#62-q-a-repeater-or-a-client-or-a-room-server-i-expect-to-see-on-my-discover-list-on-t-deck-or-contact-list-on-a-smart-device-client-are-not-listed)
|
||||||
- [6.3. Q: How to connect to a repeater via BLE (Bluetooth)?](#63-q-how-to-connect-to-a-repeater-via-ble-bluetooth)
|
- [6.3. Q: How to connect to a repeater via BLE (Bluetooth)?](#63-q-how-to-connect-to-a-repeater-via-ble-bluetooth)
|
||||||
- [6.4. Q: My companion isn't showing up over Bluetooth?](#64-q-my-companion-isnt-showing-up-over-bluetooth)
|
- [6.4. Q: My companion isn't showing up over Bluetooth?](#64-q-my-companion-isnt-showing-up-over-bluetooth)
|
||||||
- [6.5. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code)
|
- [6.5. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#65-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code)
|
||||||
- [6.6. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection)
|
- [6.6. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#66-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection)
|
||||||
- [6.7. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh)
|
- [6.7. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#67-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh)
|
||||||
- [6.8. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-linux-with-failed-to-open)
|
- [6.8. Q: WebFlasher fails on Linux with failed to open](#68-q-webflasher-fails-on-linux-with-failed-to-open)
|
||||||
- [7. Other Questions:](#7-other-questions)
|
- [7. Other Questions:](#7-other-questions)
|
||||||
- [7.1. Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app)
|
- [7.1. Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app)
|
||||||
|
- [7.1.1 Q: Can I update Seeed Studio Wio Tracker L1 Pro using OTA?](#711-q-can-i-update-seeed-studio-wio-tracker-l1-pro-using-ota)
|
||||||
- [7.2. Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air)
|
- [7.2. Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air)
|
||||||
- [7.3. Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#73-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu)
|
- [7.3. Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#73-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu)
|
||||||
- [7.4. Q: are the MeshCore logo and font available?](#74-q-are-the-meshcore-logo-and-font-available)
|
- [7.4. Q: are the MeshCore logo and font available?](#74-q-are-the-meshcore-logo-and-font-available)
|
||||||
- [7.5. Q: What is the format of a contact or channel QR code?](#75-q-what-is-the-format-of-a-contact-or-channel-qr-code)
|
- [7.5. Q: What is the format of a contact or channel QR code?](#75-q-what-is-the-format-of-a-contact-or-channel-qr-code)
|
||||||
- [7.6. Q: How do I connect to the companion via WIFI, e.g. using a heltec v3?](#76-q-how-do-i-connect-to-the-comnpanion-via-wifi-eg-using-a-heltec-v3)
|
- [7.6. Q: How do I connect to the companion via WIFI, e.g. using a heltec v3?](#76-q-how-do-i-connect-to-the-companion-via-wifi-eg-using-a-heltec-v3)
|
||||||
|
- [7.7. Q: I have a Station G2, or a Heltec V4, or an Ikoka Stick, or a radio with a EByte E22-900M30S or a E22-900M33S module, what should their transmit power be set to?](#77-q-i-have-a-station-g2-or-a-heltec-v4-or-an-ikoka-stick-or-a-radio-with-a-ebyte-e22-900m30s-or-a-e22-900m33s-module-what-should-their-transmit-power-be-set-to)
|
||||||
|
- [| | High Output | 22 dBm | 28 dBm | |](#--high-output--22-dbm--28-dbm--)
|
||||||
|
|
||||||
## 1. Introduction
|
## 1. Introduction
|
||||||
|
|
||||||
@@ -180,22 +193,17 @@ The T-Deck firmware is free to download and most features are available without
|
|||||||
|
|
||||||
|
|
||||||
### 2.3. Q: What frequencies are supported by MeshCore?
|
### 2.3. Q: What frequencies are supported by MeshCore?
|
||||||
**A:** It supports the 868MHz range in the UK/EU and the 915MHz range in New Zealand, Australia, and the USA. Countries and regions in these two frequency ranges are also supported. The firmware and client allow users to set their preferred frequency.
|
**A:** It supports the 868MHz range in the UK/EU and the 915MHz range in New Zealand, Australia, and the USA. Countries and regions in these two frequency ranges are also supported.
|
||||||
- Australia and New Zealand are on **915.8MHz**
|
|
||||||
- UK and EU are on **869.525MHz**
|
|
||||||
- Canada and USA are on **910.525MHz**
|
|
||||||
- For other regions and countries, please check your local LoRa frequency
|
|
||||||
|
|
||||||
In UK and EU, 867.5MHz is not allowed to use 250kHz bandwidth and it only allows 2.5% duty cycle for clients. 869.525Mhz allows an airtime of 10%, 250KHz bandwidth, and a higher EIRP, therefore MeshCore nodes can send more often and with more power. That is why this frequency is chosen for UK and EU. This is also why Meshtastic also uses this frequency.
|
Use the smartphone client or the repeater setup feature on there web flasher to set your radios' RF settings by choosing the preset for your regions.
|
||||||
|
|
||||||
[Source](https://discord.com/channels/826570251612323860/1330643963501351004/1356540643853209641)
|
Recently, as of October 2025, many regions have moved to the "narrow" setting, aka using BW62.5 and a lower SF number (instead of the original SF11). For example, USA/Canada (Recommended) preset is 910.525MHz, SF7, BW62.5, CR5.
|
||||||
|
|
||||||
|
After extensive testing, many regions have switched or about to switch over to BW62.5 and SF7, 8, or 9. Narrower bandwidth setting and lower SF setting allow MeshCore's radio signals to fit between interference in the ISM band, provide for a lower noise floor, better SNR, and faster transmissions.
|
||||||
|
|
||||||
|
If you have consensus from your community in your region to update your region's preset recommendation, please post your update request on the [#meshcore-app](https://discord.com/channels/1343693475589263471/1391681655911088241) channel on the [MeshCore Discord server ](https://discord.gg/cYtQNYCCRK) to let Liam Cottle know.
|
||||||
|
|
||||||
the rest of the radio settings are the same for all frequencies:
|
|
||||||
- Spread Factor (SF): 11
|
|
||||||
- Coding Rate (CR): 5
|
|
||||||
- Bandwidth (BW): 250.00
|
|
||||||
|
|
||||||
(Originally MeshCore started with SF 10. recently (as of late April 2025) the community has advocated SF 11 also a viable option for longer range but a little slower transmission. Currently there are MeshCore meshes with SF 10 and SF 11. Liam Cottle's smartphone app's presets now recommend SF 10 for Australia and SF 11 for all other regions and countries. EU and UK has SF 10 and SF 11 presets. Work with your local meshers on deciding with SF number is best for your use cases. In the future, there may be bridge nodes that can bridge SF 10 and SF 11 (or even different frequencies) traffic.)
|
|
||||||
|
|
||||||
### 2.4. Q: What is an "advert" in MeshCore?
|
### 2.4. Q: What is an "advert" in MeshCore?
|
||||||
**A:**
|
**A:**
|
||||||
@@ -243,7 +251,7 @@ Repeater or room server can be administered with one of the options below:
|
|||||||
|
|
||||||
|
|
||||||
### 3.2. Q: Do I need to set the location for a repeater?
|
### 3.2. Q: Do I need to set the location for a repeater?
|
||||||
**A:** With location set for a repeater, it can show up on a MeshCore map in the future. Set location with the following commands:
|
**A:** While not required, with location set for a repeater it will show up on the MeshCore map in the future. Set location with the following command:
|
||||||
|
|
||||||
`set lat <GPS Lat> set long <GPS Lon>`
|
`set lat <GPS Lat> set long <GPS Lon>`
|
||||||
|
|
||||||
@@ -260,6 +268,34 @@ You can get the latitude and longitude from Google Maps by right-clicking the lo
|
|||||||
|
|
||||||
`set guest.password {guest-password}`
|
`set guest.password {guest-password}`
|
||||||
|
|
||||||
|
### 3.5. Q: Can I retrieve a repeater's private key or set a repeater's private key?
|
||||||
|
|
||||||
|
**A:** You can issue these commands to get or set a repeater's private key using a USB serial connection.
|
||||||
|
|
||||||
|
`get prv.key` to print a repeater's private key on the serial console
|
||||||
|
`set prv.key <hex>` to set a repeater's private key on the serial console
|
||||||
|
|
||||||
|
Reboot the repeater after `set prv.key <hex>` command for the new private key to take effect.
|
||||||
|
|
||||||
|
### 3.6. Q: The first byte of my repeater's public key collides with an exisitng repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?
|
||||||
|
|
||||||
|
**A:** You can generate a new private key and specific the first byte of its public key here: https://gessaman.com/mc-keygen/
|
||||||
|
|
||||||
|
|
||||||
|
### 3.7. Q: My repeater maybe suffering from deafness due to high power interference near my mesh's frequency, it is not hearing other in-range MeshCore radios. what can I do?
|
||||||
|
|
||||||
|
**A:** This may be due to the SX1262 radio's auto gain control feature. You can use this command to preiodically reset its AGC.
|
||||||
|
|
||||||
|
`set agc.reset.interval <number>`
|
||||||
|
|
||||||
|
The `<number>` unit is in seconds and is incremented by 4. `set agc.reset.interval 4` works well to cure deafness.
|
||||||
|
|
||||||
|
This is a very low cost operation. AGC reset is done by simply setting `state = STATE_IDLE;` in function `RadioLibWrapper::resetAGC()` in `RadioLibWrappers.cpp`
|
||||||
|
|
||||||
|
|
||||||
|
### 3.8 Q: How do I make my repeater an observer on the mesh
|
||||||
|
|
||||||
|
**A:** The observer instruction is available here: https://analyzer.letsme.sh/observer/onboard
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -297,7 +333,9 @@ GPS on T-Deck is always enabled. You can skip the "GPS clock sync" and the T-De
|
|||||||
**A:**
|
**A:**
|
||||||
T-Deck uses the same key the smartphone apps use but in base64
|
T-Deck uses the same key the smartphone apps use but in base64
|
||||||
`izOH6cXN6mrJ5e26oRXNcg==`
|
`izOH6cXN6mrJ5e26oRXNcg==`
|
||||||
The third character is the capital letter 'O', not zero `0`
|
|
||||||
|
There is no `=` key on the T-Deck's hardware keyboard. You can use the on-screen software keyboard to enter `=`. Tap the text box to enable the on-screen software keyboard.
|
||||||
|
The third character is the capital letter `O` (Oh), not zero `0`
|
||||||
|
|
||||||
The smartphone app key is in hex:
|
The smartphone app key is in hex:
|
||||||
` 8b3387e9c5cdea6ac9e5edbaa115cd72`
|
` 8b3387e9c5cdea6ac9e5edbaa115cd72`
|
||||||
@@ -376,7 +414,23 @@ https://github.com/meshcore-dev/MeshCore/blob/main/src/Packet.h#L19
|
|||||||
|
|
||||||
**SF is spreading factor** - how much should the communication spread in time
|
**SF is spreading factor** - how much should the communication spread in time
|
||||||
|
|
||||||
**CR is coding rate** - https://www.thethingsnetwork.org/docs/lorawan/fec-and-code-rate/
|
**CR is coding rate** - from: https://www.thethingsnetwork.org/docs/lorawan/fec-and-code-rate/
|
||||||
|
|
||||||
|
TL;DR: default CR to 5 for good stable links. If it is not a solid link and is intermittent, change to CR to 7 or 8.
|
||||||
|
|
||||||
|
Forward Error Correction is a process of adding redundant bits to the data to be transmitted. During the transmission, data may get corrupted by interference (changes from 0 to 1 / 1 to 0). These error correction bits are used at the receivers for restoring corrupted bits.
|
||||||
|
|
||||||
|
The Code Rate of a forward error correction expresses the proportion of bits in a data stream that actually carry useful information.
|
||||||
|
|
||||||
|
There are 4 code rates used in LoRaWAN:
|
||||||
|
|
||||||
|
4/5
|
||||||
|
4/6
|
||||||
|
5/7
|
||||||
|
4/8
|
||||||
|
|
||||||
|
For example, if the code rate is 5/7, for every 5 bits of useful information, the coder generates a total of 7 bits of data, of which 2 bits are redundant.
|
||||||
|
|
||||||
Making the bandwidth 2x wider (from BW125 to BW250) allows you to send 2x more bytes in the same time. Making the spreading factor 1 step lower (from SF10 to SF9) allows you to send 2x more bytes in the same time.
|
Making the bandwidth 2x wider (from BW125 to BW250) allows you to send 2x more bytes in the same time. Making the spreading factor 1 step lower (from SF10 to SF9) allows you to send 2x more bytes in the same time.
|
||||||
|
|
||||||
Lowering the spreading factor makes it more difficult for the gateway to receive a transmission, as it will be more sensitive to noise. You could compare this to two people taking in a noisy place (a bar for example). If you’re far from each other, you have to talk slow (SF10), but if you’re close, you can talk faster (SF7)
|
Lowering the spreading factor makes it more difficult for the gateway to receive a transmission, as it will be more sensitive to noise. You could compare this to two people taking in a noisy place (a bar for example). If you’re far from each other, you have to talk slow (SF10), but if you’re close, you can talk faster (SF7)
|
||||||
@@ -558,7 +612,8 @@ From here, reference repeater and room server command line commands on MeshCore
|
|||||||
**A:** Yes. See the following:
|
**A:** Yes. See the following:
|
||||||
|
|
||||||
#### 5.14.1. meshcoremqtt
|
#### 5.14.1. meshcoremqtt
|
||||||
A Python script to send meshore debug and packet capture data to MQTT for analysis
|
A Python script to send meshcore debug and packet capture data to MQTT for analysis. Cisien's version is a fork of Andrew-a-g's and is being used to to collect data for https://map.w0z.is/messages and https://analyzer.letsme.sh/
|
||||||
|
https://github.com/Cisien/meshcoretomqtt
|
||||||
https://github.com/Andrew-a-g/meshcoretomqtt
|
https://github.com/Andrew-a-g/meshcoretomqtt
|
||||||
|
|
||||||
#### 5.14.2. MeshCore for Home Assistant
|
#### 5.14.2. MeshCore for Home Assistant
|
||||||
@@ -577,6 +632,40 @@ CLI interface to MeshCore companion radio over BLE, TCP, or serial. Uses Python
|
|||||||
A JavaScript library for interacting with a MeshCore device running the companion radio firmware
|
A JavaScript library for interacting with a MeshCore device running the companion radio firmware
|
||||||
https://github.com/liamcottle/meshcore.js
|
https://github.com/liamcottle/meshcore.js
|
||||||
|
|
||||||
|
#### 5.14.6. pyMC_core
|
||||||
|
pyMC_Core is a Python port of MeshCore, designed for Raspberry Pi and similar hardware, it talks to LoRa modules over SPI.
|
||||||
|
https://github.com/rightup/pyMC_core
|
||||||
|
|
||||||
|
#### 5.14.7. MeshCore Packet Decoder
|
||||||
|
A TypeScript library for decoding MeshCore mesh networking packets with full cryptographic support. Uses WebAssembly (WASM) for Ed25519 key derivation through the orlp/ed25519 library. It powers the [MeshCore Packet Analyzer](https://analyzer.letsme.sh/packets).
|
||||||
|
https://github.com/michaelhart/meshcore-decoder
|
||||||
|
|
||||||
|
#### 5.14.8. meshcore-pi
|
||||||
|
meshcore-pi is another Python port of MeshCore, designed for Raspberry Pi and similar hardware, it talks to LoRa modules over SPI or GPIO.
|
||||||
|
https://github.com/brianwiddas/meshcore-pi
|
||||||
|
|
||||||
|
#### 5.14.9. pyMC_Repeater
|
||||||
|
pyMC_Repeater is a repeater daemon in Python built on top of the [`pymc_core`](#5146-pymc_core) library.
|
||||||
|
https://github.com/rightup/pyMC_Repeater
|
||||||
|
|
||||||
|
|
||||||
|
### 5.15. Q: Are there client applications for Windows or Mac?
|
||||||
|
**A:** Yes, the same iOS and Android client is also available for Windows and Intel Mac (sorry, not available for ARM-based Mac yet). You can find them together with the Android APK here:
|
||||||
|
https://files.liamcottle.net/MeshCore
|
||||||
|
|
||||||
|
Both the Windows and Intel Mac versions of the client app are fully unlocked and are free to use.
|
||||||
|
|
||||||
|
### 5.16. Q: Are there any resources that compare MeshCore to other LoRa systems?
|
||||||
|
|
||||||
|
**A:** Here is a list of MeshCore comparison resources:
|
||||||
|
The Comms Channel on YouTube:
|
||||||
|
https://www.youtube.com/watch?v=guDoKGs02Us
|
||||||
|
MeshCore Advantages by MCarper:
|
||||||
|
https://github.com/mikecarper/meshfirmware/blob/main/MeshCoreAdvantages.md
|
||||||
|
Meshcore vs Meshtastic by austinmesh.org
|
||||||
|
https://www.austinmesh.org/learn/meshcore-vs-meshtastic/
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Troubleshooting
|
## 6. Troubleshooting
|
||||||
@@ -653,6 +742,12 @@ Allow the browser user on it:
|
|||||||
13. If it fails, try turning off and on Bluetooth on your phone. If that doesn't work, try rebooting your phone.
|
13. If it fails, try turning off and on Bluetooth on your phone. If that doesn't work, try rebooting your phone.
|
||||||
14. Wait for the update to complete. It can take a few minutes.
|
14. Wait for the update to complete. It can take a few minutes.
|
||||||
|
|
||||||
|
#### 7.1.1 Q: Can I update Seeed Studio Wio Tracker L1 Pro using OTA?
|
||||||
|
**A:** You can flash this safer bootloader to the Wio Tracker L1 Pro
|
||||||
|
https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX
|
||||||
|
|
||||||
|
After this bootloader is flashed onto the device, you can trigger over the air update using bluetooth by holding the button next to the D-Pad and then click the reset button. The follow the same OTA update instructions above. You can skip pass the `start ota` instruction and start the update using the DFU app.
|
||||||
|
|
||||||
|
|
||||||
### 7.2. Q: How to update ESP32-based devices over the air?
|
### 7.2. Q: How to update ESP32-based devices over the air?
|
||||||
|
|
||||||
@@ -673,10 +768,14 @@ Allow the browser user on it:
|
|||||||
Refer to https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX for the latest information.
|
Refer to https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX for the latest information.
|
||||||
|
|
||||||
Currently, the following boards are supported:
|
Currently, the following boards are supported:
|
||||||
- Nologo ProMicro
|
- Heltec Automation Mesh Node T114 / HT-nRF5262
|
||||||
|
- Nologo ProMicro NRF52840 (aka SuperMini NRF52840)
|
||||||
|
- Seeed Studio SenseCAP Card Tracker T1000-E
|
||||||
|
- Seeed Studio Wio Tracker L1
|
||||||
- Seeed Studio XIAO nRF52840 BLE
|
- Seeed Studio XIAO nRF52840 BLE
|
||||||
- Seeed Studio XIAO nRF52840 BLE SENSE
|
- Seeed Studio XIAO nRF52840 BLE SENSE
|
||||||
- RAK 4631
|
- RAK 4631 (See note)
|
||||||
|
- RAK WisMesh Tag (new 28/11/2025)
|
||||||
|
|
||||||
### 7.4. Q: are the MeshCore logo and font available?
|
### 7.4. Q: are the MeshCore logo and font available?
|
||||||
|
|
||||||
@@ -703,4 +802,22 @@ where `&type` is:
|
|||||||
WiFi firmware requires you to compile it yourself, as you need to set the wifi ssid and password.
|
WiFi firmware requires you to compile it yourself, as you need to set the wifi ssid and password.
|
||||||
Edit WIFI_SSID and WIFI_PWD in `./variants/heltec_v3/platformio.ini` and then flash it to your device.
|
Edit WIFI_SSID and WIFI_PWD in `./variants/heltec_v3/platformio.ini` and then flash it to your device.
|
||||||
|
|
||||||
|
### 7.7. Q: I have a Station G2, or a Heltec V4, or an Ikoka Stick, or a radio with a EByte E22-900M30S or a E22-900M33S module, what should their transmit power be set to?
|
||||||
|
**A:**
|
||||||
|
For companion radios, you can set these radios' transmit power in the smartphone app. For repeater and room server radios, you can set their transmit power using the command line command `set tx`. You can get their current value using command line comand `get tx`
|
||||||
|
|
||||||
|
|
||||||
|
> ### ⚠️ **WARNING: Set these values at your own risk. Incorrect power settings can permanently damage your radio hardware.**
|
||||||
|
|
||||||
|
| Device / Model | Region / Description | In-App Setting (dBm) | Target Radio Output | Notes |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| **Station G2** <br> [Reference](https://wiki.uniteng.com/en/meshtastic/station-g2) | US915 Max Output | 19 dBm | 36.5 dBm (4.46W) | |
|
||||||
|
| | US915 Recommended Max | 16 dBm | 35 dBm (3.16W) | 1dB compression point |
|
||||||
|
| | EU868 Recommended Max | 15 dBm | 34.5 dBm (2.82W) | 1dB compression point |
|
||||||
|
| | US915 1W Output | 10 dBm | 1W | |
|
||||||
|
| | EU868 1W Output | 9 dBm | 1W | |
|
||||||
|
| **Ikoka Stick E22-900M30S** | 1W Model | 19 dBm | 1W | **DO NOT EXCEED** (Risk of burn out) |
|
||||||
|
| **Ikoka Stick E22-900M33S** | 2W Model | 9 dBm | 2W | **DO NOT EXCEED** (Risk of burn out) |
|
||||||
|
| **Heltec V4** | Standard Output | 10 dBm | 22 dBm | |
|
||||||
|
| | High Output | 22 dBm | 28 dBm | |
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ void MyMesh::onContactsFull() {
|
|||||||
|
|
||||||
void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) {
|
void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) {
|
||||||
if (_serial->isConnected()) {
|
if (_serial->isConnected()) {
|
||||||
if (is_new) {
|
if (!shouldAutoAddContactType(contact.type) && is_new) {
|
||||||
writeContactRespFrame(PUSH_CODE_NEW_ADVERT, contact);
|
writeContactRespFrame(PUSH_CODE_NEW_ADVERT, contact);
|
||||||
} else {
|
} else {
|
||||||
out_frame[0] = PUSH_CODE_ADVERT;
|
out_frame[0] = PUSH_CODE_ADVERT;
|
||||||
@@ -358,7 +358,7 @@ void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path
|
|||||||
memcpy(p->path, path, p->path_len);
|
memcpy(p->path, path, p->path_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_new) dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY); // only schedule lazy write for contacts that are in contacts[]
|
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sort_by_recent(const void *a, const void *b) {
|
static int sort_by_recent(const void *a, const void *b) {
|
||||||
|
|||||||
@@ -390,6 +390,14 @@ bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
|||||||
MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet");
|
MESH_DEBUG_PRINTLN("allowPacketForward: unknown transport code, or wildcard not allowed for FLOOD packet");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Limit flood advert paket forwarding using a probabilistic reduction defined by P(h) = 0.308^(hops-1)
|
||||||
|
// https://github.com/meshcore-dev/MeshCore/issues/1223
|
||||||
|
double_t roll_dice = (double)rand() / RAND_MAX;
|
||||||
|
double_t forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1);
|
||||||
|
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood() && roll_dice > forw_prob)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// all other packets
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,6 +719,12 @@ bool MyMesh::onPeerPathRecv(mesh::Packet *packet, int sender_idx, const uint8_t
|
|||||||
#define CTL_TYPE_NODE_DISCOVER_RESP 0x90
|
#define CTL_TYPE_NODE_DISCOVER_RESP 0x90
|
||||||
|
|
||||||
void MyMesh::onControlDataRecv(mesh::Packet* packet) {
|
void MyMesh::onControlDataRecv(mesh::Packet* packet) {
|
||||||
|
if (!packet->payload) {
|
||||||
|
MESH_DEBUG_PRINTLN("onControlDataRecv: packet->payload is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(STEALTH_MODE)
|
||||||
uint8_t type = packet->payload[0] & 0xF0; // just test upper 4 bits
|
uint8_t type = packet->payload[0] & 0xF0; // just test upper 4 bits
|
||||||
if (type == CTL_TYPE_NODE_DISCOVER_REQ && packet->payload_len >= 6
|
if (type == CTL_TYPE_NODE_DISCOVER_REQ && packet->payload_len >= 6
|
||||||
&& !_prefs.disable_fwd && discover_limiter.allow(rtc_clock.getCurrentTime())
|
&& !_prefs.disable_fwd && discover_limiter.allow(rtc_clock.getCurrentTime())
|
||||||
@@ -739,6 +753,7 @@ void MyMesh::onControlDataRecv(mesh::Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng,
|
MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondClock &ms, mesh::RNG &rng,
|
||||||
@@ -781,8 +796,9 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
|||||||
_prefs.bw = LORA_BW;
|
_prefs.bw = LORA_BW;
|
||||||
_prefs.cr = LORA_CR;
|
_prefs.cr = LORA_CR;
|
||||||
_prefs.tx_power_dbm = LORA_TX_POWER;
|
_prefs.tx_power_dbm = LORA_TX_POWER;
|
||||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
|
||||||
_prefs.flood_advert_interval = 12; // 12 hours
|
_prefs.flood_advert_interval = DEF_FLOOD_ADVERT_INTERVAL;
|
||||||
|
_prefs.flood_advert_base = 0.308f;
|
||||||
_prefs.flood_max = 64;
|
_prefs.flood_max = 64;
|
||||||
_prefs.interference_threshold = 0; // disabled
|
_prefs.interference_threshold = 0; // disabled
|
||||||
|
|
||||||
@@ -854,10 +870,14 @@ bool MyMesh::formatFileSystem() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::sendSelfAdvertisement(int delay_millis) {
|
void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
|
||||||
mesh::Packet *pkt = createSelfAdvert();
|
mesh::Packet *pkt = createSelfAdvert();
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
|
if (flood) {
|
||||||
sendFlood(pkt, delay_millis);
|
sendFlood(pkt, delay_millis);
|
||||||
|
} else {
|
||||||
|
sendZeroHop(pkt, delay_millis);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ public:
|
|||||||
|
|
||||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
||||||
bool formatFileSystem() override;
|
bool formatFileSystem() override;
|
||||||
void sendSelfAdvertisement(int delay_millis) override;
|
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
|
||||||
void updateAdvertTimer() override;
|
void updateAdvertTimer() override;
|
||||||
void updateFloodAdvertTimer() override;
|
void updateFloodAdvertTimer() override;
|
||||||
|
|
||||||
|
|||||||
@@ -87,8 +87,10 @@ void setup() {
|
|||||||
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// send out initial Advertisement to the mesh
|
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
|
||||||
the_mesh.sendSelfAdvertisement(16000);
|
// send out initial Zero Hop Advertisement to the mesh
|
||||||
|
the_mesh.sendSelfAdvertisement(16000, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
@@ -275,6 +275,15 @@ uint32_t MyMesh::getDirectRetransmitDelay(const mesh::Packet *packet) {
|
|||||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||||
if (_prefs.disable_fwd) return false;
|
if (_prefs.disable_fwd) return false;
|
||||||
if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false;
|
if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false;
|
||||||
|
|
||||||
|
// Limit flood advert paket forwarding using a probabilistic reduction defined by P(h) = 0.308^(hops-1)
|
||||||
|
// https://github.com/meshcore-dev/MeshCore/issues/1223
|
||||||
|
double_t roll_dice = (double)rand() / RAND_MAX;
|
||||||
|
double_t forw_prob = pow(_prefs.flood_advert_base, packet->path_len - 1);
|
||||||
|
if (packet->getPayloadType() == PAYLOAD_TYPE_ADVERT && packet->isRouteFlood() && roll_dice > forw_prob)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// all other packets
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,8 +620,9 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
|||||||
_prefs.cr = LORA_CR;
|
_prefs.cr = LORA_CR;
|
||||||
_prefs.tx_power_dbm = LORA_TX_POWER;
|
_prefs.tx_power_dbm = LORA_TX_POWER;
|
||||||
_prefs.disable_fwd = 1;
|
_prefs.disable_fwd = 1;
|
||||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
|
||||||
_prefs.flood_advert_interval = 12; // 12 hours
|
_prefs.flood_advert_interval = DEF_FLOOD_ADVERT_INTERVAL;
|
||||||
|
_prefs.flood_advert_base = 0.308f;
|
||||||
_prefs.flood_max = 64;
|
_prefs.flood_max = 64;
|
||||||
_prefs.interference_threshold = 0; // disabled
|
_prefs.interference_threshold = 0; // disabled
|
||||||
#ifdef ROOM_PASSWORD
|
#ifdef ROOM_PASSWORD
|
||||||
@@ -675,10 +685,14 @@ bool MyMesh::formatFileSystem() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::sendSelfAdvertisement(int delay_millis) {
|
void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
|
||||||
mesh::Packet *pkt = createSelfAdvert();
|
mesh::Packet *pkt = createSelfAdvert();
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
|
if (flood) {
|
||||||
sendFlood(pkt, delay_millis);
|
sendFlood(pkt, delay_millis);
|
||||||
|
} else {
|
||||||
|
sendZeroHop(pkt, delay_millis);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
||||||
}
|
}
|
||||||
@@ -815,7 +829,7 @@ void MyMesh::loop() {
|
|||||||
if (c->extra.room.pending_ack && millisHasNowPassed(c->extra.room.ack_timeout)) {
|
if (c->extra.room.pending_ack && millisHasNowPassed(c->extra.room.ack_timeout)) {
|
||||||
c->extra.room.push_failures++;
|
c->extra.room.push_failures++;
|
||||||
c->extra.room.pending_ack = 0; // reset (TODO: keep prev expected_ack's in a list, incase they arrive LATER, after we retry)
|
c->extra.room.pending_ack = 0; // reset (TODO: keep prev expected_ack's in a list, incase they arrive LATER, after we retry)
|
||||||
MESH_DEBUG_PRINTLN("pending ACK timed out: push_failures: %d", (uint32_t)c->push_failures);
|
MESH_DEBUG_PRINTLN("pending ACK timed out: push_failures: %d", (uint32_t)c->extra.room.push_failures);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check next Round-Robin client, and sync next new post
|
// check next Round-Robin client, and sync next new post
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public:
|
|||||||
|
|
||||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
||||||
bool formatFileSystem() override;
|
bool formatFileSystem() override;
|
||||||
void sendSelfAdvertisement(int delay_millis) override;
|
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
|
||||||
void updateAdvertTimer() override;
|
void updateAdvertTimer() override;
|
||||||
void updateFloodAdvertTimer() override;
|
void updateFloodAdvertTimer() override;
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,10 @@ void setup() {
|
|||||||
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// send out initial Advertisement to the mesh
|
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
|
||||||
the_mesh.sendSelfAdvertisement(16000);
|
// send out initial Zero Hop Advertisement to the mesh
|
||||||
|
the_mesh.sendSelfAdvertisement(16000, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
@@ -718,7 +718,7 @@ SensorMesh::SensorMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::Millise
|
|||||||
_prefs.bw = LORA_BW;
|
_prefs.bw = LORA_BW;
|
||||||
_prefs.cr = LORA_CR;
|
_prefs.cr = LORA_CR;
|
||||||
_prefs.tx_power_dbm = LORA_TX_POWER;
|
_prefs.tx_power_dbm = LORA_TX_POWER;
|
||||||
_prefs.advert_interval = 1; // default to 2 minutes for NEW installs
|
_prefs.advert_interval = DEF_LOCAL_ADVERT_INTERVAL;
|
||||||
_prefs.flood_advert_interval = 0; // disabled
|
_prefs.flood_advert_interval = 0; // disabled
|
||||||
_prefs.disable_fwd = true;
|
_prefs.disable_fwd = true;
|
||||||
_prefs.flood_max = 64;
|
_prefs.flood_max = 64;
|
||||||
@@ -788,10 +788,14 @@ void SensorMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t
|
|||||||
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
|
revert_radio_at = futureMillis(2000 + timeout_mins*60*1000); // schedule when to revert radio params
|
||||||
}
|
}
|
||||||
|
|
||||||
void SensorMesh::sendSelfAdvertisement(int delay_millis) {
|
void SensorMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
|
||||||
mesh::Packet* pkt = createSelfAdvert();
|
mesh::Packet* pkt = createSelfAdvert();
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
|
if (flood) {
|
||||||
sendFlood(pkt, delay_millis);
|
sendFlood(pkt, delay_millis);
|
||||||
|
} else {
|
||||||
|
sendZeroHop(pkt, delay_millis);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
MESH_DEBUG_PRINTLN("ERROR: unable to create advertisement packet!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
NodePrefs* getNodePrefs() { return &_prefs; }
|
NodePrefs* getNodePrefs() { return &_prefs; }
|
||||||
void savePrefs() override { _cli.savePrefs(_fs); }
|
void savePrefs() override { _cli.savePrefs(_fs); }
|
||||||
bool formatFileSystem() override;
|
bool formatFileSystem() override;
|
||||||
void sendSelfAdvertisement(int delay_millis) override;
|
void sendSelfAdvertisement(int delay_millis, bool flood = true) override;
|
||||||
void updateAdvertTimer() override;
|
void updateAdvertTimer() override;
|
||||||
void updateFloodAdvertTimer() override;
|
void updateFloodAdvertTimer() override;
|
||||||
void setLoggingOn(bool enable) override { }
|
void setLoggingOn(bool enable) override { }
|
||||||
|
|||||||
@@ -110,8 +110,10 @@ void setup() {
|
|||||||
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// send out initial Advertisement to the mesh
|
#if !defined(STEALTH_MODE) && !defined(NO_BOOT_ADVERT)
|
||||||
the_mesh.sendSelfAdvertisement(16000);
|
// send out initial Zero Hop Advertisement to the mesh
|
||||||
|
the_mesh.sendSelfAdvertisement(16000, false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
10
fetch_prs.sh
10
fetch_prs.sh
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
git branch -D pr-1199
|
|
||||||
git branch -D pr-1297
|
|
||||||
git branch -D pr-1338
|
|
||||||
|
|
||||||
# fetch PRs
|
|
||||||
git fetch upstream pull/1338/head:pr-1338
|
|
||||||
git fetch upstream pull/1297/head:pr-1297
|
|
||||||
git fetch upstream pull/1199/head:pr-1199
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
git merge pr-1338 --no-edit -m "Integration of upstrem PR #1338"
|
|
||||||
git merge pr-1297 --no-edit -m "Integration of upstrem PR #1297"
|
|
||||||
git merge pr-1199 --no-edit -m "Integration of upstrem PR #1199"
|
|
||||||
|
|
||||||
git merge pio-ini-adjustments -m "platformio.ini: Adjust defaults for LoRa frequncies and advert interval limits"
|
|
||||||
|
|
||||||
|
|
||||||
@@ -23,12 +23,16 @@ lib_deps =
|
|||||||
adafruit/RTClib @ ^2.1.3
|
adafruit/RTClib @ ^2.1.3
|
||||||
melopero/Melopero RV3028 @ ^1.1.0
|
melopero/Melopero RV3028 @ ^1.1.0
|
||||||
electroniccats/CayenneLPP @ 1.6.1
|
electroniccats/CayenneLPP @ 1.6.1
|
||||||
build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
|
build_flags = -w -DNDEBUG
|
||||||
-D LORA_FREQ=869.525
|
-D LORA_FREQ=869.525
|
||||||
-D LORA_BW=250
|
-D LORA_BW=250
|
||||||
-D LORA_SF=11
|
-D LORA_SF=11
|
||||||
|
;
|
||||||
-D ENABLE_PRIVATE_KEY_IMPORT=1 ; NOTE: comment these out for more secure firmware
|
-D ENABLE_PRIVATE_KEY_IMPORT=1 ; NOTE: comment these out for more secure firmware
|
||||||
-D ENABLE_PRIVATE_KEY_EXPORT=1
|
-D ENABLE_PRIVATE_KEY_EXPORT=1
|
||||||
|
;
|
||||||
|
-D RADIOLIB_STATIC_ONLY=1
|
||||||
|
-D RADIOLIB_GODMODE=1
|
||||||
-D RADIOLIB_EXCLUDE_CC1101=1
|
-D RADIOLIB_EXCLUDE_CC1101=1
|
||||||
-D RADIOLIB_EXCLUDE_RF69=1
|
-D RADIOLIB_EXCLUDE_RF69=1
|
||||||
-D RADIOLIB_EXCLUDE_SX1231=1
|
-D RADIOLIB_EXCLUDE_SX1231=1
|
||||||
@@ -43,6 +47,15 @@ build_flags = -w -DNDEBUG -DRADIOLIB_STATIC_ONLY=1 -DRADIOLIB_GODMODE=1
|
|||||||
-D RADIOLIB_EXCLUDE_BELL=1
|
-D RADIOLIB_EXCLUDE_BELL=1
|
||||||
-D RADIOLIB_EXCLUDE_RTTY=1
|
-D RADIOLIB_EXCLUDE_RTTY=1
|
||||||
-D RADIOLIB_EXCLUDE_SSTV=1
|
-D RADIOLIB_EXCLUDE_SSTV=1
|
||||||
|
;
|
||||||
|
-D MIN_LOCAL_ADVERT_INTERVAL=60
|
||||||
|
-D MAX_LOCAL_ADVERT_INTERVAL=10000
|
||||||
|
-D DEF_LOCAL_ADVERT_INTERVAL=1 ; default to 2 minutes for NEW installs
|
||||||
|
-D MIN_FLOOD_ADVERT_INTERVAL=48
|
||||||
|
-D MAX_FLOOD_ADVERT_INTERVAL=10000
|
||||||
|
-D DEF_FLOOD_ADVERT_INTERVAL=48 ; default to 12 hours for NEW installs
|
||||||
|
; -D NO_BOOT_ADVERT=1 ; disable boot advertisement
|
||||||
|
; -D STEALTH_MODE=1 ; disable all advertisements and DISCOVER_REQ
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
+<*.cpp>
|
+<*.cpp>
|
||||||
+<helpers/*.cpp>
|
+<helpers/*.cpp>
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
|
|||||||
}
|
}
|
||||||
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
|
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
|
||||||
|
|
||||||
bool is_new = false; // true = not in contacts[], false = exists in contacts[]
|
bool is_new = false;
|
||||||
if (from == NULL) {
|
if (from == NULL) {
|
||||||
if (!shouldAutoAddContactType(parser.getType())) {
|
if (!shouldAutoAddContactType(parser.getType())) {
|
||||||
ContactInfo ci;
|
ContactInfo ci;
|
||||||
@@ -142,6 +142,7 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_new = true;
|
||||||
from = allocateContactSlot();
|
from = allocateContactSlot();
|
||||||
if (from == NULL) {
|
if (from == NULL) {
|
||||||
ContactInfo ci;
|
ContactInfo ci;
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||||||
file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
||||||
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
||||||
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||||
// 290
|
file.read((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290
|
||||||
|
|
||||||
|
// 294
|
||||||
|
|
||||||
// sanitise bad pref values
|
// sanitise bad pref values
|
||||||
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
|
||||||
@@ -108,6 +110,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
|||||||
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
|
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
|
||||||
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
|
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
|
||||||
|
|
||||||
|
_prefs->flood_advert_base = constrain(_prefs->flood_advert_base, 0, 1);
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,14 +169,14 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
|
|||||||
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
|
||||||
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
|
||||||
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
|
||||||
// 290
|
file.write((uint8_t *)&_prefs->flood_advert_base, sizeof(_prefs->flood_advert_base)); // 290
|
||||||
|
|
||||||
|
// 294
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_LOCAL_ADVERT_INTERVAL 60
|
|
||||||
|
|
||||||
void CommonCLI::savePrefs() {
|
void CommonCLI::savePrefs() {
|
||||||
if (_prefs->advert_interval * 2 < MIN_LOCAL_ADVERT_INTERVAL) {
|
if (_prefs->advert_interval * 2 < MIN_LOCAL_ADVERT_INTERVAL) {
|
||||||
_prefs->advert_interval = 0; // turn it off, now that device has been manually configured
|
_prefs->advert_interval = 0; // turn it off, now that device has been manually configured
|
||||||
@@ -197,6 +201,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
if (memcmp(command, "reboot", 6) == 0) {
|
if (memcmp(command, "reboot", 6) == 0) {
|
||||||
_board->reboot(); // doesn't return
|
_board->reboot(); // doesn't return
|
||||||
} else if (memcmp(command, "advert", 6) == 0) {
|
} else if (memcmp(command, "advert", 6) == 0) {
|
||||||
|
// Keep "advert" as flood for backward compatibility
|
||||||
_callbacks->sendSelfAdvertisement(1500); // longer delay, give CLI response time to be sent first
|
_callbacks->sendSelfAdvertisement(1500); // longer delay, give CLI response time to be sent first
|
||||||
strcpy(reply, "OK - Advert sent");
|
strcpy(reply, "OK - Advert sent");
|
||||||
} else if (memcmp(command, "clock sync", 10) == 0) {
|
} else if (memcmp(command, "clock sync", 10) == 0) {
|
||||||
@@ -364,6 +369,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
} else {
|
} else {
|
||||||
sprintf(reply, "> %.3f", adc_mult);
|
sprintf(reply, "> %.3f", adc_mult);
|
||||||
}
|
}
|
||||||
|
} else if (memcmp(config, "flood.advert.base", 17) == 0) {
|
||||||
|
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->flood_advert_base));
|
||||||
} else {
|
} else {
|
||||||
sprintf(reply, "??: %s", config);
|
sprintf(reply, "??: %s", config);
|
||||||
}
|
}
|
||||||
@@ -394,8 +401,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
strcpy(reply, "OK");
|
strcpy(reply, "OK");
|
||||||
} else if (memcmp(config, "flood.advert.interval ", 22) == 0) {
|
} else if (memcmp(config, "flood.advert.interval ", 22) == 0) {
|
||||||
int hours = _atoi(&config[22]);
|
int hours = _atoi(&config[22]);
|
||||||
if ((hours > 0 && hours < 3) || (hours > 48)) {
|
if ((hours > 0 && hours < MIN_FLOOD_ADVERT_INTERVAL) || (hours > MAX_FLOOD_ADVERT_INTERVAL)) {
|
||||||
strcpy(reply, "Error: interval range is 3-48 hours");
|
sprintf(reply, "Error: interval range is %d-%d hours", MIN_FLOOD_ADVERT_INTERVAL,
|
||||||
|
MAX_FLOOD_ADVERT_INTERVAL);
|
||||||
} else {
|
} else {
|
||||||
_prefs->flood_advert_interval = (uint8_t)(hours);
|
_prefs->flood_advert_interval = (uint8_t)(hours);
|
||||||
_callbacks->updateFloodAdvertTimer();
|
_callbacks->updateFloodAdvertTimer();
|
||||||
@@ -404,8 +412,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
}
|
}
|
||||||
} else if (memcmp(config, "advert.interval ", 16) == 0) {
|
} else if (memcmp(config, "advert.interval ", 16) == 0) {
|
||||||
int mins = _atoi(&config[16]);
|
int mins = _atoi(&config[16]);
|
||||||
if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > 240)) {
|
if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > MAX_LOCAL_ADVERT_INTERVAL)) {
|
||||||
sprintf(reply, "Error: interval range is %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL);
|
sprintf(reply, "Error: interval range is %d-%d minutes",MIN_LOCAL_ADVERT_INTERVAL,
|
||||||
|
MAX_LOCAL_ADVERT_INTERVAL);
|
||||||
} else {
|
} else {
|
||||||
_prefs->advert_interval = (uint8_t)(mins / 2);
|
_prefs->advert_interval = (uint8_t)(mins / 2);
|
||||||
_callbacks->updateAdvertTimer();
|
_callbacks->updateAdvertTimer();
|
||||||
@@ -583,6 +592,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
|
|||||||
_prefs->adc_multiplier = 0.0f;
|
_prefs->adc_multiplier = 0.0f;
|
||||||
strcpy(reply, "Error: unsupported by this board");
|
strcpy(reply, "Error: unsupported by this board");
|
||||||
};
|
};
|
||||||
|
} else if (memcmp(config, "flood.advert.base ", 18) == 0) {
|
||||||
|
float f = atof(&config[18]);
|
||||||
|
if((f > 0) || (f<1)) {
|
||||||
|
_prefs->flood_advert_base = f;
|
||||||
|
savePrefs();
|
||||||
|
strcpy(reply, "OK");
|
||||||
|
} else {
|
||||||
|
strcpy(reply, "Error: base must be between 0 and 1");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sprintf(reply, "unknown config: %s", config);
|
sprintf(reply, "unknown config: %s", config);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ struct NodePrefs { // persisted to file
|
|||||||
uint8_t flood_max;
|
uint8_t flood_max;
|
||||||
uint8_t interference_threshold;
|
uint8_t interference_threshold;
|
||||||
uint8_t agc_reset_interval; // secs / 4
|
uint8_t agc_reset_interval; // secs / 4
|
||||||
|
float flood_advert_base;
|
||||||
// Bridge settings
|
// Bridge settings
|
||||||
uint8_t bridge_enabled; // boolean
|
uint8_t bridge_enabled; // boolean
|
||||||
uint16_t bridge_delay; // milliseconds (default 500 ms)
|
uint16_t bridge_delay; // milliseconds (default 500 ms)
|
||||||
@@ -60,7 +61,7 @@ public:
|
|||||||
virtual const char* getBuildDate() = 0;
|
virtual const char* getBuildDate() = 0;
|
||||||
virtual const char* getRole() = 0;
|
virtual const char* getRole() = 0;
|
||||||
virtual bool formatFileSystem() = 0;
|
virtual bool formatFileSystem() = 0;
|
||||||
virtual void sendSelfAdvertisement(int delay_millis) = 0;
|
virtual void sendSelfAdvertisement(int delay_millis, bool flood = true) = 0;
|
||||||
virtual void updateAdvertTimer() = 0;
|
virtual void updateAdvertTimer() = 0;
|
||||||
virtual void updateFloodAdvertTimer() = 0;
|
virtual void updateFloodAdvertTimer() = 0;
|
||||||
virtual void setLoggingOn(bool enable) = 0;
|
virtual void setLoggingOn(bool enable) = 0;
|
||||||
|
|||||||
56
tools/maint/README.md
Normal file
56
tools/maint/README.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Maintenance Tools
|
||||||
|
|
||||||
|
This directory contains automation for managing our **Friendly Fork**. It allows us to integrate community-submitted Pull Requests from the upstream repository into our local development branches.
|
||||||
|
|
||||||
|
## Why this exists
|
||||||
|
|
||||||
|
In firmware development, critical bug fixes or hardware support often exist in the upstream "Pull Request" queue long before they are officially merged. This tool allows us to build an integrated firmware version that includes those necessary patches while remaining syncable with the official source.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### 1. Prerequisites
|
||||||
|
|
||||||
|
You must have the original repository added as a remote named `upstream`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git remote add upstream https://github.com/meshcore-dev/MeshCore.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Basic Commands
|
||||||
|
|
||||||
|
**Apply specific patches:**
|
||||||
|
To pull in PR #1338 and PR #1400 from the upstream project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tools/maint/apply_patches.sh 1338 1400
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start over (Reset):**
|
||||||
|
To wipe the integrated branch and reset it to match the official upstream `main` branch exactly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./tools/maint/apply_patches.sh --reset
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Traceability
|
||||||
|
|
||||||
|
Every time this script runs, it updates `patch_manifest.log`. This file tracks:
|
||||||
|
|
||||||
|
* The date of the integration.
|
||||||
|
* The base commit SHA we started from.
|
||||||
|
* The specific commit SHA of every PR applied.
|
||||||
|
|
||||||
|
**This log is essential for debugging firmware regressions.** If the hardware fails, check the manifest to identify which experimental patch might be the cause.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### A Note on Merge Conflicts
|
||||||
|
|
||||||
|
If a PR cannot be applied automatically, the script will abort the merge. You will need to:
|
||||||
|
|
||||||
|
1. Manually merge the PR.
|
||||||
|
2. Resolve the conflicts in your editor.
|
||||||
|
3. Commit the result.
|
||||||
|
4. Manually update the `patch_manifest.log`.
|
||||||
65
tools/maint/apply_patches.sh
Executable file
65
tools/maint/apply_patches.sh
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
UPSTREAM_REMOTE="upstream"
|
||||||
|
BASE_BRANCH="main" # Change to 'master' if that's what upstream uses
|
||||||
|
TARGET_BRANCH="main-integrated"
|
||||||
|
MANIFEST_FILE="tools/maint/patch_manifest.log"
|
||||||
|
|
||||||
|
# Function to reset the branch
|
||||||
|
reset_to_upstream() {
|
||||||
|
echo "Warning: This will wipe all local changes on $TARGET_BRANCH."
|
||||||
|
read -p "Are you sure you want to reset to $UPSTREAM_REMOTE/$BASE_BRANCH? (y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
git fetch "$UPSTREAM_REMOTE"
|
||||||
|
git checkout -B "$TARGET_BRANCH" "$UPSTREAM_REMOTE/$BASE_BRANCH"
|
||||||
|
echo "--- Reset to Upstream: $(date) ---" > "$MANIFEST_FILE"
|
||||||
|
echo "Base Commit: $(git rev-parse HEAD)" >> "$MANIFEST_FILE"
|
||||||
|
echo "Reset successful. Branch is now clean."
|
||||||
|
else
|
||||||
|
echo "Reset aborted."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for reset flag
|
||||||
|
if [[ "$1" == "--reset" ]]; then
|
||||||
|
reset_to_upstream
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Standard PR application logic
|
||||||
|
PR_IDS=("$@")
|
||||||
|
if [ ${#PR_IDS[@]} -eq 0 ]; then
|
||||||
|
echo "Usage:"
|
||||||
|
echo " Apply PRs: $0 <PR_ID1> <PR_ID2> ..."
|
||||||
|
echo " Reset: $0 --reset"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure target branch exists and is checked out
|
||||||
|
git checkout -B "$TARGET_BRANCH"
|
||||||
|
|
||||||
|
echo "--- Patch Session: $(date) ---" >> "$MANIFEST_FILE"
|
||||||
|
|
||||||
|
for PR in "${PR_IDS[@]}"; do
|
||||||
|
echo "--------------------------------------"
|
||||||
|
echo "Fetching PR #$PR..."
|
||||||
|
|
||||||
|
if git fetch "$UPSTREAM_REMOTE" "pull/$PR/head:PR_TEMP_FETCH"; then
|
||||||
|
if git merge PR_TEMP_FETCH --no-edit -m "Integrate upstream PR #$PR"; then
|
||||||
|
echo "Successfully integrated PR #$PR"
|
||||||
|
echo "PR #$PR SHA: $(git rev-parse PR_TEMP_FETCH)" >> "$MANIFEST_FILE"
|
||||||
|
else
|
||||||
|
echo "Conflict in PR #$PR. Aborting merge."
|
||||||
|
git merge --abort
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git branch -D PR_TEMP_FETCH
|
||||||
|
else
|
||||||
|
echo "Error: PR #$PR not found."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "--------------------------------------"
|
||||||
|
echo "Done. See $MANIFEST_FILE for details."
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/bin/bash # Note: switched to bash for process substitution support
|
|
||||||
|
|
||||||
export PATH="$HOME/.platformio/penv/bin:$PATH"
|
|
||||||
|
|
||||||
LOGFILE="$PWD/meshcore-evo-fw.log"
|
|
||||||
FIRMWARE_VERSION="v1.11.0-evo_0.1.3"
|
|
||||||
FIRMWARE_BUILD_DATE=$(date '+%d-%b-%Y')
|
|
||||||
|
|
||||||
collect_bin_files(){
|
|
||||||
DEST_DIR="./firmwares"
|
|
||||||
mkdir -p "$DEST_DIR"
|
|
||||||
BUILD_DIR=".pio/build"
|
|
||||||
|
|
||||||
if [ ! -d "$BUILD_DIR" ]; then
|
|
||||||
echo "Error: $BUILD_DIR not found. Did you run the build process?"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Copying firmware files to $DEST_DIR..."
|
|
||||||
|
|
||||||
for target_path in "$BUILD_DIR"/*/; do
|
|
||||||
echo $target_path
|
|
||||||
target_name=$(basename "$target_path")
|
|
||||||
# if ls "$target_path"*.bin >/dev/null 2>&1; then
|
|
||||||
for bin_file in "$target_path"*firmware*.{uf2,bin,zip}; do
|
|
||||||
filename=$(basename "$bin_file")
|
|
||||||
new_filename="${target_name}_${FIRMWARE_VERSION}_${FIRMWARE_BUILD_DATE}_${filename}"
|
|
||||||
cp "$bin_file" "$DEST_DIR/$new_filename"
|
|
||||||
echo "Done: $new_filename"
|
|
||||||
done
|
|
||||||
# fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Everything after this line goes to BOTH console and logfile
|
|
||||||
exec > >(tee -a "$LOGFILE") 2>&1
|
|
||||||
|
|
||||||
echo "-------------------- Build start ----------------"
|
|
||||||
date
|
|
||||||
echo "-------------------------------------------------"
|
|
||||||
|
|
||||||
# apply patches
|
|
||||||
# ./tools/maint/apply_patches.sh 1199 1338 1297
|
|
||||||
|
|
||||||
# build all repeater firmwares, the will be in .out
|
|
||||||
FIRMWARE_VERSION="v1.11_evo" ./build.sh build-repeater-firmwares
|
|
||||||
|
|
||||||
# build single firmwares
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware ProMicro_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware RAK_4631_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware heltec_v4_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware Heltec_v3_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware Xiao_nrf52_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware LilyGo_T3S3_sx1262_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware Heltec_t114_without_display_repeater
|
|
||||||
#FIRMWARE_VERSION=$FIRMWARE_VERSION FIRMWARE_BUILD_DATE=$FIRMWARE_BUILD_DATE ./build.sh build-firmware Heltec_t114_repeater
|
|
||||||
#collect_bin_files
|
|
||||||
|
|
||||||
|
|
||||||
echo "-------------------- Build end ------------------"
|
|
||||||
date
|
|
||||||
echo "-------------------------------------------------"
|
|
||||||
|
|
||||||
#grep -E " SUCCESS | FAILED " hansemesh_fw.log
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#include <Arduino.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
#include "RAK3401Board.h"
|
|
||||||
|
|
||||||
void RAK3401Board::begin() {
|
|
||||||
NRF52BoardDCDC::begin();
|
|
||||||
pinMode(PIN_VBAT_READ, INPUT);
|
|
||||||
#ifdef PIN_USER_BTN
|
|
||||||
pinMode(PIN_USER_BTN, INPUT_PULLUP);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PIN_USER_BTN_ANA
|
|
||||||
pinMode(PIN_USER_BTN_ANA, INPUT_PULLUP);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
|
|
||||||
Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
|
|
||||||
pinMode(PIN_3V3_EN, OUTPUT);
|
|
||||||
digitalWrite(PIN_3V3_EN, HIGH);
|
|
||||||
|
|
||||||
#ifdef P_LORA_PA_EN
|
|
||||||
// Initialize RAK13302 1W LoRa transceiver module PA control pin
|
|
||||||
pinMode(P_LORA_PA_EN, OUTPUT);
|
|
||||||
digitalWrite(P_LORA_PA_EN, LOW); // Start with PA disabled
|
|
||||||
delay(10); // Allow PA module to initialize
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <MeshCore.h>
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <helpers/NRF52Board.h>
|
|
||||||
|
|
||||||
// LoRa radio module pins for RAK13302
|
|
||||||
#define P_LORA_SCLK 3
|
|
||||||
#define P_LORA_MISO 29
|
|
||||||
#define P_LORA_MOSI 30
|
|
||||||
#define P_LORA_NSS 26
|
|
||||||
#define P_LORA_DIO_1 10
|
|
||||||
#define P_LORA_BUSY 9
|
|
||||||
#define P_LORA_RESET 4
|
|
||||||
#ifndef P_LORA_PA_EN
|
|
||||||
#define P_LORA_PA_EN 31
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define PIN_GPS_SDA 13 //GPS SDA pin (output option)
|
|
||||||
//#define PIN_GPS_SCL 14 //GPS SCL pin (output option)
|
|
||||||
// #define PIN_GPS_TX 16 //GPS TX pin
|
|
||||||
// #define PIN_GPS_RX 15 //GPS RX pin
|
|
||||||
#define PIN_GPS_1PPS 17 //GPS PPS pin
|
|
||||||
#define GPS_BAUD_RATE 9600
|
|
||||||
#define GPS_ADDRESS 0x42 //i2c address for GPS
|
|
||||||
|
|
||||||
#define SX126X_DIO2_AS_RF_SWITCH
|
|
||||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
|
||||||
|
|
||||||
|
|
||||||
// built-ins
|
|
||||||
#define PIN_VBAT_READ 5
|
|
||||||
#define ADC_MULTIPLIER (3 * 1.73 * 1.187 * 1000)
|
|
||||||
|
|
||||||
#define PIN_3V3_EN (34)
|
|
||||||
#define WB_IO2 PIN_3V3_EN
|
|
||||||
|
|
||||||
class RAK3401Board : public NRF52BoardDCDC, public NRF52BoardOTA {
|
|
||||||
public:
|
|
||||||
RAK3401Board() : NRF52BoardOTA("RAK3401_OTA") {}
|
|
||||||
void begin();
|
|
||||||
|
|
||||||
#define BATTERY_SAMPLES 8
|
|
||||||
|
|
||||||
uint16_t getBattMilliVolts() override {
|
|
||||||
analogReadResolution(12);
|
|
||||||
|
|
||||||
uint32_t raw = 0;
|
|
||||||
for (int i = 0; i < BATTERY_SAMPLES; i++) {
|
|
||||||
raw += analogRead(PIN_VBAT_READ);
|
|
||||||
}
|
|
||||||
raw = raw / BATTERY_SAMPLES;
|
|
||||||
|
|
||||||
return (ADC_MULTIPLIER * raw) / 4096;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* getManufacturerName() const override {
|
|
||||||
return "RAK 3401";
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef P_LORA_PA_EN
|
|
||||||
void onBeforeTransmit() override {
|
|
||||||
digitalWrite(P_LORA_PA_EN, HIGH); // Enable PA before transmission
|
|
||||||
}
|
|
||||||
|
|
||||||
void onAfterTransmit() override {
|
|
||||||
digitalWrite(P_LORA_PA_EN, LOW); // Disable PA after transmission to save power
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
[rak3401]
|
|
||||||
extends = nrf52_base
|
|
||||||
board = rak3401
|
|
||||||
board_check = true
|
|
||||||
build_flags = ${nrf52_base.build_flags}
|
|
||||||
${sensor_base.build_flags}
|
|
||||||
-I variants/rak3401
|
|
||||||
-D RAK_3401
|
|
||||||
-D RAK13302
|
|
||||||
-D RADIO_CLASS=CustomSX1262
|
|
||||||
-D WRAPPER_CLASS=CustomSX1262Wrapper
|
|
||||||
-D LORA_TX_POWER=22
|
|
||||||
-D SX126X_CURRENT_LIMIT=140
|
|
||||||
-D SX126X_RX_BOOSTED_GAIN=1
|
|
||||||
build_src_filter = ${nrf52_base.build_src_filter}
|
|
||||||
+<../variants/rak3401>
|
|
||||||
+<helpers/sensors>
|
|
||||||
+<helpers/ui/SSD1306Display.cpp>
|
|
||||||
+<helpers/ui/MomentaryButton.cpp>
|
|
||||||
lib_deps =
|
|
||||||
${nrf52_base.lib_deps}
|
|
||||||
${sensor_base.lib_deps}
|
|
||||||
adafruit/Adafruit SSD1306 @ ^2.5.13
|
|
||||||
sparkfun/SparkFun u-blox GNSS Arduino Library@^2.2.27
|
|
||||||
|
|
||||||
[env:RAK_3401_repeater]
|
|
||||||
extends = rak3401
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-D DISPLAY_CLASS=SSD1306Display
|
|
||||||
-D ADVERT_NAME='"RAK3401 1W Repeater"'
|
|
||||||
-D ADVERT_LAT=0.0
|
|
||||||
-D ADVERT_LON=0.0
|
|
||||||
-D ADMIN_PASSWORD='"password"'
|
|
||||||
-D MAX_NEIGHBOURS=50
|
|
||||||
;-D MESH_PACKET_LOGGING=1
|
|
||||||
;-D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<helpers/ui/SSD1306Display.cpp>
|
|
||||||
+<../examples/simple_repeater>
|
|
||||||
|
|
||||||
[env:RAK_3401_room_server]
|
|
||||||
extends = rak3401
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-D DISPLAY_CLASS=SSD1306Display
|
|
||||||
-D ADVERT_NAME='"Test Room"'
|
|
||||||
-D ADVERT_LAT=0.0
|
|
||||||
-D ADVERT_LON=0.0
|
|
||||||
-D ADMIN_PASSWORD='"password"'
|
|
||||||
-D ROOM_PASSWORD='"hello"'
|
|
||||||
;-D MESH_PACKET_LOGGING=1
|
|
||||||
;-D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<helpers/ui/SSD1306Display.cpp>
|
|
||||||
+<../examples/simple_room_server>
|
|
||||||
|
|
||||||
[env:RAK_3401_companion_radio_usb]
|
|
||||||
extends = rak3401
|
|
||||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
|
||||||
board_upload.maximum_size = 712704
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-I examples/companion_radio/ui-new
|
|
||||||
-D DISPLAY_CLASS=SSD1306Display
|
|
||||||
-D MAX_CONTACTS=350
|
|
||||||
-D MAX_GROUP_CHANNELS=40
|
|
||||||
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
|
|
||||||
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<../examples/companion_radio/*.cpp>
|
|
||||||
+<../examples/companion_radio/ui-new/*.cpp>
|
|
||||||
lib_deps =
|
|
||||||
${rak3401.lib_deps}
|
|
||||||
densaugeo/base64 @ ~1.4.0
|
|
||||||
|
|
||||||
[env:RAK_3401_companion_radio_ble]
|
|
||||||
extends = rak3401
|
|
||||||
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
|
|
||||||
board_upload.maximum_size = 712704
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-I examples/companion_radio/ui-new
|
|
||||||
-D DISPLAY_CLASS=SSD1306Display
|
|
||||||
-D MAX_CONTACTS=350
|
|
||||||
-D MAX_GROUP_CHANNELS=40
|
|
||||||
-D BLE_PIN_CODE=123456
|
|
||||||
-D BLE_DEBUG_LOGGING=1
|
|
||||||
-D OFFLINE_QUEUE_SIZE=256
|
|
||||||
;-D MESH_PACKET_LOGGING=1
|
|
||||||
;-D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<helpers/nrf52/SerialBLEInterface.cpp>
|
|
||||||
+<../examples/companion_radio/*.cpp>
|
|
||||||
+<../examples/companion_radio/ui-new/*.cpp>
|
|
||||||
lib_deps =
|
|
||||||
${rak3401.lib_deps}
|
|
||||||
densaugeo/base64 @ ~1.4.0
|
|
||||||
|
|
||||||
[env:RAK_3401_terminal_chat]
|
|
||||||
extends = rak3401
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-D MAX_CONTACTS=100
|
|
||||||
-D MAX_GROUP_CHANNELS=1
|
|
||||||
;-D MESH_PACKET_LOGGING=1
|
|
||||||
;-D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<../examples/simple_secure_chat/main.cpp>
|
|
||||||
lib_deps =
|
|
||||||
${rak3401.lib_deps}
|
|
||||||
densaugeo/base64 @ ~1.4.0
|
|
||||||
|
|
||||||
[env:RAK_3401_sensor]
|
|
||||||
extends = rak3401
|
|
||||||
build_flags =
|
|
||||||
${rak3401.build_flags}
|
|
||||||
-D DISPLAY_CLASS=SSD1306Display
|
|
||||||
-D ADVERT_NAME='"RAK3401 Sensor"'
|
|
||||||
-D ADVERT_LAT=0.0
|
|
||||||
-D ADVERT_LON=0.0
|
|
||||||
-D ADMIN_PASSWORD='"password"'
|
|
||||||
;-D MESH_PACKET_LOGGING=1
|
|
||||||
;-D MESH_DEBUG=1
|
|
||||||
build_src_filter = ${rak3401.build_src_filter}
|
|
||||||
+<helpers/ui/SSD1306Display.cpp>
|
|
||||||
+<../examples/simple_sensor>
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#include <Arduino.h>
|
|
||||||
#include "target.h"
|
|
||||||
#include <helpers/ArduinoHelpers.h>
|
|
||||||
|
|
||||||
RAK3401Board board;
|
|
||||||
|
|
||||||
#ifndef PIN_USER_BTN
|
|
||||||
#define PIN_USER_BTN (-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DISPLAY_CLASS
|
|
||||||
DISPLAY_CLASS display;
|
|
||||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true);
|
|
||||||
|
|
||||||
#if defined(PIN_USER_BTN_ANA)
|
|
||||||
MomentaryButton analog_btn(PIN_USER_BTN_ANA, 1000, 20);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
|
|
||||||
|
|
||||||
WRAPPER_CLASS radio_driver(radio, board);
|
|
||||||
|
|
||||||
VolatileRTCClock fallback_clock;
|
|
||||||
AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
|
||||||
|
|
||||||
#if ENV_INCLUDE_GPS
|
|
||||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
|
||||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
|
|
||||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
|
||||||
#else
|
|
||||||
EnvironmentSensorManager sensors;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool radio_init() {
|
|
||||||
rtc_clock.begin(Wire);
|
|
||||||
return radio.std_init(&SPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t radio_get_rng_seed() {
|
|
||||||
return radio.random(0x7FFFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
|
|
||||||
radio.setFrequency(freq);
|
|
||||||
radio.setSpreadingFactor(sf);
|
|
||||||
radio.setBandwidth(bw);
|
|
||||||
radio.setCodingRate(cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void radio_set_tx_power(uint8_t dbm) {
|
|
||||||
radio.setOutputPower(dbm);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh::LocalIdentity radio_new_identity() {
|
|
||||||
RadioNoiseListener rng(radio);
|
|
||||||
return mesh::LocalIdentity(&rng); // create new random identity
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define RADIOLIB_STATIC_ONLY 1
|
|
||||||
#include <RadioLib.h>
|
|
||||||
#include <helpers/radiolib/RadioLibWrappers.h>
|
|
||||||
#include <RAK3401Board.h>
|
|
||||||
#include <helpers/radiolib/CustomSX1262Wrapper.h>
|
|
||||||
#include <helpers/AutoDiscoverRTCClock.h>
|
|
||||||
#include <helpers/sensors/EnvironmentSensorManager.h>
|
|
||||||
|
|
||||||
#ifdef DISPLAY_CLASS
|
|
||||||
#include <helpers/ui/SSD1306Display.h>
|
|
||||||
extern DISPLAY_CLASS display;
|
|
||||||
#include <helpers/ui/MomentaryButton.h>
|
|
||||||
extern MomentaryButton user_btn;
|
|
||||||
#if defined(PIN_USER_BTN_ANA)
|
|
||||||
extern MomentaryButton analog_btn;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern RAK3401Board board;
|
|
||||||
extern WRAPPER_CLASS radio_driver;
|
|
||||||
extern AutoDiscoverRTCClock rtc_clock;
|
|
||||||
extern EnvironmentSensorManager sensors;
|
|
||||||
|
|
||||||
bool radio_init();
|
|
||||||
uint32_t radio_get_rng_seed();
|
|
||||||
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
|
|
||||||
void radio_set_tx_power(uint8_t dbm);
|
|
||||||
mesh::LocalIdentity radio_new_identity();
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
|
||||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
|
||||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "variant.h"
|
|
||||||
#include "wiring_constants.h"
|
|
||||||
#include "wiring_digital.h"
|
|
||||||
#include "nrf.h"
|
|
||||||
|
|
||||||
const uint32_t g_ADigitalPinMap[] =
|
|
||||||
{
|
|
||||||
// P0
|
|
||||||
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
|
|
||||||
8 , 9 , 10, 11, 12, 13, 14, 15,
|
|
||||||
16, 17, 18, 19, 20, 21, 22, 23,
|
|
||||||
24, 25, 26, 27, 28, 29, 30, 31,
|
|
||||||
|
|
||||||
// P1
|
|
||||||
32, 33, 34, 35, 36, 37, 38, 39,
|
|
||||||
40, 41, 42, 43, 44, 45, 46, 47
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void initVariant()
|
|
||||||
{
|
|
||||||
// LED1 & LED2
|
|
||||||
pinMode(PIN_LED1, OUTPUT);
|
|
||||||
ledOff(PIN_LED1);
|
|
||||||
|
|
||||||
pinMode(PIN_LED2, OUTPUT);
|
|
||||||
ledOff(PIN_LED2);
|
|
||||||
|
|
||||||
// 3V3 Power Rail
|
|
||||||
pinMode(PIN_3V3_EN, OUTPUT);
|
|
||||||
digitalWrite(PIN_3V3_EN, HIGH);
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
|
||||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
|
||||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the GNU Lesser General Public License for more details.
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _VARIANT_RAK3401_
|
|
||||||
#define _VARIANT_RAK3401_
|
|
||||||
|
|
||||||
#define RAK4630
|
|
||||||
|
|
||||||
/** Master clock frequency */
|
|
||||||
#define VARIANT_MCK (64000000ul)
|
|
||||||
|
|
||||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
|
||||||
// define USE_LFRC // Board uses RC for LF
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
|
||||||
* Headers
|
|
||||||
*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "WVariant.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
// Number of pins defined in PinDescription array
|
|
||||||
#define PINS_COUNT (48)
|
|
||||||
#define NUM_DIGITAL_PINS (48)
|
|
||||||
#define NUM_ANALOG_INPUTS (6)
|
|
||||||
#define NUM_ANALOG_OUTPUTS (0)
|
|
||||||
|
|
||||||
// LEDs
|
|
||||||
#define PIN_LED1 (35)
|
|
||||||
#define PIN_LED2 (36)
|
|
||||||
|
|
||||||
#define LED_BUILTIN PIN_LED1
|
|
||||||
#define LED_CONN PIN_LED2
|
|
||||||
|
|
||||||
#define LED_GREEN PIN_LED1
|
|
||||||
#define LED_BLUE PIN_LED2
|
|
||||||
|
|
||||||
#define LED_STATE_ON 1 // State when LED is litted
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Analog pins
|
|
||||||
*/
|
|
||||||
#define PIN_A0 (5) //(3)
|
|
||||||
#define PIN_A1 (31) //(4)
|
|
||||||
#define PIN_A2 (28)
|
|
||||||
#define PIN_A3 (29)
|
|
||||||
#define PIN_A4 (30)
|
|
||||||
#define PIN_A5 (31)
|
|
||||||
#define PIN_A6 (0xff)
|
|
||||||
#define PIN_A7 (0xff)
|
|
||||||
|
|
||||||
static const uint8_t A0 = PIN_A0;
|
|
||||||
static const uint8_t A1 = PIN_A1;
|
|
||||||
static const uint8_t A2 = PIN_A2;
|
|
||||||
static const uint8_t A3 = PIN_A3;
|
|
||||||
static const uint8_t A4 = PIN_A4;
|
|
||||||
static const uint8_t A5 = PIN_A5;
|
|
||||||
static const uint8_t A6 = PIN_A6;
|
|
||||||
static const uint8_t A7 = PIN_A7;
|
|
||||||
#define ADC_RESOLUTION 14
|
|
||||||
|
|
||||||
// Other pins
|
|
||||||
#define WB_I2C1_SDA (13) // SENSOR_SLOT IO_SLOT
|
|
||||||
#define WB_I2C1_SCL (14) // SENSOR_SLOT IO_SLOT
|
|
||||||
|
|
||||||
#define PIN_AREF (2)
|
|
||||||
#define PIN_NFC1 (9)
|
|
||||||
#define WB_IO5 PIN_NFC1
|
|
||||||
#define WB_IO4 (4)
|
|
||||||
#define PIN_NFC2 (10)
|
|
||||||
|
|
||||||
static const uint8_t AREF = PIN_AREF;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Serial interfaces
|
|
||||||
*/
|
|
||||||
// TXD1 RXD1 on Base Board
|
|
||||||
#define PIN_SERIAL1_RX (15)
|
|
||||||
#define PIN_SERIAL1_TX (16)
|
|
||||||
|
|
||||||
// Connected to Jlink CDC
|
|
||||||
#define PIN_SERIAL2_RX (8)
|
|
||||||
#define PIN_SERIAL2_TX (6)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SPI Interfaces
|
|
||||||
*/
|
|
||||||
#define SPI_INTERFACES_COUNT 2
|
|
||||||
|
|
||||||
#define PIN_SPI_MISO (45)
|
|
||||||
#define PIN_SPI_MOSI (44)
|
|
||||||
#define PIN_SPI_SCK (43)
|
|
||||||
|
|
||||||
#define PIN_SPI1_MISO (29)
|
|
||||||
#define PIN_SPI1_MOSI (30)
|
|
||||||
#define PIN_SPI1_SCK (3)
|
|
||||||
|
|
||||||
static const uint8_t SS = 42;
|
|
||||||
static const uint8_t MOSI = PIN_SPI_MOSI;
|
|
||||||
static const uint8_t MISO = PIN_SPI_MISO;
|
|
||||||
static const uint8_t SCK = PIN_SPI_SCK;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wire Interfaces
|
|
||||||
*/
|
|
||||||
#define WIRE_INTERFACES_COUNT 1
|
|
||||||
|
|
||||||
#define PIN_WIRE_SDA (WB_I2C1_SDA)
|
|
||||||
#define PIN_WIRE_SCL (WB_I2C1_SCL)
|
|
||||||
|
|
||||||
// QSPI Pins
|
|
||||||
// QSPI occupied by GPIO's
|
|
||||||
#define PIN_QSPI_SCK 3
|
|
||||||
#define PIN_QSPI_CS 26
|
|
||||||
#define PIN_QSPI_IO0 30
|
|
||||||
#define PIN_QSPI_IO1 29
|
|
||||||
#define PIN_QSPI_IO2 28
|
|
||||||
#define PIN_QSPI_IO3 2
|
|
||||||
|
|
||||||
// On-board QSPI Flash
|
|
||||||
// No onboard flash
|
|
||||||
#define EXTERNAL_FLASH_DEVICES IS25LP080D
|
|
||||||
#define EXTERNAL_FLASH_USE_QSPI
|
|
||||||
|
|
||||||
#define P_LORA_SCK PIN_SPI1_SCK
|
|
||||||
#define P_LORA_MISO PIN_SPI1_MISO
|
|
||||||
#define P_LORA_MOSI PIN_SPI1_MOSI
|
|
||||||
#define P_LORA_CS 26
|
|
||||||
|
|
||||||
#define USE_SX1262
|
|
||||||
#define SX126X_CS (26)
|
|
||||||
#define SX126X_DIO1 (10)
|
|
||||||
#define SX126X_BUSY (9)
|
|
||||||
#define SX126X_RESET (4)
|
|
||||||
|
|
||||||
#define SX126X_POWER_EN (21)
|
|
||||||
// DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
|
|
||||||
#define SX126X_DIO2_AS_RF_SWITCH
|
|
||||||
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
|
|
||||||
|
|
||||||
// enables 3.3V periphery like GPS or IO Module
|
|
||||||
// Do not toggle this for GPS power savings
|
|
||||||
#define PIN_3V3_EN (34)
|
|
||||||
#define WB_IO2 PIN_3V3_EN
|
|
||||||
|
|
||||||
// RAK1910 GPS module
|
|
||||||
// If using the wisblock GPS module and pluged into Port A on WisBlock base
|
|
||||||
// IO1 is hooked to PPS (pin 12 on header) = gpio 17
|
|
||||||
// IO2 is hooked to GPS RESET = gpio 34, but it can not be used to this because IO2 is ALSO used to control 3V3_S power (1 is on).
|
|
||||||
// Therefore must be 1 to keep peripherals powered
|
|
||||||
// Power is on the controllable 3V3_S rail
|
|
||||||
#define PIN_GPS_PPS (17) // Pulse per second input from the GPS
|
|
||||||
|
|
||||||
#define PIN_GPS_RX PIN_SERIAL1_RX
|
|
||||||
#define PIN_GPS_TX PIN_SERIAL1_TX
|
|
||||||
|
|
||||||
// Battery
|
|
||||||
// The battery sense is hooked to pin A0 (5)
|
|
||||||
#define BATTERY_PIN PIN_A0
|
|
||||||
// and has 12 bit resolution
|
|
||||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
|
||||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
|
||||||
#undef AREF_VOLTAGE
|
|
||||||
#define AREF_VOLTAGE 3.0
|
|
||||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
|
||||||
#define ADC_MULTIPLIER 1.73
|
|
||||||
|
|
||||||
#define HAS_RTC 1
|
|
||||||
|
|
||||||
#define RAK_4631 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
|
||||||
* Arduino objects - C++ only
|
|
||||||
*----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Reference in New Issue
Block a user