// Written in C justin downs johnhenryshammer.com
// Code that will parse a XBEE API Series2 receive packet
// started from Rob Faludis/Dan Shiftman API series 1 library
// It is broken into functions for Debugging and for easier use with a time out
// for program flow. It is not needed for raw parsing and
//runs faster without funcs. Just decomment.
//** There is also code for transmitting serial as ASCII you don't have to use those
//funcs for the XBEE, just disregard and don't use the ArrayLookChars(byte* _array) func.
//function decs
int checkHeader(int timeout);
char getIdentifier(int _timeOut);
byte* getLongAdress(int _timeOut, byte* _address);
int getLocaladdress(int _timeOut);
byte getOptions(int _timeOut);
byte* getInfo(int _packetLength, int _timeOut);
char getCheckSum(int _timeOut);
//software serial stuff this is for debuging only take out if not used
#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 3
#define ledPin 13
// end softserial
// set up a new serial port
SoftwareSerial DeBug = SoftwareSerial(rxPin, txPin);
byte pinState = 0;
void setup() {
// define pin modes for tx, rx, led pins:
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
pinMode(ledPin, OUTPUT);
// set the data rate for the SoftwareSerial port
DeBug.begin(9600);
Serial.begin(9600);
}
void loop() {
//DeBug.println("hello");
getData();
}
/* Function that receives API2 data which was sent using 16-bit addressing
broken into functions for microcontroler timeout blocks. not needed on pc
runs slower.
*/
void getData() {
int timeout=100;// bail out time
int packetLength = 0;
packetLength = checkHeader(timeout); // START BYTE AND PACKET LENGTH
if (packetLength > 0 ) { // if we have a packet continue
int apiIdentifier = getIdentifier(timeout); // GET ID
byte Adress[8];// array for 64 bit address
byte* adress = getLongAdress(timeout,Adress);//GET LONG ADRESS don't really need pointer
/*char addrByte=0;
while( port.available() < 8); // stop for bits
char adress[]= new char[8];// array for address
for (int i = 0; i<8; i++){
addrByte =char( port.read());
adress[i]=addrByte;
// print(hex(addrByte));
}
*/
int localAdress = getLocaladdress(timeout);// GET LOCAL ADDRESS
/* while (port.available() < 2); // wait for at least two bytes to be available
int localAd = port.read(); // read the most significant length byte
int localAd2 = port.read(); // read the least significant length byte
int localAdress = (localAd << 8) + localAd2; // put the two bytes together
*/
byte options = getOptions(timeout);//GET OPTION
/* while (port.available() < 1);
char options = char(port.read()); // get the options 1 packet ack returned 2 brodcast
*/
byte* dataIn = getInfo(packetLength,timeout);//GET INFO
/*
//info packet
char[] dataIn = new char[30];
while (port.available() < (packetLength - 12));
// println("packetLength22 "+packetLength);
for (int i= 0; i < (packetLength - 12); i++) { // take out other info in packet + checksu
println("packetLength "+ packetLength);
dataIn[i] = char(port.read()); // get a byte of data
// println(hex(dataIn[i]));
}
*/
char checksum = getCheckSum(timeout); //GET CHECKSUM
/*
while (port.available() < 1);
char checksum = char(port.read());
*/
/* //printall
DeBug.println("packetLength "+packetLength);
DeBug.println("sent long address");
for (int i = 0; i<8; i++){
DeBug.print(adress[i]);
}
DeBug.println();
DeBug.println ("local adress "+localAdress);
DeBug.println("options "+options);
DeBug.println("info");
for (int i= 0; i < (packetLength - 12); i++) { // take out other info in packet + checksum
DeBug.println(dataIn[i]);
}
DeBug.println("checksum "+checksum);
*/
// for (int i= 0; i < (packetLength - 12); i++) { // take out other info in packet + checksum
// DeBug.println(dataIn[i]);
// }
// DeBug.println("data");
// For ASCCII //**optional***
DeBug.println(ArrayLookChars(dataIn));
free(dataIn); // free block after use
}
}
int checkHeader(int timeout) { // timeout is in milliseconds
long startTime = millis();
int Length = 0;
int inByte = 0;
// during the timeout period, if we haven't gotten the start byte yet...
while (((millis() - startTime) < timeout) && (inByte != 0x7E)) {
if (Serial.available() > 0) { // if a byte is waiting in the buffer
inByte = Serial.read(); // read a byte from the buffer
}
}
// look at byte
if (inByte == 0x7E) { // if we got the API start byte
while (Serial.available() < 2); // wait for at least two bytes to be available
int lengthMSB = Serial.read(); // read the most significant length byte
int lengthLSB = Serial.read(); // read the least significant length byte
Length = (lengthMSB << 8) + lengthLSB; // put the two bytes together
}
return Length;
}
char getCheckSum(int _timeOut){
char checksum ='Z';
long startTime = millis();
while (Serial.available() < 1 && ((millis() - startTime) < _timeOut)); // wait for at least two bytes to be available
if (Serial.available() > 0) { // if a byte is waiting in the buffer
checksum = char(Serial.read());
return checksum; // returns null if timed out
}
/// println("checksum");
return '0'; // returns null if timed out
}
byte* getLongAdress(int _timeOut, byte* _address){
long startTime = millis();
char addrByte = 'Z';
while( Serial.available() < 8 && ((millis() - startTime) < _timeOut)); // stop for bits
if (Serial.available() > 0) { // if a byte is waiting in the buffer
for (int i = 0; i<8; i++){
addrByte =byte( Serial.read());
_address[i]=addrByte;
}
return _address; //returns null if timed out
}
//println("Adresslong");//ERROR happend
return NULL;
}
int getLocaladdress(int _timeOut){
int localAdress =0;
long startTime = millis();
while (Serial.available() < 2 && ((millis() - startTime) < _timeOut)); // wait for at least two bytes to be available
if (Serial.available() > 0) { // if a byte is waiting in the buffer
int localAd = Serial.read(); // read the most significant length byte
int localAd2 = Serial.read(); // read the least significant length byte
localAdress = (localAd << 8) + localAd2; // put the two bytes together
return localAdress; // returns null if timed out
}
///println("location");
return '0'; // returns null if timed out
}
// function that checks to see for the API Identifier
char getIdentifier(int _timeOut) {
long startTime = millis();
char apiIdentifier = 'Z'; // set apiIdentifier to an impossible value
while (Serial.available() < 1 && (millis() - startTime) < _timeOut) ; // wait for a byte or timeout
if (Serial.available() > 0) { // if a byte is waiting in the buffer
apiIdentifier = char(Serial.read());
return apiIdentifier; // returns null if timed out
}
/// println("Identifier");
return 'N'; // returns null if timed out
}
// this is your info packet
byte* getInfo(int _packetLength, int _timeOut){
long startTime = millis();
byte addrByte = 0x00;
while (Serial.available() < (_packetLength - 12) && millis() - startTime < _timeOut); // stop for bits
byte* dataIn = (byte*) malloc(_packetLength - 12);// get memory, be sure to call free in sendData or it blows real quick
if (dataIn==NULL){ DeBug.println( "brainDamaged"); return NULL;} // bail out
if (Serial.available() > 0) { // if a byte is waiting in the buffer
for (int i= 0; i < (_packetLength - 12); i++) { // take out other info in packet + checksu
dataIn[i] = byte(Serial.read()); // get a byte of data
// DeBug.println( dataIn[i]);
}
return dataIn; //returns null if timed out
}
/// println("info packet");
return NULL;
}
byte getOptions(int _timeOut){
byte options =0x00;
long startTime = millis();
while (Serial.available() < 1 && ((millis() - startTime) < _timeOut)); // wait for at least two bytes to be available
if (Serial.available() > 0) { // if a byte is waiting in the buffer
options = byte(Serial.read()); // get the options 1 packet ack returned 2 brodcast
return options; // returns null if timed out
}
////println("Options");
return '0'; // returns null if timed out
}
///////DEPackagedata ***optional****
long ArrayLookChars(byte* _array) {
char ASCIIString [100]; // in string
char inByte ='z';
long number = 0; // return number
int stringPos = 0; // keeps track of places in number
if ('a' == _array[1] ){ // for id parsing of serial
int i = 2; // change back to 1 if not using tag
while(_array[i] !='b'){
inByte =_array[i];
i++;
// save ASCII numeric characters in string:
if ((inByte >= '0') && (inByte <= '9')){
ASCIIString [stringPos] = inByte;
stringPos++;
//DeBug.println( "true");
}
}
}
number = SerialToInt( ASCIIString,stringPos ); /// convert captured string to an int
//free(_array); //for Debug
stringPos = 0; //reset count num
//if (number !=0)Serial.println(number);//DEBUG
return number;
}
/*****************
the important parts of the function conversions
are to have a inverting for loop go
from last in array to first and call the plusBaseTen()function
each time.
*******************/
// hits up the number by base ten powered
long timesBaseTen(int _move){ // the
long place = 1; //base 10
int n = 0;
if( _move < 1){ return 1;}//ones place no change
else{
for( n= 0; n<_move; n++){ place = place*10;}
}return place;
}
// converts a ten digit ASCII to int
long SerialToInt(char *_input, int _arrayLength){
long number=0;
long total=0;
int arrayLook=0;
int i = 0;
char s[]={"h"}; // work around
int arrayLength =_arrayLength-1; // need one less than actual length 0 is 1
// call invert string for proper string power order
for(i =arrayLength; i >= 0;i--){
// Serial.println(i);
// Serial.println(_input[i]);
// picks out ASCII numbers for error check
if ((_input[i] >= '0') && (_input[i]<= '9')){
s[0] = _input[i];// work around to get string arg
number = atoi(s);// ASCII to converts number
number = (number * (timesBaseTen(arrayLook))); // puts number in its place
arrayLook++;
total = number+total;
}
}
return total;
}