Fork of the espurna firmware for `mhsw` switches
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.

728 lines
20 KiB

6 years ago
  1. /*
  2. RF MODULE
  3. Copyright (C) 2016-2018 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if defined(ITEAD_SONOFF_RFBRIDGE) || RF_SUPPORT
  6. #include <queue>
  7. #include <Ticker.h>
  8. #if RFB_DIRECT || RF_SUPPORT
  9. #include <RCSwitch.h>
  10. #endif
  11. // -----------------------------------------------------------------------------
  12. // DEFINITIONS
  13. // -----------------------------------------------------------------------------
  14. // EFM8 Protocol
  15. #define RF_MESSAGE_SIZE 9
  16. #define RF_MAX_MESSAGE_SIZE (112+4)
  17. #define RF_CODE_START 0xAA
  18. #define RF_CODE_ACK 0xA0
  19. #define RF_CODE_LEARN 0xA1
  20. #define RF_CODE_LEARN_KO 0xA2
  21. #define RF_CODE_LEARN_OK 0xA3
  22. #define RF_CODE_RFIN 0xA4
  23. #define RF_CODE_RFOUT 0xA5
  24. #define RF_CODE_SNIFFING_ON 0xA6
  25. #define RF_CODE_SNIFFING_OFF 0xA7
  26. #define RF_CODE_RFOUT_NEW 0xA8
  27. #define RF_CODE_LEARN_NEW 0xA9
  28. #define RF_CODE_LEARN_KO_NEW 0xAA
  29. #define RF_CODE_LEARN_OK_NEW 0xAB
  30. #define RF_CODE_RFOUT_BUCKET 0xB0
  31. #define RF_CODE_STOP 0x55
  32. // Settings
  33. #define RF_MAX_KEY_LENGTH (9)
  34. // -----------------------------------------------------------------------------
  35. // GLOBALS TO THE MODULE
  36. // -----------------------------------------------------------------------------
  37. unsigned char _uartbuf[RF_MESSAGE_SIZE+3] = {0};
  38. unsigned char _uartpos = 0;
  39. unsigned char _learnId = 0;
  40. bool _learnStatus = true;
  41. bool _rfbin = false;
  42. #if not RF_SUPPORT
  43. typedef struct {
  44. byte code[RF_MESSAGE_SIZE];
  45. byte times;
  46. } rfb_message_t;
  47. static std::queue<rfb_message_t> _rfb_message_queue;
  48. Ticker _rfb_ticker;
  49. bool _rfb_ticker_active = false;
  50. #endif
  51. #if RFB_DIRECT || RF_SUPPORT
  52. RCSwitch * _rfModem;
  53. bool _learning = false;
  54. #endif
  55. #if WEB_SUPPORT
  56. Ticker _rfb_sendcodes;
  57. #endif
  58. // -----------------------------------------------------------------------------
  59. // PRIVATES
  60. // -----------------------------------------------------------------------------
  61. /*
  62. From a byte array to an hexa char array ("A220EE...", double the size)
  63. */
  64. static bool _rfbToChar(byte * in, char * out, int n = RF_MESSAGE_SIZE) {
  65. for (unsigned char p = 0; p<n; p++) {
  66. sprintf_P(&out[p*2], PSTR("%02X"), in[p]);
  67. }
  68. return true;
  69. }
  70. #if WEB_SUPPORT
  71. void _rfbWebSocketSendCode(unsigned char id, bool status, const char * code) {
  72. char wsb[192]; // (32 * 5): 46 bytes for json , 116 bytes raw code, reserve
  73. snprintf_P(wsb, sizeof(wsb), PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"%s\"}]}"), id, status ? 1 : 0, code);
  74. wsSend(wsb);
  75. }
  76. void _rfbWebSocketSendCodes() {
  77. for (unsigned char id=0; id<relayCount(); id++) {
  78. _rfbWebSocketSendCode(id, true, rfbRetrieve(id, true).c_str());
  79. _rfbWebSocketSendCode(id, false, rfbRetrieve(id, false).c_str());
  80. }
  81. }
  82. void _rfbWebSocketOnSend(JsonObject& root) {
  83. root["rfbVisible"] = 1;
  84. root["rfbCount"] = relayCount();
  85. #if RF_RAW_SUPPORT
  86. root["rfbrawVisible"] = 1;
  87. #endif
  88. _rfb_sendcodes.once_ms(1000, _rfbWebSocketSendCodes);
  89. }
  90. void _rfbWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) {
  91. if (strcmp(action, "rfblearn") == 0) rfbLearn(data["id"], data["status"]);
  92. if (strcmp(action, "rfbforget") == 0) rfbForget(data["id"], data["status"]);
  93. if (strcmp(action, "rfbsend") == 0) rfbStore(data["id"], data["status"], data["data"].as<const char*>());
  94. }
  95. #endif // WEB_SUPPORT
  96. void _rfbAck() {
  97. #if (not RFB_DIRECT) && (not RF_SUPPORT)
  98. DEBUG_MSG_P(PSTR("[RF] Sending ACK\n"));
  99. Serial.println();
  100. Serial.write(RF_CODE_START);
  101. Serial.write(RF_CODE_ACK);
  102. Serial.write(RF_CODE_STOP);
  103. Serial.flush();
  104. Serial.println();
  105. #endif
  106. }
  107. void _rfbLearn() {
  108. #if RFB_DIRECT || RF_SUPPORT
  109. DEBUG_MSG_P(PSTR("[RF] Entering LEARN mode\n"));
  110. _learning = true;
  111. #else
  112. DEBUG_MSG_P(PSTR("[RF] Sending LEARN\n"));
  113. Serial.println();
  114. Serial.write(RF_CODE_START);
  115. Serial.write(RF_CODE_LEARN);
  116. Serial.write(RF_CODE_STOP);
  117. Serial.flush();
  118. Serial.println();
  119. #endif
  120. #if WEB_SUPPORT
  121. char buffer[100];
  122. snprintf_P(buffer, sizeof(buffer), PSTR("{\"action\": \"rfbLearn\", \"data\":{\"id\": %d, \"status\": %d}}"), _learnId, _learnStatus ? 1 : 0);
  123. wsSend(buffer);
  124. #endif
  125. }
  126. #if not RF_SUPPORT
  127. /*
  128. From an hexa char array ("A220EE...") to a byte array (half the size)
  129. */
  130. static int _rfbToArray(const char * in, byte * out, int length = RF_MESSAGE_SIZE * 2) {
  131. int n = strlen(in);
  132. if (n > RF_MAX_MESSAGE_SIZE*2 || (length > 0 && n != length)) return 0;
  133. char tmp[3] = {0,0,0};
  134. n /= 2;
  135. for (unsigned char p = 0; p<n; p++) {
  136. memcpy(tmp, &in[p*2], 2);
  137. out[p] = strtol(tmp, NULL, 16);
  138. }
  139. return n;
  140. }
  141. void _rfbSendRaw(const byte *message, const unsigned char n = RF_MESSAGE_SIZE) {
  142. for (unsigned char j=0; j<n; j++) {
  143. Serial.write(message[j]);
  144. }
  145. }
  146. void _rfbSend(byte * message) {
  147. #if RFB_DIRECT
  148. unsigned int protocol = message[1];
  149. unsigned int timing =
  150. (message[2] << 8) |
  151. (message[3] << 0) ;
  152. unsigned int bitlength = message[4];
  153. unsigned long rf_code =
  154. (message[5] << 24) |
  155. (message[6] << 16) |
  156. (message[7] << 8) |
  157. (message[8] << 0) ;
  158. _rfModem->setProtocol(protocol);
  159. if (timing > 0) {
  160. _rfModem->setPulseLength(timing);
  161. }
  162. _rfModem->send(rf_code, bitlength);
  163. _rfModem->resetAvailable();
  164. #else
  165. Serial.println();
  166. Serial.write(RF_CODE_START);
  167. Serial.write(RF_CODE_RFOUT);
  168. _rfbSendRaw(message);
  169. Serial.write(RF_CODE_STOP);
  170. Serial.flush();
  171. Serial.println();
  172. #endif
  173. }
  174. void _rfbSend() {
  175. // Check if there is something in the queue
  176. if (_rfb_message_queue.empty()) return;
  177. // Pop the first element
  178. rfb_message_t message = _rfb_message_queue.front();
  179. _rfb_message_queue.pop();
  180. // Send the message
  181. _rfbSend(message.code);
  182. // If it should be further sent, push it to the stack again
  183. if (message.times > 1) {
  184. message.times = message.times - 1;
  185. _rfb_message_queue.push(message);
  186. }
  187. // if there are still messages in the queue...
  188. if (_rfb_message_queue.empty()) {
  189. _rfb_ticker.detach();
  190. _rfb_ticker_active = false;
  191. }
  192. }
  193. void _rfbSend(byte * code, unsigned char times) {
  194. #if RFB_DIRECT
  195. times = 1;
  196. #endif
  197. char buffer[RF_MESSAGE_SIZE];
  198. _rfbToChar(code, buffer);
  199. DEBUG_MSG_P(PSTR("[RF] Enqueuing MESSAGE '%s' %d time(s)\n"), buffer, times);
  200. rfb_message_t message;
  201. memcpy(message.code, code, RF_MESSAGE_SIZE);
  202. message.times = times;
  203. _rfb_message_queue.push(message);
  204. // Enable the ticker if not running
  205. if (!_rfb_ticker_active) {
  206. _rfb_ticker_active = true;
  207. _rfb_ticker.attach_ms(RF_SEND_DELAY, _rfbSend);
  208. }
  209. }
  210. #endif // not RF_SUPPORT
  211. #if RF_RAW_SUPPORT
  212. void _rfbSendRawOnce(byte *code, unsigned char length) {
  213. char buffer[length*2];
  214. _rfbToChar(code, buffer, length);
  215. DEBUG_MSG_P(PSTR("[RF] Sending RAW MESSAGE '%s'\n"), buffer);
  216. _rfbSendRaw(code, length);
  217. }
  218. #endif // RF_RAW_SUPPORT
  219. bool _rfbMatch(char* code, unsigned char& relayID, unsigned char& value, char* buffer = NULL) {
  220. if (strlen(code) != 18) return false;
  221. bool found = false;
  222. String compareto = String(&code[12]);
  223. compareto.toUpperCase();
  224. DEBUG_MSG_P(PSTR("[RF] Trying to match code %s\n"), compareto.c_str());
  225. for (unsigned char i=0; i<relayCount(); i++) {
  226. String code_on = rfbRetrieve(i, true);
  227. if (code_on.length() && code_on.endsWith(compareto)) {
  228. DEBUG_MSG_P(PSTR("[RF] Match ON code for relay %d\n"), i);
  229. value = 1;
  230. found = true;
  231. if (buffer) strcpy(buffer, code_on.c_str());
  232. }
  233. String code_off = rfbRetrieve(i, false);
  234. if (code_off.length() && code_off.endsWith(compareto)) {
  235. DEBUG_MSG_P(PSTR("[RF] Match OFF code for relay %d\n"), i);
  236. if (found) value = 2;
  237. found = true;
  238. if (buffer) strcpy(buffer, code_off.c_str());
  239. }
  240. if (found) {
  241. relayID = i;
  242. return true;
  243. }
  244. }
  245. return false;
  246. }
  247. void _rfbDecode() {
  248. static unsigned long last = 0;
  249. if (millis() - last < RF_RECEIVE_DELAY) return;
  250. last = millis();
  251. byte action = _uartbuf[0];
  252. char buffer[RF_MESSAGE_SIZE * 2 + 1] = {0};
  253. DEBUG_MSG_P(PSTR("[RF] Action 0x%02X\n"), action);
  254. if (action == RF_CODE_LEARN_KO) {
  255. _rfbAck();
  256. DEBUG_MSG_P(PSTR("[RF] Learn timeout\n"));
  257. #if WEB_SUPPORT
  258. wsSend_P(PSTR("{\"action\": \"rfbTimeout\"}"));
  259. #endif
  260. }
  261. if (action == RF_CODE_LEARN_OK || action == RF_CODE_RFIN) {
  262. _rfbAck();
  263. _rfbToChar(&_uartbuf[1], buffer);
  264. DEBUG_MSG_P(PSTR("[RF] Received message '%s'\n"), buffer);
  265. }
  266. if (action == RF_CODE_LEARN_OK) {
  267. DEBUG_MSG_P(PSTR("[RF] Learn success\n"));
  268. rfbStore(_learnId, _learnStatus, buffer);
  269. // Websocket update
  270. #if WEB_SUPPORT
  271. _rfbWebSocketSendCode(_learnId, _learnStatus, buffer);
  272. #endif
  273. }
  274. if (action == RF_CODE_RFIN) {
  275. /* Look for the code, possibly replacing the code with the exact learned one on match
  276. * we want to do this on learn too to be sure that the learned code is the same if it
  277. * is equivalent
  278. */
  279. unsigned char id;
  280. unsigned char status;
  281. bool matched = _rfbMatch(buffer, id, status, buffer);
  282. if (matched) {
  283. DEBUG_MSG_P(PSTR("[RF] Matched message '%s'\n"), buffer);
  284. _rfbin = true;
  285. if (status == 2) {
  286. relayToggle(id);
  287. } else {
  288. relayStatus(id, status == 1);
  289. }
  290. }
  291. #if MQTT_SUPPORT
  292. mqttSend(MQTT_TOPIC_RFIN, buffer);
  293. #endif
  294. }
  295. }
  296. void _rfbReceive() {
  297. #if RFB_DIRECT || RF_SUPPORT
  298. static long learn_start = 0;
  299. if (!_learning && learn_start) {
  300. learn_start = 0;
  301. }
  302. if (_learning) {
  303. if (!learn_start) {
  304. DEBUG_MSG_P(PSTR("[RF] Arming learn timeout\n"));
  305. learn_start = millis();
  306. }
  307. if (learn_start > 0 && millis() - learn_start > RF_LEARN_TIMEOUT) {
  308. DEBUG_MSG_P(PSTR("[RF] Learn timeout triggered\n"));
  309. memset(_uartbuf, 0, sizeof(_uartbuf));
  310. _uartbuf[0] = RF_CODE_LEARN_KO;
  311. _rfbDecode();
  312. _learning = false;
  313. }
  314. }
  315. if (_rfModem->available()) {
  316. static unsigned long last = 0;
  317. if (millis() - last > RF_DEBOUNCE) {
  318. last = millis();
  319. unsigned long rf_code = _rfModem->getReceivedValue();
  320. if ( rf_code > 0) {
  321. DEBUG_MSG_P(PSTR("[RF] Received code: %08X\n"), rf_code);
  322. unsigned int timing = _rfModem->getReceivedDelay();
  323. memset(_uartbuf, 0, sizeof(_uartbuf));
  324. unsigned char *msgbuf = _uartbuf + 1;
  325. _uartbuf[0] = _learning ? RF_CODE_LEARN_OK: RF_CODE_RFIN;
  326. msgbuf[0] = 0xC0;
  327. msgbuf[1] = _rfModem->getReceivedProtocol();
  328. msgbuf[2] = timing >> 8;
  329. msgbuf[3] = timing >> 0;
  330. msgbuf[4] = _rfModem->getReceivedBitlength();
  331. msgbuf[5] = rf_code >> 24;
  332. msgbuf[6] = rf_code >> 16;
  333. msgbuf[7] = rf_code >> 8;
  334. msgbuf[8] = rf_code >> 0;
  335. _rfbDecode();
  336. _learning = false;
  337. }
  338. }
  339. _rfModem->resetAvailable();
  340. }
  341. #else
  342. static bool receiving = false;
  343. while (Serial.available()) {
  344. yield();
  345. byte c = Serial.read();
  346. //DEBUG_MSG_P(PSTR("[RF] Received 0x%02X\n"), c);
  347. if (receiving) {
  348. if (c == RF_CODE_STOP && (_uartpos == 1 || _uartpos == RF_MESSAGE_SIZE + 1)) {
  349. _rfbDecode();
  350. receiving = false;
  351. } else if (_uartpos <= RF_MESSAGE_SIZE) {
  352. _uartbuf[_uartpos++] = c;
  353. } else {
  354. // wrong message, should have received a RF_CODE_STOP
  355. receiving = false;
  356. }
  357. } else if (c == RF_CODE_START) {
  358. _uartpos = 0;
  359. receiving = true;
  360. }
  361. }
  362. #endif
  363. }
  364. bool _rfbCompare(const char * code1, const char * code2) {
  365. return strcmp(&code1[12], &code2[12]) == 0;
  366. }
  367. bool _rfbSameOnOff(unsigned char id) {
  368. return _rfbCompare(rfbRetrieve(id, true).c_str(), rfbRetrieve(id, false).c_str());
  369. }
  370. #if MQTT_SUPPORT
  371. void _rfbMqttCallback(unsigned int type, const char * topic, const char * payload) {
  372. if (type == MQTT_CONNECT_EVENT) {
  373. char buffer[strlen(MQTT_TOPIC_RFLEARN) + 3];
  374. snprintf_P(buffer, sizeof(buffer), PSTR("%s/+"), MQTT_TOPIC_RFLEARN);
  375. mqttSubscribe(buffer);
  376. #if not RF_SUPPORT
  377. mqttSubscribe(MQTT_TOPIC_RFOUT);
  378. #endif
  379. #if RF_RAW_SUPPORT
  380. mqttSubscribe(MQTT_TOPIC_RFRAW);
  381. #endif
  382. }
  383. if (type == MQTT_MESSAGE_EVENT) {
  384. // Match topic
  385. String t = mqttMagnitude((char *) topic);
  386. // Check if should go into learn mode
  387. if (t.startsWith(MQTT_TOPIC_RFLEARN)) {
  388. _learnId = t.substring(strlen(MQTT_TOPIC_RFLEARN)+1).toInt();
  389. if (_learnId >= relayCount()) {
  390. DEBUG_MSG_P(PSTR("[RF] Wrong learnID (%d)\n"), _learnId);
  391. return;
  392. }
  393. _learnStatus = (char)payload[0] != '0';
  394. _rfbLearn();
  395. return;
  396. }
  397. #if not RF_SUPPORT
  398. bool isRFOut = t.equals(MQTT_TOPIC_RFOUT);
  399. #endif
  400. #if RF_RAW_SUPPORT
  401. bool isRFRaw = !isRFOut && t.equals(MQTT_TOPIC_RFRAW);
  402. #elif not RF_SUPPORT
  403. bool isRFRaw = false;
  404. #endif
  405. #if not RF_SUPPORT
  406. if (isRFOut || isRFRaw) {
  407. // The payload may be a code in HEX format ([0-9A-Z]{18}) or
  408. // the code comma the number of times to transmit it.
  409. char * tok = strtok((char *) payload, ",");
  410. // Check if a switch is linked to that message
  411. unsigned char id;
  412. unsigned char status = 0;
  413. if (_rfbMatch(tok, id, status)) {
  414. if (status == 2) {
  415. relayToggle(id);
  416. } else {
  417. relayStatus(id, status == 1);
  418. }
  419. return;
  420. }
  421. #if RF_RAW_SUPPORT
  422. byte message[RF_MAX_MESSAGE_SIZE];
  423. int len = _rfbToArray(tok, message, 0);
  424. if ((len > 0) && (isRFRaw || len != RF_MESSAGE_SIZE)) {
  425. _rfbSendRawOnce(message, len);
  426. } else {
  427. tok = strtok(NULL, ",");
  428. byte times = (tok != NULL) ? atoi(tok) : 1;
  429. _rfbSend(message, times);
  430. }
  431. #else // RF_RAW_SUPPORT
  432. byte message[RF_MESSAGE_SIZE];
  433. if (_rfbToArray(tok, message)) {
  434. tok = strtok(NULL, ",");
  435. byte times = (tok != NULL) ? atoi(tok) : 1;
  436. _rfbSend(message, times);
  437. }
  438. #endif // RF_RAW_SUPPORT
  439. }
  440. #endif // not RF_SUPPORT
  441. }
  442. }
  443. #endif
  444. #if TERMINAL_SUPPORT
  445. void _rfbInitCommands() {
  446. settingsRegisterCommand(F("LEARN"), [](Embedis* e) {
  447. if (e->argc < 3) {
  448. DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n"));
  449. return;
  450. }
  451. int id = String(e->argv[1]).toInt();
  452. if (id >= relayCount()) {
  453. DEBUG_MSG_P(PSTR("-ERROR: Wrong relayID (%d)\n"), id);
  454. return;
  455. }
  456. int status = String(e->argv[2]).toInt();
  457. rfbLearn(id, status == 1);
  458. DEBUG_MSG_P(PSTR("+OK\n"));
  459. });
  460. settingsRegisterCommand(F("FORGET"), [](Embedis* e) {
  461. if (e->argc < 3) {
  462. DEBUG_MSG_P(PSTR("-ERROR: Wrong arguments\n"));
  463. return;
  464. }
  465. int id = String(e->argv[1]).toInt();
  466. if (id >= relayCount()) {
  467. DEBUG_MSG_P(PSTR("-ERROR: Wrong relayID (%d)\n"), id);
  468. return;
  469. }
  470. int status = String(e->argv[2]).toInt();
  471. rfbForget(id, status == 1);
  472. DEBUG_MSG_P(PSTR("+OK\n"));
  473. });
  474. }
  475. #endif // TERMINAL_SUPPORT
  476. // -----------------------------------------------------------------------------
  477. // PUBLIC
  478. // -----------------------------------------------------------------------------
  479. void rfbStore(unsigned char id, bool status, const char * code) {
  480. DEBUG_MSG_P(PSTR("[RF] Storing %d-%s => '%s'\n"), id, status ? "ON" : "OFF", code);
  481. char key[RF_MAX_KEY_LENGTH] = {0};
  482. snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
  483. setSetting(key, code);
  484. }
  485. String rfbRetrieve(unsigned char id, bool status) {
  486. char key[RF_MAX_KEY_LENGTH] = {0};
  487. snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
  488. return getSetting(key);
  489. }
  490. #if not RF_SUPPORT
  491. void rfbStatus(unsigned char id, bool status) {
  492. String value = rfbRetrieve(id, status);
  493. if (value.length() > 0) {
  494. bool same = _rfbSameOnOff(id);
  495. #if RF_RAW_SUPPORT
  496. byte message[RF_MAX_MESSAGE_SIZE];
  497. int len = _rfbToArray(value.c_str(), message, 0);
  498. if (len == RF_MESSAGE_SIZE && // probably a standard msg
  499. (message[0] != RF_CODE_START || // raw would start with 0xAA
  500. message[1] != RF_CODE_RFOUT_BUCKET || // followed by 0xB0,
  501. message[2] + 4 != len || // needs a valid length,
  502. message[len-1] != RF_CODE_STOP)) { // and finish with 0x55
  503. if (!_rfbin) {
  504. unsigned char times = same ? 1 : RF_SEND_TIMES;
  505. _rfbSend(message, times);
  506. }
  507. } else {
  508. _rfbSendRawOnce(message, len); // send a raw message
  509. }
  510. #else // RF_RAW_SUPPORT
  511. if (!_rfbin) {
  512. byte message[RF_MESSAGE_SIZE];
  513. _rfbToArray(value.c_str(), message);
  514. unsigned char times = same ? 1 : RF_SEND_TIMES;
  515. _rfbSend(message, times);
  516. }
  517. #endif // RF_RAW_SUPPORT
  518. }
  519. _rfbin = false;
  520. }
  521. #endif // not RF_SUPPORT
  522. void rfbLearn(unsigned char id, bool status) {
  523. _learnId = id;
  524. _learnStatus = status;
  525. _rfbLearn();
  526. }
  527. void rfbForget(unsigned char id, bool status) {
  528. char key[RF_MAX_KEY_LENGTH] = {0};
  529. snprintf_P(key, sizeof(key), PSTR("rfb%s%d"), status ? "ON" : "OFF", id);
  530. delSetting(key);
  531. // Websocket update
  532. #if WEB_SUPPORT
  533. char wsb[100];
  534. snprintf_P(wsb, sizeof(wsb), PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"\"}]}"), id, status ? 1 : 0);
  535. wsSend(wsb);
  536. #endif
  537. }
  538. // -----------------------------------------------------------------------------
  539. // SETUP & LOOP
  540. // -----------------------------------------------------------------------------
  541. void rfbSetup() {
  542. #if MQTT_SUPPORT
  543. mqttRegister(_rfbMqttCallback);
  544. #endif
  545. #if WEB_SUPPORT
  546. wsOnSendRegister(_rfbWebSocketOnSend);
  547. wsOnActionRegister(_rfbWebSocketOnAction);
  548. #endif
  549. #if TERMINAL_SUPPORT
  550. _rfbInitCommands();
  551. #endif
  552. #if RFB_DIRECT || RF_SUPPORT
  553. _rfModem = new RCSwitch();
  554. #if RF_SUPPORT
  555. _rfModem->enableReceive(RF_PIN);
  556. DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), RF_PIN);
  557. #else
  558. _rfModem->enableReceive(RFB_RX_PIN);
  559. _rfModem->enableTransmit(RFB_TX_PIN);
  560. _rfModem->setRepeatTransmit(6);
  561. DEBUG_MSG_P(PSTR("[RF] RF receiver on GPIO %u\n"), RFB_RX_PIN);
  562. DEBUG_MSG_P(PSTR("[RF] RF transmitter on GPIO %u\n"), RFB_TX_PIN);
  563. #endif
  564. #endif
  565. // Register loop
  566. espurnaRegisterLoop(rfbLoop);
  567. }
  568. void rfbLoop() {
  569. _rfbReceive();
  570. }
  571. #endif