Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/neuron/tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ typedef enum {
NEU_DATATAG_ENDIAN_BL32 = 5, // #BL 2,1,4,3
NEU_DATATAG_ENDIAN_L64 = 6, // #L 8,7,6,5,4,3,2,1
NEU_DATATAG_ENDIAN_B64 = 7, // #B 1,2,3,4,5,6,7,8
NEU_DATATAG_ENDIAN_LL64 = 8,
NEU_DATATAG_ENDIAN_LB64 = 9,
NEU_DATATAG_ENDIAN_BB64 = 10,
NEU_DATATAG_ENDIAN_BL64 = 11,
} neu_datatag_endian_e;

typedef enum {
Expand All @@ -63,6 +67,7 @@ typedef union {
} value32;
struct {
neu_datatag_endian_e endian;
bool is_default;
} value64;
struct {
uint16_t length;
Expand Down
36 changes: 36 additions & 0 deletions include/neuron/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,42 @@ static inline uint64_t neu_htonll(uint64_t u)
return ret;
}

static inline uint64_t neu_htonlb(uint64_t u)
{
uint8_t *in = (uint8_t *) &u;
uint64_t out = 0;
uint8_t *out_bytes = (uint8_t *) &out;

out_bytes[0] = in[1];
out_bytes[1] = in[0];
out_bytes[2] = in[3];
out_bytes[3] = in[2];
out_bytes[4] = in[5];
out_bytes[5] = in[4];
out_bytes[6] = in[7];
out_bytes[7] = in[6];

return out;
}

static inline uint64_t neu_htonbl(uint64_t u)
{
uint8_t *in = (uint8_t *) &u;
uint64_t out = 0;
uint8_t *out_bytes = (uint8_t *) &out;

out_bytes[0] = in[6];
out_bytes[1] = in[7];
out_bytes[2] = in[4];
out_bytes[3] = in[5];
out_bytes[4] = in[2];
out_bytes[5] = in[3];
out_bytes[6] = in[0];
out_bytes[7] = in[1];

return out;
}

static inline uint64_t neu_ntohll(uint64_t u)
{
return neu_htonll(u);
Expand Down
39 changes: 34 additions & 5 deletions plugins/modbus/modbus-rtu.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@
},
{
"type": 7,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 8,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 9,
"regex": "^[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
},
{
"type": 10,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 11,
Expand Down Expand Up @@ -158,8 +158,8 @@
}
},
"endianess": {
"name": "Endianess",
"name_zh": "字节序",
"name": "Endianess of 4-Byte Data",
"name_zh": "4 字节数据字节序",
"description": "Tag byte order, ABCD corresponds to 1234",
"description_zh": "点位字节序,ABCD 对应 1234",
"attribute": "required",
Expand All @@ -186,6 +186,35 @@
]
}
},
"endianess_64": {
"name": "Endianess of 8-Byte Data",
"name_zh": "8 字节数据字节序",
"description": "Tag byte order, applicable to int64, uint64 and double types",
"description_zh": "点位字节序,适用于 int64,uint64 和 double 类型",
"attribute": "required",
"type": "map",
"default": 1,
"valid": {
"map": [
{
"key": "12 34 56 78",
"value": 1
},
{
"key": "21 43 65 87",
"value": 2
},
{
"key": "87 65 43 21",
"value": 3
},
{
"key": "78 56 34 12",
"value": 4
}
]
}
},
"address_base": {
"name": "Start Address",
"name_zh": "开始地址",
Expand Down
39 changes: 34 additions & 5 deletions plugins/modbus/modbus-tcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@
},
{
"type": 7,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 8,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 9,
"regex": "^[0-9]+![3-4][0-9]+(#BB|#BL|#LL|#LB|)$"
},
{
"type": 10,
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|)$"
"regex": "^[0-9]+![3-4][0-9]+(#B|#L|#BB|#BL|#LL|#LB|)$"
},
{
"type": 11,
Expand Down Expand Up @@ -166,8 +166,8 @@
}
},
"endianess": {
"name": "Endianess",
"name_zh": "字节序",
"name": "Endianess of 4-Byte Data",
"name_zh": "4 字节数据字节序",
"description": "Tag byte order, ABCD corresponds to 1234",
"description_zh": "点位字节序,ABCD 对应 1234",
"attribute": "required",
Expand All @@ -194,6 +194,35 @@
]
}
},
"endianess_64": {
"name": "Endianess of 8-Byte Data",
"name_zh": "8 字节数据字节序",
"description": "Tag byte order, applicable to int64, uint64 and double types",
"description_zh": "点位字节序,适用于 int64,uint64 和 double 类型",
"attribute": "required",
"type": "map",
"default": 1,
"valid": {
"map": [
{
"key": "12 34 56 78",
"value": 1
},
{
"key": "21 43 65 87",
"value": 2
},
{
"key": "87 65 43 21",
"value": 3
},
{
"key": "78 56 34 12",
"value": 4
}
]
}
},
"address_base": {
"name": "Start Address",
"name_zh": "开始地址",
Expand Down
7 changes: 7 additions & 0 deletions plugins/modbus/modbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ typedef enum modbus_endianess {
MODBUS_CDAB = 4,
} modbus_endianess;

typedef enum modbus_endianess_64 {
MODBUS_LL = 1, // 12 34 56 78
MODBUS_LB = 2, // 21 43 65 87
MODBUS_BB = 3, // 87 65 43 21
MODBUS_BL = 4, // 78 56 34 12
} modbus_endianess_64;

typedef enum modbus_address_base {
base_0 = 0,
base_1 = 1,
Expand Down
46 changes: 36 additions & 10 deletions plugins/modbus/modbus_point.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ modbus_read_cmd_sort_t *modbus_tag_sort(UT_array *tags, uint16_t max_byte)
}

int cal_n_byte(int type, neu_value_u *value, neu_datatag_addr_option_u option,
modbus_endianess endianess, bool default_tag_endian)
modbus_endianess endianess, bool default_tag_endian,
modbus_endianess_64 endianess_64, bool default_tag_endian_64)
{
int n = 0;
switch (type) {
Expand All @@ -260,6 +261,9 @@ int cal_n_byte(int type, neu_value_u *value, neu_datatag_addr_option_u option,
case NEU_TYPE_DOUBLE:
case NEU_TYPE_INT64:
case NEU_TYPE_UINT64:
if (default_tag_endian_64) {
modbus_convert_endianess_64(value, endianess_64);
}
n = sizeof(uint64_t);
value->u64 = neu_htonll(value->u64);
break;
Expand Down Expand Up @@ -293,8 +297,9 @@ int cal_n_byte(int type, neu_value_u *value, neu_datatag_addr_option_u option,
return n;
}

modbus_write_cmd_sort_t *modbus_write_tags_sort(UT_array * tags,
modbus_endianess endianess)
modbus_write_cmd_sort_t *
modbus_write_tags_sort(UT_array *tags, modbus_endianess endianess,
modbus_endianess_64 endianess_64)
{
neu_tag_sort_result_t *result =
neu_tag_sort(tags, tag_sort_write, tag_cmp_write);
Expand All @@ -316,17 +321,18 @@ modbus_write_cmd_sort_t *modbus_write_tags_sort(UT_array * tags,
utarray_foreach(result->sorts[i].tags, modbus_point_write_t **, tag_s)
{
if ((*tag_s)->point.area == MODBUS_AREA_COIL) {
n_byte_tag =
cal_n_byte((*tag_s)->point.type, &(*tag_s)->value,
(*tag_s)->point.option, endianess, true);
n_byte_tag = cal_n_byte((*tag_s)->point.type, &(*tag_s)->value,
(*tag_s)->point.option, endianess, true,
endianess_64, true);
data_bit[k / 8] += ((*tag_s)->value.i8) << k % 8;
n_byte += n_byte_tag;
k++;
} else {
n_byte_tag =
cal_n_byte((*tag_s)->point.type, &(*tag_s)->value,
(*tag_s)->point.option, endianess,
(*tag_s)->point.option.value32.is_default);
n_byte_tag = cal_n_byte(
(*tag_s)->point.type, &(*tag_s)->value,
(*tag_s)->point.option, endianess,
(*tag_s)->point.option.value32.is_default, endianess_64,
(*tag_s)->point.option.value64.is_default);
memcpy(sort_result->cmd[i].bytes +
2 *
((*tag_s)->point.start_address -
Expand Down Expand Up @@ -558,4 +564,24 @@ void modbus_convert_endianess(neu_value_u *value, modbus_endianess endianess)
default:
break;
}
}

void modbus_convert_endianess_64(neu_value_u * value,
modbus_endianess_64 endianess_64)
{
switch (endianess_64) {
case MODBUS_LL:
break;
case MODBUS_BB:
value->u64 = neu_htonll(value->u64);
break;
case MODBUS_LB:
value->u64 = neu_htonlb(value->u64);
break;
case MODBUS_BL:
value->u64 = neu_htonbl(value->u64);
break;
default:
break;
}
}
11 changes: 7 additions & 4 deletions plugins/modbus/modbus_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,15 @@ typedef struct modbus_write_cmd_sort {
modbus_write_cmd_t *cmd;
} modbus_write_cmd_sort_t;

modbus_read_cmd_sort_t * modbus_tag_sort(UT_array *tags, uint16_t max_byte);
modbus_write_cmd_sort_t *modbus_write_tags_sort(UT_array * tags,
modbus_endianess endianess);
void modbus_tag_sort_free(modbus_read_cmd_sort_t *cs);
modbus_read_cmd_sort_t *modbus_tag_sort(UT_array *tags, uint16_t max_byte);
modbus_write_cmd_sort_t *
modbus_write_tags_sort(UT_array *tags, modbus_endianess endianess,
modbus_endianess_64 endianess_64);
void modbus_tag_sort_free(modbus_read_cmd_sort_t *cs);

void modbus_convert_endianess(neu_value_u *value, modbus_endianess endianess);
void modbus_convert_endianess_64(neu_value_u * value,
modbus_endianess_64 endianess_64);

#ifdef __cplusplus
}
Expand Down
10 changes: 9 additions & 1 deletion plugins/modbus/modbus_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,10 @@ int modbus_value_handle(void *ctx, uint8_t slave_id, uint16_t n_byte,
case NEU_TYPE_DOUBLE:
case NEU_TYPE_INT64:
case NEU_TYPE_UINT64:
if ((*p_tag)->option.value64.is_default) {
modbus_convert_endianess_64(&dvalue.value,
plugin->endianess_64);
}
dvalue.value.u64 = neu_ntohll(dvalue.value.u64);
break;
case NEU_TYPE_BIT: {
Expand Down Expand Up @@ -712,6 +716,9 @@ static uint8_t convert_value(neu_plugin_t *plugin, neu_value_u *value,
case NEU_TYPE_DOUBLE:
case NEU_TYPE_INT64:
case NEU_TYPE_UINT64:
if (tag->option.value64.is_default) {
modbus_convert_endianess_64(value, plugin->endianess_64);
}
value->u64 = neu_htonll(value->u64);
n_byte = sizeof(uint64_t);
break;
Expand Down Expand Up @@ -804,7 +811,8 @@ int modbus_write_tags(neu_plugin_t *plugin, void *req, UT_array *tags)

utarray_push_back(gtags->tags, &p);
}
gtags->cmd_sort = modbus_write_tags_sort(gtags->tags, plugin->endianess);
gtags->cmd_sort = modbus_write_tags_sort(gtags->tags, plugin->endianess,
plugin->endianess_64);
for (uint16_t i = 0; i < gtags->cmd_sort->n_cmd; i++) {
ret = write_modbus_points(plugin, &gtags->cmd_sort->cmd[i], req);
if (ret <= 0) {
Expand Down
1 change: 1 addition & 0 deletions plugins/modbus/modbus_req.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct neu_plugin {

modbus_protocol_e protocol;
modbus_endianess endianess;
modbus_endianess_64 endianess_64;
modbus_address_base address_base;

uint16_t interval;
Expand Down
10 changes: 10 additions & 0 deletions plugins/modbus/modbus_rtu.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
neu_json_elem_t address_base = { .name = "address_base",
.t = NEU_JSON_INT };

neu_json_elem_t endianess_64 = { .name = "endianess_64",
.t = NEU_JSON_INT };

ret = neu_parse_param((char *) config, &err_param, 3, &link, &timeout,
&interval);
if (ret != 0) {
Expand Down Expand Up @@ -239,6 +242,12 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
address_base.v.val_int = base_1;
}

ret = neu_parse_param((char *) config, &err_param, 1, &endianess_64);
if (ret != 0) {
free(err_param);
endianess_64.v.val_int = MODBUS_LL;
}

param.log = plugin->common.log;
plugin->max_retries = max_retries.v.val_int;
plugin->retry_interval = retry_interval.v.val_int;
Expand All @@ -247,6 +256,7 @@ static int driver_config(neu_plugin_t *plugin, const char *config)
plugin->degrade_time = degrade_time.v.val_int;
plugin->endianess = endianess.v.val_int;
plugin->address_base = address_base.v.val_int;
plugin->endianess_64 = endianess_64.v.val_int;

if (link.v.val_int == 0) {
param.type = NEU_CONN_TTY_CLIENT;
Expand Down
Loading