xsns_04_snfsc.ino 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. xsns_04_snfsc.ino - sonoff SC support 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. /*********************************************************************************************\
  16. Sonoff Sc
  17. sc_value[0] DHT11 Humidity
  18. sc_value[1] DHT11 Temperature in Celsius
  19. sc_value[2] Light level from 1 (Dark) to 10 (Bright) - inverted from original
  20. sc_value[3] Noise level from 1 (Quiet) to 10 (Loud)
  21. sc_value[4] Air Quality level from 1 (Bad) to 10 (Good) - inverted from original
  22. To ATMEGA328P:
  23. AT+DEVCONFIG="uploadFreq":1800,"humiThreshold":2,"tempThreshold":1[1B]
  24. AT+NOTIFY="uploadFreq":1800,"humiThreshold":2,"tempThreshold":1[1B]
  25. response: AT+NOTIFY=ok[1B]
  26. AT+SEND=fail[1B]
  27. AT+SEND=ok[1B]
  28. AT+STATUS=4[1B]
  29. AT+STATUS[1B]
  30. AT+START[1B]
  31. From ATMEGA328P:
  32. AT+UPDATE="humidity":42,"temperature":20,"light":7,"noise":3,"dusty":1[1B]
  33. response: AT+SEND=ok[1B] or AT+SEND=fail[1B]
  34. AT+STATUS?[1B]
  35. response: AT+STATUS=4[1B]
  36. Sequence:
  37. SC sends: ATMEGA328P sends:
  38. AT+START[1B]
  39. AT+UPDATE="humidity":42,"temperature":20,"light":7,"noise":3,"dusty":1[1B]
  40. AT+SEND=ok[1B]
  41. AT+STATUS?[1B]
  42. AT+STATUS=4[1B]
  43. \*********************************************************************************************/
  44. #define XSNS_04 4
  45. uint16_t sc_value[5] = { 0 };
  46. void SonoffScSend(const char *data)
  47. {
  48. Serial.write(data);
  49. Serial.write('\x1B');
  50. snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_TRANSMIT " %s"), data);
  51. AddLog(LOG_LEVEL_DEBUG);
  52. }
  53. void SonoffScInit(void)
  54. {
  55. // SonoffScSend("AT+DEVCONFIG=\"uploadFreq\":1800");
  56. SonoffScSend("AT+START");
  57. // SonoffScSend("AT+STATUS");
  58. }
  59. void SonoffScSerialInput(char *rcvstat)
  60. {
  61. char *p;
  62. char *str;
  63. uint16_t value[5] = { 0 };
  64. snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_SERIAL D_RECEIVED " %s"), rcvstat);
  65. AddLog(LOG_LEVEL_DEBUG);
  66. if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) {
  67. int8_t i = -1;
  68. for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(NULL, ":", &p)) {
  69. value[i++] = atoi(str);
  70. }
  71. if (value[0] > 0) {
  72. for (byte i = 0; i < 5; i++) {
  73. sc_value[i] = value[i];
  74. }
  75. sc_value[2] = (11 - sc_value[2]) * 10; // Invert light level
  76. sc_value[3] *= 10;
  77. sc_value[4] = (11 - sc_value[4]) * 10; // Invert dust level
  78. SonoffScSend("AT+SEND=ok");
  79. } else {
  80. SonoffScSend("AT+SEND=fail");
  81. }
  82. }
  83. else if (!strcasecmp_P(rcvstat, PSTR("AT+STATUS?"))) {
  84. SonoffScSend("AT+STATUS=4");
  85. }
  86. }
  87. /********************************************************************************************/
  88. #ifdef USE_WEBSERVER
  89. const char HTTP_SNS_SCPLUS[] PROGMEM =
  90. "%s{s}" D_LIGHT "{m}%d%%{e}{s}" D_NOISE "{m}%d%%{e}{s}" D_AIR_QUALITY "{m}%d%%{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
  91. #endif // USE_WEBSERVER
  92. void SonoffScShow(boolean json)
  93. {
  94. if (sc_value[0] > 0) {
  95. float t = ConvertTemp(sc_value[1]);
  96. float h = sc_value[0];
  97. char temperature[33];
  98. dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
  99. char humidity[33];
  100. dtostrfd(h, Settings.flag2.humidity_resolution, humidity);
  101. if (json) {
  102. snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"),
  103. mqtt_data, temperature, humidity, sc_value[2], sc_value[3], sc_value[4]);
  104. #ifdef USE_DOMOTICZ
  105. if (0 == tele_period) {
  106. DomoticzTempHumSensor(temperature, humidity);
  107. DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]);
  108. DomoticzSensor(DZ_COUNT, sc_value[3]);
  109. DomoticzSensor(DZ_AIRQUALITY, 500 + ((100 - sc_value[4]) * 20));
  110. }
  111. #endif // USE_DOMOTICZ
  112. #ifdef USE_KNX
  113. if (0 == tele_period) {
  114. KnxSensor(KNX_TEMPERATURE, t);
  115. KnxSensor(KNX_HUMIDITY, h);
  116. }
  117. #endif // USE_KNX
  118. #ifdef USE_WEBSERVER
  119. } else {
  120. snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "", temperature, TempUnit());
  121. snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "", humidity);
  122. snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SCPLUS, mqtt_data, sc_value[2], sc_value[3], sc_value[4]);
  123. #endif // USE_WEBSERVER
  124. }
  125. }
  126. }
  127. /*********************************************************************************************\
  128. * Interface
  129. \*********************************************************************************************/
  130. boolean Xsns04(byte function)
  131. {
  132. boolean result = false;
  133. if (SONOFF_SC == Settings.module) {
  134. switch (function) {
  135. case FUNC_INIT:
  136. SonoffScInit();
  137. break;
  138. case FUNC_JSON_APPEND:
  139. SonoffScShow(1);
  140. break;
  141. #ifdef USE_WEBSERVER
  142. case FUNC_WEB_APPEND:
  143. SonoffScShow(0);
  144. break;
  145. #endif // USE_WEBSERVER
  146. }
  147. }
  148. return result;
  149. }