
/* ===== pfod Command for Menu_1 ====
pfodApp msg {.} --> {,<bg bl><b><+5>~ESP32 Led
<-5>(Sparkfun ESP32 Thing)`0~V12|A`0~Led ~%`255`0~100~0~}
 */
// Using ESP32 based board programmed via Arduino IDE
// follow the steps given on http://www.forward.com.au/pfod/ESP32/index.html to install ESP32 support for Arduino IDE

// You need to modify the WLAN_SSID, WLAN_PASS settings below 
// to match your network settings 

/* Code generated by pfodDesignerV3 V3.0.3305
 */
/*
 * (c)2014-2018 Forward Computing and Control Pty. Ltd.
 * NSW Australia, www.forward.com.au
 * This code is not warranted to be fit for any purpose. You may only use it at your own risk.
 * This generated code may be freely used for both private and commercial use
 * provide this copyright is maintained.
 */

#include <pfodEEPROM.h>
#include <WiFi.h>
#define DEBUG
  
// Download pfodESP32BufferedClient library from http://www.forward.com.au/pfod/pfodParserLibraries/index.html
// pfodESP32BufferedClient.zip contains pfodESP32BufferedClient and pfodESP32Utils
#include <pfodESP32Utils.h>
#include <pfodESP32BufferedClient.h>
  
// download the libraries from http://www.forward.com.au/pfod/pfodParserLibraries/index.html
// pfodParser.zip V3.26+ contains pfodParser, pfodSecurity, pfodBLEBufferedSerial, pfodSMS and pfodRadio

#include <pfodSecurity.h> 
int swap01(int); // method prototype for slider end swaps

pfodSecurity parser("V13"); // create a parser with menu version string to handle the pfod messages
pfodESP32BufferedClient bufferedClient;


#define WLAN_SSID       "myNetwork"        // cannot be longer than 32 characters!
#define WLAN_PASS       "myPassword"

const int portNo = 4989; // What TCP port to listen on for connections.
const char staticIP[] = "";  // set this the static IP you want, e.g. "10.1.1.200" or leave it as "" for DHCP. DHCP is not recommended.

// add your pfod Password here for 128bit security
// eg "b0Ux9akSiwKkwCtcnjTnpWp" but generate your own key, "" means no pfod password
#define pfodSecurityCode ""
// 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(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 'Led'
const int cmd_A_pin = 5; // name the output 5 for 'Led'
const int cmd_A_channel = 0; // channel to use for this PWM output 

// the setup routine runs once on reset:
void setup() {
  // Explicitly set the ESP32 to be a WiFi-client, otherwise, it by default,
  // would try to act as both a client and an access-point and could cause
  // network-issues with your other WiFi-devices on your WiFi-network. 
  WiFi.mode(WIFI_STA);
  EEPROM.begin(512);  // only use 20bytes for pfodSecurity but reserve 512 (pfodWifiConfig uses more)
  cmd_A_var = 0;
  ledcAttachPin(cmd_A_pin,cmd_A_channel); // assign pin to channel
  ledcSetup(cmd_A_channel, 490, 8); // 490hz PWM, 8-bit resolution to match Arduino Uno
  pfodESP32Utils::analogWrite(cmd_A_channel,cmd_A_var); // set PWM output
  #ifdef DEBUG
    Serial.begin(115200);
    Serial.println();
  #endif
    /* Initialise wifi module */
    if (*staticIP != '\0') {
      IPAddress ip(pfodESP32Utils::ipStrToNum(staticIP));
      IPAddress gateway(ip[0], ip[1], ip[2], 1); // set gatway to ... 1
  #ifdef DEBUG
      Serial.print(F("Setting gateway to: "));
      Serial.println(gateway);
  #endif
      IPAddress subnet(255, 255, 255, 0);
      WiFi.config(ip, gateway, subnet);
    }
    WiFi.begin(WLAN_SSID, WLAN_PASS);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
  #ifdef DEBUG
      Serial.print(".");
  #endif
    }
  #ifdef DEBUG
    Serial.println();
    Serial.println("WiFi connected");
  #endif
  
    // Start the server
    server.begin();
  #ifdef DEBUG
    Serial.println("Server started");
  #endif
  
    // Print the IP address
  #ifdef DEBUG
    Serial.println(WiFi.localIP());
  #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() {
  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;
      }

      uint8_t 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 }
        uint8_t* pfodFirstArg = parser.getFirstArg(); // may point to \0 if no arguments in this msg.
        pfod_MAYBE_UNUSED(pfodFirstArg); // may not be used, just suppress warning
        long pfodLongRtn; // used for parsing long return arguments, if any
        pfod_MAYBE_UNUSED(pfodLongRtn); // may not be used, just suppress warning
        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('A'==cmd) { // user moved PWM slider -- 'Led'
          // in the main Menu of Menu_1 
          parser.parseLong(pfodFirstArg,&pfodLongRtn); // parse first arg as a long
          cmd_A_var = (int)pfodLongRtn; // set variable
          pfodESP32Utils::analogWrite(cmd_A_channel,cmd_A_var); // set PWM 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 
  
}

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
  client.stop(); // 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("<bg bl><b><+5>~ESP32 Led\n<-5>(Sparkfun ESP32 Thing)`0"));
  parser.sendVersion(); // send the menu version 
  // send menu items
  parser.print(F("|A"));
  parser.print('`');
  parser.print(cmd_A_var); // output the current PWM setting
  parser.print(F("~Led ~%`255`0~100~0~"));
  parser.print(F("}"));  // close pfod message
}

void sendMainMenuUpdate() {
  parser.print(F("{;"));  // start an Update Menu pfod message
  // send menu items
  parser.print(F("|A"));
  parser.print('`');
  parser.print(cmd_A_var); // output the current PWM setting
  parser.print(F("}"));  // close pfod message
  // ============ end of menu ===========
}

int swap01(int in) {
  return (in==0)?1:0;
}
// ============= end generated code =========
 
