Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 49.05 KB | None | 0 0
  1. /**
  2. * Copyright (c) 2009 Andrew Rapp. All rights reserved.
  3. *
  4. * This file is part of XBee-Arduino.
  5. *
  6. * XBee-Arduino is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * XBee-Arduino is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with XBee-Arduino. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19.  
  20. //#include "XBee.h"
  21. #include </home/pi/Documents/Software/DCS_unit_Threaded/Xbee_THREADED_Library/Xbee.h>
  22.  
  23. /*
  24. #if defined(ARDUINO) && ARDUINO >= 100
  25. #include "Arduino.h"
  26. #else
  27. #include "WProgram.h"
  28. #endif
  29. */
  30. //#include "HardwareSerial.h"
  31.  
  32. ///
  33.  
  34. //#include <SerialStream.h>
  35. //#include <sstream>
  36. //#include <string>
  37. ///
  38. //using namespace LibSerial;
  39.  
  40. LibSerial::SerialStream serial_port_xbee;
  41.  
  42. ///
  43.  
  44. XBeeResponse::XBeeResponse() {
  45.  
  46. }
  47.  
  48. uint8_t XBeeResponse::getApiId() {
  49. return _apiId;
  50. }
  51.  
  52. void XBeeResponse::setApiId(uint8_t apiId) {
  53. _apiId = apiId;
  54. }
  55.  
  56. uint8_t XBeeResponse::getMsbLength() {
  57. return _msbLength;
  58. }
  59.  
  60. void XBeeResponse::setMsbLength(uint8_t msbLength) {
  61. _msbLength = msbLength;
  62. }
  63.  
  64. uint8_t XBeeResponse::getLsbLength() {
  65. return _lsbLength;
  66. }
  67.  
  68. void XBeeResponse::setLsbLength(uint8_t lsbLength) {
  69. _lsbLength = lsbLength;
  70. }
  71.  
  72. uint8_t XBeeResponse::getChecksum() {
  73. return _checksum;
  74. }
  75.  
  76. void XBeeResponse::setChecksum(uint8_t checksum) {
  77. _checksum = checksum;
  78. }
  79.  
  80. uint8_t XBeeResponse::getFrameDataLength() {
  81. return _frameLength;
  82. }
  83.  
  84. void XBeeResponse::setFrameLength(uint8_t frameLength) {
  85. _frameLength = frameLength;
  86. }
  87.  
  88. bool XBeeResponse::isAvailable() {
  89. return _complete;
  90. }
  91.  
  92. void XBeeResponse::setAvailable(bool complete) {
  93. _complete = complete;
  94. }
  95.  
  96. bool XBeeResponse::isError() {
  97. return _errorCode > 0;
  98. }
  99.  
  100. uint8_t XBeeResponse::getErrorCode() {
  101. return _errorCode;
  102. }
  103.  
  104. void XBeeResponse::setErrorCode(uint8_t errorCode) {
  105. _errorCode = errorCode;
  106. }
  107.  
  108. // copy common fields from xbee response to target response
  109. void XBeeResponse::setCommon(XBeeResponse &target) {
  110. target.setApiId(getApiId());
  111. target.setAvailable(isAvailable());
  112. target.setChecksum(getChecksum());
  113. target.setErrorCode(getErrorCode());
  114. target.setFrameLength(getFrameDataLength());
  115. target.setMsbLength(getMsbLength());
  116. target.setLsbLength(getLsbLength());
  117. }
  118.  
  119. #ifdef SERIES_2
  120.  
  121. ZBTxStatusResponse::ZBTxStatusResponse() : FrameIdResponse() {
  122.  
  123. }
  124.  
  125. uint16_t ZBTxStatusResponse::getRemoteAddress() {
  126. return (getFrameData()[1] << 8) + getFrameData()[2];
  127. }
  128.  
  129. uint8_t ZBTxStatusResponse::getTxRetryCount() {
  130. return getFrameData()[3];
  131. }
  132.  
  133. uint8_t ZBTxStatusResponse::getDeliveryStatus() {
  134. return getFrameData()[4];
  135. }
  136.  
  137. uint8_t ZBTxStatusResponse::getDiscoveryStatus() {
  138. return getFrameData()[5];
  139. }
  140.  
  141. bool ZBTxStatusResponse::isSuccess() {
  142. return getDeliveryStatus() == SUCCESS;
  143. }
  144.  
  145. void XBeeResponse::getZBTxStatusResponse(XBeeResponse &zbXBeeResponse) {
  146.  
  147. // way off?
  148. ZBTxStatusResponse* zb = static_cast<ZBTxStatusResponse*>(&zbXBeeResponse);
  149. // pass pointer array to subclass
  150. zb->setFrameData(getFrameData());
  151. setCommon(zbXBeeResponse);
  152. }
  153.  
  154. ZBRxResponse::ZBRxResponse(): RxDataResponse() {
  155. _remoteAddress64 = XBeeAddress64();
  156. }
  157.  
  158. uint16_t ZBRxResponse::getRemoteAddress16() {
  159. return (getFrameData()[8] << 8) + getFrameData()[9];
  160. }
  161.  
  162. uint8_t ZBRxResponse::getOption() {
  163. return getFrameData()[10];
  164. }
  165.  
  166. // markers to read data from packet array. this is the index, so the 12th item in the array
  167. uint8_t ZBRxResponse::getDataOffset() {
  168. return 11;
  169. }
  170.  
  171. uint8_t ZBRxResponse::getDataLength() {
  172. return getPacketLength() - getDataOffset() - 1;
  173. }
  174.  
  175. XBeeAddress64& ZBRxResponse::getRemoteAddress64() {
  176. return _remoteAddress64;
  177. }
  178.  
  179. void XBeeResponse::getZBRxResponse(XBeeResponse &rxResponse) {
  180.  
  181. ZBRxResponse* zb = static_cast<ZBRxResponse*>(&rxResponse);
  182.  
  183. //TODO verify response api id matches this api for this response
  184.  
  185. // pass pointer array to subclass
  186. zb->setFrameData(getFrameData());
  187. setCommon(rxResponse);
  188.  
  189. zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  190. zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
  191. }
  192.  
  193. ZBExplicitRxResponse::ZBExplicitRxResponse(): ZBRxResponse() {
  194. }
  195.  
  196. uint8_t ZBExplicitRxResponse::getSrcEndpoint() {
  197. return getFrameData()[10];
  198. }
  199.  
  200. uint8_t ZBExplicitRxResponse::getDstEndpoint() {
  201. return getFrameData()[11];
  202. }
  203.  
  204. uint16_t ZBExplicitRxResponse::getClusterId() {
  205. return (uint16_t)(getFrameData()[12]) << 8 | getFrameData()[13];
  206. }
  207.  
  208. uint16_t ZBExplicitRxResponse::getProfileId() {
  209. return (uint16_t)(getFrameData()[14]) << 8 | getFrameData()[15];
  210. }
  211.  
  212. uint8_t ZBExplicitRxResponse::getOption() {
  213. return getFrameData()[16];
  214. }
  215.  
  216. // markers to read data from packet array.
  217. uint8_t ZBExplicitRxResponse::getDataOffset() {
  218. return 17;
  219. }
  220.  
  221. uint8_t ZBExplicitRxResponse::getDataLength() {
  222. return getPacketLength() - getDataOffset() - 1;
  223. }
  224.  
  225. void XBeeResponse::getZBExplicitRxResponse(XBeeResponse &rxResponse) {
  226. // Nothing to add to that
  227. getZBRxResponse(rxResponse);
  228. }
  229.  
  230.  
  231. ZBRxIoSampleResponse::ZBRxIoSampleResponse() : ZBRxResponse() {
  232.  
  233. }
  234.  
  235. // 64 + 16 addresses, sample size, option = 12 (index 11), so this starts at 12
  236. uint8_t ZBRxIoSampleResponse::getDigitalMaskMsb() {
  237. return getFrameData()[12] & 0x1c;
  238. }
  239.  
  240. uint8_t ZBRxIoSampleResponse::getDigitalMaskLsb() {
  241. return getFrameData()[13];
  242. }
  243.  
  244. uint8_t ZBRxIoSampleResponse::getAnalogMask() {
  245. return getFrameData()[14] & 0x8f;
  246. }
  247.  
  248. bool ZBRxIoSampleResponse::containsAnalog() {
  249. return getAnalogMask() > 0;
  250. }
  251.  
  252. bool ZBRxIoSampleResponse::containsDigital() {
  253. return getDigitalMaskMsb() > 0 || getDigitalMaskLsb() > 0;
  254. }
  255.  
  256. bool ZBRxIoSampleResponse::isAnalogEnabled(uint8_t pin) {
  257. return ((getAnalogMask() >> pin) & 1) == 1;
  258. }
  259.  
  260. bool ZBRxIoSampleResponse::isDigitalEnabled(uint8_t pin) {
  261. if (pin <= 7) {
  262. // added extra parens to calm avr compiler
  263. return ((getDigitalMaskLsb() >> pin) & 1) == 1;
  264. } else {
  265. return ((getDigitalMaskMsb() >> (pin - 8)) & 1) == 1;
  266. }
  267. }
  268.  
  269. uint16_t ZBRxIoSampleResponse::getAnalog(uint8_t pin) {
  270. // analog starts 13 bytes after sample size, if no dio enabled
  271. uint8_t start = 15;
  272.  
  273. if (containsDigital()) {
  274. // make room for digital i/o
  275. start+=2;
  276. }
  277.  
  278. // start depends on how many pins before this pin are enabled
  279. for (int i = 0; i < pin; i++) {
  280. if (isAnalogEnabled(i)) {
  281. start+=2;
  282. }
  283. }
  284.  
  285. return (uint16_t)((getFrameData()[start] << 8) + getFrameData()[start + 1]);
  286. }
  287.  
  288. bool ZBRxIoSampleResponse::isDigitalOn(uint8_t pin) {
  289. if (pin <= 7) {
  290. // D0-7
  291. // DIO LSB is index 5
  292. return ((getFrameData()[16] >> pin) & 1) == 1;
  293. } else {
  294. // D10-12
  295. // DIO MSB is index 4
  296. return ((getFrameData()[15] >> (pin - 8)) & 1) == 1;
  297. }
  298. }
  299.  
  300. void XBeeResponse::getZBRxIoSampleResponse(XBeeResponse &response) {
  301. ZBRxIoSampleResponse* zb = static_cast<ZBRxIoSampleResponse*>(&response);
  302.  
  303.  
  304. // pass pointer array to subclass
  305. zb->setFrameData(getFrameData());
  306. setCommon(response);
  307.  
  308. zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  309. zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
  310. }
  311.  
  312. #endif
  313.  
  314. #ifdef SERIES_1
  315.  
  316. RxResponse::RxResponse() : RxDataResponse() {
  317.  
  318. }
  319.  
  320. uint16_t Rx16Response::getRemoteAddress16() {
  321. return (getFrameData()[0] << 8) + getFrameData()[1];
  322. }
  323.  
  324. XBeeAddress64& Rx64Response::getRemoteAddress64() {
  325. return _remoteAddress;
  326. }
  327.  
  328. Rx64Response::Rx64Response() : RxResponse() {
  329. _remoteAddress = XBeeAddress64();
  330. }
  331.  
  332. Rx16Response::Rx16Response() : RxResponse() {
  333.  
  334. }
  335.  
  336. RxIoSampleBaseResponse::RxIoSampleBaseResponse() : RxResponse() {
  337.  
  338. }
  339.  
  340. uint8_t RxIoSampleBaseResponse::getSampleOffset() {
  341. // sample starts 2 bytes after rssi
  342. return getRssiOffset() + 2;
  343. }
  344.  
  345.  
  346. uint8_t RxIoSampleBaseResponse::getSampleSize() {
  347. return getFrameData()[getSampleOffset()];
  348. }
  349.  
  350. bool RxIoSampleBaseResponse::containsAnalog() {
  351. return (getFrameData()[getSampleOffset() + 1] & 0x7e) > 0;
  352. }
  353.  
  354. bool RxIoSampleBaseResponse::containsDigital() {
  355. return (getFrameData()[getSampleOffset() + 1] & 0x1) > 0 || getFrameData()[getSampleOffset() + 2] > 0;
  356. }
  357.  
  358. //uint16_t RxIoSampleBaseResponse::getAnalog0(uint8_t sample) {
  359. // return getAnalog(0, sample);
  360. //}
  361.  
  362. bool RxIoSampleBaseResponse::isAnalogEnabled(uint8_t pin) {
  363. return (((getFrameData()[getSampleOffset() + 1] >> (pin + 1)) & 1) == 1);
  364. }
  365.  
  366. bool RxIoSampleBaseResponse::isDigitalEnabled(uint8_t pin) {
  367. if (pin < 8) {
  368. return ((getFrameData()[getSampleOffset() + 2] >> pin) & 1) == 1;
  369. } else {
  370. return (getFrameData()[getSampleOffset() + 1] & 1) == 1;
  371. }
  372. }
  373.  
  374. // // verified (from XBee-API)
  375. // private int getSampleWidth() {
  376. // int width = 0;
  377. //
  378. // // width of sample depends on how many I/O pins are enabled. add one for each analog that's enabled
  379. // for (int i = 0; i <= 5; i++) {
  380. // if (isAnalogEnabled(i)) {
  381. // // each analog is two bytes
  382. // width+=2;
  383. // }
  384. // }
  385. //
  386. // if (this.containsDigital()) {
  387. // // digital enabled takes two bytes, no matter how many pins enabled
  388. // width+= 2;
  389. // }
  390. //
  391. // return width;
  392. // }
  393. //
  394. // private int getStartIndex() {
  395. //
  396. // int startIndex;
  397. //
  398. // if (this.getSourceAddress() instanceof XBeeAddress16) {
  399. // // 16 bit
  400. // startIndex = 7;
  401. // } else {
  402. // // 64 bit
  403. // startIndex = 13;
  404. // }
  405. //
  406. // return startIndex;
  407. // }
  408. //
  409. // public int getDigitalMsb(int sample) {
  410. // // msb digital always starts 3 bytes after sample size
  411. // return this.getProcessedPacketBytes()[this.getStartIndex() + 3 + this.getSampleWidth() * sample];
  412. // }
  413. //
  414. // public int getDigitalLsb(int sample) {
  415. // return this.getProcessedPacketBytes()[this.getStartIndex() + 3 + this.getSampleWidth() * sample + 1];
  416. // }
  417. //
  418. // public Boolean isDigitalOn(int pin, int sample) {
  419. //
  420. // if (sample < 0 || sample >= this.getSampleSize()) {
  421. // throw new IllegalArgumentException("invalid sample size: " + sample);
  422. // }
  423. //
  424. // if (!this.containsDigital()) {
  425. // throw new RuntimeException("Digital is not enabled");
  426. // }
  427. //
  428. // if (pin >= 0 && pin < 8) {
  429. // return ((this.getDigitalLsb(sample) >> pin) & 1) == 1;
  430. // } else if (pin == 8) {
  431. // // uses msb dio line
  432. // return (this.getDigitalMsb(sample) & 1) == 1;
  433. // } else {
  434. // throw new IllegalArgumentException("Invalid pin: " + pin);
  435. // }
  436. // }
  437. //
  438. // public Integer getAnalog(int pin, int sample) {
  439. //
  440. // if (sample < 0 || sample >= this.getSampleSize()) {
  441. // throw new IllegalArgumentException("invalid sample size: " + sample);
  442. // }
  443. //
  444. // // analog starts 3 bytes after start of sample, if no dio enabled
  445. // int startIndex = this.getStartIndex() + 3;
  446. //
  447. // if (this.containsDigital()) {
  448. // // make room for digital i/o sample (2 bytes per sample)
  449. // startIndex+= 2;
  450. // }
  451. //
  452. // startIndex+= this.getSampleWidth() * sample;
  453. //
  454. // // start depends on how many pins before this pin are enabled
  455. // // this will throw illegalargumentexception if invalid pin
  456. // for (int i = 0; i < pin; i++) {
  457. // if (isAnalogEnabled(i)) {
  458. // startIndex+=2;
  459. // }
  460. // }
  461. //
  462. // return (this.getProcessedPacketBytes()[startIndex] << 8) + this.getProcessedPacketBytes()[startIndex + 1];
  463. // }
  464.  
  465. uint8_t RxIoSampleBaseResponse::getSampleStart(uint8_t sample) {
  466. uint8_t spacing = 0;
  467.  
  468. if (containsDigital()) {
  469. // make room for digital i/o sample (2 bytes per sample)
  470. spacing += 2;
  471. }
  472.  
  473. // spacing between samples depends on how many are enabled. add
  474. // 2 bytes for each analog that's enabled
  475. for (int i = 0; i <= 5; i++) {
  476. if (isAnalogEnabled(i)) {
  477. // each analog is two bytes
  478. spacing+=2;
  479. }
  480. }
  481.  
  482. // Skip 3-byte header and "sample" full samples
  483. return getSampleOffset() + 3 + sample * spacing;
  484. }
  485.  
  486. uint16_t RxIoSampleBaseResponse::getAnalog(uint8_t pin, uint8_t sample) {
  487. uint8_t start = getSampleStart(sample);
  488.  
  489. if (containsDigital()) {
  490. // Skip digital sample info
  491. start += 2;
  492. }
  493.  
  494. // Skip any analog samples before this pin
  495. for (int i = 0; i < pin; i++) {
  496. if (isAnalogEnabled(i)) {
  497. start+=2;
  498. }
  499. }
  500.  
  501. return (uint16_t)((getFrameData()[start] << 8) + getFrameData()[start + 1]);
  502. }
  503.  
  504. bool RxIoSampleBaseResponse::isDigitalOn(uint8_t pin, uint8_t sample) {
  505. if (pin < 8) {
  506. return ((getFrameData()[getSampleStart(sample) + 1] >> pin) & 1) == 1;
  507. } else {
  508. return (getFrameData()[getSampleStart(sample)] & 1) == 1;
  509. }
  510. }
  511.  
  512.  
  513. //bool RxIoSampleBaseResponse::isDigital0On(uint8_t sample) {
  514. // return isDigitalOn(0, sample);
  515. //}
  516.  
  517. Rx16IoSampleResponse::Rx16IoSampleResponse() : RxIoSampleBaseResponse() {
  518.  
  519. }
  520.  
  521. uint16_t Rx16IoSampleResponse::getRemoteAddress16() {
  522. return (uint16_t)((getFrameData()[0] << 8) + getFrameData()[1]);
  523. }
  524.  
  525. uint8_t Rx16IoSampleResponse::getRssiOffset() {
  526. return 2;
  527. }
  528.  
  529. void XBeeResponse::getRx16IoSampleResponse(XBeeResponse &response) {
  530. Rx16IoSampleResponse* rx = static_cast<Rx16IoSampleResponse*>(&response);
  531.  
  532. rx->setFrameData(getFrameData());
  533. setCommon(response);
  534. }
  535.  
  536.  
  537. Rx64IoSampleResponse::Rx64IoSampleResponse() : RxIoSampleBaseResponse() {
  538. _remoteAddress = XBeeAddress64();
  539. }
  540.  
  541. XBeeAddress64& Rx64IoSampleResponse::getRemoteAddress64() {
  542. return _remoteAddress;
  543. }
  544.  
  545. uint8_t Rx64IoSampleResponse::getRssiOffset() {
  546. return 8;
  547. }
  548.  
  549. void XBeeResponse::getRx64IoSampleResponse(XBeeResponse &response) {
  550. Rx64IoSampleResponse* rx = static_cast<Rx64IoSampleResponse*>(&response);
  551.  
  552. rx->setFrameData(getFrameData());
  553. setCommon(response);
  554.  
  555. rx->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  556. rx->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
  557. }
  558.  
  559. TxStatusResponse::TxStatusResponse() : FrameIdResponse() {
  560.  
  561. }
  562.  
  563. uint8_t TxStatusResponse::getStatus() {
  564. return getFrameData()[1];
  565. }
  566.  
  567. bool TxStatusResponse::isSuccess() {
  568. return getStatus() == SUCCESS;
  569. }
  570.  
  571. void XBeeResponse::getTxStatusResponse(XBeeResponse &txResponse) {
  572.  
  573. TxStatusResponse* txStatus = static_cast<TxStatusResponse*>(&txResponse);
  574.  
  575. // pass pointer array to subclass
  576. txStatus->setFrameData(getFrameData());
  577. setCommon(txResponse);
  578. }
  579.  
  580. uint8_t RxResponse::getRssi() {
  581. return getFrameData()[getRssiOffset()];
  582. }
  583.  
  584. uint8_t RxResponse::getOption() {
  585. return getFrameData()[getRssiOffset() + 1];
  586. }
  587.  
  588. bool RxResponse::isAddressBroadcast() {
  589. return (getOption() & 2) == 2;
  590. }
  591.  
  592. bool RxResponse::isPanBroadcast() {
  593. return (getOption() & 4) == 4;
  594. }
  595.  
  596. uint8_t RxResponse::getDataLength() {
  597. return getPacketLength() - getDataOffset() - 1;
  598. }
  599.  
  600. uint8_t RxResponse::getDataOffset() {
  601. return getRssiOffset() + 2;
  602. }
  603.  
  604. uint8_t Rx16Response::getRssiOffset() {
  605. return RX_16_RSSI_OFFSET;
  606. }
  607.  
  608. void XBeeResponse::getRx16Response(XBeeResponse &rx16Response) {
  609.  
  610. Rx16Response* rx16 = static_cast<Rx16Response*>(&rx16Response);
  611.  
  612. // pass pointer array to subclass
  613. rx16->setFrameData(getFrameData());
  614. setCommon(rx16Response);
  615. }
  616.  
  617. uint8_t Rx64Response::getRssiOffset() {
  618. return RX_64_RSSI_OFFSET;
  619. }
  620.  
  621. void XBeeResponse::getRx64Response(XBeeResponse &rx64Response) {
  622.  
  623. Rx64Response* rx64 = static_cast<Rx64Response*>(&rx64Response);
  624.  
  625. // pass pointer array to subclass
  626. rx64->setFrameData(getFrameData());
  627. setCommon(rx64Response);
  628.  
  629. rx64->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  630. rx64->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
  631. }
  632.  
  633. #endif
  634.  
  635. RemoteAtCommandResponse::RemoteAtCommandResponse() : AtCommandResponse() {
  636.  
  637. }
  638.  
  639. uint8_t* RemoteAtCommandResponse::getCommand() {
  640. return getFrameData() + 11;
  641. }
  642.  
  643. uint8_t RemoteAtCommandResponse::getStatus() {
  644. return getFrameData()[13];
  645. }
  646.  
  647. bool RemoteAtCommandResponse::isOk() {
  648. // weird c++ behavior. w/o this method, it calls AtCommandResponse::isOk(), which calls the AtCommandResponse::getStatus, not this.getStatus!!!
  649. return getStatus() == AT_OK;
  650. }
  651.  
  652. uint8_t RemoteAtCommandResponse::getValueLength() {
  653. return getFrameDataLength() - 14;
  654. }
  655.  
  656. uint8_t* RemoteAtCommandResponse::getValue() {
  657. if (getValueLength() > 0) {
  658. // value is only included for query commands. set commands does not return a value
  659. return getFrameData() + 14;
  660. }
  661.  
  662. return NULL;
  663. }
  664.  
  665. uint16_t RemoteAtCommandResponse::getRemoteAddress16() {
  666. return uint16_t((getFrameData()[9] << 8) + getFrameData()[10]);
  667. }
  668.  
  669. XBeeAddress64& RemoteAtCommandResponse::getRemoteAddress64() {
  670. return _remoteAddress64;
  671. }
  672.  
  673. void XBeeResponse::getRemoteAtCommandResponse(XBeeResponse &response) {
  674.  
  675. // TODO no real need to cast. change arg to match expected class
  676. RemoteAtCommandResponse* at = static_cast<RemoteAtCommandResponse*>(&response);
  677.  
  678. // pass pointer array to subclass
  679. at->setFrameData(getFrameData());
  680. setCommon(response);
  681.  
  682. at->getRemoteAddress64().setMsb((uint32_t(getFrameData()[1]) << 24) + (uint32_t(getFrameData()[2]) << 16) + (uint16_t(getFrameData()[3]) << 8) + getFrameData()[4]);
  683. at->getRemoteAddress64().setLsb((uint32_t(getFrameData()[5]) << 24) + (uint32_t(getFrameData()[6]) << 16) + (uint16_t(getFrameData()[7]) << 8) + (getFrameData()[8]));
  684.  
  685. }
  686.  
  687. RxDataResponse::RxDataResponse() : XBeeResponse() {
  688.  
  689. }
  690.  
  691. uint8_t RxDataResponse::getData(int index) {
  692. return getFrameData()[getDataOffset() + index];
  693. }
  694.  
  695. uint8_t* RxDataResponse::getData() {
  696. return getFrameData() + getDataOffset();
  697. }
  698.  
  699. FrameIdResponse::FrameIdResponse() {
  700.  
  701. }
  702.  
  703. uint8_t FrameIdResponse::getFrameId() {
  704. return getFrameData()[0];
  705. }
  706.  
  707.  
  708. ModemStatusResponse::ModemStatusResponse() {
  709.  
  710. }
  711.  
  712. uint8_t ModemStatusResponse::getStatus() {
  713. return getFrameData()[0];
  714. }
  715.  
  716. void XBeeResponse::getModemStatusResponse(XBeeResponse &modemStatusResponse) {
  717.  
  718. ModemStatusResponse* modem = static_cast<ModemStatusResponse*>(&modemStatusResponse);
  719.  
  720. // pass pointer array to subclass
  721. modem->setFrameData(getFrameData());
  722. setCommon(modemStatusResponse);
  723.  
  724. }
  725.  
  726. AtCommandResponse::AtCommandResponse() {
  727.  
  728. }
  729.  
  730. uint8_t* AtCommandResponse::getCommand() {
  731. return getFrameData() + 1;
  732. }
  733.  
  734. uint8_t AtCommandResponse::getStatus() {
  735. return getFrameData()[3];
  736. }
  737.  
  738. uint8_t AtCommandResponse::getValueLength() {
  739. return getFrameDataLength() - 4;
  740. }
  741.  
  742. uint8_t* AtCommandResponse::getValue() {
  743. if (getValueLength() > 0) {
  744. // value is only included for query commands. set commands does not return a value
  745. return getFrameData() + 4;
  746. }
  747.  
  748. return NULL;
  749. }
  750.  
  751. bool AtCommandResponse::isOk() {
  752. return getStatus() == AT_OK;
  753. }
  754.  
  755. void XBeeResponse::getAtCommandResponse(XBeeResponse &atCommandResponse) {
  756.  
  757. AtCommandResponse* at = static_cast<AtCommandResponse*>(&atCommandResponse);
  758.  
  759. // pass pointer array to subclass
  760. at->setFrameData(getFrameData());
  761. setCommon(atCommandResponse);
  762. }
  763.  
  764. uint16_t XBeeResponse::getPacketLength() {
  765. return ((_msbLength << 8) & 0xff) + (_lsbLength & 0xff);
  766. }
  767.  
  768. uint8_t* XBeeResponse::getFrameData() {
  769. return _frameDataPtr;
  770. }
  771.  
  772. void XBeeResponse::setFrameData(uint8_t* frameDataPtr) {
  773. _frameDataPtr = frameDataPtr;
  774. }
  775.  
  776. void XBeeResponse::init() {
  777. _complete = false;
  778. _errorCode = NO_ERROR;
  779. _checksum = 0;
  780. }
  781.  
  782. void XBeeResponse::reset() {
  783. init();
  784. _apiId = 0;
  785. _msbLength = 0;
  786. _lsbLength = 0;
  787. _checksum = 0;
  788. _frameLength = 0;
  789.  
  790. _errorCode = NO_ERROR;
  791. }
  792.  
  793. void XBee::resetResponse() {
  794. _pos = 0;
  795. _escape = false;
  796. _checksumTotal = 0;
  797. _response.reset();
  798. }
  799.  
  800. XBee::XBee(): _response(XBeeResponse()) {
  801. _pos = 0;
  802. _escape = false;
  803. _checksumTotal = 0;
  804. _nextFrameId = 0;
  805.  
  806. _response.init();
  807. _response.setFrameData(_responseFrameData);
  808. // Contributed by Paul Stoffregen for Teensy support
  809. /*
  810. #if defined(__AVR_ATmega32U4__) || (defined(TEENSYDUINO) && (defined(KINETISK) || defined(KINETISL)))
  811. _serial = &Serial1;
  812. #else
  813. _serial = &Serial;
  814. #endif
  815. */
  816. }
  817.  
  818. uint8_t XBee::getNextFrameId() {
  819.  
  820. _nextFrameId++;
  821.  
  822. if (_nextFrameId == 0) {
  823. // can't send 0 because that disables status response
  824. _nextFrameId = 1;
  825. }
  826.  
  827. return _nextFrameId;
  828. }
  829.  
  830. // Support for SoftwareSerial. Contributed by Paul Stoffregen
  831. /*
  832. void XBee::begin(SerialStream &serial) {
  833. _serial = &serial;
  834. }
  835.  
  836.  
  837.  
  838. void XBee::setSerial(SerialStream &serial) {
  839. _serial = &serial;
  840. }
  841. */
  842.  
  843. bool XBee::available() {
  844. return serial_port_xbee.rdbuf()->in_avail();
  845.  
  846. }
  847.  
  848. ///CAUTION!! ADD MUTEX maybe
  849. uint8_t serial_received;
  850. void* XbeeSerialThread(void* param)
  851. {
  852. uint8_t* received = (uint8_t* )param;
  853. serial_port_xbee >> (*received);
  854. std::cout<<"Started XBee Thread No.: "<<pthread_self()<<std::endl;
  855. pthread_exit(nullptr); ///for now!!
  856.  
  857. }
  858.  
  859. uint8_t XBee::read()
  860. {
  861.  
  862. pthread_t xbee_serial;
  863. uint8_t received_serial;
  864. int status = pthread_create(&xbee_serial, nullptr, XbeeSerialThread, &received_serial);
  865. if(status)
  866. std::cout<<"XBEE LIB ERROR PTHREAD CREATE: "<<status<<std::endl;
  867.  
  868.  
  869. ////////////////
  870.  
  871. /// TIMED JOIN
  872. struct timespec ts;
  873. int s = 0;
  874. if(clock_gettime(CLOCK_REALTIME, &ts)== -1)
  875. {
  876. std::cout<<"TIME ERROR"<<std::endl;
  877.  
  878. }
  879. ts.tv_sec += 3;
  880. ////////////////////////
  881. s = pthread_timedjoin_np(xbee_serial, nullptr, &ts);
  882.  
  883.  
  884. if(s != 0)
  885. {
  886. std::cout<<"THREAD NOT JOINED"<<std::endl;
  887. received_serial = 0xd8; /// SO IT WOULDN*T BE EMPTY : Ø character (something we don't send through xbee, marks an error)
  888. }
  889. else
  890. {
  891. std::cout<<"JOINED THREAD XBEE"<<std::endl;
  892. }
  893. // pthread_cancel(xbee_serial);
  894.  
  895. ///////
  896.  
  897.  
  898. //usleep(100000);
  899. return received_serial;
  900.  
  901.  
  902.  
  903.  
  904.  
  905. }
  906.  
  907. void XBee::write(uint8_t val) {
  908. serial_port_xbee << val;
  909. }
  910.  
  911. XBeeResponse& XBee::getResponse() {
  912. return _response;
  913. }
  914.  
  915. // TODO how to convert response to proper subclass?
  916. void XBee::getResponse(XBeeResponse &response) {
  917.  
  918. response.setMsbLength(_response.getMsbLength());
  919. response.setLsbLength(_response.getLsbLength());
  920. response.setApiId(_response.getApiId());
  921. response.setFrameLength(_response.getFrameDataLength());
  922.  
  923. response.setFrameData(_response.getFrameData());
  924. }
  925.  
  926. void XBee::readPacketUntilAvailable() {
  927. while (!(getResponse().isAvailable() || getResponse().isError())) {
  928. // read some more
  929. readPacket();
  930. }
  931. }
  932.  
  933.  
  934. /// TO BE IMPLEMENTED LATER...TIMED READPACKET
  935.  
  936. bool XBee::readPacket(int timeout) {
  937.  
  938. /*
  939. if (timeout < 0) {
  940. return false;
  941. }
  942.  
  943. unsigned long start = millis();
  944.  
  945. while (int((millis() - start)) < timeout) {
  946.  
  947. readPacket();
  948.  
  949. if (getResponse().isAvailable()) {
  950. return true;
  951. } else if (getResponse().isError()) {
  952. return false;
  953. }
  954. }
  955.  
  956. // timed out
  957. */
  958. return false;
  959.  
  960. }
  961. ///
  962. void XBee::readPacket() {
  963. // reset previous response
  964. if (_response.isAvailable() || _response.isError()) {
  965. // discard previous packet and start over
  966. resetResponse();
  967. }
  968.  
  969. while (serial_port_xbee.rdbuf()->in_avail() >= 0)
  970. {
  971.  
  972. b = read();
  973. if(b == 0xd8)
  974. break;
  975.  
  976. if (_pos > 0 && b == START_BYTE && ATAP == 2) {
  977. // new packet start before previous packeted completed -- discard previous packet and start over
  978. _response.setErrorCode(UNEXPECTED_START_BYTE);
  979. return;
  980. }
  981.  
  982. if (_pos > 0 && b == ESCAPE) {
  983. if (available()) {
  984. b = read();
  985. b = 0x20 ^ b;
  986. } else {
  987. // escape byte. next byte will be
  988. _escape = true;
  989. continue;
  990. }
  991. }
  992.  
  993. if (_escape == true) {
  994. b = 0x20 ^ b;
  995. _escape = false;
  996. }
  997.  
  998. // checksum includes all bytes starting with api id
  999. if (_pos >= API_ID_INDEX) {
  1000. _checksumTotal+= b;
  1001. }
  1002.  
  1003. switch(_pos) {
  1004. case 0:
  1005. if (b == START_BYTE) {
  1006. _pos++;
  1007. }
  1008.  
  1009. break;
  1010. case 1:
  1011. // length msb
  1012. _response.setMsbLength(b);
  1013. _pos++;
  1014.  
  1015. break;
  1016. case 2:
  1017. // length lsb
  1018. _response.setLsbLength(b);
  1019. _pos++;
  1020.  
  1021. break;
  1022. case 3:
  1023. _response.setApiId(b);
  1024. _pos++;
  1025.  
  1026. break;
  1027. default:
  1028. // starts at fifth byte
  1029.  
  1030. if (_pos > MAX_FRAME_DATA_SIZE) {
  1031. // exceed max size. should never occur
  1032. _response.setErrorCode(PACKET_EXCEEDS_BYTE_ARRAY_LENGTH);
  1033. return;
  1034. }
  1035.  
  1036. // check if we're at the end of the packet
  1037. // packet length does not include start, length, or checksum bytes, so add 3
  1038. if (_pos == (_response.getPacketLength() + 3)) {
  1039. // verify checksum
  1040.  
  1041. if ((_checksumTotal & 0xff) == 0xff) {
  1042. _response.setChecksum(b);
  1043. _response.setAvailable(true);
  1044.  
  1045. _response.setErrorCode(NO_ERROR);
  1046. } else {
  1047. // checksum failed
  1048. _response.setErrorCode(CHECKSUM_FAILURE);
  1049. }
  1050.  
  1051. // minus 4 because we start after start,msb,lsb,api and up to but not including checksum
  1052. // e.g. if frame was one byte, _pos=4 would be the byte, pos=5 is the checksum, where end stop reading
  1053. _response.setFrameLength(_pos - 4);
  1054.  
  1055. // reset state vars
  1056. _pos = 0;
  1057.  
  1058. return;
  1059. } else {
  1060. // add to packet array, starting with the fourth byte of the apiFrame
  1061. _response.getFrameData()[_pos - 4] = b;
  1062. _pos++;
  1063. }
  1064. }
  1065. } /// WHILE AVAIL >=
  1066. }
  1067.  
  1068. // it's peanut butter jelly time!!
  1069.  
  1070. XBeeRequest::XBeeRequest(uint8_t apiId, uint8_t frameId) {
  1071. _apiId = apiId;
  1072. _frameId = frameId;
  1073. }
  1074.  
  1075. void XBeeRequest::setFrameId(uint8_t frameId) {
  1076. _frameId = frameId;
  1077. }
  1078.  
  1079. uint8_t XBeeRequest::getFrameId() {
  1080. return _frameId;
  1081. }
  1082.  
  1083. uint8_t XBeeRequest::getApiId() {
  1084. return _apiId;
  1085. }
  1086.  
  1087. void XBeeRequest::setApiId(uint8_t apiId) {
  1088. _apiId = apiId;
  1089. }
  1090.  
  1091. //void XBeeRequest::reset() {
  1092. // _frameId = DEFAULT_FRAME_ID;
  1093. //}
  1094.  
  1095. //uint8_t XBeeRequest::getPayloadOffset() {
  1096. // return _payloadOffset;
  1097. //}
  1098. //
  1099. //uint8_t XBeeRequest::setPayloadOffset(uint8_t payloadOffset) {
  1100. // _payloadOffset = payloadOffset;
  1101. //}
  1102.  
  1103.  
  1104. PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength) : XBeeRequest(apiId, frameId) {
  1105. _payloadPtr = payload;
  1106. _payloadLength = payloadLength;
  1107. }
  1108.  
  1109. uint8_t* PayloadRequest::getPayload() {
  1110. return _payloadPtr;
  1111. }
  1112.  
  1113. void PayloadRequest::setPayload(uint8_t* payload) {
  1114. _payloadPtr = payload;
  1115. }
  1116.  
  1117. uint8_t PayloadRequest::getPayloadLength() {
  1118. return _payloadLength;
  1119. }
  1120.  
  1121. void PayloadRequest::setPayloadLength(uint8_t payloadLength) {
  1122. _payloadLength = payloadLength;
  1123. }
  1124.  
  1125. #ifdef SERIES_2
  1126.  
  1127. ZBTxRequest::ZBTxRequest() : PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  1128. _addr16 = ZB_BROADCAST_ADDRESS;
  1129. _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS;
  1130. _option = ZB_TX_UNICAST;
  1131. }
  1132.  
  1133. ZBTxRequest::ZBTxRequest(const XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId): PayloadRequest(ZB_TX_REQUEST, frameId, data, dataLength) {
  1134. _addr64 = addr64;
  1135. _addr16 = addr16;
  1136. _broadcastRadius = broadcastRadius;
  1137. _option = option;
  1138. }
  1139.  
  1140. ZBTxRequest::ZBTxRequest(const XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  1141. _addr64 = addr64;
  1142. _addr16 = ZB_BROADCAST_ADDRESS;
  1143. _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS;
  1144. _option = ZB_TX_UNICAST;
  1145. }
  1146.  
  1147. uint8_t ZBTxRequest::getFrameData(uint8_t pos) {
  1148. if (pos == 0) {
  1149. return (_addr64.getMsb() >> 24) & 0xff;
  1150. } else if (pos == 1) {
  1151. return (_addr64.getMsb() >> 16) & 0xff;
  1152. } else if (pos == 2) {
  1153. return (_addr64.getMsb() >> 8) & 0xff;
  1154. } else if (pos == 3) {
  1155. return _addr64.getMsb() & 0xff;
  1156. } else if (pos == 4) {
  1157. return (_addr64.getLsb() >> 24) & 0xff;
  1158. } else if (pos == 5) {
  1159. return (_addr64.getLsb() >> 16) & 0xff;
  1160. } else if (pos == 6) {
  1161. return (_addr64.getLsb() >> 8) & 0xff;
  1162. } else if (pos == 7) {
  1163. return _addr64.getLsb() & 0xff;
  1164. } else if (pos == 8) {
  1165. return (_addr16 >> 8) & 0xff;
  1166. } else if (pos == 9) {
  1167. return _addr16 & 0xff;
  1168. } else if (pos == 10) {
  1169. return _broadcastRadius;
  1170. } else if (pos == 11) {
  1171. return _option;
  1172. } else {
  1173. return getPayload()[pos - ZB_TX_API_LENGTH];
  1174. }
  1175. }
  1176.  
  1177. uint8_t ZBTxRequest::getFrameDataLength() {
  1178. return ZB_TX_API_LENGTH + getPayloadLength();
  1179. }
  1180.  
  1181. XBeeAddress64& ZBTxRequest::getAddress64() {
  1182. return _addr64;
  1183. }
  1184.  
  1185. uint16_t ZBTxRequest::getAddress16() {
  1186. return _addr16;
  1187. }
  1188.  
  1189. uint8_t ZBTxRequest::getBroadcastRadius() {
  1190. return _broadcastRadius;
  1191. }
  1192.  
  1193. uint8_t ZBTxRequest::getOption() {
  1194. return _option;
  1195. }
  1196.  
  1197. void ZBTxRequest::setAddress64(const XBeeAddress64& addr64) {
  1198. _addr64 = addr64;
  1199. }
  1200.  
  1201. void ZBTxRequest::setAddress16(uint16_t addr16) {
  1202. _addr16 = addr16;
  1203. }
  1204.  
  1205. void ZBTxRequest::setBroadcastRadius(uint8_t broadcastRadius) {
  1206. _broadcastRadius = broadcastRadius;
  1207. }
  1208.  
  1209. void ZBTxRequest::setOption(uint8_t option) {
  1210. _option = option;
  1211. }
  1212.  
  1213.  
  1214.  
  1215. ZBExplicitTxRequest::ZBExplicitTxRequest() : ZBTxRequest() {
  1216. _srcEndpoint = DEFAULT_ENDPOINT;
  1217. _dstEndpoint = DEFAULT_ENDPOINT;
  1218. _profileId = DEFAULT_PROFILE_ID;
  1219. _clusterId = DEFAULT_CLUSTER_ID;
  1220. setApiId(ZB_EXPLICIT_TX_REQUEST);
  1221. }
  1222.  
  1223. ZBExplicitTxRequest::ZBExplicitTxRequest(XBeeAddress64 &addr64, uint16_t addr16, uint8_t broadcastRadius, uint8_t option, uint8_t *payload, uint8_t payloadLength, uint8_t frameId, uint8_t srcEndpoint, uint8_t dstEndpoint, uint16_t clusterId, uint16_t profileId)
  1224. : ZBTxRequest(addr64, addr16, broadcastRadius, option, payload, payloadLength, frameId) {
  1225. _srcEndpoint = srcEndpoint;
  1226. _dstEndpoint = dstEndpoint;
  1227. _profileId = profileId;
  1228. _clusterId = clusterId;
  1229. setApiId(ZB_EXPLICIT_TX_REQUEST);
  1230. }
  1231.  
  1232. ZBExplicitTxRequest::ZBExplicitTxRequest(XBeeAddress64 &addr64, uint8_t *payload, uint8_t payloadLength)
  1233. : ZBTxRequest(addr64, payload, payloadLength) {
  1234. _srcEndpoint = DEFAULT_ENDPOINT;
  1235. _dstEndpoint = DEFAULT_ENDPOINT;
  1236. _profileId = DEFAULT_PROFILE_ID;
  1237. _clusterId = DEFAULT_CLUSTER_ID;
  1238. setApiId(ZB_EXPLICIT_TX_REQUEST);
  1239. }
  1240.  
  1241. uint8_t ZBExplicitTxRequest::getFrameData(uint8_t pos) {
  1242. if (pos < 10) {
  1243. return ZBTxRequest::getFrameData(pos);
  1244. } else if (pos == 10) {
  1245. return _srcEndpoint;
  1246. } else if (pos == 11) {
  1247. return _dstEndpoint;
  1248. } else if (pos == 12) {
  1249. return (_clusterId >> 8) & 0xff;
  1250. } else if (pos == 13) {
  1251. return _clusterId & 0xff;
  1252. } else if (pos == 14) {
  1253. return (_profileId >> 8) & 0xff;
  1254. } else if (pos == 15) {
  1255. return _profileId & 0xff;
  1256. } else if (pos == 16) {
  1257. return _broadcastRadius;
  1258. } else if (pos == 17) {
  1259. return _option;
  1260. } else {
  1261. return getPayload()[pos - ZB_EXPLICIT_TX_API_LENGTH];
  1262. }
  1263. }
  1264.  
  1265. uint8_t ZBExplicitTxRequest::getFrameDataLength() {
  1266. return ZB_EXPLICIT_TX_API_LENGTH + getPayloadLength();
  1267. }
  1268.  
  1269. uint8_t ZBExplicitTxRequest::getSrcEndpoint() {
  1270. return _srcEndpoint;
  1271. }
  1272.  
  1273. uint8_t ZBExplicitTxRequest::getDstEndpoint() {
  1274. return _dstEndpoint;
  1275. }
  1276.  
  1277. uint16_t ZBExplicitTxRequest::getClusterId() {
  1278. return _clusterId;
  1279. }
  1280.  
  1281. uint16_t ZBExplicitTxRequest::getProfileId() {
  1282. return _profileId;
  1283. }
  1284.  
  1285. void ZBExplicitTxRequest::setSrcEndpoint(uint8_t endpoint) {
  1286. _srcEndpoint = endpoint;
  1287. }
  1288.  
  1289. void ZBExplicitTxRequest::setDstEndpoint(uint8_t endpoint) {
  1290. _dstEndpoint = endpoint;
  1291. }
  1292.  
  1293. void ZBExplicitTxRequest::setClusterId(uint16_t clusterId) {
  1294. _clusterId = clusterId;
  1295. }
  1296.  
  1297. void ZBExplicitTxRequest::setProfileId(uint16_t profileId) {
  1298. _profileId = profileId;
  1299. }
  1300. #endif
  1301.  
  1302. #ifdef SERIES_1
  1303.  
  1304. Tx16Request::Tx16Request() : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  1305. _option = ACK_OPTION;
  1306. }
  1307.  
  1308. Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) {
  1309. _addr16 = addr16;
  1310. _option = option;
  1311. }
  1312.  
  1313. Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  1314. _addr16 = addr16;
  1315. _option = ACK_OPTION;
  1316. }
  1317.  
  1318. uint8_t Tx16Request::getFrameData(uint8_t pos) {
  1319.  
  1320. if (pos == 0) {
  1321. return (_addr16 >> 8) & 0xff;
  1322. } else if (pos == 1) {
  1323. return _addr16 & 0xff;
  1324. } else if (pos == 2) {
  1325. return _option;
  1326. } else {
  1327. return getPayload()[pos - TX_16_API_LENGTH];
  1328. }
  1329. }
  1330.  
  1331. uint8_t Tx16Request::getFrameDataLength() {
  1332. return TX_16_API_LENGTH + getPayloadLength();
  1333. }
  1334.  
  1335. uint16_t Tx16Request::getAddress16() {
  1336. return _addr16;
  1337. }
  1338.  
  1339. void Tx16Request::setAddress16(uint16_t addr16) {
  1340. _addr16 = addr16;
  1341. }
  1342.  
  1343. uint8_t Tx16Request::getOption() {
  1344. return _option;
  1345. }
  1346.  
  1347. void Tx16Request::setOption(uint8_t option) {
  1348. _option = option;
  1349. }
  1350.  
  1351. Tx64Request::Tx64Request() : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  1352. _option = ACK_OPTION;
  1353. }
  1354.  
  1355. Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) {
  1356. _addr64 = addr64;
  1357. _option = option;
  1358. }
  1359.  
  1360. Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  1361. _addr64 = addr64;
  1362. _option = ACK_OPTION;
  1363. }
  1364.  
  1365. uint8_t Tx64Request::getFrameData(uint8_t pos) {
  1366.  
  1367. if (pos == 0) {
  1368. return (_addr64.getMsb() >> 24) & 0xff;
  1369. } else if (pos == 1) {
  1370. return (_addr64.getMsb() >> 16) & 0xff;
  1371. } else if (pos == 2) {
  1372. return (_addr64.getMsb() >> 8) & 0xff;
  1373. } else if (pos == 3) {
  1374. return _addr64.getMsb() & 0xff;
  1375. } else if (pos == 4) {
  1376. return (_addr64.getLsb() >> 24) & 0xff;
  1377. } else if (pos == 5) {
  1378. return (_addr64.getLsb() >> 16) & 0xff;
  1379. } else if (pos == 6) {
  1380. return(_addr64.getLsb() >> 8) & 0xff;
  1381. } else if (pos == 7) {
  1382. return _addr64.getLsb() & 0xff;
  1383. } else if (pos == 8) {
  1384. return _option;
  1385. } else {
  1386. return getPayload()[pos - TX_64_API_LENGTH];
  1387. }
  1388. }
  1389.  
  1390. uint8_t Tx64Request::getFrameDataLength() {
  1391. return TX_64_API_LENGTH + getPayloadLength();
  1392. }
  1393.  
  1394. XBeeAddress64& Tx64Request::getAddress64() {
  1395. return _addr64;
  1396. }
  1397.  
  1398. void Tx64Request::setAddress64(XBeeAddress64& addr64) {
  1399. _addr64 = addr64;
  1400. }
  1401.  
  1402. uint8_t Tx64Request::getOption() {
  1403. return _option;
  1404. }
  1405.  
  1406. void Tx64Request::setOption(uint8_t option) {
  1407. _option = option;
  1408. }
  1409.  
  1410. #endif
  1411.  
  1412. AtCommandRequest::AtCommandRequest() : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  1413. _command = NULL;
  1414. clearCommandValue();
  1415. }
  1416.  
  1417. AtCommandRequest::AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  1418. _command = command;
  1419. _commandValue = commandValue;
  1420. _commandValueLength = commandValueLength;
  1421. }
  1422.  
  1423. AtCommandRequest::AtCommandRequest(uint8_t *command) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  1424. _command = command;
  1425. clearCommandValue();
  1426. }
  1427.  
  1428. uint8_t* AtCommandRequest::getCommand() {
  1429. return _command;
  1430. }
  1431.  
  1432. uint8_t* AtCommandRequest::getCommandValue() {
  1433. return _commandValue;
  1434. }
  1435.  
  1436. uint8_t AtCommandRequest::getCommandValueLength() {
  1437. return _commandValueLength;
  1438. }
  1439.  
  1440. void AtCommandRequest::setCommand(uint8_t* command) {
  1441. _command = command;
  1442. }
  1443.  
  1444. void AtCommandRequest::setCommandValue(uint8_t* value) {
  1445. _commandValue = value;
  1446. }
  1447.  
  1448. void AtCommandRequest::setCommandValueLength(uint8_t length) {
  1449. _commandValueLength = length;
  1450. }
  1451.  
  1452. uint8_t AtCommandRequest::getFrameData(uint8_t pos) {
  1453.  
  1454. if (pos == 0) {
  1455. return _command[0];
  1456. } else if (pos == 1) {
  1457. return _command[1];
  1458. } else {
  1459. return _commandValue[pos - AT_COMMAND_API_LENGTH];
  1460. }
  1461. }
  1462.  
  1463. void AtCommandRequest::clearCommandValue() {
  1464. _commandValue = NULL;
  1465. _commandValueLength = 0;
  1466. }
  1467.  
  1468. //void AtCommandRequest::reset() {
  1469. // XBeeRequest::reset();
  1470. //}
  1471.  
  1472. uint8_t AtCommandRequest::getFrameDataLength() {
  1473. // command is 2 byte + length of value
  1474. return AT_COMMAND_API_LENGTH + _commandValueLength;
  1475. }
  1476.  
  1477. XBeeAddress64 RemoteAtCommandRequest::broadcastAddress64 = XBeeAddress64(0x0, BROADCAST_ADDRESS);
  1478.  
  1479. RemoteAtCommandRequest::RemoteAtCommandRequest() : AtCommandRequest(NULL, NULL, 0) {
  1480. _remoteAddress16 = 0;
  1481. _applyChanges = false;
  1482. setApiId(REMOTE_AT_REQUEST);
  1483. }
  1484.  
  1485. RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
  1486. _remoteAddress64 = broadcastAddress64;
  1487. _remoteAddress16 = remoteAddress16;
  1488. _applyChanges = true;
  1489. setApiId(REMOTE_AT_REQUEST);
  1490. }
  1491.  
  1492. RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
  1493. _remoteAddress64 = broadcastAddress64;
  1494. _remoteAddress16 = remoteAddress16;
  1495. _applyChanges = false;
  1496. setApiId(REMOTE_AT_REQUEST);
  1497. }
  1498.  
  1499. RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
  1500. _remoteAddress64 = remoteAddress64;
  1501. // don't worry.. works for series 1 too!
  1502. _remoteAddress16 = ZB_BROADCAST_ADDRESS;
  1503. _applyChanges = true;
  1504. setApiId(REMOTE_AT_REQUEST);
  1505. }
  1506.  
  1507. RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
  1508. _remoteAddress64 = remoteAddress64;
  1509. _remoteAddress16 = ZB_BROADCAST_ADDRESS;
  1510. _applyChanges = false;
  1511. setApiId(REMOTE_AT_REQUEST);
  1512. }
  1513.  
  1514. uint16_t RemoteAtCommandRequest::getRemoteAddress16() {
  1515. return _remoteAddress16;
  1516. }
  1517.  
  1518. void RemoteAtCommandRequest::setRemoteAddress16(uint16_t remoteAddress16) {
  1519. _remoteAddress16 = remoteAddress16;
  1520. }
  1521.  
  1522. XBeeAddress64& RemoteAtCommandRequest::getRemoteAddress64() {
  1523. return _remoteAddress64;
  1524. }
  1525.  
  1526. void RemoteAtCommandRequest::setRemoteAddress64(XBeeAddress64 &remoteAddress64) {
  1527. _remoteAddress64 = remoteAddress64;
  1528. }
  1529.  
  1530. bool RemoteAtCommandRequest::getApplyChanges() {
  1531. return _applyChanges;
  1532. }
  1533.  
  1534. void RemoteAtCommandRequest::setApplyChanges(bool applyChanges) {
  1535. _applyChanges = applyChanges;
  1536. }
  1537.  
  1538.  
  1539. uint8_t RemoteAtCommandRequest::getFrameData(uint8_t pos) {
  1540. if (pos == 0) {
  1541. return (_remoteAddress64.getMsb() >> 24) & 0xff;
  1542. } else if (pos == 1) {
  1543. return (_remoteAddress64.getMsb() >> 16) & 0xff;
  1544. } else if (pos == 2) {
  1545. return (_remoteAddress64.getMsb() >> 8) & 0xff;
  1546. } else if (pos == 3) {
  1547. return _remoteAddress64.getMsb() & 0xff;
  1548. } else if (pos == 4) {
  1549. return (_remoteAddress64.getLsb() >> 24) & 0xff;
  1550. } else if (pos == 5) {
  1551. return (_remoteAddress64.getLsb() >> 16) & 0xff;
  1552. } else if (pos == 6) {
  1553. return(_remoteAddress64.getLsb() >> 8) & 0xff;
  1554. } else if (pos == 7) {
  1555. return _remoteAddress64.getLsb() & 0xff;
  1556. } else if (pos == 8) {
  1557. return (_remoteAddress16 >> 8) & 0xff;
  1558. } else if (pos == 9) {
  1559. return _remoteAddress16 & 0xff;
  1560. } else if (pos == 10) {
  1561. return _applyChanges ? 2: 0;
  1562. } else if (pos == 11) {
  1563. return getCommand()[0];
  1564. } else if (pos == 12) {
  1565. return getCommand()[1];
  1566. } else {
  1567. return getCommandValue()[pos - REMOTE_AT_COMMAND_API_LENGTH];
  1568. }
  1569. }
  1570.  
  1571. uint8_t RemoteAtCommandRequest::getFrameDataLength() {
  1572. return REMOTE_AT_COMMAND_API_LENGTH + getCommandValueLength();
  1573. }
  1574.  
  1575.  
  1576. // TODO
  1577. //GenericRequest::GenericRequest(uint8_t* frame, uint8_t len, uint8_t apiId): XBeeRequest(apiId, *(frame), len) {
  1578. // _frame = frame;
  1579. //}
  1580.  
  1581. void XBee::send(XBeeRequest &request) {
  1582. // the new new deal
  1583.  
  1584. sendByte(START_BYTE, false);
  1585.  
  1586. // send length
  1587. uint8_t msbLen = ((request.getFrameDataLength() + 2) >> 8) & 0xff;
  1588. uint8_t lsbLen = (request.getFrameDataLength() + 2) & 0xff;
  1589.  
  1590. sendByte(msbLen, true);
  1591. sendByte(lsbLen, true);
  1592.  
  1593. // api id
  1594. sendByte(request.getApiId(), true);
  1595. sendByte(request.getFrameId(), true);
  1596.  
  1597. uint8_t checksum = 0;
  1598.  
  1599. // compute checksum, start at api id
  1600. checksum+= request.getApiId();
  1601. checksum+= request.getFrameId();
  1602.  
  1603. for (int i = 0; i < request.getFrameDataLength(); i++) {
  1604. sendByte(request.getFrameData(i), true);
  1605. checksum+= request.getFrameData(i);
  1606. }
  1607.  
  1608. // perform 2s complement
  1609. checksum = 0xff - checksum;
  1610.  
  1611. // send checksum
  1612. sendByte(checksum, true);
  1613. }
  1614.  
  1615. void XBee::sendByte(uint8_t b, bool escape) {
  1616.  
  1617. if (escape && (b == START_BYTE || b == ESCAPE || b == XON || b == XOFF)) {
  1618. write(ESCAPE);
  1619. write(b ^ 0x20);
  1620. } else {
  1621. write(b);
  1622. }
  1623. }
  1624.  
  1625.  
  1626. void XBeeWithCallbacks::loop() {
  1627. if (loopTop())
  1628. loopBottom();
  1629. }
  1630.  
  1631. bool XBeeWithCallbacks::loopTop() {
  1632. readPacket();
  1633. if (getResponse().isAvailable()) {
  1634. _onResponse.call(getResponse());
  1635. return true;
  1636. } else if (getResponse().isError()) {
  1637. _onPacketError.call(getResponse().getErrorCode());
  1638. }
  1639. return false;
  1640. }
  1641.  
  1642. void XBeeWithCallbacks::loopBottom() {
  1643. bool called = false;
  1644. uint8_t id = getResponse().getApiId();
  1645.  
  1646. if (id == ZB_TX_STATUS_RESPONSE) {
  1647. ZBTxStatusResponse response;
  1648. getResponse().getZBTxStatusResponse(response);
  1649. called = _onZBTxStatusResponse.call(response);
  1650. } else if (id == ZB_RX_RESPONSE) {
  1651. ZBRxResponse response;
  1652. getResponse().getZBRxResponse(response);
  1653. called = _onZBRxResponse.call(response);
  1654. } else if (id == ZB_EXPLICIT_RX_RESPONSE) {
  1655. ZBExplicitRxResponse response;
  1656. getResponse().getZBExplicitRxResponse(response);
  1657. called = _onZBExplicitRxResponse.call(response);
  1658. } else if (id == ZB_IO_SAMPLE_RESPONSE) {
  1659. ZBRxIoSampleResponse response;
  1660. getResponse().getZBRxIoSampleResponse(response);
  1661. called = _onZBRxIoSampleResponse.call(response);
  1662. } else if (id == TX_STATUS_RESPONSE) {
  1663. TxStatusResponse response;
  1664. getResponse().getTxStatusResponse(response);
  1665. called = _onTxStatusResponse.call(response);
  1666. } else if (id == RX_16_RESPONSE) {
  1667. Rx16Response response;
  1668. getResponse().getRx16Response(response);
  1669. called = _onRx16Response.call(response);
  1670. } else if (id == RX_64_RESPONSE) {
  1671. Rx64Response response;
  1672. getResponse().getRx64Response(response);
  1673. called = _onRx64Response.call(response);
  1674. } else if (id == RX_16_IO_RESPONSE) {
  1675. Rx16IoSampleResponse response;
  1676. getResponse().getRx16IoSampleResponse(response);
  1677. called = _onRx16IoSampleResponse.call(response);
  1678. } else if (id == RX_64_IO_RESPONSE) {
  1679. Rx64IoSampleResponse response;
  1680. getResponse().getRx64IoSampleResponse(response);
  1681. called = _onRx64IoSampleResponse.call(response);
  1682. } else if (id == MODEM_STATUS_RESPONSE) {
  1683. ModemStatusResponse response;
  1684. getResponse().getModemStatusResponse(response);
  1685. called = _onModemStatusResponse.call(response);
  1686. } else if (id == AT_COMMAND_RESPONSE) {
  1687. AtCommandResponse response;
  1688. getResponse().getAtCommandResponse(response);
  1689. called = _onAtCommandResponse.call(response);
  1690. } else if (id == REMOTE_AT_COMMAND_RESPONSE) {
  1691. RemoteAtCommandResponse response;
  1692. getResponse().getRemoteAtCommandResponse(response);
  1693. called = _onRemoteAtCommandResponse.call(response);
  1694. }
  1695.  
  1696. if (!called)
  1697. _onOtherResponse.call(getResponse());
  1698. }
  1699.  
  1700. uint8_t XBeeWithCallbacks::matchStatus(uint8_t frameId) {
  1701. uint8_t id = getResponse().getApiId();
  1702. uint8_t *data = getResponse().getFrameData();
  1703. uint8_t len = getResponse().getFrameDataLength();
  1704. uint8_t offset = 0;
  1705.  
  1706. // Figure out if this frame has a frameId and if so, where the
  1707. // status byte to return is located
  1708. if (id == AT_COMMAND_RESPONSE)
  1709. offset = 3;
  1710. else if (id == REMOTE_AT_COMMAND_RESPONSE)
  1711. offset = 13;
  1712. else if (id == TX_STATUS_RESPONSE)
  1713. offset = 1;
  1714. else if (id == ZB_TX_STATUS_RESPONSE)
  1715. offset = 4;
  1716.  
  1717. // If this is an API frame that contains a status, the frame is
  1718. // long enough to contain it and the frameId matches the one
  1719. // given, return the status byte
  1720. if (offset && offset < len && data[0] == frameId)
  1721. return data[offset];
  1722. return 0xff;
  1723. }
  1724.  
  1725. uint8_t XBeeWithCallbacks::waitForInternal(uint8_t apiId, void *response, uint16_t timeout, void *func, uintptr_t data, int16_t frameId) {
  1726. /*
  1727. unsigned long start = millis();
  1728. do {
  1729. // Wait for a packet of the right type
  1730. if (loopTop()) {
  1731. if (frameId >= 0) {
  1732. uint8_t status = matchStatus(frameId);
  1733. // If a status was found, but it was not
  1734. // a zero success status, stop waiting
  1735. if (status != 0xff && status != 0)
  1736. return status;
  1737. }
  1738.  
  1739. if (getResponse().getApiId() == apiId) {
  1740. // If the type is right, call the right
  1741. // conversion function based on the
  1742. // ApiId and call the match function.
  1743. // Because the match function is
  1744. // essentially called in the same way,
  1745. // regardless of the subclass used, the
  1746. // compiler can reduce most of the below
  1747. // mess into a single piece of code
  1748. // (though for fully optimizing, the
  1749. // separate getXxxResponse() methods
  1750. // must be unified as well).
  1751. switch(apiId) {
  1752. case ZBTxStatusResponse::API_ID: {
  1753. ZBTxStatusResponse *r = (ZBTxStatusResponse*)response;
  1754. bool(*f)(ZBTxStatusResponse&,uintptr_t) = (bool(*)(ZBTxStatusResponse&,uintptr_t))func;
  1755. getResponse().getZBTxStatusResponse(*r);
  1756. if(!f || f(*r, data))
  1757. return 0;
  1758. break;
  1759. }
  1760. case ZBRxResponse::API_ID: {
  1761. ZBRxResponse *r = (ZBRxResponse*)response;
  1762. bool(*f)(ZBRxResponse&,uintptr_t) = (bool(*)(ZBRxResponse&,uintptr_t))func;
  1763. getResponse().getZBRxResponse(*r);
  1764. if(!f || f(*r, data))
  1765. return 0;
  1766. break;
  1767. }
  1768. case ZBExplicitRxResponse::API_ID: {
  1769. ZBExplicitRxResponse *r = (ZBExplicitRxResponse*)response;
  1770. bool(*f)(ZBExplicitRxResponse&,uintptr_t) = (bool(*)(ZBExplicitRxResponse&,uintptr_t))func;
  1771. getResponse().getZBExplicitRxResponse(*r);
  1772. if(!f || f(*r, data))
  1773. return 0;
  1774. break;
  1775. }
  1776. case ZBRxIoSampleResponse::API_ID: {
  1777. ZBRxIoSampleResponse *r = (ZBRxIoSampleResponse*)response;
  1778. bool(*f)(ZBRxIoSampleResponse&,uintptr_t) = (bool(*)(ZBRxIoSampleResponse&,uintptr_t))func;
  1779. getResponse().getZBRxIoSampleResponse(*r);
  1780. if(!f || f(*r, data))
  1781. return 0;
  1782. break;
  1783. }
  1784. case TxStatusResponse::API_ID: {
  1785. TxStatusResponse *r = (TxStatusResponse*)response;
  1786. bool(*f)(TxStatusResponse&,uintptr_t) = (bool(*)(TxStatusResponse&,uintptr_t))func;
  1787. getResponse().getTxStatusResponse(*r);
  1788. if(!f || f(*r, data))
  1789. return 0;
  1790. break;
  1791. }
  1792. case Rx16Response::API_ID: {
  1793. Rx16Response *r = (Rx16Response*)response;
  1794. bool(*f)(Rx16Response&,uintptr_t) = (bool(*)(Rx16Response&,uintptr_t))func;
  1795. getResponse().getRx16Response(*r);
  1796. if(!f || f(*r, data))
  1797. return 0;
  1798. break;
  1799. }
  1800. case Rx64Response::API_ID: {
  1801. Rx64Response *r = (Rx64Response*)response;
  1802. bool(*f)(Rx64Response&,uintptr_t) = (bool(*)(Rx64Response&,uintptr_t))func;
  1803. getResponse().getRx64Response(*r);
  1804. if(!f || f(*r, data))
  1805. return 0;
  1806. break;
  1807. }
  1808. case Rx16IoSampleResponse::API_ID: {
  1809. Rx16IoSampleResponse *r = (Rx16IoSampleResponse*)response;
  1810. bool(*f)(Rx16IoSampleResponse&,uintptr_t) = (bool(*)(Rx16IoSampleResponse&,uintptr_t))func;
  1811. getResponse().getRx16IoSampleResponse(*r);
  1812. if(!f || f(*r, data))
  1813. return 0;
  1814. break;
  1815. }
  1816. case Rx64IoSampleResponse::API_ID: {
  1817. Rx64IoSampleResponse *r = (Rx64IoSampleResponse*)response;
  1818. bool(*f)(Rx64IoSampleResponse&,uintptr_t) = (bool(*)(Rx64IoSampleResponse&,uintptr_t))func;
  1819. getResponse().getRx64IoSampleResponse(*r);
  1820. if(!f || f(*r, data))
  1821. return 0;
  1822. break;
  1823. }
  1824. case ModemStatusResponse::API_ID: {
  1825. ModemStatusResponse *r = (ModemStatusResponse*)response;
  1826. bool(*f)(ModemStatusResponse&,uintptr_t) = (bool(*)(ModemStatusResponse&,uintptr_t))func;
  1827. getResponse().getModemStatusResponse(*r);
  1828. if(!f || f(*r, data))
  1829. return 0;
  1830. break;
  1831. }
  1832. case AtCommandResponse::API_ID: {
  1833. AtCommandResponse *r = (AtCommandResponse*)response;
  1834. bool(*f)(AtCommandResponse&,uintptr_t) = (bool(*)(AtCommandResponse&,uintptr_t))func;
  1835. getResponse().getAtCommandResponse(*r);
  1836. if(!f || f(*r, data))
  1837. return 0;
  1838. break;
  1839. }
  1840. case RemoteAtCommandResponse::API_ID: {
  1841. RemoteAtCommandResponse *r = (RemoteAtCommandResponse*)response;
  1842. bool(*f)(RemoteAtCommandResponse&,uintptr_t) = (bool(*)(RemoteAtCommandResponse&,uintptr_t))func;
  1843. getResponse().getRemoteAtCommandResponse(*r);
  1844. if(!f || f(*r, data))
  1845. return 0;
  1846. break;
  1847. }
  1848. }
  1849. }
  1850. // Call regular callbacks
  1851. loopBottom();
  1852. }
  1853. } while (millis() - start < timeout);
  1854. */
  1855. return XBEE_WAIT_TIMEOUT;
  1856.  
  1857. }
  1858.  
  1859. uint8_t XBeeWithCallbacks::waitForStatus(uint8_t frameId, uint16_t timeout) {
  1860. /*
  1861. unsigned long start = millis();
  1862. do {
  1863. if (loopTop()) {
  1864. uint8_t status = matchStatus(frameId);
  1865. if (status != 0xff)
  1866. return status;
  1867.  
  1868. // Call regular callbacks
  1869. loopBottom();
  1870. }
  1871. } while (millis() - start < timeout);
  1872. */
  1873. return XBEE_WAIT_TIMEOUT ;
  1874.  
  1875. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement