commit
b9584a2fdf
@ -364,7 +364,7 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering.
|
|||||||
|
|
||||||
# Remote control
|
# Remote control
|
||||||
|
|
||||||
The device listenes for remote control commands on LoRaWAN Port 2. Multiple commands per downlink are possible by concatenating them.
|
The device listenes for remote control commands on LoRaWAN Port 2. Multiple commands per downlink are possible by concatenating them, but must not exceed a maximum of 10 bytes per downlink.
|
||||||
|
|
||||||
Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
#include "timesync.h"
|
#include "timesync.h"
|
||||||
#include "blescan.h"
|
#include "blescan.h"
|
||||||
|
|
||||||
|
// maximum number of elements in rcommand interpreter queue
|
||||||
|
#define RCMD_QUEUE_SIZE 5
|
||||||
|
|
||||||
|
extern TaskHandle_t rcmdTask;
|
||||||
|
|
||||||
// table of remote commands and assigned functions
|
// table of remote commands and assigned functions
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const uint8_t opcode;
|
const uint8_t opcode;
|
||||||
@ -23,9 +28,16 @@ typedef struct {
|
|||||||
const bool store;
|
const bool store;
|
||||||
} cmd_t;
|
} cmd_t;
|
||||||
|
|
||||||
extern bool rcmd_busy;
|
// Struct for remote command processing queue
|
||||||
|
typedef struct {
|
||||||
|
uint8_t cmd[10];
|
||||||
|
uint8_t cmdLen;
|
||||||
|
} RcmdBuffer_t;
|
||||||
|
|
||||||
void rcommand(const uint8_t cmd[], const uint8_t cmdlength);
|
void IRAM_ATTR rcommand(const uint8_t *cmd, const size_t cmdlength);
|
||||||
void do_reset(bool warmstart);
|
void rcmd_queuereset(void);
|
||||||
|
uint32_t rcmd_queuewaiting(void);
|
||||||
|
void rcmd_deinit(void);
|
||||||
|
esp_err_t rcmd_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -277,12 +277,11 @@ void start_BLEscan(void) {
|
|||||||
// Register callback function for capturing bluetooth packets
|
// Register callback function for capturing bluetooth packets
|
||||||
register_ble_callback(false);
|
register_ble_callback(false);
|
||||||
ESP_LOGI(TAG, "Bluetooth scanner started");
|
ESP_LOGI(TAG, "Bluetooth scanner started");
|
||||||
#endif // BLECOUNTER
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Bluetooth controller start failed. Resetting device");
|
ESP_LOGE(TAG, "Bluetooth controller start failed. Resetting device");
|
||||||
do_reset(true);
|
do_reset(true);
|
||||||
}
|
}
|
||||||
|
#endif // BLECOUNTER
|
||||||
} // start_BLEscan
|
} // start_BLEscan
|
||||||
|
|
||||||
void stop_BLEscan(void) {
|
void stop_BLEscan(void) {
|
||||||
|
@ -14,7 +14,7 @@ extern boolean isSDS011Active;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void setCyclicIRQ() {
|
void setCyclicIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, CYCLIC_IRQ, eSetBits, NULL);
|
xTaskNotify(irqHandlerTask, CYCLIC_IRQ, eSetBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do all housekeeping
|
// do all housekeeping
|
||||||
@ -34,6 +34,8 @@ void doHousekeeping() {
|
|||||||
ESP_LOGD(TAG, "MACprocessor %d bytes left | Taskstate = %d",
|
ESP_LOGD(TAG, "MACprocessor %d bytes left | Taskstate = %d",
|
||||||
uxTaskGetStackHighWaterMark(macProcessTask),
|
uxTaskGetStackHighWaterMark(macProcessTask),
|
||||||
eTaskGetState(macProcessTask));
|
eTaskGetState(macProcessTask));
|
||||||
|
ESP_LOGD(TAG, "Rcommand interpreter %d bytes left | Taskstate = %d",
|
||||||
|
uxTaskGetStackHighWaterMark(rcmdTask), eTaskGetState(rcmdTask));
|
||||||
#if (HAS_LORA)
|
#if (HAS_LORA)
|
||||||
ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d",
|
ESP_LOGD(TAG, "LMiCtask %d bytes left | Taskstate = %d",
|
||||||
uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask));
|
uxTaskGetStackHighWaterMark(lmicTask), eTaskGetState(lmicTask));
|
||||||
|
@ -19,7 +19,7 @@ RTC_DATA_ATTR lmic_t RTC_LMIC;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QueueHandle_t LoraSendQueue;
|
static QueueHandle_t LoraSendQueue;
|
||||||
TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
|
TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
|
||||||
|
|
||||||
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
|
class MyHalConfig_t : public Arduino_LMIC::HalConfiguration_t {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
QueueHandle_t MacQueue;
|
static QueueHandle_t MacQueue;
|
||||||
TaskHandle_t macProcessTask;
|
TaskHandle_t macProcessTask;
|
||||||
|
|
||||||
static uint32_t salt = renew_salt();
|
static uint32_t salt = renew_salt();
|
||||||
|
13
src/main.cpp
13
src/main.cpp
@ -38,7 +38,8 @@ timesync_proc 1 3 processes realtime time sync requests
|
|||||||
irqhandler 1 2 cyclic tasks (i.e. displayrefresh) triggered by timers
|
irqhandler 1 2 cyclic tasks (i.e. displayrefresh) triggered by timers
|
||||||
gpsloop 1 1 reads data from GPS via serial or i2c
|
gpsloop 1 1 reads data from GPS via serial or i2c
|
||||||
lorasendtask 1 1 feeds data from lora sendqueue to lmcic
|
lorasendtask 1 1 feeds data from lora sendqueue to lmcic
|
||||||
macprocess 1 1 analyzes sniffed MACs
|
macprocess 1 1 MAC analyzer loop
|
||||||
|
rmcd_process 1 1 Remote command interpreter loop
|
||||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||||
|
|
||||||
Low priority numbers denote low priority tasks.
|
Low priority numbers denote low priority tasks.
|
||||||
@ -60,8 +61,10 @@ irqHandlerTask (Core 1), see irqhandler.cpp
|
|||||||
|
|
||||||
fired by hardware
|
fired by hardware
|
||||||
DisplayIRQ -> esp32 timer 0
|
DisplayIRQ -> esp32 timer 0
|
||||||
ButtonIRQ -> external gpio
|
CLOCKIRQ -> esp32 timer 1 or external GPIO (RTC_INT or GPS_INT)
|
||||||
PMUIRQ -> PMU chip gpio
|
MatrixDisplayIRQ-> esp32 timer 3
|
||||||
|
ButtonIRQ -> external GPIO
|
||||||
|
PMUIRQ -> PMU chip GPIO
|
||||||
|
|
||||||
fired by software (Ticker.h)
|
fired by software (Ticker.h)
|
||||||
TIMESYNC_IRQ -> setTimeSyncIRQ()
|
TIMESYNC_IRQ -> setTimeSyncIRQ()
|
||||||
@ -291,6 +294,10 @@ void setup() {
|
|||||||
ESP_LOGI(TAG, "Starting MAC processor...");
|
ESP_LOGI(TAG, "Starting MAC processor...");
|
||||||
macQueueInit();
|
macQueueInit();
|
||||||
|
|
||||||
|
// start rcommand processing task
|
||||||
|
ESP_LOGI(TAG, "Starting rcommand interpreter...");
|
||||||
|
rcmd_init();
|
||||||
|
|
||||||
// start BLE scan callback if BLE function is enabled in NVRAM configuration
|
// start BLE scan callback if BLE function is enabled in NVRAM configuration
|
||||||
// or remove bluetooth stack from RAM, if option bluetooth is not compiled
|
// or remove bluetooth stack from RAM, if option bluetooth is not compiled
|
||||||
#if (BLECOUNTER)
|
#if (BLECOUNTER)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
QueueHandle_t MQTTSendQueue;
|
static QueueHandle_t MQTTSendQueue;
|
||||||
TaskHandle_t mqttTask;
|
TaskHandle_t mqttTask;
|
||||||
|
|
||||||
Ticker mqttTimer;
|
Ticker mqttTimer;
|
||||||
@ -12,6 +12,7 @@ WiFiClient netClient;
|
|||||||
MQTTClient mqttClient;
|
MQTTClient mqttClient;
|
||||||
|
|
||||||
void mqtt_deinit(void) {
|
void mqtt_deinit(void) {
|
||||||
|
mqttClient.unsubscribe(MQTT_INTOPIC);
|
||||||
mqttClient.onMessageAdvanced(NULL);
|
mqttClient.onMessageAdvanced(NULL);
|
||||||
mqttClient.disconnect();
|
mqttClient.disconnect();
|
||||||
vTaskDelete(mqttTask);
|
vTaskDelete(mqttTask);
|
||||||
@ -22,6 +23,7 @@ esp_err_t mqtt_init(void) {
|
|||||||
// setup network connection and MQTT client
|
// setup network connection and MQTT client
|
||||||
ETH.begin();
|
ETH.begin();
|
||||||
mqttClient.begin(MQTT_SERVER, MQTT_PORT, netClient);
|
mqttClient.begin(MQTT_SERVER, MQTT_PORT, netClient);
|
||||||
|
mqttClient.setKeepAlive(MQTT_KEEPALIVE);
|
||||||
mqttClient.onMessageAdvanced(mqtt_callback);
|
mqttClient.onMessageAdvanced(mqtt_callback);
|
||||||
|
|
||||||
_ASSERT(SEND_QUEUE_SIZE > 0);
|
_ASSERT(SEND_QUEUE_SIZE > 0);
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
// global variable indicating if rcommand() is executing
|
static QueueHandle_t RcmdQueue;
|
||||||
bool rcmd_busy = false;
|
TaskHandle_t rcmdTask;
|
||||||
|
|
||||||
// set of functions that can be triggered by remote commands
|
// set of functions that can be triggered by remote commands
|
||||||
void set_reset(uint8_t val[]) {
|
void set_reset(uint8_t val[]) {
|
||||||
@ -396,14 +396,13 @@ static const uint8_t cmdtablesize =
|
|||||||
sizeof(table) / sizeof(table[0]); // number of commands in command table
|
sizeof(table) / sizeof(table[0]); // number of commands in command table
|
||||||
|
|
||||||
// check and execute remote command
|
// check and execute remote command
|
||||||
void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
|
void rcmd_execute(const uint8_t cmd[], const uint8_t cmdlength) {
|
||||||
|
|
||||||
if (cmdlength == 0)
|
if (cmdlength == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t foundcmd[cmdlength], cursor = 0;
|
uint8_t foundcmd[cmdlength], cursor = 0;
|
||||||
bool storeflag = false;
|
bool storeflag = false;
|
||||||
rcmd_busy = true;
|
|
||||||
|
|
||||||
while (cursor < cmdlength) {
|
while (cursor < cmdlength) {
|
||||||
|
|
||||||
@ -436,6 +435,65 @@ void rcommand(const uint8_t cmd[], const uint8_t cmdlength) {
|
|||||||
if (storeflag)
|
if (storeflag)
|
||||||
saveConfig();
|
saveConfig();
|
||||||
|
|
||||||
rcmd_busy = false;
|
} // rcmd_execute()
|
||||||
|
|
||||||
|
// remote command processing task
|
||||||
|
void rcmd_process(void *pvParameters) {
|
||||||
|
_ASSERT((uint32_t)pvParameters == 1); // FreeRTOS check
|
||||||
|
|
||||||
|
RcmdBuffer_t RcmdBuffer;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// fetch next or wait for incoming rcommand from queue
|
||||||
|
if (xQueueReceive(RcmdQueue, &RcmdBuffer, portMAX_DELAY) != pdTRUE) {
|
||||||
|
ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rcmd_execute(RcmdBuffer.cmd, RcmdBuffer.cmdLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(2); // yield to CPU
|
||||||
|
} // rcmd_process()
|
||||||
|
|
||||||
|
// enqueue remote command
|
||||||
|
void IRAM_ATTR rcommand(const uint8_t *cmd, const size_t cmdlength) {
|
||||||
|
|
||||||
|
RcmdBuffer_t rcmd = {0};
|
||||||
|
|
||||||
|
rcmd.cmdLen = cmdlength;
|
||||||
|
memcpy(rcmd.cmd, cmd, cmdlength);
|
||||||
|
|
||||||
|
if (xQueueSendToBack(RcmdQueue, (void *)&rcmd, (TickType_t)0) != pdTRUE)
|
||||||
|
ESP_LOGW(TAG, "Remote command queue is full");
|
||||||
} // rcommand()
|
} // rcommand()
|
||||||
|
|
||||||
|
void rcmd_queuereset(void) { xQueueReset(RcmdQueue); }
|
||||||
|
|
||||||
|
uint32_t rcmd_queuewaiting(void) { return uxQueueMessagesWaiting(RcmdQueue); }
|
||||||
|
|
||||||
|
void rcmd_deinit(void) {
|
||||||
|
rcmd_queuereset();
|
||||||
|
vTaskDelete(rcmdTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t rcmd_init(void) {
|
||||||
|
|
||||||
|
_ASSERT(RCMD_QUEUE_SIZE > 0);
|
||||||
|
RcmdQueue = xQueueCreate(RCMD_QUEUE_SIZE, sizeof(RcmdBuffer_t));
|
||||||
|
if (RcmdQueue == 0) {
|
||||||
|
ESP_LOGE(TAG, "Could not create rcommand send queue. Aborting.");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Rcommand send queue created, size %d Bytes",
|
||||||
|
RCMD_QUEUE_SIZE * sizeof(RcmdBuffer_t));
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(rcmd_process, // task function
|
||||||
|
"rcmdloop", // name of task
|
||||||
|
3072, // stack size of task
|
||||||
|
(void *)1, // parameter of the task
|
||||||
|
1, // priority of the task
|
||||||
|
&rcmdTask, // task handle
|
||||||
|
1); // CPU core
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
} // rcmd_init()
|
@ -143,15 +143,7 @@ void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
|
|||||||
spi_deinit();
|
spi_deinit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// wait until rcommands are all done
|
// save LMIC state to RTC RAM
|
||||||
for (i = 10; i > 0; i--) {
|
|
||||||
if (rcmd_busy)
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save LMIC state to RTC RAM
|
|
||||||
#if (HAS_LORA)
|
#if (HAS_LORA)
|
||||||
SaveLMICToRTC(wakeup_sec);
|
SaveLMICToRTC(wakeup_sec);
|
||||||
#endif // (HAS_LORA)
|
#endif // (HAS_LORA)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
Ticker sendTimer;
|
Ticker sendTimer;
|
||||||
|
|
||||||
void setSendIRQ() {
|
void setSendIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, SENDCYCLE_IRQ, eSetBits, NULL);
|
xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
||||||
@ -12,8 +12,7 @@ void SendPayload(uint8_t port) {
|
|||||||
|
|
||||||
ESP_LOGD(TAG, "sending Payload for Port %d", port);
|
ESP_LOGD(TAG, "sending Payload for Port %d", port);
|
||||||
|
|
||||||
MessageBuffer_t
|
MessageBuffer_t SendBuffer; // contains MessageSize, MessagePort, Message[]
|
||||||
SendBuffer; // contains MessageSize, MessagePort, Message[]
|
|
||||||
|
|
||||||
SendBuffer.MessageSize = payload.getSize();
|
SendBuffer.MessageSize = payload.getSize();
|
||||||
|
|
||||||
@ -190,6 +189,7 @@ void sendData() {
|
|||||||
} // sendData()
|
} // sendData()
|
||||||
|
|
||||||
void flushQueues(void) {
|
void flushQueues(void) {
|
||||||
|
rcmd_queuereset();
|
||||||
#if (HAS_LORA)
|
#if (HAS_LORA)
|
||||||
lora_queuereset();
|
lora_queuereset();
|
||||||
#endif
|
#endif
|
||||||
@ -202,7 +202,7 @@ void flushQueues(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool allQueuesEmtpy(void) {
|
bool allQueuesEmtpy(void) {
|
||||||
uint32_t rc = 0;
|
uint32_t rc = rcmd_queuewaiting();
|
||||||
#if (HAS_LORA)
|
#if (HAS_LORA)
|
||||||
rc += lora_queuewaiting();
|
rc += lora_queuewaiting();
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,7 +43,7 @@ static const char TAG[] = __FILE__;
|
|||||||
DMA_ATTR uint8_t txbuf[BUFFER_SIZE];
|
DMA_ATTR uint8_t txbuf[BUFFER_SIZE];
|
||||||
DMA_ATTR uint8_t rxbuf[BUFFER_SIZE];
|
DMA_ATTR uint8_t rxbuf[BUFFER_SIZE];
|
||||||
|
|
||||||
QueueHandle_t SPISendQueue;
|
static QueueHandle_t SPISendQueue;
|
||||||
|
|
||||||
TaskHandle_t spiTask;
|
TaskHandle_t spiTask;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user