xdrv_17_rcswitch.ino 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota
  3. Copyright (C) 2018 Theo Arends
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifdef USE_RC_SWITCH
  16. /*********************************************************************************************\
  17. * RF send and receive using RCSwitch library https://github.com/sui77/rc-switch/
  18. \*********************************************************************************************/
  19. #define XDRV_17 17
  20. #define D_JSON_RF_PROTOCOL "Protocol"
  21. #define D_JSON_RF_BITS "Bits"
  22. #define D_JSON_RF_DATA "Data"
  23. #define D_CMND_RFSEND "RFSend"
  24. #define D_JSON_RF_PULSE "Pulse"
  25. #define D_JSON_RF_REPEAT "Repeat"
  26. #include <RCSwitch.h>
  27. RCSwitch mySwitch = RCSwitch();
  28. #define RF_TIME_AVOID_DUPLICATE 1000 // Milliseconds
  29. uint32_t rf_lasttime = 0;
  30. void RfReceiveCheck(void)
  31. {
  32. if (mySwitch.available()) {
  33. unsigned long data = mySwitch.getReceivedValue();
  34. unsigned int bits = mySwitch.getReceivedBitlength();
  35. int protocol = mySwitch.getReceivedProtocol();
  36. int delay = mySwitch.getReceivedDelay();
  37. snprintf_P(log_data, sizeof(log_data), PSTR("RFR: Data %lX (%u), Bits %d, Protocol %d, Delay %d"), data, data, bits, protocol, delay);
  38. AddLog(LOG_LEVEL_DEBUG);
  39. uint32_t now = millis();
  40. if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (data > 0)) {
  41. rf_lasttime = now;
  42. char stemp[16];
  43. if (Settings.flag.rf_receive_decimal) { // SetOption28 (0 = hexadecimal, 1 = decimal)
  44. snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data);
  45. } else {
  46. snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)data);
  47. }
  48. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"),
  49. stemp, bits, protocol, delay);
  50. MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
  51. XdrvRulesProcess();
  52. #ifdef USE_DOMOTICZ
  53. DomoticzSensor(DZ_COUNT, data); // Send data as Domoticz Counter value
  54. #endif // USE_DOMOTICZ
  55. }
  56. mySwitch.resetAvailable();
  57. }
  58. }
  59. void RfInit(void)
  60. {
  61. if (pin[GPIO_RFSEND] < 99) {
  62. mySwitch.enableTransmit(pin[GPIO_RFSEND]);
  63. }
  64. if (pin[GPIO_RFRECV] < 99) {
  65. mySwitch.enableReceive(pin[GPIO_RFRECV]);
  66. }
  67. }
  68. /*********************************************************************************************\
  69. * Commands
  70. \*********************************************************************************************/
  71. boolean RfSendCommand(void)
  72. {
  73. boolean serviced = true;
  74. boolean error = false;
  75. if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_RFSEND))) {
  76. if (XdrvMailbox.data_len) {
  77. unsigned long data = 0;
  78. unsigned int bits = 24;
  79. int protocol = 1;
  80. int repeat = 10;
  81. int pulse = 350;
  82. char dataBufUc[XdrvMailbox.data_len];
  83. UpperCase(dataBufUc, XdrvMailbox.data);
  84. StaticJsonBuffer<150> jsonBuf; // ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(5) + 40 = 134
  85. JsonObject &root = jsonBuf.parseObject(dataBufUc);
  86. if (root.success()) {
  87. // RFsend {"data":0x501014,"bits":24,"protocol":1,"repeat":10,"pulse":350}
  88. char parm_uc[10];
  89. data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input
  90. bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))];
  91. protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))];
  92. repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))];
  93. pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))];
  94. } else {
  95. // RFsend data, bits, protocol, repeat, pulse
  96. char *p;
  97. byte i = 0;
  98. for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(NULL, ", ", &p)) {
  99. switch (i++) {
  100. case 0:
  101. data = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input
  102. break;
  103. case 1:
  104. bits = atoi(str);
  105. break;
  106. case 2:
  107. protocol = atoi(str);
  108. break;
  109. case 3:
  110. repeat = atoi(str);
  111. break;
  112. case 4:
  113. pulse = atoi(str);
  114. }
  115. }
  116. }
  117. if (!protocol) { protocol = 1; }
  118. mySwitch.setProtocol(protocol);
  119. if (!pulse) { pulse = 350; } // Default pulse length for protocol 1
  120. mySwitch.setPulseLength(pulse);
  121. if (!repeat) { repeat = 10; } // Default at init
  122. mySwitch.setRepeatTransmit(repeat);
  123. if (!bits) { bits = 24; } // Default 24 bits
  124. if (data) {
  125. mySwitch.send(data, bits);
  126. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}"));
  127. } else {
  128. error = true;
  129. }
  130. } else {
  131. error = true;
  132. }
  133. if (error) {
  134. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}"));
  135. }
  136. }
  137. else serviced = false; // Unknown command
  138. return serviced;
  139. }
  140. /*********************************************************************************************\
  141. * Interface
  142. \*********************************************************************************************/
  143. boolean Xdrv17(byte function)
  144. {
  145. boolean result = false;
  146. if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) {
  147. switch (function) {
  148. case FUNC_INIT:
  149. RfInit();
  150. break;
  151. case FUNC_EVERY_50_MSECOND:
  152. if (pin[GPIO_RFRECV] < 99) {
  153. RfReceiveCheck();
  154. }
  155. break;
  156. case FUNC_COMMAND:
  157. if (pin[GPIO_RFSEND] < 99) {
  158. result = RfSendCommand();
  159. }
  160. break;
  161. }
  162. }
  163. return result;
  164. }
  165. #endif // USE_RC_SWITCH