Advertisement
Guest User

Untitled

a guest
Mar 26th, 2016
1,536
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.80 KB | None | 0 0
  1. /*
  2.   This sketch is intended to toggle a button in reponse to incoming MQTT messages.
  3.  
  4.   Many devices have a power button that can be momentarily pressed to toggle power
  5.   on and off.  Further, the device will often have something like a power LED that
  6.   can be monitored to determine the device's power state.
  7.  
  8.   This sketch will monitor the configured MQTT topic for "on" and "off" events.  It
  9.   will also monitor a selected pin to determine if the local device is "on" or "off".
  10.   If the local state is "off" and an "on" message is received, it will momentarily
  11.   toggle the output pin to turn the device on.  Likewise, if the monitored device
  12.   is "on" and an incoming message for "off" is received, the power button pin will be
  13.   toggled to turn the device off.
  14.  
  15.   The sketch will also monitor the power LED and publish an outgoing MQTT message when
  16.   the power state changes.  This will capture local user interaction and update MQTT
  17.   with the new power state.
  18.  
  19.   Finally, the sketch will periodically announce its local state every minute.
  20.  
  21.   HARDWARE NOTES:
  22.     * The power button pin can be connected to a relay or an optoisolator or similar device
  23.     to actuate the device's power button.  A pull-down resistor will probably be needed.
  24.     * The power monitor pin can be connected to one leg of an LED or maybe VCC of the
  25.     controlled device to detect the power state.  Keep in mind input voltage limits.
  26.  
  27.   REQUIREMENTS: PubSubClient
  28.   Large portions of the code here are based on the "Basic ESP8266 MQTT example" from
  29.   PubSubClient by Nick O'Leary available at http://pubsubclient.knolleary.net/
  30. */
  31.  
  32. #include <ESP8266WiFi.h>
  33. #include <PubSubClient.h>
  34. #include <ESP8266mDNS.h>
  35. #include <WiFiUdp.h>
  36. #include <ArduinoOTA.h>
  37.  
  38. #define DEBUG true // flag to turn on/off debug messages over serial
  39. #define Serial if(DEBUG)Serial
  40.  
  41. // Update these with values suitable for your network.
  42.  
  43. const char* ssid = "linksys";  // Your WiFi network name
  44. const char* password = "default";  // Your WiFi network password
  45. const char* mqtt_server = "192.168.1.199";  // Your MQTT server IP address
  46.  
  47. // This is the topic to be subscribed and published to
  48. const char* mqtt_topic = "smartthings/Tea Kettle/switch";
  49. const char* mqtt_onMessage = "on";
  50. const char* mqtt_offMessage = "off";
  51.  
  52. const int powerButton = D1;
  53. const int holdButton = D2;
  54. const int powerMonitor = D0;
  55. //const int ledPin = D4; // built-in LED on D1 mini
  56.  
  57. const int powerButtonHoldTime = 100; // How long should the button be held for toggle
  58. const int powerButtonWaitTime = 100; // How long to wait for the system to power up after toggling the power button
  59.  
  60. WiFiClient espClient;
  61. PubSubClient client(espClient);
  62.  
  63. long lastMsg = 0;
  64. int powerSetState = 0;
  65.  
  66. void setup_wifi() {
  67.   delay(10);
  68.   // We start by connecting to a WiFi network
  69.   Serial.println();
  70.   Serial.print("Connecting to WiFi network: ");
  71.   Serial.print(ssid);
  72.  
  73.   WiFi.begin(ssid, password);
  74.  
  75.   while (WiFi.status() != WL_CONNECTED) {
  76.     delay(500);
  77.     Serial.print(".");
  78.   }
  79.  
  80.   Serial.println("");
  81.   Serial.print("WiFi connected succesfully and assigned IP: ");
  82.   Serial.println(WiFi.localIP());
  83. }
  84.  
  85. void callback(char* topic, byte* payload, unsigned int length) {
  86.   String inMessage;
  87.   for (int i = 0; i < length; i++) {
  88.     inMessage += (char)payload[i];
  89.   }
  90.   Serial.print("Incoming message ");
  91.   Serial.print(topic);
  92.   Serial.print(": ");
  93.   Serial.println(inMessage);
  94.  
  95.   if (inMessage == mqtt_onMessage) {
  96.     Serial.println("Received MQTT power on message");
  97.     int powerMonitorState = digitalRead(powerMonitor);
  98.     powerSetState = 1;
  99.     if (powerMonitorState == 0) {
  100.       Serial.println("Toggling power on");
  101.       digitalWrite(powerButton, HIGH);
  102.       delay(powerButtonHoldTime);
  103.       digitalWrite(powerButton, LOW);
  104.       delay(powerButtonWaitTime);
  105.       digitalWrite(holdButton, HIGH);
  106.       delay(powerButtonHoldTime);
  107.       digitalWrite(holdButton, LOW);
  108.       delay(powerButtonWaitTime);
  109.     }
  110.   }
  111.   else if (inMessage == mqtt_offMessage) {
  112.     Serial.println("Received MQTT power off message");
  113.     powerSetState = 0;
  114.     int powerMonitorState = digitalRead(powerMonitor);
  115.     if (powerMonitorState == 1) {
  116.       Serial.println("Toggling power off");
  117.       digitalWrite(powerButton, HIGH);
  118.       delay(powerButtonHoldTime);
  119.       digitalWrite(powerButton, LOW);
  120.       delay(powerButtonWaitTime);
  121.     }
  122.   }
  123.   else {
  124.     Serial.print("No match for message: ");
  125.     Serial.println(inMessage);
  126.   }
  127.  
  128. }
  129.  
  130. void reconnect() {
  131.   // Loop until we're reconnected to MQTT
  132.   while (!client.connected()) {
  133. //    digitalWrite(ledPin, LOW);
  134.     Serial.print("Attempting MQTT connection to broker: ");
  135.     Serial.println(mqtt_server);
  136.     // Attempt to connect
  137.     if (client.connect("ESP8266Client")) {
  138. //      digitalWrite(ledPin, HIGH);
  139.       Serial.println("MQTT connected");
  140.       client.publish(mqtt_topic, "Connected");
  141.       // Subscribe to our selected topic
  142.       client.subscribe(mqtt_topic);
  143.     }
  144.     else {
  145. //      digitalWrite(ledPin, LOW);
  146.       Serial.print("MQTT connection failed, rc=");
  147.       Serial.print(client.state());
  148.       Serial.println(".  Trying again in 5 seconds.");
  149.       // Wait 5 seconds before retrying
  150.       delay(5000);
  151.     }
  152.   }
  153. }
  154.  
  155. void setup_OTA() {
  156.   // Start up OTA
  157.  
  158.   // ArduinoOTA.setPort(8266); // Port defaults to 8266
  159.   // ArduinoOTA.setHostname("myesp8266"); // Hostname defaults to esp8266-[ChipID]
  160.   // ArduinoOTA.setPassword((const char *)"123"); // No authentication by default
  161.  
  162.   ArduinoOTA.onStart([]() {
  163.     Serial.println("OTA update start");
  164.     client.publish(mqtt_topic, "OTA update start");
  165.   });
  166.   ArduinoOTA.onEnd([]() {
  167.     Serial.println("\nOTA update complete");
  168.     client.publish(mqtt_topic, "OTA update complete");
  169.   });
  170.   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  171.     Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  172.   });
  173.   ArduinoOTA.onError([](ota_error_t error) {
  174.     Serial.printf("OTA Error[%u]: ", error);
  175.     if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
  176.     else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
  177.     else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
  178.     else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
  179.     else if (error == OTA_END_ERROR) Serial.println("End Failed");
  180.   });
  181.   ArduinoOTA.begin();
  182.   Serial.println("OTA firmware update ready");  
  183. }
  184.  
  185. void setup() {
  186.   // Deal with hardware first
  187.   pinMode(powerButton, OUTPUT);
  188.   pinMode(holdButton, OUTPUT);
  189.   pinMode(powerMonitor, INPUT_PULLUP);
  190. //  pinMode(ledPin, OUTPUT);
  191.  
  192.   // Record the current state as the desired set state, possibly to be
  193.   // overwritten when we start MQTT
  194.   powerSetState = digitalRead(powerMonitor);
  195.  
  196.   Serial.begin(115200);
  197.   Serial.println("");
  198.   Serial.println("Hardware initialized, starting program load");
  199.  
  200.   // Start up networking
  201.   setup_wifi();
  202.  
  203.   // Start up MQTT
  204.   client.setServer(mqtt_server, 1883);
  205.   client.setCallback(callback);
  206.  
  207.   // Start up OTA
  208.   setup_OTA();
  209. }
  210.  
  211. void loop() {
  212.   if (!client.connected()) {
  213.     reconnect();
  214.   }
  215.  
  216.   // MQTT client loop
  217.   client.loop();
  218.  
  219.   // OTA loop
  220.   ArduinoOTA.handle();
  221.  
  222.   // If our local state has changed against the set state, publish a message to MQTT
  223.   int powerMonitorState = digitalRead(powerMonitor);
  224.   //Serial.print("powerMonitorState: ");
  225.   //Serial.println(powerMonitorState);
  226.   //delay(1000);
  227.  
  228.   if ((powerMonitorState == 0) && (powerSetState == 1)) {
  229.     Serial.println("Caught local power off, publishing to MQTT");
  230.     client.publish(mqtt_topic, mqtt_offMessage);
  231.     powerSetState = 0;
  232.   }
  233.   else if ((powerMonitorState == 1) && (powerSetState == 0)) {
  234.     Serial.println("Caught local power on, publishing to MQTT");
  235.     client.publish(mqtt_topic, mqtt_onMessage);
  236.     powerSetState = 1;
  237.  
  238.     // In this case, somebody pressed power locally.  We need to press "hold"
  239.     // after the power button has been released by the user, but I have no way
  240.     // to monitor that action.  Instead, wait 1 second then send the hold toggle.
  241.     // This way, the user can override the auto-hold by simply holding down the
  242.     // power button for longer than a second.
  243.     delay (1000);
  244.     digitalWrite(holdButton, HIGH);
  245.     delay(powerButtonHoldTime);
  246.     //delay(5000);
  247.     digitalWrite(holdButton, LOW);
  248.   }
  249.  
  250.   // Publish current state to topic every five minutes
  251.   long now = millis();
  252.   if (now - lastMsg > 300000) {
  253.     lastMsg = now;
  254.     if (powerMonitorState) {
  255.       Serial.print("Periodic publishing 'on' to topic: ");
  256.       Serial.println(mqtt_topic);
  257.       client.publish(mqtt_topic, "on");
  258.     }
  259.     else {
  260.       Serial.print("Periodic publishing 'off' to topic: ");
  261.       Serial.println(mqtt_topic);
  262.       client.publish(mqtt_topic, "off");
  263.     }
  264.   }
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement