diff --git a/host/arduino/platformio.ini b/host/arduino/platformio.ini
index 58dec1ab8899033f0d5b4dac328bbc79b74213e0..42aa8668810174009c6cbe21163499d5d1e33475 100644
--- a/host/arduino/platformio.ini
+++ b/host/arduino/platformio.ini
@@ -12,7 +12,17 @@
 platform = atmelsam
 board = mkrnb1500
 framework = arduino
-lib_deps = 
-	arduino-libraries/MKRNB@^1.5.1
-	bblanchon/ArduinoJson@^6.19.4
-	arduino-libraries/Arduino Low Power@^1.2.2
+monitor_speed = 9600
+build_flags =
+    -I include
+    -DCORE_DEBUG_LEVEL=5
+    -std=gnu++17
+build_unflags = -std=gnu++11
+monitor_port = /dev/ttyACM0
+upload_port = /dev/ttyACM0
+
+lib_deps =
+    arduino-libraries/MKRNB@^1.5.1
+    bblanchon/ArduinoJson@^6.19.4
+    arduino-libraries/Arduino Low Power@^1.2.2
+    arduino-libraries/SD@^1.2.4
diff --git a/host/arduino/src/main.cpp b/host/arduino/src/main.cpp
index 1d15df627d863b11e55b619b11cf981e2b4c1f8f..8b27c371f39af73c5b47c716c956a4bec8294f4f 100644
--- a/host/arduino/src/main.cpp
+++ b/host/arduino/src/main.cpp
@@ -6,9 +6,9 @@ this example downloads the URL "http://example.org/" and
 prints it to the Serial monitor.
 
 Circuit:
-- MKR NB 1500 board
-- Antenna
-- SIM card with a data plan
+    - MKR NB 1500 board
+    - Antenna
+    - SIM card with a data plan
 
 created 8 Mar 2012
 by Tom Igoe
@@ -18,8 +18,9 @@ by Tom Igoe
 #include "ArduinoLowPower.h"
 #include <ArduinoJson.h>
 #include <MKRNB.h>
+#include <SD.h>
+#include <SPI.h>
 #include <string>
-
 // initialize the library instance
 GPRS gprs;
 NB nbAccess;
@@ -28,6 +29,7 @@ void attachToNetwork();
 
 std::string getResponse(NBClient &client);
 std::string getResponseBody(const std::string &response);
