wip - move channels

This commit is contained in:
Kevin Hester
2021-03-11 13:02:00 +08:00
parent 959b540c02
commit ab9fe42f58
14 changed files with 113 additions and 66 deletions

View File

@@ -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
}

View File

@@ -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

View File

@@ -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,10 @@ 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.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 +168,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()
@@ -241,34 +254,29 @@ void NodeDB::pickNewNodeNum()
}
const char *preffile = "/db.proto";
const char *preftmp = "/db.proto.tmp";
const char *radiofile = "/radio.proto";
const char *channelfile = "/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);
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();
@@ -279,6 +287,30 @@ void NodeDB::loadFromDisk()
#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 is old, discarding\n");
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)) {
installDefaultRadioConfig(); // Our in RAM copy might now be corrupt
}
}
void NodeDB::saveToDisk()
@@ -370,7 +402,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;

View File

@@ -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
@@ -117,7 +118,7 @@ class NodeDB
void loadFromDisk();
/// Reinit device state from scratch (not loading from disk)
void installDefaultDeviceState();
void installDefaultDeviceState(), installDefaultRadioConfig(), installDefaultChannels();
};
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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" */

View File

@@ -9,4 +9,7 @@
PB_BIND(DeviceState, DeviceState, 2)
PB_BIND(ChannelFile, ChannelFile, 2)

View File

@@ -5,7 +5,6 @@
#define PB_DEVICEONLY_PB_H_INCLUDED
#include <pb.h>
#include "mesh.pb.h"
#include "radioconfig.pb.h"
#include "channel.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
@@ -13,9 +12,12 @@
#endif
/* Struct definitions */
typedef struct _ChannelFile {
pb_size_t channels_count;
Channel channels[8];
} ChannelFile;
typedef struct _DeviceState {
bool has_radio;
RadioConfig radio;
bool has_my_node;
MyNodeInfo my_node;
bool has_owner;
@@ -29,8 +31,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 +39,13 @@ 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 DeviceState_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 DeviceState_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 DeviceState_my_node_tag 2
#define DeviceState_owner_tag 3
#define DeviceState_node_db_tag 4
@@ -52,11 +54,9 @@ 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 DeviceState_FIELDLIST(X, a) \
X(a, STATIC, OPTIONAL, MESSAGE, radio, 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 +64,31 @@ 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_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 DeviceState_msg;
extern const pb_msgdesc_t ChannelFile_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define DeviceState_fields &DeviceState_msg
#define ChannelFile_fields &ChannelFile_msg
/* Maximum encoded size of messages (where known) */
#define DeviceState_size 6169
#define DeviceState_size 5050
#define ChannelFile_size 832
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -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

View File

@@ -24,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