mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-15 22:37:35 +00:00
Compare commits
41 Commits
v1.2.43.a4
...
v1.2.45.b6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6740548f3 | ||
|
|
5fe3ec09de | ||
|
|
079843d777 | ||
|
|
bd7171a7a2 | ||
|
|
eaa15076cd | ||
|
|
2fd74d8f47 | ||
|
|
0e91d39b27 | ||
|
|
52d7a6b8e4 | ||
|
|
472e880280 | ||
|
|
189889489b | ||
|
|
0d758347af | ||
|
|
3266d57cfb | ||
|
|
f2c9c5553c | ||
|
|
bcdc42816b | ||
|
|
b04e313665 | ||
|
|
700e799125 | ||
|
|
a9f8080ee7 | ||
|
|
9f450cb1c5 | ||
|
|
388f19da79 | ||
|
|
4f11598112 | ||
|
|
bcb54b643f | ||
|
|
04d3f44179 | ||
|
|
5110a6de82 | ||
|
|
04c5ac0d7c | ||
|
|
6d2cd73599 | ||
|
|
057b04a88a | ||
|
|
28af18389b | ||
|
|
2af4c619e1 | ||
|
|
99d529be51 | ||
|
|
39df7108a8 | ||
|
|
72807f0fa0 | ||
|
|
2fe11d4fe8 | ||
|
|
596befff74 | ||
|
|
b2524ceaff | ||
|
|
5f323e8bd1 | ||
|
|
d40b66beac | ||
|
|
afa12d6e87 | ||
|
|
676a6f3bea | ||
|
|
bf0b598908 | ||
|
|
8a79663fa0 | ||
|
|
564262e75b |
@@ -72,6 +72,9 @@ platformio lib update
|
||||
do_boards "$BOARDS_ESP32" "false"
|
||||
do_boards "$BOARDS_NRF52" "true"
|
||||
|
||||
pio run --environment native
|
||||
cp .pio/build/native/program $OUTDIR/bins/universal/meshtasticd_linux_amd64
|
||||
|
||||
echo "Building SPIFFS for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/spiffs-$VERSION.bin
|
||||
@@ -99,7 +102,7 @@ XML
|
||||
|
||||
echo Generating $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* images/system-info.bin bin/device-install.* bin/device-update.*
|
||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* $OUTDIR/bins/universal/meshtasticd* images/system-info.bin bin/device-install.* bin/device-update.*
|
||||
echo Generating $ARCHIVEDIR/elfs-$VERSION.zip
|
||||
rm -f $ARCHIVEDIR/elfs-$VERSION.zip
|
||||
zip --junk-paths $ARCHIVEDIR/elfs-$VERSION.zip $OUTDIR/elfs/universal/firmware-*-$VERSION.*
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
|
||||
You probably don't care about this section - skip to the next one.
|
||||
|
||||
* list portduino on platformio
|
||||
* router mode dropping messages? https://meshtastic.discourse.group/t/router-mode-missing-messages/3329/3
|
||||
* fix ttgo eink screen
|
||||
* figure our wss for mqtt.meshtastic - use cloudflare? 2052 ws, 2053 crypt
|
||||
* usb lora dongle from pine64, add end user instructions
|
||||
* measure rak4630 power draw and turn off power for GPS most of the time. We should be able to run on the small solar panel.
|
||||
* pine64 lora module
|
||||
* @havealoha fixedposition not working
|
||||
* turn on watchdog reset if app hangs on nrf52 or esp32
|
||||
* pine64 solar boards
|
||||
* for the matrix gateway? recommended by @sam-uk https://github.com/matrix-org/coap-proxy
|
||||
* figure our wss for mqtt.meshtastic - use cloudflare? 2052 ws, 2053 crypt
|
||||
* ask for vercel access
|
||||
* finish plan for riot.im
|
||||
* turn on setTx(timeout) and state = setDioIrqParams(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT, SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT); in sx1262 code
|
||||
* add rak4600 support (with rf95 radio and limited ram)
|
||||
* NO add rak4600 support (with rf95 radio and limited ram)
|
||||
* store esp32 crashes to flash (and 64KB coredump partition) - https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/core_dump.html
|
||||
*
|
||||
* Switch to use https://github.com/adafruit/Adafruit_nRF52_Arduino.git when available (see arduino code for examples)
|
||||
* If more nodes appear than the nodedb can hold, delete oldest entries from DB
|
||||
* send debug info 'in-band'
|
||||
* DONE @luxonn reports that after a while the android app stops showing new messages
|
||||
* DONE release android APK - fix recent 1.2.28 crash report
|
||||
* DONE remote admin busted?
|
||||
@@ -28,7 +27,6 @@ You probably don't care about this section - skip to the next one.
|
||||
* DONE tcp stream problem in python+pordtuino, server thinks client dropped when client DID NOT DROP
|
||||
* DONE TCP mode for android, localhost is at 10.0.2.2
|
||||
* DONE make sure USB still works in android
|
||||
* add portduino builds to zip
|
||||
* add license to portduino and make announcement
|
||||
* DONE naks are being dropped (though enqueuedLocal) sometimes before phone/PC gets them
|
||||
* DONE have android fill in if local GPS has poor signal
|
||||
|
||||
23
geeksville-private/bl602.md
Normal file
23
geeksville-private/bl602.md
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
* nutcracker https://www.pine64.org/2020/10/28/nutcracker-challenge-blob-free-wifi-ble/
|
||||
* https://github.com/pine64/bl_iot_sdk
|
||||
* https://github.com/pine64/bl602-docs / https://pine64.github.io/bl602-docs/
|
||||
* https://github.com/pine64/ArduinoCore-bouffalo
|
||||
|
||||
|
||||
cd ~/packages
|
||||
git clone --recursive https://github.com/pine64/bl_iot_sdk
|
||||
|
||||
https://github.com/spacemeowx2/blflash/releases
|
||||
|
||||
|
||||
# FIXME or BL604
|
||||
cd bl_iot_sdk
|
||||
export BL60X_SDK_PATH=/home/kevinh/packages/bl_iot_sdk
|
||||
export CONFIG_CHIP_NAME=BL602
|
||||
cd customer_app/bl602_boot2
|
||||
make
|
||||
|
||||
* todo run hello world on hardware (check for bl604 vs bl602 first)
|
||||
* build/run in the crummy arduino environment
|
||||
* build in platformio
|
||||
@@ -9,14 +9,14 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
default_envs = tbeam
|
||||
;default_envs = tbeam
|
||||
;default_envs = tbeam0.7
|
||||
;default_envs = heltec-v2.0
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = lora-relay-v1 # nrf board
|
||||
;default_envs = t-echo
|
||||
default_envs = t-echo
|
||||
;default_envs = nrf52840dk-geeksville
|
||||
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||
;default_envs = rak4631
|
||||
@@ -70,7 +70,7 @@ lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#35d796226b853b0c0ff818b2f1aa3d35e7296a96 ; ESP8266_SSD1306
|
||||
https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
|
||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||
https://github.com/meshtastic/arduino-fsm.git#829e967b8a95c094f73c60ef8dacfe66eae38940
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||
https://github.com/meshtastic/RadioLib.git#80ed10d689a0568782c5bd152906b0f97d2bce93
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79
|
||||
@@ -218,7 +218,7 @@ src_filter =
|
||||
${arduino_base.src_filter} -<esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<plugins/esp32> -<mqtt/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
monitor_port = /dev/ttyACM1
|
||||
; monitor_port = /dev/ttyACM1
|
||||
|
||||
# we pass in options to jlink so it can understand freertos (note: we don't use "jlink" as the tool)
|
||||
;debug_tool = jlink
|
||||
@@ -255,9 +255,12 @@ debug_init_break =
|
||||
[nrf52840_base]
|
||||
; Common base class for all nrf52840 based targets
|
||||
extends = nrf52_base
|
||||
; was -DTINY_USB
|
||||
build_flags = ${nrf52_base.build_flags}
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
Adafruit nRFCrypto
|
||||
# Adafruit TinyUSB Arduino
|
||||
# add Adafruit nRFCrypto platform IO automated scan is broken
|
||||
|
||||
[env:lora_isp4520]
|
||||
@@ -315,7 +318,7 @@ extends = nrf52840_base
|
||||
board = wiscore_rak4631
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/WisCore_RAK4631_Board
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/WisCore_RAK4631_Board
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/WisCore_RAK4631_Board>
|
||||
debug_tool = jlink
|
||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||
@@ -354,10 +357,13 @@ lib_deps =
|
||||
[env:t-echo]
|
||||
extends = nrf52840_base
|
||||
board = t-echo
|
||||
debug_tool = jlink
|
||||
upload_protocol = jlink
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library - NOTE: WE NOT LONGER USE TFT_eSPI, it was for an earlier version of the TTGO eink screens
|
||||
# -DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/t-echo
|
||||
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/t-echo
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/t-echo>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
@@ -385,7 +391,7 @@ extends = nrf52840_base
|
||||
board = lora-relay-v1
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v1
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/lora_relay_v1
|
||||
-DUSER_SETUP_LOADED
|
||||
-DTFT_WIDTH=80
|
||||
-DTFT_HEIGHT=160
|
||||
@@ -407,7 +413,7 @@ extends = nrf52840_base
|
||||
board = lora-relay-v2
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v2
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/lora_relay_v2
|
||||
-DUSER_SETUP_LOADED
|
||||
-DTFT_WIDTH=80
|
||||
-DTFT_HEIGHT=160
|
||||
|
||||
@@ -82,10 +82,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
if (v < noBatVolt)
|
||||
return -1; // If voltage is super low assume no battery installed
|
||||
|
||||
#ifndef NRF52_SERIES
|
||||
// This does not work on a RAK4631 with battery connected
|
||||
if (v > chargingVolt)
|
||||
return 0; // While charging we can't report % full on the battery
|
||||
#endif
|
||||
|
||||
return 100 * (v - emptyVolt) / (fullVolt - emptyVolt);
|
||||
return clamp((int)(100 * (v - emptyVolt) / (fullVolt - emptyVolt)), 0, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ static bool isPowered()
|
||||
|
||||
static void sdsEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SDS\n");
|
||||
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
|
||||
doDeepSleep(getPref_sds_secs() * 1000LL);
|
||||
}
|
||||
@@ -41,7 +42,7 @@ static void lsEnter()
|
||||
screen->setOn(false);
|
||||
secsSlept = 0; // How long have we been sleeping this time
|
||||
|
||||
DEBUG_MSG("lsEnter end\n");
|
||||
// DEBUG_MSG("lsEnter end\n");
|
||||
}
|
||||
|
||||
static void lsIdle()
|
||||
@@ -112,6 +113,7 @@ static void lsIdle()
|
||||
|
||||
static void lsExit()
|
||||
{
|
||||
DEBUG_MSG("Exit state: LS\n");
|
||||
// setGPSPower(true); // restore GPS power
|
||||
if (gps)
|
||||
gps->forceWake(true);
|
||||
@@ -119,6 +121,7 @@ static void lsExit()
|
||||
|
||||
static void nbEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: NB\n");
|
||||
screen->setOn(false);
|
||||
setBluetoothEnable(false);
|
||||
|
||||
@@ -133,6 +136,7 @@ static void darkEnter()
|
||||
|
||||
static void serialEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SERIAL\n");
|
||||
setBluetoothEnable(false);
|
||||
screen->setOn(true);
|
||||
screen->print("Serial connected\n");
|
||||
@@ -145,6 +149,7 @@ static void serialExit()
|
||||
|
||||
static void powerEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: POWER\n");
|
||||
if (!isPowered()) {
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
||||
DEBUG_MSG("Loss of power in Powered\n");
|
||||
@@ -174,6 +179,7 @@ static void powerExit()
|
||||
|
||||
static void onEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: ON\n");
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
|
||||
@@ -202,7 +208,9 @@ static void screenPress()
|
||||
screen->onPress();
|
||||
}
|
||||
|
||||
static void bootEnter() {}
|
||||
static void bootEnter() {
|
||||
DEBUG_MSG("Enter state: BOOT\n");
|
||||
}
|
||||
|
||||
State stateSDS(sdsEnter, NULL, NULL, "SDS");
|
||||
State stateLS(lsEnter, lsIdle, lsExit, "LS");
|
||||
@@ -226,10 +234,9 @@ void PowerFSM_setup()
|
||||
// if we are a router node, we go to NB (no need for bluetooth) otherwise we go to DARK (so we can send message to phone)
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_WAKE_TIMER, NULL, "Wake timer");
|
||||
|
||||
// Note we don't really use this transition, because when we wake from light sleep we _always_ transition to NB or dark and
|
||||
// then it handles things powerFSM.add_transition(&stateLS, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet");
|
||||
|
||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_RECEIVED_PACKET, NULL, "Received packet, resetting win wake");
|
||||
// We need this transition, because we might not transition if we were waiting to enter light-sleep, because when we wake from light sleep we _always_ transition to NB or dark and
|
||||
powerFSM.add_transition(&stateLS, isRouter ? &stateNB : &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, exiting light sleep");
|
||||
powerFSM.add_transition(&stateNB, &stateNB, EVENT_PACKET_FOR_PHONE, NULL, "Received packet, resetting win wake");
|
||||
|
||||
// Handle press events - note: we ignore button presses when in API mode
|
||||
powerFSM.add_transition(&stateLS, &stateON, EVENT_PRESS, NULL, "Press");
|
||||
@@ -253,6 +260,9 @@ void PowerFSM_setup()
|
||||
|
||||
// if we are a router we don't turn the screen on for these things
|
||||
if (!isRouter) {
|
||||
// if any packet destined for phone arrives, turn on bluetooth at least
|
||||
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
||||
|
||||
// show the latest node when we get a new node db update
|
||||
powerFSM.add_transition(&stateNB, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update");
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_NODEDB_UPDATED, NULL, "NodeDB update");
|
||||
@@ -292,13 +302,13 @@ void PowerFSM_setup()
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
|
||||
powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
|
||||
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK, getPref_screen_on_secs() * 1000, NULL, "Screen-on timeout");
|
||||
|
||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||
State *lowPowerState = &stateLS;
|
||||
|
||||
uint32_t meshSds = 0;
|
||||
|
||||
#ifndef NRF52_SERIES
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
|
||||
@@ -307,11 +317,12 @@ void PowerFSM_setup()
|
||||
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS, getPref_min_wake_secs() * 1000, NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS, getPref_wait_bluetooth_secs() * 1000, NULL, "Bluetooth timeout");
|
||||
meshSds = getPref_mesh_sds_timeout_secs();
|
||||
#else
|
||||
lowPowerState = &stateDARK;
|
||||
meshSds = UINT32_MAX; //Workaround for now: Don't go into deep sleep on the RAK4631
|
||||
#endif
|
||||
|
||||
auto meshSds = getPref_mesh_sds_timeout_secs();
|
||||
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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#define EVENT_PRESS 1
|
||||
#define EVENT_WAKE_TIMER 2
|
||||
#define EVENT_RECEIVED_PACKET 3
|
||||
// #define EVENT_RECEIVED_PACKET 3
|
||||
#define EVENT_PACKET_FOR_PHONE 4
|
||||
#define EVENT_RECEIVED_TEXT_MSG 5
|
||||
// #define EVENT_BOOT 6 // now done with a timed transition
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "RedirectablePrint.h"
|
||||
#include "RTC.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
// #include "wifi/WiFiServerAPI.h"
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -25,6 +26,10 @@ size_t RedirectablePrint::write(uint8_t c)
|
||||
SEGGER_RTT_PutChar(SEGGER_STDOUT_CH, c);
|
||||
#endif
|
||||
|
||||
// FIXME - clean this up, the whole relationship of this class to SerialConsole to TCP/bluetooth debug log output is kinda messed up. But for now, just have this hack to
|
||||
// optionally send chars to TCP also
|
||||
//WiFiServerPort::debugOut(c);
|
||||
|
||||
dest->write(c);
|
||||
return 1; // We always claim one was written, rather than trusting what the
|
||||
// serial port said (which could be zero)
|
||||
|
||||
@@ -72,14 +72,21 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
|
||||
return didIt;
|
||||
}
|
||||
|
||||
int32_t NotifiedWorkerThread::runOnce()
|
||||
void NotifiedWorkerThread::checkNotification()
|
||||
{
|
||||
auto n = notification;
|
||||
enabled = false; // Only run once per notification
|
||||
notification = 0; // clear notification
|
||||
if (n) {
|
||||
onNotify(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32_t NotifiedWorkerThread::runOnce()
|
||||
{
|
||||
enabled = false; // Only run once per notification
|
||||
checkNotification();
|
||||
|
||||
return RUN_SAME;
|
||||
}
|
||||
|
||||
@@ -38,8 +38,14 @@ class NotifiedWorkerThread : public OSThread
|
||||
protected:
|
||||
virtual void onNotify(uint32_t notification) = 0;
|
||||
|
||||
/// just calls checkNotification()
|
||||
virtual int32_t runOnce();
|
||||
|
||||
/// Sometimes we might want to check notifications independently of when our thread was getting woken up (i.e. if we are about to change
|
||||
/// radio transmit/receive modes we want to handle any pending interrupts first). You can call this method and if any notifications are currently
|
||||
/// pending they will be handled immediately.
|
||||
void checkNotification();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Notify this thread so it can run
|
||||
|
||||
@@ -946,7 +946,9 @@ void Screen::setFrames()
|
||||
normalFrames[numframes++] = drawTextMessageFrame;
|
||||
|
||||
// then all the nodes
|
||||
for (size_t i = 0; i < numnodes; i++)
|
||||
// We only show a few nodes in our scrolling list - because meshes with many nodes would have too many screens
|
||||
size_t numToShow = min(numnodes, 4U);
|
||||
for (size_t i = 0; i < numToShow; i++)
|
||||
normalFrames[numframes++] = drawNodeInfo;
|
||||
|
||||
// then the debug info
|
||||
|
||||
@@ -22,6 +22,8 @@ class Screen
|
||||
|
||||
#include <OLEDDisplayUi.h>
|
||||
|
||||
#include "../configuration.h"
|
||||
|
||||
#ifdef USE_SH1106
|
||||
#include <SH1106Wire.h>
|
||||
#elif defined(USE_ST7567)
|
||||
|
||||
20
src/main.cpp
20
src/main.cpp
@@ -25,9 +25,10 @@
|
||||
#include <Wire.h>
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "nimble/BluetoothUtil.h"
|
||||
#endif
|
||||
|
||||
@@ -337,9 +338,10 @@ void setup()
|
||||
digitalWrite(RESET_OLED, 1);
|
||||
#endif
|
||||
|
||||
bool forceSoftAP = 0;
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
#ifndef NO_ESP32
|
||||
bool forceSoftAP = 0;
|
||||
|
||||
// If the button is connected to GPIO 12, don't enable the ability to use
|
||||
// meshtasticAdmin on the device.
|
||||
@@ -536,10 +538,14 @@ void setup()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_ESP32
|
||||
#if defined(PORTDUINO) || defined(HAS_WIFI)
|
||||
mqttInit();
|
||||
#endif
|
||||
|
||||
// Initialize Wifi
|
||||
initWifi(forceSoftAP);
|
||||
|
||||
#ifndef NO_ESP32
|
||||
// Start web server thread.
|
||||
webServerThread = new WebServerThread();
|
||||
#endif
|
||||
@@ -548,10 +554,6 @@ void setup()
|
||||
initApiServer();
|
||||
#endif
|
||||
|
||||
#if defined(PORTDUINO) || defined(HAS_WIFI)
|
||||
mqttInit();
|
||||
#endif
|
||||
|
||||
// Start airtime logger thread.
|
||||
airTime = new AirTime();
|
||||
|
||||
@@ -646,7 +648,9 @@ void loop()
|
||||
mainController.nextThread->tillRun(millis())); */
|
||||
|
||||
// We want to sleep as long as possible here - because it saves power
|
||||
if (!runASAP && loopCanSleep())
|
||||
if (!runASAP && loopCanSleep()) {
|
||||
// if(delayMsec > 100) DEBUG_MSG("sleeping %ld\n", delayMsec);
|
||||
mainDelay.delay(delayMsec);
|
||||
}
|
||||
// if (didWake) DEBUG_MSG("wake!\n");
|
||||
}
|
||||
|
||||
@@ -32,6 +32,10 @@ void CryptoEngine::decrypt(uint32_t fromNode, uint64_t packetNum, size_t numByte
|
||||
void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetNum)
|
||||
{
|
||||
memset(nonce, 0, sizeof(nonce));
|
||||
*((uint64_t *)&nonce[0]) = packetNum;
|
||||
*((uint32_t *)&nonce[8]) = fromNode;
|
||||
|
||||
// use memcpy to avoid breaking strict-aliasing
|
||||
memcpy(nonce, &packetNum, sizeof(uint64_t));
|
||||
memcpy(nonce + sizeof(uint64_t), &fromNode, sizeof(uint32_t));
|
||||
//*((uint64_t *)&nonce[0]) = packetNum;
|
||||
//*((uint32_t *)&nonce[8]) = fromNode;
|
||||
}
|
||||
@@ -4,14 +4,14 @@
|
||||
#include <algorithm>
|
||||
|
||||
/// @return the priority of the specified packet
|
||||
inline uint32_t getPriority(MeshPacket *p)
|
||||
inline uint32_t getPriority(const MeshPacket *p)
|
||||
{
|
||||
auto pri = p->priority;
|
||||
return pri;
|
||||
}
|
||||
|
||||
/// @return "true" if "p1" is ordered before "p2"
|
||||
bool CompareMeshPacket::operator()(MeshPacket *p1, MeshPacket *p2)
|
||||
bool CompareMeshPacketFunc(const MeshPacket *p1, const MeshPacket *p2)
|
||||
{
|
||||
assert(p1 && p2);
|
||||
auto p1p = getPriority(p1), p2p = getPriority(p2);
|
||||
@@ -25,7 +25,12 @@ bool CompareMeshPacket::operator()(MeshPacket *p1, MeshPacket *p2)
|
||||
|
||||
MeshPacketQueue::MeshPacketQueue(size_t _maxLen) : maxLen(_maxLen) {}
|
||||
|
||||
/** Some clients might not properly set priority, therefore we fix it here.
|
||||
bool MeshPacketQueue::empty() {
|
||||
return queue.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Some clients might not properly set priority, therefore we fix it here.
|
||||
*/
|
||||
void fixPriority(MeshPacket *p)
|
||||
{
|
||||
@@ -34,7 +39,7 @@ void fixPriority(MeshPacket *p)
|
||||
if (p->priority == MeshPacket_Priority_UNSET) {
|
||||
// if acks give high priority
|
||||
// if a reliable message give a bit higher default priority
|
||||
p->priority = (p->decoded.portnum == PortNum_ROUTING_APP) ? MeshPacket_Priority_ACK :
|
||||
p->priority = (p->decoded.portnum == PortNum_ROUTING_APP) ? MeshPacket_Priority_ACK :
|
||||
(p->want_ack ? MeshPacket_Priority_RELIABLE : MeshPacket_Priority_DEFAULT);
|
||||
}
|
||||
}
|
||||
@@ -42,51 +47,70 @@ void fixPriority(MeshPacket *p)
|
||||
/** enqueue a packet, return false if full */
|
||||
bool MeshPacketQueue::enqueue(MeshPacket *p)
|
||||
{
|
||||
|
||||
fixPriority(p);
|
||||
|
||||
// fixme if there is something lower priority in the queue that can be deleted to make space, delete that instead
|
||||
if (size() >= maxLen)
|
||||
return false;
|
||||
else {
|
||||
push(p);
|
||||
return true;
|
||||
// no space - try to replace a lower priority packet in the queue
|
||||
if (queue.size() >= maxLen) {
|
||||
return replaceLowerPriorityPacket(p);
|
||||
}
|
||||
|
||||
queue.push_back(p);
|
||||
std::push_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
|
||||
return true;
|
||||
}
|
||||
|
||||
MeshPacket *MeshPacketQueue::dequeue()
|
||||
{
|
||||
if (empty())
|
||||
if (empty()) {
|
||||
return NULL;
|
||||
else {
|
||||
auto p = top();
|
||||
pop(); // remove the first item
|
||||
return p;
|
||||
}
|
||||
|
||||
auto *p = queue.front();
|
||||
std::pop_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
|
||||
queue.pop_back();
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// this is kinda yucky, but I'm not sure if all arduino c++ compilers support closuers. And we only have one
|
||||
// thread that can run at a time - so safe
|
||||
static NodeNum findFrom;
|
||||
static PacketId findId;
|
||||
|
||||
static bool isMyPacket(MeshPacket *p)
|
||||
{
|
||||
return p->id == findId && getFrom(p) == findFrom;
|
||||
}
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns true the packet which was removed from the queue */
|
||||
/** Attempt to find and remove a packet from this queue. Returns a pointer to the removed packet, or NULL if not found */
|
||||
MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id)
|
||||
{
|
||||
findFrom = from;
|
||||
findId = id;
|
||||
auto it = std::find_if(this->c.begin(), this->c.end(), isMyPacket);
|
||||
if (it != this->c.end()) {
|
||||
auto p = *it;
|
||||
this->c.erase(it);
|
||||
std::make_heap(this->c.begin(), this->c.end(), this->comp);
|
||||
return p;
|
||||
} else {
|
||||
return NULL;
|
||||
for (auto it = queue.begin(); it != queue.end(); it++) {
|
||||
auto p = (*it);
|
||||
if (getFrom(p) == from && p->id == id) {
|
||||
queue.erase(it);
|
||||
std::make_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
||||
bool MeshPacketQueue::replaceLowerPriorityPacket(MeshPacket *p) {
|
||||
std::sort_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc); // sort ascending based on priority (0 -> 127)
|
||||
|
||||
// find first packet which does not compare less (in priority) than parameter packet
|
||||
auto low = std::lower_bound(queue.begin(), queue.end(), p, &CompareMeshPacketFunc);
|
||||
|
||||
if (low == queue.begin()) { // if already at start, there are no packets with lower priority
|
||||
return false;
|
||||
}
|
||||
|
||||
if (low == queue.end()) {
|
||||
// all priorities in the vector are smaller than the incoming packet. Replace the lowest priority (first) element
|
||||
low = queue.begin();
|
||||
} else {
|
||||
// 'low' iterator points to first packet which does not compare less than parameter
|
||||
--low; // iterate to lower priority packet
|
||||
}
|
||||
|
||||
if (getPriority(p) > getPriority(*low)) {
|
||||
packetPool.release(*low); // deallocate and drop the packet we're replacing
|
||||
*low = p; // replace low-pri packet at this position with incoming packet with higher priority
|
||||
}
|
||||
|
||||
std::make_heap(queue.begin(), queue.end(), &CompareMeshPacketFunc);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,29 +5,29 @@
|
||||
#include <assert.h>
|
||||
#include <queue>
|
||||
|
||||
// this is an strucure which implements the
|
||||
// operator overloading
|
||||
struct CompareMeshPacket {
|
||||
bool operator()(MeshPacket *p1, MeshPacket *p2);
|
||||
};
|
||||
|
||||
/**
|
||||
* A priority queue of packets.
|
||||
*
|
||||
* A priority queue of packets
|
||||
*/
|
||||
class MeshPacketQueue : public std::priority_queue<MeshPacket *, std::vector<MeshPacket *>, CompareMeshPacket>
|
||||
class MeshPacketQueue
|
||||
{
|
||||
size_t maxLen;
|
||||
std::vector<MeshPacket *> queue;
|
||||
|
||||
/** Replace a lower priority package in the queue with 'mp' (provided there are lower pri packages). Return true if replaced. */
|
||||
bool replaceLowerPriorityPacket(MeshPacket *mp);
|
||||
|
||||
public:
|
||||
MeshPacketQueue(size_t _maxLen);
|
||||
|
||||
/** enqueue a packet, return false if full */
|
||||
bool enqueue(MeshPacket *p);
|
||||
|
||||
// bool isEmpty();
|
||||
/** return true if the queue is empty */
|
||||
bool empty();
|
||||
|
||||
MeshPacket *dequeue();
|
||||
|
||||
/** Attempt to find and remove a packet from this queue. Returns true the packet which was removed from the queue */
|
||||
/** Attempt to find and remove a packet from this queue. Returns the packet which was removed from the queue */
|
||||
MeshPacket *remove(NodeNum from, PacketId id);
|
||||
};
|
||||
@@ -66,7 +66,7 @@ void MeshService::init()
|
||||
|
||||
int MeshService::handleFromRadio(const MeshPacket *mp)
|
||||
{
|
||||
powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping
|
||||
powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping
|
||||
|
||||
printPacket("Forwarding to phone", mp);
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
|
||||
@@ -81,6 +81,9 @@ class PhoneAPI
|
||||
|
||||
bool isConnected() { return state != STATE_SEND_NOTHING; }
|
||||
|
||||
/// emit a debugging log character, FIXME - implement
|
||||
void debugOut(char c) { }
|
||||
|
||||
protected:
|
||||
/// Our fromradio packet while it is being assembled
|
||||
FromRadio fromRadioScratch;
|
||||
|
||||
@@ -28,7 +28,7 @@ template <class T> class ProtobufPlugin : protected SinglePortPlugin
|
||||
* In general decoded will always be !NULL. But in some special applications (where you have handling packets
|
||||
* for multiple port numbers, decoding will ONLY be attempted for packets where the portnum matches our expected ourPortNum.
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const T *decoded) = 0;
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, T *decoded) = 0;
|
||||
|
||||
/**
|
||||
* Return a mesh packet which has been preinited with a particular protobuf data payload and port number.
|
||||
|
||||
@@ -146,6 +146,8 @@ void INTERRUPT_ATTR SX1262Interface::disableInterrupt()
|
||||
|
||||
void SX1262Interface::setStandby()
|
||||
{
|
||||
checkNotification(); // handle any pending interrupts before we force standby
|
||||
|
||||
int err = lora.standby();
|
||||
assert(err == ERR_NONE);
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ int32_t StreamAPI::readStream()
|
||||
return recentRx ? 5 : 250;
|
||||
} else {
|
||||
while (stream->available()) { // Currently we never want to block
|
||||
uint8_t c = stream->read();
|
||||
int cInt = stream->read();
|
||||
if(cInt < 0)
|
||||
break; // We ran out of characters (even though available said otherwise) - this can happen on rf52 adafruit arduino
|
||||
|
||||
uint8_t c = (uint8_t) cInt;
|
||||
|
||||
// Use the read pointer for a little state machine, first look for framing, then length bytes, then payload
|
||||
size_t ptr = rxPtr;
|
||||
|
||||
@@ -68,7 +68,7 @@ class StreamAPI : public PhoneAPI, protected concurrency::OSThread
|
||||
void emitRebooted();
|
||||
|
||||
virtual void onConnectionChanged(bool connected);
|
||||
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
virtual bool checkIsConnected() = 0;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <HTTPMultipartBodyParser.hpp>
|
||||
#include <HTTPURLEncodedBodyParser.hpp>
|
||||
|
||||
|
||||
#include <WebServer.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
@@ -13,7 +12,6 @@
|
||||
#include "esp_task_wdt.h"
|
||||
#endif
|
||||
|
||||
|
||||
// Persistant Data Storage
|
||||
#include <Preferences.h>
|
||||
Preferences prefs;
|
||||
@@ -42,46 +40,41 @@ Preferences prefs;
|
||||
using namespace httpsserver;
|
||||
#include "mesh/http/ContentHandler.h"
|
||||
|
||||
SSLCert *cert;
|
||||
HTTPSServer *secureServer;
|
||||
HTTPServer *insecureServer;
|
||||
static SSLCert *cert;
|
||||
static HTTPSServer *secureServer;
|
||||
static HTTPServer *insecureServer;
|
||||
|
||||
volatile bool isWebServerReady;
|
||||
volatile bool isCertReady;
|
||||
|
||||
|
||||
|
||||
bool isWebServerReady = 0;
|
||||
bool isCertReady = 0;
|
||||
|
||||
|
||||
void handleWebResponse()
|
||||
static void handleWebResponse()
|
||||
{
|
||||
if (isWifiAvailable() == 0) {
|
||||
return;
|
||||
}
|
||||
if (isWifiAvailable()) {
|
||||
|
||||
if (isWebServerReady) {
|
||||
// We're going to handle the DNS responder here so it
|
||||
// will be ignored by the NRF boards.
|
||||
handleDNSResponse();
|
||||
if (isWebServerReady) {
|
||||
// We're going to handle the DNS responder here so it
|
||||
// will be ignored by the NRF boards.
|
||||
handleDNSResponse();
|
||||
|
||||
secureServer->loop();
|
||||
insecureServer->loop();
|
||||
}
|
||||
if(secureServer)
|
||||
secureServer->loop();
|
||||
insecureServer->loop();
|
||||
}
|
||||
|
||||
/*
|
||||
Slow down the CPU if we have not received a request within the last few
|
||||
seconds.
|
||||
*/
|
||||
|
||||
if (millis() - getTimeSpeedUp() >= (25 * 1000)) {
|
||||
setCpuFrequencyMhz(80);
|
||||
setTimeSpeedUp();
|
||||
/*
|
||||
Slow down the CPU if we have not received a request within the last few
|
||||
seconds.
|
||||
*/
|
||||
|
||||
if (millis() - getTimeSpeedUp() >= (25 * 1000)) {
|
||||
setCpuFrequencyMhz(80);
|
||||
setTimeSpeedUp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void taskCreateCert(void *parameter)
|
||||
static void taskCreateCert(void *parameter)
|
||||
{
|
||||
|
||||
prefs.begin("MeshtasticHTTPS", false);
|
||||
|
||||
// Delete the saved certs
|
||||
@@ -92,13 +85,32 @@ void taskCreateCert(void *parameter)
|
||||
prefs.remove("cert");
|
||||
}
|
||||
|
||||
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
|
||||
|
||||
size_t pkLen = prefs.getBytesLength("PK");
|
||||
size_t certLen = prefs.getBytesLength("cert");
|
||||
|
||||
DEBUG_MSG("Checking if we have a previously saved SSL Certificate.\n");
|
||||
|
||||
if (pkLen && certLen) {
|
||||
DEBUG_MSG("Existing SSL Certificate found!\n");
|
||||
|
||||
uint8_t *pkBuffer = new uint8_t[pkLen];
|
||||
prefs.getBytes("PK", pkBuffer, pkLen);
|
||||
|
||||
uint8_t *certBuffer = new uint8_t[certLen];
|
||||
prefs.getBytes("cert", certBuffer, certLen);
|
||||
|
||||
cert = new SSLCert(certBuffer, certLen, pkBuffer, pkLen);
|
||||
|
||||
DEBUG_MSG("Retrieved Private Key: %d Bytes\n", cert->getPKLength());
|
||||
// DEBUG_MSG("Retrieved Private Key: " + String(cert->getPKLength()) + " Bytes");
|
||||
// for (int i = 0; i < cert->getPKLength(); i++)
|
||||
// Serial.print(cert->getPKData()[i], HEX);
|
||||
// Serial.println();
|
||||
|
||||
DEBUG_MSG("Retrieved Certificate: %d Bytes\n", cert->getCertLength());
|
||||
// for (int i = 0; i < cert->getCertLength(); i++)
|
||||
// Serial.print(cert->getCertData()[i], HEX);
|
||||
// Serial.println();
|
||||
} else {
|
||||
DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n");
|
||||
yield();
|
||||
@@ -133,35 +145,35 @@ void taskCreateCert(void *parameter)
|
||||
}
|
||||
}
|
||||
|
||||
isCertReady = 1;
|
||||
isCertReady = true;
|
||||
|
||||
// Must delete self, can't just fall out
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void createSSLCert()
|
||||
{
|
||||
if (isWifiAvailable() && !isCertReady) {
|
||||
|
||||
if (isWifiAvailable() == 0) {
|
||||
return;
|
||||
// Create a new process just to handle creating the cert.
|
||||
// This is a workaround for Bug: https://github.com/fhessel/esp32_https_server/issues/48
|
||||
// jm@casler.org (Oct 2020)
|
||||
xTaskCreate(taskCreateCert, /* Task function. */
|
||||
"createCert", /* String with name of task. */
|
||||
16384, /* Stack size in bytes. */
|
||||
NULL, /* Parameter passed as input of the task */
|
||||
16, /* Priority of the task. */
|
||||
NULL); /* Task handle. */
|
||||
|
||||
DEBUG_MSG("Waiting for SSL Cert to be generated.\n");
|
||||
while (!isCertReady) {
|
||||
DEBUG_MSG(".");
|
||||
delay(1000);
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
DEBUG_MSG("SSL Cert Ready!\n");
|
||||
}
|
||||
|
||||
// Create a new process just to handle creating the cert.
|
||||
// This is a workaround for Bug: https://github.com/fhessel/esp32_https_server/issues/48
|
||||
// jm@casler.org (Oct 2020)
|
||||
xTaskCreate(taskCreateCert, /* Task function. */
|
||||
"createCert", /* String with name of task. */
|
||||
16384, /* Stack size in bytes. */
|
||||
NULL, /* Parameter passed as input of the task */
|
||||
16, /* Priority of the task. */
|
||||
NULL); /* Task handle. */
|
||||
|
||||
DEBUG_MSG("Waiting for SSL Cert to be generated.\n");
|
||||
while (!isCertReady) {
|
||||
DEBUG_MSG(".");
|
||||
delay(1000);
|
||||
yield();
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
DEBUG_MSG("SSL Cert Ready!\n");
|
||||
}
|
||||
|
||||
WebServerThread *webServerThread;
|
||||
@@ -181,6 +193,8 @@ void initWebServer()
|
||||
{
|
||||
DEBUG_MSG("Initializing Web Server ...\n");
|
||||
|
||||
#if 0
|
||||
// this seems to be a copypaste dup of taskCreateCert
|
||||
prefs.begin("MeshtasticHTTPS", false);
|
||||
|
||||
size_t pkLen = prefs.getBytesLength("PK");
|
||||
@@ -211,6 +225,7 @@ void initWebServer()
|
||||
} else {
|
||||
DEBUG_MSG("Web Server started without SSL keys! How did this happen?\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// We can now use the new certificate to setup our server as usual.
|
||||
secureServer = new HTTPSServer(cert);
|
||||
@@ -218,14 +233,16 @@ void initWebServer()
|
||||
|
||||
registerHandlers(insecureServer, secureServer);
|
||||
|
||||
DEBUG_MSG("Starting Web Servers...\n");
|
||||
secureServer->start();
|
||||
if(secureServer) {
|
||||
DEBUG_MSG("Starting Secure Web Server...\n");
|
||||
secureServer->start();
|
||||
}
|
||||
DEBUG_MSG("Starting Insecure Web Server...\n");
|
||||
insecureServer->start();
|
||||
if (secureServer->isRunning() && insecureServer->isRunning()) {
|
||||
DEBUG_MSG("HTTP and HTTPS Web Servers Ready! :-) \n");
|
||||
isWebServerReady = 1;
|
||||
if (insecureServer->isRunning()) {
|
||||
DEBUG_MSG("Web Servers Ready! :-) \n");
|
||||
isWebServerReady = true;
|
||||
} else {
|
||||
DEBUG_MSG("HTTP and HTTPS Web Servers Failed! ;-( \n");
|
||||
DEBUG_MSG("Web Servers Failed! ;-( \n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
void initWebServer();
|
||||
void createSSLCert();
|
||||
|
||||
|
||||
void handleWebResponse();
|
||||
|
||||
|
||||
class WebServerThread : private concurrency::OSThread
|
||||
{
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "NodeDB.h"
|
||||
#include "concurrency/Periodic.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "mesh/wifi/WiFiServerAPI.h"
|
||||
#include "target_specific.h"
|
||||
@@ -9,6 +11,8 @@
|
||||
#include <ESPmDNS.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
using namespace concurrency;
|
||||
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
|
||||
// DNS Server for the Captive Portal
|
||||
@@ -23,6 +27,47 @@ bool forcedSoftAP = 0;
|
||||
|
||||
bool APStartupComplete = 0;
|
||||
|
||||
static bool needReconnect = true; // If we create our reconnector, run it once at the beginning
|
||||
|
||||
// FIXME, veto light sleep if we have a TCP server running
|
||||
#if 0
|
||||
class WifiSleepObserver : public Observer<uint32_t> {
|
||||
protected:
|
||||
|
||||
/// Return 0 if sleep is okay
|
||||
virtual int onNotify(uint32_t newValue) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
static WifiSleepObserver wifiSleepObserver;
|
||||
//preflightSleepObserver.observe(&preflightSleep);
|
||||
#endif
|
||||
|
||||
static int32_t reconnectWiFi()
|
||||
{
|
||||
if (radioConfig.has_preferences && needReconnect) {
|
||||
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
if (*wifiName) {
|
||||
needReconnect = false;
|
||||
|
||||
DEBUG_MSG("... Reconnecting to WiFi access point");
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
}
|
||||
|
||||
return 30 * 1000; // every 30 seconds
|
||||
}
|
||||
|
||||
static Periodic *wifiReconnect;
|
||||
|
||||
bool isSoftAPForced()
|
||||
{
|
||||
return forcedSoftAP;
|
||||
@@ -37,15 +82,6 @@ bool isWifiAvailable()
|
||||
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
|
||||
// strcpy(radioConfig.preferences.wifi_ssid, "meshtastic");
|
||||
// strcpy(radioConfig.preferences.wifi_password, "meshtastic!");
|
||||
|
||||
// strcpy(radioConfig.preferences.wifi_ssid, "meshtasticAdmin");
|
||||
// strcpy(radioConfig.preferences.wifi_password, "12345678");
|
||||
|
||||
// radioConfig.preferences.wifi_ap_mode = true;
|
||||
// radioConfig.preferences.wifi_ap_mode = false;
|
||||
|
||||
if (*wifiName) {
|
||||
return true;
|
||||
} else {
|
||||
@@ -74,27 +110,44 @@ void deinitWifi()
|
||||
}
|
||||
}
|
||||
|
||||
// Startup WiFi
|
||||
void initWifi(bool forceSoftAP)
|
||||
static void onNetworkConnected()
|
||||
{
|
||||
if (!APStartupComplete) {
|
||||
// Start web server
|
||||
DEBUG_MSG("... Starting network services\n");
|
||||
|
||||
if (forceSoftAP) {
|
||||
// do nothing
|
||||
// DEBUG_MSG("----- Forcing SoftAP\n");
|
||||
} else {
|
||||
if (isWifiAvailable() == 0) {
|
||||
return;
|
||||
// start mdns
|
||||
if (!MDNS.begin("Meshtastic")) {
|
||||
DEBUG_MSG("Error setting up MDNS responder!\n");
|
||||
} else {
|
||||
DEBUG_MSG("mDNS responder started\n");
|
||||
DEBUG_MSG("mDNS Host: Meshtastic.local\n");
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
}
|
||||
}
|
||||
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
}
|
||||
|
||||
// FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected'
|
||||
if(mqtt)
|
||||
mqtt->reconnect();
|
||||
}
|
||||
|
||||
// Startup WiFi
|
||||
bool initWifi(bool forceSoftAP)
|
||||
{
|
||||
forcedSoftAP = forceSoftAP;
|
||||
|
||||
createSSLCert();
|
||||
|
||||
if (radioConfig.has_preferences || forceSoftAP) {
|
||||
if ((radioConfig.has_preferences && radioConfig.preferences.wifi_ssid[0]) || forceSoftAP) {
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
createSSLCert();
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
@@ -155,29 +208,15 @@ void initWifi(bool forceSoftAP)
|
||||
},
|
||||
WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
|
||||
|
||||
DEBUG_MSG("JOINING WIFI: ssid=%s\n", wifiName);
|
||||
if (WiFi.begin(wifiName, wifiPsw) == WL_CONNECTED) {
|
||||
DEBUG_MSG("MY IP ADDRESS: %s\n", WiFi.localIP().toString().c_str());
|
||||
} else {
|
||||
DEBUG_MSG("Started Joining WIFI\n");
|
||||
}
|
||||
DEBUG_MSG("JOINING WIFI soon: ssid=%s\n", wifiName);
|
||||
wifiReconnect = new Periodic("WifiConnect", reconnectWiFi);
|
||||
}
|
||||
}
|
||||
|
||||
if (!MDNS.begin("Meshtastic")) {
|
||||
DEBUG_MSG("Error setting up MDNS responder!\n");
|
||||
|
||||
while (1) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
DEBUG_MSG("mDNS responder started\n");
|
||||
DEBUG_MSG("mDNS Host: Meshtastic.local\n");
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("https", "tcp", 443);
|
||||
|
||||
} else
|
||||
return true;
|
||||
} else {
|
||||
DEBUG_MSG("Not using WIFI\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Called by the Espressif SDK to
|
||||
@@ -193,10 +232,10 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
DEBUG_MSG("Completed scan for access points\n");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
DEBUG_MSG("WiFi client started\n");
|
||||
DEBUG_MSG("WiFi station started\n");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_STOP:
|
||||
DEBUG_MSG("WiFi clients stopped\n");
|
||||
DEBUG_MSG("WiFi station stopped\n");
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
DEBUG_MSG("Connected to access point\n");
|
||||
@@ -205,7 +244,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
DEBUG_MSG("Disconnected from WiFi access point\n");
|
||||
// Event 5
|
||||
|
||||
reconnectWiFi();
|
||||
needReconnect = true;
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
|
||||
DEBUG_MSG("Authentication mode of access point has changed\n");
|
||||
@@ -213,18 +252,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
DEBUG_MSG("Obtained IP address: \n");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (!APStartupComplete) {
|
||||
// Start web server
|
||||
DEBUG_MSG("... Starting network services\n");
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
} else {
|
||||
DEBUG_MSG("... Not starting network services (They're already running)\n");
|
||||
}
|
||||
|
||||
onNetworkConnected();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_LOST_IP:
|
||||
DEBUG_MSG("Lost IP address and IP address is reset to 0\n");
|
||||
@@ -244,18 +272,7 @@ static void WiFiEvent(WiFiEvent_t event)
|
||||
case SYSTEM_EVENT_AP_START:
|
||||
DEBUG_MSG("WiFi access point started\n");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
if (!APStartupComplete) {
|
||||
// Start web server
|
||||
DEBUG_MSG("... Starting network services\n");
|
||||
initWebServer();
|
||||
initApiServer();
|
||||
|
||||
APStartupComplete = true;
|
||||
} else {
|
||||
DEBUG_MSG("... Not starting network services (They're already running)\n");
|
||||
}
|
||||
|
||||
onNetworkConnected();
|
||||
break;
|
||||
case SYSTEM_EVENT_AP_STOP:
|
||||
DEBUG_MSG("WiFi access point stopped\n");
|
||||
@@ -302,26 +319,6 @@ void handleDNSResponse()
|
||||
}
|
||||
}
|
||||
|
||||
void reconnectWiFi()
|
||||
{
|
||||
if (radioConfig.has_preferences) {
|
||||
|
||||
const char *wifiName = radioConfig.preferences.wifi_ssid;
|
||||
const char *wifiPsw = radioConfig.preferences.wifi_password;
|
||||
|
||||
if (!*wifiPsw) // Treat empty password as no password
|
||||
wifiPsw = NULL;
|
||||
|
||||
if (*wifiName) {
|
||||
|
||||
DEBUG_MSG("... Reconnecting to WiFi access point");
|
||||
|
||||
WiFi.mode(WIFI_MODE_STA);
|
||||
WiFi.begin(wifiName, wifiPsw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getWifiDisconnectReason()
|
||||
{
|
||||
return wifiDisconnectReason;
|
||||
|
||||
@@ -9,15 +9,15 @@
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
void initWifi(bool forceSoftAP);
|
||||
/// @return true if wifi is now in use
|
||||
bool initWifi(bool forceSoftAP);
|
||||
|
||||
void deinitWifi();
|
||||
|
||||
bool isWifiAvailable();
|
||||
|
||||
void handleDNSResponse();
|
||||
|
||||
void reconnectWiFi();
|
||||
|
||||
bool isSoftAPForced();
|
||||
|
||||
uint8_t getWifiDisconnectReason();
|
||||
|
||||
@@ -25,8 +25,6 @@ WiFiServerAPI::~WiFiServerAPI()
|
||||
// FIXME - delete this if the client dropps the connection!
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// override close to also shutdown the TCP link
|
||||
void WiFiServerAPI::close()
|
||||
{
|
||||
@@ -51,6 +49,13 @@ int32_t WiFiServerAPI::runOnce()
|
||||
}
|
||||
}
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
void WiFiServerPort::debugOut(char c)
|
||||
{
|
||||
if (apiPort && apiPort->openAPI)
|
||||
apiPort->openAPI->debugOut(c);
|
||||
}
|
||||
|
||||
#define MESHTASTIC_PORTNUM 4403
|
||||
|
||||
WiFiServerPort::WiFiServerPort() : WiFiServer(MESHTASTIC_PORTNUM), concurrency::OSThread("ApiServer") {}
|
||||
|
||||
@@ -21,8 +21,8 @@ class WiFiServerAPI : public StreamAPI
|
||||
virtual void close();
|
||||
|
||||
protected:
|
||||
|
||||
/// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to stay in the POWERED state to prevent disabling wifi)
|
||||
/// We override this method to prevent publishing EVENT_SERIAL_CONNECTED/DISCONNECTED for wifi links (we want the board to
|
||||
/// stay in the POWERED state to prevent disabling wifi)
|
||||
virtual void onConnectionChanged(bool connected) {}
|
||||
|
||||
virtual int32_t runOnce(); // Check for dropped client connections
|
||||
@@ -48,6 +48,10 @@ class WiFiServerPort : public WiFiServer, private concurrency::OSThread
|
||||
|
||||
void init();
|
||||
|
||||
/// If an api server is running, we try to spit out debug 'serial' characters there
|
||||
static void debugOut(char c);
|
||||
|
||||
protected:
|
||||
int32_t runOnce();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "MQTT.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "main.h"
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/Router.h"
|
||||
#include "mesh/generated/mqtt.pb.h"
|
||||
#include "sleep.h"
|
||||
#include <WiFi.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -57,42 +59,45 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient)
|
||||
mqtt = this;
|
||||
|
||||
pubSub.setCallback(mqttCallback);
|
||||
|
||||
// preflightSleepObserver.observe(&preflightSleep);
|
||||
}
|
||||
|
||||
void MQTT::reconnect()
|
||||
{
|
||||
// pubSub.setServer("devsrv.ezdevice.net", 1883); or 192.168.10.188
|
||||
const char *serverAddr = "mqtt.meshtastic.org:1883"; // default hostname
|
||||
if (wantsLink()) {
|
||||
const char *serverAddr = "mqtt.meshtastic.org"; // default hostname
|
||||
int serverPort = 1883; // default server port
|
||||
|
||||
if (*radioConfig.preferences.mqtt_server)
|
||||
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
|
||||
if (*radioConfig.preferences.mqtt_server)
|
||||
serverAddr = radioConfig.preferences.mqtt_server; // Override the default
|
||||
|
||||
String server = String(serverAddr);
|
||||
int delimIndex = server.indexOf(':');
|
||||
if (delimIndex > 0) {
|
||||
String host = server.substring(0, delimIndex);
|
||||
String port = server.substring(delimIndex+1, server.length());
|
||||
pubSub.setServer(host.c_str(), port.toInt());
|
||||
String server = String(serverAddr);
|
||||
int delimIndex = server.indexOf(':');
|
||||
if (delimIndex > 0) {
|
||||
String port = server.substring(delimIndex + 1, server.length());
|
||||
server[delimIndex] = 0;
|
||||
serverPort = port.toInt();
|
||||
serverAddr = server.c_str();
|
||||
}
|
||||
pubSub.setServer(serverAddr, serverPort);
|
||||
|
||||
DEBUG_MSG("Connecting to MQTT server %s, port: %d\n", serverAddr, serverPort);
|
||||
auto myStatus = (statusTopic + owner.id);
|
||||
bool connected = pubSub.connect(owner.id, "meshdev", "large4cats", myStatus.c_str(), 1, true, "offline");
|
||||
if (connected) {
|
||||
DEBUG_MSG("MQTT connected\n");
|
||||
enabled = true; // Start running background process again
|
||||
runASAP = true;
|
||||
|
||||
/// FIXME, include more information in the status text
|
||||
bool ok = pubSub.publish(myStatus.c_str(), "online", true);
|
||||
DEBUG_MSG("published %d\n", ok);
|
||||
|
||||
sendSubscriptions();
|
||||
} else
|
||||
DEBUG_MSG("Failed to contact MQTT server...\n");
|
||||
}
|
||||
else {
|
||||
pubSub.setServer(serverAddr, 1883);
|
||||
}
|
||||
|
||||
DEBUG_MSG("Connecting to MQTT server\n", serverAddr);
|
||||
auto myStatus = (statusTopic + owner.id);
|
||||
bool connected = pubSub.connect(owner.id, "meshdev", "large4cats", myStatus.c_str(), 1, true, "offline");
|
||||
if (connected) {
|
||||
DEBUG_MSG("MQTT connected\n");
|
||||
enabled = true; // Start running background process again
|
||||
runASAP = true;
|
||||
|
||||
/// FIXME, include more information in the status text
|
||||
bool ok = pubSub.publish(myStatus.c_str(), "online", true);
|
||||
DEBUG_MSG("published %d\n", ok);
|
||||
|
||||
sendSubscriptions();
|
||||
} else
|
||||
DEBUG_MSG("Failed to contact MQTT server...\n");
|
||||
}
|
||||
|
||||
void MQTT::sendSubscriptions()
|
||||
@@ -149,6 +154,7 @@ int32_t MQTT::runOnce()
|
||||
pubSub.disconnect();
|
||||
}
|
||||
|
||||
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); // Suppress entering light sleep (because that would turn off bluetooth)
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ class MQTT : private concurrency::OSThread
|
||||
WiFiClient mqttClient;
|
||||
PubSubClient pubSub;
|
||||
|
||||
// instead we supress sleep from our runOnce() callback
|
||||
// CallbackObserver<MQTT, void *> preflightSleepObserver = CallbackObserver<MQTT, void *>(this, &MQTT::preflightSleepCb);
|
||||
|
||||
public:
|
||||
MQTT();
|
||||
|
||||
@@ -32,6 +35,10 @@ class MQTT : private concurrency::OSThread
|
||||
*/
|
||||
void onSend(const MeshPacket &mp, ChannelIndex chIndex);
|
||||
|
||||
/** Attempt to connect to server if necessary
|
||||
*/
|
||||
void reconnect();
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce();
|
||||
|
||||
@@ -40,10 +47,6 @@ class MQTT : private concurrency::OSThread
|
||||
*/
|
||||
bool wantsLink() const;
|
||||
|
||||
/** Attempt to connect to server if necessary
|
||||
*/
|
||||
void reconnect();
|
||||
|
||||
/** Tell the server what subscriptions we want (based on channels.downlink_enabled)
|
||||
*/
|
||||
void sendSubscriptions();
|
||||
@@ -53,6 +56,9 @@ class MQTT : private concurrency::OSThread
|
||||
|
||||
/// Called when a new publish arrives from the MQTT server
|
||||
void onPublish(char *topic, byte *payload, unsigned int length);
|
||||
|
||||
/// Return 0 if sleep is okay, veto sleep if we are connected to pubsub server
|
||||
// int preflightSleepCb(void *unused = NULL) { return pubSub.connected() ? 1 : 0; }
|
||||
};
|
||||
|
||||
void mqttInit();
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
static bool pinShowing;
|
||||
static uint32_t doublepressed;
|
||||
|
||||
static bool bluetoothActive;
|
||||
|
||||
static void startCb(uint32_t pin)
|
||||
{
|
||||
pinShowing = true;
|
||||
@@ -52,23 +54,27 @@ void updateBatteryLevel(uint8_t level)
|
||||
|
||||
void deinitBLE()
|
||||
{
|
||||
// DEBUG_MSG("Shutting down bluetooth\n");
|
||||
// ble_gatts_show_local();
|
||||
if (bluetoothActive) {
|
||||
bluetoothActive = false;
|
||||
|
||||
// FIXME - do we need to dealloc things? - what needs to stay alive across light sleep?
|
||||
auto ret = nimble_port_stop();
|
||||
assert(ret == ESP_OK);
|
||||
// DEBUG_MSG("Shutting down bluetooth\n");
|
||||
// ble_gatts_show_local();
|
||||
|
||||
nimble_port_deinit(); // teardown nimble datastructures
|
||||
// FIXME - do we need to dealloc things? - what needs to stay alive across light sleep?
|
||||
auto ret = nimble_port_stop();
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
// DEBUG_MSG("BLE port_deinit done\n");
|
||||
nimble_port_deinit(); // teardown nimble datastructures
|
||||
|
||||
ret = esp_nimble_hci_and_controller_deinit();
|
||||
assert(ret == ESP_OK);
|
||||
// DEBUG_MSG("BLE port_deinit done\n");
|
||||
|
||||
// DEBUG_MSG("BLE task exiting\n");
|
||||
ret = esp_nimble_hci_and_controller_deinit();
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
DEBUG_MSG("Done shutting down bluetooth\n");
|
||||
// DEBUG_MSG("BLE task exiting\n");
|
||||
|
||||
DEBUG_MSG("Done shutting down bluetooth\n");
|
||||
}
|
||||
}
|
||||
|
||||
void loopBLE()
|
||||
@@ -479,6 +485,8 @@ void disablePin()
|
||||
doublepressed = millis();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This routine is called multiple times, once each time we come back from sleep
|
||||
void reinitBluetooth()
|
||||
{
|
||||
@@ -536,10 +544,10 @@ void reinitBluetooth()
|
||||
ble_store_config_init();
|
||||
|
||||
nimble_port_freertos_init(ble_host_task);
|
||||
bluetoothActive = true;
|
||||
}
|
||||
|
||||
bool bluetoothOn;
|
||||
bool firstTime = 1;
|
||||
|
||||
// Enable/disable bluetooth.
|
||||
void setBluetoothEnable(bool on)
|
||||
@@ -549,32 +557,15 @@ void setBluetoothEnable(bool on)
|
||||
|
||||
bluetoothOn = on;
|
||||
if (on) {
|
||||
Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap());
|
||||
// ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
reinitBluetooth();
|
||||
|
||||
// Don't try to reconnect wifi before bluetooth is configured.
|
||||
// WiFi is initialized from main.cpp in setup() .
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
} else {
|
||||
#ifndef NO_ESP32
|
||||
initWifi(0);
|
||||
#endif
|
||||
if (!initWifi(0)) // if we are using wifi, don't turn on bluetooth also
|
||||
{
|
||||
Serial.printf("Pre BT: %u heap size\n", ESP.getFreeHeap());
|
||||
// ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
reinitBluetooth();
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
// If WiFi is in use, disable shutting down the radio.
|
||||
if (isWifiAvailable()) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// shutdown wifi
|
||||
#ifndef NO_ESP32
|
||||
deinitWifi();
|
||||
#endif
|
||||
|
||||
// We have to totally teardown our bluetooth objects to prevent leaks
|
||||
deinitBLE();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <ble_gap.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
// #include <Adafruit_USBD_Device.h>
|
||||
|
||||
#include "NRF52Bluetooth.h"
|
||||
#include "error.h"
|
||||
@@ -20,7 +21,10 @@ static inline void debugger_break(void)
|
||||
}
|
||||
|
||||
bool loopCanSleep() {
|
||||
return !tud_cdc_connected();
|
||||
// turn off sleep only while connected via USB
|
||||
// return true;
|
||||
return !Serial; // the bool operator on the nrf52 serial class returns true if connected to a PC currently
|
||||
// return !(TinyUSBDevice.mounted() && !TinyUSBDevice.suspended());
|
||||
}
|
||||
|
||||
// handle standard gcc assert failures
|
||||
@@ -37,7 +41,7 @@ void getMacAddr(uint8_t *dmac)
|
||||
ble_gap_addr_t addr;
|
||||
if (sd_ble_gap_addr_get(&addr) == NRF_SUCCESS) {
|
||||
memcpy(dmac, addr.addr, 6);
|
||||
} else {
|
||||
} else {
|
||||
const uint8_t *src = (const uint8_t *)NRF_FICR->DEVICEADDR;
|
||||
dmac[5] = src[0];
|
||||
dmac[4] = src[1];
|
||||
@@ -90,7 +94,7 @@ void setBluetoothEnable(bool on)
|
||||
}
|
||||
|
||||
/**
|
||||
* Override printf to use the SEGGER output library
|
||||
* Override printf to use the SEGGER output library (note - this does not effect the printf method on the debug console)
|
||||
*/
|
||||
int printf(const char *fmt, ...)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,24 @@
|
||||
|
||||
AdminPlugin *adminPlugin;
|
||||
|
||||
/// A special reserved string to indicate strings we can not share with external nodes. We will use this 'reserved' word instead.
|
||||
/// Also, to make setting work correctly, if someone tries to set a string to this reserved value we assume they don't really want a change.
|
||||
static const char *secretReserved = "sekrit";
|
||||
|
||||
/// If buf is !empty, change it to secret
|
||||
static void hideSecret(char *buf) {
|
||||
if(*buf) {
|
||||
strcpy(buf, secretReserved);
|
||||
}
|
||||
}
|
||||
|
||||
/// If buf is the reserved secret word, replace the buffer with currentVal
|
||||
static void writeSecret(char *buf, const char *currentVal) {
|
||||
if(strcmp(buf, secretReserved) == 0) {
|
||||
strcpy(buf, currentVal);
|
||||
}
|
||||
}
|
||||
|
||||
void AdminPlugin::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
@@ -35,13 +53,15 @@ void AdminPlugin::handleGetRadio(const MeshPacket &req)
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private and useful for users to know current provisioning)
|
||||
hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
|
||||
r.which_variant = AdminMessage_get_radio_response_tag;
|
||||
myReply = allocDataProtobuf(r);
|
||||
}
|
||||
}
|
||||
|
||||
bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, const AdminMessage *r)
|
||||
bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *r)
|
||||
{
|
||||
assert(r);
|
||||
switch (r->which_variant) {
|
||||
@@ -139,8 +159,9 @@ void AdminPlugin::handleSetChannel(const Channel &cc)
|
||||
}
|
||||
}
|
||||
|
||||
void AdminPlugin::handleSetRadio(const RadioConfig &r)
|
||||
void AdminPlugin::handleSetRadio(RadioConfig &r)
|
||||
{
|
||||
writeSecret(r.preferences.wifi_password, radioConfig.preferences.wifi_password);
|
||||
radioConfig = r;
|
||||
|
||||
service.reloadConfig();
|
||||
|
||||
@@ -17,12 +17,12 @@ class AdminPlugin : public ProtobufPlugin<AdminMessage>
|
||||
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const AdminMessage *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, AdminMessage *p);
|
||||
|
||||
private:
|
||||
void handleSetOwner(const User &o);
|
||||
void handleSetChannel(const Channel &cc);
|
||||
void handleSetRadio(const RadioConfig &r);
|
||||
void handleSetRadio(RadioConfig &r);
|
||||
|
||||
void handleGetChannel(const MeshPacket &req, uint32_t channelIndex);
|
||||
void handleGetRadio(const MeshPacket &req);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
NodeInfoPlugin *nodeInfoPlugin;
|
||||
|
||||
bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, const User *pptr)
|
||||
bool NodeInfoPlugin::handleReceivedProtobuf(const MeshPacket &mp, User *pptr)
|
||||
{
|
||||
auto p = *pptr;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class NodeInfoPlugin : public ProtobufPlugin<User>, private concurrency::OSThrea
|
||||
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const User *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, User *p);
|
||||
|
||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
||||
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||
|
||||
@@ -14,7 +14,7 @@ PositionPlugin::PositionPlugin()
|
||||
setIntervalFromNow(60 * 1000); // Send our initial position 60 seconds after we start (to give GPS time to setup)
|
||||
}
|
||||
|
||||
bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Position *pptr)
|
||||
bool PositionPlugin::handleReceivedProtobuf(const MeshPacket &mp, Position *pptr)
|
||||
{
|
||||
auto p = *pptr;
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class PositionPlugin : public ProtobufPlugin<Position>, private concurrency::OST
|
||||
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Position *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, Position *p);
|
||||
|
||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
||||
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||
|
||||
@@ -48,7 +48,7 @@ RemoteHardwarePlugin::RemoteHardwarePlugin()
|
||||
{
|
||||
}
|
||||
|
||||
bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, const HardwareMessage *pptr)
|
||||
bool RemoteHardwarePlugin::handleReceivedProtobuf(const MeshPacket &req, HardwareMessage *pptr)
|
||||
{
|
||||
auto p = *pptr;
|
||||
DEBUG_MSG("Received RemoteHardware typ=%d\n", p.typ);
|
||||
|
||||
@@ -27,7 +27,7 @@ class RemoteHardwarePlugin : public ProtobufPlugin<HardwareMessage>, private con
|
||||
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const HardwareMessage *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, HardwareMessage *p);
|
||||
|
||||
/**
|
||||
* Periodically read the gpios we have been asked to WATCH, if they have changed,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
RoutingPlugin *routingPlugin;
|
||||
|
||||
bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing *r)
|
||||
bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, Routing *r)
|
||||
{
|
||||
printPacket("Routing sniffing", &mp);
|
||||
router->sniffReceived(&mp, r);
|
||||
|
||||
@@ -22,7 +22,7 @@ class RoutingPlugin : public ProtobufPlugin<Routing>
|
||||
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Routing *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, Routing *p);
|
||||
|
||||
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
|
||||
* so that subclasses can (optionally) send a response back to the original sender. */
|
||||
|
||||
@@ -204,7 +204,7 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
|
||||
|
||||
}
|
||||
|
||||
bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement *p)
|
||||
bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p)
|
||||
{
|
||||
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){
|
||||
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
|
||||
|
||||
@@ -18,7 +18,7 @@ class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public Pro
|
||||
/** Called to handle a particular incoming message
|
||||
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
|
||||
*/
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, const EnvironmentalMeasurement *p);
|
||||
virtual bool handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p);
|
||||
virtual int32_t runOnce();
|
||||
/**
|
||||
* Send our EnvironmentalMeasurement into the mesh
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
//#include "mesh/wifi/WiFiAPClient.h"
|
||||
|
||||
void initWifi(bool forceSoftAP) {}
|
||||
bool initWifi(bool forceSoftAP) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void deinitWifi() {}
|
||||
|
||||
|
||||
@@ -251,6 +251,26 @@ External serial flash WP25R1635FZUIL0
|
||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||
// #define USE_SEGGER
|
||||
|
||||
// Battery
|
||||
// The battery sense is hooked to pin A0 (4)
|
||||
// it is defined in the anlaolgue pin section of this file
|
||||
// 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 => 100K + 100K voltage divider on VBAT = (100K / (100K + 100K))
|
||||
#define VBAT_DIVIDER (0.5F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (2.0)
|
||||
// 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
|
||||
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 1
|
||||
minor = 2
|
||||
build = 43
|
||||
build = 45
|
||||
|
||||
Reference in New Issue
Block a user