#ifdef shell
gcc -o ${0//.c/} $0 -lxbee
exit
}
#endif
/*
libxbee - a C library to aid the use of Digi's Series 1 XBee modules
running in API mode (AP=2).
Copyright (C) 2009 Attie Grande (attie@attie.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/* this sample will scan all possible channels for remote nodes and return
the value of a few useful settings */
#include
#include
#include
#include
#include
#include
#include
#define MAXNODES 100
int ATCH = 0x0C; /* origional channel number */
int ATNT = 0x19; /* node discover timeout */
int ATNTc; /* node discover timeout counter */
int BREAK = 0;
xbee_con *con;
void sighandler(int sig) {
xbee_pkt *pkt;
if (sig == SIGINT) {
BREAK = 1;
/* wait for the rest of the timeout... */
printf("\r%c[2KWaiting for node discover command to timeout...",27);
fflush(stdout);
for (; ATNTc; ATNTc--) {
usleep(100000);
}
/* Restore the XBee's channel setting */
printf("\r%c[2KRestoring channel to 0x%02X...",27,ATCH);
fflush(stdout);
if (xbee_senddata(con,"CH%c",ATCH)) {
printf("xbee_senddata: Error\n");
exit(1);
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\r%c[2K*** XBee didnt return a result for CH... ***\nPlease manually reset your channel to 0x%02X\n",27,ATCH);
}
if (pkt->status) {
printf("\r%c[2K*** An error occured while restoring the channel setting... ***\nPlease manually reset your channel to 0x%02X\n",27,ATCH);
} else {
printf("\nDone!\n");
}
free(pkt);
/* Restore the terminal */
printf("%c[?25h%c[0m",27,27);
fflush(stdout);
exit(0);
}
}
int main(int argc, char *argv[]) {
int i;
int saidfull = 0;
int ATCHc; /* current channel number */
int XBeePro = 0; /* XBee pro? */
int nodes = 0;
unsigned char addrs[MAXNODES][19]; /* 0-7 : 64 bit address
8 : channel
9-10 : id
11 : baud
12 : API
13-14: HV
15-16: VR
17 : CC
18 : mask - not address */
xbee_pkt *pkt, *rpkt;
time_t ttime;
char stime[32];
/* handle ^C */
signal(SIGINT, sighandler);
/* setup libxbee */
if (xbee_setupAPI("/dev/ttyUSB0",57600,'+',250) == -1) {
return 1;
}
/* grab a local AT connection */
con = xbee_newcon('I',xbee_localAT);
/* get the current channel */
if (xbee_senddata(con,"CH")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("XBee didnt return a result for CH\n");
return 1;
}
ATCH = pkt->data[0];
free(pkt);
/* XBee - 0x0B - 0x1A
XBee Pro - 0x0C - 0x17 */
if (xbee_senddata(con,"CH%c",0x0B)) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("XBee didnt return a result for CH\n");
return 1;
}
/* did that fail? */
if (pkt->status == 0) {
/* nope.. its not a pro */
printf("Using XBee (not Pro) channels (0x0B - 0x1A)...\n");
XBeePro = 0;
ATCHc = 0x0B;
} else {
/* yup... its a pro */
printf("Using XBee Pro channels (0x0C - 0x17)...\n");
XBeePro = 1;
ATCHc = 0x0C;
}
free(pkt);
/* find and print data for the local node */
printf("\n%c[31mCH:%c[32m 0x%02X ",27,27,ATCH);
if (xbee_senddata(con,"ID")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for ID\n");
return 1;
}
printf("%c[31mID:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]);
free(pkt);
/* ### */
if (xbee_senddata(con,"MY")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for MY\n");
return 1;
}
printf("%c[31mMY:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]);
free(pkt);
/* ### */
if (xbee_senddata(con,"SH")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for SH\n");
return 1;
}
printf("%c[31mSH:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[0],pkt->data[1],pkt->data[2],pkt->data[3]);
free(pkt);
/* ### */
if (xbee_senddata(con,"SL")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for SL\n");
return 1;
}
printf("%c[31mSL:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[0],pkt->data[1],pkt->data[2],pkt->data[3]);
free(pkt);
/* ### */
if (xbee_senddata(con,"BD")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for BD\n");
return 1;
}
printf("%c[31mBD:%c[32m ",27,27);
/* print the baud rate */
switch (pkt->data[3]) {
case 0: printf(" 1200"); break;
case 1: printf(" 2400"); break;
case 2: printf(" 4800"); break;
case 3: printf(" 9600"); break;
case 4: printf(" 19200"); break;
case 5: printf(" 38400"); break;
case 6: printf(" 57600"); break;
case 7: printf("115200"); break;
default: printf(" other"); break;
}
printf(" ");
free(pkt);
/* ### */
if (xbee_senddata(con,"AP")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for AP\n");
return 1;
}
printf("%c[31mAP:%c[32m 0x%02X ",27,27,pkt->data[0]);
free(pkt);
/* ### */
if (xbee_senddata(con,"HV")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for HV\n");
return 1;
}
printf("%c[31mHV:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]);
free(pkt);
/* ### */
if (xbee_senddata(con,"VR")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for VR\n");
return 1;
}
printf("%c[31mVR:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]);
free(pkt);
/* ### */
if (xbee_senddata(con,"CC")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for CC\n");
return 1;
}
printf("%c[31mCC:%c[32m '%c' (0x%02X) ",27,27,pkt->data[0],pkt->data[0]);
free(pkt);
/* ### */
if (xbee_senddata(con,"NI")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("\nXBee didnt return a result for NI\n");
return 1;
}
printf("%c[31mNI:%c[32m %-20s ",27,27,pkt->data);
free(pkt);
/* ### */
printf("%c[95m* This is the lobal XBee *",27);
printf("%c[34m\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------%c[0m\n\n",27,27);
/* get the ND timeout */
if (xbee_senddata(con,"NT")) {
printf("xbee_senddata: Error\n");
return 1;
}
if ((pkt = xbee_getpacketwait(con)) == NULL) {
printf("XBee didnt return a result for NT\n");
return 1;
}
ATNT = pkt->data[0];
free(pkt);
printf("%c[?25l",27);
fflush(stdout);
usleep(100000);
while (!BREAK) {
/* set the channel to scan */
if (xbee_senddata(con,"CH%c",ATCHc)) {
printf("xbee_senddata: Error\n");
return 1;
}
pkt = xbee_getpacketwait(con);
if (!pkt || pkt->status) {
printf("\nXBee didnt return a result for CH\n");
return 1;
}
free(pkt);
printf("%c[2KScanning channel 0x%02X...\r",27,ATCHc);
fflush(stdout);
/* send a ND - Node Discover request */
if (!xbee_senddata(con,"ND")) {
/* only wait for a bit longer than the ND timeout */
ATNTc = ATNT + 10;
/* loop until the end packet has been received or timeout reached */
while (!BREAK && ATNTc--) {
/* get a packet */
pkt = xbee_getpacket(con);
/* check a packet was returned, and that its one we are after... */
if (pkt && !memcmp(pkt->atCmd,"ND",2)) {
/* is this the end packet? you can tell from the 0 datalen */
if (pkt->datalen == 0) {
/* free the packet */
free(pkt);
break;
} else {
/* check if we know this node already */
for (i = 0; i < nodes; i++) {
/* the 64bit address will match one in the list */
if (!memcmp(&(pkt->data[2]),&(addrs[i][0]),8)) break;
}
ttime = time(NULL);
strftime(stime,32,"%I:%M:%S %p",gmtime(&ttime));
/* is there space for another? */
if ((i == nodes) &&
(nodes == MAXNODES) &&
(!saidfull)) {
printf("%c[2KMAXNODES reached... Can't add more...\r",27);
/* flush so the change is seen! */
fflush(stdout);
saidfull = 1;
} else {
/* is this a rewrite? */
if (i != nodes) {
/* find the line to edit */
printf("%c[%dA",27,nodes-i+1);
/* clear the line */
printf("%c[2K",27);
} else {
/* fill the blank line */
printf("%c[%dA",27,1);
}
/* save the channel */
addrs[i][8] = ATCHc;
/* write out the info */
printf("%c[31mCH:%c[32m 0x%02X ",27,27,ATCHc);
printf("%c[31mID:%c[32m 0x",27,27);
if (i == nodes || !(addrs[i][18] & 0x80)) {
printf("....");
} else {
printf("%02X%02X",addrs[i][9],addrs[i][10]);
}
printf(" ");
printf("%c[31mMY:%c[32m 0x%02X%02X ",27,27,pkt->data[0],pkt->data[1]);
printf("%c[31mSH:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[2],pkt->data[3],pkt->data[4],pkt->data[5]);
printf("%c[31mSL:%c[32m 0x%02X%02X%02X%02X ",27,27,pkt->data[6],pkt->data[7],pkt->data[8],pkt->data[9]);
printf("%c[31mBD:%c[32m ",27,27);
if (i == nodes || !(addrs[i][18] & 0x40)) {
printf("......");
} else {
switch (addrs[i][11]) {
case 0: printf(" 1200"); break;
case 1: printf(" 2400"); break;
case 2: printf(" 4800"); break;
case 3: printf(" 9600"); break;
case 4: printf(" 19200"); break;
case 5: printf(" 38400"); break;
case 6: printf(" 57600"); break;
case 7: printf("115200"); break;
default: printf(" other"); break;
}
}
printf(" ");
printf("%c[31mAP:%c[32m 0x",27,27);
if (i == nodes || !(addrs[i][18] & 0x20)) {
printf("..");
} else {
printf("%02X",addrs[i][12]);
}
printf(" ");
printf("%c[31mHV:%c[32m 0x",27,27);
if (i == nodes || !(addrs[i][18] & 0x10)) {
printf("....");
} else {
printf("%02X%02X",addrs[i][13],addrs[i][14]);
}
printf(" ");
printf("%c[31mVR:%c[32m 0x",27,27);
if (i == nodes || !(addrs[i][18] & 0x08)) {
printf("....");
} else {
printf("%02X%02X",addrs[i][15],addrs[i][16]);
}
printf(" ");
printf("%c[31mCC:%c[32m ",27,27);
if (i == nodes || !(addrs[i][18] & 0x04)) {
printf(" . (0x..)");
} else {
printf("'%c' (0x%02X)",addrs[i][17],addrs[i][17]);
}
printf(" ");
printf("%c[31mNI:%c[32m %-20s ",27,27,&(pkt->data[11]));
printf("%c[31mdB:%c[32m -%2d ",27,27,pkt->data[10]);
printf("%c[31m@:%c[32m %s",27,27,stime);
/* is this a rewrite? */
if (i != nodes) {
/* go back the the bottom */
printf("%c[%dB\r",27,nodes-i+1);
} else {
/* if its new... save the address */
memcpy(&(addrs[nodes][0]),&(pkt->data[2]),8);
/* turn off all the flags */
addrs[nodes][18] = 0;
/* new line is only wanted for new nodes */
printf("\n%c[2K\n%c[0m",27,27);
/* if not, then add 1 to the number of nodes! */
nodes++;
}
printf("%c[0m%c[2KScanning channel 0x%02X...\r",27,27,ATCHc);
fflush(stdout);
}
/* flush so the change is seen! */
fflush(stdout);
}
/* free the packet */
free(pkt);
}
/* sleep for 100ms (same as NT steps */
usleep(100000);
}
}
fflush(stdout);
/* check for all nodes on this channel, and get thier pan id */
for (i = 0; i < nodes; i++) {
int first = 1;
if (addrs[i][8] == ATCHc) {
xbee_con *tcon;
unsigned int dh,dl;
if (first) {
printf("%c[2KGathering settings for nodes on channel 0x%02X...\r",27,ATCHc);
first = 0;
}
/* get the address, and turn it the right way up! */
memcpy(&dh,&(addrs[i][0]),4);
dh = ((dh & 0xFF) << 24) | ((dh & 0xFF00) << 8) | ((dh & 0xFF0000) >> 8) | ((dh & 0xFF000000) >> 24);
memcpy(&dl,&(addrs[i][4]),4);
dl = ((dl & 0xFF) << 24) | ((dl & 0xFF00) << 8) | ((dl & 0xFF0000) >> 8) | ((dl & 0xFF000000) >> 24);
/* setup a connection the the remote node */
if ((tcon = xbee_newcon('I',xbee_64bitRemoteAT,dh,dl)) != NULL) {
/* find the line to edit */
printf("\r%c[%dA",27,nodes-i+1);
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"ID")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the ID column */
printf("\r%c[18C",27);
/* print the ID */
printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27);
addrs[i][9] = rpkt->data[0];
addrs[i][10] = rpkt->data[1];
/* turn on the flag */
addrs[i][18] |= 0x80;
free(rpkt);
}
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"BD")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the BD column */
printf("\r%c[80C",27);
if ((rpkt->data[0] != 0x00) || (rpkt->data[1] != 0x00) || (rpkt->data[2] != 0x00) || ((rpkt->data[3] & 0xF8) != 0x00)) {
addrs[i][11] = 8;
} else {
addrs[i][11] = rpkt->data[3];
}
/* turn on the flag */
addrs[i][18] |= 0x40;
/* print the baud rate */
printf("%c[32m",27);
switch (addrs[i][11]) {
case 0: printf(" 1200"); break;
case 1: printf(" 2400"); break;
case 2: printf(" 4800"); break;
case 3: printf(" 9600"); break;
case 4: printf(" 19200"); break;
case 5: printf(" 38400"); break;
case 6: printf(" 57600"); break;
case 7: printf("115200"); break;
default: printf(" other"); break;
}
printf("%c[0m",27);
free(rpkt);
}
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"AP")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the AP column */
printf("\r%c[96C",27);
/* print the ID */
printf("%c[32m%02X%c[0m",27,rpkt->data[0],27);
addrs[i][12] = rpkt->data[0];
/* turn on the flag */
addrs[i][18] |= 0x20;
free(rpkt);
}
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"HV")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the HV column */
printf("\r%c[108C",27);
/* print the ID */
printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27);
addrs[i][13] = rpkt->data[0];
addrs[i][14] = rpkt->data[1];
/* turn on the flag */
addrs[i][18] |= 0x10;
free(rpkt);
}
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"VR")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the VR column */
printf("\r%c[122C",27);
/* print the ID */
printf("%c[32m%02X%02X%c[0m",27,rpkt->data[0],rpkt->data[1],27);
addrs[i][15] = rpkt->data[0];
addrs[i][16] = rpkt->data[1];
/* turn on the flag */
addrs[i][18] |= 0x08;
free(rpkt);
}
/* in this case we dont care if we dont get a response packet... */
if (xbee_senddata(tcon,"CC")) {
printf("xbee_senddata: Error\n");
return 1;
}
if (((rpkt = xbee_getpacketwait(tcon)) != NULL) && (rpkt->status == 0)) {
/* move over the CC column */
printf("\r%c[134C",27);
/* print the ID */
printf("%c[32m'%c' (0x%02X)%c[0m",27,rpkt->data[0],rpkt->data[0],27);
addrs[i][17] = rpkt->data[0];
/* turn on the flag */
addrs[i][18] |= 0x04;
free(rpkt);
}
/* go back the the bottom */
printf("%c[%dB\r",27,nodes-i+1);
fflush(stdout);
}
}
}
/* fall back to the first channel if that was the last */
if (XBeePro && ATCHc == 0x17) {
ATCHc = 0x0C;
} else if (!XBeePro && ATCHc == 0x1A) {
ATCHc = 0x0B;
} else {
/* else move onto next channel */
ATCHc++;
}
usleep(100000);
}
return 0;
}