sforkowany z mirror/meshtastic-firmware
commit
7118200885
|
@ -31,5 +31,6 @@ jobs:
|
|||
run: platformio run -e heltec
|
||||
- name: Build for lora-relay-v1
|
||||
run: platformio run -e lora-relay-v1
|
||||
- name: Build for linux
|
||||
run: platformio run -e linux
|
||||
# Turn off linux for now
|
||||
#- name: Build for linux
|
||||
# run: platformio run -e linux
|
||||
|
|
|
@ -6,6 +6,8 @@ BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
|
|||
|
||||
nrfjprog --eraseall -f nrf52
|
||||
|
||||
# to get tool run "sudo apt-get install srecord"
|
||||
|
||||
# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid
|
||||
# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
|
||||
# first 4 bytes should be 0x01 to indicate valid app image
|
||||
|
@ -14,7 +16,7 @@ echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
|
|||
srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel
|
||||
|
||||
echo Generating merged hex file
|
||||
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-125-gf38f8f4-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
|
||||
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-213-gf67f592-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
|
||||
|
||||
echo Telling bootloader app region is valid and telling CPU to run
|
||||
nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset
|
||||
|
|
|
@ -4,6 +4,8 @@ You probably don't care about this section - skip to the next one.
|
|||
|
||||
## 1.2 cleanup & multichannel support:
|
||||
|
||||
* cdcacm bug on nrf52: emittx thinks it emitted but client sees nothing. works again later
|
||||
* nrf52: segger logs have errors in formatting that should be impossible (because not going through serial, try stalling on segger)
|
||||
* DONE call RouterPlugin for *all* packets - not just Router packets
|
||||
* DONE generate channel hash from the name of the channel+the psk (not just one or the other)
|
||||
* DONE send a hint that can be used to select which channel to try and hash against with each message
|
||||
|
@ -40,6 +42,10 @@ You probably don't care about this section - skip to the next one.
|
|||
* DONE warn in android app about unset regions
|
||||
* DONE use set-channel from android
|
||||
* DONE add gui in android app for setting region
|
||||
* DONE clean up python channel usage
|
||||
* DONE use bindToChannel to limit admin access for remote nodes
|
||||
* DONE move channels and radio config out of device settings
|
||||
* test remote info and remote settings changes
|
||||
* make python tests more exhaustive
|
||||
* pick default random admin key
|
||||
* exclude admin channels from URL?
|
||||
|
@ -51,6 +57,7 @@ You probably don't care about this section - skip to the next one.
|
|||
* stress test multi channel
|
||||
* investigate @mc-hamster report of heap corruption
|
||||
* DONE use set-user from android
|
||||
* generalize the concept of "shortstrings" use it for both PSKs and well known channel names. Possibly use a ShortString class.
|
||||
* use portuino TCP connection to debug with python API
|
||||
* document the relationship between want_response (indicating remote node received it) and want_ack (indicating that this message should be sent reliably - and also get acks from the first rx node and naks if it is never delivered)
|
||||
* DONE android should stop fetching channels once we've reached our first empty channel definition (hasSettings == true)
|
||||
|
@ -80,6 +87,8 @@ You probably don't care about this section - skip to the next one.
|
|||
* DONE move setCrypto call into packet send and packet decode code
|
||||
* implement 'small location diffs' change
|
||||
* move battery level out of position?
|
||||
* consider "A special exception (FIXME, not sure if this is a good idea) - packets that arrive on the local interface
|
||||
are allowed on any channel (this lets the local user do anything)." Probably by adding a "secure_local_interface" settings bool.
|
||||
* DOUBLE CHECK android app can still upgrade 1.1 and 1.0 loads
|
||||
|
||||
eink:
|
||||
|
|
|
@ -45,13 +45,6 @@ build_flags = -Wno-missing-field-initializers
|
|||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
|
||||
; leave this commented out to avoid breaking Windows
|
||||
;upload_port = /dev/ttyUSB0
|
||||
;monitor_port = /dev/ttyUSB0
|
||||
|
||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||
;monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
|
||||
; the default is esptool
|
||||
; upload_protocol = esp-prog
|
||||
|
||||
|
@ -74,7 +67,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#2f106146071fc7bc620e1e8d4b88dc4e0266ce39
|
||||
https://github.com/meshtastic/arduino-fsm.git#55c47b6cded91645aff05a27b6e5821d8d0f64be
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||
https://github.com/meshtastic/RadioLib.git#07de964e929238949035fb0d5887026a3058df1a
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#f0f47067ef2f67c856475933188251c1ef615e79
|
||||
|
@ -118,6 +111,13 @@ lib_ignore = segger_rtt
|
|||
platform_packages =
|
||||
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#352c8ea7cb73f10433ed139f34251979c470ad56
|
||||
|
||||
; leave this commented out to avoid breaking Windows
|
||||
upload_port = /dev/ttyUSB0
|
||||
;monitor_port = /dev/ttyUSB0
|
||||
|
||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||
;monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
|
@ -206,7 +206,8 @@ debug_port = :2331
|
|||
# Note: the ARGUMENTS MUST BE on multiple lines. Otherwise platformio/commands/debug/helpers.py misparses everything into the "executable"
|
||||
# attribute and leaves "arguments" empty
|
||||
# /home/kevinh/.platformio/packages/tool-jlink/JLinkGDBServerCLExe
|
||||
debug_server =
|
||||
# This doesn't work yet, so not using for now
|
||||
disabled_debug_server =
|
||||
/usr/bin/JLinkGDBServerCLExe
|
||||
-singlerun
|
||||
-if
|
||||
|
|
2
proto
2
proto
|
@ -1 +1 @@
|
|||
Subproject commit e56f2770c33216ba94f289e2fb7f0b2dfd33aca2
|
||||
Subproject commit e63f9713f73ea5c9308b7822602ea75f506b6b00
|
|
@ -279,7 +279,7 @@ void setup()
|
|||
concurrency::hasBeenSetup = true;
|
||||
|
||||
#ifdef SEGGER_STDOUT_CH
|
||||
auto mode = true ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
|
||||
auto mode = false ? SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL : SEGGER_RTT_MODE_NO_BLOCK_TRIM;
|
||||
#ifdef NRF52840_XXAA
|
||||
auto buflen = 4096; // this board has a fair amount of ram
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* 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;
|
||||
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;
|
||||
|
||||
//DEBUG_MSG("memtest read=%d, write=%d\n", doRead, doWrite);
|
||||
|
||||
if (doWrite) {
|
||||
//DEBUG_MSG("writing\n");
|
||||
for (addr = start, val = pattern; addr < end; addr++) {
|
||||
*addr = val;
|
||||
val += incr;
|
||||
}
|
||||
}
|
||||
|
||||
if (doRead) {
|
||||
//DEBUG_MSG("reading\n");
|
||||
for (addr = start, val = pattern; addr < end; addr++) {
|
||||
readback = *addr;
|
||||
if (readback != val) {
|
||||
DEBUG_MSG("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++;
|
||||
}
|
|
@ -161,8 +161,8 @@ int16_t Channels::setCrypto(ChannelIndex chIndex)
|
|||
|
||||
void Channels::initDefaults()
|
||||
{
|
||||
devicestate.channels_count = MAX_NUM_CHANNELS;
|
||||
for (int i = 0; i < devicestate.channels_count; i++)
|
||||
channelFile.channels_count = MAX_NUM_CHANNELS;
|
||||
for (int i = 0; i < channelFile.channels_count; i++)
|
||||
fixupChannel(i);
|
||||
initDefaultChannel(0);
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void Channels::initDefaults()
|
|||
void Channels::onConfigChanged()
|
||||
{
|
||||
// Make sure the phone hasn't mucked anything up
|
||||
for (int i = 0; i < devicestate.channels_count; i++) {
|
||||
for (int i = 0; i < channelFile.channels_count; i++) {
|
||||
Channel &ch = fixupChannel(i);
|
||||
|
||||
if (ch.role == Channel_Role_PRIMARY)
|
||||
|
@ -180,8 +180,8 @@ void Channels::onConfigChanged()
|
|||
|
||||
Channel &Channels::getByIndex(ChannelIndex chIndex)
|
||||
{
|
||||
assert(chIndex < devicestate.channels_count);
|
||||
Channel *ch = devicestate.channels + chIndex;
|
||||
assert(chIndex < channelFile.channels_count);
|
||||
Channel *ch = channelFile.channels + chIndex;
|
||||
return *ch;
|
||||
}
|
||||
|
||||
|
@ -192,8 +192,8 @@ void Channels::setChannel(const Channel &c)
|
|||
// if this is the new primary, demote any existing roles
|
||||
if (c.role == Channel_Role_PRIMARY)
|
||||
for (int i = 0; i < getNumChannels(); i++)
|
||||
if (devicestate.channels[i].role == Channel_Role_PRIMARY)
|
||||
devicestate.channels[i].role = Channel_Role_SECONDARY;
|
||||
if (channelFile.channels[i].role == Channel_Role_PRIMARY)
|
||||
channelFile.channels[i].role = Channel_Role_SECONDARY;
|
||||
|
||||
old = c; // slam in the new settings/role
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class Channels
|
|||
/** The index of the primary channel */
|
||||
ChannelIndex getPrimaryIndex() const { return primaryIndex; }
|
||||
|
||||
ChannelIndex getNumChannels() { return devicestate.channels_count; }
|
||||
ChannelIndex getNumChannels() { return channelFile.channels_count; }
|
||||
|
||||
/**
|
||||
* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "MeshPlugin.h"
|
||||
#include "Channels.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "plugins/RoutingPlugin.h"
|
||||
#include <assert.h>
|
||||
|
||||
std::vector<MeshPlugin *> *MeshPlugin::plugins;
|
||||
|
@ -11,7 +13,7 @@ const MeshPacket *MeshPlugin::currentRequest;
|
|||
* If any of the current chain of plugins has already sent a reply, it will be here. This is useful to allow
|
||||
* the RoutingPlugin to avoid sending redundant acks
|
||||
*/
|
||||
MeshPacket *MeshPlugin::currentReply;
|
||||
MeshPacket *MeshPlugin::currentReply;
|
||||
|
||||
MeshPlugin::MeshPlugin(const char *_name) : name(_name)
|
||||
{
|
||||
|
@ -46,8 +48,15 @@ void MeshPlugin::callPlugins(const MeshPacket &mp)
|
|||
|
||||
pi.currentRequest = ∓
|
||||
|
||||
// We only call plugins that are interested in the packet (and the message is destined to us or we are promiscious)
|
||||
bool wantsPacket = (pi.isPromiscuous || toUs) && pi.wantPacket(&mp);
|
||||
/// received channel
|
||||
auto ch = channels.getByIndex(mp.channel);
|
||||
assert(ch.has_settings);
|
||||
|
||||
/// Is the channel this packet arrived on acceptable? (security check)
|
||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (strcmp(ch.settings.name, pi.boundChannel) == 0);
|
||||
|
||||
/// We only call plugins that are interested in the packet (and the message is destined to us or we are promiscious)
|
||||
bool wantsPacket = rxChannelOk && (pi.isPromiscuous || toUs) && pi.wantPacket(&mp);
|
||||
// DEBUG_MSG("Plugin %s wantsPacket=%d\n", pi.name, wantsPacket);
|
||||
if (wantsPacket) {
|
||||
pluginFound = true;
|
||||
|
@ -76,10 +85,17 @@ void MeshPlugin::callPlugins(const MeshPacket &mp)
|
|||
pi.currentRequest = NULL;
|
||||
}
|
||||
|
||||
if(currentReply) {
|
||||
DEBUG_MSG("Sending response\n");
|
||||
service.sendToMesh(currentReply);
|
||||
currentReply = NULL;
|
||||
if (mp.decoded.want_response && toUs) {
|
||||
if (currentReply) {
|
||||
DEBUG_MSG("Sending response\n");
|
||||
service.sendToMesh(currentReply);
|
||||
currentReply = NULL;
|
||||
}
|
||||
else {
|
||||
// No one wanted to reply to this requst, tell the requster that happened
|
||||
DEBUG_MSG("No one responded, send a nak\n");
|
||||
routingPlugin->sendAckNak(Routing_Error_NO_RESPONSE, getFrom(&mp), mp.id, mp.channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pluginFound)
|
||||
|
@ -95,7 +111,7 @@ void MeshPlugin::sendResponse(const MeshPacket &req)
|
|||
auto r = allocReply();
|
||||
if (r) {
|
||||
setReplyTo(r, req);
|
||||
currentReply = r;
|
||||
currentReply = r;
|
||||
} else {
|
||||
// Ignore - this is now expected behavior for routing plugin (because it ignores some replies)
|
||||
// DEBUG_MSG("WARNING: Client requested response but this plugin did not provide\n");
|
||||
|
@ -109,10 +125,11 @@ void setReplyTo(MeshPacket *p, const MeshPacket &to)
|
|||
{
|
||||
assert(p->which_payloadVariant == MeshPacket_decoded_tag); // Should already be set by now
|
||||
p->to = getFrom(&to);
|
||||
p->channel = to.channel; // Use the same channel that the request came in on
|
||||
|
||||
// No need for an ack if we are just delivering locally (it just generates an ignored ack)
|
||||
p->want_ack = (to.from != 0) ? to.want_ack : false;
|
||||
if(p->priority == MeshPacket_Priority_UNSET)
|
||||
if (p->priority == MeshPacket_Priority_UNSET)
|
||||
p->priority = MeshPacket_Priority_RELIABLE;
|
||||
p->decoded.request_id = to.id;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "mesh/MeshTypes.h"
|
||||
#include <vector>
|
||||
#include <OLEDDisplay.h>
|
||||
#include <OLEDDisplayUi.h>
|
||||
#include <vector>
|
||||
/** A baseclass for any mesh "plugin".
|
||||
*
|
||||
* A plugin allows you to add new features to meshtastic device code, without needing to know messaging details.
|
||||
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
class MeshPlugin
|
||||
{
|
||||
static std::vector<MeshPlugin *> *plugins;
|
||||
static std::vector<MeshPlugin *> *plugins;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
|
@ -37,16 +37,24 @@ class MeshPlugin
|
|||
protected:
|
||||
const char *name;
|
||||
|
||||
/* Most plugins only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific recipient)
|
||||
But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those plugins can set this to
|
||||
true and their handleReceived() will be called for every packet.
|
||||
/* Most plugins only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific
|
||||
recipient) But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those
|
||||
plugins can set this to true and their handleReceived() will be called for every packet.
|
||||
*/
|
||||
bool isPromiscuous = false;
|
||||
|
||||
/** If a bound channel name is set, we will only accept received packets that come in on that channel.
|
||||
* A special exception (FIXME, not sure if this is a good idea) - packets that arrive on the local interface
|
||||
* are allowed on any channel (this lets the local user do anything).
|
||||
*
|
||||
* We will send responses on the same channel that the request arrived on.
|
||||
*/
|
||||
const char *boundChannel = NULL;
|
||||
|
||||
/**
|
||||
* If this plugin is currently handling a request currentRequest will be preset
|
||||
* to the packet with the request. This is mostly useful for reply handlers.
|
||||
*
|
||||
*
|
||||
* Note: this can be static because we are guaranteed to be processing only one
|
||||
* plugin at a time.
|
||||
*/
|
||||
|
@ -78,16 +86,13 @@ class MeshPlugin
|
|||
*/
|
||||
virtual bool wantUIFrame() { return false; }
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* If any of the current chain of plugins has already sent a reply, it will be here. This is useful to allow
|
||||
* If any of the current chain of plugins has already sent a reply, it will be here. This is useful to allow
|
||||
* the RoutingPlugin to avoid sending redundant acks
|
||||
*/
|
||||
static MeshPacket *currentReply;
|
||||
friend class ReliableRouter;
|
||||
friend class ReliableRouter;
|
||||
|
||||
/** 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. This method calls allocReply()
|
||||
|
@ -96,7 +101,7 @@ class MeshPlugin
|
|||
void sendResponse(const MeshPacket &req);
|
||||
};
|
||||
|
||||
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
|
||||
/** set the destination and packet parameters of packet p intended as a reply to a particular "to" packet
|
||||
* This ensures that if the request packet was sent reliably, the reply is sent that way as well.
|
||||
*/
|
||||
*/
|
||||
void setReplyTo(MeshPacket *p, const MeshPacket &to);
|
|
@ -104,7 +104,7 @@ bool MeshService::reloadConfig()
|
|||
// This will also update the region as needed
|
||||
bool didReset = nodeDB.resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||
|
||||
configChanged.notifyObservers(NULL);
|
||||
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
|
||||
nodeDB.saveToDisk();
|
||||
|
||||
return didReset;
|
||||
|
|
|
@ -30,7 +30,8 @@ NodeDB nodeDB;
|
|||
// we have plenty of ram so statically alloc this tempbuf (for now)
|
||||
EXT_RAM_ATTR DeviceState devicestate;
|
||||
MyNodeInfo &myNodeInfo = devicestate.my_node;
|
||||
RadioConfig &radioConfig = devicestate.radio;
|
||||
RadioConfig radioConfig;
|
||||
ChannelFile channelFile;
|
||||
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
||||
|
@ -67,10 +68,11 @@ NodeNum displayedNodeNum;
|
|||
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
|
||||
|
||||
/**
|
||||
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on the local node.
|
||||
* If from is zero this function returns our node number instead
|
||||
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
||||
* the local node. If from is zero this function returns our node number instead
|
||||
*/
|
||||
NodeNum getFrom(const MeshPacket *p) {
|
||||
NodeNum getFrom(const MeshPacket *p)
|
||||
{
|
||||
return (p->from == 0) ? nodeDB.getNodeNum() : p->from;
|
||||
}
|
||||
|
||||
|
@ -84,7 +86,7 @@ bool NodeDB::resetRadioConfig()
|
|||
DEBUG_MSG("Performing factory reset!\n");
|
||||
installDefaultDeviceState();
|
||||
didFactoryReset = true;
|
||||
} else if (devicestate.channels_count == 0) {
|
||||
} else if (channelFile.channels_count == 0) {
|
||||
DEBUG_MSG("Setting default channel and radio preferences!\n");
|
||||
|
||||
channels.initDefaults();
|
||||
|
@ -117,6 +119,18 @@ bool NodeDB::resetRadioConfig()
|
|||
return didFactoryReset;
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultRadioConfig()
|
||||
{
|
||||
memset(&radioConfig, 0, sizeof(radioConfig));
|
||||
radioConfig.has_preferences = true;
|
||||
resetRadioConfig();
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultChannels()
|
||||
{
|
||||
memset(&channelFile, 0, sizeof(channelFile));
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultDeviceState()
|
||||
{
|
||||
// We try to preserve the region setting because it will really bum users out if we discard it
|
||||
|
@ -129,14 +143,11 @@ void NodeDB::installDefaultDeviceState()
|
|||
|
||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||
devicestate.has_my_node = true;
|
||||
devicestate.has_radio = true;
|
||||
devicestate.has_owner = true;
|
||||
devicestate.radio.has_preferences = true;
|
||||
devicestate.node_db_count = 0;
|
||||
devicestate.version = DEVICESTATE_CUR_VER;
|
||||
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
||||
|
||||
resetRadioConfig();
|
||||
|
||||
// default to no GPS, until one has been found by probing
|
||||
myNodeInfo.has_gps = false;
|
||||
myNodeInfo.message_timeout_msec = FLOOD_EXPIRE_TIME;
|
||||
|
@ -158,6 +169,9 @@ void NodeDB::installDefaultDeviceState()
|
|||
radioConfig.preferences.region = oldRegionCode;
|
||||
if (oldRegion.length()) // If the old style region was set, try to keep it up-to-date
|
||||
strcpy(myNodeInfo.region, oldRegion.c_str());
|
||||
|
||||
installDefaultChannels();
|
||||
installDefaultRadioConfig();
|
||||
}
|
||||
|
||||
void NodeDB::init()
|
||||
|
@ -186,12 +200,16 @@ void NodeDB::init()
|
|||
info->user = owner;
|
||||
info->has_user = true;
|
||||
|
||||
// removed from 1.2 (though we do use old values if found)
|
||||
// We set these _after_ loading from disk - because they come from the build and are more trusted than
|
||||
// what is stored in flash
|
||||
if (xstr(HW_VERSION)[0])
|
||||
strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region));
|
||||
else
|
||||
DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag
|
||||
//if (xstr(HW_VERSION)[0])
|
||||
// strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region));
|
||||
// else DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag
|
||||
|
||||
// DEBUG_MSG("legacy region %d\n", devicestate.legacyRadio.preferences.region);
|
||||
if(radioConfig.preferences.region == RegionCode_Unset)
|
||||
radioConfig.preferences.region = devicestate.legacyRadio.preferences.region;
|
||||
|
||||
// Check for the old style of region code strings, if found, convert to the new enum.
|
||||
// Those strings will look like "1.0-EU433"
|
||||
|
@ -209,8 +227,7 @@ void NodeDB::init()
|
|||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
|
||||
DEBUG_MSG("legacy_region=%s, region=%d, NODENUM=0x%x, dbsize=%d\n", myNodeInfo.region, radioConfig.preferences.region,
|
||||
myNodeInfo.my_node_num, *numNodes);
|
||||
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", radioConfig.preferences.region, myNodeInfo.my_node_num, *numNodes);
|
||||
}
|
||||
|
||||
// We reserve a few nodenums for future use
|
||||
|
@ -240,84 +257,134 @@ void NodeDB::pickNewNodeNum()
|
|||
myNodeInfo.my_node_num = r;
|
||||
}
|
||||
|
||||
const char *preffile = "/db.proto";
|
||||
const char *preftmp = "/db.proto.tmp";
|
||||
static const char *preffileOld = "/db.proto";
|
||||
static const char *preffile = "/prefs/db.proto";
|
||||
static const char *radiofile = "/prefs/radio.proto";
|
||||
static const char *channelfile = "/prefs/channels.proto";
|
||||
// const char *preftmp = "/db.proto.tmp";
|
||||
|
||||
void NodeDB::loadFromDisk()
|
||||
/** Load a protobuf from a file, return true for success */
|
||||
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
||||
{
|
||||
#ifdef FS
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
|
||||
auto f = FS.open(preffile);
|
||||
auto f = FS.open(filename);
|
||||
|
||||
// FIXME, temporary hack until every node in the universe is 1.2 or later - look for prefs in the old location (so we can
|
||||
// preserve region)
|
||||
if (!f && filename == preffile) {
|
||||
filename = preffileOld;
|
||||
f = FS.open(filename);
|
||||
}
|
||||
|
||||
bool okay = false;
|
||||
if (f) {
|
||||
DEBUG_MSG("Loading saved preferences\n");
|
||||
pb_istream_t stream = {&readcb, &f, DeviceState_size};
|
||||
DEBUG_MSG("Loading %s\n", filename);
|
||||
pb_istream_t stream = {&readcb, &f, protoSize};
|
||||
|
||||
// DEBUG_MSG("Preload channel name=%s\n", channelSettings.name);
|
||||
|
||||
memset(&devicestate, 0, sizeof(devicestate));
|
||||
if (!pb_decode(&stream, DeviceState_fields, &devicestate)) {
|
||||
memset(dest_struct, 0, objSize);
|
||||
if (!pb_decode(&stream, fields, dest_struct)) {
|
||||
DEBUG_MSG("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
|
||||
// FIXME - report failure to phone
|
||||
} else {
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: devicestate is old, discarding\n");
|
||||
installDefaultDeviceState();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved preferences version %d\n", devicestate.version);
|
||||
}
|
||||
|
||||
// DEBUG_MSG("Postload channel name=%s\n", channelSettings.name);
|
||||
okay = true;
|
||||
}
|
||||
|
||||
f.close();
|
||||
} else {
|
||||
DEBUG_MSG("No saved preferences found\n");
|
||||
DEBUG_MSG("No %s preferences found\n", filename);
|
||||
}
|
||||
|
||||
#else
|
||||
DEBUG_MSG("ERROR: Filesystem not implemented\n");
|
||||
#endif
|
||||
return okay;
|
||||
}
|
||||
|
||||
void NodeDB::loadFromDisk()
|
||||
{
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
if (!loadProto(preffile, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate)) {
|
||||
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: devicestate %d is old, discarding\n", devicestate.version);
|
||||
installDefaultDeviceState();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved preferences version %d\n", devicestate.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig)) {
|
||||
installDefaultRadioConfig(); // Our in RAM copy might now be corrupt
|
||||
}
|
||||
|
||||
if (!loadProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) {
|
||||
installDefaultChannels(); // Our in RAM copy might now be corrupt
|
||||
}
|
||||
}
|
||||
|
||||
/** Save a protobuf from a file, return true for success */
|
||||
bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct)
|
||||
{
|
||||
#ifdef FS
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
String filenameTmp = filename;
|
||||
filenameTmp += ".tmp";
|
||||
auto f = FS.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||
bool okay = false;
|
||||
if (f) {
|
||||
DEBUG_MSG("Saving %s\n", filename);
|
||||
pb_ostream_t stream = {&writecb, &f, protoSize};
|
||||
|
||||
if (!pb_encode(&stream, fields, dest_struct)) {
|
||||
DEBUG_MSG("Error: can't encode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
} else {
|
||||
okay = true;
|
||||
}
|
||||
|
||||
f.close();
|
||||
|
||||
// brief window of risk here ;-)
|
||||
if (!FS.remove(filename))
|
||||
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
||||
if (!FS.rename(filenameTmp.c_str(), filename))
|
||||
DEBUG_MSG("Error: can't rename new pref file\n");
|
||||
} else {
|
||||
DEBUG_MSG("Can't write prefs\n");
|
||||
}
|
||||
#else
|
||||
DEBUG_MSG("ERROR: Filesystem not implemented\n");
|
||||
#endif
|
||||
return okay;
|
||||
}
|
||||
|
||||
void NodeDB::saveChannelsToDisk()
|
||||
{
|
||||
if (!devicestate.no_save) {
|
||||
#ifdef FS
|
||||
FS.mkdir("/prefs");
|
||||
#endif
|
||||
saveProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeDB::saveToDisk()
|
||||
{
|
||||
#ifdef FS
|
||||
if (!devicestate.no_save) {
|
||||
auto f = FS.open(preftmp, FILE_O_WRITE);
|
||||
if (f) {
|
||||
DEBUG_MSG("Writing preferences\n");
|
||||
#ifdef FS
|
||||
FS.mkdir("/prefs");
|
||||
#endif
|
||||
bool okay = saveProto(preffile, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
|
||||
okay &= saveProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig);
|
||||
saveChannelsToDisk();
|
||||
|
||||
pb_ostream_t stream = {&writecb, &f, SIZE_MAX, 0};
|
||||
|
||||
// DEBUG_MSG("Presave channel name=%s\n", channelSettings.name);
|
||||
|
||||
devicestate.version = DEVICESTATE_CUR_VER;
|
||||
if (!pb_encode(&stream, DeviceState_fields, &devicestate)) {
|
||||
DEBUG_MSG("Error: can't write protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
// FIXME - report failure to phone
|
||||
|
||||
f.close();
|
||||
} else {
|
||||
// Success - replace the old file
|
||||
f.close();
|
||||
|
||||
// brief window of risk here ;-)
|
||||
if (!FS.remove(preffile))
|
||||
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
||||
if (!FS.rename(preftmp, preffile))
|
||||
DEBUG_MSG("Error: can't rename new pref file\n");
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("ERROR: can't write prefs\n"); // FIXME report to app
|
||||
}
|
||||
// remove any pre 1.2 pref files, turn on after 1.2 is in beta
|
||||
// if(okay) FS.remove(preffileOld);
|
||||
} else {
|
||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
||||
}
|
||||
#else
|
||||
DEBUG_MSG("ERROR filesystem not implemented\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
const NodeInfo *NodeDB::readNextInfo()
|
||||
|
@ -370,7 +437,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p)
|
|||
// recorded based on the packet rxTime
|
||||
if (!info->position.time && p.time)
|
||||
info->position.time = p.time;
|
||||
if(p.battery_level)
|
||||
if (p.battery_level)
|
||||
info->position.battery_level = p.battery_level;
|
||||
if (p.latitude_i || p.longitude_i) {
|
||||
info->position.latitude_i = p.latitude_i;
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
#include "mesh-pb-constants.h"
|
||||
|
||||
extern DeviceState devicestate;
|
||||
extern ChannelFile channelFile;
|
||||
extern MyNodeInfo &myNodeInfo;
|
||||
extern RadioConfig &radioConfig;
|
||||
extern RadioConfig radioConfig;
|
||||
extern User &owner;
|
||||
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
|
@ -42,7 +43,7 @@ class NodeDB
|
|||
void init();
|
||||
|
||||
/// write to flash
|
||||
void saveToDisk();
|
||||
void saveToDisk(), saveChannelsToDisk();
|
||||
|
||||
/** Reinit radio config if needed, because either:
|
||||
* a) sometimes a buggy android app might send us bogus settings or
|
||||
|
@ -117,7 +118,7 @@ class NodeDB
|
|||
void loadFromDisk();
|
||||
|
||||
/// Reinit device state from scratch (not loading from disk)
|
||||
void installDefaultDeviceState();
|
||||
void installDefaultDeviceState(), installDefaultRadioConfig(), installDefaultChannels();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -156,7 +156,6 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||
state = STATE_SEND_PACKETS;
|
||||
break;
|
||||
|
||||
case STATE_LEGACY: // Treat as the same as send packets
|
||||
case STATE_SEND_PACKETS:
|
||||
// Do we have a message from the mesh?
|
||||
if (packetForPhone) {
|
||||
|
@ -208,7 +207,6 @@ bool PhoneAPI::available()
|
|||
case STATE_SEND_COMPLETE_ID:
|
||||
return true;
|
||||
|
||||
case STATE_LEGACY: // Treat as the same as send packets
|
||||
case STATE_SEND_PACKETS: {
|
||||
// Try to pull a new packet from the service (if we haven't already)
|
||||
if (!packetForPhone)
|
||||
|
@ -236,7 +234,7 @@ int PhoneAPI::onNotify(uint32_t newValue)
|
|||
checkConnectionTimeout(); // a handy place to check if we've heard from the phone (since the BLE version doesn't call this
|
||||
// from idle)
|
||||
|
||||
if (state == STATE_SEND_PACKETS || state == STATE_LEGACY) {
|
||||
if (state == STATE_SEND_PACKETS) {
|
||||
DEBUG_MSG("Telling client we have new packets %u\n", newValue);
|
||||
onNowHasData(newValue);
|
||||
} else
|
||||
|
|
|
@ -20,7 +20,7 @@ class PhoneAPI
|
|||
: public Observer<uint32_t> // FIXME, we shouldn't be inheriting from Observer, instead use CallbackObserver as a member
|
||||
{
|
||||
enum State {
|
||||
STATE_LEGACY, // (no longer used) old default state - until Android apps are all updated, uses the old BLE API
|
||||
STATE_UNUSED, // (no longer used) old default state - until Android apps are all updated, uses the old BLE API
|
||||
STATE_SEND_NOTHING, // (Eventual) Initial state, don't send anything until the client starts asking for config
|
||||
STATE_SEND_MY_INFO, // send our my info record
|
||||
// STATE_SEND_RADIO, // in 1.2 we now send this as a regular mesh packet
|
||||
|
|
|
@ -153,6 +153,9 @@ void printPacket(const char *prefix, const MeshPacket *p)
|
|||
if (s.dest != 0)
|
||||
DEBUG_MSG(" dest=%08x", s.dest);
|
||||
|
||||
if(s.request_id)
|
||||
DEBUG_MSG(" requestId=%0x", s.request_id);
|
||||
|
||||
/* now inside Data and therefore kinda opaque
|
||||
if (s.which_ackVariant == SubPacket_success_id_tag)
|
||||
DEBUG_MSG(" successId=%08x", s.ackVariant.success_id);
|
||||
|
|
|
@ -38,7 +38,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p)
|
|||
DEBUG_MSG("generating implicit ack\n");
|
||||
// NOTE: we do NOT check p->wantAck here because p is the INCOMING rebroadcast and that packet is not expected to be
|
||||
// marked as wantAck
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id);
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,9 +65,9 @@ void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
|||
// - not DSR routing)
|
||||
if (p->want_ack) {
|
||||
if (MeshPlugin::currentReply)
|
||||
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack");
|
||||
DEBUG_MSG("Someone else has replied to this message, no need for a 2nd ack\n");
|
||||
else
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id);
|
||||
sendAckNak(Routing_Error_NONE, getFrom(p), p->id, p->channel);
|
||||
}
|
||||
|
||||
// We consider an ack to be either a !routing packet with a request ID or a routing packet with !error
|
||||
|
@ -166,7 +166,7 @@ int32_t ReliableRouter::doRetransmissions()
|
|||
if (p.numRetransmissions == 0) {
|
||||
DEBUG_MSG("Reliable send failed, returning a nak for fr=0x%x,to=0x%x,id=0x%x\n", p.packet->from, p.packet->to,
|
||||
p.packet->id);
|
||||
sendAckNak(Routing_Error_MAX_RETRANSMIT, getFrom(p.packet), p.packet->id);
|
||||
sendAckNak(Routing_Error_MAX_RETRANSMIT, getFrom(p.packet), p.packet->id, p.packet->channel);
|
||||
// Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which
|
||||
// allows the DSR version to still be able to look at the PendingPacket
|
||||
stopRetransmission(it->first);
|
||||
|
|
|
@ -103,15 +103,15 @@ MeshPacket *Router::allocForSending()
|
|||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom)
|
||||
void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex)
|
||||
{
|
||||
routingPlugin->sendAckNak(err, to, idFrom);
|
||||
routingPlugin->sendAckNak(err, to, idFrom, chIndex);
|
||||
}
|
||||
|
||||
void Router::abortSendAndNak(Routing_Error err, MeshPacket *p)
|
||||
{
|
||||
DEBUG_MSG("Error=%d, returning NAK and dropping packet.\n", err);
|
||||
sendAckNak(Routing_Error_NO_INTERFACE, getFrom(p), p->id);
|
||||
sendAckNak(Routing_Error_NO_INTERFACE, getFrom(p), p->id, p->channel);
|
||||
packetPool.release(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "PointerQueue.h"
|
||||
#include "RadioInterface.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "Channels.h"
|
||||
|
||||
/**
|
||||
* A mesh aware router that supports multiple interfaces.
|
||||
|
@ -106,7 +107,7 @@ class Router : protected concurrency::OSThread
|
|||
/**
|
||||
* Send an ack or a nak packet back towards whoever sent idFrom
|
||||
*/
|
||||
void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom);
|
||||
void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -71,12 +71,18 @@ void StreamAPI::writeStream()
|
|||
void StreamAPI::emitTxBuffer(size_t len)
|
||||
{
|
||||
if (len != 0) {
|
||||
DEBUG_MSG("emit tx %d\n", len);
|
||||
txBuf[0] = START1;
|
||||
txBuf[1] = START2;
|
||||
txBuf[2] = (len >> 8) & 0xff;
|
||||
txBuf[3] = len & 0xff;
|
||||
|
||||
stream->write(txBuf, len + HEADER_LEN);
|
||||
auto totalLen = len + HEADER_LEN;
|
||||
stream->write(txBuf, totalLen);
|
||||
/* for(size_t i = 0; i < totalLen; i++) {
|
||||
stream->write(txBuf[i]);
|
||||
// stream->flush();
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ typedef struct _AdminMessage {
|
|||
RadioConfig get_radio_response;
|
||||
uint32_t get_channel_request;
|
||||
Channel get_channel_response;
|
||||
bool confirm_set_channel;
|
||||
bool confirm_set_radio;
|
||||
};
|
||||
} AdminMessage;
|
||||
|
||||
|
@ -43,6 +45,8 @@ extern "C" {
|
|||
#define AdminMessage_get_radio_response_tag 5
|
||||
#define AdminMessage_get_channel_request_tag 6
|
||||
#define AdminMessage_get_channel_response_tag 7
|
||||
#define AdminMessage_confirm_set_channel_tag 32
|
||||
#define AdminMessage_confirm_set_radio_tag 33
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define AdminMessage_FIELDLIST(X, a) \
|
||||
|
@ -52,7 +56,9 @@ X(a, STATIC, ONEOF, MESSAGE, (variant,set_channel,set_channel), 3) \
|
|||
X(a, STATIC, ONEOF, BOOL, (variant,get_radio_request,get_radio_request), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_radio_response,get_radio_response), 5) \
|
||||
X(a, STATIC, ONEOF, UINT32, (variant,get_channel_request,get_channel_request), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_channel_response,get_channel_response), 7)
|
||||
X(a, STATIC, ONEOF, MESSAGE, (variant,get_channel_response,get_channel_response), 7) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_channel,confirm_set_channel), 32) \
|
||||
X(a, STATIC, ONEOF, BOOL, (variant,confirm_set_radio,confirm_set_radio), 33)
|
||||
#define AdminMessage_CALLBACK NULL
|
||||
#define AdminMessage_DEFAULT NULL
|
||||
#define AdminMessage_variant_set_radio_MSGTYPE RadioConfig
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct _ChannelSettings {
|
|||
} ChannelSettings;
|
||||
|
||||
typedef struct _Channel {
|
||||
uint8_t index;
|
||||
int8_t index;
|
||||
bool has_settings;
|
||||
ChannelSettings settings;
|
||||
Channel_Role role;
|
||||
|
@ -100,7 +100,7 @@ X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 17)
|
|||
#define ChannelSettings_DEFAULT NULL
|
||||
|
||||
#define Channel_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, index, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, index, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, settings, 2) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 3)
|
||||
#define Channel_CALLBACK NULL
|
||||
|
@ -116,7 +116,7 @@ extern const pb_msgdesc_t Channel_msg;
|
|||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ChannelSettings_size 87
|
||||
#define Channel_size 94
|
||||
#define Channel_size 102
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -6,7 +6,16 @@
|
|||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(LegacyRadioConfig, LegacyRadioConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(LegacyRadioConfig_LegacyPreferences, LegacyRadioConfig_LegacyPreferences, AUTO)
|
||||
|
||||
|
||||
PB_BIND(DeviceState, DeviceState, 2)
|
||||
|
||||
|
||||
PB_BIND(ChannelFile, ChannelFile, 2)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,17 +5,31 @@
|
|||
#define PB_DEVICEONLY_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "mesh.pb.h"
|
||||
#include "radioconfig.pb.h"
|
||||
#include "channel.pb.h"
|
||||
#include "radioconfig.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _ChannelFile {
|
||||
pb_size_t channels_count;
|
||||
Channel channels[8];
|
||||
} ChannelFile;
|
||||
|
||||
typedef struct _LegacyRadioConfig_LegacyPreferences {
|
||||
RegionCode region;
|
||||
} LegacyRadioConfig_LegacyPreferences;
|
||||
|
||||
typedef struct _LegacyRadioConfig {
|
||||
bool has_preferences;
|
||||
LegacyRadioConfig_LegacyPreferences preferences;
|
||||
} LegacyRadioConfig;
|
||||
|
||||
typedef struct _DeviceState {
|
||||
bool has_radio;
|
||||
RadioConfig radio;
|
||||
bool has_legacyRadio;
|
||||
LegacyRadioConfig legacyRadio;
|
||||
bool has_my_node;
|
||||
MyNodeInfo my_node;
|
||||
bool has_owner;
|
||||
|
@ -29,8 +43,6 @@ typedef struct _DeviceState {
|
|||
uint32_t version;
|
||||
bool no_save;
|
||||
bool did_gps_reset;
|
||||
pb_size_t channels_count;
|
||||
Channel channels[8];
|
||||
} DeviceState;
|
||||
|
||||
|
||||
|
@ -39,11 +51,20 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0, 0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
|
||||
#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0, 0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
|
||||
#define LegacyRadioConfig_init_default {false, LegacyRadioConfig_LegacyPreferences_init_default}
|
||||
#define LegacyRadioConfig_LegacyPreferences_init_default {_RegionCode_MIN}
|
||||
#define DeviceState_init_default {false, LegacyRadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
|
||||
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
|
||||
#define LegacyRadioConfig_init_zero {false, LegacyRadioConfig_LegacyPreferences_init_zero}
|
||||
#define LegacyRadioConfig_LegacyPreferences_init_zero {_RegionCode_MIN}
|
||||
#define DeviceState_init_zero {false, LegacyRadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
|
||||
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define DeviceState_radio_tag 1
|
||||
#define ChannelFile_channels_tag 1
|
||||
#define LegacyRadioConfig_LegacyPreferences_region_tag 15
|
||||
#define LegacyRadioConfig_preferences_tag 1
|
||||
#define DeviceState_legacyRadio_tag 1
|
||||
#define DeviceState_my_node_tag 2
|
||||
#define DeviceState_owner_tag 3
|
||||
#define DeviceState_node_db_tag 4
|
||||
|
@ -52,11 +73,21 @@ extern "C" {
|
|||
#define DeviceState_version_tag 8
|
||||
#define DeviceState_no_save_tag 9
|
||||
#define DeviceState_did_gps_reset_tag 11
|
||||
#define DeviceState_channels_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define LegacyRadioConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1)
|
||||
#define LegacyRadioConfig_CALLBACK NULL
|
||||
#define LegacyRadioConfig_DEFAULT NULL
|
||||
#define LegacyRadioConfig_preferences_MSGTYPE LegacyRadioConfig_LegacyPreferences
|
||||
|
||||
#define LegacyRadioConfig_LegacyPreferences_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, region, 15)
|
||||
#define LegacyRadioConfig_LegacyPreferences_CALLBACK NULL
|
||||
#define LegacyRadioConfig_LegacyPreferences_DEFAULT NULL
|
||||
|
||||
#define DeviceState_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, radio, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, legacyRadio, 1) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \
|
||||
|
@ -64,25 +95,38 @@ X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \
|
|||
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, no_save, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 13)
|
||||
X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
|
||||
#define DeviceState_CALLBACK NULL
|
||||
#define DeviceState_DEFAULT NULL
|
||||
#define DeviceState_radio_MSGTYPE RadioConfig
|
||||
#define DeviceState_legacyRadio_MSGTYPE LegacyRadioConfig
|
||||
#define DeviceState_my_node_MSGTYPE MyNodeInfo
|
||||
#define DeviceState_owner_MSGTYPE User
|
||||
#define DeviceState_node_db_MSGTYPE NodeInfo
|
||||
#define DeviceState_receive_queue_MSGTYPE MeshPacket
|
||||
#define DeviceState_rx_text_message_MSGTYPE MeshPacket
|
||||
#define DeviceState_channels_MSGTYPE Channel
|
||||
|
||||
#define ChannelFile_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 1)
|
||||
#define ChannelFile_CALLBACK NULL
|
||||
#define ChannelFile_DEFAULT NULL
|
||||
#define ChannelFile_channels_MSGTYPE Channel
|
||||
|
||||
extern const pb_msgdesc_t LegacyRadioConfig_msg;
|
||||
extern const pb_msgdesc_t LegacyRadioConfig_LegacyPreferences_msg;
|
||||
extern const pb_msgdesc_t DeviceState_msg;
|
||||
extern const pb_msgdesc_t ChannelFile_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define LegacyRadioConfig_fields &LegacyRadioConfig_msg
|
||||
#define LegacyRadioConfig_LegacyPreferences_fields &LegacyRadioConfig_LegacyPreferences_msg
|
||||
#define DeviceState_fields &DeviceState_msg
|
||||
#define ChannelFile_fields &ChannelFile_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define DeviceState_size 6169
|
||||
#define LegacyRadioConfig_size 4
|
||||
#define LegacyRadioConfig_LegacyPreferences_size 2
|
||||
#define DeviceState_size 5056
|
||||
#define ChannelFile_size 832
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
|
@ -37,7 +37,8 @@ typedef enum _Routing_Error {
|
|||
Routing_Error_NO_INTERFACE = 4,
|
||||
Routing_Error_MAX_RETRANSMIT = 5,
|
||||
Routing_Error_NO_CHANNEL = 6,
|
||||
Routing_Error_TOO_LARGE = 7
|
||||
Routing_Error_TOO_LARGE = 7,
|
||||
Routing_Error_NO_RESPONSE = 8
|
||||
} Routing_Error;
|
||||
|
||||
typedef enum _MeshPacket_Priority {
|
||||
|
@ -182,8 +183,8 @@ typedef struct _ToRadio {
|
|||
#define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_Brownout+1))
|
||||
|
||||
#define _Routing_Error_MIN Routing_Error_NONE
|
||||
#define _Routing_Error_MAX Routing_Error_TOO_LARGE
|
||||
#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_TOO_LARGE+1))
|
||||
#define _Routing_Error_MAX Routing_Error_NO_RESPONSE
|
||||
#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_NO_RESPONSE+1))
|
||||
|
||||
#define _MeshPacket_Priority_MIN MeshPacket_Priority_UNSET
|
||||
#define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0]))
|
||||
|
||||
/// Max number of channels allowed
|
||||
#define MAX_NUM_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0]))
|
||||
#define MAX_NUM_CHANNELS (member_size(ChannelFile, channels) / member_size(ChannelFile, channels[0]))
|
||||
|
||||
/// helper function for encoding a record as a protobuf, any failures to encode are fatal and we will panic
|
||||
/// returns the encoded packet size
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
AdminPlugin *adminPlugin;
|
||||
|
||||
void AdminPlugin::handleGetChannel(const MeshPacket &req, uint32_t channelIndex) {
|
||||
if (req.decoded.want_response) {
|
||||
void AdminPlugin::handleGetChannel(const MeshPacket &req, uint32_t channelIndex)
|
||||
{
|
||||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_channel_response = channels.getByIndex(channelIndex);
|
||||
|
@ -23,7 +24,7 @@ void AdminPlugin::handleGetRadio(const MeshPacket &req)
|
|||
if (req.decoded.want_response) {
|
||||
// We create the reply here
|
||||
AdminMessage r = AdminMessage_init_default;
|
||||
r.get_radio_response = devicestate.radio;
|
||||
r.get_radio_response = radioConfig;
|
||||
|
||||
// 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
|
||||
|
@ -65,6 +66,8 @@ bool AdminPlugin::handleReceivedProtobuf(const MeshPacket &mp, const AdminMessag
|
|||
break;
|
||||
|
||||
default:
|
||||
// Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages
|
||||
DEBUG_MSG("Ignoring nonrelevant admin %d\n", r->which_variant);
|
||||
break;
|
||||
}
|
||||
return false; // Let others look at this message also if they want
|
||||
|
@ -95,21 +98,22 @@ void AdminPlugin::handleSetChannel(const Channel &cc)
|
|||
{
|
||||
channels.setChannel(cc);
|
||||
|
||||
bool didReset = service.reloadConfig();
|
||||
/* FIXME - do we need this still?
|
||||
if (didReset) {
|
||||
state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client
|
||||
} */
|
||||
// Just update and save the channels - no need to update the radio for ! primary channel changes
|
||||
if (cc.index == 0) {
|
||||
// FIXME, this updates the user preferences also, which isn't needed - we really just want to notify on configChanged
|
||||
service.reloadConfig();
|
||||
}
|
||||
else {
|
||||
channels.onConfigChanged(); // tell the radios about this change
|
||||
nodeDB.saveChannelsToDisk();
|
||||
}
|
||||
}
|
||||
|
||||
void AdminPlugin::handleSetRadio(const RadioConfig &r)
|
||||
{
|
||||
radioConfig = r;
|
||||
|
||||
bool didReset = service.reloadConfig();
|
||||
/* FIXME - do we need this still? if (didReset) {
|
||||
state = STATE_SEND_MY_INFO; // Squirt a completely new set of configs to the client
|
||||
} */
|
||||
service.reloadConfig();
|
||||
}
|
||||
|
||||
MeshPacket *AdminPlugin::allocReply()
|
||||
|
@ -121,5 +125,6 @@ MeshPacket *AdminPlugin::allocReply()
|
|||
|
||||
AdminPlugin::AdminPlugin() : ProtobufPlugin("Admin", PortNum_ADMIN_APP, AdminMessage_fields)
|
||||
{
|
||||
// FIXME, restrict to the admin channel for rx
|
||||
// restrict to the admin channel for rx
|
||||
boundChannel = "admin";
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ MeshPacket *RoutingPlugin::allocReply()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom)
|
||||
void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex)
|
||||
{
|
||||
Routing c = Routing_init_default;
|
||||
|
||||
|
@ -47,6 +47,7 @@ void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom)
|
|||
p->hop_limit = 0; // Assume just immediate neighbors for now
|
||||
p->to = to;
|
||||
p->decoded.request_id = idFrom;
|
||||
p->channel = chIndex;
|
||||
DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
|
||||
|
||||
router->sendLocal(p); // we sometimes send directly to the local node
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "ProtobufPlugin.h"
|
||||
#include "Channels.h"
|
||||
|
||||
/**
|
||||
* Routing plugin for router control messages
|
||||
|
@ -12,6 +13,8 @@ class RoutingPlugin : public ProtobufPlugin<Routing>
|
|||
*/
|
||||
RoutingPlugin();
|
||||
|
||||
void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex);
|
||||
|
||||
protected:
|
||||
friend class Router;
|
||||
|
||||
|
@ -27,8 +30,6 @@ class RoutingPlugin : public ProtobufPlugin<Routing>
|
|||
|
||||
/// Override wantPacket to say we want to see all packets, not just those for our port number
|
||||
virtual bool wantPacket(const MeshPacket *p) { return true; }
|
||||
|
||||
void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom);
|
||||
};
|
||||
|
||||
extern RoutingPlugin *routingPlugin;
|
|
@ -83,7 +83,8 @@ int32_t StoreForwardPlugin::runOnce()
|
|||
DEBUG_MSG("Store & Forward Plugin - Sending heartbeat\n");
|
||||
|
||||
// storeForwardPluginRadio->sendPayloadHeartbeat();
|
||||
storeForwardPluginRadio->sendPayload();
|
||||
if(storeForwardPluginRadio)
|
||||
storeForwardPluginRadio->sendPayload();
|
||||
|
||||
return (1 * 60 * 1000);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[VERSION]
|
||||
major = 1
|
||||
minor = 2
|
||||
build = 6
|
||||
build = 9
|
||||
|
|
Ładowanie…
Reference in New Issue