Merge branch 'develop' into mqtt-fix

This commit is contained in:
Thomas Göttgens
2023-01-09 23:28:08 +01:00
committed by GitHub
46 changed files with 317 additions and 653 deletions

View File

@@ -8,7 +8,7 @@ build_flags =
${arduino_base.build_flags} -Wno-unused-variable
-Isrc/platform/nrf52
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
lib_ignore =
BluetoothOTA

View File

@@ -12,7 +12,7 @@ build_flags =
-D__PLAT_RP2040__
# -D _POSIX_THREADS
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
lib_ignore =
BluetoothOTA
lib_deps =

View File

@@ -10,7 +10,7 @@ build_flags =
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
lib_deps =
${env.lib_deps}
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b

View File

@@ -170,8 +170,8 @@ void fsInit()
#ifdef FSCom
if (!FSBegin())
{
LOG_ERROR("Filesystem mount Failed. Formatting...\n");
assert(0); // FIXME - report failure to phone
LOG_ERROR("Filesystem mount Failed.\n");
// assert(0); This auto-formats the partition, so no need to fail here.
}
#ifdef ARCH_ESP32
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());

View File

@@ -17,7 +17,7 @@
// RP2040
#include "LittleFS.h"
#define FSCom LittleFS
#define FSBegin() FSCom.begin()
#define FSBegin() FSCom.begin() // set autoformat
#define FILE_O_WRITE "w"
#define FILE_O_READ "r"
#endif
@@ -26,7 +26,7 @@
// ESP32 version
#include "LittleFS.h"
#define FSCom LittleFS
#define FSBegin() FSCom.begin(true)
#define FSBegin() FSCom.begin(true) // format on failure
#define FILE_O_WRITE "w"
#define FILE_O_READ "r"
#endif
@@ -35,7 +35,7 @@
// NRF52 version
#include "InternalFileSystem.h"
#define FSCom InternalFS
#define FSBegin() FSCom.begin()
#define FSBegin() FSCom.begin() // InternalFS formats on failure
using namespace Adafruit_LittleFS_Namespace;
#endif

View File

@@ -1,7 +1,6 @@
#pragma once
#include <Arduino.h>
#include <assert.h>
#include <list>
template <class T> class Observable;

View File

@@ -3,7 +3,6 @@
#include "RTC.h"
#include "NodeDB.h"
#include "concurrency/OSThread.h"
// #include "wifi/WiFiServerAPI.h"
#include <assert.h>
#include <sys/time.h>
#include <time.h>
@@ -27,10 +26,6 @@ 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);
if (!config.has_lora || config.device.serial_enabled)
dest->write(c);
@@ -108,3 +103,31 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
return r;
}
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len) {
const char alphabet[17] = "0123456789abcdef";
log(logLevel, " +------------------------------------------------+ +----------------+\n");
log(logLevel, " |.0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .a .b .c .d .e .f | | ASCII |\n");
for (uint16_t i = 0; i < len; i += 16) {
if (i % 128 == 0)
log(logLevel, " +------------------------------------------------+ +----------------+\n");
char s[] = "| | | |\n";
uint8_t ix = 1, iy = 52;
for (uint8_t j = 0; j < 16; j++) {
if (i + j < len) {
uint8_t c = buf[i + j];
s[ix++] = alphabet[(c >> 4) & 0x0F];
s[ix++] = alphabet[c & 0x0F];
ix++;
if (c > 31 && c < 128) s[iy++] = c;
else s[iy++] = '.';
}
}
uint8_t index = i / 16;
if (i < 256) log(logLevel, " ");
log(logLevel, "%02x",index);
log(logLevel, ".");
log(logLevel, s);
}
log(logLevel, " +------------------------------------------------+ +----------------+\n");
}

View File

@@ -38,6 +38,8 @@ class RedirectablePrint : public Print
/** like printf but va_list based */
size_t vprintf(const char *format, va_list arg);
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
};
class NoopPrint : public Print

View File

