commit 67f048075b6db920a10498a97b43baaf1681a4fb Author: NilsGrunwald Date: Sat Mar 6 14:41:35 2021 +0100 initial commit diff --git a/MQTTGateway/MQTTGateway.ino b/MQTTGateway/MQTTGateway.ino new file mode 100644 index 0000000..35f8f80 --- /dev/null +++ b/MQTTGateway/MQTTGateway.ino @@ -0,0 +1,304 @@ + +/* +* Getting Started example sketch for nRF24L01+ radios +* This is a very basic example of how to send data from one node to another +* Updated: Dec 2014 by TMRh20 +*/ + +//MQTT Gateway is a NodeMCU 1.0 (ESP-12E Module) - ESP8266 +#include +#include +#include +#include +#include +#include +#include + +const uint32_t wdtTimeout = 8388607; //maximum for the ESP8266 +uint32_t LastWdgFeeding; + +Ticker timer; + +#ifndef STASSID +#define STASSID "EasyBox-368239" +#define STAPSK "inginf95" +#endif + +#include +#include "RF24.h" + +/****************** User Config ***************************/ +/*** Set this radio as radio number 0 or 1 ***/ +bool radioNumber = 0; +int len = 0; + +const char* ssid = STASSID; +const char* password = STAPSK; +const char* MQTT_BROKER = "montana2000"; + +const char* MQTT_STATUS = "stat/mqtt_gateway/garagedoor/status"; +const char* MQTT_DEBUG = "stat/mqtt_gateway/garagedoor/debug"; + +#define MAXSIZE 100 +#define CHANNEL 108 + +char gotmsg[MAXSIZE]; + +char TorOffen[] = "OPENED"; +char TorGeschlossen[] = "CLOSED"; +char TorInBewegung[] = "IN TRANSIT"; + +char TorAuf[] = "Öffne Garangentor"; +char TorZu[] = "Schließe Garangentor"; + +WiFiClient espClient; +PubSubClient client(espClient); + +long lastMsg = 0; +char msg[MAXSIZE]; +int value = 0; + +/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */ +RF24 radio(D4,D8); +/**********************************************************/ + +byte addresses[][6] = {"1Node","2Node"}; + +void ICACHE_RAM_ATTR resetModule() { + Serial.print("Current time: "); + Serial.println(millis()); + Serial.print("Last fed: "); + Serial.println(LastWdgFeeding); + + //restart if the program hangs for more than 10min... + if (millis() - LastWdgFeeding > 600000) { + Serial.print("Restarting due to watchdog!"); + client.publish(MQTT_DEBUG, "Restarting due to watchdog!", true); + client.disconnect(); + ESP.restart(); + } + timer1_write(wdtTimeout); +} + +void setup() { + Serial.begin(115200); + Serial.println(F("Booting")); + + WiFi.mode(WIFI_STA); + WiFi.begin(ssid, password); + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.println("Connection Failed! Rebooting..."); + delay(5000); + ESP.restart(); + } + + // Port defaults to 8266 + // ArduinoOTA.setPort(8266); + + // Hostname defaults to esp8266-[ChipID] + ArduinoOTA.setHostname("MQTT-Gateway"); + + // No authentication by default + ArduinoOTA.setPassword("inginf"); + + // Password can be set with it's md5 value as well + // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 + // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); + + 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); + }); + ArduinoOTA.onEnd([]() { + Serial.println("\nEnd"); + }); + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }); + ArduinoOTA.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(); + Serial.println("Ready"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); + + client.setServer(MQTT_BROKER, 1883); + client.setCallback(Callback); + client.publish(MQTT_DEBUG, "Startup!", true); + + radio.begin(); + + // Set the PA Level low to prevent power supply related issues since this is a + // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default. + radio.setPALevel(RF24_PA_MAX); + radio.setDataRate(RF24_250KBPS); + //radio.setChannel(CHANNEL); + + // Open a writing and reading pipe on each radio, with opposite addresses + if(radioNumber){ + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1,addresses[0]); + }else{ + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1,addresses[1]); + } + + // Start the radio listening for data + radio.startListening(); + + timer1_attachInterrupt(resetModule); + timer1_enable(TIM_DIV256, TIM_EDGE, TIM_SINGLE); + timer1_write(wdtTimeout); +} + + +void reconnect() { + while (!client.connected()) { + Serial.print("Reconnecting..."); + if (!client.connect("MQTT-Gateway")) { + Serial.print("failed, rc="); + Serial.print(client.state()); + Serial.println(" retrying in 5 seconds"); + delay(5000); + } else { + Serial.println("connected"); + client.subscribe("cmd/mqtt-client/garagedoor/target"); + + //Heartbeat meassge every 7 min... + client.subscribe("stat/hs2/hk2/temperature"); + + client.publish(MQTT_DEBUG, "Subscribed to mqtt messages", true); + LastWdgFeeding = millis(); + } + } +} + + + + +void Callback(char* topic, byte* payload, unsigned int length) { + String msg; + + Serial.print("Message arrived ["); + + Serial.print(topic); + Serial.print("] "); + for (int i=0;i 200000 ){ // If waited longer than 200ms, indicate timeout and exit while loop + timeout = true; + break; + } + } + + if ( timeout ){ // Describe the results + Serial.println(F("Failed, response timed out.")); + } else { + // Grab the response, compare, and send to debugging spew + len = radio.getDynamicPayloadSize(); + radio.read( &gotmsg, len ); + unsigned long end_time = micros(); + + // Spew it + Serial.print(F("Sent ")); + Serial.print(start_time); + Serial.print(F(", Got response ")); + Serial.print(gotmsg); + Serial.print(F(", Round-trip delay ")); + Serial.print(end_time-start_time); + Serial.println(F(" microseconds")); + } + + //feed the watchdog... + LastWdgFeeding = millis(); +} + + +// MAIN CONTROL LOOP // +void loop() { + ArduinoOTA.handle(); + + + + if (!client.loop()) { + char msg[16]; + itoa(client.state(), msg, 10); + client.publish(MQTT_DEBUG, msg, true); + reconnect(); + } + + if ( true ) //always keep on listeing! + { + unsigned long got_time; + + if( radio.available()){ + // Variable for the received timestamp + while (radio.available()) { // While there is data ready + len = radio.getDynamicPayloadSize(); + radio.read( &gotmsg, len ); // Get the payload + } + + radio.stopListening(); // First, stop listening so we can talk + radio.write( &gotmsg, strlen(gotmsg) ); // Send the final one back. + delay(500); + radio.startListening(); + + // Now, resume listening so we catch the next packets. + Serial.print(F("Sent response ")); + Serial.println(gotmsg); + + Serial.print("Publish message: "); + Serial.println(gotmsg); + client.publish(MQTT_STATUS, gotmsg, true); + } + } +} // Loop diff --git a/SensorActorUnit/SensorActorUnit.ino b/SensorActorUnit/SensorActorUnit.ino new file mode 100644 index 0000000..f34c1c2 --- /dev/null +++ b/SensorActorUnit/SensorActorUnit.ino @@ -0,0 +1,198 @@ + +/* +* Getting Started example sketch for nRF24L01+ radios +* This is a very basic example of how to send data from one node to another +* Updated: Dec 2014 by TMRh20 +*/ + +#include +#include "RF24.h" + +/****************** User Config ***************************/ +/*** Set this radio as radio number 0 or 1 ***/ +bool radioNumber = 1; + +bool TorStatus1; +bool TorStatus2; +bool TorStatusChanged; + +int pinStatusGaragenTor1 = D1; +int pinStatusGaragenTor2 = D2; +int pinGaragenTorSchalter = 10; +int len=0; + +#define MAXSIZE 100 +#define CHANNEL 108 +char gotmsg[MAXSIZE]; + +char TorOffen[] = "OPENED"; +char TorGeschlossen[] = "CLOSED"; +char TorInBewegung[] = "IN TRANSIT"; + +char TorAuf[] = "Öffne Garangentor"; +char TorZu[] = "Schließe Garangentor"; + + +/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */ +RF24 radio(D4,D8); +/**********************************************************/ + +byte addresses[][6] = {"1Node","2Node"}; + +void setup() { + Serial.begin(115200); + + radio.begin(); + + // Set the PA Level low to prevent power supply related issues since this is a + // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default. + radio.setPALevel(RF24_PA_MAX); + radio.setDataRate(RF24_250KBPS); + //radio.setChannel(CHANNEL); + + // Open a writing and reading pipe on each radio, with opposite addresses + if(radioNumber){ + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1,addresses[0]); + }else{ + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1,addresses[1]); + } + + // Start the radio listening for data + radio.startListening(); + + pinMode(pinStatusGaragenTor1, INPUT); + pinMode(pinStatusGaragenTor2, INPUT); + pinMode(pinGaragenTorSchalter, OUTPUT); + + TorStatus1 = digitalRead(pinStatusGaragenTor1); + TorStatus2 = digitalRead(pinStatusGaragenTor2); + digitalWrite(pinGaragenTorSchalter, HIGH); + + TorStatusChanged = true; +} + + + + +// MAIN CONTROL LOOP // +void loop() { + + +/****************** Ping Out Role ***************************/ +if (TorStatusChanged == true) { + + radio.stopListening(); // First, stop listening so we can talk. + Serial.print(F("Now sending ")); + + unsigned long start_time = micros(); + if ((TorStatus1 == true) && (TorStatus2 == false)) { + Serial.println(TorOffen); + if (!radio.write( &TorOffen, strlen(TorOffen) )){ + Serial.println(F("failed")); + } + } else if ((TorStatus1 == false) && (TorStatus2 == false)) { + Serial.println(TorInBewegung); + if (!radio.write( &TorInBewegung, strlen(TorInBewegung) )){ + Serial.println(F("failed")); + } + } else if ((TorStatus1 == false) && (TorStatus2 == true)) { + Serial.println(TorGeschlossen); + if (!radio.write( &TorGeschlossen, strlen(TorGeschlossen) )){ + Serial.println(F("failed")); + } + } + + radio.startListening(); // Now, continue listening + + // Set up a timeout period, get the current microseconds + unsigned long started_waiting_at = micros(); + boolean timeout = false; // Set up a variable to indicate if a response was received or not + + while ( ! radio.available() ){ // While nothing is received + if (micros() - started_waiting_at > 200000 ){ // If waited longer than 200ms, indicate timeout and exit while loop + timeout = true; + break; + } + } + + if ( timeout ){ // Describe the results + Serial.println(F("Failed, response timed out.")); + } else { + // Grab the response, compare, and send to debugging spew + len = radio.getDynamicPayloadSize(); + radio.read( &gotmsg, len ); + unsigned long end_time = micros(); + + // Spew it + Serial.print(F("Sent ")); + Serial.print(start_time); + Serial.print(F(", Got response ")); + Serial.print(gotmsg); + Serial.print(F(", Round-trip delay ")); + Serial.print(end_time-start_time); + Serial.println(F(" microseconds")); + } + + //go back to listening + TorStatusChanged = false; + } + + + +/****************** Pong Back Role ***************************/ + + if ( TorStatusChanged == false ) + { + unsigned long got_time; + + if( radio.available()){ + // Variable for the received timestamp + while (radio.available()) { // While there is data ready + len = radio.getDynamicPayloadSize(); + radio.read( &gotmsg, len ); // Get the payload + } + + radio.stopListening(); // First, stop listening so we can talk + radio.write( &gotmsg, strlen(gotmsg) ); // Send the final one back. + radio.startListening(); // Now, resume listening so we catch the next packets. + Serial.print(F("Sent response ")); + Serial.println("ACK"); + + if ((strcmp(gotmsg,TorAuf)==0) && (!TorStatus1) && (TorStatus2)) { + Serial.println("Öffne das Tor"); + digitalWrite(pinGaragenTorSchalter, LOW); + delay(1500); + digitalWrite(pinGaragenTorSchalter, HIGH); + } + if ((strcmp(gotmsg,TorAuf)==0) && (TorStatus1)) { + Serial.println("Tor bereits offen!"); + } + + if ((strcmp(gotmsg,TorZu)==0) && (TorStatus1) && (!TorStatus2)) { + Serial.println("Schließe das Tor"); + digitalWrite(pinGaragenTorSchalter, LOW); + delay(1500); + digitalWrite(pinGaragenTorSchalter, HIGH); + } + if ((strcmp(gotmsg,TorZu)==0) && (!TorStatus1)) { + Serial.println("Tor bereits geschlossen!"); + } + } + } + +/****************** Control Logic ***************************/ + if ((digitalRead(pinStatusGaragenTor1) != TorStatus1)||(digitalRead(pinStatusGaragenTor2) != TorStatus2)) { + TorStatus1 = digitalRead(pinStatusGaragenTor1); + TorStatus2 = digitalRead(pinStatusGaragenTor2); + TorStatusChanged = true; //Tor status was changed!: Transmitting... + } + + Serial.print("Sensor 1: "); + Serial.print(TorStatus1); + Serial.print(" Sensor 2: "); + Serial.println(TorStatus2); + delay(200); + +} // Loop diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..09a9937 --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# Garagentor Steuerung + +Small project to control the GarageDoor via a RF433 Mhz connection. +It consists of two pieces: +- ESP8266: Acts as MQTT gateway to RF433 device +- Arduino Nano: Acts as sensor/actor unit in the garage \ No newline at end of file