ESP32 / ESP8266 & BME280 / SHT2x sensor with InfluxDB support
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

smart_meter.cpp 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * smart_meter.cpp
  3. *
  4. * ESP8266 / ESP32 Environmental Sensor
  5. *
  6. * ----------------------------------------------------------------------------
  7. * "THE BEER-WARE LICENSE" (Revision 42):
  8. * <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  9. * you can do whatever you want with this stuff. If we meet some day, and you
  10. * think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  11. * ----------------------------------------------------------------------------
  12. */
  13. #ifdef FEATURE_SML
  14. #include <Arduino.h>
  15. #include <sml.h>
  16. #include <SoftwareSerial.h>
  17. #include "config.h"
  18. #include "DebugLog.h"
  19. #include "lora.h"
  20. #include "smart_meter.h"
  21. #define SML_TX 33
  22. #define SML_RX 34
  23. #define SML_BAUD 9600
  24. #define SML_PARAM SWSERIAL_8N1
  25. static EspSoftwareSerial::UART port1, port2;
  26. RTC_DATA_ATTR static unsigned long counter = 0;
  27. static double SumWh = NAN, T1Wh = NAN, T2Wh = NAN;
  28. static double SumW = NAN, L1W = NAN, L2W = NAN, L3W = NAN;
  29. bool sml_data_received(void) {
  30. return counter > 0;
  31. }
  32. static void EnergySum(void) {
  33. smlOBISWh(SumWh);
  34. }
  35. static void EnergyT1(void) {
  36. smlOBISWh(T1Wh);
  37. }
  38. static void EnergyT2(void) {
  39. smlOBISWh(T2Wh);
  40. }
  41. static void PowerSum(void) {
  42. smlOBISW(SumW);
  43. }
  44. static void PowerL1(void) {
  45. smlOBISW(L1W);
  46. }
  47. static void PowerL2(void) {
  48. smlOBISW(L2W);
  49. }
  50. static void PowerL3(void) {
  51. smlOBISW(L3W);
  52. }
  53. static void init_vars(void) {
  54. SumWh = NAN;
  55. T1Wh = NAN;
  56. T2Wh = NAN;
  57. SumW = NAN;
  58. L1W = NAN;
  59. L2W = NAN;
  60. L3W = NAN;
  61. }
  62. typedef struct {
  63. const unsigned char OBIS[6];
  64. void (*Handler)();
  65. } OBISHandler;
  66. static OBISHandler handlers[] = {
  67. { { 1, 0, 1, 8, 0, 255 }, EnergySum }, // 1-0: 1.8.0*255 (T1 + T2) Wh
  68. { { 1, 0, 1, 8, 1, 255 }, EnergyT1 }, // 1-0: 1.8.1*255 (T1) Wh
  69. { { 1, 0, 1, 8, 2, 255 }, EnergyT2 }, // 1-0: 1.8.2*255 (T2) Wh
  70. { { 1, 0, 16, 7, 0, 255 }, PowerSum }, // 1-0:16.7.0*255 (L1 + L2 + L3) W
  71. { { 1, 0, 21, 7, 0, 255 }, PowerL1 }, // 1-0:21.7.0*255 (L1) W
  72. { { 1, 0, 41, 7, 0, 255 }, PowerL2 }, // 1-0:41.7.0*255 (L2) W
  73. { { 1, 0, 61, 7, 0, 255 }, PowerL3 }, // 1-0:61.7.0*255 (L3) W
  74. };
  75. void sml_init(void) {
  76. init_vars();
  77. port1.begin(SML_BAUD, SML_PARAM, SML_RX, -1, false);
  78. port2.begin(SML_BAUD, SML_PARAM, SML_TX, -1, false);
  79. }
  80. void sml_run(void) {
  81. if ((!port1.available()) && (!port2.available())) {
  82. return;
  83. }
  84. unsigned char c = port1.available() ? port1.read() : port2.read();
  85. sml_states_t s = smlState(c);
  86. if (s == SML_START) {
  87. init_vars();
  88. counter++;
  89. } else if (s == SML_LISTEND) {
  90. for (unsigned int i = 0; i < (sizeof(handlers) / sizeof(handlers[0])); i++) {
  91. if (smlOBISCheck(handlers[i].OBIS)) {
  92. handlers[i].Handler();
  93. }
  94. }
  95. } else if (s == SML_FINAL) {
  96. debug.println("SML Reading:");
  97. if (!isnan(SumWh)) {
  98. debug.printf("Sum: %14.3lf Wh\n", SumWh);
  99. }
  100. if (!isnan(T1Wh)) {
  101. debug.printf(" T1: %14.3lf Wh\n", T1Wh);
  102. }
  103. if (!isnan(T2Wh)) {
  104. debug.printf(" T2: %14.3lf Wh\n", T2Wh);
  105. }
  106. if (!isnan(SumW)) {
  107. debug.printf("Sum: %14.3lf W\n", SumW);
  108. #ifdef FEATURE_LORA
  109. lora_sml_send(LORA_SML_SUM_W, SumW, counter);
  110. #endif // FEATURE_LORA
  111. }
  112. if (!isnan(L1W)) {
  113. debug.printf(" L1: %14.3lf W\n", L1W);
  114. #ifdef FEATURE_LORA
  115. lora_sml_send(LORA_SML_L1_W, L1W, counter);
  116. #endif // FEATURE_LORA
  117. }
  118. if (!isnan(L2W)) {
  119. debug.printf(" L2: %14.3lf W\n", L2W);
  120. #ifdef FEATURE_LORA
  121. lora_sml_send(LORA_SML_L2_W, L2W, counter);
  122. #endif // FEATURE_LORA
  123. }
  124. if (!isnan(L3W)) {
  125. debug.printf(" L3: %14.3lf W\n", L3W);
  126. #ifdef FEATURE_LORA
  127. lora_sml_send(LORA_SML_L3_W, L3W, counter);
  128. #endif // FEATURE_LORA
  129. }
  130. debug.println();
  131. #ifdef FEATURE_LORA
  132. // the power readings (Watt) are just sent as is, if available.
  133. // the energy readings are consolidated if possible, to avoid
  134. // unneccessary data transmission
  135. if ((!isnan(SumWh)) && (!isnan(T1Wh))
  136. && (fabs(SumWh - T1Wh) < 0.1)
  137. && ((isnan(T2Wh)) || (fabs(T2Wh) < 0.1))) {
  138. // (SumWh == T1Wh) && ((T2Wh == 0) || (T2Wh == NAN))
  139. // just send T1Wh
  140. lora_sml_send(LORA_SML_T1_WH, T1Wh, counter);
  141. } else if ((!isnan(SumWh)) && (!isnan(T2Wh))
  142. && (fabs(SumWh - T2Wh) < 0.1)
  143. && ((isnan(T1Wh)) || (fabs(T1Wh) < 0.1))) {
  144. // (SumWh == T2Wh) && ((T1Wh == 0) || (T1Wh == NAN))
  145. // just send T2Wh
  146. lora_sml_send(LORA_SML_T2_WH, T2Wh, counter);
  147. } else {
  148. // just do normal sending if available
  149. if (!isnan(SumWh)) {
  150. lora_sml_send(LORA_SML_SUM_WH, SumWh, counter);
  151. }
  152. if (!isnan(T1Wh)) {
  153. lora_sml_send(LORA_SML_T1_WH, T1Wh, counter);
  154. }
  155. if (!isnan(T2Wh)) {
  156. lora_sml_send(LORA_SML_T2_WH, T2Wh, counter);
  157. }
  158. }
  159. // update own battery state with each sml readout
  160. lora_sml_send(LORA_SML_BAT_V, lora_get_mangled_bat(), counter);
  161. lora_sml_done();
  162. #endif // FEATURE_LORA
  163. }
  164. }
  165. #endif // FEATURE_SML