From 38965ef1e1f31a6e53c0f64738ab22b455e67815 Mon Sep 17 00:00:00 2001
From: Zoe Pfister <zoe.pfister@student.uibk.ac.at>
Date: Thu, 19 Jan 2023 13:54:10 +0100
Subject: [PATCH] Resend Data capabilities

---
 .../lib/ResendManager/ResendManager.cpp       |  72 ++
 .../lib/ResendManager/ResendManager.h         |  35 +
 .../lib/ResendManager/ResendPointType.h       |  15 +
 .../lib/Utilities/Definitions.h               |  28 +
 .../lib/Utilities/SDCardException.h           |  22 +
 .../lib/Utilities/SDSetupException.h          |  21 +
 .../lib/Utilities/Utilities.cpp               | 151 ++++
 .../lib/Utilities/Utilities.h                 |  25 +
 host/host_central_mast/src/main.cpp           | 838 ++++++++----------
 9 files changed, 739 insertions(+), 468 deletions(-)
 create mode 100644 host/host_central_mast/lib/ResendManager/ResendManager.cpp
 create mode 100644 host/host_central_mast/lib/ResendManager/ResendManager.h
 create mode 100644 host/host_central_mast/lib/ResendManager/ResendPointType.h
 create mode 100644 host/host_central_mast/lib/Utilities/Definitions.h
 create mode 100644 host/host_central_mast/lib/Utilities/SDCardException.h
 create mode 100644 host/host_central_mast/lib/Utilities/SDSetupException.h
 create mode 100644 host/host_central_mast/lib/Utilities/Utilities.cpp
 create mode 100644 host/host_central_mast/lib/Utilities/Utilities.h

