-
Notifications
You must be signed in to change notification settings - Fork 2
/
XBee.h
951 lines (889 loc) · 27.1 KB
/
XBee.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
/**
* Copyright (c) 2009 Andrew Rapp. All rights reserved.
*
* This file is part of XBee-Arduino.
*
* XBee-Arduino 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.
*
* XBee-Arduino 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 XBee-Arduino. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XBee_h
#define XBee_h
#include <WProgram.h>
#include <inttypes.h>
#define SERIES_1
#define SERIES_2
// set to ATAP value of XBee. AP=2 is recommended
#define ATAP 2
#define START_BYTE 0x7e
#define ESCAPE 0x7d
#define XON 0x11
#define XOFF 0x13
// This value determines the size of the byte array for receiving RX packets
// Most users won't be dealing with packets this large so you can adjust this
// value to reduce memory consumption. But, remember that
// if a RX packet exceeds this size, it cannot be parsed!
// This value is determined by the largest packet size (100 byte payload + 64-bit address + option byte and rssi byte) of a series 1 radio
#define MAX_FRAME_DATA_SIZE 110
#define BROADCAST_ADDRESS 0xffff
#define ZB_BROADCAST_ADDRESS 0xfffe
// the non-variable length of the frame data (not including frame id or api id or variable data size (e.g. payload, at command set value)
#define ZB_TX_API_LENGTH 12
#define TX_16_API_LENGTH 3
#define TX_64_API_LENGTH 9
#define AT_COMMAND_API_LENGTH 2
#define REMOTE_AT_COMMAND_API_LENGTH 13
// start/length(2)/api/frameid/checksum bytes
#define PACKET_OVERHEAD_LENGTH 6
// api is always the third byte in packet
#define API_ID_INDEX 3
// frame position of rssi byte
#define RX_16_RSSI_OFFSET 2
#define RX_64_RSSI_OFFSET 8
#define DEFAULT_FRAME_ID 1
#define NO_RESPONSE_FRAME_ID 0
// TODO put in tx16 class
#define ACK_OPTION 0
#define DISABLE_ACK_OPTION 1
#define BROADCAST_OPTION 4
// RX options
#define ZB_PACKET_ACKNOWLEDGED 0x01
#define ZB_BROADCAST_PACKET 0x02
// not everything is implemented!
/**
* Api Id constants
*/
#define TX_64_REQUEST 0x0
#define TX_16_REQUEST 0x1
#define AT_COMMAND_REQUEST 0x08
#define AT_COMMAND_QUEUE_REQUEST 0x09
#define REMOTE_AT_REQUEST 0x17
#define ZB_TX_REQUEST 0x10
#define ZB_EXPLICIT_TX_REQUEST 0x11
#define RX_64_RESPONSE 0x80
#define RX_16_RESPONSE 0x81
#define RX_64_IO_RESPONSE 0x82
#define RX_16_IO_RESPONSE 0x83
#define AT_RESPONSE 0x88
#define TX_STATUS_RESPONSE 0x89
#define MODEM_STATUS_RESPONSE 0x8a
#define ZB_RX_RESPONSE 0x90
#define ZB_EXPLICIT_RX_RESPONSE 0x91
#define ZB_TX_STATUS_RESPONSE 0x8b
#define ZB_IO_SAMPLE_RESPONSE 0x92
#define ZB_IO_NODE_IDENTIFIER_RESPONSE 0x95
#define AT_COMMAND_RESPONSE 0x88
#define REMOTE_AT_COMMAND_RESPONSE 0x97
/**
* TX STATUS constants
*/
#define SUCCESS 0x0
#define CCA_FAILURE 0x2
#define INVALID_DESTINATION_ENDPOINT_SUCCESS 0x15
#define NETWORK_ACK_FAILURE 0x21
#define NOT_JOINED_TO_NETWORK 0x22
#define SELF_ADDRESSED 0x23
#define ADDRESS_NOT_FOUND 0x24
#define ROUTE_NOT_FOUND 0x25
#define PAYLOAD_TOO_LARGE 0x74
// modem status
#define HARDWARE_RESET 0
#define WATCHDOG_TIMER_RESET 1
#define ASSOCIATED 2
#define DISASSOCIATED 3
#define SYNCHRONIZATION_LOST 4
#define COORDINATOR_REALIGNMENT 5
#define COORDINATOR_STARTED 6
#define ZB_BROADCAST_RADIUS_MAX_HOPS 0
#define ZB_TX_UNICAST 0
#define ZB_TX_BROADCAST 8
#define AT_OK 0
#define AT_ERROR 1
#define AT_INVALID_COMMAND 2
#define AT_INVALID_PARAMETER 3
#define AT_NO_RESPONSE 4
#define NO_ERROR 0
#define CHECKSUM_FAILURE 1
#define PACKET_EXCEEDS_BYTE_ARRAY_LENGTH 2
#define UNEXPECTED_START_BYTE 3
/**
* The super class of all XBee responses (RX packets)
* Users should never attempt to create an instance of this class; instead
* create an instance of a subclass
* It is recommend to reuse subclasses to conserve memory
*/
class XBeeResponse {
public:
//static const int MODEM_STATUS = 0x8a;
/**
* Default constructor
*/
XBeeResponse();
/**
* Returns Api Id of the response
*/
uint8_t getApiId();
void setApiId(uint8_t apiId);
/**
* Returns the MSB length of the packet
*/
uint8_t getMsbLength();
void setMsbLength(uint8_t msbLength);
/**
* Returns the LSB length of the packet
*/
uint8_t getLsbLength();
void setLsbLength(uint8_t lsbLength);
/**
* Returns the packet checksum
*/
uint8_t getChecksum();
void setChecksum(uint8_t checksum);
/**
* Returns the length of the frame data: all bytes after the api id, and prior to the checksum
* Note up to release 0.1.2, this was incorrectly including the checksum in the length.
*/
uint8_t getFrameDataLength();
void setFrameData(uint8_t* frameDataPtr);
/**
* Returns the buffer that contains the response.
* Starts with byte that follows API ID and includes all bytes prior to the checksum
* Length is specified by getFrameDataLength()
* Note: Unlike Digi's definition of the frame data, this does not start with the API ID..
* The reason for this is all responses include an API ID, whereas my frame data
* includes only the API specific data.
*/
uint8_t* getFrameData();
void setFrameLength(uint8_t frameLength);
// to support future 65535 byte packets I guess
/**
* Returns the length of the packet
*/
uint16_t getPacketLength();
/**
* Resets the response to default values
*/
void reset();
/**
* Initializes the response
*/
void init();
#ifdef SERIES_2
/**
* Call with instance of ZBTxStatusResponse class only if getApiId() == ZB_TX_STATUS_RESPONSE
* to populate response
*/
void getZBTxStatusResponse(XBeeResponse &response);
/**
* Call with instance of ZBRxResponse class only if getApiId() == ZB_RX_RESPONSE
* to populate response
*/
void getZBRxResponse(XBeeResponse &response);
/**
* Call with instance of ZBRxIoSampleResponse class only if getApiId() == ZB_IO_SAMPLE_RESPONSE
* to populate response
*/
void getZBRxIoSampleResponse(XBeeResponse &response);
#endif
#ifdef SERIES_1
/**
* Call with instance of TxStatusResponse only if getApiId() == TX_STATUS_RESPONSE
*/
void getTxStatusResponse(XBeeResponse &response);
/**
* Call with instance of Rx16Response only if getApiId() == RX_16_RESPONSE
*/
void getRx16Response(XBeeResponse &response);
/**
* Call with instance of Rx64Response only if getApiId() == RX_64_RESPONSE
*/
void getRx64Response(XBeeResponse &response);
/**
* Call with instance of Rx16IoSampleResponse only if getApiId() == RX_16_IO_RESPONSE
*/
void getRx16IoSampleResponse(XBeeResponse &response);
/**
* Call with instance of Rx64IoSampleResponse only if getApiId() == RX_64_IO_RESPONSE
*/
void getRx64IoSampleResponse(XBeeResponse &response);
#endif
/**
* Call with instance of AtCommandResponse only if getApiId() == AT_COMMAND_RESPONSE
*/
void getAtCommandResponse(XBeeResponse &responses);
/**
* Call with instance of RemoteAtCommandResponse only if getApiId() == REMOTE_AT_COMMAND_RESPONSE
*/
void getRemoteAtCommandResponse(XBeeResponse &response);
/**
* Call with instance of ModemStatusResponse only if getApiId() == MODEM_STATUS_RESPONSE
*/
void getModemStatusResponse(XBeeResponse &response);
/**
* Returns true if the response has been successfully parsed and is complete and ready for use
*/
bool isAvailable();
void setAvailable(bool complete);
/**
* Returns true if the response contains errors
*/
bool isError();
/**
* Returns an error code, or zero, if successful.
* Error codes include: CHECKSUM_FAILURE, PACKET_EXCEEDS_BYTE_ARRAY_LENGTH, UNEXPECTED_START_BYTE
*/
uint8_t getErrorCode();
void setErrorCode(uint8_t errorCode);
protected:
// pointer to frameData
uint8_t* _frameDataPtr;
private:
void setCommon(XBeeResponse &target);
uint8_t _apiId;
uint8_t _msbLength;
uint8_t _lsbLength;
uint8_t _checksum;
uint8_t _frameLength;
bool _complete;
uint8_t _errorCode;
};
class XBeeAddress {
public:
XBeeAddress();
};
/**
* Represents a 64-bit XBee Address
*/
class XBeeAddress64 : public XBeeAddress {
public:
XBeeAddress64(uint32_t msb, uint32_t lsb);
XBeeAddress64();
uint32_t getMsb();
uint32_t getLsb();
void setMsb(uint32_t msb);
void setLsb(uint32_t lsb);
private:
uint32_t _msb;
uint32_t _lsb;
};
//class XBeeAddress16 : public XBeeAddress {
//public:
// XBeeAddress16(uint16_t addr);
// XBeeAddress16();
// uint16_t getAddress();
// void setAddress(uint16_t addr);
//private:
// uint16_t _addr;
//};
/**
* This class is extended by all Responses that include a frame id
*/
class FrameIdResponse : public XBeeResponse {
public:
FrameIdResponse();
uint8_t getFrameId();
private:
uint8_t _frameId;
};
/**
* Common functionality for both Series 1 and 2 data RX data packets
*/
class RxDataResponse : public XBeeResponse {
public:
RxDataResponse();
/**
* Returns the specified index of the payload. The index may be 0 to getDataLength() - 1
* This method is deprecated; use uint8_t* getData()
*/
uint8_t getData(int index);
/**
* Returns the payload array. This may be accessed from index 0 to getDataLength() - 1
*/
uint8_t* getData();
/**
* Returns the length of the payload
*/
virtual uint8_t getDataLength() = 0;
/**
* Returns the position in the frame data where the data begins
*/
virtual uint8_t getDataOffset() = 0;
};
// getResponse to return the proper subclass:
// we maintain a pointer to each type of response, when a response is parsed, it is allocated only if NULL
// can we allocate an object in a function?
#ifdef SERIES_2
/**
* Represents a Series 2 TX status packet
*/
class ZBTxStatusResponse : public FrameIdResponse {
public:
ZBTxStatusResponse();
uint16_t getRemoteAddress();
uint8_t getTxRetryCount();
uint8_t getDeliveryStatus();
uint8_t getDiscoveryStatus();
bool isSuccess();
};
/**
* Represents a Series 2 RX packet
*/
class ZBRxResponse : public RxDataResponse {
public:
ZBRxResponse();
XBeeAddress64& getRemoteAddress64();
uint16_t getRemoteAddress16();
uint8_t getOption();
uint8_t getDataLength();
// frame position where data starts
uint8_t getDataOffset();
private:
XBeeAddress64 _remoteAddress64;
};
/**
* Represents a Series 2 RX I/O Sample packet
*/
class ZBRxIoSampleResponse : public ZBRxResponse {
public:
ZBRxIoSampleResponse();
bool containsAnalog();
bool containsDigital();
/**
* Returns true if the pin is enabled
*/
bool isAnalogEnabled(uint8_t pin);
/**
* Returns true if the pin is enabled
*/
bool isDigitalEnabled(uint8_t pin);
/**
* Returns the 10-bit analog reading of the specified pin.
* Valid pins include ADC:xxx.
*/
uint16_t getAnalog(uint8_t pin);
/**
* Returns true if the specified pin is high/on.
* Valid pins include DIO:xxx.
*/
bool isDigitalOn(uint8_t pin);
uint8_t getDigitalMaskMsb();
uint8_t getDigitalMaskLsb();
uint8_t getAnalogMask();
};
#endif
#ifdef SERIES_1
/**
* Represents a Series 1 TX Status packet
*/
class TxStatusResponse : public FrameIdResponse {
public:
TxStatusResponse();
uint8_t getStatus();
bool isSuccess();
};
/**
* Represents a Series 1 RX packet
*/
class RxResponse : public RxDataResponse {
public:
RxResponse();
// remember rssi is negative but this is unsigned byte so it's up to you to convert
uint8_t getRssi();
uint8_t getOption();
bool isAddressBroadcast();
bool isPanBroadcast();
uint8_t getDataLength();
uint8_t getDataOffset();
virtual uint8_t getRssiOffset() = 0;
};
/**
* Represents a Series 1 16-bit address RX packet
*/
class Rx16Response : public RxResponse {
public:
Rx16Response();
uint8_t getRssiOffset();
uint16_t getRemoteAddress16();
protected:
uint16_t _remoteAddress;
};
/**
* Represents a Series 1 64-bit address RX packet
*/
class Rx64Response : public RxResponse {
public:
Rx64Response();
uint8_t getRssiOffset();
XBeeAddress64& getRemoteAddress64();
private:
XBeeAddress64 _remoteAddress;
};
/**
* Represents a Series 1 RX I/O Sample packet
*/
class RxIoSampleBaseResponse : public RxResponse {
public:
RxIoSampleBaseResponse();
/**
* Returns the number of samples in this packet
*/
uint8_t getSampleSize();
bool containsAnalog();
bool containsDigital();
/**
* Returns true if the specified analog pin is enabled
*/
bool isAnalogEnabled(uint8_t pin);
/**
* Returns true if the specified digital pin is enabled
*/
bool isDigitalEnabled(uint8_t pin);
/**
* Returns the 10-bit analog reading of the specified pin.
* Valid pins include ADC:0-5. Sample index starts at 0
*/
uint16_t getAnalog(uint8_t pin, uint8_t sample);
/**
* Returns true if the specified pin is high/on.
* Valid pins include DIO:0-8. Sample index starts at 0
*/
bool isDigitalOn(uint8_t pin, uint8_t sample);
uint8_t getSampleOffset();
private:
};
class Rx16IoSampleResponse : public RxIoSampleBaseResponse {
public:
Rx16IoSampleResponse();
uint16_t getRemoteAddress16();
uint8_t getRssiOffset();
};
class Rx64IoSampleResponse : public RxIoSampleBaseResponse {
public:
Rx64IoSampleResponse();
XBeeAddress64& getRemoteAddress64();
uint8_t getRssiOffset();
private:
XBeeAddress64 _remoteAddress;
};
#endif
/**
* Represents a Modem Status RX packet
*/
class ModemStatusResponse : public XBeeResponse {
public:
ModemStatusResponse();
uint8_t getStatus();
};
/**
* Represents an AT Command RX packet
*/
class AtCommandResponse : public FrameIdResponse {
public:
AtCommandResponse();
/**
* Returns an array containing the two character command
*/
uint8_t* getCommand();
/**
* Returns the command status code.
* Zero represents a successful command
*/
uint8_t getStatus();
/**
* Returns an array containing the command value.
* This is only applicable to query commands.
*/
uint8_t* getValue();
/**
* Returns the length of the command value array.
*/
uint8_t getValueLength();
/**
* Returns true if status equals AT_OK
*/
bool isOk();
};
/**
* Represents a Remote AT Command RX packet
*/
class RemoteAtCommandResponse : public AtCommandResponse {
public:
RemoteAtCommandResponse();
/**
* Returns an array containing the two character command
*/
uint8_t* getCommand();
/**
* Returns the command status code.
* Zero represents a successful command
*/
uint8_t getStatus();
/**
* Returns an array containing the command value.
* This is only applicable to query commands.
*/
uint8_t* getValue();
/**
* Returns the length of the command value array.
*/
uint8_t getValueLength();
/**
* Returns the 16-bit address of the remote radio
*/
uint16_t getRemoteAddress16();
/**
* Returns the 64-bit address of the remote radio
*/
XBeeAddress64& getRemoteAddress64();
/**
* Returns true if command was successful
*/
bool isOk();
private:
XBeeAddress64 _remoteAddress64;
};
/**
* Super class of all XBee requests (TX packets)
* Users should never create an instance of this class; instead use an subclass of this class
* It is recommended to reuse Subclasses of the class to conserve memory
* <p/>
* This class allocates a buffer to
*/
class XBeeRequest {
public:
/**
* Constructor
* TODO make protected
*/
XBeeRequest(uint8_t apiId, uint8_t frameId);
/**
* Sets the frame id. Must be between 1 and 255 inclusive to get a TX status response.
*/
void setFrameId(uint8_t frameId);
/**
* Returns the frame id
*/
uint8_t getFrameId();
/**
* Returns the API id
*/
uint8_t getApiId();
// setting = 0 makes this a pure virtual function, meaning the subclass must implement, like abstract in java
/**
* Starting after the frame id (pos = 0) and up to but not including the checksum
* Note: Unlike Digi's definition of the frame data, this does not start with the API ID.
* The reason for this is the API ID and Frame ID are common to all requests, whereas my definition of
* frame data is only the API specific data.
*/
virtual uint8_t getFrameData(uint8_t pos) = 0;
/**
* Returns the size of the api frame (not including frame id or api id or checksum).
*/
virtual uint8_t getFrameDataLength() = 0;
//void reset();
protected:
void setApiId(uint8_t apiId);
private:
uint8_t _apiId;
uint8_t _frameId;
};
// TODO add reset/clear method since responses are often reused
/**
* Primary interface for communicating with an XBee Radio.
* This class provides methods for sending and receiving packets with an XBee radio via the serial port.
* The XBee radio must be configured in API (packet) mode (AP=2)
* in order to use this software.
* <p/>
* Since this code is designed to run on a microcontroller, with only one thread, you are responsible for reading the
* data off the serial buffer in a timely manner. This involves a call to a variant of readPacket(...).
* If your serial port is receiving data faster than you are reading, you can expect to lose packets.
* Arduino only has a 128 byte serial buffer so it can easily overflow if two or more packets arrive
* without a call to readPacket(...)
* <p/>
* In order to conserve resources, this class only supports storing one response packet in memory at a time.
* This means that you must fully consume the packet prior to calling readPacket(...), because calling
* readPacket(...) overwrites the previous response.
* <p/>
* This class creates an array of size MAX_FRAME_DATA_SIZE for storing the response packet. You may want
* to adjust this value to conserve memory.
*
* \author Andrew Rapp
*/
class XBee {
public:
XBee();
// for eclipse dev only
void setSerial(HardwareSerial &serial);
/**
* Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.
* You may call <i>xbee</i>.getResponse().isAvailable() after calling this method to determine if
* a packet is ready, or <i>xbee</i>.getResponse().isError() to determine if
* a error occurred.
* <p/>
* This method should always return quickly since it does not wait for serial data to arrive.
* You will want to use this method if you are doing other timely stuff in your loop, where
* a delay would cause problems.
* NOTE: calling this method resets the current response, so make sure you first consume the
* current response
*/
void readPacket();
/**
* Waits a maximum of <i>timeout</i> milliseconds for a response packet before timing out; returns true if packet is read.
* Returns false if timeout or error occurs.
*/
bool readPacket(int timeout);
/**
* Reads until a packet is received or an error occurs.
* Caution: use this carefully since if you don't get a response, your Arduino code will hang on this
* call forever!! often it's better to use a timeout: readPacket(int)
*/
void readPacketUntilAvailable();
/**
* Starts the serial connection at the supplied baud rate
*/
void begin(long baud);
void getResponse(XBeeResponse &response);
/**
* Returns a reference to the current response
* Note: once readPacket is called again this response will be overwritten!
*/
XBeeResponse& getResponse();
/**
* Sends a XBeeRequest (TX packet) out the serial port
*/
void send(XBeeRequest &request);
//uint8_t sendAndWaitForResponse(XBeeRequest &request, int timeout);
/**
* Returns a sequential frame id between 1 and 255
*/
uint8_t getNextFrameId();
private:
void sendByte(uint8_t b, bool escape);
void resetResponse();
XBeeResponse _response;
bool _escape;
// current packet position for response. just a state variable for packet parsing and has no relevance for the response otherwise
uint8_t _pos;
// last byte read
uint8_t b;
uint8_t _checksumTotal;
uint8_t _nextFrameId;
// buffer for incoming RX packets. holds only the api specific frame data, starting after the api id byte and prior to checksum
uint8_t _responseFrameData[MAX_FRAME_DATA_SIZE];
HardwareSerial* _xbeeSerial;
};
/**
* All TX packets that support payloads extend this class
*/
class PayloadRequest : public XBeeRequest {
public:
PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength);
/**
* Returns the payload of the packet, if not null
*/
uint8_t* getPayload();
/**
* Sets the payload array
*/
void setPayload(uint8_t* payloadPtr);
/**
* Returns the length of the payload array, as specified by the user.
*/
uint8_t getPayloadLength();
/**
* Sets the length of the payload to include in the request. For example if the payload array
* is 50 bytes and you only want the first 10 to be included in the packet, set the length to 10.
* Length must be <= to the array length.
*/
void setPayloadLength(uint8_t payloadLength);
private:
uint8_t* _payloadPtr;
uint8_t _payloadLength;
};
#ifdef SERIES_1
/**
* Represents a Series 1 TX packet that corresponds to Api Id: TX_16_REQUEST
* <p/>
* Be careful not to send a data array larger than the max packet size of your radio.
* This class does not perform any validation of packet size and there will be no indication
* if the packet is too large, other than you will not get a TX Status response.
* The datasheet says 100 bytes is the maximum, although that could change in future firmware.
*/
class Tx16Request : public PayloadRequest {
public:
Tx16Request(uint16_t addr16, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
/**
* Creates a Unicast Tx16Request with the ACK option and DEFAULT_FRAME_ID
*/
Tx16Request(uint16_t addr16, uint8_t *payload, uint8_t payloadLength);
/**
* Creates a default instance of this class. At a minimum you must specify
* a payload, payload length and a destination address before sending this request.
*/
Tx16Request();
uint16_t getAddress16();
void setAddress16(uint16_t addr16);
uint8_t getOption();
void setOption(uint8_t option);
uint8_t getFrameData(uint8_t pos);
uint8_t getFrameDataLength();
protected:
private:
uint16_t _addr16;
uint8_t _option;
};
/**
* Represents a Series 1 TX packet that corresponds to Api Id: TX_64_REQUEST
*
* Be careful not to send a data array larger than the max packet size of your radio.
* This class does not perform any validation of packet size and there will be no indication
* if the packet is too large, other than you will not get a TX Status response.
* The datasheet says 100 bytes is the maximum, although that could change in future firmware.
*/
class Tx64Request : public PayloadRequest {
public:
Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
/**
* Creates a unicast Tx64Request with the ACK option and DEFAULT_FRAME_ID
*/
Tx64Request(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength);
/**
* Creates a default instance of this class. At a minimum you must specify
* a payload, payload length and a destination address before sending this request.
*/
Tx64Request();
XBeeAddress64& getAddress64();
void setAddress64(XBeeAddress64& addr64);
// TODO move option to superclass
uint8_t getOption();
void setOption(uint8_t option);
uint8_t getFrameData(uint8_t pos);
uint8_t getFrameDataLength();
private:
XBeeAddress64 _addr64;
uint8_t _option;
};
#endif
#ifdef SERIES_2
/**
* Represents a Series 2 TX packet that corresponds to Api Id: ZB_TX_REQUEST
*
* Be careful not to send a data array larger than the max packet size of your radio.
* This class does not perform any validation of packet size and there will be no indication
* if the packet is too large, other than you will not get a TX Status response.
* The datasheet says 72 bytes is the maximum for ZNet firmware and ZB Pro firmware provides
* the ATNP command to get the max supported payload size. This command is useful since the
* maximum payload size varies according to certain settings, such as encryption.
* ZB Pro firmware provides a PAYLOAD_TOO_LARGE that is returned if payload size
* exceeds the maximum.
*/
class ZBTxRequest : public PayloadRequest {
public:
/**
* Creates a unicast ZBTxRequest with the ACK option and DEFAULT_FRAME_ID
*/
ZBTxRequest(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength);
ZBTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId);
/**
* Creates a default instance of this class. At a minimum you must specify
* a payload, payload length and a destination address before sending this request.
*/
ZBTxRequest();
XBeeAddress64& getAddress64();
uint16_t getAddress16();
uint8_t getBroadcastRadius();
uint8_t getOption();
void setAddress64(XBeeAddress64& addr64);
void setAddress16(uint16_t addr16);
void setBroadcastRadius(uint8_t broadcastRadius);
void setOption(uint8_t option);
protected:
// declare virtual functions
uint8_t getFrameData(uint8_t pos);
uint8_t getFrameDataLength();
private:
XBeeAddress64 _addr64;
uint16_t _addr16;
uint8_t _broadcastRadius;
uint8_t _option;
};
#endif
/**
* Represents an AT Command TX packet
* The command is used to configure the serially connected XBee radio
*/
class AtCommandRequest : public XBeeRequest {
public:
AtCommandRequest();
AtCommandRequest(uint8_t *command);
AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
uint8_t getFrameData(uint8_t pos);
uint8_t getFrameDataLength();
uint8_t* getCommand();
void setCommand(uint8_t* command);
uint8_t* getCommandValue();
void setCommandValue(uint8_t* command);
uint8_t getCommandValueLength();
void setCommandValueLength(uint8_t length);
/**
* Clears the optional commandValue and commandValueLength so that a query may be sent
*/
void clearCommandValue();
//void reset();
private:
uint8_t *_command;
uint8_t *_commandValue;
uint8_t _commandValueLength;
};
/**
* Represents an Remote AT Command TX packet
* The command is used to configure a remote XBee radio
*/
class RemoteAtCommandRequest : public AtCommandRequest {
public:
RemoteAtCommandRequest();
/**
* Creates a RemoteAtCommandRequest with 16-bit address to set a command.
* 64-bit address defaults to broadcast and applyChanges is true.
*/
RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
/**
* Creates a RemoteAtCommandRequest with 16-bit address to query a command.
* 64-bit address defaults to broadcast and applyChanges is true.
*/
RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command);
/**
* Creates a RemoteAtCommandRequest with 64-bit address to set a command.
* 16-bit address defaults to broadcast and applyChanges is true.
*/
RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength);
/**
* Creates a RemoteAtCommandRequest with 16-bit address to query a command.
* 16-bit address defaults to broadcast and applyChanges is true.
*/
RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command);
uint16_t getRemoteAddress16();
void setRemoteAddress16(uint16_t remoteAddress16);
XBeeAddress64& getRemoteAddress64();
void setRemoteAddress64(XBeeAddress64 &remoteAddress64);
bool getApplyChanges();
void setApplyChanges(bool applyChanges);
uint8_t getFrameData(uint8_t pos);
uint8_t getFrameDataLength();
static XBeeAddress64 broadcastAddress64;
// static uint16_t broadcast16Address;
private:
XBeeAddress64 _remoteAddress64;
uint16_t _remoteAddress16;
bool _applyChanges;
};
#endif //XBee_h