Compare commits

...

31 Commits

Author SHA1 Message Date
Jm Casler
f511baba9a Bump to 1.3.6 2022-04-12 21:25:33 -07:00
Jm Casler
0e4699d8b6 updating proto submodule to latest 2022-04-12 21:13:35 -07:00
Ben Meadors
794167c701 Removed phone sds timeout (#1372) 2022-04-12 08:04:24 -05:00
amerinoj
b59368ca3c Updated pinut in variant tlorav2_1_16 (#1365)
* Added the last mac address bytes in bluetooth device name ESP32Bluetooth.cpp
Add default notification pinout to tlora_v2_1_16/variant.h

* updated ADC_MULTIPLIER  value for more accuracy

* Update variant.h

Updated LORA_RESET GPIO in this board is 23
Removed LORA_DIO1 35 , gpio 35 is a battery pin 
Removed LORA_DIO2 34, gpio 34 is unuse in this board

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-04-12 07:13:25 -05:00
Jm Casler
02066cc8b9 Merge pull request #1370 from mc-hamster/region_unset
Work around for issue with unknown age due to not having time
2022-04-11 19:18:59 -07:00
Jm Casler
309de52f5c Merge branch 'master' into region_unset 2022-04-11 18:53:54 -07:00
Jm Casler
340737f2a8 Work around for issue with unknown age due to not having time
Work around for issue with unknown age due to not having time
2022-04-11 18:53:29 -07:00
Jm Casler
9bd970c55e Merge pull request #1368 from mc-hamster/region_unset
Show welcome screen if region unset
2022-04-10 19:55:05 -07:00
Jm Casler
6eab8f84d1 Updated text for better fit 2022-04-10 19:34:13 -07:00
Jm Casler
a31bf71ec1 Merge branch 'region_unset' of https://github.com/mc-hamster/Meshtastic-device into region_unset 2022-04-10 19:27:17 -07:00
Jm Casler
14eef42762 Disable indicator on welcome screen. 2022-04-10 19:27:11 -07:00
Jm Casler
ef85b74cec Merge branch 'master' into region_unset 2022-04-10 19:15:47 -07:00
Jm Casler
16ae867c2d Show welcome screen if region unset 2022-04-10 19:15:10 -07:00
Jm Casler
0643dcd745 Merge pull request #1367 from mc-hamster/region_unset
Disable TX if region is unset
2022-04-09 23:08:59 -07:00
Jm Casler
69ed477040 Disable TX if region is unset 2022-04-09 22:42:43 -07:00
Jm Casler
0f5b0b5f00 Update README.md 2022-04-08 19:51:13 -07:00
Sacha Weatherstone
11323acb23 Update link to site 2022-04-08 13:40:41 +10:00
Ben Meadors
a20ba7e686 Add pca10059_diy_eink to boards matrix 2022-04-06 11:04:11 -05:00
Ben Meadors
10a7071300 Remove send owner interval (#1361)
* NodeInfo slimfast

* Removed send_owner_interval
2022-04-06 08:03:44 -05:00
Thomas Göttgens
eae9673ddb Merge pull request #1360 from meshtastic/1355-bug-crash-in-json-mqtt-bridge
fixes #1355
2022-04-06 14:28:23 +02:00
Thomas Göttgens
6e9cf82b68 fixes #1355 2022-04-06 14:11:39 +02:00
Thomas Göttgens
0035469790 Merge pull request #1358 from meshtastic/gpsfix
Improve T-Echo GPS Handling
2022-04-06 09:29:59 +02:00
Thomas Göttgens
028999697e Improve T-Echo GPS Handling 2022-04-06 09:18:55 +02:00
Mark Trevor Birss
b7aa1397c7 Add DIY nRF82540 PCA10059 4.2inch NiceRF 868 (#1354)
* Update build-all.sh

* Update configuration.h

* Update EInkDisplay2.cpp

* Create platformio.ini

* Create variant.cpp

* Create variant.h

* Update platformio.ini

* Update check-all.sh

* Create nordic_pca10059.json

* Update variant.h

* Update EInkDisplay2.cpp

* Update configuration.h

* Update platformio.ini

* Update EInkDisplay2.cpp

* Update variant.h

* Update EInkDisplay2.cpp

* Update configuration.h

* Update EInkDisplay2.cpp

* Update variant.h

* Update nordic_pca10059.json

* Update platformio.ini

* Update platformio.ini

* Update platformio.ini

* Update platformio.ini

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update variant.h

* Update configuration.h

* Update EInkDisplay2.cpp

* Update variant.h

* Update variant.h

* Update platformio.ini

* Update configuration.h

* Update configuration.h

* Update platformio.ini

* Update platformio.ini

* Update configuration.h

* Update platformio.ini

* Update configuration.h

* Update platformio.ini

* Update configuration.h

* Update configuration.h

* Update platformio.ini

* Update configuration.h

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-04-05 11:46:07 -05:00
github-actions[bot]
279def7911 [create-pull-request] automated change (#1356)
Co-authored-by: thebentern <thebentern@users.noreply.github.com>
2022-04-05 11:31:13 -05:00
Ben Meadors
d73d3ca959 Update proto action to use nanopb 0.4.5 2022-04-05 11:29:54 -05:00
Michael Kleinhenz
998c90d326 Use JSON library for Web UI REST Endpoints (#1340)
* Updated rest endpoint json handling.

* Fixes, typos corrected.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Sacha Weatherstone <sachaw100@hotmail.com>
2022-04-05 06:22:38 +10:00
neilhao
0c600363c8 add nano g1 (#1351)
* add nano g1

* Update platformio.ini

* Update configuration.h

* Revert platformio.ini to previous state

* Update configuration.h

* Update platformio.ini

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-04-04 20:16:19 +10:00
Thomas Göttgens
6c2d45d866 Merge pull request #1353 from meshtastic/patch-1
Add second scancode for SH1106
2022-04-04 09:12:09 +02:00
Thomas Göttgens
cf532496a4 Merge branch 'master' into patch-1 2022-04-04 08:52:07 +02:00
Thomas Göttgens
92d32f722d Add second scancode for SH1106
This display is found on the Nano G1
2022-04-04 08:51:29 +02:00
31 changed files with 611 additions and 522 deletions

View File

@@ -162,6 +162,7 @@ jobs:
- board: rak4631_19003
- board: rak4631_5005_eink
- board: t-echo
- board: pca10059_diy_eink
runs-on: ubuntu-latest
steps:

View File

@@ -17,9 +17,9 @@ jobs:
- name: Download nanopb
run: |
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.4-linux-x86.tar.gz
tar xvzf nanopb-0.4.4-linux-x86.tar.gz
mv nanopb-0.4.4-linux-x86 nanopb-0.4.4
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.5-linux-x86.tar.gz
tar xvzf nanopb-0.4.5-linux-x86.tar.gz
mv nanopb-0.4.5-linux-x86 nanopb-0.4.5
- name: Re-generate protocol buffers
run: |

View File

@@ -2,6 +2,7 @@
[![Open in Visual Studio Code](https://open.vscode.dev/badges/open-in-vscode.svg)](https://open.vscode.dev/meshtastic/Meshtastic-device)
[![Continuous Integration](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml/badge.svg)](https://github.com/meshtastic/Meshtastic-device/actions/workflows/main.yml)
![GitHub all releases](https://img.shields.io/github/downloads/meshtastic/meshtastic-device/total)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/Meshtastic-device)](https://cla-assistant.io/meshtastic/Meshtastic-device)
## This repository contains the device firmware used in the [Meshtastic](https://meshtastic.org) project.

View File

@@ -9,7 +9,7 @@ BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-
#BOARDS_ESP32=tbeam
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
BOARDS_NRF52="rak4631_5005 rak4631_5005_eink rak4631_19003 t-echo"
BOARDS_NRF52="rak4631_5005 rak4631_5005_eink rak4631_19003 t-echo pca10059_diy_eink"
#BOARDS_NRF52=""
OUTDIR=release/latest

View File

@@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
# can override which environment by passing arg
BOARDS="$@"
else
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo"
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631_5005 rak4631_19003 rak11200 t-echo pca10059_diy_eink"
fi
echo "BOARDS:${BOARDS}"

View File

@@ -0,0 +1,72 @@
{
"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": "PCA10059",
"mcu": "nrf52840",
"variant": "nRF52840 Dongle",
"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": "nRF52840 Dongle",
"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.nordicsemi.com/Products/Development-hardware/nrf52840-dongle",
"vendor": "Nordic Semiconductor"
}

View File

@@ -19,6 +19,8 @@ default_envs = tbeam
;default_envs = rak4631_5005
;default_envs = rak4631_5005_eink
;default_envs = rak4631_19003
;default_envs = nano-g1
;default_envs = pca10059_diy_eink
;default_envs = meshtastic-diy-v1
;default_envs = meshtastic-diy-v1.1
@@ -40,13 +42,13 @@ build_flags = -Wno-missing-field-initializers
monitor_speed = 921600
lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
https://github.com/meshtastic/arduino-fsm.git
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79
https://github.com/meshtastic/TinyGPSPlus.git
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
Wire ; explicitly needed here because the AXP202 library forgets to add it
SPI
@@ -157,4 +159,4 @@ extends = nrf52_base
board = rak815
debug_tool = jlink
upload_protocol = jlink
monitor_speed = 115200
monitor_speed = 115200

2
proto

Submodule proto updated: 31eaff0924...870a62b27e

View File

@@ -363,9 +363,6 @@ void PowerFSM_setup()
if (meshSds != UINT32_MAX)
powerFSM.add_timed_transition(lowPowerState, &stateSDS, meshSds * 1000, NULL, "mesh timeout");
// removing for now, because some users don't even have phones
// powerFSM.add_timed_transition(lowPowerState, &stateSDS, getPref_phone_sds_timeout_sec() * 1000, NULL, "phone
// timeout");
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
}

View File

@@ -240,6 +240,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HW_VENDOR HardwareModel_T_ECHO
#elif defined(NANO_G1)
#define HW_VENDOR HardwareModel_NANO_G1
#elif defined(NORDIC_PCA10059)
#define HW_VENDOR HardwareModel_NRF52840_PCA10059
#elif NRF52_SERIES
#define HW_VENDOR HardwareModel_NRF52_UNKNOWN

View File

@@ -15,7 +15,7 @@ uint8_t oled_probe(byte addr)
r = Wire.read();
}
r &= 0x0f;
if (r == 0x08) {
if (r == 0x08 || r == 0x00) {
o_probe = 2; // SH1106
} else if ( r == 0x03 || r == 0x06 || r == 0x07) {
o_probe = 1; // SSD1306

View File

@@ -41,6 +41,25 @@ bool GPS::setupGPS()
#endif
#ifndef NO_ESP32
_serial_gps->setRxBufferSize(2048); // the default is 256
#endif
#ifdef TTGO_T_ECHO
// Switch to 4800 baud, then close and reopen port
_serial_gps->write("$PCAS01,0*1C\r\n");
delay(250);
_serial_gps->end();
delay(250);
_serial_gps->begin(4800);
delay(250);
// Initialize the L76K Chip, use GPS + GLONASS
_serial_gps->write("$PCAS04,5*1C\r\n");
delay(250);
// only ask for RMC and GGA
_serial_gps->write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n");
delay(250);
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
_serial_gps->write("$PCAS11,3*1E\r\n");
delay(250);
#endif
}

View File

@@ -25,6 +25,11 @@
//1.54 inch 200x200 - GxEPD2_154_M09
//#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
#elif defined(PCA10059)
//4.2 inch 300x400 - GxEPD2_420_M01
#define TECHO_DISPLAY_MODEL GxEPD2_420_M01
#endif
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
@@ -47,6 +52,11 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
//GxEPD2_154_M09
//setGeometry(GEOMETRY_RAWMODE, 200, 200);
#elif defined(PCA10059)
//GxEPD2_420_M01
setGeometry(GEOMETRY_RAWMODE, 300, 400);
#endif
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
// setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does
@@ -71,8 +81,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
for (uint64_t y = 0; y < displayHeight; y++) {
for (uint64_t x = 0; x < displayWidth; x++) {
for (uint32_t y = 0; y < displayHeight; y++) {
for (uint32_t x = 0; x < displayWidth; x++) {
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
auto b = buffer[x + (y / 8) * displayWidth];
@@ -81,11 +91,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
}
}
#if defined(TTGO_T_ECHO)
DEBUG_MSG("Updating T-ECHO E-Paper... ");
#elif defined(RAK4630)
DEBUG_MSG("Updating RAK4361_5005 E-Paper... ");
#endif
DEBUG_MSG("Updating E-Paper... ");
#if defined(TTGO_T_ECHO)
// ePaper.Reset(); // wake the screen from sleep
@@ -101,6 +107,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
// 4.2 inch 300x400 - GxEPD2_420_M01
//adafruitDisplay->nextPage();
#elif defined(PCA10059)
adafruitDisplay->nextPage();
#endif
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
@@ -176,6 +184,14 @@ bool EInkDisplay::connect()
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#elif defined(PCA10059)
{
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
adafruitDisplay->setRotation(3);
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
}
#endif

View File

@@ -168,6 +168,28 @@ static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16
}
}
// Used when booting without a region set
static void drawWelcomeScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->drawString(64 + x, y, "Meshtastic :)");
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->drawString(x, y + FONT_HEIGHT_SMALL * 2 - 3, "Set the region using the");
display->drawString(x, y + FONT_HEIGHT_SMALL * 3 - 3, "Meshtastic Android, iOS,");
display->drawString(x, y + FONT_HEIGHT_SMALL * 4 - 3, "Flasher or CLI client.");
#ifndef NO_ESP32
yield();
esp_task_wdt_reset();
#endif
}
#ifdef HAS_EINK
/// Used on eink displays while in deep sleep
static void drawSleepScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
@@ -256,7 +278,7 @@ static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *sta
display->drawString(0 + x, 0 + y, tempBuf);
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(FONT_SMALL);
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please post on\nmeshtastic.discourse.group");
display->drawString(0 + x, FONT_HEIGHT_MEDIUM + y, "For help, please visit \nmeshtastic.org");
}
// Ignore messages orginating from phone (from the current node 0x0) unless range test or store and forward module are enabled
@@ -646,8 +668,18 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
snprintf(lastStr, sizeof(lastStr), "%u seconds ago", agoSecs);
else if (agoSecs < 120 * 60) // last 2 hrs
snprintf(lastStr, sizeof(lastStr), "%u minutes ago", agoSecs / 60);
else
snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60);
else {
uint32_t hours_in_month = 730;
// Only show hours ago if it's been less than 6 months. Otherwise, we may have bad
// data.
if ((agoSecs / 60 / 60) < (hours_in_month * 6)) {
snprintf(lastStr, sizeof(lastStr), "%u hours ago", agoSecs / 60 / 60);
} else {
snprintf(lastStr, sizeof(lastStr), "unknown age");
}
}
static char distStr[20];
strcpy(distStr, "? km"); // might not have location data
@@ -766,7 +798,7 @@ void Screen::setup()
useDisplay = true;
#ifdef AutoOLEDWire_h
dispdev.setDetected(screen_model);
dispdev.setDetected(screen_model);
#endif
// I think this is not needed - redundant with ui.init
@@ -862,6 +894,10 @@ int32_t Screen::runOnce()
showingBootScreen = false;
}
if (radioConfig.preferences.region == RegionCode_Unset) {
setWelcomeFrames();
}
// Process incoming commands.
for (;;) {
ScreenCmd cmd;
@@ -975,6 +1011,20 @@ void Screen::setSSLFrames()
}
}
/* show a message that the SSL cert is being built
* it is expected that this will be used during the boot phase */
void Screen::setWelcomeFrames()
{
if (address_found) {
// DEBUG_MSG("showing Welcome frames\n");
ui.disableAllIndicators();
static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
ui.setFrames(welcomeFrames, 1);
ui.update();
}
}
// restore our regular frame list
void Screen::setFrames()
{
@@ -1366,7 +1416,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
}
auto mode = "";
if (channels.getPrimary().modem_config == 0) {
mode = "VLongSlow";
} else if (channels.getPrimary().modem_config == 1) {
@@ -1380,7 +1430,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
} else if (channels.getPrimary().modem_config == 5) {
mode = "ShortSlow";
} else if (channels.getPrimary().modem_config == 6) {
mode = "ShortFast";
mode = "ShortFast";
} else {
mode = "Custom";
}
@@ -1432,8 +1482,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
// Display Channel Utilization
char chUtil[13];
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil),
y + FONT_HEIGHT_SMALL * 1, chUtil);
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
// Line 3
if (radioConfig.preferences.gps_format != GpsCoordinateFormat_GpsFormatDMS) // if DMS then don't draw altitude
@@ -1491,16 +1540,13 @@ int Screen::handleTextMessage(const MeshPacket *packet)
int Screen::handleUIFrameEvent(const UIFrameEvent *event)
{
if (showingNormalScreen) {
if (event->frameChanged)
{
if (event->frameChanged) {
setFrames(); // Regen the list of screens (will show new text message)
}
else if (event->needRedraw)
{
} else if (event->needRedraw) {
setFastFramerate();
// TODO: We might also want switch to corresponding frame,
// but we don't know the exact frame number.
//ui.switchToFrame(0);
// ui.switchToFrame(0);
}
}

View File

@@ -235,6 +235,8 @@ class Screen : public concurrency::OSThread
/// Draws our SSL cert screen during boot (called from WebServer)
void setSSLFrames();
void setWelcomeFrames();
protected:
/// Updates the UI.
//

View File

@@ -1,250 +0,0 @@
#include "configuration.h"
#include "DSRRouter.h"
/* when we receive any packet
- sniff and update tables (especially useful to find adjacent nodes). Update user, network and position info.
- if we need to route() that packet, resend it to the next_hop based on our nodedb.
- if it is broadcast or destined for our node, deliver locally
- handle routereply/routeerror/routediscovery messages as described below
- then free it
routeDiscovery
- if we've already passed through us (or is from us), then it ignore it
- use the nodes already mentioned in the request to update our routing table
- if they were looking for us, send back a routereply
- if max_hops is zero and they weren't looking for us, drop (FIXME, send back error - I think not though?)
- if we receive a discovery packet, we use it to populate next_hop (if needed) towards the requester (after decrementing max_hops)
- if we receive a discovery packet, and we have a next_hop in our nodedb for that destination we send a (reliable) we send a route
reply towards the requester
when sending any reliable packet
- if timeout doing retries, send a routeError (nak) message back towards the original requester. all nodes eavesdrop on that
packet and update their route caches.
when we receive a routereply packet
- update next_hop on the node, if the new reply needs fewer hops than the existing one (we prefer shorter paths). fixme, someday
use a better heuristic
when we receive a routeError packet
- delete the route for that failed recipient, restartRouteDiscovery()
- if we receive routeerror in response to a discovery,
- fixme, eventually keep caches of possible other routes.
*/
ErrorCode DSRRouter::send(MeshPacket *p)
{
// We only consider multihop routing packets (i.e. those with dest set)
if (p->decoded.dest) {
// add an entry for this pending message
auto pending = startRetransmission(p);
// FIXME - when acks come in for this packet, we should _not_ delete the record unless the ack was from
// the final dest. We need to keep that record around until FIXME
// Also we should not retransmit multihop entries in that table at all
// If we have an entry in our routing tables, just send it, otherwise start a route discovery
NodeNum nextHop = getNextHop(p->decoded.dest);
if (nextHop) {
sendNextHop(nextHop, p); // start a reliable single hop send
} else {
pending->wantRoute = true;
// start discovery, but only if we don't already a discovery in progress for that node number
startDiscovery(p->decoded.dest);
}
return ERRNO_OK;
} else
return ReliableRouter::send(p);
}
void DSRRouter::sniffReceived(const MeshPacket *p, const Routing *c)
{
// Learn 0 hop routes by just hearing any adjacent nodes
// But treat broadcasts carefully, because when flood broadcasts go out they keep the same original "from". So we want to
// ignore rebroadcasts.
// this will also add records for any ACKs we receive for our messages
if (p->to != NODENUM_BROADCAST || p->hop_limit != HOP_RELIABLE) {
addRoute(getFrom(p), getFrom(p), 0); // We are adjacent with zero hops
}
if (c)
switch (c->which_variant) {
case Routing_route_request_tag:
// Handle route discovery packets (will be a broadcast message)
// FIXME - always start request with the senders nodenum
if (weAreInRoute(c->route_request)) {
DEBUG_MSG("Ignoring a route request that contains us\n");
} else {
updateRoutes(c->route_request,
true); // Update our routing tables based on the route that came in so far on this request
if (p->decoded.dest == getNodeNum()) {
// They were looking for us, send back a route reply (the sender address will be first in the list)
sendRouteReply(c->route_request);
} else {
// They were looking for someone else, forward it along (as a zero hop broadcast)
NodeNum nextHop = getNextHop(p->decoded.dest);
if (nextHop) {
// in our route cache, reply to the requester (the sender address will be first in the list)
sendRouteReply(c->route_request, nextHop);
} else {
// Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
resendRouteRequest(p);
}
}
}
break;
case Routing_route_reply_tag:
updateRoutes(c->route_reply, false);
// FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular
// pending packets until ack arrives)
// FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our
// own...
break;
case Routing_error_reason_tag:
removeRoute(p->decoded.dest);
// FIXME: if any pending packets were waiting on this route, delete them
break;
default:
break;
}
// We simply ignore ACKs - because ReliableRouter will delete the pending packet for us
// Handle regular packets
if (p->to == getNodeNum()) { // Destined for us (at least for this hop)
// We need to route this packet to some other node
if (p->decoded.dest && p->decoded.dest != p->to) {
// if we have a route out, resend the packet to the next hop, otherwise return RouteError no-route available
NodeNum nextHop = getNextHop(p->decoded.dest);
if (nextHop) {
sendNextHop(nextHop, p); // start a reliable single hop send
} else {
// We don't have a route out
assert(p->decoded.source); // I think this is guaranteed by now
// FIXME - what if the current packet _is_ a route error packet?
sendRouteError(p, Routing_Error_NO_ROUTE);
}
// FIXME, stop local processing of this packet
}
if (c) {
// handle naks - convert them to route error packets
// All naks are generated locally, because we failed resending the packet too many times
PacketId nakId = c->error_reason ? p->decoded.request_id : 0;
if (nakId) {
auto pending = findPendingPacket(p->to, nakId);
if (pending &&
pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore
removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node
sendRouteError(p, Routing_Error_GOT_NAK);
}
}
}
}
ReliableRouter::sniffReceived(p, c);
}
/**
* Does our node appear in the specified route
*/
bool DSRRouter::weAreInRoute(const RouteDiscovery &route)
{
return true; // FIXME
}
/**
* Given a DSR route, use that route to update our DB of possible routes
*
* Note: routes are always listed in the same order - from sender to receipient (i.e. route_replies also use this some order)
*
* @param isRequest is true if we are looking at a route request, else we are looking at a reply
**/
void DSRRouter::updateRoutes(const RouteDiscovery &route, bool isRequest)
{
DEBUG_MSG("FIXME not implemented updateRoutes\n");
}
/**
* send back a route reply (the sender address will be first in the list)
*/
void DSRRouter::sendRouteReply(const RouteDiscovery &route, NodeNum toAppend)
{
DEBUG_MSG("FIXME not implemented sendRoute\n");
}
/**
* Given a nodenum return the next node we should forward to if we want to reach that node.
*
* @return 0 if no route found
*/
NodeNum DSRRouter::getNextHop(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented getNextHop\n");
return 0;
}
/** Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
*
* We will bump down hop_limit in this call.
*/
void DSRRouter::resendRouteRequest(const MeshPacket *p)
{
DEBUG_MSG("FIXME not implemented resendRoute\n");
}
/**
* Record that forwarder can reach dest for us, but they will need numHops to get there.
* If our routing tables already have something that can reach that node in fewer hops we will keep the existing route
* instead.
*/
void DSRRouter::addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops)
{
DEBUG_MSG("FIXME not implemented addRoute\n");
}
/**
* Record that we no longer have a route to the dest
*/
void DSRRouter::removeRoute(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented removeRoute\n");
}
/**
* Forward the specified packet to the specified node
*/
void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
{
DEBUG_MSG("FIXME not implemented sendNextHop\n");
}
/**
* Send a route error packet towards whoever originally sent this message
*/
void DSRRouter::sendRouteError(const MeshPacket *p, Routing_Error err)
{
DEBUG_MSG("FIXME not implemented sendRouteError\n");
}
/** make a copy of p, start discovery, but only if we don't
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
* when the discovery is complete.
*/
void DSRRouter::startDiscovery(NodeNum dest)
{
DEBUG_MSG("FIXME not implemented startDiscovery\n");
}

View File

@@ -1,80 +0,0 @@
#include "ReliableRouter.h"
class DSRRouter : public ReliableRouter
{
protected:
/**
* Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to
* update routing tables etc... based on what we overhear (even for messages not destined to our node)
*/
virtual void sniffReceived(const MeshPacket *p, const Routing *c) override;
/**
* Send a packet on a suitable interface. This routine will
* later free() the packet to pool. This routine is not allowed to stall.
* If the txmit queue is full it might return an error
*/
virtual ErrorCode send(MeshPacket *p) override;
private:
/**
* Does our node appear in the specified route
*/
bool weAreInRoute(const RouteDiscovery &route);
/**
* Given a DSR route, use that route to update our DB of possible routes
*
* Note: routes are always listed in the same order - from sender to receipient (i.e. route_replies also use this some order)
*
* @param isRequest is true if we are looking at a route request, else we are looking at a reply
**/
void updateRoutes(const RouteDiscovery &route, bool isRequest);
/**
* send back a route reply (the sender address will be first in the list)
*/
void sendRouteReply(const RouteDiscovery &route, NodeNum toAppend = 0);
/**
* Given a nodenum return the next node we should forward to if we want to reach that node.
*
* @return 0 if no route found
*/
NodeNum getNextHop(NodeNum dest);
/** Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
*
* We will bump down hop_limit in this call.
*/
void resendRouteRequest(const MeshPacket *p);
/**
* Record that forwarder can reach dest for us, but they will need numHops to get there.
* If our routing tables already have something that can reach that node in fewer hops we will keep the existing route
* instead.
*/
void addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops);
/**
* Record that we no longer have a route to the dest
*/
void removeRoute(NodeNum dest);
/**
* Forward the specified packet to the specified node
*/
void sendNextHop(NodeNum n, const MeshPacket *p);
/**
* Send a route error packet towards whoever originally sent this message
*/
void sendRouteError(const MeshPacket *p, Routing_Error err);
/** make a copy of p, start discovery, but only if we don't
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
* when the discovery is complete.
*/
void startDiscovery(NodeNum dest);
};

View File

@@ -141,12 +141,10 @@ extern NodeDB nodeDB;
# prefs.position_broadcast_secs = FIXME possibly broadcast only once an hr
prefs.wait_bluetooth_secs = 1 # Don't stay in bluetooth mode
prefs.mesh_sds_timeout_secs = never
prefs.phone_sds_timeout_sec = never
# try to stay in light sleep one full day, then briefly wake and sleep again
prefs.ls_secs = oneday
prefs.send_owner_interval = 2 # Send an owner packet every other network ping
prefs.position_broadcast_secs = 12 hours # send either position or owner every 12hrs
# get a new GPS position once per day
@@ -166,7 +164,6 @@ extern NodeDB nodeDB;
#define PREF_GET(name, defaultVal) \
inline uint32_t getPref_##name() { return radioConfig.preferences.name ? radioConfig.preferences.name : (defaultVal); }
PREF_GET(send_owner_interval, IF_ROUTER(2, 4))
PREF_GET(position_broadcast_secs, IF_ROUTER(12 * 60 * 60, 15 * 60))
// Defaulting Telemetry to the same as position interval for now
PREF_GET(telemetry_module_device_update_interval, IF_ROUTER(12 * 60 * 60, 15 * 60))
@@ -178,7 +175,6 @@ PREF_GET(wait_bluetooth_secs, IF_ROUTER(1, 60))
PREF_GET(screen_on_secs, 60)
PREF_GET(mesh_sds_timeout_secs, IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60))
PREF_GET(phone_sds_timeout_sec, IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60))
PREF_GET(sds_secs, 365 * 24 * 60 * 60)
// We default to sleeping (with bluetooth off for 5 minutes at a time). This seems to be a good tradeoff between

View File

@@ -1,8 +1,8 @@
#include "configuration.h"
#include "RadioLibInterface.h"
#include "MeshTypes.h"
#include "NodeDB.h"
#include "SPILock.h"
#include "configuration.h"
#include "error.h"
#include "mesh-pb-constants.h"
#include <pb_decode.h>
@@ -93,8 +93,15 @@ bool RadioLibInterface::canSendImmediately()
/// bluetooth comms code. If the txmit queue is empty it might return an error
ErrorCode RadioLibInterface::send(MeshPacket *p)
{
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
DEBUG_MSG("send - lora_tx_disabled\n");
if (radioConfig.preferences.region != RegionCode_Unset) {
if (disabled || radioConfig.preferences.is_lora_tx_disabled) {
DEBUG_MSG("send - lora_tx_disabled\n");
packetPool.release(p);
return ERRNO_DISABLED;
}
} else {
DEBUG_MSG("send - lora_tx_disabled because RegionCode_Unset\n");
packetPool.release(p);
return ERRNO_DISABLED;
}
@@ -115,9 +122,9 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
/* We assume if rx_snr = 0 and rx_rssi = 0, the packet was not generated locally.
* This assumption is valid because of the offset generated by the radio to account for the noise
* floor.
*/
* This assumption is valid because of the offset generated by the radio to account for the noise
* floor.
*/
if (p->rx_snr == 0 && p->rx_rssi == 0) {
startTransmitTimer(true);
} else {
@@ -125,7 +132,6 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
DEBUG_MSG("rx_snr found. hop_limit:%d rx_snr:%f\n", p->hop_limit, p->rx_snr);
startTransmitTimerSNR(p->rx_snr);
}
return res;
#else
@@ -311,7 +317,7 @@ void RadioLibInterface::handleReceiveInterrupt()
printPacket("Lora RX", mp);
//xmitMsec = getPacketTime(mp);
// xmitMsec = getPacketTime(mp);
airTime->logAirtime(RX_LOG, xmitMsec);
deliverToReceiver(mp);
@@ -334,7 +340,7 @@ void RadioLibInterface::startSend(MeshPacket *txp)
size_t numbytes = beginSending(txp);
int res = iface->startTransmit(radiobuf, numbytes);
if(res != ERR_NONE) {
if (res != ERR_NONE) {
RECORD_CRITICALERROR(CriticalErrorCode_RadioSpiBug);
// This send failed, but make sure to 'complete' it properly

View File

@@ -129,7 +129,7 @@ extern const pb_msgdesc_t AdminMessage_msg;
#define AdminMessage_fields &AdminMessage_msg
/* Maximum encoded size of messages (where known) */
#define AdminMessage_size 610
#define AdminMessage_size 598
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -61,6 +61,10 @@ typedef enum _HardwareModel {
HardwareModel_DIY_V1 = 39,
/* RAK WisBlock ESP32 core: https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11200/Overview/ */
HardwareModel_RAK11200 = 40,
/* B&Q Consulting Nano Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:nano */
HardwareModel_NANO_G1 = 41,
/* nRF52840 Dongle : https://www.nordicsemi.com/Products/Development-hardware/nrf52840-dongle/ */
HardwareModel_NRF52840_PCA10059 = 42,
/* Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. */
HardwareModel_PRIVATE_HW = 255
} HardwareModel;

View File

@@ -260,11 +260,9 @@ typedef enum _RadioConfig_UserPreferences_TelemetrySensorType {
/* Struct definitions */
typedef struct _RadioConfig_UserPreferences {
uint32_t position_broadcast_secs;
uint32_t send_owner_interval;
uint32_t wait_bluetooth_secs;
uint32_t screen_on_secs;
uint32_t phone_timeout_secs;
uint32_t phone_sds_timeout_sec;
uint32_t mesh_sds_timeout_secs;
uint32_t sds_secs;
uint32_t ls_secs;
@@ -401,17 +399,15 @@ extern "C" {
/* Initializer values for message structs */
#define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
#define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, _RegionCode_MIN, _ChargeCurrent_MIN, 0, _Role_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, _GpsCoordinateFormat_MIN, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_Serial_Mode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _RadioConfig_UserPreferences_TelemetrySensorType_MIN, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, 0, 0, 0, 0, _InputEventChar_MIN, _InputEventChar_MIN, _InputEventChar_MIN, 0, 0, "", 0, 0, 0, _RadioConfig_UserPreferences_Serial_Baud_MIN, 0}
/* Field tags (for use in manual encoding/decoding) */
#define RadioConfig_UserPreferences_position_broadcast_secs_tag 1
#define RadioConfig_UserPreferences_send_owner_interval_tag 2
#define RadioConfig_UserPreferences_wait_bluetooth_secs_tag 4
#define RadioConfig_UserPreferences_screen_on_secs_tag 5
#define RadioConfig_UserPreferences_phone_timeout_secs_tag 6
#define RadioConfig_UserPreferences_phone_sds_timeout_sec_tag 7
#define RadioConfig_UserPreferences_mesh_sds_timeout_secs_tag 8
#define RadioConfig_UserPreferences_sds_secs_tag 9
#define RadioConfig_UserPreferences_ls_secs_tag 10
@@ -502,11 +498,9 @@ X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1)
#define RadioConfig_UserPreferences_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, position_broadcast_secs, 1) \
X(a, STATIC, SINGULAR, UINT32, send_owner_interval, 2) \
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 4) \
X(a, STATIC, SINGULAR, UINT32, screen_on_secs, 5) \
X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 6) \
X(a, STATIC, SINGULAR, UINT32, phone_sds_timeout_sec, 7) \
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 8) \
X(a, STATIC, SINGULAR, UINT32, sds_secs, 9) \
X(a, STATIC, SINGULAR, UINT32, ls_secs, 10) \
@@ -597,8 +591,8 @@ extern const pb_msgdesc_t RadioConfig_UserPreferences_msg;
#define RadioConfig_UserPreferences_fields &RadioConfig_UserPreferences_msg
/* Maximum encoded size of messages (where known) */
#define RadioConfig_UserPreferences_size 604
#define RadioConfig_size 607
#define RadioConfig_UserPreferences_size 592
#define RadioConfig_size 595
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -8,10 +8,11 @@
#include "mesh/http/WiFiAPClient.h"
#include "power.h"
#include "sleep.h"
#include <FSCommon.h>
#include <HTTPBodyParser.hpp>
#include <HTTPMultipartBodyParser.hpp>
#include <HTTPURLEncodedBodyParser.hpp>
#include <FSCommon.h>
#include <json11.hpp>
#ifndef NO_ESP32
#include "esp_task_wdt.h"
@@ -272,8 +273,6 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
}
bool firstFile = 1;
void htmlDeleteDir(const char * dirname)
{
File root = FSCom.open(dirname);
@@ -301,70 +300,72 @@ void htmlDeleteDir(const char * dirname)
root.close();
}
void htmlListDir(HTTPResponse *res, const char * dirname, uint8_t levels)
std::vector<std::map<char *, char *>>* htmlListDir(std::vector<std::map<char *, char *>> *fileList, const char *dirname, uint8_t levels)
{
File root = FSCom.open(dirname);
if(!root){
return;
return NULL;
}
if(!root.isDirectory()){
return;
return NULL;
}
// iterate over the file list
File file = root.openNextFile();
while(file){
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
if(levels){
htmlListDir(res, file.name(), levels -1);
htmlListDir(fileList, file.name(), levels -1);
}
} else {
if (firstFile) {
firstFile = 0;
} else {
res->println(",");
}
res->println("{");
} else {
std::map<char*, char*> thisFileMap;
thisFileMap[strdup("size")] = strdup(String(file.size()).c_str());
thisFileMap[strdup("name")] = strdup(String(file.name()).substring(1).c_str());
if (String(file.name()).substring(1).endsWith(".gz")) {
String modifiedFile = String(file.name()).substring(1);
modifiedFile.remove((modifiedFile.length() - 3), 3);
res->print("\"nameModified\": \"" + modifiedFile + "\",");
res->print("\"name\": \"" + String(file.name()).substring(1) + "\",");
} else {
res->print("\"name\": \"" + String(file.name()).substring(1) + "\",");
thisFileMap[strdup("nameModified")] = strdup(modifiedFile.c_str());
}
res->print("\"size\": " + String(file.size()));
res->print("}");
fileList->push_back(thisFileMap);
}
file.close();
file = root.openNextFile();
}
root.close();
return fileList;
}
void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res)
{
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "GET");
res->println("{");
res->println("\"data\": {");
res->print("\"files\": [");
htmlListDir(res, "/", 10);
res->print("],");
res->print("\"filesystem\" : {");
res->print("\"total\" : " + String(FSCom.totalBytes()) + ",");
res->print("\"used\" : " + String(FSCom.usedBytes()) + ",");
res->print("\"free\" : " + String(FSCom.totalBytes() - FSCom.usedBytes()));
res->println("}");
res->println("},");
res->println("\"status\": \"ok\"");
res->println("}");
}
using namespace json11;
auto fileList = htmlListDir(new std::vector<std::map<char *, char *>>(), "/", 10);
// create json output structure
Json filesystemObj = Json::object{
{"total", String(FSCom.totalBytes()).c_str()},
{"used", String(FSCom.usedBytes()).c_str()},
{"free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()},
};
Json jsonObjInner = Json::object{{"files", Json(*fileList)},
{"filesystem", filesystemObj}
};
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
}
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
ResourceParameters *params = req->getParams();
std::string paramValDelete;
@@ -375,15 +376,15 @@ void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res)
std::string pathDelete = "/" + paramValDelete;
if (FSCom.remove(pathDelete.c_str())) {
Serial.println(pathDelete.c_str());
res->println("{");
res->println("\"status\": \"ok\"");
res->println("}");
Json jsonObjOuter = Json::object{{"status", "ok"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
return;
} else {
Serial.println(pathDelete.c_str());
res->println("{");
res->println("\"status\": \"Error\"");
res->println("}");
Json jsonObjOuter = Json::object{{"status", "Error"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
return;
}
}
@@ -600,6 +601,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
void handleReport(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
ResourceParameters *params = req->getParams();
std::string content;
@@ -618,104 +620,89 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
res->println("<pre>");
}
res->println("{");
res->println("\"data\": {");
res->println("\"airtime\": {");
// data->airtime->tx_log
std::vector<String> txLogValues;
uint32_t *logArray;
res->print("\"tx_log\": [");
logArray = airTime->airtimeReport(TX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
txLogValues.push_back(String(tmp));
}
res->println("],");
res->print("\"rx_log\": [");
// data->airtime->rx_log
std::vector<String> rxLogValues;
logArray = airTime->airtimeReport(RX_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
rxLogValues.push_back(String(tmp));
}
res->println("],");
res->print("\"rx_all_log\": [");
// data->airtime->rx_all_log
std::vector<String> rxAllLogValues;
logArray = airTime->airtimeReport(RX_ALL_LOG);
for (int i = 0; i < airTime->getPeriodsToLog(); i++) {
uint32_t tmp;
tmp = *(logArray + i);
res->printf("%d", tmp);
if (i != airTime->getPeriodsToLog() - 1) {
res->print(", ");
}
rxAllLogValues.push_back(String(tmp));
}
res->println("],");
res->printf("\"channel_utilization\": %3.2f%,\n", airTime->channelUtilizationPercent());
res->printf("\"utilization_tx\": %3.2f%,\n", airTime->utilizationTXPercent());
res->printf("\"seconds_since_boot\": %u,\n", airTime->getSecondsSinceBoot());
res->printf("\"seconds_per_period\": %u,\n", airTime->getSecondsPerPeriod());
res->printf("\"periods_to_log\": %u\n", airTime->getPeriodsToLog());
res->println("},");
res->println("\"wifi\": {");
res->println("\"rssi\": " + String(WiFi.RSSI()) + ",");
Json jsonObjAirtime = Json::object{
{"tx_log", Json(txLogValues)},
{"rx_log", Json(rxLogValues)},
{"rx_all_log", Json(rxAllLogValues)},
{"channel_utilization", Json(airTime->channelUtilizationPercent())},
{"utilization_tx", Json(airTime->utilizationTXPercent())},
{"seconds_since_boot", Json(int(airTime->getSecondsSinceBoot()))},
{"seconds_per_period", Json(int(airTime->getSecondsPerPeriod()))},
{"periods_to_log", Json(airTime->getPeriodsToLog())},
};
// data->wifi
String ipStr;
if (radioConfig.preferences.wifi_ap_mode || isSoftAPForced()) {
res->println("\"ip\": \"" + String(WiFi.softAPIP().toString().c_str()) + "\"");
ipStr = String(WiFi.softAPIP().toString());
} else {
res->println("\"ip\": \"" + String(WiFi.localIP().toString().c_str()) + "\"");
ipStr = String(WiFi.localIP().toString());
}
Json jsonObjWifi = Json::object{
{"rssi", String(WiFi.RSSI())},
{"ip", ipStr.c_str()}
};
res->println("},");
// data->memory
Json jsonObjMemory = Json::object{{"heap_total", Json(int(ESP.getHeapSize()))},
{"heap_free", Json(int(ESP.getFreeHeap()))},
{"psram_total", Json(int(ESP.getPsramSize()))},
{"psram_free", Json(int(ESP.getFreePsram()))},
{"fs_total", String(FSCom.totalBytes()).c_str()},
{"fs_used", String(FSCom.usedBytes()).c_str()},
{"fs_free", String(FSCom.totalBytes() - FSCom.usedBytes()).c_str()}};
res->println("\"memory\": {");
res->printf("\"heap_total\": %d,\n", ESP.getHeapSize());
res->printf("\"heap_free\": %d,\n", ESP.getFreeHeap());
res->printf("\"psram_total\": %d,\n", ESP.getPsramSize());
res->printf("\"psram_free\": %d,\n", ESP.getFreePsram());
res->println("\"fs_total\" : " + String(FSCom.totalBytes()) + ",");
res->println("\"fs_used\" : " + String(FSCom.usedBytes()) + ",");
res->println("\"fs_free\" : " + String(FSCom.totalBytes() - FSCom.usedBytes()));
res->println("},");
// data->power
Json jsonObjPower = Json::object{{"battery_percent", Json(powerStatus->getBatteryChargePercent())},
{"battery_voltage_mv", Json(powerStatus->getBatteryVoltageMv())},
{"has_battery", BoolToString(powerStatus->getHasBattery())},
{"has_usb", BoolToString(powerStatus->getHasUSB())},
{"is_charging", BoolToString(powerStatus->getIsCharging())}};
res->println("\"power\": {");
res->printf("\"battery_percent\": %u,\n", powerStatus->getBatteryChargePercent());
res->printf("\"battery_voltage_mv\": %u,\n", powerStatus->getBatteryVoltageMv());
res->printf("\"has_battery\": %s,\n", BoolToString(powerStatus->getHasBattery()));
res->printf("\"has_usb\": %s,\n", BoolToString(powerStatus->getHasUSB()));
res->printf("\"is_charging\": %s\n", BoolToString(powerStatus->getIsCharging()));
res->println("},");
// data->device
Json jsonObjDevice = Json::object{{"reboot_counter", Json(int(myNodeInfo.reboot_count))}};
res->println("\"device\": {");
res->printf("\"reboot_counter\": %d\n", myNodeInfo.reboot_count);
res->println("},");
// data->radio
Json jsonObjRadio = Json::object{{"frequency", Json(RadioLibInterface::instance->getFreq())},
{"lora_channel", Json(int(RadioLibInterface::instance->getChannelNum()))}};
res->println("\"radio\": {");
res->printf("\"frequecy\": %f,\n", RadioLibInterface::instance->getFreq());
res->printf("\"lora_channel\": %d\n", RadioLibInterface::instance->getChannelNum());
res->println("}");
// collect data to inner data object
Json jsonObjInner = Json::object{{"airtime", jsonObjAirtime}, {"wifi", jsonObjWifi}, {"memory", jsonObjMemory},
{"power", jsonObjPower}, {"device", jsonObjDevice}, {"radio", jsonObjRadio}};
res->println("},");
res->println("\"status\": \"ok\"");
res->println("}");
// create json output structure
Json jsonObjOuter = Json::object{{"data", jsonObjInner}, {"status", "ok"}};
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
}
/*
@@ -912,6 +899,8 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res)
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "POST");
@@ -938,28 +927,25 @@ void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
screen->blink();
}
res->println("{");
res->println("\"status\": \"ok\"");
res->println("}");
Json jsonObjOuter = Json::object{{"status", "ok"}};
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
}
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
{
using namespace json11;
res->setHeader("Content-Type", "application/json");
res->setHeader("Access-Control-Allow-Origin", "*");
res->setHeader("Access-Control-Allow-Methods", "GET");
// res->setHeader("Content-Type", "text/html");
int n = WiFi.scanNetworks();
res->println("{");
res->println("\"data\": {");
if (n == 0) {
// No networks found.
res->println("\"networks\": []");
} else {
res->println("\"networks\": [");
// build list of network objects
std::vector<Json> networkObjs;
if (n > 0) {
for (int i = 0; i < n; ++i) {
char ssidArray[50];
String ssidString = String(WiFi.SSID(i));
@@ -967,19 +953,20 @@ void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
ssidString.toCharArray(ssidArray, 50);
if (WiFi.encryptionType(i) != WIFI_AUTH_OPEN) {
res->printf("{\"ssid\": \"%s\",\"rssi\": %d}", ssidArray, WiFi.RSSI(i));
if (i != n - 1) {
res->printf(",");
}
Json thisNetwork = Json::object{{"ssid", ssidArray}, {"rssi", WiFi.RSSI(i)}};
networkObjs.push_back(thisNetwork);
}
// Yield some cpu cycles to IP stack.
// This is important in case the list is large and it takes us time to return
// to the main loop.
yield();
}
res->println("]");
}
res->println("},");
res->println("\"status\": \"ok\"");
res->println("}");
// build output structure
Json jsonObjOuter = Json::object{{"data", networkObjs}, {"status", "ok"}};
// serialize and write it to the stream
std::string jsonStr = jsonObjOuter.dump();
res->print(jsonStr.c_str());
}

View File

@@ -290,8 +290,8 @@ String MQTT::downstreamPacketToJson(MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &Telemetry_msg,
&scratch)) {
decoded = &scratch;
if (decoded->which_variant == Telemetry_environment_metrics_tag) {
decoded = &scratch;
msgPayload = Json::object{
{"temperature", decoded->variant.environment_metrics.temperature},
{"relative_humidity", decoded->variant.environment_metrics.relative_humidity},

View File

@@ -0,0 +1,9 @@
[env:pca10059_diy_eink]
extends = nrf52840_base
board = nordic_pca10059
build_flags = ${nrf52840_base.build_flags} -Ivariants/Dongle_nRF52840-pca10059-v1 -D NORDIC_PCA10059
src_filter = ${nrf52_base.src_filter} +<../variants/Dongle_nRF52840-pca10059-v1>
lib_deps =
${nrf52840_base.lib_deps}
https://github.com/ZinggJM/GxEPD2.git
debug_tool = jlink

View File

@@ -0,0 +1,43 @@
/*
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);
}

View File

@@ -0,0 +1,180 @@
/*
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_NORDIC_PCA10059_
#define _VARIANT_NORDIC_PCA10059_
#define PCA10059
/** 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 (0 + 12) // Blue LED P1.12
#define PIN_LED2 (0 + 6) // Built in Green P0.06
//Green Built in LED1
//#define PIN_LED1 (0 + 6) // LED1 P1.15
//RGB NeoPixel LED2
//#define PIN_LED1 (0 + 8) Red
//#define PIN_LED1 (32 + 9) Green
//#define PIN_LED1 (0 + 12) Blue
#define LED_BUILTIN PIN_LED1
#define LED_CONN PIN_LED2
#define LED_GREEN PIN_LED1
#define LED_BLUE PIN_LED2
#define LED_STATE_ON 0 // State when LED is litted
/*
* Buttons
*/
#define PIN_BUTTON1 (32 + 6) // BTN_DN P1.06 Built in button
/*
* Analog pins
*/
#define PIN_A0 (-1)
static const uint8_t A0 = PIN_A0;
#define ADC_RESOLUTION 14
// Other pins
#define PIN_AREF (-1) // AREF Not yet used
static const uint8_t AREF = PIN_AREF;
/*
* Serial interfaces
*/
#define PIN_SERIAL1_RX (-1)
#define PIN_SERIAL1_TX (-1)
// Connected to Jlink CDC
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
/*
* SPI Interfaces
*/
#define SPI_INTERFACES_COUNT 2
#define PIN_SPI_MISO (0 + 17) // MISO P0.17
#define PIN_SPI_MOSI (0 + 15) // MOSI P0.15
#define PIN_SPI_SCK (0 + 13) // SCK P0.13
#define PIN_SPI1_MISO (-1) //
#define PIN_SPI1_MOSI (10) // EPD_MOSI P0.10
#define PIN_SPI1_SCK (9) // EPD_SCLK P0.09
static const uint8_t SS = (0 + 31); // LORA_CS P0.31
static const uint8_t MOSI = PIN_SPI_MOSI;
static const uint8_t MISO = PIN_SPI_MISO;
static const uint8_t SCK = PIN_SPI_SCK;
/*
* eink display pins
*/
//#define PIN_EINK_EN (-1)
#define PIN_EINK_EN (0 + 6) // Turn on the Green built in LED
#define PIN_EINK_CS (32) // EPD_CS
#define PIN_EINK_BUSY (20) // EPD_BUSY
#define PIN_EINK_DC (24) // EPD_D/C
#define PIN_EINK_RES (-1) // Not Connected P0.22 available
#define PIN_EINK_SCLK (9) // EPD_SCLK
#define PIN_EINK_MOSI (10) // EPD_MOSI
#define HAS_EINK
/*
* Wire Interfaces
*/
#define WIRE_INTERFACES_COUNT 1
#define PIN_WIRE_SDA (32 + 4) // SDA
#define PIN_WIRE_SCL (32 + 7) // SCL
// NiceRF 868 LoRa module
#define USE_SX1262
#define SX126X_CS (0 + 31) // LORA_CS P0.31
#define SX126X_DIO1 (0 + 29) // DIO1 P0.29
#define SX126X_BUSY (0 + 2) // LORA_BUSY P0.02
#define SX126X_RESET (32 + 15) // LORA_RESET P1.15
#define SX126X_TXEN (-1) // TXEN P1.13 NiceRF 868 dont use
#define SX126X_RXEN (-1) // RXEN P1.10 NiceRF 868 dont use
#define SX126X_E22
#define PIN_GPS_EN (-1)
#define PIN_GPS_PPS (-1) // Pulse per second input from the GPS
#define GPS_RX_PIN PIN_SERIAL1_RX
#define GPS_TX_PIN 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
// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
#define VBAT_MV_PER_LSB (0.73242188F)
// Voltage divider value => 1.5M + 1M voltage divider on VBAT = (1.5M / (1M + 1.5M))
#define VBAT_DIVIDER (0.4F)
// Compensation factor for the VBAT divider
#define VBAT_DIVIDER_COMP (1.73)
// Fixed calculation of milliVolt from compensation value
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
#undef AREF_VOLTAGE
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER VBAT_DIVIDER_COMP //REAL_VBAT_MV_PER_LSB
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
#ifdef __cplusplus
}
#endif
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/
#endif

View File

@@ -0,0 +1,8 @@
; The 1.0 release of the nano-g1 board
[env:nano-g1]
extends = esp32_base
board = ttgo-t-beam
lib_deps =
${esp32_base.lib_deps}
build_flags =
${esp32_base.build_flags} -D NANO_G1 -I variants/nano-g1

View File

@@ -0,0 +1,30 @@
// #define BUTTON_NEED_PULLUP // if set we need to turn on the internal CPU pullup during sleep
#define I2C_SDA 21
#define I2C_SCL 22
#define BUTTON_PIN 36 // The middle button GPIO on the Nano G1
//#define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed. Does anyone use this? It is not documented anywhere.
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
// common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
// not found then probe for SX1262
#define USE_RF95
#define USE_SX1262
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 23
#define LORA_DIO1 33 // SX1262 IRQ
#define LORA_DIO2 32 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB
#ifdef USE_SX1262
#define SX126X_CS RF95_NSS // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_E22 // Not really an E22
// Internally the module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface
// code)
#endif

View File

@@ -22,7 +22,5 @@
#define USE_RF95
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 14
#define LORA_DIO1 35 // Not really used
#define LORA_DIO2 34 // Not really used
#define LORA_RESET 23

View File

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