+void sendData(std::string data);
 std::string getResponse(std::string server, std::string path, int port)
 {
 	NBClient client;
@@ -108,13 +110,37 @@ std::string postRequest(std::string server, std::string path, int port, std::str
 	return token;
 }
 
+const int wakeUpPin = 0;
+const int chipSelect = 6;
+
+void wakeUp()
+{
+	Serial.println("Wake up");
+}
 void setup()
 {
 	// initialize serial communications and wait for port to open:
 	Serial.begin(9600);
+	Serial1.begin(9600);
 	while (!Serial) {
 		; // wait for serial port to connect. Needed for native USB port only
 	}
+	pinMode(wakeUpPin, INPUT);
+	// WAKE UP FROM WATCHDOG (PIN)
+	//	LowPower.attachInterruptWakeup(wakeUpPin, wakeUp, RISING);
+
+	if (!SD.begin(chipSelect)) {
+		Serial.println("initialization failed. Things to check:");
+		Serial.println("1. is a card inserted?");
+		Serial.println("2. is your wiring correct?");
+		Serial.println("3. did you change the chipSelect pin to match your shield or module?");
+		Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!");
+		while (true)
+			;
+	}
+
+	Serial.println("Attaching to network");
+	attachToNetwork();
 }
 
 void attachToNetwork()
@@ -138,7 +164,47 @@ void attachToNetwork()
 
 void loop()
 {
-	attachToNetwork();
+	//	LowPower.deepSleep();
+
+	//	Serial.println("Waking up..");
+
+	String dataString;
+
+	while (Serial1.available()) {
+		dataString += Serial1.readString();
+	}
+
+	// open the file. note that only one file can be open at a time,
+	// so you have to close this one before opening another.
+	File dataFile = SD.open("datalog.txt", FILE_WRITE);
+
+	// if the file is available, write to it:
+	if (dataFile) {
+		if (dataString.length() > 0) {
+			dataFile.println(dataString);
+			Serial.println(dataString);
+			sendData(dataString.c_str());
+		}
+		dataFile.close();
+		// print to the serial port too:
+		//		Serial.println(dataString);
+	}
+	// if the file isn't open, pop up an error:
+	else {
+		Serial.println("error opening datalog.txt");
+	}
+
+	delay(100);
+	//
+	//	Serial.println("Going to sleep");
+	//	LowPower.deepSleep(10000);
+
+	// TODO: SAVE TO EEPROM OR SD CARD VIA SPI
+	// TODO: REFACTOR CODE
+	// TODO: TEST CODE
+}
+void sendData(std::string data)
+{
 
 	Serial.println("connecting...");
 
@@ -157,13 +223,4 @@ void loop()
 	Serial.println(date);
 	Serial.println(milliseconds_since_epoch);
 	Serial.println(time);
-	nbAccess.shutdown();
-
-	// TODO: WAKE UP FROM WATCHDOG (PIN)
-	LowPower.deepSleep(10000);
-
-	// TODO: SAVE TO EEPROM OR SD CARD VIA SPI
-	// TODO: REFACTOR CODE
-	// TODO: TEST CODE
-
 }
diff --git a/host/esp-t-sim7000g/.gitignore b/host/esp-t-sim7000g/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3a67520414ce9bac15f6dcbb08355222f39264bf
--- /dev/null
+++ b/host/esp-t-sim7000g/.gitignore
@@ -0,0 +1,4 @@
+.pio
+.vscode/
+CMakeListsPrivate.txt
+cmake-build-*/ 
diff --git a/host/esp-t-sim7000g/CMakeLists.txt b/host/esp-t-sim7000g/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..03adc907c628da9d43428d810bf0cb5517dad941
--- /dev/null
+++ b/host/esp-t-sim7000g/CMakeLists.txt
@@ -0,0 +1,33 @@
+# !!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE
+# https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags
+#
+# If you need to override existing CMake configuration or add extra,
+# please create `CMakeListsUser.txt` in the root of project.
+# The `CMakeListsUser.txt` will not be overwritten by PlatformIO.
+
+cmake_minimum_required(VERSION 3.13)
+set(CMAKE_SYSTEM_NAME Generic)
+set(CMAKE_C_COMPILER_WORKS 1)
+set(CMAKE_CXX_COMPILER_WORKS 1)
+
+project("esp-t-sim7000g" C CXX)
+
+include(CMakeListsPrivate.txt)
+
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeListsUser.txt)
+include(CMakeListsUser.txt)
+endif()
+
+add_custom_target(
+    Production ALL
+    COMMAND platformio -c clion run "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_custom_target(
+    Debug ALL
+    COMMAND platformio -c clion debug "$<$<NOT:$<CONFIG:All>>:-e${CMAKE_BUILD_TYPE}>"
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_executable(Z_DUMMY_TARGET ${SRC_LIST})
diff --git a/host/esp-t-sim7000g/include/README b/host/esp-t-sim7000g/include/README
new file mode 100644
index 0000000000000000000000000000000000000000..194dcd43252dcbeb2044ee38510415041a0e7b47
--- /dev/null
+++ b/host/esp-t-sim7000g/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/host/esp-t-sim7000g/platformio.ini b/host/esp-t-sim7000g/platformio.ini
new file mode 100644
index 0000000000000000000000000000000000000000..96793c08457d3f309680fcbfcfaf430046a2c0af
--- /dev/null
+++ b/host/esp-t-sim7000g/platformio.ini
@@ -0,0 +1,28 @@
+; 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:esp-wrover-kit]
+platform = espressif32
+board = esp-wrover-kit
+framework = arduino
+monitor_speed = 115200
+; monitor_port = /dev/ttyACM0
+; upload_port = /dev/ttyACM0
+build_flags =
+    -I include
+    -DCORE_DEBUG_LEVEL=5
+    -std=gnu++17
+build_unflags = -std=gnu++11
+lib_deps =
+    vshymanskyy/TinyGSM@^0.11.5
+    vshymanskyy/StreamDebugger@^1.0.1
+    bblanchon/ArduinoJson@^6.19.4
+    fbiego/ESP32Time@^2.0.0
+
diff --git a/host/esp-t-sim7000g/src/main.cpp b/host/esp-t-sim7000g/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c9b43d08ed0d86119a2eb55a02e533b207688f42
--- /dev/null
+++ b/host/esp-t-sim7000g/src/main.cpp
@@ -0,0 +1,536 @@
+#include "FS.h"
+#include "SD.h"
+#include "SPI.h"
+#include "time.h"
+#include <Arduino.h>
+#include <ArduinoJson.h>
+#include <ESP32Time.h>
+#include <WiFi.h>
+#include <esp_log.h>
+#include <esp_now.h>
+#include <queue>
+#include <sys/unistd.h>
+
+static const std::string TAG = "MAIN";
+static const std::string TAG_ESPNOW = "ESPNOW";
+static const std::string TAG_GSM = "GSM";
+
+/*
+  FILE: AllFunctions.ino
+  AUTHOR: Koby Hale
+  PURPOSE: Test functionality
+*/
+
+#define TINY_GSM_MODEM_SIM7000
+#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
+#define SerialAT Serial1
+
+// See all AT commands, if wanted
+#define DUMP_AT_COMMANDS
+
+// set GSM PIN, if any
+#define GSM_PIN ""
+
+// Your GPRS credentials, if any
+const char apn[] = "m2m.public.at"; // SET TO YOUR APN
+const char gprsUser[] = "";
+const char gprsPass[] = "";
+
+#include <TinyGsmClient.h>
+
+#ifdef DUMP_AT_COMMANDS // if enabled it requires the streamDebugger lib
+#include <StreamDebugger.h>
+StreamDebugger debugger(SerialAT, Serial);
+TinyGsm modem(debugger);
+#else
+TinyGsm modem(SerialAT);
+#endif
+
+#define uS_TO_S_FACTOR 1000000ULL // Conversion factor for micro seconds to seconds
+#define TIME_TO_SLEEP 5           // Time ESP32 will go to sleep (in seconds)
+
+#define UART_BAUD 115200
+#define PIN_DTR 25
+#define PIN_TX 27
+#define PIN_RX 26
+#define PWR_PIN 4
+
+#define SD_MISO 2
+#define SD_MOSI 15
+#define SD_SCLK 14
+#define SD_CS 13
+#define LED_PIN 12
+
+enum MessageType{
+    dataAck,
+    hostChange
+};
+typedef struct response{
+	MessageType type;
+	uint8_t mac[6];
+	long time;
+}response;
+
+uint8_t BROADCAST_MAC[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+ESP32Time rtc;
+
+SemaphoreHandle_t xMutex;
+
+TaskHandle_t ESPNOWTask;
+
+static std::queue<String> queue;
+
+void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status)
+{
+	// go to sleep
+}
+
+static char log_print_buffer[512];
+
+int vprintf_into_sd(const char *szFormat, va_list args)
+{
+	String logstring = "[" + rtc.getDateTime() + "] ";
+	logstring += szFormat;
+	// write evaluated format string into buffer
+	int ret = vsnprintf(log_print_buffer, sizeof(log_print_buffer), logstring.c_str(), args);
+
+	String date = rtc.getDate();
+	String filename = "/log_" + date + ".txt";
+
+	// output is now in buffer. write to file.
+	if (ret >= 0) {
+		if (!SD.exists(filename)) {
+			File writeLog = SD.open(filename, FILE_WRITE);
+			if (!writeLog)
+				Serial.println("Couldn't open " + filename + " for writing");
+			delay(50);
+			writeLog.close();
+		}
+
+		File logFile = SD.open(filename, FILE_APPEND);
+
+		// debug output
+		vprintf(logstring.c_str(), args);
+		logFile.write((uint8_t *)log_print_buffer, (size_t)ret);
+		// to be safe in case of crashes: flush the output
+		logFile.flush();
+		logFile.close();
+	}
+	return ret;
+}
+
+String getMacAddressAsString(const uint8_t *mac);
+DynamicJsonDocument parseReceivedJsonData(char *data);
+void saveStringToSDCard(const std::string &dataString);
+String documentToLineProtocolString(const DynamicJsonDocument &doc);
+void turnOffLEDs();
+void setupSDCard();
+void syncUTCTimeToRTC();
+void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len)
+{
+	esp_log_write(ESP_LOG_INFO, TAG_ESPNOW.c_str(), "Message recieved\n");
+	// copy received data to a char array
+	char data[len];
+	memcpy(data, incomingData, len);
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Raw received Data: %s\n", data);
+
+	if(!esp_now_is_peer_exist(mac)){
+		esp_now_peer_info_t client = {};
+		memcpy(client.peer_addr, mac, 6);
+		client.encrypt = false;
+		client.channel = 0;
+
+		esp_err_t status = esp_now_add_peer(&client);
+		if(status != ESP_OK){
+			esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Failed to add new Peer: %d", status);
+		}
+	}
+
+	DynamicJsonDocument doc = parseReceivedJsonData(data);
+
+	String macAddress = getMacAddressAsString(mac);
+
+	// add timestamp and mac address
+	doc["timestamp"] = rtc.getEpoch();
+	doc["clientMac"] = macAddress;
+
+	// serialize json document again
+	std::string dataString{};
+	serializeJson(doc, dataString);
+
+	saveStringToSDCard(dataString);
+
+	String lineData = documentToLineProtocolString(doc);
+
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Line protocol data: %s\n", lineData.c_str());
+
+	xSemaphoreTake(xMutex, portMAX_DELAY);
+	queue.push(lineData);
+	xSemaphoreGive(xMutex);
+
+	response response;
+	response.type = dataAck;
+	esp_read_mac(response.mac, ESP_MAC_WIFI_STA);
+	response.time = rtc.getEpoch();
+	esp_err_t success = esp_now_send(mac, (uint8_t*) &response, sizeof(response));
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), 
+		(success == ESP_OK) ? "Response sent." : "Failed to respond");
+}
+
+String documentToLineProtocolString(const DynamicJsonDocument &doc)
+{
+	String measurementType = doc["measurementType"].as<String>();
+	String sensorName = doc["sensorName"].as<String>();
+	String timestamp = doc["timestamp"].as<String>();
+	String protocol = doc["protocol"].as<String>();
+	String value = doc["value"].as<String>();
+	String channel = doc["channel"].as<String>();
+	String clientMac = doc["clientMac"].as<String>();
+
+	String lineData = sensorName + ",clientMac=" + clientMac + ",protocol=" + protocol + ",channel=" + channel + " "
+	                  + measurementType + "=" + value + " " + timestamp;
+	return lineData;
+}
+void saveStringToSDCard(const std::string &dataString)
+{
+	File dataFile = SD.open("/datalog.txt", FILE_APPEND);
+
+	// if the file is available, write to it:
+	if (dataFile) {
+		if (dataString.length() > 0) {
+			dataFile.println(dataString.c_str());
+		}
+		dataFile.close();
+	}
+	// if the file isn't open, pop up an error:
+	else {
+		esp_log_write(ESP_LOG_ERROR, TAG.c_str(), "error opening datalog.txt\n");
+		// TODO: Error handling
+	}
+}
+DynamicJsonDocument parseReceivedJsonData(char *data)
+{
+	DynamicJsonDocument doc(250);
+	auto error = deserializeJson(doc, data);
+	if (error) {
+		esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW.c_str(), "Error while parsing json: %s\n", error.f_str());
+		// TODO error handling
+	}
+	return doc;
+}
+String getMacAddressAsString(const uint8_t *mac)
+{
+	String macAddress;
+	for (int i = 0; i < 6; i++) {
+		macAddress += String(mac[i], HEX);
+	}
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "MAC: %s\n", macAddress.c_str());
+	return macAddress;
+}
+
+[[noreturn]] void ESPNOWReceiveTask(void *parameter)
+{
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "ESPNOWReceiveTask started on core %d\n", xPortGetCoreID());
+
+	WiFi.mode(WIFI_STA);
+
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow...\n");
+
+	if (esp_now_init() != ESP_OK) {
+		// initialization failed
+		esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW.c_str(), "Initialising ESPNow FAILED\n");
+		exit(ESP_FAIL);
+	}
+
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow SUCCESS\n");
+
+	esp_now_register_recv_cb(on_data_recv);
+
+	while (true) {
+	}
+}
+
+time_t timeToUnixEpochSeconds(const std::string &time)
+{
+	//	22/10/27,10:16:20+00
+	struct tm tm {};
+	time_t dateInEpoch = 0;
+
+	if (strptime(time.c_str(), "%y/%m/%d,%T+00", &tm)) {
+		time_t curTime;
+		struct tm *timeinfo;
+
+		timeinfo = localtime(&curTime);
+
+		timeinfo->tm_year = tm.tm_year;
+		timeinfo->tm_mon = tm.tm_mon;
+		timeinfo->tm_mday = tm.tm_mday;
+		timeinfo->tm_hour = tm.tm_hour;
+		timeinfo->tm_min = tm.tm_min;
+		timeinfo->tm_sec = tm.tm_sec;
+		timeinfo->tm_isdst = -1;
+
+		dateInEpoch = mktime(timeinfo);
+	}
+	return dateInEpoch;
+}
+
+void setup()
+{
+	// Set console baud rate
+	Serial.begin(115200);
+	delay(10);
+	setupSDCard();
+
+	//	https://stackoverflow.com/questions/60442350/arduinos-esp-log-set-vprintf-does-not-work-on-esp32
+	esp_log_set_vprintf(&vprintf_into_sd);
+	esp_log_level_set("*", ESP_LOG_VERBOSE);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s", WiFi.macAddress().c_str());
+
+	turnOffLEDs();
+
+	xMutex = xSemaphoreCreateMutex();
+
+	delay(1000);
+
+	// create ESPNOWReceiveTask. TODO: Until the UTC time is not synced, this will not add the correct time. If we
+	// TODO: create the task after the time is synced, no messages will be received until synchronization is done
+	xTaskCreatePinnedToCore(ESPNOWReceiveTask,   /* Function to implement the task */
+	                        "ESPNOWReceiveTask", /* Name of the task */
+	                        10000,               /* Stack size in words */
+	                        nullptr,             /* Task input parameter */
+	                        0,                   /* Priority of the task */
+	                        &ESPNOWTask,         /* Task handle. */
+	                        0);                  /* Core where the task should run */
+
+	SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX);
+
+	// Restart takes quite some time
+	// To skip it, call init() instead of restart()
+	esp_log_write(ESP_LOG_DEBUG, TAG_GSM.c_str(), "Initializing modem...\n");
+	if (!modem.restart()) {
+		esp_log_write(ESP_LOG_WARN, TAG_GSM.c_str(),
+		              "Failed to restart modem, attempting to continue without restarting\n");
+	}
+
+	syncUTCTimeToRTC();
+
+	response announce = {};
+	announce.type = hostChange;
+	esp_read_mac(announce.mac, ESP_MAC_WIFI_STA);
+	announce.time = rtc.getEpoch();
+	esp_now_send(BROADCAST_MAC, (uint8_t *) &announce, sizeof(announce));
+}
+void syncUTCTimeToRTC()
+{
+	esp_log_write(ESP_LOG_DEBUG, TAG_GSM.c_str(), "NTP Server Syncing...\n");
+	modem.NTPServerSync("pool.ntp.org", 0);
+	auto gsmDateTimeString = modem.getGSMDateTime(DATE_FULL);
+	esp_log_write(ESP_LOG_DEBUG, TAG_GSM.c_str(), "GSM DateTime: %s\n", gsmDateTimeString.c_str());
+	time_t time = timeToUnixEpochSeconds(gsmDateTimeString.c_str());
+	rtc.setTime(time);
+	esp_log_write(ESP_LOG_INFO, TAG_GSM.c_str(), "Time set to EPOCH: %s\n", String(rtc.getEpoch()).c_str());
+}
+void setupSDCard()
+{
+	SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
+	if (!SD.begin(SD_CS)) {
+		esp_log_write(ESP_LOG_ERROR, TAG.c_str(), "Card MOUNT FAIL\n");
+		// TODO: Error handling
+	} else {
+		uint32_t cardSize = SD.cardSize() / (1024 * 1024);
+		String sdcardSizeString = "SDCard Size: " + String(cardSize) + "MB";
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s\n", sdcardSizeString.c_str());
+	}
+}
+
+// I don't think this does anything. Copied from the example
+void turnOffLEDs()
+{ // Set LED OFF
+	pinMode(LED_PIN, OUTPUT);
+	digitalWrite(LED_PIN, HIGH);
+
+	pinMode(PWR_PIN, OUTPUT);
+	digitalWrite(PWR_PIN, HIGH);
+	delay(300);
+	digitalWrite(PWR_PIN, LOW);
+}
+
+const String INFLUXDB_TOKEN =
+    "dUh2gbVLv7e3egqocxriDsJQNUacA9qZ5YXsYtdnVAglnHgy4nx-jDVO7nGlSF34BosfnuwnUDaviC7dQeC5RQ==";
+
+struct RequestInformation {
+	String method;
+	String host;
+	String path;
+	String body;
+};
+
+String buildRequest(const RequestInformation &requestInformation)
+{
+	String request = "";
+	request += requestInformation.method + " " + requestInformation.path + " HTTP/1.1\r\n";
+	request += "Host: " + requestInformation.host + "\r\n";
+	request += "Authorization: Token " + INFLUXDB_TOKEN + "\r\n";
+	request += "User-Agent: ESP32\r\n";
+	request += "Content-Type: text/plain\r\n";
+	request += "Content-Length: " + String(requestInformation.body.length()) + "\r\n";
+	request += "\r\n";
+	request += requestInformation.body;
+	return request;
+}
+
+void loop()
+{
+
+	// Restart takes quite some time
+	// To skip it, call init() instead of restart()
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Initializing modem...\n");
+	if (!modem.init()) {
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(),
+		              "Failed to restart modem, attempting to continue without restarting\n");
+	}
+
+	String name = modem.getModemName();
+	delay(500);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Modem Name %s\n", name.c_str());
+
+	String modemInfo = modem.getModemInfo();
+	delay(500);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Modem Info: %s\n", modemInfo.c_str());
+
+	// Set SIM7000G GPIO4 LOW ,turn off GPS power
+	// CMD:AT+SGPIO=0,4,1,0
+	// Only in version 20200415 is there a function to control GPS power
+	modem.sendAT("+SGPIO=0,4,1,0");
+	if (modem.waitResponse(10000L) != 1) {
+		DBG(" SGPIO=0,4,1,0 false ");
+	}
+
+	modem.sendAT("+CFUN=0 ");
+	if (modem.waitResponse(10000L) != 1) {
+		DBG(" +CFUN=0  false ");
+	}
+	delay(200);
+
+	/*
+	  2 Automatic
+	  13 GSM only
+	  38 LTE only
+	  51 GSM and LTE only
+	* * * */
+	String res;
+	res = modem.setNetworkMode(38);
+	if (res != "1") {
+		DBG("setNetworkMode  false ");
+		return;
+	}
+	delay(200);
+
+	/*
+	  1 CAT-M
+	  2 NB-Iot
+	  3 CAT-M and NB-IoT
+	* * */
+	//	res = modem.setPreferredMode(1);
+	//	if (res != "1") {
+	//
+	//		DBG("setPreferredMode  false ");
+	//		return;
+	//	}
+	delay(200);
+
+	/*AT+CBANDCFG=<mode>,<band>[,<band>…]
+	 * <mode> "CAT-M"   "NB-IOT"
+	 * <band>  The value of <band> must is in the band list of getting from  AT+CBANDCFG=?
+	 * For example, my SIM card carrier "NB-iot" supports B8.  I will configure +CBANDCFG= "Nb-iot ",8
+	 */
+	modem.sendAT("+CBANDCFG=\"CAT-M\",8 ");
+	if (modem.waitResponse(10000L) != 1) {
+		DBG(" +CBANDCFG=\"NB-IOT\" ");
+	}
+	delay(200);
+
+	modem.sendAT("+CFUN=1 ");
+	if (modem.waitResponse(10000L) != 1) {
+		DBG(" +CFUN=1  false ");
+	}
+	delay(200);
+
+	//	modem.disableGPS();
+	delay(200);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s\n", String(modem.getSignalQuality()).c_str());
+	delay(200);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Trying to connect to network\n");
+	modem.gprsConnect(apn, gprsUser, gprsPass);
+	delay(200);
+	syncUTCTimeToRTC();
+
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Waiting for network...\n");
+	if (!modem.isNetworkConnected()) {
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Network not connected\n");
+		return;
+	} else {
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Network connected\n");
+		delay(200);
+
+		// quality
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s\n", String(modem.getSignalQuality()).c_str());
+		// make a http post request
+		String url = "influxdb.qe-forte.uibk.ac.at";
+		String path = "/api/v2/write?org=QE&bucket=esp32test&precision=s";
+		Serial.print("Connecting to ");
+		esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s\n", url.c_str());
+		// Use WiFiClient class to create TCP connections
+
+		while (!queue.empty()) {
+
+			xSemaphoreTake(xMutex, portMAX_DELAY);
+			String lineData = queue.front();
+			queue.pop();
+			xSemaphoreGive(xMutex);
+
+			RequestInformation requestInformation{.method = "POST", .host = url, .path = path, .body = lineData};
+
+			//"sensorName":"DRS26","timestamp":1666872216,"protocol":"I2C","value":0,"channel":0,"measurementType":"CIRCUMFERENCE_INCREMENT"
+
+			String request = buildRequest(requestInformation);
+			esp_log_write(ESP_LOG_VERBOSE, TAG.c_str(), "request: %s\n", request.c_str());
+
+			TinyGsmClient client{modem};
+			const int httpPort = 80;
+			if (!client.connect(url.c_str(), httpPort)) {
+				esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "connection failed\n");
+				return;
+			}
+
+			client.print(request);
+
+			// print response
+			while (client.connected()) {
+				String line = client.readStringUntil('\n');
+				if (line == "\r") {
+					esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "headers received\n");
+					break;
+				}
+			}
+			client.stop();
+			delay(1000);
+		}
+		DBG("Network connected");
+	}
+
+#if TINY_GSM_POWERDOWN
+	// Try to power-off (modem may decide to restart automatically)
+	// To turn off modem completely, please use Reset/Enable pins
+	//	modem.sendAT("+CPOWD=1");
+	//	if (modem.waitResponse(10000L) != 1) {
+	//		DBG("+CPOWD=1");
+	//	}
+	//	modem.poweroff();
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "Poweroff.");
+#endif
+
+	delay(1000);
+}
diff --git a/host/esp-t-sim7000g/src/main2.cpp b/host/esp-t-sim7000g/src/main2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..036405dc530d2707fb79b11198afd96ba70be78a
--- /dev/null
+++ b/host/esp-t-sim7000g/src/main2.cpp
@@ -0,0 +1,304 @@
+///**************************************************************
+// *
+// * This sketch connects to a website and downloads a page.
+// * It can be used to perform HTTP/RESTful API calls.
+// *
+// * TinyGSM Getting Started guide:
+// *   https://tiny.cc/tinygsm-readme
+// *
+// **************************************************************/
+//
+//// Select your modem:
+//// #define TINY_GSM_MODEM_SIM800
+//// #define TINY_GSM_MODEM_SIM808
+//// #define TINY_GSM_MODEM_SIM868
+//// #define TINY_GSM_MODEM_SIM900
+//#define TINY_GSM_MODEM_SIM7000
+//// #define TINY_GSM_MODEM_SIM7000SSL
+//// #define TINY_GSM_MODEM_SIM7080
+//// #define TINY_GSM_MODEM_SIM5360
+//// #define TINY_GSM_MODEM_SIM7600
+//// #define TINY_GSM_MODEM_UBLOX
+//// #define TINY_GSM_MODEM_SARAR4
+//// #define TINY_GSM_MODEM_M95
+//// #define TINY_GSM_MODEM_BG96
+//// #define TINY_GSM_MODEM_A6
+//// #define TINY_GSM_MODEM_A7
+//// #define TINY_GSM_MODEM_M590
+//// #define TINY_GSM_MODEM_MC60
+//// #define TINY_GSM_MODEM_MC60E
+//// #define TINY_GSM_MODEM_ESP8266
+//// #define TINY_GSM_MODEM_XBEE
+//// #define TINY_GSM_MODEM_SEQUANS_MONARCH
+//
+//// Set serial for debug console (to the Serial Monitor, default speed 115200)
+//#define SerialMon Serial
+//
+//// Set serial for AT commands (to the module)
+//// Use Hardware Serial on Mega, Leonardo, Micro
+//#ifndef __AVR_ATmega328P__
+//#define SerialAT Serial1
+//
+//// or Software Serial on Uno, Nano
+//#else
+//#include <SoftwareSerial.h>
+//SoftwareSerial SerialAT(2, 3); // RX, TX
+//#endif
+//
+//// Increase RX buffer to capture the entire response
+//// Chips without internal buffering (A6/A7, ESP8266, M590)
+//// need enough space in the buffer for the entire response
+//// else data will be lost (and the http library will fail).
+//#if !defined(TINY_GSM_RX_BUFFER)
+//#define TINY_GSM_RX_BUFFER 650
+//#endif
+//
+//// See all AT commands, if wanted
+//#define DUMP_AT_COMMANDS
+//
+//// Define the serial console for debug prints, if needed
+//#define TINY_GSM_DEBUG SerialMon
+//
+//// Range to attempt to autobaud
+//// NOTE:  DO NOT AUTOBAUD in production code.  Once you've established
+//// communication, set a fixed baud rate using modem.setBaud(#).
+//#define GSM_AUTOBAUD_MIN 9600
+//#define GSM_AUTOBAUD_MAX 115200
+//
+//// Add a reception delay, if needed.
+//// This may be needed for a fast processor at a slow baud rate.
+//// #define TINY_GSM_YIELD() { delay(2); }
+//
+//// Uncomment this if you want to use SSL
+//// #define USE_SSL
+//
+//// Define how you're planning to connect to the internet.
+//// This is only needed for this example, not in other code.
+//#define TINY_GSM_USE_GPRS true
+//#define TINY_GSM_USE_WIFI false
+//
+//// set GSM PIN, if any
+//#define GSM_PIN ""
+//
+//// Your GPRS credentials, if any
+//const char apn[] = "m2m.public.at";
+//const char gprsUser[] = "";
+//const char gprsPass[] = "";
+//
+//// Your WiFi connection credentials, if applicable
+//const char wifiSSID[] = "YourSSID";
+//const char wifiPass[] = "YourWiFiPass";
+//
+//// Server details
+//const char server[] = "vsh.pp.ua";
+//const char resource[] = "/TinyGSM/logo.txt";
+//
+//#include <TinyGsmClient.h>
+//#include <WiFi.h>
+//#include <esp_now.h>
+//
+//// Just in case someone defined the wrong thing..
+//#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
+//#undef TINY_GSM_USE_GPRS
+//#undef TINY_GSM_USE_WIFI
+//#define TINY_GSM_USE_GPRS false
+//#define TINY_GSM_USE_WIFI true
+//#endif
+//#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
+//#undef TINY_GSM_USE_GPRS
+//#undef TINY_GSM_USE_WIFI
+//#define TINY_GSM_USE_GPRS true
+//#define TINY_GSM_USE_WIFI false
+//#endif
+//
+//#ifdef DUMP_AT_COMMANDS
+//#include <StreamDebugger.h>
+//StreamDebugger debugger(SerialAT, SerialMon);
+//TinyGsm modem(debugger);
+//#else
+//TinyGsm modem(SerialAT);
+//#endif
+//
+//#ifdef USE_SSL
+//TinyGsmClientSecure client(modem);
+//const int port = 443;
+//#else
+//TinyGsmClient client(modem);
+//const int port = 80;
+//#endif
+//
+//TaskHandle_t Task1;
+//
+//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.print("Message recieved: Core ");
+//	Serial.println(xPortGetCoreID());
+//	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);
+//}
+//
+//[[noreturn]] void Task1code(void *parameter)
+//{
+//	Serial.println(xPortGetCoreID());
+//	WiFi.mode(WIFI_STA);
+//	Serial.println("ESPNow init");
+//	if (esp_now_init() != ESP_OK) {
+//		// initialization failed
+//		Serial.println("ESPNow init failed");
+//		// not sure about this
+//	}
+//	Serial.println("ESPNow init success");
+//	esp_now_register_recv_cb(on_data_recv);
+//
+//	while (true) {
+//	}
+//}
+//
+//void setup2()
+//{
+//	// Set console baud rate
+//	SerialMon.begin(115200);
+//	delay(10);
+//
+//	// !!!!!!!!!!!
+//	// Set your reset, enable, power pins here
+//	// !!!!!!!!!!!
+//
+//	SerialMon.println("Wait...");
+//
+//	xTaskCreatePinnedToCore(Task1code, /* Function to implement the task */
+//	                        "Task1",   /* Name of the task */
+//	                        10000,     /* Stack size in words */
+//	                        nullptr,   /* Task input parameter */
+//	                        0,         /* Priority of the task */
+//	                        &Task1,    /* Task handle. */
+//	                        0);        /* Core where the task should run */
+//
+//	// Set GSM module baud rate
+//	//	TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
+//	modem.setBaud(9600);
+//	// SerialAT.begin(9600);
+//	delay(6000);
+//
+//	// Restart takes quite some time
+//	// To skip it, call init() instead of restart()
+//	SerialMon.println("Initializing modem...");
+//	modem.restart();
+//	// modem.init();
+//
+//	String modemInfo = modem.getModemInfo();
+//	SerialMon.print("Modem Info: ");
+//	SerialMon.println(modemInfo);
+//
+//#if TINY_GSM_USE_GPRS
+//	// Unlock your SIM card with a PIN if needed
+//	if (GSM_PIN && modem.getSimStatus() != 3) {
+//		modem.simUnlock(GSM_PIN);
+//	}
+//#endif
+//}
+//
+//void loop2()
+//{
+//#if TINY_GSM_USE_WIFI
+//	// Wifi connection parameters must be set before waiting for the network
+//	SerialMon.print(F("Setting SSID/password..."));
+//	if (!modem.networkConnect(wifiSSID, wifiPass)) {
+//		SerialMon.println(" fail");
+//		delay(10000);
+//		return;
+//	}
+//	SerialMon.println(" success");
+//#endif
+//
+//#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_XBEE
+//	// The XBee must run the gprsConnect function BEFORE waiting for network!
+//	modem.gprsConnect(apn, gprsUser, gprsPass);
+//#endif
+//
+//	SerialMon.print("Waiting for network...");
+//	if (!modem.waitForNetwork()) {
+//		SerialMon.println(" fail");
+//		delay(10000);
+//		return;
+//	}
+//	SerialMon.println(" success");
+//
+//	if (modem.isNetworkConnected()) {
+//		SerialMon.println("Network connected");
+//	}
+//
+//#if TINY_GSM_USE_GPRS
+//	// GPRS connection parameters are usually set after network registration
+//	SerialMon.print(F("Connecting to "));
+//	SerialMon.print(apn);
+//	if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
+//		SerialMon.println(" fail");
+//		delay(10000);
+//		return;
+//	}
+//	SerialMon.println(" success");
+//
+//	if (modem.isGprsConnected()) {
+//		SerialMon.println("GPRS connected");
+//	}
+//#endif
+//
+//	SerialMon.print("Connecting to ");
+//	SerialMon.println(server);
+//	if (!client.connect(server, port)) {
+//		SerialMon.println(" fail");
+//		delay(10000);
+//		return;
+//	}
+//	SerialMon.println(" success");
+//
+//	// Make a HTTP GET request:
+//	SerialMon.println("Performing HTTP GET request...");
+//	client.print(String("GET ") + resource + " HTTP/1.1\r\n");
+//	client.print(String("Host: ") + server + "\r\n");
+//	client.print("Connection: close\r\n\r\n");
+//	client.println();
+//
+//	uint32_t timeout = millis();
+//	while (client.connected() && millis() - timeout < 10000L) {
+//		// Print available data
+//		while (client.available()) {
+//			char c = client.read();
+//			SerialMon.print(c);
+//			timeout = millis();
+//		}
+//	}
+//	SerialMon.println();
+//
+//	// Shutdown
+//
+//	client.stop();
+//	SerialMon.println(F("Server disconnected"));
+//
+//#if TINY_GSM_USE_WIFI
+//	modem.networkDisconnect();
+//	SerialMon.println(F("WiFi disconnected"));
+//#endif
+//#if TINY_GSM_USE_GPRS
+//	modem.gprsDisconnect();
+//	SerialMon.println(F("GPRS disconnected"));
+//#endif
+//
+//	// Do nothing forevermore
+//	while (true) {
+//		delay(1000);
+//	}
+//}
diff --git a/host/esp-t-sim7000g/test/README b/host/esp-t-sim7000g/test/README
new file mode 100644
index 0000000000000000000000000000000000000000..9b1e87bc67c90e7f09a92a3e855444b085c655a6
--- /dev/null
+++ b/host/esp-t-sim7000g/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/host/esp32-espnow-recv/platformio.ini b/host/esp32-espnow-recv/platformio.ini
index 808a5bb1fc8bdb99fa2782ed3898a0cf5dcc7ae5..00e269f9df78977a0e770af2c25ff733527b665b 100644
--- a/host/esp32-espnow-recv/platformio.ini
+++ b/host/esp32-espnow-recv/platformio.ini
@@ -13,8 +13,8 @@ platform = espressif32
 board = esp32-c3-devkitm-1
 monitor_speed = 115200
 framework = arduino
-; monitor_port = /dev/ttyUSB1
-; upload_port = /dev/ttyUSB1
+monitor_port = /dev/ttyUSB0
+upload_port = /dev/ttyUSB0
 build_flags =
     -I include
     -DCORE_DEBUG_LEVEL=5
diff --git a/host/esp32-espnow-recv/src/main.cpp b/host/esp32-espnow-recv/src/main.cpp
index 0a400535d6450f1a28e117c0cd777c57470105c6..84660754ea252da3afae69374ba34ae633774579 100644
--- a/host/esp32-espnow-recv/src/main.cpp
+++ b/host/esp32-espnow-recv/src/main.cpp
@@ -4,16 +4,42 @@
 #include <Arduino.h>
 #include <WiFi.h>
 #include <esp_now.h>
+#include <queue>
 #include <sys/unistd.h>
 
 #define RXD2 18
 #define TXD2 19
 
-long time1 = 0;
+TaskHandle_t Task1;
 
-uint8_t hostMac[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+static std::queue<std::string> queue;
+const int wakeUpPin = 4;
 
-//SoftwareSerial mySerial(RXD2, TXD2);
+[[noreturn]] void Task1code(void *parameter)
+{
+	Serial.println(xPortGetCoreID());
+	while (true) {
+
+		if (!queue.empty()) {
+			std::string message = queue.front();
+			queue.pop();
+
+			digitalWrite(wakeUpPin, HIGH);
+			delay(100);
+
+			Serial.println(message.c_str());
+			Serial1.println(message.c_str());
+
+			digitalWrite(wakeUpPin, LOW);
+		}
+
+		delay(5000);
+		//	Code for task 1 - infinite loop
+		//    (...)
+	}
+}
+
+// SoftwareSerial mySerial(RXD2, TXD2);
 
 enum MessageType{
     dataAck,
@@ -42,51 +68,23 @@ 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)
 {
 	// print mac
-	Serial.print("Message recieved from: ");
-	print_mac(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);
-	Serial1.write(data);
-
-	// add client if not already peer
-	if(!esp_now_is_peer_exist(mac)){ 
-		Serial.println("adding client to peers");
-
-		esp_now_peer_info_t client = {};
-		memcpy(client.peer_addr, mac, 6);
-		client.encrypt = false;
-		client.channel = 0;
-
-		esp_err_t status = esp_now_add_peer(&client);
-		if(status != ESP_OK){
-			Serial.print("Failed to add peer: ");
-			Serial.println(status, HEX);
-		}
-		Serial.flush();
-	}
-
-	// respond with own mac + time
-	response response;
-	response.type = dataAck;
-	esp_read_mac(response.mac, ESP_MAC_WIFI_STA);
-	response.time = 7 * time1++;
-	esp_err_t success = esp_now_send(mac, (uint8_t *) &response, sizeof(response));
-	if(success != ESP_OK){
-		Serial.print("Failed to respond: ");
-		Serial.println(success, HEX);
-	}
-	else{
-		Serial.println("Response sent: " + (String) response.time);
-	}
-	Serial.println("\n");
+	queue.push(data);
 }
 
 void setup()
 {
 	Serial.begin(115200);
-	Serial1.begin(115200, SERIAL_8N1, RXD2, TXD2);
+	Serial1.begin(9600, SERIAL_8N1, RXD2, TXD2);
+	pinMode(wakeUpPin, OUTPUT);
+	digitalWrite(wakeUpPin, LOW);
 
 	WiFi.mode(WIFI_STA);
 	Serial.println("ESPNow init");
@@ -97,21 +95,16 @@ void setup()
 	}
 	Serial.println("ESPNow init success");
 
-	// tell all clients that this is now the host
-	// can probably be removed after testing
-	response hello;
-	hello.type = hostChange;
-	esp_read_mac(hello.mac, ESP_MAC_WIFI_STA);
-	hello.time = 0;
-	esp_now_send(hostMac, (uint8_t*) &hello, sizeof(hello));
+	xTaskCreatePinnedToCore(Task1code, /* Function to implement the task */
+	                        "Task1",   /* Name of the task */
+	                        10000,     /* Stack size in words */
+	                        nullptr,   /* Task input parameter */
+	                        0,         /* Priority of the task */
+	                        &Task1,    /* Task handle. */
+	                        0);        /* Core where the task should run */
 
 	esp_now_register_recv_cb(on_data_recv);
 	//  write your initialization code here
 }
 
