From 8e753e3788d22ba90627e55310981b3b7322b102 Mon Sep 17 00:00:00 2001
From: Bilal Hassan <bilal.hassan@student.uibk.ac.at>
Date: Fri, 25 Nov 2022 18:11:13 +0100
Subject: [PATCH] esp low power client

---
 .../client/.gitignore                         |   5 +
 .../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/include/Pinout.hpp                 |  10 +
 .../client/include/Protocol.hpp               |  15 +
 .../client/include/README                     |  39 +++
 .../client/include/SensorInformation.hpp      |  25 ++
 .../client/lib/LC7090203F/LC709203F.cpp       | 284 ++++++++++++++++++
 .../client/lib/LC7090203F/LC709203F.h         | 112 +++++++
 .../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         |  86 ++++++
 .../client/lib/dr26_analogue/dr26.hpp         |  29 ++
 .../client/lib/drs26_digital/drs26.cpp        |  61 ++++
 .../client/lib/drs26_digital/drs26.hpp        |  37 +++
 .../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/lib/scd30/scd30.cpp                |  44 +++
 .../client/lib/scd30/scd30.hpp                |  31 ++
 .../client/lib/time/src/Time.cpp              |  28 ++
 .../client/lib/time/src/Time.hpp              |  75 +++++
 .../client/platformio.ini                     |  35 +++
 .../client/src/main.cpp                       | 129 ++++++++
 .../client/test/README                        |  11 +
 .../client/test/TestClientDataPackage.cpp     |  46 +++
 .../client/test/TestClientDataPackage.hpp     |  16 +
 .../client/test/TestESPNow.cpp                |  12 +
 .../client/test/TestESPNow.hpp                |   6 +
 .../client/test/main.cpp                      |  18 ++
 42 files changed, 1814 insertions(+)
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/.gitignore
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/.gitkeep
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/.vscode/extensions.json
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/.vscode/settings.json
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/ForteSensor.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/MeasurementData.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/NoDataAvailableException.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/Pinout.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/Protocol.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/README
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/include/SensorInformation.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.h
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/README
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/README
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ClientDataPackage.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/Message.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/Message.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/ina219/ina219.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/ina219/ina219.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/scd30/scd30.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/scd30/scd30.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/time/src/Time.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/lib/time/src/Time.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/platformio.ini
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/src/main.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/README
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestClientDataPackage.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestClientDataPackage.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestESPNow.cpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestESPNow.hpp
 create mode 100644 Tests/Mieming/client_lowPower_esp32Wroom/client/test/main.cpp

diff --git a/Tests/Mieming/client_lowPower_esp32Wroom/client/.gitignore b/Tests/Mieming/client_lowPower_esp32Wroom/client/.gitignore
new file mode 100644
index 0000000..89cc49c
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/.gitkeep b/Tests/Mieming/client_lowPower_esp32Wroom/client/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/Tests/Mieming/client_lowPower_esp32Wroom/client/.vscode/extensions.json b/Tests/Mieming/client_lowPower_esp32Wroom/client/.vscode/extensions.json
new file mode 100644
index 0000000..080e70d
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/.vscode/settings.json b/Tests/Mieming/client_lowPower_esp32Wroom/client/.vscode/settings.json
new file mode 100644
index 0000000..85c4d1b
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/ForteSensor.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/ForteSensor.hpp
new file mode 100644
index 0000000..add5a01
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/MeasurementData.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/MeasurementData.hpp
new file mode 100644
index 0000000..36bd5db
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/NoDataAvailableException.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/NoDataAvailableException.hpp
new file mode 100644
index 0000000..83c5697
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/Pinout.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/Pinout.hpp
new file mode 100644
index 0000000..f277fd9
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/Protocol.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/Protocol.hpp
new file mode 100644
index 0000000..92270db
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/README b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/include/SensorInformation.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/include/SensorInformation.hpp
new file mode 100644
index 0000000..4b8af5d
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.cpp
new file mode 100644
index 0000000..f0cefcd
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.cpp
@@ -0,0 +1,284 @@
+/*!
+ *  @file LC709203F.cpp
+ *
+ *  @mainpage LC709203F Battery Monitor code
+ *
+ *  @section intro_sec Introduction
+ *
+ * 	I2C Driver for the LC709203F Battery Monitor IC
+ *
+ *  @section author Author
+ *
+ *  Daniel deBeer (EzSBC)
+ *
+ * 	@section license License
+ *
+ * 	BSD (see license.txt)
+ *
+ * 	@section  HISTORY
+ *
+ *     v1.0 - First release
+ */
+
+#include "Arduino.h"
+#include <Wire.h>
+#include "LC709203F.h"
+
+/*!
+ *    @brief  Instantiates a new LC709203F class
+ */
+LC709203F::LC709203F(void) {}
+
+LC709203F::~LC709203F(void) {}
+
+uint8_t i2c_address = LC709203F_I2C_ADDR ;
+
+/*!
+ *    @brief  Sets up the hardware and initializes I2C
+ *    @param  
+ *    @return True if initialization was successful, otherwise false.
+ */
+bool LC709203F::begin( void ) 
+{
+  Wire.begin();
+  setPowerMode(LC709203F_POWER_OPERATE) ;
+  setCellCapacity(LC709203F_APA_500MAH) ;
+  setTemperatureMode(LC709203F_TEMPERATURE_THERMISTOR) ;
+  
+  return true;
+}
+
+
+/*!
+ *    @brief  Get IC version
+ *    @return 16-bit value read from LC709203F_RO_ICVERSION registers
+ */
+uint16_t LC709203F::getICversion(void) 
+{
+  uint16_t vers = 0;
+  vers = read16(LC709203F_RO_ICVERSION);
+  return vers;
+}
+
+
+/*!
+ *    @brief  Initialize the RSOC algorithm
+ *    @return
+ */
+void LC709203F::initRSOC(void) 
+{
+  write16(LC709203F_WO_INITRSOC, 0xAA55);
+}
+
+
+/*!
+ *    @brief  Get battery voltage
+ *    @return Cell voltage in milliVolt
+ */
+uint16_t LC709203F::cellVoltage_mV(void) 
+{
+  uint16_t mV = 0;
+  mV = read16(LC709203F_RO_CELLVOLTAGE);
+  return 1000 * ( mV / 1000.0 ) ;
+}
+
+
+/*!
+ *    @brief  Get cell remaining charge in percent (0-100%)
+ *    @return point value from 0 to 1000
+ */
+uint16_t LC709203F::cellRemainingPercent10(void) 
+{
+  uint16_t percent = 0;
+  percent = read16(LC709203F_RO_ITE );
+  return percent ;
+}
+
+/*!
+ *    @brief  Get battery state of charge in percent (0-100%)
+ *    @return point value from 0 to 100
+ */
+uint16_t LC709203F::cellStateOfCharge(void)
+{
+  uint16_t percent = 0;
+  percent = read16(LC709203F_RW_RSOC );
+  return percent ;
+}
+
+
+/*!
+ *    @brief  Get battery thermistor temperature
+ *    @return value from -20 to 60 *C  // CdB Needs testing, no thermistor on ESP32_Bat_R2 board
+ */
+uint16_t LC709203F::getCellTemperature(void) 
+{
+  uint16_t temp = 0;
+  temp = read16(LC709203F_RW_CELLTEMPERATURE );
+  return temp ;
+}
+
+
+/*!
+ *    @brief  Set the temperature mode (external or internal)
+ *    @param t The desired mode: LC709203F_TEMPERATURE_I2C or
+ * LC709203F_TEMPERATURE_THERMISTOR
+ */
+void LC709203F::setTemperatureMode(lc709203_tempmode_t t) 
+{
+  return write16(LC709203F_RW_STATUSBIT, (uint16_t)t);
+}
+
+
+/*!
+ *    @brief  Set the cell capacity, 
+ *    @param apa The lc709203_adjustment_t enumerated approximate cell capacity
+ */
+void LC709203F::setCellCapacity(lc709203_adjustment_t apa) 
+{
+  write16(LC709203F_RW_APA, (uint16_t)apa);
+}
+
+
+/*!
+ *    @brief  Set the alarm pin to respond to an RSOC percentage level
+ *    @param percent The threshold value, set to 0 to disable alarm
+ */
+void LC709203F::setAlarmRSOC(uint8_t percent) 
+{
+  write16(LC709203F_RW_ALARMRSOC, percent);
+}
+
+
+/*!
+ *    @brief  Set the alarm pin to respond to a battery voltage level
+ *    @param voltage The threshold value, set to 0 to disable alarm
+ */
+void LC709203F::setAlarmVoltage(float voltage) 
+{
+  write16(LC709203F_RW_ALARMVOLT, voltage * 1000);
+}
+
+
+/*!
+ *    @brief  Set the power mode, LC709203F_POWER_OPERATE or
+ *            LC709203F_POWER_SLEEP
+ *    @param t The power mode desired
+ *    @return 
+ */
+void LC709203F::setPowerMode(lc709203_powermode_t t) 
+{
+  write16(LC709203F_RW_POWERMODE, (uint16_t)t);
+}
+
+/*!
+ *    @brief  Set cell type 
+ *    @param t The profile, Table 8.  Normally 1 for 3.7 nominal 4.2V Full carge cells
+ *    @return
+ */
+void LC709203F::setCellProfile(lc709203_cell_profile_t t) 
+{
+  write16(LC709203F_RW_PROFILE, (uint16_t)t);
+}
+
+/*!
+ *    @brief  Get the thermistor Beta value //For completeness since we have to write it.
+ *    @return The uint16_t Beta value
+ */
+uint16_t LC709203F::getThermistorBeta(void) 
+{
+  uint16_t val = 0;
+  val = read16(LC709203F_RW_THERMISTORB);
+  return val;
+}
+
+
+/*!
+ *    @brief  Set the thermistor Beta value
+ *    @param b The value to set it to
+ *    @return 
+ */
+void LC709203F::setThermistorB(uint16_t beta) 
+{
+  write16(LC709203F_RW_THERMISTORB, beta);
+}
+
+
+std::list<Message> LC709203F::buildMessages()
+{
+	std::list<Message> messages;
+	float data =cellVoltage_mV()/1000.0;
+	MeasurementData IncrementData{data, 0, {},"Voltage-Batterie"};
+	messages.emplace_back(IncrementData, sensorInformation, Time::getInstance().getEpochSeconds());
+	return messages;
+}
+
+
+//
+// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+/*
+    INTERNAL I2C FUNCTIONS and CRC CALCULATION
+*/
+
+
+/**
+ * Performs a CRC8 calculation on the supplied values.
+ *
+ * @param data  Pointer to the data to use when calculating the CRC8.
+ * @param len   The number of bytes in 'data'.
+ *
+ * @return The computed CRC8 value.
+ */
+static uint8_t crc8(uint8_t *data, int len) 
+{
+  const uint8_t POLYNOMIAL(0x07);
+  uint8_t crc(0x00);
+
+  for (int j = len; j; --j) {
+    crc ^= *data++;
+
+    for (int i = 8; i; --i) {
+      crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
+    }
+  }
+  return crc;
+}
+
+
+// writes a 16-bit word (d) to register pointer regAddress
+// when selecting a register pointer to read from, data = 0
+void LC709203F::write16(uint8_t regAddress, uint16_t data)
+{
+  // Setup array to hold bytes to send including CRC-8
+  uint8_t crcArray[5];
+  crcArray[0] = 0x16;
+  crcArray[1] = regAddress;
+  crcArray[2] = lowByte(data);
+  crcArray[3] = highByte(data);
+  // Calculate crc of preceding four bytes and place in crcArray[4]
+  crcArray[4] = crc8( crcArray, 4 );
+  // Device address
+  Wire.beginTransmission(i2c_address);
+  // Register address
+  Wire.write(regAddress);
+  // low byte
+  Wire.write(crcArray[2]);
+  // high byte
+  Wire.write(crcArray[3]);
+  // Send crc8 
+  Wire.write(crcArray[4]);
+  Wire.endTransmission();
+}
+
+int16_t LC709203F::read16( uint8_t regAddress)
+{
+  int16_t data = 0;
+  Wire.beginTransmission(i2c_address);
+  Wire.write(regAddress);
+  Wire.endTransmission(false);
+  Wire.requestFrom(i2c_address, 2);
+  uint8_t lowByteData = Wire.read();
+  uint8_t highByteData = Wire.read();
+  data = word(highByteData, lowByteData);
+  return( data );
+}
diff --git a/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.h b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.h
new file mode 100644
index 0000000..bf4a1b4
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/LC7090203F/LC709203F.h
@@ -0,0 +1,112 @@
+/*!
+ *  @file LC709203F.h
+ *
+ * 	I2C Driver for the  LC709203F LiPo Cell Monitor
+ *
+ *	BSD license (see license.txt)
+ */
+
+#ifndef _LC709203F_H
+#define _LC709203F_H
+
+#include "Arduino.h"
+//#include <I2CDevice.h>
+#include <Wire.h>
+#include "Message.hpp"
+
+#define LC709203F_I2C_ADDR              0x0B    // LC709203F default i2c address
+
+// Registers per datasheet Table 6
+
+#define LC709203F_WO_BEFORE_RSOC        0x04    // Executes RSOC initialization with sampled maximum voltage when 0xAA55 is set
+#define LC709203F_RW_THERMISTORB 	      0x06    // Sets B−constant of the thermistor to be measured.
+#define LC709203F_WO_INITRSOC 			    0x07    // Executes RSOC initialization when 0xAA55 is set.
+#define LC709203F_RW_CELLTEMPERATURE 	  0x08 	  // Read or Write Cell Temperature  For ESP32-Bar-Rev2 must write temperature, no thermistor on board
+#define LC709203F_RO_CELLVOLTAGE 		    0x09    // Read cell voltage
+#define LC709203F_RW_CURRENTDIRECTION   0x0A    // Selects Auto/Charge/Discharge mode 0x0000: Auto mode, 0x0001: Charge mode, 0xFFFF: Discharge mode
+#define LC709203F_RW_APA 				        0x0B    // APA Register, Table 7
+#define LC709203F_RW_APTHERMISTOR       0x0C    // Sets a value to adjust temperature measurement delay timing. Defaults to0x001E
+#define LC709203F_RW_RSOC               0x0D    // Read cell indicator to empty in 1% steps
+#define LC709203F_RO_ITE     			      0x0F    // Read cell indicator to empty in 0.1% steps
+#define LC709203F_RO_ICVERSION 		      0x11    // Contains the ID number of the IC
+#define LC709203F_RW_PROFILE	 		      0x12    // Adjusts the battery profile for nominal and fully charged voltages, see Table 8
+#define LC709203F_RW_ALARMRSOC 		      0x13    // Alarm on percent threshold
+#define LC709203F_RW_ALARMVOLT 		      0x14    // Alarm on voltage threshold
+#define LC709203F_RW_POWERMODE 		      0x15    // Sets sleep/power mode 0x0001: Operational mode 0x0002: Sleep mode
+#define LC709203F_RW_STATUSBIT 		      0x16    // Temperature method, 0x0000: I2C mode, 0x0001: Thermistor mode 
+#define LC709203F_RO_CELLPROFILE        0x1A    // Displays battery profile code
+
+static uint8_t crc8(uint8_t *data, int len);
+
+/*!  Approx cell capacity Table 7 */
+typedef enum {
+  LC709203F_APA_100MAH              = 0x08,
+  LC709203F_APA_200MAH              = 0x0B,
+  LC709203F_APA_500MAH              = 0x10,
+  LC709203F_APA_1000MAH             = 0x19,
+  LC709203F_APA_2000MAH             = 0x2D,
+  LC709203F_APA_3000MAH             = 0x36,
+} lc709203_adjustment_t;
+
+/*!  Cell profile */
+typedef enum {
+  LC709203_NOM3p7_Charge4p2         = 1,
+  LC709203_NOM3p8_Charge4p35        = 3,
+  LC709203_NOM3p8_Charge4p35_Less500mAh = 6,
+  LC709203_ICR18650_SAMSUNG         = 5,
+  LC709203_ICR18650_PANASONIC       = 4
+}lc709203_cell_profile_t ;
+
+/*!  Cell temperature source */
+typedef enum {
+  LC709203F_TEMPERATURE_I2C         = 0x0000,
+  LC709203F_TEMPERATURE_THERMISTOR  = 0x0001,
+} lc709203_tempmode_t;
+
+/*!  Chip power state */
+typedef enum {
+  LC709203F_POWER_OPERATE           = 0x0001,
+  LC709203F_POWER_SLEEP             = 0x0002,
+} lc709203_powermode_t;
+
+/*!
+ *    @brief  Class that stores state and functions for interacting with
+ *            the LC709203F I2C LiPo monitor
+ */
+class LC709203F {
+public:
+  LC709203F();
+  ~LC709203F();
+
+  bool begin( void );
+  void initRSOC(void);
+
+  void setPowerMode(lc709203_powermode_t t);
+  void setCellCapacity(lc709203_adjustment_t apa);
+  void setCellProfile(lc709203_cell_profile_t t);
+  
+  uint16_t getICversion(void);
+
+  uint16_t cellVoltage_mV(void);
+  uint16_t cellRemainingPercent10(void);	// Remaining capacity in increments of 0.1% as integer
+	uint16_t cellStateOfCharge(void);				// In increments of 1% as integer
+	
+
+  uint16_t getThermistorBeta(void);
+  void setThermistorB(uint16_t beta);
+
+  void setTemperatureMode(lc709203_tempmode_t t);
+  uint16_t getCellTemperature(void);
+
+  void setAlarmRSOC(uint8_t percent);
+  void setAlarmVoltage(float voltage);
+  std::list<Message> buildMessages();
+
+protected:
+  void write16( uint8_t regAddress, uint16_t data);
+  int16_t read16(uint8_t regAddress);
+private:
+  const SensorInformation sensorInformation{"DR26", Protocol::Analog};
+};
+
+#endif
diff --git a/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/README b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.cpp
new file mode 100644
index 0000000..641f974
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/caching/src/ram_caching.hpp
new file mode 100644
index 0000000..c1a4ac5
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.cpp
new file mode 100644
index 0000000..c434f53
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/deep_sleep/f_deep_sleep.hpp
new file mode 100644
index 0000000..7a528c8
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.cpp
new file mode 100644
index 0000000..f39dc49
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.cpp
@@ -0,0 +1,86 @@
+#include "dr26.hpp"
+
+void ForteDR26 ::setup()
+{
+    pinMode(2,OUTPUT);
+	Wire.begin();
+  //  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_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/dr26_analogue/dr26.hpp
new file mode 100644
index 0000000..b60c099
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.cpp
new file mode 100644
index 0000000..5c21f3a
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/drs26_digital/drs26.hpp
new file mode 100644
index 0000000..0d713ca
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/README b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/README
new file mode 100644
index 0000000..bbf1db0
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/src/ClientDataPackage.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ClientDataPackage.hpp
new file mode 100644
index 0000000..f08e6bb
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.cpp
new file mode 100644
index 0000000..28eedfb
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/ESPNow.hpp
new file mode 100644
index 0000000..266b139
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/src/Message.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/Message.cpp
new file mode 100644
index 0000000..7f7f8e2
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/espnow/src/Message.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/espnow/src/Message.hpp
new file mode 100644
index 0000000..5a6ca81
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/ina219/ina219.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/ina219/ina219.cpp
new file mode 100644
index 0000000..def6a9d
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/ina219/ina219.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/ina219/ina219.hpp
new file mode 100644
index 0000000..4a34d95
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/scd30/scd30.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/scd30/scd30.cpp
new file mode 100644
index 0000000..7cff381
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/scd30/scd30.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/scd30/scd30.hpp
new file mode 100644
index 0000000..db3e855
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/time/src/Time.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/time/src/Time.cpp
new file mode 100644
index 0000000..5cc3dbc
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/lib/time/src/Time.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/lib/time/src/Time.hpp
new file mode 100644
index 0000000..783bdef
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/platformio.ini b/Tests/Mieming/client_lowPower_esp32Wroom/client/platformio.ini
new file mode 100644
index 0000000..403649d
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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:esp32dev]
+platform = espressif32
+board = esp32dev
+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_lowPower_esp32Wroom/client/src/main.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/src/main.cpp
new file mode 100644
index 0000000..2f0b55b
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/client/src/main.cpp
@@ -0,0 +1,129 @@
+#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 "LC709203F.h"
+
+LC709203F gg;
+// #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_32, GPIO_MODE_OUTPUT);
+	
+	gg.begin();
+	gg.setCellCapacity(LC709203F_APA_1000MAH);
+
+
+	DeepSleep::print_wakeup_reason();
+	DeepSleep::bootCount++;
+	ESP_LOGD(TAG.c_str(), "Boot number: %d", DeepSleep::bootCount);
+
+gpio_set_level(GPIO_NUM_32, 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_32, 0);
+
+	espnow_setup();
+	//	log_e("Setup complete.");
+}
+
+void loop()
+{
+gpio_set_level(GPIO_NUM_32, 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);
+
+Serial.println("***********************REAL-Voltage-Battery**********************************");
+Serial.println(gg.cellVoltage_mV()/1000.0);
+
+	try {
+
+		auto messages = dr26_channel0_power.buildMessages();
+		
+		
+		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());
+			}
+		}
+
+		auto messages4=gg.buildMessages();
+		for (const Message &message4 : messages4) {
+			if(message4.send() != ESP_OK){
+				RtcMemory::store(message4.getMessageAsMinifiedJsonString());
+			}
+			delay(5000);
+			if(!was_msg_received()){
+				RtcMemory::store(message4.getMessageAsMinifiedJsonString());
+			}
+		}
+
+
+	} catch (const NoDataAvailableException &e) {
+		std::cerr << e.what() << '\n';
+	}
+
+
+
+	Serial.print("This device: ");
+	Serial.println("\n");
+gpio_set_level(GPIO_NUM_32, 0);
+	delay(5000);
+	DeepSleep::deep_sleep(100);
+}
diff --git a/Tests/Mieming/client_lowPower_esp32Wroom/client/test/README b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/README
new file mode 100644
index 0000000..9b1e87b
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/test/TestClientDataPackage.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestClientDataPackage.cpp
new file mode 100644
index 0000000..eea536c
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/test/TestClientDataPackage.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestClientDataPackage.hpp
new file mode 100644
index 0000000..fa5f203
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/test/TestESPNow.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestESPNow.cpp
new file mode 100644
index 0000000..3a4c149
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/test/TestESPNow.hpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/TestESPNow.hpp
new file mode 100644
index 0000000..a2512b2
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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_lowPower_esp32Wroom/client/test/main.cpp b/Tests/Mieming/client_lowPower_esp32Wroom/client/test/main.cpp
new file mode 100644
index 0000000..5ad5f3f
--- /dev/null
+++ b/Tests/Mieming/client_lowPower_esp32Wroom/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