int main(int argc, char *argv[]) { struct xbee *xbee; xbee_err ret; int level; if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_logLevelGet(xbee, &level)) != XBEE_ENONE) { printf("xbee_logLevelGet() returned: %d\n", ret); return ret; } printf("libxbee log level is currently: %d\n", level); printf("\nDon't forget you can set the log level via the environment, for example:\n\tXBEE_LOG_LEVEL=100 %s\n\n", argv[0]); xbee_log(xbee, 50, "Test Message 1..."); printf("setting libxbee log level to: 100\n"); if ((ret = xbee_logLevelSet(xbee, 100)) != XBEE_ENONE) { printf("xbee_logLevelSet() returned: %d\n", ret); return ret; } xbee_log(xbee, 50, "Test Message 2..."); xbee_shutdown(xbee); return 0; }
/* get a packet from a connection if no packet is avaliable or an error occurs, then NULL is returned */ EXPORT struct xbee_pkt *xbee_conRx(struct xbee *xbee, struct xbee_con *con) { struct xbee_pkt *pkt; /* check parameters */ if (!xbee) { if (!xbee_default) return NULL; xbee = xbee_default; } if (!xbee_validate(xbee)) return NULL; if (!con) return NULL; /* check the provided connection */ if (_xbee_conValidate(xbee, con, NULL)) return NULL; /* you aren't allowed at the packets this way if a callback is enabled... */ if (con->callback) { xbee_log(1,"Cannot retrieve a packet while callback is enabled for connection @ %p", con); return NULL; } /* try to get a packet */ if ((pkt = (struct xbee_pkt*)ll_ext_head(&(con->rxList))) == NULL) { /* if there isnt one, then log a message */ xbee_log(10,"No packets for connection @ %p", con); return NULL; } /* if there is one, then log its details and return it */ xbee_log(2,"Gave a packet @ %p to the user from connection @ %p, %d remain...", pkt, con, ll_count_items(&(con->rxList))); return pkt; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; char txRet; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee2", "/dev/ttyUSB1", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conNew(xbee, &con, "Identify", NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } sleep(3000); if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
void catchallCB(struct xbee *xbee, struct xbee_con *con, struct xbee_pkt **pkt, void **data) { xbee_err ret; struct xbee_con *newCon; printf("Got packet from new node!\n"); if ((*pkt)->address.addr16_enabled) { printf(" 16-bit (0x%02X%02X)\n", (*pkt)->address.addr16[0], (*pkt)->address.addr16[1]); } if ((*pkt)->address.addr64_enabled) { printf(" 64-bit (0x%02X%02X%02X%02X 0x%02X%02X%02X%02X)\n", (*pkt)->address.addr64[0], (*pkt)->address.addr64[1], (*pkt)->address.addr64[2], (*pkt)->address.addr64[3], (*pkt)->address.addr64[4], (*pkt)->address.addr64[5], (*pkt)->address.addr64[6], (*pkt)->address.addr64[7]); } if ((*pkt)->address.endpoints_enabled) { printf(" Endpoints (local: 0x%02X, remote: 0x%02X)\n", (*pkt)->address.endpoint_local, (*pkt)->address.endpoint_remote); } /* you should really hold on to the returned newCon somehow, but for the sample it is just let loose! */ if ((ret = xbee_conNew(xbee, &newCon, (*pkt)->conType, &(*pkt)->address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return; } if ((ret = xbee_conCallbackSet(newCon, specificCB, NULL)) != XBEE_ENONE) { xbee_conEnd(newCon); xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return; } specificCB(xbee, newCon, pkt, data); }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 9600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0x08; address.addr64[6] = 0x18; address.addr64[7] = 0x26; if ((ret = xbee_conNew(xbee, &con, "64-bit Data", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conDataSet(con, xbee, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } for (;;) { void *p; if ((ret = xbee_conCallbackGet(con, (xbee_t_conCallback*)&p)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackGet() returned: %d", ret); return ret; } if (p == NULL) break; usleep(1000000); } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_pkt *pkt; struct xbee_conAddress address; char txRet; int i; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee2", "/dev/ttyUSB1", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0x2D; address.addr64[6] = 0x60; address.addr64[7] = 0x7B; if ((ret = xbee_conNew(xbee, &con, "Remote AT", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } for (i = 0; i < 60 * 4; i++) { unsigned char value; if ((ret = xbee_conTx(con, NULL, "IS")) != XBEE_ENONE) break; if ((ret = xbee_conRx(con, &pkt, NULL)) != XBEE_ENONE) break; if ((ret = xbee_pktDigitalGet(pkt, 3, 0, &value)) != XBEE_ENONE) { printf("xbee_pktDigitalGet(channel=3): ret %d\n", ret); } else { printf("D3: %d\n", value); } xbee_pktFree(pkt); usleep(250000); } if (ret != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conTx() or xbee_conRx() returned: %d", ret); return ret; } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; unsigned char txRet; xbee_err ret; /* setup libxbee, using the USB to Serial adapter '/dev/ttyUSB0' at 57600 baud */ if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } /* create a new AT connection to the local XBee */ if ((ret = xbee_conNew(xbee, &con, "Local AT", NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } /* send the AT command 'NI' (request the Node Identifier) when the response is recieved, the packet will be directed to the callback function */ ret = xbee_conTx(con, &txRet, "NI"); /* print out the return value if this is non-zero, then check 'enum xbee_errors' in xbee.h for its meaning alternatively look at the xbee_errorToStr() function */ printf("tx: %d\n", ret); if (ret) { /* if ret was non-zero, then some error occured if ret == XBEE_ETX then it is possible that txRet is now -17 / XBEE_ETIMEOUT alternatively, txRet will contain the status code returned by the XBee */ printf("txRet: %d\n", txRet); } else { struct xbee_pkt *pkt; if ((ret = xbee_conRx(con, &pkt, NULL)) != XBEE_ENONE) { printf("Error after calling xbee_conRx(): %s\n", xbee_errorToStr(ret)); } else { int i; printf("Response is %d bytes long:\n", pkt->dataLen); for (i = 0; i < pkt->dataLen; i++) { printf("%3d: 0x%02X - %c\n", i, pkt->data[i], (((pkt->data[i] >= ' ') && (pkt->data[i] <= '~'))?pkt->data[i]:'.')); } } } /* shutdown the connection */ if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } /* shutdown libxbee */ xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; xbee_err ret; unsigned char txRet; struct timespec to; if (sem_init(&ndComplete, 0, 0) != 0) { printf("sem_init() returned an error: %d - %s\n", errno, strerror(errno)); return -1; } if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conNew(xbee, &con, "Local AT", NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, nodeCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } if ((ret = xbee_conTx(con, &txRet, "ND")) != XBEE_ENONE && (ret != XBEE_ETX && ret != XBEE_ETIMEOUT)) { xbee_log(xbee, -1, "xbee_conTx() returned: %d-%d", ret, txRet); return ret; } printf("ND Sent!... waiting for completion\n"); clock_gettime(CLOCK_REALTIME, &to); to.tv_sec += 10; if (sem_timedwait(&ndComplete, &to) != 0) { if (errno == ETIMEDOUT) { printf("Timeout while waiting for ND command to complete...\n"); } else { printf("Error calling sem_timedwait()... sleeping for 10 seconds instead\n"); sleep(10); } } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; struct xbee_conSettings settings; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee2", "/dev/ttyUSB1", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x00; address.addr64[2] = 0x00; address.addr64[3] = 0x00; address.addr64[4] = 0x00; address.addr64[5] = 0x00; address.addr64[6] = 0xFF; address.addr64[7] = 0xFF; if ((ret = xbee_conNew(xbee, &con, "Data", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } /* getting an ACK for a broadcast message is kinda pointless... */ xbee_conSettings(con, NULL, &settings); settings.disableAck = 1; xbee_conSettings(con, &settings, NULL); for (;;) { xbee_conTx(con, NULL, "Hello...\r\n"); /* you probrably don't want to transmit much quicker than once per 2 seconds... read the datashee for more info */ sleep(2); } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; unsigned char txRet; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee2", "/dev/ttyUSB1", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } /* this is the 64-bit address of the remote XBee module it should be entered with the MSB first, so the address below is SH = 0x0013A200 SL = 0x40081826 */ memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0x2D; address.addr64[6] = 0x60; address.addr64[7] = 0x7B; if ((ret = xbee_conNew(xbee, &con, "Remote AT", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } ret = xbee_conTx(con, &txRet, "NI"); printf("tx: %d\n", ret); if (ret) { printf("txRet: %d\n", txRet); } else { usleep(1000000); } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
/* write the provided address information to the log */ void xbee_conLogAddress(struct xbee *xbee, struct xbee_conAddress *address) { if (address->addr16_enabled) { xbee_log(6,"16-bit address: 0x%02X%02X", address->addr16[0], address->addr16[1]); } if (address->addr64_enabled) { xbee_log(6,"64-bit address: 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X", address->addr64[0], address->addr64[1], address->addr64[2], address->addr64[3], address->addr64[4], address->addr64[5], address->addr64[6], address->addr64[7]); } if (address->endpoints_enabled) { xbee_log(6,"Endpoints (local/remote): 0x%02X/0x%02X", address->local_endpoint, address->remote_endpoint); } }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; struct xbee_conSettings settings; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x00; address.addr64[2] = 0x00; address.addr64[3] = 0x00; address.addr64[4] = 0x00; address.addr64[5] = 0x00; address.addr64[6] = 0xFF; address.addr64[7] = 0xFF; if ((ret = xbee_conNew(xbee, &con, "64-bit Data", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } xbee_conSettings(con, NULL, &settings); settings.catchAll = 1; xbee_conSettings(con, &settings, NULL); if ((ret = xbee_conCallbackSet(con, catchallCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } printf("Ready!... waiting for 30 secs\n"); usleep(30000000); if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; char txRet; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee2", "/dev/ttyUSB1", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0x2D; address.addr64[6] = 0x60; address.addr64[7] = 0x7B; if ((ret = xbee_conNew(xbee, &con, "Remote AT", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } ret = xbee_conTx(con, &txRet, "NI"); printf("tx: %d\n", ret); if (ret) { printf("txRet: %d\n", txRet); } else { sleep(1); } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
xbee_err _xbee_logData(const char *file, int line, const char *function, struct xbee *xbee, int minLevel, char *label, unsigned char *data, size_t length) { int i; int l; /* format: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 | ........ */ char lineBufA[41]; char lineBufB[9]; /* prepare the format string */ for (l = 0; l < sizeof(lineBufA) - 1; l++) { switch (l % 5) { case 0: case 2: case 3: lineBufA[l] = '0'; break; case 1: lineBufA[l] = 'x'; break; case 4: lineBufA[l] = ' '; break; } } lineBufA[l] = '\0'; lineBufB[sizeof(lineBufB) - 1] = '\0'; xbee_log(25, "%s length: %d", label, length); for (i = 0; i < length; i += l) { /* fill in the data */ for (l = 0; l < 8 && i + l < length; l++) { snprintf(&(lineBufA[(5 * l) + 2]), 3, "%02X", data[i + l]); lineBufA[(5 * l) + 4] = ' '; lineBufB[l] = ((data[i + l] >= ' ' && data[i + l] <= '~')?data[i + l]:'.'); } /* wipe out the unneeded space */ for (; l < 8; l++) { strncpy(&(lineBufA[5 * l]), " ", 6); lineBufB[l] = ' '; } xbee_log(25, "%s: 0x%04X : %s | %s", label, i, lineBufA, lineBufB); } return XBEE_ENONE; }
xbee_err xbee_rx(struct xbee *xbee, int *restart, void *arg) { xbee_err ret; struct xbee_rxInfo *info; struct xbee_tbuf *buf; info = arg; if (!info->bufList || !info->ioFunc) { *restart = 0; return XBEE_EINVAL; } while (!xbee->die) { buf = NULL; if ((ret = info->ioFunc(xbee, info->ioArg, &buf)) != XBEE_ENONE) { if (ret == XBEE_EEOF) { *restart = 0; if (info->eofCallback) info->eofCallback(xbee, info); return XBEE_EEOF; } else if (ret == XBEE_ESHUTDOWN && xbee->die) { break; } xbee_log(1, "rx() returned %d (%s)... retrying in 10 ms", ret, xbee_errorToStr(ret)); usleep(10000); /* 10 ms */ continue; } #ifndef XBEE_DISABLE_LOGGING #ifndef XBEE_LOG_NO_RX if (xbee->log->enable_rx) { /* format: tx[0x0000000000000000] */ char label[42]; /* enough space for a 64-bit pointer and ANSI color codes */ #ifndef XBEE_LOG_NO_COLOR if (xbee->log->use_color) { snprintf(label, sizeof(label), "Rx[%c[%dm%p%c[0m]", 27, 30 + info->logColor, info, 27); } else { #endif /* !XBEE_LOG_NO_COLOR */ snprintf(label, sizeof(label), "Rx[%p]", info); #ifndef XBEE_LOG_NO_COLOR } #endif /* !XBEE_LOG_NO_COLOR */ xbee_logData(25, label, buf->data, buf->len); } #endif /* !XBEE_LOG_NO_RX */ #endif /* !XBEE_DISABLE_LOGGING */ if (xbee_ll_add_tail(info->bufList, buf) != XBEE_ENONE) return XBEE_ELINKEDLIST; buf = NULL; if (xsys_sem_post(&info->sem) != 0) return XBEE_ESEMAPHORE; } return XBEE_ESHUTDOWN; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; char txRet; xbee_err ret; if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conNew(xbee, &con, "Local AT", NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } ret = xbee_conTx(con, &txRet, "NI"); printf("tx: %d\n", ret); if (ret) { printf("txRet: %d\n", txRet); } else { sleep(1); } if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; xbee_err ret; if ((ret = xbee_setup(&xbee, "debug", "xbee1")) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0x08; address.addr64[6] = 0x18; address.addr64[7] = 0x26; if ((ret = xbee_conNew(xbee, &con, "64-bit Data", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } xbee_conTx(con, NULL, "testing..."); if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
EXPORT xbee_err xbee_logTargetSet(struct xbee *xbee, FILE *f) { if (!xbee) return XBEE_EMISSINGPARAM; #ifndef XBEE_DISABLE_STRICT_OBJECTS if (xbee_validate(xbee) != XBEE_ENONE) return XBEE_EINVAL; #endif /* XBEE_DISABLE_STRICT_OBJECTS */ if (!xbee->log) return XBEE_ENOTIMPLEMENTED; xbee_mutex_lock(&xbee->log->mutex); xbee->log->f = f; xbee_mutex_unlock(&xbee->log->mutex); xbee_log(xbee->log->logLevel, "Set log target to: %p (fd:%d)", f, xsys_fileno(f)); return XBEE_ENONE; }
EXPORT xbee_err xbee_logLevelSet(struct xbee *xbee, int level) { if (!xbee) return XBEE_EMISSINGPARAM; #ifndef XBEE_DISABLE_STRICT_OBJECTS if (xbee_validate(xbee) != XBEE_ENONE) return XBEE_EINVAL; #endif /* XBEE_DISABLE_STRICT_OBJECTS */ if (!xbee->log) return XBEE_ENOTIMPLEMENTED; xbee_mutex_lock(&xbee->log->mutex); xbee->log->logLevel = level; xbee_mutex_unlock(&xbee->log->mutex); xbee_log(xbee->log->logLevel, "Set log level to: %d", level); return XBEE_ENONE; }
/* set the callback for a connection this function can provide the previously set callback, as well as assign a new one */ EXPORT int xbee_conAttachCallback(struct xbee *xbee, struct xbee_con *con, void(*callback)(struct xbee *xbee, struct xbee_con *con, struct xbee_pkt **pkt, void **userData), void **prevCallback) { struct xbee_conType *conType; /* check parameters */ if (!xbee) { if (!xbee_default) return XBEE_ENOXBEE; xbee = xbee_default; } if (!xbee_validate(xbee)) return XBEE_ENOXBEE; if (!con) return XBEE_EMISSINGPARAM; /* check the connection */ if (_xbee_conValidate(xbee, con, &conType)) return XBEE_EINVAL; /* give the currently assigned callback */ if (prevCallback) *prevCallback = con->callback; /* we don't need to kill the existing callback, because it is refreshed each time the callback function returns */ /* assign the new callback */ con->callback = callback; /* and if a callback was assigned, kick it off */ if (callback) { xbee_log(5,"Attached callback to connection @ %p", con); /* but only kick it off if there are packets in the queue */ if (ll_count_items(&con->rxList)) { xbee_log(5,"... and triggering callback due to packets in queue"); xbee_triggerCallback(xbee, con); } } else { /* otherwise log that we disabled callbacks for this connection */ xbee_log(5,"Detached callback from connection @ %p", con); } return XBEE_ENONE; }
int setupXbee(struct xbee **xbee, char *port, struct xbee_con **con, unsigned int addrH, unsigned int addrL) { int ret; char conType; struct xbee_conAddress addr; /* make a lixbee instance, and connect it to /dev/ttyUSB1 @ 57600 baud you don't have to keep hold of the returned xbee, in which case you can pass NULL and the most recently started instance will be used! */ if ((ret = xbee_setup(port, 57600, xbee)) != 0) { fprintf(stderr,"xbee_setup(): failed... (%d)\n", ret); return 1; } /* setup libxbee to use the series 1 packets - you have to do this before you do anything else! */ xbee_modeSet(*xbee, "series2"); /* get the connection type ID, you pass in a string, it returns an ID */ if ((ret = xbee_conTypeIdFromName(*xbee, "Data (explicit)", &conType)) != 0) { fprintf(stderr, "xbee_conTypeIdFromName(): failed... (%d)\n", ret); return 2; } /* clear the address field */ memset(&addr, 0, sizeof(addr)); /* build a connection to the following address */ addr.addr64_enabled = 1; addr.addr64[0] = ((addrH >> 24) & 0xFF); addr.addr64[1] = ((addrH >> 16) & 0xFF); addr.addr64[2] = ((addrH >> 8) & 0xFF); addr.addr64[3] = ((addrH) & 0xFF); addr.addr64[4] = ((addrL >> 24) & 0xFF); addr.addr64[5] = ((addrL >> 16) & 0xFF); addr.addr64[6] = ((addrL >> 8) & 0xFF); addr.addr64[7] = ((addrL) & 0xFF); addr.endpoints_enabled = 0; if ((ret = xbee_conNew(*xbee, con, conType, &addr, NULL)) != 0) { fprintf(stderr, "xbee_newcon(): failed... (%d)\n", ret); return 3; } if ((ret = xbee_conAttachCallback(*xbee, *con, myCB, NULL)) != 0) { fprintf(stderr, "xbee_conAttachCallback(): failed (%d)\n", ret); return 4; } /* you have access to the error log! Your messages will be prefixed with "DEV:" */ xbee_log(*xbee,0,"Hello! [%s]", port); return 0; }
/* just echo it back */ void callback(struct xbee *xbee, struct xbee_con *con, struct xbee_pkt **pkt, void **data) { xbee_err ret; unsigned char retVal; int seq; int pktLen; if ((*pkt)->dataLen < 6) { xbee_log(xbee, -10, "SHRT - short packet..."); ret = xbee_conTx(con, &retVal, "SHRT"); } else { seq = ((*pkt)->data[0] << 24) & 0xFF000000; seq |= ((*pkt)->data[1] << 16) & 0xFF0000; seq |= ((*pkt)->data[2] << 8) & 0xFF00; seq |= ((*pkt)->data[3] ) & 0xFF; pktLen = (((*pkt)->data[4]) << 8) & 0xFF00; pktLen |= (((*pkt)->data[5]) ) & 0xFF; if (pktLen < 6 || pktLen != (*pkt)->dataLen - 6) { xbee_log(xbee, -10, "XLEN - packet length mismatch... (rx'd %d / expected %d bytes)", (*pkt)->dataLen - 6, pktLen); ret = xbee_conTx(con, &retVal, "XLEN"); } else if (seq >= PACKET_COUNT) { xbee_log(xbee, -10, "DONE - test complete!"); ret = xbee_conTx(con, &retVal, "DONE"); *data = NULL; } else { xbee_log(xbee, -10, "Tx #%d", seq); ret = xbee_connTx(con, &retVal, (*pkt)->data, (*pkt)->dataLen); } } if (ret != XBEE_ENONE) { xbee_log(xbee, -1, "ret = %d retVal = %d", ret, retVal); } }
/* end a connection the userData parameter can be used to retrieve the data stored with the connection */ EXPORT int xbee_conEnd(struct xbee *xbee, struct xbee_con *con, void **userData) { struct xbee_conType *conType; struct xbee_pkt *pkt; int i; /* check parameters */ if (!xbee) { if (!xbee_default) return XBEE_ENOXBEE; xbee = xbee_default; } if (!xbee_validate(xbee)) return XBEE_ENOXBEE; if (!con) return XBEE_EMISSINGPARAM; /* check the connection */ if (_xbee_conValidate(xbee, con, &conType)) return XBEE_EINVAL; /* remove the connection from the list */ if (ll_ext_item(&(conType->conList), con)) return XBEE_EINVAL; /* chop up any queued packets */ for (i = 0; (pkt = ll_ext_head(&(con->rxList))) != NULL; i++) { xbee_pktFree(pkt); } xbee_log(2,"Ended '%s' connection @ %p (destroyed %d packet%s)", conType->name, con, i, (i!=1)?"s":""); /* if the userData parameter is provided, then give the con's userData back to the caller */ if (userData) *userData = con->userData; /* if there is a callback thread running, then kill it off */ if (con->callbackRunning) { con->destroySelf = 1; xsys_sem_post(&con->callbackSem); /* inform the caller that we are waiting for the callback to complete */ return XBEE_ECALLBACK; } /* it is only safe to call _xbee_conEnd2() once the callback thread has completed, this will finish tidying up the connection */ return _xbee_conEnd2(xbee, con); }
/* the thread monitoring thread... hmm */ void xbee_threadMonitor(struct xbee *xbee) { struct threadInfo *info; void *tRet; int ret; int count, joined, restarted; /* detach self, so that resources are free'd as soon as we return */ xsys_thread_detach_self(); while (xbee->running) { /* wait for 10 seconds, unless prodded */ xsys_sem_timedwait(&xbee->semMonitor, 10, 0); xbee_log(15,"Scanning for dead threads..."); /* keep track of some stats */ count = 0; joined = 0; restarted = 0; /* iterate through each monitored thread */ for (info = NULL; (info = ll_get_next(&xbee->threadList, info)) != NULL;) { /* if thread is supposed to be running */ if (info->running) { #warning TODO - find an alternative to pthread_tryjoin_np() /* try to join with the thread */ if ((ret = xsys_thread_tryjoin(*info->thread, &tRet)) == 0) { /* apparently it died! mark it dead, and report it */ info->running = 0; xbee_log(15,"Thread 0x%X died (%s), it returned 0x%X", info->thread, info->funcName, ret); joined++; } else { /* if the join failed, then find out why (to the best of our ability) and log the details */ if (ret == EBUSY) { xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) EBUSY", info->thread, info->funcName); } else if (ret == ETIMEDOUT) { xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) ETIMEDOUT", info->thread, info->funcName); } else if (ret == EINVAL) { xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) EINVAL", info->thread, info->funcName); } else { xbee_log(10,"xsys_thread_tryjoin(): 0x%X (%s) unknown (%d)", info->thread, info->funcName, ret); } count++; } } /* we need to re-test info->running, because it may have just been marked dead */ if (!info->running) { /* try to restart the thread */ if (xsys_thread_create(info->thread, info->start_routine, info->arg) == 0) { /* success! keep the stats */ restarted++; info->restartCount++; info->running = 1; } else { /* otherwise log the info */ xbee_log(10,"Failed to restart thread (%s)...\n", info->funcName); } } } /* log the stats */ xbee_log(15,"Scan complete! joined/restarted/remain %d/%d/%d threads", joined, restarted, count); } }
/* transmit a message on the provided connection this function takes the raw data and its length */ EXPORT int xbee_connTx(struct xbee *xbee, struct xbee_con *con, char *data, int length) { int ret = XBEE_ENONE; struct bufData *buf; struct xbee_conType *conType; int waitForAckEnabled; /* check parameters */ if (!xbee) { if (!xbee_default) return XBEE_ENOXBEE; xbee = xbee_default; } if (!xbee_validate(xbee)) return XBEE_ENOXBEE; if (!con) return XBEE_EMISSINGPARAM; /* check the provided connection */ if (_xbee_conValidate(xbee, con, &conType)) return XBEE_EINVAL; /* check that we are able to send the message, if there is no xbee->f->connTx mapping, then we need a conType->txHandler */ if (!conType->txHandler && !xbee->f->connTx) return XBEE_ECANTTX; /* allocate a buffer, 1 byte is already held within the bufData struct, and we don't send the trailing '\0' */ if ((buf = calloc(1, sizeof(struct bufData) + (sizeof(unsigned char) * (length - 1)))) == NULL) { ret = XBEE_ENOMEM; goto die1; } /* populate the buffer */ buf->len = length; memcpy(buf->buf, data, length); /* cache the value of waitForAck, because it may change halfway through! */ waitForAckEnabled = con->options.waitForAck; /* if the connection has 'waitForAck' enabled, then we need to get a free FrameID that can be used */ if (waitForAckEnabled) { /* if we are configured to wait for an Ack, then we need to lock down the connection */ xbee_log(4,"Locking txMutex for con @ %p", con); xsys_mutex_lock(&con->txMutex); if ((con->frameID = xbee_frameIdGet(xbee, con)) == 0) { /* currently we don't inform the user (BAD), but this is unlikely unless you are communicating with >256 remote nodes */ xbee_log(1,"No avaliable frame IDs... we can't validate delivery"); xbee_log(4,"Unlocking txMutex for con @ %p (failed to get FrameID)", con); xsys_mutex_unlock(&con->txMutex); } else { /* mark the FrameID as present */ con->frameID_enabled = 1; } } /* if there is a custom mapping for connTx, then the handlers are skipped (but can be called from within the mapping!) */ if (!xbee->f->connTx) { struct bufData *oBuf; oBuf = buf; /* execute the conType handler, this should take the data provided, and convert it into an XBee formatted block of data this is given, and returned via the 'buf' argument */ xbee_log(6,"Executing handler (%s)...", conType->txHandler->handlerName); if ((ret = conType->txHandler->handler(xbee, conType->txHandler, 0, &buf, con, NULL)) != XBEE_ENONE) goto die2; /* a bit of sanity checking... */ if (!buf || buf == oBuf) { ret = XBEE_EUNKNOWN; goto die2; } free(oBuf); } if (!xbee->f->connTx) { /* if there is no connTx mapped, then add the packet to libxbee's txlist, and prod the tx thread */ ll_add_tail(&xbee->txList, buf); xsys_sem_post(&xbee->txSem); } else { /* same as before, if a mapping is registered, then the packet isn't queued for Tx, at least not here instead we execute the mapped function */ if ((ret = xbee->f->connTx(xbee, con, buf)) != XBEE_ENONE) goto die2; } /* if we should be waiting for an Ack, we now need to wait */ if (waitForAckEnabled && con->frameID) { xbee_log(4,"Waiting for txSem for con @ %p", con); /* the wait occurs inside xbee_frameIdGetACK() */ ret = xbee_frameIdGetACK(xbee, con, con->frameID); if (ret) xbee_log(4,"--- xbee_frameIdGetACK() returned: %d",ret); /* unlock the connection so that other transmitters may follow on */ xbee_log(4,"Unlocking txMutex for con @ %p", con); xsys_mutex_unlock(&con->txMutex); } /* disable the frameID */ con->frameID_enabled = 0; goto done; die2: free(buf); die1: done: return ret; }
static xbee_err prepare_backchannel(struct xbee *xbee) { xbee_err ret; struct xbee_modeData *data; unsigned char retVal; struct xbee_conAddress address; struct xbee_pkt *pkt; int callbackCount; int i, pos, slen; struct xbee_con *bc_start; data = xbee->modeData; pkt = NULL; /* create the 'start' backchannel connection - this is ALWAYS ON ENDPOINT 0x00 */ memset(&address, 0, sizeof(address)); address.endpoints_enabled = 1; address.endpoint_local = 0; address.endpoint_remote = 0; if ((ret = _xbee_conNew(xbee, &xbee->iface, 1, &bc_start, "backchannel", &address)) != XBEE_ENONE) return ret; /* transmit our libxbee_commit string - the git commit id */ if ((ret = xbee_conTx(bc_start, &retVal, "%s", libxbee_commit)) != XBEE_ENONE) { switch (retVal) { case 1: xbee_log(0, "The server encountered an internal error"); break; case 2: xbee_log(0, "The server is running a different version of libxbee"); break; default: xbee_log(0, "Failed to initialize connection to server for an unknown reason..."); } goto done; } /* grab the returned data (an in-order list of the back channel endpoints, starting at 0x01) */ if ((ret = xbee_conRx(bc_start, &pkt, NULL)) != XBEE_ENONE) goto done; /* pick out the remote system's mode name, and try to locate it */ for (i = 0; i < pkt->dataLen && pkt->data[i] != '\0'; i++); if (i > 0) { if ((data->serverModeName = malloc(sizeof(char) * (i + 1))) == NULL) { ret = XBEE_ENOMEM; goto done; } strncpy(data->serverModeName, (char*)pkt->data, i); data->serverModeName[i] = '\0'; if (xbee_modeRetrieve(data->serverModeName, &data->serverMode) != XBEE_ENONE) { xbee_log(-10, "WARNING: remote mode '%s' is not avaliable on this system... Some packets may not be fully processed", data->serverModeName); } } callbackCount = pkt->data[i + 1]; memset(&address, 0, sizeof(address)); address.endpoints_enabled = 1; for (pos = i + 2, i = 1; pos < pkt->dataLen && i < callbackCount + 1; pos += slen + 1, i++) { char *name; struct xbee_con **retCon; name = (char *)&(pkt->data[pos]); slen = strlen(name); /* check for a buffer overflow */ if (slen > pkt->dataLen - pos) { slen = pkt->dataLen - pos; name[slen] = '\0'; } retCon = NULL; /* try to match the string with an element in struct xbee_modeData */ #define TRY(conName) if (!data->bc_##conName && !strncasecmp(name, #conName, slen)) TRY (conValidate) { retCon = &data->bc_conValidate; } else TRY (conSleep) { retCon = &data->bc_conSleep; } else TRY (conSettings) {
/* Init kmsg input */ int in_xbee_init(struct flb_config *config) { int ret; int opt_baudrate = 9600; char *tmp; char *opt_device = FLB_XBEE_DEFAULT_DEVICE; struct stat dev_st; struct xbee *xbee; struct xbee_con *con; struct xbee_conAddress address; struct flb_in_xbee_config *ctx; /* Check an optional baudrate */ tmp = getenv("FLB_XBEE_BAUDRATE"); if (tmp) { opt_baudrate = atoi(tmp); } /* Get the target device entry */ tmp = getenv("FLB_XBEE_DEVICE"); if (tmp) { opt_device = strdup(tmp); } flb_info("XBee device=%s, baudrate=%i", opt_device, opt_baudrate); ret = stat(opt_device, &dev_st); if (ret < 0) { printf("Error: could not open %s device\n", opt_device); exit(EXIT_FAILURE); } if (!S_ISCHR(dev_st.st_mode)) { printf("Error: invalid device %s \n", opt_device); exit(EXIT_FAILURE); } if (access(opt_device, R_OK | W_OK) == -1) { printf("Error: cannot open the device %s (permission denied ?)\n", opt_device); exit(EXIT_FAILURE); } /* Init library */ xbee_init(); ret = xbee_setup(&xbee, "xbeeZB", opt_device, opt_baudrate); if (ret != XBEE_ENONE) { flb_utils_error_c("xbee_setup"); return ret; } /* FIXME: just a built-in example */ memset(&address, 0, sizeof(address)); address.addr64_enabled = 1; address.addr64[0] = 0x00; address.addr64[1] = 0x13; address.addr64[2] = 0xA2; address.addr64[3] = 0x00; address.addr64[4] = 0x40; address.addr64[5] = 0xB7; address.addr64[6] = 0xB1; address.addr64[7] = 0xEB; /* Prepare a connection with the peer XBee */ if ((ret = xbee_conNew(xbee, &con, "Data", &address)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } /* Prepare the configuration context */ ctx = calloc(1, sizeof(struct flb_in_xbee_config)); if (!ctx) { perror("calloc"); return -1; } ctx->device = opt_device; ctx->baudrate = opt_baudrate; ctx->con = con; ctx->buffer_len = 0; if ((ret = xbee_conDataSet(con, ctx, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret); return ret; } if ((ret = xbee_conCallbackSet(con, in_xbee_cb, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } /* Set the context */ ret = flb_input_set_context("xbee", ctx, config); if (ret == -1) { flb_utils_error_c("Could not set configuration for xbee input plugin"); } /* * Set our collector based on time. We will trigger a collection at certain * intervals. For now it works but it's not the ideal implementation. I am * talking with libxbee maintainer to check possible workarounds and use * proper events mechanism. */ ret = flb_input_set_collector_time("xbee", in_xbee_collect, IN_XBEE_COLLECT_SEC, IN_XBEE_COLLECT_NSEC, config); if (ret == -1) { flb_utils_error_c("Could not set collector for xbee input plugin"); } return 0; }
int main(void) { void *d; struct xbee *xbee; struct xbee_con *con; char txRet; xbee_err ret; int i, o, t; sem_init(&sem, 0, 0); if ((ret = xbee_setup(&xbee, "xbee1", "/dev/ttyUSB0", 57600)) != XBEE_ENONE) { printf("ret: %d (%s)\n", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conNew(xbee, &con, "Local AT", NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret)); return ret; } if ((ret = xbee_conCallbackSet(con, myCB, NULL)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret); return ret; } o = 0; t = 0; for (i = 0; i < 1000; i++) { ret = xbee_conTx(con, &txRet, "NI"); printf("tx: %d\n", ret); if (ret) { printf("txRet: %d\n", txRet); sleep(1); } else { struct timespec to; clock_gettime(CLOCK_REALTIME, &to); to.tv_sec++; if (sem_timedwait(&sem, &to) == 0) { o++; usleep(10000); } else { printf(" TIMEOUT!\n"); usleep(250000); t++; } } } printf("%d / %d / %d - success/timeout/total - success rate (%2.1f%%) / timeout rate (%2.1f%%)\n", o, t, i, (double)((double)o/(double)i)*100.0, (double)((double)t/(double)i)*100.0); if ((ret = xbee_conEnd(con)) != XBEE_ENONE) { xbee_log(xbee, -1, "xbee_conEnd() returned: %d", ret); return ret; } xbee_shutdown(xbee); return 0; }
int main(int argc, char *argv[]) { int ret; sem_t sem; void *p; /* this is our xbee instance... from 'user' space you don't have access to the struct */ struct xbee *xbee; /* this is the connection we will make... again, you don't have access to the struct */ struct xbee_con *con; struct xbee_conAddress addr; /* the packet that is recieved... you have access to this! (see xbee.h) */ struct xbee_pkt *pkt; /* make a lixbee instance, and connect it to /dev/ttyUSB1 @ 57600 baud you don't have to keep hold of the returned xbee, in which case you can pass NULL and the most recently started instance will be used! */ if ((ret = xbee_setup("/dev/ttyUSB0", 57600, &xbee)) != 0) { xbee_log(NULL,-1,"xbee_setup(): failed... (%d)", ret); exit(1); } /* setup libxbee to use the series 1 packets - you have to do this before you do anything else! */ xbee_modeSet(xbee, "series1"); /* get the connection type ID, you pass in a string, it returns an ID */ if ((ret = xbee_conTypeIdFromName(xbee, "Remote AT", &conType)) != 0) { xbee_log(xbee,-1,"xbee_conTypeIdFromName(): failed... (%d)", ret); exit(1); } if ((ret = sem_init(&sem, 0, 0)) != 0) { xbee_log(xbee,-1,"sem_init(): failed... (%d)", ret); exit(1); } /* clear the address field */ memset(&addr, 0, sizeof(addr)); /* build a connection to the following address */ addr.addr64_enabled = 1; addr.addr64[0] = 0x00; addr.addr64[1] = 0x13; addr.addr64[2] = 0xA2; addr.addr64[3] = 0x00; addr.addr64[4] = 0x40; addr.addr64[5] = 0x33; addr.addr64[6] = 0xCA; addr.addr64[7] = 0xCB; if ((ret = xbee_conNew(xbee, &con, conType, &addr, &sem)) != 0) { xbee_log(xbee,-1,"xbee_newcon(): failed... (%d)", ret); exit(1); } { struct xbee_conOptions opts; /* enable waitForAck... this allows us to see if the packet was sent successfully! */ xbee_conOptions(xbee, con, &opts, NULL); opts.waitForAck = 1; xbee_conOptions(xbee, con, NULL, &opts); } /* attach the callback */ xbee_conAttachCallback(xbee, con, myCB, NULL); /* send the request */ if ((ret = xbee_conTx(xbee, con, "NI")) != 0) { xbee_log(xbee,-1,"Something went wrong... (%d)", ret); } else { struct timespec to; clock_gettime(CLOCK_REALTIME, &to); to.tv_sec += 5; if (sem_timedwait(&sem, &to)) { printf("Timeout...\n"); } } sem_destroy(&sem); /* shutdown the connection */ xbee_conEnd(xbee, con, NULL); /* shutdown the libxbee instance */ xbee_shutdown(xbee); return 0; }
xbee_err xbee_s2_io_parseInputs(struct xbee *xbee, struct xbee_pkt *pkt, unsigned char *data, int len) { int sampleCount; int sample, channel; int ioMask; if (len < 4) return XBEE_ELENGTH; sampleCount = data[0]; data++; len--; /* mask is ordered: MSB - Supply Voltage * n/a * * n/a * * n/a * AD3 AD2 AD1 - AD0 - * n/a * * n/a * * n/a * CD/DIO12 PWM/DIO11 RSSI/DIO10 * n/a * - * n/a * - CTS/DIO7 RTS/DIO6 Assoc/DIO5 DIO4 AD3/DIO3 AD2/DIO2 AD1/DIO1 LSB - AD0/DIO0 */ ioMask = ((data[2] << 16) & 0xFF0000) | ((data[0] << 8) & 0xFF00) | (data[1] & 0xFF); data += 3; len -= 3; /* poke out the n/a fields, just incase */ ioMask &= 0x8F1CFF; for (sample = 0; sample < sampleCount; sample++) { int mask; if (ioMask & 0x001CFF) { int digitalValue; if (len < 2) return XBEE_ELENGTH; digitalValue = ((data[0] << 8) & 0xFF00) | (data[1] & 0xFF); /* poke out the n/a fields */ digitalValue &= 0x1CFF; mask = 0x000001; for (channel = 0; channel <= 12; channel++, mask <<= 1) { if (ioMask & mask) { if (xbee_pktDigitalAdd(pkt, channel, digitalValue & mask)) { xbee_log(1,"Failed to add digital sample information to packet (channel D%d)", channel); } } } data += 2; len -= 2; } mask = 0x010000; for (channel = 0; channel <= 4; channel++, mask <<= 1) { if (channel == 4) mask = 0x800000; if (ioMask & mask) { if (len < 2) return XBEE_ELENGTH; if (xbee_pktAnalogAdd(pkt, channel, ((data[0] << 8) & 0x3F00) | (data[1] & 0xFF))) { xbee_log(1,"Failed to add analog sample information to packet (channel A%d)", channel); } data += 2; len -= 2; } } } return XBEE_ENONE; }