MeterLogger
Functions
en61107.c File Reference
#include <stdint.h>
#include <string.h>
#include <esp8266.h>
#include "utils.h"
#include "led.h"
#include "tinyprintf.h"
#include "en61107.h"
Include dependency graph for en61107.c:

Go to the source code of this file.

Functions

ICACHE_FLASH_ATTR bool parse_en61107_frame (en61107_response_t *response, char *frame, unsigned int frame_length)
 
ICACHE_FLASH_ATTR bool parse_mc66cde_standard_data_1_frame (en61107_response_t *response, char *frame, unsigned int frame_length)
 
ICACHE_FLASH_ATTR bool parse_mc66cde_standard_data_2_frame (en61107_response_t *response, char *frame, unsigned int frame_length)
 
ICACHE_FLASH_ATTR bool parse_mc66cde_inst_values_frame (en61107_response_t *response, char *frame, unsigned int frame_length)
 
ICACHE_FLASH_ATTR void en61107_response_set_value (en61107_response_t *response, char *rid, char *value, unsigned int value_length)
 
ICACHE_FLASH_ATTR void en61107_response_set_unit (en61107_response_t *response, char *rid, char *unit, unsigned int unit_length)
 

Function Documentation

◆ en61107_response_set_unit()

ICACHE_FLASH_ATTR void en61107_response_set_unit ( en61107_response_t response,
char *  rid,
char *  unit,
unsigned int  unit_length 
)

Definition at line 320 of file en61107.c.

References en61107_response_t::e1, EN61107_RID_L, EN61107_UNIT_L, en61107_response_t::hr, memcpy, memset, strncmp, tfp_snprintf(), en61107_response_register_t::unit, and en61107_response_t::v1.

Referenced by parse_en61107_frame().

320  {
321  char unit_copy[EN61107_UNIT_L];
322 
323  // make null terminated string - unit_length is not including null termination
324  memset(unit_copy, 0, EN61107_UNIT_L);
325  if (unit_length >= EN61107_UNIT_L) {
326  unit_length = EN61107_UNIT_L - 1;
327 
328  }
329  memcpy(unit_copy, unit, unit_length);
330  unit_copy[unit_length] = 0;
331  unit_length++;
332 
333  if (strncmp(rid, "6.8", EN61107_RID_L) == 0) {
334  // energy
335  tfp_snprintf(response->e1.unit, unit_length, "%s", unit_copy);
336  }
337  else if (strncmp(rid, "6.26", EN61107_RID_L) == 0) {
338  // volume
339  tfp_snprintf(response->v1.unit, unit_length, "%s", unit_copy);
340  }
341  else if (strncmp(rid, "6.31", EN61107_RID_L) == 0) {
342  // hours
343  tfp_snprintf(response->hr.unit, unit_length, "%s", unit_copy);
344  }
345 }
en61107_response_register_t hr
Definition: en61107.h:39
en61107_response_register_t e1
Definition: en61107.h:41
#define memset(x, a, b)
Definition: platform.h:21
#define EN61107_UNIT_L
Definition: en61107.h:7
en61107_response_register_t v1
Definition: en61107.h:40
char unit[EN61107_UNIT_L]
Definition: en61107.h:14
#define EN61107_RID_L
Definition: en61107.h:6
#define strncmp(a, b, c)
Definition: platform.h:18
ICACHE_FLASH_ATTR int tfp_snprintf(char *str, size_t size, const char *format,...)
Definition: tinyprintf.c:480
#define memcpy(x, a, b)
Definition: platform.h:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ en61107_response_set_value()

ICACHE_FLASH_ATTR void en61107_response_set_value ( en61107_response_t response,
char *  rid,
char *  value,
unsigned int  value_length 
)

Definition at line 292 of file en61107.c.

References en61107_response_t::e1, EN61107_RID_L, EN61107_VALUE_L, en61107_response_t::hr, ICACHE_FLASH_ATTR, memcpy, memset, strncmp, tfp_snprintf(), en61107_response_t::v1, and en61107_response_register_t::value.

Referenced by parse_en61107_frame().

