-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmbus-protocol.h
541 lines (426 loc) · 15.6 KB
/
mbus-protocol.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
//------------------------------------------------------------------------------
// Copyright (C) 2010-2011, Robert Johansson, Raditex AB
// All rights reserved.
//
// FreeSCADA
// http://www.FreeSCADA.com
//
//------------------------------------------------------------------------------
/**
* @file mbus-protocol.h
*
* @brief Functions and data structures for M-Bus protocol parsing.
*
*/
#ifndef _MBUS_PROTOCOL_H_
#define _MBUS_PROTOCOL_H_
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
#include <windows.h>
//
// Packet formats:
//
// ACK: size = 1 byte
//
// byte1: ack = 0xE5
//
// SHORT: size = 5 byte
//
// byte1: start = 0x10
// byte2: control = ...
// byte3: address = ...
// byte4: chksum = ...
// byte5: stop = 0x16
//
// CONTROL: size = 9 byte
//
// byte1: start1 = 0x68
// byte2: length1 = ...
// byte3: length2 = ...
// byte4: start2 = 0x68
// byte5: control = ...
// byte6: address = ...
// byte7: ctl.info= ...
// byte8: chksum = ...
// byte9: stop = 0x16
//
// LONG: size = N >= 9 byte
//
// byte1: start1 = 0x68
// byte2: length1 = ...
// byte3: length2 = ...
// byte4: start2 = 0x68
// byte5: control = ...
// byte6: address = ...
// byte7: ctl.info= ...
// byte8: data = ...
// ... = ...
// byteN-1: chksum = ...
// byteN: stop = 0x16
//
//
//
typedef struct _mbus_frame {
u_char start1;
u_char length1;
u_char length2;
u_char start2;
u_char control;
u_char address;
u_char control_information;
// variable data field
u_char checksum;
u_char stop;
u_char data[252];
size_t data_size;
int type;
//mbus_frame_data frame_data;
} mbus_frame;
typedef struct _mbus_slave_data {
int state_fcb;
int state_acd;
} mbus_slave_data;
#define NITEMS(x) (sizeof(x)/sizeof(x[0]))
//------------------------------------------------------------------------------
// MBUS FRAME DATA FORMATS
//
// DATA RECORDS
#define MBUS_DIB_DIF_EXTENSION_BIT 0x80
#define MBUS_DIB_VIF_EXTENSION_BIT 0x80
typedef struct _mbus_data_information_block {
u_char dif;
u_char dife[10];
size_t ndife;
} mbus_data_information_block;
typedef struct _mbus_value_information_block {
u_char vif;
u_char vife[10];
size_t nvife;
u_char custom_vif[128];
} mbus_value_information_block;
typedef struct _mbus_data_record_header {
mbus_data_information_block dib;
mbus_value_information_block vib;
} mbus_data_record_header;
typedef struct _mbus_data_record {
mbus_data_record_header drh;
u_char data[234];
size_t data_len;
void *next;
} mbus_data_record;
//
// HEADER FOR VARIABLE LENGTH DATA FORMAT
//
typedef struct _mbus_data_variable_header {
//Ident.Nr. Manufr. Version Medium Access No. Status Signature
//4 Byte 2 Byte 1 Byte 1 Byte 1 Byte 1 Byte 2 Byte
// ex
// 88 63 80 09 82 4D 02 04 15 00 00 00
u_char id_bcd[4]; // 88 63 80 09
u_char manufacturer[2]; // 82 4D
u_char version; // 02
u_char medium; // 04
u_char access_no; // 15
u_char status; // 00
u_char signature[2]; // 00 00
} mbus_data_variable_header;
//
// VARIABLE LENGTH DATA FORMAT
//
typedef struct _mbus_data_variable {
mbus_data_variable_header header;
mbus_data_record *record; // XXX: this max num must be dynamic
size_t nrecords;
u_char *data;
size_t data_len;
// are these needed/used?
u_char mdh;
u_char *mfg_data;
size_t mfg_data_len;
} mbus_data_variable;
//
// FIXED LENGTH DATA FORMAT
//
typedef struct _mbus_data_fixed {
// ex
// 35 01 00 00 counter 2 = 135 l (historic value)
//
// e.g.
//
// 78 56 34 12 identification number = 12345678
// 0A transmission counter = 0Ah = 10d
// 00 status 00h: counters coded BCD, actual values, no errors
// E9 7E Type&Unit: medium water, unit1 = 1l, unit2 = 1l (same, but historic)
// 01 00 00 00 counter 1 = 1l (actual value)
// 35 01 00 00 counter 2 = 135 l (historic value)
u_char id_bcd[4];
u_char tx_cnt;
u_char status;
u_char cnt1_type;
u_char cnt2_type;
u_char cnt1_val[4];
u_char cnt2_val[4];
} mbus_data_fixed;
//
// ABSTRACT DATA FORMAT (either fixed or variable length)
//
#define MBUS_DATA_TYPE_FIXED 1
#define MBUS_DATA_TYPE_VARIABLE 2
typedef struct _mbus_frame_data {
mbus_data_variable data_var;
mbus_data_fixed data_fix;
int type;
} mbus_frame_data;
//
// HEADER FOR SECONDARY ADDRESSING
//
typedef struct _mbus_data_secondary_address {
//Ident.Nr. Manufr. Version Medium
//4 Byte 2 Byte 1 Byte 1 Byte
// ex
// 14 49 10 01 10 57 01 06
u_char id_bcd[4]; // 14 49 10 01
u_char manufacturer[2]; // 10 57
u_char version; // 01
u_char medium; // 06
} mbus_data_secondary_address;
//
// for compatibility with non-gcc compilers:
//
//#ifndef __PRETTY_FUNCTION__
//#define __PRETTY_FUNCTION__ "libmbus"
//#endif
//------------------------------------------------------------------------------
// FRAME types
//
#define MBUS_FRAME_TYPE_ANY 0x00
#define MBUS_FRAME_TYPE_ACK 0x01
#define MBUS_FRAME_TYPE_SHORT 0x02
#define MBUS_FRAME_TYPE_CONTROL 0x03
#define MBUS_FRAME_TYPE_LONG 0x04
#define MBUS_FRAME_ACK_BASE_SIZE 1
#define MBUS_FRAME_SHORT_BASE_SIZE 5
#define MBUS_FRAME_CONTROL_BASE_SIZE 9
#define MBUS_FRAME_LONG_BASE_SIZE 9
#define MBUS_FRAME_BASE_SIZE_ACK 1
#define MBUS_FRAME_BASE_SIZE_SHORT 5
#define MBUS_FRAME_BASE_SIZE_CONTROL 9
#define MBUS_FRAME_BASE_SIZE_LONG 9
#define MBUS_FRAME_FIXED_SIZE_ACK 1
#define MBUS_FRAME_FIXED_SIZE_SHORT 5
#define MBUS_FRAME_FIXED_SIZE_CONTROL 6
#define MBUS_FRAME_FIXED_SIZE_LONG 6
//
// Frame start/stop bits
//
#define MBUS_FRAME_ACK_START 0xE5
#define MBUS_FRAME_SHORT_START 0x10
#define MBUS_FRAME_CONTROL_START 0x68
#define MBUS_FRAME_LONG_START 0x68
#define MBUS_FRAME_STOP 0x16
//
//
//
#define MBUS_MAX_PRIMARY_SLAVES 256
//
// Control field
//
#define MBUS_CONTROL_FIELD_DIRECTION 0x07
#define MBUS_CONTROL_FIELD_FCB 0x06
#define MBUS_CONTROL_FIELD_ACD 0x06
#define MBUS_CONTROL_FIELD_FCV 0x05
#define MBUS_CONTROL_FIELD_DFC 0x05
#define MBUS_CONTROL_FIELD_F3 0x04
#define MBUS_CONTROL_FIELD_F2 0x03
#define MBUS_CONTROL_FIELD_F1 0x02
#define MBUS_CONTROL_FIELD_F0 0x01
#define MBUS_CONTROL_MASK_SND_NKE 0x40
#define MBUS_CONTROL_MASK_SND_UD 0x53
#define MBUS_CONTROL_MASK_REQ_UD2 0x5B
#define MBUS_CONTROL_MASK_REQ_UD1 0x5A
#define MBUS_CONTROL_MASK_RSP_UD 0x08
#define MBUS_CONTROL_MASK_FCB 0x20
#define MBUS_CONTROL_MASK_FCV 0x10
#define MBUS_CONTROL_MASK_ACD 0x20
#define MBUS_CONTROL_MASK_DFC 0x10
#define MBUS_CONTROL_MASK_DIR 0x40
#define MBUS_CONTROL_MASK_DIR_M2S 0x40
#define MBUS_CONTROL_MASK_DIR_S2M 0x00
//
// Address field
//
#define MBUS_ADDRESS_BROADCAST_REPLY 0xFE
#define MBUS_ADDRESS_BROADCAST_NOREPLY 0xFF
#define MBUS_ADDRESS_NETWORK_LAYER 0xFD
//
// Control Information field
//
//Mode 1 Mode 2 Application Definition in
// 51h 55h data send EN1434-3
// 52h 56h selection of slaves Usergroup July ́93
// 50h application reset Usergroup March ́94
// 54h synronize action suggestion
// B8h set baudrate to 300 baud Usergroup July ́93
// B9h set baudrate to 600 baud Usergroup July ́93
// BAh set baudrate to 1200 baud Usergroup July ́93
// BBh set baudrate to 2400 baud Usergroup July ́93
// BCh set baudrate to 4800 baud Usergroup July ́93
// BDh set baudrate to 9600 baud Usergroup July ́93
// BEh set baudrate to 19200 baud suggestion
// BFh set baudrate to 38400 baud suggestion
// B1h request readout of complete RAM content Techem suggestion
// B2h send user data (not standardized RAM write) Techem suggestion
// B3h initialize test calibration mode Usergroup July ́93
// B4h EEPROM read Techem suggestion
// B6h start software test Techem suggestion
// 90h to 97h codes used for hashing longer recommended
#define MBUS_CONTROL_INFO_DATA_SEND 0x51
#define MBUS_CONTROL_INFO_DATA_SEND_MSB 0x55
#define MBUS_CONTROL_INFO_SELECT_SLAVE 0x52
#define MBUS_CONTROL_INFO_SELECT_SLAVE_MSB 0x56
#define MBUS_CONTROL_INFO_APPLICATION_RESET 0x50
#define MBUS_CONTROL_INFO_SYNC_ACTION 0x54
#define MBUS_CONTROL_INFO_SET_BAUDRATE_300 0xB8
#define MBUS_CONTROL_INFO_SET_BAUDRATE_600 0xB9
#define MBUS_CONTROL_INFO_SET_BAUDRATE_1200 0xBA
#define MBUS_CONTROL_INFO_SET_BAUDRATE_2400 0xBB
#define MBUS_CONTROL_INFO_SET_BAUDRATE_4800 0xBC
#define MBUS_CONTROL_INFO_SET_BAUDRATE_9600 0xBD
#define MBUS_CONTROL_INFO_SET_BAUDRATE_19200 0xBE
#define MBUS_CONTROL_INFO_SET_BAUDRATE_38400 0xBF
#define MBUS_CONTROL_INFO_REQUEST_RAM_READ 0xB1
#define MBUS_CONTROL_INFO_SEND_USER_DATA 0xB2
#define MBUS_CONTROL_INFO_INIT_TEST_CALIB 0xB3
#define MBUS_CONTROL_INFO_EEPROM_READ 0xB4
#define MBUS_CONTROL_INFO_SW_TEST_START 0xB6
#define MBUS_CONTROL_INFO_RESP_FIXED 0x73
#define MBUS_CONTROL_INFO_RESP_FIXED_MSB 0x77
#define MBUS_CONTROL_INFO_RESP_VARIABLE 0x72
#define MBUS_CONTROL_INFO_RESP_VARIABLE_MSB 0x76
//
// DATA BITS
//
#define MBUS_DATA_FIXED_STATUS_FORMAT_MASK 0x80
#define MBUS_DATA_FIXED_STATUS_FORMAT_BCD 0x00
#define MBUS_DATA_FIXED_STATUS_FORMAT_INT 0x80
#define MBUS_DATA_FIXED_STATUS_DATE_MASK 0x40
#define MBUS_DATA_FIXED_STATUS_DATE_STORED 0x40
#define MBUS_DATA_FIXED_STATUS_DATE_CURRENT 0x00
//
// data record fields
//
#define MBUS_DATA_RECORD_DIF_MASK_INST 0x00
#define MBUS_DATA_RECORD_DIF_MASK_MIN 0x10
#define MBUS_DATA_RECORD_DIF_MASK_TYPE_INT32 0x04
#define MBUS_DATA_RECORD_DIF_MASK_STORAGE_NO 0x40
#define MBUS_DATA_RECORD_DIF_MASK_EXTENTION 0x80
//
// FIXED DATA FLAGS
//
//
// VARIABLE DATA FLAGS
//
#define MBUS_VARIABLE_DATA_MEDIUM_OTHER 0x00
#define MBUS_VARIABLE_DATA_MEDIUM_OIL 0x01
#define MBUS_VARIABLE_DATA_MEDIUM_ELECTRICITY 0x02
#define MBUS_VARIABLE_DATA_MEDIUM_GAS 0x03
#define MBUS_VARIABLE_DATA_MEDIUM_HEAT 0x04
#define MBUS_VARIABLE_DATA_MEDIUM_STEAM 0x05
#define MBUS_VARIABLE_DATA_MEDIUM_HOT_WATER 0x06
#define MBUS_VARIABLE_DATA_MEDIUM_WATER 0x07
#define MBUS_VARIABLE_DATA_MEDIUM_HEAT_COST 0x08
#define MBUS_VARIABLE_DATA_MEDIUM_COMPR_AIR 0x09
#define MBUS_VARIABLE_DATA_MEDIUM_COOL_OUT 0x0A
#define MBUS_VARIABLE_DATA_MEDIUM_COOL_IN 0x0B
#define MBUS_VARIABLE_DATA_MEDIUM_BUS 0x0E
#define MBUS_VARIABLE_DATA_MEDIUM_COLD_WATER 0x16
#define MBUS_VARIABLE_DATA_MEDIUM_DUAL_WATER 0x17
#define MBUS_VARIABLE_DATA_MEDIUM_PRESSURE 0x18
#define MBUS_VARIABLE_DATA_MEDIUM_ADC 0x19
//
// variable length records
//
mbus_data_record *mbus_data_record_new();
void mbus_data_record_free(mbus_data_record *record);
void mbus_data_record_append(mbus_data_variable *data, mbus_data_record *record);
// XXX: Add application reset subcodes
mbus_frame *mbus_frame_new(int frame_type);
int mbus_frame_free(mbus_frame *frame);
mbus_frame_data *mbus_frame_data_new();
void mbus_frame_data_free(mbus_frame_data *data);
//
//
//
int mbus_frame_calc_checksum(mbus_frame *frame);
int mbus_frame_calc_length (mbus_frame *frame);
//
// Parse/Pack to bin
//
int mbus_parse(mbus_frame *frame, u_char *data, size_t data_size);
int mbus_data_fixed_parse (mbus_frame *frame, mbus_data_fixed *data);
int mbus_data_variable_parse(mbus_frame *frame, mbus_data_variable *data);
int mbus_frame_data_parse (mbus_frame *frame, mbus_frame_data *data);
int mbus_frame_pack(mbus_frame *frame, u_char *data, size_t data_size);
int mbus_frame_verify(mbus_frame *frame);
int mbus_frame_internal_pack(mbus_frame *frame, mbus_frame_data *frame_data);
//
// data parsing
//
const char *mbus_data_record_unit(mbus_data_record *record);
const char *mbus_data_record_value(mbus_data_record *record);
const char *mbus_data_record_function(mbus_data_record *record);
const char *mbus_data_fixed_function(int status);
//
// M-Bus frame data struct access/write functions
//
int mbus_frame_type(mbus_frame *frame);
//
// Slave status data register.
//
mbus_slave_data *mbus_slave_data_get(size_t i);
//
// XML generating functions
//
void mbus_str_xml_encode(u_char *dst, const u_char *src, size_t max_len);
char *mbus_data_xml(mbus_frame_data *data);
char *mbus_data_variable_xml(mbus_data_variable *data);
char *mbus_data_fixed_xml(mbus_data_fixed *data);
char *mbus_frame_data_xml(mbus_frame_data *data);
char *mbus_data_variable_header_xml(mbus_data_variable_header *header);
//
// Debug/dump
//
int mbus_frame_print(mbus_frame *frame);
int mbus_frame_data_print(mbus_frame_data *data);
int mbus_data_fixed_print(mbus_data_fixed *data);
int mbus_data_variable_header_print(mbus_data_variable_header *header);
int mbus_data_variable_print(mbus_data_variable *data);
char *mbus_error_str();
void mbus_error_str_set(char *message);
void mbus_error_reset();
//
// data encode/decode functions
//
int mbus_data_manufacturer_encode(u_char *m_data, u_char *m_code);
const char *mbus_decode_manufacturer(u_char byte1, u_char byte2);
int mbus_data_bcd_encode(u_char *bcd_data, size_t bcd_data_size, int value);
int mbus_data_int_encode(u_char *int_data, size_t int_data_size, int value);
long mbus_data_bcd_decode(u_char *bcd_data, size_t bcd_data_size);
int mbus_data_int_decode(u_char *int_data, size_t int_data_size);
float mbus_data_float_decode(u_char *float_data, size_t float_data_size);
long mbus_data_long_decode(u_char *int_data, size_t int_data_size);
void mbus_data_tm_decode(struct tm *t, u_char *t_data, size_t t_data_size);
void mbus_data_str_decode(u_char *dst, const u_char *src, size_t len);
const char *mbus_data_fixed_medium(mbus_data_fixed *data);
const char *mbus_data_fixed_unit(int medium_unit_byte);
const char *mbus_data_variable_medium_lookup(u_char medium);
const char *mbus_unit_prefix(int exp);
const char *mbus_vib_unit_lookup(mbus_value_information_block *vib);
const char *mbus_vif_unit_lookup(u_char vif);
u_char mbus_dif_datalength_lookup(u_char dif);
char *mbus_frame_get_secondary_address(mbus_frame *frame);
int mbus_frame_select_secondary_pack(mbus_frame *frame, char *address);
void mbus_hexdump(const char *c, int len);
#endif /* _MBUS_PROTOCOL_H_ */