Postkastl_MQTT.ino 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Postkastl_MQTT v5
  2. // Author: Flo Kra
  3. // Desc: nach dem Start wird zunächst GPIO0 als output definiert und auf high gesetzt (Selbsthalteschaltung, dieser Pin ist mit CH_PD verbunden)
  4. // danach wird GPIO3 abgefragt - wenn high ist der Türkontakt und nicht der Klappenkontakt aktiv (event="emptied", da der Postkasten ja gerade entleert wird,
  5. // ansonsten event="new_post".
  6. // 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
  7. // abgeschaltet
  8. // MQTT payload: {"event":"<event>","Vcc":"<vcc>","Batt":"<batt>"}
  9. // event = "new_post" -> Klappe wurde geöffnet, vermutlich ist neue Post da!
  10. // "emptied" -> Postkasten wurde entleert (wenn die Tür und nicht die Klappe geöffnet ist)
  11. // Vcc = -> Vcc in mV (sollte zwischen 2400 - 3500 liegen)
  12. // Batt = normalerweise "OK", "LOW" wenn Vcc unter definiertem Wert ist
  13. #include <ESP8266WiFi.h>
  14. #include <PubSubClient.h>
  15. #define SerialDebug false
  16. const char* ssid = ""; // WiFi SSID
  17. const char* password = "!"; // WiFi PWD
  18. const char* server = ""; // gateway server IP
  19. const int port = 1883;
  20. const char* mqtt_user = "";
  21. const char* mqtt_pwd = "";
  22. const char* topic = "Postkasten";
  23. const int BattLowValue = 2600; // mV @ ADC (always some 10 mV less than external supply voltage!)
  24. const int powerdownAfter = 20; // sec
  25. // NO CONFIG BELOW!
  26. 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
  27. byte inputPin = 3; // GPIO 3 ist Input, wenn high bedeutet das, dass die Postkastentür und nicht die Klappe geöffnet wurde
  28. bool event_is_emptying = false;
  29. ADC_MODE(ADC_VCC);
  30. int Vcc;
  31. byte BattLow;
  32. WiFiClient wifiClient;
  33. PubSubClient client(server, port, callback, wifiClient);
  34. void setup() {
  35. pinMode(holdPin, OUTPUT); // GPIO 0 ist output
  36. digitalWrite(holdPin, HIGH); // setze GPIO 0 auf high, dadurch wird CH_PD high gehalten auch wenn der Kontakt nicht mehr betätigt ist
  37. #if SerialDebug
  38. // Serial TX only!! GPIO3 = RX wird als Input gebraucht
  39. Serial.begin(9600, SERIAL_8N1, SERIAL_TX_ONLY, 1); // void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin);
  40. #endif
  41. // wenn GPIO3 / RX jetzt HIGH ist, dann ist der Kontakt der Postkastentür betätigt, also wird der Postkasten gerade entleert
  42. pinMode(inputPin, INPUT); // GPIO 3 = RX = input
  43. delay(100);
  44. if ( digitalRead(inputPin) == HIGH ) event_is_emptying = true;
  45. #if SerialDebug
  46. delay(1000);
  47. Serial.print("begin...\n");
  48. Serial.print("inputPin/event_is_emptying=");
  49. Serial.print(digitalRead(inputPin));
  50. Serial.print("\n");
  51. #endif
  52. #if SerialDebug
  53. Serial.print("connecting WiFi");
  54. #endif
  55. WiFi.begin(ssid, password);
  56. uint8_t wifiRetryCounter = 0;
  57. while (WiFi.status() != WL_CONNECTED) { // loop until WiFi connected
  58. delay(500);
  59. #if SerialDebug
  60. Serial.print(".");
  61. #endif
  62. wifiRetryCounter++;
  63. if (wifiRetryCounter >= 60) {
  64. #if SerialDebug
  65. Serial.println();
  66. #endif
  67. break;
  68. }
  69. }
  70. if (WiFi.status() == WL_CONNECTED) {
  71. #if SerialDebug
  72. Serial.println("WiFi connected");
  73. Serial.println("IP: ");
  74. Serial.println(WiFi.localIP());
  75. #endif
  76. }
  77. else {
  78. #if SerialDebug
  79. Serial.println("ERROR: could not connect WiFi. Powering down now.");
  80. #endif
  81. ESP.deepSleep(0);
  82. }
  83. // Generate client name based on MAC address and last 8 bits of microsecond counter
  84. String clientName;
  85. clientName += "esp8266-";
  86. uint8_t mac[6];
  87. WiFi.macAddress(mac);
  88. clientName += macToStr(mac);
  89. clientName += "-";
  90. clientName += String(micros() & 0xff, 16);
  91. Vcc = ESP.getVcc();
  92. #if SerialDebug
  93. Serial.print("Connecting to ");
  94. Serial.print(server);
  95. Serial.print(" as ");
  96. Serial.println(clientName);
  97. Serial.print("Vcc=");
  98. Serial.print(Vcc);
  99. Serial.print("\n");
  100. Serial.print("Batt=");
  101. if ( Vcc <= BattLowValue ) Serial.print("LOW");
  102. else Serial.print("OK");
  103. Serial.print("\n");
  104. #endif
  105. //if (client.connect((char*) clientName.c_str())) {
  106. //if (client.connect("ESP-Post-5", "espclient", "1Weinum9")) {
  107. if (client.connect((char*) clientName.c_str(), mqtt_user, mqtt_pwd)) {
  108. #if SerialDebug
  109. Serial.println("Connected to MQTT broker");
  110. Serial.print("Topic: ");
  111. Serial.println(topic);
  112. #endif
  113. client.loop();
  114. String payload = "{\"event\":\"";
  115. if ( !event_is_emptying ) payload += "new_post";
  116. else payload += "emptied";
  117. payload += "\",\"Vcc\":\"";
  118. payload += Vcc;
  119. payload += "\",\"Batt\":";
  120. if ( Vcc <= BattLowValue ) payload += "\"LOW\"";
  121. else payload += "\"OK\"";
  122. payload += "}";
  123. #if SerialDebug
  124. Serial.print("Sending payload: ");
  125. Serial.println(payload);
  126. #endif
  127. client.loop();
  128. if (client.publish(topic, (char*) payload.c_str())) {
  129. client.loop();
  130. #if SerialDebug
  131. Serial.println("Publish ok");
  132. #endif
  133. }
  134. else {
  135. client.loop();
  136. #if SerialDebug
  137. Serial.println("Publish failed");
  138. #endif
  139. }
  140. client.loop();
  141. client.disconnect();
  142. }
  143. else {
  144. #if SerialDebug
  145. Serial.println("MQTT connect failed");
  146. //Serial.println("Will reset and try again...");
  147. #endif
  148. //abort(); // reboot ESP
  149. }
  150. #if SerialDebug
  151. Serial.print("sent, stopping WIFI...\n");
  152. #endif
  153. WiFi.disconnect();
  154. WiFi.mode(WIFI_OFF);
  155. WiFi.forceSleepBegin();
  156. #if SerialDebug
  157. Serial.print("WIFI deactivated\n");
  158. #endif
  159. // powerdownAfter Sekunden warten bevor PowerDown erfolgt, um doppelausloesung zu vermeiden falls waehrenddessen der Kontakt nochmal betaetigt wird (GPIO2 = HIGH) den Counter reseten
  160. for (int i = 0; i <= powerdownAfter; i++) {
  161. delay(1000);
  162. }
  163. // power down now
  164. #if SerialDebug
  165. Serial.print("power down now\n");
  166. #endif
  167. //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 ;-) )
  168. // nur deepSleep einschalten - müsste auch den GPIO 0 automatisch abschalten ..?
  169. ESP.deepSleep(0);
  170. // // ab hier nichts mehr tun, nur mehr auf bessere zeiten warten! (wenn wir hier gelandet sind ist eh etwas schief gelaufen!)
  171. // delay(5000);
  172. //#if SerialDebug
  173. // Serial.print("PWRDOWN failed, check circuit on CH_PD\n");
  174. //#endif
  175. // // 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
  176. // // wieder hochkommen wird zumindest der ESP-01 nie, da hierfür eine Verbindung von GPIO-16 zu RES nötig wäre
  177. // ESP.deepSleep(0); // 300 sec
  178. } // END Setup
  179. void loop() {
  180. } // END loop
  181. void callback(char* topic, byte* payload, unsigned int length) {
  182. // handle message arrived
  183. }
  184. String macToStr(const uint8_t* mac)
  185. {
  186. String result;
  187. for (int i = 0; i < 6; ++i) {
  188. result += String(mac[i], 16);
  189. if (i < 5)
  190. result += ':';
  191. }
  192. return result;
  193. }