Xbee

Files at this revision

API Documentation at this revision

Comitter:
renanbmx123
Date:
Sun Oct 14 02:01:07 2018 +0000
Commit message:
Xbee

Changed in this revision

XBEE.cpp Show annotated file Show diff for this revision Revisions of this file
XBEE.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r fbed291691a6 XBEE.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBEE.cpp	Sun Oct 14 02:01:07 2018 +0000
@@ -0,0 +1,448 @@
+#include "XBEE.h"
+#include <stdlib.h>
+
+/* Class constructor */
+XBEE::XBEE(Serial* serial, int baud):xbee(serial)
+{
+    xbee->baud(baud);
+    /* Enable the reception of bytes on the serial interface by providing a cb */
+    xbee->attach(callback(this, &XBEE::recvAttach), Serial::RxIrq);
+}
+
+/* Class destructor */
+XBEE::~XBEE() 
+{
+    if (xbee != NULL) {
+        delete xbee;
+    }
+}
+
+/* Chamada por Interrupcao, RX */
+void XBEE::recvAttach (void) 
+{
+    if (int_ctrl == 1)
+        while(xbee->readable()) {
+            buf_rx[count_rx%sizeof(buf_rx)] = xbee->getc();
+            //buf_rx.push(xbee->getc());
+            count_rx++;
+        }
+}
+
+/* Initialize the Device XBEE */
+void XBEE::init(void)
+{
+ //   memset(&NI,0,sizeof(NI));
+    ID = 0;
+    MY = 0;
+    SH = 0;
+    SL = 0;
+    PL = 0;
+    BD = 0;
+    AO = 0;
+    DB = 0;
+    TP = 0;
+    
+    wait(0.5);
+    
+    memset(&buf_rx,0,sizeof(buf_rx));
+    
+    create_CMD("NI",0);    // Pan ID da rede
+    sendBuffer();
+    wait(0.5);
+    
+    recv_NI();
+    read_cfg("ID", ID);
+    read_cfg("SH", SH);
+    read_cfg("SL", SL);
+    read_cfg("PL", PL);
+    read_cfg("BD", BD);
+    read_cfg("AO", AO);
+    read_cfg("DB", DB);
+    read_cfg("TP", TP);
+    
+    count_rx = 0;
+    memset(&buf_rx,0,sizeof(buf_rx));
+}
+
+/* Send message to the destination */
+int XBEE::send_msg(char * str, int dest)
+{
+    int n = strlen(str);
+    if(n > 92) {
+        return -1;
+    }
+    create_TX(str,dest);
+    sendBuffer();
+    wait(0.2);
+    return 0;
+}
+
+/* Sets a configuration value into the module device */
+int XBEE::set_cfg(char * cmd, int value)
+{
+    int n = strlen(cmd);
+    if(n != 2) {
+        return -1;
+    }
+    create_CMD(cmd,hex2dec(value));
+    sendBuffer();
+    wait(0.2);
+    
+    create_CMD("WR",0);
+    sendBuffer();
+    wait(0.2);
+    
+    create_CMD("AC",0);
+    sendBuffer();
+    wait(0.2);
+    return 0;
+}
+
+/* Receives a message, writes in str */
+int XBEE::recv_msg(char * buf, int tam)
+{
+    pkt_tx *p;
+    int i;
+    int ptam = 0;
+    int j = 0;
+    
+    memset(buf,0,tam);
+    
+    for(i = 0; i < count_rx; i++) {
+        if(buf_rx[i] == 0x7E) {
+            
+            p = (pkt_tx *) &buf_rx[i];
+            
+            if(p->frame_type == 0x90) {
+                ptam = p->length - 0x0C;
+                if(tam < ptam + j) {
+                    return -1;
+                }
+                // posicao aonde comeca a msg em um pacote de Receive
+                memcpy(&buf[j], ((char *)(&p->broadcast_radius)), ptam);
+                j += ptam;
+            }
+        }
+    }
+    return j;
+}
+
+/* Updates the command value, call a request from device configurations */
+int XBEE::read_cfg(char * cmd, int & var)
+{
+    int n = strlen(cmd);
+    if(n != 2) {
+        return -1;    
+    }
+    count_rx = 0;
+    memset(&buf_rx,0,sizeof(buf_rx));
+    
+    create_CMD(cmd,0);    // Pan ID da rede
+    sendBuffer();
+    wait(0.5);
+    recv_CMD(var);
+    return 0;
+}
+
+/* Clear all the Receive buffer */
+void XBEE::clear_buf(void)
+{
+    count_rx = 0;
+    memset(buf_rx,0,sizeof(buf_rx));
+}
+
+/* Cria pacote de mensagem */
+int XBEE::create_TX(char * str, int dest) 
+{
+    int i = 0;
+    int n = strlen(str);
+
+    pkt_tx *p = (pkt_tx *) buf_tx; // ponteiro para buffer global
+    
+    uint8_t count = 0;
+
+    if(n > 92) {
+        // Error: data nao pode exceder 92 bytes
+        return -1;
+    }
+
+    count_tx = 0;
+    memset(&buf_tx,0,sizeof(buf_tx));
+
+    p->start_delimiter = 0x7E;
+    p->length = 0x0E + n;   // pacote vazio + dados
+    p->frame_type = 0x10;   // transmit request
+    p->frame_id = 1;
+
+    if(dest == XBEE_COORD) {
+        p->dest_addr64[6] = 0x00;   //SL_H
+        p->dest_addr64[7] = 0x00;   //SL_L
+    } else if(dest == XBEE_BROAD) {
+        p->dest_addr64[6] = 0xFF;   //SL_H
+        p->dest_addr64[7] = 0xFF;   //SL_L
+    } else {
+        p->dest_addr64[0] = 0x00;
+        p->dest_addr64[1] = 0x13;
+        p->dest_addr64[2] = 0xA2;
+        p->dest_addr64[3] = 0x00;
+        
+        p->dest_addr64[4] = (dest >> 24);
+        p->dest_addr64[5] = (dest & 0x00FF0000) >> 16;
+        p->dest_addr64[6] = (dest & 0x0000FF00) >> 8;
+        p->dest_addr64[7] = (dest & 0x000000FF);
+    }
+    p->dest_addr16[0] = 0xFF;   //MY_H
+    p->dest_addr16[1] = 0xFF;   //MY_L
+    
+    memcpy(&p->rf_data, str, n);
+
+    // Calcula Checksum
+
+    // comeca 3 pra frente, tenq passar 3 adiante no final
+    // para ler o mesmo tamanho de pacote
+    for(i = 3; i < p->length + 3; i++) {
+        count += buf_tx[i];
+        //printf("\n%d\n", count);
+    }
+    count = 0xFF - count;
+
+    p->rf_data[n] = count;
+
+    //p->length tem o tamanho soh do frame, 
+    //pacote total eh o starter + length alto + length baixo + checksum
+    count_tx = p->length + 4;
+    return count_tx;
+}
+
+/* Cria pacote de comando */
+int XBEE::create_CMD(char * cmd, int val) 
+{
+    pkt_cmd *p = (pkt_cmd *) buf_tx; // ponteiro para buffer global
+    char str[4];    // string do val
+    int size_cmd = strlen(cmd);
+    //int value = dec2hex(val);
+    int value = val;
+    int n = 0;  // tamanho em bytes do parametro do comando
+    int i;
+    uint8_t count = 0;
+    
+    if(size_cmd != 2) {
+        // Error: comando deve conter 2 chars
+        return -1;
+    }
+    
+    if(val != 0) {
+        if( (value >> 24) & 0xFF ) {
+            str[0] = (value >> 24) & 0xFF;
+            str[1] = (value >> 16) & 0xFF;
+            str[2] = (value >> 8) & 0xFF;
+            str[3] = value & 0xFF;
+            n = 4;
+        } else if( (value >> 16) & 0xFF ) {
+            str[0] = (value >> 16) & 0xFF;
+            str[1] = (value >> 8) & 0xFF;
+            str[2] = value & 0xFF;
+            n = 3;
+        } else if( (value >> 8) & 0xFF ) {
+            str[0] = (value >> 8) & 0xFF;
+            str[1] = value & 0xFF;
+            n = 2;
+        } else {
+            str[0] = value & 0xFF;
+            n = 1;
+        }
+    }
+
+    count_tx = 0;
+    memset(&buf_tx,0,sizeof(buf_tx));
+
+    p->start_delimiter = 0x7E;
+    p->length = 0x04 + n;   // pacote vazio + dados
+    p->frame_type = 0x09;   // AT Command Queue
+    p->frame_id = 1;
+    
+    p->command[0] = cmd[0];
+    p->command[1] = cmd[1];
+    
+    if(val != 0) {
+        memcpy(&p->rf_data, str, n);
+    }
+
+    // Calcula Checksum
+
+    // comeca 3 pra frente, tenq passar 3 adiante no final
+    // para ler o mesmo tamanho de pacote
+    for(i = 3; i < p->length + 3; i++) {
+        count += buf_tx[i];
+        //printf("\n%d\n", count);
+    }
+    count = 0xFF - count;
+
+    p->rf_data[n] = count;
+
+    //p->length tem o tamanho soh do frame, 
+    //pacote total eh o starter + length alto + length baixo + checksum
+    count_tx = p->length + 4;
+    return count_tx;
+}
+
+/* Envia pacote do buffer_tx */
+void XBEE::sendBuffer(void) 
+{
+    if(xbee->writeable()) {
+        for(int i = 0; i < count_tx; i++) {
+            xbee->putc(buf_tx[i]);
+        }
+        //pode zerar pacote aqui
+    }
+}
+
+/* Printa todo o buffer de Receive, e limpa */
+/*
+void XBEE::printBuffer(void) 
+{
+    char flag_msg = 0;
+    int size = sizeof(buf_rx);
+    if(count_rx < size) {
+        size = count_rx;
+    }
+    for(int i = 0; i < size; i++) {
+        printf("%c", buf_rx[i]);
+        flag_msg++;
+    }
+    if (flag_msg) {
+        printf("\n");
+    }
+    
+    //Limpa buffer
+    count_rx = 0;
+    memset(&buf_rx,0,sizeof(buf_rx));
+} 
+*/
+
+/* Receive and update NI variable */
+void XBEE::recv_NI(void)
+{
+    pkt_cmd *p;
+    int i;
+    for(i = 0; i < count_rx; i++) {
+        if(buf_rx[i] == 0x7E) {
+            p = (pkt_cmd *) &buf_rx[i];
+        }
+    }
+    if(p->frame_type == 0x88) {
+        memcpy(NI, ((char *)(&p->rf_data))+2, 16);
+        // remove o checksum do nome
+        for(i = 15; i >= 0; i--) {
+            if(NI[i] != 0) {
+                NI[i] = '\0';
+                break;
+            }
+        }
+    }
+}
+
+/* Receive and update CMD variable */
+void XBEE::recv_CMD(int &cmd)
+{
+    char data[16];
+    pkt_cmd *p;
+    int i;
+    int j = -1;
+    
+    for(i = 0; i < count_rx; i++) {
+        if(buf_rx[i] == 0x7E) {
+            p = (pkt_cmd *) &buf_rx[i];
+        }
+    }
+    if(p->frame_type == 0x88) {
+        memcpy(data, &p->rf_data, 16);
+        for(i = 15; i > -1; i--) {
+            if(data[i] != 0 || j != -1) {
+                // pular o checksum
+                if(j==-1) {
+                    j++;
+                } else {
+                    //ID = (int)(dec2hex((data[i] << 8)) + dec2hex(data[i+1]));
+                    cmd += data[i] << 8*j;
+                    j++;
+                }
+            }
+        }
+    }
+}
+
+/* Verify Packet Checksum return 0 if msg OK, just work with Transmit Package*/
+/*
+char XBEE::validPackage(uint8_t * buf, int tam) 
+{
+    int i = 0;
+    uint8_t count = 0;
+    
+    if(buf[0] != 0x7E) return 1;
+    if(buf[1] != 0) return 2;
+    if(buf[2] != tam-4) return 3;
+    
+    for(i = 3; i < tam; i++) {
+        count += buf[i];
+    }
+    if(count != 0xFF) return 4;
+    
+    return 0; // OK
+}
+*/
+
+/* Convert Dec to Hex, OBS: just for Hex number without Letter */
+int XBEE::dec2hex(int nbr)
+{
+    char hexa[8];
+    int temp;
+    int result = 0;
+    int i = 0;
+    char hasLetter = 0;
+    
+    while(nbr != 0)
+    {
+        temp = nbr % 16;
+        hexa[i] = temp;
+        nbr = nbr / 16;
+        i++;
+        if(temp > 9) {
+            hasLetter++;
+        }
+    }
+    // concat number
+    for(i=i-1; i > -1; i--) {
+        result += hexa[i] * pow(10.0,(double)i);
+    }
+    
+    return result;
+}
+
+/* Convert Hex to Dec */
+int XBEE::hex2dec(int nbr)
+{
+    char deci[8];
+    int result = 0;
+    int i = 0;
+    int temp;
+    char hasLetter = 0;
+    
+    while(nbr != 0) {
+        temp = nbr % 10;
+        deci[i] = temp;
+        nbr = nbr / 10;
+        i++;
+        if(temp > 9) {
+            hasLetter++;
+        }
+    }
+    // concat number
+    for(i=i-1; i > -1; i--) {
+        result += (deci[i] * pow(16.0,(double)i) );
+    }
+    return result;
+}
+void XBEE::int_mng(int value){
+    int_ctrl = value;
+}
diff -r 000000000000 -r fbed291691a6 XBEE.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBEE.h	Sun Oct 14 02:01:07 2018 +0000
@@ -0,0 +1,98 @@
+#if !defined(__XBEE_H_)
+#define __XBEE_H_
+
+#include "mbed.h"
+#include <string.h>
+#include <stdint.h> // uint8_t
+#include <stdlib.h> // itoa
+#include <math.h>
+
+#define XB_SIZEBUF  64
+#define XB_PAYLOAD  16
+
+#define XBEE_COORD  0
+#define XBEE_BROAD  1
+
+// para poder declarar como typedef
+typedef struct __attribute__ ((__packed__)) {
+    uint8_t start_delimiter;
+    uint8_t length_H;
+    uint8_t length;
+    // Frame do Pacote
+    uint8_t frame_type;     // 10
+    uint8_t frame_id;
+    uint8_t dest_addr64[8];
+    uint8_t dest_addr16[2];
+    uint8_t broadcast_radius;
+    uint8_t options;
+    uint8_t rf_data[100]; //NOTE: last byte MUST be checksum
+}pkt_tx;
+
+// para poder declarar como typedef
+typedef struct __attribute__ ((__packed__)) {
+    uint8_t start_delimiter;
+    uint8_t length_H;
+    uint8_t length;
+    // Frame do Pacote
+    uint8_t frame_type;     // 8
+    uint8_t frame_id;
+    uint8_t command[2];         // ASCII
+    uint8_t rf_data[16]; //NOTE: last byte MUST be checksum
+}pkt_cmd;
+
+
+/* Classe para controlar XBEE Zigbee usando API*/
+class XBEE {
+    public:
+        uint8_t buf_tx[XB_SIZEBUF];     // Serial TX
+        uint8_t buf_rx[XB_SIZEBUF];     // Serial RX
+        //CircularBuffer<uint8_t, XB_SIZEBUF> buf_rx;
+        int count_tx;
+        int count_rx;
+        // DEVICE DATA
+        char NI[16];    // Device Name
+        int ID;         // Net ID
+        int MY;         // Device Net Address
+        int SH;         // Serial High
+        int SL;         // Serial Low
+        int PL;         // Power Level
+        int BD;         // Baud Rate
+        int AO;         // API option
+        int DB;         // RSSI between messages
+        int TP;         // Temperature inside module
+        
+        //XBEE(PinName tx, PinName rx, int baud = 9600);
+        XBEE(Serial* serial, int baud = 9600);
+        /** Class destructor */
+        virtual ~XBEE();
+        void recvAttach (void);
+        
+        // High Level Function
+        void init (void);
+        int send_msg(char * str, int dest);
+        int set_cfg(char * cmd, int value);
+        int recv_msg(char * buf, int tam);
+        int read_cfg(char * cmd, int & var);
+        void clear_buf(void);
+        
+        // Low Level Function
+        int create_TX(char * str, int dest);
+        int create_CMD(char * cmd, int val);
+        void sendBuffer(void);
+        //void printBuffer(void);
+        void recv_NI(void);
+        void recv_CMD(int & cmd);
+        void int_mng(int value);
+        
+        // Auxiliar Function
+        //char validPackage (uint8_t * buf, int tam);
+        int dec2hex(int nbr);
+        int hex2dec(int nbr);   //ToDo
+        
+    protected:
+        //RawSerial   *xbee;
+        Serial* xbee;
+        int int_ctrl;
+};
+
+#endif /* defined(__XBEE_H_) */
\ No newline at end of file