292  {
293  char value_copy[EN61107_VALUE_L];
294 
295  // make null terminated string - value_length is not including null termination
296  memset(value_copy, 0, EN61107_VALUE_L);
297  if (value_length >= EN61107_VALUE_L) {
298  value_length = EN61107_VALUE_L - 1;
299 
300  }
301  memcpy(value_copy, value, value_length);
302  value_copy[value_length] = 0;
303  value_length++;
304 
305  if (strncmp(rid, "6.8", EN61107_RID_L) == 0) {
306  // energy
307  tfp_snprintf(response->e1.value, value_length, "%s", value_copy);
308  }
309  else if (strncmp(rid, "6.26", EN61107_RID_L) == 0) {
310  // volume
311  tfp_snprintf(response->v1.value, value_length, "%s", value_copy);
312  }
313  else if (strncmp(rid, "6.31", EN61107_RID_L) == 0) {
314  // hours
315  tfp_snprintf(response->hr.value, value_length, "%s", value_copy);
316  }
317 }
en61107_response_register_t hr
Definition: en61107.h:39
en61107_response_register_t e1
Definition: en61107.h:41
#define memset(x, a, b)
Definition: platform.h:21
char value[EN61107_VALUE_L]
Definition: en61107.h:13
#define EN61107_VALUE_L
Definition: en61107.h:8
en61107_response_register_t v1
Definition: en61107.h:40
#define EN61107_RID_L
Definition: en61107.h:6
#define strncmp(a, b, c)
Definition: platform.h:18
ICACHE_FLASH_ATTR int tfp_snprintf(char *str, size_t size, const char *format,...)
Definition: tinyprintf.c:480
#define memcpy(x, a, b)
Definition: platform.h:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_en61107_frame()

ICACHE_FLASH_ATTR bool parse_en61107_frame ( en61107_response_t response,
char *  frame,
unsigned int  frame_length 
)

Definition at line 11 of file en61107.c.

References cleanup_decimal_str(), en61107_response_t::customer_no, EN61107_CUSTOMER_NO_L, EN61107_FRAME_L, EN61107_METER_TYPE_L, EN61107_REGISTER_L, en61107_response_set_unit(), en61107_response_set_value(), EN61107_RID_L, EN61107_VALUE_L, frame, frame_length, ICACHE_FLASH_ATTR, memcpy, memset, en61107_response_t::meter_type, NULL, strlen, strncmp, and strstr.

Referenced by en61107_received_task().