@@ -1,7 +1,6 @@
#include "configuration.h"
#include "NotifiedWorkerThread.h"
#include "main.h"
#include <assert.h>
namespace concurrency
{

View File

@@ -3,7 +3,6 @@
#include "RTC.h"
#include "configuration.h"
#include "sleep.h"
#include <assert.h>
// If we have a serial GPS port it will not be null
#ifdef GPS_SERIAL_NUM

View File

@@ -36,12 +36,12 @@
#endif
#if HAS_WIFI
#include "mesh/wifi/WiFiServerAPI.h"
#include "mesh/api/WiFiServerAPI.h"
#include "mqtt/MQTT.h"
#endif
#if HAS_ETHERNET
#include "mesh/eth/ethServerAPI.h"
#include "mesh/api/ethServerAPI.h"
#include "mqtt/MQTT.h"
#endif

View File

@@ -1,318 +0,0 @@
/*
* mtest - Perform a memory test
*
* (C) Copyright 2000
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include "configuration.h"
/*
* Perform a memory test. A more complete alternative test can be
* configured using CONFIG_CMD_MTEST_ALTERNATIVE. The complete test
* loops until interrupted by ctrl-c or by a failure of one of the
* sub-tests.
*/
#ifdef CONFIG_CMD_MTEST_ALTERNATIVE
static int mem_test(uint32_t _start, uint32_t _end, uint32_t pattern_unused)
{
volatile uint32_t *start = (volatile uint32_t *)_start;
volatile uint32_t *end = (volatile uint32_t *)_end;
volatile uint32_t *addr;
uint32_t val;
uint32_t readback;
vu_long addr_mask;
vu_long offset;
vu_long test_offset;
vu_long pattern;
vu_long temp;
vu_long anti_pattern;
vu_long num_words;
#ifdef CFG_MEMTEST_SCRATCH
volatile uint32_t *dummy = (vu_long *)CFG_MEMTEST_SCRATCH;
#else
volatile uint32_t *dummy = start;
#endif
int j;
int iterations = 1;
static const uint32_t bitpattern[] = {
0x00000001, /* single bit */
0x00000003, /* two adjacent bits */
0x00000007, /* three adjacent bits */
0x0000000F, /* four adjacent bits */
0x00000005, /* two non-adjacent bits */
0x00000015, /* three non-adjacent bits */
0x00000055, /* four non-adjacent bits */
0xaaaaaaaa, /* alternating 1/0 */
};
/* XXX: enforce alignment of start and end? */
for (;;) {
if (ctrlc()) {
putchar('\n');
return 1;
}
printf("Iteration: %6d\r", iterations);
iterations++;
/*
* Data line test: write a pattern to the first
* location, write the 1's complement to a 'parking'
* address (changes the state of the data bus so a
* floating bus doen't give a false OK), and then
* read the value back. Note that we read it back
* into a variable because the next time we read it,
* it might be right (been there, tough to explain to
* the quality guys why it prints a failure when the
* "is" and "should be" are obviously the same in the
* error message).
*
* Rather than exhaustively testing, we test some
* patterns by shifting '1' bits through a field of
* '0's and '0' bits through a field of '1's (i.e.
* pattern and ~pattern).
*/
addr = start;
/* XXX */
if (addr == dummy)
++addr;
for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) {
val = bitpattern[j];
for (; val != 0; val <<= 1) {
*addr = val;
*dummy = ~val; /* clear the test data off of the bus */
readback = *addr;
if (readback != val) {
printf("FAILURE (data line): "
"expected 0x%08lx, actual 0x%08lx at address 0x%p\n",
val, readback, addr);
}
*addr = ~val;
*dummy = val;
readback = *addr;
if (readback != ~val) {
printf("FAILURE (data line): "
"Is 0x%08lx, should be 0x%08lx at address 0x%p\n",
readback, ~val, addr);
}
}
}
/*
* Based on code whose Original Author and Copyright
* information follows: Copyright (c) 1998 by Michael
* Barr. This software is placed into the public
* domain and may be used for any purpose. However,
* this notice must not be changed or removed and no
* warranty is either expressed or implied by its
* publication or distribution.
*/
/*
* Address line test
*
* Description: Test the address bus wiring in a
* memory region by performing a walking
* 1's test on the relevant bits of the
* address and checking for aliasing.
* This test will find single-bit
* address failures such as stuck -high,
* stuck-low, and shorted pins. The base
* address and size of the region are
* selected by the caller.
*
* Notes: For best results, the selected base
* address should have enough LSB 0's to
* guarantee single address bit changes.
* For example, to test a 64-Kbyte
* region, select a base address on a
* 64-Kbyte boundary. Also, select the
* region size as a power-of-two if at
* all possible.
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*
* ## NOTE ## Be sure to specify start and end
* addresses such that addr_mask has
* lots of bits set. For example an
* address range of 01000000 02000000 is
* bad while a range of 01000000
* 01ffffff is perfect.
*/
addr_mask = ((uint32_t)end - (uint32_t)start) / sizeof(vu_long);
pattern = (vu_long)0xaaaaaaaa;
anti_pattern = (vu_long)0x55555555;
debug("%s:%d: addr mask = 0x%.8lx\n", __FUNCTION__, __LINE__, addr_mask);
/*
* Write the default pattern at each of the
* power-of-two offsets.
*/
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1)
start[offset] = pattern;
/*
* Check for address bits stuck high.
*/
test_offset = 0;
start[test_offset] = anti_pattern;
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
temp = start[offset];
if (temp != pattern) {
printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx\n",
(uint32_t)&start[offset], pattern, temp);
return 1;
}
}
start[test_offset] = pattern;
/*
* Check for addr bits stuck low or shorted.
*/
for (test_offset = 1; (test_offset & addr_mask) != 0; test_offset <<= 1) {
start[test_offset] = anti_pattern;
for (offset = 1; (offset & addr_mask) != 0; offset <<= 1) {
temp = start[offset];
if ((temp != pattern) && (offset != test_offset)) {
printf("\nFAILURE: Address bit stuck low or shorted @"
" 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n",
(uint32_t)&start[offset], pattern, temp);
return 1;
}
}
start[test_offset] = pattern;
}
/*
* Description: Test the integrity of a physical
* memory device by performing an
* increment/decrement test over the
* entire region. In the process every
* storage bit in the device is tested
* as a zero and a one. The base address
* and the size of the region are
* selected by the caller.
*
* Returns: 0 if the test succeeds, 1 if the test fails.
*/
num_words = ((uint32_t)end - (uint32_t)start) / sizeof(vu_long) + 1;
/*
* Fill memory with a known pattern.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
start[offset] = pattern;
}
/*
* Check each location and invert it for the second pass.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
temp = start[offset];
if (temp != pattern) {
printf("\nFAILURE (read/write) @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx)\n",
(uint32_t)&start[offset], pattern, temp);
return 1;
}
anti_pattern = ~pattern;
start[offset] = anti_pattern;
}
/*
* Check each location for the inverted pattern and zero it.
*/
for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) {
anti_pattern = ~pattern;
temp = start[offset];
if (temp != anti_pattern) {
printf("\nFAILURE (read/write): @ 0x%.8lx:"
" expected 0x%.8lx, actual 0x%.8lx)\n",
(uint32_t)&start[offset], anti_pattern, temp);
return 1;
}
start[offset] = 0;
}
}
}
#else
static int mem_test(uint32_t *_start, size_t len, bool doRead = true, bool doWrite = true)
{
volatile uint32_t *addr;
volatile uint32_t *start = (volatile uint32_t *)_start;
const volatile uint32_t *end = start + len / sizeof(uint32_t);
uint32_t pattern = 0;
uint32_t val;
uint32_t readback;
uint32_t incr;
int rcode = 0;
incr = 1;
//LOG_DEBUG("memtest read=%d, write=%d\n", doRead, doWrite);
if (doWrite) {
//LOG_DEBUG("writing\n");
for (addr = start, val = pattern; addr < end; addr++) {
*addr = val;
val += incr;
}
}
if (doRead) {
//LOG_DEBUG("reading\n");
for (addr = start, val = pattern; addr < end; addr++) {
readback = *addr;
if (readback != val) {
LOG_ERROR("Mem error @ 0x%08X: "
"found 0x%08lX, expected 0x%08lX\n",
addr, readback, val);
rcode++;
}
val += incr;
}
}
#if 0
/*
* Flip the pattern each time to make lots of zeros and
* then, the next time, lots of ones. We decrement
* the "negative" patterns and increment the "positive"
* patterns to preserve this feature.
*/
if(pattern & 0x80000000) {
pattern = -pattern; /* complement & increment */
}
else {
pattern = ~pattern;
}
#endif
return rcode;
}
#endif
#define TESTBUF_LEN 16384
#include <assert.h>
void doMemTest()
{
static uint32_t *testBuf;
static int iter;
if (!testBuf)
testBuf = (uint32_t *)malloc(TESTBUF_LEN);
assert(testBuf);
if (mem_test(testBuf, TESTBUF_LEN, iter % 2 == 1, iter % 2 == 0) > 0)
assert(0); // FIXME report error better
iter++;
}

