2018-03-18 19:45:17 +01:00
|
|
|
// remote command interpreter
|
|
|
|
// parses multiple number of command / value pairs from LoRaWAN remote command port (RCMDPORT)
|
|
|
|
// checks commands and executes each command with 1 argument per command
|
|
|
|
|
2018-03-21 18:03:14 +01:00
|
|
|
// Basic Config
|
2018-03-18 19:45:17 +01:00
|
|
|
#include "globals.h"
|
|
|
|
|
2018-03-21 23:44:22 +01:00
|
|
|
// LMIC-Arduino LoRaWAN Stack
|
|
|
|
#include <lmic.h>
|
|
|
|
#include <hal/hal.h>
|
|
|
|
|
2018-03-18 19:45:17 +01:00
|
|
|
// Local logging tag
|
2018-06-02 18:28:01 +02:00
|
|
|
static const char TAG[] = "main";
|
2018-03-18 19:45:17 +01:00
|
|
|
|
2018-03-27 12:46:38 +02:00
|
|
|
// table of remote commands and assigned functions
|
|
|
|
typedef struct {
|
2018-04-28 14:09:27 +02:00
|
|
|
const uint8_t nam;
|
|
|
|
void (*func)(uint8_t);
|
2018-03-27 12:46:38 +02:00
|
|
|
const bool store;
|
|
|
|
} cmd_t;
|
|
|
|
|
|
|
|
// function defined in antenna.cpp
|
2018-03-24 13:38:43 +01:00
|
|
|
#ifdef HAS_ANTENNA_SWITCH
|
2018-04-28 14:09:27 +02:00
|
|
|
void antenna_select(const uint8_t _ant);
|
2018-03-24 13:38:43 +01:00
|
|
|
#endif
|
|
|
|
|
2018-06-02 22:23:50 +02:00
|
|
|
// function defined in adcread.cpp
|
|
|
|
#ifdef HAS_BATTERY_PROBE
|
|
|
|
uint32_t read_voltage(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2018-03-27 12:46:38 +02:00
|
|
|
// help function to assign LoRa datarates to numeric spreadfactor values
|
2018-04-28 14:09:27 +02:00
|
|
|
void switch_lora (uint8_t sf, uint8_t tx) {
|
2018-03-18 19:45:17 +01:00
|
|
|
if ( tx > 20 ) return;
|
|
|
|
cfg.txpower = tx;
|
|
|
|
switch (sf) {
|
|
|
|
case 7: LMIC_setDrTxpow(DR_SF7,tx); cfg.lorasf=sf; break;
|
|
|
|
case 8: LMIC_setDrTxpow(DR_SF8,tx); cfg.lorasf=sf; break;
|
|
|
|
case 9: LMIC_setDrTxpow(DR_SF9,tx); cfg.lorasf=sf; break;
|
|
|
|
case 10: LMIC_setDrTxpow(DR_SF10,tx); cfg.lorasf=sf; break;
|
2018-03-24 15:58:12 +01:00
|
|
|
case 11:
|
|
|
|
#if defined(CFG_eu868)
|
|
|
|
LMIC_setDrTxpow(DR_SF11,tx); cfg.lorasf=sf; break;
|
|
|
|
#elif defined(CFG_us915)
|
|
|
|
LMIC_setDrTxpow(DR_SF11CR,tx); cfg.lorasf=sf; break;
|
|
|
|
#endif
|
|
|
|
case 12:
|
|
|
|
#if defined(CFG_eu868)
|
|
|
|
LMIC_setDrTxpow(DR_SF12,tx); cfg.lorasf=sf; break;
|
|
|
|
#elif defined(CFG_us915)
|
|
|
|
LMIC_setDrTxpow(DR_SF12CR,tx); cfg.lorasf=sf; break;
|
|
|
|
#endif
|
2018-03-18 19:45:17 +01:00
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set of functions that can be triggered by remote commands
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_reset(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
switch (val) {
|
|
|
|
case 0: // restart device
|
|
|
|
ESP_LOGI(TAG, "Remote command: restart device");
|
2018-04-16 11:03:12 +02:00
|
|
|
sprintf(display_lora, "Reset pending");
|
2018-03-18 19:45:17 +01:00
|
|
|
vTaskDelay(10000/portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server
|
|
|
|
esp_restart();
|
|
|
|
break;
|
|
|
|
case 1: // reset MAC counter
|
|
|
|
ESP_LOGI(TAG, "Remote command: reset MAC counter");
|
2018-04-19 15:17:23 +02:00
|
|
|
reset_counters(); // clear macs
|
|
|
|
reset_salt(); // get new salt
|
2018-04-16 11:03:12 +02:00
|
|
|
sprintf(display_lora, "Reset counter");
|
2018-03-18 19:45:17 +01:00
|
|
|
break;
|
|
|
|
case 2: // reset device to factory settings
|
|
|
|
ESP_LOGI(TAG, "Remote command: reset device to factory settings");
|
2018-04-16 11:03:12 +02:00
|
|
|
sprintf(display_lora, "Factory reset");
|
2018-03-18 19:45:17 +01:00
|
|
|
eraseConfig();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_rssi(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
cfg.rssilimit = val * -1;
|
2018-04-27 21:29:46 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set RSSI limit to %d", cfg.rssilimit);
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_sendcycle(uint8_t val) {
|
2018-04-28 13:07:35 +02:00
|
|
|
cfg.sendcycle = val;
|
|
|
|
ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds", cfg.sendcycle*2);
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_wifichancycle(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
cfg.wifichancycle = val;
|
2018-04-28 14:09:27 +02:00
|
|
|
// modify wifi channel rotation IRQ
|
|
|
|
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle
|
|
|
|
ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %.1f seconds", cfg.wifichancycle/float(100));
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_blescantime(uint8_t val) {
|
2018-04-02 21:26:22 +02:00
|
|
|
cfg.blescantime = val;
|
2018-05-20 13:50:00 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", cfg.blescantime/float(100));
|
2018-05-19 16:55:18 +02:00
|
|
|
#ifdef BLECOUNTER
|
2018-05-20 13:50:00 +02:00
|
|
|
// stop & restart BLE scan task to apply new parameter
|
|
|
|
if (cfg.blescan)
|
|
|
|
{
|
|
|
|
stop_BLEscan();
|
|
|
|
start_BLEscan();
|
|
|
|
}
|
2018-05-19 16:55:18 +02:00
|
|
|
#endif
|
2018-04-02 21:26:22 +02:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_countmode(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
switch (val) {
|
|
|
|
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;
|
|
|
|
default: // cyclic confirmed
|
|
|
|
cfg.countermode = 2;
|
|
|
|
ESP_LOGI(TAG, "Remote command: set counter mode to cyclic confirmed");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_screensaver(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off");
|
|
|
|
switch (val) {
|
|
|
|
case 1: cfg.screensaver = val; break;
|
|
|
|
default: cfg.screensaver = 0; break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_display(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off");
|
|
|
|
switch (val) {
|
|
|
|
case 1: cfg.screenon = val; break;
|
|
|
|
default: cfg.screenon = 0; break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_lorasf(uint8_t val) {
|
2018-04-27 21:29:46 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set LoRa SF to %d", val);
|
2018-03-18 19:45:17 +01:00
|
|
|
switch_lora(val, cfg.txpower);
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_loraadr(uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off");
|
|
|
|
switch (val) {
|
|
|
|
case 1: cfg.adrmode = val; break;
|
|
|
|
default: cfg.adrmode = 0; break;
|
|
|
|
}
|
|
|
|
LMIC_setAdrMode(cfg.adrmode);
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_blescan(uint8_t val) {
|
2018-05-20 13:50:00 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val ? "on" : "off");
|
2018-03-18 19:45:17 +01:00
|
|
|
switch (val) {
|
2018-04-16 22:48:00 +02:00
|
|
|
case 0:
|
2018-04-19 10:55:59 +02:00
|
|
|
cfg.blescan = 0;
|
|
|
|
macs_ble = 0; // clear BLE counter
|
2018-05-20 13:50:00 +02:00
|
|
|
#ifdef BLECOUNTER
|
|
|
|
stop_BLEscan();
|
|
|
|
#endif
|
2018-04-16 22:48:00 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cfg.blescan = 1;
|
2018-05-20 13:50:00 +02:00
|
|
|
#ifdef BLECOUNTER
|
|
|
|
start_BLEscan();
|
|
|
|
#endif
|
2018-04-16 22:48:00 +02:00
|
|
|
break;
|
2018-03-18 19:45:17 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_wifiant(uint8_t val) {
|
2018-03-24 13:38:43 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s", val ? "external" : "internal");
|
|
|
|
switch (val) {
|
|
|
|
case 1: cfg.wifiant = val; break;
|
|
|
|
default: cfg.wifiant = 0; break;
|
|
|
|
}
|
|
|
|
#ifdef HAS_ANTENNA_SWITCH
|
|
|
|
antenna_select(cfg.wifiant);
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_vendorfilter(uint8_t val) {
|
2018-04-15 12:12:06 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", val ? "on" : "off");
|
|
|
|
switch (val) {
|
|
|
|
case 1: cfg.vendorfilter = val; break;
|
|
|
|
default: cfg.vendorfilter = 0; break;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_rgblum(uint8_t val) {
|
2018-04-02 01:33:49 +02:00
|
|
|
// Avoid wrong parameters
|
|
|
|
cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY;
|
|
|
|
ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum);
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_lorapower(uint8_t val) {
|
2018-04-27 21:29:46 +02:00
|
|
|
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %d", val);
|
2018-03-18 19:45:17 +01:00
|
|
|
switch_lora(cfg.lorasf, val);
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void set_noop (uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: noop - doing nothing");
|
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void get_config (uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: get configuration");
|
|
|
|
int size = sizeof(configData_t);
|
2018-06-03 21:02:16 +02:00
|
|
|
LMIC_setTxData2(RCMDPORT, (byte*)&cfg, size, 0); // send data unconfirmed on RCMD Port
|
|
|
|
ESP_LOGI(TAG, "%d bytes queued in send queue", size);
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void get_uptime (uint8_t val) {
|
2018-03-18 19:45:17 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: get uptime");
|
2018-04-17 19:20:54 +02:00
|
|
|
int size = sizeof(uptimecounter);
|
2018-06-03 21:02:16 +02:00
|
|
|
LMIC_setTxData2(RCMDPORT, (byte*)&uptimecounter, size, 0); // send data unconfirmed on RCMD Port
|
|
|
|
ESP_LOGI(TAG, "%d bytes queued in send queue", size);
|
2018-03-21 14:33:55 +01:00
|
|
|
};
|
|
|
|
|
2018-04-28 14:09:27 +02:00
|
|
|
void get_cputemp (uint8_t val) {
|
2018-03-21 14:33:55 +01:00
|
|
|
ESP_LOGI(TAG, "Remote command: get cpu temperature");
|
|
|
|
float temp = temperatureRead();
|
|
|
|
int size = sizeof(temp);
|
2018-06-03 21:02:16 +02:00
|
|
|
LMIC_setTxData2(RCMDPORT, (byte*)&temp, size, 0); // send data unconfirmed on RCMD Port
|
|
|
|
ESP_LOGI(TAG, "%d bytes queued in send queue", size);
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
2018-06-02 22:23:50 +02:00
|
|
|
void get_voltage (uint8_t val) {
|
|
|
|
ESP_LOGI(TAG, "Remote command: get battery voltage");
|
|
|
|
#ifdef HAS_BATTERY_PROBE
|
2018-06-03 21:02:16 +02:00
|
|
|
uint16_t voltage = read_voltage();
|
2018-06-02 22:23:50 +02:00
|
|
|
#else
|
2018-06-03 21:02:16 +02:00
|
|
|
uint16_t voltage = 0;
|
2018-06-02 22:23:50 +02:00
|
|
|
#endif
|
|
|
|
int size = sizeof(voltage);
|
2018-06-03 21:02:16 +02:00
|
|
|
LMIC_setTxData2(RCMDPORT, (byte*)&voltage, size, 0); // send data unconfirmed on RCMD Port
|
|
|
|
ESP_LOGI(TAG, "%d bytes queued in send queue", size);
|
2018-06-02 22:23:50 +02:00
|
|
|
};
|
|
|
|
|
2018-06-03 21:02:16 +02:00
|
|
|
|
2018-03-18 19:45:17 +01:00
|
|
|
// assign previously defined functions to set of numeric remote commands
|
|
|
|
// format: opcode, function, flag (1 = do make settings persistent / 0 = don't)
|
|
|
|
//
|
|
|
|
cmd_t table[] = {
|
|
|
|
{0x01, set_rssi, true},
|
|
|
|
{0x02, set_countmode, true},
|
2018-04-16 11:03:12 +02:00
|
|
|
{0x03, set_noop, false},
|
2018-03-18 19:45:17 +01:00
|
|
|
{0x04, set_display, true},
|
|
|
|
{0x05, set_lorasf, true},
|
|
|
|
{0x06, set_lorapower, true},
|
|
|
|
{0x07, set_loraadr, true},
|
2018-04-16 11:03:12 +02:00
|
|
|
{0x08, set_screensaver, true},
|
2018-03-18 19:45:17 +01:00
|
|
|
{0x09, set_reset, false},
|
2018-04-28 13:07:35 +02:00
|
|
|
{0x0a, set_sendcycle, true},
|
2018-03-18 19:45:17 +01:00
|
|
|
{0x0b, set_wifichancycle, true},
|
2018-04-02 21:26:22 +02:00
|
|
|
{0x0c, set_blescantime, true},
|
2018-04-15 12:12:06 +02:00
|
|
|
{0x0d, set_vendorfilter, false},
|
2018-04-02 21:26:22 +02:00
|
|
|
{0x0e, set_blescan, true},
|
|
|
|
{0x0f, set_wifiant, true},
|
|
|
|
{0x10, set_rgblum, true},
|
2018-03-18 19:45:17 +01:00
|
|
|
{0x80, get_config, false},
|
|
|
|
{0x81, get_uptime, false},
|
2018-06-02 22:23:50 +02:00
|
|
|
{0x82, get_cputemp, false},
|
|
|
|
{0x83, get_voltage, false}
|
2018-03-18 19:45:17 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// check and execute remote command
|
2018-04-28 14:09:27 +02:00
|
|
|
void rcommand(uint8_t cmd, uint8_t arg) {
|
2018-03-18 19:45:17 +01:00
|
|
|
int i = sizeof(table) / sizeof(table[0]); // number of commands in command table
|
|
|
|
bool store_flag = false;
|
|
|
|
while(i--) {
|
|
|
|
if(cmd == table[i].nam) { // check if valid command
|
|
|
|
table[i].func(arg); // then execute assigned function
|
|
|
|
if ( table[i].store ) store_flag = true; // set save flag if function needs to store configuration
|
|
|
|
break; // exit check loop, since command was found
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (store_flag) saveConfig(); // if save flag is set: store new configuration in NVS to make it persistent
|
|
|
|
}
|