ESP32-PaxCounter/src/rcommand.cpp

435 lines
13 KiB
C++
Raw Normal View History

2018-03-21 18:03:14 +01:00
// Basic Config
2018-03-18 19:45:17 +01:00
#include "globals.h"
2018-07-17 11:53:43 +02:00
#include "rcommand.h"
2018-03-18 19:45:17 +01:00
// Local logging tag
2019-02-27 00:49:32 +01:00
static const char TAG[] = __FILE__;
2018-03-18 19:45:17 +01:00
// set of functions that can be triggered by remote commands
2018-07-31 00:00:24 +02:00
void set_reset(uint8_t val[]) {
switch (val[0]) {
case 0: // restart device with cold start (clear RTC saved variables)
ESP_LOGI(TAG, "Remote command: restart device cold");
do_reset(false);
break;
case 1: // reset MAC counter
ESP_LOGI(TAG, "Remote command: reset MAC counter");
reset_counters(); // clear macs
2018-09-24 16:36:11 +02:00
get_salt(); // get new salt
break;
case 2: // reset device to factory settings
ESP_LOGI(TAG, "Remote command: reset device to factory settings");
eraseConfig();
break;
2018-08-05 12:16:54 +02:00
case 3: // reset send queues
ESP_LOGI(TAG, "Remote command: flush send queue");
flushQueues();
break;
case 4: // restart device with warm start (keep RTC saved variables)
ESP_LOGI(TAG, "Remote command: restart device warm");
do_reset(true);
break;
2018-09-15 18:59:20 +02:00
case 9: // reset and ask for software update via Wifi OTA
ESP_LOGI(TAG, "Remote command: software update via Wifi");
2019-03-09 22:08:57 +01:00
#if (USE_OTA)
2019-10-16 21:14:34 +02:00
RTC_runmode = RUNMODE_UPDATE;
2018-09-24 16:36:11 +02:00
#endif // USE_OTA
2018-09-15 18:59:20 +02:00
break;
2018-09-24 16:36:11 +02:00
2018-08-02 11:33:02 +02:00
default:
ESP_LOGW(TAG, "Remote command: reset called with invalid parameter(s)");
}
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_rssi(uint8_t val[]) {
cfg.rssilimit = val[0] * -1;
ESP_LOGI(TAG, "Remote command: set RSSI limit to %d", cfg.rssilimit);
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_sendcycle(uint8_t val[]) {
cfg.sendcycle = val[0];
2020-10-01 15:39:54 +02:00
// update send cycle interrupt [seconds / 2]
sendTimer.attach(cfg.sendcycle * 2, setSendIRQ);
2018-08-02 11:33:02 +02:00
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
cfg.sendcycle * 2);
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_wifichancycle(uint8_t val[]) {
cfg.wifichancycle = val[0];
// update Wifi channel rotation timer period
2019-02-24 13:35:40 +01:00
xTimerChangePeriod(WifiChanTimer, pdMS_TO_TICKS(cfg.wifichancycle * 10), 100);
2018-07-14 23:38:43 +02:00
ESP_LOGI(TAG,
"Remote command: set Wifi channel switch interval to %.1f seconds",
cfg.wifichancycle / float(100));
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_blescantime(uint8_t val[]) {
cfg.blescantime = val[0];
ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds",
cfg.blescantime / float(100));
// stop & restart BLE scan task to apply new parameter
if (cfg.blescan) {
stop_BLEscan();
start_BLEscan();
}
2018-08-07 22:39:49 +02:00
}
2018-07-31 00:00:24 +02:00
void set_countmode(uint8_t val[]) {
switch (val[0]) {
case 0: // cyclic unconfirmed
cfg.countermode = 0;
ESP_LOGI(TAG, "Remote command: set counter mode to cyclic unconfirmed");
break;
case 1: // cumulative
cfg.countermode = 1;
ESP_LOGI(TAG, "Remote command: set counter mode to cumulative");
break;
2018-08-02 11:33:02 +02:00
case 2: // cyclic confirmed
cfg.countermode = 2;
ESP_LOGI(TAG, "Remote command: set counter mode to cyclic confirmed");
break;
2018-08-02 11:33:02 +02:00
default: // invalid parameter
ESP_LOGW(
TAG,
"Remote command: set counter mode called with invalid parameter(s)");
2018-10-27 22:40:17 +02:00
return;
}
2018-10-27 22:40:17 +02:00
reset_counters(); // clear macs
get_salt(); // get new salt
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_screensaver(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set screen saver to %s ",
val[0] ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.screensaver = val[0] ? 1 : 0;
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_display(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set screen to %s", val[0] ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.screenon = val[0] ? 1 : 0;
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_gps(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set GPS mode to %s", val[0] ? "on" : "off");
2018-11-19 00:41:15 +01:00
if (val[0]) {
cfg.payloadmask |= (uint8_t)GPS_DATA; // set bit in mask
} else {
2019-09-01 00:17:13 +02:00
cfg.payloadmask &= (uint8_t)~GPS_DATA; // clear bit in mask
2018-11-19 00:41:15 +01:00
}
2018-08-02 11:33:02 +02:00
}
2018-06-08 22:41:37 +02:00
void set_bme(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set BME mode to %s", val[0] ? "on" : "off");
if (val[0]) {
cfg.payloadmask |= (uint8_t)MEMS_DATA; // set bit in mask
} else {
2019-09-01 00:17:13 +02:00
cfg.payloadmask &= (uint8_t)~MEMS_DATA; // clear bit in mask
}
}
2019-08-30 18:53:30 +02:00
void set_batt(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set battery mode to %s",
val[0] ? "on" : "off");
if (val[0]) {
cfg.payloadmask |= (uint8_t)BATT_DATA; // set bit in mask
} else {
2019-09-01 00:17:13 +02:00
cfg.payloadmask &= (uint8_t)~BATT_DATA; // clear bit in mask
2019-08-30 18:53:30 +02:00
}
}
void set_payloadmask(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set payload mask to %X", val[0]);
cfg.payloadmask = val[0];
}
2018-11-20 15:44:33 +01:00
void set_sensor(uint8_t val[]) {
#if (HAS_SENSORS)
2018-11-20 15:44:33 +01:00
switch (val[0]) { // check if valid sensor number 1...4
case 1:
case 2:
case 3:
break; // valid sensor number -> continue
default:
ESP_LOGW(
TAG,
"Remote command set sensor mode called with invalid sensor number");
return; // invalid sensor number -> exit
}
ESP_LOGI(TAG, "Remote command: set sensor #%d mode to %s", val[0],
val[1] ? "on" : "off");
if (val[1])
cfg.payloadmask |= sensor_mask(val[0]); // set bit
else
cfg.payloadmask &= ~sensor_mask(val[0]); // clear bit
2018-11-20 21:24:35 +01:00
#endif
2018-11-20 15:44:33 +01:00
}
2018-07-31 00:00:24 +02:00
void set_beacon(uint8_t val[]) {
2018-08-02 11:33:02 +02:00
uint8_t id = val[0]; // use first parameter as beacon storage id
memmove(val, val + 1, 6); // strip off storage id
beacons[id] = macConvert(val); // store beacon MAC in array
ESP_LOGI(TAG, "Remote command: set beacon ID#%d", id);
printKey("MAC", val, 6, false); // show beacon MAC
2018-08-07 22:39:49 +02:00
}
2018-07-31 00:00:24 +02:00
void set_monitor(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set beacon monitor mode to %s",
val ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.monitormode = val[0] ? 1 : 0;
}
2019-09-20 13:22:45 +02:00
void set_loradr(uint8_t val[]) {
#if (HAS_LORA)
2019-09-20 13:22:45 +02:00
if (validDR(val[0])) {
cfg.loradr = val[0];
ESP_LOGI(TAG, "Remote command: set LoRa Datarate to %d", cfg.loradr);
LMIC_setDrTxpow(assertDR(cfg.loradr), KEEP_TXPOW);
2019-09-20 13:22:45 +02:00
ESP_LOGI(TAG, "Radio parameters now %s / %s / %s",
getSfName(updr2rps(LMIC.datarate)),
getBwName(updr2rps(LMIC.datarate)),
getCrName(updr2rps(LMIC.datarate)));
} else
ESP_LOGI(
TAG,
"Remote command: set LoRa Datarate called with illegal datarate %d",
val[0]);
2018-07-14 20:07:33 +02:00
#else
ESP_LOGW(TAG, "Remote command: LoRa not implemented");
#endif // HAS_LORA
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_loraadr(uint8_t val[]) {
#if (HAS_LORA)
2018-07-31 00:00:24 +02:00
ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s",
val[0] ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.adrmode = val[0] ? 1 : 0;
LMIC_setAdrMode(cfg.adrmode);
2018-07-14 20:07:33 +02:00
#else
ESP_LOGW(TAG, "Remote command: LoRa not implemented");
#endif // HAS_LORA
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
2018-07-31 00:00:24 +02:00
void set_blescan(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val[0] ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.blescan = val[0] ? 1 : 0;
if (cfg.blescan)
start_BLEscan();
2018-08-07 22:39:49 +02:00
else {
macs_ble = 0; // clear BLE counter
stop_BLEscan();
}
2018-08-07 22:39:49 +02:00
}
2018-03-18 19:45:17 +01:00
void set_wifiscan(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set WIFI scanner to %s",
val[0] ? "on" : "off");
cfg.wifiscan = val[0] ? 1 : 0;
switch_wifi_sniffer(cfg.wifiscan);
}
2018-07-31 00:00:24 +02:00
void set_wifiant(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s",
2018-07-31 00:00:24 +02:00
val[0] ? "external" : "internal");
2018-08-07 22:39:49 +02:00
cfg.wifiant = val[0] ? 1 : 0;
#ifdef HAS_ANTENNA_SWITCH
antenna_select(cfg.wifiant);
#endif
2018-08-07 22:39:49 +02:00
}
2018-07-31 00:00:24 +02:00
void set_vendorfilter(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s",
2018-07-31 00:00:24 +02:00
val[0] ? "on" : "off");
2018-08-07 22:39:49 +02:00
cfg.vendorfilter = val[0] ? 1 : 0;
}
2018-04-15 12:12:06 +02:00
2018-07-31 00:00:24 +02:00
void set_rgblum(uint8_t val[]) {
// Avoid wrong parameters
2018-07-31 00:00:24 +02:00
cfg.rgblum = (val[0] >= 0 && val[0] <= 100) ? (uint8_t)val[0] : RGBLUMINOSITY;
ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum);
2018-04-02 01:33:49 +02:00
};
2018-07-31 00:00:24 +02:00
void set_lorapower(uint8_t val[]) {
#if (HAS_LORA)
2019-09-20 13:22:45 +02:00
// set data rate and transmit power only if we have no ADR
if (!cfg.adrmode) {
2019-09-20 21:42:59 +02:00
cfg.txpower = val[0];
2019-09-20 13:22:45 +02:00
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", cfg.txpower);
LMIC_setDrTxpow(assertDR(cfg.loradr), cfg.txpower);
} else
ESP_LOGI(
TAG,
"Remote command: set LoRa TXPOWER, not executed because ADR is on");
2018-07-14 20:07:33 +02:00
#else
2018-07-14 23:38:43 +02:00
ESP_LOGW(TAG, "Remote command: LoRa not implemented");
2018-07-14 20:07:33 +02:00
#endif // HAS_LORA
2018-03-18 19:45:17 +01:00
};
2018-07-31 00:00:24 +02:00
void get_config(uint8_t val[]) {
2018-06-16 19:50:36 +02:00
ESP_LOGI(TAG, "Remote command: get device configuration");
payload.reset();
payload.addConfig(cfg);
SendPayload(CONFIGPORT, prio_high);
2018-03-18 19:45:17 +01:00
};
2018-07-31 00:00:24 +02:00
void get_status(uint8_t val[]) {
2018-06-16 19:50:36 +02:00
ESP_LOGI(TAG, "Remote command: get device status");
payload.reset();
payload.addStatus(read_voltage(), uptime() / 1000, temperatureRead(),
getFreeRAM(), rtc_get_reset_reason(0),
rtc_get_reset_reason(1));
SendPayload(STATUSPORT, prio_high);
2018-06-08 22:41:37 +02:00
};
2018-07-31 00:00:24 +02:00
void get_gps(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get gps status");
#if (HAS_GPS)
gpsStatus_t gps_status;
gps_storelocation(&gps_status);
2018-06-16 19:50:36 +02:00
payload.reset();
payload.addGPS(gps_status);
SendPayload(GPSPORT, prio_high);
#else
2018-07-14 23:38:43 +02:00
ESP_LOGW(TAG, "GPS function not supported");
#endif
};
2018-11-17 18:30:19 +01:00
void get_bme(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get bme680 sensor data");
2019-03-13 21:15:28 +01:00
#if (HAS_BME)
2018-11-17 18:30:19 +01:00
payload.reset();
payload.addBME(bme_status);
SendPayload(BMEPORT, prio_high);
2018-11-17 18:30:19 +01:00
#else
2019-03-13 21:15:28 +01:00
ESP_LOGW(TAG, "BME sensor not supported");
2018-11-17 18:30:19 +01:00
#endif
};
2019-08-30 18:53:30 +02:00
void get_batt(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get battery voltage");
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
2019-08-30 18:53:30 +02:00
payload.reset();
payload.addVoltage(read_voltage());
SendPayload(BATTPORT, prio_normal);
#else
ESP_LOGW(TAG, "Battery voltage not supported");
#endif
};
2019-02-24 13:35:40 +01:00
void get_time(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get time");
payload.reset();
2019-02-24 15:04:47 +01:00
payload.addTime(now());
2019-03-31 19:13:06 +02:00
payload.addByte(timeStatus() << 4 | timeSource);
2019-04-06 19:46:00 +02:00
SendPayload(TIMEPORT, prio_high);
2019-02-24 13:35:40 +01:00
};
2019-03-09 22:08:57 +01:00
void set_time(uint8_t val[]) {
ESP_LOGI(TAG, "Timesync requested by timeserver");
setTimeSyncIRQ();
2019-03-09 22:08:57 +01:00
};
void set_flush(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: flush");
// does nothing
// used to open receive window on LoRaWAN class a nodes
};
void set_enscount(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: set ENS_COUNT to %s",
val[0] ? "on" : "off");
cfg.enscount = val[0] ? 1 : 0;
if (val[0])
cfg.payloadmask |= SENSOR1_DATA;
else
cfg.payloadmask &= ~SENSOR1_DATA;
}
// assign previously defined functions to set of numeric remote commands
// format: opcode, function, #bytes params,
// flag (true = do make settings persistent / false = don't)
//
static const cmd_t table[] = {
{0x01, set_rssi, 1, true},
{0x02, set_countmode, 1, true},
{0x03, set_gps, 1, true},
{0x04, set_display, 1, true},
{0x05, set_loradr, 1, true},
{0x06, set_lorapower, 1, true},
{0x07, set_loraadr, 1, true},
{0x08, set_screensaver, 1, true},
{0x09, set_reset, 1, false},
{0x0a, set_sendcycle, 1, true},
{0x0b, set_wifichancycle, 1, true},
{0x0c, set_blescantime, 1, true},
{0x0d, set_vendorfilter, 1, false},
{0x0e, set_blescan, 1, true},
{0x0f, set_wifiant, 1, true},
{0x10, set_rgblum, 1, true},
{0x11, set_monitor, 1, true},
{0x12, set_beacon, 7, false},
{0x13, set_sensor, 2, true},
{0x14, set_payloadmask, 1, true},
{0x15, set_bme, 1, true},
{0x16, set_batt, 1, true},
{0x17, set_wifiscan, 1, true},
{0x18, set_enscount, 1, true},
{0x80, get_config, 0, false},
{0x81, get_status, 0, false},
{0x83, get_batt, 0, false},
{0x84, get_gps, 0, false},
{0x85, get_bme, 0, false},
{0x86, get_time, 0, false},
{0x87, set_time, 0, false},
{0x99, set_flush, 0, false}};
2018-03-18 19:45:17 +01:00
2019-08-31 18:37:36 +02:00
static const uint8_t cmdtablesize =
2018-08-04 18:09:25 +02:00
sizeof(table) / sizeof(table[0]); // number of commands in command table
// check and execute remote command
2019-08-31 15:19:49 +02:00
void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
2018-08-04 18:09:25 +02:00
if (cmdlength == 0)
return;
uint8_t foundcmd[cmdlength], cursor = 0;
bool storeflag = false;
while (cursor < cmdlength) {
2018-08-04 18:09:25 +02:00
int i = cmdtablesize;
while (i--) {
if (cmd[cursor] == table[i].opcode) { // lookup command in opcode table
cursor++; // strip 1 byte opcode
if ((cursor + table[i].params) <= cmdlength) {
memmove(foundcmd, cmd + cursor,
table[i].params); // strip opcode from cmd array
cursor += table[i].params;
if (table[i].store) // ceck if function needs to store configuration
storeflag = true;
table[i].func(
foundcmd); // execute assigned function with given parameters
} else
ESP_LOGI(
TAG,
"Remote command x%02X called with missing parameter(s), skipped",
table[i].opcode);
2018-08-14 22:28:34 +02:00
break; // command found -> exit table lookup loop
} // end of command validation
} // end of command table lookup loop
if (i < 0) { // command not found -> exit parser
ESP_LOGI(TAG, "Unknown remote command x%02X, ignored", cmd[cursor]);
break;
2018-08-14 22:28:34 +02:00
}
} // command parsing loop
2018-08-04 18:09:25 +02:00
if (storeflag)
saveConfig();
} // rcommand()