11  {
12  unsigned int i, j;
13  uint8_t bcc;
14  uint8_t calculated_bcc;
15 
16 #ifndef MC_66B
17  const char *separator = "\x0D\x0A";
18 #else
19  const char *separator = ")";
20 #endif
21  const char *stx = "\x02";
22  const char *etx = "\x21\x0D\x0A\x03";
23  char rid[EN61107_RID_L];
24  char rid_value_unit_string[EN61107_REGISTER_L];
25  char register_list_string[EN61107_FRAME_L];
26  char *register_list_string_ptr;
27  char *rid_value_unit_string_ptr;
28  char *pos;
29  size_t length;
30  size_t rid_string_length;
31  size_t value_string_length;
32  size_t unit_string_length;
33  size_t customer_no_string_length;
34 
35  char decimal_str[EN61107_VALUE_L + 1]; // 1 char more for .
36 
37  // sanity check
38  if (!frame_length) {
39  return 0;
40  }
41 
42  bcc = frame[frame_length - 1];
43  calculated_bcc = 0;
44  for (i = 0; i < frame_length; i++) {
45  if (frame[i] == 0x02) {
46  // stx
47  calculated_bcc = 0;
48  }
49  else {
50  calculated_bcc += frame[i];
51  calculated_bcc &= 0x7f; // 7 bit value
52 
53  if (frame[i] == 0x03) {
54  // etx
55  if (bcc == calculated_bcc) {
56  // crc ok
57  // parse meter_type
58  memset(response->meter_type, 0, EN61107_METER_TYPE_L); // clear meter_type_string (null terminalte)
59  pos = strstr(frame, stx); // find position of stx char
60  if (pos != NULL) { // if found stx char...
61  length = pos - frame; // ...save meter_type string
62  // DEBUG: check if length - 3 is >= 0
63  memcpy(response->meter_type, frame + 1, length - 3); // DEBUG: check bounds
64  // detect meter type and protocol from returned meter type
65  frame += length + 3;
66  }
67 
68  // parse to etx and save to register_list_string
69  memset(register_list_string, 0, EN61107_FRAME_L);
70  pos = strstr(frame, etx); // find position of etx
71  if (pos != NULL) {
72  length = pos - frame;
73  memcpy(register_list_string, frame, length);
74  }
75 
76  // parse values
77  j = 0;
78  register_list_string_ptr = register_list_string; // force pointer arithmetics
79  while ((pos = strstr(register_list_string_ptr, separator)) != NULL) {
80 #ifndef MC_66B
81  length = pos - register_list_string_ptr;
82 #else
83  length = pos - register_list_string_ptr + 1; // + 1 becouse we need the last ')' in further parsing
84 #endif
85  memset(rid_value_unit_string, 0, EN61107_REGISTER_L); // zero (null terminate)
86  memcpy(rid_value_unit_string, register_list_string_ptr, length);
87  rid_value_unit_string_ptr = rid_value_unit_string; // force pointer arithmetics
88 
89  // parse register number, value and unit unless rid == 0
90  pos = strstr(rid_value_unit_string, "(");
91  if (pos != NULL) {
92  rid_string_length = pos - rid_value_unit_string;
93  memset(rid, 0, EN61107_RID_L); // zero (null terminate)
94  memcpy(rid, rid_value_unit_string, rid_string_length);
95  rid_value_unit_string_ptr += rid_string_length + 1;
96  }
97  pos = strstr(rid_value_unit_string_ptr, "*");
98  if (pos != NULL) {
99  value_string_length = pos - rid_value_unit_string_ptr;
100  cleanup_decimal_str(rid_value_unit_string_ptr, decimal_str, value_string_length);
101  en61107_response_set_value(response, rid, decimal_str, strlen(decimal_str));
102  rid_value_unit_string_ptr += value_string_length + 1;
103  }
104  pos = strstr(rid_value_unit_string_ptr, ")");
105  if (pos != NULL) {
106  if (strncmp(rid, "0", 1) == 0) {
107  // customer number, no unit
108  customer_no_string_length = pos - rid_value_unit_string_ptr;
109  memset(response->customer_no, 0, EN61107_CUSTOMER_NO_L); // zero (null terminate)
110  memcpy(response->customer_no, rid_value_unit_string_ptr, customer_no_string_length);
111  }
112  else {
113  unit_string_length = pos - rid_value_unit_string_ptr;
114  en61107_response_set_unit(response, rid, rid_value_unit_string_ptr, unit_string_length);
115  j++;
116 
117  }
118  }
119 #ifndef MC_66B
120  register_list_string_ptr += length + 2;
121 #else
122  register_list_string_ptr += length; // DEBUG: separator not two chars: 0x0D 0x0A
123 #endif
124  }
125 
126 #ifndef MC_66B
127  // handle the last
128  length = strlen(register_list_string_ptr);
129  memset(rid_value_unit_string, 0, EN61107_REGISTER_L); // zero (null terminate)
130  memcpy(rid_value_unit_string, register_list_string_ptr, length);
131  rid_value_unit_string_ptr = rid_value_unit_string; // force pointer arithmetics
132 
133  // parse register number, value and unit unless rid == 0
134  pos = strstr(rid_value_unit_string, "(");
135  if (pos != NULL) {
136  rid_string_length = pos - rid_value_unit_string;
137  memset(rid, 0, EN61107_RID_L); // zero (null terminate)
138  memcpy(rid, rid_value_unit_string, rid_string_length);
139  rid_value_unit_string_ptr += rid_string_length + 1;
140  }
141  pos = strstr(rid_value_unit_string_ptr, "*");
142  if (pos != NULL) {
143  value_string_length = pos - rid_value_unit_string_ptr;
144  cleanup_decimal_str(rid_value_unit_string_ptr, decimal_str, value_string_length);
145  en61107_response_set_value(response, rid, decimal_str, strlen(decimal_str));
146  rid_value_unit_string_ptr += value_string_length + 1;
147  }
148  pos = strstr(rid_value_unit_string_ptr, ")");
149  if (pos != NULL) {
150  if (strncmp(rid, "0", 1) == 0) {
151  // customer number, no unit
152  customer_no_string_length = pos - rid_value_unit_string_ptr;
153  memset(response->customer_no, 0, EN61107_CUSTOMER_NO_L); // zero (null terminate)
154  memcpy(response->customer_no, rid_value_unit_string_ptr, customer_no_string_length);
155  }
156  else {
157  unit_string_length = pos - rid_value_unit_string_ptr;
158  en61107_response_set_unit(response, rid, rid_value_unit_string_ptr, unit_string_length);
159  }
160  }
161 #endif
162 
163  return true;
164  }
165  }
166  }
167  }
168  return false;
169 }
unsigned int frame_length
#define memset(x, a, b)
Definition: platform.h:21
char frame[EN61107_FRAME_L]
#define NULL
Definition: def.h:47
#define strstr(a, b)
Definition: platform.h:24
ICACHE_FLASH_ATTR void en61107_response_set_unit(en61107_response_t *response, char *rid, char *unit, unsigned int unit_length)
Definition: en61107.c:320
#define EN61107_VALUE_L
Definition: en61107.h:8
char meter_type[EN61107_METER_TYPE_L]
Definition: en61107.h:29
#define EN61107_RID_L
Definition: en61107.h:6
#define strncmp(a, b, c)
Definition: platform.h:18
ICACHE_FLASH_ATTR void en61107_response_set_value(en61107_response_t *response, char *rid, char *value, unsigned int value_length)
Definition: en61107.c:292
#define EN61107_REGISTER_L
Definition: en61107.h:5
#define memcpy(x, a, b)
Definition: platform.h:22
ICACHE_FLASH_ATTR void cleanup_decimal_str(char *decimal_str, char *cleaned_up_str, unsigned int length)
Definition: utils.c:151
#define EN61107_FRAME_L
Definition: en61107.h:4
#define strlen(a)
Definition: platform.h:25
#define EN61107_CUSTOMER_NO_L
Definition: en61107.h:9
char customer_no[EN61107_CUSTOMER_NO_L]
Definition: en61107.h:28
#define EN61107_METER_TYPE_L
Definition: en61107.h:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_mc66cde_inst_values_frame()

