diff --git a/APP_Framework/Applications/connection_app/4g_app/4g_app.c b/APP_Framework/Applications/connection_app/4g_app/4g_app.c new file mode 100644 index 000000000..fc7eb0213 --- /dev/null +++ b/APP_Framework/Applications/connection_app/4g_app/4g_app.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file 4g_app.c + * @brief support get data from and send data to 4g server + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.12.12 + */ + +#include +#include +#include +#include + +static uint8_t adapter_4g_status = 0; +static pthread_t recv_4g_heart_task; +struct Adapter *adapter_4g; + +static const uint8_t server_addr[] = "xxx.xxx.xxx.xxx"; +static const uint8_t server_port[] = "xxx"; + +#define ADAPTER_4G_HEART "HEART" + +int Adapter4GConnectFunction(struct Adapter *adapter, uint8_t reconnect) +{ + int ret = 0; + int baud_rate = BAUD_RATE_115200; + + if (1 != reconnect) { + ret = AdapterDeviceOpen(adapter); + if (ret < 0) { + goto out; + } + + ret = AdapterDeviceControl(adapter, OPE_INT, &baud_rate); + if (ret < 0) { + goto out; + } + } + + ret = AdapterDeviceConnect(adapter, CLIENT, server_addr, server_port, IPV4); + if (ret < 0) { + goto out; + } + +out: + if (ret < 0) { + AdapterDeviceClose(adapter); + } + return ret; +} + +void Adapter4gSend(uint8_t *send_data, size_t length) +{ + if (adapter_4g_status) { + AdapterDeviceSend(adapter_4g, send_data, length); + } +} + +static void *Receive4gHeartTask(void* parameter) +{ + char recv_msg[16] = {0}; + ssize_t recv_length = 0; + uint8_t net_status_cnt = 0; + + while (1) { + + SetTaskStatus(0x01); + + if (net_status_cnt > 5) { + adapter_4g_status = 0; + + while (Adapter4GConnectFunction(adapter_4g, 1) < 0) { + PrivTaskDelay(10000); + } + + net_status_cnt = 0; + } + + adapter_4g_status = 1; + + recv_length = AdapterDeviceRecv(adapter_4g, recv_msg, 6); + if (recv_length > 0) { + //if (0 == strcmp(recv_msg, ADAPTER_4G_HEART)) { + net_status_cnt = 0; + //} + } else { + printf("4G recv heart error re-recv cnt %d\n", net_status_cnt); + net_status_cnt++; + } + memset(recv_msg, 0, sizeof(recv_msg)); + } +} + +int Adapter4GActive(void) +{ + int ret = 0; + adapter_4g = AdapterDeviceFindByName(ADAPTER_4G_NAME); + +#ifdef ADAPTER_EC200T + adapter_4g->socket.socket_id = 0; + + ret = Adapter4GConnectFunction(adapter_4g, 0); + if (ret < 0) { + printf("Adapter4GConnect failed %d\n", ret); + } + + adapter_4g_status = 1; + + pthread_attr_t attr; + attr.schedparam.sched_priority = 22; + attr.stacksize = 2048; + + PrivTaskCreate(&recv_4g_heart_task, &attr, &Receive4gHeartTask, NULL); + PrivTaskStartup(&recv_4g_heart_task); + +#endif + + return ret; +} + + diff --git a/APP_Framework/Applications/connection_app/4g_app/Makefile b/APP_Framework/Applications/connection_app/4g_app/Makefile new file mode 100644 index 000000000..68d972542 --- /dev/null +++ b/APP_Framework/Applications/connection_app/4g_app/Makefile @@ -0,0 +1,3 @@ +SRC_FILES := 4g_app.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/connection_app/Makefile b/APP_Framework/Applications/connection_app/Makefile index f50c4dbda..0cb8c9568 100755 --- a/APP_Framework/Applications/connection_app/Makefile +++ b/APP_Framework/Applications/connection_app/Makefile @@ -10,6 +10,10 @@ endif ifeq ($(CONFIG_ADD_XIZI_FETURES),y) + ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y) + SRC_DIR += 4g_app + endif + ifeq ($(CONFIG_RESOURCES_LWIP),y) SRC_DIR += socket_demo endif diff --git a/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c b/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c index 9567871c3..985a5fc61 100644 --- a/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c +++ b/APP_Framework/Applications/control_app/plc_demo/mitsubishi/mitsubishi_fx3u.c @@ -18,6 +18,47 @@ * @date 2022.9.27 */ - +#include + +extern int Adapter4GActive(void); + +void ControlFx3uTest(void) +{ + int i, j = 0; + int read_data_length = 0; + uint8_t read_data[128] = {0}; + +#ifdef CONNECTION_ADAPTER_4G + Adapter4GActive(); +#endif + + ControlProtocolType modbus_tcp_protocol = ControlProtocolFind(); + if (NULL == modbus_tcp_protocol) { + printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol); + return; + } + + printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol); + + if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) { + ControlProtocolOpen(modbus_tcp_protocol); + + for (;;) { + read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data)); + printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length); + if (read_data_length) { + for (j = 0; j < read_data_length; j ++) { + printf("j %d data 0x%x\n", j, read_data[j]); + } + } + i++; + memset(read_data, 0, sizeof(read_data)); + PrivTaskDelay(10000); + } + + //ControlProtocolClose(modbus_tcp_protocol); + } +} +PRIV_SHELL_CMD_FUNCTION(ControlFx3uTest, Mitsubishi fx3u Demo, PRIV_SHELL_CMD_MAIN_ATTR); diff --git a/APP_Framework/Framework/control/ipc_protocol/Kconfig b/APP_Framework/Framework/control/ipc_protocol/Kconfig index bc72c4672..3c586a36b 100755 --- a/APP_Framework/Framework/control/ipc_protocol/Kconfig +++ b/APP_Framework/Framework/control/ipc_protocol/Kconfig @@ -1,8 +1,13 @@ config CONTROL_PROTOCOL_MODBUS_TCP bool "Using modbus_tcp control protocol" default n +if CONTROL_PROTOCOL_MODBUS_TCP + source "$APP_DIR/Framework/control/ipc_protocol/modbus_tcp/Kconfig" +endif config CONTROL_PROTOCOL_MODBUS_UART bool "Using modbus_uart control protocol" default n - +if CONTROL_PROTOCOL_MODBUS_UART + source "$APP_DIR/Framework/control/ipc_protocol/modbus_uart/Kconfig" +endif diff --git a/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h new file mode 100755 index 000000000..4eb8210b8 --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/include/modbus_tcp.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2022 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * @file modbus_tcp.h + * @brief support modbus_tcp function + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022.09.27 + */ + +#ifndef MODBUS_TCP_H +#define MODBUS_TCP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MODBUS_TCP_UNIT_ID 0x00 +#define MODBUS_TCP_READ_CMD_LENGTH 0x0C +#define MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH 0x0C + +#define MODBUS_TCP_WRITE_MULTI_HEAD 0x07 + +typedef enum +{ + READ_COIL_STATUS = 0x01, //read coil cmd + READ_INPUT_STATUS = 0x02, //read input colr cmd + READ_HOLDING_REGISTER = 0x03, //read register info cmd + READ_INPUT_REGISTER = 0x04, //read input register cmd + WRITE_SINGLE_COIL = 0x05, //write coil cmd + WRITE_SINGLE_REGISTER = 0x06, //write single register cmd + WRITE_MULTIPLE_COIL = 0x0F, //write multi coil cmd + WRITE_MULTIPLE_REGISTER = 0x10 //write multi register cmd +}ModbusTcpFunctionCode; + +typedef struct +{ + BasicPlcDataInfo base_data_info; + ModbusTcpFunctionCode function_code; +}ModbusTcpDataInfo; + +typedef struct +{ + ModbusTcpDataInfo data_info; + + UniformValueType value_type; + char value_name[20]; + + uint16_t start_address; + uint16_t quantity; +}ModbusTcpReadItem; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c index 9fc2d4c6a..45734f2ca 100755 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c @@ -15,6 +15,436 @@ * @brief support modbus_tcp function * @version 3.0 * @author AIIT XUOS Lab - * @date 2022.09.27 + * @date 2022.12.09 */ +#include + +/*using cirtular area to receive write-data*/ +#define CA_DATA_LENGTH 512 +struct CircularAreaApp *g_write_data; + +static BasicSocketPlc plc_socket = {0}; +static uint8_t recv_buff[1024] = {0}; + +/** + * @description: Modbus Tcp Data Transform from Receive Buffer To Control-Data + * @param p_read_item - read item pointer + * @param recv_buff - receive buff + * @return success : 0 error : -1 + */ +static int ModbusTcpTransformRecvBuffToData(ModbusTcpReadItem *p_read_item, uint8_t *recv_buff) +{ + uint8_t *data_buffer; + ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info); + uint16_t quantity = p_read_item->quantity; + + ModbusTcpFunctionCode function_code = p_modbus_tcp_data_info->function_code; + uint8_t *p_data = p_modbus_tcp_data_info->base_data_info.p_data; + + printf("Receive data is "); + + uint8_t bytes_count = recv_buff[8]; + data_buffer = recv_buff + 9;//remove head data + + if (READ_COIL_STATUS == function_code || READ_INPUT_STATUS == function_code) { + for (int i = 0;i < bytes_count;i ++) { + for (int j = 0;j < 8;j ++) { + if ((i * 8 + j) < p_read_item->quantity) { + *(uint8_t *)(p_data + i * 8 + j) = ((data_buffer[i] >> j) & 0x01) ? 1 : 0; + printf("0x%x", *(uint8_t *)(p_data + i * 8 + j)); + } + } + } + } else { + for (uint16_t i = 0; i < quantity; i ++) { + ((int16_t *)p_data)[i] = ((int16_t *)data_buffer)[quantity - i - 1]; + printf("0x%x 0x%x ", p_data[2 * i], p_data[2 * i + 1]); + } + } + printf("\n"); +} + +/** + * @description: Modbus Tcp Get Data From Socket + * @param socket - socket + * @param p_read_item - read item pointer + * @return success : 0 error : -1 -2 + */ +static int ModbusTcpGetData(int32_t socket, ModbusTcpReadItem *p_read_item) +{ + uint8_t try_count = 0; + int32_t write_error = 0; + + ModbusTcpDataInfo *p_modbus_tcp_data_info = &(p_read_item->data_info); + BasicPlcDataInfo *p_base_data_info = &(p_modbus_tcp_data_info->base_data_info); + + if (!p_base_data_info->command_ready) { + //command not ready, just return + return 1; + } + + memset(recv_buff, 0, sizeof(recv_buff)); + + while (try_count < 10) { + ControlPrintfList("SEND", p_base_data_info->p_command, p_base_data_info->command_length); + try_count++; + + write_error = socket_write(socket, p_base_data_info->p_command, p_base_data_info->command_length); + if (write_error < 0) { + printf("Write socket error, errno is %d!", errno); + } else { + PrivTaskDelay(20); + + int32_t recv_length = socket_read(socket, recv_buff, sizeof(recv_buff)); + if (recv_length < 0) { + printf("Read socket error, errno is %d!", errno); + } else { + ControlPrintfList("RECV", recv_buff, recv_length); + return ModbusTcpTransformRecvBuffToData(p_read_item, recv_buff); + } + } + + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + printf("Send command failed, errno is %d!", errno); + continue; + } else { + return -1; + } + } + return -2; +} + +/** + * @description: Modbus Tcp Data Info Init + * @param p_read_item - read item pointer + * @param index - read item index + * @param p_data - control-data pointer + * @return success : 0 error : -1 + */ +static int ModbusTcpInitialDataInfo(ModbusTcpReadItem *p_read_item, uint16_t index, uint8_t *p_data) +{ + uint16_t command_index = 0; + uint8_t function_code = p_read_item->data_info.function_code; + uint16_t start_address = p_read_item->start_address; + uint16_t quantity = p_read_item->quantity; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + + switch (function_code) + { + case READ_COIL_STATUS: + case READ_INPUT_STATUS: + case READ_HOLDING_REGISTER: + case READ_INPUT_REGISTER: + p_base_data_info->command_length = MODBUS_TCP_READ_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->command_ready = 1; + break; + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + if (p_data == NULL) { + return -1; + } else { + p_base_data_info->command_length = MODBUS_TCP_WRITE_SINGLE_CMD_LENGTH; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = 2; + p_base_data_info->command_ready = 0; + } + break; + case WRITE_MULTIPLE_COIL: + if (p_data == NULL) { + return -1; + } else { + //"quantity" define how many coil need to be written,"n_byte" define the bytes of write-data(counted by bit) + uint16_t n_byte = (quantity - 1) / 8 + 1; + p_base_data_info->command_length = n_byte + MODBUS_TCP_WRITE_MULTI_HEAD + 6; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + + //13th command define the bytes of write-data + p_base_data_info->p_command[12] = ((quantity - 1) / 8 + 1); + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = n_byte; + p_base_data_info->command_ready = 0; + } + break; + case WRITE_MULTIPLE_REGISTER: + if (p_data == NULL) { + return -1; + } else { + //"quantity" define how many register need to be written + p_base_data_info->command_length = quantity * 2 + MODBUS_TCP_WRITE_MULTI_HEAD + 6; + p_base_data_info->p_command = PrivMalloc(p_base_data_info->command_length); + + //13th command define the bytes of write-data + p_base_data_info->p_command[12] = 2 * quantity; + p_base_data_info->p_data = p_data; + p_base_data_info->data_size = quantity * 2; + p_base_data_info->command_ready = 0; + } + break; + default: + return -2; + break; + } + + command_index = 0; + p_base_data_info->p_command[command_index++] = index >> 8; + p_base_data_info->p_command[command_index++] = index; + p_base_data_info->p_command[command_index++] = 0x00; + p_base_data_info->p_command[command_index++] = 0x00; + p_base_data_info->p_command[command_index++] = 0x00; + + if (function_code < 5) { + p_base_data_info->p_command[command_index++] = 0x06; + } else { + p_base_data_info->p_command[command_index++] = 0x09; + } + + p_base_data_info->p_command[command_index++] = MODBUS_TCP_UNIT_ID; + p_base_data_info->p_command[command_index++] = function_code; + p_base_data_info->p_command[command_index++] = start_address >> 8; + p_base_data_info->p_command[command_index++] = start_address; + + if (function_code != WRITE_SINGLE_COIL || function_code != WRITE_SINGLE_REGISTER) { + p_base_data_info->p_command[command_index++] = quantity >> 8; + p_base_data_info->p_command[command_index++] = quantity; + } + return 0; +} + +/** + * @description: Modbus Tcp Format write data from "g_write_data" + * @param p_read_item - read item pointer + * @return success : 0 error : -1 + */ +static int ModbusTcpForamatWriteData(ModbusTcpReadItem *p_read_item) +{ + int i = 0; + uint16_t command_index = 0; + int write_data_length = 0; + uint8_t write_data_buffer[32] = {0}; + + BasicPlcDataInfo *p_base_data_info = &(p_read_item->data_info.base_data_info); + uint8_t *p_command = p_base_data_info->p_command; + uint8_t function_code = p_read_item->data_info.function_code; + + if (function_code < WRITE_SINGLE_COIL) { + return 0; + } + + write_data_length = CircularAreaAppRead(g_write_data, write_data_buffer, p_base_data_info->data_size); + if (p_base_data_info->data_size != write_data_length) { + printf("%s get write data %d [should be %d]failed!", __func__, write_data_length, p_base_data_info->data_size); + return 0; + } + + switch (function_code) + { + case WRITE_SINGLE_COIL: + case WRITE_SINGLE_REGISTER: + command_index = 10; + case WRITE_MULTIPLE_COIL: + case WRITE_MULTIPLE_REGISTER: + command_index = 13; + break; + default: + return -2; + break; + } + + for (i = 0; i < write_data_length; i ++) { + p_base_data_info->p_command[command_index++] = write_data_buffer[i]; + } + + return write_data_length; +} + +/** + * @description: Modbus Tcp Receive Plc Data Task + * @param parameter - parameter pointer + * @return + */ +void *ReceivePlcDataTask(void *parameter) +{ + int i = 0; + uint8_t try_count = 0; + uint16_t data_length = 0; + uint8_t *modbus_tcp_data; + uint16_t read_item_size = sizeof(ModbusTcpReadItem); + + struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter; + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + ModbusTcpReadItem *modbus_tcp_read_item = (ModbusTcpReadItem *)control_protocol->recipe->read_item; + modbus_tcp_data = control_protocol->recipe->protocol_data.data; + data_length = control_protocol->recipe->protocol_data.data_length; + + memset(&plc_socket, 0, sizeof(BasicSocketPlc)); + memcpy(plc_socket.ip, control_protocol->recipe->socket_config.plc_ip, 4); + plc_socket.port = control_protocol->recipe->socket_config.port; + plc_socket.socket = -1; + plc_socket.secondary_connect_flag = 0; + + while (1) { + for (i = 0; i < control_protocol->recipe->read_item_count; i ++) { + /*only connect socket when close socket or init*/ + while (ControlConnectSocket(&plc_socket) < 0) { + PrivTaskDelay(1000); + } + + ModbusTcpForamatWriteData((ModbusTcpReadItem *)modbus_tcp_read_item + i); + + ModbusTcpGetData(plc_socket.socket, (ModbusTcpReadItem *)modbus_tcp_read_item + i); + } + + /*read all variable item data, put them into circular_area*/ + if (i == control_protocol->recipe->read_item_count) { + printf("%s get %d item %d length modbus_tcp_data %p\n", __func__, i, data_length, modbus_tcp_data); + CircularAreaAppWrite(circular_area, modbus_tcp_data, data_length, 0); + } + + /*read data every single 'read_period' ms*/ + PrivTaskDelay(control_protocol->recipe->read_period); + } +} + +/** + * @description: Modbus Tcp Protocol Open + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusTcpOpen(struct ControlProtocol *control_protocol) +{ + ControlProtocolOpenDef(control_protocol); + + g_write_data = CircularAreaAppInit(CA_DATA_LENGTH); + if (NULL == g_write_data) { + printf("%s CircularAreaInit error\n", __func__); + return -1; + } + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Close + * @param control_protocol - control protocol pointer + * @return success : 0 error + */ +int ModbusTcpClose(struct ControlProtocol *control_protocol) +{ + CircularAreaAppRelease(g_write_data); + + ControlDisconnectSocket(&plc_socket); + + ControlProtocolCloseDef(); + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Read Data + * @param control_protocol - control protocol pointer + * @param buf - read data buffer + * @param len - read data length + * @return success : data length error : 0 + */ +int ModbusTcpRead(struct ControlProtocol *control_protocol, void *buf, size_t len) +{ + struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args; + return CircularAreaAppRead(circular_area, buf, len); +} + +/** + * @description: Modbus Tcp Protocol Write Data + * @param control_protocol - control protocol pointer + * @param buf - write data buffer + * @param len - write data length + * @return success : data length error : 0 + */ +int ModbusTcpWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len) +{ + CircularAreaAppWrite(g_write_data, (uint8_t *)buf, len, 0); + + return 0; +} + +/** + * @description: Modbus Tcp Protocol Ioctl + * @param control_protocol - control protocol pointer + * @param cmd - ioctl cmd + * @param args - ioctl args + * @return success : data length error : 0 + */ +int ModbusTcpIoctl(struct ControlProtocol *control_protocol, int cmd, void *args) +{ + //to do + return 0; +} + +static struct ControlDone modbustcp_protocol_done = +{ + ._open = ModbusTcpOpen, + ._close = ModbusTcpClose, + ._read = ModbusTcpRead, + ._write = ModbusTcpWrite, + ._ioctl = ModbusTcpIoctl, +}; + +/** + * @description: Modbus TCP Protocol Cmd Generate + * @param p_recipe - recipe pointer + * @param protocol_format_info - protocol format info pointer + * @return success : 0 error : -1 + */ +int ModbusTcpProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) +{ + int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; + + ModbusTcpReadItem *modbustcp_read_item = (ModbusTcpReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; + + modbustcp_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; + strncpy(modbustcp_read_item->value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20); + modbustcp_read_item->data_info.function_code = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "function_code")->valueint; + modbustcp_read_item->start_address = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "start_address")->valueint; + modbustcp_read_item->quantity = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "quantity")->valueint; + + ret = ModbusTcpInitialDataInfo(modbustcp_read_item, + protocol_format_info->read_item_index, + p_read_item_data); + + ControlPrintfList("CMD", modbustcp_read_item->data_info.base_data_info.p_command, modbustcp_read_item->data_info.base_data_info.command_length); + protocol_format_info->last_item_size = GetValueTypeMemorySize(modbustcp_read_item->value_type); + + last_item_size += protocol_format_info->last_item_size; + + return ret; + +} + +/** + * @description: Modbus TCP Protocol Init + * @param p_recipe - recipe pointer + * @return success : 0 error : -1 + */ +int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe) +{ + p_recipe->read_item = PrivMalloc(sizeof(ModbusTcpReadItem) * p_recipe->read_item_count); + if (NULL == p_recipe->read_item) { + PrivFree(p_recipe->read_item); + return -1; + } + + memset(p_recipe->read_item, 0, sizeof(ModbusTcpReadItem)); + + p_recipe->ControlProtocolFormatCmd = ModbusTcpProtocolFormatCmd; + + p_recipe->done = &modbustcp_protocol_done; + + return 0; +} + diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h deleted file mode 100755 index a2063e96f..000000000 --- a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2022 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -/** - * @file modbus_tcp.h - * @brief support modbus_tcp function - * @version 3.0 - * @author AIIT XUOS Lab - * @date 2022.09.27 - */ - -#ifndef MODBUS_TCP_H -#define MODBUS_TCP_H - - - -#endif diff --git a/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json new file mode 100644 index 000000000..b08980aaf --- /dev/null +++ b/APP_Framework/Framework/control/ipc_protocol/modbus_tcp/test_recipe_modbus.json @@ -0,0 +1,142 @@ +{ + "device_id": 4, + "device_name": "GJ2", + "communication_type": 0, + "socket_config": { + "plc_ip": "192.168.250.9", + "local_ip": "192.168.250.233", + "gateway": "192.168.250.1", + "netmask": "255.255.254.0", + "port": 502 + }, + "protocol_type": 2, + "read_period": 100, + "read_item_list": [ + { + "value_name": "M0", + "value_type": 1, + "function_code": 1, + "start_address": 8192, + "quantity": 1 + }, + { + "value_name": "M1", + "value_type": 1, + "function_code": 1, + "start_address":8193, + "quantity": 1 + }, + { + "value_name": "M102", + "value_type": 1, + "function_code": 1, + "start_address": 8294, + "quantity": 1 + }, + { + "value_name": "M200", + "value_type": 1, + "function_code": 1, + "start_address": 8392, + "quantity": 1 + }, + { + "value_name": "M201", + "value_type": 1, + "function_code": 1, + "start_address":8393, + "quantity": 1 + }, + { + "value_name": "M202", + "value_type": 1, + "function_code": 1, + "start_address": 8394, + "quantity": 1 + }, + { + "value_name": "M203", + "value_type": 1, + "function_code": 1, + "start_address": 8395, + "quantity": 1 + }, + { + "value_name": "M204", + "value_type": 1, + "function_code": 1, + "start_address": 8396, + "quantity": 1 + }, + { + "value_name": "M205", + "value_type": 1, + "function_code": 1, + "start_address": 8397, + "quantity": 1 + }, + { + "value_name": "M206", + "value_type": 1, + "function_code": 1, + "start_address": 8398, + "quantity": 1 + }, + { + "value_name": "D20", + "value_type": 3, + "function_code": 3, + "start_address": 20, + "quantity": 1 + }, + { + "value_name": "D21", + "value_type": 3, + "function_code": 3, + "start_address": 21, + "quantity": 1 + }, + { + "value_name": "D22", + "value_type": 3, + "function_code": 3, + "start_address": 22, + "quantity": 1 + }, + { + "value_name": "D23", + "value_type": 3, + "function_code": 3, + "start_address": 23, + "quantity": 1 + }, + { + "value_name": "D202", + "value_type": 9, + "function_code": 3, + "start_address": 202, + "quantity": 2 + }, + { + "value_name": "D204", + "value_type": 9, + "function_code": 3, + "start_address": 204, + "quantity": 2 + }, + { + "value_name": "D206", + "value_type": 9, + "function_code": 3, + "start_address": 206, + "quantity": 2 + }, + { + "value_name": "D208", + "value_type": 9, + "function_code": 3, + "start_address": 208, + "quantity": 2 + } + ] +} \ No newline at end of file diff --git a/APP_Framework/Framework/control/plc_protocol/fins/fins.c b/APP_Framework/Framework/control/plc_protocol/fins/fins.c index 1c20eba77..1b0419a88 100644 --- a/APP_Framework/Framework/control/plc_protocol/fins/fins.c +++ b/APP_Framework/Framework/control/plc_protocol/fins/fins.c @@ -328,7 +328,7 @@ void *ReceivePlcDataTask(void *parameter) CircularAreaAppWrite(circular_area, fins_data, data_length, 0); } - /*read data every single 200ms*/ + /*read data every single 'read_period' ms*/ PrivTaskDelay(control_protocol->recipe->read_period); } } @@ -390,6 +390,8 @@ static struct ControlDone fins_protocol_done = int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) { int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; FinsReadItem *fins_read_item = (FinsReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; @@ -405,11 +407,13 @@ int FinsProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *pr ret = FinsInitialDataInfo(fins_read_item, p_recipe->socket_config.plc_ip[3], p_recipe->socket_config.local_ip[3], - protocol_format_info->p_read_item_data + protocol_format_info->last_item_size); + p_read_item_data); ControlPrintfList("CMD", fins_read_item->data_info.base_data_info.p_command, fins_read_item->data_info.base_data_info.command_length); protocol_format_info->last_item_size = GetValueTypeMemorySize(fins_read_item->value_type); + last_item_size += protocol_format_info->last_item_size; + return ret; } @@ -426,6 +430,8 @@ int FinsProtocolInit(struct ControlRecipe *p_recipe) return -1; } + memset(p_recipe->read_item, 0, sizeof(FinsReadItem)); + p_recipe->ControlProtocolFormatCmd = FinsProtocolFormatCmd; p_recipe->done = &fins_protocol_done; diff --git a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c index 9d95485eb..4a48288d8 100644 --- a/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c +++ b/APP_Framework/Framework/control/plc_protocol/melsec/melsec.c @@ -566,7 +566,7 @@ void *ReceivePlcDataTask(void *parameter) CircularAreaAppWrite(circular_area, melsec_data, data_length, 0); } - /*read data every single read_period*/ + /*read data every single 'read_period' ms*/ PrivTaskDelay(control_protocol->recipe->read_period); } } @@ -628,6 +628,9 @@ static struct ControlDone melsec_protocol_done = int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info) { int ret = 0; + static uint8_t last_item_size = 0; + uint8_t *p_read_item_data = protocol_format_info->p_read_item_data + last_item_size; + MelsecReadItem *melsec_read_item = (MelsecReadItem *)(p_recipe->read_item) + protocol_format_info->read_item_index; melsec_read_item->value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint; @@ -639,12 +642,13 @@ int MelsecProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo * strncpy(melsec_read_item->head_device_number_string, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "head_device_number_string")->valuestring, 6); melsec_read_item->device_points_count = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "device_points_count")->valueint; - ret = MelsecInitialDataInfo(melsec_read_item, - protocol_format_info->p_read_item_data + protocol_format_info->last_item_size); + ret = MelsecInitialDataInfo(melsec_read_item, p_read_item_data); ControlPrintfList("CMD", melsec_read_item->data_info.base_data_info.p_command, melsec_read_item->data_info.base_data_info.command_length); protocol_format_info->last_item_size = GetValueTypeMemorySize(melsec_read_item->value_type); + last_item_size += protocol_format_info->last_item_size; + return ret; } @@ -661,6 +665,8 @@ int MelsecProtocolInit(struct ControlRecipe *p_recipe) return -1; } + memset(p_recipe->read_item, 0, sizeof(MelsecReadItem)); + p_recipe->ControlProtocolFormatCmd = MelsecProtocolFormatCmd; p_recipe->done = &melsec_protocol_done; diff --git a/APP_Framework/Framework/control/shared/control_def.c b/APP_Framework/Framework/control/shared/control_def.c index fbc33225c..33783456b 100644 --- a/APP_Framework/Framework/control/shared/control_def.c +++ b/APP_Framework/Framework/control/shared/control_def.c @@ -37,6 +37,10 @@ extern int FinsProtocolInit(struct ControlRecipe *p_recipe); extern int MelsecProtocolInit(struct ControlRecipe *p_recipe); #endif +#ifdef CONTROL_PROTOCOL_MODBUS_TCP +extern int ModbusTcpProtocolInit(struct ControlRecipe *p_recipe); +#endif + /* CONTROL FRAMEWORK READ DATA FORMAT: | HEAD |device_id|read data length|read item count| data | @@ -66,6 +70,9 @@ static struct ControlProtocolInitParam protocol_init[] = { PROTOCOL_MELSEC_1C, MelsecProtocolInit }, { PROTOCOL_MELSEC_3C, MelsecProtocolInit }, #endif +#ifdef CONTROL_PROTOCOL_MODBUS_TCP + { PROTOCOL_MODBUS_TCP, ModbusTcpProtocolInit }, +#endif { PROTOCOL_END, NULL }, }; diff --git a/APP_Framework/Framework/control/shared/control_def.h b/APP_Framework/Framework/control/shared/control_def.h index 9126c6c1d..fced6fd80 100644 --- a/APP_Framework/Framework/control/shared/control_def.h +++ b/APP_Framework/Framework/control/shared/control_def.h @@ -69,6 +69,7 @@ typedef struct { uint16_t command_length; uint16_t data_size; + uint8_t command_ready; uint8_t *p_command; uint8_t *p_data; }BasicPlcDataInfo;