Send Queues (experimental)

This commit is contained in:
Klaus K Wilting 2018-08-03 23:50:04 +02:00
parent 862c339166
commit 7b35c6a539
12 changed files with 110 additions and 38 deletions

View File

@ -227,7 +227,7 @@ function Converter(decoded, port) {
The device listenes for remote control commands on LoRaWAN Port 2.
Note: all settings are stored in NVRAM and will be reloaded when device starts. To reset device to factory settings press button (if device has one), or send remote command 09 02 09 00 unconfirmed(!) once.
Note: all settings are stored in NVRAM and will be reloaded when device starts. To reset device to factory settings send remote command 09 02 09 00 unconfirmed(!) once.
0x01 set scan RSSI limit

View File

@ -16,7 +16,7 @@ void readButton() {
ESP_LOGI(TAG, "Button pressed");
payload.reset();
payload.addButton(0x01);
senddata(BUTTONPORT);
EnqueueSendData(BUTTONPORT, payload.getBuffer(), payload.getSize());
}
}
#endif

View File

@ -37,7 +37,7 @@ void doHomework() {
"Memory full, counter cleared (heap low water mark = %d Bytes / "
"free heap = %d bytes)",
esp_get_minimum_free_heap_size(), ESP.getFreeHeap());
senddata(COUNTERPORT); // send data before clearing counters
EnqueueSendData(COUNTERPORT, payload.getBuffer(), payload.getSize()); // send data before clearing counters
reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes
}

View File

@ -8,7 +8,7 @@
#include <esp32-hal-log.h>
// attn: increment version after modifications to configData_t truct!
#define PROGVERSION "1.4.1" // use max 10 chars here!
#define PROGVERSION "1.4.2" // use max 10 chars here!
#define PROGNAME "PAXCNT"
// std::set for unified array functions

View File