View File

@@ -191,9 +191,20 @@ void Channels::onConfigChanged()
Channel &Channels::getByIndex(ChannelIndex chIndex)
{
assert(chIndex < channelFile.channels_count); // This should be equal to MAX_NUM_CHANNELS
// remove this assert cause malformed packets can make our firmware reboot here.
if (chIndex < channelFile.channels_count) { // This should be equal to MAX_NUM_CHANNELS
Channel *ch = channelFile.channels + chIndex;
return *ch;
} else {
LOG_ERROR("Invalid channel index %d > %d, malformed packet received?\n", chIndex , channelFile.channels_count);
static Channel *ch = (Channel *)malloc(sizeof(Channel));
memset(ch, 0, sizeof(Channel));
// ch.index -1 means we don't know the channel locally and need to look it up by settings.name
// not sure this is handled right everywhere
ch->index = -1;
return *ch;
}
}
Channel &Channels::getByName(const char* chName)

View File

@@ -2,9 +2,23 @@
#include "SX126xInterface.cpp"
#include "SX128xInterface.h"
#include "SX128xInterface.cpp"
#include "api/ServerAPI.h"
#include "api/ServerAPI.cpp"
// We need this declaration for proper linking in derived classes
template class SX126xInterface<SX1262>;
template class SX126xInterface<SX1268>;
template class SX126xInterface<LLCC68>;
template class SX128xInterface<SX1280>;
#if HAS_ETHERNET
#include "api/ethServerAPI.h"
template class ServerAPI<EthernetClient>;
template class APIServerPort<ethServerAPI, EthernetServer>;
#endif
#if HAS_WIFI
#include "api/WiFiServerAPI.h"
template class ServerAPI<WiFiClient>;
template class APIServerPort<WiFiServerAPI, WiFiServer>;
#endif

