Advertisement
Guest User

SmartThingsContactSensor.ino

a guest
Apr 17th, 2016
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Groovy 10.10 KB | None | 0 0
  1. /*
  2.     This sketch demonstrates how to set up a simple REST-like server
  3.     to monitor a door/window opening and closing.
  4.     A reed switch is connected to gnd and the other end is
  5.     connected to gpio2, when door
  6.     is closed, reed switch should be closed and vice versa.
  7.     ip is the IP address of the ESP8266 module if you want to hard code it,
  8.     Otherwise remove ip, gateway and subnet and also WiFi.config to use dhcp.
  9.    
  10.     Status of contact is returned as json: {"name":"contact","status":0}
  11.     To get status: http://{ip}:{serverPort}/getstatus
  12.    
  13.     Any time status changes, the same json above will be posted to {hubIp}:{hubPort}.
  14. */
  15.  
  16. #include "FS.h"
  17. #include <WiFiManager.h>
  18. #include <ArduinoJson.h>
  19. #include <ESP8266WiFi.h>
  20. #include <ESP8266mDNS.h>
  21. #include <WiFiUdp.h>
  22. #include <ArduinoOTA.h>
  23.  
  24. // 0 == D3
  25. #define CONTACT_PIN 4
  26.  
  27. void contactChanged();
  28.  
  29. const char APPSETTINGS[] PROGMEM = "/appSettings.json";
  30. const char LOADED[] PROGMEM = " loaded: ";
  31. const char HUBPORT[] PROGMEM = "hubPort";
  32. const char HUPIP[] PROGMEM = "hubIp";
  33. const char DEVICENAME[] PROGMEM = "deviceName";
  34.  
  35. const unsigned int serverPort = 9060; // port to run the http server on
  36.  
  37. // Smartthings hub information
  38. IPAddress hubIp = INADDR_NONE; // smartthings hub ip
  39. unsigned int hubPort = 0; // smartthings hub port
  40.  
  41. String deviceName = "ESP8266 Contact Sensor";
  42. const char *OTApassword = ""; //you should probably change this…
  43.  
  44. byte oldSensorState, currentSensorState;
  45. volatile unsigned long last_micros;
  46. long debounceDelay = 10;    // the debounce time (in ms); increase if false positives
  47. bool sendUpdate = false;
  48.  
  49. WiFiServer server(serverPort); //server
  50. WiFiClient client; //client
  51.  
  52. IPAddress IPfromString(String address) {
  53.   int ip1, ip2, ip3, ip4;
  54.   ip1 = address.toInt();
  55.   address = address.substring(address.indexOf('.') + 1);
  56.   ip2 = address.toInt();
  57.   address = address.substring(address.indexOf('.') + 1);
  58.   ip3 = address.toInt();
  59.   address = address.substring(address.indexOf('.') + 1);
  60.   ip4 = address.toInt();
  61.   return IPAddress(ip1, ip2, ip3, ip4);
  62. }
  63.  
  64. void configModeCallback (WiFiManager *myWiFiManager) {
  65.   Serial.println(F("Entered config mode"));
  66.   Serial.println(WiFi.softAPIP());
  67.   Serial.println(myWiFiManager->getConfigPortalSSID());
  68. }
  69.  
  70. bool loadAppConfig() {
  71.   File configFile = SPIFFS.open(FPSTR(APPSETTINGS), "r");
  72.   if (!configFile) {
  73.     Serial.println(F("Failed to open config file"));
  74.     return false;
  75.   }
  76.  
  77.   size_t size = configFile.size();
  78.   if (size > 1024) {
  79.     Serial.println(F("Config file size is too large"));
  80.     return false;
  81.   }
  82.  
  83.   std::unique_ptr<char[]> buf(new char[size]);
  84.   configFile.readBytes(buf.get(), size);
  85.   configFile.close();
  86.  
  87.   const int BUFFER_SIZE = JSON_OBJECT_SIZE(3);
  88.   StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
  89.   JsonObject& json = jsonBuffer.parseObject(buf.get());
  90.  
  91.   if (!json.success()) {
  92.     Serial.println(F("Failed to parse application config file"));
  93.     return false;
  94.   }
  95.  
  96.   hubPort = json[FPSTR(HUBPORT)];
  97.   Serial.print(FPSTR(HUBPORT));
  98.   Serial.print(FPSTR(LOADED));
  99.   Serial.println(hubPort);
  100.   String hubAddress = json[FPSTR(HUPIP)];
  101.   Serial.print(FPSTR(HUPIP));
  102.   Serial.print(FPSTR(LOADED));
  103.   Serial.println(hubAddress);
  104.   hubIp = IPfromString(hubAddress);
  105.   String savedDeviceName = json[FPSTR(DEVICENAME)];
  106.   deviceName = savedDeviceName;
  107.   Serial.print(FPSTR(DEVICENAME));
  108.   Serial.print(FPSTR(LOADED));
  109.   Serial.println(deviceName);
  110.   return true;
  111. }
  112.  
  113. bool saveAppConfig(String jsonString) {
  114.   Serial.print(F("Saving new settings: "));
  115.   Serial.println(jsonString);
  116.   File configFile = SPIFFS.open(FPSTR(APPSETTINGS), "w");
  117.   if (!configFile) {
  118.     Serial.println(F("Failed to open application config file for writing"));
  119.     return false;
  120.   }
  121.   configFile.print(jsonString);
  122.   configFile.close();
  123.   return true;
  124. }
  125.  
  126. void setup() {
  127.   delay(10);
  128.   Serial.begin(115200);
  129.  
  130.   Serial.print(F("Sketch size: "));
  131.   Serial.println(ESP.getSketchSize());
  132.   Serial.print(F("Free size: "));
  133.   Serial.print(ESP.getFreeSketchSpace());
  134.  
  135.   Serial.println();
  136.   Serial.println(F("Initializing IO..."));
  137.   // prepare GPIO2
  138.   pinMode(CONTACT_PIN, INPUT);
  139.   attachInterrupt(CONTACT_PIN, contactChanged, CHANGE);
  140.  
  141.   Serial.println(F("Mounting FS..."));
  142.  
  143.   if (!SPIFFS.begin()) {
  144.     Serial.println(F("Failed to mount file system"));
  145.     return;
  146.   }
  147.  
  148.   // DEBUG: remove all files from file system
  149. //  SPIFFS.format();
  150.  
  151.   if (!loadAppConfig()) {
  152.     Serial.println(F("Failed to load application config"));
  153.   } else {
  154.     Serial.println(F("Application config loaded"));
  155.   }
  156.  
  157.   //WiFiManager
  158.   //Local intialization. Once its business is done, there is no need to keep it around
  159.   WiFiManager wifiManager;
  160.   // DEBUG: reset WiFi settings
  161. //  wifiManager.resetSettings();
  162.   // set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
  163.   wifiManager.setAPCallback(configModeCallback);
  164.   // tries to connect to last known settings
  165.   // if it does not connect it starts an access point
  166.   // and goes into a blocking loop awaiting configuration
  167.   if (!wifiManager.autoConnect()) {
  168.     Serial.println(F("Failed to connect to WiFi and hit timeout"));
  169.     // reset and try again, or maybe put it to deep sleep
  170.     ESP.reset();
  171.     delay(1000);
  172.   }
  173.   Serial.print(F("Successfully connected to SSID '"));
  174.   Serial.print(WiFi.SSID());
  175.   Serial.print(F("' - local IP: "));
  176.   Serial.println(WiFi.localIP());
  177.   // Start the application server
  178.   Serial.print(F("Starting Application HTTP Server on port "));
  179.   Serial.println(serverPort);
  180.   server.begin();
  181.  
  182.   // Enable Arduino OTA (if we have enough room to update in place)
  183.   if (ESP.getSketchSize() < ESP.getFreeSketchSpace()) {
  184.     Serial.println(F("Starting OTA Server..."));
  185.     ArduinoOTA.setHostname(deviceName.c_str());
  186.     ArduinoOTA.setPassword(OTApassword);
  187.  
  188.     ArduinoOTA.onStart([]() {
  189.       Serial.println(F("Start"));
  190.     });
  191.     ArduinoOTA.onEnd([]() {
  192.       Serial.println(F("End"));
  193.       ESP.reset();
  194.     });
  195.     ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  196.       Serial.printf((const char *)F("Progress: %u%%\n"), (progress / (total / 100)));
  197.     });
  198.     ArduinoOTA.onError([](ota_error_t error) {
  199.       Serial.printf((const char *)F("Error[%u]: "), error);
  200.       if (error == OTA_AUTH_ERROR) Serial.println(F("Auth Failed"));
  201.       else if (error == OTA_BEGIN_ERROR) Serial.println(F("Begin Failed"));
  202.       else if (error == OTA_CONNECT_ERROR) Serial.println(F("Connect Failed"));
  203.       else if (error == OTA_RECEIVE_ERROR) Serial.println(F("Receive Failed"));
  204.       else if (error == OTA_END_ERROR) Serial.println(F("End Failed"));
  205.       ESP.reset();
  206.     });
  207.     ArduinoOTA.begin();
  208.   }
  209.  
  210.   Serial.println(F("*** Application ready."));
  211. }
  212.  
  213. // send json data to client connection
  214. void sendJSONData(WiFiClient client) {
  215.   client.println(F("CONTENT-TYPE: application/json"));
  216.   client.println(F("CONTENT-LENGTH: 29"));
  217.   client.println();
  218.   client.print("{\"name\":\"contact\",\"status\":");
  219.   client.print(currentSensorState);
  220.   client.println("}");
  221. }
  222.  
  223. // send response to client for a request for status
  224. void handleRequest(WiFiClient client)
  225. {
  226.   // Wait until the client sends some data
  227.   Serial.print(F("Received request: "));
  228.   while(!client.available()){
  229.     delay(1);
  230.   }
  231.  
  232.   // Read the first line of the request
  233.   String req = client.readStringUntil('\r');
  234.   Serial.println(req);
  235.   if (!req.indexOf(F("GET")))
  236.   {
  237.     client.flush(); // we don't care about anything else for a GET request
  238.   }
  239.  
  240.   // Match the request
  241.   if (req.indexOf(F("/getstatus")) != -1) {
  242.     client.println(F("HTTP/1.1 200 OK")); //send new page
  243.     sendJSONData(client);
  244.   }
  245.   else if (req.indexOf(F("POST /updateSettings")) != -1) {
  246.     // get the body in order to retrieve the POST data
  247.     while (client.available() && client.readStringUntil('\r').length() > 1);
  248.     String settingsJSON = client.readStringUntil('\r');
  249.     client.flush();
  250.     const int BUFFER_SIZE = JSON_OBJECT_SIZE(3);
  251.     StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
  252.     JsonObject& root = jsonBuffer.parseObject(settingsJSON);
  253.     if (root[FPSTR(HUPIP)]) hubIp = IPfromString(root[FPSTR(HUPIP)]);
  254.     if (root[FPSTR(HUBPORT)]) hubPort = root[FPSTR(HUBPORT)];
  255.     if (root[FPSTR(DEVICENAME)]) {
  256.       String newDeviceName = root[FPSTR(DEVICENAME)];
  257.       deviceName = newDeviceName;
  258.     }
  259.     saveAppConfig(settingsJSON);
  260.     client.println(F("HTTP/1.1 204 No Content"));
  261.     client.println();
  262.     client.println();
  263.   }
  264.   else {
  265.     client.println(F("HTTP/1.1 204 No Content"));
  266.     client.println();
  267.     client.println();
  268.   }
  269.  
  270.   delay(1);
  271.   //stopping client
  272.   client.stop();
  273. }
  274.  
  275. // send data
  276. int sendNotify() //client function to send/receieve POST data.
  277. {
  278.   int returnStatus = 1;
  279.   if (client.connect(hubIp, hubPort)) {
  280.     client.println(F("POST / HTTP/1.1"));
  281.     client.print(F("HOST: "));
  282.     client.print(hubIp);
  283.     client.print(F(":"));
  284.     client.println(hubPort);
  285.     sendJSONData(client);
  286.     Serial.println(F("Pushing new values to hub..."));
  287.   }
  288.   else {
  289.     //connection failed
  290.     returnStatus = 0;
  291.     Serial.println(F("Connection to hub failed."));
  292.   }
  293.  
  294.   // read any data returned from the POST
  295.   while(client.connected() && !client.available()) delay(1); //waits for data
  296.   while (client.connected() || client.available()) { //connected or data available
  297.     char c = client.read();
  298.   }
  299.  
  300.   delay(1);
  301.   client.stop();
  302.   return returnStatus;
  303. }
  304.  
  305. void contactChanged() {
  306.   if((long)(micros() - last_micros) >= debounceDelay * 1000) {
  307.     currentSensorState = digitalRead(CONTACT_PIN);
  308.     if (currentSensorState != oldSensorState) {
  309.       sendUpdate = true;
  310.     }
  311.     last_micros = micros();
  312.   }
  313. }
  314.  
  315. void loop() {
  316.   if (sendUpdate) {
  317.     if (hubIp != INADDR_NONE && sendNotify()) {
  318.       // update old sensor state after we’ve sent the notify
  319.       oldSensorState = currentSensorState;
  320.     }
  321.     sendUpdate = false;
  322.   }
  323.   ArduinoOTA.handle();
  324.   // Handle any incoming requests
  325.   WiFiClient client = server.available();
  326.   if (client) {
  327.     handleRequest(client);
  328.   }  
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement