Files
Hladinac/arduino/arduino.ino

246 lines
5.6 KiB
C++

#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <esp_sleep.h>
#else
#error "This sketch supports ESP8266 and ESP32 boards only."
#endif
const int PIN_COMMON_ELECTRODE = 13; // GPIO13 / D7
const int PIN_LEVEL1 = 5; // GPIO5 / D1 - najnizsia hladina
const int PIN_LEVEL2 = 4; // GPIO4 / D2
const int PIN_LEVEL3 = 14; // GPIO14 / D5
const int PIN_LEVEL4 = 12; // GPIO12 / D6 - najvyssia hladina
const int DEBUG = 1;
const char WIFI_SSID[] = "TP-Link_DD1E";
const char WIFI_PASS[] = "33784120";
const unsigned long SLEEP_TIME_SEC = 1800;
const char URL_LOG[] = "https://vihorlat.tpsoft.org/hladinac/server/log.php";
const unsigned long WIFI_TIMEOUT_MS = 15000;
const unsigned long MEASUREMENT_STABILIZE_MS = 50;
struct WaterLevels {
int level1;
int level2;
int level3;
int level4;
};
void initPins();
WaterLevels readLevels();
void printLevels(const WaterLevels &levels);
String buildPostBody(const WaterLevels &levels);
bool connectWifi();
bool sendLevelsToServer(const WaterLevels &levels);
void enterDeepSleep();
void setupLevelPin(int pin);
void setCommonElectrodeOn();
void setCommonElectrodeOff();
int readLevelPin(int pin);
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("Hladinac v0.3 started.");
initPins();
if (DEBUG == 0) {
WaterLevels levels = readLevels();
printLevels(levels);
if (connectWifi()) {
sendLevelsToServer(levels);
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
} else {
Serial.println("WiFi connection failed, skipping upload.");
}
enterDeepSleep();
} else if (DEBUG == 2) {
connectWifi();
}
}
void loop() {
if (DEBUG == 1) {
WaterLevels levels = readLevels();
printLevels(levels);
delay(1000);
} else if (DEBUG == 2) {
WaterLevels levels = readLevels();
printLevels(levels);
if (WiFi.status() != WL_CONNECTED) {
connectWifi();
}
sendLevelsToServer(levels);
delay(5000);
}
}
void initPins() {
pinMode(PIN_COMMON_ELECTRODE, OUTPUT);
setCommonElectrodeOff();
setupLevelPin(PIN_LEVEL1);
setupLevelPin(PIN_LEVEL2);
setupLevelPin(PIN_LEVEL3);
setupLevelPin(PIN_LEVEL4);
}
void setupLevelPin(int pin) {
#if defined(ESP32)
pinMode(pin, INPUT_PULLDOWN);
#else
// ESP8266 pouziva externe pull-down rezistory na GND.
pinMode(pin, INPUT);
#endif
}
void setCommonElectrodeOn() {
#if defined(ESP8266)
digitalWrite(PIN_COMMON_ELECTRODE, HIGH);
#else
digitalWrite(PIN_COMMON_ELECTRODE, HIGH);
#endif
}
void setCommonElectrodeOff() {
#if defined(ESP8266)
digitalWrite(PIN_COMMON_ELECTRODE, LOW);
#else
digitalWrite(PIN_COMMON_ELECTRODE, LOW);
#endif
}
int readLevelPin(int pin) {
#if defined(ESP8266)
return digitalRead(pin) == HIGH ? 1 : 0;
#else
return digitalRead(pin) == HIGH ? 1 : 0;
#endif
}
WaterLevels readLevels() {
WaterLevels levels;
// Spolocna elektroda je zapnuta iba pocas merania, aby sa znizila korozia.
setCommonElectrodeOn();
delay(MEASUREMENT_STABILIZE_MS);
levels.level1 = readLevelPin(PIN_LEVEL1);
levels.level2 = readLevelPin(PIN_LEVEL2);
levels.level3 = readLevelPin(PIN_LEVEL3);
levels.level4 = readLevelPin(PIN_LEVEL4);
setCommonElectrodeOff();
return levels;
}
void printLevels(const WaterLevels &levels) {
Serial.print("level1=");
Serial.print(levels.level1);
Serial.print(" level2=");
Serial.print(levels.level2);
Serial.print(" level3=");
Serial.print(levels.level3);
Serial.print(" level4=");
Serial.println(levels.level4);
}
String buildPostBody(const WaterLevels &levels) {
String body = "level1=" + String(levels.level1);
body += "&level2=" + String(levels.level2);
body += "&level3=" + String(levels.level3);
body += "&level4=" + String(levels.level4);
return body;
}
bool connectWifi() {
if (WiFi.status() == WL_CONNECTED) {
return true;
}
Serial.print("Connecting to WiFi");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
unsigned long startedAt = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startedAt < WIFI_TIMEOUT_MS) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.print("WiFi connected, IP=");
Serial.println(WiFi.localIP());
return true;
}
Serial.println();
Serial.println("WiFi connection timeout.");
return false;
}
bool sendLevelsToServer(const WaterLevels &levels) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Cannot send data, WiFi is not connected.");
return false;
}
#if defined(ESP8266)
BearSSL::WiFiClientSecure client;
#else
WiFiClientSecure client;
#endif
client.setInsecure();
HTTPClient http;
if (!http.begin(client, URL_LOG)) {
Serial.println("HTTP begin failed.");
return false;
}
String body = buildPostBody(levels);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.POST(body);
if (httpCode > 0) {
Serial.print("POST sent, HTTP code=");
Serial.println(httpCode);
} else {
Serial.print("POST failed: ");
Serial.println(http.errorToString(httpCode));
}
http.end();
return httpCode > 0 && httpCode < 400;
}
void enterDeepSleep() {
Serial.print("Entering deep sleep for ");
Serial.print(SLEEP_TIME_SEC);
Serial.println(" seconds.");
Serial.flush();
#if defined(ESP8266)
ESP.deepSleep((uint64_t)SLEEP_TIME_SEC * 1000000ULL);
#else
esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_TIME_SEC * 1000000ULL);
esp_deep_sleep_start();
#endif
}