diff --git a/secrets.h.example b/secrets.h.example new file mode 100644 index 0000000..865e01e --- /dev/null +++ b/secrets.h.example @@ -0,0 +1,3 @@ +#define SECRET_SSID "" +#define SECRET_PASS "" +#define BROKER "" diff --git a/water_sensor.ino b/water_sensor.ino index de2b282..b78c751 100644 --- a/water_sensor.ino +++ b/water_sensor.ino @@ -1,13 +1,30 @@ -#define ADC_PIN A0 -#define RELAY_PIN 13 -#define RELAY_OFF LOW -#define RELAY_ON HIGH +#include +#include -#define NUM_SAMPLES 20 -#define SAMPLE_TIME 100 -#define WATER_THRESHOLD 750 +#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; -bool leakDetected = false; void relayOn() { Serial.println("Setting relay ON"); @@ -41,24 +58,99 @@ bool sampleWater() { 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); - //Serial.setDebugOutput(true); + delay(1000); Serial.println(); Serial.println(); Serial.println(); Serial.println("===== BOOT UP ====="); - pinMode(RELAY_PIN, OUTPUT); + 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() { - if (sampleWater()) { - Serial.println("Water detected"); + 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 { - Serial.println("No water"); + if (!last_neg_message || millis() - last_neg_message > MESSAGE_INTERVAL) { + last_pos_message = 0; + last_neg_message = millis(); + sendWaterLeakFalse(); + } } }