Advertisement
hanpa

Post Box automation with ESP8266

Jul 28th, 2017
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.79 KB | None | 0 0
  1. #include <Arduino.h>
  2. #include <ESP8266WiFi.h>
  3. #include <ESP8266mDNS.h>
  4. #include "Adafruit_MQTT.h"
  5. #include "Adafruit_MQTT_Client.h"
  6. #include <ArduinoOTA.h>
  7. #include "/Users/hanpa/Dropbox/Hem/Arduino/common/credentials.h"
  8.  
  9. const char* version   = "postbox 1.0";
  10. const char* date_name = "2017-07-28 Hans Palm";
  11.  
  12. // Hans Palm 2017
  13. // http://www.hobbyelektronik.nu/
  14. //
  15. // This code checks the lid and door of my post box using a Wemos D1 mini (ESP8266)
  16. // The post box has a lid and a separate lockable door used when the box is emptied
  17. //
  18. // Reed switches are used together with a permanent magnet for detection
  19. // The D1 pin is connected to the lid switch, 0 = lid closed, 1 = lid open
  20. // The D2 pin is connected to the door switch, 0 = door closed, 1 = door open
  21. //
  22. // MQTT WiFi messages are sent on the event of opening lid or door
  23. // The lid or door must be closed more than 30 seconds before a new open event can be sent
  24. //
  25. // MQTT WiFi messages are also sent continously each second for function monitoring
  26. // of the complete circuit, switches and MQTT connection to the server
  27. // The continous messages are not filtered, reflects the current state of the switches
  28.  
  29. // Credentials are assumed to be stated in a #include(d) .h file or stated directly below instead
  30. // of constant names for ssid, password, mqtt_server and mqtt_port
  31. //
  32. // OTA support included
  33.  
  34. /************************* WiFi Access Point *********************************/
  35.  
  36. #define WLAN_SSID   ssid
  37. #define WLAN_PASS   password
  38.  
  39. /***************************** MQTT settings *********************************/
  40. #define SERVER      mqtt_server
  41. #define SERVERPORT  mqtt_port              // use 8883 for SSL
  42. #define USERNAME    ""                     // Not used, from Adafruit.io Setup
  43. #define KEY         ""                     // Not used, from Adafruit.io Setup
  44.  
  45. /************************* OTA *********************************/
  46. #define OTA_HOST_NAME   "PostBox"          // No _ in hostnames!
  47. const char* host = OTA_HOST_NAME;
  48.  
  49. // The follwing parameters are only required for fixed IP, otherwise uncomment, also uncomment WiFi.config(ip, gateway, subnet)
  50. IPAddress ip(192, 168, 0, 157);
  51. IPAddress gateway(192, 168, 0, 1);
  52. IPAddress subnet(255, 255, 255, 0);
  53.  
  54. // Input pin settings for post box
  55. const int LidInputPin = D1;
  56. const int DoorInputPin = D2;
  57.  
  58. // Types and states
  59. enum openOrClosed {
  60.   Open,
  61.   Closed
  62. };
  63. openOrClosed lidState = Closed;
  64. openOrClosed doorState = Closed;
  65.  
  66. int lidBeforeConsideredClosedCounter = 0;
  67. int doorBeforeConsideredClosedCounter = 0;
  68. unsigned long lastContinousPublishTime = 0;
  69.  
  70. const int SECONDS_BEFORE_CONSIDERED_CLOSED = 30;
  71.  
  72. // Create an ESP8266 WiFiClient class to connect to the MQTT server.
  73. WiFiClient client;
  74. // or... use WiFiFlientSecure for SSL
  75. //WiFiClientSecure client;
  76.  
  77. // Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
  78. Adafruit_MQTT_Client mqtt(&client, SERVER, SERVERPORT, USERNAME, KEY);
  79.  
  80. /****************************** Feeds ***************************************/
  81.  
  82. // Setup feeds for publishing.
  83.  
  84. // Continous data, unfiltered
  85. Adafruit_MQTT_Publish postBoxLidOpen = Adafruit_MQTT_Publish(&mqtt, USERNAME "PostBoxLidOpen");
  86. Adafruit_MQTT_Publish postBoxDoorOpen = Adafruit_MQTT_Publish(&mqtt, USERNAME "PostBoxDoorOpen");
  87.  
  88. // Event data, filtered to avoid multiple events when when several post items are delivered
  89. Adafruit_MQTT_Publish postBoxLidOpened = Adafruit_MQTT_Publish(&mqtt, USERNAME "PostBoxLidOpened");
  90. Adafruit_MQTT_Publish postBoxDoorOpened = Adafruit_MQTT_Publish(&mqtt, USERNAME "PostBoxDoorOpened");
  91.  
  92. void MQTT_connect();
  93.  
  94. void OTA_setup() {
  95.   ArduinoOTA.setHostname(host);
  96.  
  97.   ArduinoOTA.onStart([]() {
  98.     String type;
  99. //    if (ArduinoOTA.getCommand() == U_FLASH)
  100.       type = "sketch";
  101. //    else // U_SPIFFS
  102. //      type = "filesystem";
  103.  
  104.     // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
  105.     Serial.println("Start updating " + type);
  106.   });
  107.   ArduinoOTA.onEnd([]() {
  108.     Serial.println("\nEnd");
  109.   });
  110.   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  111.     Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  112.   });
  113.   ArduinoOTA.onError([](ota_error_t error) {
  114.     Serial.printf("Error[%u]: ", error);
  115.     if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
  116.     else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
  117.     else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
  118.     else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
  119.     else if (error == OTA_END_ERROR) Serial.println("End Failed");
  120.   });
  121.   ArduinoOTA.begin();
  122. }
  123.  
  124. void setup() {
  125.   Serial.begin(115200);
  126.   delay(10);
  127.  
  128.   pinMode(LidInputPin, INPUT_PULLUP);
  129.   pinMode(DoorInputPin, INPUT_PULLUP);
  130.  
  131.   // Connect to WiFi access point.
  132.   Serial.println(); Serial.println();
  133.   Serial.print("Connecting to ");
  134.   Serial.println(WLAN_SSID);
  135.  
  136.  
  137.   WiFi.config(ip, gateway, subnet); // Only required for fixed IP
  138.   WiFi.begin(WLAN_SSID, WLAN_PASS);
  139.   while (WiFi.status() != WL_CONNECTED) {
  140.     delay(500);
  141.     Serial.print(".");
  142.   }
  143.   Serial.println();
  144.  
  145.   Serial.println("WiFi connected");
  146.   Serial.println("IP address: "); Serial.println(WiFi.localIP());
  147.  
  148.   OTA_setup();
  149. }
  150.  
  151. void loop() {
  152.   ArduinoOTA.handle();
  153.  
  154.   // Ensure the connection to the MQTT server is alive (this will make the first
  155.   // connection and automatically reconnect when disconnected).  See the MQTT_connect
  156.   // function definition further below.
  157.   MQTT_connect();
  158.  
  159.   const int CYCLE_TIME = 50; // 50ms
  160.  
  161.   // Process mqtt data
  162.   mqtt.processPackets(CYCLE_TIME);
  163.  
  164.   int lidSwitch = digitalRead(LidInputPin); // Reed switch normally closed = 0
  165.   int doorSwitch = digitalRead(DoorInputPin); // Reed switch normally closed = 0
  166.  
  167.   // Check lid switch
  168.   if (lidSwitch == 1) {
  169.     // Open
  170.     if (lidState == Closed) {
  171.       lidState = Open;
  172.       postBoxLidOpened.publish(1); // open lid event data
  173.     }
  174.     lidBeforeConsideredClosedCounter = 0;
  175.   } else {
  176.     // closed
  177.     if (lidState == Open) {
  178.       // Consider closed after a rather long time, to avoid separate events if lid is open/closed many times in a short time
  179.       if (lidBeforeConsideredClosedCounter > SECONDS_BEFORE_CONSIDERED_CLOSED * 1000/CYCLE_TIME) {
  180.         lidState = Closed;
  181.         lidBeforeConsideredClosedCounter = 0;
  182.       }
  183.       lidBeforeConsideredClosedCounter++;
  184.     }
  185.   }
  186.  
  187.   // Check door switch
  188.   if (doorSwitch == 1) {
  189.     // Open
  190.     if (doorState == Closed) {
  191.       doorState = Open;
  192.       postBoxDoorOpened.publish(1); // open door event data
  193.     }
  194.     doorBeforeConsideredClosedCounter = 0;
  195.   } else {
  196.     // closed
  197.     if (doorState == Open) {
  198.       // Consider closed after a rather long time, to avoid separate events if door is open/closed many times in a short time
  199.       if (doorBeforeConsideredClosedCounter > SECONDS_BEFORE_CONSIDERED_CLOSED * 1000/CYCLE_TIME) {
  200.         doorState = Closed;
  201.         doorBeforeConsideredClosedCounter = 0;
  202.       }
  203.       doorBeforeConsideredClosedCounter++;
  204.     }
  205.   }
  206.  
  207.   unsigned long now = millis();
  208.   if ( (now - lastContinousPublishTime) > 1000 ) {
  209.     // Send continous unfiltered data about lid and door state each second
  210.     postBoxLidOpen.publish(lidSwitch == 1);
  211.     postBoxDoorOpen.publish(doorSwitch == 1);
  212.     lastContinousPublishTime = now;
  213.   }
  214.  
  215.   // No delay() is used, mqtt.processPackets consumes 50ms in each cycle
  216. }
  217.  
  218. // Function to connect and reconnect as necessary to the MQTT server.
  219. // Should be called in the loop function and it will take care if connecting.
  220. void MQTT_connect() {
  221.   int8_t ret;
  222.  
  223.   // Stop if already connected.
  224.   if (mqtt.connected()) {
  225.     return;
  226.   }
  227.  
  228.   Serial.print("Connecting to MQTT... ");
  229.  
  230.   while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
  231.     Serial.println(mqtt.connectErrorString(ret));
  232.     Serial.println("Retrying MQTT connection in 5 seconds...");
  233.     delay(5000);  // wait 5 seconds
  234.   }
  235.   Serial.println("MQTT Connected!");
  236. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement