// InlineWiFiPowerSwitch // Rev 4 revised for pfodApp V2 and pfodParser V2.34 // Rev 3 revised for ESP8266.com IDE plug-in V2.2, needs V2.2 of pfodESP8266BufferedClient library // Rev 2 Added auto reconnect to WiFi network if connection lost, needs V2.0.2 of pfodESP8266WiFi library /* To Config Remove power, press pushbutton, apply power and connect to the pfodWifiWebConfig access point using the password set in #define pfodSecurityCode (below) Scan this password from the QR code generated with http://www.forward.com.au/pfod/secureChallengeResponse/keyGenerator/index.html Once you connect to the Access Point open the webpage http://10.1.1.1 to setup your network parameters ssid, password and either DHCP or staticIP and portNo. Then when you reboot (without pressing the pusbbutton) the switch will connect to your network and you can control it via pfodApp using the ip:portNo you setup */ /* ===== pfod Command for Inline Power Switch ==== pfodApp msg {.} --> {,<+2>~Extension Cord Inline Power Switch`1000~V3|!B<+7>~|A<+6>`0~Extension Power is ~~Off\On~} */ // Using ESP8266 based board programmed via Arduino IDE // follow the steps given on https://github.com/esp8266/arduino under Installing With Boards Manager // You need to modify the WLAN_SSID, WLAN_PASS settings below // to match your network settings /* Code generated by pfodDesignerV2 V2.0.2082 * (c)2014-2016 Forward Computing and Control Pty. Ltd. * NSW Australia, www.forward.com.au * This generated code may be freely used for both private and commercial use */ #include // Download pfodESP8266BufferedClient library from http://www.forward.com.au/pfod/pfodParserLibraries/index.html #include #include #include // Download pfodParser library from http://www.forward.com.au/pfod/pfodParserLibraries/index.html #include // V2.31 or higher int swap01(int); // method prototype for slider end swaps pfodSecurity parser("V3m"); // create a parser to handle the pfod messages pfodESP8266BufferedClient bufferedClient; // =============================== extra library and definitions for push button =============================== // add DeboucedSwitch library #include // Download library from http://www.forward.com.au/pfod/ArduinoProgramming/DebouncedSwitch/DebouncedSwitch.html // define push button int pushbutton_pin = 4; // name the input pin for setup mode detection GPIO2 on most ESP8266 boards // define DeboucedSwitch DebouncedSwitch sw(pushbutton_pin); // monitor a switch on input pushbutton_pin // ===================================================================================================== // =============== start of pfodESP8266WebConfig settings ============== // add includes for Web Config #include #include // Access point password is same as pfodSecurityCode #define pfodWifiWebConfigAP "pfodWifiWebConfig" // note pfodSecurity uses 19 bytes of eeprom usually starting from 0 so // start the eeprom address from 20 for configureWifiConfig const uint8_t webConfigEEPROMStartAddress = 20; pfodESP8266WebConfig webConfig(webConfigEEPROMStartAddress); // webConfig for ESP8266 // =============== end of pfodESP8266WebConfig settings ============== // ----------------------------------- // These settings not used as web page sets network settings //#define WLAN_SSID "myNetwork" // cannot be longer than 32 characters! //#define WLAN_PASS "myPassword" //const int portNo = 4989; // not used //const char staticIP[] = ""; // not used // ----------------------------------------- // add you 32 char Hex pfod Password here for 128bit security // eg "b0Ux9akSiwKkwCtcnjTnpWp" but generate your own key, "" means no pfod password // update this define with the password from your QR code // http://www.forward.com.au/pfod/secureChallengeResponse/keyGenerator/index.html // 128bit password encoded in ascii #define pfodSecurityCode "b0Ux9akSiwKkwCtcnjTnpWp" // see http://www.forward.com.au/pfod/ArduinoWiFi_simple_pfodDevice/index.html for more information and an example // and QR image key generator. WiFiServer server(80); // server is re-initialize below with correct portNo WiFiClient client; boolean alreadyConnected = false; // whether or not the client was connected previously // give the board pins names, if you change the pin number here you will change the pin controlled int cmd_A_var; // name the variable for 'Extension Power is ' const int cmd_A_pin = 5; // name the output pin for 'Extension Power is ' // the setup routine runs once on reset: void setup() { EEPROM.begin(512); // only use 20bytes for pfodSecurity but reserve 512 (pfodWifiConfig uses more) cmd_A_var = 0; //pinMode(cmd_A_pin, INPUT_PULLUP); pinMode(cmd_A_pin, OUTPUT); // output for 'Extension Power is ' is initially LOW, //uncomment INPUT_PULLUP line above and set variable to 1, if you want it initially HIGH digitalWrite(cmd_A_pin, cmd_A_var); // set output #ifdef DEBUG Serial.begin(115200); #endif #ifdef DEBUG for (int i = 10; i > 0; i--) { Serial.print(i); Serial.print(' '); delay(500); } Serial.println(); #endif //============ pfodESP8266WebConfig config in Access Point mode ==================== // see if config button is pressed if (digitalRead(pushbutton_pin) == LOW) { #ifdef DEBUG Serial.println(F("Setting up Access Point for pfodWifiWebConfig")); #endif // connect to temporary wifi network for setup // the features determine the format of the {set...} command webConfig.setupAP(pfodWifiWebConfigAP, pfodSecurityCode); while (1) { webConfig.handleClient(); // process the requests delay(0); } // Need to reboot afterwards } //============ end pfodESP8266WebConfig config ==================== // else button was not pressed continue to load the stored network settings from EEPROM and join network WiFi.mode(WIFI_STA); // load existing config if there is one pfodESP8266WebConfig::BASIC_STORAGE *storage = webConfig.loadConfig(); server.close(); // close any existing server server = WiFiServer(storage->portNo); // Start the server server.begin(); #ifdef DEBUG Serial.print("Server started on "); Serial.println(storage->portNo); #endif // initialize client client = server.available(); // evaluates to false if no connection // <<<<<<<<< Your extra setup code goes here } // the loop routine runs over and over again forever: void loop() { webConfig.joinWiFiIfNotConnected(); // rejoin if we lost WiFi network if (!client) { // see if a client is available client = server.available(); // evaluates to false if no connection } else { // have client if (!client.connected()) { if (alreadyConnected) { // client closed so clean up closeConnection(parser.getPfodAppStream()); } } else { // have connected client if (!alreadyConnected) { parser.connect(bufferedClient.connect(&client), F(pfodSecurityCode)); // sets new io stream to read from and write to EEPROM.commit(); // does nothing if nothing to do alreadyConnected = true; } byte cmd = parser.parse(); // parse incoming data from connection // parser returns non-zero when a pfod command is fully parsed if (cmd != 0) { // have parsed a complete msg { to } byte* pfodFirstArg = parser.getFirstArg(); // may point to \0 if no arguments in this msg. long pfodLongRtn; // used for parsing long return arguments, if any if ('.' == cmd) { // pfodApp has connected and sent {.} , it is asking for the main menu if (!parser.isRefresh()) { sendMainMenu(); // send back the menu designed } else { sendMainMenuUpdate(); // menu is cached just send update } // now handle commands returned from button/sliders // } else if('B'==cmd) { // this is a label. pfodApp NEVER sends this cmd -- '' // // in the main Menu of Inline Power Switch } else if ('A' == cmd) { // user moved slider -- 'Extension Power is ' // in the main Menu of Inline Power Switch // set output based on slider 0 == LOW, 1 == HIGH parser.parseLong(pfodFirstArg, &pfodLongRtn); // parse first arg as a long cmd_A_var = (int)pfodLongRtn; // set variable digitalWrite(cmd_A_pin, cmd_A_var); // set output sendMainMenuUpdate(); // always send back a pfod msg otherwise pfodApp will disconnect. } else if ('!' == cmd) { // CloseConnection command closeConnection(parser.getPfodAppStream()); } else { // unknown command parser.print(F("{}")); // always send back a pfod msg otherwise pfodApp will disconnect. } } } } // <<<<<<<<<<< Your other loop() code goes here sw.update(); // call this every loop to update switch state if (sw.isChanged()) { // debounced switch changed state Up or Down // isChanged() is only true for one loop(), cleared when update() called again if (!sw.isDown()) { // switch was just released // toggle the state cmd_A_var = swap01(cmd_A_var); digitalWrite(cmd_A_pin, cmd_A_var); // set output } } } void closeConnection(Stream *io) { // add any special code here to force connection to be dropped parser.closeConnection(); // nulls io stream alreadyConnected = false; bufferedClient.stop(); // clears client reference WiFiClient::stopAll(); // cleans up memory client = server.available(); // evaluates to false if no connection } void sendMainMenu() { // !! Remember to change the parser version string // every time you edit this method parser.print(F("{,")); // start a Menu screen pfod message // send menu background, format, prompt, refresh and version parser.print(F("<+2>~Extension Cord Inline Power Switch`1000")); parser.sendVersion(); // send the menu version // send menu items parser.print(F("|!B<+7>")); parser.print(F("~")); parser.print(F("|A")); if (cmd_A_var == 1) { parser.print(F("")); // red if on } else { parser.print(F("")); // black if off } parser.print(F("<+6>")); parser.print('`'); parser.print(cmd_A_var); // output the current state 0 Low or 1 High parser.print(F("~Extension Power is\n~~Off\\On~")); // Note the \\ inside the "'s to send \ ... parser.print(F("}")); // close pfod message } void sendMainMenuUpdate() { parser.print(F("{;")); // start an Update Menu pfod message // send menu items parser.print(F("|A")); if (cmd_A_var == 1) { parser.print(F("")); // red if on } else { parser.print(F("")); // black if off } parser.print('`'); parser.print(cmd_A_var); // output the current state 0 Low or 1 High parser.print(F("}")); // close pfod message // ============ end of menu =========== } int swap01(int in) { return (in == 0) ? 1 : 0; } // ============= end generated code =========