From 6be64b61dea11ecc6f29ed0ffa4bbd3c524e1a69 Mon Sep 17 00:00:00 2001
From: Zoe Pfister <zoe.pfister@uibk.ac.at>
Date: Thu, 2 Feb 2023 14:04:55 +0100
Subject: [PATCH] Possibility to send 6 messages with one ESPNow-send action

---
 client/client_mock/src/main.cpp               | 21 +++----
 client/libs/espnow/src/Message.cpp            | 45 +++++++--------
 client/libs/espnow/src/Message.hpp            |  5 +-
 client/libs/includes/ErrorTypes.h             | 15 -----
 .../lib/Utilities/Utilities.cpp               | 16 +++---
 .../lib/Utilities/Utilities.h                 |  5 +-
 host/host_central_mast/src/main.cpp           | 14 +++--
 .../DataTransfer}/ClientDataPackage.hpp       | 39 +++++++------
 .../DataTransfer/CompressedDataPackage.hpp    | 56 -------------------
 shared-libs/DataTransfer/ErrorTypes.h         |  5 +-
 .../DataTransfer}/MeasurementData.hpp         |  0
 .../DataTransfer}/SensorInformation.hpp       |  0
 12 files changed, 80 insertions(+), 141 deletions(-)
 delete mode 100644 client/libs/includes/ErrorTypes.h
 rename {client/libs/espnow/src => shared-libs/DataTransfer}/ClientDataPackage.hpp (65%)
 delete mode 100644 shared-libs/DataTransfer/CompressedDataPackage.hpp
 rename {client/libs/includes => shared-libs/DataTransfer}/MeasurementData.hpp (100%)
 rename {client/libs/includes => shared-libs/DataTransfer}/SensorInformation.hpp (100%)

diff --git a/client/client_mock/src/main.cpp b/client/client_mock/src/main.cpp
index 4d3b9d7..35cd73c 100644
--- a/client/client_mock/src/main.cpp
+++ b/client/client_mock/src/main.cpp
@@ -3,7 +3,7 @@
 #include "NoDataAvailableException.hpp"
 #include "f_deep_sleep.hpp"
 #include <Arduino.h>
-#include <CompressedDataPackage.hpp>
+#include <ClientDataPackage.hpp>
 #include <soc/rtc_cntl_reg.h>
 
 
@@ -92,29 +92,30 @@ void setup() {
     // sizeof float
     ESP_LOGD(TAG, "Size of float: %d", sizeof(float));
     // list of 5 compresseddatapackage
-    CompressedDataPackage compresseddatapackage{};
+    ClientDataPackage compresseddatapackage{};
     ESP_LOGD(TAG,
-             "Size of list of 4 CompressedDataPackage: %d",
-             sizeof(std::list<CompressedDataPackage>)
-                 + (sizeof(CompressedDataPackage) * 4));
+             "Size of list of 4 ClientDataPackage: %d",
+             sizeof(std::list<ClientDataPackage>)
+                 + (sizeof(ClientDataPackage) * 4));
     // sizeof compresseddatapackage
     ESP_LOGD(TAG,
-             "Size of CompressedDataPackage: %d",
-             sizeof(CompressedDataPackage));
+             "Size of ClientDataPackage: %d",
+             sizeof(ClientDataPackage));
     // sizeof list
-    ESP_LOGD(TAG, "Size of list: %d", sizeof(std::list<CompressedDataPackage>));
+    ESP_LOGD(TAG, "Size of list: %d", sizeof(std::list<ClientDataPackage>));
     // sizeof vector
     ESP_LOGD(TAG,
              "Size of vector: %d",
-             sizeof(std::vector<CompressedDataPackage>));
+             sizeof(std::vector<ClientDataPackage>));
 
     // FIXME: put this outside the try loop?
     ts = millis();
     espnow_setup();
     ESP_LOGD(TAG, "EPSNow setup took %ld ms", millis() - ts);
     // make a list of messages
-    std::array<Message, 4> messages =
+    std::array<Message, 6> messages =
         {messages0.front(), messages1.front(), messages2.front(),
+         Message::nullMessage(), Message::nullMessage(),
          Message::nullMessage()};
 
     ts = millis();
diff --git a/client/libs/espnow/src/Message.cpp b/client/libs/espnow/src/Message.cpp
index 4431b91..f56f6cd 100644
--- a/client/libs/espnow/src/Message.cpp
+++ b/client/libs/espnow/src/Message.cpp
@@ -1,18 +1,15 @@
 #include "Message.hpp"