ICACHE_FLASH_ATTR bool parse_mc66cde_inst_values_frame ( en61107_response_t response,
char *  frame,
unsigned int  frame_length 
)

Definition at line 269 of file en61107.c.

References divide_str_by_100(), EN61107_UNIT_L, EN61107_VALUE_L, ICACHE_FLASH_ATTR, NULL, en61107_response_t::t3, tfp_snprintf(), en61107_response_register_t::unit, and en61107_response_register_t::value.

Referenced by en61107_received_task().

269  {
270  char *p;
271  int i = 0;
272  char decimal_str[EN61107_VALUE_L + 1]; // 1 char more for .
273 
274  p = strtok(frame, " "); // returns null terminated string
275  while (p != NULL) {
276  switch (i) {
277  case 1:
278  divide_str_by_100(p, decimal_str); // t3 resolution of 0.01°C.
279  tfp_snprintf(response->t3.value, EN61107_VALUE_L, "%s", decimal_str);
280  tfp_snprintf(response->t3.unit, EN61107_UNIT_L, "%s", "C");
281  break;
282  }
283  i++;
284  p = strtok(NULL, " ");
285  };
286 
287  return true;
288 }
char frame[EN61107_FRAME_L]
#define NULL
Definition: def.h:47
char value[EN61107_VALUE_L]
Definition: en61107.h:13
#define EN61107_UNIT_L
Definition: en61107.h:7
#define EN61107_VALUE_L
Definition: en61107.h:8
en61107_response_register_t t3
Definition: en61107.h:34
char unit[EN61107_UNIT_L]
Definition: en61107.h:14
ICACHE_FLASH_ATTR int tfp_snprintf(char *str, size_t size, const char *format,...)
Definition: tinyprintf.c:480
ICACHE_FLASH_ATTR void divide_str_by_100(char *str, char *decimal_str)
Definition: utils.c:128
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_mc66cde_standard_data_1_frame()

ICACHE_FLASH_ATTR bool parse_mc66cde_standard_data_1_frame ( en61107_response_t response,
char *  frame,
unsigned int  frame_length 
)

Definition at line 172 of file en61107.c.

References cleanup_decimal_str(), divide_str_by_10(), divide_str_by_100(), en61107_response_t::effect1, EN61107_UNIT_L, EN61107_VALUE_L, en61107_response_t::flow1, ICACHE_FLASH_ATTR, NULL, strlen, en61107_response_t::t1, en61107_response_t::t2, en61107_response_t::tdif, tfp_snprintf(), en61107_response_register_t::unit, and en61107_response_register_t::value.

Referenced by en61107_received_task().

172  {
173  char *p;
174  int i = 0;
175  char decimal_str[EN61107_VALUE_L + 1]; // 1 char more for .
176 
177  p = strtok(frame, " "); // returns null terminated string
178  while (p != NULL) {
179  switch (i) {
180  case 3:
181  divide_str_by_100(p, decimal_str);
182  tfp_snprintf(response->t1.value, EN61107_VALUE_L, "%s", decimal_str);
183  tfp_snprintf(response->t1.unit, EN61107_UNIT_L, "%s", "C");
184  break;
185  case 4:
186  divide_str_by_100(p, decimal_str);
187  tfp_snprintf(response->t2.value, EN61107_VALUE_L, "%s", decimal_str);
188  tfp_snprintf(response->t2.unit, EN61107_UNIT_L, "%s", "C");
189  break;
190  case 5:
191  divide_str_by_100(p, decimal_str);
192  tfp_snprintf(response->tdif.value, EN61107_VALUE_L, "%s", decimal_str);
193  tfp_snprintf(response->tdif.unit, EN61107_UNIT_L, "%s", "C");
194  break;
195  case 6:
196  divide_str_by_10(p, decimal_str);
197  tfp_snprintf(response->effect1.value, EN61107_VALUE_L, "%s", decimal_str);
198  tfp_snprintf(response->effect1.unit, EN61107_UNIT_L, "%s", "kW");
199  break;
200  case 7:
201  cleanup_decimal_str(p, decimal_str, strlen(p));
202  tfp_snprintf(response->flow1.value, EN61107_VALUE_L, "%s", decimal_str);
203  tfp_snprintf(response->flow1.unit, EN61107_UNIT_L, "%s", "l/h");
204  break;
205  }
206  i++;
207  p = strtok(NULL, " ");
208  };
209 
210  return true;
211 }
en61107_response_register_t effect1
Definition: en61107.h:38
char frame[EN61107_FRAME_L]
ICACHE_FLASH_ATTR void divide_str_by_10(char *str, char *decimal_str)
Definition: utils.c:110
#define NULL
Definition: def.h:47
en61107_response_register_t flow1
Definition: en61107.h:37
char value[EN61107_VALUE_L]
Definition: en61107.h:13
#define EN61107_UNIT_L
Definition: en61107.h:7
#define EN61107_VALUE_L
Definition: en61107.h:8
en61107_response_register_t t1
Definition: en61107.h:31
en61107_response_register_t t2
Definition: en61107.h:32
char unit[EN61107_UNIT_L]
Definition: en61107.h:14
en61107_response_register_t tdif
Definition: en61107.h:36
ICACHE_FLASH_ATTR int tfp_snprintf(char *str, size_t size, const char *format,...)
Definition: tinyprintf.c:480
ICACHE_FLASH_ATTR void cleanup_decimal_str(char *decimal_str, char *cleaned_up_str, unsigned int length)
Definition: utils.c:151
#define strlen(a)
Definition: platform.h:25
ICACHE_FLASH_ATTR void divide_str_by_100(char *str, char *decimal_str)
Definition: utils.c:128
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_mc66cde_standard_data_2_frame()

ICACHE_FLASH_ATTR bool parse_mc66cde_standard_data_2_frame ( en61107_response_t response,
char *  frame,
unsigned int  frame_length 
)

Definition at line 214 of file en61107.c.

References en61107_meter_program_t::a, en61107_meter_program_t::b, en61107_meter_program_t::ccc, en61107_meter_program_t::dd, en61107_meter_program_t::e, en61107_meter_program_t::ff, en61107_meter_program_t::gg, ICACHE_FLASH_ATTR, memcpy, memset, en61107_response_t::meter_program, and NULL.

Referenced by en61107_received_task().

214  {
215  char *p;
216  int i = 0;
217  char value[4];
218 
219  p = strtok(frame, " ");
220  while (p != NULL) {
221  switch (i) {
222  case 7: // ABCCC
223  // A
224  memset(value, 0, sizeof(value));
225  memcpy(value, p + 2, 1);
226  response->meter_program.a = atoi(value);
227 
228  // B
229  memset(value, 0, sizeof(value));
230  memcpy(value, p + 2 + 1, 1);
231  response->meter_program.b = atoi(value);
232 
233  // CCC
234  memset(value, 0, sizeof(value));
235  memcpy(value, p + 2 + 2, 3);
236  response->meter_program.ccc = atoi(value);
237  break;
238  case 8: // DDEFFGG
239  // DD
240  memset(value, 0, sizeof(value));
241  memcpy(value, p, 2);
242  response->meter_program.dd = atoi(value);
243 
244  // E
245  memset(value, 0, sizeof(value));
246  memcpy(value, p + 2, 1);
247  response->meter_program.e = atoi(value);
248 
249  // FF
250  memset(value, 0, sizeof(value));
251  memcpy(value, p + 3, 2);
252  response->meter_program.ff = atoi(value);
253 
254  // GG
255  memset(value, 0, sizeof(value));
256  memcpy(value, p + 5, 2);
257  response->meter_program.gg = atoi(value);
258  break;
259  }
260  i++;
261  p = strtok(NULL, " "); // returns null terminated string
262  };
263 
264  return true;
265 }
#define memset(x, a, b)
Definition: platform.h:21
char frame[EN61107_FRAME_L]
#define NULL
Definition: def.h:47
en61107_meter_program_t meter_program
Definition: en61107.h:30
#define memcpy(x, a, b)
Definition: platform.h:22
Here is the caller graph for this function: