diff --git a/client/client/include/ForteSensor.hpp b/client/client/include/ForteSensor.hpp
index d322213ea9c89554540b75ea158ddb99e4886e2f..add5a01d566ef5977eef3e0286d908c4b49fcb0b 100644
--- a/client/client/include/ForteSensor.hpp
+++ b/client/client/include/ForteSensor.hpp
@@ -2,14 +2,16 @@
 #define _FORTE_SENSOR
 
 #include "Message.hpp"
+#include "Protocol.hpp"
+#include "SensorInformation.hpp"
 template <class T>
-class Forte_Sensor {
+class ForteSensor {
   public:
-	virtual T read_data() = 0;
+	virtual T readData() = 0;
 	virtual void setup() = 0;
-	virtual Message build_message() = 0;
-
-  private:
+	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/client/client/include/MeasurementData.hpp b/client/client/include/MeasurementData.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..36bd5db75fbdb714dad723d67b92affd4d4fd189
--- /dev/null
+++ b/client/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/client/client/include/NoDataAvailableException.hpp b/client/client/include/NoDataAvailableException.hpp
index a5de09a1410326f7f6352f4e27a455b3f2b0061f..83c56973868a76a1dca7f49487bcdb6fd33e86d8 100644
--- a/client/client/include/NoDataAvailableException.hpp
+++ b/client/client/include/NoDataAvailableException.hpp
@@ -4,5 +4,5 @@
 #include <iostream>
 
 struct NoDataAvailableException : public std::exception {
-	const char *what() const throw() { return "Sensor could not read data"; }
+	const char *what() const noexcept override { return "Sensor could not read data"; }
 };
\ No newline at end of file
diff --git a/client/client/include/pinout.hpp b/client/client/include/Pinout.hpp
similarity index 77%
rename from client/client/include/pinout.hpp
rename to client/client/include/Pinout.hpp
index b80b32dce021c98f1ea68e88871da9288e4be270..f277fd91b274caa1de127f0380ba75164dd9b707 100644
--- a/client/client/include/pinout.hpp
+++ b/client/client/include/Pinout.hpp
@@ -2,8 +2,8 @@
 #define _FORTE_PINOUT
 
 // Pins for I2C
-#define I2C_SDA 18
-#define I2C_SCL 19
+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)
 
diff --git a/client/client/include/Protocol.hpp b/client/client/include/Protocol.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..92270db81e4a54e525f2cd054a15a03e7ebade15
--- /dev/null
+++ b/client/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/client/client/include/SensorInformation.hpp b/client/client/include/SensorInformation.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b8af5d357534be81670b503790960a2781bc282
--- /dev/null
+++ b/client/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/client/client/lib/caching/src/ram_caching.cpp b/client/client/lib/caching/src/ram_caching.cpp
index f5ebd717149218834742eb644e479c4554b30b3d..b7df125c9f9885d5040b4a2c6cf38d14bdb69594 100644
--- a/client/client/lib/caching/src/ram_caching.cpp
+++ b/client/client/lib/caching/src/ram_caching.cpp
@@ -1,27 +1,28 @@
 #include "ram_caching.hpp"
 
 static const char* TAG = "CACHING";
+const int NUM_SENSORS = 10;
 
-RTC_DATA_ATTR int cachedAmount = -1;
-RTC_DATA_ATTR ClientDataPackage backup[NUM_SENSORS];
-
-ClientDataPackage ram_cache_pop()
-{
-	return backup[cachedAmount--];
-}
-
-void ram_cache_push(ClientDataPackage data)
-{
-	backup[++cachedAmount] = data;
-	ESP_LOGI(TAG, "ClientDataPackage saved");
-}
-
-bool ram_cache_is_empty()
-{
-	return cachedAmount == -1;
-}
-
-bool ram_cache_is_full()
-{
-	return cachedAmount == 9;
-}
\ No newline at end of file
+//RTC_DATA_ATTR int cachedAmount = -1;
+//RTC_DATA_ATTR ClientDataPackage backup[NUM_SENSORS];
+//
+//ClientDataPackage ram_cache_pop()
+//{
+//	return backup[cachedAmount--];
+//}
+//
+//void ram_cache_push(ClientDataPackage data)
+//{
+//	backup[++cachedAmount] = data;
+//	ESP_LOGI(TAG, "ClientDataPackage saved");
+//}
+//
+//bool ram_cache_is_empty()
+//{
+//	return cachedAmount == -1;
+//}
+//
+//bool ram_cache_is_full()
+//{
+//	return cachedAmount == 9;
+//}
\ No newline at end of file
diff --git a/client/client/lib/caching/src/ram_caching.hpp b/client/client/lib/caching/src/ram_caching.hpp
index 3ade9626a58bf94c7eb4b044eff615ce82677474..f4152ce799a7f746158ba80cc769ff879557f9ea 100644
--- a/client/client/lib/caching/src/ram_caching.hpp
+++ b/client/client/lib/caching/src/ram_caching.hpp
@@ -1,12 +1,12 @@
 #ifndef _RAM_CACHE
 #define _RAM_CACHE
-#include "ClientDataPackage.hpp"
+//#include "ClientDataPackage.hpp"
 #include "esp_log.h"
 #include <ESP32Time.h>
 
 bool ram_cache_is_empty();
 bool ram_cache_is_full();
-void ram_cache_push(ClientDataPackage data);
-ClientDataPackage ram_cache_pop();
+//void ram_cache_push(ClientDataPackage data);
+//ClientDataPackage ram_cache_pop();
 
 #endif
\ No newline at end of file
diff --git a/client/client/lib/dr26_analogue/src/dr26.cpp b/client/client/lib/dr26_analogue/dr26.cpp
similarity index 73%
rename from client/client/lib/dr26_analogue/src/dr26.cpp
rename to client/client/lib/dr26_analogue/dr26.cpp
index c2cec295747bbce97a4be6e09785d18e36bd1525..e8d4555fff9470023788f92abfcd8af61d8aa905 100644
--- a/client/client/lib/dr26_analogue/src/dr26.cpp
+++ b/client/client/lib/dr26_analogue/dr26.cpp
@@ -1,23 +1,18 @@
 #include "dr26.hpp"
 
-static const char* TAG = "DR26";
-
-Adafruit_ADS1115 ads;
-
-void Forte_DR26 ::setup()
+void ForteDR26 ::setup()
 {
 	Wire.begin(I2C_SDA, I2C_SCL);
 	// ads.setGain(0);
-	if(ads.begin()){
-		ESP_LOGI(TAG, "ADS initialized.");
-	}
-	else{
-		ESP_LOGW(TAG, "ADS initialization failed.");
+	if (ads.begin()) {
+		ESP_LOGI(sensorInformation.getSensorName().c_str(), "ADS initialized.");
+	} else {
+		ESP_LOGW(sensorInformation.getSensorName().c_str(), "ADS initialization failed.");
 	}
 	delay(100);
 }
 
-float Forte_DR26 ::read_data()
+float ForteDR26 ::readData()
 {
 	float volts = 0;
 	for (int i = 0; i < 10; i++) {
@@ -44,12 +39,16 @@ float Forte_DR26 ::read_data()
 // 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 Forte_DR26 ::change_Gain(adsGain_t gain)
+void ForteDR26 ::changeGain(adsGain_t gain)
 {
 	ads.setGain(gain);
 }
 
-Message Forte_DR26::build_message()
+std::list<Message> ForteDR26::buildMessages()
 {
 	throw "Not implemented";
-}
\ No newline at end of file
+}
+SensorInformation ForteDR26::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/client/client/lib/dr26_analogue/dr26.hpp b/client/client/lib/dr26_analogue/dr26.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..778f8fe112e1b4e2e85588e517811fc661a858ad
--- /dev/null
+++ b/client/client/lib/dr26_analogue/dr26.hpp
@@ -0,0 +1,24 @@
+#ifndef _DR26
+#define _DR26
+
+#include "Adafruit_ADS1X15.h"
+#include "ForteSensor.hpp"
+#include "Message.hpp"
+#include "Pinout.hpp"
+#include "esp_log.h"
+#include <Wire.h>
+
+class ForteDR26 : public ForteSensor<float> {
+  public:
+	void setup() override;
+	float readData() override;
+	void changeGain(adsGain_t gain);
+	std::list<Message> buildMessages() override;
+	[[nodiscard]] SensorInformation getSensorInformation() const override;
+
+  private:
+	Adafruit_ADS1115 ads;
+	const SensorInformation sensorInformation{"DR26", Protocol::Analog};
+};
+
+#endif
\ No newline at end of file
diff --git a/client/client/lib/dr26_analogue/src/dr26.hpp b/client/client/lib/dr26_analogue/src/dr26.hpp
deleted file mode 100644
index b06c420e530ab082e47074094629e8c87cf84cd6..0000000000000000000000000000000000000000
--- a/client/client/lib/dr26_analogue/src/dr26.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _DR26
-#define _DR26
-
-#include "ForteSensor.hpp"
-#include "Message.hpp"
-#include "esp_log.h"
-#include "pinout.hpp"
-#include <Adafruit_ADS1X15.h>
-#include <Wire.h>
-
-class Forte_DR26 : public Forte_Sensor<float> {
-  public:
-	void setup() override;
-	float read_data() override;
-	void change_Gain(adsGain_t gain);
-	Message build_message() override;
-
-  private:
-};
-
-#endif
\ No newline at end of file
diff --git a/client/client/lib/drs26_digital/drs26.cpp b/client/client/lib/drs26_digital/drs26.cpp
index f6f97caa2c147ec1c3493b610107e76a019395ee..5c21f3a98e01d665c38a879fb23f37217b39e8f4 100644
--- a/client/client/lib/drs26_digital/drs26.cpp
+++ b/client/client/lib/drs26_digital/drs26.cpp
@@ -1,18 +1,17 @@
 #include <drs26.hpp>
 
-static const char* TAG = "DRS26";
 /*
 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 Forte_DRS26 ::setup()
+void ForteDRS26 ::setup()
 {
 	drs26.begin(4);
 }
 
-out_data_drs26 Forte_DRS26 ::read_data()
+out_data_drs26 ForteDRS26 ::readData()
 {
 	String sdiResponse = "";
 	String measurement_command =
@@ -36,16 +35,27 @@ out_data_drs26 Forte_DRS26 ::read_data()
 
 	if (sdiResponse.length() > 1) {
 		data.id = sdiResponse.substring(0, 8).toInt();
-		data.circumference = sdiResponse.substring(9, 15).toFloat();
-		data.temperatur = sdiResponse.substring(16, 22).toFloat();
+		data.circumferenceIncrement = sdiResponse.substring(9, 15).toFloat();
+		data.temperature = sdiResponse.substring(16, 22).toFloat();
 	}
 	return data;
 }
 
-Message Forte_DRS26 ::build_message()
+std::list<Message> ForteDRS26 ::buildMessages()
 {
-	 auto message = Message();
-	 message.add_data(12.12, 1);
-	 ESP_LOGE(TAG, "test");
-	 return message;
-}
\ No newline at end of file
+	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/client/client/lib/drs26_digital/drs26.hpp b/client/client/lib/drs26_digital/drs26.hpp
index 6a64da5870bd1b060ce13933826a5af6eb19a247..0d713ca66260895f63cdc1e2137ec4027294e8bd 100644
--- a/client/client/lib/drs26_digital/drs26.hpp
+++ b/client/client/lib/drs26_digital/drs26.hpp
@@ -3,26 +3,35 @@
 
 #include "ForteSensor.hpp"
 #include "Message.hpp"
+#include "Pinout.hpp"
 #include "Wire.h"
 #include "esp_log.h"
-#include "pinout.hpp"
 #include <SDI12.h>
+#include <map>
 
 struct out_data_drs26 {
 	int id;
-	float circumference;
-	float temperatur;
+	float circumferenceIncrement;
+	float temperature;
 };
 
-class Forte_DRS26 : public Forte_Sensor<out_data_drs26> {
+class ForteDRS26 : public ForteSensor<out_data_drs26> {
   public:
 	void setup() override;
-	out_data_drs26 read_data() override;
-	Message build_message() 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/client/client/lib/espnow/README b/client/client/lib/espnow/README
index 55f89c0b2141283b3dd2d94c882cdaccbe2064fe..bbf1db0c44bf4b375af8aefcd9f6649864d64677 100644
--- a/client/client/lib/espnow/README
+++ b/client/client/lib/espnow/README
@@ -1,7 +1,7 @@
 # basic usage
 
 To send data using espnow, create a new Message object,
-then use the add_data(value, identifier) method for every value
+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
diff --git a/client/client/lib/espnow/src/ClientDataPackage.hpp b/client/client/lib/espnow/src/ClientDataPackage.hpp
index 52f2be6032a190e6346bef71457cb78c983b0038..7cdd66fdc3b9175a4870933654a82c31bcf392d1 100644
--- a/client/client/lib/espnow/src/ClientDataPackage.hpp
+++ b/client/client/lib/espnow/src/ClientDataPackage.hpp
@@ -1,14 +1,54 @@
 #pragma once
 
-#define NUM_SENSORS 10
-// packing the struct without padding, makes reading it on the fipy easier
-#pragma pack(1)
+#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
-struct ClientDataPackage {
-	int identifiers[NUM_SENSORS];
-	float values[NUM_SENSORS];
-	int amountData;
-	long timestamp; // maybe make this array
+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/client/client/lib/espnow/src/ESPNow.cpp b/client/client/lib/espnow/src/ESPNow.cpp
index 8d7eb36da571a604af922485e31cad1b837147ea..890392ad22e6b2c7a596c12c5d7030085a76bcab 100644
--- a/client/client/lib/espnow/src/ESPNow.cpp
+++ b/client/client/lib/espnow/src/ESPNow.cpp
@@ -1,6 +1,6 @@
 #include "ESPNow.hpp"
 
-static const char* TAG = "ESPNOW";
+static const char *TAG = "ESPNOW";
 
 uint8_t BROADCAST_MAC[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 esp_now_peer_info_t hostInfo;
@@ -53,7 +53,10 @@ esp_err_t espnow_setup()
 	get_host_mac(hostInfo.peer_addr); // check if there is a host saved in flash mem, broadcast otherwise
 
 	hostInfo.channel = 0;
-	hostInfo.encrypt = 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);
 
 	esp_now_register_recv_cb(on_data_recv);
diff --git a/client/client/lib/espnow/src/Message.cpp b/client/client/lib/espnow/src/Message.cpp
index 447242cffb717bb8eabb5a10021e4a9f56d4d47c..7de1fc9d38ed4ea322994c52bb6a608ff74d332a 100644
--- a/client/client/lib/espnow/src/Message.cpp
+++ b/client/client/lib/espnow/src/Message.cpp
@@ -1,52 +1,45 @@
 #include "Message.hpp"
 
-static const char *TAG = "MESSAGE";
+#include <utility>
 
-void Message::add_data(float value, int identifier)
-{
-	if (data.amountData < NUM_SENSORS) {
-		data.values[data.amountData] = value;
-		data.identifiers[data.amountData] = identifier;
-		data.amountData++;
-	}
-}
+static const char *TAG = "MESSAGE";
 
-esp_err_t Message::send()
+esp_err_t Message::send() const
 {
 	ESP_LOGI(TAG, "Sending message");
 	esp_err_t success;
-	success = esp_now_send(recipient, (uint8_t *)&data, sizeof(data));
-	// if(success != ESP_OK){
-	//     if(!ram_cache_is_full()){
-	//         ram_cache_push(*data);
-	//     }
-	// }
-	for (int i = 0; i < data.amountData; i++) {
-		ESP_LOGD(TAG, "Sent data: %i", data.values[i]);
+	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");
+		// TODO REWRITE FOR JSON
+		//		if (!ram_cache_is_full()) {
+		//			//			ram_cache_push(messageData);
+		//		}
 	}
+	ESP_LOGD(TAG, "Sent data: %s", messageData.c_str());
 
-	ESP_LOGD(TAG, "time sent: %l", data.timestamp);
+	ESP_LOGD(TAG, "time sent: %l", clientDataPackage.getTimestamp());
 	ESP_LOGD(TAG, "send status: %d", success);
 
 	return success;
 }
 
-Message ::Message()
+std::string Message::getMessageAsMinifiedJsonString() const
 {
-	// check for existing host mac address, use broadcast otherwise
-	get_host_mac(recipient);
-
-	data.amountData = 0;
-	data.timestamp = esptime::rtc.getMillis(); // I am assuming we are not sending data from Unix Epoch
+	return clientDataPackage.getDataPackageAsMinifiedJsonString();
 }
 
-Message ::Message(ClientDataPackage old_data)
+Message::Message(ClientDataPackage data) : clientDataPackage(std::move(data))
 {
-	data = old_data;
-	// memcpy(&data, &old_data, sizeof(data));
+	// check for existing host mac address, use broadcast otherwise
 	get_host_mac(recipient);
 }
-ClientDataPackage Message::getData()
+Message::Message(MeasurementData const &data, const SensorInformation &information, unsigned long timestamp)
+    : clientDataPackage(data, information, timestamp)
 {
-	return data;
+	// check for existing host mac address, use broadcast otherwise
+	get_host_mac(recipient);
 }
diff --git a/client/client/lib/espnow/src/Message.hpp b/client/client/lib/espnow/src/Message.hpp
index 101f7549bc4e87019ddf000045665804c1057644..3711df244474bb1f7e38bb50bdbac029e73681e0 100644
--- a/client/client/lib/espnow/src/Message.hpp
+++ b/client/client/lib/espnow/src/Message.hpp
@@ -5,6 +5,7 @@
 #include "Time.hpp"
 #include "esp_log.h"
 #include <Arduino.h>
+#include <ArduinoJson.h>
 #include <ESP32Time.h>
 #include <esp_now.h>
 
@@ -12,13 +13,14 @@
 // if more things are sent from the host the name might not be accurate anymore
 class Message {
   public:
-	Message();
-	explicit Message(ClientDataPackage old_data);
-	void add_data(float value, int identifier);
-	esp_err_t send();
-	ClientDataPackage getData();
+
+	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 data;
-	uint8_t recipient[6];
+	ClientDataPackage clientDataPackage;
+	uint8_t recipient[6]{};
 };
\ No newline at end of file
diff --git a/client/client/lib/ina219/ina219.cpp b/client/client/lib/ina219/ina219.cpp
index 7c9360c5400bce65e67c0cefe18acb2a65d7c80c..def6a9d73acefe00e1a160a1c3fc2ba64ab2099d 100644
--- a/client/client/lib/ina219/ina219.cpp
+++ b/client/client/lib/ina219/ina219.cpp
@@ -1,18 +1,16 @@
 #include "ina219.hpp"
 
-static const char* TAG = "INA219";
-
-void Forte_INA219 ::setup()
+void ForteINA219 ::setup()
 {
 	Wire.begin(I2C_SDA, I2C_SCL);
 	if (!ina219.init()) {
 		// Sensor init went wrong
-		ESP_LOGW(TAG, "Initialization failed");
+		ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed");
 		return;
 	}
 }
 
-out_data_ina219 Forte_INA219 ::read_data()
+out_data_ina219 ForteINA219 ::readData()
 {
 	if (!ina219.getOverflow()) {
 		data.shuntVoltage_mV = ina219.getShuntVoltage_mV();
@@ -27,7 +25,11 @@ out_data_ina219 Forte_INA219 ::read_data()
 		return data;
 }
 
-Message Forte_INA219::build_message()
+std::list<Message> ForteINA219::buildMessages()
 {
 	throw "Not yet implemented";
-}
\ No newline at end of file
+}
+SensorInformation ForteINA219::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/client/client/lib/ina219/ina219.hpp b/client/client/lib/ina219/ina219.hpp
index 64e8728e31e43e25dd6a4d8da5a9376b5fb379a8..4a34d9591a325f9232f90ef61b4a74077fe1cf51 100644
--- a/client/client/lib/ina219/ina219.hpp
+++ b/client/client/lib/ina219/ina219.hpp
@@ -3,9 +3,9 @@
 
 #include "ForteSensor.hpp"
 #include "Message.hpp"
+#include "Pinout.hpp"
 #include "Wire.h"
 #include "esp_log.h"
-#include "pinout.hpp"
 #include <INA219_WE.h>
 
 struct out_data_ina219 {
@@ -17,15 +17,17 @@ struct out_data_ina219 {
 	bool ina219_overflow = false;
 };
 
-class Forte_INA219 : public Forte_Sensor<out_data_ina219> {
+class ForteINA219 : public ForteSensor<out_data_ina219> {
   public:
 	void setup() override;
-	out_data_ina219 read_data() override;
-	Message build_message() 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/client/client/lib/scd30/scd30.cpp b/client/client/lib/scd30/scd30.cpp
index 0ad4f2c440daf10c8368bb62db037dc41aba6085..507d815ea7c401a4872aec3f7a4e2567409d3ddb 100644
--- a/client/client/lib/scd30/scd30.cpp
+++ b/client/client/lib/scd30/scd30.cpp
@@ -1,18 +1,16 @@
 #include "scd30.hpp"
 
-static const char* TAG = "SCD30";
-
-void Forte_SCD30 ::setup()
+void ForteSCD30 ::setup()
 {
 	Wire.begin(I2C_SDA, I2C_SCL);
 	if (!airSensor.begin()) {
 		// Sensor init went wrong
-		ESP_LOGW(TAG, "Initialization failed.");
+		ESP_LOGW(sensorInformation.getSensorName().c_str(), "Initialization failed.");
 		return;
 	}
 }
 
-out_data_scd30 Forte_SCD30 ::read_data()
+out_data_scd30 ForteSCD30 ::readData()
 {
 	if (airSensor.dataAvailable()) {
 		data.C02 = airSensor.getCO2();
@@ -22,10 +20,13 @@ out_data_scd30 Forte_SCD30 ::read_data()
 		return data;
 	}
 	throw NoDataAvailableException();
-	// return out_data_scd30{-1, -1, -1};
 }
 
-Message Forte_SCD30::build_message()
+std::list<Message> ForteSCD30::buildMessages()
 {
 	throw "Not yet implemented";
-}
\ No newline at end of file
+}
+SensorInformation ForteSCD30::getSensorInformation() const
+{
+	return sensorInformation;
+}
diff --git a/client/client/lib/scd30/scd30.hpp b/client/client/lib/scd30/scd30.hpp
index dcd05a4a4cba4198245e69b58d5c6e5f3b17eb2c..db3e85500924db80ac3c0b5cd3698314564f6fd6 100644
--- a/client/client/lib/scd30/scd30.hpp
+++ b/client/client/lib/scd30/scd30.hpp
@@ -4,8 +4,8 @@
 #include "ForteSensor.hpp"
 #include "Message.hpp"
 #include "NoDataAvailableException.hpp"
+#include "Pinout.hpp"
 #include "esp_log.h"
-#include "pinout.hpp"
 #include <SparkFun_SCD30_Arduino_Library.h>
 #include <Wire.h>
 
@@ -15,15 +15,17 @@ struct out_data_scd30 {
 	float Humidity;
 };
 
-class Forte_SCD30 : public Forte_Sensor<out_data_scd30> {
+class ForteSCD30 : public ForteSensor<out_data_scd30> {
   public:
 	void setup() override;
-	out_data_scd30 read_data() override;
-	Message build_message() 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/client/client/platformio.ini b/client/client/platformio.ini
index 8b0ba5710afc13eeb3489c185f40cf3c33a09629..435ae69baa774f3494c60228192f3fbfaec44f94 100644
--- a/client/client/platformio.ini
+++ b/client/client/platformio.ini
@@ -13,16 +13,24 @@ platform = espressif32
 board = esp32-c3-devkitm-1
 framework = arduino
 monitor_speed = 115200
-build_flags =
-    -I include
-    -DCORE_DEBUG_LEVEL=5
+; 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
+; serial port
+monitor_port = /dev/ttyUSB1
+upload_port = /dev/ttyUSB1
 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
+	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/client/client/src/main.cpp b/client/client/src/main.cpp
index 266c4c78072af0f01a23454e5524118150f8692d..bf964c0c5c0280b41dc8e0a514f76408276314d0 100644
--- a/client/client/src/main.cpp
+++ b/client/client/src/main.cpp
@@ -1,19 +1,21 @@
+#include "../lib/dr26_analogue/dr26.hpp"
 #include "NoDataAvailableException.hpp"
 #include "esp_log.h"
 #include <Arduino.h>
-#include <dr26.hpp>
 #include <drs26.hpp>
 #include <ina219.hpp>
 #include <scd30.hpp>
 // #include "esp32-hal-log.h"
-static const char *TAG = "MAIN";
+static const std::string TAG = "MAIN";
 
-Forte_DRS26 drs26;
+ForteDRS26 drs26;
 
 void setup()
 {
 	Serial.begin(115200);
 	drs26.setup();
+	espnow_setup();
+
 	//	log_e("Setup complete.");
 }
 
@@ -23,15 +25,18 @@ void loop()
 	out_data_drs26 data{};
 
 	try {
-		espnow_setup();
-		//			data = drs26.read_data();
-		auto message = drs26.build_message();
-		message.send();
+		//			data = drs26.readData();
+		auto messages = drs26.buildMessages();
+
+		for (const Message &message : messages) {
+			message.send();
+		}
+
 	} catch (const NoDataAvailableException &e) {
 		std::cerr << e.what() << '\n';
 	}
 
-	ESP_LOGE(TAG, "Sensor Circumference: ");
+	ESP_LOGE(TAG.c_str(), "Sensor Circumference: ");
 	//	log_e("Temperature: ");
 	//	log_e("Id: ");
 
diff --git a/client/client/test/TestClientDataPackage.cpp b/client/client/test/TestClientDataPackage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..eea536cfbc63f7c6dc9797d8288a5887c384aa0c
--- /dev/null
+++ b/client/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/client/client/test/TestClientDataPackage.hpp b/client/client/test/TestClientDataPackage.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fa5f20396c423714daff914dfd16b24c8cd6cff5
--- /dev/null
+++ b/client/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/client/client/test/TestMessage.cpp b/client/client/test/TestMessage.cpp
deleted file mode 100644
index 56b7ccc83ab80707afba68c9c33fbe1f6ad6f0b1..0000000000000000000000000000000000000000
--- a/client/client/test/TestMessage.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "TestMessage.hpp"
-
-void test_on_data_recv()
-{
-	Message message = Message{};
-
-	TEST_ASSERT_EQUAL(0, message.getData().amountData);
-}
-
-void test_new_message_filled()
-{
-	Message message = Message{};
-
-	message.add_data(1.1, 0);
-	message.add_data(1.2, 1);
-	message.add_data(1.3, 2);
-
-	float expectedValuesArray[] = {1.1, 1.2, 1.3};
-	int expectedIdentifiersArray[] = {0, 1, 2};
-
-	TEST_ASSERT_EQUAL(3, message.getData().amountData);
-	TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedValuesArray, message.getData().values, 3);
-	TEST_ASSERT_EQUAL_INT_ARRAY(expectedIdentifiersArray, message.getData().identifiers, 3);
-}
\ No newline at end of file
diff --git a/client/client/test/TestMessage.hpp b/client/client/test/TestMessage.hpp
deleted file mode 100644
index 80d5be09d9d13954d96d1b6ef0b366783b414398..0000000000000000000000000000000000000000
--- a/client/client/test/TestMessage.hpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-#include <Arduino.h>
-#include <ESPNow.hpp>
-#include <unity.h>
-
-void test_on_data_recv();
-
-void test_new_message_filled();
\ No newline at end of file
diff --git a/client/client/test/main.cpp b/client/client/test/main.cpp
index 82d68817015b01f036c346b18fa79601a5e842aa..5ad5f3f7a0c3626689b5093cfbec886b6afa4e96 100644
--- a/client/client/test/main.cpp
+++ b/client/client/test/main.cpp
@@ -1,7 +1,7 @@
 #include "TestESPNow.hpp"
-#include "TestMessage.hpp"
 #include <Arduino.h>
 #include <unity.h>
+#include "TestClientDataPackage.hpp"
 
 void setup()
 {
@@ -9,8 +9,9 @@ void setup()
 
 	UNITY_BEGIN();
 	RUN_TEST(test_on_data_recv_valid_config);
-	RUN_TEST(test_on_data_recv);
-	RUN_TEST(test_new_message_filled);
+	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();
 }
 
diff --git a/host/esp32/src/main.cpp b/host/esp32/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..132224b96d1c3240b9c6ef17df736f0d1f16c01c
--- /dev/null
+++ b/host/esp32/src/main.cpp
@@ -0,0 +1,42 @@
+#include <Arduino.h>
+#include <WiFi.h>
+#include <esp_now.h>
+
+void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status)
+{
+	// go to sleep
+}
+
+void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len)
+{
+	// print mac
+	Serial.println("Message recieved");
+	for (int i = 0; i < 6; i++) {
+		Serial.print(mac[i], HEX);
+		Serial.print(":");
+	}
+	Serial.println();
+
+	char data[len];
+	memcpy(data, incomingData, len);
+	Serial.println(data);
+}
+
+void setup()
+{
+	Serial.begin(115200);
+	WiFi.mode(WIFI_STA);
+	Serial.println("ESPNow init");
+	if (esp_now_init() != ESP_OK) {
+		// initialization failed
+		Serial.println("ESPNow init failed");
+		return; // not sure about this
+	}
+	Serial.println("ESPNow init success");
+
+	esp_now_register_recv_cb(on_data_recv);
+	//  write your initialization code here
+}
+
+void loop() {
+}
\ No newline at end of file