View File

@@ -1,5 +1,6 @@
#include "configuration.h"
#include "MeshPacketQueue.h"
#include <assert.h>
#include <algorithm>

View File

@@ -2,7 +2,6 @@
#include "MeshTypes.h"
#include <assert.h>
#include <queue>

View File

@@ -3,7 +3,6 @@
#include <string>
#include "GPS.h"
//#include "MeshBluetoothService.h"
#include "../concurrency/Periodic.h"
#include "BluetoothCommon.h" // needed for updateBatteryLevel, FIXME, eventually when we pull mesh out into a lib we shouldn't be whacking bluetooth from here
#include "MeshService.h"
@@ -61,7 +60,6 @@ Allocator<QueueStatus> &queueStatusPool = staticQueueStatusPool;
MeshService::MeshService() : toPhoneQueue(MAX_RX_TOPHONE), toPhoneQueueStatusQueue(MAX_RX_TOPHONE)
{
lastQueueStatus = { 0, 0, 16, 0 };
// assert(MAX_RX_TOPHONE == 32); // FIXME, delete this, just checking my clever macro
}
void MeshService::init()
@@ -261,7 +259,7 @@ void MeshService::sendToPhone(MeshPacket *p)
MeshPacket *copied = packetPool.allocCopy(*p);
perhapsDecode(copied);
assert(toPhoneQueue.enqueue(copied, 0)); // FIXME, instead of failing for full queue, delete the oldest mssages
assert(toPhoneQueue.enqueue(copied, 0));
fromNum++;
}

View File

@@ -1,5 +1,4 @@
#include "configuration.h"
#include <assert.h>
#include "Channels.h"
#include "CryptoEngine.h"

View File

@@ -6,7 +6,6 @@
#include "PowerFSM.h"
#include "RadioInterface.h"
#include "configuration.h"
#include <assert.h>
#if FromRadio_size > MAX_TO_FROM_RADIO_SIZE
#error FromRadio is too big
@@ -209,6 +208,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.config.which_payload_variant = Config_bluetooth_tag;
fromRadioScratch.config.payload_variant.bluetooth = config.bluetooth;
break;
default:
LOG_ERROR("Unknown config type %d\n", config_state);
}
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
@@ -262,6 +263,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.moduleConfig.which_payload_variant = ModuleConfig_remote_hardware_tag;
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
break;
default:
LOG_ERROR("Unknown module config type %d\n", config_state);
}
config_state++;
@@ -299,7 +302,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
break;
default:
assert(0); // unexpected state - FIXME, make an error code and reboot
LOG_ERROR("getFromRadio unexpected state %d\n", state);
}
// Do we have a message from the mesh?
@@ -369,7 +372,7 @@ bool PhoneAPI::available()
return hasPacket;
}
default:
assert(0); // unexpected state - FIXME, make an error code and reboot
LOG_ERROR("PhoneAPI::available unexpected state %d\n", state);
}
return false;

View File

@@ -86,9 +86,6 @@ class PhoneAPI : public Observer<uint32_t> // FIXME, we shouldn't be inheriting
void setInitialState() { state = STATE_SEND_MY_INFO; }
/// emit a debugging log character, FIXME - implement
void debugOut(char c) { }
protected:
/// Our fromradio packet while it is being assembled
FromRadio fromRadioScratch = {};

View File

