Marin Assaliyski / XBee_EA_LPC4088_QS

Dependents:   XBee_WiFi_EA_LPC4088

Fork of XBee by Suga koubou

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers XBeeWiFi.cpp Source File

XBeeWiFi.cpp

Go to the documentation of this file.
00001 /**
00002  * XBee Wi-Fi library for mbed
00003  * Copyright (c) 2011 Hiroshi Suga
00004  * Released under the MIT License: http://mbed.org/license/mit
00005  */
00006 
00007 /** @file
00008  * @brief XBee Wi-Fi library for mbed
00009  */
00010 
00011 #include "XBee_conf.h"
00012 #ifdef ENABLE_XBEE_WIFI
00013 
00014 #define DEBUG
00015 #include "dbg.h"
00016 
00017 #include "mbed.h"
00018 #include "XBee.h"
00019 #include "XBeeWiFi.h"
00020 #include "EthernetNetIf.h"
00021 
00022 #define REVERSE_ENDIAN(x) (uint16_t)(((uint16_t)x >> 8) | ((uint16_t)x << 8))
00023 
00024 XBeeWiFi::XBeeWiFi (PinName p_tx, PinName p_rx, PinName p_cts, PinName p_rts) : XBee(p_tx, p_rx, p_cts, p_rts) {
00025 }
00026 
00027 int XBeeWiFi::setup (int security, const char *ssid, const char *pin) {
00028     int len, r;
00029     uint8_t cmd[2], val[32];
00030     AtCommandRequest atRequest;
00031 
00032     // SSID
00033     memcpy(cmd, "ID", 2);
00034     len = strlen(ssid);
00035     memcpy(val, ssid, len);
00036     atRequest.setCommand(cmd);
00037     atRequest.setCommandValue(val);
00038     atRequest.setCommandValueLength(len);
00039     atRequest.setFrameId(getNextFrameId());
00040     send(atRequest);
00041     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00042     DBG("wifi ID: %d\r\n", r);
00043     if (r < 0) return -1;
00044 
00045     if (security != SECURITY_OPEN) {
00046         // PIN
00047         memcpy(cmd, "PK", 2);
00048         len = strlen(pin);
00049         memcpy(val, pin, len);
00050         atRequest.setCommand(cmd);
00051         atRequest.setCommandValue(val);
00052         atRequest.setCommandValueLength(len);
00053         atRequest.setFrameId(getNextFrameId());
00054         send(atRequest);
00055         r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00056         DBG("wifi PK: %d\r\n", r);
00057         if (r < 0) return -1;
00058     }
00059 
00060     // security type
00061     memcpy(cmd, "EE", 2);
00062     val[0] = security;
00063     atRequest.setCommand(cmd);
00064     atRequest.setCommandValue(val);
00065     atRequest.setCommandValueLength(1);
00066     atRequest.setFrameId(getNextFrameId());
00067     send(atRequest);
00068     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00069     DBG("wifi EE: %d\r\n", r);
00070     if (r < 0) return -1;
00071 
00072     return 0;
00073 }
00074 
00075 int XBeeWiFi::setup (const char *ssid) {
00076     return setup(SECURITY_OPEN, ssid, NULL);
00077 }
00078 
00079 int XBeeWiFi::reset () {
00080     // RESET
00081     uint8_t cmd[2] = {'N', 'R'}; // Network reset
00082 //    uint8_t cmd[2] = {'F', 'R'}; // Software reset
00083     AtCommandRequest atRequest;
00084 
00085     atRequest.setCommand(cmd);
00086     atRequest.setFrameId(getNextFrameId());
00087     send(atRequest);
00088     return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00089 }
00090 
00091 int XBeeWiFi::baud (int b) {
00092     // RESET
00093     uint8_t cmd[2] = {'B', 'D'};
00094     char val[4];
00095     AtCommandRequest atRequest;
00096     int r, len;
00097 
00098     if (b < 0x100) {
00099         val[0] = b;
00100         len = 1;
00101     } else {
00102         val[0] = (b >> 24) & 0xff;
00103         val[1] = (b >> 16) & 0xff;
00104         val[2] = (b >> 8) & 0xff;
00105         val[3] = b & 0xff;
00106         len = 4;
00107     }
00108     atRequest.setCommand(cmd);
00109     atRequest.setCommandValue((uint8_t*)val);
00110     atRequest.setCommandValueLength(len);
00111     atRequest.setFrameId(getNextFrameId());
00112     send(atRequest);
00113     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00114 
00115     if (r == 0) {
00116         begin(b);
00117     }
00118     return r;
00119 }
00120 
00121 int XBeeWiFi::setAddress () {
00122     // DHCP
00123     uint8_t cmd[2] = {'M', 'A'};
00124     char val[1] = {0};
00125     AtCommandRequest atRequest;
00126 
00127     _nameserver = IpAddr(0,0,0,0);
00128     _nameport = DNS_PORT;
00129 
00130     atRequest.setCommand(cmd);
00131     atRequest.setCommandValue((uint8_t*)val);
00132     atRequest.setCommandValueLength(1);
00133     atRequest.setFrameId(getNextFrameId());
00134     send(atRequest);
00135 
00136     return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00137 }
00138 
00139 int XBeeWiFi::setAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) {
00140     uint8_t cmd[2];
00141     char val[32];
00142     AtCommandRequest atRequest;
00143 
00144     // Static
00145     memcpy(cmd, "MA", 2);
00146     val[0] = 1;
00147     atRequest.setCommand(cmd);
00148     atRequest.setCommandValue((uint8_t*)val);
00149     atRequest.setCommandValueLength(1);
00150     atRequest.setFrameId(getNextFrameId());
00151     send(atRequest);
00152     getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00153 
00154     // IP address
00155     memcpy(cmd, "MY", 2);
00156     sprintf(val, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
00157     atRequest.setCommand(cmd);
00158     atRequest.setCommandValue((uint8_t*)val);
00159     atRequest.setCommandValueLength(strlen(val));
00160     atRequest.setFrameId(getNextFrameId());
00161     send(atRequest);
00162     getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00163 
00164     // sub netmask
00165     memcpy(cmd, "NK", 2);
00166     sprintf(val, "%d.%d.%d.%d", netmask[0], netmask[1], netmask[2], netmask[3]);
00167     atRequest.setCommand(cmd);
00168     atRequest.setCommandValue((uint8_t*)val);
00169     atRequest.setCommandValueLength(strlen(val));
00170     atRequest.setFrameId(getNextFrameId());
00171     send(atRequest);
00172     getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00173 
00174     // default gateway
00175     memcpy(cmd, "GW", 2);
00176     sprintf(val, "%d.%d.%d.%d", gateway[0], gateway[1], gateway[2], gateway[3]);
00177     atRequest.setCommand(cmd);
00178     atRequest.setCommandValue((uint8_t*)val);
00179     atRequest.setCommandValueLength(strlen(val));
00180     atRequest.setFrameId(getNextFrameId());
00181     send(atRequest);
00182     getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00183 
00184     // name server
00185     _nameserver = nameserver;
00186     _nameport = DNS_PORT;
00187 
00188     return 0;
00189 }
00190 
00191 int XBeeWiFi::getAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) {
00192     int r;
00193     uint8_t cmd[2];
00194     AtCommandRequest atRequest;
00195     AtCommandResponse atResponse;
00196 
00197     memcpy(cmd, "MY", 2);
00198     atRequest.setCommand(cmd);
00199     atRequest.clearCommandValue();
00200     atRequest.setFrameId(getNextFrameId());
00201     send(atRequest);
00202     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00203     DBG("wifi MY: %d\r\n", r);
00204     if (r >= 0) {
00205         r = getWiAddr(ipaddr);
00206     }
00207 
00208     memcpy(cmd, "MK", 2);
00209     atRequest.setCommand(cmd);
00210     atRequest.clearCommandValue();
00211     atRequest.setFrameId(getNextFrameId());
00212     send(atRequest);
00213     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00214     DBG("wifi MK: %d\r\n", r);
00215     if (r >= 0) {
00216         r = getWiAddr(netmask);
00217     }
00218 
00219     memcpy(cmd, "GW", 2);
00220     atRequest.setCommand(cmd);
00221     atRequest.clearCommandValue();
00222     atRequest.setFrameId(getNextFrameId());
00223     send(atRequest);
00224     r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00225     DBG("wifi GW: %d\r\n", r);
00226     if (r >= 0) {
00227         r = getWiAddr(gateway);
00228     }
00229 
00230     nameserver = _nameserver;
00231 
00232     return 0;
00233 }
00234 
00235 int XBeeWiFi::getWiAddr (IpAddr &ipaddr) {
00236     int ip1, ip2, ip3, ip4;
00237     AtCommandResponse atResponse;
00238 
00239     getResponse().getAtCommandResponse(atResponse);
00240     DBG("**in getWiAddr after getResponse()**\r\n");
00241     
00242     DBG("**isOK: %d **\r\n", atResponse.isOk() );
00243     DBG("**Response length: %d **\r\n", atResponse.getValueLength() );
00244     DBG("**Response: %s **\r\n", atResponse.getValue() );
00245     
00246     if (atResponse.isOk() && atResponse.getValueLength() >= 7) {
00247         DBG("**Inside getWiAddr if**\r\n");
00248         sscanf((char*)atResponse.getValue(), "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
00249         DBG("**ip(getWiAddr): %d.%d.%d.%d **\r\n", ip1,ip2,ip3,ip4);
00250         ipaddr = IpAddr(ip1, ip2, ip3, ip4);
00251         return 0;
00252     }
00253     return -1;
00254 }
00255 
00256 int XBeeWiFi::setTimeout (int timeout) {
00257     // timeout
00258     uint8_t cmd[2] = {'T', 'P'};
00259     char val[1];
00260     AtCommandRequest atRequest;
00261 
00262     val[0] = timeout;
00263     atRequest.setCommand(cmd);
00264     atRequest.setCommandValue((uint8_t*)val);
00265     atRequest.setCommandValueLength(1);
00266     atRequest.setFrameId(getNextFrameId());
00267     send(atRequest);
00268 
00269     return getWiResponse(AT_COMMAND_RESPONSE);
00270 }
00271 
00272 int XBeeWiFi::getStatus () {
00273     // AI
00274     uint8_t cmd[2] = {'A', 'I'};
00275     AtCommandRequest atRequest;
00276 
00277     atRequest.setCommand(cmd);
00278     atRequest.setFrameId(getNextFrameId());
00279     send(atRequest);
00280 
00281     return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00282 }
00283 
00284 int XBeeWiFi::getWiResponse (int apiId, int frameid, int timeout) {
00285     AtCommandResponse atResponse;
00286 
00287     if (readPacket(timeout)) {
00288         if (frameid && frameid != getResponse().getFrameData()[0]) {
00289             DBG("Expected AT response but got %x (frame %d)\r\n", getResponse().getApiId(), getResponse().getFrameData()[0]);
00290             if (! readPacket(timeout)) return -1;
00291             DBG("Retry ok\r\n");
00292         }
00293 
00294         if (getResponse().getApiId() == apiId) {
00295             getResponse().getAtCommandResponse(atResponse);
00296 
00297             if (getResponse().getApiId() == IPv4_RX_FRAME) {
00298                 return 0;
00299             } else
00300             if (atResponse.isOk()) {
00301 
00302 //                if (getResponse().getFrameDataLength() > 4) {
00303                 return atResponse.getValue()[0];
00304 
00305             } else {
00306                 DBG("Command return error code: %x\r\n", atResponse.getStatus());
00307             }
00308         } else {
00309             DBG("Expected AT response but got %x\r\n", getResponse().getApiId());
00310         }
00311     } else {
00312         if (getResponse().isError()) {
00313             DBG("Error reading packet.  Error code: %x\r\n", getResponse().getErrorCode());  
00314         } else {
00315             DBG("No response from radio\r\n");  
00316         }
00317     }
00318 
00319     return -1;
00320 }
00321 
00322 #ifdef USE_WIFIDNS
00323 int XBeeWiFi::setNameserver (IpAddr &nameserver, int port = DNS_PORT) {
00324     _nameserver = nameserver;
00325     _nameport = port;
00326     return 0;
00327 }
00328 
00329 // *** Note: wifi is turned off when XBee send the port 53 udp packet.
00330 int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) {
00331     Timer timeout;
00332     char buf[600];
00333     int r, len;
00334     uint8_t cmd[2] = {'C', '0'};
00335     char val[2];
00336     IPv4TransmitRequest dnsRequest;
00337     AtCommandRequest atRequest;
00338     AtCommandResponse atResponse;
00339 
00340     if (!strcmp(name, "localhost")) {
00341         addr = IpAddr(127, 0, 0, 1);
00342         return 0;
00343     }
00344 
00345     // bind src port
00346     val[0] = (DNS_SRC_PORT >> 8) & 0xff;
00347     val[1] = DNS_SRC_PORT & 0xff;
00348     atRequest.setCommand(cmd);
00349     atRequest.setCommandValue((uint8_t*)val);
00350     atRequest.setCommandValueLength(2);
00351     atRequest.setFrameId(getNextFrameId());
00352     send(atRequest);
00353     r = getWiResponse(AT_COMMAND_RESPONSE);
00354     DBG("wifi C0: %d\r\n", r);
00355 
00356     // send DNS request
00357     len = createDnsRequest(name, buf);
00358     dnsRequest.setAddress(_nameserver);
00359     dnsRequest.setDstPort(_nameport);
00360     dnsRequest.setSrcPort(DNS_SRC_PORT);
00361     dnsRequest.setProtocol(PROTOCOL_UDP);
00362     dnsRequest.setPayload((uint8_t*)buf);
00363     dnsRequest.setPayloadLength(len);
00364     
00365     // wait responce
00366     timeout.reset();
00367     timeout.start();
00368     while (timeout.read_ms() < DNS_TIMEOUT) {
00369         dnsRequest.setFrameId(getNextFrameId());
00370         send(dnsRequest);
00371 
00372         r = getWiResponse(TX_STATUS_RESPONSE, dnsRequest.getFrameId());
00373         DBG("wifi TX: %d\r\n", r);
00374 
00375         if (r >= 0) {
00376             // recv DNS request
00377             r = getWiResponse(IPv4_RX_FRAME, 0, 3000);
00378             DBG("wifi RX: %d\r\n", r);
00379             if (r >= 0) {
00380                 timeout.stop();
00381                 getResponse().getAtCommandResponse(atResponse);
00382                 return getDnsResponse(atResponse.getValue() + 6, atResponse.getValueLength() - 6, addr);
00383             }
00384         } else {
00385             break;
00386         }
00387     }
00388     timeout.stop();
00389 
00390     return -1;
00391 }
00392 
00393 int XBeeWiFi::createDnsRequest (const char* name, char *buf) {
00394     struct DNSHeader *dnsHeader;
00395     struct DnsQuestionEnd *dnsEnd;
00396     int len, num;
00397 
00398     // DNS header
00399     dnsHeader = (DNSHeader*)buf;
00400     dnsHeader->id = REVERSE_ENDIAN(0xdead);
00401     dnsHeader->flags = REVERSE_ENDIAN(0x100);
00402     dnsHeader->questions = REVERSE_ENDIAN(1);
00403     dnsHeader->answers = 0;
00404     dnsHeader->authorities = 0;
00405     dnsHeader->additional = 0;
00406 
00407     // DNS question
00408     len = sizeof(DNSHeader);
00409     while ((num = (int)strchr(name, '.')) != NULL) {
00410         num = num - (int)name;
00411         buf[len] = num;
00412         len ++;
00413         strncpy(&buf[len], name, num); 
00414         name = name + num + 1;
00415         len = len + num;
00416     }
00417 
00418     if ((num = strlen(name)) != NULL) {
00419         buf[len] = num;
00420         len ++; 
00421         strncpy(&buf[len], name, num); 
00422         len = len + num;
00423     }
00424     buf[len] = 0;
00425     len ++; 
00426 
00427     dnsEnd = (DnsQuestionEnd*)&buf[len];
00428     dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A);
00429     dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN);
00430 
00431     return len + sizeof(DnsQuestionEnd);
00432 }
00433 
00434 int XBeeWiFi::getDnsResponse (const uint8_t *buf, int len, IpAddr &addr) {
00435     int i;
00436     struct DNSHeader *dnsHeader;
00437     struct DnsAnswer *dnsAnswer;
00438 
00439     // DNS header
00440     dnsHeader = (DNSHeader*)buf;
00441     if (REVERSE_ENDIAN(dnsHeader->id) != 0xdead || (REVERSE_ENDIAN(dnsHeader->flags) & 0x800f) != 0x8000) {
00442         return -1;
00443     }
00444 
00445     // skip question
00446     for (i = sizeof(DNSHeader); buf[i] && i < len; i ++);
00447     i = i + 1 + sizeof(DnsQuestionEnd);
00448 
00449     // DNS answer
00450     while (i < len) {
00451         dnsAnswer = (DnsAnswer*)&buf[i];
00452         if (dnsAnswer->clas != REVERSE_ENDIAN(DNS_CLASS_IN)) {
00453             return -1;
00454         }
00455 
00456         i = i + sizeof(DnsAnswer);
00457         if (dnsAnswer->type == REVERSE_ENDIAN(DNS_QUERY_A)) {
00458             addr = IpAddr(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
00459             return 0;
00460         }
00461         i = i + dnsAnswer->length;
00462     }
00463 
00464     return -1;
00465 }
00466 #endif
00467 
00468 
00469 IPv4TransmitRequest::IPv4TransmitRequest() : PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
00470 }
00471 
00472 IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint16_t srcPort, uint8_t protocol, uint8_t option, uint8_t *data, uint16_t dataLength, uint8_t frameId): PayloadRequest(IPv4_TRANSMIT_REQUEST, frameId, data, dataLength) {
00473     _dstAddr = dstAddr;
00474     _dstPort = dstPort;
00475     _srcPort = srcPort;
00476     _protocol = protocol;
00477     _option = option;
00478 }
00479 
00480 IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint8_t *data, uint16_t dataLength): PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
00481     _dstAddr = dstAddr;
00482     _dstPort = dstPort;
00483     _srcPort = 0x270f;
00484     _protocol = PROTOCOL_UDP;
00485     _option = 0;
00486 }
00487 
00488 uint8_t IPv4TransmitRequest::getFrameData(uint16_t pos) {
00489     if (pos == 0) {
00490         return _dstAddr[0];
00491     } else if (pos == 1) {
00492         return _dstAddr[1];
00493     } else if (pos == 2) {
00494         return _dstAddr[2];
00495     } else if (pos == 3) {
00496         return _dstAddr[3];
00497     } else if (pos == 4) {
00498         return (_dstPort >> 8) & 0xff;
00499     } else if (pos == 5) {
00500         return _dstPort & 0xff;
00501     } else if (pos == 6) {
00502         return (_srcPort >> 8) & 0xff;
00503     } else if (pos == 7) {
00504         return _srcPort & 0xff;
00505     } else if (pos == 8) {
00506         return _protocol;
00507     } else if (pos == 9) {
00508         return _option;
00509     } else {
00510         return getPayload()[pos - IPv4_TRANSMIT_REQUEST_API_LENGTH];
00511     }
00512 }
00513 
00514 uint16_t IPv4TransmitRequest::getFrameDataLength() {
00515     return IPv4_TRANSMIT_REQUEST_API_LENGTH + getPayloadLength();
00516 }
00517 
00518 IpAddr& IPv4TransmitRequest::getAddress() {
00519     return _dstAddr;
00520 }
00521 
00522 uint16_t IPv4TransmitRequest::getDstPort() {
00523     return _dstPort;
00524 }
00525 
00526 uint16_t IPv4TransmitRequest::getSrcPort() {
00527     return _srcPort;
00528 }
00529 
00530 uint8_t IPv4TransmitRequest::getProtocol() {
00531     return _protocol;
00532 }
00533 
00534 uint8_t IPv4TransmitRequest::getOption() {
00535     return _option;
00536 }
00537 
00538 void IPv4TransmitRequest::setAddress(IpAddr &dstAddr) {
00539     _dstAddr = dstAddr;
00540 }
00541 
00542 void IPv4TransmitRequest::setDstPort(uint16_t dstPort) {
00543     _dstPort = dstPort;
00544 }
00545 
00546 void IPv4TransmitRequest::setSrcPort(uint16_t srcPort) {
00547     _srcPort = srcPort;
00548 }
00549 
00550 void IPv4TransmitRequest::setProtocol(uint8_t protocol) {
00551     _protocol = protocol;
00552 }
00553 
00554 void IPv4TransmitRequest::setOption(uint8_t option) {
00555     _option = option;
00556 }
00557 
00558 
00559 Transmit_Status::Transmit_Status() : FrameIdResponse() {
00560 
00561 }
00562 
00563 uint8_t Transmit_Status::getStatus() {
00564     return getFrameData()[1];
00565 }
00566 
00567 bool Transmit_Status::isSuccess() {
00568     return getStatus() == SUCCESS;
00569 }
00570 
00571 
00572 IPV4RxFrame::IPV4RxFrame () {
00573 }
00574 
00575 IpAddr& IPV4RxFrame::getSrcAddress() {
00576     _srcAddr = IpAddr(getFrameData()[0], getFrameData()[1], getFrameData()[2], getFrameData()[3]);
00577     return _srcAddr;
00578 }
00579 
00580 uint16_t IPV4RxFrame::getDstPort() {
00581     return (getFrameData()[4] << 8) + getFrameData()[5];
00582 }
00583 
00584 uint16_t IPV4RxFrame::getSrcPort() {
00585     return (getFrameData()[6] << 8) + getFrameData()[7];
00586 }
00587 
00588 uint8_t IPV4RxFrame::getProtocol() {
00589     return getFrameData()[8];
00590 }
00591 
00592 uint8_t IPV4RxFrame::getStatus() {
00593     return getFrameData()[9];
00594 }
00595 
00596 // markers to read data from packet array.  this is the index, so the 12th item in the array
00597 uint8_t IPV4RxFrame::getDataOffset() {
00598     return 10;
00599 }
00600 
00601 uint16_t IPV4RxFrame::getDataLength() {
00602     return getPacketLength() - getDataOffset() - 1;
00603 }
00604 
00605 #endif
00606