XBee-mbed library http://mbed.org/users/okini3939/notebook/xbee-mbed/

Dependents:   device_server_udp led_sender_post XBee_API_ex1 XBee_API_ex2 ... more

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     if (atResponse.isOk() && atResponse.getValueLength() >= 7) {
00241         sscanf((char*)atResponse.getValue(), "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
00242         ipaddr = IpAddr(ip1, ip2, ip3, ip4);
00243         return 0;
00244     }
00245     return -1;
00246 }
00247 
00248 int XBeeWiFi::setTimeout (int timeout) {
00249     // timeout
00250     uint8_t cmd[2] = {'T', 'P'};
00251     char val[1];
00252     AtCommandRequest atRequest;
00253 
00254     val[0] = timeout;
00255     atRequest.setCommand(cmd);
00256     atRequest.setCommandValue((uint8_t*)val);
00257     atRequest.setCommandValueLength(1);
00258     atRequest.setFrameId(getNextFrameId());
00259     send(atRequest);
00260 
00261     return getWiResponse(AT_COMMAND_RESPONSE);
00262 }
00263 
00264 int XBeeWiFi::getStatus () {
00265     // AI
00266     uint8_t cmd[2] = {'A', 'I'};
00267     AtCommandRequest atRequest;
00268 
00269     atRequest.setCommand(cmd);
00270     atRequest.setFrameId(getNextFrameId());
00271     send(atRequest);
00272 
00273     return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
00274 }
00275 
00276 int XBeeWiFi::getWiResponse (int apiId, int frameid, int timeout) {
00277     AtCommandResponse atResponse;
00278 
00279     if (readPacket(timeout)) {
00280         if (frameid && frameid != getResponse().getFrameData()[0]) {
00281             DBG("Expected AT response but got %x (frame %d)\r\n", getResponse().getApiId(), getResponse().getFrameData()[0]);
00282             if (! readPacket(timeout)) return -1;
00283             DBG("Retry ok\r\n");
00284         }
00285 
00286         if (getResponse().getApiId() == apiId) {
00287             getResponse().getAtCommandResponse(atResponse);
00288 
00289             if (getResponse().getApiId() == IPv4_RX_FRAME) {
00290                 return 0;
00291             } else
00292             if (atResponse.isOk()) {
00293 
00294 //                if (getResponse().getFrameDataLength() > 4) {
00295                 return atResponse.getValue()[0];
00296 
00297             } else {
00298                 DBG("Command return error code: %x\r\n", atResponse.getStatus());
00299             }
00300         } else {
00301             DBG("Expected AT response but got %x\r\n", getResponse().getApiId());
00302         }
00303     } else {
00304         if (getResponse().isError()) {
00305             DBG("Error reading packet.  Error code: %x\r\n", getResponse().getErrorCode());  
00306         } else {
00307             DBG("No response from radio\r\n");  
00308         }
00309     }
00310 
00311     return -1;
00312 }
00313 
00314 #ifdef USE_WIFIDNS
00315 int XBeeWiFi::setNameserver (IpAddr &nameserver, int port = DNS_PORT) {
00316     _nameserver = nameserver;
00317     _nameport = port;
00318     return 0;
00319 }
00320 
00321 // *** Note: wifi is turned off when XBee send the port 53 udp packet.
00322 int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) {
00323     Timer timeout;
00324     char buf[600];
00325     int r, len;
00326     uint8_t cmd[2] = {'C', '0'};
00327     char val[2];
00328     IPv4TransmitRequest dnsRequest;
00329     AtCommandRequest atRequest;
00330     AtCommandResponse atResponse;
00331 
00332     if (!strcmp(name, "localhost")) {
00333         addr = IpAddr(127, 0, 0, 1);
00334         return 0;
00335     }
00336 
00337     // bind src port
00338     val[0] = (DNS_SRC_PORT >> 8) & 0xff;
00339     val[1] = DNS_SRC_PORT & 0xff;
00340     atRequest.setCommand(cmd);
00341     atRequest.setCommandValue((uint8_t*)val);
00342     atRequest.setCommandValueLength(2);
00343     atRequest.setFrameId(getNextFrameId());
00344     send(atRequest);
00345     r = getWiResponse(AT_COMMAND_RESPONSE);
00346     DBG("wifi C0: %d\r\n", r);
00347 
00348     // send DNS request
00349     len = createDnsRequest(name, buf);
00350     dnsRequest.setAddress(_nameserver);
00351     dnsRequest.setDstPort(_nameport);
00352     dnsRequest.setSrcPort(DNS_SRC_PORT);
00353     dnsRequest.setProtocol(PROTOCOL_UDP);
00354     dnsRequest.setPayload((uint8_t*)buf);
00355     dnsRequest.setPayloadLength(len);
00356     
00357     // wait responce
00358     timeout.reset();
00359     timeout.start();
00360     while (timeout.read_ms() < DNS_TIMEOUT) {
00361         dnsRequest.setFrameId(getNextFrameId());
00362         send(dnsRequest);
00363 
00364         r = getWiResponse(TX_STATUS_RESPONSE, dnsRequest.getFrameId());
00365         DBG("wifi TX: %d\r\n", r);
00366 
00367         if (r >= 0) {
00368             // recv DNS request
00369             r = getWiResponse(IPv4_RX_FRAME, 0, 3000);
00370             DBG("wifi RX: %d\r\n", r);
00371             if (r >= 0) {
00372                 timeout.stop();
00373                 getResponse().getAtCommandResponse(atResponse);
00374                 return getDnsResponse(atResponse.getValue() + 6, atResponse.getValueLength() - 6, addr);
00375             }
00376         } else {
00377             break;
00378         }
00379     }
00380     timeout.stop();
00381 
00382     return -1;
00383 }
00384 
00385 int XBeeWiFi::createDnsRequest (const char* name, char *buf) {
00386     struct DNSHeader *dnsHeader;
00387     struct DnsQuestionEnd *dnsEnd;
00388     int len, num;
00389 
00390     // DNS header
00391     dnsHeader = (DNSHeader*)buf;
00392     dnsHeader->id = REVERSE_ENDIAN(0xdead);
00393     dnsHeader->flags = REVERSE_ENDIAN(0x100);
00394     dnsHeader->questions = REVERSE_ENDIAN(1);
00395     dnsHeader->answers = 0;
00396     dnsHeader->authorities = 0;
00397     dnsHeader->additional = 0;
00398 
00399     // DNS question
00400     len = sizeof(DNSHeader);
00401     while ((num = (int)strchr(name, '.')) != NULL) {
00402         num = num - (int)name;
00403         buf[len] = num;
00404         len ++;
00405         strncpy(&buf[len], name, num); 
00406         name = name + num + 1;
00407         len = len + num;
00408     }
00409 
00410     if ((num = strlen(name)) != NULL) {
00411         buf[len] = num;
00412         len ++; 
00413         strncpy(&buf[len], name, num); 
00414         len = len + num;
00415     }
00416     buf[len] = 0;
00417     len ++; 
00418 
00419     dnsEnd = (DnsQuestionEnd*)&buf[len];
00420     dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A);
00421     dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN);
00422 
00423     return len + sizeof(DnsQuestionEnd);
00424 }
00425 
00426 int XBeeWiFi::getDnsResponse (const uint8_t *buf, int len, IpAddr &addr) {
00427     int i;
00428     struct DNSHeader *dnsHeader;
00429     struct DnsAnswer *dnsAnswer;
00430 
00431     // DNS header
00432     dnsHeader = (DNSHeader*)buf;
00433     if (REVERSE_ENDIAN(dnsHeader->id) != 0xdead || (REVERSE_ENDIAN(dnsHeader->flags) & 0x800f) != 0x8000) {
00434         return -1;
00435     }
00436 
00437     // skip question
00438     for (i = sizeof(DNSHeader); buf[i] && i < len; i ++);
00439     i = i + 1 + sizeof(DnsQuestionEnd);
00440 
00441     // DNS answer
00442     while (i < len) {
00443         dnsAnswer = (DnsAnswer*)&buf[i];
00444         if (dnsAnswer->clas != REVERSE_ENDIAN(DNS_CLASS_IN)) {
00445             return -1;
00446         }
00447 
00448         i = i + sizeof(DnsAnswer);
00449         if (dnsAnswer->type == REVERSE_ENDIAN(DNS_QUERY_A)) {
00450             addr = IpAddr(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
00451             return 0;
00452         }
00453         i = i + dnsAnswer->length;
00454     }
00455 
00456     return -1;
00457 }
00458 #endif
00459 
00460 
00461 IPv4TransmitRequest::IPv4TransmitRequest() : PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
00462 }
00463 
00464 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) {
00465     _dstAddr = dstAddr;
00466     _dstPort = dstPort;
00467     _srcPort = srcPort;
00468     _protocol = protocol;
00469     _option = option;
00470 }
00471 
00472 IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint8_t *data, uint16_t dataLength): PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
00473     _dstAddr = dstAddr;
00474     _dstPort = dstPort;
00475     _srcPort = 0x270f;
00476     _protocol = PROTOCOL_UDP;
00477     _option = 0;
00478 }
00479 
00480 uint8_t IPv4TransmitRequest::getFrameData(uint16_t pos) {
00481     if (pos == 0) {
00482         return _dstAddr[0];
00483     } else if (pos == 1) {
00484         return _dstAddr[1];
00485     } else if (pos == 2) {
00486         return _dstAddr[2];
00487     } else if (pos == 3) {
00488         return _dstAddr[3];
00489     } else if (pos == 4) {
00490         return (_dstPort >> 8) & 0xff;
00491     } else if (pos == 5) {
00492         return _dstPort & 0xff;
00493     } else if (pos == 6) {
00494         return (_srcPort >> 8) & 0xff;
00495     } else if (pos == 7) {
00496         return _srcPort & 0xff;
00497     } else if (pos == 8) {
00498         return _protocol;
00499     } else if (pos == 9) {
00500         return _option;
00501     } else {
00502         return getPayload()[pos - IPv4_TRANSMIT_REQUEST_API_LENGTH];
00503     }
00504 }
00505 
00506 uint16_t IPv4TransmitRequest::getFrameDataLength() {
00507     return IPv4_TRANSMIT_REQUEST_API_LENGTH + getPayloadLength();
00508 }
00509 
00510 IpAddr& IPv4TransmitRequest::getAddress() {
00511     return _dstAddr;
00512 }
00513 
00514 uint16_t IPv4TransmitRequest::getDstPort() {
00515     return _dstPort;
00516 }
00517 
00518 uint16_t IPv4TransmitRequest::getSrcPort() {
00519     return _srcPort;
00520 }
00521 
00522 uint8_t IPv4TransmitRequest::getProtocol() {
00523     return _protocol;
00524 }
00525 
00526 uint8_t IPv4TransmitRequest::getOption() {
00527     return _option;
00528 }
00529 
00530 void IPv4TransmitRequest::setAddress(IpAddr &dstAddr) {
00531     _dstAddr = dstAddr;
00532 }
00533 
00534 void IPv4TransmitRequest::setDstPort(uint16_t dstPort) {
00535     _dstPort = dstPort;
00536 }
00537 
00538 void IPv4TransmitRequest::setSrcPort(uint16_t srcPort) {
00539     _srcPort = srcPort;
00540 }
00541 
00542 void IPv4TransmitRequest::setProtocol(uint8_t protocol) {
00543     _protocol = protocol;
00544 }
00545 
00546 void IPv4TransmitRequest::setOption(uint8_t option) {
00547     _option = option;
00548 }
00549 
00550 
00551 Transmit_Status::Transmit_Status() : FrameIdResponse() {
00552 
00553 }
00554 
00555 uint8_t Transmit_Status::getStatus() {
00556     return getFrameData()[1];
00557 }
00558 
00559 bool Transmit_Status::isSuccess() {
00560     return getStatus() == SUCCESS;
00561 }
00562 
00563 
00564 IPV4RxFrame::IPV4RxFrame () {
00565 }
00566 
00567 IpAddr& IPV4RxFrame::getSrcAddress() {
00568     _srcAddr = IpAddr(getFrameData()[0], getFrameData()[1], getFrameData()[2], getFrameData()[3]);
00569     return _srcAddr;
00570 }
00571 
00572 uint16_t IPV4RxFrame::getDstPort() {
00573     return (getFrameData()[4] << 8) + getFrameData()[5];
00574 }
00575 
00576 uint16_t IPV4RxFrame::getSrcPort() {
00577     return (getFrameData()[6] << 8) + getFrameData()[7];
00578 }
00579 
00580 uint8_t IPV4RxFrame::getProtocol() {
00581     return getFrameData()[8];
00582 }
00583 
00584 uint8_t IPV4RxFrame::getStatus() {
00585     return getFrameData()[9];
00586 }
00587 
00588 // markers to read data from packet array.  this is the index, so the 12th item in the array
00589 uint8_t IPV4RxFrame::getDataOffset() {
00590     return 10;
00591 }
00592 
00593 uint16_t IPV4RxFrame::getDataLength() {
00594     return getPacketLength() - getDataOffset() - 1;
00595 }
00596 
00597 #endif
00598