PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1469 line
36KB

  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. #include "XBee.h"
  20. #if defined(ARDUINO) && ARDUINO >= 100
  21. #include "Arduino.h"
  22. #else
  23. #include "WProgram.h"
  24. #endif
  25. #include "HardwareSerial.h"
  26. XBeeResponse::XBeeResponse() {
  27. }
  28. uint8_t XBeeResponse::getApiId() {
  29. return _apiId;
  30. }
  31. void XBeeResponse::setApiId(uint8_t apiId) {
  32. _apiId = apiId;
  33. }
  34. uint8_t XBeeResponse::getMsbLength() {
  35. return _msbLength;
  36. }
  37. void XBeeResponse::setMsbLength(uint8_t msbLength) {
  38. _msbLength = msbLength;
  39. }
  40. uint8_t XBeeResponse::getLsbLength() {
  41. return _lsbLength;
  42. }
  43. void XBeeResponse::setLsbLength(uint8_t lsbLength) {
  44. _lsbLength = lsbLength;
  45. }
  46. uint8_t XBeeResponse::getChecksum() {
  47. return _checksum;
  48. }
  49. void XBeeResponse::setChecksum(uint8_t checksum) {
  50. _checksum = checksum;
  51. }
  52. uint8_t XBeeResponse::getFrameDataLength() {
  53. return _frameLength;
  54. }
  55. void XBeeResponse::setFrameLength(uint8_t frameLength) {
  56. _frameLength = frameLength;
  57. }
  58. bool XBeeResponse::isAvailable() {
  59. return _complete;
  60. }
  61. void XBeeResponse::setAvailable(bool complete) {
  62. _complete = complete;
  63. }
  64. bool XBeeResponse::isError() {
  65. return _errorCode > 0;
  66. }
  67. uint8_t XBeeResponse::getErrorCode() {
  68. return _errorCode;
  69. }
  70. void XBeeResponse::setErrorCode(uint8_t errorCode) {
  71. _errorCode = errorCode;
  72. }
  73. // copy common fields from xbee response to target response
  74. void XBeeResponse::setCommon(XBeeResponse &target) {
  75. target.setApiId(getApiId());
  76. target.setAvailable(isAvailable());
  77. target.setChecksum(getChecksum());
  78. target.setErrorCode(getErrorCode());
  79. target.setFrameLength(getFrameDataLength());
  80. target.setMsbLength(getMsbLength());
  81. target.setLsbLength(getLsbLength());
  82. }
  83. #ifdef SERIES_2
  84. ZBTxStatusResponse::ZBTxStatusResponse() : FrameIdResponse() {
  85. }
  86. uint16_t ZBTxStatusResponse::getRemoteAddress() {
  87. return (getFrameData()[1] << 8) + getFrameData()[2];
  88. }
  89. uint8_t ZBTxStatusResponse::getTxRetryCount() {
  90. return getFrameData()[3];
  91. }
  92. uint8_t ZBTxStatusResponse::getDeliveryStatus() {
  93. return getFrameData()[4];
  94. }
  95. uint8_t ZBTxStatusResponse::getDiscoveryStatus() {
  96. return getFrameData()[5];
  97. }
  98. bool ZBTxStatusResponse::isSuccess() {
  99. return getDeliveryStatus() == SUCCESS;
  100. }
  101. void XBeeResponse::getZBTxStatusResponse(XBeeResponse &zbXBeeResponse) {
  102. // way off?
  103. ZBTxStatusResponse* zb = static_cast<ZBTxStatusResponse*>(&zbXBeeResponse);
  104. // pass pointer array to subclass
  105. zb->setFrameData(getFrameData());
  106. setCommon(zbXBeeResponse);
  107. }
  108. ZBRxResponse::ZBRxResponse(): RxDataResponse() {
  109. _remoteAddress64 = XBeeAddress64();
  110. }
  111. uint16_t ZBRxResponse::getRemoteAddress16() {
  112. return (getFrameData()[8] << 8) + getFrameData()[9];
  113. }
  114. uint8_t ZBRxResponse::getOption() {
  115. return getFrameData()[10];
  116. }
  117. // markers to read data from packet array. this is the index, so the 12th item in the array
  118. uint8_t ZBRxResponse::getDataOffset() {
  119. return 11;
  120. }
  121. uint8_t ZBRxResponse::getDataLength() {
  122. return getPacketLength() - getDataOffset() - 1;
  123. }
  124. XBeeAddress64& ZBRxResponse::getRemoteAddress64() {
  125. return _remoteAddress64;
  126. }
  127. void XBeeResponse::getZBRxResponse(XBeeResponse &rxResponse) {
  128. ZBRxResponse* zb = static_cast<ZBRxResponse*>(&rxResponse);
  129. //TODO verify response api id matches this api for this response
  130. // pass pointer array to subclass
  131. zb->setFrameData(getFrameData());
  132. setCommon(rxResponse);
  133. zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  134. zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
  135. }
  136. ZBRxIoSampleResponse::ZBRxIoSampleResponse() : ZBRxResponse() {
  137. }
  138. // 64 + 16 addresses, sample size, option = 12 (index 11), so this starts at 12
  139. uint8_t ZBRxIoSampleResponse::getDigitalMaskMsb() {
  140. return getFrameData()[12] & 0x1c;
  141. }
  142. uint8_t ZBRxIoSampleResponse::getDigitalMaskLsb() {
  143. return getFrameData()[13];
  144. }
  145. uint8_t ZBRxIoSampleResponse::getAnalogMask() {
  146. return getFrameData()[14] & 0x8f;
  147. }
  148. bool ZBRxIoSampleResponse::containsAnalog() {
  149. return getAnalogMask() > 0;
  150. }
  151. bool ZBRxIoSampleResponse::containsDigital() {
  152. return getDigitalMaskMsb() > 0 || getDigitalMaskLsb() > 0;
  153. }
  154. bool ZBRxIoSampleResponse::isAnalogEnabled(uint8_t pin) {
  155. return ((getAnalogMask() >> pin) & 1) == 1;
  156. }
  157. bool ZBRxIoSampleResponse::isDigitalEnabled(uint8_t pin) {
  158. if (pin <= 7) {
  159. // added extra parens to calm avr compiler
  160. return ((getDigitalMaskLsb() >> pin) & 1) == 1;
  161. } else {
  162. return ((getDigitalMaskMsb() >> (pin - 8)) & 1) == 1;
  163. }
  164. }
  165. uint16_t ZBRxIoSampleResponse::getAnalog(uint8_t pin) {
  166. // analog starts 13 bytes after sample size, if no dio enabled
  167. uint8_t start = 15;
  168. if (containsDigital()) {
  169. // make room for digital i/o
  170. start+=2;
  171. }
  172. // std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl;
  173. // start depends on how many pins before this pin are enabled
  174. for (int i = 0; i < pin; i++) {
  175. if (isAnalogEnabled(i)) {
  176. start+=2;
  177. }
  178. }
  179. // std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl;
  180. // std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl;
  181. return (uint16_t)((getFrameData()[start] << 8) + getFrameData()[start + 1]);
  182. }
  183. bool ZBRxIoSampleResponse::isDigitalOn(uint8_t pin) {
  184. if (pin <= 7) {
  185. // D0-7
  186. // DIO LSB is index 5
  187. return ((getFrameData()[16] >> pin) & 1) == 1;
  188. } else {
  189. // D10-12
  190. // DIO MSB is index 4
  191. return ((getFrameData()[15] >> (pin - 8)) & 1) == 1;
  192. }
  193. }
  194. void XBeeResponse::getZBRxIoSampleResponse(XBeeResponse &response) {
  195. ZBRxIoSampleResponse* zb = static_cast<ZBRxIoSampleResponse*>(&response);
  196. // pass pointer array to subclass
  197. zb->setFrameData(getFrameData());
  198. setCommon(response);
  199. zb->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  200. zb->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + (getFrameData()[7]));
  201. }
  202. #endif
  203. #ifdef SERIES_1
  204. RxResponse::RxResponse() : RxDataResponse() {
  205. }
  206. uint16_t Rx16Response::getRemoteAddress16() {
  207. return (getFrameData()[0] << 8) + getFrameData()[1];
  208. }
  209. XBeeAddress64& Rx64Response::getRemoteAddress64() {
  210. return _remoteAddress;
  211. }
  212. Rx64Response::Rx64Response() : RxResponse() {
  213. _remoteAddress = XBeeAddress64();
  214. }
  215. Rx16Response::Rx16Response() : RxResponse() {
  216. }
  217. RxIoSampleBaseResponse::RxIoSampleBaseResponse() : RxResponse() {
  218. }
  219. uint8_t RxIoSampleBaseResponse::getSampleOffset() {
  220. // sample starts 2 bytes after rssi
  221. return getRssiOffset() + 2;
  222. }
  223. uint8_t RxIoSampleBaseResponse::getSampleSize() {
  224. return getFrameData()[getSampleOffset()];
  225. }
  226. bool RxIoSampleBaseResponse::containsAnalog() {
  227. return (getFrameData()[getSampleOffset() + 1] & 0x7e) > 0;
  228. }
  229. bool RxIoSampleBaseResponse::containsDigital() {
  230. return (getFrameData()[getSampleOffset() + 1] & 0x1) > 0 || getFrameData()[getSampleOffset() + 2] > 0;
  231. }
  232. //uint16_t RxIoSampleBaseResponse::getAnalog0(uint8_t sample) {
  233. // return getAnalog(0, sample);
  234. //}
  235. bool RxIoSampleBaseResponse::isAnalogEnabled(uint8_t pin) {
  236. return (((getFrameData()[getSampleOffset() + 1] >> (pin + 1)) & 1) == 1);
  237. }
  238. bool RxIoSampleBaseResponse::isDigitalEnabled(uint8_t pin) {
  239. if (pin < 8) {
  240. return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1;
  241. } else {
  242. return (getFrameData()[getSampleOffset() + 3] & 1) == 1;
  243. }
  244. }
  245. // // verified (from XBee-API)
  246. // private int getSampleWidth() {
  247. // int width = 0;
  248. //
  249. // // width of sample depends on how many I/O pins are enabled. add one for each analog that's enabled
  250. // for (int i = 0; i <= 5; i++) {
  251. // if (isAnalogEnabled(i)) {
  252. // // each analog is two bytes
  253. // width+=2;
  254. // }
  255. // }
  256. //
  257. // if (this.containsDigital()) {
  258. // // digital enabled takes two bytes, no matter how many pins enabled
  259. // width+= 2;
  260. // }
  261. //
  262. // return width;
  263. // }
  264. //
  265. // private int getStartIndex() {
  266. //
  267. // int startIndex;
  268. //
  269. // if (this.getSourceAddress() instanceof XBeeAddress16) {
  270. // // 16 bit
  271. // startIndex = 7;
  272. // } else {
  273. // // 64 bit
  274. // startIndex = 13;
  275. // }
  276. //
  277. // return startIndex;
  278. // }
  279. //
  280. // public int getDigitalMsb(int sample) {
  281. // // msb digital always starts 3 bytes after sample size
  282. // return this.getProcessedPacketBytes()[this.getStartIndex() + 3 + this.getSampleWidth() * sample];
  283. // }
  284. //
  285. // public int getDigitalLsb(int sample) {
  286. // return this.getProcessedPacketBytes()[this.getStartIndex() + 3 + this.getSampleWidth() * sample + 1];
  287. // }
  288. //
  289. // public Boolean isDigitalOn(int pin, int sample) {
  290. //
  291. // if (sample < 0 || sample >= this.getSampleSize()) {
  292. // throw new IllegalArgumentException("invalid sample size: " + sample);
  293. // }
  294. //
  295. // if (!this.containsDigital()) {
  296. // throw new RuntimeException("Digital is not enabled");
  297. // }
  298. //
  299. // if (pin >= 0 && pin < 8) {
  300. // return ((this.getDigitalLsb(sample) >> pin) & 1) == 1;
  301. // } else if (pin == 8) {
  302. // // uses msb dio line
  303. // return (this.getDigitalMsb(sample) & 1) == 1;
  304. // } else {
  305. // throw new IllegalArgumentException("Invalid pin: " + pin);
  306. // }
  307. // }
  308. //
  309. // public Integer getAnalog(int pin, int sample) {
  310. //
  311. // if (sample < 0 || sample >= this.getSampleSize()) {
  312. // throw new IllegalArgumentException("invalid sample size: " + sample);
  313. // }
  314. //
  315. // // analog starts 3 bytes after start of sample, if no dio enabled
  316. // int startIndex = this.getStartIndex() + 3;
  317. //
  318. // if (this.containsDigital()) {
  319. // // make room for digital i/o sample (2 bytes per sample)
  320. // startIndex+= 2;
  321. // }
  322. //
  323. // startIndex+= this.getSampleWidth() * sample;
  324. //
  325. // // start depends on how many pins before this pin are enabled
  326. // // this will throw illegalargumentexception if invalid pin
  327. // for (int i = 0; i < pin; i++) {
  328. // if (isAnalogEnabled(i)) {
  329. // startIndex+=2;
  330. // }
  331. // }
  332. //
  333. // return (this.getProcessedPacketBytes()[startIndex] << 8) + this.getProcessedPacketBytes()[startIndex + 1];
  334. // }
  335. // THIS IS WRONG
  336. uint16_t RxIoSampleBaseResponse::getAnalog(uint8_t pin, uint8_t sample) {
  337. // analog starts 3 bytes after sample size, if no dio enabled
  338. uint8_t start = 3;
  339. if (containsDigital()) {
  340. // make room for digital i/o sample (2 bytes per sample)
  341. start+=2*(sample + 1);
  342. }
  343. uint8_t spacing = 0;
  344. // spacing between samples depends on how many are enabled. add one for each analog that's enabled
  345. for (int i = 0; i <= 5; i++) {
  346. if (isAnalogEnabled(i)) {
  347. // each analog is two bytes
  348. spacing+=2;
  349. }
  350. }
  351. // std::cout << "spacing is " << static_cast<unsigned int>(spacing) << std::endl;
  352. // start depends on how many pins before this pin are enabled
  353. for (int i = 0; i < pin; i++) {
  354. if (isAnalogEnabled(i)) {
  355. start+=2;
  356. }
  357. }
  358. start+= sample * spacing;
  359. // std::cout << "start for analog pin ["<< static_cast<unsigned int>(pin) << "]/sample " << static_cast<unsigned int>(sample) << " is " << static_cast<unsigned int>(start) << std::endl;
  360. // std::cout << "returning index " << static_cast<unsigned int>(getSampleOffset() + start) << " and index " << static_cast<unsigned int>(getSampleOffset() + start + 1) << ", val is " << static_cast<unsigned int>(getFrameData()[getSampleOffset() + start] << 8) << " and " << + static_cast<unsigned int>(getFrameData()[getSampleOffset() + start + 1]) << std::endl;
  361. return (uint16_t)((getFrameData()[getSampleOffset() + start] << 8) + getFrameData()[getSampleOffset() + start + 1]);
  362. }
  363. bool RxIoSampleBaseResponse::isDigitalOn(uint8_t pin, uint8_t sample) {
  364. if (pin < 8) {
  365. return ((getFrameData()[getSampleOffset() + 4] >> pin) & 1) == 1;
  366. } else {
  367. return (getFrameData()[getSampleOffset() + 3] & 1) == 1;
  368. }
  369. }
  370. //bool RxIoSampleBaseResponse::isDigital0On(uint8_t sample) {
  371. // return isDigitalOn(0, sample);
  372. //}
  373. Rx16IoSampleResponse::Rx16IoSampleResponse() : RxIoSampleBaseResponse() {
  374. }
  375. uint16_t Rx16IoSampleResponse::getRemoteAddress16() {
  376. return (uint16_t)((getFrameData()[0] << 8) + getFrameData()[1]);
  377. }
  378. uint8_t Rx16IoSampleResponse::getRssiOffset() {
  379. return 2;
  380. }
  381. void XBeeResponse::getRx16IoSampleResponse(XBeeResponse &response) {
  382. Rx16IoSampleResponse* rx = static_cast<Rx16IoSampleResponse*>(&response);
  383. rx->setFrameData(getFrameData());
  384. setCommon(response);
  385. }
  386. Rx64IoSampleResponse::Rx64IoSampleResponse() : RxIoSampleBaseResponse() {
  387. _remoteAddress = XBeeAddress64();
  388. }
  389. XBeeAddress64& Rx64IoSampleResponse::getRemoteAddress64() {
  390. return _remoteAddress;
  391. }
  392. uint8_t Rx64IoSampleResponse::getRssiOffset() {
  393. return 8;
  394. }
  395. void XBeeResponse::getRx64IoSampleResponse(XBeeResponse &response) {
  396. Rx64IoSampleResponse* rx = static_cast<Rx64IoSampleResponse*>(&response);
  397. rx->setFrameData(getFrameData());
  398. setCommon(response);
  399. rx->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  400. rx->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
  401. }
  402. TxStatusResponse::TxStatusResponse() : FrameIdResponse() {
  403. }
  404. uint8_t TxStatusResponse::getStatus() {
  405. return getFrameData()[1];
  406. }
  407. bool TxStatusResponse::isSuccess() {
  408. return getStatus() == SUCCESS;
  409. }
  410. void XBeeResponse::getTxStatusResponse(XBeeResponse &txResponse) {
  411. TxStatusResponse* txStatus = static_cast<TxStatusResponse*>(&txResponse);
  412. // pass pointer array to subclass
  413. txStatus->setFrameData(getFrameData());
  414. setCommon(txResponse);
  415. }
  416. uint8_t RxResponse::getRssi() {
  417. return getFrameData()[getRssiOffset()];
  418. }
  419. uint8_t RxResponse::getOption() {
  420. return getFrameData()[getRssiOffset() + 1];
  421. }
  422. bool RxResponse::isAddressBroadcast() {
  423. return (getOption() & 2) == 2;
  424. }
  425. bool RxResponse::isPanBroadcast() {
  426. return (getOption() & 4) == 4;
  427. }
  428. uint8_t RxResponse::getDataLength() {
  429. return getPacketLength() - getDataOffset() - 1;
  430. }
  431. uint8_t RxResponse::getDataOffset() {
  432. return getRssiOffset() + 2;
  433. }
  434. uint8_t Rx16Response::getRssiOffset() {
  435. return RX_16_RSSI_OFFSET;
  436. }
  437. void XBeeResponse::getRx16Response(XBeeResponse &rx16Response) {
  438. Rx16Response* rx16 = static_cast<Rx16Response*>(&rx16Response);
  439. // pass pointer array to subclass
  440. rx16->setFrameData(getFrameData());
  441. setCommon(rx16Response);
  442. // rx16->getRemoteAddress16().setAddress((getFrameData()[0] << 8) + getFrameData()[1]);
  443. }
  444. uint8_t Rx64Response::getRssiOffset() {
  445. return RX_64_RSSI_OFFSET;
  446. }
  447. void XBeeResponse::getRx64Response(XBeeResponse &rx64Response) {
  448. Rx64Response* rx64 = static_cast<Rx64Response*>(&rx64Response);
  449. // pass pointer array to subclass
  450. rx64->setFrameData(getFrameData());
  451. setCommon(rx64Response);
  452. rx64->getRemoteAddress64().setMsb((uint32_t(getFrameData()[0]) << 24) + (uint32_t(getFrameData()[1]) << 16) + (uint16_t(getFrameData()[2]) << 8) + getFrameData()[3]);
  453. rx64->getRemoteAddress64().setLsb((uint32_t(getFrameData()[4]) << 24) + (uint32_t(getFrameData()[5]) << 16) + (uint16_t(getFrameData()[6]) << 8) + getFrameData()[7]);
  454. }
  455. #endif
  456. RemoteAtCommandResponse::RemoteAtCommandResponse() : AtCommandResponse() {
  457. }
  458. uint8_t* RemoteAtCommandResponse::getCommand() {
  459. return getFrameData() + 11;
  460. }
  461. uint8_t RemoteAtCommandResponse::getStatus() {
  462. return getFrameData()[13];
  463. }
  464. bool RemoteAtCommandResponse::isOk() {
  465. // weird c++ behavior. w/o this method, it calls AtCommandResponse::isOk(), which calls the AtCommandResponse::getStatus, not this.getStatus!!!
  466. return getStatus() == AT_OK;
  467. }
  468. uint8_t RemoteAtCommandResponse::getValueLength() {
  469. return getFrameDataLength() - 14;
  470. }
  471. uint8_t* RemoteAtCommandResponse::getValue() {
  472. if (getValueLength() > 0) {
  473. // value is only included for query commands. set commands does not return a value
  474. return getFrameData() + 14;
  475. }
  476. return NULL;
  477. }
  478. uint16_t RemoteAtCommandResponse::getRemoteAddress16() {
  479. return uint16_t((getFrameData()[9] << 8) + getFrameData()[10]);
  480. }
  481. XBeeAddress64& RemoteAtCommandResponse::getRemoteAddress64() {
  482. return _remoteAddress64;
  483. }
  484. void XBeeResponse::getRemoteAtCommandResponse(XBeeResponse &response) {
  485. // TODO no real need to cast. change arg to match expected class
  486. RemoteAtCommandResponse* at = static_cast<RemoteAtCommandResponse*>(&response);
  487. // pass pointer array to subclass
  488. at->setFrameData(getFrameData());
  489. setCommon(response);
  490. at->getRemoteAddress64().setMsb((uint32_t(getFrameData()[1]) << 24) + (uint32_t(getFrameData()[2]) << 16) + (uint16_t(getFrameData()[3]) << 8) + getFrameData()[4]);
  491. at->getRemoteAddress64().setLsb((uint32_t(getFrameData()[5]) << 24) + (uint32_t(getFrameData()[6]) << 16) + (uint16_t(getFrameData()[7]) << 8) + (getFrameData()[8]));
  492. }
  493. RxDataResponse::RxDataResponse() : XBeeResponse() {
  494. }
  495. uint8_t RxDataResponse::getData(int index) {
  496. return getFrameData()[getDataOffset() + index];
  497. }
  498. uint8_t* RxDataResponse::getData() {
  499. return getFrameData() + getDataOffset();
  500. }
  501. FrameIdResponse::FrameIdResponse() {
  502. }
  503. uint8_t FrameIdResponse::getFrameId() {
  504. return getFrameData()[0];
  505. }
  506. ModemStatusResponse::ModemStatusResponse() {
  507. }
  508. uint8_t ModemStatusResponse::getStatus() {
  509. return getFrameData()[0];
  510. }
  511. void XBeeResponse::getModemStatusResponse(XBeeResponse &modemStatusResponse) {
  512. ModemStatusResponse* modem = static_cast<ModemStatusResponse*>(&modemStatusResponse);
  513. // pass pointer array to subclass
  514. modem->setFrameData(getFrameData());
  515. setCommon(modemStatusResponse);
  516. }
  517. AtCommandResponse::AtCommandResponse() {
  518. }
  519. uint8_t* AtCommandResponse::getCommand() {
  520. return getFrameData() + 1;
  521. }
  522. uint8_t AtCommandResponse::getStatus() {
  523. return getFrameData()[3];
  524. }
  525. uint8_t AtCommandResponse::getValueLength() {
  526. return getFrameDataLength() - 4;
  527. }
  528. uint8_t* AtCommandResponse::getValue() {
  529. if (getValueLength() > 0) {
  530. // value is only included for query commands. set commands does not return a value
  531. return getFrameData() + 4;
  532. }
  533. return NULL;
  534. }
  535. bool AtCommandResponse::isOk() {
  536. return getStatus() == AT_OK;
  537. }
  538. void XBeeResponse::getAtCommandResponse(XBeeResponse &atCommandResponse) {
  539. AtCommandResponse* at = static_cast<AtCommandResponse*>(&atCommandResponse);
  540. // pass pointer array to subclass
  541. at->setFrameData(getFrameData());
  542. setCommon(atCommandResponse);
  543. }
  544. uint16_t XBeeResponse::getPacketLength() {
  545. return ((_msbLength << 8) & 0xff) + (_lsbLength & 0xff);
  546. }
  547. uint8_t* XBeeResponse::getFrameData() {
  548. return _frameDataPtr;
  549. }
  550. void XBeeResponse::setFrameData(uint8_t* frameDataPtr) {
  551. _frameDataPtr = frameDataPtr;
  552. }
  553. void XBeeResponse::init() {
  554. _complete = false;
  555. _errorCode = NO_ERROR;
  556. _checksum = 0;
  557. }
  558. void XBeeResponse::reset() {
  559. init();
  560. _apiId = 0;
  561. _msbLength = 0;
  562. _lsbLength = 0;
  563. _checksum = 0;
  564. _frameLength = 0;
  565. _errorCode = NO_ERROR;
  566. }
  567. void XBee::resetResponse() {
  568. _pos = 0;
  569. _escape = false;
  570. _response.reset();
  571. }
  572. XBee::XBee(): _response(XBeeResponse()) {
  573. _pos = 0;
  574. _escape = false;
  575. _checksumTotal = 0;
  576. _nextFrameId = 0;
  577. _response.init();
  578. _response.setFrameData(_responseFrameData);
  579. // Contributed by Paul Stoffregen for Teensy support
  580. #if defined(__AVR_ATmega32U4__) || defined(__MK20DX128__) || defined(__MK20DX256__)
  581. _serial = &Serial1;
  582. #else
  583. _serial = &Serial;
  584. #endif
  585. }
  586. uint8_t XBee::getNextFrameId() {
  587. _nextFrameId++;
  588. if (_nextFrameId == 0) {
  589. // can't send 0 because that disables status response
  590. _nextFrameId = 1;
  591. }
  592. return _nextFrameId;
  593. }
  594. // Support for SoftwareSerial. Contributed by Paul Stoffregen
  595. void XBee::begin(Stream &serial) {
  596. _serial = &serial;
  597. }
  598. void XBee::setSerial(Stream &serial) {
  599. _serial = &serial;
  600. }
  601. bool XBee::available() {
  602. return _serial->available();
  603. }
  604. uint8_t XBee::read() {
  605. return _serial->read();
  606. }
  607. void XBee::flush() {
  608. _serial->flush();
  609. }
  610. void XBee::write(uint8_t val) {
  611. _serial->write(val);
  612. }
  613. XBeeResponse& XBee::getResponse() {
  614. return _response;
  615. }
  616. // TODO how to convert response to proper subclass?
  617. void XBee::getResponse(XBeeResponse &response) {
  618. response.setMsbLength(_response.getMsbLength());
  619. response.setLsbLength(_response.getLsbLength());
  620. response.setApiId(_response.getApiId());
  621. response.setFrameLength(_response.getFrameDataLength());
  622. response.setFrameData(_response.getFrameData());
  623. }
  624. void XBee::readPacketUntilAvailable() {
  625. while (!(getResponse().isAvailable() || getResponse().isError())) {
  626. // read some more
  627. readPacket();
  628. }
  629. }
  630. bool XBee::readPacket(int timeout) {
  631. if (timeout < 0) {
  632. return false;
  633. }
  634. unsigned long start = millis();
  635. while (int((millis() - start)) < timeout) {
  636. readPacket();
  637. if (getResponse().isAvailable()) {
  638. return true;
  639. } else if (getResponse().isError()) {
  640. return false;
  641. }
  642. }
  643. // timed out
  644. return false;
  645. }
  646. void XBee::readPacket() {
  647. // reset previous response
  648. if (_response.isAvailable() || _response.isError()) {
  649. // discard previous packet and start over
  650. resetResponse();
  651. }
  652. while (available()) {
  653. b = read();
  654. if (_pos > 0 && b == START_BYTE && ATAP == 2) {
  655. // new packet start before previous packeted completed -- discard previous packet and start over
  656. _response.setErrorCode(UNEXPECTED_START_BYTE);
  657. return;
  658. }
  659. if (_pos > 0 && b == ESCAPE) {
  660. if (available()) {
  661. b = read();
  662. b = 0x20 ^ b;
  663. } else {
  664. // escape byte. next byte will be
  665. _escape = true;
  666. continue;
  667. }
  668. }
  669. if (_escape == true) {
  670. b = 0x20 ^ b;
  671. _escape = false;
  672. }
  673. // checksum includes all bytes starting with api id
  674. if (_pos >= API_ID_INDEX) {
  675. _checksumTotal+= b;
  676. }
  677. switch(_pos) {
  678. case 0:
  679. if (b == START_BYTE) {
  680. _pos++;
  681. }
  682. break;
  683. case 1:
  684. // length msb
  685. _response.setMsbLength(b);
  686. _pos++;
  687. break;
  688. case 2:
  689. // length lsb
  690. _response.setLsbLength(b);
  691. _pos++;
  692. break;
  693. case 3:
  694. _response.setApiId(b);
  695. _pos++;
  696. break;
  697. default:
  698. // starts at fifth byte
  699. if (_pos > MAX_FRAME_DATA_SIZE) {
  700. // exceed max size. should never occur
  701. _response.setErrorCode(PACKET_EXCEEDS_BYTE_ARRAY_LENGTH);
  702. return;
  703. }
  704. // check if we're at the end of the packet
  705. // packet length does not include start, length, or checksum bytes, so add 3
  706. if (_pos == (_response.getPacketLength() + 3)) {
  707. // verify checksum
  708. //std::cout << "read checksum " << static_cast<unsigned int>(b) << " at pos " << static_cast<unsigned int>(_pos) << std::endl;
  709. if ((_checksumTotal & 0xff) == 0xff) {
  710. _response.setChecksum(b);
  711. _response.setAvailable(true);
  712. _response.setErrorCode(NO_ERROR);
  713. } else {
  714. // checksum failed
  715. _response.setErrorCode(CHECKSUM_FAILURE);
  716. }
  717. // minus 4 because we start after start,msb,lsb,api and up to but not including checksum
  718. // e.g. if frame was one byte, _pos=4 would be the byte, pos=5 is the checksum, where end stop reading
  719. _response.setFrameLength(_pos - 4);
  720. // reset state vars
  721. _pos = 0;
  722. _checksumTotal = 0;
  723. return;
  724. } else {
  725. // add to packet array, starting with the fourth byte of the apiFrame
  726. _response.getFrameData()[_pos - 4] = b;
  727. _pos++;
  728. }
  729. }
  730. }
  731. }
  732. // it's peanut butter jelly time!!
  733. XBeeRequest::XBeeRequest(uint8_t apiId, uint8_t frameId) {
  734. _apiId = apiId;
  735. _frameId = frameId;
  736. }
  737. void XBeeRequest::setFrameId(uint8_t frameId) {
  738. _frameId = frameId;
  739. }
  740. uint8_t XBeeRequest::getFrameId() {
  741. return _frameId;
  742. }
  743. uint8_t XBeeRequest::getApiId() {
  744. return _apiId;
  745. }
  746. void XBeeRequest::setApiId(uint8_t apiId) {
  747. _apiId = apiId;
  748. }
  749. //void XBeeRequest::reset() {
  750. // _frameId = DEFAULT_FRAME_ID;
  751. //}
  752. //uint8_t XBeeRequest::getPayloadOffset() {
  753. // return _payloadOffset;
  754. //}
  755. //
  756. //uint8_t XBeeRequest::setPayloadOffset(uint8_t payloadOffset) {
  757. // _payloadOffset = payloadOffset;
  758. //}
  759. PayloadRequest::PayloadRequest(uint8_t apiId, uint8_t frameId, uint8_t *payload, uint8_t payloadLength) : XBeeRequest(apiId, frameId) {
  760. _payloadPtr = payload;
  761. _payloadLength = payloadLength;
  762. }
  763. uint8_t* PayloadRequest::getPayload() {
  764. return _payloadPtr;
  765. }
  766. void PayloadRequest::setPayload(uint8_t* payload) {
  767. _payloadPtr = payload;
  768. }
  769. uint8_t PayloadRequest::getPayloadLength() {
  770. return _payloadLength;
  771. }
  772. void PayloadRequest::setPayloadLength(uint8_t payloadLength) {
  773. _payloadLength = payloadLength;
  774. }
  775. XBeeAddress::XBeeAddress() {
  776. }
  777. XBeeAddress64::XBeeAddress64() : XBeeAddress() {
  778. }
  779. XBeeAddress64::XBeeAddress64(uint32_t msb, uint32_t lsb) : XBeeAddress() {
  780. _msb = msb;
  781. _lsb = lsb;
  782. }
  783. uint32_t XBeeAddress64::getMsb() {
  784. return _msb;
  785. }
  786. void XBeeAddress64::setMsb(uint32_t msb) {
  787. _msb = msb;
  788. }
  789. uint32_t XBeeAddress64::getLsb() {
  790. return _lsb;
  791. }
  792. void XBeeAddress64::setLsb(uint32_t lsb) {
  793. _lsb = lsb;
  794. }
  795. #ifdef SERIES_2
  796. ZBTxRequest::ZBTxRequest() : PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  797. }
  798. ZBTxRequest::ZBTxRequest(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) {
  799. _addr64 = addr64;
  800. _addr16 = addr16;
  801. _broadcastRadius = broadcastRadius;
  802. _option = option;
  803. }
  804. ZBTxRequest::ZBTxRequest(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength): PayloadRequest(ZB_TX_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  805. _addr64 = addr64;
  806. _addr16 = ZB_BROADCAST_ADDRESS;
  807. _broadcastRadius = ZB_BROADCAST_RADIUS_MAX_HOPS;
  808. _option = ZB_TX_UNICAST;
  809. }
  810. uint8_t ZBTxRequest::getFrameData(uint8_t pos) {
  811. if (pos == 0) {
  812. return (_addr64.getMsb() >> 24) & 0xff;
  813. } else if (pos == 1) {
  814. return (_addr64.getMsb() >> 16) & 0xff;
  815. } else if (pos == 2) {
  816. return (_addr64.getMsb() >> 8) & 0xff;
  817. } else if (pos == 3) {
  818. return _addr64.getMsb() & 0xff;
  819. } else if (pos == 4) {
  820. return (_addr64.getLsb() >> 24) & 0xff;
  821. } else if (pos == 5) {
  822. return (_addr64.getLsb() >> 16) & 0xff;
  823. } else if (pos == 6) {
  824. return (_addr64.getLsb() >> 8) & 0xff;
  825. } else if (pos == 7) {
  826. return _addr64.getLsb() & 0xff;
  827. } else if (pos == 8) {
  828. return (_addr16 >> 8) & 0xff;
  829. } else if (pos == 9) {
  830. return _addr16 & 0xff;
  831. } else if (pos == 10) {
  832. return _broadcastRadius;
  833. } else if (pos == 11) {
  834. return _option;
  835. } else {
  836. return getPayload()[pos - ZB_TX_API_LENGTH];
  837. }
  838. }
  839. uint8_t ZBTxRequest::getFrameDataLength() {
  840. return ZB_TX_API_LENGTH + getPayloadLength();
  841. }
  842. XBeeAddress64& ZBTxRequest::getAddress64() {
  843. return _addr64;
  844. }
  845. uint16_t ZBTxRequest::getAddress16() {
  846. return _addr16;
  847. }
  848. uint8_t ZBTxRequest::getBroadcastRadius() {
  849. return _broadcastRadius;
  850. }
  851. uint8_t ZBTxRequest::getOption() {
  852. return _option;
  853. }
  854. void ZBTxRequest::setAddress64(XBeeAddress64& addr64) {
  855. _addr64 = addr64;
  856. }
  857. void ZBTxRequest::setAddress16(uint16_t addr16) {
  858. _addr16 = addr16;
  859. }
  860. void ZBTxRequest::setBroadcastRadius(uint8_t broadcastRadius) {
  861. _broadcastRadius = broadcastRadius;
  862. }
  863. void ZBTxRequest::setOption(uint8_t option) {
  864. _option = option;
  865. }
  866. #endif
  867. #ifdef SERIES_1
  868. Tx16Request::Tx16Request() : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  869. }
  870. Tx16Request::Tx16Request(uint16_t addr16, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_16_REQUEST, frameId, data, dataLength) {
  871. _addr16 = addr16;
  872. _option = option;
  873. }
  874. Tx16Request::Tx16Request(uint16_t addr16, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_16_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  875. _addr16 = addr16;
  876. _option = ACK_OPTION;
  877. }
  878. uint8_t Tx16Request::getFrameData(uint8_t pos) {
  879. if (pos == 0) {
  880. return (_addr16 >> 8) & 0xff;
  881. } else if (pos == 1) {
  882. return _addr16 & 0xff;
  883. } else if (pos == 2) {
  884. return _option;
  885. } else {
  886. return getPayload()[pos - TX_16_API_LENGTH];
  887. }
  888. }
  889. uint8_t Tx16Request::getFrameDataLength() {
  890. return TX_16_API_LENGTH + getPayloadLength();
  891. }
  892. uint16_t Tx16Request::getAddress16() {
  893. return _addr16;
  894. }
  895. void Tx16Request::setAddress16(uint16_t addr16) {
  896. _addr16 = addr16;
  897. }
  898. uint8_t Tx16Request::getOption() {
  899. return _option;
  900. }
  901. void Tx16Request::setOption(uint8_t option) {
  902. _option = option;
  903. }
  904. Tx64Request::Tx64Request() : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, NULL, 0) {
  905. }
  906. Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t option, uint8_t *data, uint8_t dataLength, uint8_t frameId) : PayloadRequest(TX_64_REQUEST, frameId, data, dataLength) {
  907. _addr64 = addr64;
  908. _option = option;
  909. }
  910. Tx64Request::Tx64Request(XBeeAddress64 &addr64, uint8_t *data, uint8_t dataLength) : PayloadRequest(TX_64_REQUEST, DEFAULT_FRAME_ID, data, dataLength) {
  911. _addr64 = addr64;
  912. _option = ACK_OPTION;
  913. }
  914. uint8_t Tx64Request::getFrameData(uint8_t pos) {
  915. if (pos == 0) {
  916. return (_addr64.getMsb() >> 24) & 0xff;
  917. } else if (pos == 1) {
  918. return (_addr64.getMsb() >> 16) & 0xff;
  919. } else if (pos == 2) {
  920. return (_addr64.getMsb() >> 8) & 0xff;
  921. } else if (pos == 3) {
  922. return _addr64.getMsb() & 0xff;
  923. } else if (pos == 4) {
  924. return (_addr64.getLsb() >> 24) & 0xff;
  925. } else if (pos == 5) {
  926. return (_addr64.getLsb() >> 16) & 0xff;
  927. } else if (pos == 6) {
  928. return(_addr64.getLsb() >> 8) & 0xff;
  929. } else if (pos == 7) {
  930. return _addr64.getLsb() & 0xff;
  931. } else if (pos == 8) {
  932. return _option;
  933. } else {
  934. return getPayload()[pos - TX_64_API_LENGTH];
  935. }
  936. }
  937. uint8_t Tx64Request::getFrameDataLength() {
  938. return TX_64_API_LENGTH + getPayloadLength();
  939. }
  940. XBeeAddress64& Tx64Request::getAddress64() {
  941. return _addr64;
  942. }
  943. void Tx64Request::setAddress64(XBeeAddress64& addr64) {
  944. _addr64 = addr64;
  945. }
  946. uint8_t Tx64Request::getOption() {
  947. return _option;
  948. }
  949. void Tx64Request::setOption(uint8_t option) {
  950. _option = option;
  951. }
  952. #endif
  953. AtCommandRequest::AtCommandRequest() : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  954. _command = NULL;
  955. clearCommandValue();
  956. }
  957. AtCommandRequest::AtCommandRequest(uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  958. _command = command;
  959. _commandValue = commandValue;
  960. _commandValueLength = commandValueLength;
  961. }
  962. AtCommandRequest::AtCommandRequest(uint8_t *command) : XBeeRequest(AT_COMMAND_REQUEST, DEFAULT_FRAME_ID) {
  963. _command = command;
  964. clearCommandValue();
  965. }
  966. uint8_t* AtCommandRequest::getCommand() {
  967. return _command;
  968. }
  969. uint8_t* AtCommandRequest::getCommandValue() {
  970. return _commandValue;
  971. }
  972. uint8_t AtCommandRequest::getCommandValueLength() {
  973. return _commandValueLength;
  974. }
  975. void AtCommandRequest::setCommand(uint8_t* command) {
  976. _command = command;
  977. }
  978. void AtCommandRequest::setCommandValue(uint8_t* value) {
  979. _commandValue = value;
  980. }
  981. void AtCommandRequest::setCommandValueLength(uint8_t length) {
  982. _commandValueLength = length;
  983. }
  984. uint8_t AtCommandRequest::getFrameData(uint8_t pos) {
  985. if (pos == 0) {
  986. return _command[0];
  987. } else if (pos == 1) {
  988. return _command[1];
  989. } else {
  990. return _commandValue[pos - AT_COMMAND_API_LENGTH];
  991. }
  992. }
  993. void AtCommandRequest::clearCommandValue() {
  994. _commandValue = NULL;
  995. _commandValueLength = 0;
  996. }
  997. //void AtCommandRequest::reset() {
  998. // XBeeRequest::reset();
  999. //}
  1000. uint8_t AtCommandRequest::getFrameDataLength() {
  1001. // command is 2 byte + length of value
  1002. return AT_COMMAND_API_LENGTH + _commandValueLength;
  1003. }
  1004. XBeeAddress64 RemoteAtCommandRequest::broadcastAddress64 = XBeeAddress64(0x0, BROADCAST_ADDRESS);
  1005. RemoteAtCommandRequest::RemoteAtCommandRequest() : AtCommandRequest(NULL, NULL, 0) {
  1006. _remoteAddress16 = 0;
  1007. _applyChanges = false;
  1008. setApiId(REMOTE_AT_REQUEST);
  1009. }
  1010. RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
  1011. _remoteAddress64 = broadcastAddress64;
  1012. _remoteAddress16 = remoteAddress16;
  1013. _applyChanges = true;
  1014. setApiId(REMOTE_AT_REQUEST);
  1015. }
  1016. RemoteAtCommandRequest::RemoteAtCommandRequest(uint16_t remoteAddress16, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
  1017. _remoteAddress64 = broadcastAddress64;
  1018. _remoteAddress16 = remoteAddress16;
  1019. _applyChanges = false;
  1020. setApiId(REMOTE_AT_REQUEST);
  1021. }
  1022. RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command, uint8_t *commandValue, uint8_t commandValueLength) : AtCommandRequest(command, commandValue, commandValueLength) {
  1023. _remoteAddress64 = remoteAddress64;
  1024. // don't worry.. works for series 1 too!
  1025. _remoteAddress16 = ZB_BROADCAST_ADDRESS;
  1026. _applyChanges = true;
  1027. setApiId(REMOTE_AT_REQUEST);
  1028. }
  1029. RemoteAtCommandRequest::RemoteAtCommandRequest(XBeeAddress64 &remoteAddress64, uint8_t *command) : AtCommandRequest(command, NULL, 0) {
  1030. _remoteAddress64 = remoteAddress64;
  1031. _remoteAddress16 = ZB_BROADCAST_ADDRESS;
  1032. _applyChanges = false;
  1033. setApiId(REMOTE_AT_REQUEST);
  1034. }
  1035. uint16_t RemoteAtCommandRequest::getRemoteAddress16() {
  1036. return _remoteAddress16;
  1037. }
  1038. void RemoteAtCommandRequest::setRemoteAddress16(uint16_t remoteAddress16) {
  1039. _remoteAddress16 = remoteAddress16;
  1040. }
  1041. XBeeAddress64& RemoteAtCommandRequest::getRemoteAddress64() {
  1042. return _remoteAddress64;
  1043. }
  1044. void RemoteAtCommandRequest::setRemoteAddress64(XBeeAddress64 &remoteAddress64) {
  1045. _remoteAddress64 = remoteAddress64;
  1046. }
  1047. bool RemoteAtCommandRequest::getApplyChanges() {
  1048. return _applyChanges;
  1049. }
  1050. void RemoteAtCommandRequest::setApplyChanges(bool applyChanges) {
  1051. _applyChanges = applyChanges;
  1052. }
  1053. uint8_t RemoteAtCommandRequest::getFrameData(uint8_t pos) {
  1054. if (pos == 0) {
  1055. return (_remoteAddress64.getMsb() >> 24) & 0xff;
  1056. } else if (pos == 1) {
  1057. return (_remoteAddress64.getMsb() >> 16) & 0xff;
  1058. } else if (pos == 2) {
  1059. return (_remoteAddress64.getMsb() >> 8) & 0xff;
  1060. } else if (pos == 3) {
  1061. return _remoteAddress64.getMsb() & 0xff;
  1062. } else if (pos == 4) {
  1063. return (_remoteAddress64.getLsb() >> 24) & 0xff;
  1064. } else if (pos == 5) {
  1065. return (_remoteAddress64.getLsb() >> 16) & 0xff;
  1066. } else if (pos == 6) {
  1067. return(_remoteAddress64.getLsb() >> 8) & 0xff;
  1068. } else if (pos == 7) {
  1069. return _remoteAddress64.getLsb() & 0xff;
  1070. } else if (pos == 8) {
  1071. return (_remoteAddress16 >> 8) & 0xff;
  1072. } else if (pos == 9) {
  1073. return _remoteAddress16 & 0xff;
  1074. } else if (pos == 10) {
  1075. return _applyChanges ? 2: 0;
  1076. } else if (pos == 11) {
  1077. return getCommand()[0];
  1078. } else if (pos == 12) {
  1079. return getCommand()[1];
  1080. } else {
  1081. return getCommandValue()[pos - REMOTE_AT_COMMAND_API_LENGTH];
  1082. }
  1083. }
  1084. uint8_t RemoteAtCommandRequest::getFrameDataLength() {
  1085. return REMOTE_AT_COMMAND_API_LENGTH + getCommandValueLength();
  1086. }
  1087. // TODO
  1088. //GenericRequest::GenericRequest(uint8_t* frame, uint8_t len, uint8_t apiId): XBeeRequest(apiId, *(frame), len) {
  1089. // _frame = frame;
  1090. //}
  1091. void XBee::send(XBeeRequest &request) {
  1092. // the new new deal
  1093. sendByte(START_BYTE, false);
  1094. // send length
  1095. uint8_t msbLen = ((request.getFrameDataLength() + 2) >> 8) & 0xff;
  1096. uint8_t lsbLen = (request.getFrameDataLength() + 2) & 0xff;
  1097. sendByte(msbLen, true);
  1098. sendByte(lsbLen, true);
  1099. // api id
  1100. sendByte(request.getApiId(), true);
  1101. sendByte(request.getFrameId(), true);
  1102. uint8_t checksum = 0;
  1103. // compute checksum, start at api id
  1104. checksum+= request.getApiId();
  1105. checksum+= request.getFrameId();
  1106. //std::cout << "frame length is " << static_cast<unsigned int>(request.getFrameDataLength()) << std::endl;
  1107. for (int i = 0; i < request.getFrameDataLength(); i++) {
  1108. // std::cout << "sending byte [" << static_cast<unsigned int>(i) << "] " << std::endl;
  1109. sendByte(request.getFrameData(i), true);
  1110. checksum+= request.getFrameData(i);
  1111. }
  1112. // perform 2s complement
  1113. checksum = 0xff - checksum;
  1114. // std::cout << "checksum is " << static_cast<unsigned int>(checksum) << std::endl;
  1115. // send checksum
  1116. sendByte(checksum, true);
  1117. // send packet (Note: prior to Arduino 1.0 this flushed the incoming buffer, which of course was not so great)
  1118. flush();
  1119. }
  1120. void XBee::sendByte(uint8_t b, bool escape) {
  1121. if (escape && (b == START_BYTE || b == ESCAPE || b == XON || b == XOFF)) {
  1122. // std::cout << "escaping byte [" << toHexString(b) << "] " << std::endl;
  1123. write(ESCAPE);
  1124. write(b ^ 0x20);
  1125. } else {
  1126. write(b);
  1127. }
  1128. }