From 8f675f685980aae06983f723b22dbe5c251fc02f Mon Sep 17 00:00:00 2001 From: Zoe Pfister <zoe.pfister@uibk.ac.at> Date: Tue, 7 Feb 2023 11:03:59 +0100 Subject: [PATCH] Getting Ack-Response time down to <15ms --- client/client_mock/src/main.cpp | 15 +- client/libs/espnow/src/ESPNow.cpp | 230 +++++++++--------- client/libs/espnow/src/Message.cpp | 2 +- client/libs/mock_sensor/MockSensor.cpp | 32 +-- .../lib/Utilities/SDCardLogger.cpp | 6 +- .../lib/Utilities/Utilities.cpp | 3 +- .../lib/Utilities/Utilities.h | 2 +- host/host_central_mast/platformio.ini | 4 +- host/host_central_mast/src/main.cpp | 136 +++++++---- 9 files changed, 238 insertions(+), 192 deletions(-) diff --git a/client/client_mock/src/main.cpp b/client/client_mock/src/main.cpp index 407e3c4..151f202 100644 --- a/client/client_mock/src/main.cpp +++ b/client/client_mock/src/main.cpp @@ -37,7 +37,7 @@ void send_msgs(const std::__cxx11::list<Message> msgs) { // one loop takes ~2200 ms void setup() { // disable brownout - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); +// WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); unsigned long ts = millis(); Serial.begin(115200); @@ -56,11 +56,13 @@ void setup() { mock_channel2.setChannel(2); mock_channel3.setChannel(3); - ESP_LOGD(TAG, "Setup took %ld ms", millis() - ts); + // disable led + gpio_set_direction(GPIO_NUM_32, GPIO_MODE_OUTPUT); - try { - // FIXME: put me into seperate trys? No data will be sent when 1 exception occurs + ESP_LOGD(TAG, "Setup took %ld ms", millis() - ts); + try { + // FIXME: put me into seperate trys? No data will be sent when 1 exception occurs ts = millis(); auto messages0 = mock_channel0.buildMessages(); auto messages1 = mock_channel1.buildMessages(); @@ -126,11 +128,6 @@ void setup() { ts = millis(); Message::sendMessages(messages); -// send_msgs(messages0); -// send_msgs(messages1); -// send_msgs(messages2); -// send_msgs(messages3); - // roughly takes 3s in ideal conditions ESP_LOGD(TAG, "Sending messages took %ld ms", millis() - ts); } catch (const NoDataAvailableException &e) { diff --git a/client/libs/espnow/src/ESPNow.cpp b/client/libs/espnow/src/ESPNow.cpp index e230b55..6ef9054 100644 --- a/client/libs/espnow/src/ESPNow.cpp +++ b/client/libs/espnow/src/ESPNow.cpp @@ -7,129 +7,141 @@ esp_now_peer_info_t hostInfo; Preferences preferences; bool msg_recv = false; -bool was_msg_received(){ - if(msg_recv){ - msg_recv = false; - return true; - } - return false; +bool was_msg_received() { + if (msg_recv) { + msg_recv = false; + return true; + } + return false; } -void get_host_mac(uint8_t *destination) -{ - preferences.begin("config", true); - if (preferences.isKey("host")) { - preferences.getBytes("host", destination, sizeof(uint8_t) * 6); - } else { - memcpy(destination, BROADCAST_MAC, sizeof(BROADCAST_MAC)); - ESP_LOGI(TAG, "Backup MAC address used"); - } - preferences.end(); +void get_host_mac(uint8_t *destination) { + preferences.begin("config", true); + if (preferences.isKey("host")) { + preferences.getBytes("host", destination, sizeof(uint8_t) * 6); + } else { + memcpy(destination, BROADCAST_MAC, sizeof(BROADCAST_MAC)); + ESP_LOGI(TAG, "Backup MAC address used"); + } + preferences.end(); } -esp_err_t add_host_to_peers(config received){ - esp_now_peer_info_t host; - memset(&host, 0, sizeof(host)); - memcpy(host.peer_addr, received.host, sizeof(received.host)); - host.encrypt = false; - host.channel = 0; - return esp_now_add_peer(&host); +esp_err_t add_host_to_peers(config received) { + esp_now_peer_info_t host; + memset(&host, 0, sizeof(host)); + memcpy(host.peer_addr, received.host, sizeof(received.host)); + host.encrypt = false; + host.channel = 0; + return esp_now_add_peer(&host); } -void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) -{ - ESP_LOGE(TAG, "Message sent to %02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], - mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); +void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { + ESP_LOGE(TAG, "Message sent to %02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], + mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); } -void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) -{ - // is msg host -> yes -> set bool - // assume host change not happening, rare event - // => on host change, broadcast - ESP_LOGD(TAG, "Message received"); - config received_msg; - memcpy(&received_msg, incomingData, sizeof(received_msg)); // TODO: check for valid mac - // all the esp32 macs so far use the same first 3(?) bytes so maybe use that - // First three bytes of MACs are always vendor specific. But vendors have a range of them. - // all Espressif registered MAC starting bytes: https://maclookup.app/vendors/espressif-inc - // you can also set your own MAC https://randomnerdtutorials.com/get-change-esp32-esp8266-mac-address-arduino/ - switch (received_msg.type){ - case hostChange:{ - ESP_LOGI(TAG, "hostChange received"); - Time::getInstance().setTime(received_msg.epoch_seconds); - // delete old host - preferences.begin("config", false); - if(preferences.isKey("host")){ - ESP_LOGI(TAG, "removing old host"); - uint8_t old[6]; - preferences.end(); - get_host_mac(old); // maybe problem here, re-opening preferences - esp_now_del_peer(old); - } - // add new host - preferences.begin("config", false); - if(preferences.putBytes("host", received_msg.host, sizeof(received_msg.host)) > 0){ - ESP_LOGI(TAG, "Host MAC address saved to flash %02X:%02X:%02X:%02X:%02X:%02X", received_msg.host[0], - received_msg.host[1],received_msg.host[2],received_msg.host[3],received_msg.host[4],received_msg.host[5]); - } - else{ - ESP_LOGI(TAG, "Couldn't save Host Mac to flash"); - } - preferences.end(); - add_host_to_peers(received_msg); - } - case dataAck:{ - ESP_LOGI(TAG, "dataAck received."); - Time::getInstance().setTime( - received_msg.epoch_seconds); // see https://www.esp32.com/viewtopic.php?t=9965, maybe this needs an offset - - ESP_LOGI(TAG, "Timestamp received: %ld", Time::getInstance().getEpochSeconds()); - preferences.begin("config", false); - if (!preferences.isKey("host")) { - if(preferences.putBytes("host", received_msg.host, sizeof(received_msg.host)) > 0){ - ESP_LOGI(TAG, "host MAC address saved to flash %02X:%02X:%02X:%02X:%02X:%02X", received_msg.host[0], - received_msg.host[1],received_msg.host[2],received_msg.host[3],received_msg.host[4],received_msg.host[5]); - } - - // add host to peers - add_host_to_peers(received_msg); - } - preferences.end(); - // delay(50); - msg_recv = true; - } - default:{ - break; - } - } +void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { + // is msg host -> yes -> set bool + // assume host change not happening, rare event + // => on host change, broadcast +// ESP_LOGD(TAG, "Message received"); +// time this + auto start = millis(); + config received_msg; + memcpy(&received_msg, + incomingData, + sizeof(received_msg)); // TODO: check for valid mac + // all the esp32 macs so far use the same first 3(?) bytes so maybe use that + // First three bytes of MACs are always vendor specific. But vendors have a range of them. + // all Espressif registered MAC starting bytes: https://maclookup.app/vendors/espressif-inc + // you can also set your own MAC https://randomnerdtutorials.com/get-change-esp32-esp8266-mac-address-arduino/ + switch (received_msg.type) { + case hostChange: { + ESP_LOGI(TAG, "hostChange received"); + Time::getInstance().setTime(received_msg.epoch_seconds); + // delete old host + preferences.begin("config", false); + if (preferences.isKey("host")) { + ESP_LOGI(TAG, "removing old host"); + uint8_t old[6]; + preferences.end(); + get_host_mac(old); // maybe problem here, re-opening preferences + esp_now_del_peer(old); + } + // add new host + preferences.begin("config", false); + if (preferences.putBytes("host", + received_msg.host, + sizeof(received_msg.host)) > 0) { + ESP_LOGI(TAG, + "Host MAC address saved to flash %02X:%02X:%02X:%02X:%02X:%02X", + received_msg.host[0], + received_msg.host[1], + received_msg.host[2], + received_msg.host[3], + received_msg.host[4], + received_msg.host[5]); + } else { + ESP_LOGI(TAG, "Couldn't save Host Mac to flash"); + } + preferences.end(); + add_host_to_peers(received_msg); + } + case dataAck: { +// ESP_LOGI(TAG, "dataAck received."); + Time::getInstance().setTime( + received_msg.epoch_seconds); // see https://www.esp32.com/viewtopic.php?t=9965, maybe this needs an offset + +// ESP_LOGI(TAG, "Timestamp received: %ld", Time::getInstance().getEpochSeconds()); + preferences.begin("config", false); + if (!preferences.isKey("host")) { + if (preferences.putBytes("host", + received_msg.host, + sizeof(received_msg.host)) > 0) { +// ESP_LOGI(TAG, "host MAC address saved to flash %02X:%02X:%02X:%02X:%02X:%02X", received_msg.host[0], +// received_msg.host[1],received_msg.host[2],received_msg.host[3],received_msg.host[4],received_msg.host[5]); +// } + + // add host to peers + add_host_to_peers(received_msg); + } + } + preferences.end(); + // delay(50); + msg_recv = true; + } + default: { + break; + } + } + auto end = millis(); + } -esp_err_t espnow_setup() -{ - esp_err_t result; - WiFi.mode(WIFI_STA); - result = esp_now_init(); - if (result != ESP_OK) { - // initialization failed - ESP_LOGE(TAG, "ESPNow setup failed"); - return result; // not sure about this - } +esp_err_t espnow_setup() { + esp_err_t result; + WiFi.mode(WIFI_STA); + result = esp_now_init(); + if (result != ESP_OK) { + // initialization failed + ESP_LOGE(TAG, "ESPNow setup failed"); + return result; // not sure about this + } - get_host_mac(hostInfo.peer_addr); // check if there is a host saved in flash mem, broadcast otherwise + get_host_mac(hostInfo.peer_addr); // check if there is a host saved in flash mem, broadcast otherwise - hostInfo.channel = 0; + hostInfo.channel = 0; - // TODO: PMK is used to encrypt LMK with the AES-128 algorithm. Call esp_now_set_pmk() to set PMK. If PMK is not - // set, a default PMK will be used. - // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html - hostInfo.encrypt = false; - esp_now_add_peer(&hostInfo); + // TODO: PMK is used to encrypt LMK with the AES-128 algorithm. Call esp_now_set_pmk() to set PMK. If PMK is not + // set, a default PMK will be used. + // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html + hostInfo.encrypt = false; + esp_now_add_peer(&hostInfo); - esp_now_register_recv_cb(on_data_recv); - esp_now_register_send_cb(on_data_sent); + esp_now_register_recv_cb(on_data_recv); + esp_now_register_send_cb(on_data_sent); - ESP_LOGI(TAG, "ESPNow started. MAC: %s", WiFi.macAddress().c_str()); - return ESP_OK; + ESP_LOGI(TAG, "ESPNow started. MAC: %s", WiFi.macAddress().c_str()); + return ESP_OK; } diff --git a/client/libs/espnow/src/Message.cpp b/client/libs/espnow/src/Message.cpp index fb3dd18..0df90ac 100644 --- a/client/libs/espnow/src/Message.cpp +++ b/client/libs/espnow/src/Message.cpp @@ -32,7 +32,7 @@ esp_err_t Message::sendMessages(const std::array<Message, 6> &messages) { std::array<ClientDataPackage, 6> clientDataPackages{}; // max 6 messages int i = 0; - for (const auto &message : messages) { + for (const auto &message: messages) { if (i >= 6) { ESP_LOGE(TAG, "Too many messages to send"); break; diff --git a/client/libs/mock_sensor/MockSensor.cpp b/client/libs/mock_sensor/MockSensor.cpp index e70f207..bc1deaf 100644 --- a/client/libs/mock_sensor/MockSensor.cpp +++ b/client/libs/mock_sensor/MockSensor.cpp @@ -5,36 +5,36 @@ static const char *TAG = "MOCK"; void MockSensor::setup() { - ESP_LOGD(TAG, "MOCK Sensor initialized"); - delay(100); - channel = 0; + ESP_LOGD(TAG, "MOCK Sensor initialized"); + delay(100); + channel = 0; } Measurement MockSensor::readData() { - // generate a random float value between 0 and 100 - float randomValue = (float) rand() / (float) RAND_MAX * 100.0; - randomValue += static_cast<float>(DeepSleep::bootCount); - ESP_LOGD(TAG, "MOCK Sensor read value: %f", randomValue); - return {randomValue, channel, NO_I2C_ADDRESS, MeasurementType::MOCK, ErrorType::DATA_OK}; + // generate a random float value between 0 and 100 + float randomValue = DeepSleep::bootCount * 10 + channel; + ESP_LOGD(TAG, "MOCK Sensor read value: %f", randomValue); + return {randomValue, channel, NO_I2C_ADDRESS, MeasurementType::MOCK, + ErrorType::DATA_OK}; } void MockSensor::setChannel(int c) { - channel = c; + channel = c; } std::list<Message> MockSensor::buildMessages() { - std::list<Message> messages; - auto measurement = readData(); + std::list<Message> messages; + auto measurement = readData(); // Measurement // MockData{data, channel, NO_I2C_ADDRESS, MeasurementType::MOCK, ErrorType::DATA_OK}; - messages.emplace_back(measurement, - sensorInformation, - Time::getInstance().getEpochSeconds()); - return messages; + messages.emplace_back(measurement, + sensorInformation, + Time::getInstance().getEpochSeconds()); + return messages; } SensorInformation MockSensor::getSensorInformation() const { - return sensorInformation; + return sensorInformation; } diff --git a/host/host_central_mast/lib/Utilities/SDCardLogger.cpp b/host/host_central_mast/lib/Utilities/SDCardLogger.cpp index f3ee7a6..d0c5991 100644 --- a/host/host_central_mast/lib/Utilities/SDCardLogger.cpp +++ b/host/host_central_mast/lib/Utilities/SDCardLogger.cpp @@ -15,10 +15,14 @@ namespace SDCardLogger { int vprintf_into_sd(const char *szFormat, va_list args) { String logstring = "[" + rtc.getDateTime() + "] "; logstring += szFormat; - + // print current core + logstring += "Core: "; + logstring += xPortGetCoreID(); + logstring += ". "; if (!SDUtilities::isSDAvailable()) { if (printToSerial) { logstring += " (SD card not available)\n"; + vprintf(logstring.c_str(), args); } return 1; diff --git a/host/host_central_mast/lib/Utilities/Utilities.cpp b/host/host_central_mast/lib/Utilities/Utilities.cpp index 98909c0..1f3c8d8 100644 --- a/host/host_central_mast/lib/Utilities/Utilities.cpp +++ b/host/host_central_mast/lib/Utilities/Utilities.cpp @@ -305,8 +305,7 @@ String documentToServerReadableString(const DynamicJsonDocument &doc) { return serverString; } -String compressedDataPackageToServerReadableString(ClientDataPackage clientDataPackage, - const String &clientMacAddress) { +String dataPackageToServerReadableString(ClientDataPackage clientDataPackage, const String &clientMacAddress) { StaticJsonDocument<300> serverDoc; String hostMacAddressString = WiFi.macAddress(); hostMacAddressString.replace(":", ""); diff --git a/host/host_central_mast/lib/Utilities/Utilities.h b/host/host_central_mast/lib/Utilities/Utilities.h index 7ac445f..e3a7abb 100644 --- a/host/host_central_mast/lib/Utilities/Utilities.h +++ b/host/host_central_mast/lib/Utilities/Utilities.h @@ -35,6 +35,6 @@ String getMacAddressAsString(const uint8_t *mac); String documentToLineProtocolString(const DynamicJsonDocument &doc); DynamicJsonDocument parseReceivedJsonData(char *data); String documentToServerReadableString(const DynamicJsonDocument &doc); -String compressedDataPackageToServerReadableString(ClientDataPackage clientDataPackage, const String &clientMacAddress); +String dataPackageToServerReadableString(ClientDataPackage clientDataPackage, const String &clientMacAddress); #endif // HOST_CENTRAL_MAST_UTILITIES_H diff --git a/host/host_central_mast/platformio.ini b/host/host_central_mast/platformio.ini index 3a473d3..5cd5785 100644 --- a/host/host_central_mast/platformio.ini +++ b/host/host_central_mast/platformio.ini @@ -14,8 +14,8 @@ board = esp-wrover-kit framework = arduino monitor_speed = 115200 lib_ldf_mode = deep -monitor_port = /dev/ttyACM0 -upload_port = /dev/ttyACM0 +monitor_port = /dev/ttyACM1 +upload_port = /dev/ttyACM1 lib_extra_dirs = ../../shared-libs build_flags = diff --git a/host/host_central_mast/src/main.cpp b/host/host_central_mast/src/main.cpp index f3351d7..6faa74c 100644 --- a/host/host_central_mast/src/main.cpp +++ b/host/host_central_mast/src/main.cpp @@ -20,6 +20,7 @@ #include <esp_log.h> #include <esp_now.h> #include <queue> +#include <soc/rtc_cntl_reg.h> #include <sys/unistd.h> ESP32Time rtc; @@ -50,20 +51,19 @@ SemaphoreHandle_t xMutex; TaskHandle_t ESPNOWTask; -static std::queue<String> queue; +struct QueueStruct { + std::array<ClientDataPackage, 6> data; + uint8_t mac[6]{}; +}; -void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { - // go to sleep +void sendResponse(const uint8_t *mac) { + response response = {}; + response.type = dataAck; + esp_read_mac(response.mac, ESP_MAC_WIFI_STA); + response.time = rtc.getEpoch(); + esp_err_t success = esp_now_send(mac, (uint8_t *)&response, sizeof(response)); } - -/** - * @brief ESPNOW callback function that is called when data is received - * @param mac - * @param incomingData - * @param len length of the incoming data in bytes - */ -void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { - +void checkPeerExistence(const uint8_t *mac) { if (!esp_now_is_peer_exist(mac)) { esp_now_peer_info_t client = {}; memcpy(client.peer_addr, mac, sizeof(uint8_t) * 6); @@ -75,48 +75,26 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Failed to add new Peer: %d", status); } } +} +void handleDataReceive(const uint8_t *mac, const uint8_t *incomingData); +static std::queue<QueueStruct> queue; - response response = {}; - response.type = dataAck; - esp_read_mac(response.mac, ESP_MAC_WIFI_STA); - response.time = rtc.getEpoch(); - esp_err_t success = esp_now_send(mac, (uint8_t *)&response, sizeof(response)); - - esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "Message recieved\n"); - esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, (success == ESP_OK) ? "Response sent\n" : "Failed to respond\n"); - - // copy received data to a char array - std::array<ClientDataPackage, 6> compressedDataPackage{}; - memcpy(&compressedDataPackage, incomingData, sizeof(ClientDataPackage) * 6); - // esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Raw received Data: %s\n", data); - - String macAddress = getMacAddressAsString(mac); - - for (auto &data : compressedDataPackage) { - - // ignore padding messages - if (data.getMeasurementData().getErrorType() == ErrorType::NULL_MESSAGE) { - continue; - } - - auto doc = compressedDataPackageToServerReadableString(data, macAddress); - // log received data - esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "Received Data: %s\n", - data.getDataPackageAsMinifiedJsonString().c_str()); +void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { + // go to sleep +} - // serialize json document again - std::string dataString{}; +/** + * @brief ESPNOW callback function that is called when data is received + * @param mac + * @param incomingData + * @param len length of the incoming data in bytes + */ +void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { + checkPeerExistence(mac); - try { - SDUtilities::saveStringToSDCard(dataString); - } catch (const std::exception &e) { - esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW, "Failed to save data to SD card: %s", e.what()); - } + sendResponse(mac); - xSemaphoreTake(xMutex, portMAX_DELAY); - queue.emplace(dataString.c_str()); - xSemaphoreGive(xMutex); - } + handleDataReceive(mac, incomingData); } [[noreturn]] void esp_loop() { @@ -125,7 +103,7 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { } [[noreturn]] void ESPNOWReceiveTask(void *parameter) { - esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "ESPNOWReceiveTask started on core %d\n", xPortGetCoreID()); + esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "ESPNOWReceiveTask started on core %d\n", xPortGetCoreID()); WiFi.mode(WIFI_STA); @@ -164,6 +142,7 @@ void setup() { // Set console baud rate Serial.begin(115200); delay(10); + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable detector try { SDUtilities::setupSDCard(SD_MISO, SD_MOSI, SD_SCLK, SD_CS); } catch (const SDSetupException &e) { @@ -202,6 +181,54 @@ void setup() { void loop() { + bool emptyQueue; + + // check if queue is empty + xSemaphoreTake(xMutex, portMAX_DELAY); + emptyQueue = queue.empty(); + xSemaphoreGive(xMutex); + + // exit after 10 retries + int earlyExitCounter = 0; + + // do while loop that takes one element of the queue each until the queue is empty + while (!emptyQueue) { + xSemaphoreTake(xMutex, portMAX_DELAY); + auto data = queue.front(); + queue.pop(); + xSemaphoreGive(xMutex); + + // get mac address as string + String macAddress = getMacAddressAsString(data.mac); + + for (const auto &dataPackage : data.data) { + // ignore padding messages + if (dataPackage.getMeasurementData().getErrorType() == ErrorType::NULL_MESSAGE) { + continue; + } + + auto serverReadableString = dataPackageToServerReadableString(dataPackage, macAddress); + + try { + SDUtilities::saveStringToSDCard(serverReadableString.c_str()); + } catch (const std::exception &e) { + esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW, "Failed to save data to SD card: %s", e.what()); + } + + // TODO: Try send or add to queue + } + + if (earlyExitCounter > 10) { + break; + } + earlyExitCounter++; + + // check if queue is empty + xSemaphoreTake(xMutex, portMAX_DELAY); + emptyQueue = queue.empty(); + xSemaphoreGive(xMutex); + } + connectionManager.modemPowerOn(); delay(5000L); @@ -276,3 +303,10 @@ void loop() { delay(10000); } +void handleDataReceive(const uint8_t *mac, const uint8_t *incomingData) { + std::array<ClientDataPackage, 6> compressedDataPackage{}; + memcpy(&compressedDataPackage, incomingData, sizeof(ClientDataPackage) * 6); + xSemaphoreTake(xMutex, portMAX_DELAY); + queue.emplace(QueueStruct{compressedDataPackage, {mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]}}); + xSemaphoreGive(xMutex); +} \ No newline at end of file -- GitLab