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

Revision:
3:8573b122fa84
Parent:
2:6efb3541af61
Child:
4:f6d73acc1f75
--- a/XBeeWiFi.cpp	Fri Jul 29 16:22:15 2011 +0000
+++ b/XBeeWiFi.cpp	Thu Mar 08 17:41:29 2012 +0000
@@ -5,9 +5,12 @@
  */
 
 /** @file
- * @brief Weather Station
+ * @brief XBee Wi-Fi library for mbed
  */
 
+//#define DEBUG
+#include "dbg.h"
+
 #include "mbed.h"
 #include "XBee.h"
 #include "XBeeWiFi.h"
@@ -16,44 +19,53 @@
 #define REVERSE_ENDIAN(x) (uint16_t)(((uint16_t)x >> 8) | ((uint16_t)x << 8))
 
 #ifdef USE_WIFICLASS
-XBeeWiFi::XBeeWiFi (PinName p_tx, PinName p_rx) : XBee(p_tx, p_rx) {
+XBeeWiFi::XBeeWiFi (PinName p_tx, PinName p_rx, PinName p_cts) : XBee(p_tx, p_rx, p_cts) {
 }
 
 int XBeeWiFi::setup (int security, const char *ssid, const char *pin) {
-    int len;
+    int len, r;
     uint8_t cmd[2], val[32];
     AtCommandRequest atRequest;
 
+    // SSID
+    memcpy(cmd, "ID", 2);
+    len = strlen(ssid);
+    memcpy(val, ssid, len);
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue(val);
+    atRequest.setCommandValueLength(len);
+    atRequest.setFrameId(getNextFrameId());
+    send(atRequest);
+    r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+    DBG("wifi ID: %d\r\n", r);
+    if (r < 0) return -1;
+
+    if (security != SECURITY_OPEN) {
+        // PIN
+        memcpy(cmd, "PK", 2);
+        len = strlen(pin);
+        memcpy(val, pin, len);
+        atRequest.setCommand(cmd);
+        atRequest.setCommandValue(val);
+        atRequest.setCommandValueLength(len);
+        atRequest.setFrameId(getNextFrameId());
+        send(atRequest);
+        r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+        DBG("wifi PK: %d\r\n", r);
+        if (r < 0) return -1;
+    }
+
     // security type
     memcpy(cmd, "EE", 2);
     val[0] = security;
     atRequest.setCommand(cmd);
     atRequest.setCommandValue(val);
     atRequest.setCommandValueLength(1);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-    getWiResponse(AT_COMMAND_RESPONSE);
-
-    if (security != SECURITY_OPEN) {
-        // SSID
-        memcpy(cmd, "ID", 2);
-        len = strlen(ssid);
-        memcpy(val, ssid, len);
-        atRequest.setCommand(cmd);
-        atRequest.setCommandValue(val);
-        atRequest.setCommandValueLength(len);
-        send(atRequest);
-        getWiResponse(AT_COMMAND_RESPONSE);
-
-        // PIN
-        memcpy(cmd, "PK", 2);
-        len = strlen(pin);
-        memcpy(val, pin, len);
-        atRequest.setCommand(cmd);
-        atRequest.setCommandValue(val);
-        atRequest.setCommandValueLength(len);
-        send(atRequest);
-        getWiResponse(AT_COMMAND_RESPONSE);
-    }
+    r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+    DBG("wifi EE: %d\r\n", r);
+    if (r < 0) return -1;
 
     return 0;
 }
@@ -64,13 +76,14 @@
 
 int XBeeWiFi::reset () {
     // RESET
-    uint8_t cmd[2] = {'N', 'R'};
+    uint8_t cmd[2] = {'N', 'R'}; // Network reset
+//    uint8_t cmd[2] = {'F', 'R'}; // Software reset
     AtCommandRequest atRequest;
 
     atRequest.setCommand(cmd);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-
-    return getWiResponse(AT_COMMAND_RESPONSE);
+    return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 }
 
 int XBeeWiFi::setAddress () {
@@ -82,9 +95,10 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(1);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
 
-    return getWiResponse(AT_COMMAND_RESPONSE);
+    return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 }
 
 int XBeeWiFi::setAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) {
@@ -98,8 +112,9 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(1);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-    getWiResponse(AT_COMMAND_RESPONSE);
+    getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 
     // IP address
     memcpy(cmd, "MY", 2);
@@ -107,8 +122,9 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(strlen(val));
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-    getWiResponse(AT_COMMAND_RESPONSE);
+    getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 
     // sub netmask
     memcpy(cmd, "NK", 2);
@@ -116,8 +132,9 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(strlen(val));
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-    getWiResponse(AT_COMMAND_RESPONSE);
+    getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 
     // default gateway
     memcpy(cmd, "GW", 2);
@@ -125,8 +142,9 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(strlen(val));
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
-    getWiResponse(AT_COMMAND_RESPONSE);
+    getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 
     // name server
     _nameserver = nameserver;
@@ -134,6 +152,63 @@
     return 0;
 }
 
