MODIFIED from mbed official WiflyInterface (interface for Roving Networks Wifly modules). Numerous performance and reliability improvements (see the detailed documentation). Also, tracking changes in mbed official version to retain functional parity.

Dependents:   Smart-WiFly-WebServer PUB_WiflyInterface_Demo

Fork of WiflyInterface by mbed official

Resources

Derivative from mbed Official

  • Documentation update, improved consistency, documented parameters that were inadvertently omitted.
  • Avoid c++ string handling, which causes dynamic allocation and free, side effect, fewer CPU cycles spent for same purpose.
  • Fixed socket APIs to support non-blocking mode.
  • Increase communication baud-rate to Wifly module
  • sendCommand - added retries for improved robustness.
  • setConnectionState - method to force the connection state (used by TCPSocketServer)
  • gethostbyname - added a length parameter to the size of the buffer being written
  • flushIn - a private method to flush the input buffer
  • Changed the timeout from 500 to 2500 msec for commands - measured some at 700 to 850 msec.
  • Performance improvements - reduced some unnecessary delays.
  • Added additional security options for the wi-fi connection (that are supported by the WiFly module).
  • Added setSecurity API which permits revising the security when connecting to, or selecting from, one of several access points.
  • Improved DEBUG interface (slightly more consistent printout).
  • gathers information from the Wifly module on reboot (SW version info), which permits customizing behavior based on Wifly capabilities (like the improved security).
  • Avoid potential for recursive crash (if exit fails, it calls sendcommand, which calls exit...)
  • Update to support permissible SSID and PassCode lengths.

Robustness testing

I've had some mixed behavior with the Wifly module, some of which seems to be traceable to the module itself, and some in my derivative code. The result, after running for minutes, hours, sometimes days, it hangs and I have to reset the module.

To test, I created a fairly simple test program -

  • check for Watchdog induced reset and count it.
  • initialize the Watchdog for 60 sec timeout.
  • Init the Wifly interface and connect to my network.
  • Wait 10 seconds and force mbed_reset().

If the Watchdog induces the restart, then it is pretty clear that either:

  • The communications hung with the Wifly module causing the failure.
  • The Wifly module decided to go unresponsive.

If it gets to the end, it typically takes about 4 to 6 seconds for the boot and connect, then the 10 second delay.

But I can't really pin down the root cause easily. My strongest theory is that the Wifly module has rebooted, and since I don't store the high baud rate I configure it for, it resets back to 9600.

Also, one of the objectives for my revised send( ) is to avoid the c++ string, as that can fragment memory, and it wasn't very well bounded in behavior.

Latest tests:

Warm BootsWatchdog EventsNotes
100's30An early version of my derivative WiflyInterface, including my derivative of "send( )" API. Let's call this version 0.1.
26684My derivative WiflyInterface, but with the mbed official "send( )" API. Much improved. This was over the course of about 12 hours.
24003Most recent derivative - incremental change to "send( )", but this relative number does not rule out the Wifly module itself.

I think with these numbers, +/- 1 means that the changes have had no measurable effect. Which is good, since this incremental change eliminates the c++ string handling.

Test Software

This is pieces of a test program, clipped and copied to here. What I have compiled and run for hours and hours is almost exactly what you see. This uses this simple Watchdog library.

#include "mbed.h"
#include "WiflyInterface.h"
#include "Watchdog.h"

Serial pc(USBTX, USBRX);

Watchdog wd;
extern "C" void mbed_reset();

// Pinout for SmartBoard
WiflyInterface wifly(p9, p10, p30, p29, "ssid", "pass", WPA);

