feat(cli): support relative minutes in radio schedules
This commit is contained in:
1 parent
7c9cb59400
commit
ff50589b69
8 files changed
+121
-16
No files matched your search
@@ -675,6 +675,23 @@ inline bool parseUnsignedIntegerStrict(const char* text, uint32_t& result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bare values are UTC seconds; +N is N minutes from one command-time snapshot.
|
||||
// Resolve both endpoints against the same snapshot, never end against start.
|
||||
inline bool parseRadioScheduleTime(const char* text, uint32_t now, uint32_t& result) {
|
||||
if (text == nullptr) return false;
|
||||
while (*text == ' ' || *text == '\t') ++text;
|
||||
const bool relative = *text == '+';
|
||||
if (relative && (text[1] < '0' || text[1] > '9')) return false;
|
||||
uint32_t value;
|
||||
if (!parseUnsignedIntegerStrict(relative ? text + 1 : text, value)) return false;
|
||||
if (relative) {
|
||||
if (!value || value > (UINT32_MAX - now) / 60U) return false;
|
||||
value = now + value * 60U;
|
||||
}
|
||||
result = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Zero clears a custom port override; a full broker URI supplies its default.
|
||||
inline bool parseMqttPort(const char* text, uint16_t& result) {
|
||||
uint32_t value;
|
||||
|
||||
@@ -364,7 +364,7 @@ static int countSeparatedParts(const char* s, char separator) {
|
||||
|
||||
static bool parseScheduledRadioArgs(const char* args, bool temporary, float& freq, float& bw,
|
||||
uint8_t& sf, uint8_t& cr, uint32_t& start_time,
|
||||
uint32_t& end_time) {
|
||||
uint32_t& end_time, uint32_t now) {
|
||||
const int expected_parts = temporary ? 6 : 5;
|
||||
args = skipSpacesConst(args);
|
||||
if (countSeparatedParts(args, ',') != expected_parts) {
|
||||
@@ -387,7 +387,7 @@ static bool parseScheduledRadioArgs(const char* args, bool temporary, float& fre
|
||||
|| !mesh::cli::parseDecimalStrict(parts[1], bw)
|
||||
|| !parseUint32Strict(parts[2], sf_u32)
|
||||
|| !parseUint32Strict(parts[3], cr_u32)
|
||||
|| !parseUint32Strict(parts[4], start_time)) {
|
||||
|| !mesh::cli::parseRadioScheduleTime(parts[4], now, start_time)) {
|
||||
return false;
|
||||
}
|
||||
if (sf_u32 > 255 || cr_u32 > 255) {
|
||||
@@ -396,7 +396,7 @@ static bool parseScheduledRadioArgs(const char* args, bool temporary, float& fre
|
||||
|
||||
sf = (uint8_t)sf_u32;
|
||||
cr = (uint8_t)cr_u32;
|
||||
if (temporary && !parseUint32Strict(parts[5], end_time)) {
|
||||
if (temporary && !mesh::cli::parseRadioScheduleTime(parts[5], now, end_time)) {
|
||||
return false;
|
||||
}
|
||||
if (!temporary) {
|
||||
@@ -3854,8 +3854,8 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
uint16_t preamble = 0;
|
||||
char legacy[120];
|
||||
if (!mesh::RadioProfileCLI::parseSuffix(&config[8], 5, legacy, sizeof(legacy), preamble)
|
||||
|| !parseScheduledRadioArgs(legacy, false, freq, bw, sf, cr, start_time, end_time)) {
|
||||
strcpy(reply, "Error, use: set radioat f,bw,sf,cr,start");
|
||||
|| !parseScheduledRadioArgs(legacy, false, freq, bw, sf, cr, start_time, end_time, _rtc->getCurrentTime())) {
|
||||
strcpy(reply, "Error, use: set radioat f,bw,sf,cr,start (UTC or +minutes)");
|
||||
} else if (freq < 150.0f || freq > 2500.0f || sf < 5 || sf > 12 || cr < 5 || cr > 8 || !isValidLoRaBandwidth(bw)
|
||||
|| !_radio_profiles.acceptsPrimary(freq, bw, sf, cr, preamble)) {
|
||||
strcpy(reply, "Error, invalid radio params");
|
||||
@@ -3873,8 +3873,8 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
uint16_t preamble = 0;
|
||||
char legacy[120];
|
||||
if (!mesh::RadioProfileCLI::parseSuffix(&config[12], 6, legacy, sizeof(legacy), preamble)
|
||||
|| !parseScheduledRadioArgs(legacy, true, freq, bw, sf, cr, start_time, end_time)) {
|
||||
strcpy(reply, "Error, use: set tempradioat f,bw,sf,cr,start,end");
|
||||
|| !parseScheduledRadioArgs(legacy, true, freq, bw, sf, cr, start_time, end_time, _rtc->getCurrentTime())) {
|
||||
strcpy(reply, "Error, use: set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)");
|
||||
} else if (freq < 150.0f || freq > 2500.0f || sf < 5 || sf > 12 || cr < 5 || cr > 8 || !isValidLoRaBandwidth(bw)
|
||||
|| !_radio_profiles.acceptsPrimary(freq, bw, sf, cr, preamble)) {
|
||||
strcpy(reply, "Error, invalid radio params");
|
||||
|
||||
@@ -665,17 +665,17 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
&& cli::parseUnsignedIntegerStrict(parts[3], cr) && cr <= 255
|
||||
&& parseMode(parts[4], config.mode);
|
||||
config.params.sf = sf; config.params.cr = cr;
|
||||
const uint32_t epoch = scheduled && rtc_ ? rtc_->getCurrentTime() : 0;
|
||||
if (valid && count > expected) valid = parsePreamble(parts[expected], config.params.preamble);
|
||||
if (valid && temporary) valid = cli::parseUnsignedIntegerStrict(parts[5], minutes) && minutes >= 1 && minutes <= 10080;
|
||||
if (valid && scheduled) valid = cli::parseUnsignedIntegerStrict(parts[5], start);
|
||||
if (valid && scheduled_temp) valid = cli::parseUnsignedIntegerStrict(parts[6], end);
|
||||
if (valid && scheduled) valid = cli::parseRadioScheduleTime(parts[5], epoch, start);
|
||||
if (valid && scheduled_temp) valid = cli::parseRadioScheduleTime(parts[6], epoch, end);
|
||||
if (valid) valid = radio_->validateProfile(config.params);
|
||||
RadioProfiles preview = *radio_->profiles(); preview.setSecondary(config, false);
|
||||
if (valid) valid = preview.automaticPreambleFits();
|
||||
if (!valid) { snprintf(reply, capacity, "Error: use %s f,bw,sf,cr,rx|rxtx%s[,preamble|auto]", key,
|
||||
scheduled_temp ? ",start,end" : scheduled ? ",start" : temporary ? ",minutes" : ""); return true; }
|
||||
scheduled_temp ? ",start,end (UTC or +minutes)" : scheduled ? ",start (UTC or +minutes)" : temporary ? ",minutes" : ""); return true; }
|
||||
if (scheduled) {
|
||||
const uint32_t epoch = rtc_ ? rtc_->getCurrentTime() : 0;
|
||||
if (!epoch || start <= epoch || (uint64_t)(start-epoch) * 1000 > 0x7fffffffULL
|
||||
|| (scheduled_temp && (end <= start || (uint64_t)(end-epoch) * 1000 > 0x7fffffffULL))) {
|
||||
snprintf(reply, capacity, "Error: future UTC start/end required, within 24 days"); return true;
|
||||
|
||||
Reference in new issue
Block a user