Skip to content
Snippets Groups Projects
Verified Commit 08edd213 authored by Zoe Michaela Dietmar Pfister's avatar Zoe Michaela Dietmar Pfister :gay_pride_flag:
Browse files

WIP: Refactor

parent b7494847
No related branches found
No related tags found
4 merge requests!39Merge Develop into Main,!19development into master,!17Inital Host, initial Client,!14Merge gsm host into development
...@@ -15,6 +15,10 @@ framework = arduino ...@@ -15,6 +15,10 @@ framework = arduino
monitor_speed = 115200 monitor_speed = 115200
monitor_port = /dev/ttyACM0 monitor_port = /dev/ttyACM0
upload_port = /dev/ttyACM0 upload_port = /dev/ttyACM0
build_flags =
-DCORE_DEBUG_LEVEL=5
-std=gnu++17
build_unflags = -std=gnu++11
lib_deps = lib_deps =
vshymanskyy/TinyGSM@^0.11.5 vshymanskyy/TinyGSM@^0.11.5
vshymanskyy/StreamDebugger@^1.0.1 vshymanskyy/StreamDebugger@^1.0.1
......
...@@ -6,112 +6,14 @@ ...@@ -6,112 +6,14 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <ESP32Time.h> #include <ESP32Time.h>
#include <WiFi.h> #include <WiFi.h>
#include <esp_log.h>
#include <esp_now.h> #include <esp_now.h>
#include <queue> #include <queue>
#include <sys/unistd.h> #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>(); static const std::string TAG = "MAIN";
String sensorName = doc["sensorName"].as<String>(); static const std::string TAG_ESPNOW = "ESPNOW";
String timestamp = doc["timestamp"].as<String>(); static const std::string TAG_GSM = "GSM";
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) {
}
}
/* /*
FILE: AllFunctions.ino FILE: AllFunctions.ino
...@@ -124,14 +26,7 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len) ...@@ -124,14 +26,7 @@ void on_data_recv(const uint8_t *mac, const uint8_t *incomingData, int len)
#define SerialAT Serial1 #define SerialAT Serial1
// See all AT commands, if wanted // See all AT commands, if wanted
#define DUMP_AT_COMMANDS // #define DUMP_AT_COMMANDS
/*
Tests enabled
*/
#define TINY_GSM_TEST_GPRS true
#define TINY_GSM_TEST_GPS false
#define TINY_GSM_POWERDOWN true
// set GSM PIN, if any // set GSM PIN, if any
#define GSM_PIN "" #define GSM_PIN ""
...@@ -141,9 +36,6 @@ const char apn[] = "m2m.public.at"; // SET TO YOUR APN ...@@ -141,9 +36,6 @@ const char apn[] = "m2m.public.at"; // SET TO YOUR APN
const char gprsUser[] = ""; const char gprsUser[] = "";
const char gprsPass[] = ""; const char gprsPass[] = "";
#include <SD.h>
#include <SPI.h>
#include <Ticker.h>
#include <TinyGsmClient.h> #include <TinyGsmClient.h>
#ifdef DUMP_AT_COMMANDS // if enabled it requires the streamDebugger lib #ifdef DUMP_AT_COMMANDS // if enabled it requires the streamDebugger lib
...@@ -169,63 +61,134 @@ TinyGsm modem(SerialAT); ...@@ -169,63 +61,134 @@ TinyGsm modem(SerialAT);
#define SD_CS 13 #define SD_CS 13
#define LED_PIN 12 #define LED_PIN 12
int counter, lastIndex, numberOfPieces = 24; ESP32Time rtc;
String pieces[24], input;
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 // go to sleep
Serial.begin(115200); }
delay(10);
rtc.setTime(1666873212); String getMacAddressAsString(const uint8_t *mac);
// Set LED OFF DynamicJsonDocument parseReceivedJsonData(char *data);
pinMode(LED_PIN, OUTPUT); void saveStringToSDCard(const std::string &dataString);
digitalWrite(LED_PIN, HIGH); 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); DynamicJsonDocument doc = parseReceivedJsonData(data);
digitalWrite(PWR_PIN, HIGH);
delay(300);
digitalWrite(PWR_PIN, LOW);
SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS); String macAddress = getMacAddressAsString(mac);
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);
}
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 ESP_LOGD(TAG_ESPNOW.c_str(), "Line protocol data: %s", lineData.c_str());
// To skip it, call init() instead of restart()
Serial.println("Initializing modem..."); xSemaphoreTake(xMutex, portMAX_DELAY);
if (!modem.restart()) { queue.push(lineData);
Serial.println("Failed to restart modem, attempting to continue without restarting"); 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 ESP_LOGD(TAG_ESPNOW.c_str(), "Initialising ESPNow SUCCESS");
xTaskCreatePinnedToCore(Task1code, /* Function to implement the task */
"Task1", /* Name of the task */ esp_now_register_recv_cb(on_data_recv);
10000, /* Stack size in words */
nullptr, /* Task input parameter */ while (true) {
0, /* Priority of the task */ }
&Task1, /* Task handle. */
0); /* Core where the task should run */
} }
time_t timeToUnixEpochSeconds(const std::string &time) time_t timeToUnixEpochSeconds(const std::string &time)
{ {
// 22/10/27,10:16:20+00 // 22/10/27,10:16:20+00
struct tm tm; struct tm tm {};
time_t dateInEpoch = 0; time_t dateInEpoch = 0;
if (strptime(time.c_str(), "%y/%m/%d,%T+00", &tm)) { if (strptime(time.c_str(), "%y/%m/%d,%T+00", &tm)) {
...@@ -247,23 +210,95 @@ time_t timeToUnixEpochSeconds(const std::string &time) ...@@ -247,23 +210,95 @@ time_t timeToUnixEpochSeconds(const std::string &time)
return dateInEpoch; 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() void loop()
{ {
// Restart takes quite some time // Restart takes quite some time
// To skip it, call init() instead of restart() // To skip it, call init() instead of restart()
Serial.println("Initializing modem..."); ESP_LOGD(TAG.c_str(), "Initializing modem...");
if (!modem.init()) { 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(); String name = modem.getModemName();
delay(500); delay(500);
Serial.println("Modem Name: " + name); ESP_LOGD(TAG.c_str(), "Modem Name %s", name);
String modemInfo = modem.getModemInfo(); String modemInfo = modem.getModemInfo();
delay(500); delay(500);
Serial.println("Modem Info: " + modemInfo); ESP_LOGD(TAG.c_str(), "Modem Info: %s", modemInfo);
// Set SIM7000G GPIO4 LOW ,turn off GPS power // Set SIM7000G GPIO4 LOW ,turn off GPS power
// CMD:AT+SGPIO=0,4,1,0 // CMD:AT+SGPIO=0,4,1,0
...@@ -325,34 +360,28 @@ void loop() ...@@ -325,34 +360,28 @@ void loop()
// modem.disableGPS(); // modem.disableGPS();
delay(200); delay(200);
Serial.println(modem.getSignalQuality()); ESP_LOGD(TAG.c_str(), "%s", String(modem.getSignalQuality()));
delay(200); delay(200);
Serial.println("Trying to connect to network"); ESP_LOGD(TAG.c_str(), "Trying to connect to network");
modem.gprsConnect(apn, gprsUser, gprsPass); modem.gprsConnect(apn, gprsUser, gprsPass);
delay(200); delay(200);
modem.NTPServerSync("pool.ntp.org", 0); syncUTCTimeToRTC();
auto test = modem.getGSMDateTime(DATE_FULL);
Serial.println(test);
delay(200);
time_t time = timeToUnixEpochSeconds(test.c_str());
Serial.println(time);
rtc.setTime(time);
Serial.println("Waiting for network..."); ESP_LOGD(TAG.c_str(), "Waiting for network...");
if (!modem.isNetworkConnected()) { if (!modem.isNetworkConnected()) {
Serial.println("Network not connected"); ESP_LOGD(TAG.c_str(), "Network not connected");
return; return;
} else { } else {
Serial.println("Network connected"); ESP_LOGD(TAG.c_str(), "Network connected");
delay(200); delay(200);
// quality // quality
Serial.println(modem.getSignalQuality()); ESP_LOGD(TAG.c_str(), "%s", String(modem.getSignalQuality()));
// make a http post request // make a http post request
String url = "influxdb.qe-forte.uibk.ac.at"; String url = "influxdb.qe-forte.uibk.ac.at";
String path = "/api/v2/write?org=QE&bucket=esp32test&precision=s"; String path = "/api/v2/write?org=QE&bucket=esp32test&precision=s";
Serial.print("Connecting to "); Serial.print("Connecting to ");
Serial.println(url); ESP_LOGD(TAG.c_str(), "%s", url);
// Use WiFiClient class to create TCP connections // Use WiFiClient class to create TCP connections
while (!queue.empty()) { while (!queue.empty()) {
...@@ -360,7 +389,7 @@ void loop() ...@@ -360,7 +389,7 @@ void loop()
TinyGsmClient client{modem}; TinyGsmClient client{modem};
const int httpPort = 80; const int httpPort = 80;
if (!client.connect(url.c_str(), httpPort)) { if (!client.connect(url.c_str(), httpPort)) {
Serial.println("connection failed"); ESP_LOGD(TAG.c_str(), "connection failed");
return; return;
} }
...@@ -391,7 +420,7 @@ void loop() ...@@ -391,7 +420,7 @@ void loop()
while (client.connected()) { while (client.connected()) {
String line = client.readStringUntil('\n'); String line = client.readStringUntil('\n');
if (line == "\r") { if (line == "\r") {
Serial.println("headers received"); ESP_LOGD(TAG.c_str(), "headers received");
break; break;
} }
} }
...@@ -409,15 +438,8 @@ void loop() ...@@ -409,15 +438,8 @@ void loop()
// DBG("+CPOWD=1"); // DBG("+CPOWD=1");
// } // }
// modem.poweroff(); // modem.poweroff();
Serial.println("Poweroff."); ESP_LOGD(TAG.c_str(), "Poweroff.");
#endif #endif
// esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
delay(1000); delay(1000);
// esp_deep_sleep_start();
// Do nothing forevermore
// while (true) {
// modem.maintain();
// }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment