mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
171 lines
6.4 KiB
C++
171 lines
6.4 KiB
C++
|
|
#include <Arduino.h>
|
||
|
|
#include "CommonCLI.h"
|
||
|
|
#include "TxtDataHelpers.h"
|
||
|
|
#include <RTClib.h>
|
||
|
|
|
||
|
|
// Believe it or not, this std C function is busted on some platforms!
|
||
|
|
static uint32_t _atoi(const char* sp) {
|
||
|
|
uint32_t n = 0;
|
||
|
|
while (*sp && *sp >= '0' && *sp <= '9') {
|
||
|
|
n *= 10;
|
||
|
|
n += (*sp++ - '0');
|
||
|
|
}
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
|
||
|
|
#define MIN_LOCAL_ADVERT_INTERVAL 60
|
||
|
|
|
||
|
|
void CommonCLI::checkAdvertInterval() {
|
||
|
|
if (_prefs->advert_interval * 2 < MIN_LOCAL_ADVERT_INTERVAL) {
|
||
|
|
_prefs->advert_interval = 0; // turn it off, now that device has been manually configured
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, char* reply) {
|
||
|
|
while (*command == ' ') command++; // skip leading spaces
|
||
|
|
|
||
|
|
if (strlen(command) > 4 && command[2] == '|') { // optional prefix (for companion radio CLI)
|
||
|
|
memcpy(reply, command, 3); // reflect the prefix back
|
||
|
|
reply += 3;
|
||
|
|
command += 3;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (memcmp(command, "reboot", 6) == 0) {
|
||
|
|
_board->reboot(); // doesn't return
|
||
|
|
} else if (memcmp(command, "advert", 6) == 0) {
|
||
|
|
_callbacks->sendSelfAdvertisement(400);
|
||
|
|
strcpy(reply, "OK - Advert sent");
|
||
|
|
} else if (memcmp(command, "clock sync", 10) == 0) {
|
||
|
|
uint32_t curr = getRTCClock()->getCurrentTime();
|
||
|
|
if (sender_timestamp > curr) {
|
||
|
|
getRTCClock()->setCurrentTime(sender_timestamp + 1);
|
||
|
|
strcpy(reply, "OK - clock set");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "ERR: clock cannot go backwards");
|
||
|
|
}
|
||
|
|
} else if (memcmp(command, "start ota", 9) == 0) {
|
||
|
|
if (_board->startOTAUpdate()) {
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "Error");
|
||
|
|
}
|
||
|
|
} else if (memcmp(command, "clock", 5) == 0) {
|
||
|
|
uint32_t now = getRTCClock()->getCurrentTime();
|
||
|
|
DateTime dt = DateTime(now);
|
||
|
|
sprintf(reply, "%02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
|
||
|
|
} else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds)
|
||
|
|
uint32_t secs = _atoi(&command[5]);
|
||
|
|
uint32_t curr = getRTCClock()->getCurrentTime();
|
||
|
|
if (secs > curr) {
|
||
|
|
getRTCClock()->setCurrentTime(secs);
|
||
|
|
strcpy(reply, "(OK - clock set!)");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "(ERR: clock cannot go backwards)");
|
||
|
|
}
|
||
|
|
} else if (memcmp(command, "password ", 9) == 0) {
|
||
|
|
// change admin password
|
||
|
|
StrHelper::strncpy(_prefs->password, &command[9], sizeof(_prefs->password));
|
||
|
|
checkAdvertInterval();
|
||
|
|
savePrefs();
|
||
|
|
sprintf(reply, "password now: %s", _prefs->password); // echo back just to let admin know for sure!!
|
||
|
|
} else if (memcmp(command, "set ", 4) == 0) {
|
||
|
|
const char* config = &command[4];
|
||
|
|
if (memcmp(config, "af ", 3) == 0) {
|
||
|
|
_prefs->airtime_factor = atof(&config[3]);
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else if (memcmp(config, "advert.interval ", 16) == 0) {
|
||
|
|
int mins = _atoi(&config[16]);
|
||
|
|
if (mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) {
|
||
|
|
sprintf(reply, "Error: min is %d mins", MIN_LOCAL_ADVERT_INTERVAL);
|
||
|
|
} else if (mins > 240) {
|
||
|
|
strcpy(reply, "Error: max is 240 mins");
|
||
|
|
} else {
|
||
|
|
_prefs->advert_interval = (uint8_t)(mins / 2);
|
||
|
|
_callbacks->updateAdvertTimer();
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
}
|
||
|
|
} else if (memcmp(config, "guest.password ", 15) == 0) {
|
||
|
|
StrHelper::strncpy(_prefs->guest_password, &config[15], sizeof(_prefs->guest_password));
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else if (memcmp(config, "name ", 5) == 0) {
|
||
|
|
StrHelper::strncpy(_prefs->node_name, &config[5], sizeof(_prefs->node_name));
|
||
|
|
checkAdvertInterval();
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else if (memcmp(config, "repeat ", 7) == 0) {
|
||
|
|
_prefs->disable_fwd = memcmp(&config[7], "off", 3) == 0;
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
|
||
|
|
} else if (memcmp(config, "lat ", 4) == 0) {
|
||
|
|
_prefs->node_lat = atof(&config[4]);
|
||
|
|
checkAdvertInterval();
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else if (memcmp(config, "lon ", 4) == 0) {
|
||
|
|
_prefs->node_lon = atof(&config[4]);
|
||
|
|
checkAdvertInterval();
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else if (memcmp(config, "rxdelay ", 8) == 0) {
|
||
|
|
float db = atof(&config[8]);
|
||
|
|
if (db >= 0) {
|
||
|
|
_prefs->rx_delay_base = db;
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "Error, cannot be negative");
|
||
|
|
}
|
||
|
|
} else if (memcmp(config, "txdelay ", 8) == 0) {
|
||
|
|
float f = atof(&config[8]);
|
||
|
|
if (f >= 0) {
|
||
|
|
_prefs->tx_delay_factor = f;
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "Error, cannot be negative");
|
||
|
|
}
|
||
|
|
} else if (memcmp(config, "direct.txdelay ", 15) == 0) {
|
||
|
|
float f = atof(&config[15]);
|
||
|
|
if (f >= 0) {
|
||
|
|
_prefs->direct_tx_delay_factor = f;
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK");
|
||
|
|
} else {
|
||
|
|
strcpy(reply, "Error, cannot be negative");
|
||
|
|
}
|
||
|
|
} else if (memcmp(config, "tx ", 3) == 0) {
|
||
|
|
_prefs->tx_power_dbm = atoi(&config[3]);
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK - reboot to apply");
|
||
|
|
} else if (sender_timestamp == 0 && memcmp(config, "freq ", 5) == 0) {
|
||
|
|
_prefs->freq = atof(&config[5]);
|
||
|
|
savePrefs();
|
||
|
|
strcpy(reply, "OK - reboot to apply");
|
||
|
|
} else {
|
||
|
|
sprintf(reply, "unknown config: %s", config);
|
||
|
|
}
|
||
|
|
} else if (sender_timestamp == 0 && strcmp(command, "erase") == 0) {
|
||
|
|
bool s = _callbacks->formatFileSystem();
|
||
|
|
sprintf(reply, "File system erase: %s", s ? "OK" : "Err");
|
||
|
|
} else if (memcmp(command, "ver", 3) == 0) {
|
||
|
|
strcpy(reply, _callbacks->getFirmwareVer());
|
||
|
|
} else if (memcmp(command, "log start", 9) == 0) {
|
||
|
|
_callbacks->setLoggingOn(true);
|
||
|
|
strcpy(reply, " logging on");
|
||
|
|
} else if (memcmp(command, "log stop", 8) == 0) {
|
||
|
|
_callbacks->setLoggingOn(false);
|
||
|
|
strcpy(reply, " logging off");
|
||
|
|
} else if (memcmp(command, "log erase", 9) == 0) {
|
||
|
|
_callbacks->eraseLogFile();
|
||
|
|
strcpy(reply, " log erased");
|
||
|
|
} else if (sender_timestamp == 0 && memcmp(command, "log", 3) == 0) {
|
||
|
|
_callbacks->dumpLogFile();
|
||
|
|
strcpy(reply, " EOF");
|
||
|
|
} else {
|
||
|
|
sprintf(reply, "Unknown: %s", command);
|
||
|
|
}
|
||
|
|
}
|