From 6e4d88e8c4d9f6a18b70153dd3fc415680a33c8a Mon Sep 17 00:00:00 2001
From: Bilal Hassan <bilal.hassan@student.uibk.ac.at>
Date: Fri, 18 Nov 2022 17:26:30 +0100
Subject: [PATCH] adding code for Mieming

---
 .../Mieming/client_esp32C3/client/.gitignore  |   5 +
 Tests/Mieming/client_esp32C3/client/.gitkeep  |   0
 .../client/.vscode/extensions.json            |  10 ++
 .../client/.vscode/settings.json              |  54 ++++++++
 .../client/include/ForteSensor.hpp            |  17 +++
 .../client/include/MeasurementData.hpp        |  39 ++++++
 .../include/NoDataAvailableException.hpp      |   8 ++
 .../client_esp32C3/client/include/Pinout.hpp  |  10 ++
 .../client/include/Protocol.hpp               |  15 +++
 .../client_esp32C3/client/include/README      |  39 ++++++
 .../client/include/SensorInformation.hpp      |  25 ++++
 .../Mieming/client_esp32C3/client/lib/README  |  46 +++++++
 .../client/lib/caching/src/ram_caching.cpp    |  56 +++++++++
 .../client/lib/caching/src/ram_caching.hpp    |  16 +++
 .../client/lib/deep_sleep/f_deep_sleep.cpp    |  43 +++++++
 .../client/lib/deep_sleep/f_deep_sleep.hpp    |  18 +++
 .../client/lib/dr26_analogue/dr26.cpp         |  85 +++++++++++++
 .../client/lib/dr26_analogue/dr26.hpp         |  29 +++++
 .../client/lib/drs26_digital/drs26.cpp        |  61 +++++++++
 .../client/lib/drs26_digital/drs26.hpp        |  37 ++++++
 .../client_esp32C3/client/lib/espnow/README   |  11 ++
 .../lib/espnow/src/ClientDataPackage.hpp      |  54 ++++++++
 .../client/lib/espnow/src/ESPNow.cpp          | 118 ++++++++++++++++++
 .../client/lib/espnow/src/ESPNow.hpp          |  32 +++++
 .../client/lib/espnow/src/Message.cpp         |  43 +++++++
 .../client/lib/espnow/src/Message.hpp         |  27 ++++
 .../client/lib/ina219/ina219.cpp              |  35 ++++++
 .../client/lib/ina219/ina219.hpp              |  33 +++++
 .../client_esp32C3/client/lib/scd30/scd30.cpp |  44 +++++++
 .../client_esp32C3/client/lib/scd30/scd30.hpp |  31 +++++
 .../client/lib/time/src/Time.cpp              |  28 +++++
 .../client/lib/time/src/Time.hpp              |  75 +++++++++++
 .../client_esp32C3/client/platformio.ini      |  35 ++++++
 .../client_esp32C3/client/src/main.cpp        | 114 +++++++++++++++++
 .../Mieming/client_esp32C3/client/test/README |  11 ++
 .../client/test/TestClientDataPackage.cpp     |  46 +++++++
 .../client/test/TestClientDataPackage.hpp     |  16 +++
 .../client_esp32C3/client/test/TestESPNow.cpp |  12 ++
 .../client_esp32C3/client/test/TestESPNow.hpp |   6 +
 .../client_esp32C3/client/test/main.cpp       |  18 +++
 40 files changed, 1402 insertions(+)
 create mode 100644 Tests/Mieming/client_esp32C3/client/.gitignore
 create mode 100644 Tests/Mieming/client_esp32C3/client/.gitkeep
 create mode 100644 Tests/Mieming/client_esp32C3/client/.vscode/extensions.json
 create mode 100644 Tests/Mieming/client_esp32C3/client/.vscode/settings.json
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/ForteSensor.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/MeasurementData.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/NoDataAvailableException.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/Pinout.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/Protocol.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/README
 create mode 100644 Tests/Mieming/client_esp32C3/client/include/SensorInformation.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/README
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/README
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/src/ClientDataPackage.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/time/src/Time.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/lib/time/src/Time.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/platformio.ini
 create mode 100644 Tests/Mieming/client_esp32C3/client/src/main.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/README
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/TestESPNow.cpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/TestESPNow.hpp
 create mode 100644 Tests/Mieming/client_esp32C3/client/test/main.cpp

diff --git a/Tests/Mieming/client_esp32C3/client/.gitignore b/Tests/Mieming/client_esp32C3/client/.gitignore
new file mode 100644
index 0000000..89cc49c
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/.gitignore
@@ -0,0 +1,5 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch
diff --git a/Tests/Mieming/client_esp32C3/client/.gitkeep b/Tests/Mieming/client_esp32C3/client/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/Mieming/client_esp32C3/client/.vscode/extensions.json b/Tests/Mieming/client_esp32C3/client/.vscode/extensions.json
new file mode 100644
index 0000000..080e70d
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/.vscode/extensions.json
@@ -0,0 +1,10 @@
+{
+    // See http://go.microsoft.com/fwlink/?LinkId=827846
+    // for the documentation about the extensions.json format
+    "recommendations": [
+        "platformio.platformio-ide"
+    ],
+    "unwantedRecommendations": [
+        "ms-vscode.cpptools-extension-pack"
+    ]
+}
diff --git a/Tests/Mieming/client_esp32C3/client/.vscode/settings.json b/Tests/Mieming/client_esp32C3/client/.vscode/settings.json
new file mode 100644
index 0000000..85c4d1b
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/.vscode/settings.json
@@ -0,0 +1,54 @@
+{
+    "files.associations": {
+        "optional": "cpp",
+        "array": "cpp",
+        "atomic": "cpp",
+        "*.tcc": "cpp",
+        "cctype": "cpp",
+        "clocale": "cpp",
+        "cmath": "cpp",
+        "cstdarg": "cpp",
+        "cstddef": "cpp",
+        "cstdint": "cpp",
+        "cstdio": "cpp",
+        "cstdlib": "cpp",
+        "cstring": "cpp",
+        "ctime": "cpp",
+        "cwchar": "cpp",
+        "cwctype": "cpp",
+        "deque": "cpp",
+        "list": "cpp",
+        "unordered_map": "cpp",
+        "unordered_set": "cpp",
+        "vector": "cpp",
+        "exception": "cpp",
+        "algorithm": "cpp",
+        "functional": "cpp",
+        "iterator": "cpp",
+        "map": "cpp",
+        "memory": "cpp",
+        "memory_resource": "cpp",
+        "numeric": "cpp",
+        "random": "cpp",
+        "string": "cpp",
+        "string_view": "cpp",
+        "system_error": "cpp",
+        "tuple": "cpp",
+        "type_traits": "cpp",
+        "utility": "cpp",
+        "fstream": "cpp",
+        "initializer_list": "cpp",
+        "iomanip": "cpp",
+        "iosfwd": "cpp",
+        "iostream": "cpp",
+        "istream": "cpp",
+        "limits": "cpp",
+        "new": "cpp",
+        "ostream": "cpp",
+        "sstream": "cpp",
+        "stdexcept": "cpp",
+        "streambuf": "cpp",
+        "cinttypes": "cpp",
+        "typeinfo": "cpp"
+    }
+}
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/include/ForteSensor.hpp b/Tests/Mieming/client_esp32C3/client/include/ForteSensor.hpp
new file mode 100644
index 0000000..add5a01
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/ForteSensor.hpp
@@ -0,0 +1,17 @@
+#ifndef _FORTE_SENSOR
+#define _FORTE_SENSOR
+
+#include "Message.hpp"
+#include "Protocol.hpp"
+#include "SensorInformation.hpp"
+template <class T>
+class ForteSensor {
+  public:
+	virtual T readData() = 0;
+	virtual void setup() = 0;
+	virtual std::list<Message> buildMessages() = 0;
+	[[nodiscard]] virtual SensorInformation getSensorInformation() const = 0;
+	virtual ~ForteSensor() = default;
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/include/MeasurementData.hpp b/Tests/Mieming/client_esp32C3/client/include/MeasurementData.hpp
new file mode 100644
index 0000000..36bd5db
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/MeasurementData.hpp
@@ -0,0 +1,39 @@
+//
+// Created by cynthya on 10/6/22.
+//
+
+#ifndef CLIENT_MEASUREMENTDATA_HPP
+#define CLIENT_MEASUREMENTDATA_HPP
+
+#include "ArduinoJson.h"
+#include "Protocol.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;
+};
+#endif // CLIENT_MEASUREMENTDATA_HPP
diff --git a/Tests/Mieming/client_esp32C3/client/include/NoDataAvailableException.hpp b/Tests/Mieming/client_esp32C3/client/include/NoDataAvailableException.hpp
new file mode 100644
index 0000000..83c5697
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/NoDataAvailableException.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <exception>
+#include <iostream>
+
+struct NoDataAvailableException : public std::exception {
+	const char *what() const noexcept override { return "Sensor could not read data"; }
+};
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/include/Pinout.hpp b/Tests/Mieming/client_esp32C3/client/include/Pinout.hpp
new file mode 100644
index 0000000..f277fd9
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/Pinout.hpp
@@ -0,0 +1,10 @@
+#ifndef _FORTE_PINOUT
+#define _FORTE_PINOUT
+
+// Pins for I2C
+constexpr int I2C_SDA = 18;
+constexpr int I2C_SCL = 19;
+
+// TODO: IF THE BOARD CHANGES (I.E. ESPCAM MODULE), THESE HAVE TO BE CHANGED (EITHER COMPILE TIME FLAG OR IFDEF OR SMTH)
+
+#endif
diff --git a/Tests/Mieming/client_esp32C3/client/include/Protocol.hpp b/Tests/Mieming/client_esp32C3/client/include/Protocol.hpp
new file mode 100644
index 0000000..92270db
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/Protocol.hpp
@@ -0,0 +1,15 @@
+//
+// Created by zoe on 10/5/22.
+//
+
+#ifndef CLIENT_PROTOCOL_HPP
+#define CLIENT_PROTOCOL_HPP
+
+#include <map>
+enum class Protocol { I2C, RS485, Analog };
+
+// protocol to string
+const static std::map<Protocol, const char *> protocolToString = {
+    {Protocol::I2C, "I2C"}, {Protocol::RS485, "RS485"}, {Protocol::Analog, "ANALOG"}};
+
+#endif // CLIENT_PROTOCOL_HPP
diff --git a/Tests/Mieming/client_esp32C3/client/include/README b/Tests/Mieming/client_esp32C3/client/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/README
@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
diff --git a/Tests/Mieming/client_esp32C3/client/include/SensorInformation.hpp b/Tests/Mieming/client_esp32C3/client/include/SensorInformation.hpp
new file mode 100644
index 0000000..4b8af5d
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/include/SensorInformation.hpp
@@ -0,0 +1,25 @@
+//
+// Created by cynthya on 10/6/22.
+//
+
+#ifndef CLIENT_SENSORINFORMATION_HPP
+#define CLIENT_SENSORINFORMATION_HPP
+
+#include "Protocol.hpp"
+#include <string>
+
+class SensorInformation {
+  public:
+	SensorInformation(std::string sensorName, Protocol protocol) : sensorName(std::move(sensorName)), protocol(protocol)
+	{
+	}
+
+	[[nodiscard]] const std::string &getSensorName() const { return sensorName; }
+	[[nodiscard]] Protocol getProtocol() const { return protocol; }
+
+  private:
+	std::string sensorName;
+	Protocol protocol;
+};
+
+#endif // CLIENT_SENSORINFORMATION_HPP
diff --git a/Tests/Mieming/client_esp32C3/client/lib/README b/Tests/Mieming/client_esp32C3/client/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+|  |
+|  |--Bar
+|  |  |--docs
+|  |  |--examples
+|  |  |--src
+|  |     |- Bar.c
+|  |     |- Bar.h
+|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+|  |
+|  |--Foo
+|  |  |- Foo.c
+|  |  |- Foo.h
+|  |
+|  |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+   |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+  ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.cpp b/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.cpp
new file mode 100644
index 0000000..641f974
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.cpp
@@ -0,0 +1,56 @@
+#include "ram_caching.hpp"
+
+namespace RtcMemory{
+    // 2D array of 20 Strings with maxLength of 251
+    RTC_DATA_ATTR char storage[maxLength_][maxSize_];
+    RTC_DATA_ATTR int storedElements;
+    RTC_DATA_ATTR int headElement = 0;
+    RTC_DATA_ATTR int tailElement = 0;
+
+    static const char* TAG = "CACHING";
+
+
+    void store(std::string message){
+
+        // turn data into char array
+        const char* jsonString = message.c_str();
+    
+        // move head to new element
+        headElement = (headElement + 1) % maxSize_;
+        // apparently I am not allowed to copy to rtc mem
+        for(int i=0; i<maxLength_; i++){
+            storage[i][headElement] = jsonString[i];
+            if(jsonString[i] == '\0'){
+                break;
+            }
+        }
+        storedElements++;
+        ESP_LOGE(TAG, "Moved message to storage.");
+    }
+
+    String get_from_storage(){
+        // remove element pointed at by tail
+        String buf = "";
+        char current = '\0';
+        for(int i = 0; i<maxLength_; i++){
+            current = storage[i][tailElement];
+            buf += current;
+            if(current == '\0'){
+                break;
+            }
+        }
+        // move tail to next element
+        tailElement = (tailElement + 1) % maxSize_;
+        storedElements--;
+        ESP_LOGE(TAG, "Retrieved message from storage");
+        return buf;
+    }
+
+    bool is_full(){
+        return headElement == tailElement;
+    }
+
+    int stored_amount(){
+        return storedElements;
+    }
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.hpp b/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.hpp
new file mode 100644
index 0000000..c1a4ac5
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/caching/src/ram_caching.hpp
@@ -0,0 +1,16 @@
+#ifndef _RAM_CACHE
+#define _RAM_CACHE
+#include "esp_log.h"
+#include <ESP32Time.h>
+
+#define maxSize_ 20
+#define maxLength_ 251
+
+namespace RtcMemory {
+    void store(std::string message);
+    String get_from_storage();
+    bool is_full();
+    int stored_amount();
+}
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.cpp b/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.cpp
new file mode 100644
index 0000000..c434f53
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.cpp
@@ -0,0 +1,43 @@
+#include "f_deep_sleep.hpp"
+#include "esp32-hal-log.h"
+#include "esp_log.h"
+
+namespace DeepSleep {
+static const std::string TAG = "DEEP_SLEEP";
+
+
+void print_wakeup_reason()
+{
+	esp_sleep_wakeup_cause_t wakeup_reason;
+
+	wakeup_reason = esp_sleep_get_wakeup_cause();
+
+	switch (wakeup_reason) {
+	case ESP_SLEEP_WAKEUP_EXT0:
+		ESP_LOGD(TAG.c_str(), "Wakeup caused by external signal using RTC_IO");
+		break;
+	case ESP_SLEEP_WAKEUP_EXT1:
+		ESP_LOGD(TAG.c_str(), "Wakeup caused by external signal using RTC_CNTL");
+		break;
+	case ESP_SLEEP_WAKEUP_TIMER:
+		ESP_LOGD(TAG.c_str(), "Wakeup caused by timer");
+		break;
+	case ESP_SLEEP_WAKEUP_TOUCHPAD:
+		ESP_LOGD(TAG.c_str(), "Wakeup caused by touchpad");
+		break;
+	case ESP_SLEEP_WAKEUP_ULP:
+		ESP_LOGD(TAG.c_str(), "Wakeup caused by ULP program");
+		break;
+	default:
+		ESP_LOGD(TAG.c_str(), "Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
+		break;
+	}
+}
+
+void deep_sleep(int time_in_sec)
+{
+	esp_sleep_enable_timer_wakeup(time_in_sec * 1000000);
+	esp_deep_sleep_start();
+}
+
+}; // namespace DeepSleep
diff --git a/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.hpp b/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.hpp
new file mode 100644
index 0000000..7a528c8
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/deep_sleep/f_deep_sleep.hpp
@@ -0,0 +1,18 @@
+#ifndef F_DEEP_SLEEP_H
+#define F_DEEP_SLEEP_H
+
+#include <Arduino.h>
+
+namespace DeepSleep {
+// https://en.cppreference.com/w/cpp/language/storage_duration
+// When used in a declaration at namespace scope, it specifies internal linkage.
+// internal linkage. The variable can be referred to from all scopes in the current translation unit. All variables
+// which are declared at file scope have this linkage, including variables declared static at file scope.
+static RTC_DATA_ATTR int bootCount = 0;
+
+void deep_sleep(int time_to_sleep_in_seconds);
+void print_wakeup_reason();
+
+} // namespace DeepSleep
+
+#endif
diff --git a/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.cpp b/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.cpp
new file mode 100644
index 0000000..f41a445
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.cpp
@@ -0,0 +1,85 @@
+#include "dr26.hpp"
+
+void ForteDR26 ::setup()
+{
+	Wire.begin(6, 7);
+  //  ads.setGain(GAIN_ONE);
+  //  ads.begin() ?  Serial.println("ADS initialized") : Serial.println("failed to initialize ADS");
+
+
+    ads1.setGain(GAIN_ONE);
+    ads1.begin() ?  Serial.println("ADS initialized") : Serial.println("failed to initialize ADS");
+    delay(100);
+    channel=0;
+}
+
+float ForteDR26 ::readData()
+{
+	float volts=0;
+    for(int i=0; i<10; i++){
+        int16_t adc = 0;
+        float volt = 0;
+        try
+        {
+            adc = ads1.readADC_SingleEnded(channel);
+            volt = ads1.computeVolts(adc);
+        }
+        catch(NoDataAvailableException& e)
+        {
+	        throw NoDataAvailableException();  //propagate exception
+        }
+        volts += volt;
+    }
+
+    volts /= 10;
+    return volts;
+}
+
+// The following functions change the ADC input range: be careful
+// to never to exceed VDD +0.3V max, or to exceed the upper and
+// lower limits if you adjust the input range.
+// SETTING THE GAIN VALUE INCORRECTLY MAY DESTROY THE ADC!
+// The maximum output of the dendrometer is 2.5V, and so a gain of
+// one (max 4.096V) or two (max 2.048V) is optimal. Changing the gain
+// changes the accuracy of the sensor: higher gain gives a higher
+// precision but a smaller range.
+//
+// GAIN_TWOTHIRDS  // 2/3x gain +/- 6.144V  1 bit = 0.1875mV (default)
+// GAIN_ONE        // 1x gain   +/- 4.096V  1 bit = 0.125mV
+// GAIN_TWO        // 2x gain   +/- 2.048V  1 bit = 0.0625mV
+// GAIN_FOUR       // 4x gain   +/- 1.024V  1 bit = 0.03125mV
+// GAIN_EIGHT      // 8x gain   +/- 0.512V  1 bit = 0.015625mV
+// GAIN_SIXTEEN    // 16x gain  +/- 0.256V  1 bit = 0.0078125mV
+void ForteDR26 ::changeGain(adsGain_t gain)
+{
+	ads1.setGain(gain);
+}
+
+void ForteDR26 ::setChannel(int c)
+{
+	channel=c;
+}
+std::list<Message> ForteDR26::buildMessages()
+{
+	std::list<Message> messages;
+	float data = readData();
+	MeasurementData IncrementData{data, 0, {}, "CIRCUMFERENCE_INCREMENT"};
+	messages.emplace_back(IncrementData, sensorInformation, Time::getInstance().getEpochSeconds());
+	return messages;
+}
+
+std::list<Message> ForteDR26::buildMessages(int channel,std::string measurementType)
+{
+	std::list<Message> messages;
+	float data = readData();
+	MeasurementData IncrementData{data, channel, {}, measurementType};
+	messages.emplace_back(IncrementData, sensorInformation, Time::getInstance().getEpochSeconds());
+	return messages;
+}
+SensorInformation ForteDR26::getSensorInformation() const
+{
+	return sensorInformation;
+}
+
+
+Adafruit_ADS1115 ForteDR26::ads1=ads1;
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.hpp b/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.hpp
new file mode 100644
index 0000000..b60c099
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/dr26_analogue/dr26.hpp
@@ -0,0 +1,29 @@
+#ifndef _DR26
+#define _DR26
+
+#include "Adafruit_ADS1X15.h"
+#include "ForteSensor.hpp"
+#include "Message.hpp"
+#include "Pinout.hpp"
+#include "esp_log.h"
+#include <Wire.h>
+#include "NoDataAvailableException.hpp"
+
+class ForteDR26 : public ForteSensor<float> {
+  public:
+	void setup() override;
+	float readData() override;
+	void changeGain(adsGain_t gain);
+	void setChannel(int channel);
+	std::list<Message> buildMessages() override;
+	std::list<Message> buildMessages(int channel,std::string mesurment_type);
+	[[nodiscard]] SensorInformation getSensorInformation() const override;
+	static Adafruit_ADS1115 ads1;
+
+  private:
+	Adafruit_ADS1115 ads;
+	const SensorInformation sensorInformation{"DR26", Protocol::Analog};
+	int channel;
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.cpp b/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.cpp
new file mode 100644
index 0000000..5c21f3a
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.cpp
@@ -0,0 +1,61 @@
+#include <drs26.hpp>
+
+/*
+It happens for some reason that the sensor cant get reached every 2 time
+Because the sensor use sdi12 protocoll we have to wait aproxemettly 1 secound between the commands
+It is not known how lond the response takes so we use a while loop which can be a risk wehre the programm can get stuck
+*/
+
+void ForteDRS26 ::setup()
+{
+	drs26.begin(4);
+}
+
+out_data_drs26 ForteDRS26 ::readData()
+{
+	String sdiResponse = "";
+	String measurement_command =
+	    "1M!"; // The drs26 sensor uses the sdi12 protocoll , in the sdi12 protocoll is the measurement command is
+	           // specified as 1M!=Sebsir measurement request at adress 1
+	String data_command = "1D0!"; // and the followed data command 1D0! = Sensor data request at adress 1
+
+	drs26.sendCommand(measurement_command);
+	delay(1000);
+	drs26.sendCommand(data_command);
+
+	data = {-1, -1, -1};
+
+	while (drs26.available()) {
+		char next_character = drs26.read();
+		if ((next_character != '\n') && (next_character != '\r')) {
+			sdiResponse += next_character;
+			delay(10); // 1 character ~ 7.5ms
+		}
+	}
+
+	if (sdiResponse.length() > 1) {
+		data.id = sdiResponse.substring(0, 8).toInt();
+		data.circumferenceIncrement = sdiResponse.substring(9, 15).toFloat();
+		data.temperature = sdiResponse.substring(16, 22).toFloat();
+	}
+	return data;
+}
+
+std::list<Message> ForteDRS26 ::buildMessages()
+{
+	std::list<Message> messages;
+	MeasurementData circumferenceIncrementMeasurementData{
+	    data.circumferenceIncrement, 0, {}, measurementTypeToString.at(MeasurementType::CIRCUMFERENCE_INCREMENT)};
+	MeasurementData temperatureMeasurementData{
+	    data.temperature, 0, {}, measurementTypeToString.at(MeasurementType::TEMPERATURE)};
+
+	messages.emplace_back(Message{circumferenceIncrementMeasurementData, sensorInformation, 0});
+	messages.emplace_back(Message{temperatureMeasurementData, sensorInformation, 0});
+
+	ESP_LOGE(sensorInformation.getSensorName().c_str(), "test");
+	return messages;
+}
+SensorInformation ForteDRS26::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.hpp b/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.hpp
new file mode 100644
index 0000000..0d713ca
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/drs26_digital/drs26.hpp
@@ -0,0 +1,37 @@
+#ifndef _DRS26
+#define _DRS26
+
+#include "ForteSensor.hpp"
+#include "Message.hpp"
+#include "Pinout.hpp"
+#include "Wire.h"
+#include "esp_log.h"
+#include <SDI12.h>
+#include <map>
+
+struct out_data_drs26 {
+	int id;
+	float circumferenceIncrement;
+	float temperature;
+};
+
+class ForteDRS26 : public ForteSensor<out_data_drs26> {
+  public:
+	void setup() override;
+	out_data_drs26 readData() override;
+	std::list<Message> buildMessages() override;
+	[[nodiscard]] SensorInformation getSensorInformation() const override;
+
+  private:
+	SDI12 drs26;
+	out_data_drs26 data;
+	const SensorInformation sensorInformation{"DRS26", Protocol::I2C};
+	enum class MeasurementType { TEMPERATURE, CIRCUMFERENCE_INCREMENT };
+
+	// enum to string
+	std::map<MeasurementType, const char *> measurementTypeToString = {
+	    {MeasurementType::TEMPERATURE, "TEMPERATURE"},
+	    {MeasurementType::CIRCUMFERENCE_INCREMENT, "CIRCUMFERENCE_INCREMENT"}};
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/espnow/README b/Tests/Mieming/client_esp32C3/client/lib/espnow/README
new file mode 100644
index 0000000..bbf1db0
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/README
@@ -0,0 +1,11 @@
+# basic usage
+
+To send data using espnow, create a new Message object,
+then use the addData(value, identifier) method for every value
+to fill the message.
+when every value is added, use the send() method to send the data
+to the host (fipy). If the esp client has never recieved a config
+message from the host, it will instead broadcast the message.
+
+---
+right now, it is not possible to add more than 10 values.
diff --git a/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ClientDataPackage.hpp b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ClientDataPackage.hpp
new file mode 100644
index 0000000..f08e6bb
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ClientDataPackage.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <ArduinoJson.h>
+#include "MeasurementData.hpp"
+#include "Protocol.hpp"
+#include "SensorInformation.hpp"
+#include <list>
+#include <optional>
+#include <string>
+#include <utility>
+
+// 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;
+	}
+
+};
diff --git a/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.cpp b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.cpp
new file mode 100644
index 0000000..28eedfb
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.cpp
@@ -0,0 +1,118 @@
+#include "ESPNow.hpp"
+
+static const char *TAG = "ESPNOW";
+
+uint8_t BROADCAST_MAC[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+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;
+}
+
+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_LOGE(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);
+}
+
+void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status)
+{
+	ESP_LOGE(TAG, "Message sent to");
+	for(int i=0; i<6; i++){
+		Serial.print(mac_addr[i], HEX);
+		Serial.print(":");
+	}
+	Serial.println();
+	// go to sleep
+}
+
+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_LOGE(TAG, "Message recieved");
+	preferences.begin("config", false);
+	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	
+	switch (received_msg.type){
+		case dataAck:{
+			msg_recv = true;
+			Time::getInstance().setTime(
+			received_msg.epoch_seconds); // see https://www.esp32.com/viewtopic.php?t=9965, maybe this needs an offset
+			Serial.println(Time::getInstance().getEpochSeconds());
+			if (!preferences.isKey("host")) {
+			preferences.putBytes("host", received_msg.host, sizeof(received_msg.host));
+			ESP_LOGI(TAG, "host MAC address saved to flash");
+
+			// add host to peers
+			add_host_to_peers(received_msg);
+			}
+		}
+		case hostChange:{
+			Time::getInstance().setTime(received_msg.epoch_seconds);
+			// delete old host
+			if(preferences.isKey("host")){
+				uint8_t old[6];
+				get_host_mac(old);
+				esp_now_del_peer(old);
+			}
+			// add new host
+			add_host_to_peers(received_msg);
+		}
+		default:{
+			return;
+		}
+	}
+	preferences.end();
+}
+
+
+esp_err_t espnow_setup()
+{
+	esp_err_t result;
+	WiFi.mode(WIFI_STA);
+	result = esp_now_init();
+	if (result != ESP_OK) {
+		// initialization 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
+
+	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);
+
+	preferences.clear();
+	esp_now_register_recv_cb(on_data_recv);
+	esp_now_register_send_cb(on_data_sent);
+
+	return ESP_OK;
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.hpp b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.hpp
new file mode 100644
index 0000000..266b139
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/ESPNow.hpp
@@ -0,0 +1,32 @@
+#ifndef _ESPNOW
+#define _ESPNOW
+
+#include "Message.hpp"
+#include "Time.hpp"
+#include "esp_log.h"
+#include "ram_caching.hpp"
+#include <ClientDataPackage.hpp>
+#include <ESP32Time.h>
+#include <Preferences.h>
+#include <WiFi.h>
+#include <esp_now.h>
+
+enum MessageType{
+    dataAck,
+    hostChange
+};
+typedef struct config {
+	MessageType type;
+	uint8_t host[6];
+	long epoch_seconds;
+} config;
+
+esp_err_t espnow_setup();
+//esp_err_t espnow_send_message(const Message& message);
+bool is_host_defined();
+bool was_msg_received();
+void get_host_mac(uint8_t *destination);
+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);
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.cpp b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.cpp
new file mode 100644
index 0000000..7f7f8e2
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.cpp
@@ -0,0 +1,43 @@
+#include "Message.hpp"
+
+#include <utility>
+
+static const char *TAG = "MESSAGE";
+
+esp_err_t Message::send() const
+{
+	ESP_LOGI(TAG, "Sending message");
+	esp_err_t success;
+	auto messageData = getMessageAsMinifiedJsonString();
+
+	// 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");
+		Serial.println(success, HEX);
+		// Removed caching from here, better do this in main
+	}
+	ESP_LOGE(TAG, "Sent data: %s", messageData.c_str());
+
+	ESP_LOGD(TAG, "time sent: %l", clientDataPackage.getTimestamp());
+	ESP_LOGD(TAG, "send status: %d", success);
+
+	return success;
+}
+
+std::string Message::getMessageAsMinifiedJsonString() const
+{
+	return clientDataPackage.getDataPackageAsMinifiedJsonString();
+}
+
+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/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.hpp b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.hpp
new file mode 100644
index 0000000..5a6ca81
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/espnow/src/Message.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "ClientDataPackage.hpp"
+#include "ESPNow.hpp"
+#include "Time.hpp"
+#include "esp_log.h"
+#include <Arduino.h>
+#include <ArduinoJson.h>
+#include <ESP32Time.h>
+#include <esp_now.h>
+
+// Format of the message sent from host to client
+// if more things are sent from the host the name might not be accurate anymore
+class Message {
+  public:
+
+	explicit Message(ClientDataPackage data);
+
+	Message(MeasurementData const &data, const SensorInformation &information, unsigned long timestamp);
+	esp_err_t send() const;
+	[[nodiscard]] std::string getMessageAsMinifiedJsonString() const;
+
+  private:
+	ClientDataPackage clientDataPackage;
+	uint8_t recipient[6]{};
+};
+
diff --git a/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.cpp b/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.cpp
new file mode 100644
index 0000000..def6a9d
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.cpp
@@ -0,0 +1,35 @@
+#include "ina219.hpp"
+
+void ForteINA219 ::setup()
+{
+	Wire.begin(I2C_SDA, I2C_SCL);
+	if (!ina219.init()) {
+		// Sensor init went wrong
+		ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed");
+		return;
+	}
+}
+
+out_data_ina219 ForteINA219 ::readData()
+{
+	if (!ina219.getOverflow()) {
+		data.shuntVoltage_mV = ina219.getShuntVoltage_mV();
+		data.busVoltage_V = ina219.getBusVoltage_V();
+		data.current_mA = ina219.getCurrent_mA();
+		data.power_mW = ina219.getBusPower();
+		data.loadVoltage_V = data.busVoltage_V + (data.shuntVoltage_mV / 1000);
+		data.ina219_overflow = ina219.getOverflow();
+
+		return data;
+	} else
+		return data;
+}
+
+std::list<Message> ForteINA219::buildMessages()
+{
+	throw "Not yet implemented";
+}
+SensorInformation ForteINA219::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.hpp b/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.hpp
new file mode 100644
index 0000000..4a34d95
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/ina219/ina219.hpp
@@ -0,0 +1,33 @@
+#ifndef _INA219
+#define _INA219
+
+#include "ForteSensor.hpp"
+#include "Message.hpp"
+#include "Pinout.hpp"
+#include "Wire.h"
+#include "esp_log.h"
+#include <INA219_WE.h>
+
+struct out_data_ina219 {
+	float shuntVoltage_mV = 0.0;
+	float loadVoltage_V = 0.0;
+	float busVoltage_V = 0.0;
+	float current_mA = 0.0;
+	float power_mW = 0.0;
+	bool ina219_overflow = false;
+};
+
+class ForteINA219 : public ForteSensor<out_data_ina219> {
+  public:
+	void setup() override;
+	out_data_ina219 readData() override;
+	std::list<Message> buildMessages() override;
+	[[nodiscard]] SensorInformation getSensorInformation() const override;
+
+  private:
+	INA219_WE ina219;
+	out_data_ina219 data;
+	const SensorInformation sensorInformation{"INA219", Protocol::I2C};
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.cpp b/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.cpp
new file mode 100644
index 0000000..7cff381
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.cpp
@@ -0,0 +1,44 @@
+#include "scd30.hpp"
+
+void ForteSCD30 ::setup()
+{
+	Wire.begin(I2C_SDA, I2C_SCL);
+	if (!airSensor.begin()) {
+		// Sensor init went wrong
+		ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed.");
+		return;
+	}
+}
+
+out_data_scd30 ForteSCD30 ::readData()
+{
+	if (airSensor.dataAvailable()) {
+		data.C02 = airSensor.getCO2();
+		data.Temperature = airSensor.getTemperature();
+		data.Humidity = airSensor.getHumidity();
+
+		return data;
+	}
+	throw NoDataAvailableException();
+}
+
+std::list<Message> ForteSCD30::buildMessages()
+{
+	std::list<Message> messages;
+
+	out_data_scd30 data = readData();
+	MeasurementData CO2Data{data.C02, 0, {}, "CO2"};
+	MeasurementData TempData{data.Temperature, 0, {}, "Temperature"};
+	MeasurementData HumidData{data.Humidity, 0, {}, "Humidity"};
+
+	messages.emplace_back(Message(CO2Data, sensorInformation, Time::getInstance().getEpochSeconds()));
+	messages.emplace_back(Message(TempData, sensorInformation, Time::getInstance().getEpochSeconds()));
+	messages.emplace_back(Message(HumidData, sensorInformation, Time::getInstance().getEpochSeconds()));
+	
+	return messages;
+}
+
+SensorInformation ForteSCD30::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.hpp b/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.hpp
new file mode 100644
index 0000000..db3e855
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/scd30/scd30.hpp
@@ -0,0 +1,31 @@
+#ifndef _SCD30
+#define _SCD30
+
+#include "ForteSensor.hpp"
+#include "Message.hpp"
+#include "NoDataAvailableException.hpp"
+#include "Pinout.hpp"
+#include "esp_log.h"
+#include <SparkFun_SCD30_Arduino_Library.h>
+#include <Wire.h>
+
+struct out_data_scd30 {
+	float C02;
+	float Temperature;
+	float Humidity;
+};
+
+class ForteSCD30 : public ForteSensor<out_data_scd30> {
+  public:
+	void setup() override;
+	out_data_scd30 readData() override;
+	std::list<Message> buildMessages() override;
+	[[nodiscard]] SensorInformation getSensorInformation() const override;
+
+  private:
+	SCD30 airSensor;
+	out_data_scd30 data;
+	const SensorInformation sensorInformation{"SCD30", Protocol::I2C};
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.cpp b/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.cpp
new file mode 100644
index 0000000..5cc3dbc
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.cpp
@@ -0,0 +1,28 @@
+#include "Time.hpp"
+
+#include <utility>
+void Time::setTime(long epoch, int ms)
+{
+	this->rtc.setTime(epoch, ms);
+}
+tm Time::getTimeStruct()
+{
+	return this->rtc.getTimeStruct();
+}
+String Time::getDateTime(bool mode)
+{
+	return this->rtc.getDateTime(mode);
+}
+String Time::getTime(String format)
+{
+	return this->rtc.getTime(std::move(format));
+}
+unsigned long Time::getEpochSeconds()
+{
+	return this->rtc.getEpoch();
+}
+
+long Time::getMillis()
+{
+	return this->rtc.getMillis();
+}
diff --git a/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.hpp b/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.hpp
new file mode 100644
index 0000000..783bdef
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/lib/time/src/Time.hpp
@@ -0,0 +1,75 @@
+#ifndef ESPTIME
+#define ESPTIME
+
+#include <ESP32Time.h>
+
+class Time {
+  public:
+	static Time &getInstance()
+	{
+		static Time instance; // Guaranteed to be destroyed.
+		                      // Instantiated on first use.
+		return instance;
+	}
+
+	/*!
+	@brief  set the internal RTC time
+	@param  epoch
+	        epoch time in seconds
+	@param  ms
+	        microseconds (optional)
+	*/
+	void setTime(long epoch, int ms = 0);
+
+	/*!
+	@brief  get the internal RTC time as a tm struct
+	*/
+	tm getTimeStruct();
+
+	/*!
+	@brief  get the time and date as an Arduino String object
+	@param  mode
+	        true = Long date format
+	        false = Short date format
+	*/
+	String getDateTime(bool mode);
+
+	/*!
+	@brief  get the time as an Arduino String object with the specified format
+	@param	format
+	        time format
+	        http://www.cplusplus.com/reference/ctime/strftime/
+	*/
+	String getTime(String format = "%H:%M:%S");
+
+	/*!
+	@brief  get the current epoch seconds as long
+	*/
+	unsigned long getEpochSeconds();
+
+	/*!
+	@brief  get the current milliseconds as long
+	*/
+	long getMillis();
+
+  private:
+	Time() {} // Constructor? (the {} brackets) are needed here.
+
+	ESP32Time rtc = ESP32Time{};
+
+	// C++ 11
+	// =======
+	// We can use the better technique of deleting the methods
+	// we don't want.
+  public:
+	Time(Time const &) = delete;
+	void operator=(Time const &) = delete;
+
+	// Note: Scott Meyers mentions in his Effective Modern
+	//       C++ book, that deleted functions should generally
+	//       be public as it results in better error messages
+	//       due to the compilers behavior to check accessibility
+	//       before deleted status
+};
+
+#endif
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/platformio.ini b/Tests/Mieming/client_esp32C3/client/platformio.ini
new file mode 100644
index 0000000..19ee957
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/platformio.ini
@@ -0,0 +1,35 @@
+; PlatformIO Project Configuration File
+;
+;   Build options: build flags, source filter
+;   Upload options: custom upload port, speed and extra flags
+;   Library options: dependencies, extra library storages
+;   Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:esp32-c3-devkitm-1]
+platform = espressif32
+board = esp32-c3-devkitm-1
+framework = arduino
+monitor_speed = 115200
+; C++17 https://community.platformio.org/t/esp32-c-17-toolchain-missing-std-optional/25850/6
+; we use c++17 features (i.e. optionals in ClientDataPackage.hpp)
+build_flags = 
+	-I include
+	-DCORE_DEBUG_LEVEL=5
+	-std=gnu++17
+build_unflags = -std=gnu++11
+monitor_port = /dev/ttyUSB0
+upload_port = /dev/ttyUSB0
+lib_deps =
+	sparkfun/SparkFun SCD30 Arduino Library@^1.0.18
+	Wire
+	adafruit/Adafruit ADS1X15@^2.4.0
+	wollewald/INA219_WE@^1.3.1
+	adafruit/Adafruit BusIO@^1.13.2
+	Adafruit_I2CDevice
+	SPI
+	envirodiy/SDI-12@^2.1.4
+	fbiego/ESP32Time@^2.0.0
+	bblanchon/ArduinoJson@^6.19.4
diff --git a/Tests/Mieming/client_esp32C3/client/src/main.cpp b/Tests/Mieming/client_esp32C3/client/src/main.cpp
new file mode 100644
index 0000000..9cfb9c8
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/src/main.cpp
@@ -0,0 +1,114 @@
+#include "../lib/dr26_analogue/dr26.hpp"
+#include "NoDataAvailableException.hpp"
+#include "esp_log.h"
+#include "f_deep_sleep.hpp"
+#include <Arduino.h>
+#include <drs26.hpp>
+#include <ina219.hpp>
+#include <scd30.hpp>
+#include "ESPNow.hpp"
+// #include "esp32-hal-log.h"
+static const std::string TAG = "MAIN";
+
+
+ForteDR26 dr26_channel3;
+ForteDR26 dr26_channel1;
+ForteDR26 dr26_channel2;
+ForteDR26 dr26_channel0_power;
+
+void setup()
+{
+	Serial.begin(115200);
+	//Set the GPIO which conrtols the step up to OUTPUT
+	 gpio_set_direction(GPIO_NUM_3, GPIO_MODE_OUTPUT);
+	
+	
+
+
+	DeepSleep::print_wakeup_reason();
+	DeepSleep::bootCount++;
+	ESP_LOGD(TAG.c_str(), "Boot number: %d", DeepSleep::bootCount);
+
+gpio_set_level(GPIO_NUM_3, 1);
+	dr26_channel1.setup();
+	dr26_channel3.setChannel(3);
+	dr26_channel1.setChannel(1);
+	dr26_channel2.setChannel(2);
+	dr26_channel0_power.setChannel(0);
+gpio_set_level(GPIO_NUM_3, 0);
+
+	espnow_setup();
+	//	log_e("Setup complete.");
+}
+
+void loop()
+{
+gpio_set_level(GPIO_NUM_3, 1);	
+Serial.println("***********************1-DRS26 NOT YET CONNECTED**********************************");
+Serial.println(dr26_channel1.readData(),5);
+Serial.println("***********************2-DRS26**********************************");
+Serial.println(dr26_channel2.readData(),5);
+Serial.println("***********************3-DRS26 *********************************");
+Serial.println(dr26_channel3.readData(),5);
+
+
+Serial.println("***********************0-Voltage-Battery**********************************");
+dr26_channel3.changeGain(GAIN_TWOTHIRDS);
+Serial.println(dr26_channel0_power.readData(),5);
+
+
+
+	try {
+
+		auto messages = dr26_channel0_power.buildMessages(0,"Voltage-Battery");
+		
+		
+		for (const Message &message : messages) {
+			if(message.send() != ESP_OK){
+				RtcMemory::store(message.getMessageAsMinifiedJsonString());
+			}
+			delay(5000);
+			if(!was_msg_received()){
+				RtcMemory::store(message.getMessageAsMinifiedJsonString());
+			}
+		}
+		
+		dr26_channel3.changeGain(GAIN_ONE);
+		auto messages2=dr26_channel2.buildMessages(2,"CIRCUMFERENCE_INCREMENT");
+		
+		for (const Message &message2 : messages2) {
+			if(message2.send() != ESP_OK){
+				RtcMemory::store(message2.getMessageAsMinifiedJsonString());
+			}
+			delay(5000);
+			if(!was_msg_received()){
+				RtcMemory::store(message2.getMessageAsMinifiedJsonString());
+			}
+		}
+
+		auto messages3=dr26_channel3.buildMessages(3,"CIRCUMFERENCE_INCREMENT");
+
+		for (const Message &message3 : messages3) {
+			if(message3.send() != ESP_OK){
+				RtcMemory::store(message3.getMessageAsMinifiedJsonString());
+			}
+			delay(5000);
+			if(!was_msg_received()){
+				RtcMemory::store(message3.getMessageAsMinifiedJsonString());
+			}
+		}
+
+
+	} catch (const NoDataAvailableException &e) {
+		std::cerr << e.what() << '\n';
+	}
+
+
+
+	Serial.print("This device: ");
+	Serial.println("\n");
+	
+gpio_set_level(GPIO_NUM_3, 0);
+delay(5);
+	DeepSleep::deep_sleep(600);
+}
diff --git a/Tests/Mieming/client_esp32C3/client/test/README b/Tests/Mieming/client_esp32C3/client/test/README
new file mode 100644
index 0000000..9b1e87b
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PlatformIO Test Runner and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PlatformIO Unit Testing:
+- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
diff --git a/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.cpp b/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.cpp
new file mode 100644
index 0000000..eea536c
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.cpp
@@ -0,0 +1,46 @@
+//
+// Created by zoe on 10/6/22.
+//
+
+#include "TestClientDataPackage.hpp"
+#include "MeasurementData.hpp"
+#include "Protocol.hpp"
+#include <vector>
+
+void test_export_to_json()
+{
+	auto dataPackage =
+	    ClientDataPackage(MeasurementData{1.1, 0, {}, "TEMPERATURE"}, SensorInformation{"DRS26", Protocol::Analog}, 0);
+
+	std::string json = dataPackage.getDataPackageAsMinifiedJsonString();
+	// expected
+	std::string expected =
+	    R"({"sensorName":"DRS26","timestamp":0,"protocol":"ANALOG","value":1.1,"channel":0,"measurementType":"TEMPERATURE"})";
+
+	TEST_ASSERT_EQUAL_STRING(expected.c_str(), json.c_str());
+}
+void test_export_to_json_no_analog()
+{
+	auto dataPackage =
+	    ClientDataPackage(MeasurementData{1.1, {}, {}, "TEMPERATURE"}, SensorInformation{"DRS26_DIGITAL", Protocol::I2C}, 0);
+
+	std::string json = dataPackage.getDataPackageAsMinifiedJsonString();
+	// expected
+	std::string expected =
+	    R"({"sensorName":"DRS26_DIGITAL","timestamp":0,"protocol":"I2C","value":1.1,"measurementType":"TEMPERATURE"})";
+
+	TEST_ASSERT_EQUAL_STRING(expected.c_str(), json.c_str());
+}
+
+void test_export_to_json_no_channel_no_address()
+{
+	auto dataPackage =
+	    ClientDataPackage(MeasurementData{1.1,"TEMPERATURE"}, SensorInformation{"DRS26_DIGITAL", Protocol::I2C}, 0);
+
+	std::string json = dataPackage.getDataPackageAsMinifiedJsonString();
+	// expected
+	std::string expected =
+	    R"({"sensorName":"DRS26_DIGITAL","timestamp":0,"protocol":"I2C","value":1.1,"measurementType":"TEMPERATURE"})";
+
+	TEST_ASSERT_EQUAL_STRING(expected.c_str(), json.c_str());
+}
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.hpp b/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.hpp
new file mode 100644
index 0000000..fa5f203
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/TestClientDataPackage.hpp
@@ -0,0 +1,16 @@
+//
+// Created by zoe on 10/6/22.
+//
+
+#ifndef CLIENT_TESTCLIENTDATAPACKAGE_HPP
+#define CLIENT_TESTCLIENTDATAPACKAGE_HPP
+
+#include <unity.h>
+#include <Arduino.h>
+#include <ClientDataPackage.hpp>
+
+void test_export_to_json();
+void test_export_to_json_no_analog();
+void test_export_to_json_no_channel_no_address();
+
+#endif // CLIENT_TESTCLIENTDATAPACKAGE_HPP
diff --git a/Tests/Mieming/client_esp32C3/client/test/TestESPNow.cpp b/Tests/Mieming/client_esp32C3/client/test/TestESPNow.cpp
new file mode 100644
index 0000000..3a4c149
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/TestESPNow.cpp
@@ -0,0 +1,12 @@
+#include "TestESPNow.hpp"
+
+void test_on_data_recv_valid_config()
+{
+	uint8_t mac_addr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	int len = 0;
+	config conf = {host : {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, time_millis : 0};
+
+	// preferences / hostinfo would need to be global for this to work
+
+	TEST_FAIL();
+}
diff --git a/Tests/Mieming/client_esp32C3/client/test/TestESPNow.hpp b/Tests/Mieming/client_esp32C3/client/test/TestESPNow.hpp
new file mode 100644
index 0000000..a2512b2
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/TestESPNow.hpp
@@ -0,0 +1,6 @@
+#pragma once
+#include <Arduino.h>
+#include <ESPNow.hpp>
+#include <unity.h>
+
+void test_on_data_recv_valid_config();
\ No newline at end of file
diff --git a/Tests/Mieming/client_esp32C3/client/test/main.cpp b/Tests/Mieming/client_esp32C3/client/test/main.cpp
new file mode 100644
index 0000000..5ad5f3f
--- /dev/null
+++ b/Tests/Mieming/client_esp32C3/client/test/main.cpp
@@ -0,0 +1,18 @@
+#include "TestESPNow.hpp"
+#include <Arduino.h>
+#include <unity.h>
+#include "TestClientDataPackage.hpp"
+
+void setup()
+{
+	delay(2000); // service delay
+
+	UNITY_BEGIN();
+	RUN_TEST(test_on_data_recv_valid_config);
+	RUN_TEST(test_export_to_json);
+	RUN_TEST(test_export_to_json_no_analog);
+	RUN_TEST(test_export_to_json_no_channel_no_address);
+	UNITY_END();
+}
+
+void loop() {}
\ No newline at end of file
-- 
GitLab