* companion radio CMD_SET_RADIO_PARAMS

This commit is contained in:
Scott Powell 2025-02-01 12:43:06 +11:00
parent 7ed2b17b35
commit f9fa913d9e

View file

@ -91,6 +91,7 @@ static uint32_t _atoi(const char* sp) {
#define CMD_SET_ADVERT_NAME 8
#define CMD_ADD_UPDATE_CONTACT 9
#define CMD_SYNC_NEXT_MESSAGE 10
#define CMD_SET_RADIO_PARAMS 11
#define RESP_CODE_OK 0
#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 {
FILESYSTEM* _fs;
NodePrefs _prefs;
uint32_t expected_ack_crc; // TODO: keep table of expected ACKs
mesh::GroupChannel* _public;
BaseSerialInterface* _serial;
@ -338,31 +352,68 @@ protected:
}
public:
char self_name[sizeof(ContactInfo::name)];
MyMesh(RadioLibWrapper& radio, mesh::RNG& rng, mesh::RTCClock& rtc, SimpleMeshTables& tables)
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables), _serial(NULL)
{
_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) {
_fs = &fs;
_serial = &serial;
BaseChatMesh::begin();
strcpy(self_name, "UNSET");
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
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();
_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) {
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];
@ -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;
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);
} else if (cmd_frame[0] == CMD_SEND_TXT_MSG && len >= 14) {
int i = 1;
@ -457,11 +516,10 @@ public:
}
} else if (cmd_frame[0] == CMD_SET_ADVERT_NAME && len >= 2) {
int nlen = len - 1;
if (nlen > sizeof(self_name)-1) nlen = sizeof(self_name)-1; // max len
memcpy(self_name, &cmd_frame[1], nlen);
self_name[nlen] = 0;
IdentityStore store(*_fs, "/identity"); // update IdentityStore
store.save("_main", self_id, self_name);
if (nlen > sizeof(_prefs.node_name)-1) nlen = sizeof(_prefs.node_name)-1; // max len
memcpy(_prefs.node_name, &cmd_frame[1], nlen);
_prefs.node_name[nlen] = 0; // null terminator
savePrefs();
writeOKFrame();
} else if (cmd_frame[0] == CMD_GET_DEVICE_TIME) {
uint8_t reply[5];
@ -480,7 +538,7 @@ public:
writeErrFrame();
}
} else if (cmd_frame[0] == CMD_SEND_SELF_ADVERT) {
auto pkt = createSelfAdvert(self_name);
auto pkt = createSelfAdvert(_prefs.node_name);
if (pkt) {
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
sendFlood(pkt);
@ -515,6 +573,25 @@ public:
if ((out_len = getFromOfflineQueue(out_frame)) > 0) {
_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 {
writeErrFrame();
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
@ -631,6 +708,19 @@ void setup() {
#else
#error "need to define filesystem"
#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() {