RadioLib/src/modules/XBee.cpp

305 wiersze
7.1 KiB
C++
Czysty Zwykły widok Historia

2018-03-09 19:18:33 +00:00
#include "XBee.h"
2018-07-19 14:21:47 +00:00
XBee::XBee(Module* mod) {
_mod = mod;
_frameID = 0x01;
2018-03-31 08:09:51 +00:00
}
2018-07-19 14:21:47 +00:00
uint8_t XBee::begin(long speed) {
// set module properties
_mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE);
// wait for boot
delay(2000);
// empty UART buffer (garbage data)
_mod->ATemptyBuffer();
// send test frame (get baudrate setting)
uint8_t frameID = _frameID++;
sendApiFrame(XBEE_API_FRAME_AT_COMMAND, frameID, "BD");
delay(20);
// get response code
return(readApiFrame(frameID, 4));
2018-03-09 19:18:33 +00:00
}
2018-07-19 14:21:47 +00:00
uint8_t XBee::transmit(uint8_t* dest, const char* payload, uint8_t radius) {
uint8_t destNetwork[] = {0xFF, 0xFE};
return(transmit(dest, destNetwork, payload));
}
uint8_t XBee::transmit(uint8_t* dest, uint8_t* destNetwork, const char* payload, uint8_t radius) {
// build the frame
size_t payloadLen = strlen(payload);
size_t dataLen = 8 + 2 + 1 + 1 + payloadLen;
uint8_t* cmd = new uint8_t[dataLen];
memcpy(cmd, dest, 8);
memcpy(cmd + 8, destNetwork, 2);
cmd[10] = radius;
cmd[11] = 0x01; // options: no retries
memcpy(cmd + 12, payload, payloadLen);
// send frame
uint8_t frameID = _frameID++;
sendApiFrame(XBEE_API_FRAME_ZIGBEE_TRANSMIT_REQUEST, frameID, cmd, dataLen);
delete[] cmd;
delay(40);
// get response code
return(readApiFrame(frameID, 5));
}
size_t XBee::available() {
}
String XBee::getPacketSource() {
}
String XBee::getPacketData() {
}
uint8_t XBee::setPanId(uint8_t* panId) {
// build AT command
uint8_t cmd[10];
memcpy(cmd, "ID", 2);
memcpy(cmd + 2, panId, 8);
// send frame
uint8_t frameID = _frameID++;
sendApiFrame(XBEE_API_FRAME_AT_COMMAND, frameID, cmd, 10);
delay(40);
// get response code
return(readApiFrame(frameID, 4));
}
XBeeSerial::XBeeSerial(Module* mod) : ISerial(mod) {
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
}
uint8_t XBeeSerial::begin(long speed) {
2018-04-19 15:32:16 +00:00
// set module properties
2018-03-31 08:09:51 +00:00
_mod->AtLineFeed = "\r";
2018-03-09 19:18:33 +00:00
_mod->baudrate = speed;
_mod->init(USE_UART, INT_NONE);
2018-04-19 15:32:16 +00:00
// empty UART buffer (garbage data)
2018-03-31 08:09:51 +00:00
_mod->ATemptyBuffer();
2018-04-19 15:32:16 +00:00
// enter command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Entering command mode ...");
2018-03-31 08:09:51 +00:00
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
2018-04-19 15:32:16 +00:00
// test AT setup
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Sending test command ...");
2018-03-31 08:09:51 +00:00
if(!_mod->ATsendCommand("AT")) {
return(ERR_AT_FAILED);
}
2018-04-19 15:32:16 +00:00
// exit command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Exiting command mode ...");
2018-03-31 08:09:51 +00:00
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
}
return(ERR_NONE);
}
2018-07-19 14:21:47 +00:00
uint8_t XBeeSerial::setDestinationAddress(const char* destinationAddressHigh, const char* destinationAddressLow) {
2018-04-19 15:32:16 +00:00
// enter command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Entering command mode ...");
2018-03-31 08:09:51 +00:00
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
2018-04-19 15:32:16 +00:00
// set higher address bytes
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Setting address (high) ...");
char* addressHigh = new char[strlen(destinationAddressHigh) + 4];
strcpy(addressHigh, "ATDH");
strcat(addressHigh, destinationAddressHigh);
bool res = _mod->ATsendCommand(addressHigh);
delete[] addressHigh;
if(!res) {
2018-03-31 08:09:51 +00:00
return(ERR_AT_FAILED);
}
2018-04-19 15:32:16 +00:00
// set lower address bytes
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Setting address (low) ...");
char* addressLow = new char[strlen(destinationAddressLow) + 4];
strcpy(addressLow, "ATDL");
strcat(addressLow, destinationAddressLow);
res = _mod->ATsendCommand(addressLow);
delete[] addressLow;
if(!res) {
2018-03-31 08:09:51 +00:00
return(ERR_AT_FAILED);
}
2018-04-19 15:32:16 +00:00
// exit command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Exiting command mode ...");
2018-03-31 08:09:51 +00:00
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
}
return(ERR_NONE);
}
2018-07-19 14:21:47 +00:00
uint8_t XBeeSerial::setPanId(const char* panId) {
2018-04-19 15:32:16 +00:00
// enter command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Entering command mode ...");
2018-04-02 11:22:57 +00:00
if(!enterCmdMode()) {
return(ERR_CMD_MODE_FAILED);
}
2018-03-31 08:09:51 +00:00
2018-04-19 15:32:16 +00:00
// set PAN ID
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Setting PAN ID ...");
char* cmd = new char[strlen(panId) + 4];
strcpy(cmd, "ATID");
strcat(cmd, panId);
bool res = _mod->ATsendCommand(cmd);
delete[] cmd;
if(!res) {
2018-04-02 11:22:57 +00:00
return(ERR_AT_FAILED);
2018-03-31 08:09:51 +00:00
}
2018-03-09 19:18:33 +00:00
2018-04-19 15:32:16 +00:00
// exit command mode
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Exiting command mode ...");
2018-04-02 11:22:57 +00:00
if(!_mod->ATsendCommand("ATCN")) {
return(ERR_AT_FAILED);
2018-03-31 08:09:51 +00:00
}
return(ERR_NONE);
2018-04-02 11:22:57 +00:00
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
bool XBeeSerial::enterCmdMode() {
2018-03-31 08:09:51 +00:00
for(uint8_t i = 0; i < 10; i++) {
delay(1000);
_mod->ModuleSerial->write('+');
_mod->ModuleSerial->write('+');
_mod->ModuleSerial->write('+');
delay(1000);
if(_mod->ATgetResponse()) {
return(true);
} else {
2018-04-19 16:50:42 +00:00
DEBUG_PRINT_STR("Unable to enter command mode! (");
DEBUG_PRINT(i + 1);
DEBUG_PRINTLN_STR(" of 10 tries)");
2018-03-31 08:09:51 +00:00
2018-04-13 18:51:12 +00:00
pinMode(3, OUTPUT);
delay(10);
digitalWrite(3, HIGH);
delay(500);
digitalWrite(3, LOW);
delay(500);
pinMode(3, INPUT);
delay(500);
2018-03-31 08:09:51 +00:00
_mod->ATsendCommand("ATCN");
if(i == 9) {
2018-04-19 16:50:42 +00:00
DEBUG_PRINTLN_STR("Terminated, check your wiring. Is AT FW uploaded?");
2018-03-31 08:09:51 +00:00
return(false);
}
}
}
}
2018-07-19 14:21:47 +00:00
void XBee::sendApiFrame(uint8_t type, uint8_t id, const char* data) {
sendApiFrame(type, id, (uint8_t*)data, strlen(data));
}
void XBee::sendApiFrame(uint8_t type, uint8_t id, uint8_t* data, uint16_t length) {
// build the API frame
size_t frameLength = 1 + 2 + length + 1 + 2;
uint8_t* frame = new uint8_t[frameLength];
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
frame[0] = 0x7E; // start delimiter
frame[1] = ((length + 2) & 0xFF00) >> 8; // length MSB
frame[2] = (length + 2) & 0x00FF; // length LSB
frame[3] = type; // frame type
frame[4] = id; // frame ID
memcpy(frame + 5, data, length); // data
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// calculate the checksum
uint8_t checksum = 0;
for(uint16_t i = 3; i < frameLength - 1; i++) {
checksum += frame[i];
}
frame[5 + length] = 0xFF - checksum;
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// send the frame
for(uint16_t i = 0; i < frameLength; i++) {
_mod->ModuleSerial->write(frame[i]);
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// deallocate memory
delete[] frame;
}
uint8_t XBee::readApiFrame(uint8_t frameID, uint8_t codePos) {
// get number of bytes in response
uint16_t numBytes = getNumBytes(10000, 5);
if(numBytes == 0) {
return(ERR_FRAME_MALFORMED);
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// checksum byte is not included in length field
numBytes++;
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// read the response
uint8_t* resp = new uint8_t[numBytes];
for(uint16_t i = 0; i < numBytes; i++) {
resp[i] = _mod->ModuleSerial->read();
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// verify checksum
uint8_t checksum = 0;
for(uint16_t i = 0; i < numBytes; i++) {
checksum += resp[i];
}
if(checksum != 0xFF) {
return(ERR_FRAME_INCORRECT_CHECKSUM);
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
// check frame ID
if(resp[1] != frameID) {
return(ERR_FRAME_UNEXPECTED_ID);
2018-03-31 08:09:51 +00:00
}
2018-07-19 14:21:47 +00:00
uint8_t code = resp[codePos];
delete[] resp;
return(code);
}
2018-03-31 08:09:51 +00:00
2018-07-19 14:21:47 +00:00
uint16_t XBee::getNumBytes(uint32_t timeout, size_t minBytes) {
// wait for available data
uint32_t start = millis();
while(_mod->ModuleSerial->available() < minBytes) {
if(millis() - start >= timeout) {
return(0);
2018-03-31 08:09:51 +00:00
}
}
2018-07-19 14:21:47 +00:00
// read response
uint8_t resp[3];
uint8_t i = 0;
while(_mod->ModuleSerial->available() > 0) {
uint8_t b = _mod->ModuleSerial->read();
resp[i++] = b;
if(i == 3) {
break;
}
2018-03-31 08:09:51 +00:00
}
2018-07-19 14:21:47 +00:00
return((resp[1] << 8) | resp[2]);
}