-#include "CompressedDataPackage.hpp"
-#include "GlobalDefinitions.hpp"
 
 static const char *TAG = "MESSAGE";
 
 esp_err_t Message::send() const {
   ESP_LOGD(TAG, "Sending message");
   esp_err_t success;
-  auto messageData = getCompressedDataPackage();
 
   // conversion from std::string to c_str adds null terminator, which is why we add 1 to message length
   success = esp_now_send(recipient,
-                         (uint8_t *) &messageData,
-                         sizeof(CompressedDataPackage));
+                         (uint8_t *) &clientDataPackage,
+                         sizeof(ClientDataPackage));
   if (success != ESP_OK) {
     ESP_LOGE(TAG, "Error sending the data");
     // Removed caching from here, better do this in main
@@ -25,26 +22,31 @@ esp_err_t Message::send() const {
   return success;
 }
 
-esp_err_t Message::sendMessages(const std::array<Message, 4> &messages) {
+esp_err_t Message::sendMessages(const std::array<Message, 6> &messages) {
   // recipient
   uint8_t rec[6]{};
   get_host_mac(rec);
   ESP_LOGD(TAG, "Sending messages");
   esp_err_t success;
-  // list of compressed data. Sending 4 at a time
-  std::array<CompressedDataPackage, 4> compressedDataPackages{};
-//  std::array<std::optional<CompressedDataPackage>, 4> cpd{};
-  // max 4 messages
-  for (int i = 0; i < 4; i++) {
-    compressedDataPackages[i] = messages[i].getCompressedDataPackage();
-    if (messages[i].clientDataPackage.getTimestamp() == NULL_TIMESTAMP) {
-      compressedDataPackages[i].errorType = ErrorTypes::NULL_MESSAGE;
+  // list of compressed data. Sending 6 at a time
+  std::array<ClientDataPackage, 6> clientDataPackages{};
+  // max 6 messages
+  int i = 0;
+  for (const auto &message : messages) {
+    if (i >= 6) {
+      ESP_LOGE(TAG, "Too many messages to send");
+      break;
+    }
+    clientDataPackages[i] = message.getClientDataPackage();
+    if (message.clientDataPackage.getTimestamp() == NULL_TIMESTAMP) {
+      clientDataPackages[i].setErrorType(ErrorType::NULL_MESSAGE);
     }
+    i++;
   }
 
   // conversion from std::string to c_str adds null terminator, which is why we add 1 to message length
-  success = esp_now_send(rec, (uint8_t *) &compressedDataPackages,
-                         sizeof(std::array<CompressedDataPackage, 4>));
+  success = esp_now_send(rec, (uint8_t *) &clientDataPackages,
+                         sizeof(std::array<ClientDataPackage, 6>));
   if (success != ESP_OK) {
     ESP_LOGE(TAG, "Error sending the data");
     // Removed caching from here, better do this in main
@@ -71,11 +73,7 @@ std::string Message::getMessageAsMinifiedJsonString() const {
   return clientDataPackage.getDataPackageAsMinifiedJsonString();
 }
 
-CompressedDataPackage Message::getCompressedDataPackage() const {
-  return clientDataPackage.getCompressedDataPackage();
-}
-
-Message::Message(ClientDataPackage data) : clientDataPackage(std::move(data)) {
+Message::Message(ClientDataPackage data) : clientDataPackage(data) {
   // check for existing host mac address, use broadcast otherwise
   get_host_mac(recipient);
 }
@@ -83,8 +81,11 @@ Message::Message(ClientDataPackage data) : clientDataPackage(std::move(data)) {
 Message::Message(MeasurementData const &data,
                  const SensorInformation &information,
                  unsigned long timestamp)
-    : clientDataPackage(data, information, timestamp) {
+    : clientDataPackage(data, information, ErrorType::DATA_OK, timestamp) {
   // check for existing host mac address, use broadcast otherwise
   get_host_mac(recipient);
 }
+const ClientDataPackage &Message::getClientDataPackage() const {
+  return clientDataPackage;
+}
 
diff --git a/client/libs/espnow/src/Message.hpp b/client/libs/espnow/src/Message.hpp
index 35c38c7..4e30b9b 100644
--- a/client/libs/espnow/src/Message.hpp
+++ b/client/libs/espnow/src/Message.hpp
@@ -4,7 +4,6 @@
 #include "ESPNow.hpp"
 #include "Time.hpp"
 #include "esp_log.h"
-#include "CompressedDataPackage.hpp"
 #include "GlobalDefinitions.hpp"
 #include <Arduino.h>
 #include <ArduinoJson.h>
@@ -34,11 +33,11 @@ class Message {
                    NULL_TIMESTAMP};
   }
 
-  static esp_err_t sendMessages(const std::array<Message, 4> &messages);
+  static esp_err_t sendMessages(const std::array<Message, 6> &messages);
+  [[nodiscard]] const ClientDataPackage &getClientDataPackage() const;
  private:
   ClientDataPackage clientDataPackage;
 
   uint8_t recipient[6]{};
 
-  CompressedDataPackage getCompressedDataPackage() const;
 };
diff --git a/client/libs/includes/ErrorTypes.h b/client/libs/includes/ErrorTypes.h
deleted file mode 100644
index 27cf139..0000000
--- a/client/libs/includes/ErrorTypes.h
+++ /dev/null
@@ -1,15 +0,0 @@
-//
-// Created by zoe on 1/27/23.
-//
-
-#ifndef CLIENT_SATELLITE_ERRORTYPES_H
-#define CLIENT_SATELLITE_ERRORTYPES_H
-
-enum ERROR_TYPES {
-  SENSOR_DOES_NOT_RETURN_DATA = 1,
-  BATTERY_VOLTAGE_TOO_LOW = 2,
-  INVALID_VALUE = 3,
-  SENSOR_NOT_CONNECTED = 4,
-};
-
-#endif //CLIENT_SATELLITE_ERRORTYPES_H
diff --git a/host/host_central_mast/lib/Utilities/Utilities.cpp b/host/host_central_mast/lib/Utilities/Utilities.cpp
index bc7a7ec..98909c0 100644
--- a/host/host_central_mast/lib/Utilities/Utilities.cpp
+++ b/host/host_central_mast/lib/Utilities/Utilities.cpp
@@ -305,7 +305,7 @@ String documentToServerReadableString(const DynamicJsonDocument &doc) {
     return serverString;
 }
 
-String compressedDataPackageToServerReadableString(CompressedDataPackage compressedDataPackage,
+String compressedDataPackageToServerReadableString(ClientDataPackage clientDataPackage,
                                                    const String &clientMacAddress) {
     StaticJsonDocument<300> serverDoc;
     String hostMacAddressString = WiFi.macAddress();
@@ -314,16 +314,16 @@ String compressedDataPackageToServerReadableString(CompressedDataPackage compres
 
     serverDoc["host"] = hostMacAddressString;
     serverDoc["client"] = clientMacAddress;
-    serverDoc["sensorProtocol"] = compressedDataPackage.sensorProtocol;
-    serverDoc["protocolAddress"] = compressedDataPackage.channel;
-    serverDoc["i2cAddress"] = compressedDataPackage.i2cAddress;
-    serverDoc["hardwareName"] = compressedDataPackage.hardwareName;
+    serverDoc["sensorProtocol"] = clientDataPackage.getSensorInformation().getProtocolString();
+    serverDoc["protocolAddress"] = clientDataPackage.getMeasurementData().getChannel();
+    serverDoc["i2cAddress"] = clientDataPackage.getMeasurementData().getI2CAddress();
+    serverDoc["hardwareName"] = clientDataPackage.getSensorInformation().getHardwareNameString();
     // each value is a element in the readigs array
     JsonArray readings = serverDoc.createNestedArray("readings");
     JsonObject reading = readings.createNestedObject();
-    reading["name"] = compressedDataPackage.measurementType;
-    reading["value"] = compressedDataPackage.value;
-    serverDoc["time"] = compressedDataPackage.timestamp;
+    reading["name"] = clientDataPackage.getMeasurementData().getMeasurementTypeString();
+    reading["value"] = clientDataPackage.getMeasurementData().getValue();
+    serverDoc["time"] = clientDataPackage.getTimestamp();
 
     String serverString;
     serializeJson(serverDoc, serverString);
diff --git a/host/host_central_mast/lib/Utilities/Utilities.h b/host/host_central_mast/lib/Utilities/Utilities.h
index 6cd7624..7ac445f 100644
--- a/host/host_central_mast/lib/Utilities/Utilities.h
+++ b/host/host_central_mast/lib/Utilities/Utilities.h
@@ -6,12 +6,12 @@
 #define HOST_CENTRAL_MAST_UTILITIES_H
 
 #include "ArduinoJson.h"
-#include "CompressedDataPackage.hpp"
 #include "SD.h"
 #include "SDCardException.h"
 #include "SDSetupException.h"
 #include "WiFi.h"
 #include <Arduino.h>
+#include <ClientDataPackage.hpp>
 #include <Definitions.h>
 #include <WString.h>
 #include <list>
@@ -35,7 +35,6 @@ String getMacAddressAsString(const uint8_t *mac);
 String documentToLineProtocolString(const DynamicJsonDocument &doc);
 DynamicJsonDocument parseReceivedJsonData(char *data);
 String documentToServerReadableString(const DynamicJsonDocument &doc);
-String compressedDataPackageToServerReadableString(CompressedDataPackage compressedDataPackage,
-                                                   const String &clientMacAddress);
+String compressedDataPackageToServerReadableString(ClientDataPackage clientDataPackage, const String &clientMacAddress);
 
 #endif // HOST_CENTRAL_MAST_UTILITIES_H
diff --git a/host/host_central_mast/src/main.cpp b/host/host_central_mast/src/main.cpp
index 8f3030f..3b141a1 100644
--- a/host/host_central_mast/src/main.cpp
+++ b/host/host_central_mast/src/main.cpp
@@ -5,7 +5,7 @@
 
 #define TINY_GSM_MODEM_SIM7000
 
-#include "CompressedDataPackage.hpp"
+#include "ClientDataPackage.hpp"
 #include "ConnectionManager.h"
 #include "MessageType.h"
 #include "SDCardLogger.h"
@@ -81,12 +81,13 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) {
     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<CompressedDataPackage, 4> compressedDataPackage{};
-    memcpy(&compressedDataPackage, incomingData, sizeof(std::array<CompressedDataPackage, 4>));
+    std::array<ClientDataPackage, 6> compressedDataPackage{};
+    memcpy(&compressedDataPackage, incomingData, sizeof(std::array<ClientDataPackage, 6>));
     //    esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Raw received Data: %s\n", data);
 
     String macAddress = getMacAddressAsString(mac);
@@ -94,13 +95,14 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) {
     for (auto &data : compressedDataPackage) {
 
         // ignore padding messages
-        if (data.timestamp == NULL_TIMESTAMP && data.errorType == NULL_MESSAGE) {
+        if (data.getTimestamp() == NULL_TIMESTAMP && data.getErrorType() == ErrorType::NULL_MESSAGE) {
             continue;
         }
 
-        // log received data
-        esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "Received Data: %s\n", data.toString().c_str());
         auto doc = compressedDataPackageToServerReadableString(data, macAddress);
+        // log received data
+        esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "Received Data: %s\n",
+                      data.getDataPackageAsMinifiedJsonString().c_str());
 
         // serialize json document again
         std::string dataString{};
diff --git a/client/libs/espnow/src/ClientDataPackage.hpp b/shared-libs/DataTransfer/ClientDataPackage.hpp
similarity index 65%
rename from client/libs/espnow/src/ClientDataPackage.hpp
rename to shared-libs/DataTransfer/ClientDataPackage.hpp
index 0cbaecf..54296f9 100644
--- a/client/libs/espnow/src/ClientDataPackage.hpp
+++ b/shared-libs/DataTransfer/ClientDataPackage.hpp
@@ -4,11 +4,11 @@
 #include "MeasurementData.hpp"
 #include "SensorProtocol.hpp"
 #include "SensorInformation.hpp"
-#include "CompressedDataPackage.hpp"
 #include <list>
 #include <optional>
 #include <string>
 #include <utility>
+#include <ErrorTypes.h>
 
 // having the data be a struct of basic types makes sending easier,
 // otherwise we would have to serialize the data before sending
@@ -16,14 +16,27 @@ class ClientDataPackage {
  private:
   MeasurementData measurementData;
   SensorInformation sensorInformation;
+  ErrorType errorType;
   unsigned long timestamp; // maybe make this array
 
  public:
-  ClientDataPackage(MeasurementData value, SensorInformation sensorInformation,
+  ClientDataPackage(MeasurementData value,
+                    SensorInformation sensorInformation,
+                    ErrorType errorType,
                     unsigned long timestamp)
       : measurementData(value),
         sensorInformation(sensorInformation),
-        timestamp(timestamp) {
+        timestamp(timestamp),
+        errorType(errorType) {
+  }
+
+
+  [[nodiscard]] ErrorType getErrorType() const {
+    return errorType;
+  }
+
+  void setErrorType(ErrorType error) {
+    ClientDataPackage::errorType = error;
   }
 
   [[nodiscard]] const MeasurementData &
@@ -55,18 +68,10 @@ class ClientDataPackage {
     return jsonString;
   }
 
-  [[nodiscard]] CompressedDataPackage getCompressedDataPackage() const {
-    CompressedDataPackage compressedDataPackage{};
-    compressedDataPackage.channel = measurementData.getChannel();
-    compressedDataPackage.i2cAddress = measurementData.getI2CAddress();
-    compressedDataPackage.value = measurementData.getValue();
-    compressedDataPackage.timestamp = timestamp;
-    compressedDataPackage.errorType = ErrorTypes::DATA_OK;
-    compressedDataPackage.hardwareName = sensorInformation.getHardwareName();
-    compressedDataPackage.sensorProtocol = sensorInformation.getProtocol();
-    compressedDataPackage.measurementType =
-        measurementData.getMeasurementType();
-    return compressedDataPackage;
-  }
-
+  ClientDataPackage() : measurementData(MeasurementData(ERROR_VALUE,
+                                                        MeasurementType::TEMPERATURE)),
+                        sensorInformation(SensorInformation(HardwareName::NONE,
+                                                            SensorProtocol::NULL_PROTOCOL)),
+                        timestamp(0),
+                        errorType(ErrorType::NO_DATA) {}
 };
diff --git a/shared-libs/DataTransfer/CompressedDataPackage.hpp b/shared-libs/DataTransfer/CompressedDataPackage.hpp
deleted file mode 100644
index ece1ea7..0000000
--- a/shared-libs/DataTransfer/CompressedDataPackage.hpp
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Created by cynthya on 1/27/23.
-//
-
-#ifndef CLIENT_MOCK_COMPRESSEDDATAPACKAGE_HPP
-#define CLIENT_MOCK_COMPRESSEDDATAPACKAGE_HPP
-
-#include <ArduinoJson.h>
-#include <list>
-#include <string>
-#include <utility>
-#include "ErrorTypes.h"
-
-// null timestamp
-
-
-struct CompressedDataPackage {
-  int channel;    // can this be short?
-  int i2cAddress; // can this be short?
-  double value;
-  unsigned long timestamp;
-  ErrorTypes errorType;
-  HardwareName hardwareName;
-  SensorProtocol sensorProtocol;
-  MeasurementType measurementType;
-  // same could be done for hardwarename and sensorprotocol
-
-  // tostring
-  [[nodiscard]] std::string toString() const {
-    StaticJsonDocument<250> document; // 250 byte is the max send size of espnow
-
-    document["hardwareName"] =
-        HardwareNames::hardwareNameToString(hardwareName);
-    document["timestamp"] = timestamp;
-    document["sensorProtocol"] =
-        SensorProtocols::sensorProtocolToString(sensorProtocol);
-    document["value"] = value;
-
-    if (channel != -1) {
-      document["channel"] = channel;
-    }
-
-    if (i2cAddress != -1) {
-      document["i2cAddress"] = i2cAddress;
-    }
-
-    document["measurementType"] =
-        MeasurementTypes::measurementTypeToString(measurementType);
-
-    std::string jsonString;
-    serializeJson(document, jsonString);
-    return jsonString;
-  }
-};
-
-#endif // CLIENT_MOCK_COMPRESSEDDATAPACKAGE_HPP
diff --git a/shared-libs/DataTransfer/ErrorTypes.h b/shared-libs/DataTransfer/ErrorTypes.h
index 227bae7..aebcfc2 100644
--- a/shared-libs/DataTransfer/ErrorTypes.h
+++ b/shared-libs/DataTransfer/ErrorTypes.h
@@ -6,12 +6,15 @@
 #define CLIENT_MOCK_ERRORTYPES_H
 
 
-enum class ErrorTypes: char {
+enum class ErrorType: char {
   SENSOR_NOT_FOUND,
   SENSOR_NOT_CONNECTED,
   NO_DATA,
   DATA_OK,
   NULL_MESSAGE, // message that is sent as padding, should be thrown away
+  SENSOR_DOES_NOT_RETURN_DATA,
+  BATTERY_VOLTAGE_TOO_LOW,
+  INVALID_VALUE,
 };
 
 
diff --git a/client/libs/includes/MeasurementData.hpp b/shared-libs/DataTransfer/MeasurementData.hpp
similarity index 100%
rename from client/libs/includes/MeasurementData.hpp
rename to shared-libs/DataTransfer/MeasurementData.hpp
diff --git a/client/libs/includes/SensorInformation.hpp b/shared-libs/DataTransfer/SensorInformation.hpp
similarity index 100%
rename from client/libs/includes/SensorInformation.hpp
rename to shared-libs/DataTransfer/SensorInformation.hpp
-- 
GitLab