├── .gitattributes ├── .gitignore ├── License GNU GPL v2.txt ├── README.md ├── SimpleZigBeeAddress.cpp ├── SimpleZigBeeAddress.h ├── SimpleZigBeePacket.cpp ├── SimpleZigBeePacket.h ├── SimpleZigBeeRadio.cpp ├── SimpleZigBeeRadio.h ├── XBee-ZB-manual.pdf ├── examples ├── GettingStarted │ ├── Part1_Coordinator │ │ └── Part1_Coordinator.ino │ ├── Part1_Router │ │ └── Part1_Router.ino │ ├── Part2_Coordinator │ │ └── Part2_Coordinator.ino │ ├── Part2_Router │ │ └── Part2_Router.ino │ ├── Part3_Coordinator │ │ └── Part3_Coordinator.ino │ └── Part3_Router │ │ └── Part3_Router.ino ├── SimpleZigBeePacketExamples │ ├── ATCommandPacket │ │ └── ATCommandPacket.ino │ ├── SimpleIncomingZigBeePacket │ │ └── SimpleIncomingZigBeePacket.ino │ ├── SimpleZigBeeAddress │ │ └── SimpleZigBeeAddress.ino │ ├── SimpleZigBeePacket │ │ └── SimpleZigBeePacket.ino │ └── TXPacket │ │ └── TXPacket.ino └── SimpleZigBeeRadioExamples │ ├── ATCommand │ └── ATCommand.ino │ └── ModemStatus │ └── ModemStatus.ino └── keywords.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /License GNU GPL v2.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleZigBee 2 | Arduino Library for XBee S2 ZigBee 3 | 4 | SimpleZigBee is an easy-to-use Arduino library for communicating with XBee Series 2 and 2B ZigBee radios. The library implements the most popular XBee API frame types (TX, RX, AT Command, etc.) and makes it easy to add a wireless communication network to your Arduino project. 5 | 6 | A 3 part tutorial for getting started with the SimpleZigBee library can be found at: 7 | * Getting Started with SimpleZigBee for Arduino & XBee: Part 1 8 | * Getting Started with SimpleZigBee for Arduino & XBee: Part 2 9 | * Getting Started with SimpleZigBee for Arduino & XBee: Part 3 10 | -------------------------------------------------------------------------------- /SimpleZigBeeAddress.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Eric Burger. All rights reserved. 3 | */ 4 | 5 | #include "SimpleZigBeeAddress.h" 6 | 7 | /*////////////////////////////////////////////////////////////////////// 8 | //////////////////////////////////////////////////////////////////////// 9 | SimpleZigBeeAddress64 Class 10 | //////////////////////////////////////////////////////////////////////// 11 | /*////////////////////////////////////////////////////////////////////// 12 | 13 | /*////////////////////////////////////////////////////////////////////// 14 | INITIALIZATION METHODS 15 | /*////////////////////////////////////////////////////////////////////// 16 | 17 | /** 18 | * Constructor: SimpleZigBeeAddress64() 19 | * @ Since v0.1.0 by Eric Burger, August 2013 20 | * @ Default constructor for ZigBee 64-bit address. Default to broadcast address. 21 | */ 22 | SimpleZigBeeAddress64::SimpleZigBeeAddress64(){ 23 | setAddress( BROADCAST_ADDRESS_64_MSB, BROADCAST_ADDRESS_64_LSB ); 24 | } 25 | 26 | /** 27 | * Constructor: SimpleZigBeeAddress64() 28 | * @ Since v0.1.0 by Eric Burger, August 2013 29 | * @ Constructor with input address for ZigBee 64-bit address. 30 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 31 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 32 | */ 33 | SimpleZigBeeAddress64::SimpleZigBeeAddress64(uint32_t adr64MSB, uint32_t adr64LSB){ 34 | setAddress( adr64MSB, adr64LSB ); 35 | } 36 | 37 | /*////////////////////////////////////////////////////////////////////// 38 | PRIVATE VARIABLE METHODS 39 | /*////////////////////////////////////////////////////////////////////// 40 | 41 | /** 42 | * Method: setAddress(uint32_t adr64MSB, uint32_t adr64LSB) 43 | * @ Since v0.1.0 by Eric Burger, August 2013 44 | * @ Set 64-bit address 45 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 46 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 47 | */ 48 | void SimpleZigBeeAddress64::setAddress(uint32_t adr64MSB, uint32_t adr64LSB){ 49 | _address64MSB = adr64MSB; 50 | _address64LSB = adr64LSB; 51 | } 52 | 53 | /** 54 | * Method: getAddressMSB() 55 | * @ Since v0.1.0 by Eric Burger, August 2013 56 | * @ Returns MSB of 64-bit address 57 | */ 58 | uint32_t SimpleZigBeeAddress64::getAddressMSB(){ 59 | return _address64MSB; 60 | } 61 | 62 | /** 63 | * Method: getAddressLSB() 64 | * @ Since v0.1.0 by Eric Burger, August 2013 65 | * @ Returns LSB of 64-bit address 66 | */ 67 | uint32_t SimpleZigBeeAddress64::getAddressLSB(){ 68 | return _address64LSB; 69 | } 70 | 71 | /*////////////////////////////////////////////////////////////////////// 72 | //////////////////////////////////////////////////////////////////////// 73 | SimpleZigBeeAddress16 Class 74 | //////////////////////////////////////////////////////////////////////// 75 | /*////////////////////////////////////////////////////////////////////// 76 | 77 | /*////////////////////////////////////////////////////////////////////// 78 | INITIALIZATION METHODS 79 | /*////////////////////////////////////////////////////////////////////// 80 | /** 81 | * Constructor: SimpleZigBeeAddress16() 82 | * @ Since v0.1.0 by Eric Burger, August 2013 83 | * @ Default constructor for ZigBee 16-bit address. Default to broadcast address. 84 | */ 85 | SimpleZigBeeAddress16::SimpleZigBeeAddress16(){ 86 | setAddress( BROADCAST_ADDRESS_16 ); 87 | } 88 | 89 | /** 90 | * Constructor: SimpleZigBeeAddress64() 91 | * @ Since v0.1.0 by Eric Burger, August 2013 92 | * @ Constructor with input address for ZigBee 16-bit address. 93 | * @ param uint16_t adr16: 16-bit destination address 94 | */ 95 | SimpleZigBeeAddress16::SimpleZigBeeAddress16(uint16_t adr16){ 96 | setAddress( adr16 ); 97 | } 98 | 99 | /*////////////////////////////////////////////////////////////////////// 100 | PRIVATE VARIABLE METHODS 101 | /*////////////////////////////////////////////////////////////////////// 102 | 103 | /** 104 | * Method: setAddress(uint16_t adr16) 105 | * @ Since v0.1.0 by Eric Burger, August 2013 106 | * @ Set 16-bit address 107 | * @ param uint16_t adr16: 16-bit destination address 108 | */ 109 | void SimpleZigBeeAddress16::setAddress(uint16_t adr16){ 110 | _address16 = adr16; 111 | } 112 | 113 | /** 114 | * Method: getAddress() 115 | * @ Since v0.1.0 by Eric Burger, August 2013 116 | * @ Returns 16-bit address 117 | */ 118 | uint16_t SimpleZigBeeAddress16::getAddress(){ 119 | return _address16; 120 | } 121 | 122 | /*////////////////////////////////////////////////////////////////////// 123 | //////////////////////////////////////////////////////////////////////// 124 | SimpleZigBeeAddress Class 125 | //////////////////////////////////////////////////////////////////////// 126 | /*////////////////////////////////////////////////////////////////////// 127 | 128 | /*////////////////////////////////////////////////////////////////////// 129 | INITIALIZATION METHODS 130 | /*////////////////////////////////////////////////////////////////////// 131 | 132 | /** 133 | * Constructor: SimpleZigBeeAddress() 134 | * @ Since v0.1.0 by Eric Burger, August 2013 135 | * @ Default constructor for ZigBee address object. Default to 64-bit and 16-bit broadcast address. 136 | */ 137 | SimpleZigBeeAddress::SimpleZigBeeAddress(){ 138 | _address64 = SimpleZigBeeAddress64(); 139 | _address16 = SimpleZigBeeAddress16(); 140 | } 141 | 142 | /** 143 | * Constructor: SimpleZigBeeAddress() 144 | * @ Since v0.1.0 by Eric Burger, July 2014 145 | * @ Constructor with 64-bit input address for ZigBee address object. Default to 16-bit broadcast address. 146 | * @ param SimpleZigBeeAddress64 adr64: Object containing 64-bit address 147 | */ 148 | SimpleZigBeeAddress::SimpleZigBeeAddress(SimpleZigBeeAddress64 adr64){ 149 | _address64 = adr64; 150 | _address16 = SimpleZigBeeAddress16(); 151 | } 152 | 153 | /** 154 | * Constructor: SimpleZigBeeAddress() 155 | * @ Since v0.1.0 by Eric Burger, July 2014 156 | * @ Constructor with 64-bit and 16-bit input addresses for ZigBee address object. 157 | * @ param SimpleZigBeeAddress64 adr64: Object containing 64-bit address 158 | * @ param SimpleZigBeeAddress16 adr16: Object containing 16-bit address 159 | */ 160 | SimpleZigBeeAddress::SimpleZigBeeAddress(SimpleZigBeeAddress64 adr64, SimpleZigBeeAddress16 adr16){ 161 | _address64 = adr64; 162 | _address16 = adr16; 163 | } 164 | 165 | /** 166 | * Constructor: SimpleZigBeeAddress() 167 | * @ Since v0.1.0 by Eric Burger, August 2013 168 | * @ Constructor with 64-bit input address for ZigBee address object. Default to 16-bit broadcast address. 169 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 170 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 171 | */ 172 | SimpleZigBeeAddress::SimpleZigBeeAddress(uint32_t adr64MSB, uint32_t adr64LSB){ 173 | _address64 = SimpleZigBeeAddress64(adr64MSB,adr64LSB); 174 | _address16 = SimpleZigBeeAddress16(); 175 | } 176 | 177 | /** 178 | * Constructor: SimpleZigBeeAddress() 179 | * @ Since v0.1.0 by Eric Burger, August 2013 180 | * @ Constructor with 64-bit and 16-bit input addresses for ZigBee address object. 181 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 182 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 183 | * @ param uint16_t adr16: 16-bit address 184 | */ 185 | SimpleZigBeeAddress::SimpleZigBeeAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16){ 186 | _address64 = SimpleZigBeeAddress64(adr64MSB,adr64LSB); 187 | _address16 = SimpleZigBeeAddress16(adr16); 188 | } 189 | 190 | /*////////////////////////////////////////////////////////////////////// 191 | PRIVATE VARIABLE METHODS 192 | /*////////////////////////////////////////////////////////////////////// 193 | 194 | /** 195 | * Method: getAddress64() 196 | * @ Since v0.1.0 by Eric Burger, August 2013 197 | * @ Returns 64-bit address object 198 | */ 199 | SimpleZigBeeAddress64 SimpleZigBeeAddress::getAddress64(){ 200 | return _address64; 201 | } 202 | 203 | /** 204 | * Method: setAddress64(SimpleZigBeeAddress64 adr64) 205 | * @ Since v0.1.0 by Eric Burger, August 2013 206 | * @ Sets 64-bit address 207 | * @ param SimpleZigBeeAddress64 adr64: Object containing 64-bit address 208 | */ 209 | void SimpleZigBeeAddress::setAddress64(SimpleZigBeeAddress64 adr64){ 210 | _address64 = adr64; 211 | } 212 | 213 | /** 214 | * Method: setAddress64(uint32_t adr64MSB, uint32_t adr64LSB) 215 | * @ Since v0.1.0 by Eric Burger, August 2013 216 | * @ Sets 64-bit address 217 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 218 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 219 | */ 220 | void SimpleZigBeeAddress::setAddress64(uint32_t adr64MSB, uint32_t adr64LSB){ 221 | _address64.setAddress(adr64MSB,adr64LSB); 222 | } 223 | 224 | /** 225 | * Method: getAddress16() 226 | * @ Since v0.1.0 by Eric Burger, August 2013 227 | * @ Returns 16-bit address object 228 | */ 229 | SimpleZigBeeAddress16 SimpleZigBeeAddress::getAddress16(){ 230 | return _address16; 231 | } 232 | 233 | /** 234 | * Method: setAddress16(SimpleZigBeeAddress16 adr16) 235 | * @ Since v0.1.0 by Eric Burger, August 2013 236 | * @ Sets 16-bit address 237 | * @ param SimpleZigBeeAddress16 adr16: Object containing 16-bit address 238 | */ 239 | void SimpleZigBeeAddress::setAddress16(SimpleZigBeeAddress16 adr16){ 240 | _address16 = adr16; 241 | } 242 | 243 | /** 244 | * Method: setAddress16(uint16_t adr16) 245 | * @ Since v0.1.0 by Eric Burger, August 2013 246 | * @ Sets 16-bit address 247 | * @ param uint16_t adr16: 16-bit address 248 | */ 249 | void SimpleZigBeeAddress::setAddress16(uint16_t adr16){ 250 | _address16.setAddress( adr16 ); 251 | } 252 | -------------------------------------------------------------------------------- /SimpleZigBeeAddress.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Library Name: SimpleZigBeeAddress 3 | * Library URI: https://github.com/ericburger/simple-zigbee 4 | * Description: Classes for managing ZigBee addresses 5 | * by the connected radio. 6 | * Version: 0.1.1 7 | * Author(s): Eric Burger 8 | * Author URI: WallflowerOpen.com 9 | * License: GNU General Public License v2.0 or later 10 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html 11 | * 12 | * Copyright (c) 2013 Eric Burger. All rights reserved. 13 | * 14 | * This file is part of SimpleZigBee, written for XBee S2 Radios. 15 | * 16 | * SimpleZigBee is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published by 18 | * the Free Software Foundation, either version 2 of the License, or 19 | * (at your option) any later version. 20 | * 21 | * SimpleZigBee is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with SimpleZigBee. If not, see . 28 | */ 29 | 30 | #ifndef SimpleZigBeeAddress_h 31 | #define SimpleZigBeeAddress_h 32 | 33 | #include "Arduino.h" 34 | // Required for uint8_t type 35 | #include 36 | 37 | // ZigBee 64-bit Broadcast Address 38 | #define BROADCAST_ADDRESS_64_MSB 0x00000000 39 | #define BROADCAST_ADDRESS_64_LSB 0x0000ffff 40 | // ZigBee 64-bit Unknown/Broadcast Address 41 | #define COORDINATOR_ADDRESS_64_MSB 0x00000000 42 | #define COORDINATOR_ADDRESS_64_LSB 0x00000000 43 | // ZigBee 16-bit Unknown/Broadcast Address 44 | #define BROADCAST_ADDRESS_16 0xfffe 45 | 46 | /** 47 | * Class: SimpleZigBeeAddress64 48 | * @ Since v0.1.0 by Eric Burger, August 2013 49 | * @ Object for storing ZigBee 64-bit address 50 | */ 51 | class SimpleZigBeeAddress64 { 52 | public: 53 | // INITIALIZATION METHODS // 54 | SimpleZigBeeAddress64(); 55 | SimpleZigBeeAddress64(uint32_t adr64MSB, uint32_t adr64LSB); 56 | 57 | // PRIVATE VARIABLE METHODS // 58 | void setAddress(uint32_t adr64MSB, uint32_t adr64LSB); 59 | uint32_t getAddressMSB(); 60 | uint32_t getAddressLSB(); 61 | 62 | private: 63 | // Most significant bytes (1st half) of 64-bit address 64 | uint32_t _address64MSB; 65 | // Least significant bytes (2nd half) of 64-bit address 66 | uint32_t _address64LSB; 67 | }; 68 | 69 | /** 70 | * Class: SimpleZigBeeAddress64 71 | * @ Since v0.1.0 by Eric Burger, August 2013 72 | * @ Object for storing ZigBee 16-bit address 73 | */ 74 | class SimpleZigBeeAddress16 { 75 | public: 76 | // INITIALIZATION METHODS // 77 | SimpleZigBeeAddress16(); 78 | SimpleZigBeeAddress16(uint16_t adr16); 79 | 80 | // PRIVATE VARIABLE METHODS // 81 | void setAddress(uint16_t adr16); 82 | uint16_t getAddress(); 83 | 84 | private: 85 | // 16-bit address 86 | uint16_t _address16; 87 | }; 88 | 89 | /** 90 | * Class: SimpleZigBeeAddress64 91 | * @ Since v0.1.0 by Eric Burger, August 2013 92 | * @ Object for storing ZigBee 64-bit and 16-bit addresses 93 | */ 94 | class SimpleZigBeeAddress { 95 | public: 96 | // INITIALIZATION METHODS // 97 | SimpleZigBeeAddress(); 98 | SimpleZigBeeAddress(SimpleZigBeeAddress64 adr64); 99 | SimpleZigBeeAddress(SimpleZigBeeAddress64 adr64, SimpleZigBeeAddress16 adr16); 100 | SimpleZigBeeAddress(uint32_t adr64MSB, uint32_t adr64LSB); 101 | SimpleZigBeeAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16); 102 | 103 | // PRIVATE VARIABLE METHODS // 104 | SimpleZigBeeAddress64 getAddress64(); 105 | void setAddress64(SimpleZigBeeAddress64 adr64); 106 | void setAddress64(uint32_t adr64MSB, uint32_t adr64LSB); 107 | SimpleZigBeeAddress16 getAddress16(); 108 | void setAddress16(SimpleZigBeeAddress16 adr16); 109 | void setAddress16(uint16_t adr16); 110 | 111 | private: 112 | SimpleZigBeeAddress64 _address64; 113 | SimpleZigBeeAddress16 _address16; 114 | }; 115 | 116 | #endif //SimpleZigBeeAddress 117 | -------------------------------------------------------------------------------- /SimpleZigBeePacket.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Eric Burger. All rights reserved. 3 | */ 4 | 5 | #include "SimpleZigBeePacket.h" 6 | // For memory allocation of array pointer (malloc and realloc) 7 | //#include < ctype.h > 8 | 9 | /*////////////////////////////////////////////////////////////////////// 10 | //////////////////////////////////////////////////////////////////////// 11 | SimpleZigBeePacket Class 12 | //////////////////////////////////////////////////////////////////////// 13 | /*////////////////////////////////////////////////////////////////////// 14 | 15 | /*////////////////////////////////////////////////////////////////////// 16 | INITIALIZATION METHODS 17 | /*////////////////////////////////////////////////////////////////////// 18 | 19 | /** 20 | * Constructor: SimpleZigBeePacket() 21 | * @ Since v0.1.0 by Eric Burger, August 2013 22 | * @ Default constructor. Allocates 20 bytes of memory to the memory array. 23 | * In this case, the function sizeof(uint8_t) is a little unnecessary since sizeof() 24 | * returns the number of bytes and since uint8_t represents one byte, sizeof(uint8_t) = 1. 25 | * I have left the complete expression because it is also a good way of creating an int array (sizeof(int)=4). 26 | * The expression (uint8_t*) casts the pointer returned by malloc as a uint8_t pointer. 27 | * For reference: http://www.cplusplus.com/reference/cstdlib/malloc/ 28 | */ 29 | SimpleZigBeePacket::SimpleZigBeePacket() { 30 | _memoryArrayLength = 20; 31 | _ptrMemoryArray = (uint8_t*) malloc(sizeof(uint8_t) * _memoryArrayLength); 32 | _maxFrameLength = 50; 33 | init(); 34 | } 35 | 36 | /** 37 | * Constructor: SimpleZigBeePacket() 38 | * @ Since v0.1.0 by Eric Burger, August 2013 39 | * @ Constructor with parameter. Set the maximum frame size to increase or decrease maximum memory 40 | * allocation. Note the 64 byte size of the Arduino serial port buffer. If _maxFrameLength is set to larger 41 | * than 64, Arduino program must insure that serial buffer does not overflow, resulting in incomplete packets. 42 | * @ param int maxFrameLength: Limit to the length (# of bytes) of the packet frame 43 | */ 44 | SimpleZigBeePacket::SimpleZigBeePacket(int maxFrameLength) { 45 | _memoryArrayLength = 20; 46 | _ptrMemoryArray = (uint8_t*) malloc(sizeof(uint8_t) * _memoryArrayLength); 47 | _maxFrameLength = maxFrameLength; 48 | init(); 49 | } 50 | 51 | /** 52 | * Method: init() 53 | * @ Since v0.1.0 by Eric Burger, August 2013 54 | * @ Initiate the packet's private parameters 55 | */ 56 | void SimpleZigBeePacket::init() { 57 | _checksum = 0; 58 | _frameLength = 0; 59 | _errorCode = NO_ERROR; 60 | } 61 | 62 | /** 63 | * Method: reset() 64 | * @ Since v0.1.0 by Eric Burger, August 2013 65 | * @ Resets the packet's private parameters 66 | */ 67 | void SimpleZigBeePacket::reset() { 68 | init(); 69 | } 70 | 71 | /*////////////////////////////////////////////////////////////////////// 72 | MEMORY METHODS 73 | /*////////////////////////////////////////////////////////////////////// 74 | 75 | /** 76 | * Method: expandMemoryArray(int size) 77 | * @ Since v0.1.0 by Eric Burger, August 2013 78 | * @ Expands the packet class's memory array based on input size or until maximum frame size limit is reached. 79 | * Input sizes smaller than current memory array length will be ignored. The packet class does not contain 80 | * a function for reducing the memory array size. The reasoning being that if a certain size of packet has 81 | * been sent or received in the past, it is likely to occur again. 82 | * @ param int size: Desired size (# of bytes) of memory allocated to store the packet frame data 83 | */ 84 | void SimpleZigBeePacket::expandMemoryArray(int size){ 85 | if( size > _memoryArrayLength && size <= getMaxFrameLength() ){ 86 | uint8_t* new_array = NULL; 87 | // Re-allocate memory to accommodate the increased size of the memory array. 88 | // For reference: http://www.cplusplus.com/reference/cstdlib/realloc/ 89 | new_array = (uint8_t*) realloc(_ptrMemoryArray,(sizeof(uint8_t) * size)); 90 | if( new_array != NULL ){ 91 | _ptrMemoryArray = new_array; 92 | _memoryArrayLength = size; 93 | }else{ 94 | // Error re-allocating memory. No change change made to memory array. 95 | setErrorCode(ERROR_REALLOCATING_MEMORY); 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * Method: SimpleZigBeePacket::getMemoryData(int index) 102 | * @ Since v0.1.0 by Eric Burger, August 2013 103 | * @ Return the byte that is stored at the specified index of the memory array. 104 | * Be aware that since you are accessing data from a memory address, the byte that is 105 | * returned may be junk from a previous packet or a previous code running on your Arduino. 106 | * @ param int index: Index of data in the memory array 107 | */ 108 | uint8_t SimpleZigBeePacket::getMemoryData(int index){ 109 | if( index < _memoryArrayLength ){ 110 | return _ptrMemoryArray[index]; 111 | } 112 | return 0; 113 | } 114 | 115 | /** 116 | * Method: setMemoryData(int index, uint8_t byte) 117 | * @ Since v0.1.0 by Eric Burger, August 2013 118 | * @ Set the byte at the specified index of the memory array. 119 | * First, check that index is within permitted range. Expand memory array, if necessary. 120 | * Note: If maximum index is 49, maximum size is 50. 121 | * @ param int index: Index of the memory array to store data 122 | * @ param uint8_t byte: Data to store 123 | */ 124 | void SimpleZigBeePacket::setMemoryData(int index, uint8_t byte){ 125 | if( index < getMaxFrameLength() ){ 126 | if( index < _memoryArrayLength ){ 127 | _ptrMemoryArray[index] = byte; 128 | }else{ 129 | expandMemoryArray( (index+10) ); 130 | _ptrMemoryArray[index] = byte; 131 | } 132 | }else{ 133 | setErrorCode( MAX_FRAME_LENGTH_EXCEEDED ); 134 | } 135 | } 136 | 137 | /*////////////////////////////////////////////////////////////////////// 138 | PACKET PRIVATE VARIABLE METHODS 139 | /*////////////////////////////////////////////////////////////////////// 140 | 141 | /** 142 | * Method: getFrameLength() 143 | * @ Since v0.1.0 by Eric Burger, August 2013 144 | * @ Returns current frame length 145 | */ 146 | int SimpleZigBeePacket::getFrameLength(){ 147 | return _frameLength; 148 | } 149 | 150 | /** 151 | * Method: getLengthMSB() 152 | * @ Since v0.1.0 by Eric Burger, August 2013 153 | * @ Returns "Most Significant Byte" of packet frame length (Packet Index 1) using the operators 154 | * right shift (>>) and bitwise AND (&). 155 | */ 156 | uint8_t SimpleZigBeePacket::getLengthMSB(){ 157 | return ((getFrameLength() >> 8) & 0xff); 158 | } 159 | 160 | /** 161 | * Method: getLengthLSB() 162 | * @ Since v0.1.0 by Eric Burger, August 2013 163 | * @ Returns "Least Significant Byte" of packet frame length (Packet Index 2) using the operator bitwise AND (&). 164 | */ 165 | uint8_t SimpleZigBeePacket::getLengthLSB(){ 166 | return (getFrameLength() & 0xff); 167 | } 168 | 169 | /** 170 | * Method: setFrameLength(int frameLength) 171 | * @ Since v0.1.0 by Eric Burger, August 2013 172 | * @ Sets current frame length 173 | * @ param int frameLength: Frame length value to store 174 | */ 175 | void SimpleZigBeePacket::setFrameLength(int frameLength){ 176 | _frameLength = frameLength; 177 | } 178 | 179 | /** 180 | * Method: setFrameLengthMSB(uint8_t msb) 181 | * @ Since v0.1.0 by Eric Burger, August 2013 182 | * @ Sets "Most Significant Byte" of packet's length (Packet Index 1) 183 | * @ param uint8_t msb: Most Significant Byte of length 184 | */ 185 | void SimpleZigBeePacket::setFrameLengthMSB(uint8_t msb){ 186 | // Update frame length using the left shift (<<) operator. 187 | setFrameLength( uint16_t(msb << 8) + getLengthLSB() ); 188 | } 189 | 190 | /** 191 | * Method: setFrameLengthLSB(uint8_t lsb) 192 | * @ Since v0.1.0 by Eric Burger, August 2013 193 | * @ Sets "Least Significant Byte" of packet's length (Packet Index 2) 194 | * @ param uint8_t lsb: Least Significant Byte of length 195 | */ 196 | void SimpleZigBeePacket::setFrameLengthLSB(uint8_t lsb){ 197 | // Update frame length using the left shift (<<) operator. 198 | setFrameLength( uint16_t(getLengthMSB() << 8) + lsb ); 199 | } 200 | 201 | /** 202 | * Method: getFrameType() 203 | * @ Since v0.1.0 by Eric Burger, August 2013 204 | * @ Returns frame type (Packet Index 3, Frame Index 0) 205 | */ 206 | uint8_t SimpleZigBeePacket::getFrameType(){ 207 | return getFrameData(0); 208 | } 209 | 210 | /** 211 | * Method: getFrameID() 212 | * @ Since v0.1.0 by Eric Burger, August 2013 213 | * @ Returns frame ID. 214 | */ 215 | uint8_t SimpleZigBeePacket::getFrameID(){ 216 | return getFrameData(1); 217 | } 218 | 219 | /** 220 | * Method: getChecksum() 221 | * @ Since v0.1.0 by Eric Burger, August 2013 222 | * @ Returns the packet checksum (End of Packet) 223 | */ 224 | uint8_t SimpleZigBeePacket::getChecksum(){ 225 | return _checksum; 226 | } 227 | 228 | /** 229 | * Method: calculateChecksum() 230 | * @ Since v0.1.0 by Eric Burger, June 2014 231 | * @ Calculates and returns the packet checksum (Does not set _checksum) 232 | */ 233 | uint8_t SimpleZigBeePacket::calculateChecksum(){ 234 | uint8_t checksum = 0; 235 | for( int i=0; i getFrameLength() ){ 278 | setFrameLength(index+1); 279 | } 280 | }else{ 281 | setErrorCode( MAX_FRAME_LENGTH_EXCEEDED ); 282 | } 283 | } 284 | 285 | /** 286 | * Method: setFrameData(int startIndex, uint8_t* frameData, int frameDataLength) 287 | * @ Since v0.1.0 by Eric Burger, August 2013 288 | * @ Sets an array of bytes in the memory array of the packet, starting 289 | * from specified start index,and updates _frameLength, if necessary. 290 | * @ param int startIndex: Index at which to start storing bytes 291 | * @ param uint8_t* frameData: Pointer to array of bytes to store 292 | * @ param int frameDataLength: Length of array to input 293 | */ 294 | void SimpleZigBeePacket::setFrameData(int startIndex, uint8_t* frameData, int frameDataLength){ 295 | int lastIndex = startIndex + (frameDataLength - 1); 296 | if( lastIndex < getMaxFrameLength() ){ 297 | // Expand memory array, if necessary 298 | expandMemoryArray( (lastIndex+10) ); 299 | for(int i=0;i getFrameLength() ){ 303 | setFrameLength(lastIndex+1); 304 | } 305 | }else{ 306 | setErrorCode( MAX_FRAME_LENGTH_EXCEEDED ); 307 | } 308 | } 309 | 310 | /** 311 | * Method: getFrameData(int index) 312 | * @ Since v0.1.0 by Eric Burger, August 2013 313 | * @ Returns the frame byte of the incoming packet at the specified index 314 | * @ param int index: Index of frame data 315 | */ 316 | uint8_t SimpleZigBeePacket::getFrameData(int index){ 317 | if( index < getFrameLength() ){ 318 | return getMemoryData( index ); 319 | }else{ 320 | setErrorCode( FRAME_LENGTH_EXCEEDED ); 321 | return 0; 322 | } 323 | } 324 | 325 | /** 326 | * Method: getFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength) 327 | * @ Since v0.1.0 by Eric Burger, August 2013 328 | * @ Places an array of bytes from the memory array of the incoming packet in the 329 | * provided array pointer, starting from specified start index. 330 | * @ param int startIndex: Index of frame data at which to start 331 | * @ param uint8_t* arrayPtr: Array for storing bytes 332 | * @ param int frameDataLength: Number of bytes to return 333 | */ 334 | void SimpleZigBeePacket::getFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength){ 335 | // Check that requested data is within length of frame 336 | if( (startIndex + (frameDataLength - 1)) < getFrameLength() ){ 337 | for(int i=0;i 0; 356 | } 357 | 358 | /** 359 | * Method: getErrorCode() 360 | * @ Since v0.1.0 by Eric Burger, August 2013 361 | * @ Return error code 362 | */ 363 | int SimpleZigBeePacket::getErrorCode() { 364 | return _errorCode; 365 | } 366 | 367 | /** 368 | * Method: setErrorCode(int errorCode) 369 | * @ Since v0.1.0 by Eric Burger, August 2013 370 | * @ Sets error code 371 | * @ param int errorCode: Error code value to store 372 | */ 373 | void SimpleZigBeePacket::setErrorCode(int errorCode) { 374 | _errorCode = errorCode; 375 | } 376 | 377 | 378 | /*////////////////////////////////////////////////////////////////////// 379 | //////////////////////////////////////////////////////////////////////// 380 | SimpleIncomingZigBeePacket Class 381 | //////////////////////////////////////////////////////////////////////// 382 | /*////////////////////////////////////////////////////////////////////// 383 | 384 | /*////////////////////////////////////////////////////////////////////// 385 | INITIALIZATION METHODS 386 | /*////////////////////////////////////////////////////////////////////// 387 | 388 | /** 389 | * Constructor: SimpleZigBeeRadio() 390 | * @ Since v0.1.0 by Eric Burger, August 2013 391 | * @ Default constructor that creates packet object for incoming packets. 392 | */ 393 | SimpleIncomingZigBeePacket::SimpleIncomingZigBeePacket() : SimpleZigBeePacket(){ 394 | SimpleZigBeePacket::init(); 395 | } 396 | 397 | /** 398 | * Constructor: SimpleZigBeeRadio() 399 | * @ Since v0.1.0 by Eric Burger, August 2013 400 | * @ Constructor with inputs that creates packet object for incoming packets. 401 | * @ param int maxFrameLength: Limit (# of bytes) on packet frame size 402 | */ 403 | SimpleIncomingZigBeePacket::SimpleIncomingZigBeePacket(int maxFrameLength) : SimpleZigBeePacket(maxFrameLength) { 404 | SimpleZigBeePacket::init(); 405 | } 406 | 407 | /*////////////////////////////////////////////////////////////////////// 408 | ZIGBEE RECIEVED (RX) PACKET METHODS 409 | /*////////////////////////////////////////////////////////////////////// 410 | 411 | /** 412 | * Method: getRXAddress() 413 | * @ Since v0.1.0 by Eric Burger, January 2014 414 | * @ Returns the source address of packet 415 | */ 416 | SimpleZigBeeAddress SimpleIncomingZigBeePacket::getRXAddress(){ 417 | return SimpleZigBeeAddress( getRXAddress64(), getRXAddress16() ); 418 | } 419 | 420 | /** 421 | * Method: getRXAddress64() 422 | * @ Since v0.1.0 by Eric Burger, January 2014 423 | * @ Returns the 64-bit source address of packet 424 | * @ There is a typo in Digi XBee S2 manual. No Frame ID for RX Packet 425 | * @ Cast bytes as 32-bit or 16-bit before bitshift left 426 | */ 427 | SimpleZigBeeAddress64 SimpleIncomingZigBeePacket::getRXAddress64(){ 428 | uint32_t msb = (uint32_t(getFrameData(1)) << 24) + (uint32_t(getFrameData(2)) << 16) + (uint16_t(getFrameData(3)) << 8) + getFrameData(4); 429 | uint32_t lsb = (uint32_t(getFrameData(5)) << 24) + (uint32_t(getFrameData(6)) << 16) + (uint16_t(getFrameData(7)) << 8) + getFrameData(8); 430 | return SimpleZigBeeAddress64( msb, lsb ); 431 | } 432 | 433 | /** 434 | * Method: getRXAddress16() 435 | * @ Since v0.1.0 by Eric Burger, January 2014 436 | * @ Returns the 16-bit source address of packet 437 | * @ Cast bytes as 16-bit before bitshift left 438 | */ 439 | SimpleZigBeeAddress16 SimpleIncomingZigBeePacket::getRXAddress16(){ 440 | uint16_t addr = (uint16_t(getFrameData(9)) << 8) + getFrameData(10); 441 | return SimpleZigBeeAddress16( addr ); 442 | } 443 | 444 | /** 445 | * Method: getRXOptions() 446 | * @ Since v0.1.0 by Eric Burger, January 2014 447 | * @ Returns value of packet receive option (Packet Index 14, Frame Index 11) 448 | */ 449 | uint8_t SimpleIncomingZigBeePacket::getRXOptions(){ 450 | return getFrameData(11); 451 | } 452 | /** 453 | * Method: getRXPayloadLength(int index) 454 | * @ Since v0.1.0 by Eric Burger, June 2014 455 | * @ Returns the payload length of the incoming packet. 456 | */ 457 | uint8_t SimpleIncomingZigBeePacket::getRXPayloadLength(){ 458 | return getFrameLength()-12; 459 | } 460 | /** 461 | * Method: getRXPayload(int index) 462 | * @ Since v0.1.0 by Eric Burger, January 2014 463 | * @ Returns the payload byte of the incoming packet at the specified index. 464 | * @ (Starting at Packet Index 15, Frame Index 12) 465 | * @ param int index: Index of payload data 466 | */ 467 | uint8_t SimpleIncomingZigBeePacket::getRXPayload(int index){ 468 | return getFrameData(index+12); 469 | } 470 | 471 | /*////////////////////////////////////////////////////////////////////// 472 | ZIGBEE TRANSMIT (TX) STATUS METHODS 473 | /*////////////////////////////////////////////////////////////////////// 474 | 475 | /** 476 | * Method: getTXStatusAddress16() 477 | * @ Since v0.1.0 by Eric Burger, January 2014 478 | * @ Returns the 16-bit source address of packet (destination of TX request) 479 | * @ Cast bytes as 16-bit before bitshift left 480 | */ 481 | SimpleZigBeeAddress16 SimpleIncomingZigBeePacket::getTXStatusAddress16(){ 482 | uint16_t addr = (uint16_t(getFrameData(9)) << 2) + getFrameData(3); 483 | return SimpleZigBeeAddress16( addr ); 484 | } 485 | 486 | /** 487 | * Method: getTXStatusRetryCount() 488 | * @ Since v0.1.0 by Eric Burger, April 2014 489 | * @ Returns value of retry count (Packet Index 7, Frame Index 4) 490 | */ 491 | uint8_t SimpleIncomingZigBeePacket::getTXStatusRetryCount(){ 492 | return getFrameData(4); 493 | } 494 | 495 | /** 496 | * Method: getTXStatusDeliveryStatus() 497 | * @ Since v0.1.0 by Eric Burger, April 2014 498 | * @ Returns value of packet delivery status (Packet Index 8, Frame Index 5) 499 | */ 500 | uint8_t SimpleIncomingZigBeePacket::getTXStatusDeliveryStatus(){ 501 | return getFrameData(5); 502 | } 503 | 504 | /** 505 | * Method: getTXStatusDiscoveryStatus() 506 | * @ Since v0.1.0 by Eric Burger, April 2014 507 | * @ Returns value of packet discovery status (Packet Index 9, Frame Index 6) 508 | */ 509 | uint8_t SimpleIncomingZigBeePacket::getTXStatusDiscoveryStatus(){ 510 | return getFrameData(6); 511 | } 512 | 513 | /*////////////////////////////////////////////////////////////////////// 514 | AT COMMAND RESPONSE METHODS 515 | /*////////////////////////////////////////////////////////////////////// 516 | 517 | /** 518 | * Method: getATResponseCommand() 519 | * @ Since v0.1.0 by Eric Burger, January 2014 520 | * @ Returns AT Command of packet (Packet index 5 and 6, Frame Index 2 and 3) 521 | */ 522 | uint16_t SimpleIncomingZigBeePacket::getATResponseCommand(){ 523 | return uint16_t( getFrameData(2) << 8 ) + getFrameData(3) ; 524 | } 525 | 526 | /** 527 | * Method: getATResponseStatus() 528 | * @ Since v0.1.0 by Eric Burger, January 2014 529 | * @ Returns AT Command Status (Packet index 7, Frame Index 4) 530 | */ 531 | uint8_t SimpleIncomingZigBeePacket::getATResponseStatus(){ 532 | return getFrameData(4) ; 533 | } 534 | 535 | /** 536 | * Method: getATResponsePayloadLength() 537 | * @ Since v0.1.0 by Eric Burger, June 2014 538 | * @ Returns AT Command Data Length 539 | */ 540 | uint8_t SimpleIncomingZigBeePacket::getATResponsePayloadLength(){ 541 | return getFrameLength()-5; 542 | } 543 | 544 | /** 545 | * Method: getATResponsePayload() 546 | * @ Since v0.1.0 by Eric Burger, January 2014 547 | * @ Returns AT Command Data (Packet index 8, Frame Index 5) 548 | */ 549 | uint8_t SimpleIncomingZigBeePacket::getATResponsePayload(){ 550 | return getFrameData(5); 551 | } 552 | 553 | /** 554 | * Method: getATResponsePayload(int index) 555 | * @ Since v0.1.0 by Eric Burger, January 2014 556 | * @ Returns AT Command Data (Starting at Packet index 8, Frame Index 5) 557 | * @ param int index: Index of command data 558 | */ 559 | uint8_t SimpleIncomingZigBeePacket::getATResponsePayload(int index){ 560 | return getFrameData(index+5); 561 | } 562 | 563 | /*////////////////////////////////////////////////////////////////////// 564 | REMOTE AT COMMAND RESPONSE METHODS 565 | /*////////////////////////////////////////////////////////////////////// 566 | 567 | /** 568 | * Method: getRemoteATResponseAddress() 569 | * @ Since v0.1.0 by Eric Burger, July 2014 570 | * @ Returns the source (remote) address of packet 571 | */ 572 | SimpleZigBeeAddress SimpleIncomingZigBeePacket::getRemoteATResponseAddress(){ 573 | return SimpleZigBeeAddress( getRemoteATResponseAddress64(), getRemoteATResponseAddress16() ); 574 | } 575 | 576 | /** 577 | * Method: getRemoteATResponseAddress64() 578 | * @ Since v0.1.0 by Eric Burger, July 2014 579 | * @ Returns the 64-bit source (remote) address of packet 580 | */ 581 | SimpleZigBeeAddress64 SimpleIncomingZigBeePacket::getRemoteATResponseAddress64(){ 582 | uint32_t msb = (uint32_t(getFrameData(2)) << 24) + (uint32_t(getFrameData(3)) << 16) + (uint16_t(getFrameData(4)) << 8) + getFrameData(5); 583 | uint32_t lsb = (uint32_t(getFrameData(6)) << 24) + (uint32_t(getFrameData(7)) << 16) + (uint16_t(getFrameData(8)) << 8) + getFrameData(9); 584 | return SimpleZigBeeAddress64( msb, lsb ); 585 | } 586 | 587 | /** 588 | * Method: getRemoteATResponseAddress16() 589 | * @ Since v0.1.0 by Eric Burger, July 2014 590 | * @ Returns the 16-bit source (remote) address of packet 591 | */ 592 | SimpleZigBeeAddress16 SimpleIncomingZigBeePacket::getRemoteATResponseAddress16(){ 593 | uint16_t addr = (uint16_t(getFrameData(10)) << 8) + getFrameData(11); 594 | return SimpleZigBeeAddress16( addr ); 595 | } 596 | 597 | /** 598 | * Method: getRemoteATResponseCommand() 599 | * @ Since v0.1.0 by Eric Burger, July 2014 600 | * @ Returns Remote AT Command of packet (Packet index 15 and 16, Frame Index 12 and 13) 601 | */ 602 | uint16_t SimpleIncomingZigBeePacket::getRemoteATResponseCommand(){ 603 | return uint16_t( getFrameData(12) << 8 ) + getFrameData(13) ; 604 | } 605 | 606 | /** 607 | * Method: getRemoteATResponseStatus() 608 | * @ Since v0.1.0 by Eric Burger, July 2014 609 | * @ Returns Remote AT Command Status (Packet index 17, Frame Index 14) 610 | */ 611 | uint8_t SimpleIncomingZigBeePacket::getRemoteATResponseStatus(){ 612 | return getFrameData(14) ; 613 | } 614 | 615 | /** 616 | * Method: getRemoteATResponsePayloadLength() 617 | * @ Since v0.1.0 by Eric Burger, July 2014 618 | * @ Returns Remote AT Command Data Length 619 | */ 620 | uint8_t SimpleIncomingZigBeePacket::getRemoteATResponsePayloadLength(){ 621 | return getFrameLength()-15; 622 | } 623 | 624 | /** 625 | * Method: getRemoteATResponsePayload() 626 | * @ Since v0.1.0 by Eric Burger, July 2014 627 | * @ Returns Remote AT Command Data (Packet index 18, Frame Index 15) 628 | */ 629 | uint8_t SimpleIncomingZigBeePacket::getRemoteATResponsePayload(){ 630 | return getFrameData(15); 631 | } 632 | 633 | /** 634 | * Method: getRemoteATResponsePayload(int index) 635 | * @ Since v0.1.0 by Eric Burger, July 2014 636 | * @ Returns Remote AT Command Data (Starting at Packet index 18, Frame Index 15) 637 | * @ param int index: Index of command data 638 | */ 639 | uint8_t SimpleIncomingZigBeePacket::getRemoteATResponsePayload(int index){ 640 | return getFrameData(index+15); 641 | } 642 | 643 | /*////////////////////////////////////////////////////////////////////// 644 | Modem Status Methods 645 | /*////////////////////////////////////////////////////////////////////// 646 | 647 | /** 648 | * Method: getModemStatus() 649 | * @ Since v0.1.0 by Eric Burger, April 2014 650 | * @ Returns value of packet modem status (Packet Index 4, Frame Index 1) 651 | */ 652 | uint8_t SimpleIncomingZigBeePacket::getModemStatus(){ 653 | return getFrameData(1); 654 | } 655 | 656 | /*////////////////////////////////////////////////////////////////////// 657 | //////////////////////////////////////////////////////////////////////// 658 | SimpleOutgoingZigBeePacket Class 659 | //////////////////////////////////////////////////////////////////////// 660 | /*////////////////////////////////////////////////////////////////////// 661 | 662 | /*////////////////////////////////////////////////////////////////////// 663 | INITIALIZATION METHODS 664 | /*////////////////////////////////////////////////////////////////////// 665 | 666 | /** 667 | * Constructor: SimpleOutgoingZigBeePacket() 668 | * @ Since v0.1.0 by Eric Burger, August 2013 669 | * @ Default constructor that creates packet object for outgoing packets. 670 | */ 671 | SimpleOutgoingZigBeePacket::SimpleOutgoingZigBeePacket() : SimpleZigBeePacket(){ 672 | SimpleZigBeePacket::init(); 673 | } 674 | 675 | /** 676 | * Constructor: SimpleZigBeeRadio() 677 | * @ Since v0.1.0 by Eric Burger, August 2013 678 | * @ Constructor with inputs that creates packet object for outgoing packets. 679 | * @ param int maxFrameLength: Limit (# of bytes) on packet frame size 680 | */ 681 | SimpleOutgoingZigBeePacket::SimpleOutgoingZigBeePacket(int maxFrameLength) : SimpleZigBeePacket(maxFrameLength) { 682 | SimpleZigBeePacket::init(); 683 | } 684 | 685 | /*////////////////////////////////////////////////////////////////////// 686 | GENERAL PACKET METHODS 687 | /*////////////////////////////////////////////////////////////////////// 688 | 689 | /** 690 | * Method: setFrameType(uint8_t frameType) 691 | * @ Since v0.1.0 by Eric Burger, August 2013 692 | * @ Sets Frame Type (Packet Index 3, Frame Index 0). Method does not check if 693 | * @ input is a valid ZigBee frame type. 694 | * @ param uint8_t frameType: Frame type value to store 695 | */ 696 | void SimpleOutgoingZigBeePacket::setFrameType(uint8_t frameType){ 697 | setFrameData(0,frameType); 698 | } 699 | 700 | /** 701 | * Method: setFrameID(uint8_t id) 702 | * @ Since v0.1.0 by Eric Burger, August 2013 703 | * @ Sets frame ID (Packet index 4, Frame Index 1). If zero, no response or status will be sent. 704 | * @ param uint8_t id: Frame ID value to store 705 | */ 706 | void SimpleOutgoingZigBeePacket::setFrameID(uint8_t id){ 707 | setFrameData(1, id); 708 | } 709 | 710 | /** 711 | * Method: setAddress(SimpleZigBeeAddress address) 712 | * @ Since v0.1.0 by Eric Burger, August 2013 713 | * @ Set the 64-bit and 16-bit destination addresses 714 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 715 | */ 716 | void SimpleOutgoingZigBeePacket::setAddress(SimpleZigBeeAddress address){ 717 | SimpleZigBeeAddress64 adr64 = address.getAddress64(); 718 | SimpleZigBeeAddress16 adr16 = address.getAddress16(); 719 | setAddress64( adr64.getAddressMSB(), adr64.getAddressLSB() ); 720 | setAddress16( adr16.getAddress() ); 721 | } 722 | 723 | /** 724 | * Method: setAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16) 725 | * @ Since v0.1.0 by Eric Burger, August 2013 726 | * @ Set the 64-bit and 16-bit destination addresses 727 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 728 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 729 | * @ param uint16_t adr16: 16-bit destination address 730 | */ 731 | void SimpleOutgoingZigBeePacket::setAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16){ 732 | setAddress64( adr64MSB, adr64LSB ); 733 | setAddress16( adr16 ); 734 | } 735 | 736 | /** 737 | * Method: setAddress64(uint32_t adr64MSB, uint32_t adr64LSB) 738 | * @ Since v0.1.0 by Eric Burger, August 2013 739 | * @ Set the 64-bit destination address (Packet Index 5 to 12, Frame Index 2 to 9) 740 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 741 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 742 | */ 743 | void SimpleOutgoingZigBeePacket::setAddress64(uint32_t adr64MSB, uint32_t adr64LSB){ 744 | uint8_t startIndex = 2; // Frame data index marking start of 64-bit address. 745 | for(uint8_t i=0;i<4;i++){ 746 | uint8_t by = (8*(3-i)); 747 | uint8_t byte1 = (adr64MSB >> by) & 0xff; 748 | uint8_t byte2 = (adr64LSB >> by) & 0xff; 749 | setFrameData( startIndex+i, byte1); 750 | setFrameData( startIndex+i+4, byte2); 751 | } 752 | } 753 | 754 | /** 755 | * Method: setAddress16(uint16_t adr16) 756 | * @ Since v0.1.0 by Eric Burger, August 2013 757 | * @ Set the 16-bit destination address. (Packet Index 13 and 14, Frame Index 10 and 11) 758 | * @ param uint16_t adr16: 16-bit destination address 759 | */ 760 | void SimpleOutgoingZigBeePacket::setAddress16(uint16_t adr16){ 761 | setFrameData( 10, ((adr16 >> 8) & 0xff) ); 762 | setFrameData( 11, (adr16 & 0xff) ); 763 | } 764 | 765 | /*////////////////////////////////////////////////////////////////////// 766 | ZIGBEE TRANSMIT (TX) REQUEST METHODS 767 | /*////////////////////////////////////////////////////////////////////// 768 | 769 | /** 770 | * Method: setTXRequestBroadcastRadius(uint8_t rad) 771 | * @ Since v0.1.0 by Eric Burger, August 2013 772 | * @ Set broadcast radius. (Packet Index 15, Frame Index 12) 773 | * @ param uint8_t rad: Maximum radius (# of hops) of packets, 0 for no limit 774 | */ 775 | void SimpleOutgoingZigBeePacket::setTXRequestBroadcastRadius(uint8_t rad){ 776 | setFrameData( 12, rad ); 777 | } 778 | 779 | /** 780 | * Method: setTXRequestOption(uint8_t opt) 781 | * @ Since v0.1.0 by Eric Burger, August 2013 782 | * @ Set frame option. (Packet Index 16, Frame Index 13) 783 | * @ param uint8_t opt: Option value to set 784 | */ 785 | void SimpleOutgoingZigBeePacket::setTXRequestOption(uint8_t opt){ 786 | setFrameData( 13, opt ); 787 | } 788 | 789 | /** 790 | * Method: setTXRequestPayload(uint8_t* payload, int payloadSize) 791 | * @ Since v0.1.0 by Eric Burger, August 2013 792 | * @ Store payload array. (Start Packet Index 17, Frame Index 14) 793 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 794 | * @ param int payloadSize: Length of payload array 795 | */ 796 | void SimpleOutgoingZigBeePacket::setTXRequestPayload(uint8_t* payload, int payloadSize){ 797 | setFrameData( 14, payload, payloadSize ); 798 | } 799 | 800 | /*////////////////////////////////////////////////////////////////////// 801 | AT COMMAND METHODS 802 | /*////////////////////////////////////////////////////////////////////// 803 | 804 | /** 805 | * Method: setATCommand(uint16_t command) 806 | * @ Since v0.1.0 by Eric Burger, April 2014 807 | * @ Store AT command. (Start Packet Index 5, Frame Index 2) 808 | * @ param uint16_t command: 16-bit AT Command 809 | */ 810 | void SimpleOutgoingZigBeePacket::setATCommand(uint16_t command){ 811 | setFrameData( 2, ((command >> 8) & 0xff) ); 812 | setFrameData( 3, (command & 0xff) ); 813 | } 814 | 815 | /** 816 | * Method: setATCommandPayload(uint8_t payload) 817 | * @ Since v0.1.0 by Eric Burger, July 2014 818 | * @ Store AT command parameter. (Start Packet Index 7, Frame Index 4) 819 | * @ param uint8_t payload: Byte containing payload 820 | */ 821 | void SimpleOutgoingZigBeePacket::setATCommandPayload(uint8_t payload){ 822 | setFrameData( 4, payload ); 823 | } 824 | 825 | /** 826 | * Method: setATCommandPayload(uint8_t* payload, int payloadSize) 827 | * @ Since v0.1.0 by Eric Burger, July 2014 828 | * @ Store AT command parameter. (Start Packet Index 7, Frame Index 4) 829 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 830 | * @ param int payloadSize: Length of payload array 831 | */ 832 | void SimpleOutgoingZigBeePacket::setATCommandPayload(uint8_t* payload, int payloadSize){ 833 | setFrameData( 4, payload, payloadSize ); 834 | } 835 | 836 | /*////////////////////////////////////////////////////////////////////// 837 | REMOTE AT COMMAND METHODS 838 | /*////////////////////////////////////////////////////////////////////// 839 | /** 840 | * Method: setRemoteATCommandOption(uint8_t opt) 841 | * @ Since v0.1.0 by Eric Burger, July 2014 842 | * @ Set remote command option. (Packet Index 15, Frame Index 12) 843 | * @ param uint8_t opt: Option value to set 844 | */ 845 | void SimpleOutgoingZigBeePacket::setRemoteATCommandOption(uint8_t opt){ 846 | setFrameData( 12, opt ); 847 | } 848 | /** 849 | * Method: setRemoteATCommand(uint16_t command) 850 | * @ Since v0.1.0 by Eric Burger, April 2014 851 | * @ Store Remote AT command. (Start Packet Index 16, Frame Index 13) 852 | * @ param uint16_t command: 16-bit AT Command 853 | */ 854 | void SimpleOutgoingZigBeePacket::setRemoteATCommand(uint16_t command){ 855 | setFrameData( 13, ((command >> 8) & 0xff) ); 856 | setFrameData( 14, (command & 0xff) ); 857 | } 858 | 859 | /** 860 | * Method: setRemoteATCommandPayload(uint8_t payload) 861 | * @ Since v0.1.0 by Eric Burger, July 2014 862 | * @ Store AT command parameter. (Start Packet Index 18, Frame Index 15) 863 | * @ param uint8_t payload: Byte containing payload 864 | */ 865 | void SimpleOutgoingZigBeePacket::setRemoteATCommandPayload(uint8_t payload){ 866 | setFrameData( 15, payload ); 867 | } 868 | 869 | /** 870 | * Method: setRemoteATCommandPayload(uint8_t* payload, int payloadSize) 871 | * @ Since v0.1.0 by Eric Burger, July 2014 872 | * @ Store AT command parameter. (Start Packet Index 18, Frame Index 15) 873 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 874 | * @ param int payloadSize: Length of payload array 875 | */ 876 | void SimpleOutgoingZigBeePacket::setRemoteATCommandPayload(uint8_t* payload, int payloadSize){ 877 | setFrameData( 15, payload, payloadSize ); 878 | } 879 | 880 | -------------------------------------------------------------------------------- /SimpleZigBeePacket.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Library Name: SimpleZigBeePacket 3 | * Library URI: https://github.com/ericburger/simple-zigbee 4 | * Description: Classes for managing ZigBee packets that are sent or received 5 | * by the connected radio. 6 | * Version: 0.1.1 7 | * Author(s): Eric Burger 8 | * Author URI: WallflowerOpen.com 9 | * License: GNU General Public License v2.0 or later 10 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html 11 | * 12 | * Copyright (c) 2013 Eric Burger. All rights reserved. 13 | * 14 | * This file is part of SimpleZigBee, written for XBee S2 Radios. 15 | * 16 | * SimpleZigBee is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published by 18 | * the Free Software Foundation, either version 2 of the License, or 19 | * (at your option) any later version. 20 | * 21 | * SimpleZigBee is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with SimpleZigBee. If not, see . 28 | */ 29 | 30 | #ifndef SimpleZigBeePacket_h 31 | #define SimpleZigBeePacket_h 32 | 33 | #include "Arduino.h" 34 | #include "SimpleZigBeeAddress.h" 35 | // Required for uint8_t type 36 | #include 37 | 38 | // Start Frame Delimiter 39 | #define START 0x7e 40 | // Escape Byte 41 | #define ESCAPE 0x7d 42 | // Software Flow Control Characters to be Escaped 43 | #define XON 0x11 44 | #define XOFF 0x13 45 | 46 | // Error Codes 47 | #define NO_ERROR 0 48 | #define ERROR_REALLOCATING_MEMORY 1 49 | // "Unexpected start of a new packet". Only applies to radios in escaped API Mode. 50 | #define UNEXPECTED_PACKET_START 2 51 | #define PACKET_INCOMPLETE 3 52 | #define MAX_FRAME_LENGTH_EXCEEDED 4 53 | #define FRAME_LENGTH_EXCEEDED 5 54 | #define CHECKSUM_FAILURE 6 55 | 56 | // Frame Indexes 57 | #define MSB_INDEX 1 58 | #define LSB_INDEX 2 59 | #define FRAME_TYPE_INDEX 3 60 | #define FRAME_ID_INDEX 4 61 | #define AT_COMMAND_INDEX_START 5 62 | #define AT_COMMAND_INDEX_END 6 63 | #define AT_RESPONSE_COMMAND_STATUS_INDEX 7 64 | #define ZIGBEE_TX_REQUEST_64_ADDR_START 5 65 | #define ZIGBEE_TX_REQUEST_64_ADDR_END 12 66 | #define ZIGBEE_TX_REQUEST_16_ADDR_START 13 67 | #define ZIGBEE_TX_REQUEST_16_ADDR_END 14 68 | #define ZIGBEE_TX_REQUEST_RADIUS 15 69 | #define ZIGBEE_TX_REQUEST_OPTIONS 16 70 | 71 | /** 72 | * List of API Frame Types 73 | * (not fully implemented) 74 | */ 75 | #define AT_COMMAND 0x08 // # 76 | #define AT_COMMAND_QUEUED 0x09 77 | #define ZIGBEE_TRANSMIT_REQUEST 0x10 // # 78 | #define ZIGBEE_EXPLICIT_ADDRESSING_COMMAND_FRAME 0x11 79 | #define REMOTE_AT_COMMAND 0x17 // # 80 | #define AT_COMMAND_RESPONSE 0x88 // # 81 | #define MODEM_STATUS 0x8a // # 82 | #define ZIGBEE_TX_STATUS 0x8b // # 83 | #define ZIGBEE_RECIEVED_PACKET 0x90 // # 84 | #define ZIGBEE_EXPLICIT_RX_INDICATOR 0x91 85 | #define ZIGBEE_IO_RX_INDICATOR 0x92 86 | #define NODE_INDENTIFICATION_INDICATOR 0x95 87 | #define REMOTE_AT_COMMAND_RESPONSE 0x97 // # 88 | 89 | // AT COMMANDS, 0x08 90 | // REMOTE AT COMMANDS, 0x17 (INCOMPLETE LIST) 91 | 92 | // AT COMMAND RESPONSE STATUS, 0x88 93 | // REMOTE AT COMMAND RESPONSE STATUS, 0x97 94 | #define AT_COMMAND_STATUS_OK 0x00 95 | #define AT_COMMAND_STATUS_ERROR 0x01 96 | #define AT_COMMAND_STATUS_INVALID_COMMAND 0x02 97 | #define AT_COMMAND_STATUS_INVALID_PARAMETER 0x03 98 | #define AT_COMMAND_STATUS_TX_FAILURE 0x04 99 | 100 | // ZigBee Modem Status, 0x8a (INCOMPLETE LIST) 101 | #define MODEM_STATUS_HARDWARE_RESET 0x00 102 | #define MODEM_STATUS_WATCHDOG_TIMER_RESET 0x01 103 | #define MODEM_STATUS_JOINED_NETWORK 0x02 104 | #define MODEM_STATUS_DISASSOCIATED 0x03 105 | #define MODEM_STATUS_COORDINATOR_STARTED 0x06 106 | 107 | // ZigBee Transmit Status, 0x8b (INCOMPLETE LIST) 108 | #define TRANSMIT_STATUS_SUCCESS 0x00 109 | #define TRANSMIT_STATUS_MAC_ACK_FAILURE 0x01 110 | #define TRANSMIT_STATUS_CCA_FAILURE 0x02 111 | #define TRANSMIT_STATUS_INVALID_DEST_ENDPOINT 0x15 112 | #define TRANSMIT_STATUS_NETWORK_ACK_FAILURE 0x21 113 | #define TRANSMIT_STATUS_NOT_JOINED_TO_NETWORK 0x22 114 | #define TRANSMIT_STATUS_SELF_ADDRESSED 0x23 115 | #define TRANSMIT_STATUS_ADDRESS_NOT_FOUND 0x24 116 | #define TRANSMIT_STATUS_ROUTE_NOT_FOUND 0x25 117 | #define TRANSMIT_STATUS_PAYLOAD_TOO_LARGE 0x74 118 | 119 | 120 | 121 | /** 122 | * Class: SimpleZigBeePacket 123 | * @ Since v0.1.0 by Eric Burger, August 2013 124 | * @ Object for incoming and outgoing packets. 125 | */ 126 | class SimpleZigBeePacket { 127 | public: 128 | // INITIALIZATION METHODS // 129 | SimpleZigBeePacket(); 130 | SimpleZigBeePacket(int maxFrameLength); 131 | void init(); 132 | void reset(); 133 | 134 | // MEMORY METHODS // 135 | void expandMemoryArray(int size); 136 | uint8_t getMemoryData(int index); 137 | void setMemoryData(int index, uint8_t byte); 138 | 139 | // PACKET PRIVATE VARIABLE METHODS // 140 | int getFrameLength(); 141 | uint8_t getLengthMSB(); 142 | uint8_t getLengthLSB(); 143 | void setFrameLength(int frameLength); 144 | void setFrameLengthMSB(uint8_t msb); 145 | void setFrameLengthLSB(uint8_t lsb); 146 | 147 | uint8_t getFrameType(); 148 | uint8_t getFrameID(); 149 | uint8_t getChecksum(); 150 | uint8_t calculateChecksum(); 151 | void setChecksum(uint8_t checksum); 152 | 153 | // PACKET FRAME METHODS // 154 | int getMaxFrameLength(); 155 | void setFrameData(int index, uint8_t byte); 156 | void setFrameData(int startIndex, uint8_t* frameData, int frameDataLength); 157 | uint8_t getFrameData(int index); 158 | void getFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength); 159 | 160 | // ERROR CODE METHODS // 161 | bool isError(); 162 | int getErrorCode(); 163 | void setErrorCode(int errorCode); 164 | 165 | private: 166 | // Current length of memory array 167 | int _memoryArrayLength; 168 | // Maximum length of packet frame (also defines maximum length of memory array). 169 | // Note that this does not define the maximum length of the packet, only the max number of bytes 170 | // between the LSB and checksum. For receiving packets, be aware that the Arduino serial buffer 171 | // is 64 bytes (http://arduino.cc/en/Serial/Available). For this reason, a frame limit around 50 bytes 172 | // is recommended. Incoming packets that exceed the _maxFrameLength will not be parsed. While it is 173 | // possible to receive packets larger than 64 bytes by reading from the serial port as bytes are being 174 | // received, failure to do so will result in incomplete packets. To support Arduino to Arduino 175 | // communication, the length of outgoing packets is also restricted by _maxFrameLength. 176 | int _maxFrameLength; 177 | // Memory array used to store frame data 178 | uint8_t *_ptrMemoryArray; 179 | 180 | // Packet checksum (End of packet) 181 | uint8_t _checksum; 182 | // Tracks frame length based on input data 183 | int _frameLength; 184 | // Error code 185 | int _errorCode; 186 | }; 187 | 188 | 189 | /** 190 | * Class: SimpleIncomingZigBeePacket 191 | * @ Since v0.1.0 by Eric Burger, August 2013 192 | * @ Object for incoming packets. 193 | */ 194 | class SimpleIncomingZigBeePacket : public SimpleZigBeePacket { 195 | public: 196 | // INITIALIZATION METHODS // 197 | SimpleIncomingZigBeePacket(); 198 | SimpleIncomingZigBeePacket(int maxFrameLength); 199 | 200 | // ZIGBEE RECIEVED (RX) PACKET METHODS // 201 | // No Frame ID 202 | SimpleZigBeeAddress getRXAddress(); 203 | SimpleZigBeeAddress64 getRXAddress64(); 204 | SimpleZigBeeAddress16 getRXAddress16(); 205 | uint8_t getRXOptions(); 206 | uint8_t getRXPayloadLength(); 207 | uint8_t getRXPayload(int index); 208 | 209 | // ZIGBEE TRANSMIT (TX) STATUS METHODS // 210 | // For Frame ID, use getFrameID() 211 | SimpleZigBeeAddress16 getTXStatusAddress16(); 212 | uint8_t getTXStatusRetryCount(); 213 | uint8_t getTXStatusDeliveryStatus(); 214 | uint8_t getTXStatusDiscoveryStatus(); 215 | 216 | // AT COMMAND RESPONSE METHODS // 217 | // For Frame ID, use getFrameID() 218 | uint16_t getATResponseCommand(); 219 | uint8_t getATResponseStatus(); 220 | uint8_t getATResponsePayloadLength(); 221 | uint8_t getATResponsePayload(); 222 | uint8_t getATResponsePayload(int index); 223 | 224 | // REMOTE AT COMMAND RESPONSE METHODS // 225 | // For Frame ID, use getFrameID() 226 | SimpleZigBeeAddress getRemoteATResponseAddress(); 227 | SimpleZigBeeAddress64 getRemoteATResponseAddress64(); 228 | SimpleZigBeeAddress16 getRemoteATResponseAddress16(); 229 | uint16_t getRemoteATResponseCommand(); 230 | uint8_t getRemoteATResponseStatus(); 231 | uint8_t getRemoteATResponsePayloadLength(); 232 | uint8_t getRemoteATResponsePayload(); 233 | uint8_t getRemoteATResponsePayload(int index); 234 | 235 | // MODEM STATUS METHODS // 236 | uint8_t getModemStatus(); 237 | }; 238 | 239 | 240 | /** 241 | * Class: SimpleZigBeePacket 242 | * @ Since v0.1.0 by Eric Burger, August 2013 243 | * @ Object for outgoing packets. 244 | */ 245 | class SimpleOutgoingZigBeePacket : public SimpleZigBeePacket { 246 | public: 247 | // INITIALIZATION METHODS // 248 | SimpleOutgoingZigBeePacket(); 249 | SimpleOutgoingZigBeePacket(int maxFrameLength); 250 | 251 | // GENERAL PACKET METHODS // 252 | void setFrameType(uint8_t frameType); 253 | void setFrameID(uint8_t id); 254 | void setAddress(SimpleZigBeeAddress address); 255 | void setAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16); 256 | void setAddress64(uint32_t adr64MSB, uint32_t adr64LSB); 257 | void setAddress16(uint16_t adr16); 258 | 259 | // ZIGBEE TRANSMIT (TX) REQUEST METHODS // 260 | // Use General Packet Methods for Frame Type, Frame ID, and Address 261 | void setTXRequestBroadcastRadius(uint8_t rad); 262 | void setTXRequestOption(uint8_t opt); 263 | void setTXRequestPayload(uint8_t* payload, int payloadSize); 264 | 265 | // AT COMMAND METHODS // 266 | // Use General Packet Methods for Frame Type and Frame ID 267 | void setATCommand(uint16_t command); 268 | void setATCommandPayload(uint8_t payload); // aka, parameter 269 | void setATCommandPayload(uint8_t* payload, int payloadSize); 270 | 271 | // REMOTE AT COMMAND METHODS // 272 | // Use General Packet Methods for Frame Type, Frame ID, and Address 273 | void setRemoteATCommandOption(uint8_t opt); 274 | void setRemoteATCommand(uint16_t command); 275 | void setRemoteATCommandPayload(uint8_t payload); 276 | void setRemoteATCommandPayload(uint8_t* payload, int payloadSize); 277 | 278 | }; 279 | 280 | 281 | #endif //SimpleZigBeePacket 282 | -------------------------------------------------------------------------------- /SimpleZigBeeRadio.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Eric Burger. All rights reserved. 3 | */ 4 | 5 | #include "SimpleZigBeeRadio.h" 6 | // For Stream class (serial port object) 7 | #include "HardwareSerial.h" 8 | 9 | /*////////////////////////////////////////////////////////////////////// 10 | //////////////////////////////////////////////////////////////////////// 11 | SimpleZigBeeRadio Class 12 | //////////////////////////////////////////////////////////////////////// 13 | /*////////////////////////////////////////////////////////////////////// 14 | 15 | /*////////////////////////////////////////////////////////////////////// 16 | INITIALIZATION METHODS 17 | /*////////////////////////////////////////////////////////////////////// 18 | 19 | /** 20 | * Constructor: SimpleZigBeeRadio() 21 | * @ Since v0.1.0 by Eric Burger, September 2013 22 | * @ Default constructor that creates packet object for incoming and outgoing packets. 23 | * @ By default, library assumes XBee is in Escaped API Mode (ATAP=2). 24 | */ 25 | SimpleZigBeeRadio::SimpleZigBeeRadio() { 26 | _incoming_packet = SimpleIncomingZigBeePacket(); 27 | _outgoing_packet = SimpleOutgoingZigBeePacket(); 28 | _escaped_mode = true; 29 | reset(); 30 | } 31 | 32 | 33 | /** 34 | * Constructor: SimpleZigBeeRadio(bool escaped_mode) 35 | * @ Since v0.1.0 by Eric Burger, September 2013 36 | * @ Constructor with parameter. Creates packet object for incoming and outgoing packets. 37 | * @ param bool escaped_mode: FALSE if API Mode (ATAP=1) and TRUE if Escaped API Mode (ATAP=2). 38 | */ 39 | SimpleZigBeeRadio::SimpleZigBeeRadio(bool escaped_mode) { 40 | _incoming_packet = SimpleIncomingZigBeePacket(); 41 | _outgoing_packet = SimpleOutgoingZigBeePacket(); 42 | _escaped_mode = escaped_mode; 43 | reset(); 44 | } 45 | 46 | /** 47 | * Method: reset() 48 | * @ Since v0.1.0 by Eric Burger, September 2013 49 | * @ Resets the radio's private parameters. 50 | */ 51 | void SimpleZigBeeRadio::reset(){ 52 | resetIncoming(); 53 | resetOutgoing(); 54 | _out_frame_id = 0; 55 | _out_acknowledgement = false; 56 | } 57 | 58 | /** 59 | * Method: resetIncoming() 60 | * @ Since v0.1.0 by Eric Burger, July 2014 61 | * @ Resets incoming packet and the radio's private parameters. 62 | */ 63 | void SimpleZigBeeRadio::resetIncoming(){ 64 | _incoming_packet.reset(); 65 | _in_complete = false; 66 | _in_escaping = false; 67 | _in_checksum = 0; 68 | _in_index = 0; 69 | } 70 | 71 | /** 72 | * Method: resetOutgoing() 73 | * @ Since v0.1.0 by Eric Burger, July 2014 74 | * @ Resets outgoing packet and the radio's private parameters. 75 | */ 76 | void SimpleZigBeeRadio::resetOutgoing(){ 77 | _outgoing_packet.reset(); 78 | } 79 | 80 | /** 81 | * Method: setSerial(HardwareSerial & serial) 82 | * @ Since v0.1.0 by Eric Burger, September 2013 83 | * @ Updated v0.1.1 by Eric Burger, April 2016 84 | * @ Set the pointer to the HardwareSerial object communicating with the XBee radio 85 | * @ param HardwareSerial& serial: Pointer to HardwareSerial object. 86 | */ 87 | void SimpleZigBeeRadio::setSerial(HardwareSerial & serial){ 88 | _serial = &serial; 89 | } 90 | 91 | /** 92 | * Method: setSerial(Stream & serial) 93 | * @ Since v0.1.0 by Eric Burger, September 2013 94 | * @ Updated v0.1.1 by Eric Burger, April 2016 95 | * @ For SoftwareSerial port, set the pointer to the Stream object 96 | * communicating with the XBee radio. 97 | * @ param Stream& serial: Pointer to Stream object. 98 | */ 99 | void SimpleZigBeeRadio::setSerial(Stream & serial){ 100 | _serial = &serial; 101 | } 102 | 103 | /*////////////////////////////////////////////////////////////////////// 104 | PACKET METHODS 105 | /*////////////////////////////////////////////////////////////////////// 106 | 107 | /** 108 | * Method: getIncomingPacketObject() 109 | * @ Since v0.1.0 by Eric Burger, September 2013 110 | * @ Returns the packet object for storing incoming packet 111 | */ 112 | SimpleIncomingZigBeePacket& SimpleZigBeeRadio::getIncomingPacketObject() { 113 | return _incoming_packet; 114 | } 115 | 116 | /** 117 | * Method: getOutgoingPacketObject() 118 | * @ Since v0.1.0 by Eric Burger, September 2013 119 | * @ Returns the packet object for storing outgoing packet 120 | */ 121 | SimpleOutgoingZigBeePacket& SimpleZigBeeRadio::getOutgoingPacketObject() { 122 | return _outgoing_packet; 123 | } 124 | 125 | /*////////////////////////////////////////////////////////////////////// 126 | INCOMING PACKET METHODS 127 | /*////////////////////////////////////////////////////////////////////// 128 | 129 | /** 130 | * Method: available() 131 | * @ Since v0.1.0 by Eric Burger, January 2014 132 | * @ Checks if bytes received by serial port and returns boolean 133 | */ 134 | bool SimpleZigBeeRadio::available(){ 135 | if( _serial->available() > 0 ){ 136 | return true; 137 | } 138 | return false; 139 | } 140 | 141 | /** 142 | * Method: read() 143 | * @ Since v0.1.0 by Eric Burger, September 2013 144 | * @ Reads incoming ZigBee packet from serial port and stores in packet object 145 | */ 146 | void SimpleZigBeeRadio::read(){ 147 | // Don't do anything if _serial not available 148 | if( _serial->available() ){ 149 | // Before receiving a new packet from the serial buffer, reset incoming packet object, if necessary 150 | if( _incoming_packet.isError() || isComplete() ){ 151 | // Store error code before resetting 152 | int err = _incoming_packet.getErrorCode(); 153 | // If the previous packet was completely received or contained an error, reset. 154 | resetIncoming(); 155 | // If error was caused by UNEXPECTED_PACKET_START, set current index to 1 since the START byte has already been read from the serial buffer. 156 | if( UNEXPECTED_PACKET_START == err ){ 157 | _in_index = 1; 158 | } 159 | } 160 | 161 | // Otherwise, if the previous packet was incomplete but free of errors, try and receive the rest of the packet. 162 | 163 | // Read from serial port, while bytes are available 164 | while( _serial->available() ){ 165 | _in_byte = _serial->read(); 166 | 167 | // First, check if XBee is in Escaped API Mode (ATAP=2) 168 | if ( true == _escaped_mode ) { 169 | // Next, check if a (non-escaped) start frame delimiter is found anywhere other than the start of the packet. 170 | if ( START == _in_byte && _in_index > 0 ) { 171 | // AN ERROR OCCURED 172 | // If found, it means that a new packet has started before the previous packet was completely received. 173 | // This may indicate a noisy environment or that the buffer overflowed when the previous packet was being 174 | // received by the XBee. 175 | // Set error message and return. If read() is called again, packet object will be reset but current index will be set to 1. 176 | _incoming_packet.setErrorCode( UNEXPECTED_PACKET_START ); 177 | return; 178 | } 179 | 180 | // If byte has been flagged as escaped, "un-escape" the byte using the "Excusive bitwise OR" operator (^) 181 | if ( true == isEscaping() ) { 182 | _in_byte = 0x20 ^ _in_byte; 183 | setEscaping(false); 184 | } 185 | 186 | // Check if current byte is escape byte. If true, this indicates that the next byte in the packet has been escaped. 187 | if ( _in_byte == ESCAPE && _in_index > 0 ) { 188 | // Try and read the next byte from the serial buffer, otherwise, note that next byte is escaped by 189 | // setting _escaping to true and continuing loop. 190 | if ( _serial->available() ) { 191 | _in_byte = _serial->read(); 192 | // "Un-escape" the byte using the "Excusive bitwise OR" operator (^) 193 | _in_byte = 0x20 ^ _in_byte; 194 | } else { 195 | setEscaping(true); 196 | // Jump to the start of the while loop and re-check the condition (maybe buffer will be ready). 197 | continue; 198 | } 199 | } 200 | 201 | } 202 | // Note that if the XBee is not in Escaped API Mode (ATAP=2) and the start delimiter is found in a position other than the beginning of a packet, 203 | // it is not treated as the start of a packet. In this case, it is treated as just another byte. This can lead to trouble when radios 204 | // are placed in a noisy environment. 205 | // For reference: http://www.digi.com/support/kbase/kbaseresultdetl?id=2199 206 | 207 | // All bytes starting with the Frame Type are included in the checksum 208 | if ( _in_index >= FRAME_TYPE_INDEX ) { 209 | _in_checksum += _in_byte; 210 | } 211 | 212 | // Start storing incoming information in _incoming_packet object 213 | if ( 0 == _in_index ){ 214 | if ( START == _in_byte ) { 215 | // There is nothing to do with the start byte, so move unto the next position. 216 | _in_index++; 217 | }else{ 218 | // AN ERROR OCCURED 219 | // If START byte was not found, set error code indicating that packet was not read correctly 220 | _incoming_packet.setErrorCode( PACKET_INCOMPLETE ); 221 | } 222 | }else if( 1 == _in_index ){ 223 | // Store "Most Significant Byte" of packet's length 224 | _incoming_packet.setFrameLengthMSB(_in_byte); 225 | _in_index++; 226 | }else if( 2 == _in_index ){ 227 | // Store "Least Significant Byte" of packet's length 228 | _incoming_packet.setFrameLengthLSB(_in_byte); 229 | _in_index++; 230 | }else{ 231 | // For the remaining bytes in the packet, check that the maximum frame length has not been exceeded... 232 | if ( _in_index > _incoming_packet.getMaxFrameLength() ) { 233 | // AN ERROR OCCURED 234 | _incoming_packet.setErrorCode( MAX_FRAME_LENGTH_EXCEEDED ); 235 | return; 236 | } 237 | // ...Then check if the end of the packet has been reached (which should be the checksum). 238 | // Note: When setFrameLengthLSB() was last called, the frame length of the incoming packet was updated 239 | // based on the MSB and LSB. Therefore, the frame length should not have increased due to calls to 240 | // setOutgoingFrameData(). 241 | // This length does not include the start byte, MSB, LSB, or checksum byte. Therefore, the length 242 | // plus 3 should be the position of the checksum (i.e. frame length plus 4 minus 1). 243 | if ( (_incoming_packet.getFrameLength() + 3) == _in_index ) { 244 | // Verify checksum using the bitwise AND operator (&) 245 | if ( 0xff == (_in_checksum & 0xff) ) { 246 | // Success!!! The packet was completely received and the checksum verified. 247 | setComplete(true); 248 | _incoming_packet.setChecksum(_in_checksum); 249 | _incoming_packet.setErrorCode( NO_ERROR ); 250 | }else{ 251 | // Failure!!! The packet is not usable because the checksum failed. 252 | // AN ERROR OCCURED 253 | _incoming_packet.setErrorCode( CHECKSUM_FAILURE ); 254 | return; 255 | } 256 | 257 | 258 | // TODO: Process packet? 259 | 260 | 261 | return; 262 | } 263 | 264 | // Otherwise, beginning with Packet index 3 (Frame index 0), store byte is FrameData array. 265 | // Frame index 0 should contain the Frame Type 266 | _incoming_packet.setFrameData( (_in_index - FRAME_TYPE_INDEX) , _in_byte); 267 | _in_index++; 268 | } 269 | } 270 | } 271 | } 272 | 273 | /** 274 | * Method: isEscaping() 275 | * @ Since v0.1.0 by Eric Burger, January 2014 276 | * @ Checks if next byte of incoming packet should be escaped 277 | */ 278 | bool SimpleZigBeeRadio::isEscaping(){ 279 | return _in_escaping; 280 | } 281 | 282 | /** 283 | * Method: setEscaping(bool escape) 284 | * @ Since v0.1.0 by Eric Burger, August 2013 285 | * @ Sets boolean indicating if next byte of incoming packet should be escaped 286 | * @ param bool escape: Boolean value to store 287 | */ 288 | void SimpleZigBeeRadio::setEscaping(bool escape){ 289 | _in_escaping = escape; 290 | } 291 | 292 | /** 293 | * Method: isComplete() 294 | * @ Since v0.1.0 by Eric Burger, January 2014 295 | * @ Checks if incoming packet is complete and returns boolean 296 | */ 297 | bool SimpleZigBeeRadio::isComplete(){ 298 | return _in_complete; 299 | } 300 | 301 | /** 302 | * Method: setComplete(bool complete) 303 | * @ Since v0.1.0 by Eric Burger, August 2013 304 | * @ Sets boolean indicating if incoming packet is complete 305 | * @ param bool complete: Boolean value to store 306 | */ 307 | void SimpleZigBeeRadio::setComplete(bool complete){ 308 | _in_complete = complete; 309 | } 310 | 311 | /** 312 | * Method: getIncomingFrameType() 313 | * @ Since v0.1.0 by Eric Burger, September 2013 314 | * @ Returns frame type for incoming packets 315 | */ 316 | uint8_t SimpleZigBeeRadio::getIncomingFrameType(){ 317 | return _incoming_packet.getFrameType(); 318 | } 319 | 320 | /** 321 | * Method: getIncomingFrameID() 322 | * @ Since v0.1.0 by Eric Burger, September 2013 323 | * @ Returns frame ID for incoming packets 324 | */ 325 | uint8_t SimpleZigBeeRadio::getIncomingFrameID(){ 326 | return _incoming_packet.getFrameID(); 327 | } 328 | 329 | /** 330 | * Method: getIncomingFrameData(int index) 331 | * @ Since v0.1.0 by Eric Burger, September 2013 332 | * @ Returns the frame byte of the incoming packet at the specified index 333 | * @ param int index: Index of frame data 334 | */ 335 | uint8_t SimpleZigBeeRadio::getIncomingFrameData(int index){ 336 | return _incoming_packet.getFrameData(index); 337 | } 338 | 339 | /** 340 | * Method: getIncomingFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength) 341 | * @ Since v0.1.0 by Eric Burger, September 2013 342 | * @ Places an array of bytes from the memory array of the incoming packet in the 343 | * provided array pointer, starting from specified start index. 344 | * @ param int startIndex: Index of frame data at which to start 345 | * @ param uint8_t* arrayPtr: Array for storing bytes 346 | * @ param int frameDataLength: Number of byte to return 347 | */ 348 | void SimpleZigBeeRadio::getIncomingFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength){ 349 | return _incoming_packet.getFrameData(startIndex,arrayPtr,frameDataLength); 350 | } 351 | 352 | /*////////////////////////////////////////////////////////////////////// 353 | ZIGBEE RECIEVED PACKET METHODS 354 | /*////////////////////////////////////////////////////////////////////// 355 | 356 | /** 357 | * Method: isRX() 358 | * @ Since v0.1.0 by Eric Burger, January 2014 359 | * @ Checks if received packet is a RX packet and returns boolean 360 | */ 361 | bool SimpleZigBeeRadio::isRX(){ 362 | if( getIncomingFrameType() == ZIGBEE_RECIEVED_PACKET ){ 363 | return true; 364 | } 365 | return false; 366 | } 367 | 368 | /** 369 | * Method: getRXAddress() 370 | * @ Since v0.1.0 by Eric Burger, January 2014 371 | * @ Returns the source address of incoming packet 372 | */ 373 | SimpleZigBeeAddress SimpleZigBeeRadio::getRXAddress(){ 374 | return _incoming_packet.getRXAddress(); 375 | } 376 | 377 | /** 378 | * Method: getRXAddress64() 379 | * @ Since v0.1.0 by Eric Burger, June 2014 380 | * @ Returns the 64-bit source address of incoming packet 381 | */ 382 | SimpleZigBeeAddress64 SimpleZigBeeRadio::getRXAddress64(){ 383 | return _incoming_packet.getRXAddress64(); 384 | } 385 | 386 | /** 387 | * Method: getRXAddress16() 388 | * @ Since v0.1.0 by Eric Burger, June 2014 389 | * @ Returns the 16-bit source address of incoming packet 390 | */ 391 | SimpleZigBeeAddress16 SimpleZigBeeRadio::getRXAddress16(){ 392 | return _incoming_packet.getRXAddress16(); 393 | } 394 | 395 | /** 396 | * Method: getRXOptions() 397 | * @ Since v0.1.0 by Eric Burger, June 2014 398 | * @ Returns the options byte incoming packet 399 | */ 400 | uint8_t SimpleZigBeeRadio::getRXOptions(){ 401 | return _incoming_packet.getRXOptions(); 402 | } 403 | 404 | /** 405 | * Method: getRXPayloadLength() 406 | * @ Since v0.1.0 by Eric Burger, June 2014 407 | * @ Returns the payload length of the incoming packet. 408 | */ 409 | uint8_t SimpleZigBeeRadio::getRXPayloadLength(){ 410 | return _incoming_packet.getRXPayloadLength(); 411 | } 412 | 413 | /** 414 | * Method: getRXPayload(int index) 415 | * @ Since v0.1.0 by Eric Burger, January 2014 416 | * @ Returns the payload byte of the incoming packet at the specified index 417 | * @ param int index: Index of payload data 418 | */ 419 | uint8_t SimpleZigBeeRadio::getRXPayload(int index){ 420 | return _incoming_packet.getRXPayload(index); 421 | } 422 | 423 | /*////////////////////////////////////////////////////////////////////// 424 | ZIGBEE TRANSMIT (TX) STATUS METHODS 425 | /*////////////////////////////////////////////////////////////////////// 426 | 427 | /** 428 | * Method: isTXStatus() 429 | * @ Since v0.1.0 by Eric Burger, June 2014 430 | * @ Checks if received packet is a TX Status and returns boolean 431 | */ 432 | bool SimpleZigBeeRadio::isTXStatus(){ 433 | if( getIncomingFrameType() == ZIGBEE_TX_STATUS ){ 434 | return true; 435 | } 436 | return false; 437 | } 438 | 439 | /** 440 | * Method: getTXStatusAddress16() 441 | * @ Since v0.1.0 by Eric Burger, June 2014 442 | * @ Returns the 16-bit source address of incoming packet (destination of TX request) 443 | */ 444 | SimpleZigBeeAddress16 SimpleZigBeeRadio::getTXStatusAddress16(){ 445 | return _incoming_packet.getTXStatusAddress16(); 446 | } 447 | 448 | /** 449 | * Method: getTXStatusRetryCount() 450 | * @ Since v0.1.0 by Eric Burger, June 2014 451 | * @ Returns value of retry count 452 | */ 453 | uint8_t SimpleZigBeeRadio::getTXStatusRetryCount(){ 454 | return _incoming_packet.getTXStatusRetryCount(); 455 | } 456 | 457 | /** 458 | * Method: getTXStatusDeliveryStatus() 459 | * @ Since v0.1.0 by Eric Burger, June 2014 460 | * @ Returns value of packet delivery status 461 | */ 462 | uint8_t SimpleZigBeeRadio::getTXStatusDeliveryStatus(){ 463 | return _incoming_packet.getTXStatusDeliveryStatus(); 464 | } 465 | 466 | /** 467 | * Method: getTXStatusDiscoveryStatus() 468 | * @ Since v0.1.0 by Eric Burger, June 2014 469 | * @ Returns value of packet discovery status 470 | */ 471 | uint8_t SimpleZigBeeRadio::getTXStatusDiscoveryStatus(){ 472 | return _incoming_packet.getTXStatusDiscoveryStatus(); 473 | } 474 | 475 | /*////////////////////////////////////////////////////////////////////// 476 | AT COMMAND RESPONSE METHODS 477 | /*////////////////////////////////////////////////////////////////////// 478 | 479 | /** 480 | * Method: isATResponse() 481 | * @ Since v0.1.0 by Eric Burger, January 2014 482 | * @ Checks if received packet is an AT Command Response and returns boolean 483 | */ 484 | bool SimpleZigBeeRadio::isATResponse(){ 485 | if( getIncomingFrameType() == AT_COMMAND_RESPONSE ){ 486 | return true; 487 | } 488 | return false; 489 | } 490 | 491 | /** 492 | * Method: getATResponseCommand() 493 | * @ Since v0.1.0 by Eric Burger, January 2014 494 | * @ Returns AT Response Command of incoming packet 495 | */ 496 | uint16_t SimpleZigBeeRadio::getATResponseCommand(){ 497 | return _incoming_packet.getATResponseCommand(); 498 | } 499 | 500 | /** 501 | * Method: getATResponseStatus() 502 | * @ Since v0.1.0 by Eric Burger, January 2014 503 | * @ Returns AT Response Status 504 | */ 505 | uint8_t SimpleZigBeeRadio::getATResponseStatus(){ 506 | return _incoming_packet.getATResponseStatus(); 507 | } 508 | 509 | /** 510 | * Method: getATResponsePayloadLength() 511 | * @ Since v0.1.0 by Eric Burger, June 2014 512 | * @ Returns AT Response Payload Length 513 | */ 514 | uint8_t SimpleZigBeeRadio::getATResponsePayloadLength(){ 515 | return _incoming_packet.getATResponsePayloadLength(); 516 | } 517 | 518 | /** 519 | * Method: getATResponsePayload() 520 | * @ Since v0.1.0 by Eric Burger, January 2014 521 | * @ Returns AT Command Payload 522 | */ 523 | uint8_t SimpleZigBeeRadio::getATResponsePayload(){ 524 | return _incoming_packet.getATResponsePayload(); 525 | } 526 | 527 | /** 528 | * Method: getATResponsePayload(int index) 529 | * @ Since v0.1.0 by Eric Burger, January 2014 530 | * @ Returns AT Command Payload 531 | * @ param int index: Index of command payload 532 | */ 533 | uint8_t SimpleZigBeeRadio::getATResponsePayload(int index){ 534 | return _incoming_packet.getATResponsePayload(index); 535 | } 536 | 537 | /*////////////////////////////////////////////////////////////////////// 538 | REMOTE AT COMMAND RESPONSE METHODS 539 | /*////////////////////////////////////////////////////////////////////// 540 | 541 | /** 542 | * Method: isRemoteATResponse() 543 | * @ Since v0.1.0 by Eric Burger, July 2014 544 | * @ Checks if received packet is a Remote AT Command Response and returns boolean 545 | */ 546 | bool SimpleZigBeeRadio::isRemoteATResponse(){ 547 | if( getIncomingFrameType() == REMOTE_AT_COMMAND_RESPONSE ){ 548 | return true; 549 | } 550 | return false; 551 | } 552 | 553 | /** 554 | * Method: getRemoteATResponseAddress() 555 | * @ Since v0.1.0 by Eric Burger, July 2014 556 | * @ Returns the source (remote) address of incoming packet 557 | */ 558 | SimpleZigBeeAddress SimpleZigBeeRadio::getRemoteATResponseAddress(){ 559 | return _incoming_packet.getRemoteATResponseAddress(); 560 | } 561 | 562 | /** 563 | * Method: getRemoteATResponseAddress64() 564 | * @ Since v0.1.0 by Eric Burger, July 2014 565 | * @ Returns the 64-bit source (remote) address of incoming packet 566 | */ 567 | SimpleZigBeeAddress64 SimpleZigBeeRadio::getRemoteATResponseAddress64(){ 568 | return _incoming_packet.getRemoteATResponseAddress64(); 569 | } 570 | 571 | /** 572 | * Method: getRemoteATResponseAddress16() 573 | * @ Since v0.1.0 by Eric Burger, July 2014 574 | * @ Returns the 16-bit source (remote) address of incoming packet 575 | */ 576 | SimpleZigBeeAddress16 SimpleZigBeeRadio::getRemoteATResponseAddress16(){ 577 | return _incoming_packet.getRemoteATResponseAddress16(); 578 | } 579 | 580 | /** 581 | * Method: getRemoteATResponseCommand() 582 | * @ Since v0.1.0 by Eric Burger, July 2014 583 | * @ Returns AT Command of incoming packet 584 | */ 585 | uint16_t SimpleZigBeeRadio::getRemoteATResponseCommand(){ 586 | return _incoming_packet.getRemoteATResponseCommand(); 587 | } 588 | 589 | /** 590 | * Method: getRemoteATResponseStatus() 591 | * @ Since v0.1.0 by Eric Burger, July 2014 592 | * @ Returns AT Command Status 593 | */ 594 | uint8_t SimpleZigBeeRadio::getRemoteATResponseStatus(){ 595 | return _incoming_packet.getRemoteATResponseStatus(); 596 | } 597 | 598 | /** 599 | * Method: getRemoteATResponsePayloadLength() 600 | * @ Since v0.1.0 by Eric Burger, July 2014 601 | * @ Returns AT Command Data Length 602 | */ 603 | uint8_t SimpleZigBeeRadio::getRemoteATResponsePayloadLength(){ 604 | return _incoming_packet.getRemoteATResponsePayloadLength(); 605 | } 606 | 607 | /** 608 | * Method: getRemoteATResponsePayload() 609 | * @ Since v0.1.0 by Eric Burger, July 2014 610 | * @ Returns AT Command Data 611 | */ 612 | uint8_t SimpleZigBeeRadio::getRemoteATResponsePayload(){ 613 | return _incoming_packet.getRemoteATResponsePayload(); 614 | } 615 | 616 | /** 617 | * Method: getRemoteATResponsePayload(int index) 618 | * @ Since v0.1.0 by Eric Burger, July 2014 619 | * @ Returns AT Command Data 620 | * @ param int index: Index of command data 621 | */ 622 | uint8_t SimpleZigBeeRadio::getRemoteATResponsePayload(int index){ 623 | return _incoming_packet.getRemoteATResponsePayload(index); 624 | } 625 | 626 | /*////////////////////////////////////////////////////////////////////// 627 | Modem Status Methods 628 | /*////////////////////////////////////////////////////////////////////// 629 | 630 | /** 631 | * Method: isModemStatus() 632 | * @ Since v0.1.0 by Eric Burger, July 2014 633 | * @ Checks if received packet is an Modem Status and returns boolean 634 | */ 635 | bool SimpleZigBeeRadio::isModemStatus(){ 636 | if( getIncomingFrameType() == MODEM_STATUS ){ 637 | return true; 638 | } 639 | return false; 640 | } 641 | 642 | /** 643 | * Method: getModemStatus() 644 | * @ Since v0.1.0 by Eric Burger, July 2014 645 | * @ Returns value of incoming packet modem status 646 | */ 647 | uint8_t SimpleZigBeeRadio::getModemStatus(){ 648 | return _incoming_packet.getModemStatus(); 649 | } 650 | 651 | /*////////////////////////////////////////////////////////////////////// 652 | OUTGOING PACKET METHODS 653 | /*////////////////////////////////////////////////////////////////////// 654 | 655 | /** 656 | * Method: setOutgoingFrameType(uint8_t frameType) 657 | * @ Since v0.1.0 by Eric Burger, September 2013 658 | * @ Set frame type for outgoing packets 659 | * @ param uint8_t frameType: Frame type of outgoing ZigBee packet 660 | */ 661 | void SimpleZigBeeRadio::setOutgoingFrameType(uint8_t frameType){ 662 | _outgoing_packet.setFrameType(frameType); 663 | } 664 | 665 | /** 666 | * Method: setOutgoingFrameID(uint8_t id) 667 | * @ Since v0.1.0 by Eric Burger, September 2013 668 | * @ Set frame ID for outgoing packets 669 | * @ param uint8_t id: Frame id number 670 | */ 671 | void SimpleZigBeeRadio::setOutgoingFrameID(uint8_t id){ 672 | _outgoing_packet.setFrameID(id); 673 | } 674 | 675 | /** 676 | * Method: setAcknowledgement(bool ack) 677 | * @ Since v0.1.0 by Eric Burger, September 2013 678 | * @ Require acknowledgement for outgoing packets 679 | * @ param bool ack: True to require acknowledgement and set frame id 680 | */ 681 | void SimpleZigBeeRadio::setAcknowledgement(bool ack){ 682 | _out_acknowledgement = ack; 683 | if( _out_acknowledgement == true){ 684 | setOutgoingFrameID( 1 ); 685 | }else{ 686 | setOutgoingFrameID( 0 ); 687 | } 688 | } 689 | 690 | /** 691 | * Method: getLastFrameID() 692 | * @ Since v0.1.0 by Eric Burger, July 2014 693 | * @ Return frame id of the last outgoing packet 694 | */ 695 | uint8_t SimpleZigBeeRadio::getLastFrameID(){ 696 | return _out_frame_id; 697 | } 698 | 699 | /** 700 | * Method: saveLastFrameID(uint8_t frameID) 701 | * @ Since v0.1.0 by Eric Burger, July 2014 702 | * @ Save the frame id of the last outgoing packet 703 | * @ uint8_t frameID: ID to store 704 | */ 705 | void SimpleZigBeeRadio::saveLastFrameID(uint8_t frameID){ 706 | _out_frame_id = frameID; 707 | } 708 | 709 | /** 710 | * Method: setNextFrameID() 711 | * @ Since v0.1.0 by Eric Burger, August 2013 712 | * @ Sets frame ID (Packet index 4, Frame Index 1) 713 | * If acknowledgement requested, increment frame id using mod operator and set value. Otherwise, set 0. 714 | * Note: Maximum value stored in a byte is 255. 715 | */ 716 | void SimpleZigBeeRadio::setNextFrameID(){ 717 | uint8_t id = 0; 718 | if( _out_acknowledgement == true ){ 719 | uint8_t prev = getLastFrameID(); 720 | id = ((prev)%255 + 1) ; 721 | } 722 | setOutgoingFrameID( id ); 723 | } 724 | 725 | /** 726 | * Method: setOutgoingFrameData(int index, uint8_t byte) 727 | * @ Since v0.1.0 by Eric Burger, September 2013 728 | * @ Sets the frame byte of the outgoing packet at the specified index. 729 | * @ int index: Index of frame data 730 | * @ uint8_t byte: Byte to store 731 | */ 732 | void SimpleZigBeeRadio::setOutgoingFrameData(int index, uint8_t byte){ 733 | _outgoing_packet.setFrameData(index,byte); 734 | } 735 | 736 | /** 737 | * Method: setOutgoingFrameData(int startIndex, uint8_t* frameData, int frameDataLength) 738 | * @ Since v0.1.0 by Eric Burger, September 2013 739 | * @ Sets an array of bytes in the memory array of the outgoing packet, 740 | * starting from specified start index. 741 | * @ param int startIndex: Index at which to start storing bytes 742 | * @ param uint8_t* frameData: Pointer to array of bytes to store 743 | * @ param int frameDataLength: Length of array to input 744 | */ 745 | void SimpleZigBeeRadio::setOutgoingFrameData(int startIndex, uint8_t* frameData, int frameDataLength){ 746 | _outgoing_packet.setFrameData(startIndex,frameData,frameDataLength); 747 | } 748 | 749 | 750 | /** 751 | * Method: setOutgoingAddress(SimpleZigBeeAddress address) 752 | * @ Since v0.1.0 by Eric Burger, September 2013 753 | * @ Set the 64-bit and 16-bit destination addresses of the outgoing packet 754 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 755 | */ 756 | void SimpleZigBeeRadio::setOutgoingAddress(SimpleZigBeeAddress address){ 757 | _outgoing_packet.setAddress(address); 758 | } 759 | 760 | /** 761 | * Method: setOutgoingAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16) 762 | * @ Since v0.1.0 by Eric Burger, September 2013 763 | * @ Set the 64-bit and 16-bit destination addresses of the outgoing packet 764 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 765 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 766 | * @ param uint16_t adr16: 16-bit destination address 767 | */ 768 | void SimpleZigBeeRadio::setOutgoingAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16){ 769 | _outgoing_packet.setAddress(adr64MSB,adr64LSB,adr16); 770 | } 771 | 772 | /** 773 | * Method: setOutgoingAddress64(uint32_t adr64MSB, uint32_t adr64LSB) 774 | * @ Since v0.1.0 by Eric Burger, September 2013 775 | * @ Set the 64-bit destination addresses of the outgoing packet 776 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 777 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 778 | */ 779 | void SimpleZigBeeRadio::setOutgoingAddress64(uint32_t adr64MSB, uint32_t adr64LSB){ 780 | _outgoing_packet.setAddress64(adr64MSB,adr64LSB); 781 | } 782 | 783 | /** 784 | * Method: setOutgoingAddress16(uint16_t adr16) 785 | * @ Since v0.1.0 by Eric Burger, September 2013 786 | * @ Set the 16-bit destination address of the outgoing packet 787 | * @ param uint16_t adr16: 16-bit destination address 788 | */ 789 | void SimpleZigBeeRadio::setOutgoingAddress16(uint16_t adr16){ 790 | _outgoing_packet.setAddress16(adr16); 791 | } 792 | 793 | /** 794 | * Method: send() 795 | * @ Since v0.1.0 by Eric Burger, September 2013 796 | * @ Send packet to serial port based on _outgoing_packet object 797 | */ 798 | void SimpleZigBeeRadio::send(){ 799 | saveLastFrameID( _outgoing_packet.getFrameID() ); // Record frame ID 800 | sendPacket(_outgoing_packet); 801 | } 802 | 803 | /** 804 | * Method: send(SimpleZigBeePacket & packet) 805 | * @ Since v0.1.0 by Eric Burger, September 2013 806 | * @ Send packet to serial port based on input Packet object 807 | * @ param SimpleZigBeePacket & packet: Pointer to packet object 808 | */ 809 | void SimpleZigBeeRadio::send(SimpleZigBeePacket & packet){ 810 | sendPacket(packet); 811 | } 812 | 813 | /** 814 | * Method: sendPacket(SimpleZigBeePacket & p) 815 | * @ Since v0.1.0 by Eric Burger, September 2013 816 | * @ Send packet to serial port 817 | * @ param SimpleZigBeePacket & p: Pointer to packet object 818 | */ 819 | void SimpleZigBeeRadio::sendPacket(SimpleZigBeePacket & p){ 820 | // Everything should be ready to go, so write it to the serial port... 821 | write( START ); 822 | writeByte( p.getLengthMSB() ); 823 | writeByte( p.getLengthLSB() ); 824 | // Frame Type and Frame ID are stored in Frame Data 825 | uint8_t checksum = 0; 826 | for( int i=0; iwrite(byte); 860 | } 861 | 862 | /** 863 | * Method: flush() 864 | * @ Since v0.1.0 by Eric Burger, September 2013 865 | * @ Updated v0.1.1 by Eric Burger, April 2016 866 | * @ Flush serial port (wait until all outgoing bytes have been sent) 867 | */ 868 | void SimpleZigBeeRadio::flush(){ 869 | // For HardwareSerial, this will wait until TX buffer is clear 870 | // For SoftwareSerial, there is no TX buffer and so this simply returns 871 | _serial->flush(); 872 | } 873 | 874 | /*////////////////////////////////////////////////////////////////////// 875 | ZIGBEE TRANSMIT (TX) REQUEST METHODS 876 | /*////////////////////////////////////////////////////////////////////// 877 | 878 | /** 879 | * Method: setTXRequestBroadcastRadius(uint8_t rad) 880 | * @ Since v0.1.0 by Eric Burger, September 2013 881 | * @ Set broadcast radius of the outgoing packet 882 | * @ param uint8_t rad: Maximum radius (# of hops) of packets, 0 for no limit 883 | */ 884 | void SimpleZigBeeRadio::setTXRequestBroadcastRadius(uint8_t rad){ 885 | _outgoing_packet.setTXRequestBroadcastRadius(rad); 886 | } 887 | 888 | /** 889 | * Method: setTXRequestOption(uint8_t opt) 890 | * @ Since v0.1.0 by Eric Burger, September 2013 891 | * @ Set broadcast radius of the outgoing packet 892 | * @ param uint8_t opt: Option byte 893 | */ 894 | void SimpleZigBeeRadio::setTXRequestOption(uint8_t opt){ 895 | _outgoing_packet.setTXRequestOption(opt); 896 | } 897 | 898 | /** 899 | * Method: setTXRequestPayload(uint8_t* payload, int payloadSize) 900 | * @ Since v0.1.0 by Eric Burger, September 2013 901 | * @ Set payload of the outgoing packet 902 | * @ param uint8_t* payload: Pointer to array of bytes containing payload data 903 | * @ param int payloadSize: Length of payload array 904 | */ 905 | void SimpleZigBeeRadio::setTXRequestPayload(uint8_t* payload, int payloadSize){ 906 | _outgoing_packet.setTXRequestPayload(payload,payloadSize); 907 | } 908 | 909 | /** 910 | * Method: prepareTXRequest(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint8_t* payload, int payloadSize) 911 | * @ Since v0.1.0 by Eric Burger, April 2014 912 | * @ Easy to use method for sending transmit request 913 | * @ param uint32_t adr64MSB: Most significant bytes (1st half) of 64-bit address 914 | * @ param uint32_t adr64LSB: Least significant bytes (2nd half) of 64-bit address 915 | * @ param uint16_t adr16: 16-bit destination address 916 | * @ param uint8_t* payload: Pointer to array of bytes to store 917 | * @ param int payloadSize: Length of payload array 918 | */ 919 | void SimpleZigBeeRadio::prepareTXRequest(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint8_t* payload, int payloadSize){ 920 | // Clear checksum, frame length, and any error. Set broadcast radius and frame options to 0. 921 | resetOutgoing(); 922 | setTXRequestPayload(payload, payloadSize); // Set payload first so that memory array expansion occurs only once, if applicable 923 | setOutgoingFrameType(ZIGBEE_TRANSMIT_REQUEST); 924 | setOutgoingAddress(adr64MSB,adr64LSB,adr16); 925 | setTXRequestBroadcastRadius(0); 926 | setTXRequestOption(0); 927 | setNextFrameID(); 928 | } 929 | 930 | /** 931 | * Method: prepareTXRequest(SimpleZigBeeAddress address, uint8_t* payload, int payloadSize) 932 | * @ Since v0.1.0 by Eric Burger, April 2014 933 | * @ Easy to use method for sending transmit request 934 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 935 | * @ param uint8_t* payload: Pointer to array of bytes to store 936 | * @ param int payloadSize: Length of payload array 937 | */ 938 | void SimpleZigBeeRadio::prepareTXRequest(SimpleZigBeeAddress address, uint8_t* payload, int payloadSize){ 939 | prepareTXRequest(COORDINATOR_ADDRESS_64_MSB,COORDINATOR_ADDRESS_64_LSB,BROADCAST_ADDRESS_16,payload,payloadSize); 940 | setOutgoingAddress(address); 941 | } 942 | 943 | /** 944 | * Method: prepareTXRequestBroadcast(uint8_t* payload, int payloadSize) 945 | * @ Since v0.1.0 by Eric Burger, April 2014 946 | * @ Easy to use method for sending broadcast payload 947 | * @ param uint8_t* payload: Pointer to array of bytes to store 948 | * @ param int payloadSize: Length of payload array 949 | */ 950 | void SimpleZigBeeRadio::prepareTXRequestBroadcast(uint8_t* payload, int payloadSize){ 951 | prepareTXRequest(BROADCAST_ADDRESS_64_MSB,BROADCAST_ADDRESS_64_LSB,BROADCAST_ADDRESS_16,payload,payloadSize); 952 | } 953 | 954 | /** 955 | * Method: prepareTXRequestToCoordinator(uint8_t* payload, int payloadSize) 956 | * @ Since v0.1.0 by Eric Burger, April 2014 957 | * @ Easy to use method for sending payload to coordinator 958 | * @ param uint8_t* payload: Pointer to array of bytes to store 959 | * @ param int payloadSize: Length of payload array 960 | */ 961 | void SimpleZigBeeRadio::prepareTXRequestToCoordinator(uint8_t* payload, int payloadSize){ 962 | prepareTXRequest(COORDINATOR_ADDRESS_64_MSB,COORDINATOR_ADDRESS_64_LSB,BROADCAST_ADDRESS_16,payload,payloadSize); 963 | } 964 | 965 | /*////////////////////////////////////////////////////////////////////// 966 | AT COMMAND METHODS 967 | /*////////////////////////////////////////////////////////////////////// 968 | 969 | /** 970 | * Method: setATCommand(uint16_t command) 971 | * @ Since v0.1.0 by Eric Burger, July 2014 972 | * @ Set AT command of outgoing packet. 973 | * @ param uint16_t command: 16-bit AT Command 974 | */ 975 | void SimpleZigBeeRadio::setATCommand(uint16_t command){ 976 | _outgoing_packet.setATCommand(command); 977 | } 978 | 979 | /** 980 | * Method: setATCommandPayload(uint8_t payload) 981 | * @ Since v0.1.0 by Eric Burger, July 2014 982 | * @ Set AT command parameter of outgoing packet. 983 | * @ param uint8_t payload: Byte containing payload 984 | */ 985 | void SimpleZigBeeRadio::setATCommandPayload(uint8_t payload){ 986 | _outgoing_packet.setATCommandPayload(payload); 987 | } 988 | 989 | /** 990 | * Method: setATCommandPayload(uint8_t* payload, int payloadSize) 991 | * @ Since v0.1.0 by Eric Burger, July 2014 992 | * @ Set AT command parameter of outgoing packet. 993 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 994 | * @ param int payloadSize: Length of payload array 995 | */ 996 | void SimpleZigBeeRadio::setATCommandPayload(uint8_t* payload, int payloadSize){ 997 | _outgoing_packet.setATCommandPayload(payload, payloadSize); 998 | } 999 | 1000 | /** 1001 | * Method: prepareATCommand(uint16_t command) 1002 | * @ Since v0.1.0 by Eric Burger, April 2014 1003 | * @ Easy to use method for sending AT command 1004 | * @ param uint16_t command: 16-bit AT Command 1005 | */ 1006 | void SimpleZigBeeRadio::prepareATCommand(uint16_t command){ 1007 | // Clear checksum, frame length, and any error. 1008 | resetOutgoing(); 1009 | setATCommand(command); 1010 | setOutgoingFrameType(AT_COMMAND); 1011 | setNextFrameID(); 1012 | } 1013 | 1014 | /** 1015 | * Method: prepareATCommand(uint16_t command, uint8_t payload) 1016 | * @ Since v0.1.0 by Eric Burger, April 2014 1017 | * @ Easy to use method for sending AT command 1018 | * @ param uint16_t command: 16-bit AT Command 1019 | * @ param uint8_t payload: Byte containing payload 1020 | */ 1021 | void SimpleZigBeeRadio::prepareATCommand(uint16_t command, uint8_t payload){ 1022 | prepareATCommand(command); 1023 | setATCommandPayload(payload); 1024 | } 1025 | 1026 | /** 1027 | * Method: prepareATCommand(uint16_t command, uint8_t* payload, int payloadSize) 1028 | * @ Since v0.1.0 by Eric Burger, April 2014 1029 | * @ Easy to use method for sending AT command 1030 | * @ param uint16_t command: 16-bit AT Command 1031 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 1032 | * @ param int payloadSize: Length of payload array 1033 | */ 1034 | void SimpleZigBeeRadio::prepareATCommand(uint16_t command, uint8_t* payload, int payloadSize){ 1035 | prepareATCommand(command); 1036 | setATCommandPayload(payload, payloadSize); 1037 | } 1038 | 1039 | /*////////////////////////////////////////////////////////////////////// 1040 | REMOTE AT COMMAND METHODS 1041 | /*////////////////////////////////////////////////////////////////////// 1042 | 1043 | /** 1044 | * Method: setRemoteATCommandOption(uint8_t opt) 1045 | * @ Since v0.1.0 by Eric Burger, July 2014 1046 | * @ Set remote command option of outgoing packet. 1047 | * @ param uint8_t opt: Option value to set 1048 | */ 1049 | void SimpleZigBeeRadio::setRemoteATCommandOption(uint8_t opt){ 1050 | _outgoing_packet.setRemoteATCommandOption(opt); 1051 | } 1052 | 1053 | /** 1054 | * Method: setRemoteATCommand(uint16_t command) 1055 | * @ Since v0.1.0 by Eric Burger, April 2014 1056 | * @ Store Remote AT command of outgoing packet. 1057 | * @ param uint16_t command: 16-bit AT Command 1058 | */ 1059 | void SimpleZigBeeRadio::setRemoteATCommand(uint16_t command){ 1060 | _outgoing_packet.setRemoteATCommand(command); 1061 | } 1062 | 1063 | /** 1064 | * Method: setRemoteATCommandPayload(uint8_t payload) 1065 | * @ Since v0.1.0 by Eric Burger, July 2014 1066 | * @ Store AT command parameter of outgoing packet. 1067 | * @ param uint8_t payload: Byte containing payload 1068 | */ 1069 | void SimpleZigBeeRadio::setRemoteATCommandPayload(uint8_t payload){ 1070 | _outgoing_packet.setRemoteATCommandPayload(payload); 1071 | } 1072 | 1073 | /** 1074 | * Method: setRemoteATCommandPayload(uint8_t* payload, int payloadSize) 1075 | * @ Since v0.1.0 by Eric Burger, July 2014 1076 | * @ Store AT command parameter of outgoing packet. 1077 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 1078 | * @ param int payloadSize: Length of payload array 1079 | */ 1080 | void SimpleZigBeeRadio::setRemoteATCommandPayload(uint8_t* payload, int payloadSize){ 1081 | _outgoing_packet.setRemoteATCommandPayload(payload,payloadSize); 1082 | } 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | /** 1090 | * Method: prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command) 1091 | * @ Since v0.1.0 by Eric Burger, July 2014 1092 | * @ Easy to use method for sending AT command 1093 | * @ param uint32_t adr64MSB: Most significant bytes of 64-bit address 1094 | * @ param uint32_t adr64LSB: Least significant bytes of 64-bit address 1095 | * @ param uint16_t adr16: 16-bit destination address 1096 | * @ param uint16_t command: 16-bit AT Command 1097 | */ 1098 | void SimpleZigBeeRadio::prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command){ 1099 | // Clear checksum, frame length, and any error. Set option to apply changes (0x02). 1100 | resetOutgoing(); 1101 | setRemoteATCommand(command); 1102 | setOutgoingFrameType(REMOTE_AT_COMMAND); 1103 | setOutgoingAddress(adr64MSB,adr64LSB,adr16); 1104 | setRemoteATCommandOption(0x02); 1105 | setNextFrameID(); 1106 | } 1107 | 1108 | /** 1109 | * Method: prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t payload) 1110 | * @ Since v0.1.0 by Eric Burger, July 2014 1111 | * @ Easy to use method for sending AT command 1112 | * @ param uint32_t adr64MSB: Most significant bytes of 64-bit address 1113 | * @ param uint32_t adr64LSB: Least significant bytes of 64-bit address 1114 | * @ param uint16_t adr16: 16-bit destination address 1115 | * @ param uint16_t command: 16-bit AT Command 1116 | * @ param uint8_t payload: Byte containing payload 1117 | */ 1118 | void SimpleZigBeeRadio::prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t payload){ 1119 | prepareRemoteATCommand(adr64MSB,adr64LSB,adr16,command); 1120 | setRemoteATCommandPayload(payload); 1121 | } 1122 | 1123 | /** 1124 | * Method: prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t* payload, int payloadSize) 1125 | * @ Since v0.1.0 by Eric Burger, July 2014 1126 | * @ Easy to use method for sending AT command 1127 | * @ param uint32_t adr64MSB: Most significant bytes of 64-bit address 1128 | * @ param uint32_t adr64LSB: Least significant bytes of 64-bit address 1129 | * @ param uint16_t adr16: 16-bit destination address 1130 | * @ param uint16_t command: 16-bit AT Command 1131 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 1132 | * @ param int payloadSize: Length of payload array 1133 | */ 1134 | void SimpleZigBeeRadio::prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t* payload, int payloadSize){ 1135 | prepareRemoteATCommand(adr64MSB,adr64LSB,adr16,command); 1136 | setRemoteATCommandPayload(payload, payloadSize); 1137 | } 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | /** 1148 | * Method: prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command) 1149 | * @ Since v0.1.0 by Eric Burger, July 2014 1150 | * @ Easy to use method for sending AT command 1151 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 1152 | * @ param uint16_t command: 16-bit AT Command 1153 | */ 1154 | void SimpleZigBeeRadio::prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command){ 1155 | // Clear checksum, frame length, and any error. Set option to apply changes (0x02). 1156 | resetOutgoing(); 1157 | setRemoteATCommand(command); 1158 | setOutgoingFrameType(REMOTE_AT_COMMAND); 1159 | setOutgoingAddress(address); 1160 | setRemoteATCommandOption(0x02); 1161 | setNextFrameID(); 1162 | } 1163 | 1164 | /** 1165 | * Method: prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t payload) 1166 | * @ Since v0.1.0 by Eric Burger, July 2014 1167 | * @ Easy to use method for sending AT command 1168 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 1169 | * @ param uint16_t command: 16-bit AT Command 1170 | * @ param uint8_t payload: Byte containing payload 1171 | */ 1172 | void SimpleZigBeeRadio::prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t payload){ 1173 | prepareRemoteATCommand(address,command); 1174 | setRemoteATCommandPayload(payload); 1175 | } 1176 | 1177 | /** 1178 | * Method: prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t* payload, int payloadSize) 1179 | * @ Since v0.1.0 by Eric Burger, July 2014 1180 | * @ Easy to use method for sending AT command 1181 | * @ param SimpleZigBeeAddress address: Object containing 64-bit and 16-bit destination addresses 1182 | * @ param uint16_t command: 16-bit AT Command 1183 | * @ param uint8_t* payload: Pointer to array of bytes containing payload 1184 | * @ param int payloadSize: Length of payload array 1185 | */ 1186 | void SimpleZigBeeRadio::prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t* payload, int payloadSize){ 1187 | prepareRemoteATCommand(address,command); 1188 | setRemoteATCommandPayload(payload, payloadSize); 1189 | } 1190 | -------------------------------------------------------------------------------- /SimpleZigBeeRadio.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Library Name: SimpleZigBeeRadio 3 | * Library URI: https://github.com/ericburger/simple-zigbee 4 | * Description: Library for sending and receiving packets through the Arduino Serial port 5 | * using the ZigBee protocol. Intended for use with XBee S2 radios. These radios can 6 | * be connected directly to the Arduino's TX and RX pins or to any two digital pins 7 | * using the SoftwareSerial Arduino library. For more details about this library and 8 | * examples of its use, please visit https://github.com/ericburger/simple-zigbee. 9 | * Version: 0.1.1 10 | * Author(s): Eric Burger 11 | * Author URI: WallflowerOpen.com 12 | * License: GNU General Public License v2.0 or later 13 | * License URI: http://www.gnu.org/licenses/gpl-2.0.html 14 | * 15 | * Copyright (c) 2013 Eric Burger. All rights reserved. 16 | * 17 | * This file is part of SimpleZigBee. 18 | * 19 | * SimpleZigBee is free software: you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation, either version 2 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * SimpleZigBee is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with SimpleZigBee. If not, see . 31 | */ 32 | 33 | /** 34 | * Notes for modifying Arduino files: 35 | * 1. To encourage the use of these libraries for educational purposes, please provide detailed explanations 36 | * throughout the code. 37 | * 2. When adding a class or method, please provide a description of the class or method and information 38 | * concerning when the addition was made, who made it, and the upcoming release in which the addition will appear. 39 | * Descriptions of CLASSES should be placed in the .h file and of METHODS in the .cpp file. 40 | * 41 | * Example for classes: 42 | * Class: SimpleZigBeeAddress() 43 | * @ Since v0.1.0 by Eric Burger, September 2013 44 | * @ Stores the 64-bit and 16-bit addresses of an ZigBee packet 45 | * 46 | * Example for methods: 47 | * Method: setAddress64(uint32_t adr64MSB, uint32_t adr64LSB) 48 | * @ Since v0.1.0 by Eric Burger, September 2013 49 | * @ Sets 64-bit address 50 | * @ param uint32_t adr64MSB: 32-bit integer representing the first half of the 64-bit address 51 | * @ param uint32_t adr64LSB: 32-bit integer representing the second half of the 64-bit address 52 | * 53 | * 3. When modifying an existing class or method, please append a description of the changes 54 | * 55 | * Example for classes: 56 | * Class: SimpleZigBeeAddress() 57 | * @ Since v0.1.0 by Eric Burger, September 2013 58 | * @ Class storing the 64-bit and 16-bit addresses of an ZigBee packet 59 | * @ Last Modified v0.1.1 by Joe Smith, December 2013 60 | * @ Changlog for v0.1.1: 61 | * - Added variable "foo" for storing information 62 | * - Added method setFoo 63 | * 64 | * Example for methods: 65 | * Method: setAddress64(uint32_t adr64MSB, uint32_t adr64LSB) 66 | * @ Since v0.1.0 by Eric Burger, September 2013 67 | * @ Sets 64-bit address 68 | * @ param uint32_t adr64MSB: 32-bit integer representing the first half of the 64-bit address 69 | * @ param uint32_t adr64LSB: 32-bit integer representing the second half of the 64-bit address 70 | * @ Last Modified v0.1.1 by Joe Smith, December 2013 71 | * @ Changlog for v0.1.1: 72 | * - Added error check 73 | * 74 | */ 75 | 76 | #ifndef SimpleZigBeeRadio_h 77 | #define SimpleZigBeeRadio_h 78 | 79 | #include "Arduino.h" 80 | // Requires SimpleZigBeePacket classes 81 | #include "SimpleZigBeePacket.h" 82 | // Required for uint8_t type 83 | #include 84 | 85 | /** 86 | * Class: SimpleZigBeeRadio 87 | * @ Since v0.1.0 by Eric Burger, August 2013 88 | * @ Object for reading and sending ZigBee packets via serial port. The class 89 | * assumes the XBee radio is in Escaped API Mode (ATAP=2) by default. The class includes 90 | * an alternative constructor for radios that are not in Escaped API Mode, though this is 91 | * not recommended due to the inability to identify incoming packets that are incomplete. 92 | * In other words, in Escaped API Mode, incoming packets can only contain the start byte, 93 | * 0x7E, at the start of a packet since the byte is "escaped" at all other positions. 94 | */ 95 | class SimpleZigBeeRadio { 96 | public: 97 | // INITIALIZATION METHODS // 98 | SimpleZigBeeRadio(); 99 | SimpleZigBeeRadio(bool escaped_mode); 100 | void reset(); 101 | void resetIncoming(); 102 | void resetOutgoing(); 103 | void setSerial(HardwareSerial & serial); 104 | void setSerial(Stream & serial); 105 | 106 | // PACKET METHODS // 107 | SimpleIncomingZigBeePacket & getIncomingPacketObject(); 108 | SimpleOutgoingZigBeePacket & getOutgoingPacketObject(); 109 | 110 | // INCOMING PACKET METHODS // 111 | bool available(); 112 | void read(); 113 | bool isEscaping(); 114 | void setEscaping(bool escape); 115 | bool isComplete(); 116 | void setComplete(bool complete); 117 | 118 | uint8_t getIncomingFrameType(); 119 | uint8_t getIncomingFrameID(); 120 | uint8_t getIncomingFrameData(int index); 121 | void getIncomingFrameData(int startIndex, uint8_t* arrayPtr, int frameDataLength); 122 | 123 | // ZIGBEE RECIEVED (RX) PACKET METHODS // 124 | bool isRX(); 125 | SimpleZigBeeAddress getRXAddress(); 126 | SimpleZigBeeAddress64 getRXAddress64(); 127 | SimpleZigBeeAddress16 getRXAddress16(); 128 | uint8_t getRXOptions(); 129 | uint8_t getRXPayloadLength(); 130 | uint8_t getRXPayload(int index); 131 | 132 | // ZIGBEE TRANSMIT (TX) STATUS METHODS // 133 | bool isTXStatus(); 134 | // For Frame ID, use getIncomingFrameID() 135 | SimpleZigBeeAddress16 getTXStatusAddress16(); 136 | uint8_t getTXStatusRetryCount(); 137 | uint8_t getTXStatusDeliveryStatus(); 138 | uint8_t getTXStatusDiscoveryStatus(); 139 | 140 | // AT COMMAND RESPONSE METHODS // 141 | bool isATResponse(); 142 | // For Frame ID, use getIncomingFrameID() 143 | uint16_t getATResponseCommand(); 144 | uint8_t getATResponseStatus(); 145 | uint8_t getATResponsePayloadLength(); 146 | uint8_t getATResponsePayload(); 147 | uint8_t getATResponsePayload(int index); 148 | 149 | // REMOTE AT COMMAND RESPONSE METHODS // 150 | bool isRemoteATResponse(); 151 | // For Frame ID, use getIncomingFrameID() 152 | SimpleZigBeeAddress getRemoteATResponseAddress(); 153 | SimpleZigBeeAddress64 getRemoteATResponseAddress64(); 154 | SimpleZigBeeAddress16 getRemoteATResponseAddress16(); 155 | uint16_t getRemoteATResponseCommand(); 156 | uint8_t getRemoteATResponseStatus(); 157 | uint8_t getRemoteATResponsePayloadLength(); 158 | uint8_t getRemoteATResponsePayload(); 159 | uint8_t getRemoteATResponsePayload(int index); 160 | 161 | // MODEM STATUS METHODS // 162 | bool isModemStatus(); 163 | uint8_t getModemStatus(); 164 | 165 | // OUTGOING PACKET METHODS // 166 | void setOutgoingFrameType(uint8_t frameType); 167 | void setOutgoingFrameID(uint8_t id); 168 | uint8_t getLastFrameID(); 169 | void saveLastFrameID(uint8_t frameID); 170 | void setNextFrameID(); 171 | void setAcknowledgement(bool ack); 172 | void setOutgoingFrameData(int index, uint8_t byte); 173 | void setOutgoingFrameData(int startIndex, uint8_t* frameData, int frameDataLength); 174 | 175 | void setOutgoingAddress(SimpleZigBeeAddress address); 176 | void setOutgoingAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16); 177 | void setOutgoingAddress64(uint32_t adr64MSB, uint32_t adr64LSB); 178 | void setOutgoingAddress16(uint16_t adr16); 179 | 180 | void send(); 181 | void send(SimpleZigBeePacket & packet); 182 | void sendPacket(SimpleZigBeePacket & packet); 183 | void writeByte(uint8_t byte); 184 | void write(uint8_t byte); 185 | void flush(); 186 | 187 | // ZIGBEE TRANSMIT (TX) REQUEST METHODS // 188 | // Use General Packet Methods for Frame Type, Frame ID, and Address 189 | void setTXRequestBroadcastRadius(uint8_t rad); 190 | void setTXRequestOption(uint8_t opt); 191 | void setTXRequestPayload(uint8_t* payload, int payloadSize); 192 | 193 | void prepareTXRequest(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint8_t* payload, int payloadSize); 194 | void prepareTXRequest(SimpleZigBeeAddress address, uint8_t* payload, int payloadSize); 195 | void prepareTXRequestBroadcast(uint8_t* payload, int payloadSize); 196 | void prepareTXRequestToCoordinator(uint8_t* payload, int payloadSize); 197 | 198 | // AT COMMAND METHODS // 199 | // Use General Packet Methods for Frame Type, Frame ID, and Address 200 | void setATCommand(uint16_t command); 201 | void setATCommandPayload(uint8_t payload); // aka, parameter 202 | void setATCommandPayload(uint8_t* payload, int payloadSize); 203 | 204 | void prepareATCommand(uint16_t command); 205 | void prepareATCommand(uint16_t command, uint8_t payload); 206 | void prepareATCommand(uint16_t command, uint8_t* payload, int payloadSize); 207 | 208 | // REMOTE AT COMMAND METHODS // 209 | // Use General Packet Methods for Frame Type, Frame ID, and Address 210 | void setRemoteATCommandOption(uint8_t opt); 211 | void setRemoteATCommand(uint16_t command); 212 | void setRemoteATCommandPayload(uint8_t payload); 213 | void setRemoteATCommandPayload(uint8_t* payload, int payloadSize); 214 | 215 | void prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command); 216 | void prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t payload); 217 | void prepareRemoteATCommand(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint16_t command, uint8_t* payload, int payloadSize); 218 | 219 | void prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command); 220 | void prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t payload); 221 | void prepareRemoteATCommand(SimpleZigBeeAddress address, uint16_t command, uint8_t* payload, int payloadSize); 222 | 223 | // ERRORS // 224 | 225 | 226 | private: 227 | Stream * _serial; 228 | // Boolean indicating whether or not XBee radio is in escaped API Mode (ATAP=2) 229 | bool _escaped_mode; 230 | // Boolean indicating whether or not serial port is SoftwareSerial 231 | bool _is_software_serial; 232 | 233 | // Object for storing incoming packet 234 | SimpleIncomingZigBeePacket _incoming_packet; 235 | // Most recent byte received from incoming packet 236 | uint8_t _in_byte; 237 | // Current index of incoming packet 238 | int _in_index; 239 | // Current checksum of incoming packet 240 | uint8_t _in_checksum; 241 | // Escape the next byte of incoming packet 242 | bool _in_escaping; 243 | // Boolean for tracking if incoming packet is completely received 244 | bool _in_complete; 245 | 246 | // Object for preparing outgoing packet 247 | SimpleOutgoingZigBeePacket _outgoing_packet; 248 | // Boolean specifying if outgoing packets should require acknowledgement. 249 | bool _out_acknowledgement; 250 | // Frame ID of last outgoing packet 251 | uint8_t _out_frame_id; 252 | 253 | }; 254 | 255 | #endif //SimpleZigBeeRadio_h 256 | -------------------------------------------------------------------------------- /XBee-ZB-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ericburger/simple-zigbee/c178b4f00dff250c2e5aae8b4e858c89cce870bd/XBee-ZB-manual.pdf -------------------------------------------------------------------------------- /examples/GettingStarted/Part1_Coordinator/Part1_Coordinator.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Getting Started, Part 1: Coordinator 3 | 4 | Welcome to the SimpleZigBee library. This library 5 | is intented to make it easy to setup a network of 6 | Arduinos using XBee S2 (ZigBee) radios. Please note 7 | that the library will only work with ZigBee radios 8 | (not XBee S1) and that the radios must be in API Mode 2 9 | (not in transparent mode). 10 | 11 | If this is your first introduction into wireless networks, 12 | I highly recommend the book "Building Wireless Sensor Networks" 13 | by Robert Faludi. When I first began working with sensor 14 | networks, I found the text very helpful for understanding 15 | hexidecimals, networking protocols in general, and 16 | specifically the ZigBee protocol. 17 | 18 | These example sketchs will help you quickly get a 19 | wirless network of Arduinos up and running. To complete 20 | the example, you will need two XBee S2 radios (one with 21 | Coordinator API firmware and one with Router API firmware) 22 | and two Arduino boards. 23 | 24 | This example will setup the network coordinator and display 25 | the contents of incoming packets. 26 | 27 | ########################################################### 28 | created 30 June 2014 29 | updated 16 Sept 2015 30 | by Eric Burger 31 | 32 | This example code is in the public domain. 33 | The SimpleZigBee library is released under the GNU GPL v2 License 34 | ########################################################### 35 | 36 | Setup: 37 | 1. This code will be used to interact with the coordinator. 38 | Use the XCTU Software to load the Coordinator API firmware 39 | onto an XBee S2 radio. Next, set an easy to remember PAN ID 40 | (like 1, 100, or 2020) or leave the value as 0 and a PAN ID 41 | will automatically be set. Lastly, make sure the API Mode 42 | is set to 2 (AP=2). 43 | 44 | 2. In this example, the Arduino will connect to the XBee 45 | using a Software Serial port. This allows the Hardware 46 | Serial port to remain free, making it easier to reprogram the 47 | Arduino and to debug the code. Begin by connecting the XBee. 48 | Connect DOUT to Pin 10 (RX) and DIN to Pin 11 (TX). Also, 49 | connect the XBee to 3.3V and ground (GND). 50 | 51 | 3. Upload this sketch (to the Arduino attached to the 52 | Coordinator) and open the Arduino IDE's Serial Monitor. 53 | Read through the commented code below to understand what 54 | is being displayed in the serial monitor. 55 | 56 | 4. Complete "Getting Started, Part 1: Router". 57 | 58 | */ 59 | 60 | #include 61 | #include 62 | 63 | // Create the XBee object ... 64 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 65 | // ... and the software serial port. Note: Only one 66 | // SoftwareSerial object can receive data at a time. 67 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 68 | 69 | void setup() { 70 | // Start the serial ports ... 71 | Serial.begin( 9600 ); 72 | while( !Serial ){;} // Wait for serial port (for Leonardo only). 73 | xbeeSerial.begin( 9600 ); 74 | // ... and set the serial port for the XBee radio. 75 | xbee.setSerial( xbeeSerial ); 76 | // Set a non-zero frame id to receive Status packets. 77 | xbee.setAcknowledgement(true); 78 | } 79 | 80 | void loop() { 81 | // Each SimpleZigBeeRadio instance contains two 82 | // SimpleZigBeePacket instances, one for storing incoming 83 | // messages and one for preparing outgoing messages. 84 | // This example will not send any messages to the network. 85 | // Rather, the coordinator will receive messages and display 86 | // the contents to the hardware serial port. 87 | 88 | // While data is waiting in the XBee serial port ... 89 | while( xbee.available() ){ 90 | // ... read the data. 91 | xbee.read(); 92 | // If a complete message is available, display the contents 93 | if( xbee.isComplete() ){ 94 | Serial.print("\nIncoming Message: "); 95 | printPacket( xbee.getIncomingPacketObject() ); 96 | // While the SimpleZigBeeRadio class includes 97 | // methods for getting and setting the contents 98 | // of the incoming and outgoing packet objects, 99 | // you can always access the objects directly 100 | // using: 101 | //SimpleIncomingZigBeePacket zbpIn = xbee.getIncomingPacketObject(); 102 | //SimpleOutgoingZigBeePacket zbpOut = xbee.getOutgoingPacketObject(); 103 | } 104 | } 105 | // Note: Because the .isComplete() check is inside the 106 | // .available() loop, an incoming message will never 107 | // pass the .isComplete() check more than once. The next 108 | // time the .available() loop is entered (i.e. a new message 109 | // arrives), the previous incoming message will be erased. 110 | 111 | delay(10); // Small delay for stability 112 | // That's it! The coordinator is ready to go. 113 | } 114 | 115 | 116 | ///////////////////////////////////////////////////////////// 117 | // Function for printing the complete contents of a packet // 118 | ///////////////////////////////////////////////////////////// 119 | void printPacket(SimpleZigBeePacket & p){ 120 | Serial.print( START, HEX ); 121 | Serial.print(' '); 122 | Serial.print( p.getLengthMSB(), HEX ); 123 | Serial.print(' '); 124 | Serial.print( p.getLengthLSB(), HEX ); 125 | Serial.print(' '); 126 | // Frame Type and Frame ID are stored in Frame Data 127 | uint8_t checksum = 0; 128 | for( int i=0; i 53 | #include 54 | 55 | // Create the XBee object ... 56 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 57 | // ... and the software serial port. Note: Only one 58 | // SoftwareSerial object can receive data at a time. 59 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 60 | 61 | // Packet to send: In this example, we will update 62 | // the contents of a packet before sending it. 63 | SimpleZigBeePacket zbp = SimpleZigBeePacket(); 64 | 65 | // Value and payload to be sent 66 | int val = 0; 67 | // Variables to store time 68 | unsigned long time = 0; 69 | unsigned long last_sent = 0; 70 | 71 | void setup() { 72 | // Start the serial ports ... 73 | Serial.begin( 9600 ); 74 | while( !Serial ){;}// Wait for serial port (for Leonardo only). 75 | xbeeSerial.begin( 9600 ); 76 | // ... and set the serial port for the XBee radio. 77 | xbee.setSerial( xbeeSerial ); 78 | // Receive TX Status packets 79 | xbee.setAcknowledgement(true); 80 | 81 | // The frame data in a ZigBee packet refers to the data between 82 | // the length LSB and the checksum. Below is an example of 83 | // a frame where: 84 | // Frame type = 0x10 (ZigBee Transmit Request) 85 | // Frame id = 0x01 86 | // 64-bit destination address = 0x0000000000000000 (Coordinator address) 87 | // 16-bit destination address = 0xfffe (unknown or broadcast) 88 | // Broadcast radius = 0x00 89 | // Options = 0x00 90 | // Payload data = 0xffff 91 | uint8_t exFrame[] = { 0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xfe,0x00,0x00,0xff,0xff }; 92 | 93 | // Now store the example frame in the packet object. 94 | // The setFrameData() method accepts a starting index 95 | // (where in the frame to begin), an array, and the 96 | // array's length (number of bytes to store). 97 | zbp.setFrameData(0, exFrame, sizeof(exFrame)); 98 | 99 | // If you are having trouble connecting the Router 100 | // to the Coordinator, you can try sending the 101 | // AT command to leave the current network and then 102 | // wait for the Router to reconnect. 103 | /* 104 | Serial.println( "Send command to leave network (CB4)" ); 105 | xbee.prepareATCommand('CB',4); 106 | xbee.send(); 107 | delay(10000); 108 | */ 109 | } 110 | 111 | 112 | void loop() { 113 | // While data is waiting in the XBee serial port ... 114 | while( xbee.available() ){ 115 | // ... read the data. 116 | xbee.read(); 117 | // If a complete message is available and it 118 | // has not been read yet, read it. 119 | if( xbee.isComplete() ){ 120 | // Print the contents of the incoming packet 121 | Serial.print("\nIncoming Message: "); 122 | printPacket( xbee.getIncomingPacketObject() ); 123 | } 124 | } 125 | 126 | // The Arduino will send a packet to the XBee once every 5 127 | // seconds. To avoid overflowing the serial buffer, you 128 | // should avoid putting long delays, like delay(5000), 129 | // in a sketch. 130 | time = millis(); 131 | if( time > (last_sent+5000) ){ 132 | last_sent = time; // Update the last_sent variable 133 | // Update the payload (in this case, the last 2 bytes of the frame) 134 | // The rest of the frame (address, etc) does not need to be changed. 135 | // Note: The max value of a byte is 255. Therefore, larger values, 136 | // like ints, must be broken into bytes. 137 | zbp.setFrameData( zbp.getFrameLength()-2, val >> 8 & 0xff ); 138 | zbp.setFrameData( zbp.getFrameLength()-1, val & 0xff ); 139 | Serial.print("\nSend Message: "); 140 | printPacket( zbp ); 141 | // Send the packet. This example does not use the outgoing packet 142 | // object contained in the SimpleZigBeeRadio class. 143 | xbee.send( zbp ); 144 | 145 | val = (val + 10)%500; // Increase val by 10 (start over at 500) 146 | } 147 | 148 | delay(10); // Small delay for stability 149 | // That's it! The router is ready to go. 150 | } 151 | 152 | 153 | ///////////////////////////////////////////////////////////// 154 | // Function for printing the complete contents of a packet // 155 | ///////////////////////////////////////////////////////////// 156 | void printPacket(SimpleZigBeePacket & p){ 157 | Serial.print( START, HEX ); 158 | Serial.print(' '); 159 | Serial.print( p.getLengthMSB(), HEX ); 160 | Serial.print(' '); 161 | Serial.print( p.getLengthLSB(), HEX ); 162 | Serial.print(' '); 163 | // Frame Type and Frame ID are stored in Frame Data 164 | uint8_t checksum = 0; 165 | for( int i=0; i 39 | #include 40 | 41 | // Create the XBee object ... 42 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 43 | // ... and the software serial port. Note: Only one 44 | // SoftwareSerial object can receive data at a time. 45 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 46 | 47 | // Setup check 48 | int check = 0; 49 | 50 | void setup() { 51 | // Start the serial ports ... 52 | Serial.begin( 9600 ); 53 | while( !Serial ){;} // Wait for serial port (for Leonardo only). 54 | xbeeSerial.begin( 9600 ); 55 | // ... and set the serial port for the XBee radio. 56 | xbee.setSerial( xbeeSerial ); 57 | // Receive TX Status packets 58 | xbee.setAcknowledgement(true); 59 | 60 | // To ensure that the radio is in API Mode 2 and is 61 | // operating on the correct PAN ID, you can use the 62 | // AT Commands AP and ID. Note: These changes will 63 | // be stored in volatile memory and will not persist 64 | // if power is lost. 65 | xbee.prepareATCommand('AP',0x02); 66 | xbee.send(); 67 | delay(200); 68 | uint8_t panID[] = {0x12,0x34}; // Max: 64-bit 69 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 70 | xbee.send(); 71 | 72 | // The changes above can be saved to non-volatile memory 73 | // (and will survive power on/off) using the WR command. 74 | // However, the WR command should be used sparingly! 75 | // The EM250 chip inside the XBee only supports a 76 | // limited number of write cycles. 77 | //xbee.prepareATCommand('WR'); 78 | //xbee.send(); 79 | //delay(500); 80 | } 81 | 82 | void loop() { 83 | // If data is waiting in the XBee serial port ... 84 | while( xbee.available() ){ 85 | // ... read the data. 86 | xbee.read(); 87 | // If a complete message is available, check the contents 88 | if( xbee.isComplete() ){ 89 | // Remember, you can use 90 | //SimpleIncomingZigBeePacket zbpIn = xbee.getIncomingPacketObject(); 91 | // to access the incoming packet. However, in this example, 92 | // we will use SimpleZigBeeRadio methods to interpret the 93 | // message. 94 | 95 | Serial.print("\nIncoming Message: "); 96 | printPacket( xbee.getIncomingPacketObject() ); 97 | 98 | // Check the frame type. Currently, the only types 99 | // recognized by the SimpleZigBeeRadio class are 100 | // ZigBee RX Packet (0x90), ZigBee TX Status (0x8b), 101 | // AT Command Response (0x88), Remote AT Command 102 | // Response (0x97), and Modem Status (0x8a). 103 | if( xbee.isRX() ){ 104 | Serial.println( "RX Packet Received" ); 105 | // Methods for RX packets are... 106 | SimpleZigBeeAddress addr = xbee.getRXAddress(); 107 | SimpleZigBeeAddress64 addr64 = xbee.getRXAddress64(); 108 | SimpleZigBeeAddress16 addr16 = xbee.getRXAddress16(); 109 | uint8_t rxOpt = xbee.getRXOptions(); 110 | uint8_t rxLength = xbee.getRXPayloadLength(); 111 | Serial.print( "Payload: " ); 112 | for(int i=0;i 1 ){ 144 | Serial.print( "Payload: " ); 145 | for(int i=0;i 1 ){ 170 | Serial.print( "Payload: " ); 171 | for(int i=0;i 38 | #include 39 | 40 | // Create the XBee object ... 41 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 42 | // ... and the software serial port. Note: Only one 43 | // SoftwareSerial object can receive data at a time. 44 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 45 | 46 | int val = 0; 47 | uint8_t payload[] = {0x00,0x00}; 48 | unsigned long time = 0; 49 | unsigned long last_sent = 0; 50 | 51 | void setup() { 52 | // Start the serial ports ... 53 | Serial.begin( 9600 ); 54 | while( !Serial ){;// Wait for serial port (for Leonardo only). 55 | } 56 | xbeeSerial.begin( 9600 ); 57 | // ... and set the serial port for the XBee radio. 58 | xbee.setSerial( xbeeSerial ); 59 | // Receive TX Status packets 60 | xbee.setAcknowledgement(true); 61 | 62 | // To ensure that the radio is in API Mode 2 and is 63 | // operating on the correct PAN ID, you can use the 64 | // AT Commands AP and ID. Note: These changes will 65 | // be stored in volatile memory and will not persist 66 | // if power is lost. 67 | xbee.prepareATCommand('AP',2); 68 | xbee.send(); 69 | delay(200); 70 | uint8_t panID[] = {0x12,0x34}; // Max: 64-bit 71 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 72 | xbee.send(); 73 | 74 | // The changes above can be saved to non-volatile memory 75 | // (and will survive power on/off) using the WR command. 76 | // However, the WR command should be used sparingly! 77 | // The EM250 chip inside the XBee only supports a 78 | // limited number of write cycles. 79 | //xbee.prepareATCommand('WR'); 80 | //xbee.send(); 81 | //delay(500); 82 | } 83 | 84 | 85 | void loop() { 86 | // If data is waiting in the XBee serial port ... 87 | while( xbee.available() ){ 88 | // ... read the data. 89 | xbee.read(); 90 | // If a complete message is available, display the contents 91 | if( xbee.isComplete() ){ 92 | // Print the contents of the incoming packet 93 | Serial.print("\nIncoming Message: "); 94 | printPacket( xbee.getIncomingPacketObject() ); 95 | } 96 | } 97 | 98 | // The Arduino will send a packet to the XBee once every 5 99 | // seconds. To avoid overflowing the serial buffer, you 100 | // should avoid putting long delays, like delay(5000), 101 | // in a sketch. 102 | time = millis(); 103 | if( time > (last_sent+5000) ){ 104 | last_sent = time; // Update the last_sent variable 105 | payload[0] = val >> 8 & 0xff; 106 | payload[1] = val & 0xff; 107 | // Each SimpleZigBeeRadio objects contains two 108 | // SimpleZigBeePacket objects, one for storing 109 | // incoming messages and one for outgoing messages. 110 | // The SimpleZigBeeRadio class includes several 111 | // methods to make it easy to prepare outgoing packets. 112 | // For example, prepareTXRequestToCoordinator() 113 | // will accept a payload and payload length and will 114 | // set the frame type, frame ID, option, and address. 115 | xbee.prepareTXRequestToCoordinator( payload, 2 ); 116 | 117 | // Other TX methods include: 118 | // setFrameType(uint8_t frameType); 119 | // setFrameID(uint8_t id); 120 | // setAddress(SimpleZigBeeAddress address); 121 | // setAddress(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16); 122 | // setTXRequestBroadcastRadius(uint8_t rad); 123 | // setTXRequestOption(uint8_t opt); 124 | // setTXRequestPayload(uint8_t* payload, int payloadSize); 125 | // prepareTXRequest(uint32_t adr64MSB, uint32_t adr64LSB, uint16_t adr16, uint8_t* payload, int payloadSize); 126 | // prepareTXRequest(SimpleZigBeeAddress address, uint8_t* payload, int payloadSize); 127 | // prepareTXRequestBroadcast(uint8_t* payload, int payloadSize); 128 | 129 | // If no packet is passed to send(), the SimpleZigBeeRadio's 130 | // outgoing packet will be sent. 131 | xbee.send(); 132 | Serial.print("\nSend: "); 133 | printPacket( xbee.getOutgoingPacketObject() ); 134 | val = (val + 10)%500; // Increase val by 10 (start over at 500) 135 | } 136 | 137 | delay(10); // Small delay for stability 138 | // That's it! The router is ready to go. 139 | } 140 | 141 | 142 | ///////////////////////////////////////////////////////////// 143 | // Function for printing the complete contents of a packet // 144 | ///////////////////////////////////////////////////////////// 145 | void printPacket(SimpleZigBeePacket & p){ 146 | Serial.print( START, HEX ); 147 | Serial.print(' '); 148 | Serial.print( p.getLengthMSB(), HEX ); 149 | Serial.print(' '); 150 | Serial.print( p.getLengthLSB(), HEX ); 151 | Serial.print(' '); 152 | // Frame Type and Frame ID are stored in Frame Data 153 | uint8_t checksum = 0; 154 | for( int i=0; i 40 | #include 41 | 42 | // Create the XBee object ... 43 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 44 | // ... and the software serial port. Note: Only one 45 | // SoftwareSerial object can receive data at a time. 46 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 47 | 48 | void setup() { 49 | // Start the serial ports ... 50 | Serial.begin( 9600 ); 51 | while( !Serial ){;// Wait for serial port (for Leonardo only). 52 | } 53 | xbeeSerial.begin( 9600 ); 54 | // ... and set the serial port for the XBee radio. 55 | xbee.setSerial( xbeeSerial ); 56 | // Receive TX Status packets 57 | xbee.setAcknowledgement(true); 58 | 59 | // To ensure that the radio is in API Mode 2 and is 60 | // operating on the correct PAN ID, you can use the 61 | // AT Commands AP and ID. Note: These changes will 62 | // be stored in volatile memory and will not persist 63 | // if power is lost. 64 | xbee.prepareATCommand('AP',2); 65 | xbee.send(); 66 | delay(200); 67 | uint8_t panID[] = {0x12,0x34}; // Max: 64-bit 68 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 69 | xbee.send(); 70 | 71 | } 72 | 73 | 74 | void loop() { 75 | // If data is waiting in the XBee serial port ... 76 | while( xbee.available() ){ 77 | // ... read the data. 78 | xbee.read(); 79 | // If a complete message is available, check the contents 80 | if( xbee.isComplete() ){ 81 | // Print the contents of the incoming packet 82 | Serial.print("\nIncoming Message: "); 83 | printPacket( xbee.getIncomingPacketObject() ); 84 | 85 | // Check the packet type. Currently, the only types 86 | // recognized by the SimpleZigBeeRadio class are 87 | // ZigBee RX Packet (0x90), ZigBee TX Status (0x8b), 88 | // AT Command Response (0x88), Remote AT Command 89 | // Response (0x97), and Modem Status (0x8a). 90 | if( xbee.isRX() ){ 91 | Serial.println( "RX Packet Received" ); 92 | // In this example, we will treat the payload as a list 93 | // of numbers that need to be summed. The Arduino will 94 | // add up the values in the list and return the solution 95 | // to the sender. 96 | Serial.print( "Sum: " ); 97 | int sum = 0; 98 | for(int i=0;i 37 | #include 38 | 39 | // Create the XBee object ... 40 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 41 | // ... and the software serial port. Note: Only one 42 | // SoftwareSerial object can receive data at a time. 43 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 44 | 45 | unsigned long time = 0; 46 | unsigned long last_sent = 0; 47 | int sum = 0; 48 | int check = 0; 49 | 50 | void setup() { 51 | // Start the serial ports ... 52 | Serial.begin( 9600 ); 53 | while( !Serial ){;// Wait for serial port (for Leonardo only). 54 | } 55 | xbeeSerial.begin( 9600 ); 56 | // ... and set the serial port for the XBee radio. 57 | xbee.setSerial( xbeeSerial ); 58 | // Receive TX Status packets 59 | xbee.setAcknowledgement(true); 60 | 61 | // To ensure that the radio is in API Mode 2 and is 62 | // operating on the correct PAN ID, you can use the 63 | // AT Commands AP and ID. Note: These changes will 64 | // be stored in volatile memory and will not persist 65 | // if power is lost. 66 | xbee.prepareATCommand('AP',2); 67 | xbee.send(); 68 | delay(200); 69 | uint8_t panID[] = {0x12,0x34}; // Max: 64-bit 70 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 71 | xbee.send(); 72 | 73 | } 74 | 75 | 76 | void loop() { 77 | // If data is waiting in the XBee serial port ... 78 | while( xbee.available() ){ 79 | // ... read the data. 80 | xbee.read(); 81 | // If a complete message is available, check the contents 82 | if( xbee.isComplete() ){ 83 | // Print the contents of the incoming packet 84 | Serial.print("\nIncoming Message: "); 85 | printPacket( xbee.getIncomingPacketObject() ); 86 | 87 | // Check the packet type. 88 | if( xbee.isRX() ){ 89 | Serial.println( "RX Packet Received" ); 90 | // In this example, we expect the Coordinator to send 91 | // a TX Request containing an integer (2 bytes) in 92 | // the payload. This int should match the sum of 93 | // the numbers last sent by the router. 94 | if( xbee.getRXPayloadLength() == 2 ){ 95 | int payloadVal = (xbee.getRXPayload(0) << 8) + xbee.getRXPayload(1); 96 | 97 | Serial.print( "Received Sum: " ); 98 | Serial.println( payloadVal ); 99 | Serial.print( "Stored Sum: " ); 100 | Serial.println( sum ); 101 | } 102 | }else if( xbee.isTXStatus() ){ 103 | Serial.println( "TX Status Received" ); 104 | Serial.print( "Status: " ); 105 | Serial.println(xbee.getTXStatusDeliveryStatus(),HEX); 106 | 107 | }else if( xbee.isATResponse() ){ 108 | Serial.println( "AT Command Response Received" ); 109 | Serial.print( "Status: " ); 110 | Serial.println(xbee.getATResponseStatus(),HEX); 111 | 112 | }else if( xbee.isRemoteATResponse() ){ 113 | Serial.println( "Remote AT Command Response Received" ); 114 | Serial.print( "Status: " ); 115 | Serial.println(xbee.getRemoteATResponseStatus(),HEX); 116 | 117 | }else if( xbee.isModemStatus() ){ 118 | Serial.println( "Modem Status Received" ); 119 | Serial.print( "Status: " ); 120 | Serial.println(xbee.getModemStatus(),HEX); 121 | 122 | }else{ 123 | // Other or unimplemented frame type 124 | Serial.println( "Other Frame Type" ); 125 | } 126 | } 127 | } 128 | 129 | // The Arduino will send a packet to the XBee once every 5 130 | // seconds. To avoid overflowing the serial buffer, you 131 | // should avoid putting long delays in a sketch and instead 132 | // use other methods of tracking time. 133 | time = millis(); 134 | if( time > (last_sent+5000) ){ 135 | last_sent = time; // Update the last_sent variable 136 | 137 | // Send 3 random numbers (between 0 and 254) to the 138 | // coordinator. 139 | uint8_t payload[3]; 140 | payload[0] = random(255) & 0xff; 141 | payload[1] = random(255) & 0xff; 142 | payload[2] = random(255) & 0xff; 143 | sum = payload[0] + payload[1] + payload[2]; 144 | xbee.prepareTXRequestToCoordinator( payload, sizeof(payload) ); 145 | xbee.send(); 146 | Serial.println(); 147 | Serial.print( "Send: " ); 148 | printPacket( xbee.getOutgoingPacketObject() ); 149 | } 150 | 151 | delay(10); // Small delay for stability 152 | } 153 | 154 | 155 | ///////////////////////////////////////////////////////////// 156 | // Function for printing the complete contents of a packet // 157 | ///////////////////////////////////////////////////////////// 158 | void printPacket(SimpleZigBeePacket & p){ 159 | Serial.print( START, HEX ); 160 | Serial.print(' '); 161 | Serial.print( p.getLengthMSB(), HEX ); 162 | Serial.print(' '); 163 | Serial.print( p.getLengthLSB(), HEX ); 164 | Serial.print(' '); 165 | // Frame Type and Frame ID are stored in Frame Data 166 | uint8_t checksum = 0; 167 | for( int i=0; i 21 | // Create an outgoing packet object. The 22 | // SimpleOutgoingZigBeePacket class inherits 23 | // from the SimpleZigBeePacket class and 24 | // provides useful methods relevant to 25 | // preparing a message. 26 | SimpleOutgoingZigBeePacket zbp = SimpleOutgoingZigBeePacket(); 27 | 28 | void setup() { 29 | Serial.begin( 9600 ); 30 | while( !Serial ){;}// Wait to connect. Needed for Leonardo only 31 | 32 | // To assemble an outgoing packet, 33 | // we will first set the frame type... 34 | zbp.setFrameType(AT_COMMAND); // Same as zbp.setFrameType(0x08) 35 | // ... and the frame id 36 | zbp.setFrameID(0x01); 37 | 38 | // *** CHANGE THIS TO TEST CODE *** // 39 | // Next, set the command. Below are 3 examples 40 | // of AT Commands. Change ex to 0, 1, or 2 41 | // to try a different example. 42 | int ex = 0; 43 | 44 | if( 0 == ex ){ 45 | // The command MY (0x4d,0x59) requests 46 | // the radio's 16-bit network address. 47 | zbp.setATCommand(0x4d59); 48 | }else if( 1 == ex ){ 49 | // The command AP (0x41,0x50) sets the 50 | // API Mode of the radio (1 or 2). 51 | zbp.setATCommand(0x4150); 52 | zbp.setATCommandPayload(0x02); 53 | }else if( 2 == ex ){ 54 | // The command NI (0x4e,0x49) sets 55 | // the Node Identifier string 56 | uint8_t nodeID[] = { 0x4e,0x6f,0x64,0x65,0x49,0x44 }; // "NodeID" 57 | zbp.setATCommand(0x4e49); 58 | zbp.setATCommandPayload(nodeID,sizeof(nodeID)); 59 | } 60 | 61 | // Now that the AT Command packet is complete, 62 | // we will display the contents to the serial port. 63 | printPacket(zbp); 64 | } 65 | 66 | void loop() { 67 | // Do nothing 68 | delay(1000); 69 | } 70 | 71 | // Function for printing the complete contents of a packet 72 | void printPacket(SimpleZigBeePacket & p){ 73 | Serial.print( START, HEX ); 74 | Serial.print(' '); 75 | Serial.print( p.getLengthMSB(), HEX ); 76 | Serial.print(' '); 77 | Serial.print( p.getLengthLSB(), HEX ); 78 | Serial.print(' '); 79 | // Frame Type and Frame ID are stored in Frame Data 80 | uint8_t checksum = 0; 81 | for( int i=0; i 20 | // Create an incoming packet object. The 21 | // SimpleIncomingZigBeePacket class inherits 22 | // from the SimpleZigBeePacket class and 23 | // provides useful methods relevant to 24 | // receiving a message. 25 | SimpleIncomingZigBeePacket zbp = SimpleIncomingZigBeePacket(); 26 | 27 | void setup() { 28 | Serial.begin( 9600 ); 29 | while( !Serial ){;}// Wait to connect. Needed for Leonardo only 30 | 31 | // ################################################### // 32 | // ################################################### // 33 | 34 | // For the sake of example, we will pretend that the 35 | // following data has been successfully received and 36 | // stored in the packet object 37 | 38 | // *** CHANGE THIS TO TEST CODE *** // 39 | int ex = 0; // Change ex to 0, 1, 2, or 3 to try a different example 40 | 41 | if( 0 == ex ){ 42 | uint8_t exFrame[] = { 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xfe,0x00,0x00,0xf1,0xf2,0xf3 }; 43 | zbp.setFrameData(0, exFrame, sizeof(exFrame)); 44 | }else if( 1 == ex ){ 45 | uint8_t exFrame[] = { 0x88,0x01,0x4d,0x59,0x00,0xff,0xfe}; 46 | zbp.setFrameData(0, exFrame, sizeof(exFrame)); 47 | }else if( 2 == ex ){ 48 | uint8_t exFrame[] = { 0x8b,0x01,0x7d,0x84,0x00,0x00,0x01}; 49 | zbp.setFrameData(0, exFrame, sizeof(exFrame)); 50 | }else if( 3 == ex ){ 51 | uint8_t exFrame[] = { 0x8a,0x02}; 52 | zbp.setFrameData(0, exFrame, sizeof(exFrame)); 53 | } 54 | zbp.setChecksum( zbp.calculateChecksum() ); 55 | 56 | // ################################################### // 57 | // ################################################### // 58 | 59 | // We can use a number of methods to figure out what 60 | // is contained in the packet. 61 | Serial.print("Example Packet: "); 62 | printPacket( zbp ); 63 | 64 | // Check the packet type. Currenlty, the recognized types 65 | // are ZigBee Received RX (0x90), AT Command Response (0x88), 66 | // ZigBee Transmit TX Status (0x8b), and Modem Status (0x8a) 67 | uint8_t frameType = zbp.getFrameType(); 68 | Serial.print("Frame Type: "); 69 | Serial.println( frameType, HEX ); 70 | if( frameType == ZIGBEE_RECIEVED_PACKET ){ 71 | 72 | Serial.println( "ZIGBEE_RECIEVED_PACKET" ); 73 | 74 | // Methods specific to RX packets are... 75 | SimpleZigBeeAddress addr = zbp.getRXAddress(); // Get the 64-bit and 16-bit address 76 | uint8_t receiveOptions = zbp.getRXOptions(); 77 | uint8_t payloadLength = zbp.getRXPayloadLength(); 78 | int index = payloadLength - 1; 79 | uint8_t last = zbp.getRXPayload(index); // Search the payload by index 80 | 81 | Serial.print("Payload Length: "); 82 | Serial.println( payloadLength ); 83 | Serial.print("Last Byte of Payload: "); 84 | Serial.println( last, HEX); 85 | 86 | }else if( frameType == AT_COMMAND_RESPONSE ){ 87 | 88 | Serial.println( "AT_COMMAND_RESPONSE" ); 89 | 90 | // Methods specific to AT Command Response packets are... 91 | uint16_t atCmd = zbp.getATResponseCommand(); 92 | uint8_t atStat = zbp.getATResponseStatus(); 93 | uint8_t atLength = zbp.getATResponsePayloadLength(); 94 | int index = atLength - 1; 95 | uint8_t last = zbp.getATResponsePayload(index); 96 | 97 | Serial.print("AT Command: "); 98 | Serial.print( atCmd, HEX ); 99 | // Convert command to characters... 100 | Serial.print( " (" ); 101 | Serial.print( char((atCmd >> 8) & 0xff) ); 102 | Serial.print( char((atCmd) & 0xff) ); 103 | Serial.println( ")" ); 104 | 105 | Serial.print("Command Data Length: "); 106 | Serial.println( atLength ); 107 | Serial.print("Last Byte of Command Data: "); 108 | Serial.println( last, HEX); 109 | 110 | }else if( frameType == ZIGBEE_TX_STATUS ){ 111 | 112 | Serial.println( "ZIGBEE_TX_STATUS" ); 113 | 114 | // Methods specific to TX Status packets are... 115 | SimpleZigBeeAddress16 addr16 = zbp.getTXStatusAddress16(); 116 | uint8_t txRetry = zbp.getTXStatusRetryCount(); 117 | uint8_t txStat = zbp.getTXStatusDeliveryStatus(); 118 | uint8_t txDscovery = zbp.getTXStatusDiscoveryStatus(); 119 | 120 | Serial.print("Transmit Status ( >0 means failure ): "); 121 | Serial.println( txStat ); 122 | Serial.print("Number of retries: "); 123 | Serial.println( txRetry ); 124 | 125 | }else if( frameType == MODEM_STATUS ){ 126 | 127 | Serial.println( "MODEM_STATUS" ); 128 | 129 | // Methods specific to Modem Statuc packets are... 130 | uint8_t modemStat = zbp.getModemStatus(); 131 | Serial.print("Status: "); 132 | Serial.println( modemStat ); 133 | 134 | }else{ 135 | // Unknown or unimplemented frame type 136 | Serial.println( "Unknown Frame Type" ); 137 | } 138 | } 139 | 140 | 141 | void loop() { 142 | // Do nothing 143 | delay(1000); 144 | } 145 | 146 | ///////////////////////////////////////////////////////////// 147 | // Function for printing the complete contents of a packet // 148 | ///////////////////////////////////////////////////////////// 149 | void printPacket(SimpleZigBeePacket & p){ 150 | Serial.print( START, HEX ); 151 | Serial.print(' '); 152 | Serial.print( p.getLengthMSB(), HEX ); 153 | Serial.print(' '); 154 | Serial.print( p.getLengthLSB(), HEX ); 155 | Serial.print(' '); 156 | // Frame Type and Frame ID are stored in Frame Data 157 | uint8_t checksum = 0; 158 | for( int i=0; i 20 | 21 | // Every radio in a ZigBee mesh network has a globally 22 | // unique 64-bit address and a 16-bit address assigned 23 | // by the network. The SimpleZigBeeAddress class 24 | // makes it easy to store this information for use 25 | // in an Arduino sketch. For consistency, all 26 | // addresses will be shown in their hexadecimal 27 | // (base 16) form. 28 | 29 | // Create a SimpleZigBeeAddress object. If no address is given, 30 | // the constructor will assign the broadcast addresses: 31 | // - 64-bit address of 0x000000000000ffff 32 | // - 16-bit address of 0xfffe 33 | SimpleZigBeeAddress addrOne = SimpleZigBeeAddress(); 34 | 35 | // The Arduino UNO cannot create variables larger 36 | // than 32-bits (4 bytes). Therefore, to express a 37 | // 64-bit address, we need 2 variables. msb represents 38 | // the most significant bytes and lsb represents the 39 | // least significant bytes of the 64-bit address. 40 | // The SimpleZigBeeAddress class uses the inttype 41 | // library (inttypes.h) to create 32-bit (uint32_t), 42 | // 16-bit (uint16_t), and 8-byte (uint8_t) variables. 43 | uint32_t msb64 = 0x0013a200; 44 | uint32_t lsb64 = 0x40a8bb63; 45 | 46 | // Create another SimpleZigBeeAddress object. Again, 47 | // we have not given a 16-bit address, therefore 48 | // the 16-bit broadcast address is assigned. 49 | SimpleZigBeeAddress addrTwo = SimpleZigBeeAddress( msb64, lsb64 ); 50 | 51 | uint16_t addr16 = 0xf3a9; 52 | // Create one more SimpleZigBeeAddress object. 53 | // This time, set a 16-bit address. 54 | SimpleZigBeeAddress addrThree = SimpleZigBeeAddress( msb64, lsb64, addr16 ); 55 | 56 | void setup() { 57 | Serial.begin( 9600 ); 58 | while( !Serial ){;}// Wait to connect. Needed for Leonardo only 59 | 60 | Serial.println("Demo of SimpleZigBeeAddress classes and methods"); 61 | Serial.println(); 62 | 63 | // The 64-bit address can be accessed using the 64 | // getAddress64() method, which returns a 65 | // SimpleZigBeeAddress64 object. 66 | SimpleZigBeeAddress64 addr64 = addrThree.getAddress64(); 67 | // The getAddress16() method returns a 68 | // SimpleZigBeeAddress16 object. 69 | SimpleZigBeeAddress16 addr16 = addrThree.getAddress16(); 70 | // Store address data in variables. 71 | uint32_t msb = addr64.getAddressMSB(); // Most significant bytes 72 | uint32_t lsb = addr64.getAddressLSB(); // Least significant bytes 73 | uint16_t addr = addr16.getAddress(); 74 | 75 | 76 | // Print addresses for addrThree 77 | Serial.print( "64-bit address of addrThree is: " ); 78 | Serial.print( msb, HEX ); // Print the address in HEX form 79 | Serial.print( lsb, HEX ); 80 | Serial.println(); 81 | Serial.print( "16-bit address of addrThree is: " ); 82 | Serial.print( addr, HEX ); 83 | Serial.println(); 84 | Serial.println(); 85 | // Notice that using "Serial.print( msb, HEX );" 86 | // caused the leading zeros to be dropped. 87 | // I have written the printFullAddress() function 88 | // to check each byte and to print every zero. 89 | 90 | 91 | // Print addresses for addrOne 92 | Serial.print( "64-bit address of addrOne is: " ); 93 | printFullAddress( addrOne.getAddress64().getAddressMSB(), 4 ); 94 | printFullAddress( addrOne.getAddress64().getAddressLSB(), 4 ); 95 | Serial.println(); 96 | Serial.print( "16-bit address of addrOne is: " ); 97 | printFullAddress( addrOne.getAddress16().getAddress(), 2 ); 98 | Serial.println(); 99 | Serial.println(); 100 | 101 | Serial.println("Assign new values to addrOne"); 102 | // The address can be changed using the setAddress64() 103 | // and setAddress16() methods. 104 | // Pass a SimpleZigBeeAddress64 object... 105 | addrOne.setAddress64( addr64 ); 106 | // ...or pass the 32-bit msb and 32-bit lsb of the address 107 | addrOne.setAddress64( msb, lsb ); 108 | // Pass a SimpleZigBeeAddress16 object... 109 | addrOne.setAddress16( addr16 ); 110 | // ...or pass the 16-bit address 111 | addrOne.setAddress16( addr ); 112 | 113 | // Print new addresses for addrOne 114 | Serial.print( "64-bit address of addrOne is now: " ); 115 | printFullAddress( addrOne.getAddress64().getAddressMSB(), 4 ); // Print the address in HEX form 116 | printFullAddress( addrOne.getAddress64().getAddressLSB(), 4 ); 117 | Serial.println(); 118 | Serial.print( "16-bit address of addrOne is now: " ); 119 | printFullAddress( addrOne.getAddress16().getAddress(), 2 ); 120 | Serial.println(); 121 | Serial.println(); 122 | Serial.println( "End of Demo" ); 123 | } 124 | 125 | void loop() { 126 | // Do nothing 127 | delay(1000); 128 | } 129 | 130 | // Function for printing every byte of an address (including leading zeros). 131 | void printFullAddress( uint32_t addr, int bytes ){ 132 | for(int i=0;i> 8*i) & 0xf0) == 0 ){ 134 | Serial.print( 0 ); 135 | Serial.print( ((addr >> 8*i) & 0xf), HEX ); 136 | }else{ 137 | Serial.print( ((addr >> 8*i) & 0xff), HEX ); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /examples/SimpleZigBeePacketExamples/SimpleZigBeePacket/SimpleZigBeePacket.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SimpleZigBeePacket class example 3 | 4 | This sketch demonstrates how to use the 5 | SimpleZigBeePacket class to store data that has 6 | been received from or will be sent to an XBee 7 | radio. The SimpleZigBeeAddress class does not 8 | interact with the XBee radio and thus it is 9 | not necessary to connect a radio to run 10 | this example code. 11 | 12 | created 27 June 2014 13 | by Eric Burger 14 | 15 | This example code is in the public domain. 16 | 17 | */ 18 | 19 | #include 20 | // Create a packet object. When you create a packet, 21 | // the Arduino allocates 4 bytes of memory to store 22 | // the frame data. As you add to the content in the 23 | // packet, the memory allocation is expanded, as 24 | // necessary, up to a maximum of 50 bytes (default max 25 | // packet frame length is 50). Some of the frame data, 26 | // such as the start delimiter, packet length, and checksum, 27 | // are not stored in the memory. Therefore, the actual 28 | // packet length will be larger than the frame length. 29 | SimpleZigBeePacket zbpOne = SimpleZigBeePacket(); 30 | 31 | // The max memory allocation can be changed by passing 32 | // an int to the constructor. However, note that the 33 | // Arduino serial port buffer is 64 bytes. Therefore, 34 | // you may be able to send larger packets but you will 35 | // not be able to receive them. 36 | SimpleZigBeePacket zbpTwo = SimpleZigBeePacket(40); 37 | 38 | // Below is an example of a frame where: 39 | // Frame type = 0x10 (ZigBee Transmit Request) 40 | // Frame id = 0x01 41 | // 64-bit destination address = 0x0000000000000000 (Coordinator address) 42 | // 16-bit destination address = 0xfffe (unknown or broadcast) 43 | // Broadcast radius = 0x00 44 | // Options = 0x00 45 | // Payload data = 0xff 46 | uint8_t exFrame[] = { 0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xfe,0x00,0x00,0xff }; 47 | 48 | void setup() { 49 | Serial.begin( 9600 ); 50 | while( !Serial ){;}// Wait to connect. Needed for Leonardo only 51 | 52 | // Now store the example frame in a packet object. 53 | // The setFrameData() method accepts a starting index 54 | // (where to start in the packet memory), an array, 55 | // and the array's length (number of bytes to store). 56 | zbpOne.setFrameData( 0, exFrame, sizeof(exFrame)); 57 | 58 | // Below are several examples of methods for 59 | // recalling information stored in the packet... 60 | Serial.print("Frame Type: "); 61 | Serial.println( zbpOne.getFrameType(), HEX ); 62 | Serial.print("Frame ID: "); 63 | Serial.println( zbpOne.getFrameID(), HEX ); 64 | 65 | // ...and for getting non-frame information. 66 | Serial.print("Frame Length: "); 67 | Serial.println( zbpOne.getFrameLength() ); 68 | Serial.print("Checksum: "); 69 | Serial.println( zbpOne.calculateChecksum(), HEX ); 70 | Serial.println(); 71 | 72 | // Here is a functions for printing the entire 73 | // packet (frame + non-frame data). 74 | Serial.print("Packet One: "); 75 | printPacket(zbpOne); 76 | 77 | // You can also get and set a specific index of 78 | // the frame data. 79 | Serial.print("Frame Payload: "); 80 | Serial.println( zbpOne.getFrameData( zbpOne.getFrameLength()-1 ), HEX ); 81 | Serial.println("Change Payload... "); 82 | uint8_t newPayload = 0xaa; 83 | zbpOne.setFrameData( zbpOne.getFrameLength()-1 , newPayload ); 84 | Serial.println("Change Frame ID... "); 85 | zbpOne.setFrameData( 1, 0x05 ); 86 | Serial.print("Packet One: "); 87 | printPacket(zbpOne); 88 | Serial.println(); 89 | 90 | // Last, the SimpleZigBeePacket class can report 91 | // if an error has occur. 92 | // The Error Codes are: 93 | // NO_ERROR = 0 94 | // ERROR_REALLOCATING_MEMORY = 1 95 | // UNEXPECTED_PACKET_START = 2 96 | // PACKET_INCOMPLETE = 3 97 | // MAX_FRAME_LENGTH_EXCEEDED = 4 98 | // FRAME_LENGTH_EXCEEDED = 5 99 | // CHECKSUM_FAILURE = 6 100 | 101 | // For example, if we try to access data that 102 | // is outside the frame, 103 | zbpOne.getFrameData( zbpOne.getFrameLength()+5 ); 104 | // we can see that an error will be reported. 105 | Serial.print("Error Check: "); 106 | Serial.println( zbpOne.isError()); 107 | Serial.print("Error Code: "); 108 | Serial.println( zbpOne.getErrorCode() ); 109 | 110 | Serial.println(); 111 | Serial.println(); 112 | Serial.println( "End of Demo" ); 113 | } 114 | 115 | 116 | void loop() { 117 | // Do nothing 118 | delay(1000); 119 | } 120 | 121 | // Function for printing the complete contents of a packet 122 | void printPacket(SimpleZigBeePacket & p){ 123 | Serial.print( START, HEX ); 124 | Serial.print(' '); 125 | Serial.print( p.getLengthMSB(), HEX ); 126 | Serial.print(' '); 127 | Serial.print( p.getLengthLSB(), HEX ); 128 | Serial.print(' '); 129 | // Frame Type and Frame ID are stored in Frame Data 130 | uint8_t checksum = 0; 131 | for( int i=0; i 20 | // Create an outgoing packet object. The 21 | // SimpleOutgoingZigBeePacket class inherits 22 | // from the SimpleZigBeePacket class and 23 | // provides useful methods relevant to 24 | // preparing a message. 25 | SimpleOutgoingZigBeePacket zbp = SimpleOutgoingZigBeePacket(); 26 | 27 | void setup() { 28 | Serial.begin( 9600 ); 29 | while( !Serial ){;}// Wait to connect. Needed for Leonardo only 30 | 31 | // To assemble an outgoing packet, 32 | // we will first set the frame type... 33 | zbp.setFrameType(ZIGBEE_TRANSMIT_REQUEST); // Same as zbp.setFrameType(0x10) 34 | // ...and the frame id 35 | zbp.setFrameID(0x01); 36 | 37 | // Next, set the destination address 38 | // (in this example, the coordinator address). 39 | // You can pass a SimpleZigBeeAddress object ... 40 | SimpleZigBeeAddress coorAddr = SimpleZigBeeAddress(0x00000000,0x00000000,0xfffe); 41 | zbp.setAddress(coorAddr); 42 | // ... or directly set the address. 43 | zbp.setAddress(0x00000000,0x00000000,0xfffe); 44 | // Note: 0x00000000 is the same as 0. I have 45 | // written 0x00000000 to show that the functions 46 | // accept a 32-bit, 32-bit, and 16-bit value. 47 | 48 | // Next, set the Broadcast Radius and Option 49 | // (A radius of 0 means unlimited jumps). 50 | zbp.setTXRequestBroadcastRadius(0x00); 51 | zbp.setTXRequestOption(0x00); 52 | 53 | // Finally, set the payload. 54 | uint8_t exPayload[] = { 0xa1,0xa2,0xa3 }; 55 | zbp.setTXRequestPayload( exPayload, sizeof(exPayload) ); // Same as zbp.setPayload( exPayload, 3 ); 56 | 57 | // Now that the TX packet is complete, 58 | // we will display the contents to the serial port. 59 | printPacket(zbp); 60 | } 61 | 62 | void loop() { 63 | // Do nothing 64 | delay(1000); 65 | } 66 | 67 | // Function for printing the complete contents of a packet 68 | void printPacket(SimpleZigBeePacket & p){ 69 | Serial.print( START, HEX ); 70 | Serial.print(' '); 71 | Serial.print( p.getLengthMSB(), HEX ); 72 | Serial.print(' '); 73 | Serial.print( p.getLengthLSB(), HEX ); 74 | Serial.print(' '); 75 | // Frame Type and Frame ID are stored in Frame Data 76 | uint8_t checksum = 0; 77 | for( int i=0; i 32 | #include 33 | 34 | // Create the XBee object ... 35 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 36 | // ... and the software serial port. Note: Only one 37 | // SoftwareSerial object can receive data at a time. 38 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 39 | 40 | // Setup check 41 | int check = 0; 42 | 43 | void setup() { 44 | // Start the serial ports ... 45 | Serial.begin( 9600 ); 46 | while( !Serial ){;// Wait for serial port (for Leonardo only). 47 | } 48 | xbeeSerial.begin( 9600 ); 49 | // ... and set the serial port for the XBee radio. 50 | xbee.setSerial( xbeeSerial ); 51 | // Set a non-zero frame id to receive Status and Response packets. 52 | xbee.setAcknowledgement(true); 53 | } 54 | 55 | void loop() { 56 | // If data is waiting in the XBee serial port ... 57 | while( xbee.available() ){ 58 | // ... read the data. 59 | xbee.read(); 60 | // If a complete message is available, check the contents 61 | if( xbee.isComplete() ){ 62 | 63 | Serial.print("\nIncoming Message: "); 64 | printPacket( xbee.getIncomingPacketObject() ); 65 | 66 | if( xbee.isATResponse() ){ 67 | Serial.println( "AT Command Response Packet" ); 68 | // Methods specific to AT Command Response packets are... 69 | uint8_t frameID = xbee.getIncomingFrameID(); 70 | uint16_t atCmd = xbee.getATResponseCommand(); 71 | uint8_t atStat = xbee.getATResponseStatus(); 72 | uint8_t atLength = xbee.getATResponsePayloadLength(); 73 | 74 | // Below are the possible AT Response Status Values 75 | // AT_COMMAND_STATUS_OK = 0x00 76 | // AT_COMMAND_STATUS_ERROR = 0x01 77 | // AT_COMMAND_STATUS_INVALID_COMMAND = 0x02 78 | // AT_COMMAND_STATUS_INVALID_PARAMETER = 0x03 79 | // AT_COMMAND_STATUS_TX_FAILURE = 0x04 80 | 81 | Serial.print("AT Command: "); 82 | Serial.println( atCmd, HEX ); 83 | 84 | if( atCmd == 'ID' ){ 85 | if( atLength > 0 ){ 86 | Serial.print("PAN ID: "); 87 | for(int i=0;i 0 ){ 102 | Serial.print("API Mode: "); 103 | Serial.println( xbee.getATResponsePayload(0), HEX); 104 | }else if( atStat == AT_COMMAND_STATUS_OK ){ 105 | Serial.println("API Mode Set"); 106 | }else if( atStat == AT_COMMAND_STATUS_ERROR ){ 107 | Serial.println("Error While Setting API Mode"); 108 | }else{ 109 | Serial.print("AT Command Error: "); 110 | Serial.println(atStat); 111 | } 112 | } 113 | 114 | }else{ 115 | Serial.println( "Other Frame Type" ); 116 | } 117 | } 118 | } 119 | 120 | delay(10); // Small delay for stability 121 | 122 | // Below are examples of using AT Commands to set and 123 | // check the API Mode and the PAN ID. 124 | if( check < 5){ 125 | if( check == 0 ){ 126 | // To ensure that the radio is in API Mode 2 and is 127 | // operating on the correct PAN ID, you can use the 128 | // AT Commands AP and ID. Note: These changes will 129 | // be stored in volitile memory and will not persist 130 | // if power is lost. 131 | Serial.println(); 132 | Serial.println( "Set API Mode (AP2)" ); 133 | xbee.prepareATCommand('AP',2); 134 | //printPacket( xbee.getOutgoingPacketObject() ); 135 | xbee.send(); 136 | }else if( check == 1){ 137 | Serial.println(); 138 | Serial.println( "Set the PAN ID" ); 139 | uint8_t panID[] = {0x12,0x34}; // Max: 64-bit 140 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 141 | //printPacket( xbee.getOutgoingPacketObject() ); 142 | xbee.send(); 143 | }else if( check == 2){ 144 | // Since changes were made to the radio's settings, 145 | // below are a fews checks to verify that the changes 146 | // were applied. 147 | Serial.println(); 148 | Serial.println( "Send command to check API Mode (AP)" ); 149 | xbee.prepareATCommand('AP'); 150 | //printPacket( xbee.getOutgoingPacketObject() ); 151 | xbee.send(); 152 | }else if( check == 3){ 153 | Serial.println(); 154 | Serial.println( "Send command to check PAN ID (ID)" ); 155 | xbee.prepareATCommand('ID'); 156 | //printPacket( xbee.getOutgoingPacketObject() ); 157 | xbee.send(); 158 | } 159 | check++; 160 | delay(2000); 161 | } 162 | } 163 | 164 | 165 | ///////////////////////////////////////////////////////////// 166 | // Function for printing the complete contents of a packet // 167 | ///////////////////////////////////////////////////////////// 168 | void printPacket(SimpleZigBeePacket & p){ 169 | Serial.print( START, HEX ); 170 | Serial.print(' '); 171 | Serial.print( p.getLengthMSB(), HEX ); 172 | Serial.print(' '); 173 | Serial.print( p.getLengthLSB(), HEX ); 174 | Serial.print(' '); 175 | // Frame Type and Frame ID are stored in Frame Data 176 | uint8_t checksum = 0; 177 | for( int i=0; i 35 | #include 36 | 37 | // Create the XBee object ... 38 | SimpleZigBeeRadio xbee = SimpleZigBeeRadio(); 39 | // ... and the software serial port. Note: Only one 40 | // SoftwareSerial object can receive data at a time. 41 | SoftwareSerial xbeeSerial(10, 11); // (RX=>DOUT, TX=>DIN) 42 | 43 | // Setup check 44 | int check = 0; 45 | 46 | void setup() { 47 | // Start the serial ports ... 48 | Serial.begin( 9600 ); 49 | while( !Serial ){;// Wait for serial port (for Leonardo only). 50 | } 51 | xbeeSerial.begin( 9600 ); 52 | // ... and set the serial port for the XBee radio. 53 | xbee.setSerial( xbeeSerial ); 54 | // Set a non-zero frame id to receive Status and Response packets. 55 | xbee.setAcknowledgement(true); 56 | // Random seed (for random PAN ID) 57 | randomSeed(analogRead(0)); 58 | } 59 | 60 | 61 | void loop() { 62 | // If data is waiting in the XBee serial port ... 63 | while( xbee.available() ){ 64 | // ... read the data. 65 | xbee.read(); 66 | // If a complete message is available, check the contents 67 | if( xbee.isComplete() ){ 68 | Serial.println(); 69 | Serial.print("Incoming Message: "); 70 | printPacket( xbee.getIncomingPacketObject() ); 71 | 72 | if( xbee.isModemStatus() ){ 73 | Serial.print("Modem Status: "); 74 | uint8_t mStat = xbee.getModemStatus(); 75 | 76 | // Below is an incomplete list of modem status values: 77 | // MODEM_STATUS_HARDWARE_RESET = 0x00 78 | // MODEM_STATUS_WATCHDOG_TIMER_RESET = 0x01 79 | // MODEM_STATUS_JOINED_NETWORK = 0x02 80 | // MODEM_STATUS_DISASSOCIATED = 0x03 81 | // MODEM_STATUS_COORDINATOR_STARTED = 0x06 82 | 83 | if( mStat == MODEM_STATUS_HARDWARE_RESET ){ 84 | Serial.println("Hardware Reset"); 85 | }else if( mStat == MODEM_STATUS_JOINED_NETWORK ){ 86 | Serial.println("Network Joined"); 87 | }else if( mStat == MODEM_STATUS_DISASSOCIATED ){ 88 | Serial.println("Disassociated"); 89 | }else if( mStat == MODEM_STATUS_COORDINATOR_STARTED ){ 90 | Serial.println("Coordinator Started"); 91 | }else{ 92 | Serial.print("Code "); 93 | Serial.println(mStat); 94 | } 95 | 96 | }else if( xbee.isATResponse() ){ 97 | Serial.println( "AT Command Response Packet" ); 98 | uint16_t atCmd = xbee.getATResponseCommand(); 99 | uint8_t atStat = xbee.getATResponseStatus(); 100 | uint8_t atLength = xbee.getATResponsePayloadLength(); 101 | 102 | //Serial.print("AT Command: "); 103 | //Serial.println( atCmd, HEX ); 104 | 105 | if( atCmd == 'ID' ){ 106 | if( atLength > 0 ){ 107 | Serial.print("PAN ID: "); 108 | for(int i=0;i 0 ){ 123 | Serial.print("API Mode: "); 124 | Serial.println( xbee.getATResponsePayload(0), HEX); 125 | }else if( atStat == AT_COMMAND_STATUS_OK ){ 126 | Serial.println("API Mode Set"); 127 | }else if( atStat == AT_COMMAND_STATUS_ERROR ){ 128 | Serial.println("Error While Setting API Mode"); 129 | }else{ 130 | Serial.print("AT Command Error: "); 131 | Serial.println(atStat); 132 | } 133 | } 134 | 135 | }else{ 136 | Serial.println( "Other Frame Type" ); 137 | } 138 | } 139 | } 140 | 141 | delay(10); // Small delay for stability 142 | 143 | // Send a series of AT Commands which will 144 | // change the Modem Status. 145 | if( check < 7 ){ 146 | if( check == 0 ){ 147 | Serial.println(); 148 | Serial.println( "Send command to leave network (CB4)" ); 149 | xbee.prepareATCommand('CB',4); 150 | xbee.send(); 151 | delay(5000); 152 | }else if( check == 1){ 153 | Serial.println(); 154 | Serial.println( "Set API Mode (AP2)" ); 155 | xbee.prepareATCommand('AP',2); 156 | xbee.send(); 157 | }else if( check == 2 ){ 158 | Serial.println(); 159 | Serial.println( "Send command to check PAN ID (ID)" ); 160 | xbee.prepareATCommand('ID'); 161 | xbee.send(); 162 | }else if( check == 3){ 163 | Serial.println(); 164 | Serial.print( "Set random PAN ID: " ); 165 | uint8_t panID[] = {uint8_t(random(255)),uint8_t(random(255))}; 166 | Serial.print( panID[0], HEX ); 167 | Serial.println( panID[1], HEX ); 168 | xbee.prepareATCommand('ID',panID,sizeof(panID)); 169 | xbee.send(); 170 | delay(5000); 171 | }else if( check == 4){ 172 | Serial.println(); 173 | Serial.println( "Send command to check PAN ID (ID)" ); 174 | xbee.prepareATCommand('ID'); 175 | xbee.send(); 176 | }else if( check == 5){ 177 | Serial.println(); 178 | Serial.println( "Send command to check API Mode (AP)" ); 179 | xbee.prepareATCommand('AP'); 180 | xbee.send(); 181 | }else if( check == 6){ 182 | Serial.println(); 183 | Serial.println( "Power the XBee off and on to see Hardware Reset notice." ); 184 | } 185 | check++; 186 | delay(2000); 187 | } 188 | 189 | } 190 | 191 | 192 | ///////////////////////////////////////////////////////////// 193 | // Function for printing the complete contents of a packet // 194 | ///////////////////////////////////////////////////////////// 195 | void printPacket(SimpleZigBeePacket & p){ 196 | Serial.print( START, HEX ); 197 | Serial.print(' '); 198 | Serial.print( p.getLengthMSB(), HEX ); 199 | Serial.print(' '); 200 | Serial.print( p.getLengthLSB(), HEX ); 201 | Serial.print(' '); 202 | // Frame Type and Frame ID are stored in Frame Data 203 | uint8_t checksum = 0; 204 | for( int i=0; i