int main() {
    pc.baud(460800);                         // I like a snappy terminal
    
    wd.Configure(60.0);                     // Set time limit for the test to 1 minute
    LPC_RTC->GPREG0++;                      // Count boots here
    if (wd.WatchdogCausedReset()) {
        LPC_RTC->GPREG1++;                  // Count Watchdog events here
        pc.printf("\r\n\r\nWatchdog event.\r\n");
    }
    pc.printf("\r\nWifly Test: %d boots, %d watchdogs. %s %s\r\n", LPC_RTC->GPREG0, LPC_RTC->GPREG1, __DATE__, __TIME__);
    
    wifly.init(); // use DHCP
    pc.printf("Connect...  ");
    while (!wifly.connect());               // join the network
    pc.printf("Address is %s.  ", wifly.getIPAddress());
    pc.printf("Disconnect...  ");
    wifly.disconnect();
    pc.printf("OK. Reset in 10 sec...\r\n");
    wait(10);
    if (pc.readable()) {
        if (pc.getc() == 'r') {             // secret 'r'eset of the counters
            LPC_RTC->GPREG0 = 0;
            LPC_RTC->GPREG1 = 0;
            pc.printf("counters reset\r\n");
        }
    }
    mbed_reset();                           // reset here indicates successful communication
}
Committer:
WiredHome
Date:
Mon Jun 24 19:52:51 2013 +0000
Revision:
7:b3d740f89f27
Parent:
6:9b25f2bc3b03
Child:
8:79415e982c32
Permit TCPSocketConnection to be non-blocking.
; Permit Wifly to generation documentation.
; Other cosmetic changes.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 5:cc0506dc3565 1 /* Copyright (C) 2012 mbed.org, MIT License
WiredHome 5:cc0506dc3565 2 *
WiredHome 5:cc0506dc3565 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
WiredHome 5:cc0506dc3565 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
WiredHome 5:cc0506dc3565 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
WiredHome 5:cc0506dc3565 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
WiredHome 5:cc0506dc3565 7 * furnished to do so, subject to the following conditions:
WiredHome 5:cc0506dc3565 8 *
WiredHome 5:cc0506dc3565 9 * The above copyright notice and this permission notice shall be included in all copies or
WiredHome 5:cc0506dc3565 10 * substantial portions of the Software.
WiredHome 5:cc0506dc3565 11 *
WiredHome 5:cc0506dc3565 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
WiredHome 5:cc0506dc3565 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
WiredHome 5:cc0506dc3565 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
WiredHome 5:cc0506dc3565 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
WiredHome 5:cc0506dc3565 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
WiredHome 5:cc0506dc3565 17 */
WiredHome 5:cc0506dc3565 18
WiredHome 5:cc0506dc3565 19 /* Modifications by David Smart
WiredHome 5:cc0506dc3565 20 * It is a lengthy set of small mods, including timeout, refactoring to flush the input
WiredHome 5:cc0506dc3565 21 * not store after a join, ability to kick up the baud rate, and many more.
WiredHome 5:cc0506dc3565 22 */
WiredHome 5:cc0506dc3565 23 #include "mbed.h"
WiredHome 5:cc0506dc3565 24 #include "Wifly.h"
WiredHome 5:cc0506dc3565 25 #include <string>
WiredHome 5:cc0506dc3565 26 #include <algorithm>
WiredHome 5:cc0506dc3565 27
WiredHome 5:cc0506dc3565 28 //Debug is disabled by default
WiredHome 5:cc0506dc3565 29 #if (0 && !defined(TARGET_LPC11U24))
WiredHome 5:cc0506dc3565 30 #define DEBUG
WiredHome 5:cc0506dc3565 31 #define DBG(x, ...) std::printf("[DBG Wifly%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
WiredHome 5:cc0506dc3565 32 #define WARN(x, ...) std::printf("[WRN Wifly%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
WiredHome 5:cc0506dc3565 33 #define ERR(x, ...) std::printf("[ERR Wifly%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
WiredHome 5:cc0506dc3565 34 #define INFO(x, ...) std::printf("[INF Wifly%4d] "x"\r\n", __LINE__, ##__VA_ARGS__);
WiredHome 5:cc0506dc3565 35 #else
WiredHome 5:cc0506dc3565 36 #define DBG(x, ...)
WiredHome 5:cc0506dc3565 37 #define WARN(x, ...)
WiredHome 5:cc0506dc3565 38 #define ERR(x, ...)
WiredHome 5:cc0506dc3565 39 #define INFO(x, ...)
WiredHome 5:cc0506dc3565 40 #endif
WiredHome 5:cc0506dc3565 41
WiredHome 5:cc0506dc3565 42 #define MAX_TRY_JOIN 3
WiredHome 5:cc0506dc3565 43
WiredHome 5:cc0506dc3565 44 Wifly * Wifly::inst;
WiredHome 5:cc0506dc3565 45
WiredHome 5:cc0506dc3565 46 Wifly::Wifly( PinName tx, PinName rx, PinName _reset, PinName tcp_status, const char * ssid, const char * phrase, Security sec):
WiredHome 5:cc0506dc3565 47 wifi(tx, rx), reset_pin(_reset), tcp_status(tcp_status), buf_wifly(256)
WiredHome 5:cc0506dc3565 48 {
WiredHome 5:cc0506dc3565 49 memset(&state, 0, sizeof(state));
WiredHome 5:cc0506dc3565 50 state.sec = sec;
WiredHome 5:cc0506dc3565 51
WiredHome 5:cc0506dc3565 52 // change all ' ' in '$' in the ssid and the passphrase
WiredHome 5:cc0506dc3565 53 strcpy(this->ssid, ssid);
WiredHome 5:cc0506dc3565 54 for (int i = 0; i < strlen(ssid); i++) {
WiredHome 5:cc0506dc3565 55 if (this->ssid[i] == ' ')
WiredHome 5:cc0506dc3565 56 this->ssid[i] = '$';
WiredHome 5:cc0506dc3565 57 }
WiredHome 5:cc0506dc3565 58 strcpy(this->phrase, phrase);
WiredHome 5:cc0506dc3565 59 for (int i = 0; i < strlen(phrase); i++) {
WiredHome 5:cc0506dc3565 60 if (this->phrase[i] == ' ')
WiredHome 5:cc0506dc3565 61 this->phrase[i] = '$';
WiredHome 5:cc0506dc3565 62 }
WiredHome 5:cc0506dc3565 63
WiredHome 5:cc0506dc3565 64 inst = this;
WiredHome 5:cc0506dc3565 65 attach_rx(false);
WiredHome 5:cc0506dc3565 66 state.cmd_mode = false;
WiredHome 5:cc0506dc3565 67 reset();
WiredHome 5:cc0506dc3565 68 baudrate = 9600;
WiredHome 5:cc0506dc3565 69 }
WiredHome 5:cc0506dc3565 70
WiredHome 5:cc0506dc3565 71
WiredHome 5:cc0506dc3565 72 void Wifly::flushIn(int timeout_ms)
WiredHome 5:cc0506dc3565 73 {
WiredHome 5:cc0506dc3565 74 Timer tmr;
WiredHome 5:cc0506dc3565 75 tmr.start();
WiredHome 5:cc0506dc3565 76 if (timeout_ms == 0) {
WiredHome 5:cc0506dc3565 77 timeout_ms = 2 * 10000 / baudrate;
WiredHome 5:cc0506dc3565 78 if (timeout_ms == 0)
WiredHome 5:cc0506dc3565 79 timeout_ms = 2;
WiredHome 5:cc0506dc3565 80 }
WiredHome 5:cc0506dc3565 81 while (wifi.readable() || (tmr.read_ms() < timeout_ms)) {
WiredHome 5:cc0506dc3565 82 if (wifi.readable()) {
WiredHome 5:cc0506dc3565 83 tmr.reset();
WiredHome 5:cc0506dc3565 84 tmr.start(); // start should not be necessary
WiredHome 7:b3d740f89f27 85 #if defined(DEBUG)
WiredHome 5:cc0506dc3565 86 std::putchar(wifi.getc());
WiredHome 5:cc0506dc3565 87 #else
WiredHome 5:cc0506dc3565 88 wifi.getc();
WiredHome 5:cc0506dc3565 89 #endif
WiredHome 5:cc0506dc3565 90 }
WiredHome 5:cc0506dc3565 91 }
WiredHome 5:cc0506dc3565 92 }
WiredHome 5:cc0506dc3565 93
WiredHome 5:cc0506dc3565 94
WiredHome 5:cc0506dc3565 95 void Wifly::baud(int _baudrate)
WiredHome 5:cc0506dc3565 96 {
WiredHome 5:cc0506dc3565 97 char cmd[20];
WiredHome 5:cc0506dc3565 98
WiredHome 5:cc0506dc3565 99 baudrate = _baudrate;
WiredHome 5:cc0506dc3565 100 sprintf(cmd, "set u i %d\r", baudrate);
WiredHome 5:cc0506dc3565 101 // set u i # causes it to exit command mode (manual 2.3.64)
WiredHome 5:cc0506dc3565 102 // but testing indicates that it does not exit command mode.
WiredHome 5:cc0506dc3565 103 if (sendCommand(cmd, NULL, NULL, 0)) {
WiredHome 5:cc0506dc3565 104 // state.cmd_mode = false; // see note above why this is disabled
WiredHome 5:cc0506dc3565 105 wifi.baud(baudrate);
WiredHome 5:cc0506dc3565 106 }
WiredHome 5:cc0506dc3565 107 }
WiredHome 5:cc0506dc3565 108
WiredHome 5:cc0506dc3565 109 bool Wifly::join()
WiredHome 5:cc0506dc3565 110 {
WiredHome 5:cc0506dc3565 111 char cmd[20];
WiredHome 5:cc0506dc3565 112
WiredHome 5:cc0506dc3565 113 for (int i= 0; i < MAX_TRY_JOIN; i++) {
WiredHome 5:cc0506dc3565 114 // no auto join
WiredHome 5:cc0506dc3565 115 if (!sendCommand("set w j 0\r", "AOK"))
WiredHome 5:cc0506dc3565 116 continue;
WiredHome 5:cc0506dc3565 117
WiredHome 5:cc0506dc3565 118 //no echo
WiredHome 5:cc0506dc3565 119 if (!sendCommand("set u m 1\r", "AOK"))
WiredHome 5:cc0506dc3565 120 continue;
WiredHome 5:cc0506dc3565 121
WiredHome 5:cc0506dc3565 122 // set time
WiredHome 5:cc0506dc3565 123 if (!sendCommand("set c t 30\r", "AOK"))
WiredHome 5:cc0506dc3565 124 continue;
WiredHome 5:cc0506dc3565 125
WiredHome 5:cc0506dc3565 126 // set size
WiredHome 5:cc0506dc3565 127 if (!sendCommand("set c s 1420\r", "AOK"))
WiredHome 5:cc0506dc3565 128 continue;
WiredHome 5:cc0506dc3565 129
WiredHome 5:cc0506dc3565 130 // red led on when tcp connection active
WiredHome 5:cc0506dc3565 131 if (!sendCommand("set s i 0x40\r", "AOK"))
WiredHome 5:cc0506dc3565 132 continue;
WiredHome 5:cc0506dc3565 133
WiredHome 5:cc0506dc3565 134 // no string sent to the tcp client
WiredHome 5:cc0506dc3565 135 if (!sendCommand("set c r 0\r", "AOK"))
WiredHome 5:cc0506dc3565 136 continue;
WiredHome 5:cc0506dc3565 137
WiredHome 5:cc0506dc3565 138 // tcp protocol
WiredHome 5:cc0506dc3565 139 if (!sendCommand("set i p 2\r", "AOK"))
WiredHome 5:cc0506dc3565 140 continue;
WiredHome 5:cc0506dc3565 141
WiredHome 5:cc0506dc3565 142 // tcp retry
WiredHome 5:cc0506dc3565 143 if (!sendCommand("set i f 0x7\r", "AOK"))
WiredHome 5:cc0506dc3565 144 continue;
WiredHome 5:cc0506dc3565 145
WiredHome 5:cc0506dc3565 146 // set dns server
WiredHome 5:cc0506dc3565 147 if (!sendCommand("set d n rn.microchip.com\r", "AOK"))
WiredHome 5:cc0506dc3565 148 continue;
WiredHome 5:cc0506dc3565 149
WiredHome 5:cc0506dc3565 150 //dhcp
WiredHome 5:cc0506dc3565 151 sprintf(cmd, "set i d %d\r", (state.dhcp) ? 1 : 0);
WiredHome 5:cc0506dc3565 152 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 153 continue;
WiredHome 5:cc0506dc3565 154
WiredHome 5:cc0506dc3565 155 // ssid
WiredHome 5:cc0506dc3565 156 sprintf(cmd, "set w s %s\r", ssid);
WiredHome 5:cc0506dc3565 157 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 158 continue;
WiredHome 5:cc0506dc3565 159
WiredHome 5:cc0506dc3565 160 //auth
WiredHome 5:cc0506dc3565 161 sprintf(cmd, "set w a %d\r", state.sec);
WiredHome 5:cc0506dc3565 162 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 163 continue;
WiredHome 5:cc0506dc3565 164
WiredHome 5:cc0506dc3565 165 // if no dhcp, set ip, netmask and gateway
WiredHome 5:cc0506dc3565 166 if (!state.dhcp) {
WiredHome 5:cc0506dc3565 167 DBG("not dhcp");
WiredHome 5:cc0506dc3565 168
WiredHome 5:cc0506dc3565 169 sprintf(cmd, "set i a %s\r\n", ip);
WiredHome 5:cc0506dc3565 170 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 171 continue;
WiredHome 5:cc0506dc3565 172
WiredHome 5:cc0506dc3565 173 sprintf(cmd, "set i n %s\r", netmask);
WiredHome 5:cc0506dc3565 174 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 175 continue;
WiredHome 5:cc0506dc3565 176
WiredHome 5:cc0506dc3565 177 sprintf(cmd, "set i g %s\r", gateway);
WiredHome 5:cc0506dc3565 178 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 179 continue;
WiredHome 5:cc0506dc3565 180 }
WiredHome 5:cc0506dc3565 181
WiredHome 5:cc0506dc3565 182 //key step
WiredHome 5:cc0506dc3565 183 if (state.sec != NONE) {
WiredHome 5:cc0506dc3565 184 if (state.sec == WPA)
WiredHome 5:cc0506dc3565 185 sprintf(cmd, "set w p %s\r", phrase);
WiredHome 5:cc0506dc3565 186 else if (state.sec == WEP_128)
WiredHome 5:cc0506dc3565 187 sprintf(cmd, "set w k %s\r", phrase);
WiredHome 5:cc0506dc3565 188
WiredHome 5:cc0506dc3565 189 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 190 continue;
WiredHome 5:cc0506dc3565 191 }
WiredHome 5:cc0506dc3565 192
WiredHome 5:cc0506dc3565 193 //join the network (10s timeout)
WiredHome 5:cc0506dc3565 194 if (state.dhcp) {
WiredHome 5:cc0506dc3565 195 if (!sendCommand("join\r", "DHCP=ON", NULL, 10000))
WiredHome 5:cc0506dc3565 196 continue;
WiredHome 5:cc0506dc3565 197 } else {
WiredHome 5:cc0506dc3565 198 if (!sendCommand("join\r", "Associated", NULL, 10000))
WiredHome 5:cc0506dc3565 199 continue;
WiredHome 5:cc0506dc3565 200 }
WiredHome 5:cc0506dc3565 201
WiredHome 5:cc0506dc3565 202 //do not store, so it is default on every start
WiredHome 5:cc0506dc3565 203 //if (!sendCommand("save\r", "Stor"))
WiredHome 5:cc0506dc3565 204 // continue;
WiredHome 5:cc0506dc3565 205 exit(); // exit command mode
WiredHome 5:cc0506dc3565 206
WiredHome 5:cc0506dc3565 207 state.associated = true;
WiredHome 5:cc0506dc3565 208 //INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase, getStringSecurity());
WiredHome 5:cc0506dc3565 209 return true;
WiredHome 5:cc0506dc3565 210 }
WiredHome 5:cc0506dc3565 211 return false;
WiredHome 5:cc0506dc3565 212 }
WiredHome 5:cc0506dc3565 213
WiredHome 5:cc0506dc3565 214
WiredHome 5:cc0506dc3565 215 bool Wifly::setProtocol(Protocol p)
WiredHome 5:cc0506dc3565 216 {
WiredHome 5:cc0506dc3565 217 // use udp auto pairing
WiredHome 5:cc0506dc3565 218 char cmd[20];
WiredHome 5:cc0506dc3565 219 sprintf(cmd, "set i p %d\r", p);
WiredHome 5:cc0506dc3565 220 if (!sendCommand(cmd, "AOK"))
WiredHome 5:cc0506dc3565 221 return false;
WiredHome 5:cc0506dc3565 222
WiredHome 5:cc0506dc3565 223 switch(p) {
WiredHome 5:cc0506dc3565 224 case TCP:
WiredHome 5:cc0506dc3565 225 // set ip flags: tcp retry enabled
WiredHome 5:cc0506dc3565 226 if (!sendCommand("set i f 0x07\r", "AOK"))
WiredHome 5:cc0506dc3565 227 return false;
WiredHome 5:cc0506dc3565 228 break;
WiredHome 5:cc0506dc3565 229 case UDP:
WiredHome 5:cc0506dc3565 230 // set ip flags: udp auto pairing enabled
WiredHome 5:cc0506dc3565 231 if (!sendCommand("set i h 0.0.0.0\r", "AOK"))
WiredHome 5:cc0506dc3565 232 return false;
WiredHome 5:cc0506dc3565 233 if (!sendCommand("set i f 0x40\r", "AOK"))
WiredHome 5:cc0506dc3565 234 return false;
WiredHome 5:cc0506dc3565 235 break;
WiredHome 5:cc0506dc3565 236 }
WiredHome 5:cc0506dc3565 237 state.proto = p;
WiredHome 5:cc0506dc3565 238 return true;
WiredHome 5:cc0506dc3565 239 }
WiredHome 5:cc0506dc3565 240
WiredHome 5:cc0506dc3565 241 char * Wifly::getStringSecurity()
WiredHome 5:cc0506dc3565 242 {
WiredHome 5:cc0506dc3565 243 switch(state.sec) {
WiredHome 5:cc0506dc3565 244 case NONE:
WiredHome 5:cc0506dc3565 245 return "NONE";
WiredHome 5:cc0506dc3565 246 case WEP_128:
WiredHome 5:cc0506dc3565 247 return "WEP_128";
WiredHome 5:cc0506dc3565 248 case WPA:
WiredHome 5:cc0506dc3565 249 return "WPA";
WiredHome 5:cc0506dc3565 250 }
WiredHome 5:cc0506dc3565 251 return "UNKNOWN";
WiredHome 5:cc0506dc3565 252 }
WiredHome 5:cc0506dc3565 253
WiredHome 5:cc0506dc3565 254 bool Wifly::connect(const char * host, int port)
WiredHome 5:cc0506dc3565 255 {
WiredHome 5:cc0506dc3565 256 char rcv[20];
WiredHome 5:cc0506dc3565 257 char cmd[20];
WiredHome 5:cc0506dc3565 258
WiredHome 5:cc0506dc3565 259 // try to open
WiredHome 5:cc0506dc3565 260 printf("Wifly::connect(%s,%d)\r\n", host, port);
WiredHome 5:cc0506dc3565 261 sprintf(cmd, "open %s %d\r", host, port);
WiredHome 5:cc0506dc3565 262 if (sendCommand(cmd, "OPEN", NULL, 10000)) {
WiredHome 5:cc0506dc3565 263 state.tcp = true;
WiredHome 5:cc0506dc3565 264 state.cmd_mode = false;
WiredHome 5:cc0506dc3565 265 return true;
WiredHome 5:cc0506dc3565 266 }
WiredHome 5:cc0506dc3565 267
WiredHome 5:cc0506dc3565 268 // if failed, retry and parse the response
WiredHome 5:cc0506dc3565 269 if (sendCommand(cmd, NULL, rcv, 5000)) {
WiredHome 5:cc0506dc3565 270 if (strstr(rcv, "OPEN") == NULL) {
WiredHome 5:cc0506dc3565 271 if (strstr(rcv, "Connected") != NULL) {
WiredHome 6:9b25f2bc3b03 272 //wait_ms(250); //DS This should be unnecessary
WiredHome 5:cc0506dc3565 273 if (!sendCommand("close\r", "CLOS"))
WiredHome 5:cc0506dc3565 274 return false;
WiredHome 6:9b25f2bc3b03 275 //wait_ms(250); //DS This should be unnecessary
WiredHome 5:cc0506dc3565 276 if (!sendCommand(cmd, "OPEN", NULL, 10000))
WiredHome 5:cc0506dc3565 277 return false;
WiredHome 5:cc0506dc3565 278 } else {
WiredHome 5:cc0506dc3565 279 return false;
WiredHome 5:cc0506dc3565 280 }
WiredHome 5:cc0506dc3565 281 }
WiredHome 5:cc0506dc3565 282 } else {
WiredHome 5:cc0506dc3565 283 return false;
WiredHome 5:cc0506dc3565 284 }
WiredHome 5:cc0506dc3565 285
WiredHome 5:cc0506dc3565 286 state.tcp = true;
WiredHome 5:cc0506dc3565 287 state.cmd_mode = false;
WiredHome 5:cc0506dc3565 288
WiredHome 5:cc0506dc3565 289 return true;
WiredHome 5:cc0506dc3565 290 }
WiredHome 5:cc0506dc3565 291
WiredHome 5:cc0506dc3565 292 void Wifly::setConnectionState(bool value) {
WiredHome 5:cc0506dc3565 293 state.tcp = value;
WiredHome 5:cc0506dc3565 294 }
WiredHome 5:cc0506dc3565 295
WiredHome 5:cc0506dc3565 296
WiredHome 5:cc0506dc3565 297
WiredHome 5:cc0506dc3565 298 bool Wifly::gethostbyname(const char * host, char * ip, int sizeof_ip)
WiredHome 5:cc0506dc3565 299 {
WiredHome 5:cc0506dc3565 300 string h = host;
WiredHome 5:cc0506dc3565 301 char cmd[30], rcv[100];
WiredHome 5:cc0506dc3565 302 int l = 0;
WiredHome 5:cc0506dc3565 303 char * point;
WiredHome 5:cc0506dc3565 304 int nb_digits = 0;
WiredHome 5:cc0506dc3565 305
WiredHome 5:cc0506dc3565 306 // no dns needed
WiredHome 5:cc0506dc3565 307 int pos = h.find(".");
WiredHome 5:cc0506dc3565 308 if (pos != string::npos) {
WiredHome 5:cc0506dc3565 309 string sub = h.substr(0, h.find("."));
WiredHome 5:cc0506dc3565 310 nb_digits = atoi(sub.c_str());
WiredHome 5:cc0506dc3565 311 }
WiredHome 5:cc0506dc3565 312 //printf("substrL %s\r\n", sub.c_str());
WiredHome 5:cc0506dc3565 313 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) {
WiredHome 5:cc0506dc3565 314 strcpy(ip, host);
WiredHome 5:cc0506dc3565 315 }
WiredHome 5:cc0506dc3565 316 // dns needed
WiredHome 5:cc0506dc3565 317 else {
WiredHome 5:cc0506dc3565 318 nb_digits = 0;
WiredHome 5:cc0506dc3565 319 sprintf(cmd, "lookup %s\r", host);
WiredHome 5:cc0506dc3565 320 if (!sendCommand(cmd, NULL, rcv))
WiredHome 5:cc0506dc3565 321 return false;
WiredHome 5:cc0506dc3565 322
WiredHome 5:cc0506dc3565 323 // look for the ip address
WiredHome 5:cc0506dc3565 324 char * begin = strstr(rcv, "=") + 1;
WiredHome 5:cc0506dc3565 325 for (int i = 0; i < 3; i++) {
WiredHome 5:cc0506dc3565 326 point = strstr(begin + l, ".");
WiredHome 5:cc0506dc3565 327 DBG("str: %s", begin + l);
WiredHome 5:cc0506dc3565 328 l += point - (begin + l) + 1;
WiredHome 5:cc0506dc3565 329 }
WiredHome 5:cc0506dc3565 330 DBG("str: %s", begin + l);
WiredHome 5:cc0506dc3565 331 while(*(begin + l + nb_digits) >= '0' && *(begin + l + nb_digits) <= '9') {
WiredHome 5:cc0506dc3565 332 DBG("digit: %c", *(begin + l + nb_digits));
WiredHome 5:cc0506dc3565 333 nb_digits++;
WiredHome 5:cc0506dc3565 334 }
WiredHome 5:cc0506dc3565 335 if (l + nb_digits <= sizeof_ip) {
WiredHome 5:cc0506dc3565 336 memcpy(ip, begin, l + nb_digits);
WiredHome 5:cc0506dc3565 337 ip[l+nb_digits] = 0;
WiredHome 5:cc0506dc3565 338 DBG("ip from dns: %s", ip);
WiredHome 5:cc0506dc3565 339 } else {
WiredHome 5:cc0506dc3565 340 return false;
WiredHome 5:cc0506dc3565 341 }
WiredHome 5:cc0506dc3565 342 }
WiredHome 5:cc0506dc3565 343 return true;
WiredHome 5:cc0506dc3565 344 }
WiredHome 5:cc0506dc3565 345
WiredHome 5:cc0506dc3565 346
WiredHome 5:cc0506dc3565 347 void Wifly::flush()
WiredHome 5:cc0506dc3565 348 {
WiredHome 5:cc0506dc3565 349 buf_wifly.flush();
WiredHome 5:cc0506dc3565 350 }
WiredHome 5:cc0506dc3565 351
WiredHome 5:cc0506dc3565 352 bool Wifly::sendCommand(const char * cmd, const char * ack, char * res, int timeout)
WiredHome 5:cc0506dc3565 353 {
WiredHome 5:cc0506dc3565 354 if (!state.cmd_mode) {
WiredHome 5:cc0506dc3565 355 cmdMode();
WiredHome 5:cc0506dc3565 356 }
WiredHome 5:cc0506dc3565 357 if (send(cmd, strlen(cmd), ack, res, timeout) == -1) {
WiredHome 5:cc0506dc3565 358 ERR("sendCommand: cannot %s\r\n", cmd);
WiredHome 5:cc0506dc3565 359 exit();
WiredHome 5:cc0506dc3565 360 return false;
WiredHome 5:cc0506dc3565 361 }
WiredHome 5:cc0506dc3565 362 return true;
WiredHome 5:cc0506dc3565 363 }
WiredHome 5:cc0506dc3565 364
WiredHome 5:cc0506dc3565 365 bool Wifly::cmdMode()
WiredHome 5:cc0506dc3565 366 {
WiredHome 5:cc0506dc3565 367 // if already in cmd mode, return
WiredHome 5:cc0506dc3565 368 if (state.cmd_mode)
WiredHome 5:cc0506dc3565 369 return true;
WiredHome 5:cc0506dc3565 370
WiredHome 5:cc0506dc3565 371 wait_ms(250); // manual 1.2.1 (250 msec before and after)
WiredHome 5:cc0506dc3565 372 if (send("$$$", 3, "CMD") == -1) {
WiredHome 5:cc0506dc3565 373 ERR("cannot enter in cmd mode\r\n");
WiredHome 5:cc0506dc3565 374 exit();
WiredHome 5:cc0506dc3565 375 return false;
WiredHome 5:cc0506dc3565 376 }
WiredHome 5:cc0506dc3565 377 state.cmd_mode = true;
WiredHome 5:cc0506dc3565 378 return true;
WiredHome 5:cc0506dc3565 379 }
WiredHome 5:cc0506dc3565 380
WiredHome 5:cc0506dc3565 381 bool Wifly::disconnect()
WiredHome 5:cc0506dc3565 382 {
WiredHome 5:cc0506dc3565 383 // if already disconnected, return
WiredHome 5:cc0506dc3565 384 if (!state.associated)
WiredHome 5:cc0506dc3565 385 return true;
WiredHome 5:cc0506dc3565 386
WiredHome 5:cc0506dc3565 387 if (!sendCommand("leave\r", "DeAuth"))
WiredHome 5:cc0506dc3565 388 return false;
WiredHome 5:cc0506dc3565 389 exit();
WiredHome 5:cc0506dc3565 390
WiredHome 5:cc0506dc3565 391 state.associated = false;
WiredHome 5:cc0506dc3565 392 return true;
WiredHome 5:cc0506dc3565 393
WiredHome 5:cc0506dc3565 394 }
WiredHome 5:cc0506dc3565 395
WiredHome 5:cc0506dc3565 396 bool Wifly::is_connected()
WiredHome 5:cc0506dc3565 397 {
WiredHome 5:cc0506dc3565 398 return (tcp_status.read() == 1) ? true : false;
WiredHome 5:cc0506dc3565 399 }
WiredHome 5:cc0506dc3565 400
WiredHome 5:cc0506dc3565 401
WiredHome 5:cc0506dc3565 402 void Wifly::reset()
WiredHome 5:cc0506dc3565 403 {
WiredHome 5:cc0506dc3565 404 reset_pin = 0;
WiredHome 5:cc0506dc3565 405 wait_ms(200);
WiredHome 5:cc0506dc3565 406 reset_pin = 1;
WiredHome 5:cc0506dc3565 407 wait_ms(200);
WiredHome 5:cc0506dc3565 408 flushIn(); // clear the reset text
WiredHome 5:cc0506dc3565 409 }
WiredHome 5:cc0506dc3565 410
WiredHome 5:cc0506dc3565 411 bool Wifly::reboot()
WiredHome 5:cc0506dc3565 412 {
WiredHome 5:cc0506dc3565 413 // if already in cmd mode, return
WiredHome 5:cc0506dc3565 414 if (!sendCommand("reboot\r"))
WiredHome 5:cc0506dc3565 415 return false;
WiredHome 5:cc0506dc3565 416
WiredHome 5:cc0506dc3565 417 wait_ms(300);
WiredHome 5:cc0506dc3565 418 wifi.baud(9600); // After a reboot, it is back at 9600 baud because we don't store
WiredHome 5:cc0506dc3565 419 baud(baudrate); // shift it up to where you want it
WiredHome 5:cc0506dc3565 420 exit(); // exit command mode
WiredHome 5:cc0506dc3565 421 return true;
WiredHome 5:cc0506dc3565 422 }
WiredHome 5:cc0506dc3565 423
WiredHome 5:cc0506dc3565 424 bool Wifly::close()
WiredHome 5:cc0506dc3565 425 {
WiredHome 5:cc0506dc3565 426 if (!state.tcp)
WiredHome 5:cc0506dc3565 427 return true;
WiredHome 5:cc0506dc3565 428
WiredHome 5:cc0506dc3565 429 if (!sendCommand("close\r", "CLOS"))
WiredHome 5:cc0506dc3565 430 return false;
WiredHome 5:cc0506dc3565 431 exit();
WiredHome 5:cc0506dc3565 432
WiredHome 5:cc0506dc3565 433 state.tcp = false;
WiredHome 5:cc0506dc3565 434 return true;
WiredHome 5:cc0506dc3565 435 }
WiredHome 5:cc0506dc3565 436
WiredHome 5:cc0506dc3565 437
WiredHome 5:cc0506dc3565 438 int Wifly::putc(char c)
WiredHome 5:cc0506dc3565 439 {
WiredHome 5:cc0506dc3565 440 while (!wifi.writeable())
WiredHome 5:cc0506dc3565 441 ;
WiredHome 5:cc0506dc3565 442 return wifi.putc(c);
WiredHome 5:cc0506dc3565 443 }
WiredHome 5:cc0506dc3565 444
WiredHome 5:cc0506dc3565 445
WiredHome 5:cc0506dc3565 446 bool Wifly::exit()
WiredHome 5:cc0506dc3565 447 {
WiredHome 5:cc0506dc3565 448 flush();
WiredHome 5:cc0506dc3565 449 if (!state.cmd_mode)
WiredHome 5:cc0506dc3565 450 return true;
WiredHome 5:cc0506dc3565 451 if (!sendCommand("exit\r", "EXIT"))
WiredHome 5:cc0506dc3565 452 return false;
WiredHome 5:cc0506dc3565 453 state.cmd_mode = false;
WiredHome 5:cc0506dc3565 454 flush();
WiredHome 5:cc0506dc3565 455 return true;
WiredHome 5:cc0506dc3565 456 }
WiredHome 5:cc0506dc3565 457
WiredHome 5:cc0506dc3565 458
WiredHome 5:cc0506dc3565 459 int Wifly::readable()
WiredHome 5:cc0506dc3565 460 {
WiredHome 5:cc0506dc3565 461 return buf_wifly.available();
WiredHome 5:cc0506dc3565 462 }
WiredHome 5:cc0506dc3565 463
WiredHome 5:cc0506dc3565 464 int Wifly::writeable()
WiredHome 5:cc0506dc3565 465 {
WiredHome 5:cc0506dc3565 466 return wifi.writeable();
WiredHome 5:cc0506dc3565 467 }
WiredHome 5:cc0506dc3565 468
WiredHome 5:cc0506dc3565 469 char Wifly::getc()
WiredHome 5:cc0506dc3565 470 {
WiredHome 5:cc0506dc3565 471 char c;
WiredHome 5:cc0506dc3565 472 while (!buf_wifly.available())
WiredHome 5:cc0506dc3565 473 ;
WiredHome 5:cc0506dc3565 474 buf_wifly.dequeue(&c);
WiredHome 5:cc0506dc3565 475 return c;
WiredHome 5:cc0506dc3565 476 }
WiredHome 5:cc0506dc3565 477
WiredHome 5:cc0506dc3565 478 void Wifly::handler_rx(void)
WiredHome 5:cc0506dc3565 479 {
WiredHome 5:cc0506dc3565 480 //read characters
WiredHome 5:cc0506dc3565 481 while (wifi.readable())
WiredHome 5:cc0506dc3565 482 buf_wifly.queue(wifi.getc());
WiredHome 5:cc0506dc3565 483 }
WiredHome 5:cc0506dc3565 484
WiredHome 5:cc0506dc3565 485 void Wifly::attach_rx(bool callback)
WiredHome 5:cc0506dc3565 486 {
WiredHome 5:cc0506dc3565 487 if (!callback)
WiredHome 5:cc0506dc3565 488 wifi.attach(NULL);
WiredHome 5:cc0506dc3565 489 else
WiredHome 5:cc0506dc3565 490 wifi.attach(this, &Wifly::handler_rx);
WiredHome 5:cc0506dc3565 491 }
WiredHome 5:cc0506dc3565 492
WiredHome 5:cc0506dc3565 493
WiredHome 5:cc0506dc3565 494 int Wifly::send(const char * str, int len, const char * ACK, char * res, int timeout)
WiredHome 5:cc0506dc3565 495 {
WiredHome 5:cc0506dc3565 496 char read;
WiredHome 5:cc0506dc3565 497 size_t found = string::npos;
WiredHome 5:cc0506dc3565 498 string checking;
WiredHome 5:cc0506dc3565 499 Timer tmr;
WiredHome 5:cc0506dc3565 500 int result = 0;
WiredHome 5:cc0506dc3565 501
WiredHome 5:cc0506dc3565 502 attach_rx(false);
WiredHome 5:cc0506dc3565 503
WiredHome 5:cc0506dc3565 504 //We flush the buffer
WiredHome 5:cc0506dc3565 505 flushIn();
WiredHome 5:cc0506dc3565 506
WiredHome 5:cc0506dc3565 507 #ifdef DEBUG
WiredHome 5:cc0506dc3565 508 char dbuf[100];
WiredHome 5:cc0506dc3565 509 strcpy(dbuf, str);
WiredHome 5:cc0506dc3565 510 char * p = dbuf;
WiredHome 5:cc0506dc3565 511 while (*p && *p >= ' ')
WiredHome 5:cc0506dc3565 512 *p++;
WiredHome 5:cc0506dc3565 513 *p = '\0';
WiredHome 5:cc0506dc3565 514 DBG("send(%s,%d,%s,...,%d)",dbuf,len,ACK,timeout);
WiredHome 5:cc0506dc3565 515 #endif
WiredHome 5:cc0506dc3565 516
WiredHome 5:cc0506dc3565 517 if (!ACK || !strcmp(ACK, "NO")) {
WiredHome 5:cc0506dc3565 518 for (int i = 0; i < len; i++)
WiredHome 5:cc0506dc3565 519 result = (putc(str[i]) == str[i]) ? result + 1 : result;
WiredHome 5:cc0506dc3565 520 } else {
WiredHome 5:cc0506dc3565 521 tmr.start();
WiredHome 5:cc0506dc3565 522 for (int i = 0; i < len; i++)
WiredHome 5:cc0506dc3565 523 result = (putc(str[i]) == str[i]) ? result + 1 : result;
WiredHome 5:cc0506dc3565 524 while (1) {
WiredHome 5:cc0506dc3565 525 if (tmr.read_ms() > timeout) {
WiredHome 5:cc0506dc3565 526 DBG(" timeout");
WiredHome 5:cc0506dc3565 527 flushIn();
WiredHome 5:cc0506dc3565 528
WiredHome 5:cc0506dc3565 529 //DBG("check: %s", checking.c_str());
WiredHome 5:cc0506dc3565 530
WiredHome 5:cc0506dc3565 531 result = -1;
WiredHome 5:cc0506dc3565 532 break;
WiredHome 5:cc0506dc3565 533 } else if (wifi.readable()) {
WiredHome 5:cc0506dc3565 534 read = wifi.getc();
WiredHome 5:cc0506dc3565 535 if ( read != '\r' && read != '\n') {
WiredHome 5:cc0506dc3565 536 checking += read;
WiredHome 5:cc0506dc3565 537 found = checking.find(ACK);
WiredHome 5:cc0506dc3565 538 if (found != string::npos) {
WiredHome 5:cc0506dc3565 539 wait_ms(10);
WiredHome 5:cc0506dc3565 540 flushIn();
WiredHome 5:cc0506dc3565 541 break;
WiredHome 5:cc0506dc3565 542 }
WiredHome 5:cc0506dc3565 543 // We can "early out" if we got an error response
WiredHome 5:cc0506dc3565 544 found = checking.find("ERR: ");
WiredHome 5:cc0506dc3565 545 if (found != string::npos) {
WiredHome 5:cc0506dc3565 546 wait_ms(10);
WiredHome 5:cc0506dc3565 547 ERR(" response: %s", checking.c_str());
WiredHome 5:cc0506dc3565 548 flushIn();
WiredHome 5:cc0506dc3565 549 result = -1;
WiredHome 5:cc0506dc3565 550 break;
WiredHome 5:cc0506dc3565 551 }
WiredHome 5:cc0506dc3565 552 }
WiredHome 5:cc0506dc3565 553 }
WiredHome 5:cc0506dc3565 554 }
WiredHome 5:cc0506dc3565 555 attach_rx(true);
WiredHome 5:cc0506dc3565 556 return result;
WiredHome 5:cc0506dc3565 557 }
WiredHome 5:cc0506dc3565 558
WiredHome 5:cc0506dc3565 559 //the user wants the result from the command (ACK == NULL, res != NULL)
WiredHome 5:cc0506dc3565 560 if ( res != NULL) {
WiredHome 5:cc0506dc3565 561 int i = 0;
WiredHome 5:cc0506dc3565 562 Timer timeout;
WiredHome 5:cc0506dc3565 563 timeout.start();
WiredHome 5:cc0506dc3565 564 tmr.reset();
WiredHome 5:cc0506dc3565 565 while (1) {
WiredHome 5:cc0506dc3565 566 if (timeout.read() > 2) {
WiredHome 5:cc0506dc3565 567 if (i == 0) {
WiredHome 5:cc0506dc3565 568 res = NULL;
WiredHome 5:cc0506dc3565 569 break;
WiredHome 5:cc0506dc3565 570 }
WiredHome 5:cc0506dc3565 571 res[i] = '\0';
WiredHome 5:cc0506dc3565 572 DBG("user str 1: %s", res);
WiredHome 5:cc0506dc3565 573 break;
WiredHome 5:cc0506dc3565 574 } else {
WiredHome 5:cc0506dc3565 575 if (tmr.read_ms() > 300) {
WiredHome 5:cc0506dc3565 576 res[i] = '\0';
WiredHome 5:cc0506dc3565 577 DBG("user str: %s", res);
WiredHome 5:cc0506dc3565 578 break;
WiredHome 5:cc0506dc3565 579 }
WiredHome 5:cc0506dc3565 580 if (wifi.readable()) {
WiredHome 5:cc0506dc3565 581 tmr.start();
WiredHome 5:cc0506dc3565 582 read = wifi.getc();
WiredHome 5:cc0506dc3565 583
WiredHome 5:cc0506dc3565 584 // we drop \r and \n
WiredHome 5:cc0506dc3565 585 if ( read != '\r' && read != '\n') {
WiredHome 5:cc0506dc3565 586 res[i++] = read;
WiredHome 5:cc0506dc3565 587 }
WiredHome 5:cc0506dc3565 588 }
WiredHome 5:cc0506dc3565 589 }
WiredHome 5:cc0506dc3565 590 }
WiredHome 5:cc0506dc3565 591 DBG("user str: %s", res);
WiredHome 5:cc0506dc3565 592 }
WiredHome 5:cc0506dc3565 593
WiredHome 5:cc0506dc3565 594 //We flush the buffer
WiredHome 5:cc0506dc3565 595 flushIn();
WiredHome 5:cc0506dc3565 596
WiredHome 5:cc0506dc3565 597 attach_rx(true);
WiredHome 5:cc0506dc3565 598 return result;
WiredHome 5:cc0506dc3565 599 }