Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/cli_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
- `bw`: Bandwidth in kHz (7.8-500)
- `sf`: Spreading factor (5-12)
- `cr`: Coding rate (5-8)
- `timeout_mins`: Duration in minutes (must be > 0)
- `timeout_mins`: Duration in minutes (must be 1-32767)

**Note:** This is not saved to preferences and will clear on reboot

Expand Down
71 changes: 62 additions & 9 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "TxtDataHelpers.h"
#include "AdvertDataHelpers.h"
#include <RTClib.h>
#include <stdlib.h>

// Believe it or not, this std C function is busted on some platforms!
static uint32_t _atoi(const char* sp) {
Expand All @@ -22,6 +23,58 @@ static bool isValidName(const char *n) {
return true;
}

static bool parseTempradioFloatField(const char*& sp, float& out_val, bool is_last = false) {
while (*sp == ' ' || *sp == '\t') sp++;
if (*sp == 0) return false;

char* ep = nullptr;
out_val = strtof(sp, &ep);
if (ep == sp) return false;

sp = ep;
while (*sp == ' ' || *sp == '\t') sp++;
if (is_last) return *sp == 0;
if (*sp != ',') return false;
sp++;
return true;
}

static bool parseTempradioIntField(const char*& sp, long& out_val, bool is_last = false) {
while (*sp == ' ' || *sp == '\t') sp++;
if (*sp == 0) return false;

char* ep = nullptr;
out_val = strtol(sp, &ep, 10);
if (ep == sp) return false;

sp = ep;
while (*sp == ' ' || *sp == '\t') sp++;
if (is_last) return *sp == 0;
if (*sp != ',') return false;
sp++;
return true;
}

static bool parseTempradioArgs(const char* args, float& freq, float& bw, uint8_t& sf, uint8_t& cr, int& timeout_mins) {
long sf_l = 0;
long cr_l = 0;
long timeout_l = 0;
const char* sp = args;

if (!parseTempradioFloatField(sp, freq)) return false;
if (!parseTempradioFloatField(sp, bw)) return false;
if (!parseTempradioIntField(sp, sf_l)) return false;
if (!parseTempradioIntField(sp, cr_l)) return false;
if (!parseTempradioIntField(sp, timeout_l, true)) return false;
if (sf_l < 0 || sf_l > 255 || cr_l < 0 || cr_l > 255) return false;
if (timeout_l < -32768 || timeout_l > 32767) return false;

sf = (uint8_t)sf_l;
cr = (uint8_t)cr_l;
timeout_mins = (int)timeout_l;
return true;
}

void CommonCLI::loadPrefs(FILESYSTEM* fs) {
if (fs->exists("/com_prefs")) {
loadPrefsInt(fs, "/com_prefs"); // new filename
Expand Down Expand Up @@ -250,15 +303,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
strcpy(reply, "ERR: bad pubkey");
}
} else if (memcmp(command, "tempradio ", 10) == 0) {
strcpy(tmp, &command[10]);
const char *parts[5];
int num = mesh::Utils::parseTextParts(tmp, parts, 5);
float freq = num > 0 ? strtof(parts[0], nullptr) : 0.0f;
float bw = num > 1 ? strtof(parts[1], nullptr) : 0.0f;
uint8_t sf = num > 2 ? atoi(parts[2]) : 0;
uint8_t cr = num > 3 ? atoi(parts[3]) : 0;
int temp_timeout_mins = num > 4 ? atoi(parts[4]) : 0;
if (freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
float freq = 0.0f;
float bw = 0.0f;
uint8_t sf = 0;
uint8_t cr = 0;
int temp_timeout_mins = 0;
bool parsed = parseTempradioArgs(&command[10], freq, bw, sf, cr, temp_timeout_mins);

if (parsed && freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 &&
bw >= 7.0f && bw <= 500.0f && temp_timeout_mins > 0) {
_callbacks->applyTempRadioParams(freq, bw, sf, cr, temp_timeout_mins);
sprintf(reply, "OK - temp params for %d mins", temp_timeout_mins);
} else {
Expand Down