diff --git a/host/esp-t-sim7000g/platformio.ini b/host/esp-t-sim7000g/platformio.ini index a0e06547137fd772a6c2b2e61ba30fdef542e09d..e73dc1b69765f4c69684d23118762f672b8c00b6 100644 --- a/host/esp-t-sim7000g/platformio.ini +++ b/host/esp-t-sim7000g/platformio.ini @@ -15,6 +15,10 @@ framework = arduino monitor_speed = 115200 monitor_port = /dev/ttyACM0 upload_port = /dev/ttyACM0 +build_flags = + -DCORE_DEBUG_LEVEL=5 + -std=gnu++17 +build_unflags = -std=gnu++11 lib_deps = vshymanskyy/TinyGSM@^0.11.5 vshymanskyy/StreamDebugger@^1.0.1 diff --git a/host/esp-t-sim7000g/src/main.cpp b/host/esp-t-sim7000g/src/main.cpp index 06a9655e012ebe594581a7dd01f48a43408711a5..49f58a464dcc95148c7608a559a1fafff0c87a7a 100644 --- a/host/esp-t-sim7000g/src/main.cpp +++ b/host/esp-t-sim7000g/src/main.cpp @@ -6,112 +6,14 @@ #include <ArduinoJson.h> #include <ESP32Time.h> #include <WiFi.h> +#include <esp_log.h> #include <esp_now.h> #include <queue> #include <sys/unistd.h> -ESP32Time rtc; - -#define RXD2 18 -#define TXD2 19 - -const char *ntpServer = "pool.ntp.org"; -const long gmtOffset_sec = 0; -const int daylightOffset_sec = 0; - -SemaphoreHandle_t xMutex; - -TaskHandle_t Task1; - -static std::queue<String> queue; -const int wakeUpPin = 4; - -// SoftwareSerial mySerial(RXD2, TXD2); - -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"); - String macAddress; - for (int i = 0; i < 6; i++) { - Serial.print(mac[i], HEX); - macAddress += String(mac[i], HEX); - Serial.print(":"); - } - Serial.println(); - char data[len]; - memcpy(data, incomingData, len); - - DynamicJsonDocument doc(250); - auto error = deserializeJson(doc, data); - if (error) { - Serial.print(F("deserializeJson() failed: ")); - Serial.println(error.f_str()); - return; - } - doc["timestamp"] = rtc.getEpoch(); - doc["clientMac"] = macAddress; - serializeJson(doc, Serial); - Serial.println(); - - std::string dataString{}; - serializeJson(doc, 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(); - // 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"); - } - 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; - Serial.println(lineData); - - xSemaphoreTake(xMutex, portMAX_DELAY); - queue.push(lineData); - xSemaphoreGive(xMutex); -} - -[[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"); - return; // not sure about this - } - Serial.println("ESPNow init success"); - - esp_now_register_recv_cb(on_data_recv); - - while (true) { - } -} +static const std::string TAG = "MAIN"; +static const std::string TAG_ESPNOW = "ESPNOW"; +static const std::string TAG_GSM = "GSM"; /* FILE: AllFunctions.ino @@ -124,14 +26,7 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) #define SerialAT Serial1 // See all AT commands, if wanted -#define DUMP_AT_COMMANDS - -/* - Tests enabled -*/ -#define TINY_GSM_TEST_GPRS true -#define TINY_GSM_TEST_GPS false -#define TINY_GSM_POWERDOWN true +// #define DUMP_AT_COMMANDS // set GSM PIN, if any #define GSM_PIN "" @@ -141,9 +36,6 @@ const char apn[] = "m2m.public.at"; // SET TO YOUR APN const char gprsUser[] = ""; const char gprsPass[] = ""; -#include <SD.h> -#include <SPI.h> -#include <Ticker.h> #include <TinyGsmClient.h> #ifdef DUMP_AT_COMMANDS // if enabled it requires the streamDebugger lib @@ -169,63 +61,134 @@ TinyGsm modem(SerialAT); #define SD_CS 13 #define LED_PIN 12 -int counter, lastIndex, numberOfPieces = 24; -String pieces[24], input; +ESP32Time rtc; -void setup() +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) { - // Set console baud rate - Serial.begin(115200); - delay(10); + // go to sleep +} - rtc.setTime(1666873212); - // Set LED OFF - pinMode(LED_PIN, OUTPUT); - digitalWrite(LED_PIN, HIGH); +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_LOGD(TAG_ESPNOW.c_str(), "Message recieved"); + // copy received data to a char array + char data[len]; + memcpy(data, incomingData, len); + ESP_LOGD(TAG_ESPNOW.c_str(), "Raw received Data: %s", data); - pinMode(PWR_PIN, OUTPUT); - digitalWrite(PWR_PIN, HIGH); - delay(300); - digitalWrite(PWR_PIN, LOW); + DynamicJsonDocument doc = parseReceivedJsonData(data); - SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS); - if (!SD.begin(SD_CS)) { - Serial.println("SDCard MOUNT FAIL"); - } else { - uint32_t cardSize = SD.cardSize() / (1024 * 1024); - String str = "SDCard Size: " + String(cardSize) + "MB"; - Serial.println(str); - } + String macAddress = getMacAddressAsString(mac); - xMutex = xSemaphoreCreateMutex(); + // add timestamp and mac address + doc["timestamp"] = rtc.getEpoch(); + doc["clientMac"] = macAddress; - Serial.println("\nWait..."); + // serialize json document again + std::string dataString{}; + serializeJson(doc, dataString); - delay(1000); + saveStringToSDCard(dataString); - SerialAT.begin(UART_BAUD, SERIAL_8N1, PIN_RX, PIN_TX); + String lineData = documentToLineProtocolString(doc); - // Restart takes quite some time - // To skip it, call init() instead of restart() - Serial.println("Initializing modem..."); - if (!modem.restart()) { - Serial.println("Failed to restart modem, attempting to continue without restarting"); + ESP_LOGD(TAG_ESPNOW.c_str(), "Line protocol data: %s", lineData.c_str()); + + xSemaphoreTake(xMutex, portMAX_DELAY); + queue.push(lineData); + xSemaphoreGive(xMutex); +} + +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_LOGE(TAG.c_str(), "error opening datalog.txt"); + // TODO: Error handling + } +} +DynamicJsonDocument parseReceivedJsonData(char *data) +{ + DynamicJsonDocument doc(250); + auto error = deserializeJson(doc, data); + if (error) { + ESP_LOGE(TAG_ESPNOW.c_str(), "Error while parsing json: %s", 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_LOGD(TAG_ESPNOW.c_str(), "MAC: %s", macAddress.c_str()); + return macAddress; +} + +[[noreturn]] void ESPNOWReceiveTask(void *parameter) +{ + ESP_LOGD(TAG_ESPNOW.c_str(), "ESPNOWReceiveTask started on core %d", xPortGetCoreID()); + + WiFi.mode(WIFI_STA); + + ESP_LOGD(TAG_ESPNOW.c_str(), "Initialising ESPNow..."); + + if (esp_now_init() != ESP_OK) { + // initialization failed + ESP_LOGE(TAG_ESPNOW.c_str(), "Initialising ESPNow FAILED"); + exit(ESP_FAIL); } - // create task1 - 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_LOGD(TAG_ESPNOW.c_str(), "Initialising ESPNow SUCCESS"); + + 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; + struct tm tm {}; time_t dateInEpoch = 0; if (strptime(time.c_str(), "%y/%m/%d,%T+00", &tm)) { @@ -247,23 +210,95 @@ time_t timeToUnixEpochSeconds(const std::string &time) return dateInEpoch; } +void setup() +{ + // Set console baud rate + Serial.begin(115200); + delay(10); + + ESP_LOGD(TAG.c_str(), "%s", WiFi.macAddress()); + + turnOffLEDs(); + + setupSDCard(); + + 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_LOGD(TAG_GSM.c_str(), "Initializing modem..."); + if (!modem.restart()) { + ESP_LOGW(TAG_GSM.c_str(), "Failed to restart modem, attempting to continue without restarting"); + } + + syncUTCTimeToRTC(); +} +void syncUTCTimeToRTC() +{ + ESP_LOGD(TAG_GSM.c_str(), "NTP Server Syncing..."); + modem.NTPServerSync("pool.ntp.org", 0); + auto gsmDateTimeString = modem.getGSMDateTime(DATE_FULL); + ESP_LOGD(TAG_GSM.c_str(), "GSM DateTime: %s", gsmDateTimeString.c_str()); + time_t time = timeToUnixEpochSeconds(gsmDateTimeString.c_str()); + rtc.setTime(time); + ESP_LOGI(TAG_GSM.c_str(), "Time set to EPOCH: %s", String(rtc.getEpoch())); +} +void setupSDCard() +{ + SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS); + if (!SD.begin(SD_CS)) { + ESP_LOGE(TAG.c_str(), "Card MOUNT FAIL"); + // TODO: Error handling + } else { + uint32_t cardSize = SD.cardSize() / (1024 * 1024); + String sdcardSizeString = "SDCard Size: " + String(cardSize) + "MB"; + ESP_LOGD(TAG.c_str(), "%s", 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); +} + void loop() { // Restart takes quite some time // To skip it, call init() instead of restart() - Serial.println("Initializing modem..."); + ESP_LOGD(TAG.c_str(), "Initializing modem..."); if (!modem.init()) { - Serial.println("Failed to restart modem, attempting to continue without restarting"); + ESP_LOGD(TAG.c_str(), "Failed to restart modem, attempting to continue without restarting"); } String name = modem.getModemName(); delay(500); - Serial.println("Modem Name: " + name); + ESP_LOGD(TAG.c_str(), "Modem Name %s", name); String modemInfo = modem.getModemInfo(); delay(500); - Serial.println("Modem Info: " + modemInfo); + ESP_LOGD(TAG.c_str(), "Modem Info: %s", modemInfo); // Set SIM7000G GPIO4 LOW ,turn off GPS power // CMD:AT+SGPIO=0,4,1,0 @@ -325,34 +360,28 @@ void loop() // modem.disableGPS(); delay(200); - Serial.println(modem.getSignalQuality()); + ESP_LOGD(TAG.c_str(), "%s", String(modem.getSignalQuality())); delay(200); - Serial.println("Trying to connect to network"); + ESP_LOGD(TAG.c_str(), "Trying to connect to network"); modem.gprsConnect(apn, gprsUser, gprsPass); delay(200); - modem.NTPServerSync("pool.ntp.org", 0); - auto test = modem.getGSMDateTime(DATE_FULL); - Serial.println(test); - delay(200); - time_t time = timeToUnixEpochSeconds(test.c_str()); - Serial.println(time); - rtc.setTime(time); + syncUTCTimeToRTC(); - Serial.println("Waiting for network..."); + ESP_LOGD(TAG.c_str(), "Waiting for network..."); if (!modem.isNetworkConnected()) { - Serial.println("Network not connected"); + ESP_LOGD(TAG.c_str(), "Network not connected"); return; } else { - Serial.println("Network connected"); + ESP_LOGD(TAG.c_str(), "Network connected"); delay(200); // quality - Serial.println(modem.getSignalQuality()); + ESP_LOGD(TAG.c_str(), "%s", String(modem.getSignalQuality())); // 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 "); - Serial.println(url); + ESP_LOGD(TAG.c_str(), "%s", url); // Use WiFiClient class to create TCP connections while (!queue.empty()) { @@ -360,7 +389,7 @@ void loop() TinyGsmClient client{modem}; const int httpPort = 80; if (!client.connect(url.c_str(), httpPort)) { - Serial.println("connection failed"); + ESP_LOGD(TAG.c_str(), "connection failed"); return; } @@ -391,7 +420,7 @@ void loop() while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { - Serial.println("headers received"); + ESP_LOGD(TAG.c_str(), "headers received"); break; } } @@ -409,15 +438,8 @@ void loop() // DBG("+CPOWD=1"); // } // modem.poweroff(); - Serial.println("Poweroff."); + ESP_LOGD(TAG.c_str(), "Poweroff."); #endif - // esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); delay(1000); - // esp_deep_sleep_start(); - - // Do nothing forevermore - // while (true) { - // modem.maintain(); - // } }