@ -108,7 +108,7 @@ void get_hard_deveui(uint8_t *pdeveui) {
#ifdef VERBOSE
// Display OTAA keys
void printKeys(void) {
void showLoraKeys(void) {
// LMIC may not have used callback to fill
// all EUI buffer so we do it here to a temp
// buffer to be able to display them

View File

@ -13,7 +13,7 @@ void get_hard_deveui(uint8_t *pdeveui);
void os_getDevKey(u1_t *buf);
void os_getArtEui(u1_t *buf);
void os_getDevEui(u1_t *buf);
void printKeys(void);
void showLoraKeys(void);
void lorawan_loop(void *pvParameters);
#endif

View File

@ -106,7 +106,7 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
#endif
payload.reset();
payload.addAlarm(rssi, beaconID);
senddata(BEACONPORT);
EnqueueSendData(BEACONPORT, payload.getBuffer(), payload.getSize());
}
};

View File

@ -41,6 +41,10 @@ hw_timer_t *channelSwitch = NULL, *displaytimer = NULL, *sendCycle = NULL,
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0,
DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
// send queues
QueueHandle_t LoraSendQueue, SPISendQueue;
MessageBuffer_t SendBuffer;
portMUX_TYPE timerMux =
portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ
// handler shared variables
@ -104,6 +108,26 @@ void setup() {
#endif // verbose
// initialize send queues for transmit channels
#ifdef HAS_LORA
LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(struct SendBuffer *));
if (LoraSendQueue == 0) {
ESP_LOGE(TAG, "Could not create LORA send queue. Aborting.");
exit(0);
} else
ESP_LOGI(TAG, "LORA send queue created, size %d Bytes",
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
#endif
#ifdef HAS_SPI
SPISendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(struct SendBuffer *));
if (SPISendQueue == 0) {
ESP_LOGE(TAG, "Could not create SPI send queue. Aborting.");
exit(0);
} else
ESP_LOGI(TAG, "SPI send queue created, size %d Bytes",
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
#endif
// read settings from NVRAM
loadConfig(); // includes initialize if necessary
@ -223,7 +247,7 @@ void setup() {
#ifdef HAS_LORA
// output LoRaWAN keys to console
#ifdef VERBOSE
printKeys();
showLoraKeys();
#endif
// initialize LoRaWAN LMIC run-time environment
@ -299,7 +323,9 @@ void loop() {
// check housekeeping cycle and if expired do homework
checkHousekeeping();
// check send cycle and send payload if cycle is expired
// check send queue and process it
processSendBuffer();
// check send cycle and enqueue payload if cycle is expired
sendPayload();
// reset watchdog
vTaskDelay(1 / portTICK_PERIOD_MS);

View File

@ -45,6 +45,7 @@
#define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit
#define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
#define SEND_QUEUE_SIZE 10 // maximum number of messages in payload send queue
// Ports on which the device sends and listenes on LoRaWAN and SPI
#define COUNTERPORT 1 // Port on which device sends counts

View File

@ -293,7 +293,7 @@ void get_config(uint8_t val[]) {
ESP_LOGI(TAG, "Remote command: get device configuration");
payload.reset();
payload.addConfig(cfg);
senddata(CONFIGPORT);
EnqueueSendData(CONFIGPORT, payload.getBuffer(), payload.getSize());
};
void get_status(uint8_t val[]) {
@ -305,7 +305,7 @@ void get_status(uint8_t val[]) {
#endif
payload.reset();
payload.addStatus(voltage, uptime() / 1000, temperatureRead());
senddata(STATUSPORT);
EnqueueSendData(STATUSPORT, payload.getBuffer(), payload.getSize());
};
void get_gps(uint8_t val[]) {
@ -314,7 +314,7 @@ void get_gps(uint8_t val[]) {
gps_read();
payload.reset();
payload.addGPS(gps_status);
senddata(GPSPORT);
EnqueueSendData(GPSPORT, payload.getBuffer(), payload.getSize());
#else
ESP_LOGW(TAG, "GPS function not supported");
#endif
@ -337,6 +337,8 @@ cmd_t table[] = {
{0x80, get_config, 0, false}, {0x81, get_status, 0, false},
{0x84, get_gps, 0, false}};
const uint8_t cmdtablesize = sizeof(table) / sizeof(table[0]); // number of commands in command table
// check and execute remote command
void rcommand(uint8_t cmd[], uint8_t cmdlength) {
@ -345,14 +347,13 @@ void rcommand(uint8_t cmd[], uint8_t cmdlength) {
else
cmdlength--; // minus 1 byte for opcode
int i =
sizeof(table) / sizeof(table[0]); // number of commands in command table
int i = cmdtablesize;
while (i--) {
if ((cmd[0] == table[i].opcode) &&
(table[i].params == cmdlength)) { // lookup command in opcode table
memmove(cmd, cmd + 1,
cmdlength); // strip opcode
cmdlength); // strip opcode from cmd array
table[i].func(cmd); // execute assigned function with given parameters
if (table[i].store) // ceck if function needs to store configuration
saveConfig();

View File

@ -1,28 +1,27 @@
// Basic Config
#include "globals.h"
void senddata(uint8_t port) {
// put data to send in RTos Queues used for transmit over channels Lora and SPI
void EnqueueSendData(uint8_t port, uint8_t data[], uint8_t size) {
MessageBuffer_t *xMsg; // create pointer to struct which holds the sendbuffer
SendBuffer.MessageSize = size;
SendBuffer.MessagePort = PAYLOAD_ENCODER <= 2
? port
: (PAYLOAD_ENCODER == 4 ? LPP2PORT : LPP1PORT);
memcpy(SendBuffer.Message, data, size);
xMsg = &SendBuffer;
// enqueue message in LoRa send queue
#ifdef HAS_LORA
// Check if there is a pending TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
ESP_LOGI(TAG, "LoRa busy, data not sent");
sprintf(display_line7, "LORA BUSY");
// to be done: add queuing here, e.g. use RTos xQueueSend
} else {
LMIC_setTxData2(
PAYLOAD_ENCODER <= 2 ? port
: (PAYLOAD_ENCODER == 4 ? LPP2PORT : LPP1PORT),
payload.getBuffer(), payload.getSize(), (cfg.countermode & 0x02));
ESP_LOGI(TAG, "%d bytes queued to send on LoRa", payload.getSize());
sprintf(display_line7, "PACKET QUEUED");
}
xQueueSend(LoraSendQueue, (void *)&xMsg, (TickType_t)0);
ESP_LOGI(TAG, "%d bytes enqueued to send on LoRa", size);
#endif
// enqueue message in SPI send queue
#ifdef HAS_SPI
// to come here: code for sending payload to a local master via SPI
ESP_LOGI(TAG, "%d bytes sent on SPI", payload.getSize());
xQueueSend(SPISendQueue, (void *)&xMsg, (TickType_t)0);
ESP_LOGI(TAG, "%d bytes enqueued to send on SPI", size);
#endif
// clear counter if not in cumulative counter mode
@ -34,8 +33,8 @@ void senddata(uint8_t port) {
} // senddata
// cyclic called function to prepare payload to send
void sendPayload() {
if (SendCycleTimerIRQ) {
portENTER_CRITICAL(&timerMux);
SendCycleTimerIRQ = 0;
@ -64,12 +63,46 @@ void sendPayload() {
ESP_LOGD(TAG, "No valid GPS position or GPS data mode disabled");
}
#endif
senddata(COUNTERPORT);
EnqueueSendData(COUNTERPORT, payload.getBuffer(), payload.getSize());
}
} // sendpayload();
} // sendpayload()
// interrupt handler used for payload send cycle timer
void IRAM_ATTR SendCycleIRQ() {
portENTER_CRITICAL(&timerMux);
SendCycleTimerIRQ++;
portEXIT_CRITICAL(&timerMux);
}
// cyclic called function to eat data from RTos send queues and transmit it
void processSendBuffer() {
MessageBuffer_t *xMsg;
#ifdef HAS_LORA
// Check if there is a pending TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
sprintf(display_line7, "LORA BUSY");
} else {
if (xQueueReceive(LoraSendQueue, &(xMsg), (TickType_t)10)) {
// xMsg now holds the struct MessageBuffer from queue
LMIC_setTxData2(xMsg->MessagePort, xMsg->Message, xMsg->MessageSize,
(cfg.countermode & 0x02));
ESP_LOGI(TAG, "%d bytes sent to LORA", xMsg->MessageSize);
sprintf(display_line7, "PACKET QUEUED");
}
}
#endif
#ifdef HAS_SPI
if (xQueueReceive(SPISendQueue, &(xMsg), (TickType_t)10)) {
// to come here: send data over SPI
// use these pointers to the payload:
// xMsg->MessagePort
// xMsg->MessageSize
// xMsg->Message
ESP_LOGI(TAG, "%d bytes sent to SPI", xMsg->MessageSize);
}
#endif
} // processSendBuffer

View File

@ -1,8 +1,19 @@
#ifndef _SENDDATA_H
#define _SENDDATA_H
void senddata(uint8_t port);
// Struct holding payload for data send queue
typedef struct {
uint8_t MessageSize;
uint8_t MessagePort;
uint8_t Message[PAYLOAD_BUFFER_SIZE];
} MessageBuffer_t;
extern QueueHandle_t LoraSendQueue, SPISendQueue;
extern MessageBuffer_t SendBuffer;
void EnqueueSendData(uint8_t port, uint8_t data[], uint8_t size);
void sendPayload(void);
void SendCycleIRQ(void);
void processSendBuffer(void);
#endif // _SENDDATA_H_