* companion radio CMD_SET_RADIO_PARAMS
This commit is contained in:
@@ -91,6 +91,7 @@ static uint32_t _atoi(const char* sp) {
|
|||||||
#define CMD_SET_ADVERT_NAME 8
|
#define CMD_SET_ADVERT_NAME 8
|
||||||
#define CMD_ADD_UPDATE_CONTACT 9
|
#define CMD_ADD_UPDATE_CONTACT 9
|
||||||
#define CMD_SYNC_NEXT_MESSAGE 10
|
#define CMD_SYNC_NEXT_MESSAGE 10
|
||||||
|
#define CMD_SET_RADIO_PARAMS 11
|
||||||
|
|
||||||
#define RESP_CODE_OK 0
|
#define RESP_CODE_OK 0
|
||||||
#define RESP_CODE_ERR 1
|
#define RESP_CODE_ERR 1
|
||||||
@@ -110,8 +111,21 @@ static uint32_t _atoi(const char* sp) {
|
|||||||
|
|
||||||
/* -------------------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
struct NodePrefs { // persisted to file
|
||||||
|
float airtime_factor;
|
||||||
|
char node_name[32];
|
||||||
|
double node_lat, node_lon;
|
||||||
|
float freq;
|
||||||
|
uint8_t sf;
|
||||||
|
uint8_t cr;
|
||||||
|
uint8_t reserved1;
|
||||||
|
uint8_t reserved2;
|
||||||
|
float bw;
|
||||||
|
};
|
||||||
|
|
||||||
class MyMesh : public BaseChatMesh {
|
class MyMesh : public BaseChatMesh {
|
||||||
FILESYSTEM* _fs;
|
FILESYSTEM* _fs;
|
||||||
|
NodePrefs _prefs;
|
||||||
uint32_t expected_ack_crc; // TODO: keep table of expected ACKs
|
uint32_t expected_ack_crc; // TODO: keep table of expected ACKs
|
||||||
mesh::GroupChannel* _public;
|
mesh::GroupChannel* _public;
|
||||||
BaseSerialInterface* _serial;
|
BaseSerialInterface* _serial;
|
||||||
@@ -338,31 +352,68 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
char self_name[sizeof(ContactInfo::name)];
|
|
||||||
|
|
||||||
MyMesh(RadioLibWrapper& radio, mesh::RNG& rng, mesh::RTCClock& rtc, SimpleMeshTables& tables)
|
MyMesh(RadioLibWrapper& radio, mesh::RNG& rng, mesh::RTCClock& rtc, SimpleMeshTables& tables)
|
||||||
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables), _serial(NULL)
|
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables), _serial(NULL)
|
||||||
{
|
{
|
||||||
_iter_started = false;
|
_iter_started = false;
|
||||||
|
|
||||||
|
// defaults
|
||||||
|
_prefs.airtime_factor = 1.0; // one half
|
||||||
|
strcpy(_prefs.node_name, "NONAME");
|
||||||
|
_prefs.node_lat = 0;
|
||||||
|
_prefs.node_lon = 0;
|
||||||
|
_prefs.freq = LORA_FREQ;
|
||||||
|
_prefs.sf = LORA_SF;
|
||||||
|
_prefs.bw = LORA_BW;
|
||||||
|
_prefs.cr = LORA_CR;
|
||||||
|
_prefs.reserved1 = 0;
|
||||||
|
_prefs.reserved2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getFreqPref() const { return _prefs.freq; }
|
||||||
|
uint8_t getSFPref() const { return _prefs.sf; }
|
||||||
|
uint8_t getCRPref() const { return _prefs.cr; }
|
||||||
|
float getBWPref() const { return _prefs.bw; }
|
||||||
|
|
||||||
void begin(FILESYSTEM& fs, BaseSerialInterface& serial) {
|
void begin(FILESYSTEM& fs, BaseSerialInterface& serial) {
|
||||||
_fs = &fs;
|
_fs = &fs;
|
||||||
_serial = &serial;
|
_serial = &serial;
|
||||||
|
|
||||||
BaseChatMesh::begin();
|
BaseChatMesh::begin();
|
||||||
|
|
||||||
strcpy(self_name, "UNSET");
|
|
||||||
IdentityStore store(fs, "/identity");
|
IdentityStore store(fs, "/identity");
|
||||||
if (!store.load("_main", self_id, self_name, sizeof(self_name))) {
|
if (!store.load("_main", self_id)) {
|
||||||
self_id = mesh::LocalIdentity(getRNG()); // create new random identity
|
self_id = mesh::LocalIdentity(getRNG()); // create new random identity
|
||||||
store.save("_main", self_id);
|
store.save("_main", self_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load persisted prefs
|
||||||
|
if (_fs->exists("/node_prefs")) {
|
||||||
|
File file = _fs->open("/node_prefs");
|
||||||
|
if (file) {
|
||||||
|
file.read((uint8_t *) &_prefs, sizeof(_prefs));
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadContacts();
|
loadContacts();
|
||||||
_public = addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
|
_public = addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void savePrefs() {
|
||||||
|
#if defined(NRF52_PLATFORM)
|
||||||
|
File file = _fs->open("/node_prefs", FILE_O_WRITE);
|
||||||
|
if (file) { file.seek(0); file.truncate(); }
|
||||||
|
#else
|
||||||
|
File file = _fs->open("/node_prefs", "w", true);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
|
file.write((const uint8_t *)&_prefs, sizeof(_prefs));
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleCmdFrame(size_t len) {
|
void handleCmdFrame(size_t len) {
|
||||||
if (cmd_frame[0] == CMD_APP_START && len >= 8) { // sent when app establishes connection, respond with node ID
|
if (cmd_frame[0] == CMD_APP_START && len >= 8) { // sent when app establishes connection, respond with node ID
|
||||||
uint8_t app_ver = cmd_frame[1];
|
uint8_t app_ver = cmd_frame[1];
|
||||||
@@ -382,8 +433,16 @@ public:
|
|||||||
memcpy(&out_frame[i], &latlonsats, 4); i += 4; // reserved future, for companion radios with GPS (like T-Beam, T1000)
|
memcpy(&out_frame[i], &latlonsats, 4); i += 4; // reserved future, for companion radios with GPS (like T-Beam, T1000)
|
||||||
memcpy(&out_frame[i], &latlonsats, 4); i += 4;
|
memcpy(&out_frame[i], &latlonsats, 4); i += 4;
|
||||||
memcpy(&out_frame[i], &latlonsats, 4); i += 4;
|
memcpy(&out_frame[i], &latlonsats, 4); i += 4;
|
||||||
int tlen = strlen(self_name); // revisit: UTF_8 ??
|
|
||||||
memcpy(&out_frame[i], self_name, tlen); i += tlen;
|
uint32_t freq = _prefs.freq * 1000;
|
||||||
|
memcpy(&out_frame[i], &freq, 4); i += 4;
|
||||||
|
uint32_t bw = _prefs.bw*1000;
|
||||||
|
memcpy(&out_frame[i], &bw, 4); i += 4;
|
||||||
|
out_frame[i++] = _prefs.sf;
|
||||||
|
out_frame[i++] = _prefs.cr;
|
||||||
|
|
||||||
|
int tlen = strlen(_prefs.node_name); // revisit: UTF_8 ??
|
||||||
|
memcpy(&out_frame[i], _prefs.node_name, tlen); i += tlen;
|
||||||
_serial->writeFrame(out_frame, i);
|
_serial->writeFrame(out_frame, i);
|
||||||
} else if (cmd_frame[0] == CMD_SEND_TXT_MSG && len >= 14) {
|
} else if (cmd_frame[0] == CMD_SEND_TXT_MSG && len >= 14) {
|
||||||
int i = 1;
|
int i = 1;
|
||||||
@@ -457,11 +516,10 @@ public:
|
|||||||
}
|
}
|
||||||
} else if (cmd_frame[0] == CMD_SET_ADVERT_NAME && len >= 2) {
|
} else if (cmd_frame[0] == CMD_SET_ADVERT_NAME && len >= 2) {
|
||||||
int nlen = len - 1;
|
int nlen = len - 1;
|
||||||
if (nlen > sizeof(self_name)-1) nlen = sizeof(self_name)-1; // max len
|
if (nlen > sizeof(_prefs.node_name)-1) nlen = sizeof(_prefs.node_name)-1; // max len
|
||||||
memcpy(self_name, &cmd_frame[1], nlen);
|
memcpy(_prefs.node_name, &cmd_frame[1], nlen);
|
||||||
self_name[nlen] = 0;
|
_prefs.node_name[nlen] = 0; // null terminator
|
||||||
IdentityStore store(*_fs, "/identity"); // update IdentityStore
|
savePrefs();
|
||||||
store.save("_main", self_id, self_name);
|
|
||||||
writeOKFrame();
|
writeOKFrame();
|
||||||
} else if (cmd_frame[0] == CMD_GET_DEVICE_TIME) {
|
} else if (cmd_frame[0] == CMD_GET_DEVICE_TIME) {
|
||||||
uint8_t reply[5];
|
uint8_t reply[5];
|
||||||
@@ -480,7 +538,7 @@ public:
|
|||||||
writeErrFrame();
|
writeErrFrame();
|
||||||
}
|
}
|
||||||
} else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) {
|
} else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) {
|
||||||
auto pkt = createSelfAdvert(self_name);
|
auto pkt = createSelfAdvert(_prefs.node_name);
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
|
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
|
||||||
sendFlood(pkt);
|
sendFlood(pkt);
|
||||||
@@ -515,6 +573,25 @@ public:
|
|||||||
if ((out_len = getFromOfflineQueue(out_frame)) > 0) {
|
if ((out_len = getFromOfflineQueue(out_frame)) > 0) {
|
||||||
_serial->writeFrame(out_frame, out_len);
|
_serial->writeFrame(out_frame, out_len);
|
||||||
}
|
}
|
||||||
|
} else if (cmd_frame[0] == CMD_SET_RADIO_PARAMS) {
|
||||||
|
int i = 1;
|
||||||
|
uint32_t freq;
|
||||||
|
memcpy(&freq, &cmd_frame[i], 4); i += 4;
|
||||||
|
uint32_t bw;
|
||||||
|
memcpy(&bw, &cmd_frame[i], 4); i += 4;
|
||||||
|
uint8_t sf = out_frame[i++];
|
||||||
|
uint8_t cr = out_frame[i++];
|
||||||
|
|
||||||
|
if (freq >= 300000 && freq <= 2500000 && sf >= 7 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7000 && bw <= 500000) {
|
||||||
|
_prefs.sf = sf;
|
||||||
|
_prefs.cr = cr;
|
||||||
|
_prefs.freq = (float)freq / 1000.0;
|
||||||
|
_prefs.bw = (float)bw / 1000.0;
|
||||||
|
savePrefs();
|
||||||
|
writeOKFrame(); // reboot now required!
|
||||||
|
} else {
|
||||||
|
writeErrFrame();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
writeErrFrame();
|
writeErrFrame();
|
||||||
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
|
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
|
||||||
@@ -631,6 +708,19 @@ void setup() {
|
|||||||
#else
|
#else
|
||||||
#error "need to define filesystem"
|
#error "need to define filesystem"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (LORA_FREQ != the_mesh.getFreqPref()) {
|
||||||
|
radio.setFrequency(the_mesh.getFreqPref());
|
||||||
|
}
|
||||||
|
if (LORA_SF != the_mesh.getSFPref()) {
|
||||||
|
radio.setSpreadingFactor(the_mesh.getSFPref());
|
||||||
|
}
|
||||||
|
if (LORA_BW != the_mesh.getBWPref()) {
|
||||||
|
radio.setBandwidth(the_mesh.getBWPref());
|
||||||
|
}
|
||||||
|
if (LORA_CR != the_mesh.getCRPref()) {
|
||||||
|
radio.setCodingRate(the_mesh.getCRPref());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
Reference in New Issue
Block a user