/* ===== pfod Command for Menu_1 ==== pfodApp msg {.} --> {,<+5>~Adafruit WICED`0~V1|A<+5>`0~LED brightness ~%`65535`0~100~0~} */ // Using Adafruit Feather WICED board // You need to modify the WLAN_SSID, WLAN_PASS settings below // to match your network settings /* Code generated by pfodDesignerV2 V2.0.2214 * (c)2014-2016 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. */ int swap01(int); // method prototype for slider end swaps uint32_t ipStrToNum(const char* ipStr); // ====================== // this is the pfodParser.h V2 file with the class renamed pfodParser_codeGenerated and with comments, constants and un-used methods removed class pfodParser_codeGenerated: public Print { public: pfodParser_codeGenerated(const char* version); pfodParser_codeGenerated(); void connect(Stream* ioPtr); void closeConnection(); byte parse(); bool isRefresh(); const char* getVersion(); void setVersion(const char* version); void sendVersion(); byte* getCmd(); byte* getFirstArg(); byte* getNextArg(byte *start); byte getArgsCount(); byte* parseLong(byte* idxPtr, long *result); byte getParserState(); void setCmd(byte cmd); void setDebugStream(Print* debugOut); size_t write(uint8_t c); int available(); int read(); int peek(); void flush(); void setIdleTimeout(unsigned long timeout); Stream* getPfodAppStream(); void init(); byte parse(byte in); private: Stream* io; byte emptyVersion[1] = {0}; byte argsCount; byte argsIdx; byte parserState; byte args[255 + 1]; byte *versionStart; byte *cmdStart; bool refresh; const char *version; }; //============= end of pfodParser_codeGenerated.h pfodParser_codeGenerated parser("V2"); // create a parser to handle the pfod messages #include //#define DEBUG #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. AdafruitTCPServer server(portNo); AdafruitTCP client; const unsigned long CONNECTION_TIMEOUT = 15000; // close connection if nothing received for 15 sec, prevents half-closed problems unsigned long timeoutTimerStart = 0; 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 long cmd_A_var; // name the variable for 'LED brightness' const int cmd_A_pin = PA15; // name the output A15 for 'LED brightness' // the setup routine runs once on reset: void setup() { cmd_A_var = 0; pinMode(cmd_A_pin, PWM); // output for 'LED brightness' is initially LOW, pwmWrite(cmd_A_pin,cmd_A_var); // set output #ifdef DEBUG Serial.begin(115200); while (!Serial) { delay(1); // Delay required to avoid RTOS task switching problems } #endif #ifdef DEBUG for (int i = 10; i > 0; i--) { Serial.print(i); Serial.print(' '); delay(500); } Serial.println(); #endif /* Initialise wifi module */ if (*staticIP != '\0') { IPAddress ip(__swap32(ipStrToNum(staticIP))); // WICED stores dwords in reverse order to Arduino Uno 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); Feather.config(ip, gateway, subnet); } while ( !Feather.connected() ) { delay(500); // delay between each attempt if ( Feather.connect(WLAN_SSID, WLAN_PASS) ) { #ifdef DEBUG Serial.println("Wifi connected"); #endif } else { #ifdef DEBUG Serial.printf("Failed! %s (%d)", Feather.errstr(), Feather.errno()); Serial.println(); #endif } } #ifdef DEBUG Feather.printNetwork(); #endif #ifdef DEBUG server.err_actions(true, true); // Tell the TCP Server to auto print error codes and halt on errors #else server.err_actions(false, false); #endif server.begin(); #ifdef DEBUG Serial.println("Server started"); #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 and valid client = server.available(); // evaluates to false if no connection } else { // have client if ((!client.valid()) || (!client.connected()) ) { if (alreadyConnected) { // client closed so clean up closeConnection(parser.getPfodAppStream()); } } else { // have connected client if (!alreadyConnected) { parser.connect(&client); // sets new io stream to read from and write to alreadyConnected = true; timeoutTimerStart = millis(); // start timer } 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 } timeoutTimerStart = millis(); // start timer uint8_t* 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('A'==cmd) { // user moved PWM slider -- 'LED brightness' // in the main Menu of Menu_1 parser.parseLong(pfodFirstArg,&pfodLongRtn); // parse first arg as a long cmd_A_var = (long)pfodLongRtn; // set variable pwmWrite(cmd_A_pin,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. } } } } // see if we should drop the connection if (alreadyConnected && (CONNECTION_TIMEOUT > 0) && ((millis() - timeoutTimerStart) > CONNECTION_TIMEOUT)) { closeConnection(parser.getPfodAppStream()); } // <<<<<<<<<<< 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; if (client) { client.stop(); } 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("<+5>~Adafruit WICED`0")); parser.sendVersion(); // send the menu version // send menu items parser.print(F("|A<+5>")); parser.print('`'); parser.print(cmd_A_var); // output the current PWM setting parser.print(F("~LED brightness\n~%`65535`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 =========== } /* You can remove from here on if you have the pfodParser V2 library installed from http://www.forward.com.au/pfod/pfodParserLibraries/index.html * and add #include * at the top of this file * and replace the line pfodParser_codeGenerated parser("V1"); // create a parser to handle the pfod messages * with pfodParser parser("V1"); */ // this is the pfodParser.cpp V2 file with the class renamed pfodParser_codeGenerated and with comments, constants and un-used methods removed pfodParser_codeGenerated::pfodParser_codeGenerated() { pfodParser_codeGenerated(""); } pfodParser_codeGenerated::pfodParser_codeGenerated(const char *_version) { setVersion(_version); io = NULL; init(); } void pfodParser_codeGenerated::init() { argsCount = 0; argsIdx = 0; args[0] = 0; args[1] = 0; cmdStart = args; versionStart = emptyVersion; parserState = ((byte)0xff); refresh = false; } void pfodParser_codeGenerated::connect(Stream* ioPtr) { init(); io = ioPtr; } void pfodParser_codeGenerated::closeConnection() { init(); } Stream* pfodParser_codeGenerated::getPfodAppStream() { return io; } size_t pfodParser_codeGenerated::write(uint8_t c) { if (!io) { return 1; } return io->write(c); } int pfodParser_codeGenerated::available() { return 0; } int pfodParser_codeGenerated::read() { return 0; } int pfodParser_codeGenerated::peek() { return 0; } void pfodParser_codeGenerated::flush() { if (!io) { return; } // nothing here for now } void pfodParser_codeGenerated::setIdleTimeout(unsigned long timeout) { } void pfodParser_codeGenerated::setCmd(byte cmd) { init(); args[0] = cmd; args[1] = 0; cmdStart = args; versionStart = emptyVersion; } byte* pfodParser_codeGenerated::getCmd() { return cmdStart; } bool pfodParser_codeGenerated::isRefresh() { return refresh; } const char* pfodParser_codeGenerated::getVersion() { return version; } void pfodParser_codeGenerated::setVersion(const char* _version) { version = _version; } void pfodParser_codeGenerated::sendVersion() { print('~'); print(getVersion()); } byte* pfodParser_codeGenerated::getFirstArg() { byte* idxPtr = cmdStart; while (*idxPtr != 0) { ++idxPtr; } if (argsCount > 0) { ++idxPtr; } return idxPtr; } byte* pfodParser_codeGenerated::getNextArg(byte *start) { byte* idxPtr = start; while ( *idxPtr != 0) { ++idxPtr; } if (idxPtr != start) { ++idxPtr; } return idxPtr; } byte pfodParser_codeGenerated::getArgsCount() { return argsCount; } byte pfodParser_codeGenerated::getParserState() { if ((parserState == ((byte)0xff)) || (parserState == ((byte)'{')) || (parserState == 0) || (parserState == ((byte)'}')) ) { return parserState; } return 0; } byte pfodParser_codeGenerated::parse() { byte rtn = 0; if (!io) { return rtn; } while (io->available()) { int in = io->read(); rtn = parse((byte)in); if (rtn != 0) { if (rtn == '!') { closeConnection(); } return rtn; } } return rtn; } byte pfodParser_codeGenerated::parse(byte in) { if (in == 0xff) { // note 0xFF is not a valid utf-8 char // but is returned by underlying stream if start or end of connection // NOTE: Stream.read() is wrapped in while(Serial.available()) so should not get this // unless explicitlly added to stream buffer init(); // clean out last partial msg if any return 0; } if ((parserState == ((byte)0xff)) || (parserState == ((byte)'}'))) { parserState = ((byte)0xff); if (in == ((byte)'{')) { init(); parserState = ((byte)'{'); } return 0; } if ((argsIdx >= (255 - 2)) && (in != ((byte)'}'))) { init(); return 0; } if (parserState == ((byte)'{')) { parserState = 0; if (in == ((byte)':')) { refresh = true; return 0; } } if ((in == ((byte)':')) && (versionStart != args)) { args[argsIdx++] = 0; versionStart = args; cmdStart = args+argsIdx; refresh = (strcmp((const char*)versionStart,version) == 0); return 0; } if ((in == ((byte)'}')) || (in == ((byte)'|')) || (in == ((byte)'~')) || (in == ((byte)'`'))) { args[argsIdx++] = 0; if (parserState == ((byte)0xfe)) { argsCount++; } if (in == ((byte)'}')) { parserState = ((byte)'}'); args[argsIdx++] = 0; return cmdStart[0]; } else { parserState = ((byte)0xfe); } return 0; } args[argsIdx++] = in; return 0; } byte* pfodParser_codeGenerated::parseLong(byte* idxPtr, long *result) { long rtn = 0; boolean neg = false; while ( *idxPtr != 0) { if (*idxPtr == ((byte)'-')) { neg = true; } else { rtn = (rtn << 3) + (rtn << 1); rtn = rtn + (*idxPtr - '0'); } ++idxPtr; } if (neg) { rtn = -rtn; } *result = rtn; return ++idxPtr; } void pfodParser_codeGenerated::setDebugStream(Print* debugOut) { } /** * ipStrToNum * works for IPV4 only * parses "10.1.1.200" and "10,1,1,200" strings * extra spaces ignored eg "10, 1, 1, 200" is OK also * return uint32_t for passing to ipAddress( ); * NOTE: for WICED uint32_t stored in reverse order to Arduino Uno */ uint32_t ipStrToNum(const char* ipStr) { const int SIZE_OF_NUMS = 4; union { uint8_t bytes[SIZE_OF_NUMS]; // IPv4 address uint32_t dword; } _address; _address.dword = 0; // clear return int i = 0; uint8_t num = 0; // start with 0 while ((*ipStr) != '\0') { // while not end of string if ((*ipStr == '.') || (*ipStr == ',')) { // store num and move on to next position _address.bytes[i++] = num; num = 0; if (i>=SIZE_OF_NUMS) { break; // filled array } } else { if (*ipStr != ' ') { // skip blanks num = (num << 3) + (num << 1); // *10 = *8+*2 num = num + (*ipStr - '0'); } } ipStr++; } if (i