ESP32 / ESP8266 & BME280 / SHT2x sensor with InfluxDB support
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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