This program calculate location of Wi-Fi receiver, by using AP beacon. Please check the Japanese magazine "Interface 2012/12".

Dependencies:   TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WiFiScanner.h Source File

WiFiScanner.h

00001 #include <string.h>
00002 
00003 #define BAUD_RATE 115200
00004 
00005 #define MULTI_CHANNEL
00006 #ifdef  MULTI_CHANNEL
00007 #define TOTAL_CHANNELS  13
00008 #else
00009 #define TOTAL_CHANNELS  1
00010 #endif
00011 #define MAX_AP_COUNT    (10 * TOTAL_CHANNELS)
00012 //#define PASSIVE_SCAN  // uncommnet here when you need passive scan
00013 
00014 #define CR  '\r'
00015 #define SHORT_WAIT  0.00032
00016 #define BUFF_LEN    4096
00017 #define ESSID_LEN   33
00018 #define MACADDR_LEN 6
00019 
00020 struct apinfo {
00021     unsigned char essid[ESSID_LEN];
00022     unsigned char bssid[MACADDR_LEN];
00023     int power;
00024 };
00025 
00026 struct apinfo apinfos[MAX_AP_COUNT];
00027 int apinfo_count;
00028 
00029 Serial wifi(p13, p14);
00030 
00031 DigitalOut PRST(p15);
00032 
00033 class WiFiScanner {
00034 private:
00035     int sequence;
00036     unsigned char buff[BUFF_LEN];
00037         
00038     void wifiPutc(int c)
00039     {
00040         wifi.putc(c);
00041     }
00042 
00043     int wifiGetc()
00044     {
00045         return wifi.getc();
00046     }
00047 
00048     int num2hex(int i)
00049     {
00050         static const char hexadecimal[] = "0123456789ABCDEF";
00051     
00052         if ( i < 0 || i > 15 )
00053             return '0';
00054 
00055         return ((int)hexadecimal[i]);
00056     }
00057 
00058     int hex2num(int i)
00059     {
00060         switch (i) {
00061         case '0':
00062         case '1':
00063         case '2':
00064         case '3':
00065         case '4':
00066         case '5':
00067         case '6':
00068         case '7':
00069         case '8':
00070         case '9':
00071             return (i - '0');
00072         case 'A':
00073         case 'B':
00074         case 'C':
00075         case 'D':
00076         case 'E':
00077         case 'F':
00078             return ( i - 'A' + 10);
00079         case 'a':
00080         case 'b':
00081         case 'c':
00082         case 'd':
00083         case 'e':
00084         case 'f':
00085             return ( i - 'a' + 10);
00086         }
00087         return (-1);
00088     }
00089 
00090     void delayedPutc(unsigned char c)
00091     {
00092         wifiPutc(c);
00093         wait(SHORT_WAIT);
00094     }
00095 
00096  
00097     void wifiWrite(unsigned char *data)
00098     {
00099         int i;
00100         int len = ((int)data[3]) * 256 + data[2];
00101 
00102         delayedPutc('*');
00103         delayedPutc(num2hex((len >> 4) & 0xf));
00104         delayedPutc(num2hex(len & 0xf));
00105         delayedPutc('4');
00106         delayedPutc(num2hex((len >> 8) & 0xf)); 
00107         for ( i = 0; i < len; i++ ) {
00108             if ( i == 1 ) {
00109                 delayedPutc(num2hex((sequence >> 4) & 0x0f));
00110                 delayedPutc(num2hex(sequence & 0x0f));
00111             } else {
00112                 delayedPutc(num2hex((data[i] >> 4) & 0x0f));
00113                 delayedPutc(num2hex(data[i] & 0x0f));
00114             }
00115         }
00116         delayedPutc(CR);
00117         sequence++;
00118     }
00119 
00120     int wifiRead()
00121     {
00122         int len = 0;
00123         int index = 0;
00124         int c;
00125     
00126         while (true) {
00127             c = wifiGetc();
00128             if ( c == CR ) {
00129                 if ( (index - 5) >= len * 2 ) {
00130                     break;
00131                 }
00132 
00133                 len = 0;
00134                 index = 0;
00135                 continue;
00136             }
00137             if ( index == 0 ) {
00138                 if ( c == '*' ) {
00139                     index++;
00140                 } else {
00141                     while (wifiGetc() != CR)
00142                         ;   //empty loop body
00143                 }
00144                 continue;
00145             }
00146 
00147             c = hex2num(c);
00148             if ( c < 0 ) {
00149                 while (wifiGetc() != CR)
00150                     ;   // empty loop body
00151                 len = 0;
00152                 index = 0;
00153                 continue;
00154             }
00155             if ( index == 1 ) {
00156                 len = c << 4;
00157             } else if ( index == 2 ) {
00158                 len |= c;
00159             } else if ( index == 3 ) {
00160                 if ( c != 3 ) {
00161                     return -3;
00162                 }
00163             } else if ( index == 4 ) {
00164                 len |= c << 8;
00165             } else if ( index & 1 ) {
00166                 buff[(index - 5)/2] = c << 4;
00167             } else {
00168                 buff[(index - 5)/2] |= c;
00169             }
00170             index++;
00171         }
00172         return len;
00173     }
00174 
00175 public:
00176     WiFiScanner()
00177     {
00178         sequence = 0;
00179     }
00180     
00181     void reset()
00182     {
00183         wifi.baud(BAUD_RATE);
00184         wifi.format(8, Serial::None, 1);
00185     
00186         sequence = 0;
00187         PRST = 0;       // reset BP3591
00188         wait(1.0);    // perhaps needs 1 sec
00189         PRST = 1;
00190     }
00191 
00192     void serialInit()
00193     {
00194         int i;
00195         int c = 0;
00196     
00197         while (true) {
00198             wifiPutc('A');
00199             if (wifi.readable()) {
00200                if ( c == '*' ) {
00201                     c = wifiGetc();
00202                     if ( c == CR ) {
00203                         break;
00204                     }
00205                 } else {
00206                     c = wifiGetc();
00207                 }
00208             }
00209             wait(SHORT_WAIT);  // this wait is important
00210         }
00211 
00212         while (wifi.readable())
00213             wifiGetc();
00214         for ( i = 0; i < 8; i++ ) {
00215             delayedPutc(0xf1);
00216         }
00217         c = 0;
00218         while (true) {
00219             if (wifi.readable()) {
00220                 if ( c == '*' ) {
00221                     c = wifiGetc();
00222                     if ( c == CR ) {
00223                         break;
00224                     }
00225                 } else {
00226                     c = wifiGetc();
00227                 }
00228             }
00229         }
00230     }
00231 
00232     void waitStartup()
00233     {
00234         int i;
00235         int len = 0;
00236         bool loopFlag = true;
00237         for (i = 0; loopFlag || len <= 0 || wifi.readable(); i++) {
00238             len = wifiRead();
00239             if ( len == 8 && buff[5] == 0x00 && buff[4] == 0x3d) {
00240                 loopFlag = false;
00241             }
00242             lcd.putc('+');
00243         }
00244     }
00245 
00246     void scanMode()
00247     {
00248         // WID_SSID
00249         unsigned char cmd0[] = { 0x57, 0x00, 0x08, 0x00, 0x00, 0x30, 0x01, 0x00 };
00250         wifiWrite(cmd0);
00251         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00252             wait(SHORT_WAIT);
00253         
00254         // WID_BSS_TYPE
00255         unsigned char cmd1[] = { 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00 };
00256         wifiWrite(cmd1);
00257         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00258             wait(SHORT_WAIT);
00259         
00260         // WID_BCAST_SSID
00261         unsigned char cmd2[] = { 0x57, 0x00, 0x08, 0x00, 0x15, 0x00, 0x01, 0x01 };
00262         wifiWrite(cmd2);
00263         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00264             wait(SHORT_WAIT);
00265         
00266         // WID_SCAN_TYPE
00267 #ifdef  PASSIVE_SCAN
00268         unsigned char cmd3[] = { 0x57, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x00 };
00269 #else
00270         unsigned char cmd3[] = { 0x57, 0x00, 0x08, 0x00, 0x07, 0x00, 0x01, 0x01 };
00271 #endif
00272         wifiWrite(cmd3);
00273         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00274             wait(SHORT_WAIT);
00275 
00276         // WID_ENABLE_CHANNEL
00277         unsigned char cmd4[] = { 0x57, 0x02, 0x0b, 0x00, 0x24, 0x20, 0x04, 0xff, 0x1f, 0x00, 0x00 };
00278         wifiWrite(cmd4);
00279         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00280             wait(SHORT_WAIT);
00281 
00282         // WID_SITE_SURVEY
00283 #ifdef  MULTI_CHANNEL
00284         unsigned char cmd5[] = { 0x57, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x01, 0x11 };
00285 #else
00286         unsigned char cmd5[] = { 0x57, 0x01, 0x08, 0x00, 0x0e, 0x00, 0x01, 0x01 };
00287 #endif
00288         wifiWrite(cmd5);
00289         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00290             wait(SHORT_WAIT);
00291         
00292         // WID_SCAN_FILTER
00293 #ifdef  MULTI_CHANNEL
00294         unsigned char cmd6[] = { 0x57, 0x02, 0x08, 0x00, 0x36, 0x00, 0x01, 0x00 };
00295 #else
00296         unsigned char cmd6[] = { 0x57, 0x02, 0x08, 0x00, 0x36, 0x00, 0x01, 0x00 };
00297 #endif
00298         wifiWrite(cmd6);
00299         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00300             wait(SHORT_WAIT);
00301 
00302 #ifdef  PASSIVE_SCAN
00303         // WID_SITE_SURVEY_SCAN_TIME
00304         unsigned char cmd7[] = { 0x57, 0x00, 0x09, 0x00, 0x0e, 0x10, 0x02, 0x00, 0x02 };
00305         wifiWrite(cmd7);
00306         while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00307             wait(SHORT_WAIT);
00308 #endif
00309     }
00310 
00311     void doScan()
00312     {
00313         int i, len, channel;
00314         int count, write_index;
00315     
00316         apinfo_count = 0;
00317         for (channel = 0; channel < TOTAL_CHANNELS; channel++ ) {
00318             myled1 = (channel >> 3) & 1;
00319             myled2 = (channel >> 2) & 1;
00320             myled3 = (channel >> 1) & 1;
00321             myled4 = channel & 1;
00322         
00323             // WID_CURRENT_CHANNEL
00324 #ifdef  MULTI_CHANNEL
00325             unsigned char cmd8[] = { 0x57, 0x02, 0x08, 0x00, 0x02, 0x00, 0x01, 0x10 };
00326             cmd8[7] = channel + 1; // 1 origin
00327             wifiWrite(cmd8);
00328             while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00329                 wait(SHORT_WAIT);
00330 #endif
00331             // WID_START_SCAN_REQ
00332             unsigned char cmd9[] = { 0x57, 0x02, 0x08, 0x00, 0x1e, 0x00, 0x01, 0x01 };
00333             wifiWrite(cmd9);
00334             while ( wifiRead() <= 0 || (buff[5] != 0x00 || buff[4] != 0x05 || buff[7] != 1))
00335                 wait(SHORT_WAIT);
00336 
00337 #ifdef  PASSIVE_SCAN
00338             wait(0.5);
00339 #else
00340             wait(0.02);
00341 #endif
00342     
00343             // WID_SITE_SURVER_RESULTS
00344             unsigned char cmd10[] = { 0x51, 0x03, 0x06, 0x00, 0x12, 0x30 };
00345             wifiWrite(cmd10);
00346             while ( (len = wifiRead()) <= 0 || (buff[5] != 0x30 || buff[4] != 0x12))
00347                 wait(SHORT_WAIT);
00348             if ( len < 10 ) {
00349                 continue;
00350             }
00351             count = (buff[7] - 2) / 44;
00352             for ( i = 0; i < count; i++ ) {
00353                 for ( write_index = 0; write_index < apinfo_count; write_index++) {
00354                     if ( memcmp(apinfos[write_index].essid, buff + (9 + i *44), 33) == 0 &&
00355                          memcmp(apinfos[write_index].bssid, buff + (9 + i * 44 + 36), 6) == 0 ) {
00356                         break;  // already recorded
00357                     }
00358                 }
00359                 if ( write_index == apinfo_count ) {
00360                     memcpy(apinfos[write_index].essid, buff + (9 + i * 44), 33);
00361                     memcpy(apinfos[write_index].bssid, buff + (9 + i * 44 + 36), 6);
00362                     apinfos[write_index].power = (signed char)buff[9 + i * 44 + 42];
00363                     apinfo_count++;
00364                 } else if ( apinfos[write_index].power < (signed char)buff[9 + i * 44 + 42] ) {
00365                     apinfos[write_index].power = (signed char)buff[9 + i * 44 + 42];
00366                 }
00367             }
00368         }
00369     }
00370 };