ban4jp - / XBee_with_SPI

Dependents:   XBeeWiFi_SPI_example

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