|
@@ -0,0 +1,238 @@
|
|
|
|
+// Postkastl_MQTT v5
|
|
|
|
+// Author: Flo Kra
|
|
|
|
+// Desc: nach dem Start wird zunächst GPIO0 als output definiert und auf high gesetzt (Selbsthalteschaltung, dieser Pin ist mit CH_PD verbunden)
|
|
|
|
+// danach wird GPIO3 abgefragt - wenn high ist der Türkontakt und nicht der Klappenkontakt aktiv (event="emptied", da der Postkasten ja gerade entleert wird,
|
|
|
|
+// ansonsten event="new_post".
|
|
|
|
+// dann wird eine WIFI Verbindung aufgebaut, eine Message mit ein paar Daten als JSON string an einen MQTT broker gesendet und nach einer Wartezeit das Modul wieder
|
|
|
|
+// abgeschaltet
|
|
|
|
+// MQTT payload: {"event":"<event>","Vcc":"<vcc>","Batt":"<batt>"}
|
|
|
|
+// event = "new_post" -> Klappe wurde geöffnet, vermutlich ist neue Post da!
|
|
|
|
+// "emptied" -> Postkasten wurde entleert (wenn die Tür und nicht die Klappe geöffnet ist)
|
|
|
|
+// Vcc = -> Vcc in mV (sollte zwischen 2400 - 3500 liegen)
|
|
|
|
+// Batt = normalerweise "OK", "LOW" wenn Vcc unter definiertem Wert ist
|
|
|
|
+
|
|
|
|
+#include <ESP8266WiFi.h>
|
|
|
|
+#include <PubSubClient.h>
|
|
|
|
+
|
|
|
|
+#define SerialDebug false
|
|
|
|
+
|
|
|
|
+const char* ssid = ""; // WiFi SSID
|
|
|
|
+const char* password = "!"; // WiFi PWD
|
|
|
|
+
|
|
|
|
+const char* server = ""; // gateway server IP
|
|
|
|
+const int port = 1883;
|
|
|
|
+const char* mqtt_user = "";
|
|
|
|
+const char* mqtt_pwd = "";
|
|
|
|
+const char* topic = "Postkasten";
|
|
|
|
+
|
|
|
|
+const int BattLowValue = 2600; // mV @ ADC (always some 10 mV less than external supply voltage!)
|
|
|
|
+const int powerdownAfter = 20; // sec
|
|
|
|
+
|
|
|
|
+// NO CONFIG BELOW!
|
|
|
|
+byte holdPin = 0; // GPIO 0 ist via Diode mit CH_PD verbunden, muss high gehalten werden bis das Programm fertig ist, dann wird auf low geschaltet und dadurch das Modul abgeschaltet
|
|
|
|
+byte inputPin = 3; // GPIO 3 ist Input, wenn high bedeutet das, dass die Postkastentür und nicht die Klappe geöffnet wurde
|
|
|
|
+
|
|
|
|
+bool event_is_emptying = false;
|
|
|
|
+
|
|
|
|
+ADC_MODE(ADC_VCC);
|
|
|
|
+int Vcc;
|
|
|
|
+byte BattLow;
|
|
|
|
+
|
|
|
|
+WiFiClient wifiClient;
|
|
|
|
+PubSubClient client(server, port, callback, wifiClient);
|
|
|
|
+
|
|
|
|
+void setup() {
|
|
|
|
+ pinMode(holdPin, OUTPUT); // GPIO 0 ist output
|
|
|
|
+ digitalWrite(holdPin, HIGH); // setze GPIO 0 auf high, dadurch wird CH_PD high gehalten auch wenn der Kontakt nicht mehr betätigt ist
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ // Serial TX only!! GPIO3 = RX wird als Input gebraucht
|
|
|
|
+ Serial.begin(9600, SERIAL_8N1, SERIAL_TX_ONLY, 1); // void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ // wenn GPIO3 / RX jetzt HIGH ist, dann ist der Kontakt der Postkastentür betätigt, also wird der Postkasten gerade entleert
|
|
|
|
+ pinMode(inputPin, INPUT); // GPIO 3 = RX = input
|
|
|
|
+ delay(100);
|
|
|
|
+ if ( digitalRead(inputPin) == HIGH ) event_is_emptying = true;
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ delay(1000);
|
|
|
|
+ Serial.print("begin...\n");
|
|
|
|
+ Serial.print("inputPin/event_is_emptying=");
|
|
|
|
+ Serial.print(digitalRead(inputPin));
|
|
|
|
+ Serial.print("\n");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("connecting WiFi");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ WiFi.begin(ssid, password);
|
|
|
|
+ uint8_t wifiRetryCounter = 0;
|
|
|
|
+ while (WiFi.status() != WL_CONNECTED) { // loop until WiFi connected
|
|
|
|
+ delay(500);
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print(".");
|
|
|
|
+#endif
|
|
|
|
+ wifiRetryCounter++;
|
|
|
|
+ if (wifiRetryCounter >= 60) {
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println();
|
|
|
|
+#endif
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (WiFi.status() == WL_CONNECTED) {
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("WiFi connected");
|
|
|
|
+ Serial.println("IP: ");
|
|
|
|
+ Serial.println(WiFi.localIP());
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("ERROR: could not connect WiFi. Powering down now.");
|
|
|
|
+#endif
|
|
|
|
+ ESP.deepSleep(0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // Generate client name based on MAC address and last 8 bits of microsecond counter
|
|
|
|
+ String clientName;
|
|
|
|
+ clientName += "esp8266-";
|
|
|
|
+ uint8_t mac[6];
|
|
|
|
+ WiFi.macAddress(mac);
|
|
|
|
+ clientName += macToStr(mac);
|
|
|
|
+ clientName += "-";
|
|
|
|
+ clientName += String(micros() & 0xff, 16);
|
|
|
|
+
|
|
|
|
+ Vcc = ESP.getVcc();
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("Connecting to ");
|
|
|
|
+ Serial.print(server);
|
|
|
|
+ Serial.print(" as ");
|
|
|
|
+ Serial.println(clientName);
|
|
|
|
+ Serial.print("Vcc=");
|
|
|
|
+ Serial.print(Vcc);
|
|
|
|
+ Serial.print("\n");
|
|
|
|
+ Serial.print("Batt=");
|
|
|
|
+ if ( Vcc <= BattLowValue ) Serial.print("LOW");
|
|
|
|
+ else Serial.print("OK");
|
|
|
|
+ Serial.print("\n");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //if (client.connect((char*) clientName.c_str())) {
|
|
|
|
+ //if (client.connect("ESP-Post-5", "espclient", "1Weinum9")) {
|
|
|
|
+ if (client.connect((char*) clientName.c_str(), mqtt_user, mqtt_pwd)) {
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("Connected to MQTT broker");
|
|
|
|
+ Serial.print("Topic: ");
|
|
|
|
+ Serial.println(topic);
|
|
|
|
+#endif
|
|
|
|
+ client.loop();
|
|
|
|
+
|
|
|
|
+ String payload = "{\"event\":\"";
|
|
|
|
+
|
|
|
|
+ if ( !event_is_emptying ) payload += "new_post";
|
|
|
|
+ else payload += "emptied";
|
|
|
|
+
|
|
|
|
+ payload += "\",\"Vcc\":\"";
|
|
|
|
+ payload += Vcc;
|
|
|
|
+ payload += "\",\"Batt\":";
|
|
|
|
+
|
|
|
|
+ if ( Vcc <= BattLowValue ) payload += "\"LOW\"";
|
|
|
|
+ else payload += "\"OK\"";
|
|
|
|
+
|
|
|
|
+ payload += "}";
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("Sending payload: ");
|
|
|
|
+ Serial.println(payload);
|
|
|
|
+#endif
|
|
|
|
+ client.loop();
|
|
|
|
+ if (client.publish(topic, (char*) payload.c_str())) {
|
|
|
|
+ client.loop();
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("Publish ok");
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ client.loop();
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("Publish failed");
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+ client.loop();
|
|
|
|
+ client.disconnect();
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.println("MQTT connect failed");
|
|
|
|
+ //Serial.println("Will reset and try again...");
|
|
|
|
+#endif
|
|
|
|
+ //abort(); // reboot ESP
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("sent, stopping WIFI...\n");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ WiFi.disconnect();
|
|
|
|
+ WiFi.mode(WIFI_OFF);
|
|
|
|
+ WiFi.forceSleepBegin();
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("WIFI deactivated\n");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ // powerdownAfter Sekunden warten bevor PowerDown erfolgt, um doppelausloesung zu vermeiden falls waehrenddessen der Kontakt nochmal betaetigt wird (GPIO2 = HIGH) den Counter reseten
|
|
|
|
+ for (int i = 0; i <= powerdownAfter; i++) {
|
|
|
|
+ delay(1000);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // power down now
|
|
|
|
+#if SerialDebug
|
|
|
|
+ Serial.print("power down now\n");
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //digitalWrite(holdPin, LOW); // setze GPIO 0 auf low. dadurch wird CH_PD low und der ESP abgeschaltet (den Ast auf dem wir sitzen absägen ;-) )
|
|
|
|
+
|
|
|
|
+ // nur deepSleep einschalten - müsste auch den GPIO 0 automatisch abschalten ..?
|
|
|
|
+ ESP.deepSleep(0);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // // ab hier nichts mehr tun, nur mehr auf bessere zeiten warten! (wenn wir hier gelandet sind ist eh etwas schief gelaufen!)
|
|
|
|
+ // delay(5000);
|
|
|
|
+ //#if SerialDebug
|
|
|
|
+ // Serial.print("PWRDOWN failed, check circuit on CH_PD\n");
|
|
|
|
+ //#endif
|
|
|
|
+ // // deep sleep auslösen, da wir nun nichts mehr zu tun haben. falls das powerdown via GPIO0->CH_PD nicht funktioniert sparen wir so zumindest energie
|
|
|
|
+ // // wieder hochkommen wird zumindest der ESP-01 nie, da hierfür eine Verbindung von GPIO-16 zu RES nötig wäre
|
|
|
|
+ // ESP.deepSleep(0); // 300 sec
|
|
|
|
+} // END Setup
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void loop() {
|
|
|
|
+
|
|
|
|
+} // END loop
|
|
|
|
+
|
|
|
|
+void callback(char* topic, byte* payload, unsigned int length) {
|
|
|
|
+ // handle message arrived
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+String macToStr(const uint8_t* mac)
|
|
|
|
+{
|
|
|
|
+ String result;
|
|
|
|
+ for (int i = 0; i < 6; ++i) {
|
|
|
|
+ result += String(mac[i], 16);
|
|
|
|
+ if (i < 5)
|
|
|
|
+ result += ':';
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+}
|