+int XBeeWiFi::getAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) {
+    int r;
+    uint8_t cmd[2];
+    AtCommandRequest atRequest;
+    AtCommandResponse atResponse;
+
+    memcpy(cmd, "MY", 2);
+    atRequest.setCommand(cmd);
+    atRequest.clearCommandValue();
+    atRequest.setFrameId(getNextFrameId());
+    send(atRequest);
+    r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+    DBG("wifi MY: %d\r\n", r);
+    if (r >= 0) {
+        r = getWiAddr(ipaddr);
+    }
+
+    memcpy(cmd, "MK", 2);
+    atRequest.setCommand(cmd);
+    atRequest.clearCommandValue();
+    atRequest.setFrameId(getNextFrameId());
+    send(atRequest);
+    r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+    DBG("wifi MK: %d\r\n", r);
+    if (r >= 0) {
+        r = getWiAddr(netmask);
+    }
+
+    memcpy(cmd, "GW", 2);
+    atRequest.setCommand(cmd);
+    atRequest.clearCommandValue();
+    atRequest.setFrameId(getNextFrameId());
+    send(atRequest);
+    r = getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
+    DBG("wifi GW: %d\r\n", r);
+    if (r >= 0) {
+        r = getWiAddr(gateway);
+    }
+
+    nameserver = _nameserver;
+
+    return 0;
+}
+
+int XBeeWiFi::getWiAddr (IpAddr &ipaddr) {
+    int ip1, ip2, ip3, ip4;
+    AtCommandResponse atResponse;
+
+    getResponse().getAtCommandResponse(atResponse);
+    if (atResponse.isOk() && atResponse.getValueLength() >= 7) {
+        sscanf((char*)atResponse.getValue(), "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+        ipaddr = IpAddr(ip1, ip2, ip3, ip4);
+        return 0;
+    }
+    return -1;
+}
+
 int XBeeWiFi::setTimeout (int timeout) {
     // timeout
     uint8_t cmd[2] = {'T', 'P'};
@@ -144,6 +219,7 @@
     atRequest.setCommand(cmd);
     atRequest.setCommandValue((uint8_t*)val);
     atRequest.setCommandValueLength(1);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
 
     return getWiResponse(AT_COMMAND_RESPONSE);
@@ -155,33 +231,44 @@
     AtCommandRequest atRequest;
 
     atRequest.setCommand(cmd);
+    atRequest.setFrameId(getNextFrameId());
     send(atRequest);
 
-    return getWiResponse(AT_COMMAND_RESPONSE);
+    return getWiResponse(AT_COMMAND_RESPONSE, atRequest.getFrameId());
 }
 
-int XBeeWiFi::getWiResponse (int apiId, int timeout) {
+int XBeeWiFi::getWiResponse (int apiId, int frameid, int timeout) {
     AtCommandResponse atResponse;
 
     if (readPacket(timeout)) {
+        if (frameid && frameid != getResponse().getFrameData()[0]) {
+            DBG("Expected AT response but got %x (frame %d)\r\n", getResponse().getApiId(), getResponse().getFrameData()[0]);
+            if (! readPacket(timeout)) return -1;
+            DBG("Retry ok\r\n");
+        }
+
         if (getResponse().getApiId() == apiId) {
             getResponse().getAtCommandResponse(atResponse);
 
+            if (getResponse().getApiId() == IPv4_RX_FRAME) {
+                return 0;
+            } else
             if (atResponse.isOk()) {
 
+//                if (getResponse().getFrameDataLength() > 4) {
                 return atResponse.getValue()[0];
 
             } else {
-                printf("Command return error code: %x\r\n", atResponse.getStatus());
+                DBG("Command return error code: %x\r\n", atResponse.getStatus());
             }
         } else {
-            printf("Expected AT response but got %x\r\n", getResponse().getApiId());
+            DBG("Expected AT response but got %x\r\n", getResponse().getApiId());
         }
     } else {
         if (getResponse().isError()) {
-            printf("Error reading packet.  Error code: %x\r\n", getResponse().getErrorCode());  
+            DBG("Error reading packet.  Error code: %x\r\n", getResponse().getErrorCode());  
         } else {
-            printf("No response from radio");  
+            DBG("No response from radio\r\n");  
         }
     }
 
@@ -189,9 +276,16 @@
 }
 
 #ifdef USE_WIFIDNS
+int XBeeWiFi::setNameserver (IpAddr &nameserver) {
+    _nameserver = nameserver;
+    return 0;
+}
+
 int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) {
     char buf[1024];
-    int len;
+    int i, r, len;
+    uint8_t cmd[2] = {'C', '0'};
+    char val[2];
     IPv4TransmitRequest dnsRequest;
     AtCommandRequest atRequest;
     AtCommandResponse atResponse;
@@ -200,25 +294,43 @@
         addr = IpAddr(127, 0, 0, 1);
         return 0;
     }
-
-    len = createDnsRequest(name, buf);
+    
+    // bind src port
+    val[0] = (DNS_SRC_PORT >> 8) & 0xff;
+    val[1] = DNS_SRC_PORT & 0xff;
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(2);
+    atRequest.setFrameId(getNextFrameId());
+    send(atRequest);
+    r = getWiResponse(AT_COMMAND_RESPONSE);
+    DBG("wifi C0: %d\r\n", r);
 
     // send DNS request
+    len = createDnsRequest(name, buf);
     dnsRequest.setAddress(_nameserver);
-    dnsRequest.setDstPort(53);
-    dnsRequest.setSrcPort(1243);
+    dnsRequest.setDstPort(DNS_PORT);
+    dnsRequest.setSrcPort(DNS_SRC_PORT);
     dnsRequest.setProtocol(PROTOCOL_UDP);
     dnsRequest.setPayload((uint8_t*)buf);
     dnsRequest.setPayloadLength(len);
-    send(dnsRequest);
+    for (i = 0; i < DNS_TIMEOUT; i ++) {
+        dnsRequest.setFrameId(getNextFrameId());
+        send(dnsRequest);
+
+        r = getWiResponse(TX_STATUS_RESPONSE, dnsRequest.getFrameId());
+        DBG("wifi TX: %d\r\n", r);
 
-    if (getWiResponse(IPv4_TRANSMIT_STATUS) == 0) {
-        // recv DNS request
-        if (getWiResponse(IPv4_RX_FRAME, 30000) != -1) {
-            getResponse().getAtCommandResponse(atResponse);
-            if (atResponse.isOk()) {
-                return getDnsResponse(atResponse.getValue(), atResponse.getValueLength(), addr);
+        if (r == 0) {
+            // recv DNS request
+            r = getWiResponse(IPv4_RX_FRAME, 0, 3000);
+            DBG("wifi RX: %d\r\n", r);
+            if (r >= 0) {
+                getResponse().getAtCommandResponse(atResponse);
+                return getDnsResponse(atResponse.getValue() + 6, atResponse.getValueLength() - 6, addr);
             }
+        } else {
+            break;
         }
     }
 
@@ -238,33 +350,32 @@
     dnsHeader->answers = 0;
     dnsHeader->authorities = 0;
     dnsHeader->additional = 0;
-    len = sizeof(dnsHeader);
 
     // DNS question
-    num = (int)strchr(name, '.');
-    while (num) {
+    len = sizeof(DNSHeader);
+    while ((num = (int)strchr(name, '.')) != NULL) {
         num = num - (int)name;
         buf[len] = num;
         len ++;
         strncpy(&buf[len], name, num); 
-        name = name + num;
+        name = name + num + 1;
         len = len + num;
-        num = (int)strchr(name, '.');
     }
 
-    num = (int)strlen(name);
-    if (num) {
+    if ((num = strlen(name)) != NULL) {
         buf[len] = num;
         len ++; 
         strncpy(&buf[len], name, num); 
-        len = len + num + 1;
+        len = len + num;
     }
+    buf[len] = 0;
+    len ++; 
 
     dnsEnd = (DnsQuestionEnd*)&buf[len];
     dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A);
     dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN);
 
-    return len + sizeof(dnsEnd);
+    return len + sizeof(DnsQuestionEnd);
 }
 
 int XBeeWiFi::getDnsResponse (const uint8_t *buf, int len, IpAddr &addr) {
@@ -279,7 +390,7 @@
     }
 
     // skip question
-    for (i = sizeof(dnsHeader); buf[i] && i < len; i ++);
+    for (i = sizeof(DNSHeader); buf[i] && i < len; i ++);
     i = i + 1 + sizeof(DnsQuestionEnd);
 
     // DNS answer
@@ -289,7 +400,7 @@
             return -1;
         }
 
-        i = i + sizeof(dnsAnswer);
+        i = i + sizeof(DnsAnswer);
         if (dnsAnswer->type == REVERSE_ENDIAN(DNS_QUERY_A)) {
             addr = IpAddr(buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
             return 0;