@@ -4,7 +4,6 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "Router.h"
#include "assert.h"
#include "configuration.h"
#include "main.h"
#include "sleep.h"
@@ -111,6 +110,8 @@ const RegionInfo regions[] = {
const RegionInfo *myRegion;
static uint8_t bytes[MAX_RHPACKETLEN];
void initRegion()
{
const RegionInfo *r = regions;
@@ -164,17 +165,19 @@ uint32_t RadioInterface::getPacketTime(uint32_t pl)
uint32_t RadioInterface::getPacketTime(MeshPacket *p)
{
assert(p->which_payload_variant == MeshPacket_encrypted_tag); // It should have already been encoded by now
uint32_t pl = p->encrypted.size + sizeof(PacketHeader);
uint32_t pl = 0;
if(p->which_payload_variant == MeshPacket_encrypted_tag) {
pl = p->encrypted.size + sizeof(PacketHeader);
} else {
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &Data_msg, &p->decoded);
pl = numbytes + sizeof(PacketHeader);
}
return getPacketTime(pl);
}
/** The delay to use for retransmitting dropped packets */
uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
{
assert(slotTimeMsec); // Better be non zero
static uint8_t bytes[MAX_RHPACKETLEN];
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &Data_msg, &p->decoded);
uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader));
// Make sure enough time has elapsed for this packet to be sent and an ACK is received.
@@ -271,9 +274,6 @@ void printPacket(const char *prefix, const MeshPacket *p)
RadioInterface::RadioInterface()
{
assert(sizeof(PacketHeader) == 16); // make sure the compiler did what we expected
// Can't print strings this early - serial not setup yet
// LOG_DEBUG("Set meshradio defaults name=%s\n", channelSettings.name);
}
bool RadioInterface::reconfigure()
@@ -384,7 +384,7 @@ void RadioInterface::applyModemConfig()
cr = 8;
sf = 10;
break;
case Config_LoRaConfig_ModemPreset_LONG_FAST:
default: // Config_LoRaConfig_ModemPreset_LONG_FAST is default. Gracefully use this is preset is something illegal.
bw = (myRegion->wideLora) ? 812.5 : 250;
cr = 8;
sf = 11;
@@ -399,8 +399,6 @@ void RadioInterface::applyModemConfig()
cr = 8;
sf = 12;
break;
default:
assert(0); // Unknown enum
}
} else {
sf = loraConfig.spread_factor;
@@ -422,7 +420,6 @@ void RadioInterface::applyModemConfig()
}
power = loraConfig.tx_power;
assert(myRegion); // Should have been found in init
if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed))
power = myRegion->powerLimit;
@@ -502,7 +499,10 @@ size_t RadioInterface::beginSending(MeshPacket *p)
h->to = p->to;
h->id = p->id;
h->channel = p->channel;
assert(p->hop_limit <= HOP_MAX);
if (p->hop_limit > HOP_MAX) {
LOG_WARN("hop limit %d is too high, setting to %d\n", p->hop_limit, HOP_MAX);
p->hop_limit = HOP_MAX;
}
h->flags = p->hop_limit | (p->want_ack ? PACKET_FLAGS_WANT_ACK_MASK : 0);
// if the sender nodenum is zero, that means uninitialized

View File

@@ -372,7 +372,6 @@ QueueStatus RadioLibInterface::getQueueStatus()
printPacket("Lora RX", mp);
// xmitMsec = getPacketTime(mp);
airTime->logAirtime(RX_LOG, xmitMsec);
deliverToReceiver(mp);

View File

