* companion: refactor of all filesystem access to new DataStore module
This commit is contained in:
306
examples/companion_radio/DataStore.cpp
Normal file
306
examples/companion_radio/DataStore.cpp
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "DataStore.h"
|
||||||
|
|
||||||
|
DataStore::DataStore(FILESYSTEM& fs) : _fs(&fs),
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
identity_store(fs, "")
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
identity_store(fs, "/identity")
|
||||||
|
#else
|
||||||
|
identity_store(fs, "/identity")
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::begin() {
|
||||||
|
#if defined(RP2040_PLATFORM)
|
||||||
|
identity_store.begin();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// init 'blob store' support
|
||||||
|
_fs->mkdir("/bl");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
#include <LittleFS.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool DataStore::formatFileSystem() {
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
return _fs->format();
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
return LittleFS.format();
|
||||||
|
#elif defined(ESP32)
|
||||||
|
return ((fs::SPIFFSFS *)_fs)->format();
|
||||||
|
#else
|
||||||
|
#error "need to implement format()"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataStore::loadMainIdentity(mesh::LocalIdentity &identity) {
|
||||||
|
return identity_store.load("_main", identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataStore::saveMainIdentity(const mesh::LocalIdentity &identity) {
|
||||||
|
return identity_store.save("_main", identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon) {
|
||||||
|
if (_fs->exists("/new_prefs")) {
|
||||||
|
loadPrefsInt("/new_prefs", prefs, node_lat, node_lon); // new filename
|
||||||
|
} else if (_fs->exists("/node_prefs")) {
|
||||||
|
loadPrefsInt("/node_prefs", prefs, node_lat, node_lon);
|
||||||
|
savePrefs(prefs, node_lat, node_lon); // save to new filename
|
||||||
|
_fs->remove("/node_prefs"); // remove old
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& node_lat, double& node_lon) {
|
||||||
|
#if defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open(filename, "r");
|
||||||
|
#else
|
||||||
|
File file = _fs->open(filename);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
uint8_t pad[8];
|
||||||
|
|
||||||
|
file.read((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
|
||||||
|
file.read((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
|
||||||
|
file.read(pad, 4); // 36
|
||||||
|
file.read((uint8_t *)&node_lat, sizeof(node_lat)); // 40
|
||||||
|
file.read((uint8_t *)&node_lon, sizeof(node_lon)); // 48
|
||||||
|
file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
||||||
|
file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
||||||
|
file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
||||||
|
file.read((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
||||||
|
file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
||||||
|
file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
||||||
|
file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
||||||
|
file.read((uint8_t *)&_prefs.telemetry_mode_base, sizeof(_prefs.telemetry_mode_base)); // 69
|
||||||
|
file.read((uint8_t *)&_prefs.telemetry_mode_loc, sizeof(_prefs.telemetry_mode_loc)); // 70
|
||||||
|
file.read((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
||||||
|
file.read((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
||||||
|
file.read(pad, 4); // 76
|
||||||
|
file.read((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_lon) {
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
_fs->remove("/new_prefs");
|
||||||
|
File file = _fs->open("/new_prefs", FILE_O_WRITE);
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open("/new_prefs", "w");
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/new_prefs", "w", true);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
uint8_t pad[8];
|
||||||
|
memset(pad, 0, sizeof(pad));
|
||||||
|
|
||||||
|
file.write((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
|
||||||
|
file.write((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
|
||||||
|
file.write(pad, 4); // 36
|
||||||
|
file.write((uint8_t *)&node_lat, sizeof(node_lat)); // 40
|
||||||
|
file.write((uint8_t *)&node_lon, sizeof(node_lon)); // 48
|
||||||
|
file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
||||||
|
file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
||||||
|
file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
||||||
|
file.write((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
||||||
|
file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
||||||
|
file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
||||||
|
file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
||||||
|
file.write((uint8_t *)&_prefs.telemetry_mode_base, sizeof(_prefs.telemetry_mode_base)); // 69
|
||||||
|
file.write((uint8_t *)&_prefs.telemetry_mode_loc, sizeof(_prefs.telemetry_mode_loc)); // 70
|
||||||
|
file.write((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
||||||
|
file.write((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
||||||
|
file.write(pad, 4); // 76
|
||||||
|
file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::loadContacts(DataStoreHost* host) {
|
||||||
|
if (_fs->exists("/contacts3")) {
|
||||||
|
#if defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open("/contacts3", "r");
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/contacts3");
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
bool full = false;
|
||||||
|
while (!full) {
|
||||||
|
ContactInfo c;
|
||||||
|
uint8_t pub_key[32];
|
||||||
|
uint8_t unused;
|
||||||
|
|
||||||
|
bool success = (file.read(pub_key, 32) == 32);
|
||||||
|
success = success && (file.read((uint8_t *)&c.name, 32) == 32);
|
||||||
|
success = success && (file.read(&c.type, 1) == 1);
|
||||||
|
success = success && (file.read(&c.flags, 1) == 1);
|
||||||
|
success = success && (file.read(&unused, 1) == 1);
|
||||||
|
success = success && (file.read((uint8_t *)&c.sync_since, 4) == 4); // was 'reserved'
|
||||||
|
success = success && (file.read((uint8_t *)&c.out_path_len, 1) == 1);
|
||||||
|
success = success && (file.read((uint8_t *)&c.last_advert_timestamp, 4) == 4);
|
||||||
|
success = success && (file.read(c.out_path, 64) == 64);
|
||||||
|
success = success && (file.read((uint8_t *)&c.lastmod, 4) == 4);
|
||||||
|
success = success && (file.read((uint8_t *)&c.gps_lat, 4) == 4);
|
||||||
|
success = success && (file.read((uint8_t *)&c.gps_lon, 4) == 4);
|
||||||
|
|
||||||
|
if (!success) break; // EOF
|
||||||
|
|
||||||
|
c.id = mesh::Identity(pub_key);
|
||||||
|
if (!host->onContactLoaded(c)) full = true;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::saveContacts(DataStoreHost* host) {
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
_fs->remove("/contacts3");
|
||||||
|
File file = _fs->open("/contacts3", FILE_O_WRITE);
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open("/contacts3", "w");
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/contacts3", "w", true);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
uint32_t idx = 0;
|
||||||
|
ContactInfo c;
|
||||||
|
uint8_t unused = 0;
|
||||||
|
|
||||||
|
while (host->getContactForSave(idx, c)) {
|
||||||
|
bool success = (file.write(c.id.pub_key, 32) == 32);
|
||||||
|
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
|
||||||
|
success = success && (file.write(&c.type, 1) == 1);
|
||||||
|
success = success && (file.write(&c.flags, 1) == 1);
|
||||||
|
success = success && (file.write(&unused, 1) == 1);
|
||||||
|
success = success && (file.write((uint8_t *)&c.sync_since, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.out_path_len, 1) == 1);
|
||||||
|
success = success && (file.write((uint8_t *)&c.last_advert_timestamp, 4) == 4);
|
||||||
|
success = success && (file.write(c.out_path, 64) == 64);
|
||||||
|
success = success && (file.write((uint8_t *)&c.lastmod, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.gps_lat, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)&c.gps_lon, 4) == 4);
|
||||||
|
|
||||||
|
if (!success) break; // write failed
|
||||||
|
|
||||||
|
idx++; // advance to next contact
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::loadChannels(DataStoreHost* host) {
|
||||||
|
if (_fs->exists("/channels2")) {
|
||||||
|
#if defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open("/channels2", "r");
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/channels2");
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
bool full = false;
|
||||||
|
uint8_t channel_idx = 0;
|
||||||
|
while (!full) {
|
||||||
|
ChannelDetails ch;
|
||||||
|
uint8_t unused[4];
|
||||||
|
|
||||||
|
bool success = (file.read(unused, 4) == 4);
|
||||||
|
success = success && (file.read((uint8_t *)ch.name, 32) == 32);
|
||||||
|
success = success && (file.read((uint8_t *)ch.channel.secret, 32) == 32);
|
||||||
|
|
||||||
|
if (!success) break; // EOF
|
||||||
|
|
||||||
|
if (host->onChannelLoaded(channel_idx, ch)) {
|
||||||
|
channel_idx++;
|
||||||
|
} else {
|
||||||
|
full = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataStore::saveChannels(DataStoreHost* host) {
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
_fs->remove("/channels2");
|
||||||
|
File file = _fs->open("/channels2", FILE_O_WRITE);
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
File file = _fs->open("/channels2", "w");
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/channels2", "w", true);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
uint8_t channel_idx = 0;
|
||||||
|
ChannelDetails ch;
|
||||||
|
uint8_t unused[4];
|
||||||
|
memset(unused, 0, 4);
|
||||||
|
|
||||||
|
while (host->getChannelForSave(channel_idx, ch)) {
|
||||||
|
bool success = (file.write(unused, 4) == 4);
|
||||||
|
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
|
||||||
|
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
|
||||||
|
|
||||||
|
if (!success) break; // write failed
|
||||||
|
channel_idx++;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataStore::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) {
|
||||||
|
char path[64];
|
||||||
|
char fname[18];
|
||||||
|
|
||||||
|
if (key_len > 8) key_len = 8; // just use first 8 bytes (prefix)
|
||||||
|
mesh::Utils::toHex(fname, key, key_len);
|
||||||
|
sprintf(path, "/bl/%s", fname);
|
||||||
|
|
||||||
|
if (_fs->exists(path)) {
|
||||||
|
#if defined(RP2040_PLATFORM)
|
||||||
|
File f = _fs->open(path, "r");
|
||||||
|
#else
|
||||||
|
File f = _fs->open(path);
|
||||||
|
#endif
|
||||||
|
if (f) {
|
||||||
|
int len = f.read(dest_buf, 255); // currently MAX 255 byte blob len supported!!
|
||||||
|
f.close();
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; // not found
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DataStore::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len) {
|
||||||
|
char path[64];
|
||||||
|
char fname[18];
|
||||||
|
|
||||||
|
if (key_len > 8) key_len = 8; // just use first 8 bytes (prefix)
|
||||||
|
mesh::Utils::toHex(fname, key, key_len);
|
||||||
|
sprintf(path, "/bl/%s", fname);
|
||||||
|
|
||||||
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
|
_fs->remove(path);
|
||||||
|
File f = _fs->open(path, FILE_O_WRITE);
|
||||||
|
#elif defined(RP2040_PLATFORM)
|
||||||
|
File f = _fs->open(path, "w");
|
||||||
|
#else
|
||||||
|
File f = _fs->open(path, "w", true);
|
||||||
|
#endif
|
||||||
|
if (f) {
|
||||||
|
int n = f.write(src_buf, len);
|
||||||
|
f.close();
|
||||||
|
if (n == len) return true; // success!
|
||||||
|
|
||||||
|
_fs->remove(path); // blob was only partially written!
|
||||||
|
}
|
||||||
|
return false; // error
|
||||||
|
}
|
||||||
36
examples/companion_radio/DataStore.h
Normal file
36
examples/companion_radio/DataStore.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <helpers/IdentityStore.h>
|
||||||
|
#include <helpers/ContactInfo.h>
|
||||||
|
#include <helpers/ChannelDetails.h>
|
||||||
|
#include "NodePrefs.h"
|
||||||
|
|
||||||
|
class DataStoreHost {
|
||||||
|
public:
|
||||||
|
virtual bool onContactLoaded(const ContactInfo& contact) =0;
|
||||||
|
virtual bool getContactForSave(uint32_t idx, ContactInfo& contact) =0;
|
||||||
|
virtual bool onChannelLoaded(uint8_t channel_idx, const ChannelDetails& ch) =0;
|
||||||
|
virtual bool getChannelForSave(uint8_t channel_idx, ChannelDetails& ch) =0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DataStore {
|
||||||
|
FILESYSTEM* _fs;
|
||||||
|
IdentityStore identity_store;
|
||||||
|
|
||||||
|
void loadPrefsInt(const char *filename, NodePrefs& prefs, double& node_lat, double& node_lon);
|
||||||
|
|
||||||
|
public:
|
||||||
|
DataStore(FILESYSTEM& fs);
|
||||||
|
void begin();
|
||||||
|
bool formatFileSystem();
|
||||||
|
bool loadMainIdentity(mesh::LocalIdentity &identity);
|
||||||
|
bool saveMainIdentity(const mesh::LocalIdentity &identity);
|
||||||
|
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
|
||||||
|
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
||||||
|
void loadContacts(DataStoreHost* host);
|
||||||
|
void saveContacts(DataStoreHost* host);
|
||||||
|
void loadChannels(DataStoreHost* host);
|
||||||
|
void saveChannels(DataStoreHost* host);
|
||||||
|
int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]);
|
||||||
|
bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len);
|
||||||
|
};
|
||||||
@@ -103,200 +103,6 @@
|
|||||||
#include "UITask.h"
|
#include "UITask.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void MyMesh::loadMainIdentity() {
|
|
||||||
if (!_identity_store->load("_main", self_id)) {
|
|
||||||
self_id = radio_new_identity(); // create new random identity
|
|
||||||
int count = 0;
|
|
||||||
while (count < 10 && (self_id.pub_key[0] == 0x00 || self_id.pub_key[0] == 0xFF)) { // reserved id hashes
|
|
||||||
self_id = radio_new_identity();
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
saveMainIdentity(self_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyMesh::saveMainIdentity(const mesh::LocalIdentity &identity) {
|
|
||||||
return _identity_store->save("_main", identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::loadContacts() {
|
|
||||||
if (_fs->exists("/contacts3")) {
|
|
||||||
#if defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open("/contacts3", "r");
|
|
||||||
#else
|
|
||||||
File file = _fs->open("/contacts3");
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
bool full = false;
|
|
||||||
while (!full) {
|
|
||||||
ContactInfo c;
|
|
||||||
uint8_t pub_key[32];
|
|
||||||
uint8_t unused;
|
|
||||||
|
|
||||||
bool success = (file.read(pub_key, 32) == 32);
|
|
||||||
success = success && (file.read((uint8_t *)&c.name, 32) == 32);
|
|
||||||
success = success && (file.read(&c.type, 1) == 1);
|
|
||||||
success = success && (file.read(&c.flags, 1) == 1);
|
|
||||||
success = success && (file.read(&unused, 1) == 1);
|
|
||||||
success = success && (file.read((uint8_t *)&c.sync_since, 4) == 4); // was 'reserved'
|
|
||||||
success = success && (file.read((uint8_t *)&c.out_path_len, 1) == 1);
|
|
||||||
success = success && (file.read((uint8_t *)&c.last_advert_timestamp, 4) == 4);
|
|
||||||
success = success && (file.read(c.out_path, 64) == 64);
|
|
||||||
success = success && (file.read((uint8_t *)&c.lastmod, 4) == 4);
|
|
||||||
success = success && (file.read((uint8_t *)&c.gps_lat, 4) == 4);
|
|
||||||
success = success && (file.read((uint8_t *)&c.gps_lon, 4) == 4);
|
|
||||||
|
|
||||||
if (!success) break; // EOF
|
|
||||||
|
|
||||||
c.id = mesh::Identity(pub_key);
|
|
||||||
if (!addContact(c)) full = true;
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::saveContacts() {
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
||||||
_fs->remove("/contacts3");
|
|
||||||
File file = _fs->open("/contacts3", FILE_O_WRITE);
|
|
||||||
#elif defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open("/contacts3", "w");
|
|
||||||
#else
|
|
||||||
File file = _fs->open("/contacts3", "w", true);
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
ContactsIterator iter;
|
|
||||||
ContactInfo c;
|
|
||||||
uint8_t unused = 0;
|
|
||||||
|
|
||||||
while (iter.hasNext(this, c)) {
|
|
||||||
bool success = (file.write(c.id.pub_key, 32) == 32);
|
|
||||||
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
|
|
||||||
success = success && (file.write(&c.type, 1) == 1);
|
|
||||||
success = success && (file.write(&c.flags, 1) == 1);
|
|
||||||
success = success && (file.write(&unused, 1) == 1);
|
|
||||||
success = success && (file.write((uint8_t *)&c.sync_since, 4) == 4);
|
|
||||||
success = success && (file.write((uint8_t *)&c.out_path_len, 1) == 1);
|
|
||||||
success = success && (file.write((uint8_t *)&c.last_advert_timestamp, 4) == 4);
|
|
||||||
success = success && (file.write(c.out_path, 64) == 64);
|
|
||||||
success = success && (file.write((uint8_t *)&c.lastmod, 4) == 4);
|
|
||||||
success = success && (file.write((uint8_t *)&c.gps_lat, 4) == 4);
|
|
||||||
success = success && (file.write((uint8_t *)&c.gps_lon, 4) == 4);
|
|
||||||
|
|
||||||
if (!success) break; // write failed
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::loadChannels() {
|
|
||||||
if (_fs->exists("/channels2")) {
|
|
||||||
#if defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open("/channels2", "r");
|
|
||||||
#else
|
|
||||||
File file = _fs->open("/channels2");
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
bool full = false;
|
|
||||||
uint8_t channel_idx = 0;
|
|
||||||
while (!full) {
|
|
||||||
ChannelDetails ch;
|
|
||||||
uint8_t unused[4];
|
|
||||||
|
|
||||||
bool success = (file.read(unused, 4) == 4);
|
|
||||||
success = success && (file.read((uint8_t *)ch.name, 32) == 32);
|
|
||||||
success = success && (file.read((uint8_t *)ch.channel.secret, 32) == 32);
|
|
||||||
|
|
||||||
if (!success) break; // EOF
|
|
||||||
|
|
||||||
if (setChannel(channel_idx, ch)) {
|
|
||||||
channel_idx++;
|
|
||||||
} else {
|
|
||||||
full = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::saveChannels() {
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
||||||
_fs->remove("/channels2");
|
|
||||||
File file = _fs->open("/channels2", FILE_O_WRITE);
|
|
||||||
#elif defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open("/channels2", "w");
|
|
||||||
#else
|
|
||||||
File file = _fs->open("/channels2", "w", true);
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
uint8_t channel_idx = 0;
|
|
||||||
ChannelDetails ch;
|
|
||||||
uint8_t unused[4];
|
|
||||||
memset(unused, 0, 4);
|
|
||||||
|
|
||||||
while (getChannel(channel_idx, ch)) {
|
|
||||||
bool success = (file.write(unused, 4) == 4);
|
|
||||||
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
|
|
||||||
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
|
|
||||||
|
|
||||||
if (!success) break; // write failed
|
|
||||||
channel_idx++;
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int MyMesh::getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) {
|
|
||||||
char path[64];
|
|
||||||
char fname[18];
|
|
||||||
|
|
||||||
if (key_len > 8) key_len = 8; // just use first 8 bytes (prefix)
|
|
||||||
mesh::Utils::toHex(fname, key, key_len);
|
|
||||||
sprintf(path, "/bl/%s", fname);
|
|
||||||
|
|
||||||
if (_fs->exists(path)) {
|
|
||||||
#if defined(RP2040_PLATFORM)
|
|
||||||
File f = _fs->open(path, "r");
|
|
||||||
#else
|
|
||||||
File f = _fs->open(path);
|
|
||||||
#endif
|
|
||||||
if (f) {
|
|
||||||
int len = f.read(dest_buf, 255); // currently MAX 255 byte blob len supported!!
|
|
||||||
f.close();
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0; // not found
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyMesh::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len) {
|
|
||||||
char path[64];
|
|
||||||
char fname[18];
|
|
||||||
|
|
||||||
if (key_len > 8) key_len = 8; // just use first 8 bytes (prefix)
|
|
||||||
mesh::Utils::toHex(fname, key, key_len);
|
|
||||||
sprintf(path, "/bl/%s", fname);
|
|
||||||
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
||||||
_fs->remove(path);
|
|
||||||
File f = _fs->open(path, FILE_O_WRITE);
|
|
||||||
#elif defined(RP2040_PLATFORM)
|
|
||||||
File f = _fs->open(path, "w");
|
|
||||||
#else
|
|
||||||
File f = _fs->open(path, "w", true);
|
|
||||||
#endif
|
|
||||||
if (f) {
|
|
||||||
int n = f.write(src_buf, len);
|
|
||||||
f.close();
|
|
||||||
if (n == len) return true; // success!
|
|
||||||
|
|
||||||
_fs->remove(path); // blob was only partially written!
|
|
||||||
}
|
|
||||||
return false; // error
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::writeOKFrame() {
|
void MyMesh::writeOKFrame() {
|
||||||
uint8_t buf[1];
|
uint8_t buf[1];
|
||||||
buf[0] = RESP_CODE_OK;
|
buf[0] = RESP_CODE_OK;
|
||||||
@@ -724,14 +530,13 @@ uint32_t MyMesh::calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t
|
|||||||
|
|
||||||
void MyMesh::onSendTimeout() {}
|
void MyMesh::onSendTimeout() {}
|
||||||
|
|
||||||
MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables)
|
MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store)
|
||||||
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables),
|
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables),
|
||||||
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4) {
|
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store) {
|
||||||
_iter_started = false;
|
_iter_started = false;
|
||||||
_cli_rescue = false;
|
_cli_rescue = false;
|
||||||
offline_queue_len = 0;
|
offline_queue_len = 0;
|
||||||
app_target_ver = 0;
|
app_target_ver = 0;
|
||||||
_identity_store = NULL;
|
|
||||||
pending_login = pending_status = pending_telemetry = 0;
|
pending_login = pending_status = pending_telemetry = 0;
|
||||||
next_ack_idx = 0;
|
next_ack_idx = 0;
|
||||||
sign_data = NULL;
|
sign_data = NULL;
|
||||||
@@ -749,62 +554,18 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
|||||||
//_prefs.rx_delay_base = 10.0f; enable once new algo fixed
|
//_prefs.rx_delay_base = 10.0f; enable once new algo fixed
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::loadPrefsInt(const char *filename) {
|
void MyMesh::begin(bool has_display) {
|
||||||
#if defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open(filename, "r");
|
|
||||||
#else
|
|
||||||
File file = _fs->open(filename);
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
uint8_t pad[8];
|
|
||||||
|
|
||||||
file.read((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
|
|
||||||
file.read((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
|
|
||||||
file.read(pad, 4); // 36
|
|
||||||
file.read((uint8_t *)&sensors.node_lat, sizeof(sensors.node_lat)); // 40
|
|
||||||
file.read((uint8_t *)&sensors.node_lon, sizeof(sensors.node_lon)); // 48
|
|
||||||
file.read((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
|
||||||
file.read((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
|
||||||
file.read((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
|
||||||
file.read((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
|
||||||
file.read((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
|
||||||
file.read((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
|
||||||
file.read((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
|
||||||
file.read((uint8_t *)&_prefs.telemetry_mode_base, sizeof(_prefs.telemetry_mode_base)); // 69
|
|
||||||
file.read((uint8_t *)&_prefs.telemetry_mode_loc, sizeof(_prefs.telemetry_mode_loc)); // 70
|
|
||||||
file.read((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
|
||||||
file.read((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
|
||||||
file.read(pad, 4); // 76
|
|
||||||
file.read((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
|
||||||
|
|
||||||
// sanitise bad pref values
|
|
||||||
_prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f);
|
|
||||||
_prefs.airtime_factor = constrain(_prefs.airtime_factor, 0, 9.0f);
|
|
||||||
_prefs.freq = constrain(_prefs.freq, 400.0f, 2500.0f);
|
|
||||||
_prefs.bw = constrain(_prefs.bw, 62.5f, 500.0f);
|
|
||||||
_prefs.sf = constrain(_prefs.sf, 7, 12);
|
|
||||||
_prefs.cr = constrain(_prefs.cr, 5, 8);
|
|
||||||
_prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::begin(FILESYSTEM &fs, bool has_display) {
|
|
||||||
_fs = &fs;
|
|
||||||
|
|
||||||
BaseChatMesh::begin();
|
BaseChatMesh::begin();
|
||||||
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
if (!_store->loadMainIdentity(self_id)) {
|
||||||
_identity_store = new IdentityStore(fs, "");
|
self_id = radio_new_identity(); // create new random identity
|
||||||
#elif defined(RP2040_PLATFORM)
|
int count = 0;
|
||||||
_identity_store = new IdentityStore(fs, "/identity");
|
while (count < 10 && (self_id.pub_key[0] == 0x00 || self_id.pub_key[0] == 0xFF)) { // reserved id hashes
|
||||||
_identity_store->begin();
|
self_id = radio_new_identity();
|
||||||
#else
|
count++;
|
||||||
_identity_store = new IdentityStore(fs, "/identity");
|
}
|
||||||
#endif
|
_store->saveMainIdentity(self_id);
|
||||||
|
}
|
||||||
loadMainIdentity();
|
|
||||||
|
|
||||||
// use hex of first 4 bytes of identity public key as default node name
|
// use hex of first 4 bytes of identity public key as default node name
|
||||||
char pub_key_hex[10];
|
char pub_key_hex[10];
|
||||||
@@ -817,13 +578,16 @@ void MyMesh::begin(FILESYSTEM &fs, bool has_display) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// load persisted prefs
|
// load persisted prefs
|
||||||
if (_fs->exists("/new_prefs")) {
|
_store->loadPrefs(_prefs, sensors.node_lat, sensors.node_lon);
|
||||||
loadPrefsInt("/new_prefs"); // new filename
|
|
||||||
} else if (_fs->exists("/node_prefs")) {
|
// sanitise bad pref values
|
||||||
loadPrefsInt("/node_prefs");
|
_prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f);
|
||||||
savePrefs(); // save to new filename
|
_prefs.airtime_factor = constrain(_prefs.airtime_factor, 0, 9.0f);
|
||||||
_fs->remove("/node_prefs"); // remove old
|
_prefs.freq = constrain(_prefs.freq, 400.0f, 2500.0f);
|
||||||
}
|
_prefs.bw = constrain(_prefs.bw, 62.5f, 500.0f);
|
||||||
|
_prefs.sf = constrain(_prefs.sf, 7, 12);
|
||||||
|
_prefs.cr = constrain(_prefs.cr, 5, 8);
|
||||||
|
_prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER);
|
||||||
|
|
||||||
#ifdef BLE_PIN_CODE
|
#ifdef BLE_PIN_CODE
|
||||||
if (_prefs.ble_pin == 0) {
|
if (_prefs.ble_pin == 0) {
|
||||||
@@ -844,12 +608,9 @@ void MyMesh::begin(FILESYSTEM &fs, bool has_display) {
|
|||||||
_active_ble_pin = 0;
|
_active_ble_pin = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// init 'blob store' support
|
_store->loadContacts(this);
|
||||||
_fs->mkdir("/bl");
|
|
||||||
|
|
||||||
loadContacts();
|
|
||||||
addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
|
addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
|
||||||
loadChannels();
|
_store->loadChannels(this);
|
||||||
|
|
||||||
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr);
|
||||||
radio_set_tx_power(_prefs.tx_power_dbm);
|
radio_set_tx_power(_prefs.tx_power_dbm);
|
||||||
@@ -870,42 +631,6 @@ void MyMesh::startInterface(BaseSerialInterface &serial) {
|
|||||||
serial.enable();
|
serial.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::savePrefs() {
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
||||||
_fs->remove("/new_prefs");
|
|
||||||
File file = _fs->open("/new_prefs", FILE_O_WRITE);
|
|
||||||
#elif defined(RP2040_PLATFORM)
|
|
||||||
File file = _fs->open("/new_prefs", "w");
|
|
||||||
#else
|
|
||||||
File file = _fs->open("/new_prefs", "w", true);
|
|
||||||
#endif
|
|
||||||
if (file) {
|
|
||||||
uint8_t pad[8];
|
|
||||||
memset(pad, 0, sizeof(pad));
|
|
||||||
|
|
||||||
file.write((uint8_t *)&_prefs.airtime_factor, sizeof(float)); // 0
|
|
||||||
file.write((uint8_t *)_prefs.node_name, sizeof(_prefs.node_name)); // 4
|
|
||||||
file.write(pad, 4); // 36
|
|
||||||
file.write((uint8_t *)&sensors.node_lat, sizeof(sensors.node_lat)); // 40
|
|
||||||
file.write((uint8_t *)&sensors.node_lon, sizeof(sensors.node_lon)); // 48
|
|
||||||
file.write((uint8_t *)&_prefs.freq, sizeof(_prefs.freq)); // 56
|
|
||||||
file.write((uint8_t *)&_prefs.sf, sizeof(_prefs.sf)); // 60
|
|
||||||
file.write((uint8_t *)&_prefs.cr, sizeof(_prefs.cr)); // 61
|
|
||||||
file.write((uint8_t *)&_prefs.reserved1, sizeof(_prefs.reserved1)); // 62
|
|
||||||
file.write((uint8_t *)&_prefs.manual_add_contacts, sizeof(_prefs.manual_add_contacts)); // 63
|
|
||||||
file.write((uint8_t *)&_prefs.bw, sizeof(_prefs.bw)); // 64
|
|
||||||
file.write((uint8_t *)&_prefs.tx_power_dbm, sizeof(_prefs.tx_power_dbm)); // 68
|
|
||||||
file.write((uint8_t *)&_prefs.telemetry_mode_base, sizeof(_prefs.telemetry_mode_base)); // 69
|
|
||||||
file.write((uint8_t *)&_prefs.telemetry_mode_loc, sizeof(_prefs.telemetry_mode_loc)); // 70
|
|
||||||
file.write((uint8_t *)&_prefs.telemetry_mode_env, sizeof(_prefs.telemetry_mode_env)); // 71
|
|
||||||
file.write((uint8_t *)&_prefs.rx_delay_base, sizeof(_prefs.rx_delay_base)); // 72
|
|
||||||
file.write(pad, 4); // 76
|
|
||||||
file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::handleCmdFrame(size_t len) {
|
void MyMesh::handleCmdFrame(size_t len) {
|
||||||
if (cmd_frame[0] == CMD_DEVICE_QEURY && len >= 2) { // sent when app establishes connection
|
if (cmd_frame[0] == CMD_DEVICE_QEURY && len >= 2) { // sent when app establishes connection
|
||||||
app_target_ver = cmd_frame[1]; // which version of protocol does app understand
|
app_target_ver = cmd_frame[1]; // which version of protocol does app understand
|
||||||
@@ -1286,7 +1011,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
#if ENABLE_PRIVATE_KEY_IMPORT
|
#if ENABLE_PRIVATE_KEY_IMPORT
|
||||||
mesh::LocalIdentity identity;
|
mesh::LocalIdentity identity;
|
||||||
identity.readFrom(&cmd_frame[1], 64);
|
identity.readFrom(&cmd_frame[1], 64);
|
||||||
if (saveMainIdentity(identity)) {
|
if (_store->saveMainIdentity(identity)) {
|
||||||
self_id = identity;
|
self_id = identity;
|
||||||
writeOKFrame();
|
writeOKFrame();
|
||||||
} else {
|
} else {
|
||||||
@@ -1536,19 +1261,6 @@ void MyMesh::enterCLIRescue() {
|
|||||||
Serial.println("========= CLI Rescue =========");
|
Serial.println("========= CLI Rescue =========");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MyMesh::formatFileSystem() {
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
|
||||||
return InternalFS.format();
|
|
||||||
#elif defined(RP2040_PLATFORM)
|
|
||||||
return LittleFS.format();
|
|
||||||
#elif defined(ESP32)
|
|
||||||
return SPIFFS.format();
|
|
||||||
#else
|
|
||||||
#error "need to implement file system erase"
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyMesh::checkCLIRescueCmd() {
|
void MyMesh::checkCLIRescueCmd() {
|
||||||
int len = strlen(cli_command);
|
int len = strlen(cli_command);
|
||||||
while (Serial.available() && len < sizeof(cli_command)-1) {
|
while (Serial.available() && len < sizeof(cli_command)-1) {
|
||||||
@@ -1576,16 +1288,16 @@ void MyMesh::checkCLIRescueCmd() {
|
|||||||
Serial.printf(" Error: unknown config: %s\n", config);
|
Serial.printf(" Error: unknown config: %s\n", config);
|
||||||
}
|
}
|
||||||
} else if (strcmp(cli_command, "rebuild") == 0) {
|
} else if (strcmp(cli_command, "rebuild") == 0) {
|
||||||
bool success = formatFileSystem();
|
bool success = _store->formatFileSystem();
|
||||||
if (success) {
|
if (success) {
|
||||||
saveMainIdentity(self_id);
|
_store->saveMainIdentity(self_id);
|
||||||
saveContacts();
|
saveContacts();
|
||||||
Serial.println(" > erase and rebuild done");
|
Serial.println(" > erase and rebuild done");
|
||||||
} else {
|
} else {
|
||||||
Serial.println(" Error: erase failed");
|
Serial.println(" Error: erase failed");
|
||||||
}
|
}
|
||||||
} else if (strcmp(cli_command, "erase") == 0) {
|
} else if (strcmp(cli_command, "erase") == 0) {
|
||||||
bool success = formatFileSystem();
|
bool success = _store->formatFileSystem();
|
||||||
if (success) {
|
if (success) {
|
||||||
Serial.println(" > erase done");
|
Serial.println(" > erase done");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "DataStore.h"
|
||||||
#include "NodePrefs.h"
|
#include "NodePrefs.h"
|
||||||
|
|
||||||
#include <RTClib.h>
|
#include <RTClib.h>
|
||||||
@@ -76,14 +77,12 @@
|
|||||||
#define REQ_TYPE_KEEP_ALIVE 0x02
|
#define REQ_TYPE_KEEP_ALIVE 0x02
|
||||||
#define REQ_TYPE_GET_TELEMETRY_DATA 0x03
|
#define REQ_TYPE_GET_TELEMETRY_DATA 0x03
|
||||||
|
|
||||||
class MyMesh : public BaseChatMesh {
|
class MyMesh : public BaseChatMesh, public DataStoreHost {
|
||||||
public:
|
public:
|
||||||
MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables);
|
MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store);
|
||||||
|
|
||||||
void begin(FILESYSTEM &fs, bool has_display);
|
void begin(bool has_display);
|
||||||
void startInterface(BaseSerialInterface &serial);
|
void startInterface(BaseSerialInterface &serial);
|
||||||
void loadPrefsInt(const char *filename);
|
|
||||||
void savePrefs();
|
|
||||||
|
|
||||||
const char *getNodeName();
|
const char *getNodeName();
|
||||||
NodePrefs *getNodePrefs();
|
NodePrefs *getNodePrefs();
|
||||||
@@ -127,6 +126,12 @@ protected:
|
|||||||
uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const override;
|
uint32_t calcDirectTimeoutMillisFor(uint32_t pkt_airtime_millis, uint8_t path_len) const override;
|
||||||
void onSendTimeout() override;
|
void onSendTimeout() override;
|
||||||
|
|
||||||
|
// DataStoreHost methods
|
||||||
|
bool onContactLoaded(const ContactInfo& contact) override { return addContact(contact); }
|
||||||
|
bool getContactForSave(uint32_t idx, ContactInfo& contact) override { return getContactByIdx(idx, contact); }
|
||||||
|
bool onChannelLoaded(uint8_t channel_idx, const ChannelDetails& ch) override { return setChannel(channel_idx, ch); }
|
||||||
|
bool getChannelForSave(uint8_t channel_idx, ChannelDetails& ch) override { return getChannel(channel_idx, ch); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeOKFrame();
|
void writeOKFrame();
|
||||||
void writeErrFrame(uint8_t err_code);
|
void writeErrFrame(uint8_t err_code);
|
||||||
@@ -135,22 +140,17 @@ private:
|
|||||||
void updateContactFromFrame(ContactInfo &contact, const uint8_t *frame, int len);
|
void updateContactFromFrame(ContactInfo &contact, const uint8_t *frame, int len);
|
||||||
void addToOfflineQueue(const uint8_t frame[], int len);
|
void addToOfflineQueue(const uint8_t frame[], int len);
|
||||||
int getFromOfflineQueue(uint8_t frame[]);
|
int getFromOfflineQueue(uint8_t frame[]);
|
||||||
void loadMainIdentity();
|
|
||||||
bool saveMainIdentity(const mesh::LocalIdentity &identity);
|
|
||||||
void loadContacts();
|
|
||||||
void saveContacts();
|
|
||||||
void loadChannels();
|
|
||||||
void saveChannels();
|
|
||||||
int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) override;
|
|
||||||
bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], int len) override;
|
|
||||||
|
|
||||||
void checkCLIRescueCmd();
|
void checkCLIRescueCmd();
|
||||||
void checkSerialInterface();
|
void checkSerialInterface();
|
||||||
bool formatFileSystem();
|
|
||||||
|
// helpers, short-cuts
|
||||||
|
void savePrefs() { _store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon); }
|
||||||
|
void saveChannels() { _store->saveChannels(this); }
|
||||||
|
void saveContacts() { _store->saveContacts(this); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILESYSTEM *_fs;
|
DataStore* _store;
|
||||||
IdentityStore *_identity_store;
|
|
||||||
NodePrefs _prefs;
|
NodePrefs _prefs;
|
||||||
uint32_t pending_login;
|
uint32_t pending_login;
|
||||||
uint32_t pending_status;
|
uint32_t pending_status;
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ static uint32_t _atoi(const char* sp) {
|
|||||||
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
#include <InternalFileSystem.h>
|
#include <InternalFileSystem.h>
|
||||||
|
DataStore store(InternalFS);
|
||||||
#elif defined(RP2040_PLATFORM)
|
#elif defined(RP2040_PLATFORM)
|
||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
|
DataStore store(LittleFS);
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
|
DataStore store(SPIFFS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
@@ -74,7 +77,7 @@ static uint32_t _atoi(const char* sp) {
|
|||||||
/* GLOBAL OBJECTS */
|
/* GLOBAL OBJECTS */
|
||||||
StdRNG fast_rng;
|
StdRNG fast_rng;
|
||||||
SimpleMeshTables tables;
|
SimpleMeshTables tables;
|
||||||
MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables);
|
MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store);
|
||||||
|
|
||||||
#ifdef DISPLAY_CLASS
|
#ifdef DISPLAY_CLASS
|
||||||
#include "UITask.h"
|
#include "UITask.h"
|
||||||
@@ -82,7 +85,6 @@ MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables);
|
|||||||
#endif
|
#endif
|
||||||
/* END GLOBAL OBJECTS */
|
/* END GLOBAL OBJECTS */
|
||||||
|
|
||||||
|
|
||||||
void halt() {
|
void halt() {
|
||||||
while (1) ;
|
while (1) ;
|
||||||
}
|
}
|
||||||
@@ -108,7 +110,8 @@ void setup() {
|
|||||||
|
|
||||||
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
|
||||||
InternalFS.begin();
|
InternalFS.begin();
|
||||||
the_mesh.begin(InternalFS,
|
store.begin();
|
||||||
|
the_mesh.begin(
|
||||||
#ifdef DISPLAY_CLASS
|
#ifdef DISPLAY_CLASS
|
||||||
disp != NULL
|
disp != NULL
|
||||||
#else
|
#else
|
||||||
@@ -126,7 +129,8 @@ void setup() {
|
|||||||
the_mesh.startInterface(serial_interface);
|
the_mesh.startInterface(serial_interface);
|
||||||
#elif defined(RP2040_PLATFORM)
|
#elif defined(RP2040_PLATFORM)
|
||||||
LittleFS.begin();
|
LittleFS.begin();
|
||||||
the_mesh.begin(LittleFS,
|
store.begin();
|
||||||
|
the_mesh.begin(
|
||||||
#ifdef DISPLAY_CLASS
|
#ifdef DISPLAY_CLASS
|
||||||
disp != NULL
|
disp != NULL
|
||||||
#else
|
#else
|
||||||
@@ -151,7 +155,8 @@ void setup() {
|
|||||||
the_mesh.startInterface(serial_interface);
|
the_mesh.startInterface(serial_interface);
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
SPIFFS.begin(true);
|
SPIFFS.begin(true);
|
||||||
the_mesh.begin(SPIFFS,
|
store.begin();
|
||||||
|
the_mesh.begin(
|
||||||
#ifdef DISPLAY_CLASS
|
#ifdef DISPLAY_CLASS
|
||||||
disp != NULL
|
disp != NULL
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -699,6 +699,13 @@ int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool BaseChatMesh::getContactByIdx(uint32_t idx, ContactInfo& contact) {
|
||||||
|
if (idx >= num_contacts) return false;
|
||||||
|
|
||||||
|
contact = contacts[idx];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ContactsIterator BaseChatMesh::startContactsIterator() {
|
ContactsIterator BaseChatMesh::startContactsIterator() {
|
||||||
return ContactsIterator();
|
return ContactsIterator();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,7 @@
|
|||||||
|
|
||||||
#define MAX_TEXT_LEN (10*CIPHER_BLOCK_SIZE) // must be LESS than (MAX_PACKET_PAYLOAD - 4 - CIPHER_MAC_SIZE - 1)
|
#define MAX_TEXT_LEN (10*CIPHER_BLOCK_SIZE) // must be LESS than (MAX_PACKET_PAYLOAD - 4 - CIPHER_MAC_SIZE - 1)
|
||||||
|
|
||||||
struct ContactInfo {
|
#include "ContactInfo.h"
|
||||||
mesh::Identity id;
|
|
||||||
char name[32];
|
|
||||||
uint8_t type; // on of ADV_TYPE_*
|
|
||||||
uint8_t flags;
|
|
||||||
int8_t out_path_len;
|
|
||||||
uint8_t out_path[MAX_PATH_SIZE];
|
|
||||||
uint32_t last_advert_timestamp; // by THEIR clock
|
|
||||||
uint8_t shared_secret[PUB_KEY_SIZE];
|
|
||||||
uint32_t lastmod; // by OUR clock
|
|
||||||
int32_t gps_lat, gps_lon; // 6 dec places
|
|
||||||
uint32_t sync_since;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_SEARCH_RESULTS 8
|
#define MAX_SEARCH_RESULTS 8
|
||||||
|
|
||||||
@@ -61,10 +49,7 @@ struct ConnectionInfo {
|
|||||||
uint32_t expected_ack;
|
uint32_t expected_ack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChannelDetails {
|
#include "ChannelDetails.h"
|
||||||
mesh::GroupChannel channel;
|
|
||||||
char name[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief abstract Mesh class for common 'chat' client
|
* \brief abstract Mesh class for common 'chat' client
|
||||||
@@ -158,6 +143,7 @@ public:
|
|||||||
bool removeContact(ContactInfo& contact);
|
bool removeContact(ContactInfo& contact);
|
||||||
bool addContact(const ContactInfo& contact);
|
bool addContact(const ContactInfo& contact);
|
||||||
int getNumContacts() const { return num_contacts; }
|
int getNumContacts() const { return num_contacts; }
|
||||||
|
bool getContactByIdx(uint32_t idx, ContactInfo& contact);
|
||||||
ContactsIterator startContactsIterator();
|
ContactsIterator startContactsIterator();
|
||||||
ChannelDetails* addChannel(const char* name, const char* psk_base64);
|
ChannelDetails* addChannel(const char* name, const char* psk_base64);
|
||||||
bool getChannel(int idx, ChannelDetails& dest);
|
bool getChannel(int idx, ChannelDetails& dest);
|
||||||
|
|||||||
9
src/helpers/ChannelDetails.h
Normal file
9
src/helpers/ChannelDetails.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Mesh.h>
|
||||||
|
|
||||||
|
struct ChannelDetails {
|
||||||
|
mesh::GroupChannel channel;
|
||||||
|
char name[32];
|
||||||
|
};
|
||||||
18
src/helpers/ContactInfo.h
Normal file
18
src/helpers/ContactInfo.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Mesh.h>
|
||||||
|
|
||||||
|
struct ContactInfo {
|
||||||
|
mesh::Identity id;
|
||||||
|
char name[32];
|
||||||
|
uint8_t type; // on of ADV_TYPE_*
|
||||||
|
uint8_t flags;
|
||||||
|
int8_t out_path_len;
|
||||||
|
uint8_t out_path[MAX_PATH_SIZE];
|
||||||
|
uint32_t last_advert_timestamp; // by THEIR clock
|
||||||
|
uint8_t shared_secret[PUB_KEY_SIZE];
|
||||||
|
uint32_t lastmod; // by OUR clock
|
||||||
|
int32_t gps_lat, gps_lon; // 6 dec places
|
||||||
|
uint32_t sync_since;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user