Use shorter CLI validation replies on the constrained Mini
This commit is contained in:
1 parent
c778abceab
commit
cea654cb47
15 files changed
+901
-163
No files matched your search
@@ -1,3 +1,4 @@
|
||||
#include <helpers/CLIReplyText.h>
|
||||
#include "MyMesh.h"
|
||||
#include <helpers/ui/DisplayNightLocation.h>
|
||||
|
||||
@@ -234,7 +235,7 @@ static const char FLOOD_PACKET_FILTER_USAGE[] =
|
||||
#if MESH_ENABLE_FLOOD_RULE_ENGINE
|
||||
"Err - use: set flood.rule[.n] type=<type> [hops=<range>] [...]";
|
||||
#else
|
||||
"Err - use: set flood.filter[.n] <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]";
|
||||
MESH_CLI_REPLY_TEXT("Err - use: set flood.filter[.n] <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]", "Err - set flood.filter[.n] <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]");
|
||||
#endif
|
||||
static const char FLOOD_PACKET_FILTER_DUPLICATE[] =
|
||||
"Err - duplicate filter option";
|
||||
@@ -3173,8 +3174,8 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
|
||||
request_id, packet->radio_profile,
|
||||
packet->radio_generation)) {
|
||||
const char* error = deferred_cli_command.pending
|
||||
? "Err - another remote command is still running"
|
||||
: "Err - remote command is too long";
|
||||
? MESH_CLI_REPLY_TEXT("Err - another remote command is still running", "Err - remote command busy")
|
||||
: MESH_CLI_REPLY_TEXT("Err - remote command is too long", "Err - remote command too long");
|
||||
remote_cli_reply_cache.remember(client->id.pub_key, request_id,
|
||||
command_fingerprint, error);
|
||||
sendRemoteCliReply(client, secret, packet->getPathHashSize(),
|
||||
@@ -4926,15 +4927,15 @@ void MyMesh::addScheduledRadioParams(bool temporary, float freq, float bw, uint8
|
||||
return;
|
||||
}
|
||||
if (start_time <= now) {
|
||||
strcpy(reply, "Error: start is in the past");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error: start is in the past", "Error: start in past"));
|
||||
return;
|
||||
}
|
||||
if (temporary && end_time <= now) {
|
||||
strcpy(reply, "Error: end is in the past");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error: end is in the past", "Error: end in past"));
|
||||
return;
|
||||
}
|
||||
if (temporary && end_time <= start_time) {
|
||||
strcpy(reply, "Error: end must be after start");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error: end must be after start", "Error: end must follow start"));
|
||||
return;
|
||||
}
|
||||
if (countScheduledRadioSettings(temporary) >= MAX_SCHEDULED_RADIO_SETTINGS_PER_TYPE) {
|
||||
@@ -5054,7 +5055,7 @@ void MyMesh::formatScheduledRadioParams(bool temporary, const char* selector, ch
|
||||
|
||||
int wanted = 0;
|
||||
if (!parsePositiveSelector(selector, wanted)) {
|
||||
strcpy(reply, temporary ? "Error, use: get tempradioat [n]" : "Error, use: get radioat [n]");
|
||||
strcpy(reply, temporary ? MESH_CLI_REPLY_TEXT("Error, use: get tempradioat [n]", "Error, get tempradioat [n]") : MESH_CLI_REPLY_TEXT("Error, use: get radioat [n]", "Error, get radioat [n]"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5077,7 +5078,7 @@ void MyMesh::deleteScheduledRadioParams(bool temporary, const char* selector, ch
|
||||
if (!all) {
|
||||
int wanted = 0;
|
||||
if (!parsePositiveSelector(selector, wanted)) {
|
||||
strcpy(reply, temporary ? "Error, use: del tempradioat [n]" : "Error, use: del radioat [n]"); return;
|
||||
strcpy(reply, temporary ? MESH_CLI_REPLY_TEXT("Error, use: del tempradioat [n]", "Error, del tempradioat [n]") : MESH_CLI_REPLY_TEXT("Error, use: del radioat [n]", "Error, del radioat [n]")); return;
|
||||
}
|
||||
idx = findScheduledRadioSettingByIndex(temporary, wanted);
|
||||
if (idx < 0) { strcpy(reply, "Error: not found"); return; }
|
||||
@@ -5122,7 +5123,7 @@ void MyMesh::deleteScheduledRadioParams(bool temporary, const char* selector, ch
|
||||
|
||||
int wanted = 0;
|
||||
if (!parsePositiveSelector(selector, wanted)) {
|
||||
strcpy(reply, temporary ? "Error, use: del tempradioat [n]" : "Error, use: del radioat [n]");
|
||||
strcpy(reply, temporary ? MESH_CLI_REPLY_TEXT("Error, use: del tempradioat [n]", "Error, del tempradioat [n]") : MESH_CLI_REPLY_TEXT("Error, use: del radioat [n]", "Error, del radioat [n]"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5696,7 +5697,7 @@ bool MyMesh::handleGuestCommand(const char* command, char* reply, size_t capacit
|
||||
const char* value = command + 9;
|
||||
while (*value == ' ' || *value == '\t') ++value;
|
||||
if ((get && *value) || (set && strcmp(value, "on") && strcmp(value, "off"))) {
|
||||
snprintf(reply, capacity, "Err - use get guest or set guest on|off");
|
||||
snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("Err - use get guest or set guest on|off", "Err - get guest / set guest on|off"));
|
||||
} else if (get) {
|
||||
snprintf(reply, capacity, "> %s%s", guest_login.enabled() ? "on" : "off",
|
||||
guest_login.healthy() ? "" : " (settings unavailable)");
|
||||
@@ -6391,7 +6392,7 @@ void MyMesh::formatFloodPacketFilterBlacklist(const char* args, char* reply) con
|
||||
uint8_t slot = 0;
|
||||
if (!parseFloodFilterUnsigned(selector, FLOOD_PACKET_FILTER_BLACKLIST_MAX, slot)
|
||||
|| slot == 0 || slot > flood_packet_filter_blacklist_count) {
|
||||
snprintf(reply, 160, "Err - blacklist slot must be 1-%u",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - blacklist slot must be 1-%u", "Err - blacklist slot: 1-%u"),
|
||||
(uint32_t)flood_packet_filter_blacklist_count);
|
||||
return;
|
||||
}
|
||||
@@ -6437,7 +6438,7 @@ void MyMesh::setFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
size_t slot_len = (size_t)(cursor - slot_start);
|
||||
char slot_text[8];
|
||||
if (slot_len == 0 || slot_len >= sizeof(slot_text)) {
|
||||
snprintf(reply, 160, "Err - blacklist slot must be 1-%u",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - blacklist slot must be 1-%u", "Err - blacklist slot: 1-%u"),
|
||||
(uint32_t)FLOOD_PACKET_FILTER_BLACKLIST_MAX);
|
||||
return;
|
||||
}
|
||||
@@ -6446,13 +6447,13 @@ void MyMesh::setFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
uint8_t slot = 0;
|
||||
if (!parseFloodFilterUnsigned(slot_text, FLOOD_PACKET_FILTER_BLACKLIST_MAX, slot)
|
||||
|| slot == 0) {
|
||||
snprintf(reply, 160, "Err - blacklist slot must be 1-%u",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - blacklist slot must be 1-%u", "Err - blacklist slot: 1-%u"),
|
||||
(uint32_t)FLOOD_PACKET_FILTER_BLACKLIST_MAX);
|
||||
return;
|
||||
}
|
||||
requested_slot = slot - 1;
|
||||
if (*cursor != ' ') {
|
||||
strcpy(reply, "Err - expected six-digit repeater ID");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - expected six-digit repeater ID", "Err - repeater ID: six hex digits"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -6463,10 +6464,10 @@ void MyMesh::setFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
uint8_t count = 0;
|
||||
if (!parseFloodPacketFilterBlacklist(cursor, parsed, count)) {
|
||||
if (requested_slot >= 0) {
|
||||
snprintf(reply, 160, "Err - use 1-%d unique six-digit hex IDs separated by commas",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - use 1-%d unique six-digit hex IDs separated by commas", "Err - use 1-%d unique six-digit hex IDs, comma-separated"),
|
||||
FLOOD_PACKET_FILTER_BLACKLIST_REPLACE_MAX);
|
||||
} else {
|
||||
snprintf(reply, 160, "Err - use 1-%d unique six-digit hex IDs separated by commas",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - use 1-%d unique six-digit hex IDs separated by commas", "Err - use 1-%d unique six-digit hex IDs, comma-separated"),
|
||||
FLOOD_PACKET_FILTER_BLACKLIST_REPLACE_MAX);
|
||||
}
|
||||
return;
|
||||
@@ -6478,12 +6479,12 @@ void MyMesh::setFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
|
||||
if (requested_slot >= 0) {
|
||||
if (requested_slot > flood_packet_filter_blacklist_count) {
|
||||
snprintf(reply, 160, "Err - next blacklist slot is %u",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - next blacklist slot is %u", "Err - next blacklist slot: %u"),
|
||||
(uint32_t)flood_packet_filter_blacklist_count + 1U);
|
||||
return;
|
||||
}
|
||||
if ((uint16_t)requested_slot + count > FLOOD_PACKET_FILTER_BLACKLIST_MAX) {
|
||||
snprintf(reply, 160, "Err - blacklist range exceeds slot %u",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - blacklist range exceeds slot %u", "Err - blacklist range past slot %u"),
|
||||
(uint32_t)FLOOD_PACKET_FILTER_BLACKLIST_MAX);
|
||||
return;
|
||||
}
|
||||
@@ -6513,7 +6514,7 @@ void MyMesh::setFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
if (!saveFloodPacketFilterBlacklist()) {
|
||||
flood_packet_filter_blacklist_count = previous_count;
|
||||
memcpy(flood_packet_filter_blacklist, previous, sizeof(previous));
|
||||
strcpy(reply, "Err - unable to save flood filter blacklist");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter blacklist", "Err - flood filter blacklist not saved"));
|
||||
return;
|
||||
}
|
||||
if (requested_slot >= 0) {
|
||||
@@ -6538,7 +6539,7 @@ void MyMesh::deleteFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
if (!delete_all
|
||||
&& (!parseFloodFilterUnsigned(selector, FLOOD_PACKET_FILTER_BLACKLIST_MAX, slot)
|
||||
|| slot == 0 || slot > flood_packet_filter_blacklist_count)) {
|
||||
snprintf(reply, 160, "Err - use: del flood.filter.blacklist[.<1-%u>| all]",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - use: del flood.filter.blacklist[.<1-%u>| all]", "Err - del flood.filter.blacklist[.<1-%u>| all]"),
|
||||
(uint32_t)FLOOD_PACKET_FILTER_BLACKLIST_MAX);
|
||||
return;
|
||||
}
|
||||
@@ -6564,7 +6565,7 @@ void MyMesh::deleteFloodPacketFilterBlacklist(const char* args, char* reply) {
|
||||
if (!saveFloodPacketFilterBlacklist()) {
|
||||
flood_packet_filter_blacklist_count = previous_count;
|
||||
memcpy(flood_packet_filter_blacklist, previous, sizeof(previous));
|
||||
strcpy(reply, "Err - unable to save flood filter blacklist");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter blacklist", "Err - flood filter blacklist not saved"));
|
||||
return;
|
||||
}
|
||||
if (delete_all) {
|
||||
@@ -8330,7 +8331,7 @@ void MyMesh::formatFloodPacketFilters(const char* args, char* reply, bool compac
|
||||
}
|
||||
uint8_t slot;
|
||||
if (!parseFloodFilterUnsigned(selector, flood_packet_filter_slots, slot) || slot == 0) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
formatFloodPacketFilterDetail(slot - 1, reply, 160, compact);
|
||||
@@ -8402,14 +8403,14 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
size_t slot_len = (size_t)(cursor - slot_start);
|
||||
char slot_text[8];
|
||||
if (slot_len == 0 || slot_len >= sizeof(slot_text)) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
memcpy(slot_text, slot_start, slot_len);
|
||||
slot_text[slot_len] = 0;
|
||||
uint8_t slot;
|
||||
if (!parseFloodFilterUnsigned(slot_text, flood_packet_filter_slots, slot) || slot == 0) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
requested_slot = slot - 1;
|
||||
@@ -8464,7 +8465,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
? tokens[0] + strlen("type=")
|
||||
: floodFilterAsciiStartsWith(tokens[0], "t=") ? tokens[0] + 2 : tokens[0];
|
||||
if (!parseFloodFilterPayloadType(type_text, payload_type)) {
|
||||
strcpy(reply, "Err - packet type must be name, any, 0-15, or 0x00-0x0F");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - packet type must be name, any, 0-15, or 0x00-0x0F", "Err - type: name|any|0-15|0x00-0x0F"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8673,7 +8674,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
if (floodFilterAsciiEqual(tokens[i], "tx=slow")) {
|
||||
scope_uses_slow_timing = true;
|
||||
} else if (!floodFilterAsciiEqual(tokens[i], "tx=fast")) {
|
||||
strcpy(reply, "Err - tx timing must be fast or slow");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - tx timing must be fast or slow", "Err - tx: fast|slow"));
|
||||
return;
|
||||
}
|
||||
scope_timing_set = true;
|
||||
@@ -8685,7 +8686,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
}
|
||||
if (!normalizeFloodFilterScopeName(strchr(tokens[i], '=') + 1,
|
||||
scope_name, sizeof(scope_name))) {
|
||||
strcpy(reply, "Err - scope must be a public name of at most 30 characters");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - scope must be a public name of at most 30 characters", "Err - scope: public name, max 30 chars"));
|
||||
return;
|
||||
}
|
||||
target_set = true;
|
||||
@@ -8953,7 +8954,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
if (!saveFloodPacketFilters()) {
|
||||
flood_packet_filters[slot] = previous;
|
||||
flood_channel_data_rule_slot = previous_channel_data_slot;
|
||||
strcpy(reply, "Err - unable to save flood filter");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter", "Err - flood filter not saved"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9003,7 +9004,7 @@ void MyMesh::formatFloodPacketFilters(const char* args, char* reply, bool compac
|
||||
if (*selector != 0) {
|
||||
uint8_t slot;
|
||||
if (!parseFloodFilterUnsigned(selector, flood_packet_filter_slots, slot) || slot == 0) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
formatFloodPacketFilterDetail(slot - 1, reply, 160);
|
||||
@@ -9055,19 +9056,19 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
size_t slot_len = (size_t)(cursor - slot_start);
|
||||
char slot_text[8];
|
||||
if (slot_len == 0 || slot_len >= sizeof(slot_text)) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
memcpy(slot_text, slot_start, slot_len);
|
||||
slot_text[slot_len] = 0;
|
||||
uint8_t slot;
|
||||
if (!parseFloodFilterUnsigned(slot_text, flood_packet_filter_slots, slot) || slot == 0) {
|
||||
snprintf(reply, 160, "Err - filter slot must be 1-%d", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - filter slot must be 1-%d", "Err - filter slot: 1-%d"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
requested_slot = slot - 1;
|
||||
if (*cursor != ' ') {
|
||||
strcpy(reply, "Err - packet type must be name, any, 0-15, or 0x00-0x0F");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - packet type must be name, any, 0-15, or 0x00-0x0F", "Err - type: name|any|0-15|0x00-0x0F"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -9078,7 +9079,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
char params[140];
|
||||
#endif
|
||||
if (strlen(cursor) >= sizeof(params)) {
|
||||
strcpy(reply, "Err - filter parameters too long");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - filter parameters too long", "Err - filter params too long"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9088,7 +9089,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
char* token = params;
|
||||
while (*token != 0) {
|
||||
if (token_count >= 7) {
|
||||
strcpy(reply, "Err - too many flood filter parameters");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - too many flood filter parameters", "Err - excess flood filter parameters"));
|
||||
return;
|
||||
}
|
||||
tokens[token_count++] = token;
|
||||
@@ -9105,7 +9106,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
|
||||
uint8_t payload_type;
|
||||
if (!parseFloodFilterPayloadType(tokens[0], payload_type)) {
|
||||
strcpy(reply, "Err - packet type must be name, any, 0-15, or 0x00-0x0F");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - packet type must be name, any, 0-15, or 0x00-0x0F", "Err - type: name|any|0-15|0x00-0x0F"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9146,7 +9147,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
if (floodFilterAsciiEqual(tokens[i], "tx=slow")) {
|
||||
scope_uses_slow_timing = true;
|
||||
} else if (!floodFilterAsciiEqual(tokens[i], "tx=fast")) {
|
||||
strcpy(reply, "Err - tx timing must be fast or slow");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - tx timing must be fast or slow", "Err - tx: fast|slow"));
|
||||
return;
|
||||
}
|
||||
scope_timing_set = true;
|
||||
@@ -9157,7 +9158,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
}
|
||||
if (!normalizeFloodFilterScopeName(tokens[i] + strlen("scope="),
|
||||
scope_name, sizeof(scope_name))) {
|
||||
strcpy(reply, "Err - scope must be a public name of at most 30 characters");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - scope must be a public name of at most 30 characters", "Err - scope: public name, max 30 chars"));
|
||||
return;
|
||||
}
|
||||
} else if (!hops_set && parseFloodFilterHopSpec(tokens[i], min_hops, max_hops)) {
|
||||
@@ -9168,11 +9169,11 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
}
|
||||
}
|
||||
if (scope_requires_region_match && scope_name[0] == 0) {
|
||||
strcpy(reply, "Err - require=region requires scope=<name>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - require=region requires scope=<name>", "Err - require=region needs scope=<name>"));
|
||||
return;
|
||||
}
|
||||
if (scope_timing_set && scope_name[0] == 0) {
|
||||
strcpy(reply, "Err - tx timing requires scope=<name>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - tx timing requires scope=<name>", "Err - tx needs scope=<name>"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9217,7 +9218,7 @@ void MyMesh::setFloodPacketFilter(const char* args, char* reply,
|
||||
StrHelper::strzcpy(entry.scopeName(), scope_name, sizeof(entry.scopeName()));
|
||||
if (!saveFloodPacketFilters()) {
|
||||
entry = previous;
|
||||
strcpy(reply, "Err - unable to save flood filter");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter", "Err - flood filter not saved"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9232,20 +9233,20 @@ void MyMesh::deleteFloodPacketFilter(const char* args, char* reply) {
|
||||
if (*selector == '.') selector = skipFloodFilterSpaces(selector + 1);
|
||||
if (floodFilterAsciiEqual(selector, "all")) {
|
||||
if (!saveFloodPacketFilters(false, true)) {
|
||||
strcpy(reply, "Err - unable to save flood filter");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter", "Err - flood filter not saved"));
|
||||
} else {
|
||||
if (flood_packet_filters) memset(flood_packet_filters, 0, sizeof(FloodPacketFilterEntry) * flood_packet_filter_slots);
|
||||
#if MESH_ENABLE_FLOOD_RULE_ENGINE
|
||||
flood_channel_data_rule_slot = 0xFF;
|
||||
#endif
|
||||
strcpy(reply, "OK - all flood filters removed");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("OK - all flood filters removed", "OK - flood filters cleared"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t slot;
|
||||
if (!parseFloodFilterUnsigned(selector, flood_packet_filter_slots, slot) || slot == 0) {
|
||||
snprintf(reply, 160, "Err - use: del flood.filter.<1-%d>|all", flood_packet_filter_slots);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - use: del flood.filter.<1-%d>|all", "Err - del flood.filter.<1-%d>|all"), flood_packet_filter_slots);
|
||||
return;
|
||||
}
|
||||
int index = slot - 1;
|
||||
@@ -9266,7 +9267,7 @@ void MyMesh::deleteFloodPacketFilter(const char* args, char* reply) {
|
||||
#if MESH_ENABLE_FLOOD_RULE_ENGINE
|
||||
flood_channel_data_rule_slot = previous_channel_data_slot;
|
||||
#endif
|
||||
strcpy(reply, "Err - unable to save flood filter");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unable to save flood filter", "Err - flood filter not saved"));
|
||||
} else {
|
||||
strcpy(reply, "OK");
|
||||
}
|
||||
@@ -9821,7 +9822,7 @@ static bool parseFloodChannelScopeIndex(const char*& cursor, int& index) {
|
||||
|
||||
void MyMesh::formatFloodChannelScopeDetail(int index, char* reply, size_t reply_len) {
|
||||
if (index < 0 || index >= FLOOD_CHANNEL_SCOPE_SLOTS) {
|
||||
snprintf(reply, reply_len, "Err - scope slot must be 1-%d", FLOOD_CHANNEL_SCOPE_SLOTS);
|
||||
snprintf(reply, reply_len, MESH_CLI_REPLY_TEXT("Err - scope slot must be 1-%d", "Err - scope slot: 1-%d"), FLOOD_CHANNEL_SCOPE_SLOTS);
|
||||
return;
|
||||
}
|
||||
const auto& entry = floodChannelScopes()[index];
|
||||
@@ -9879,7 +9880,7 @@ void MyMesh::formatFloodChannelScopes(const char* args, char* reply) {
|
||||
const char* cursor = args;
|
||||
int index = -1;
|
||||
if (!parseFloodChannelScopeIndex(cursor, index)) {
|
||||
snprintf(reply, 160, "Err - scope slot must be 1-%d", FLOOD_CHANNEL_SCOPE_SLOTS);
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - scope slot must be 1-%d", "Err - scope slot: 1-%d"), FLOOD_CHANNEL_SCOPE_SLOTS);
|
||||
return;
|
||||
}
|
||||
if (*cursor != 0) {
|
||||
@@ -9956,7 +9957,7 @@ void MyMesh::setFloodChannelScope(const char* args, char* reply) {
|
||||
option + (option[0] == 'p' && option[1] == '=' ? 3 : 12),
|
||||
FLOOD_RETRY_BRIDGE_BUCKETS, bucket)
|
||||
|| bucket == 0) {
|
||||
strcpy(reply, "Err - path bucket must be 1-6");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - path bucket must be 1-6", "Err - path bucket: 1-6"));
|
||||
return;
|
||||
}
|
||||
path_set = true;
|
||||
@@ -9981,7 +9982,7 @@ void MyMesh::setFloodChannelScope(const char* args, char* reply) {
|
||||
target_text + strlen("scope="), direct_scope_name,
|
||||
sizeof(direct_scope_name))) {
|
||||
strcpy(reply,
|
||||
"Err - scope must be a public name of at most 30 characters");
|
||||
MESH_CLI_REPLY_TEXT("Err - scope must be a public name of at most 30 characters", "Err - scope: public name, max 30 chars"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -10151,7 +10152,7 @@ void MyMesh::deleteFloodChannelScope(const char* args, char* reply) {
|
||||
void MyMesh::formatFloodChannelScopeRequirementDetail(
|
||||
int index, char* reply, size_t reply_len) const {
|
||||
if (index < 0 || index >= FLOOD_CHANNEL_SCOPE_REQUIRE_SLOTS) {
|
||||
snprintf(reply, reply_len, "Err - require slot must be 1-%d",
|
||||
snprintf(reply, reply_len, MESH_CLI_REPLY_TEXT("Err - require slot must be 1-%d", "Err - require slot: 1-%d"),
|
||||
FLOOD_CHANNEL_SCOPE_REQUIRE_SLOTS);
|
||||
return;
|
||||
}
|
||||
@@ -10174,7 +10175,7 @@ void MyMesh::formatFloodChannelScopeRequirements(const char* args,
|
||||
const char* cursor = args;
|
||||
int index = -1;
|
||||
if (!parseFloodChannelScopeIndex(cursor, index)) {
|
||||
snprintf(reply, 160, "Err - require slot must be 1-%d",
|
||||
snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - require slot must be 1-%d", "Err - require slot: 1-%d"),
|
||||
FLOOD_CHANNEL_SCOPE_REQUIRE_SLOTS);
|
||||
return;
|
||||
}
|
||||
@@ -10219,7 +10220,7 @@ void MyMesh::setFloodChannelScopeRequirement(const char* args, char* reply) {
|
||||
char ignored_name[FLOOD_GROUP_MODERATION_NAME_LEN];
|
||||
if (!parseFloodModerationChannel(channel_text, secret, key_len, hash_prefix,
|
||||
ignored_name, sizeof(ignored_name))) {
|
||||
strcpy(reply, "Err - channel must be public, #name, or 128/256-bit key");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - channel must be public, #name, or 128/256-bit key", "Err - channel: public|#name|128/256-bit key"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12474,7 +12475,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
}
|
||||
|
||||
if (region_load_active && sender && !sender->isAdmin() && !sender->isRegionMgr()) {
|
||||
strcpy(reply, "Err - region load owned by admin/region manager");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - region load owned by admin/region manager", "Err - region load: admin/region manager only"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13194,7 +13195,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
&& mesh::Utils::fromHex(pubkey, (int)(hex_len / 2), hex)) {
|
||||
uint32_t perms;
|
||||
if (!mesh::cli::parseUnsignedIntegerStrict(sp, perms) || perms > UINT8_MAX) {
|
||||
strcpy(reply, "Err - permissions must be 0-255");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - permissions must be 0-255", "Err - permissions: 0-255"));
|
||||
} else if (acl.applyPermissions(self_id, pubkey, (int)(hex_len / 2), static_cast<uint8_t>(perms))) {
|
||||
mesh::scheduleLazyPersistenceMutation(
|
||||
dirty_contacts_expiry, contacts_save_failures,
|
||||
@@ -13240,7 +13241,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
} else if (strncmp(command, "send text.flood ", 16) == 0) {
|
||||
char* text = trimSpaces(command + 16);
|
||||
if (*text == 0) {
|
||||
strcpy(reply, "Err - usage: send text.flood <message>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - usage: send text.flood <message>", "Err - send text.flood <message>"));
|
||||
} else if (sendRepeatersFloodText(text)) {
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
@@ -13275,7 +13276,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
snprintf(reply, 160, "OK - saved off; rx.watchdog=%s",
|
||||
radio_timing.watchdogLabel(_prefs.rx_watchdog_enabled));
|
||||
} else {
|
||||
strcpy(reply, "Err - usage: set rx.watchdog <on|off>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - usage: set rx.watchdog <on|off>", "Err - set rx.watchdog <on|off>"));
|
||||
}
|
||||
} else if (strncmp(command, "set battery.alert ", 18) == 0) {
|
||||
const char* value = command + 18;
|
||||
@@ -13286,22 +13287,22 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
|
||||
if (*region_name) {
|
||||
if (strchr(region_name, ' ') != NULL) {
|
||||
strcpy(reply, "Err - region names cannot contain spaces");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - region names cannot contain spaces", "Err - region name: no spaces"));
|
||||
return;
|
||||
}
|
||||
region = region_map.findByName(region_name);
|
||||
if (region == NULL || region->isWildcard()) {
|
||||
strcpy(reply, "Err - unknown or invalid alert region");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - unknown or invalid alert region", "Err - unknown/invalid alert region"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
region = findNarrowestBatteryAlertRegion(ambiguous);
|
||||
if (region == NULL) {
|
||||
strcpy(reply, "Err - define a usable region before enabling battery alerts");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - define a usable region before enabling battery alerts", "Err - battery alerts need a usable region first"));
|
||||
return;
|
||||
}
|
||||
if (ambiguous) {
|
||||
strcpy(reply, "Err - multiple narrowest regions; specify one");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - multiple narrowest regions; specify one", "Err - specify one of the narrowest regions"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -13324,14 +13325,14 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Err - usage: set battery.alert <on [region]|off>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - usage: set battery.alert <on [region]|off>", "Err - set battery.alert <on [region]|off>"));
|
||||
}
|
||||
} else if (strncmp(command, "set battery.alert.low ", 22) == 0) {
|
||||
uint8_t percent;
|
||||
if (!parseBatteryAlertPercent(command + 22, 1, 100, percent)) {
|
||||
strcpy(reply, "Err - usage: set battery.alert.low <1-100>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - usage: set battery.alert.low <1-100>", "Err - set battery.alert.low <1-100>"));
|
||||
} else if (percent <= _prefs.battery_alert_critical_percent) {
|
||||
strcpy(reply, "Err - low must be greater than critical");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - low must be greater than critical", "Err - low must exceed critical"));
|
||||
} else {
|
||||
_prefs.battery_alert_low_percent = percent;
|
||||
next_battery_alert_check = 0;
|
||||
@@ -13341,9 +13342,9 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, ClientInfo* sender, char *
|
||||
} else if (strncmp(command, "set battery.alert.critical ", 27) == 0) {
|
||||
uint8_t percent;
|
||||
if (!parseBatteryAlertPercent(command + 27, 0, 99, percent)) {
|
||||
strcpy(reply, "Err - usage: set battery.alert.critical <0-99>");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - usage: set battery.alert.critical <0-99>", "Err - set battery.alert.critical <0-99>"));
|
||||
} else if (percent >= _prefs.battery_alert_low_percent) {
|
||||
strcpy(reply, "Err - critical must be less than low");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Err - critical must be less than low", "Err - critical must be below low"));
|
||||
} else {
|
||||
_prefs.battery_alert_critical_percent = percent;
|
||||
next_battery_alert_check = 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "CLIReplyText.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
// Constrained profiles may shorten human CLI prose. Command syntax, structured
|
||||
// replies, protocol acknowledgements, destructive and rollback warnings keep
|
||||
// their exact text.
|
||||
#ifndef MESH_CLI_COMPACT_REPLIES
|
||||
#define MESH_CLI_COMPACT_REPLIES 0
|
||||
#endif
|
||||
|
||||
#if MESH_CLI_COMPACT_REPLIES
|
||||
#define MESH_CLI_REPLY_TEXT(verbose, concise) concise
|
||||
#else
|
||||
#define MESH_CLI_REPLY_TEXT(verbose, concise) verbose
|
||||
#endif
|
||||
+71
-70
@@ -1,3 +1,4 @@
|
||||
#include "CLIReplyText.h"
|
||||
#include <helpers/RegulatorSettings.h>
|
||||
#if defined(USE_LR2021)
|
||||
#include <helpers/radiolib/LR2021CalibrationSettings.h>
|
||||
@@ -262,7 +263,7 @@ bool CommonCLI::applyAndSavePrimaryRadioParams(float freq, float bw, uint8_t sf,
|
||||
uint8_t cr, uint16_t preamble, char* reply) {
|
||||
const int8_t previous_power = _prefs->tx_power_dbm;
|
||||
if (!savePrimaryRadioParams(freq, bw, sf, cr, preamble)) {
|
||||
mesh::cli::formatError(reply, 160, "radio settings could not be saved");
|
||||
mesh::cli::formatError(reply, 160, MESH_CLI_REPLY_TEXT("radio settings could not be saved", "radio settings not saved"));
|
||||
return false;
|
||||
}
|
||||
// Arm the role's reply handoff now, while the originating CLI command is
|
||||
@@ -3691,7 +3692,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
_callbacks->onManualClockSet();
|
||||
uint32_t now = getRTCClock()->getCurrentTime();
|
||||
DateTime dt = DateTime(now);
|
||||
sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("OK - clock set: %02d:%02d - %d/%d/%d UTC", "OK - clock: %02d:%02d - %d/%d/%d UTC"), dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
|
||||
} else {
|
||||
strcpy(reply, "ERR: clock cannot go backwards");
|
||||
}
|
||||
@@ -3866,7 +3867,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
_callbacks->onManualClockSet();
|
||||
uint32_t now = getRTCClock()->getCurrentTime();
|
||||
DateTime dt = DateTime(now);
|
||||
sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("OK - clock set: %02d:%02d - %d/%d/%d UTC", "OK - clock: %02d:%02d - %d/%d/%d UTC"), dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year());
|
||||
} else {
|
||||
strcpy(reply, "(ERR: clock cannot go backwards)");
|
||||
}
|
||||
@@ -3900,7 +3901,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
} else if (memcmp(command, "tempradio ", 10) == 0) {
|
||||
uint16_t preamble = 0;
|
||||
if (!mesh::RadioProfileCLI::parseSuffix(command + 10, 5, tmp, sizeof(tmp), preamble)) {
|
||||
strcpy(reply, "Error, use: tempradio f,bw,sf,cr,minutes[,preamble]"); return;
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use: tempradio f,bw,sf,cr,minutes[,preamble]", "Error, tempradio f,bw,sf,cr,minutes[,preamble]")); return;
|
||||
}
|
||||
const char *parts[5];
|
||||
int num = mesh::Utils::parseTextParts(tmp, parts, 5);
|
||||
@@ -3965,7 +3966,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
_callbacks->clearRecentRepeaters();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, unsupported on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, unsupported on this role", "Error, unsupported role"));
|
||||
}
|
||||
} else if (memcmp(command, "get ", 4) == 0) {
|
||||
handleGetCmd(sender_timestamp, command, reply);
|
||||
@@ -4047,7 +4048,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
|
||||
}
|
||||
} else if (memcmp(command, "sensor set ", 11) == 0) {
|
||||
if (!copyCLIArgument(tmp, sizeof(tmp), &command[11])) {
|
||||
strcpy(reply, "Error, argument too long");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, argument too long", "Error, arg too long"));
|
||||
return;
|
||||
}
|
||||
const char *parts[2];
|
||||
@@ -4391,7 +4392,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0,1, or 2");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0,1, or 2", "Error, 0|1|2"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -4781,18 +4782,18 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
}
|
||||
#endif
|
||||
if (isAdvancedRetryConfig(config) && !_callbacks->supportsAdvancedRetryConfig()) {
|
||||
strcpy(reply, "Error, unsupported on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, unsupported on this role", "Error, unsupported role"));
|
||||
return;
|
||||
}
|
||||
if (isBasicRetryConfig(config) && !_callbacks->supportsBasicRetryConfig()) {
|
||||
strcpy(reply, "Error, retry configuration unsupported on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, retry configuration unsupported on this role", "Error, retry unsupported for role"));
|
||||
return;
|
||||
}
|
||||
if (memcmp(config, "dutycycle ", 10) == 0) {
|
||||
float dc = 0.0f;
|
||||
if (!mesh::cli::parseDecimalStrict(&config[10], dc)
|
||||
|| dc < 1.0f || dc > 100.0f) {
|
||||
strcpy(reply, "ERROR: dutycycle must be 1-100");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERROR: dutycycle must be 1-100", "ERROR: dutycycle 1-100"));
|
||||
} else {
|
||||
_prefs->airtime_factor = (100.0f / dc) - 1.0f;
|
||||
savePrefs();
|
||||
@@ -4816,7 +4817,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
mesh::cli::formatError(reply, 160, "use set system.watchdog on|off");
|
||||
}
|
||||
#else
|
||||
mesh::cli::formatError(reply, 160, "unsupported on this platform");
|
||||
mesh::cli::formatError(reply, 160, MESH_CLI_REPLY_TEXT("unsupported on this platform", "platform unsupported"));
|
||||
#endif
|
||||
} else if (memcmp(config, "af ", 3) == 0) {
|
||||
float factor = 0.0f;
|
||||
@@ -4825,7 +4826,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid airtime factor");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid airtime factor", "Error, bad airtime factor"));
|
||||
}
|
||||
} else if (memcmp(config, "int.thresh ", 11) == 0) {
|
||||
_prefs->interference_threshold = atoi(&config[11]);
|
||||
@@ -4847,7 +4848,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
} else {
|
||||
_prefs->agc_reset_interval = seconds / 4;
|
||||
savePrefs();
|
||||
sprintf(reply, "OK - interval rounded to %d", ((uint32_t) _prefs->agc_reset_interval) * 4);
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("OK - interval rounded to %d", "OK - rounded interval %d"), ((uint32_t) _prefs->agc_reset_interval) * 4);
|
||||
}
|
||||
} else if (memcmp(config, "multi.acks ", 11) == 0) {
|
||||
_prefs->multi_acks = atoi(&config[11]);
|
||||
@@ -4867,7 +4868,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "ERROR: telemetry.access must be all or acl");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERROR: telemetry.access must be all or acl", "ERROR: telemetry.access all|acl"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.advert.interval ", 22) == 0) {
|
||||
uint32_t hours = 0;
|
||||
@@ -4889,7 +4890,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
uint32_t mins = 0;
|
||||
if (!parseUint32Strict(&config[16], mins)
|
||||
|| (mins != 0 && (mins < MIN_LOCAL_ADVERT_INTERVAL || mins > 240))) {
|
||||
sprintf(reply, "Error: interval must be 0 (off) or %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL);
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("Error: interval must be 0 (off) or %d-240 minutes", "Error: interval 0 (off) or %d-240 minutes"), MIN_LOCAL_ADVERT_INTERVAL);
|
||||
} else {
|
||||
const uint8_t previous = _prefs->advert_interval;
|
||||
_prefs->advert_interval = (uint8_t)(mins / 2);
|
||||
@@ -4940,9 +4941,9 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
_prefs->disable_fwd = strcmp(&config[7], "off") == 0;
|
||||
savePrefs();
|
||||
_callbacks->onRetryConfigChanged();
|
||||
strcpy(reply, _prefs->disable_fwd ? "OK - repeat is now OFF" : "OK - repeat is now ON");
|
||||
strcpy(reply, _prefs->disable_fwd ? MESH_CLI_REPLY_TEXT("OK - repeat is now OFF", "OK - repeat OFF") : MESH_CLI_REPLY_TEXT("OK - repeat is now ON", "OK - repeat ON"));
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "radio.rxgain ", 13) == 0) {
|
||||
const char* value = &config[13];
|
||||
@@ -4984,7 +4985,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (changed) _callbacks->recalibrateNoiseFloor();
|
||||
_prefs->radio_fem_rxgain = 1;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK - LoRa FEM RX gain on");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("OK - LoRa FEM RX gain on", "OK - FEM RX gain on"));
|
||||
} else {
|
||||
mesh::cli::formatError(reply, 160, "failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
@@ -4994,7 +4995,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (changed) _callbacks->recalibrateNoiseFloor();
|
||||
_prefs->radio_fem_rxgain = 0;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK - LoRa FEM RX gain off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("OK - LoRa FEM RX gain off", "OK - FEM RX gain off"));
|
||||
} else {
|
||||
mesh::cli::formatError(reply, 160, "failed to apply LoRa FEM RX gain");
|
||||
}
|
||||
@@ -5013,7 +5014,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (_board->setLoRaFemPaGainEnabled(true)) {
|
||||
_prefs->radio_fem_txgain = 1;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK - LoRa FEM TX gain on");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("OK - LoRa FEM TX gain on", "OK - FEM TX gain on"));
|
||||
} else {
|
||||
mesh::cli::formatError(reply, 160, "failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
@@ -5021,7 +5022,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (_board->setLoRaFemPaGainEnabled(false)) {
|
||||
_prefs->radio_fem_txgain = 0;
|
||||
savePrefs();
|
||||
strcpy(reply, "OK - LoRa FEM TX gain off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("OK - LoRa FEM TX gain off", "OK - FEM TX gain off"));
|
||||
} else {
|
||||
mesh::cli::formatError(reply, 160, "failed to apply LoRa FEM TX gain");
|
||||
}
|
||||
@@ -5144,14 +5145,14 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (manual_timings_requested
|
||||
&& (rx_us < RX_POWERSAVING_MIN_MANUAL_PERIOD_US
|
||||
|| sleep_us < RX_POWERSAVING_MIN_MANUAL_PERIOD_US)) {
|
||||
sprintf(reply, "ERROR: range is %lu-%lu us",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("ERROR: range is %lu-%lu us", "ERROR: range %lu-%lu us"),
|
||||
(unsigned long)RX_POWERSAVING_MIN_MANUAL_PERIOD_US,
|
||||
(unsigned long)RX_POWERSAVING_MAX_PERIOD_US);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidRxPowerSavingPeriod(rx_us) || !isValidRxPowerSavingPeriod(sleep_us)) {
|
||||
sprintf(reply, "ERROR: range is %lu-%lu us",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("ERROR: range is %lu-%lu us", "ERROR: range %lu-%lu us"),
|
||||
(unsigned long)RX_POWERSAVING_MIN_MANUAL_PERIOD_US,
|
||||
(unsigned long)RX_POWERSAVING_MAX_PERIOD_US);
|
||||
return;
|
||||
@@ -5223,7 +5224,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
appendRxPowerSavingAdjustmentNote(reply, _prefs, sf, bw);
|
||||
_radio_profiles.appendPrimaryChirpWarning(reply, 160, sf, bw, preamble);
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid radio params");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid radio params", "Error, bad radio params"));
|
||||
}
|
||||
} else if (memcmp(config, "radioat ", 8) == 0) {
|
||||
float freq, bw;
|
||||
@@ -5233,9 +5234,9 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
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, _rtc->getCurrentTime())) {
|
||||
strcpy(reply, "Error, use: set radioat f,bw,sf,cr,start (UTC or +minutes)");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use: set radioat f,bw,sf,cr,start (UTC or +minutes)", "Error, set radioat f,bw,sf,cr,start (UTC or +minutes)"));
|
||||
} else if (!acceptsPrimaryRadioParams(freq, bw, sf, cr, preamble)) {
|
||||
strcpy(reply, "Error, invalid radio params");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid radio params", "Error, bad radio params"));
|
||||
} else {
|
||||
_callbacks->addScheduledRadioParams(false, freq, bw, sf, cr, start_time, end_time, reply, preamble);
|
||||
if (strncmp(reply, "OK", 2) == 0) {
|
||||
@@ -5251,9 +5252,9 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
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, _rtc->getCurrentTime())) {
|
||||
strcpy(reply, "Error, use: set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use: set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)", "Error, set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)"));
|
||||
} else if (!acceptsPrimaryRadioParams(freq, bw, sf, cr, preamble)) {
|
||||
strcpy(reply, "Error, invalid radio params");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid radio params", "Error, bad radio params"));
|
||||
} else {
|
||||
_callbacks->addScheduledRadioParams(true, freq, bw, sf, cr, start_time, end_time, reply, preamble);
|
||||
if (strncmp(reply, "OK", 2) == 0) {
|
||||
@@ -5268,7 +5269,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid latitude");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid latitude", "Error, bad latitude"));
|
||||
}
|
||||
} else if (memcmp(config, "lon ", 4) == 0) {
|
||||
float longitude = 0.0f;
|
||||
@@ -5277,7 +5278,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid longitude");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid longitude", "Error, bad longitude"));
|
||||
}
|
||||
} else if (memcmp(config, "rxdelay ", 8) == 0) {
|
||||
float db = 0.0f;
|
||||
@@ -5287,7 +5288,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-20");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-20", "Error, 0-20"));
|
||||
}
|
||||
} else if (memcmp(config, "txdelay ", 8) == 0) {
|
||||
float f = 0.0f;
|
||||
@@ -5297,7 +5298,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-2");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-2", "Error, 0-2"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.max.unscoped ", 19) == 0) {
|
||||
uint32_t m;
|
||||
@@ -5334,7 +5335,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-2");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-2", "Error, 0-2"));
|
||||
}
|
||||
} else if (memcmp(config, "retry.preset ", 13) == 0) {
|
||||
uint8_t preset;
|
||||
@@ -5343,7 +5344,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
sprintf(reply, "OK - %s", retryPresetName(_prefs->retry_preset));
|
||||
} else {
|
||||
strcpy(reply, "Error, must be infra, rooftop, or mobile");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be infra, rooftop, or mobile", "Error, infra|rooftop|mobile"));
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry ", 13) == 0) {
|
||||
if (strcmp(&config[13], "on") == 0) {
|
||||
@@ -5357,7 +5358,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
_callbacks->onRetryConfigChanged();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.heard ", 19) == 0) {
|
||||
if (strcmp(&config[19], "on") == 0) {
|
||||
@@ -5369,11 +5370,11 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.margin ", 20) == 0) {
|
||||
if (!looksNumeric(&config[20])) {
|
||||
strcpy(reply, "Error, must be 0-40 dB");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-40 dB", "Error, 0-40 dB"));
|
||||
} else {
|
||||
int16_t margin_x4 = parseSnrDbX4(&config[20]);
|
||||
if (margin_x4 >= 0 && margin_x4 <= 160) {
|
||||
@@ -5382,7 +5383,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-40 dB");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-40 dB", "Error, 0-40 dB"));
|
||||
}
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.count ", 19) == 0) {
|
||||
@@ -5393,7 +5394,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 1-15");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 1-15", "Error, 1-15"));
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.base ", 18) == 0) {
|
||||
int base_ms = looksUnsignedInteger(&config[18]) ? _atoi(&config[18]) : -1;
|
||||
@@ -5403,7 +5404,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 10-5000 ms");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 10-5000 ms", "Error, 10-5000 ms"));
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.step ", 18) == 0) {
|
||||
int step_ms = looksUnsignedInteger(&config[18]) ? _atoi(&config[18]) : -1;
|
||||
@@ -5413,7 +5414,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-5000 ms");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-5000 ms", "Error, 0-5000 ms"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.channel.data.hops ", 24) == 0) {
|
||||
uint8_t max_hops;
|
||||
@@ -5422,7 +5423,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be all or 1-7");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be all or 1-7", "Error, all|1-7"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.channel.data ", 19) == 0) {
|
||||
if (strcmp(&config[19], "on") == 0) {
|
||||
@@ -5434,7 +5435,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.count ", 18) == 0) {
|
||||
int attempts = looksUnsignedInteger(&config[18]) ? _atoi(&config[18]) : -1;
|
||||
@@ -5445,7 +5446,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
_callbacks->onRetryConfigChanged();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-15");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-15", "Error, 0-15"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.path ", 17) == 0) {
|
||||
uint8_t path_gate;
|
||||
@@ -5458,7 +5459,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-63 or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-63 or off", "Error, 0-63|off"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.group.path ", 23) == 0) {
|
||||
uint8_t path_gate;
|
||||
@@ -5470,7 +5471,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be 0-63 or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be 0-63 or off", "Error, 0-63|off"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.prefixes ", 21) == 0) {
|
||||
if (parseFloodRetryPrefixList(_prefs->flood_retry_prefixes, FLOOD_RETRY_PREFIX_SLOTS, &config[21])) {
|
||||
@@ -5479,7 +5480,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
strcpy(reply, "OK");
|
||||
}
|
||||
} else {
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("Error, use up to %u comma-separated 3-byte hex prefixes", "Error, max %u comma-separated 3-byte hex prefixes"),
|
||||
(unsigned int)FLOOD_RETRY_PREFIX_SLOTS);
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.ignore ", 19) == 0) {
|
||||
@@ -5488,7 +5489,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("Error, use up to %u comma-separated 3-byte hex prefixes", "Error, max %u comma-separated 3-byte hex prefixes"),
|
||||
(unsigned int)FLOOD_RETRY_IGNORE_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.advert ", 19) == 0) {
|
||||
@@ -5501,7 +5502,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.bridge ", 19) == 0) {
|
||||
if (strcmp(&config[19], "on") == 0) {
|
||||
@@ -5519,7 +5520,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, must be on or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be on or off", "Error, on|off"));
|
||||
}
|
||||
} else if (memcmp(config, "flood.retry.bucket ", 19) == 0) {
|
||||
const char* params = &config[19];
|
||||
@@ -5536,12 +5537,12 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
strcpy(reply, "OK");
|
||||
}
|
||||
} else {
|
||||
sprintf(reply, "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("Error, use up to %u comma-separated 3-byte hex prefixes", "Error, max %u comma-separated 3-byte hex prefixes"),
|
||||
(unsigned int)FLOOD_RETRY_BUCKET_PREFIXES);
|
||||
}
|
||||
} else if (memcmp(config, "direct.retry.cr ", 16) == 0) {
|
||||
if (!copyCLIArgument(tmp, sizeof(tmp), &config[16])) {
|
||||
strcpy(reply, "Error, argument too long");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, argument too long", "Error, arg too long"));
|
||||
return;
|
||||
}
|
||||
if (strcmp(&config[16], "off") == 0) {
|
||||
@@ -5554,7 +5555,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, use on or off on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use on or off on this role", "Error, on|off"));
|
||||
}
|
||||
} else {
|
||||
const char *parts[4];
|
||||
@@ -5573,15 +5574,15 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
} else {
|
||||
strcpy(reply, "Error, SNR must fit -32.00..31.75 dB");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, SNR must fit -32.00..31.75 dB", "Error, SNR -32.00..31.75 dB"));
|
||||
}
|
||||
} else {
|
||||
strcpy(reply, "Error, use CR4,CR5,CR7,CR8 SNRs or off");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use CR4,CR5,CR7,CR8 SNRs or off", "Error, CR4,CR5,CR7,CR8 SNRs|off"));
|
||||
}
|
||||
}
|
||||
} else if (memcmp(config, "recent.repeater ", 16) == 0) {
|
||||
if (!copyCLIArgument(tmp, sizeof(tmp), &config[16])) {
|
||||
strcpy(reply, "Error, argument too long");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, argument too long", "Error, arg too long"));
|
||||
return;
|
||||
}
|
||||
const char *parts[2];
|
||||
@@ -5590,15 +5591,15 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
uint8_t prefix_len = 0;
|
||||
int16_t snr_x4 = 12; // default to +3.0 dB when omitted or invalid
|
||||
if (num < 1 || !parseHashPrefix(parts[0], prefix, prefix_len)) {
|
||||
strcpy(reply, "Error, use: set recent.repeater <hex> [snr_db]");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use: set recent.repeater <hex> [snr_db]", "Error, set recent.repeater <hex> [snr_db]"));
|
||||
} else if (num > 1 && !looksNumeric(parts[1])) {
|
||||
strcpy(reply, "Error, SNR must be numeric");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, SNR must be numeric", "Error, numeric SNR needed"));
|
||||
} else {
|
||||
if (num > 1) {
|
||||
snr_x4 = parseSnrDbX4(parts[1]);
|
||||
}
|
||||
if (snr_x4 < -128 || snr_x4 > 127) {
|
||||
strcpy(reply, "Error, SNR must fit -32.00..31.75 dB");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, SNR must fit -32.00..31.75 dB", "Error, SNR -32.00..31.75 dB"));
|
||||
} else if (_callbacks->setRecentRepeater(prefix, prefix_len, (int8_t)snr_x4)) {
|
||||
char prefix_hex[RECENT_REPEATER_PREFIX_MAX_BYTES * 2 + 1];
|
||||
char snr[12];
|
||||
@@ -5607,7 +5608,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
formatSnrDbX4Short(snr, sizeof(snr), snr_x4);
|
||||
sprintf(reply, "OK - set %s at %s SNR", prefix_hex, snr);
|
||||
} else {
|
||||
strcpy(reply, "Error, table rejected prefix");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, table rejected prefix", "Error, prefix rejected"));
|
||||
}
|
||||
}
|
||||
} else if (memcmp(config, "owner.info ", 11) == 0) {
|
||||
@@ -5633,7 +5634,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
mode = LOOP_DETECT_STRICT;
|
||||
} else {
|
||||
mode = 0xFF;
|
||||
strcpy(reply, "Error, must be: off, minimal, moderate, or strict");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, must be: off, minimal, moderate, or strict", "Error, off|minimal|moderate|strict"));
|
||||
}
|
||||
if (mode != 0xFF) {
|
||||
_prefs->loop_detect = mode;
|
||||
@@ -5647,7 +5648,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
if (!mesh::cli::parseIntegerStrict(&config[3], power)) {
|
||||
mesh::cli::formatError(reply, 160, "invalid TX power");
|
||||
} else if (!mesh::isLoRaTxPowerValid(power, _prefs->freq)) {
|
||||
sprintf(reply, "Error: TX power range is %d to %d dBm",
|
||||
sprintf(reply, MESH_CLI_REPLY_TEXT("Error: TX power range is %d to %d dBm", "Error: TX power %d..%d dBm"),
|
||||
(int)minimum, (int)maximum);
|
||||
} else {
|
||||
applyAndSaveTxPower(static_cast<int8_t>(power), reply);
|
||||
@@ -5659,7 +5660,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
applyAndSavePrimaryRadioParams(freq, _prefs->bw, _prefs->sf, _prefs->cr,
|
||||
_prefs->primary_radio_preamble, reply);
|
||||
} else {
|
||||
strcpy(reply, "Error, invalid frequency");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, invalid frequency", "Error, bad frequency"));
|
||||
}
|
||||
#ifdef WITH_BRIDGE
|
||||
} else if (memcmp(config, "bridge.enabled ", 15) == 0) {
|
||||
@@ -6167,11 +6168,11 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
}
|
||||
#endif
|
||||
if (isAdvancedRetryConfig(config) && !_callbacks->supportsAdvancedRetryConfig()) {
|
||||
strcpy(reply, "Error, unsupported on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, unsupported on this role", "Error, unsupported role"));
|
||||
return;
|
||||
}
|
||||
if (isBasicRetryConfig(config) && !_callbacks->supportsBasicRetryConfig()) {
|
||||
strcpy(reply, "Error, retry configuration unsupported on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, retry configuration unsupported on this role", "Error, retry unsupported for role"));
|
||||
return;
|
||||
}
|
||||
mesh::cli::RecentRepeaterGetQuery recent_query;
|
||||
@@ -6186,7 +6187,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
#if defined(NRF52_PLATFORM)
|
||||
sprintf(reply, "> %s", _prefs->system_watchdog_enabled ? "on" : "off");
|
||||
#else
|
||||
mesh::cli::formatError(reply, 160, "unsupported on this platform");
|
||||
mesh::cli::formatError(reply, 160, MESH_CLI_REPLY_TEXT("unsupported on this platform", "platform unsupported"));
|
||||
#endif
|
||||
} else if (configKeyEquals(config, "af")) {
|
||||
sprintf(reply, "> %s", StrHelper::ftoa(_prefs->airtime_factor));
|
||||
@@ -6357,7 +6358,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
recent_query.search_prefix_len == 0 ? NULL : recent_query.search_prefix,
|
||||
recent_query.search_prefix_len);
|
||||
} else if (recent_query_match == mesh::cli::RecentRepeaterGetMatch::Invalid) {
|
||||
strcpy(reply, "Error, use: get recent.repeaters [page] | search <2|4|6 hex> [page]");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("Error, use: get recent.repeaters [page] | search <2|4|6 hex> [page]", "Error, get recent.repeaters [page] | search <2|4|6 hex> [page]"));
|
||||
} else if (configKeyEquals(config, "owner.info")) {
|
||||
*reply++ = '>';
|
||||
*reply++ = ' ';
|
||||
@@ -6513,7 +6514,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
strcpy(reply, _board->isExternalPowered() ? "> external" : "> battery");
|
||||
#else
|
||||
strcpy(reply, "ERROR: Power management not supported");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERROR: Power management not supported", "ERROR: Power management unsupported"));
|
||||
#endif
|
||||
} else if (configKeyEquals(config, "pwrmgt.bootreason")) {
|
||||
sprintf(reply, "> Reset: %s; Shutdown: %s",
|
||||
@@ -6523,7 +6524,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
sprintf(reply, "> %u mV", _board->getBootVoltage());
|
||||
#else
|
||||
strcpy(reply, "ERROR: Power management not supported");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERROR: Power management not supported", "ERROR: Power management unsupported"));
|
||||
#endif
|
||||
} else if (configKeyEquals(config, "reboot.interval")) {
|
||||
if (_prefs->reboot_interval == 0) {
|
||||
@@ -6608,7 +6609,7 @@ static bool processRegionDefSegment(RegionMap* map, char* tok, RegionEntry** cur
|
||||
|
||||
if (jump) {
|
||||
RegionEntry* j = map->findByNamePrefix(jump);
|
||||
if (j == NULL) { snprintf(reply, 160, "Err - unknown or ambiguous jump: %s", jump); return false; }
|
||||
if (j == NULL) { snprintf(reply, 160, MESH_CLI_REPLY_TEXT("Err - unknown or ambiguous jump: %s", "Err - unknown/ambiguous jump: %s"), jump); return false; }
|
||||
*cursor = j;
|
||||
} else {
|
||||
*cursor = r;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CLIReplyText.h"
|
||||
|
||||
#include "FloodAdvertLimiter.h"
|
||||
#include "FloodCommandAliases.h"
|
||||
#include <Utils.h>
|
||||
@@ -43,7 +45,7 @@ inline bool handleFloodAdvertGet(FloodAdvertLimiter* limiter, const char* comman
|
||||
return true;
|
||||
}
|
||||
if (!limiter) {
|
||||
strcpy(reply, "ERR: advert limiter unavailable on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERR: advert limiter unavailable on this role", "ERR: advert limiter unavailable for role"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,7 +56,7 @@ inline bool handleFloodAdvertGet(FloodAdvertLimiter* limiter, const char* comman
|
||||
if (total == 0 && !detail && number == 1) {
|
||||
strcpy(reply, "> no rate-limited adverts");
|
||||
} else if (offset >= total) {
|
||||
strcpy(reply, "ERR: advert list index out of range");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERR: advert list index out of range", "ERR: advert index out of range"));
|
||||
} else if (detail) {
|
||||
const auto& row = rows[0];
|
||||
char key[PUB_KEY_SIZE * 2 + 1];
|
||||
@@ -100,11 +102,11 @@ inline bool handleFloodAdvertClear(FloodAdvertLimiter* limiter, const char* comm
|
||||
if (*end || !valid) {
|
||||
strcpy(reply, "ERR: clear flood.advert all|<64-hex-key>");
|
||||
} else if (!limiter) {
|
||||
strcpy(reply, "ERR: advert limiter unavailable on this role");
|
||||
strcpy(reply, MESH_CLI_REPLY_TEXT("ERR: advert limiter unavailable on this role", "ERR: advert limiter unavailable for role"));
|
||||
} else {
|
||||
if (all) limiter->reset();
|
||||
else limiter->clear(key);
|
||||
strcpy(reply, all ? "OK - all advert limit history cleared" : "OK - key advert limit history cleared");
|
||||
strcpy(reply, all ? MESH_CLI_REPLY_TEXT("OK - all advert limit history cleared", "OK - all advert history cleared") : MESH_CLI_REPLY_TEXT("OK - key advert limit history cleared", "OK - key advert history cleared"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "CLIReplyText.h"
|
||||
#include "LedSettings.h"
|
||||
#include "CheckedSettingsFile.h"
|
||||
#include <MeshCore.h>
|
||||
@@ -80,12 +81,12 @@ bool handleCommand(const char* command, char* reply, size_t capacity) {
|
||||
if (*value && *value != ' ' && *value != '\t') return false;
|
||||
const char* message;
|
||||
if (get) {
|
||||
message = *value ? "Error: usage get leds" : enabled() ? "> on" : "> off";
|
||||
message = *value ? MESH_CLI_REPLY_TEXT("Error: usage get leds", "Error: get leds") : enabled() ? "> on" : "> off";
|
||||
} else {
|
||||
while (*value == ' ' || *value == '\t') ++value;
|
||||
const bool on = strcmp(value, "on") == 0;
|
||||
if (!on && strcmp(value, "off") != 0) {
|
||||
message = "Error: usage set leds on|off";
|
||||
message = MESH_CLI_REPLY_TEXT("Error: usage set leds on|off", "Error: set leds on|off");
|
||||
} else if (!main_board || !saveSetting(on)) {
|
||||
message = "Error: LED setting save unconfirmed; reboot may differ";
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CLIReplyText.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -315,17 +317,17 @@ inline bool handleCommand(const char* command, char* reply, size_t capacity,
|
||||
if (argument(tail, "on") || argument(tail, "off")) {
|
||||
const bool on = argument(tail, "on");
|
||||
setEnabled(on, now_ms);
|
||||
snprintf(reply, capacity, "OK - power diagnostics %s (RAM only; sleep policy unchanged)",
|
||||
snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("OK - power diagnostics %s (RAM only; sleep policy unchanged)", "OK - power diag %s (RAM only; sleep policy unchanged)"),
|
||||
on ? "on" : "off");
|
||||
} else snprintf(reply, capacity, "Error: use set powersaving.diag on|off");
|
||||
} else snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("Error: use set powersaving.diag on|off", "Error: set powersaving.diag on|off"));
|
||||
return true;
|
||||
}
|
||||
tail = suffix(command, "clear powersaving.diag");
|
||||
if (tail) {
|
||||
if (!*tail) {
|
||||
reset(now_ms);
|
||||
snprintf(reply, capacity, "OK - power diagnostics cleared; sleep policy unchanged");
|
||||
} else snprintf(reply, capacity, "Error: use clear powersaving.diag");
|
||||
snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("OK - power diagnostics cleared; sleep policy unchanged", "OK - power diag cleared; sleep policy unchanged"));
|
||||
} else snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("Error: use clear powersaving.diag", "Error: clear powersaving.diag"));
|
||||
return true;
|
||||
}
|
||||
tail = suffix(command, "get powersaving.diag");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "CLIReplyText.h"
|
||||
#include "RadioProfileCLI.h"
|
||||
#include "CarrierTools.h"
|
||||
#if MESH_ENABLE_CARRIER_TOOLS
|
||||
@@ -1144,7 +1145,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
reply_setting_ = 0xb0 | policy | (force ? 8 : 0);
|
||||
if (!save(saved_, primary_preamble_, cross_)) {
|
||||
reply_setting_ = previous;
|
||||
cli::formatError(reply, capacity, "settings could not be saved");
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("settings could not be saved", "settings not saved"));
|
||||
} else {
|
||||
publish();
|
||||
snprintf(reply, capacity, "OK - tx.reply=%s%s", radioTxPolicyName(policy), force ? " force" : "");
|
||||
@@ -1182,7 +1183,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
} else if (verb == Set && (!strcmp(args, "auto") || !strcmp(args, "on") || !strcmp(args, "off"))) {
|
||||
auto mode = !strcmp(args, "auto") ? RadioCrossMode::Auto : !strcmp(args, "on") ? RadioCrossMode::On : RadioCrossMode::Off;
|
||||
if (save(saved_, primary_preamble_, mode)) { cross_ = mode; publish(); snprintf(reply, capacity, "OK"); }
|
||||
else cli::formatError(reply, capacity, "settings could not be saved");
|
||||
else cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("settings could not be saved", "settings not saved"));
|
||||
} else cli::formatError(reply, capacity, "use get/set radio2.cross [auto|on|off]");
|
||||
return true;
|
||||
}
|
||||
@@ -1249,7 +1250,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
return true;
|
||||
}
|
||||
if (!save({}, primary_preamble_, cross_, 0)) {
|
||||
cli::formatError(reply, capacity, "settings could not be saved"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("settings could not be saved", "settings not saved")); return true;
|
||||
}
|
||||
noteSecondaryManualChange();
|
||||
saved_ = {}; manual_secondary_ = false;
|
||||
@@ -1264,7 +1265,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
if ((base || temporary) && verb == Set && !strcmp(args, "off")) {
|
||||
if (base && !(remote_command_ ? prepareSavedImage(ReplyPath, {}, primary_preamble_, cross_, true)
|
||||
: save({}, primary_preamble_, cross_, true))) {
|
||||
cli::formatError(reply, capacity, "settings could not be saved"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("settings could not be saved", "settings not saved")); return true;
|
||||
}
|
||||
if (remote_command_) {
|
||||
stageRemoteMutation(base ? RemoteMutation::Off : RemoteMutation::TempOff);
|
||||
@@ -1287,7 +1288,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
if (scheduled && (verb == Get || verb == Delete)) {
|
||||
uint32_t index = 0;
|
||||
if (*args && strcmp(args, "all") && (!cli::parseUnsignedIntegerStrict(args, index) || index < 1 || index > 4)) {
|
||||
cli::formatError(reply, capacity, "slot must be 1-4 or all"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("slot must be 1-4 or all", "slot: 1-4|all")); return true;
|
||||
}
|
||||
const unsigned first = scheduled_temp ? 4 : 0;
|
||||
if (verb == Delete) {
|
||||
@@ -1326,7 +1327,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (verb != Set) { cli::formatError(reply, capacity, "invalid radio2 command"); return true; }
|
||||
if (verb != Set) { cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("invalid radio2 command", "bad radio2 command")); return true; }
|
||||
if (base) {
|
||||
const char* preset = cli::radio2PresetTuple(args);
|
||||
if (preset) args = preset;
|
||||
@@ -1354,15 +1355,15 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
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,
|
||||
if (!valid) { snprintf(reply, capacity, MESH_CLI_REPLY_TEXT("Error: use %s f,bw,sf,cr,rx|rxtx%s[,preamble|auto]", "Error: %s f,bw,sf,cr,rx|rxtx%s[,preamble|auto]"), key,
|
||||
scheduled_temp ? ",start,end (UTC or +minutes)" : scheduled ? ",start (UTC or +minutes)" : temporary ? ",minutes" : ""); return true; }
|
||||
if (base && !mediaMeshScopeReady(config)) {
|
||||
cli::formatError(reply, capacity, "MediaMesh region unavailable or full"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("MediaMesh region unavailable or full", "MediaMesh region unavailable/full")); return true;
|
||||
}
|
||||
if (scheduled) {
|
||||
if (!epoch || start <= epoch || (uint64_t)(start-epoch) * 1000 > 0x7fffffffULL
|
||||
|| (scheduled_temp && (end <= start || (uint64_t)(end-epoch) * 1000 > 0x7fffffffULL))) {
|
||||
cli::formatError(reply, capacity, "future UTC start/end required, within 24 days"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("future UTC start/end required, within 24 days", "future UTC start/end within 24 days")); return true;
|
||||
}
|
||||
if (scheduled_temp) {
|
||||
const uint64_t pending_left = temp_pending_
|
||||
@@ -1397,7 +1398,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
snprintf(reply, capacity, "OK - %s %u queued, preamble=%u", key, i+1, preview.preamble(1, 32));
|
||||
appendSecondaryWarnings(reply, capacity, preview); return true;
|
||||
}
|
||||
cli::formatError(reply, capacity, "all four schedule slots occupied"); return true;
|
||||
cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("all four schedule slots occupied", "all four slots full")); return true;
|
||||
}
|
||||
if (temporary) {
|
||||
for (const auto& s : schedules_) if (s.active && s.temporary) {
|
||||
@@ -1429,7 +1430,7 @@ bool RadioProfileCLI::handle(const char* command, char* reply, size_t capacity,
|
||||
}
|
||||
snprintf(reply, capacity, "OK - radio2 %s%s; preamble=%u", modeName(config.mode),
|
||||
remote_command_ ? " pending after reply" : "", preview.preamble(1, 32));
|
||||
} else cli::formatError(reply, capacity, "settings could not be saved");
|
||||
} else cli::formatError(reply, capacity, MESH_CLI_REPLY_TEXT("settings could not be saved", "settings not saved"));
|
||||
if (!strncmp(reply, "OK", 2)) appendSecondaryWarnings(reply, capacity, preview);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "CLIReplyText.h"
|
||||
#include "StorageLayout.h"
|
||||
|
||||
#if defined(ESP32_PLATFORM)
|
||||
@@ -185,7 +186,7 @@ bool handleStorageLayoutGet(const char* config, MainBoard& board, char* reply,
|
||||
if (match == StorageLayoutGetMatch::NotMatched) return false;
|
||||
if (reply == nullptr || reply_size == 0) return true;
|
||||
if (match == StorageLayoutGetMatch::InvalidArguments) {
|
||||
snprintf(reply, reply_size, "Error: use get storage.layout");
|
||||
snprintf(reply, reply_size, MESH_CLI_REPLY_TEXT("Error: use get storage.layout", "Error: get storage.layout"));
|
||||
} else {
|
||||
formatStorageLayout(board, reply, reply_size);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CLIReplyText.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -141,7 +143,7 @@ public:
|
||||
const uint8_t available = backend_ ? backend_->available() : 0;
|
||||
const char* name = command.scope == All ? "2.4ghz" : command.scope == EspNow ? "espnow" : "wifi";
|
||||
if (command.action == Action::Invalid) {
|
||||
snprintf(reply, size, "Error: use set wifi/espnow on|off [force]; set 2.4ghz on [all|force]|off [force]");
|
||||
snprintf(reply, size, MESH_CLI_REPLY_TEXT("Error: use set wifi/espnow on|off [force]; set 2.4ghz on [all|force]|off [force]", "Error: set wifi/espnow on|off [force]; set 2.4ghz on [all|force]|off [force]"));
|
||||
return true;
|
||||
}
|
||||
const uint8_t current = enabled();
|
||||
@@ -158,7 +160,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
if (!(available & command.scope)) {
|
||||
snprintf(reply, size, "Error: requested wireless service unavailable in this build/boot");
|
||||
snprintf(reply, size, MESH_CLI_REPLY_TEXT("Error: requested wireless service unavailable in this build/boot", "Error: wireless service unavailable this build/boot"));
|
||||
return true;
|
||||
}
|
||||
const bool on = command.action == Action::On || command.action == Action::OnAll;
|
||||
@@ -167,7 +169,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
if (command.scope != All && on && master_off_) {
|
||||
snprintf(reply, size, "Error: 2.4ghz is off; use set 2.4ghz on first");
|
||||
snprintf(reply, size, MESH_CLI_REPLY_TEXT("Error: 2.4ghz is off; use set 2.4ghz on first", "Error: 2.4ghz off; set 2.4ghz on first"));
|
||||
return true;
|
||||
}
|
||||
const uint8_t scope = command.scope & available;
|
||||
|
||||
Vendored
+598
@@ -0,0 +1,598 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"profiles": [
|
||||
"wio-e5-mini_repeater"
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, unsupported on this role",
|
||||
"concise": "Error, unsupported role"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, retry configuration unsupported on this role",
|
||||
"concise": "Error, retry unsupported for role"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "ERROR: dutycycle must be 1-100",
|
||||
"concise": "ERROR: dutycycle 1-100"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, invalid airtime factor",
|
||||
"concise": "Error, bad airtime factor"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "ERROR: telemetry.access must be all or acl",
|
||||
"concise": "ERROR: telemetry.access all|acl"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error: interval must be 0 (off) or %d-240 minutes",
|
||||
"concise": "Error: interval 0 (off) or %d-240 minutes"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0,1, or 2",
|
||||
"concise": "Error, 0|1|2"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be on or off",
|
||||
"concise": "Error, on|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-20",
|
||||
"concise": "Error, 0-20"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-2",
|
||||
"concise": "Error, 0-2"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-40 dB",
|
||||
"concise": "Error, 0-40 dB"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 1-15",
|
||||
"concise": "Error, 1-15"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 10-5000 ms",
|
||||
"concise": "Error, 10-5000 ms"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-5000 ms",
|
||||
"concise": "Error, 0-5000 ms"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be all or 1-7",
|
||||
"concise": "Error, all|1-7"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-15",
|
||||
"concise": "Error, 0-15"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be 0-63 or off",
|
||||
"concise": "Error, 0-63|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be infra, rooftop, or mobile",
|
||||
"concise": "Error, infra|rooftop|mobile"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use up to %u comma-separated 3-byte hex prefixes",
|
||||
"concise": "Error, max %u comma-separated 3-byte hex prefixes"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use on or off on this role",
|
||||
"concise": "Error, on|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, SNR must fit -32.00..31.75 dB",
|
||||
"concise": "Error, SNR -32.00..31.75 dB"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use CR4,CR5,CR7,CR8 SNRs or off",
|
||||
"concise": "Error, CR4,CR5,CR7,CR8 SNRs|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, must be: off, minimal, moderate, or strict",
|
||||
"concise": "Error, off|minimal|moderate|strict"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error: TX power range is %d to %d dBm",
|
||||
"concise": "Error: TX power %d..%d dBm"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, invalid radio params",
|
||||
"concise": "Error, bad radio params"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, invalid latitude",
|
||||
"concise": "Error, bad latitude"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, invalid longitude",
|
||||
"concise": "Error, bad longitude"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, table rejected prefix",
|
||||
"concise": "Error, prefix rejected"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Err - unknown or ambiguous jump: %s",
|
||||
"concise": "Err - unknown/ambiguous jump: %s"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "ERROR: Power management not supported",
|
||||
"concise": "ERROR: Power management unsupported"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - repeat is now OFF",
|
||||
"concise": "OK - repeat OFF"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - repeat is now ON",
|
||||
"concise": "OK - repeat ON"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - clock set: %02d:%02d - %d/%d/%d UTC",
|
||||
"concise": "OK - clock: %02d:%02d - %d/%d/%d UTC"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - interval rounded to %d",
|
||||
"concise": "OK - rounded interval %d"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "radio settings could not be saved",
|
||||
"concise": "radio settings not saved"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "unsupported on this platform",
|
||||
"concise": "platform unsupported"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - LoRa FEM RX gain on",
|
||||
"concise": "OK - FEM RX gain on"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - LoRa FEM RX gain off",
|
||||
"concise": "OK - FEM RX gain off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - LoRa FEM TX gain on",
|
||||
"concise": "OK - FEM TX gain on"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "OK - LoRa FEM TX gain off",
|
||||
"concise": "OK - FEM TX gain off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "ERROR: range is %lu-%lu us",
|
||||
"concise": "ERROR: range %lu-%lu us"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, argument too long",
|
||||
"concise": "Error, arg too long"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, SNR must be numeric",
|
||||
"concise": "Error, numeric SNR needed"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, invalid frequency",
|
||||
"concise": "Error, bad frequency"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use: tempradio f,bw,sf,cr,minutes[,preamble]",
|
||||
"concise": "Error, tempradio f,bw,sf,cr,minutes[,preamble]"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use: set radioat f,bw,sf,cr,start (UTC or +minutes)",
|
||||
"concise": "Error, set radioat f,bw,sf,cr,start (UTC or +minutes)"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use: set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)",
|
||||
"concise": "Error, set tempradioat f,bw,sf,cr,start,end (UTC or +minutes)"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use: set recent.repeater <hex> [snr_db]",
|
||||
"concise": "Error, set recent.repeater <hex> [snr_db]"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/CommonCLI.cpp",
|
||||
"verbose": "Error, use: get recent.repeaters [page] | search <2|4|6 hex> [page]",
|
||||
"concise": "Error, get recent.repeaters [page] | search <2|4|6 hex> [page]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - blacklist slot must be 1-%u",
|
||||
"concise": "Err - blacklist slot: 1-%u"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - expected six-digit repeater ID",
|
||||
"concise": "Err - repeater ID: six hex digits"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - use 1-%d unique six-digit hex IDs separated by commas",
|
||||
"concise": "Err - use 1-%d unique six-digit hex IDs, comma-separated"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - next blacklist slot is %u",
|
||||
"concise": "Err - next blacklist slot: %u"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - blacklist range exceeds slot %u",
|
||||
"concise": "Err - blacklist range past slot %u"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - unable to save flood filter blacklist",
|
||||
"concise": "Err - flood filter blacklist not saved"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - filter slot must be 1-%d",
|
||||
"concise": "Err - filter slot: 1-%d"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - packet type must be name, any, 0-15, or 0x00-0x0F",
|
||||
"concise": "Err - type: name|any|0-15|0x00-0x0F"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - tx timing must be fast or slow",
|
||||
"concise": "Err - tx: fast|slow"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - scope must be a public name of at most 30 characters",
|
||||
"concise": "Err - scope: public name, max 30 chars"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - unable to save flood filter",
|
||||
"concise": "Err - flood filter not saved"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - too many flood filter parameters",
|
||||
"concise": "Err - excess flood filter parameters"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - require=region requires scope=<name>",
|
||||
"concise": "Err - require=region needs scope=<name>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - tx timing requires scope=<name>",
|
||||
"concise": "Err - tx needs scope=<name>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - scope slot must be 1-%d",
|
||||
"concise": "Err - scope slot: 1-%d"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - path bucket must be 1-6",
|
||||
"concise": "Err - path bucket: 1-6"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - require slot must be 1-%d",
|
||||
"concise": "Err - require slot: 1-%d"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - channel must be public, #name, or 128/256-bit key",
|
||||
"concise": "Err - channel: public|#name|128/256-bit key"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - permissions must be 0-255",
|
||||
"concise": "Err - permissions: 0-255"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - region names cannot contain spaces",
|
||||
"concise": "Err - region name: no spaces"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - unknown or invalid alert region",
|
||||
"concise": "Err - unknown/invalid alert region"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - define a usable region before enabling battery alerts",
|
||||
"concise": "Err - battery alerts need a usable region first"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - multiple narrowest regions; specify one",
|
||||
"concise": "Err - specify one of the narrowest regions"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - low must be greater than critical",
|
||||
"concise": "Err - low must exceed critical"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - critical must be less than low",
|
||||
"concise": "Err - critical must be below low"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "OK - all flood filters removed",
|
||||
"concise": "OK - flood filters cleared"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - use get guest or set guest on|off",
|
||||
"concise": "Err - get guest / set guest on|off"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - region load owned by admin/region manager",
|
||||
"concise": "Err - region load: admin/region manager only"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error: start is in the past",
|
||||
"concise": "Error: start in past"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error: end is in the past",
|
||||
"concise": "Error: end in past"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error: end must be after start",
|
||||
"concise": "Error: end must follow start"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - another remote command is still running",
|
||||
"concise": "Err - remote command busy"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - remote command is too long",
|
||||
"concise": "Err - remote command too long"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - filter parameters too long",
|
||||
"concise": "Err - filter params too long"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - use: set flood.filter[.n] <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]",
|
||||
"concise": "Err - set flood.filter[.n] <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error, use: get tempradioat [n]",
|
||||
"concise": "Error, get tempradioat [n]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error, use: get radioat [n]",
|
||||
"concise": "Error, get radioat [n]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error, use: del tempradioat [n]",
|
||||
"concise": "Error, del tempradioat [n]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Error, use: del radioat [n]",
|
||||
"concise": "Error, del radioat [n]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - use: del flood.filter.blacklist[.<1-%u>| all]",
|
||||
"concise": "Err - del flood.filter.blacklist[.<1-%u>| all]"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - use: del flood.filter.<1-%d>|all",
|
||||
"concise": "Err - del flood.filter.<1-%d>|all"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - usage: send text.flood <message>",
|
||||
"concise": "Err - send text.flood <message>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - usage: set rx.watchdog <on|off>",
|
||||
"concise": "Err - set rx.watchdog <on|off>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - usage: set battery.alert <on [region]|off>",
|
||||
"concise": "Err - set battery.alert <on [region]|off>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - usage: set battery.alert.low <1-100>",
|
||||
"concise": "Err - set battery.alert.low <1-100>"
|
||||
},
|
||||
{
|
||||
"file": "examples/simple_repeater/MyMesh.cpp",
|
||||
"verbose": "Err - usage: set battery.alert.critical <0-99>",
|
||||
"concise": "Err - set battery.alert.critical <0-99>"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "slot must be 1-4 or all",
|
||||
"concise": "slot: 1-4|all"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "future UTC start/end required, within 24 days",
|
||||
"concise": "future UTC start/end within 24 days"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "all four schedule slots occupied",
|
||||
"concise": "all four slots full"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "settings could not be saved",
|
||||
"concise": "settings not saved"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "invalid radio2 command",
|
||||
"concise": "bad radio2 command"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "MediaMesh region unavailable or full",
|
||||
"concise": "MediaMesh region unavailable/full"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/RadioProfileCLI.cpp",
|
||||
"verbose": "Error: use %s f,bw,sf,cr,rx|rxtx%s[,preamble|auto]",
|
||||
"concise": "Error: %s f,bw,sf,cr,rx|rxtx%s[,preamble|auto]"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/WirelessControl.h",
|
||||
"verbose": "Error: requested wireless service unavailable in this build/boot",
|
||||
"concise": "Error: wireless service unavailable this build/boot"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/WirelessControl.h",
|
||||
"verbose": "Error: 2.4ghz is off; use set 2.4ghz on first",
|
||||
"concise": "Error: 2.4ghz off; set 2.4ghz on first"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/WirelessControl.h",
|
||||
"verbose": "Error: use set wifi/espnow on|off [force]; set 2.4ghz on [all|force]|off [force]",
|
||||
"concise": "Error: set wifi/espnow on|off [force]; set 2.4ghz on [all|force]|off [force]"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/PowerSavingDiagnostics.h",
|
||||
"verbose": "OK - power diagnostics %s (RAM only; sleep policy unchanged)",
|
||||
"concise": "OK - power diag %s (RAM only; sleep policy unchanged)"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/PowerSavingDiagnostics.h",
|
||||
"verbose": "OK - power diagnostics cleared; sleep policy unchanged",
|
||||
"concise": "OK - power diag cleared; sleep policy unchanged"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/PowerSavingDiagnostics.h",
|
||||
"verbose": "Error: use set powersaving.diag on|off",
|
||||
"concise": "Error: set powersaving.diag on|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/PowerSavingDiagnostics.h",
|
||||
"verbose": "Error: use clear powersaving.diag",
|
||||
"concise": "Error: clear powersaving.diag"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/FloodAdvertCLI.h",
|
||||
"verbose": "ERR: advert limiter unavailable on this role",
|
||||
"concise": "ERR: advert limiter unavailable for role"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/FloodAdvertCLI.h",
|
||||
"verbose": "ERR: advert list index out of range",
|
||||
"concise": "ERR: advert index out of range"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/FloodAdvertCLI.h",
|
||||
"verbose": "OK - all advert limit history cleared",
|
||||
"concise": "OK - all advert history cleared"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/FloodAdvertCLI.h",
|
||||
"verbose": "OK - key advert limit history cleared",
|
||||
"concise": "OK - key advert history cleared"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/LedSettings.cpp",
|
||||
"verbose": "Error: usage get leds",
|
||||
"concise": "Error: get leds"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/LedSettings.cpp",
|
||||
"verbose": "Error: usage set leds on|off",
|
||||
"concise": "Error: set leds on|off"
|
||||
},
|
||||
{
|
||||
"file": "src/helpers/StorageLayout.cpp",
|
||||
"verbose": "Error: use get storage.layout",
|
||||
"concise": "Error: get storage.layout"
|
||||
}
|
||||
],
|
||||
"noncompact_tokens_sha256": {
|
||||
"src/helpers/CommonCLI.cpp": "0a3d2e2eabd3e161e352176c4a6a4c4baa184944c08c93b522d4f1ddb5a24edd",
|
||||
"examples/simple_repeater/MyMesh.cpp": "8567eeef2f327100e397c40b0aaf5b675fcdfea254987437d1ca8d005ad3a6f0",
|
||||
"src/helpers/RadioProfileCLI.cpp": "d641d16e872eba3e73b9b5a50f9718c10b0b7da72782f793706ac36b3724a624",
|
||||
"src/helpers/WirelessControl.h": "bbde183f091a8afa7fd65c7b379783f8be2ac4e74ae6037a99a71fde3fb89f1e",
|
||||
"src/helpers/PowerSavingDiagnostics.h": "18b78f5780046ea8c772c4ce6c337741ae0c027039d9399c94c5f4205d114000",
|
||||
"src/helpers/FloodAdvertCLI.h": "0f378e4d0f6c3b9b79991068a4b4208139484d2144ee1d7c5094d39043463be4",
|
||||
"src/helpers/LedSettings.cpp": "df0681234ca1337148ad59caa935857bc692f98bf18603ca6d099c0382028400",
|
||||
"src/helpers/StorageLayout.cpp": "5dd1c8bcbe2902e1f22d14f9ab425465bdc38926fae23989987d850b484cbb18"
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -106,7 +106,7 @@ static void exercise(const std::string& kind, size_t size, bool advanced, bool a
|
||||
const auto input = command(kind, args);
|
||||
cli.run(input.c_str(), reply.data());
|
||||
if (size >= COMMON_CLI_TMP_LEN) {
|
||||
assert(strcmp(reply.data(), "Error, argument too long") == 0);
|
||||
assert(strcmp(reply.data(), MESH_CLI_REPLY_TEXT("Error, argument too long", "Error, arg too long")) == 0);
|
||||
untouched(cli);
|
||||
for (char value : cli.tmp) assert(value == char(0x55));
|
||||
} else if (kind == "sensor" || kind == "gps") {
|
||||
@@ -117,7 +117,7 @@ static void exercise(const std::string& kind, size_t size, bool advanced, bool a
|
||||
} else if (kind == "retry") {
|
||||
assert(cli.callbacks.support_calls == 1);
|
||||
assert(cli.saves == (advanced ? 1U : 0U));
|
||||
assert(strcmp(reply.data(), advanced ? "OK" : "Error, use on or off on this role") == 0);
|
||||
assert(strcmp(reply.data(), advanced ? "OK" : MESH_CLI_REPLY_TEXT("Error, use on or off on this role", "Error, on|off")) == 0);
|
||||
if (advanced) {
|
||||
assert(cli.prefs.direct_retry_cr_enabled == 1);
|
||||
assert(cli.prefs.direct_retry_cr4_snr_x4 == 0 && cli.prefs.direct_retry_cr5_snr_x4 == 0);
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
"""Keep constrained CLI prose separate from commands and protocol replies."""
|
||||
from pathlib import Path
|
||||
import configparser
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FIXTURE = ROOT / 'test/fixtures/cli_reply_text.json'
|
||||
SELECTION = re.compile(
|
||||
r'MESH_CLI_REPLY_TEXT\(("(?:\\.|[^"\\])*"),\s*("(?:\\.|[^"\\])*")\)')
|
||||
TOKENS = re.compile(r'"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|'
|
||||
r'//[^\n]*|/\*.*?\*/|[A-Za-z_][A-Za-z_0-9]*|[^\s]', re.S)
|
||||
|
||||
|
||||
def original_tokens(source):
|
||||
source = re.sub(r'^#include [<"](?:helpers/)?CLIReplyText\.h[>"]\s*\n',
|
||||
'', source, flags=re.M)
|
||||
source = SELECTION.sub(lambda match: match.group(1), source)
|
||||
return '\n'.join(token.group() for token in TOKENS.finditer(source)
|
||||
if not token.group().startswith(('//', '/*'))).encode()
|
||||
|
||||
|
||||
class CliReplyTextTests(unittest.TestCase):
|
||||
def test_only_reviewed_human_literals_change_and_control_flow_stays_exact(self):
|
||||
fixture = json.loads(FIXTURE.read_text())
|
||||
self.assertEqual(fixture['schema'], 1)
|
||||
expected = {}
|
||||
for row in fixture['messages']:
|
||||
expected.setdefault(row['file'], set()).add((row['verbose'], row['concise']))
|
||||
old, new = row['verbose'], row['concise']
|
||||
self.assertLess(len(new), len(old))
|
||||
formats = r'%(?:[-+ #0]*[0-9.*]*[a-zA-Z]+|%)'
|
||||
self.assertEqual(re.findall(formats, old), re.findall(formats, new))
|
||||
category = r'^(Error|ERROR|ERR|Err|OK)(?=[: ,\-])'
|
||||
self.assertEqual(re.findall(category, old), re.findall(category, new))
|
||||
self.assertEqual(re.findall(r'\d+(?:\.\d+)?', old),
|
||||
re.findall(r'\d+(?:\.\d+)?', new))
|
||||
self.assertFalse(old.startswith(('> ', '{', 'KEYBACKUP ', 'ACK')))
|
||||
self.assertNotRegex(old.lower(),
|
||||
r'host|replay|password|login|save unconfirmed|reboot|'
|
||||
r'retained|default|warning|applying in|restore scheduled')
|
||||
if 'unchanged' in old:
|
||||
self.assertIn('sleep policy unchanged', old)
|
||||
self.assertIn('sleep policy unchanged', new)
|
||||
for file, messages in expected.items():
|
||||
source = (ROOT / file).read_text()
|
||||
actual = {(json.loads(match.group(1)), json.loads(match.group(2)))
|
||||
for match in SELECTION.finditer(source)}
|
||||
self.assertEqual(actual, messages, file)
|
||||
# Substituting each original literal recovers every original C++
|
||||
# token, including command tests, branches, calls and arguments.
|
||||
self.assertEqual(hashlib.sha256(original_tokens(source)).hexdigest(),
|
||||
fixture['noncompact_tokens_sha256'][file], file)
|
||||
|
||||
def test_profile_activation_is_explicit_and_default_is_off(self):
|
||||
fixture = json.loads(FIXTURE.read_text())
|
||||
enabled = []
|
||||
for path in [ROOT / 'platformio.ini', *sorted((ROOT / 'variants').rglob('*.ini'))]:
|
||||
config = configparser.ConfigParser(interpolation=None, strict=False)
|
||||
config.read(path)
|
||||
for section in config.sections():
|
||||
if re.search(r'-D\s*MESH_CLI_COMPACT_REPLIES=1\b',
|
||||
config[section].get('build_flags', '')):
|
||||
self.assertTrue(section.startswith('env:'), str(path))
|
||||
enabled.append(section[4:])
|
||||
self.assertEqual(sorted(enabled), sorted(fixture['profiles']))
|
||||
header = (ROOT / 'src/helpers/CLIReplyText.h').read_text()
|
||||
self.assertIn('#ifndef MESH_CLI_COMPACT_REPLIES\n'
|
||||
'#define MESH_CLI_COMPACT_REPLIES 0', header)
|
||||
|
||||
def test_actual_header_selects_exact_text_without_a_runtime_lookup(self):
|
||||
compiler = os.environ.get('CXX') or shutil.which('g++') or shutil.which('clang++')
|
||||
if not compiler:
|
||||
self.skipTest('host C++ compiler required')
|
||||
messages = json.loads(FIXTURE.read_text())['messages']
|
||||
selections = ',\n'.join('MESH_CLI_REPLY_TEXT(%s, %s)' %
|
||||
(json.dumps(row['verbose']), json.dumps(row['concise']))
|
||||
for row in messages)
|
||||
source = ('#include <CLIReplyText.h>\n#include <cstdio>\n'
|
||||
'int main(){const char* text[]={'+selections+'};'
|
||||
'for(const char* line:text)puts(line);}\n')
|
||||
with tempfile.TemporaryDirectory(prefix='cli-reply-text-') as folder:
|
||||
work = Path(folder)
|
||||
(work / 'test.cpp').write_text(source)
|
||||
for flag, key in ((None, 'verbose'), (0, 'verbose'), (1, 'concise')):
|
||||
flags = [] if flag is None else ['-DMESH_CLI_COMPACT_REPLIES='+str(flag)]
|
||||
built = subprocess.run([compiler, '-std=c++11', '-Os', '-Wall', '-Wextra',
|
||||
'-Werror', *flags, '-I'+str(ROOT / 'src/helpers'),
|
||||
str(work / 'test.cpp'), '-o', str(work / 'test')], capture_output=True)
|
||||
self.assertEqual(built.returncode, 0, built.stderr.decode(errors='replace'))
|
||||
result = subprocess.run([str(work / 'test')], capture_output=True)
|
||||
self.assertEqual(result.returncode, 0, result.stderr.decode(errors='replace'))
|
||||
self.assertEqual(result.stdout.decode().splitlines(),
|
||||
[row[key] for row in messages])
|
||||
if flag == 1:
|
||||
image = (work / 'test').read_bytes()
|
||||
selected = {row['concise'] for row in messages}
|
||||
for row in messages:
|
||||
if row['verbose'] not in selected:
|
||||
self.assertNotIn(row['verbose'].encode()+b'\0', image)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -54,12 +54,15 @@ class CommonCLIArgumentBoundsTests(unittest.TestCase):
|
||||
cls.work = tempfile.TemporaryDirectory(prefix="meshcore-cli-argument-bounds-")
|
||||
cls.binaries = {}
|
||||
for name, defines in (("default", []), ("larger", ["-DCOMMON_CLI_TMP_LEN=192"]),
|
||||
("compact", ["-DMESH_CLI_COMPACT_REPLIES=1"]),
|
||||
("legacy", [])):
|
||||
generated = source
|
||||
if name == "legacy":
|
||||
# Restore all three audited unchecked copies as a negative control.
|
||||
error = (r'(?:"Error, argument too long"|MESH_CLI_REPLY_TEXT\('
|
||||
r'"Error, argument too long", "Error, arg too long"\))')
|
||||
pattern = (r'if \(!copyCLIArgument\(tmp, sizeof\(tmp\), (&(?:command|config)\[\d+\])\)\) '
|
||||
r'\{\s*strcpy\(reply, "Error, argument too long"\);\s*return;\s*\}')
|
||||
r'\{\s*strcpy\(reply, ' + error + r'\);\s*return;\s*\}')
|
||||
generated, count = re.subn(pattern, r"strcpy(tmp, \1);", generated)
|
||||
assert count == 3, "review the negative controls after branch changes"
|
||||
directory = Path(cls.work.name)
|
||||
@@ -86,7 +89,7 @@ class CommonCLIArgumentBoundsTests(unittest.TestCase):
|
||||
env=dict(os.environ, ASAN_OPTIONS="detect_leaks=0:abort_on_error=0"))
|
||||
|
||||
def test_production_boundaries_and_rejection_without_effects(self):
|
||||
for variant in ("default", "larger"):
|
||||
for variant in ("default", "larger", "compact"):
|
||||
with self.subTest(variant=variant):
|
||||
result = self.run_case(variant, "production")
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
|
||||
@@ -60,6 +60,7 @@ build_flags = ${lora_e5_mini.build_flags}
|
||||
-D MESH_ENABLE_CLOCK_SYNC=0 ; preserve the 16 KiB filesystem on this 256 KiB part
|
||||
-D MESH_ENABLE_FLOOD_GROUP_MODERATION=0 ; keep core routing and radio scheduling in flash
|
||||
-D MESH_PACKET_LOGGING_COMPACT=1 ; retain complete RX/TX bytes without the duplicate parsed RX line
|
||||
-D MESH_CLI_COMPACT_REPLIES=1 ; concise human prose; command/protocol replies stay intact
|
||||
; User-approved Mini Repeater cuts only; other boards keep their defaults.
|
||||
-D MESH_ENABLE_CARRIER_TOOLS=0
|
||||
-D MESH_ENABLE_MANAGEMENT_REPORTING=0
|
||||
|
||||
Reference in new issue
Block a user