157 lines
3.4 KiB
C++
157 lines
3.4 KiB
C++
#include <ArduinoMqttClient.h>
|
|
#include <ESP8266WiFi.h>
|
|
|
|
#include "secrets.h"
|
|
|
|
#define ADC_PIN A0
|
|
#define RELAY_PIN 13
|
|
#define RELAY_OFF LOW
|
|
#define RELAY_ON HIGH
|
|
|
|
#define NUM_SAMPLES 20
|
|
#define SAMPLE_TIME 100
|
|
#define WATER_THRESHOLD 750
|
|
|
|
#define MESSAGE_INTERVAL 1000 * 60 * 60 // one hour
|
|
|
|
WiFiClient wifiClient;
|
|
MqttClient mqttClient(wifiClient);
|
|
|
|
const char broker[] = BROKER;
|
|
int port = 1883;
|
|
const char topic[] = "iot/water";
|
|
|
|
String macAddress = String(ESP.getChipId(), HEX);
|
|
String shortName = macAddress.substring(0, 4);
|
|
String deviceName = "ws_" + shortName;
|
|
|
|
|
|
void relayOn() {
|
|
Serial.println("Setting relay ON");
|
|
digitalWrite(RELAY_PIN, RELAY_ON);
|
|
}
|
|
|
|
void relayOff() {
|
|
Serial.println("Setting relay OFF");
|
|
digitalWrite(RELAY_PIN, RELAY_OFF);
|
|
}
|
|
|
|
bool sampleWater() {
|
|
bool waterDetected = true;
|
|
|
|
Serial.print("Samples: ");
|
|
|
|
for (int i = 0; i < NUM_SAMPLES; i++) {
|
|
int sample = analogRead(ADC_PIN);
|
|
Serial.print(sample);
|
|
Serial.print(",\t");
|
|
|
|
if (sample < WATER_THRESHOLD) {
|
|
waterDetected = false;
|
|
}
|
|
|
|
delay(SAMPLE_TIME);
|
|
}
|
|
|
|
Serial.println(waterDetected ? "POS" : "NEG");
|
|
|
|
return waterDetected;
|
|
}
|
|
|
|
void sendWaterLeakTrue() {
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("{\"id\": \"");
|
|
mqttClient.print(deviceName);
|
|
mqttClient.print("\", \"water_leak\": true}");
|
|
mqttClient.endMessage();
|
|
}
|
|
|
|
void sendWaterLeakFalse() {
|
|
mqttClient.beginMessage(topic);
|
|
mqttClient.print("{\"id\": \"");
|
|
mqttClient.print(deviceName);
|
|
mqttClient.print("\", \"water_leak\": false}");
|
|
mqttClient.endMessage();
|
|
}
|
|
|
|
void setup() {
|
|
pinMode(RELAY_PIN, OUTPUT);
|
|
|
|
Serial.begin(115200);
|
|
delay(1000);
|
|
|
|
Serial.println();
|
|
Serial.println();
|
|
Serial.println();
|
|
Serial.println("===== BOOT UP =====");
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
WiFi.begin(SECRET_SSID, SECRET_PASS);
|
|
Serial.print("[WIFI] Attempting to connect to wifi");
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
|
|
Serial.println("");
|
|
Serial.println("[WIFI] Connected to the network");
|
|
Serial.println();
|
|
|
|
mqttClient.setId(deviceName);
|
|
|
|
Serial.print("[MQTT] Attempting to connect to the MQTT broker: ");
|
|
Serial.println(broker);
|
|
|
|
while (!mqttClient.connect(broker, port)) {
|
|
Serial.print("MQTT connection failed! Error code = ");
|
|
Serial.println(mqttClient.connectError());
|
|
delay(5000);
|
|
}
|
|
|
|
Serial.println("[MQTT] Connected to the MQTT broker.");
|
|
|
|
Serial.println("Turning relay on.");
|
|
relayOn();
|
|
}
|
|
|
|
void loop() {
|
|
static unsigned long last_pos_message = 0;
|
|
static unsigned long last_neg_message = 0;
|
|
|
|
bool leakDetected = sampleWater();
|
|
|
|
if (leakDetected) {
|
|
relayOff();
|
|
Serial.println("Leak detected");
|
|
}
|
|
|
|
mqttClient.poll();
|
|
|
|
if (WiFi.status() != WL_CONNECTED) {
|
|
Serial.println("[WIFI] Lost connection. Reconnecting...");
|
|
WiFi.begin(SECRET_SSID, SECRET_PASS);
|
|
return;
|
|
} else if (!mqttClient.connected()) {
|
|
Serial.print("[MQTT] Not connected! Error code = ");
|
|
Serial.println(mqttClient.connectError());
|
|
Serial.println("[MQTT] Reconnecting...");
|
|
mqttClient.connect(broker, port);
|
|
return;
|
|
}
|
|
|
|
// TODO: replace this spaghetti with a state machine
|
|
if (leakDetected) {
|
|
if (!last_pos_message || millis() - last_pos_message > MESSAGE_INTERVAL) {
|
|
last_pos_message = millis();
|
|
last_neg_message = 0;
|
|
sendWaterLeakTrue();
|
|
}
|
|
} else {
|
|
if (!last_neg_message || millis() - last_neg_message > MESSAGE_INTERVAL) {
|
|
last_pos_message = 0;
|
|
last_neg_message = millis();
|
|
sendWaterLeakFalse();
|
|
}
|
|
}
|
|
}
|