diff --git a/client/client_mock/src/main.cpp b/client/client_mock/src/main.cpp index faae21bb2a8b5ff08a56c6c0f26348cd1cc7cdaa..ca790730dc00ceedbe1ffb9d7f899811bff6337b 100644 --- a/client/client_mock/src/main.cpp +++ b/client/client_mock/src/main.cpp @@ -3,6 +3,8 @@ #include "NoDataAvailableException.hpp" #include "f_deep_sleep.hpp" #include <Arduino.h> +#include <CompressedDataPackage.hpp> +#include <soc/rtc_cntl_reg.h> static const char *TAG = "MAIN"; @@ -34,20 +36,15 @@ 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); unsigned long ts = millis(); Serial.begin(115200); - // Set the GPIO which conrtols the step up to OUTPUT - gpio_set_direction(GPIO_NUM_32, GPIO_MODE_OUTPUT); - - // blinking led for debug - // gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT); - // gpio_set_level(GPIO_NUM_17, 1); DeepSleep::print_wakeup_reason(); DeepSleep::bootCount++; ESP_LOGD(TAG, "Boot number: %d", DeepSleep::bootCount); - gpio_set_level(GPIO_NUM_32, 1); // delay(100); mock_channel0.setup(); mock_channel1.setup(); @@ -73,28 +70,57 @@ void setup() { ESP_LOGD(TAG, "Reading data and building messages took %ld ms", millis() - ts); gpio_set_level(GPIO_NUM_32, 0); + ESP_LOGD(TAG, "Size of message to be sent: %d", sizeof(messages0.front())); + ESP_LOGD(TAG, "Size of Message class: %d", sizeof(Message)); + ESP_LOGD(TAG, "Size of ClientDataPackage class: %d", sizeof(ClientDataPackage)); + // sizeof string + ESP_LOGD(TAG, "Size of string: %d", sizeof(std::string)); + // sizeof string with 5 char + ESP_LOGD(TAG, "Size of string with 5 char: %d", sizeof(char[5])); + // sizeof optional int + ESP_LOGD(TAG, "Size of optional int: %d", sizeof(std::optional<int>)); + // sizeof int + ESP_LOGD(TAG, "Size of int: %d", sizeof(int)); + // sizeof double + ESP_LOGD(TAG, "Size of double: %d", sizeof(double)); + // sizeof float + ESP_LOGD(TAG, "Size of float: %d", sizeof(float)); + // list of 5 compresseddatapackage + CompressedDataPackage compresseddatapackage{}; + ESP_LOGD(TAG, "Size of list of 4 CompressedDataPackage: %d", sizeof(std::list<CompressedDataPackage>) + (sizeof(CompressedDataPackage) * 4)); + // sizeof compresseddatapackage + ESP_LOGD(TAG, "Size of CompressedDataPackage: %d", sizeof(CompressedDataPackage)); + // sizeof list + ESP_LOGD(TAG, "Size of list: %d", sizeof(std::list<CompressedDataPackage>)); + // sizeof vector + ESP_LOGD(TAG, "Size of vector: %d", sizeof(std::vector<CompressedDataPackage>)); + // 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::list<Message> messages; + messages.insert(messages.end(), messages0.begin(), messages0.end()); + messages.insert(messages.end(), messages1.begin(), messages1.end()); + messages.insert(messages.end(), messages2.begin(), messages2.end()); + messages.insert(messages.end(), messages3.begin(), messages3.end()); + ts = millis(); +// Message::sendMessages(messages); send_msgs(messages0); - send_msgs(messages1); - send_msgs(messages2); - send_msgs(messages3); +// 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) { std::cerr << e.what() << '\n'; } - // just to be safe in case exception happens above - gpio_set_level(GPIO_NUM_32, 0); - // keep it in deep sleep - gpio_hold_en((gpio_num_t) GPIO_NUM_32); // battery protection: go to deep sleep for unlimited time when voltage less than 3.2V - DeepSleep::deep_sleep(20); + DeepSleep::deep_sleep(5); } diff --git a/client/libs/LC7090203F/LC709203F.h b/client/libs/LC7090203F/LC709203F.h index 75ed26c319f43810ea13e331a9b28854d3611081..b5902d8cf0fb92f425c3690d702ba7c276c1ea72 100644 --- a/client/libs/LC7090203F/LC709203F.h +++ b/client/libs/LC7090203F/LC709203F.h @@ -117,7 +117,7 @@ protected: int16_t read16(uint8_t regAddress); private: - const SensorInformation sensorInformation{"LC709203", Protocol::I2C}; + const SensorInformation sensorInformation{"LC709203", SensorProtocol::I2C}; enum class MeasurementType { BATTERY_VOLTAGE, diff --git a/client/libs/dr26_analogue/dr26.hpp b/client/libs/dr26_analogue/dr26.hpp index e1bc6b3e6c1857716a4e0fc6a0870ffd48774fbb..5e7a4c956a11d621290b611c7fc62dad2b9da505 100644 --- a/client/libs/dr26_analogue/dr26.hpp +++ b/client/libs/dr26_analogue/dr26.hpp @@ -22,7 +22,7 @@ class ForteDR26 : public ForteSensor<float> { private: Adafruit_ADS1115 ads; - const SensorInformation sensorInformation{"DR26", Protocol::Analog}; + const SensorInformation sensorInformation{"DR26", SensorProtocol::Analog}; int channel; }; diff --git a/client/libs/drs26_digital/drs26.cpp b/client/libs/drs26_digital/drs26.cpp index 5c21f3a98e01d665c38a879fb23f37217b39e8f4..84066008a3acc312deda88b5ef13e56d844da101 100644 --- a/client/libs/drs26_digital/drs26.cpp +++ b/client/libs/drs26_digital/drs26.cpp @@ -52,7 +52,7 @@ std::list<Message> ForteDRS26 ::buildMessages() messages.emplace_back(Message{circumferenceIncrementMeasurementData, sensorInformation, 0}); messages.emplace_back(Message{temperatureMeasurementData, sensorInformation, 0}); - ESP_LOGE(sensorInformation.getSensorName().c_str(), "test"); + ESP_LOGE(sensorInformation.getHardwareName().c_str(), "test"); return messages; } SensorInformation ForteDRS26::getSensorInformation() const diff --git a/client/libs/drs26_digital/drs26.hpp b/client/libs/drs26_digital/drs26.hpp index 0d713ca66260895f63cdc1e2137ec4027294e8bd..e0f7de0a36f4f61454522f5f37d4e343e10f868d 100644 --- a/client/libs/drs26_digital/drs26.hpp +++ b/client/libs/drs26_digital/drs26.hpp @@ -25,7 +25,7 @@ class ForteDRS26 : public ForteSensor<out_data_drs26> { private: SDI12 drs26; out_data_drs26 data; - const SensorInformation sensorInformation{"DRS26", Protocol::I2C}; + const SensorInformation sensorInformation{"DRS26", SensorProtocol::I2C}; enum class MeasurementType { TEMPERATURE, CIRCUMFERENCE_INCREMENT }; // enum to string diff --git a/client/libs/espnow/src/ClientDataPackage.hpp b/client/libs/espnow/src/ClientDataPackage.hpp index f08e6bba4ea43308e606f06f7870735d7f4820bc..58833fa3f5eb563ea721754154e61971737dd727 100644 --- a/client/libs/espnow/src/ClientDataPackage.hpp +++ b/client/libs/espnow/src/ClientDataPackage.hpp @@ -2,8 +2,9 @@ #include <ArduinoJson.h> #include "MeasurementData.hpp" -#include "Protocol.hpp" +#include "SensorProtocol.hpp" #include "SensorInformation.hpp" +#include "CompressedDataPackage.hpp" #include <list> #include <optional> #include <string> @@ -12,43 +13,62 @@ // having the data be a struct of basic types makes sending easier, // otherwise we would have to serialize the data before sending class ClientDataPackage { - private: - MeasurementData measurementData; - SensorInformation sensorInformation; - unsigned long timestamp; // maybe make this array - - public: - ClientDataPackage(MeasurementData value, SensorInformation sensorInformation, unsigned long timestamp) - : measurementData(std::move(value)), sensorInformation(std::move(sensorInformation)), timestamp(timestamp) - { - } - - [[nodiscard]] const MeasurementData &getMeasurementData() const { return measurementData; } - [[nodiscard]] const SensorInformation &getSensorInformation() const { return sensorInformation; } - [[nodiscard]] unsigned long getTimestamp() const { return timestamp; } - - [[nodiscard]] std::string getDataPackageAsMinifiedJsonString() const - { - StaticJsonDocument<250> document; // 250 byte is the max send size of espnow - - document["sensorName"] = sensorInformation.getSensorName(); - document["timestamp"] = timestamp; - document["protocol"] = protocolToString.at(sensorInformation.getProtocol()); - document["value"] = measurementData.getValue(); - - if (measurementData.getChannel().has_value()) { - document["channel"] = measurementData.getChannel().value(); - } - - if (measurementData.getI2CAddress().has_value()) { - document["i2cAddress"] = measurementData.getI2CAddress().value(); - } - - document["measurementType"] = measurementData.getMeasurementType(); - - std::string jsonString; - serializeJson(document, jsonString); - return jsonString; - } +private: + MeasurementData measurementData; + SensorInformation sensorInformation; + unsigned long timestamp; // maybe make this array + +public: + ClientDataPackage(MeasurementData value, SensorInformation sensorInformation, + unsigned long timestamp) + : measurementData(std::move(value)), sensorInformation(std::move(sensorInformation)), + timestamp(timestamp) { + } + + [[nodiscard]] const MeasurementData &getMeasurementData() const { return measurementData; } + + [[nodiscard]] const SensorInformation & + getSensorInformation() const { return sensorInformation; } + + [[nodiscard]] unsigned long getTimestamp() const { return timestamp; } + + [[nodiscard]] std::string getDataPackageAsMinifiedJsonString() const { + StaticJsonDocument<250> document; // 250 byte is the max send size of espnow + + document["hardwareName"] = sensorInformation.getHardwareName(); + document["timestamp"] = timestamp; + document["sensorProtocol"] = protocolToString.at(sensorInformation.getProtocol()); + document["value"] = measurementData.getValue(); + + if (measurementData.getChannel().has_value()) { + document["channel"] = measurementData.getChannel().value(); + } + + if (measurementData.getI2CAddress().has_value()) { + document["i2cAddress"] = measurementData.getI2CAddress().value(); + } + + document["measurementType"] = measurementData.getMeasurementType(); + + std::string jsonString; + serializeJson(document, jsonString); + return jsonString; + } + + [[nodiscard]] CompressedDataPackage getCompressedDataPackage() const { + CompressedDataPackage compressedDataPackage{}; + compressedDataPackage.channel = measurementData.getChannel().value_or(-1); + compressedDataPackage.i2cAddress = measurementData.getI2CAddress().value_or(-1); + compressedDataPackage.value = measurementData.getValue(); + compressedDataPackage.timestamp = timestamp; + compressedDataPackage.errorType = ErrorTypes::DATA_OK; + strcpy(compressedDataPackage.hardwareName, sensorInformation.getHardwareName().c_str()); + strcpy(compressedDataPackage.sensorProtocol, + protocolToString.at(sensorInformation.getProtocol())); + strcpy(compressedDataPackage.measurementType, + measurementData.getMeasurementType().c_str()); + return compressedDataPackage; + } + }; diff --git a/client/libs/espnow/src/CompressedDataPackage.hpp b/client/libs/espnow/src/CompressedDataPackage.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ead67045edc91013a271d5d65bbb0b77558c3ab8 --- /dev/null +++ b/client/libs/espnow/src/CompressedDataPackage.hpp @@ -0,0 +1,55 @@ +// +// 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> + +enum ErrorTypes : short { + SENSOR_NOT_FOUND, + SENSOR_NOT_CONNECTED, + NO_DATA, + DATA_OK, +}; + +struct CompressedDataPackage { + int channel; + int i2cAddress; + double value; + unsigned long timestamp; + ErrorTypes errorType; + char hardwareName[6]; + char sensorProtocol[6]; + char measurementType[18]; + + // tostring + [[nodiscard]] std::string toString() const { + StaticJsonDocument<250> document; // 250 byte is the max send size of espnow + + document["hardwareName"] = hardwareName; + document["timestamp"] = timestamp; + document["sensorProtocol"] = sensorProtocol; + document["value"] = value; + + if (channel != -1) { + document["channel"] = channel; + } + + if (i2cAddress != -1) { + document["i2cAddress"] = i2cAddress; + } + + document["measurementType"] = measurementType; + + std::string jsonString; + serializeJson(document, jsonString); + return jsonString; + } +}; + +#endif // CLIENT_MOCK_COMPRESSEDDATAPACKAGE_HPP diff --git a/client/libs/espnow/src/Message.cpp b/client/libs/espnow/src/Message.cpp index b24ecadcf682489c227894733fc5c612a166700e..fbfe8d2a8451bce8801ee52aeff461c9239c464e 100644 --- a/client/libs/espnow/src/Message.cpp +++ b/client/libs/espnow/src/Message.cpp @@ -1,40 +1,78 @@ #include "Message.hpp" +#include "CompressedDataPackage.hpp" static const char *TAG = "MESSAGE"; -esp_err_t Message::send() const -{ - ESP_LOGD(TAG, "Sending message"); - esp_err_t success; - auto messageData = getMessageAsMinifiedJsonString(); +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.c_str(), (messageData.length() + 1) * sizeof(char)); - if (success != ESP_OK) { - ESP_LOGE(TAG, "Error sending the data"); - // Removed caching from here, better do this in main - } - ESP_LOGD(TAG, "Sent data: %s", messageData.c_str()); + // 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)); + if (success != ESP_OK) { + ESP_LOGE(TAG, "Error sending the data"); + // Removed caching from here, better do this in main + } +// ESP_LOGD(TAG, "Sent data: %s", messageData.c_str()); - ESP_LOGD(TAG, "Timestamp sent: %ld", clientDataPackage.getTimestamp()); - ESP_LOGD(TAG, "send status: %d", success); + ESP_LOGD(TAG, "Timestamp sent: %ld", clientDataPackage.getTimestamp()); + ESP_LOGD(TAG, "send status: %d", success); - return success; + return success; } -std::string Message::getMessageAsMinifiedJsonString() const -{ - return clientDataPackage.getDataPackageAsMinifiedJsonString(); +esp_err_t Message::sendMessages(const std::list<Message> &messages) { + // recipient + uint8_t rec[6]{}; + get_host_mac(rec); + ESP_LOGD(TAG, "Sending messages"); + esp_err_t success; + // list of compressed data + std::list<CompressedDataPackage> compressedDataPackages; + // max 4 messages + int i = 0; + for (const auto &message: messages) { + i++; + compressedDataPackages.push_back(message.getCompressedDataPackage()); + if (i == 4) { + break; + } + } + + // 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::list<CompressedDataPackage>) + + 4 * sizeof(CompressedDataPackage)); + if (success != ESP_OK) { + ESP_LOGE(TAG, "Error sending the data"); + // Removed caching from here, better do this in main + } +// ESP_LOGD(TAG, "Sent data: %s", messageData.c_str()); + +// ESP_LOGD(TAG, "Timestamp sent: %ld", clientDataPackage.getTimestamp()); + ESP_LOGD(TAG, "send status: %d", success); + + return success; } -Message::Message(ClientDataPackage data) : clientDataPackage(std::move(data)) -{ - // check for existing host mac address, use broadcast otherwise - get_host_mac(recipient); +std::string Message::getMessageAsMinifiedJsonString() const { + return clientDataPackage.getDataPackageAsMinifiedJsonString(); } -Message::Message(MeasurementData const &data, const SensorInformation &information, unsigned long timestamp) - : clientDataPackage(data, information, timestamp) -{ - // check for existing host mac address, use broadcast otherwise - get_host_mac(recipient); + +CompressedDataPackage Message::getCompressedDataPackage() const { + return clientDataPackage.getCompressedDataPackage(); } + +Message::Message(ClientDataPackage data) : clientDataPackage(std::move(data)) { + // check for existing host mac address, use broadcast otherwise + get_host_mac(recipient); +} + +Message::Message(MeasurementData const &data, const SensorInformation &information, + unsigned long timestamp) + : clientDataPackage(data, information, timestamp) { + // check for existing host mac address, use broadcast otherwise + get_host_mac(recipient); +} + diff --git a/client/libs/espnow/src/Message.hpp b/client/libs/espnow/src/Message.hpp index ba2724deaf3e01ffcc56d146ca75909d20c69446..16e58bee29f4a2a6bea31f1a0acaf6ce46c9698f 100644 --- a/client/libs/espnow/src/Message.hpp +++ b/client/libs/espnow/src/Message.hpp @@ -4,6 +4,7 @@ #include "ESPNow.hpp" #include "Time.hpp" #include "esp_log.h" +#include "CompressedDataPackage.hpp" #include <Arduino.h> #include <ArduinoJson.h> #include <ESP32Time.h> @@ -20,7 +21,12 @@ class Message { esp_err_t send() const; [[nodiscard]] std::string getMessageAsMinifiedJsonString() const; - private: - ClientDataPackage clientDataPackage; + + static esp_err_t sendMessages(const std::list<Message>& messages); +private: + ClientDataPackage clientDataPackage; + uint8_t recipient[6]{}; + + CompressedDataPackage getCompressedDataPackage() const; }; diff --git a/client/libs/ina219/ina219.cpp b/client/libs/ina219/ina219.cpp index 930885f2d99e6ccd1571b778441dfd39668c2108..ac287e8b17d07b67ef72cb28c92f998d62a793ff 100644 --- a/client/libs/ina219/ina219.cpp +++ b/client/libs/ina219/ina219.cpp @@ -5,7 +5,7 @@ void ForteINA219 ::setup() Wire.begin(I2C_SDA, I2C_SCL); if (!ina219.init()) { // Sensor init went wrong - ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed"); + ESP_LOGW(sensorInformation.getHardwareName().c_str(), "Initialization failed"); return; } } diff --git a/client/libs/ina219/ina219.hpp b/client/libs/ina219/ina219.hpp index 1985b996820f696290be13bc776a5f238fcd466a..6172f6d7f1bdb0c4d34863fb0f6b44d7dd241d5b 100644 --- a/client/libs/ina219/ina219.hpp +++ b/client/libs/ina219/ina219.hpp @@ -27,7 +27,7 @@ class ForteINA219 : public ForteSensor<out_data_ina219> { private: INA219_WE ina219; out_data_ina219 data; - const SensorInformation sensorInformation{"INA219", Protocol::I2C}; + const SensorInformation sensorInformation{"INA219", SensorProtocol::I2C}; enum class MeasurementType {SHUNT_VOLTAGE, BUS_VOLTAGE, CURRENT_mA, POWER_mA, LOAD_VOLTAGE_V, INA219_OVERFLOW}; std::map<MeasurementType, const char*> measurementTypeToString = { diff --git a/client/libs/includes/ForteSensor.hpp b/client/libs/includes/ForteSensor.hpp index add5a01d566ef5977eef3e0286d908c4b49fcb0b..1da7c49716cdf7c0bfc133babfc83cd834fc1216 100644 --- a/client/libs/includes/ForteSensor.hpp +++ b/client/libs/includes/ForteSensor.hpp @@ -2,7 +2,7 @@ #define _FORTE_SENSOR #include "Message.hpp" -#include "Protocol.hpp" +#include "SensorProtocol.hpp" #include "SensorInformation.hpp" template <class T> class ForteSensor { diff --git a/client/libs/includes/MeasurementData.hpp b/client/libs/includes/MeasurementData.hpp index 36bd5db75fbdb714dad723d67b92affd4d4fd189..ce0c859e194ac11bf93d811559a465f9d468a269 100644 --- a/client/libs/includes/MeasurementData.hpp +++ b/client/libs/includes/MeasurementData.hpp @@ -6,34 +6,39 @@ #define CLIENT_MEASUREMENTDATA_HPP #include "ArduinoJson.h" -#include "Protocol.hpp" +#include "SensorProtocol.hpp" #include "SensorInformation.hpp" #include <list> #include <optional> #include <string> #include <utility> + class MeasurementData { - public: - MeasurementData(double value, std::optional<int> channel, std::optional<int> i2cAddress, - std::string measurementType) - : value(value), measurementType(std::move(measurementType)), channel(channel), i2cAddress(i2cAddress) - { - } - - MeasurementData(double value, std::string measurementType) - : value(value), measurementType(std::move(measurementType)) - { - } - - [[nodiscard]] double getValue() const { return value; } - [[nodiscard]] const std::string &getMeasurementType() const { return measurementType; } - [[nodiscard]] const std::optional<int> &getChannel() const { return channel; } - [[nodiscard]] const std::optional<int> &getI2CAddress() const { return i2cAddress; } - - private: - double value; - std::string measurementType; // TODO: consider using an enum - std::optional<int> channel; - std::optional<int> i2cAddress; +public: + MeasurementData(double value, std::optional<int> channel, std::optional<int> i2cAddress, + std::string measurementType) + : value(value), measurementType(std::move(measurementType)), channel(channel), + i2cAddress(i2cAddress) { + } + + MeasurementData(double value, std::string measurementType) + : value(value), measurementType(std::move(measurementType)) { + } + + [[nodiscard]] double getValue() const { return value; } + + [[nodiscard]] const std::string &getMeasurementType() const { return measurementType; } + + [[nodiscard]] const std::optional<int> &getChannel() const { return channel; } + + [[nodiscard]] const std::optional<int> &getI2CAddress() const { return i2cAddress; } + +private: + double value; + std::string measurementType; // TODO: consider using an enum + // TODO: is it possible for a sensor to have both a channel and an i2cAddress? + std::optional<int> channel; + std::optional<int> i2cAddress; }; + #endif // CLIENT_MEASUREMENTDATA_HPP diff --git a/client/libs/includes/Protocol.hpp b/client/libs/includes/Protocol.hpp deleted file mode 100644 index f9a124978a42626fd128e579adc497bd23257678..0000000000000000000000000000000000000000 --- a/client/libs/includes/Protocol.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by zoe on 10/5/22. -// - -#ifndef CLIENT_PROTOCOL_HPP -#define CLIENT_PROTOCOL_HPP - -#include <map> -enum class Protocol { I2C, RS485, Analog, Mock }; - -// protocol to string -const static std::map<Protocol, const char *> protocolToString = { - {Protocol::I2C, "I2C"}, {Protocol::RS485, "RS485"}, {Protocol::Analog, "ANALOG"}, {Protocol::Mock, "MOCK"}}; - -#endif // CLIENT_PROTOCOL_HPP diff --git a/client/libs/includes/SensorInformation.hpp b/client/libs/includes/SensorInformation.hpp index 4b8af5d357534be81670b503790960a2781bc282..0b392f04b263cfa0f93024f13d850fef89bcdc23 100644 --- a/client/libs/includes/SensorInformation.hpp +++ b/client/libs/includes/SensorInformation.hpp @@ -5,21 +5,21 @@ #ifndef CLIENT_SENSORINFORMATION_HPP #define CLIENT_SENSORINFORMATION_HPP -#include "Protocol.hpp" +#include "SensorProtocol.hpp" #include <string> class SensorInformation { public: - SensorInformation(std::string sensorName, Protocol protocol) : sensorName(std::move(sensorName)), protocol(protocol) + SensorInformation(std::string hardwareName, SensorProtocol sensorProtocol) : hardwareName(std::move(hardwareName)), sensorProtocol(sensorProtocol) { } - [[nodiscard]] const std::string &getSensorName() const { return sensorName; } - [[nodiscard]] Protocol getProtocol() const { return protocol; } + [[nodiscard]] const std::string &getHardwareName() const { return hardwareName; } + [[nodiscard]] SensorProtocol getProtocol() const { return sensorProtocol; } private: - std::string sensorName; - Protocol protocol; + std::string hardwareName; + SensorProtocol sensorProtocol; }; #endif // CLIENT_SENSORINFORMATION_HPP diff --git a/client/libs/includes/SensorProtocol.hpp b/client/libs/includes/SensorProtocol.hpp new file mode 100644 index 0000000000000000000000000000000000000000..363da3bc0e4f5c85d6ffaf3824f8bbe452b407f8 --- /dev/null +++ b/client/libs/includes/SensorProtocol.hpp @@ -0,0 +1,15 @@ +// +// Created by zoe on 10/5/22. +// + +#ifndef CLIENT_PROTOCOL_HPP +#define CLIENT_PROTOCOL_HPP + +#include <map> +enum class SensorProtocol { I2C, RS485, Analog, Mock }; + +// sensorProtocol to string +const static std::map<SensorProtocol, const char *> protocolToString = { + {SensorProtocol::I2C, "I2C"}, {SensorProtocol::RS485, "RS485"}, {SensorProtocol::Analog, "ANALOG"}, {SensorProtocol::Mock, "MOCK"}}; + +#endif // CLIENT_PROTOCOL_HPP diff --git a/client/libs/mock_sensor/MockSensor.hpp b/client/libs/mock_sensor/MockSensor.hpp index 20df4d1d2c66b954949a5fbce9a7e074293d28b2..86cfc03bde30913532ce07e482d5d81d2c825085 100644 --- a/client/libs/mock_sensor/MockSensor.hpp +++ b/client/libs/mock_sensor/MockSensor.hpp @@ -17,7 +17,7 @@ class MockSensor : public ForteSensor<float> { [[nodiscard]] SensorInformation getSensorInformation() const override; private: - const SensorInformation sensorInformation{"MOCK", Protocol::Mock}; + const SensorInformation sensorInformation{"MOCK", SensorProtocol::Mock}; int channel; }; diff --git a/client/libs/rs485/rs485.hpp b/client/libs/rs485/rs485.hpp index 4fc4f5e3d5b9e49f2748bc72406f1091625b7aa4..a379b89711d0e7887b09fd75020b6364496b0c74 100644 --- a/client/libs/rs485/rs485.hpp +++ b/client/libs/rs485/rs485.hpp @@ -24,7 +24,7 @@ class Forte_RS485 : public ForteSensor <out_data_rs485> { [[nodiscard]] SensorInformation getSensorInformation() const override; private: - const SensorInformation sensorInformation{"RS485", Protocol::RS485}; + const SensorInformation sensorInformation{"RS485", SensorProtocol::RS485}; enum class MeasurementType { SOLAR_RADIATION, diff --git a/client/libs/scd30/scd30.cpp b/client/libs/scd30/scd30.cpp index 7cff381af4ac4034d955366bf571a89b7e551ddf..a0bd13f86f71fea2063509701d62b311b0ac7371 100644 --- a/client/libs/scd30/scd30.cpp +++ b/client/libs/scd30/scd30.cpp @@ -5,7 +5,7 @@ void ForteSCD30 ::setup() Wire.begin(I2C_SDA, I2C_SCL); if (!airSensor.begin()) { // Sensor init went wrong - ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed."); + ESP_LOGW(sensorInformation.getHardwareName().c_str(), "Initialization failed."); return; } } diff --git a/client/libs/scd30/scd30.hpp b/client/libs/scd30/scd30.hpp index db3e85500924db80ac3c0b5cd3698314564f6fd6..253414a59399a43b089f8938070375bae3f85c6b 100644 --- a/client/libs/scd30/scd30.hpp +++ b/client/libs/scd30/scd30.hpp @@ -25,7 +25,7 @@ class ForteSCD30 : public ForteSensor<out_data_scd30> { private: SCD30 airSensor; out_data_scd30 data; - const SensorInformation sensorInformation{"SCD30", Protocol::I2C}; + const SensorInformation sensorInformation{"SCD30", SensorProtocol::I2C}; }; #endif \ No newline at end of file diff --git a/client/libs/sht85/Sht85.hpp b/client/libs/sht85/Sht85.hpp index 00c7114f27a7ab0382bc09e765d2728fd7d1b219..02e978c7e254ceb38002033b80959f8001e9c0c0 100644 --- a/client/libs/sht85/Sht85.hpp +++ b/client/libs/sht85/Sht85.hpp @@ -37,7 +37,7 @@ class Sht85 : public ForteSensor<out_data_sht85> { private: SHTSensor sht; // I2C address: 0x44 out_data_sht85 data; - const SensorInformation sensorInformation{"SHT85", Protocol::I2C}; + const SensorInformation sensorInformation{"SHT85", SensorProtocol::I2C}; void readSHT(); enum class MeasurementType { TEMPERATURE, HUMIDITY }; diff --git a/host/host_central_mast/lib/Utilities/Utilities.cpp b/host/host_central_mast/lib/Utilities/Utilities.cpp index 316d33c95d27260f7b3c0ca299ed049db6305bce..bc7a7ec6a22498f651514f6558fc46c1627de8ff 100644 --- a/host/host_central_mast/lib/Utilities/Utilities.cpp +++ b/host/host_central_mast/lib/Utilities/Utilities.cpp @@ -288,16 +288,43 @@ String documentToServerReadableString(const DynamicJsonDocument &doc) { serverDoc["host"] = hostMacAddressString; serverDoc["client"] = doc["clientMac"].as<String>(); - serverDoc["sensorProtocol"] = doc["protocol"].as<String>(); + serverDoc["sensorProtocol"] = doc["sensorProtocol"].as<String>(); serverDoc["protocolAddress"] = doc["channel"].as<String>(); - serverDoc["hardwareName"] = doc["sensorName"].as<String>(); + serverDoc["i2cAddress"] = doc["i2cAddress"].as<String>(); + serverDoc["hardwareName"] = doc["hardwareName"].as<String>(); // each value is a element in the readigs array JsonArray readings = serverDoc.createNestedArray("readings"); JsonObject reading = readings.createNestedObject(); reading["name"] = doc["measurementType"].as<String>(); - reading["value"] = doc["value"].as<float>(); + reading["value"] = doc["value"].as<double>(); serverDoc["time"] = doc["timestamp"].as<uint32_t>(); + String serverString; + serializeJson(serverDoc, serverString); + esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Server readable data: %s\n", serverString.c_str()); + return serverString; +} + +String compressedDataPackageToServerReadableString(CompressedDataPackage compressedDataPackage, + const String &clientMacAddress) { + StaticJsonDocument<300> serverDoc; + String hostMacAddressString = WiFi.macAddress(); + hostMacAddressString.replace(":", ""); + hostMacAddressString.toLowerCase(); + + serverDoc["host"] = hostMacAddressString; + serverDoc["client"] = clientMacAddress; + serverDoc["sensorProtocol"] = compressedDataPackage.sensorProtocol; + serverDoc["protocolAddress"] = compressedDataPackage.channel; + serverDoc["i2cAddress"] = compressedDataPackage.i2cAddress; + serverDoc["hardwareName"] = compressedDataPackage.hardwareName; + // 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; + String serverString; serializeJson(serverDoc, serverString); esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Server readable data: %s\n", serverString.c_str()); diff --git a/host/host_central_mast/lib/Utilities/Utilities.h b/host/host_central_mast/lib/Utilities/Utilities.h index dc18e3459e0fabe83c64f2e09a4a9ae3bf8c45f6..0b7c61417991f8f45a162ad06eda93ea1e33bb2e 100644 --- a/host/host_central_mast/lib/Utilities/Utilities.h +++ b/host/host_central_mast/lib/Utilities/Utilities.h @@ -5,6 +5,7 @@ #ifndef HOST_CENTRAL_MAST_UTILITIES_H #define HOST_CENTRAL_MAST_UTILITIES_H +#include "../../../client/libs/espnow/src/CompressedDataPackage.hpp" #include "ArduinoJson.h" #include "SD.h" #include "SDCardException.h" @@ -34,5 +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); #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 f58fa1c40856d2fef8709c785c7308b50a97618e..f653905482e385958aa0c8ba695d2c126dc8ab52 100644 --- a/host/host_central_mast/src/main.cpp +++ b/host/host_central_mast/src/main.cpp @@ -5,6 +5,7 @@ #define TINY_GSM_MODEM_SIM7000 +#include "../../../client/libs/espnow/src/CompressedDataPackage.hpp" #include "ConnectionManager.h" #include "MessageType.h" #include "SDCardLogger.h" @@ -58,9 +59,12 @@ void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) { void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { esp_log_write(ESP_LOG_INFO, TAG_ESPNOW, "Message recieved\n"); // copy received data to a char array - char data[len]; - memcpy(data, incomingData, len); - esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Raw received Data: %s\n", data); + CompressedDataPackage compressedDataPackage{}; + memcpy(&compressedDataPackage, incomingData, sizeof(CompressedDataPackage)); + // esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Raw received Data: %s\n", data); + + // log received data + esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Received Data: %s\n", compressedDataPackage.toString().c_str()); if (!esp_now_is_peer_exist(mac)) { esp_now_peer_info_t client = {}; @@ -74,8 +78,6 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { } } - DynamicJsonDocument doc = parseReceivedJsonData(data); - // TODO: Respond to the client. Maybe do that before parsing anything response response = {}; response.type = dataAck; @@ -86,15 +88,10 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { String macAddress = getMacAddressAsString(mac); - // add timestamp and mac address - // doc["timestamp"] = rtc.getEpoch(); - doc["clientMac"] = macAddress; - - documentToServerReadableString(doc); + auto doc = compressedDataPackageToServerReadableString(compressedDataPackage, macAddress); // serialize json document again std::string dataString{}; - serializeJson(doc, dataString); try { SDUtilities::saveStringToSDCard(dataString); @@ -102,12 +99,8 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) { esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW, "Failed to save data to SD card: %s", e.what()); } - String lineData = documentToLineProtocolString(doc); - - esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW, "Line protocol data: %s\n", lineData.c_str()); - xSemaphoreTake(xMutex, portMAX_DELAY); - queue.push(lineData); + queue.emplace(dataString.c_str()); xSemaphoreGive(xMutex); }