diff --git a/esp32-door-sensor-mqtt/esp32-door-sensor-mqtt.ino b/esp32-door-sensor-mqtt/esp32-door-sensor-mqtt.ino new file mode 100644 index 0000000..743dc4b --- /dev/null +++ b/esp32-door-sensor-mqtt/esp32-door-sensor-mqtt.ino @@ -0,0 +1,205 @@ +#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 + +#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) { + pubPirState = true; + pirPrevState = pirState; + } + delay(250); + } + + 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; + } + delay(250); + } + + last_button_time = button_time; +} + +void IRAM_ATTR window_ISR() { + mqttClient.publish("esp32/temperature", "The window is closed."); +} + +/* 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 setup() { + Serial.begin(115200); + + pinMode(PIR_SENSOR_PIN, INPUT_PULLUP); // declare sensor as input + attachInterrupt(digitalPinToInterrupt(PIR_SENSOR_PIN), pir_ISR, HIGH); + + pinMode(DOOR_SENSOR_PIN, INPUT_PULLUP); // declare sensor as input + attachInterrupt(digitalPinToInterrupt(DOOR_SENSOR_PIN), door_ISR, CHANGE); + + + WiFi.setHostname(hostname); + 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()); + + 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) { + mqttClient.publish("esp32/motion", "Motion detected at door."); + pubDoorState = false; + delay(100); + } + // put your main code here, to run repeatedly: + +} \ No newline at end of file diff --git a/esp32-light-switch/esp32-light-switch.ino b/esp32-light-switch/esp32-light-switch.ino new file mode 100644 index 0000000..df84fdf --- /dev/null +++ b/esp32-light-switch/esp32-light-switch.ino @@ -0,0 +1,166 @@ +#ifdef CORE_DEBUG_LEVEL +#undef CORE_DEBUG_LEVEL +#endif + +#define CORE_DEBUG_LEVEL 3 +#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include + +// WiFi Info +const char* ssid = "Unknown Network"; +const char* password = "HDUUpdcbEc3w"; + +// MQTT +const char *mqtt_broker = "192.168.0.42"; +const char *topic = "esp32/switch"; +const int mqtt_port = 1883; + +WiFiClient espClient; +PubSubClient mqttClient(espClient); +long lastMsg = 0; +char msg[50]; +int value = 0; + +// Servo Vars +int lightPin = 13; +int pos = 0; + +Servo leftServo; +Servo rightServo; + +// Arduino OTA Info +// Port defaults to 3232 +// Hostname defaults to esp3232-[MAC] +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 callback(char* topic, byte* message, unsigned int length) { + Serial.print("Message arrived on topic: "); + Serial.print(topic); + Serial.print(". Message: "); + String messageTemp; + + for (int i = 0; i < length; i++) { + Serial.print((char)message[i]); + messageTemp += (char)message[i]; + } + Serial.println(); + + // Feel free to add more if statements to control more GPIOs with MQTT + + // If a message is received on the topic esp32/switch, you check if the message is either "on" or "off". + // Changes the output state according to the message + if (String(topic) == "esp32/switch") { + Serial.print("Changing switch to "); + if(messageTemp == "on"){ + Serial.println("lights on"); + leftServo.write(15); + rightServo.write(30); + } + else if(messageTemp == "off"){ + Serial.println("lights off"); + leftServo.write(30); + rightServo.write(15); + } + } +} + +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 setup() { + Serial.begin(115200); + Serial.println("Starting up"); + + setupWifi(); + + Serial.print("Subscribing to "); + Serial.println(mqtt_broker); + mqttClient.setServer(mqtt_broker, 1883); + mqttClient.subscribe(topic); + mqttClient.setCallback(callback); + + Serial.println("Attaching servo at pin 13"); + leftServo.attach(13); + Serial.println("Attaching servo at pin 12"); + rightServo.attach(12); + + leftServo.write(0); + rightServo.write(45); +} + +void reconnect() { + // Loop until we're reconnected + while (!mqttClient.connected()) { + Serial.print("Attempting MQTT connection..."); + // Attempt to connect + if (mqttClient.connect("ESP8266Client")) { + Serial.println("connected"); + // Subscribe + mqttClient.subscribe(topic); + } 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(); +} \ No newline at end of file diff --git a/signal-mgtt.py b/signal-mgtt.py new file mode 100644 index 0000000..3977cf3 --- /dev/null +++ b/signal-mgtt.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# signal-talker-server.py +# +# Copyright 2022 matt +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# +from pydbus import SessionBus +from gi.repository import GLib +from zeroconf import ServiceBrowser, ServiceListener, Zeroconf +import paho.mqtt.client as mqtt +import time + +mqttBroker ="127.0.0.1" +client = mqtt.Client("homeServer") + +def on_message(client, userdata, message): + print("received message: " ,str(message.payload.decode("utf-8"))) + signal.sendMessage(str(message.payload.decode("utf-8")), [], ['+16027106778']) + doorState = message + +def on_signal_message(timestamp, source, groupID, message, attachments): + print("received signal message: ", message) + client.publish("esp32/switch", message) + signal.sendMessage('Turned light {}'.format(message), [], ['+16027106778']) + +class MyListener(ServiceListener): + + def update_service(self, zc: Zeroconf, type_: str, name: str) -> None: + print(f"Service {name} updated") + + def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None: + print(f"Service {name} removed") + + def add_service(self, zc: Zeroconf, type_: str, name: str) -> None: + info = zc.get_service_info(type_, name) + print(f"Service {name} added, service info: {info}") + +bus = SessionBus() +#signal = bus.get('org.asamk.Signal') +#signal.onMessageReceived = on_signal_message +#signal.sendMessage('Server online', [], ['+16027106778']) +zeroconf = Zeroconf() +listener = MyListener() +browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener) + +if __name__ == "__main__": + doorState = "The door is closed." + while True : + client.connect(mqttBroker, 1883, 60) + client.loop_start() + client.subscribe("esp32/door") + client.on_message=on_message + + loop = GLib.MainLoop() + signal = bus.get('org.asamk.Signal', object_path='/org/asamk/Signal') + + def on_signal_message(timestamp, source, groupID, message, attachments): + print("received signal message: ", message) + client.publish("esp32/switch", message.lower()) + signal.sendMessage('Turned light {}'.format(message.lower()), [], ['+16027106778']) + + signal.onMessageReceived = on_signal_message + loop.run() \ No newline at end of file diff --git a/signal-talker.sh b/signal-talker.sh new file mode 100644 index 0000000..fc6f87c --- /dev/null +++ b/signal-talker.sh @@ -0,0 +1,6 @@ +#! /bin/bash +$(dbus-launch) + +export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$UID/test-dbus" DBUS_SESSION_BUS_PID=$(dbus-daemon --fork --print-pid --session --address="$DBUS_SESSION_BUS_ADDRESS") + +python ~/signal-talker/signal-mqtt.py \ No newline at end of file