@@ -39,6 +39,8 @@ static MemoryDynamic<MeshPacket> staticPool;
Allocator<MeshPacket> &packetPool = staticPool;
static uint8_t bytes[MAX_RHPACKETLEN];
/**
* Constructor
*
@@ -94,8 +96,7 @@ PacketId generatePacketId()
static uint32_t i; // Note: trying to keep this in noinit didn't help for working across reboots
static bool didInit = false;
assert(sizeof(PacketId) == 4 || sizeof(PacketId) == 1); // only supported values
uint32_t numPacketId = sizeof(PacketId) == 1 ? UINT8_MAX : UINT32_MAX; // 0 is consider invalid
uint32_t numPacketId = UINT32_MAX;
if (!didInit) {
didInit = true;
@@ -191,7 +192,11 @@ void printBytes(const char *label, const uint8_t *p, size_t numbytes)
*/
ErrorCode Router::send(MeshPacket *p)
{
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal
if (p->to == nodeDB.getNodeNum()) {
LOG_ERROR("BUG! send() called with packet destined for local node!\n");
packetPool.release(p);
return Routing_Error_BAD_REQUEST;
} // should have already been handled by sendLocal
// Abort sending if we are violating the duty cycle
if (!config.lora.override_duty_cycle && myRegion->dutyCycle != 100) {
@@ -286,7 +291,6 @@ bool Router::cancelSending(NodeNum from, PacketId id)
*/
void Router::sniffReceived(const MeshPacket *p, const Routing *c)
{
LOG_DEBUG("FIXME-update-db Sniffing packet\n");
// FIXME, update nodedb here for any packet that passes through us
}
@@ -305,7 +309,6 @@ bool perhapsDecode(MeshPacket *p)
// Try to use this hash/channel pair
if (channels.decryptForHash(chIndex, p->channel)) {
// Try to decrypt the packet if we can
static uint8_t bytes[MAX_RHPACKETLEN];
size_t rawSize = p->encrypted.size;
assert(rawSize <= sizeof(bytes));
memcpy(bytes, p->encrypted.bytes,
@@ -325,14 +328,6 @@ bool perhapsDecode(MeshPacket *p)
p->which_payload_variant = MeshPacket_decoded_tag; // change type to decoded
p->channel = chIndex; // change to store the index instead of the hash
/*
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
LOG_DEBUG("\n\n** TEXT_MESSAGE_APP\n");
} else if (p->decoded.portnum == PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
LOG_DEBUG("\n\n** PortNum_TEXT_MESSAGE_COMPRESSED_APP\n");
}
*/
// Decompress if needed. jm
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_COMPRESSED_APP) {
// Decompress the payload
@@ -368,7 +363,6 @@ Routing_Error perhapsEncode(MeshPacket *p)
{
// If the packet is not yet encrypted, do so now
if (p->which_payload_variant == MeshPacket_decoded_tag) {
static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &Data_msg, &p->decoded);

View File

@@ -0,0 +1,67 @@
#include "ServerAPI.h"
#include "configuration.h"
#include <Arduino.h>
template<typename T>
ServerAPI<T>::ServerAPI(T &_client) : StreamAPI(&client), concurrency::OSThread("ServerAPI"), client(_client)
{
LOG_INFO("Incoming wifi connection\n");
}
template<typename T>
ServerAPI<T>::~ServerAPI()
{
client.stop();
}
template<typename T>
void ServerAPI<T>::close()
{
client.stop(); // drop tcp connection
StreamAPI::close();
}
/// Check the current underlying physical link to see if the client is currently connected
template<typename T>
bool ServerAPI<T>::checkIsConnected()
{
return client.connected();
}
template<class T>
int32_t ServerAPI<T>::runOnce()
{
if (client.connected()) {
return StreamAPI::runOncePart();
} else {
LOG_INFO("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run
return 0;
}
}
template<class T, class U>
APIServerPort<T, U>::APIServerPort(int port) : U(port), concurrency::OSThread("ApiServer") {}
template<class T, class U>
void APIServerPort<T, U>::init()
{
U::begin();
}
template<class T, class U>
int32_t APIServerPort<T, U>::runOnce()
{
auto client = U::available();
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
LOG_INFO("Force closing previous TCP connection\n");
delete openAPI;
}
openAPI = new T(client);
}
return 100; // only check occasionally for incoming connections
}

View File

@@ -1,21 +1,21 @@
#pragma once
#include "StreamAPI.h"
#include <WiFi.h>
/**
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
*/
class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
template<class T>
class ServerAPI : public StreamAPI, private concurrency::OSThread
{
private:
WiFiClient client;
T client;
public:
explicit WiFiServerAPI(WiFiClient &_client);
explicit ServerAPI(T &_client);
virtual ~WiFiServerAPI();
virtual ~ServerAPI();
/// override close to also shutdown the TCP link
virtual void close();
@@ -34,25 +34,21 @@ class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class WiFiServerPort : public WiFiServer, private concurrency::OSThread
template<class T, class U>
class APIServerPort : public U, private concurrency::OSThread
{
/** The currently open port
*
* FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
*/
WiFiServerAPI *openAPI = NULL;
T *openAPI = NULL;
public:
explicit WiFiServerPort(int port);
explicit APIServerPort(int port);
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() override;
};
void initApiServer(int port=4403);

View File

@@ -0,0 +1,25 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_WIFI
#include "WiFiServerAPI.h"
static WiFiServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new WiFiServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : ServerAPI(_client)
{
LOG_INFO("Incoming wifi connection\n");
}
WiFiServerPort::WiFiServerPort(int port) : APIServerPort(port) {}
#endif

View File

@@ -0,0 +1,25 @@
#pragma once
#include "ServerAPI.h"
#include <WiFi.h>
/**
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
*/
class WiFiServerAPI : public ServerAPI<WiFiClient>
{
public:
explicit WiFiServerAPI(WiFiClient &_client);
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class WiFiServerPort : public APIServerPort<WiFiServerAPI, WiFiServer>
{
public:
explicit WiFiServerPort(int port);
};
void initApiServer(int port=4403);

View File

@@ -0,0 +1,27 @@
#include "configuration.h"
#include <Arduino.h>
#if HAS_ETHERNET
#include "ethServerAPI.h"
static ethServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new ethServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
ethServerAPI::ethServerAPI(EthernetClient &_client) : ServerAPI(_client)
{
LOG_INFO("Incoming ethernet connection\n");
}
ethServerPort::ethServerPort(int port) : APIServerPort(port) {}
#endif

View File

@@ -0,0 +1,25 @@
#pragma once
#include "ServerAPI.h"
#include <RAK13800_W5100S.h>
/**
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
*/
class ethServerAPI : public ServerAPI<EthernetClient>
{
public:
explicit ethServerAPI(EthernetClient &_client);
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class ethServerPort : public APIServerPort<ethServerAPI, EthernetServer>
{
public:
explicit ethServerPort(int port);
};
void initApiServer(int port=4403);

View File

@@ -5,7 +5,7 @@
#include <SPI.h>
#include <RAK13800_W5100S.h>
#include "target_specific.h"
#include "mesh/eth/ethServerAPI.h"
#include "mesh/api/ethServerAPI.h"
#include "mqtt/MQTT.h"
#ifndef DISABLE_NTP

View File

@@ -1,82 +0,0 @@
#include "ethServerAPI.h"
#include "configuration.h"
#include <Arduino.h>
static ethServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new ethServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), concurrency::OSThread("ethServerAPI"), client(_client)
{
LOG_INFO("Incoming ethernet connection\n");
}
ethServerAPI::~ethServerAPI()
{
client.stop();
// FIXME - delete this if the client dropps the connection!
}
/// override close to also shutdown the TCP link
void ethServerAPI::close()
{
client.stop(); // drop tcp connection
StreamAPI::close();
}
/// Check the current underlying physical link to see if the client is currently connected
bool ethServerAPI::checkIsConnected()
{
return client.connected();
}
int32_t ethServerAPI::runOnce()
{
if (client.connected()) {
return StreamAPI::runOncePart();
} else {
LOG_INFO("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run
return 0;
}
}
/// If an api server is running, we try to spit out debug 'serial' characters there
void ethServerPort::debugOut(char c)
{
if (apiPort && apiPort->openAPI)
apiPort->openAPI->debugOut(c);
}
ethServerPort::ethServerPort(int port) : EthernetServer(port), concurrency::OSThread("ApiServer") {}
void ethServerPort::init()
{
begin();
}
int32_t ethServerPort::runOnce()
{
auto client = available();
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
LOG_WARN("Force closing previous TCP connection\n");
delete openAPI;
}
openAPI = new ethServerAPI(client);
}
return 100; // only check occasionally for incoming connections
}

View File

@@ -1,58 +0,0 @@
#pragma once
#include "StreamAPI.h"
#include <RAK13800_W5100S.h>
/**
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
*/
class ethServerAPI : public StreamAPI, private concurrency::OSThread
{
private:
EthernetClient client;
public:
explicit ethServerAPI(EthernetClient &_client);
virtual ~ethServerAPI();
/// override close to also shutdown the TCP link
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)
virtual void onConnectionChanged(bool connected) override {}
virtual int32_t runOnce() override; // Check for dropped client connections
/// Check the current underlying physical link to see if the client is currently connected
virtual bool checkIsConnected() override;
};
/**
* Listens for incoming connections and does accepts and creates instances of WiFiServerAPI as needed
*/
class ethServerPort : public EthernetServer, private concurrency::OSThread
{
/** The currently open port
*
* FIXME: We currently only allow one open TCP connection at a time, because we depend on the loop() call in this class to
* delegate to the worker. Once coroutines are implemented we can relax this restriction.
*/
ethServerAPI *openAPI = NULL;
public:
explicit ethServerPort(int port);
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() override;
};
void initApiServer(int port=4403);

View File

@@ -184,6 +184,7 @@ bool initWifi()
WiFi.onEvent(
[](WiFiEvent_t event, WiFiEventInfo_t info) {
LOG_WARN("WiFi lost connection. Reason: %d\n", info.wifi_sta_disconnected.reason);
/*

View File

@@ -1,82 +0,0 @@
#include "WiFiServerAPI.h"
#include "configuration.h"
#include <Arduino.h>
static WiFiServerPort *apiPort;
void initApiServer(int port)
{
// Start API server on port 4403
if (!apiPort) {
apiPort = new WiFiServerPort(port);
LOG_INFO("API server listening on TCP port %d\n", port);
apiPort->init();
}
}
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), concurrency::OSThread("WiFiServerAPI"), client(_client)
{
LOG_INFO("Incoming wifi connection\n");
}
WiFiServerAPI::~WiFiServerAPI()
{
client.stop();
// FIXME - delete this if the client dropps the connection!
}
/// override close to also shutdown the TCP link
void WiFiServerAPI::close()
{
client.stop(); // drop tcp connection
StreamAPI::close();
}
/// Check the current underlying physical link to see if the client is currently connected
bool WiFiServerAPI::checkIsConnected()
{
return client.connected();
}
int32_t WiFiServerAPI::runOnce()
{
if (client.connected()) {
return StreamAPI::runOncePart();
} else {
LOG_INFO("Client dropped connection, suspending API service\n");
enabled = false; // we no longer need to run
return 0;
}
}
/// 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);
}
WiFiServerPort::WiFiServerPort(int port) : WiFiServer(port), concurrency::OSThread("ApiServer") {}
void WiFiServerPort::init()
{
begin();
}
int32_t WiFiServerPort::runOnce()
{
auto client = available();
if (client) {
// Close any previous connection (see FIXME in header file)
if (openAPI) {
LOG_INFO("Force closing previous TCP connection\n");
delete openAPI;
}
openAPI = new WiFiServerAPI(client);
}
return 100; // only check occasionally for incoming connections
}

View File

@@ -549,10 +549,10 @@ AdminMessageHandleResult CannedMessageModule::handleAdminMessageForModule(const
void CannedMessageModule::handleGetCannedMessageModuleMessages(const MeshPacket &req, AdminMessage *response)
{
LOG_DEBUG("*** handleGetCannedMessageModuleMessages\n");
assert(req.decoded.want_response);
if(req.decoded.want_response) {
response->which_payload_variant = AdminMessage_get_canned_message_module_messages_response_tag;
strcpy(response->get_canned_message_module_messages_response, cannedMessageModuleConfig.messages);
} // Don't send anything if not instructed to. Better than asserting.
}

View File

@@ -347,10 +347,10 @@ AdminMessageHandleResult ExternalNotificationModule::handleAdminMessageForModule
void ExternalNotificationModule::handleGetRingtone(const MeshPacket &req, AdminMessage *response)
{
LOG_INFO("*** handleGetRingtone\n");
assert(req.decoded.want_response);
if(req.decoded.want_response) {
response->which_payload_variant = AdminMessage_get_ringtone_response_tag;
strcpy(response->get_ringtone_response, rtttlConfig.ringtone);
} // Don't send anything if not instructed to. Better than asserting.
}

View File

@@ -7,8 +7,6 @@
#include "configuration.h"
#include <Arduino.h>
#include <assert.h>
/*
SerialModule
A simple interface to send messages over the mesh network by sending strings

View File

@@ -8,8 +8,6 @@
#include "Router.h"
#include "FSCommon.h"
#include <assert.h>
#ifdef OLED_RU
#include "graphics/fonts/OLEDDisplayFontsRU.h"
#endif

View File

@@ -9,7 +9,6 @@
#include "gps/GeoCoord.h"
#include <Arduino.h>
#include <FSCommon.h>
//#include <assert.h>
/*
As a sender, I can send packets every n seconds. These packets include an incremented PacketID.

View File

@@ -392,7 +392,7 @@ bool StoreForwardModule::handleReceivedProtobuf(const MeshPacket &mp, StoreAndFo
break;
default:
assert(0); // unexpected state - FIXME, make an error code and reboot
assert(0); // unexpected state
}
return true; // There's no need for others to look at this message.
}

View File

@@ -42,19 +42,21 @@ class ESP32CryptoEngine : public CryptoEngine
virtual void encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
{
if (key.length > 0) {
uint8_t stream_block[16];
static uint8_t scratch[MAX_BLOCKSIZE];
size_t nc_off = 0;
LOG_DEBUG("ESP32 crypt fr=%x, num=%x, numBytes=%d!\n", fromNode, (uint32_t) packetId, numBytes);
initNonce(fromNode, packetId);
assert(numBytes <= MAX_BLOCKSIZE);
if (numBytes <= MAX_BLOCKSIZE) {
static uint8_t scratch[MAX_BLOCKSIZE];
uint8_t stream_block[16];
size_t nc_off = 0;
memcpy(scratch, bytes, numBytes);
memset(scratch + numBytes, 0,
sizeof(scratch) - numBytes); // Fill rest of buffer with zero (in case cypher looks at it)
auto res = mbedtls_aes_crypt_ctr(&aes, numBytes, &nc_off, nonce, stream_block, scratch, bytes);
assert(!res);
} else {
LOG_ERROR("Packet too large for crypto engine: %d. noop encryption!\n", numBytes);
}
}
}

View File

@@ -50,13 +50,9 @@ class CrossPlatformCryptoEngine : public CryptoEngine
virtual void encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
{
if (key.length > 0) {
//uint8_t stream_block[16];
static uint8_t scratch[MAX_BLOCKSIZE];
//size_t nc_off = 0;
// LOG_DEBUG("ESP32 encrypt!\n");
initNonce(fromNode, packetId);
assert(numBytes <= MAX_BLOCKSIZE);
if (numBytes <= MAX_BLOCKSIZE) {
static uint8_t scratch[MAX_BLOCKSIZE];
memcpy(scratch, bytes, numBytes);
memset(scratch + numBytes, 0,
sizeof(scratch) - numBytes); // Fill rest of buffer with zero (in case cypher looks at it)
@@ -64,6 +60,9 @@ class CrossPlatformCryptoEngine : public CryptoEngine
ctr->setIV(nonce, sizeof(nonce));
ctr->setCounterSize(4);
ctr->encrypt(bytes, scratch, numBytes);
} else {
LOG_ERROR("Packet too large for crypto engine: %d. noop encryption!\n", numBytes);
}
}
}

View File

@@ -230,7 +230,12 @@ void SimRadio::handleReceiveInterrupt(MeshPacket *p)
{
LOG_DEBUG("HANDLE RECEIVE INTERRUPT\n");
uint32_t xmitMsec;
assert(isReceiving);
if (!isReceiving) {
LOG_DEBUG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode\n");
return;
}
isReceiving = false;
// read the number of actually received bytes

View File

@@ -2,7 +2,7 @@
#include "RadioInterface.h"
#include "MeshPacketQueue.h"
#include "wifi/WiFiServerAPI.h"
#include "api/WiFiServerAPI.h"
#include <RadioLib.h>

View File

@@ -163,7 +163,7 @@ static void waitEnterSleep()
}
// Code that still needs to be moved into notifyObservers
Serial.flush(); // send all our characters before we stop cpu clock
console->flush(); // send all our characters before we stop cpu clock
setBluetoothEnable(false); // has to be off before calling light sleep
notifySleep.notifyObservers(NULL);

View File

@@ -3,7 +3,7 @@
extends = nrf52840_base
board = wiscore_rak4631
build_flags = ${nrf52840_base.build_flags} -Ivariants/rak4631 -D RAK_4631
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mqtt/>
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/rak4631> +<mesh/eth/> +<mesh/api/> +<mqtt/>
lib_deps =
${nrf52840_base.lib_deps}
${networking_base.lib_deps}