// ESP_GW_V1.0 // // This MQTT client will connect over Wifi to the MQTT broker and controls a digital output (LED, relay): // - toggle output and send status message on local button press // - receive messages from the MQTT broker to control output, change settings and query state // - periodically send status messages // // Several nodes can operate within the same network; each node has a unique node ID. // On startup the node operates with default values, as set during compilation. // Hardware used is a ESP8266 WiFi module that connects directly to the MQTT broker. // // Message structure is equal to the RFM69-based gateway/node sytem by the same author. // This means both type of gateway/nodes can be used in a single Openhab system. // // The MQTT topic is /home/esp_gw/direction/nodeid/devid // where direction is "sb" towards the node and "nb" towards the MQTT broker. // // Defined devices are: // 0 uptime: read uptime in minutes // 1 interval: read/set transmission interval for push messages // 3 version: read software version // 5 ACK: read/set acknowledge message after a 'set' request // 6 toggle: read/set select toggle / timer function // 7 timer: read/set timer interval in seconds // 16 actuator: read/set LED or relay output // 40 button: tx only: message sent when button pressed // 92 error: tx only: device not supported // 91 error: tx only: syntax error // 99 wakeup: tx only: first message sent on node startup // // Hardware connections: // - pin 0 is connected to a button that switches to GND, pullup to VCC // - pin 2 is connected to LED and current limiting resistor to GND // // version 1.0 by computourist@gmail.com May 2016 // #include #include #define VERSION "WDIG V1.0" // this value can be queried as device 3 #define wifi_ssid "xxxxx" // wifi station name #define wifi_password "xxxxxx" // wifi password #define mqtt_server "192.168.xxx.xxx" // mqtt server IP #define nodeId 80 // node ID // sensor setting #define ACT1 2 // Actuator pin (LED or relay to ground) #define BTN 0 // Button pin (also used for Flash setting) #define SERIAL_BAUD 115200 #define HOLDOFF 1000 // blocking period between button messages // STARTUP DEFAULTS long TXinterval = 60; // periodic transmission interval in seconds long TIMinterval = 20; // timer interval in seconds bool ackButton = false; // flag for message on button press bool toggleOnButton = true; // toggle output on button press // VARIABLES int DID; // Device ID int error; // Syntax error code long lastPeriod = -1; // timestamp last transmission long lastBtnPress = -1; // timestamp last buttonpress long lastMinute = -1; // timestamp last minute long upTime = 0; // uptime in minutes int ACT1State; // status ACT1 output bool wakeUp = true; // wakeup indicator bool setAck = false; // acknowledge receipt of actions bool curState = true; // current button state bool lastState = true; // last button state bool timerOnButton = false; // timer output on button press bool msgBlock = false; // flag to hold button message bool readAction; // indicates read / set a value bool send0, send1, send3, send5, send6, send7; bool send16, send40, send99; // message triggers char buff_topic[30]; // mqtt topic char buff_msg[32]; // mqtt message void mqttSubs(char* topic, byte* payload, unsigned int length); WiFiClient espClient; PubSubClient client(mqtt_server, 1883, mqttSubs, espClient); // instantiate MQTT client // FUNCTIONS //=============================================================================================== void pubMQTT(String topic, String topic_val){ // publish MQTT message to broker Serial.print("topic " + topic + " value:"); Serial.println(String(topic_val).c_str()); client.publish(topic.c_str(), String(topic_val).c_str(), true); } void mqttSubs(char* topic, byte* payload, unsigned int length) { // receive and handle MQTT messages int i; error = 4; // assume invalid device until proven otherwise Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); if (strlen(topic) == 27) { // correct topic length ? DID = (topic[25]-'0')*10 + topic[26]-'0'; // extract device ID from MQTT topic payload[length] = '\0'; // terminate string with '0' String strPayload = String((char*)payload); // convert to string readAction = false; // default is 'SET' value if (strPayload == "READ") readAction = true; // in this case 'READ' value if (length == 0) {error = 2;} // no payload sent else { if (DID ==0) { // uptime if (readAction) { sprintf(buff_topic, "home/esp_gw/nb/node%02d/dev00", nodeId); sprintf(buff_msg, "%d", upTime); pubMQTT(buff_topic, buff_msg); error = 0; } else error = 3; // invalid payload; do not process } if (DID==1) { // transmission interval error = 0; if (readAction) { sprintf(buff_topic, "home/esp_gw/nb/node%02d/dev01", nodeId); sprintf(buff_msg, "%d", TXinterval); pubMQTT(buff_topic, buff_msg); } else { // set transmission interval TXinterval = strPayload.toInt(); if (TXinterval <10 && TXinterval !=0) TXinterval = 10; // minimum interval is 10 seconds } } if (DID==3) { // version if (readAction) { sprintf(buff_topic, "home/esp_gw/nb/node%02d/dev03", nodeId); for (i=0; i 0 && !timerOnButton) { // button in timer state ? timerOnButton = true; // start timer interval ACT1State = HIGH; // switch on ACT1 digitalWrite(ACT1, ACT1State); }} lastState = curState; } // TIMER CHECK if (TIMinterval > 0 && timerOnButton) { // =0 means no timer if ( millis() - lastBtnPress > TIMinterval*1000) { // timer expired ? timerOnButton = false; // then end timer interval ACT1State = LOW; // and switch off Actuator digitalWrite(ACT1, ACT1State); } } // INCREASE UPTIME if (lastMinute != (millis()/60000)) { // another minute passed ? lastMinute = millis()/60000; upTime++; } // PERIODIC TRANSMISSION if (TXinterval > 0){ int currPeriod = millis()/(TXinterval*1000); if (currPeriod != lastPeriod) { // interval elapsed ? lastPeriod = currPeriod; // list of sensordata to be sent periodically.. // remove comment to include parameter in transmission send3 = true; // send version send16 = true; // output state } } sendMsg(); // send any mqtt messages } // end loop