diff --git a/host/host_central_mast/lib/ResendManager/ResendManager.cpp b/host/host_central_mast/lib/ResendManager/ResendManager.cpp
new file mode 100644
index 0000000..1c8eb12
--- /dev/null
+++ b/host/host_central_mast/lib/ResendManager/ResendManager.cpp
@@ -0,0 +1,72 @@
+//
+// Created by cynthya on 1/5/23.
+//
+
+#include "ResendManager.h"
+#include "Utilities.h"
+
+void ResendManager::init() {
+    createResendDirectory();
+    // log
+    uint lastResendFileId = getLastResendFileId();
+    nextResendFileId = lastResendFileId + 1;
+    esp_log_write(ESP_LOG_INFO, "ResendManager", "nextResendFileId: %d\n", nextResendFileId);
+}
+
+uint ResendManager::getLastResendFileId() const { // get the next file id to be resend
+    auto filesInDirectory = getFilesInDirectory(resendDirectoryPath);
+    // convert the file names to uint
+    std::list<uint> fileUintIDs;
+
+    try {
+        for (const auto &fileName : filesInDirectory) {
+            fileUintIDs.emplace_back(std::stoul(fileName.c_str()));
+        }
+    } catch (std::invalid_argument &e) {
+        esp_log_write(ESP_LOG_ERROR, "getLastResendFileId", "Failed to convert file name to uint\n");
+        throw;
+    }
+    // get the max
+    uint max = 0;
+    for (const auto &fileID : fileUintIDs) {
+        if (fileID > max) {
+            max = fileID;
+        }
+    }
+
+    return max;
+}
+
+void ResendManager::createResendDirectory() const { // create directory if it doesn't exist
+    createDirectory("/resend");
+}
+
+void ResendManager::storeForResend(const String &messageToBeSend) {
+    // create file
+    String filename = String(nextResendFileId);
+    writeFile(messageToBeSend, resendDirectoryPath + "/" + filename);
+    ResendManager::incrementCount();
+}
+
+std::optional<ResendPointType> ResendManager::loadNextToBeResendMessage() {
+    // get first file in resend directory
+    auto filename = getFirstFileNameInDirectory(resendDirectoryPath.c_str());
+
+    if (filename.has_value()) {
+
+        // read file
+        auto message = readFile(resendDirectoryPath + "/" + filename.value().c_str());
+        return ResendPointType{message, filename.value()};
+    }
+    return std::nullopt;
+}
+
+void ResendManager::deleteResendMessage(const String &filename) {
+    auto filePath = resendDirectoryPath + "/" + filename;
+    if (SD.remove(filePath.c_str())) {
+        esp_log_write(ESP_LOG_INFO, "ResendManager", "Deleted file: %s\n", filePath.c_str());
+    } else {
+        esp_log_write(ESP_LOG_ERROR, "ResendManager", "Failed to delete file: %s\n", filePath.c_str());
+        throw;
+    }
+}
diff --git a/host/host_central_mast/lib/ResendManager/ResendManager.h b/host/host_central_mast/lib/ResendManager/ResendManager.h
new file mode 100644
index 0000000..5d7495a
--- /dev/null
+++ b/host/host_central_mast/lib/ResendManager/ResendManager.h
@@ -0,0 +1,35 @@
+//
+// Created by cynthya on 1/5/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_RESENDMANAGER_H
+#define HOST_CENTRAL_MAST_RESENDMANAGER_H
+
+#include "ResendPointType.h"
+#include "SD.h"
+#include "Utilities.h"
+#include <Arduino.h>
+#include <cstdio>
+
+class ResendManager {
+  public:
+    // File name (as uint) of the next file to be re-send (i.e. a counter of files to be resend). Max value is
+    // 4'294'967'295
+
+    void storeForResend(const String &messageToBeSend);
+    // I am making this an optional since i want to avoid creating a 'hasNextToBeResend' method since that would require
+    // another fs operation. If this method returns std::nullopt, it means that there is no file to be resend.
+    std::optional<ResendPointType> loadNextToBeResendMessage();
+    void deleteResendMessage(const String &filename);
+
+    void init();
+
+  private:
+    const String resendDirectoryPath = "/resend";
+    uint nextResendFileId = 0;
+    void incrementCount() { nextResendFileId++; }
+    void createResendDirectory() const;
+    uint getLastResendFileId() const;
+};
+
+#endif // HOST_CENTRAL_MAST_RESENDMANAGER_H
diff --git a/host/host_central_mast/lib/ResendManager/ResendPointType.h b/host/host_central_mast/lib/ResendManager/ResendPointType.h
new file mode 100644
index 0000000..11a4bfc
--- /dev/null
+++ b/host/host_central_mast/lib/ResendManager/ResendPointType.h
@@ -0,0 +1,15 @@
+//
+// Created by cynthya on 1/5/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
+#define HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
+
+#include <Arduino.h>
+
+struct ResendPointType {
+	String message;
+	String filename;
+};
+
+#endif // HOST_CENTRAL_MAST_RESENDPOINTTYPE_H
diff --git a/host/host_central_mast/lib/Utilities/Definitions.h b/host/host_central_mast/lib/Utilities/Definitions.h
new file mode 100644
index 0000000..ed28c03
--- /dev/null
+++ b/host/host_central_mast/lib/Utilities/Definitions.h
@@ -0,0 +1,28 @@
+//
+// Created by zoe on 1/12/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_DEFINITIONS_H
+#define HOST_CENTRAL_MAST_DEFINITIONS_H
+
+#include "Arduino.h"
+
+#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
+
+const String INFLUXDB_TOKEN =
+    "dUh2gbVLv7e3egqocxriDsJQNUacA9qZ5YXsYtdnVAglnHgy4nx-jDVO7nGlSF34BosfnuwnUDaviC7dQeC5RQ==";
+
+#endif // HOST_CENTRAL_MAST_DEFINITIONS_H
diff --git a/host/host_central_mast/lib/Utilities/SDCardException.h b/host/host_central_mast/lib/Utilities/SDCardException.h
new file mode 100644
index 0000000..039d703
--- /dev/null
+++ b/host/host_central_mast/lib/Utilities/SDCardException.h
@@ -0,0 +1,22 @@
+//
+// Created by zoe on 1/12/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
+#define HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
+
+#include <Arduino.h>
+#include <exception>
+
+// create a custom exception type called SD Card Exception
+
+class SDCardException : public std::exception {
+  public:
+    SDCardException(const String &message) : message(message) {}
+    const char *what() const noexcept override { return message.c_str(); }
+
+  private:
+    String message;
+};
+
+#endif // HOST_CENTRAL_MAST_SDCARDEXCEPTION_H
diff --git a/host/host_central_mast/lib/Utilities/SDSetupException.h b/host/host_central_mast/lib/Utilities/SDSetupException.h
new file mode 100644
index 0000000..09c1ed3
--- /dev/null
+++ b/host/host_central_mast/lib/Utilities/SDSetupException.h
@@ -0,0 +1,21 @@
+//
+// Created by zoe on 1/12/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
+#define HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
+
+#include <Arduino.h>
+#include <exception>
+// create a custom exception type called SD Setup Exception
+
+class SDSetupException : public std::exception {
+  public:
+    SDSetupException(const String &message) : message(message) {}
+    const char *what() const noexcept override { return message.c_str(); }
+
+  private:
+    String message;
+};
+
+#endif // HOST_CENTRAL_MAST_SDSETUPEXCEPTION_H
diff --git a/host/host_central_mast/lib/Utilities/Utilities.cpp b/host/host_central_mast/lib/Utilities/Utilities.cpp
new file mode 100644
index 0000000..21f3aca
--- /dev/null
+++ b/host/host_central_mast/lib/Utilities/Utilities.cpp
@@ -0,0 +1,151 @@
+//
+// Created by zoe on 1/9/23.
+//
+
+#include "Utilities.h"
+
+void setupSDCard();
+void saveStringToSDCard(const std::string &dataString);
+std::list<String> getFilesInDirectory(const String &dirname) {
+    std::list<String> files;
+    File dir = openDirectory(dirname);
+    while (true) {
+        File nextFile = dir.openNextFile();
+        if (!nextFile) {
+            break;
+        }
+        if (!nextFile.isDirectory()) {
+            files.emplace_back(nextFile.name());
+        }
+        nextFile.close();
+    }
+    return files;
+}
+
+std::optional<String> getLastFileInDirectory(const String &dirname) {
+
+    File root = openDirectory(dirname);
+    root.rewindDirectory();
+
+    File file = root.openNextFile();
+    while (file) {
+        File nextFile = root.openNextFile();
+        if (!nextFile) {
+            break;
+        }
+        file = nextFile;
+    }
+    // log
+    if (file) {
+        esp_log_write(ESP_LOG_INFO, "getLastFileInDirectory", "Last file name: %s\n", file.name());
+        return file.name();
+    } else {
+        esp_log_write(ESP_LOG_INFO, "getLastFileInDirectory", "No file found\n");
+        return std::nullopt;
+    }
+}
+File openDirectory(const String &dirname) {
+    File root = SD.open(dirname);
+    if (!root) {
+        esp_log_write(ESP_LOG_ERROR, "openDirectory", "Failed to open directory\n");
+        throw;
+    }
+    if (!root.isDirectory()) {
+        esp_log_write(ESP_LOG_ERROR, "openDirectory", "Not a directory\n");
+        throw;
+    }
+    return root;
+}
+std::optional<String> getFirstFileNameInDirectory(const String &dirname) {
+
+    File root = openDirectory(dirname);
+    root.rewindDirectory();
+
+    File file = root.openNextFile();
+    if (file) {
+        esp_log_write(ESP_LOG_INFO, "getFirstFileNameInDirectory", "file found: %s\n", file.name());
+        return file.name();
+    } else {
+        esp_log_write(ESP_LOG_INFO, "getFirstFileNameInDirectory", "no file found\n");
+        return std::nullopt;
+    }
+}
+
+File openForWrite(const String &filePath) {
+    File file = SD.open(filePath, FILE_WRITE);
+    if (!file) {
+        esp_log_write(ESP_LOG_ERROR, "SD", "Failed to open file for writing\n");
+        throw;
+    }
+    return file;
+}
+
+File openForRead(const String &filePath) {
+    File file = SD.open(filePath, FILE_READ);
+    if (!file) {
+        esp_log_write(ESP_LOG_ERROR, "SD", "Failed to open file for reading\n");
+        throw;
+    }
+    return file;
+}
+
+void writeFile(const String &messageToBeSend, const String &filePath) {
+    File file = openForWrite(filePath);
+    if (file.print(messageToBeSend)) {
+        esp_log_write(ESP_LOG_INFO, "SD", "File written %s\n", filePath.c_str());
+    } else {
+        esp_log_write(ESP_LOG_ERROR, "SD", "Write failed %s\n", filePath.c_str());
+        throw;
+    }
+    file.close();
+}
+String readFile(const String &filePath) {
+    File file = openForRead(filePath);
+
+    String ret;
+
+    while (file.available()) {
+        ret += (char)file.read();
+    }
+
+    file.close();
+    return ret;
+}
+
+void createDirectory(const String &dirname) {
+    if (!SD.exists(dirname)) {
+        SD.mkdir(dirname);
+        esp_log_write(ESP_LOG_INFO, "createDirectory", "Created directory: %s\n", dirname.c_str());
+    } else {
+        esp_log_write(ESP_LOG_WARN, "createDirectory", "Directory already exists\n");
+    }
+}
+
+void setupSDCard(int MISO, int MOSI, int SCLK, int CS) {
+    SPI.begin(SCLK, MISO, MOSI, CS);
+    if (!SD.begin(CS)) {
+        esp_log_write(ESP_LOG_ERROR, "Utilities", "Card MOUNT FAIL\n");
+        throw SDSetupException("Card MOUNT FAIL");
+    } else {
+        uint32_t cardSize = SD.cardSize() / (1024 * 1024);
+        String sdcardSizeString = "SDCard Size: " + String(cardSize) + "MB";
+        esp_log_write(ESP_LOG_DEBUG, "Utilities", "%s\n", sdcardSizeString.c_str());
+    }
+}
+
+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, "Utilities", "error opening datalog.txt\n");
+        throw SDCardException("error opening datalog.txt");
+    }
+}
\ No newline at end of file
diff --git a/host/host_central_mast/lib/Utilities/Utilities.h b/host/host_central_mast/lib/Utilities/Utilities.h
new file mode 100644
index 0000000..1156c02
--- /dev/null
+++ b/host/host_central_mast/lib/Utilities/Utilities.h
@@ -0,0 +1,25 @@
+//
+// Created by zoe on 1/9/23.
+//
+
+#ifndef HOST_CENTRAL_MAST_UTILITIES_H
+#define HOST_CENTRAL_MAST_UTILITIES_H
+
+#include "SD.h"
+#include "SDCardException.h"
+#include "SDSetupException.h"
+#include <Arduino.h>
+#include <Definitions.h>
+#include <WString.h>
+#include <list>
+
+File openDirectory(const String &dirname);
+std::list<String> getFilesInDirectory(const String &dirname);
+std::optional<String> getFirstFileNameInDirectory(const String &dirname);
+std::optional<String> getLastFileInDirectory(const String &dirname);
+void writeFile(const String &messageToBeSend, const String &filePath);
+String readFile(const String &filePath);
+void createDirectory(const String &dirname);
+void setupSDCard(int MISO, int MOSI, int SCLK, int CS);
+void saveStringToSDCard(const std::string &dataString);
+#endif // HOST_CENTRAL_MAST_UTILITIES_H
diff --git a/host/host_central_mast/src/main.cpp b/host/host_central_mast/src/main.cpp
index 9a56051..850beac 100644
--- a/host/host_central_mast/src/main.cpp
+++ b/host/host_central_mast/src/main.cpp
@@ -1,6 +1,7 @@
 #include "FS.h"
 #include "SD.h"
 #include "SPI.h"
+#include "Utilities.h"
 #include "time.h"
 #include <Arduino.h>
 #include <ArduinoJson.h>
@@ -46,32 +47,16 @@ TinyGsm modem(debugger);
 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)
+#include "Definitions.h"
 
-#define UART_BAUD 115200
-#define PIN_DTR 25
-#define PIN_TX 27
-#define PIN_RX 26
-#define PWR_PIN 4
+enum MessageType { dataAck, hostChange };
+typedef struct response {
+    MessageType type;
+    uint8_t mac[6];
+    long time;
+} response;
 
-#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};
+uint8_t BROADCAST_MAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 esp_now_peer_info_t broadcast = {};
 response announce = {};
 
@@ -83,483 +68,400 @@ 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
+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;
+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)
-{
-	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\n" : "Failed to respond\n");
-		
-	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, sizeof(uint8_t) * 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\n" : "Failed to respond\n");
-}
+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, sizeof(uint8_t) * 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);
 
-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;
+    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\n" : "Failed to respond\n");
 }
-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
-	}
+
+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;
 }
-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;
+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;
+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());
+[[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);
+    WiFi.mode(WIFI_STA);
 
-	esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow...\n");
+    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);
-	}
+    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_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Initialising ESPNow SUCCESS\n");
 
-	esp_now_register_recv_cb(on_data_recv);
+    esp_now_register_recv_cb(on_data_recv);
 
-	while (true) {
-	}
+    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;
-}
+time_t timeToUnixEpochSeconds(const std::string &time) {
+    //	22/10/27,10:16:20+00
+    struct tm tm {};
+    time_t dateInEpoch = 0;
 
-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();
-
-	broadcast.channel = 0;
-	broadcast.encrypt = false;
-	memcpy(&broadcast.peer_addr, &BROADCAST_MAC, sizeof(BROADCAST_MAC));
-	if(esp_now_add_peer(&broadcast) != ESP_OK){
-		esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to add Broadcast Host");
-	}
-
-	announce.type = hostChange;
-	esp_read_mac(announce.mac, ESP_MAC_WIFI_STA);
-	announce.time = rtc.getEpoch();
-	if(esp_now_send(BROADCAST_MAC, (uint8_t *) &announce, sizeof(announce)) != ESP_OK){
-		esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to announce mac");
-	}
-	else{
-		esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Mac announced!");
-	}
-}
-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());
-	}
-}
+    if (strptime(time.c_str(), "%y/%m/%d,%T+00", &tm)) {
+        time_t curTime;
+        struct tm *timeinfo;
+
+        timeinfo = localtime(&curTime);
 
-// I don't think this does anything. Copied from the example
-void turnOffLEDs()
-{ // Set LED OFF
-	pinMode(LED_PIN, OUTPUT);
-	digitalWrite(LED_PIN, HIGH);
+        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;
 
-	pinMode(PWR_PIN, OUTPUT);
-	digitalWrite(PWR_PIN, HIGH);
-	delay(300);
-	digitalWrite(PWR_PIN, LOW);
+        dateInEpoch = mktime(timeinfo);
+    }
+    return dateInEpoch;
 }
 
-const String INFLUXDB_TOKEN =
-    "dUh2gbVLv7e3egqocxriDsJQNUacA9qZ5YXsYtdnVAglnHgy4nx-jDVO7nGlSF34BosfnuwnUDaviC7dQeC5RQ==";
+void setup() {
+    // Set console baud rate
+    Serial.begin(115200);
+    delay(10);
+    setupSDCard(SD_MISO, SD_MOSI, SD_SCLK, SD_CS);
+
+    //	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());
+
+    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();
+
+    broadcast.channel = 0;
+    broadcast.encrypt = false;
+    memcpy(&broadcast.peer_addr, &BROADCAST_MAC, sizeof(BROADCAST_MAC));
+    if (esp_now_add_peer(&broadcast) != ESP_OK) {
+        esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to add Broadcast Host");
+    }
+
+    announce.type = hostChange;
+    esp_read_mac(announce.mac, ESP_MAC_WIFI_STA);
+    announce.time = rtc.getEpoch();
+    if (esp_now_send(BROADCAST_MAC, (uint8_t *)&announce, sizeof(announce)) != ESP_OK) {
+        esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to announce mac");
+    } else {
+        esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Mac announced!");
+    }
+}
+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());
+}
 
 struct RequestInformation {
-	String method;
-	String host;
-	String path;
-	String body;
+    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;
+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");
-	}
-
-	announce.time = rtc.getEpoch();
-	if(esp_now_send(BROADCAST_MAC, (uint8_t *) &announce, sizeof(announce)) != ESP_OK){
-		esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to announce mac\n");
-	}
-	else{
-		esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Mac announced!\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);
+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");
+    }
+
+    announce.time = rtc.getEpoch();
+    if (esp_now_send(BROADCAST_MAC, (uint8_t *)&announce, sizeof(announce)) != ESP_OK) {
+        esp_log_write(ESP_LOG_WARN, TAG_ESPNOW.c_str(), "Failed to announce mac\n");
+    } else {
+        esp_log_write(ESP_LOG_DEBUG, TAG_ESPNOW.c_str(), "Mac announced!\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");
+    }
+    delay(1000);
 }
-- 
GitLab