-void loop() {
-	Serial.print("This device: ");
-	Serial.println(WiFi.macAddress());
-	Serial.println("\n");
-	delay(1000000);
-}
\ No newline at end of file
+void loop() {}
\ No newline at end of file
diff --git a/host/mock/.gitignore b/host/mock/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3fe18ad4795165c312b8998befee223818bd4b33
--- /dev/null
+++ b/host/mock/.gitignore
@@ -0,0 +1,3 @@
+.pio
+CMakeListsPrivate.txt
+cmake-build-*/ 
diff --git a/host/mock/include/README b/host/mock/include/README
new file mode 100644
index 0000000000000000000000000000000000000000..194dcd43252dcbeb2044ee38510415041a0e7b47
--- /dev/null
+++ b/host/mock/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/host/mock/platformio.ini b/host/mock/platformio.ini
new file mode 100644
index 0000000000000000000000000000000000000000..0ff4a4f14ee0965865eb3ca282fa9234b346d248
--- /dev/null
+++ b/host/mock/platformio.ini
@@ -0,0 +1,17 @@
+; PlatformIO Project Configuration File
+;
+;   Build options: build flags, source filter
+;   Upload options: custom upload port, speed and extra flags
+;   Library options: dependencies, extra library storages
+;   Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:esp32-c3-devkitm-1]
+platform = espressif32
+board = esp32-c3-devkitm-1
+framework = arduino
+lib_deps =
+    bblanchon/ArduinoJson@^6.19.4
+    fbiego/ESP32Time@^2.0.0
diff --git a/host/mock/src/main.cpp b/host/mock/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..268d8f7f1e4204500ca060584f659551b63a3e33
--- /dev/null
+++ b/host/mock/src/main.cpp
@@ -0,0 +1,113 @@
+#include "ESP32Time.h"
+#include <Arduino.h>
+#include <ArduinoJson.h>
+#include <WiFi.h>
+#include <esp_log.h>
+#include <esp_now.h>
+
+static const std::string TAG = "MAIN";
+static const std::string TAG_ESPNOW = "ESPNOW";
+static const std::string TAG_GSM = "GSM";
+
+ESP32Time rtc;
+TaskHandle_t ESPNOWTask;
+
+void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status)
+{
+	// go to sleep
+}
+
+String getMacAddressAsString(const uint8_t *mac);
+DynamicJsonDocument parseReceivedJsonData(char *data);
+
+void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len)
+{
+	esp_log_write(ESP_LOG_INFO, TAG_ESPNOW.c_str(), "Message recieved\n");
+	// copy received data to a char array
+	char data[len];
+	memcpy(data, incomingData, len);
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Raw received Data: %s\n", data);
+
+	DynamicJsonDocument doc = parseReceivedJsonData(data);
+
+	String macAddress = getMacAddressAsString(mac);
+
+	// add timestamp and mac address
+	doc["timestamp"] = rtc.getEpoch();
+	doc["clientMac"] = macAddress;
+
+	// serialize json document again
+	std::string dataString{};
+	serializeJson(doc, dataString);
+}
+
+DynamicJsonDocument parseReceivedJsonData(char *data)
+{
+	DynamicJsonDocument doc(250);
+	auto error = deserializeJson(doc, data);
+	if (error) {
+		esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW.c_str(), "Error while parsing json: %s\n", error.f_str());
+		// TODO error handling
+	}
+	return doc;
+}
+String getMacAddressAsString(const uint8_t *mac)
+{
+	String macAddress;
+	for (int i = 0; i < 6; i++) {
+		macAddress += String(mac[i], HEX);
+	}
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "MAC: %s\n", macAddress.c_str());
+	return macAddress;
+}
+
+[[noreturn]] void ESPNOWReceiveTask(void *parameter)
+{
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "ESPNOWReceiveTask started on core %d\n", xPortGetCoreID());
+
+	WiFi.mode(WIFI_STA);
+
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow...\n");
+
+	if (esp_now_init() != ESP_OK) {
+		// initialization failed
+		esp_log_write(ESP_LOG_ERROR, TAG_ESPNOW.c_str(), "Initialising ESPNow FAILED\n");
+		exit(ESP_FAIL);
+	}
+
+	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow SUCCESS\n");
+
+	esp_now_register_recv_cb(on_data_recv);
+
+	while (true) {
+	}
+}
+
+void setup()
+{
+	// Set console baud rate
+	Serial.begin(115200);
+	delay(10);
+
+	//	https://stackoverflow.com/questions/60442350/arduinos-esp-log-set-vprintf-does-not-work-on-esp32
+	esp_log_level_set("*", ESP_LOG_VERBOSE);
+	esp_log_write(ESP_LOG_DEBUG, TAG.c_str(), "%s", WiFi.macAddress().c_str());
+
+	delay(1000);
+
+	// create ESPNOWReceiveTask. TODO: Until the UTC time is not synced, this will not add the correct time. If we
+	// TODO: create the task after the time is synced, no messages will be received until synchronization is done
+	xTaskCreatePinnedToCore(ESPNOWReceiveTask,   /* Function to implement the task */
+	                        "ESPNOWReceiveTask", /* Name of the task */
+	                        10000,               /* Stack size in words */
+	                        nullptr,             /* Task input parameter */
+	                        0,                   /* Priority of the task */
+	                        &ESPNOWTask,         /* Task handle. */
+	                        0);                  /* Core where the task should run */
+
+	// Restart takes quite some time
+	// To skip it, call init() instead of restart()
+	esp_log_write(ESP_LOG_DEBUG, TAG_GSM.c_str(), "Initializing modem...\n");
+}
+
+void loop() {}
diff --git a/host/mock/test/README b/host/mock/test/README
new file mode 100644
index 0000000000000000000000000000000000000000..9b1e87bc67c90e7f09a92a3e855444b085c655a6
--- /dev/null
+++ b/host/mock/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