forked from harlequin-tech/WiFlyHQ
-
Notifications
You must be signed in to change notification settings - Fork 2
/
WiFlyHQ.h
609 lines (518 loc) · 19.8 KB
/
WiFlyHQ.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
/*-
* Copyright (c) 2012 Darran Hunt (darran [at] hunt dot net dot nz)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Release history
*
* Version Date Description
* 0.1 25-Mar-2012 First release.
* 0.2 09-Apr-2012 Added features to support http servers.
* - added an httpserver.ino example.
* - added sendChunk() and sendChunkln() to send chunked HTTP bodies.
* - added terminal() method for simple terminal access via debug stream
* - replaced getFreeMemory() with simpler version that works with 0 bytes
* - turned peek buffer into a circular buffer to fix bug with detecting
* *CLOS* and *OPEN* after a partial match.
* - Added new TCP connection detection via *OPEN* match from available().
* isConnected() can now be polled until a client connects.
* - made the match() function public, handy for matching text in a stream.
* - Added a getProtocol() function to get current set of protocols.
* 0.3 21-Apr-2012 Added createAdhocNetwork() to create an Ad Hoc WiFi network.
* Optimised the setopt() and getopt() function so they handle
* integer conversions and refactored all of the set and get functions.
* Added a multMatch_P() function to match serial data against multiple
* progmem strings.
* Added failure detection to the join() function to quickly detect
* a failure rather than relying on a timeout.
* Added setJoin() and getJoin() function for access to the wlan join parameter.
* Refactored getres() to use the new multiMatch_P() function.
* 0.4 20-Dec-2012 By Felix Bonowski. Added an easy setup function. Lots of minor changes.
*
*/
#ifndef _WIFLYHQ_H_
#define _WIFLYHQ_H_
#include <Arduino.h>
#include <Stream.h>
#include <avr/pgmspace.h>
#include <IPAddress.h>
/* IP Protocol bits */
#define WIFLY_PROTOCOL_UDP 0x01
#define WIFLY_PROTOCOL_TCP 0x02
#define WIFLY_PROTOCOL_SECURE 0x04
#define WIFLY_PROTOCOL_TCP_CLIENT 0x08
#define WIFLY_PROTOCOL_HTTP 0x10 /* HTTP Client mode */
#define WIFLY_PROTOCOL_RAW 0x20
#define WIFLY_PROTOCOL_SMTP 0x40
/* IP Flag bits */
#define WIFLY_FLAG_TCP_KEEP 0x01 /* Keep TCP connection alive when wifi lost */
#define WIFLY_FLAG_TCP_NODELAY 0x02
#define WIFLY_FLAG_TCP_RETRY 0x04
#define WIFLY_FLAG_UDP_RETRY 0x08
#define WIFLY_FLAG_DNS_CACHING 0x10
#define WIFLY_FLAG_ARP_CACHING 0x20
#define WIFLY_FLAG_UDP_AUTO_PAIR 0x40
#define WIFLY_FLAG_ADD_TIMESTAMP 0x80
/* UART mode bits */
#define WIFLY_UART_MODE_NOECHO 0x01
#define WIFLY_UART_MODE_DATA_TRIGGER 0x02
#define WIFLY_UART_MODE_SLEEP_RX_BREAK 0x08
#define WIFLY_UART_MODE_RX_BUFFER 0x10
/* DHCP modes */
#define WIFLY_DHCP_MODE_OFF 0x00 /* No DHCP, static IP mode */
#define WIFLY_DHCP_MODE_ON 0x01 /* get IP, Gateway, and DNS from AP */
#define WIFLY_DHCP_MODE_AUTOIP 0x02 /* Used with Adhoc networks */
#define WIFLY_DHCP_MODE_CACHE 0x03 /* Use previous DHCP address based on lease */
#define WIFLY_DHCP_MODE_SERVER 0x04 /* Server DHCP IP addresses? */
/* WLAN Join modes */
#define WIFLY_WLAN_JOIN_MANUAL 0x00 /* Don't auto-join a network */
#define WIFLY_WLAN_JOIN_AUTO 0x01 /* Auto-join network set in SSID, passkey, and channel. */
#define WIFLY_WLAN_JOIN_ANY 0x02 /* Ignore SSID and join strongest network using passkey. */
#define WIFLY_WLAN_JOIN_ADHOC 0x04 /* Create an Adhoc network using SSID, Channel, IP and NetMask */
#define WIFLY_DEFAULT_TIMEOUT 500 /* 500 milliseconds */
#define WIFLY_MODE_WPA 0
#define WIFLY_MODE_WEP 1
//Debug out
#ifndef TRACE
#define TRACE(x) do { if (DEBUG) Serial.print( x); } while (0)
#endif
#ifndef TRACELN
#define TRACELN(x) do { if (DEBUG) Serial.println( x); } while (0)
#endif
class WFDebug : public Stream {
public:
WFDebug();
void begin(Stream *debugPrint);
virtual size_t write(uint8_t byte);
virtual int read() { return debug->read(); }
virtual int available() { return debug->available(); }
virtual void flush() { return debug->flush(); }
virtual int peek() { return debug->peek(); }
using Print::write;
private:
Stream *debug;
};
class WiFly : public Stream {
public:
WiFly();
/// a complete setup of all functionality for UDP. Templated with the type of the Serial you want to use.
template <class serialType> void setupForUDP(
serialType* wiFlySerial,
const uint32_t newSerialSpeed,
const bool tryOtherSpeeds, ///< should we try some other baudrates if the currently selected one fails?
const char* SSID,
const char* password,
const char* deviceID, ///< for identifacation in the network
const char* localIP, ///< a string with numbers, if 0, we will use dhcp to get an ip
const uint16_t localPort,
const char* remoteHost,
const uint16_t remotePort,
const bool printTrace ///< show debug information on Serial
){
bool DEBUG=printTrace;
TRACE((F("Free memory: ")));
TRACELN((this->getFreeMemory()));
boolean saveAndReboot=false;
char buf[32];
//try out some different serial speeds until we find one that is working...
const uint32_t serialSpeeds[]={
newSerialSpeed,9600, 19200, 38400, 57600, 115200 };
int speedIndex=0;
int maxSpeedIndex;
if(tryOtherSpeeds){
maxSpeedIndex=6;
}
else{
maxSpeedIndex=1;
};
boolean baudrateFound=false;
TRACELN(F("Trying to connect to this"));
for (speedIndex=0;speedIndex<maxSpeedIndex;speedIndex++){
TRACE(F("Connecting to this using Baudrate:"));
TRACELN(serialSpeeds[speedIndex]);
wiFlySerial->begin(serialSpeeds[speedIndex]);
if(this->begin(wiFlySerial, &Serial)){
baudrateFound=true;
break;
}
}
if(!baudrateFound){
TRACELN(F("Could not find working Baud rate to connect to this"));
return;
}
else{
TRACE(F("Working Baud rate is "));
TRACELN(serialSpeeds[speedIndex]);
}
this->startCommand(); //made this public to avoid the annoing waiting times
if(serialSpeeds[speedIndex]!=newSerialSpeed){
TRACE(F("Setting new baud rate to "));
TRACELN(newSerialSpeed);
//set the new this baud rate
this->setBaud(newSerialSpeed);
TRACE(F("Saving this config."));
this->save();
TRACE(F("Rebooting this->.."));
this->reboot();
wiFlySerial->begin(newSerialSpeed);
saveAndReboot=false;
}
//set
this->getDeviceID(buf, sizeof(buf));
if(strcmp(buf, deviceID) != 0){
TRACE(F("Changing device ID to "));
TRACELN(deviceID);
this->setDeviceID(deviceID);
saveAndReboot=true;
}
//setup dhcp or an ip..
if(localIP==0){
TRACELN(F("No fixed IP provided"));
if(this->getDHCPMode()!=WIFLY_DHCP_MODE_ON){
TRACELN(F("Enabling DHCP"));
this->enableDHCP();
saveAndReboot=true;
}
}
else{
if(this->getDHCPMode()!=WIFLY_DHCP_MODE_OFF){
TRACE(F("Disabling DHCP; setting IP to "));
TRACELN(localIP);
this->disableDHCP();
this->setIP(localIP);
saveAndReboot=true;
}
//set ip only if necessary...
this->getIP(buf,sizeof(buf));
if(strcmp(buf, localIP) != 0){
TRACE(F("Setting IP to "));
TRACELN(localIP);
this->setIP(localIP);
saveAndReboot=true;
}
}
//receive packets at this port...
if(this->getPort()!=localPort){
TRACE(F("Setting listen Port to "));
TRACELN(localPort);
this->setPort( localPort); // Send UPD packets to this server and port
saveAndReboot=true;
}
//2 millis seems to be the minimum for 9600 baud
if (this->getFlushTimeout() != 2) {
TRACE(F("Setting Flush timeout to 2ms "));
this->setFlushTimeout(2);
saveAndReboot=true;
}
//set SSID only if necessary...
this->getSSID(buf,sizeof(buf));
if(strcmp(buf, SSID) != 0){
TRACE(F("Setting SSID to "));
TRACELN((SSID));
this->setSSID(SSID);
TRACE(F("Setting Wifi Passwd to "));
TRACELN((password));
this->setPassphrase(password);
saveAndReboot=true;
}
this->save();
this->finishCommand();
if(saveAndReboot==true){
this->reboot();
wiFlySerial->begin(newSerialSpeed);
}
this->startCommand();
//set SSID only if necessary...
this->getSSID(buf,sizeof(buf));
if(strcmp(buf, SSID) != 0){
this->setSSID(SSID);
this->setPassphrase(password);
}
/* Join wifi network if not already associated */
if (!this->isAssociated()) {
// if(true){
/* Setup the this to connect to a wifi network */
TRACELN(F("Joining network"));
this->setSSID(SSID);
if (this->join()) {
// this->setopt("set w a ", 1);
//if (this->join(SSID, password, localIP==0, this_MODE_WEP)) {
TRACELN(F("Joined wifi network"));
}
else {
TRACELN(F("Failed to join wifi network"));
}
}
else {
TRACELN(F("Already joined network"));
}
//enable auto join
this->setJoin(WIFLY_WLAN_JOIN_AUTO);
/* Setup for UDP packets, sent automatically */
this->setIpProtocol(WIFLY_PROTOCOL_UDP);
this->setHost(remoteHost, remotePort); // Send UPD packets to this server and port
TRACE("MAC: ");
TRACELN(this->getMAC(buf, sizeof(buf)));
TRACE("IP: ");
TRACELN(this->getIP(buf, sizeof(buf)));
TRACE("Netmask: ");
TRACELN(this->getNetmask(buf, sizeof(buf)));
TRACE("Gateway: ");
TRACELN(this->getGateway(buf, sizeof(buf)));
TRACE("Listen Port:");
TRACELN(this->getPort());
this->finishCommand();
TRACELN(F("this setup finished"));
};
void printStatusInfo(){
this->startCommand();
char buf[32];
/* Ping the gateway */
this->getGateway(buf, sizeof(buf));
Serial.print("ping ");
Serial.print(buf);
Serial.print(" ... ");
if (this->ping(buf)) {
Serial.println("ok");
}
else {
Serial.println("failed");
}
Serial.print("ping google.com ... ");
if (this->ping("google.com")) {
Serial.println("ok");
}
else {
Serial.println("failed");
}
Serial.print("MAC: ");
Serial.println(this->getMAC(buf, sizeof(buf)));
Serial.print("IP: ");
Serial.println(this->getIP(buf, sizeof(buf)));
Serial.print("Netmask: ");
Serial.println(this->getNetmask(buf, sizeof(buf)));
Serial.print("Gateway: ");
Serial.println(this->getGateway(buf, sizeof(buf)));
Serial.print("Listen Port:");
Serial.println(this->getPort());
this->finishCommand();
}
boolean begin(Stream *serialdev, Stream *debugPrint = NULL);
char *getSSID(char *buf, int size);
uint8_t getJoin();
char *getDeviceID(char *buf, int size);
char *getIP(char *buf, int size);
uint16_t getPort();
char *getNetmask(char *buf, int size);
char *getGateway(char *buf, int size);
char *getDNS(char *buf, int size);
char *getMAC(char *buf, int size);
int8_t getDHCPMode();
uint32_t getRate();
uint8_t getTxPower();
uint16_t getConnection();
int8_t getRSSI();
bool setJoin(uint8_t join);
boolean setDeviceID(const char *buf);
boolean setBaud(uint32_t baud);
uint32_t getBaud();
uint8_t getUartMode();
uint8_t getIpFlags();
uint8_t getProtocol();
uint8_t getFlushChar();
uint16_t getFlushSize();
uint16_t getFlushTimeout();
char *getHostIP(char *buf, int size);
uint16_t getHostPort();
boolean setSSID(const char *buf);
boolean setIP(const char *buf);
boolean setIP(const __FlashStringHelper *buf);
boolean setPort(const uint16_t port);
boolean setNetmask(const char *buf);
boolean setNetmask(const __FlashStringHelper *buf);
boolean setGateway(const char *buf);
boolean setDNS(const char *buf);
boolean setChannel(uint8_t channel);
boolean setKey(const char *buf);
boolean setPassphrase(const char *buf);
boolean setSpaceReplace(const char *buf);
boolean setDHCP(const uint8_t mode);
boolean setRate(uint32_t rate);
boolean setTxPower(uint8_t dBm);
boolean setHostIP(const char *buf);
boolean setHostIP(const __FlashStringHelper *buf);
boolean setHostPort(const uint16_t port);
boolean setHost(const char *buf, uint16_t port);
boolean setProtocol(const uint8_t protocol);
boolean setIpProtocol(const uint8_t protocol); /* obsolete */
boolean setIpFlags(const uint8_t flags);
boolean setUartMode(const uint8_t mode);
boolean setBroadcastInterval(const uint8_t seconds);
boolean setTimeAddress(const char *buf);
boolean setTimePort(const uint16_t port);
boolean setTimezone(const uint8_t zone);
boolean setTimeEnable(const uint16_t enable);
boolean setAdhocBeacon(const uint16_t msecs);
boolean setAdhocProbe(const uint16_t secs);
uint16_t getAdhocBeacon();
uint16_t getAdhocProbe();
uint16_t getAdhocReboot();
boolean setFlushTimeout(const uint16_t timeout);
boolean setFlushChar(const char flushChar);
boolean setFlushSize(uint16_t size);
boolean enableDataTrigger(const uint16_t flushtime=10, const char flushChar=0, const uint16_t flushSize=64);
boolean disableDataTrigger();
boolean enableUdpAutoPair();
boolean disableUdpAutoPair();
boolean setIOFunc(const uint8_t func);
char *getTime(char *buf, int size);
uint32_t getUptime();
uint8_t getTimezone();
uint32_t getRTC();
bool getHostByName(const char *hostname, char *buf, int size);
boolean ping(const char *host);
boolean enableDHCP();
boolean disableDHCP();
boolean createAdhocNetwork(const char *ssid, uint8_t channel);
boolean join(const char *ssid, uint16_t timeout=20000);
boolean join(uint16_t timeout=20000);
boolean join(const char *ssid, const char *password, bool dhcp=true, uint8_t mode=WIFLY_MODE_WPA, uint16_t timeout=20000);
boolean leave();
boolean isAssociated();
boolean save();
boolean reboot();
boolean factoryRestore();
boolean sendto(const uint8_t *data, uint16_t size, const char *host, uint16_t port);
boolean sendto(const uint8_t *data, uint16_t size, IPAddress host, uint16_t port);
boolean sendto(const char *data, const char *host, uint16_t port);
boolean sendto(const char *data, IPAddress host, uint16_t port);
boolean sendto(const __FlashStringHelper *data, const char *host, uint16_t port);
boolean sendto(const __FlashStringHelper *data, IPAddress host, uint16_t port);
void enableHostRestore();
void disableHostRestore();
boolean open(const char *addr, int port=80, boolean block=true);
boolean open(IPAddress addr, int port=80, boolean block=true);
boolean close();
boolean openComplete();
boolean isConnected();
boolean isInCommandMode();
virtual size_t write(uint8_t byte);
virtual int read();
virtual int readBufTimeout(char* buf, int size, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT); ///< read data into the buffer until it is full or the next character takes more than timeout millis to arrive
virtual int available();
virtual void flush();
virtual int peek();
char *iptoa(IPAddress addr, char *buf, int size);
IPAddress atoip(char *buf);
boolean isDotQuad(const char *addr);
void sendChunk(const char *str);
void sendChunk(const __FlashStringHelper *str);
void sendChunkln(const char *str);
void sendChunkln(const __FlashStringHelper *str);
void sendChunkln(void);
int getFreeMemory();
void terminal();
using Print::write;
void dbgBegin(int size=256);
void dbgDump();
void dbgEnd();
boolean debugOn;
boolean match(const char *str, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
boolean match(const __FlashStringHelper *str, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
int multiMatch_P(uint16_t timeout, uint8_t count, ...);
int gets(char *buf, int size, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
int getsTerm(char *buf, int size, char term, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
void flushRx(int timeout=WIFLY_DEFAULT_TIMEOUT);
boolean setFtpDefaults(void);
boolean setFtpAddress(const char *addr);
boolean setFtpPort(uint16_t port);
boolean setFtpDirectory(const char *dir);
boolean setFtpUser(const char *user);
boolean setFtpPassword(const char *password);
boolean setFtpFilename(const char *filename);
boolean setFtpTimer(uint16_t msecs);
boolean setFtpMode(uint8_t mode);
boolean ftpGet(
const char *addr,
const char *dir,
const char *user,
const char *password,
const char *filename);
boolean startCommand();
boolean finishCommand();
boolean setopt(const prog_char *cmd, const char *buf=NULL, const __FlashStringHelper *buf_P=NULL);
boolean setopt(const prog_char *opt, const uint32_t value, uint8_t base=DEC);
private:
void init(void);
void dump(const char *str);
boolean sendto(
const uint8_t *data,
uint16_t size,
const __FlashStringHelper *flashData,
const char *host,
uint16_t port);
boolean match_P(const prog_char *str, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
int8_t multiMatch_P(const prog_char *str[], uint8_t count, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
void send_P(const prog_char *str);
void send(const char *str);
void send(const char ch);
boolean enterCommandMode();
boolean exitCommandMode();
boolean setPrompt();
boolean getPrompt(uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
boolean checkPrompt(const char *str);
int getResponse(char *buf, int size, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
boolean readTimeout(char *ch, uint16_t timeout=WIFLY_DEFAULT_TIMEOUT);
char *getopt(int opt, char *buf, int size);
uint32_t getopt(int opt, uint8_t base=DEC);
boolean getres(char *buf, int size);
boolean checkStream(const prog_char *str, boolean peeked);
boolean checkClose(boolean peeked);
boolean checkOpen(boolean peeked);
boolean hide();
boolean inCommandMode;
int exitCommand;
boolean dhcp;
bool restoreHost;
bool restoreHostStored;
char lastHost[32];
uint16_t lastPort;
boolean tcpMode;
boolean udpAutoPair;
boolean connected;
boolean connecting;
struct {
uint8_t tcp;
uint8_t assoc;
uint8_t authen;
uint8_t dnsServer;
uint8_t dnsFound;
uint8_t channel;
} status;
Stream *serial; /* Serial interface to WiFly */
WFDebug debug; /* Internal debug channel. */
/* for dbgDump() */
char *dbgBuf;
int dbgInd;
int dbgMax;
};
#endif