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

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Fri Jul 29 16:22:15 2011 +0000
Parent:
1:e3b2027e685c
Child:
3:8573b122fa84
Commit message:

Changed in this revision

XBee.cpp Show annotated file Show diff for this revision Revisions of this file
XBeeWiFi.cpp Show annotated file Show diff for this revision Revisions of this file
XBeeWiFi.h Show annotated file Show diff for this revision Revisions of this file
--- a/XBee.cpp	Mon Jan 10 16:32:18 2011 +0000
+++ b/XBee.cpp	Fri Jul 29 16:22:15 2011 +0000
@@ -661,7 +661,7 @@
     _response.reset();
 }
 
-XBee::XBee(PinName p_tx, PinName p_rx): _xbee(p_tx, p_rx), _response(XBeeResponse()) {
+XBee::XBee(PinName p_tx, PinName p_rx): _xbee(p_tx, p_rx) {
     _pos = 0;
     _escape = false;
     _checksumTotal = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeWiFi.cpp	Fri Jul 29 16:22:15 2011 +0000
@@ -0,0 +1,438 @@
+/**
+ * XBee Wi-Fi library for mbed
+ * Copyright (c) 2011 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Weather Station
+ */
+
+#include "mbed.h"
+#include "XBee.h"
+#include "XBeeWiFi.h"
+#include "EthernetNetIf.h"
+
+#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) {
+}
+
+int XBeeWiFi::setup (int security, const char *ssid, const char *pin) {
+    int len;
+    uint8_t cmd[2], val[32];
+    AtCommandRequest atRequest;
+
+    // security type
+    memcpy(cmd, "EE", 2);
+    val[0] = security;
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue(val);
+    atRequest.setCommandValueLength(1);
+    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);
+    }
+
+    return 0;
+}
+
+int XBeeWiFi::setup (const char *ssid) {
+    return setup(SECURITY_OPEN, ssid, NULL);
+}
+
+int XBeeWiFi::reset () {
+    // RESET
+    uint8_t cmd[2] = {'N', 'R'};
+    AtCommandRequest atRequest;
+
+    atRequest.setCommand(cmd);
+    send(atRequest);
+
+    return getWiResponse(AT_COMMAND_RESPONSE);
+}
+
+int XBeeWiFi::setAddress () {
+    // DHCP
+    uint8_t cmd[2] = {'M', 'A'};
+    char val[1] = {0};
+    AtCommandRequest atRequest;
+
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(1);
+    send(atRequest);
+
+    return getWiResponse(AT_COMMAND_RESPONSE);
+}
+
+int XBeeWiFi::setAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver) {
+    uint8_t cmd[2];
+    char val[32];
+    AtCommandRequest atRequest;
+
+    // Static
+    memcpy(cmd, "MA", 2);
+    val[0] = 1;
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(1);
+    send(atRequest);
+    getWiResponse(AT_COMMAND_RESPONSE);
+
+    // IP address
+    memcpy(cmd, "MY", 2);
+    sprintf(val, "%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(strlen(val));
+    send(atRequest);
+    getWiResponse(AT_COMMAND_RESPONSE);
+
+    // sub netmask
+    memcpy(cmd, "NK", 2);
+    sprintf(val, "%d.%d.%d.%d", netmask[0], netmask[1], netmask[2], netmask[3]);
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(strlen(val));
+    send(atRequest);
+    getWiResponse(AT_COMMAND_RESPONSE);
+
+    // default gateway
+    memcpy(cmd, "GW", 2);
+    sprintf(val, "%d.%d.%d.%d", gateway[0], gateway[1], gateway[2], gateway[3]);
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(strlen(val));
+    send(atRequest);
+    getWiResponse(AT_COMMAND_RESPONSE);
+
+    // name server
+    _nameserver = nameserver;
+
+    return 0;
+}
+
+int XBeeWiFi::setTimeout (int timeout) {
+    // timeout
+    uint8_t cmd[2] = {'T', 'P'};
+    char val[1];
+    AtCommandRequest atRequest;
+
+    val[0] = timeout;
+    atRequest.setCommand(cmd);
+    atRequest.setCommandValue((uint8_t*)val);
+    atRequest.setCommandValueLength(1);
+    send(atRequest);
+
+    return getWiResponse(AT_COMMAND_RESPONSE);
+}
+
+int XBeeWiFi::getStatus () {
+    // AI
+    uint8_t cmd[2] = {'A', 'I'};
+    AtCommandRequest atRequest;
+
+    atRequest.setCommand(cmd);
+    send(atRequest);
+
+    return getWiResponse(AT_COMMAND_RESPONSE);
+}
+
+int XBeeWiFi::getWiResponse (int apiId, int timeout) {
+    AtCommandResponse atResponse;
+
+    if (readPacket(timeout)) {
+        if (getResponse().getApiId() == apiId) {
+            getResponse().getAtCommandResponse(atResponse);
+
+            if (atResponse.isOk()) {
+
+                return atResponse.getValue()[0];
+
+            } else {
+                printf("Command return error code: %x\r\n", atResponse.getStatus());
+            }
+        } else {
+            printf("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());  
+        } else {
+            printf("No response from radio");  
+        }
+    }
+
+    return -1;
+}
+
+#ifdef USE_WIFIDNS
+int XBeeWiFi::getHostByName (const char* name, IpAddr &addr) {
+    char buf[1024];
+    int len;
+    IPv4TransmitRequest dnsRequest;
+    AtCommandRequest atRequest;
+    AtCommandResponse atResponse;
+
+    if (!strcmp(name, "localhost")) {
+        addr = IpAddr(127, 0, 0, 1);
+        return 0;
+    }
+
+    len = createDnsRequest(name, buf);
+
+    // send DNS request
+    dnsRequest.setAddress(_nameserver);
+    dnsRequest.setDstPort(53);
+    dnsRequest.setSrcPort(1243);
+    dnsRequest.setProtocol(PROTOCOL_UDP);
+    dnsRequest.setPayload((uint8_t*)buf);
+    dnsRequest.setPayloadLength(len);
+    send(dnsRequest);
+
+    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);
+            }
+        }
+    }
+
+    return -1;
+}
+
+int XBeeWiFi::createDnsRequest (const char* name, char *buf) {
+    struct DNSHeader *dnsHeader;
+    struct DnsQuestionEnd *dnsEnd;
+    int len, num;
+
+    // DNS header
+    dnsHeader = (DNSHeader*)buf;
+    dnsHeader->id = REVERSE_ENDIAN(0xdead);
+    dnsHeader->flags = REVERSE_ENDIAN(0x100);
+    dnsHeader->questions = REVERSE_ENDIAN(1);
+    dnsHeader->answers = 0;
+    dnsHeader->authorities = 0;
+    dnsHeader->additional = 0;
+    len = sizeof(dnsHeader);
+
+    // DNS question
+    num = (int)strchr(name, '.');
+    while (num) {
+        num = num - (int)name;
+        buf[len] = num;
+        len ++;
+        strncpy(&buf[len], name, num); 
+        name = name + num;
+        len = len + num;
+        num = (int)strchr(name, '.');
+    }
+
+    num = (int)strlen(name);
+    if (num) {
+        buf[len] = num;
+        len ++; 
+        strncpy(&buf[len], name, num); 
+        len = len + num + 1;
+    }
+
+    dnsEnd = (DnsQuestionEnd*)&buf[len];
+    dnsEnd->type = REVERSE_ENDIAN(DNS_QUERY_A);
+    dnsEnd->clas = REVERSE_ENDIAN(DNS_CLASS_IN);
+
+    return len + sizeof(dnsEnd);
+}
+
+int XBeeWiFi::getDnsResponse (const uint8_t *buf, int len, IpAddr &addr) {
+    int i;
+    struct DNSHeader *dnsHeader;
+    struct DnsAnswer *dnsAnswer;
+
+    // DNS header
+    dnsHeader = (DNSHeader*)buf;
+    if (REVERSE_ENDIAN(dnsHeader->id) != 0xdead || (REVERSE_ENDIAN(dnsHeader->flags) & 0x800f) != 0x8000) {
+        return -1;
+    }
+
+    // skip question
+    for (i = sizeof(dnsHeader); buf[i] && i < len; i ++);
+    i = i + 1 + sizeof(DnsQuestionEnd);
+
+    // DNS answer
+    while (i < len) {
+        dnsAnswer = (DnsAnswer*)&buf[i];
+        if (dnsAnswer->clas != REVERSE_ENDIAN(DNS_CLASS_IN)) {
+            return -1;
+        }
+
+        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;
+        }
+        i = i + dnsAnswer->length;
+    }
+
+    return -1;
+}
+#endif
+
+#endif
+
+
+IPv4TransmitRequest::IPv4TransmitRequest() : PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
+}
+
+IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint16_t srcPort, uint8_t protocol, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId): PayloadRequest(IPv4_TRANSMIT_REQUEST, frameId, data, dataLength) {
+    _dstAddr = dstAddr;
+    _dstPort = dstPort;
+    _srcPort = srcPort;
+    _protocol = protocol;
+    _option = option;
+}
+
+IPv4TransmitRequest::IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint8_t *data, uint8_t dataLength): PayloadRequest(IPv4_TRANSMIT_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
+    _dstAddr = dstAddr;
+    _dstPort = dstPort;
+    _srcPort = 0x270f;
+    _protocol = PROTOCOL_UDP;
+    _option = 0;
+}
+
+uint8_t IPv4TransmitRequest::getFrameData(uint8_t pos) {
+    if (pos == 0) {
+        return _dstAddr[0];
+    } else if (pos == 1) {
+        return _dstAddr[1];
+    } else if (pos == 2) {
+        return _dstAddr[2];
+    } else if (pos == 3) {
+        return _dstAddr[3];
+    } else if (pos == 4) {
+        return (_dstPort >> 8) & 0xff;
+    } else if (pos == 5) {
+        return _dstPort & 0xff;
+    } else if (pos == 6) {
+        return (_srcPort >> 8) & 0xff;
+    } else if (pos == 7) {
+        return _srcPort & 0xff;
+    } else if (pos == 8) {
+        return _protocol;
+    } else if (pos == 9) {
+        return _option;
+    } else {
+        return getPayload()[pos - IPv4_TRANSMIT_REQUEST_API_LENGTH];
+    }
+}
+
+uint8_t IPv4TransmitRequest::getFrameDataLength() {
+    return IPv4_TRANSMIT_REQUEST_API_LENGTH + getPayloadLength();
+}
+
+IpAddr& IPv4TransmitRequest::getAddress() {
+    return _dstAddr;
+}
+
+uint16_t IPv4TransmitRequest::getDstPort() {
+    return _dstPort;
+}
+
+uint16_t IPv4TransmitRequest::getSrcPort() {
+    return _srcPort;
+}
+
+uint8_t IPv4TransmitRequest::getProtocol() {
+    return _protocol;
+}
+
+uint8_t IPv4TransmitRequest::getOption() {
+    return _option;
+}
+
+void IPv4TransmitRequest::setAddress(IpAddr &dstAddr) {
+    _dstAddr = dstAddr;
+}
+
+void IPv4TransmitRequest::setDstPort(uint16_t dstPort) {
+    _dstPort = dstPort;
+}
+
+void IPv4TransmitRequest::setSrcPort(uint16_t srcPort) {
+    _srcPort = srcPort;
+}
+
+void IPv4TransmitRequest::setProtocol(uint8_t protocol) {
+    _protocol = protocol;
+}
+
+void IPv4TransmitRequest::setOption(uint8_t option) {
+    _option = option;
+}
+
+
+Transmit_Status::Transmit_Status() : FrameIdResponse() {
+
+}
+
+uint8_t Transmit_Status::getStatus() {
+    return getFrameData()[1];
+}
+
+bool Transmit_Status::isSuccess() {
+    return getStatus() == SUCCESS;
+}
+
+
+IpAddr& IPV4RxFrame::getSrcAddress() {
+    _srcAddr = IpAddr(getFrameData()[4], getFrameData()[5], getFrameData()[6], getFrameData()[7]);
+    return _srcAddr;
+}
+
+uint16_t IPV4RxFrame::getDstPort() {
+    return (getFrameData()[8] << 8) + getFrameData()[9];
+}
+
+uint16_t IPV4RxFrame::getSrcPort() {
+    return (getFrameData()[10] << 8) + getFrameData()[11];
+}
+
+uint8_t IPV4RxFrame::getProtocol() {
+    return getFrameData()[12];
+}
+
+uint8_t IPV4RxFrame::getStatus() {
+    return getFrameData()[13];
+}
+
+// markers to read data from packet array.  this is the index, so the 12th item in the array
+uint8_t IPV4RxFrame::getDataOffset() {
+    return 14;
+}
+
+uint8_t IPV4RxFrame::getDataLength() {
+    return getPacketLength() - getDataOffset() - 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeWiFi.h	Fri Jul 29 16:22:15 2011 +0000
@@ -0,0 +1,188 @@
+/**
+ * XBee Wi-Fi library for mbed
+ * Copyright (c) 2011 Hiroshi Suga
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+/** @file
+ * @brief Weather Station
+ */
+
+#ifndef XBeeWiFi_h
+#define XBeeWiFi_h
+
+#include "mbed.h"
+#include "EthernetNetIf.h"
+#include "XBee.h"
+#include <inttypes.h>
+
+#undef USE_WIFICLASS
+#undef USE_WIFIDNS
+
+// the non-variable length of the frame data (not including frame id or api id or variable data size (e.g. payload, at command set value)
+#define IPv4_TRANSMIT_REQUEST_API_LENGTH 10
+
+/**
+ * Api Id constants
+ */
+#define IPv4_TRANSMIT_REQUEST 0x20
+#define IPv4_RX_FRAME 0xb0
+#define IPv4_TRANSMIT_STATUS 0x89
+
+/// status
+#define MAC_FAILUE 0x01
+#define PHYSICAL_ERROR 0x04
+#define NETWORK_ACK_FAILUE 0x21
+#define NOT_ASSOCIATED 0x22
+#define NO_RESOURCES 0x32
+#define CONNECTIONS_FAILUE 0x76
+
+/// protocol
+#define PROTOCOL_UDP 0
+#define PROTOCOL_TCP 1
+
+/// option
+#define OPTION_LEAVEOPEN 1
+
+/// security
+#define SECURITY_OPEN 0
+#define SECURITY_WPA 1
+#define SECURITY_WPA2 2
+#define SECURITY_WEP40 3
+#define SECURITY_WEP104 4
+
+/// modem status
+#define JOINED_AP 0
+#define SSID_NOT_CONFIGURED 0x23
+#define JOINING_AP 0xff
+
+/// dns
+#define DNS_QUERY_A 1
+#define DNS_QUERY_NS 2
+#define DNS_QUERY_CNAME 5
+#define DNS_QUERY_PTR 12
+#define DNS_QUERY_MX 15
+#define DNS_QUERY_AAAA 28
+#define DNS_QUERY_ANY 255
+#define DNS_CLASS_IN 1
+
+struct DNSHeader {
+        uint16_t id; 
+        uint16_t flags; 
+        uint16_t questions; 
+        uint16_t answers; 
+        uint16_t authorities; 
+        uint16_t additional; 
+};
+
+struct DnsQuestionEnd { 
+        uint16_t type; 
+        uint16_t clas; 
+};
+
+struct DnsAnswer {
+        uint16_t name; 
+        uint16_t type; 
+        uint16_t clas; 
+        uint32_t ttl; 
+        uint16_t length; 
+} __attribute__((packed)); 
+
+
+#ifdef USE_WIFICLASS
+/**
+ * Primary interface for communicating with an XBee Wi-Fi.
+ */
+class XBeeWiFi : public XBee {
+public:
+    XBeeWiFi (PinName p_tx, PinName p_rx);
+
+    int setup (int security, const char *ssid, const char *pin);
+    int setup (const char *ssid);
+    int reset ();
+    int setAddress ();
+    int setAddress (IpAddr &ipaddr, IpAddr &netmask, IpAddr &gateway, IpAddr &nameserver);
+    int setTimeout (int timeout);
+    int getStatus ();
+#ifdef USE_WIFIDNS
+    int getHostByName (const char* name, IpAddr &addr);
+#endif
+
+protected:
+    int getWiResponse (int apiId, int timeout = 1500);
+#ifdef USE_WIFIDNS
+    int createDnsRequest (const char* name, char *buf);
+    int getDnsResponse (const uint8_t *buf, int len, IpAddr &addr);
+#endif
+
+private:
+    IpAddr _nameserver;
+};
+#endif
+
+/**
+ * Represents a Wi-Fi TX packet that corresponds to Api Id: IPv4_TRANSMIT_REQUEST
+ */
+class IPv4TransmitRequest : public PayloadRequest {
+public:
+    /**
+     * Creates a unicast IPv4TransmitRequest with the DEFAULT_FRAME_ID
+     */
+    IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint16_t srcPort, uint8_t protocol, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId);
+    IPv4TransmitRequest(IpAddr &dstAddr, uint16_t dstPort, uint8_t *data, uint8_t dataLength);
+    /**
+     * Creates a default instance of this class.  At a minimum you must specify
+     * a payload, payload length and a destination address before sending this request.
+     */
+    IPv4TransmitRequest();
+    IpAddr& getAddress();
+    uint16_t getDstPort();
+    uint16_t getSrcPort();
+    uint8_t getProtocol();
+    uint8_t getOption();
+    void setAddress(IpAddr& dstAddr);
+    void setDstPort(uint16_t dstPort);
+    void setSrcPort(uint16_t srcPort);
+    void setProtocol(uint8_t protocol);
+    void setOption(uint8_t option);
+protected:
+    // declare virtual functions
+    virtual uint8_t getFrameData(uint8_t pos);
+    virtual uint8_t getFrameDataLength();
+private:
+    IpAddr _dstAddr;
+    uint16_t _dstPort;
+    uint16_t _srcPort;
+    uint8_t _protocol;
+    uint8_t _option;
+};
+
+/**
+ * Represents a Wi-Fi TX status packet
+ */
+class Transmit_Status : public FrameIdResponse {
+public:
+    Transmit_Status();
+    uint8_t getStatus();
+    bool isSuccess();
+};
+
+/**
+ * Represents a Wi-Fi RX packet
+ */
+class IPV4RxFrame : public RxDataResponse {
+public:
+    IPV4RxFrame();
+    IpAddr& getSrcAddress();
+    uint16_t getDstPort();
+    uint16_t getSrcPort();
+    uint8_t getProtocol();
+    uint8_t getStatus();
+    virtual uint8_t getDataLength();
+    // frame position where data starts
+    virtual uint8_t getDataOffset();
+private:
+    IpAddr _srcAddr;
+};
+
+#endif //XBeeWiFi_h