#ifdef CORE_DEBUG_LEVEL #undef CORE_DEBUG_LEVEL #endif #define CORE_DEBUG_LEVEL 3 #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG #define DOOR_SENSOR_PIN 19 #define PIR_SENSOR_PIN 13 #define ONBOARD_LED_PIN 2 #include #include #include #include #include #include #include #include #include IPAddress serverIp; const char* ssid = "Unknown Network"; const char* password = "HDUUpdcbEc3w"; const char* hostname = "Front-Door"; // MQTT Broker const char *mqtt_broker = "192.168.0.42"; const char *doorTopic = "esp32/door"; const char *movementTopic = "esp32/movement"; const int mqtt_port = 1883; WiFiClient espClient; PubSubClient mqttClient(espClient); long lastMsg = 0; char msg[50]; int doorState = LOW; int pirState = LOW; int doorPrevState = LOW; int pirPrevState = LOW; bool pubDoorState = false; bool pubPirState = false; //variables to keep track of the timing of recent interrupts unsigned long button_time = 0; unsigned long last_button_time = 0; unsigned long motion_time = 0; unsigned long last_motion_time = 0; void IRAM_ATTR pir_ISR() { motion_time = millis(); if (motion_time - last_motion_time > 750) { pirState = digitalRead(PIR_SENSOR_PIN); if (pirState != pirPrevState) { Serial.print("PIR state: "); Serial.println(pirState); digitalWrite(ONBOARD_LED_PIN, pirState); pubPirState = true; pirPrevState = pirState; } } last_motion_time = motion_time; } void IRAM_ATTR door_ISR() { button_time = millis(); if (button_time - last_button_time > 500) { doorState = digitalRead(DOOR_SENSOR_PIN); if (doorState != doorPrevState) { Serial.print("Door state: "); Serial.println(doorState); pubDoorState = true; doorPrevState = doorState; } } last_button_time = button_time; } /* Returns a semi-unique id for the device. The id is based on part of a MAC address or chip ID so it won't be globally unique. */ uint16_t GetDeviceId() { #if defined(ARDUINO_ARCH_ESP32) return ESP.getEfuseMac(); #else return ESP.getChipId(); #endif } /* Append a semi-unique id to the name template */ String MakeMine(const char *NameTemplate) { uint16_t uChipId = GetDeviceId(); String Result = String(NameTemplate) + String(uChipId, HEX); return Result; } void AdvertiseServices(const char *MyName) { if (MDNS.begin(MyName)) { Serial.println(F("mDNS responder started")); Serial.print(F("I am: ")); Serial.println(MyName); // Add service to MDNS-SD //MDNS.addService("sensor", "tcp", 8080); } else { while (1) { Serial.println(F("Error setting up MDNS responder")); delay(1000); } } } void FindServer() { while (serverIp.toString() == "0.0.0.0") { Serial.println("Resolving host..."); delay(250); serverIp = MDNS.queryHost("Home-Server"); } Serial.println("Server IP: " + serverIp.toString()); } void setupWifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); Serial.println("Connecting"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to WiFi network with IP Address: "); Serial.println(WiFi.localIP()); } void setupOTA() { // Arduino OTA Info // Port defaults to 3232 // Hostname defaults to esp3232-[MAC] String MyName = MakeMine("Door monitor"); ArduinoOTA.setHostname("DoorMon"); ArduinoOTA.setPasswordHash("b2cb7bf46d7afe5ad2ed16d87093d342"); ArduinoOTA .onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem"; // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Serial.println("Start updating " + type); }) .onEnd([]() { Serial.println("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); } void setup() { Serial.begin(115200); pinMode(PIR_SENSOR_PIN, INPUT_PULLUP); // declare sensor as input attachInterrupt(digitalPinToInterrupt(PIR_SENSOR_PIN), pir_ISR, CHANGE); pinMode(DOOR_SENSOR_PIN, INPUT_PULLUP); // declare sensor as input attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR_PIN), door_ISR, CHANGE); // Set LED to LOW pinMode(ONBOARD_LED_PIN, OUTPUT); digitalWrite(ONBOARD_LED_PIN, LOW); setupWifi(); setupOTA(); mqttClient.setServer(mqtt_broker, 1883); String MyName = MakeMine("Door monitor"); //AdvertiseServices(MyName.c_str()); //FindServer(); } void reconnect() { // Loop until we're reconnected while (!mqttClient.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect String MyName = MakeMine("Door monitor"); if (mqttClient.connect(MyName.c_str())) { Serial.println("connected"); mqttClient.publish("esp32/movement", "Door sensor online."); } else { Serial.print("failed, rc="); Serial.print(mqttClient.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void loop() { if (!mqttClient.connected()) { reconnect(); } mqttClient.loop(); if (pubDoorState) { if (doorState == LOW) { mqttClient.publish("esp32/door", "The door is open."); } else { mqttClient.publish("esp32/door", "The door is closed."); } pubDoorState = false; delay(100); } if (pubPirState) { if (pirState == HIGH) { mqttClient.publish(movementTopic, "Motion detected at door."); } pubPirState = false; delay(100); } // put your main code here, to run repeatedly: ArduinoOTA.handle(); }