diff --git a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c index a5526d093..b386f441f 100755 --- a/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c +++ b/APP_Framework/Applications/control_app/opcua_demo/opcua_demo.c @@ -42,38 +42,34 @@ * Variables ******************************************************************************/ -char test_ua_ip[] = {192, 168, 250, 5}; +char test_ua_ip[] = {192, 168, 250, 2}; /******************************************************************************* * Code ******************************************************************************/ -static void UaConnectTestTask(void *arg) +static void UaConnectTestTask(void* arg) { struct netif net; UA_StatusCode retval; char ua_uri[UA_URL_SIZE]; - memset(ua_uri, 0, sizeof(ua_uri)); + UA_Client* client = UA_Client_new(); - UA_Client *client = UA_Client_new(); - - if (client == NULL) + if(client == NULL) { ua_print("ua: [%s] tcp client null\n", __func__); return; } - UA_ClientConfig *config = UA_Client_getConfig(client); + UA_ClientConfig* config = UA_Client_getConfig(client); UA_ClientConfig_setDefault(config); - snprintf(ua_uri, sizeof(ua_uri), "opc.tcp://%d.%d.%d.%d:4840", - test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]); - + test_ua_ip[0], test_ua_ip[1], test_ua_ip[2], test_ua_ip[3]); ua_pr_info("ua uri: %d %s\n", strlen(ua_uri), ua_uri); - retval = UA_Client_connect(client,ua_uri); - if (retval != UA_STATUSCODE_GOOD) + + if(retval != UA_STATUSCODE_GOOD) { ua_pr_info("ua: [%s] connected failed %x\n", __func__, retval); UA_Client_delete(client); @@ -85,7 +81,7 @@ static void UaConnectTestTask(void *arg) UA_Client_delete(client); } -void UaConnectTest(void *arg) +void UaConnectTest(void* arg) { lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); sys_thread_new("ua test", UaConnectTestTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO); @@ -94,23 +90,23 @@ void UaConnectTest(void *arg) SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), UaConnect, UaConnectTest, Test Opc UA connection); -void UaBrowserObjectsTestTask(void *param) +void UaBrowserObjectsTestTask(void* param) { - UA_Client *client = UA_Client_new(); - + UA_Client* client = UA_Client_new(); ua_pr_info("ua: [%s] start ...\n", __func__); - if (client == NULL) + if(client == NULL) { ua_print("ua: [%s] tcp client null\n", __func__); return; } - UA_ClientConfig *config = UA_Client_getConfig(client); + UA_ClientConfig* config = UA_Client_getConfig(client); UA_ClientConfig_setDefault(config); - UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); - if(retval != UA_STATUSCODE_GOOD) { + + if(retval != UA_STATUSCODE_GOOD) + { ua_print("ua: [%s] connect failed %#x\n", __func__, retval); UA_Client_delete(client); return; @@ -118,18 +114,15 @@ void UaBrowserObjectsTestTask(void *param) ua_print("ua: [%s] connect ok!\n", __func__); ua_pr_info("--- start read time ---\n", __func__); - ua_read_time(client); - ua_pr_info("--- get server info ---\n", __func__); - ua_browser_objects(client); - + ua_test_browser_objects(client); /* Clean up */ UA_Client_disconnect(client); - UA_Client_delete(client); /* Disconnects the client internally */ + UA_Client_delete(client); /* Disconnects the client internally */ } -void *UaBrowserObjectsTest(int argc, char *argv[]) +void* UaBrowserObjectsTest(int argc, char* argv[]) { if(argc == 2) { @@ -151,38 +144,37 @@ void *UaBrowserObjectsTest(int argc, char *argv[]) SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), UaObj, UaBrowserObjectsTest, UaObj [IP]); -void UaGetInfoTestTask(void *param) +void UaGetInfoTestTask(void* param) { - UA_Client *client = UA_Client_new(); - + UA_Client* client = UA_Client_new(); ua_pr_info("ua: [%s] start ...\n", __func__); - if (client == NULL) + if(client == NULL) { ua_print("ua: [%s] tcp client null\n", __func__); return; } - UA_ClientConfig *config = UA_Client_getConfig(client); + UA_ClientConfig* config = UA_Client_getConfig(client); UA_ClientConfig_setDefault(config); - UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); - if(retval != UA_STATUSCODE_GOOD) { + + if(retval != UA_STATUSCODE_GOOD) + { ua_print("ua: [%s] connect failed %#x\n", __func__, retval); UA_Client_delete(client); return; } ua_print("ua: [%s] connect ok!\n", __func__); - ua_pr_info("--- get server info ---\n", __func__); - ua_get_server_info(client); - + ua_pr_info("--- interactive server ---\n", __func__); + ua_test_interact_server(client); /* Clean up */ UA_Client_disconnect(client); - UA_Client_delete(client); /* Disconnects the client internally */ + UA_Client_delete(client); /* Disconnects the client internally */ } -void *UaGetInfoTest(int argc, char *argv[]) +void* UaGetInfoTest(int argc, char* argv[]) { if(argc == 2) { @@ -204,3 +196,55 @@ void *UaGetInfoTest(int argc, char *argv[]) SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), UaInfo, UaGetInfoTest, UaInfo [IP]); +void UaAddNodesTask(void* param) +{ + UA_Client* client = UA_Client_new(); + ua_pr_info("ua: [%s] start ...\n", __func__); + + if(client == NULL) + { + ua_print("ua: [%s] tcp client null\n", __func__); + return; + } + + UA_ClientConfig* config = UA_Client_getConfig(client); + UA_ClientConfig_setDefault(config); + UA_StatusCode retval = UA_Client_connect(client, OPC_SERVER); + + if(retval != UA_STATUSCODE_GOOD) + { + ua_print("ua: [%s] connect failed %#x\n", __func__, retval); + UA_Client_delete(client); + return; + } + + ua_print("ua: [%s] connect ok!\n", __func__); + ua_pr_info("--- add nodes ---\n", __func__); + ua_add_nodes(client); + /* Clean up */ + UA_Client_disconnect(client); + UA_Client_delete(client); /* Disconnects the client internally */ +} + +void* UaAddNodesTest(int argc, char* argv[]) +{ + if(argc == 2) + { + if(isdigit(argv[1][0])) + { + if(sscanf(argv[1], "%d.%d.%d.%d", &test_ua_ip[0], &test_ua_ip[1], &test_ua_ip[2], &test_ua_ip[3]) == EOF) + { + lw_pr_info("input wrong ip\n"); + return NULL; + } + } + } + + lwip_config_tcp(lwip_ipaddr, lwip_netmask, test_ua_ip); + sys_thread_new("ua add nodes", UaAddNodesTask, NULL, UA_STACK_SIZE, UA_TASK_PRIO); + return NULL; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + UaAdd, UaAddNodesTest, UA Add Nodes); + diff --git a/APP_Framework/Applications/control_app/plc_demo/Makefile b/APP_Framework/Applications/control_app/plc_demo/Makefile index 36aa97af0..e732c37d4 100755 --- a/APP_Framework/Applications/control_app/plc_demo/Makefile +++ b/APP_Framework/Applications/control_app/plc_demo/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := plc_demo.c +SRC_FILES := plc_show_demo.c plc_control_demo.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Applications/control_app/plc_demo/plc_control_demo.c b/APP_Framework/Applications/control_app/plc_demo/plc_control_demo.c new file mode 100755 index 000000000..429d5bcbe --- /dev/null +++ b/APP_Framework/Applications/control_app/plc_demo/plc_control_demo.c @@ -0,0 +1,232 @@ +/* + * 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 plc_control_demo.c + * @brief Demo for PLC control + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.2.22 + */ + +#include "transform.h" +#include "open62541.h" +#include "ua_api.h" +#include "sys_arch.h" +#include "plc_ch.h" +#include "plc_dev.h" +#include "plc_demo.h" + +struct PlcChannel plc_demo_ch; +struct PlcDriver plc_demo_drv; +struct PlcDevice plc_demo_dev; + +PlcCtrlParamType plc_ctrl_param; + +char plc_demo_ip[] = {192, 168, 250, 2}; + +#define TEST_STR_NID "ServiceInterfaces" +#define PLC_NS_FORMAT "n%d,%s" + +UA_NodeId test_nodeid = +{ + 4, + UA_NODEIDTYPE_NUMERIC, + 5 +}; + + +/******************************************************************************/ + +void PlcDemoChannelDrvInit(void) +{ + static uint8_t init_flag = 0; + if(init_flag) + return; + init_flag = 1; + + lwip_config_tcp(lwip_ipaddr, lwip_netmask, plc_demo_ip); + PlcChannelInit(&plc_demo_ch, PLC_CH_NAME); + if(PlcDriverInit(&plc_demo_drv, PLC_DRV_NAME) == EOK) + { + PlcDriverAttachToChannel(PLC_DRV_NAME, PLC_CH_NAME); + } + memset(&plc_demo_dev, 0, sizeof(plc_demo_dev)); +} + +static void PlcCtrlDemoInit(void) +{ + static uint8_t init_flag = 0; + + PlcDemoChannelDrvInit(); + // register plc device + plc_demo_dev.state = CHDEV_INIT; + strcpy(plc_demo_dev.name, "UA Demo"); + plc_demo_dev.info.product = "CPU 1215C"; + plc_demo_dev.info.vendor = "SIEMENS"; + plc_demo_dev.info.model = "S7-1200"; + plc_demo_dev.info.id = 123; + plc_demo_dev.net = PLC_IND_ENET_OPCUA; + + // register UA parameter + if(!plc_demo_dev.priv_data) + { + plc_demo_dev.priv_data = (UaParamType*)malloc(sizeof(UaParamType)); + } + UaParamType* ua_ptr = plc_demo_dev.priv_data; + memset(ua_ptr, 0, sizeof(UaParamType)); + strcpy(ua_ptr->ua_remote_ip, OPC_SERVER); + ua_ptr->act = UA_ACT_ATTR; + memcpy(&ua_ptr->ua_id, &test_nodeid, sizeof(test_nodeid)); + + if(init_flag) + return; + init_flag = 1; + + if(PlcDevRegister(&plc_demo_dev, NULL, plc_demo_dev.name) != EOK) + { + return; + } + PlcDeviceAttachToChannel(plc_demo_dev.name, PLC_CH_NAME); +} + +void PlcReadUATask(void* arg) +{ + int ret = 0; + struct PlcOps* ops = NULL; + char buf[PLC_BUF_SIZE]; + memset(buf, 0, sizeof(buf)); + PlcCtrlDemoInit(); + ops = plc_demo_dev.ops; + ret = ops->open(&plc_demo_dev); + + if(EOK != ret) + { + plc_print("plc: [%s] open failed %#x\n", __func__, ret); +// free(plc_demo_dev.priv_data); +// plc_demo_dev.priv_data = NULL; + return; + } + + ret = ops->read(&plc_demo_dev, buf, PLC_BUF_SIZE); + + if(EOK != ret) + { + plc_print("plc: [%s] read failed %x\n", __func__, ret); + } + + ops->close(&plc_demo_dev); +} + +void PlcReadTest(int argc, char* argv[]) +{ + static char node_str[UA_NODE_LEN]; + memset(node_str, 0, sizeof(node_str)); + + if(argc > 1) + { + plc_print("plc: arg %s\n", argv[1]); + + if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF) + { + if(isdigit(node_str[0])) + { + test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC; + test_nodeid.identifier.numeric = atoi(node_str); + plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric); + } + else + { + test_nodeid.identifierType = UA_NODEIDTYPE_STRING; + test_nodeid.identifier.string.length = strlen(node_str); + test_nodeid.identifier.string.data = node_str; + plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data); + } + } + } + + sys_thread_new("plc read", PlcReadUATask, NULL, PLC_STACK_SIZE, PLC_TASK_PRIO); +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + PlcRead, PlcReadTest, Read PLC); + +void PlcWriteUATask(void* arg) +{ + int ret = 0; + struct PlcOps* ops = NULL; + char buf[PLC_BUF_SIZE]; + memset(buf, 0, sizeof(buf)); + PlcCtrlDemoInit(); + + ops = plc_demo_dev.ops; + ret = ops->open(&plc_demo_dev); + + if(EOK != ret) + { + plc_print("plc: [%s] open failed %#x\n", __func__, ret); +// free(plc_demo_dev.priv_data); +// plc_demo_dev.priv_data = NULL; + return; + } + + ret = ops->write(&plc_demo_dev, arg, PLC_BUF_SIZE); + + if(EOK != ret) + { + plc_print("plc: [%s] read failed\n", __func__); + } + + ops->close(&plc_demo_dev); +} + +void PlcWriteTest(int argc, char* argv[]) +{ + static char node_str[UA_NODE_LEN]; + static char val_param[UA_NODE_LEN]; + memset(node_str, 0, sizeof(node_str)); + memset(val_param, 0, sizeof(val_param)); + + if(argc > 1) + { + plc_print("plc: arg %s\n", argv[1]); + + if(sscanf(argv[1], PLC_NS_FORMAT, &test_nodeid.namespaceIndex, node_str) != EOF) + { + if(isdigit(node_str[0])) + { + test_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC; + test_nodeid.identifier.numeric = atoi(node_str); + plc_print("ns %d num %d\n", test_nodeid.namespaceIndex, test_nodeid.identifier.numeric); + } + else + { + test_nodeid.identifierType = UA_NODEIDTYPE_STRING; + test_nodeid.identifier.string.length = strlen(node_str); + test_nodeid.identifier.string.data = node_str; + plc_print("ns %d str %s\n", test_nodeid.namespaceIndex, test_nodeid.identifier.string.data); + } + } + + if(argc > 2) + { + strcpy(val_param, argv[2]); + plc_print("write value %s\n", val_param); + } + } + + sys_thread_new("plc write", PlcWriteUATask, val_param, PLC_STACK_SIZE, PLC_TASK_PRIO); +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + PlcWrite, PlcWriteTest, Read PLC); + diff --git a/APP_Framework/Applications/control_app/plc_demo/plc_demo.c b/APP_Framework/Applications/control_app/plc_demo/plc_demo.c deleted file mode 100755 index 659322635..000000000 --- a/APP_Framework/Applications/control_app/plc_demo/plc_demo.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021 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 ua_demo.c - * @brief Demo for OpcUa function - * @version 1.0 - * @author AIIT XUOS Lab - * @date 2021.11.11 - */ - -#include "open62541.h" -#include "ua_api.h" -#include "sys_arch.h" -#include "plc_bus.h" -#include "plc_dev.h" - -#define PLC_BUS_NAME "PLC" -#define PLC_DRV_NAME "OPCUA" -#define PLC_DEV_NAME "PLC_1" - -#define PLC_BUF_LEN 1000 - -#define PLC_STACK_SIZE 4096 -#define PLC_TASK_PRIO 15 - -struct PlcBus plc_demo_bus; -struct PlcDriver plc_demo_drv; -struct PlcDevice plc_demo_dev; - -char plc_demo_ip[] = {192, 168, 250, 5}; - -/******************************************************************************/ - -void PlcTestInit(void) -{ - lwip_config_tcp(lwip_ipaddr, lwip_netmask, plc_demo_ip); - - PlcBusInit(&plc_demo_bus, PLC_BUS_NAME); - PlcDriverInit(&plc_demo_drv, PLC_DRV_NAME); - PlcDriverAttachToBus(PLC_DRV_NAME, PLC_BUS_NAME); - - // register plc device - plc_demo_dev.state = DEV_INIT; - PlcDevRegister(&plc_demo_dev, NULL, PLC_DEV_NAME); - - PlcDeviceAttachToBus(PLC_DEV_NAME, PLC_BUS_NAME); -} - -void PlcReadUATask(void *arg) -{ - int ret = 0; - struct PlcOps *ops = NULL; - char buf[PLC_BUF_LEN]; - - plc_demo_dev.priv_data = (ua_dev_t *)malloc(sizeof(ua_dev_t)); - ua_dev_t *ua_ptr = plc_demo_dev.priv_data; - memset(ua_ptr, 0, sizeof(ua_dev_t)); - strcpy(ua_ptr->ua_remote_ip, OPC_SERVER); - - PlcTestInit(); - plc_demo_dev.net = PLC_IND_ENET_OPCUA; - ops = plc_demo_dev.ops; - ret = ops->open(&plc_demo_dev); - if(EOK != ret) - { - plc_print("plc: [%s] open failed %#x\n", __func__, ret); - free(plc_demo_dev.priv_data); - return; - } - ret = ops->read(&plc_demo_dev, buf, PLC_BUF_LEN); - if(EOK != ret) - { - plc_print("plc: [%s] read failed\n", __func__); - } - free(plc_demo_dev.priv_data); - ops->close(&plc_demo_dev); -} - -void PlcReadTest(int argc, char *argv[]) -{ - sys_thread_new("plc read", PlcReadUATask, NULL, PLC_STACK_SIZE, PLC_TASK_PRIO); -} - -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), - plc, PlcReadTest, Read PLC); - diff --git a/APP_Framework/Applications/control_app/plc_demo/plc_demo.h b/APP_Framework/Applications/control_app/plc_demo/plc_demo.h new file mode 100755 index 000000000..45df0f4fa --- /dev/null +++ b/APP_Framework/Applications/control_app/plc_demo/plc_demo.h @@ -0,0 +1,38 @@ +/* + * 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 plc_show_demo.c + * @brief Demo for PLC information show + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.02.24 + */ + +#ifndef __PLC_DEMO_H_ +#define __PLC_DEMO_H_ + +#define PLC_CH_NAME "PLC" +#define PLC_DRV_NAME "OPCUA" + +#define PLC_BUF_SIZE 128 + +#define PLC_STACK_SIZE 4096 +#define PLC_TASK_PRIO 15 + +extern struct PlcChannel plc_demo_ch; +extern struct PlcDriver plc_demo_drv; +extern struct PlcDevice plc_demo_dev; + +void PlcDemoChannelDrvInit(void); + +#endif diff --git a/APP_Framework/Applications/control_app/plc_demo/plc_show_demo.c b/APP_Framework/Applications/control_app/plc_demo/plc_show_demo.c new file mode 100755 index 000000000..87864b3b8 --- /dev/null +++ b/APP_Framework/Applications/control_app/plc_demo/plc_show_demo.c @@ -0,0 +1,256 @@ +/* + * 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 plc_show_demo.c + * @brief Demo for PLC information show + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.02.24 + */ + +#include "transform.h" +#include "list.h" + +#include "open62541.h" +#include "ua_api.h" +#include "sys_arch.h" +#include "plc_ch.h" +#include "plc_dev.h" +#include "plc_demo.h" + + +#define PLC_DEMO_NUM 5 + +struct PlcDevice plc_demo_array[PLC_DEMO_NUM]; + +typedef struct PlcShowParam +{ + int id; + char* vector; + char* model; + char* product; +} PlcShowParamType; + +PlcShowParamType plc_demo_param[PLC_NAME_SIZE] = +{ + {1, "SIEMENS", "S7-1500", "CPU 1512SP-1PN"}, + {2, "SIEMENS", "S7-1200", "CPU 1215C"}, + {3, "SIEMSNS", "S7-200", "CPU SR60"}, + {4, "B&R", "X20", "X20 CP1586"}, + {5, "B&R", "X20", "X20 CP1381"} +}; + +static char* const channel_type_str[] = +{ + "PLC_Channel", + "Unknown" +}; + +extern DoublelistType plcdev_list; +extern DoublelistType ch_linklist; + +void PlcShowTitle(const char* item_array[]) +{ + int i = 0, max_len = 65; + KPrintf(" %-15s%-15s%-15s%-15s%-20s\n", item_array[0], item_array[1], item_array[2], item_array[3], item_array[4]); + + while(i < max_len) + { + i++; + + if(max_len == i) + { + KPrintf("-\n"); + } + else + { + KPrintf("-"); + } + } +} + +static ChDrvType ShowChannelFindDriver(struct Channel* ch) +{ + struct ChDrv* driver = NONE; + DoublelistType* node = NONE; + DoublelistType* head = &ch->ch_drvlink; + + for(node = head->node_next; node != head; node = node->node_next) + { + driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link); + return driver; + } + + return NONE; +} + +void PlcShowChannel(void) +{ + ChannelType ch; + ChDrvType driver; + ChDevType device; + int dev_cnt; + DoublelistType* ch_node = NONE; + DoublelistType* ch_head = &ch_linklist; + const char* item_array[] = {"ch_type", "ch_name", "drv_name", "dev_name", "cnt"}; + PlcShowTitle(item_array); + ch_node = ch_head->node_next; + + do + { + ch = DOUBLE_LIST_ENTRY(ch_node, struct Channel, ch_link); + + if((ch) && (ch->ch_type == CH_PLC_TYPE)) + { + KPrintf("%s", " "); + KPrintf("%-15s%-15s", + channel_type_str[ch->ch_type], + ch->ch_name); + + driver = ShowChannelFindDriver(ch); + + if(driver) + { + KPrintf("%-15s", driver->drv_name); + } + else + { + KPrintf("%-15s", "nil"); + } + + if(ch->haldev_cnt) + { + DoublelistType* dev_node = NONE; + DoublelistType* dev_head = &ch->ch_devlink; + dev_node = dev_head->node_next; + dev_cnt = 1; + + while(dev_node != dev_head) + { + device = DOUBLE_LIST_ENTRY(dev_node, struct ChDev, dev_link); + + if(1 == dev_cnt) + { + if(device) + { + KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt); + } + else + { + KPrintf("%-16s%-4d\n", "nil", dev_cnt); + } + } + else + { + KPrintf("%46s", " "); + + if(device) + { + KPrintf("%-16s%-4d\n", device->dev_name, dev_cnt); + } + else + { + KPrintf("%-16s%-4d\n", "nil", dev_cnt); + } + } + + dev_cnt++; + dev_node = dev_node->node_next; + } + } + else + { + KPrintf("\n"); + } + } + + ch_node = ch_node->node_next; + } + while(ch_node != ch_head); + + return; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + ShowChannel, PlcShowChannel, Show PLC information); + +static void PlcShowDemoInit(void) +{ + static uint8_t init_flag = 0; + int i; + PlcDemoChannelDrvInit(); + + for(i = 0; i < PLC_DEMO_NUM; i++) + { + // register plc device + plc_demo_array[i].state = CHDEV_INIT; + snprintf(plc_demo_array[i].name, PLC_NAME_SIZE, "PLC Demo %d", i); + plc_demo_array[i].info.vendor = plc_demo_param[i].vector; + plc_demo_array[i].info.model = plc_demo_param[i].model; + plc_demo_array[i].info.id = plc_demo_param[i].id; + plc_demo_array[i].info.product = plc_demo_param[i].product; + plc_demo_array[i].net = PLC_IND_ENET_OPCUA; + } + + if(init_flag) + return; + init_flag = 1; + + for(i = 0; i < PLC_DEMO_NUM; i++) + { + if(PlcDevRegister(&plc_demo_array[i], NULL, plc_demo_array[i].name) == EOK) + { + PlcDeviceAttachToChannel(plc_demo_array[i].name, PLC_CH_NAME); + } + } +} + +void PlcShowDev(void) +{ + PlcDeviceType* plc_dev; + ChDrvType driver; + ChDevType device; + DoublelistType* plc_node = NONE; + DoublelistType* plc_head = &plcdev_list; + const char* item_array[] = {"device", "vendor", "model", "product", "id"}; + PlcShowDemoInit(); + PlcShowTitle(item_array); + plc_node = plc_head->node_next; + + do + { + plc_dev = DOUBLE_LIST_ENTRY(plc_node, struct PlcDevice, link); + + if(plc_dev) + { + KPrintf("%s", " "); + KPrintf("%-15s%-15s%-15s%-15s%-20d", + plc_dev->name, + plc_dev->info.vendor, + plc_dev->info.model, + plc_dev->info.product, + plc_dev->info.id); + KPrintf("\n"); + } + + plc_node = plc_node->node_next; + } + while(plc_node != plc_head); + + return; +} + + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), + ShowPlc, PlcShowDev, Show PLC information); + diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile b/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile index 74c252d73..47d275fda 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c ua_api.c +SRC_FILES := ua_data.c open62541.c ua_client.c ua_server.c ua_api.c ua_test.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c b/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c index d94e28a6b..83d4b6732 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/open62541.c @@ -44256,7 +44256,7 @@ UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) { client->sessionState < UA_SESSIONSTATE_ACTIVATED) { retval = connectIterate(client, timeout); notifyClientState(client); - lw_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout, + ua_print("lw: [%s] ret %d timeout %d state %d ch %d\n", __func__, retval, timeout, client->sessionState, client->channel.state); return retval; } @@ -45299,7 +45299,7 @@ connectIterate(UA_Client *client, UA_UInt32 timeout) { break; } - lw_print("lw: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus); + ua_print("ua: [%s] sess %d conn %d\n", __func__, client->sessionState, client->connectStatus); return client->connectStatus; } diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c index f14a69934..e2e5fdb3e 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.c @@ -10,33 +10,39 @@ * See the Mulan PSL v2 for more details. */ +/** + * @file ua_api.c + * @brief Demo for OpcUa function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + #include "open62541.h" #include #include "ua_api.h" - int ua_open(void *dev) { - ua_dev_t *pdev = (ua_dev_t *)dev; + UaParamType *param = (UaParamType *)dev; - pdev->client = UA_Client_new(); + param->client = UA_Client_new(); ua_pr_info("ua: [%s] start ...\n", __func__); - if (pdev->client == NULL) + if (param->client == NULL) { ua_print("ua: [%s] tcp client null\n", __func__); return EEMPTY; } - UA_ClientConfig *config = UA_Client_getConfig(pdev->client); + UA_ClientConfig *config = UA_Client_getConfig(param->client); UA_ClientConfig_setDefault(config); - ua_pr_info("ua: [%s] %d %s\n", __func__, strlen(pdev->ua_remote_ip), pdev->ua_remote_ip); + ua_pr_info("ua: [%s] %d %s\n", __func__, strlen(param->ua_remote_ip), param->ua_remote_ip); - UA_StatusCode retval = UA_Client_connect(pdev->client, pdev->ua_remote_ip); + UA_StatusCode retval = UA_Client_connect(param->client, param->ua_remote_ip); if(retval != UA_STATUSCODE_GOOD) { -// UA_Client_delete(pdev->client); ua_pr_info("ua: [%s] deleted ret %x!\n", __func__, retval); return (int)retval; } @@ -45,28 +51,48 @@ int ua_open(void *dev) void ua_close(void *dev) { - ua_dev_t *pdev = (ua_dev_t *)dev; - UA_Client_disconnect(pdev->client); - UA_Client_delete(pdev->client); /* Disconnects the client internally */ + UaParamType *param = (UaParamType *)dev; + UA_Client_disconnect(param->client); + UA_Client_delete(param->client); /* Disconnects the client internally */ } -int ua_read(void* dev, void *buf, size_t len) +int ua_read(void *dev, void *buf, size_t len) { - ua_dev_t *pdev = (ua_dev_t *)dev; - ua_get_server_info(pdev->client); + UaParamType *param = (UaParamType *)dev; + switch(param->act) + { + case UA_ACT_ATTR: + ua_read_nodeid_value(param->client, param->ua_id, buf); + break; + case UA_ACT_OBJ: + ua_test_browser_objects(param->client); + break; + default: + break; + } return EOK; } -int ua_write(void* dev, const void *buf, size_t len) +int ua_write(void *dev, const void *buf, size_t len) { - ua_dev_t *pdev = (ua_dev_t *)dev; + UaParamType *param = (UaParamType *)dev; + switch(param->act) + { + case UA_ACT_ATTR: + ua_write_nodeid_value(param->client, param->ua_id, (char *)buf); + break; + case UA_ACT_OBJ: + ua_test_browser_objects(param->client); + break; + default: + break; + } return EOK; } -int ua_ioctl(void* dev, int cmd, void *arg) +int ua_ioctl(void *dev, int cmd, void *arg) { return EOK; } - diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h index f3d1103ee..2a34e81bd 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_api.h @@ -9,35 +9,50 @@ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ + +/** + * @file ua_api.h + * @brief API for OpcUa function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + #ifndef __UA_API_H__ #define __UA_API_H__ #include "open62541.h" -#define UA_DEV_IP_LEN 128 -#define UA_NODE_LEN 50 +#define UA_DEV_IP_LEN 48 +#define UA_NODE_LEN 32 -typedef struct _ua_dev_t +enum UaAction_e { + UA_ACT_ATTR, + UA_ACT_OBJ, +}; + +typedef struct UaParam +{ + enum UaAction_e act; + UA_NodeId ua_id; char ua_remote_ip[UA_DEV_IP_LEN]; char ua_node[UA_NODE_LEN]; UA_Client *client; -}ua_dev_t; +}UaParamType; -#define OPC_SERVER "opc.tcp://192.168.250.5:4840" +#define OPC_SERVER "opc.tcp://192.168.250.2:4840" #define ua_print //KPrintf #define ua_trace() //KPrintf("ua: [%s] line %d checked!\n", __func__, __LINE__) #define ua_pr_info KPrintf -#define ua_debug +#define ua_debug //KPrintf int ua_server_connect(void); -int ua_get_server_info(UA_Client *client); -void ua_browser_objects(UA_Client *client); void ua_browser_nodes(UA_Client *client); +void ua_browser_id(UA_Client *client, UA_NodeId id); void ua_read_time(UA_Client *client); -int16 ua_test(void); - +void ua_add_nodes(UA_Client *client); int ua_open(void *dev); // open and connect PLC device void ua_close(void* dev); // close and disconnect PLC device @@ -45,4 +60,12 @@ int ua_read(void* dev, void *buf, size_t len); // read data from PLC int ua_write(void* dev, const void *buf, size_t len); // write data from PLC int ua_ioctl(void* dev, int cmd, void *arg); // send control command to PLC +char *ua_get_nodeid_str(UA_NodeId *node_id); +void ua_read_nodeid_value(UA_Client *client, UA_NodeId id, UA_Int32 *value); +void ua_write_nodeid_value(UA_Client *client, UA_NodeId id, char* value); +void ua_test_attr(UA_Client *client); +UA_StatusCode ua_read_array_value(UA_Client *client, int array_size, UA_ReadValueId *array); +void ua_test_browser_objects(UA_Client *client); +int ua_test_interact_server(UA_Client *client); + #endif diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c index bda66dd07..7f469f21a 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_client.c @@ -10,185 +10,365 @@ * See the Mulan PSL v2 for more details. */ -#include "open62541.h" +/** + * @file ua_client.c + * @brief Client for OpcUa function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + #include +#include "open62541.h" #include "ua_api.h" +#define UA_RESPONSE_TIMEOUT 10000 + #ifdef UA_ENABLE_SUBSCRIPTIONS -static void handler_TheAnswerChanged(UA_Client *client, UA_UInt32 subId, void *subContext, - UA_UInt32 monId, void *monContext, UA_DataValue *value) +static void handler_TheAnswerChanged(UA_Client* client, UA_UInt32 subId, void* subContext, + UA_UInt32 monId, void* monContext, UA_DataValue* value) { ua_print("The Answer has changed!\n"); } #endif -static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void *handle) +static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId, void* handle) { if(isInverse) { return UA_STATUSCODE_GOOD; } - UA_NodeId *parent = (UA_NodeId *)handle; + UA_NodeId* parent = (UA_NodeId*)handle; ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n", - parent->namespaceIndex, parent->identifier.numeric, - referenceTypeId.identifier.numeric, childId.namespaceIndex, - childId.identifier.numeric); - + parent->namespaceIndex, parent->identifier.numeric, + referenceTypeId.identifier.numeric, childId.namespaceIndex, + childId.identifier.numeric); return UA_STATUSCODE_GOOD; } -int ua_get_points(UA_Client *client) +int ua_get_points(UA_Client* client) { /* Listing endpoints */ UA_EndpointDescription* endpointArray = NULL; size_t endpointArraySize = 0; - UA_StatusCode retval = UA_Client_getEndpoints(client, OPC_SERVER, + UA_StatusCode ret = UA_Client_getEndpoints(client, OPC_SERVER, &endpointArraySize, &endpointArray); - if(retval != UA_STATUSCODE_GOOD) + + if(ret != UA_STATUSCODE_GOOD) { UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); return EXIT_FAILURE; } ua_print("%i endpoints found\n", (int)endpointArraySize); - for(size_t i=0;itype == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]) + { + UA_LocalizedText* ptr = (UA_LocalizedText*)val->data; + ua_pr_info("%.*s (Text)\n", ptr->text.length, ptr->text.data); + } + else if(val->type == &UA_TYPES[UA_TYPES_UINT32]) + { + UA_UInt32* ptr = (UA_UInt32*)val->data; + ua_pr_info("%d (UInt32)\n", *ptr); + } + else if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN]) + { + UA_Boolean* ptr = (UA_Boolean*)val->data; + ua_pr_info("%i (BOOL)\n", *ptr); + } + else if(val->type == &UA_TYPES[UA_TYPES_INT32]) + { + UA_Int32* ptr = (UA_Int32*)val->data; + ua_pr_info("%d (Int32)\n", *ptr); + } + else if(val->type == &UA_TYPES[UA_TYPES_INT16]) + { + UA_Int16* ptr = (UA_Int16*)val->data; + ua_pr_info("%d (Int16)\n", *ptr); + } + else if(val->type == &UA_TYPES[UA_TYPES_STRING]) + { + UA_String* ptr = (UA_String*)val->data; + ua_pr_info("%*.s (String)\n", ptr->length, ptr->data); + } + else if(val->type == &UA_TYPES[UA_TYPES_DATETIME]) + { + UA_DateTime* ptr = (UA_DateTime*)val->data; + UA_DateTimeStruct dts = UA_DateTime_toStruct(*ptr); + ua_pr_info("%d-%d-%d %d:%d:%d.%03d (Time)\n", + dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec); + } +} - UA_BrowseRequest bReq; - UA_BrowseRequest_init(&bReq); +char *ua_get_nodeid_str(UA_NodeId *node_id) +{ + static char nodeid_str[UA_NODE_LEN] = {0}; - bReq.requestedMaxReferencesPerNode = 0; - bReq.nodesToBrowse = UA_BrowseDescription_new(); - bReq.nodesToBrowseSize = 1; - bReq.nodesToBrowse[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); /* browse objects folder */ - bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */ + switch(node_id->identifierType) + { + case UA_NODEIDTYPE_NUMERIC: + snprintf(nodeid_str, UA_NODE_LEN, "n%d,%d", node_id->namespaceIndex, node_id->identifier.numeric); + break; + case UA_NODEIDTYPE_STRING: + snprintf(nodeid_str, UA_NODE_LEN, "n%d,%.*s", node_id->namespaceIndex, node_id->identifier.string.length, + node_id->identifier.string.data); + break; + case UA_NODEIDTYPE_BYTESTRING: + snprintf(nodeid_str, UA_NODE_LEN, "n%d,%s", node_id->namespaceIndex, node_id->identifier.byteString.data); + break; + default: + break; + } + return nodeid_str; +} - UA_BrowseResponse bResp = UA_Client_Service_browse(client, bReq); +void ua_print_nodeid(UA_NodeId *node_id) +{ + switch(node_id->identifierType) + { + case UA_NODEIDTYPE_NUMERIC: + ua_pr_info(" NodeID n%d,%d ", node_id->namespaceIndex, node_id->identifier.numeric); + break; + case UA_NODEIDTYPE_STRING: + ua_pr_info(" NodeID n%d,%.*s ", node_id->namespaceIndex, node_id->identifier.string.length, + node_id->identifier.string.data); + break; + case UA_NODEIDTYPE_BYTESTRING: + ua_pr_info(" NodeID n%d,%s ", node_id->namespaceIndex, node_id->identifier.byteString.data); + break; + default: + break; + } +} +void ua_print_object(UA_BrowseResponse* res) +{ ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME"); - for(size_t i = 0; i < bResp.resultsSize; ++i) + for(size_t i = 0; i < res->resultsSize; ++i) { - for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) + for(size_t j = 0; j < res->results[i].referencesSize; ++j) { - UA_ReferenceDescription *ref = &(bResp.results[i].references[j]); + UA_ReferenceDescription* ref = &(res->results[i].references[j]); + if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC) { ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, - ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length, - ref->browseName.name.data, (int)ref->displayName.text.length, - ref->displayName.text.data); + ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length, + ref->browseName.name.data, (int)ref->displayName.text.length, + ref->displayName.text.data); } else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING) { ua_pr_info("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex, - (int)ref->nodeId.nodeId.identifier.string.length, - ref->nodeId.nodeId.identifier.string.data, - (int)ref->browseName.name.length, ref->browseName.name.data, - (int)ref->displayName.text.length, ref->displayName.text.data); + (int)ref->nodeId.nodeId.identifier.string.length, + ref->nodeId.nodeId.identifier.string.data, + (int)ref->browseName.name.length, ref->browseName.name.data, + (int)ref->displayName.text.length, ref->displayName.text.data); } + /* TODO: distinguish further types */ } } + ua_pr_info("\n"); - UA_BrowseRequest_clear(&bReq); - UA_BrowseResponse_clear(&bResp); } -void ua_browser_nodes(UA_Client *client) +UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValueId* array) { - /* Same thing, this time using the node iterator... */ - UA_NodeId *parent = UA_NodeId_new(); + UA_ReadRequest request; + UA_ReadRequest_init(&request); + request.nodesToRead = array; + request.nodesToReadSize = array_size; + UA_ReadResponse response = UA_Client_Service_read(client, request); + + if((response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) + || (response.resultsSize != array_size)) + { + UA_ReadResponse_clear(&response); + ua_pr_info("ua: [%s] read failed 0x%x\n", __func__, + response.responseHeader.serviceResult); + return UA_STATUSCODE_BADUNEXPECTEDERROR; + } + + UA_StatusCode* arr_ret = malloc(array_size * sizeof(UA_StatusCode)); + + for(int i = 0; i < array_size; ++i) + { + if((response.results[i].status == UA_STATUSCODE_GOOD) + && (response.results[i].hasValue)) + { + ua_pr_info("node %s: ", ua_get_nodeid_str(&array[i].nodeId)); + ua_print_value(&response.results[i].value); + } + } + ua_pr_info("\n"); + + free(arr_ret); + UA_ReadResponse_clear(&response); + return UA_STATUSCODE_GOOD; +} + +void ua_browser_id(UA_Client* client, UA_NodeId id) +{ + /* Browse some objects */ + ua_pr_info("Browsing nodes in objects folder:\n"); + UA_BrowseRequest bReq; + UA_BrowseRequest_init(&bReq); + bReq.requestedMaxReferencesPerNode = 0; + bReq.nodesToBrowse = UA_BrowseDescription_new(); + bReq.nodesToBrowseSize = 1; + bReq.nodesToBrowse[0].nodeId = id; /* browse objects folder */ + bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; /* return everything */ + UA_BrowseResponse res = UA_Client_Service_browse(client, bReq); + ua_print_object(&res); + UA_BrowseResponse_clear(&res); +// UA_BrowseRequest_clear(&bReq); +} + +void ua_browser_nodes(UA_Client* client) +{ + UA_NodeId* parent = UA_NodeId_new(); *parent = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER); - UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), - nodeIter, (void *) parent); + UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter, (void*) parent); UA_NodeId_delete(parent); } -UA_UInt32 ua_start_sub(UA_Client *client) +UA_UInt32 ua_start_sub(UA_Client* client, UA_NodeId node_id) { /* Create a subscription */ UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default(); UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request, NULL, NULL, NULL); - UA_UInt32 subId = response.subscriptionId; + if(response.responseHeader.serviceResult == UA_STATUSCODE_GOOD) + { ua_print("Create subscription succeeded, id %u\n", subId); + } + else + { + ua_print("Create subscription failed, id %u\n", response.responseHeader.serviceResult); + return response.responseHeader.serviceResult; + } UA_MonitoredItemCreateRequest monRequest = - UA_MonitoredItemCreateRequest_default(UA_NODEID_STRING(1, "the.answer")); - + UA_MonitoredItemCreateRequest_default(node_id); UA_MonitoredItemCreateResult monResponse = - UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId, - UA_TIMESTAMPSTORETURN_BOTH, - monRequest, NULL, handler_TheAnswerChanged, NULL); - if(monResponse.statusCode == UA_STATUSCODE_GOOD) - ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId); + UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId, + UA_TIMESTAMPSTORETURN_BOTH, + monRequest, NULL, handler_TheAnswerChanged, NULL); + if(monResponse.statusCode == UA_STATUSCODE_GOOD) + { + ua_print("Monitoring 'the.answer', id %u\n", monResponse.monitoredItemId); + } + else + { + ua_print("%s return 0x%x\n", __func__, monResponse.statusCode); + } /* The first publish request should return the initial value of the variable */ - UA_Client_run_iterate(client, 1000); + UA_Client_run_iterate(client, UA_RESPONSE_TIMEOUT); return subId; } -void ua_read_attr(UA_Client *client) +void ua_write_nodeid_value(UA_Client* client, UA_NodeId id, char* value) { - /* Read attribute */ - UA_Int32 value = 0; - ua_pr_info("\nReading the value of node (1, \"the.answer\"):\n"); - UA_Variant *val = UA_Variant_new(); - UA_StatusCode retval = UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), val); - if(retval == UA_STATUSCODE_GOOD && UA_Variant_isScalar(val) && - val->type == &UA_TYPES[UA_TYPES_INT32]) { - value = *(UA_Int32*)val->data; - ua_pr_info("the value is: %i\n", value); - } - UA_Variant_delete(val); - - /* Write node attribute */ - value++; - ua_pr_info("\nWriting a value of node (1, \"the.answer\"):\n"); + UA_Boolean bool_val; + uint32_t integer_val; UA_WriteRequest wReq; UA_WriteRequest_init(&wReq); + wReq.nodesToWrite = UA_WriteValue_new(); wReq.nodesToWriteSize = 1; - wReq.nodesToWrite[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer"); + + if(strncmp(value, "1b", 2) == 0) + { + wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN]; + bool_val = 1; + wReq.nodesToWrite[0].value.value.data = &bool_val; + } + else if(strncmp(value, "0b", 2) == 0) + { + wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_BOOLEAN]; + bool_val = 0; + wReq.nodesToWrite[0].value.value.data = &bool_val; + } + else + { + wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT16]; + sscanf(value, "%d", &integer_val); + wReq.nodesToWrite[0].value.value.data = &integer_val; + } + + wReq.nodesToWrite[0].nodeId = id; wReq.nodesToWrite[0].attributeId = UA_ATTRIBUTEID_VALUE; wReq.nodesToWrite[0].value.hasValue = true; - wReq.nodesToWrite[0].value.value.type = &UA_TYPES[UA_TYPES_INT32]; wReq.nodesToWrite[0].value.value.storageType = UA_VARIANT_DATA_NODELETE; /* do not free the integer on deletion */ - wReq.nodesToWrite[0].value.value.data = &value; UA_WriteResponse wResp = UA_Client_Service_write(client, wReq); + if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD) - ua_pr_info("the new value is: %i\n", value); + { + ua_pr_info("write new value is: %s\n", value); + } UA_WriteRequest_clear(&wReq); UA_WriteResponse_clear(&wResp); - /* Write node attribute (using the highlevel API) */ - value++; - UA_Variant *myVariant = UA_Variant_new(); - UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]); - UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, "the.answer"), myVariant); - UA_Variant_delete(myVariant); - +// /* Write node attribute (using the highlevel API) */ +// value++; +// UA_Variant *myVariant = UA_Variant_new(); +// UA_Variant_setScalarCopy(myVariant, &value, &UA_TYPES[UA_TYPES_INT32]); +// UA_Client_writeValueAttribute(client, UA_NODEID_STRING(1, UA_NODE_STR), myVariant); +// UA_Variant_delete(myVariant); } -void ua_call_remote(UA_Client *client) +/* Read attribute */ +void ua_read_nodeid_value(UA_Client* client, UA_NodeId id, UA_Int32 *value) +{ + UA_Variant* val = UA_Variant_new(); + UA_StatusCode ret = UA_Client_readValueAttribute(client, id, val); + + if(ret == UA_STATUSCODE_GOOD) + { + ua_print_value(val); + if(UA_Variant_isScalar(val)) + { + if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN]) + { + *value = *(UA_Boolean *)val->data; + } + else if(val->type == &UA_TYPES[UA_TYPES_INT32]) + { + *value = *(UA_Int32 *)val->data; + } + else if(val->type == &UA_TYPES[UA_TYPES_INT16]) + { + *value = *(UA_Int16 *)val->data; + } + } + } + + UA_Variant_delete(val); +} + +void ua_call_remote(UA_Client* client) { /* Call a remote method */ UA_Variant input; @@ -196,24 +376,26 @@ void ua_call_remote(UA_Client *client) UA_Variant_init(&input); UA_Variant_setScalarCopy(&input, &argString, &UA_TYPES[UA_TYPES_STRING]); size_t outputSize; - UA_Variant *output; - UA_StatusCode retval = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), - UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); - if(retval == UA_STATUSCODE_GOOD) + UA_Variant* output; + UA_StatusCode ret = UA_Client_call(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), + UA_NODEID_NUMERIC(1, 62541), 1, &input, &outputSize, &output); + + if(ret == UA_STATUSCODE_GOOD) { ua_print("Method call was successful, and %lu returned values available.\n", - (unsigned long)outputSize); + (unsigned long)outputSize); UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]); } else { - ua_print("Method call was unsuccessful, and %x returned values available.\n", retval); + ua_print("Method call was unsuccessful, and %x returned values available.\n", ret); } + UA_Variant_clear(&input); } -void ua_add_nodes(UA_Client *client) +void ua_add_nodes(UA_Client* client) { /* Add new nodes*/ /* New ReferenceType */ @@ -222,43 +404,52 @@ void ua_add_nodes(UA_Client *client) ref_attr.displayName = UA_LOCALIZEDTEXT("en-US", "NewReference"); ref_attr.description = UA_LOCALIZEDTEXT("en-US", "References something that might or might not exist"); ref_attr.inverseName = UA_LOCALIZEDTEXT("en-US", "IsNewlyReferencedBy"); - UA_StatusCode retval = UA_Client_addReferenceTypeNode(client, - UA_NODEID_NUMERIC(1, 12133), - UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), - UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), - UA_QUALIFIEDNAME(1, "NewReference"), - ref_attr, &ref_id); - if(retval == UA_STATUSCODE_GOOD ) + UA_StatusCode ret = UA_Client_addReferenceTypeNode(client, + UA_NODEID_NUMERIC(1, 12133), + UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), + UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), + UA_QUALIFIEDNAME(1, "NewReference"), + ref_attr, &ref_id); + + if(ret == UA_STATUSCODE_GOOD) + { ua_print("Created 'NewReference' with numeric NodeID %u\n", ref_id.identifier.numeric); + } /* New ObjectType */ UA_NodeId objt_id; UA_ObjectTypeAttributes objt_attr = UA_ObjectTypeAttributes_default; objt_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewObjectType"); objt_attr.description = UA_LOCALIZEDTEXT("en-US", "Put innovative description here"); - retval = UA_Client_addObjectTypeNode(client, + ret = UA_Client_addObjectTypeNode(client, UA_NODEID_NUMERIC(1, 12134), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_QUALIFIEDNAME(1, "NewObjectType"), objt_attr, &objt_id); - if(retval == UA_STATUSCODE_GOOD) + + if(ret == UA_STATUSCODE_GOOD) + { ua_print("Created 'NewObjectType' with numeric NodeID %u\n", objt_id.identifier.numeric); + } /* New Object */ UA_NodeId obj_id; UA_ObjectAttributes obj_attr = UA_ObjectAttributes_default; obj_attr.displayName = UA_LOCALIZEDTEXT("en-US", "TheNewGreatNode"); obj_attr.description = UA_LOCALIZEDTEXT("de-DE", "Hier koennte Ihre Webung stehen!"); - retval = UA_Client_addObjectNode(client, + ret = UA_Client_addObjectNode(client, UA_NODEID_NUMERIC(1, 0), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(1, "TheGreatNode"), UA_NODEID_NUMERIC(1, 12134), obj_attr, &obj_id); - if(retval == UA_STATUSCODE_GOOD ) + + if(ret == UA_STATUSCODE_GOOD) + { ua_print("Created 'NewObject' with numeric NodeID %u\n", obj_id.identifier.numeric); + } /* New Integer Variable */ UA_NodeId var_id; @@ -270,68 +461,36 @@ void ua_add_nodes(UA_Client *client) /* This does not copy the value */ UA_Variant_setScalar(&var_attr.value, &int_value, &UA_TYPES[UA_TYPES_INT32]); var_attr.dataType = UA_TYPES[UA_TYPES_INT32].typeId; - retval = UA_Client_addVariableNode(client, + ret = UA_Client_addVariableNode(client, UA_NODEID_NUMERIC(1, 0), // Assign new/random NodeID UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_QUALIFIEDNAME(0, "VariableNode"), UA_NODEID_NULL, // no variable type var_attr, &var_id); - if(retval == UA_STATUSCODE_GOOD ) + + if(ret == UA_STATUSCODE_GOOD) + { ua_print("Created 'NewVariable' with numeric NodeID %u\n", var_id.identifier.numeric); - + } } -int ua_get_server_info(UA_Client *client) +void ua_read_time(UA_Client* client) { - ua_browser_objects(client); - - /* Same thing, this time using the node iterator... */ - ua_browser_nodes(client); - -#ifdef UA_ENABLE_SUBSCRIPTIONS - UA_Int32 subId = ua_start_sub(client); -#endif - - ua_read_attr(client); - -#ifdef UA_ENABLE_SUBSCRIPTIONS - /* Take another look at the.answer */ - UA_Client_run_iterate(client, 10000); - /* Delete the subscription */ - if(UA_Client_Subscriptions_deleteSingle(client, subId) == UA_STATUSCODE_GOOD) - ua_print("Subscription removed\n"); -#endif - -#ifdef UA_ENABLE_METHODCALLS - ua_call_remote(client); -#endif - -#ifdef UA_ENABLE_NODEMANAGEMENT - ua_add_nodes(client); -#endif - - return EXIT_SUCCESS; -} - -void ua_read_time(UA_Client *client) -{ - /* Read the value attribute of the node. UA_Client_readValueAttribute is a - * wrapper for the raw read service available as UA_Client_Service_read. */ - UA_Variant value; /* Variants can hold scalar values and arrays of any type */ + UA_Variant value; UA_Variant_init(&value); - /* NodeId of the variable holding the current time */ const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME); - UA_StatusCode retval = UA_Client_readValueAttribute(client, nodeId, &value); + UA_StatusCode ret = UA_Client_readValueAttribute(client, nodeId, &value); - if(retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) + if(ret == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) { - UA_DateTime raw_date = *(UA_DateTime *) value.data; + UA_DateTime raw_date = *(UA_DateTime*) value.data; UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date); - UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "date is: %u-%u-%u %u:%u:%u.%03u\n", - dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec); + ua_pr_info("date is: %d-%d-%d %d:%d:%d.%03d\n", + dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec); } + /* Clean up */ UA_Variant_clear(&value); } diff --git a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_test.c b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_test.c index 60da43487..055f9c5e1 100755 --- a/APP_Framework/Framework/control/plc/interoperability/opcua/ua_test.c +++ b/APP_Framework/Framework/control/plc/interoperability/opcua/ua_test.c @@ -10,6 +10,75 @@ * See the Mulan PSL v2 for more details. */ +/** + * @file ua_test.c + * @brief Test for OpcUa function + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021.11.11 + */ + +#include +#include "open62541.h" +#include "ua_api.h" + +//for target NODEID +#define UA_TEST_BROWSER_NODEID UA_NODEID_STRING(3, "ServerInterfaces") +#define UA_TEST_BROWSER_NODEID1 UA_NODEID_NUMERIC(4, 1) +#define UA_TEST_WRITE_NODEID UA_NODEID_NUMERIC(4, 5) + + +static UA_StatusCode ua_test_read_array(UA_Client *client) +{ + const int item_size = 4; + UA_ReadValueId test_item[item_size]; + + for (int i = 0; i < item_size; i++) + { + UA_ReadValueId_init(&test_item[i]); + test_item[i].attributeId = UA_ATTRIBUTEID_VALUE; + } + + test_item[0].nodeId = UA_NODEID_NUMERIC(4, 2); + test_item[1].nodeId = UA_NODEID_NUMERIC(4, 3); + test_item[2].nodeId = UA_NODEID_NUMERIC(4, 4); + test_item[3].nodeId = UA_NODEID_NUMERIC(4, 5); + + return ua_read_array_value(client, item_size, test_item); +} + +void ua_test_browser_objects(UA_Client *client) +{ + UA_NodeId test_id; + ua_browser_id(client, UA_TEST_BROWSER_NODEID); + ua_browser_id(client, UA_TEST_BROWSER_NODEID1); + test_id = UA_TEST_BROWSER_NODEID1; + ua_pr_info("Show values in %s:\n", ua_get_nodeid_str(&test_id)); + ua_test_read_array(client); + return; +} + +void ua_test_write_attr(UA_Client *client) +{ + UA_Int32 value; + char val_str[UA_NODE_LEN]; + UA_NodeId id = UA_TEST_WRITE_NODEID; + + ua_pr_info("--- Test write %s ---\n", ua_get_nodeid_str(&id)); + ua_read_nodeid_value(client, id, &value); + ua_write_nodeid_value(client, id, itoa(value + 1, val_str, 10)); + ua_read_nodeid_value(client, id, &value); + ua_pr_info("\n"); +} + +int ua_test_interact_server(UA_Client *client) +{ + ua_read_time(client); + ua_test_browser_objects(client); + ua_test_write_attr(client); + return EXIT_SUCCESS; +} + int16 ua_test(void) { UA_Client *client = UA_Client_new(); @@ -20,7 +89,6 @@ int16 ua_test(void) } ua_read_time(client); - ua_run_test(client); /* Clean up */ UA_Client_disconnect(client); diff --git a/APP_Framework/Framework/control/plc/shared/Makefile b/APP_Framework/Framework/control/plc/shared/Makefile index 1dd297b03..e72134886 100755 --- a/APP_Framework/Framework/control/plc/shared/Makefile +++ b/APP_Framework/Framework/control/plc/shared/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := plc_dev.c plc_bus.c plc_drv.c +SRC_FILES := plc_dev.c plc_ch.c plc_drv.c channel.c include $(KERNEL_ROOT)/compiler.mk diff --git a/APP_Framework/Framework/control/plc/shared/channel.c b/APP_Framework/Framework/control/plc/shared/channel.c new file mode 100755 index 000000000..22b76fbfb --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/channel.c @@ -0,0 +1,433 @@ +/* +* Copyright (c) 2020 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 plc_ch.c +* @brief Support channel driver framework provide ch API version 1.0 +* @author AIIT XUOS Lab +* @date 2021-04-24 +*/ + +#include "string.h" +#include "channel.h" +#include "transform.h" + +DoublelistType ch_linklist; + +/*Create the ch linklist*/ +static void ChannelLinkInit(struct Channel *ch) +{ + static uint8 ch_link_flag = RET_FALSE; + + if(!ch_link_flag) { + AppInitDoubleList(&ch_linklist); + ch_link_flag = RET_TRUE; + ch->ch_link_flag = RET_TRUE; + } + + /*Create the driver of the ch linklist*/ + if(!ch->ch_drvlink_flag) { + AppInitDoubleList(&ch->ch_drvlink); + ch->ch_drvlink_flag = RET_TRUE; + } + + /*Create the hardware device of the ch linklist*/ + if(!ch->ch_devlink_flag) { + AppInitDoubleList(&ch->ch_devlink); + ch->ch_devlink_flag = RET_TRUE; + } +} + +static int ChannelMatchDrvDev(struct ChDrv *driver, struct ChDev *device) +{ + CHECK_CH_PARAM(driver); + CHECK_CH_PARAM(device); + + if(!strncmp(driver->owner_ch->ch_name, device->owner_ch->ch_name, NAME_NUM_MAX)) { + KPrintf("ChannelMatchDrvDev match successfully, ch name %s\n", driver->owner_ch->ch_name); + + driver->private_data = device->private_data;//driver get the device param + device->owner_ch->owner_driver = driver; + driver->owner_ch->owner_haldev = device; + + return EOK; + } + + return ERROR; +} + +/** +* @Description: support to obtain ch for a certain dev if necessary, then configure and init its drv +* @param ch - ch pointer +* @param dev - dev pointer +* @param drv_name - drv name +* @param config - ChConfigInfo pointer +* @return successful:EOK,failed:ERROR +*/ +int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *cfg) +{ + CHECK_CH_PARAM(ch); + CHECK_CH_PARAM(dev); + + int32 ret = EOK; + + ret = PrivMutexObtain(&ch->ch_lock); + if(EOK != ret) { + KPrintf("DevObtainChannel ch_lock error %d!\n", ret); + return ret; + } + + if(ch->owner_haldev != dev) { + struct ChDrv *drv = ChannelFindDriver(ch, drv_name); + + cfg->configure_cmd = OPE_CFG; + drv->configure(drv, cfg); + + cfg->configure_cmd = OPE_INT; + drv->configure(drv, cfg); + + ch->owner_haldev = dev; + } + + return ret; +} + +/** +* @Description: support to register ch pointer with linklist +* @param ch - ch pointer +* @return successful:EOK,failed:NONE +*/ +int ChannelRegister(struct Channel *ch) +{ + int ret = EOK; + CHECK_CH_PARAM(ch); + + ch->match = ChannelMatchDrvDev; + + ChannelLinkInit(ch); + + PrivMutexCreate(&ch->ch_lock, NULL); + + AppDoubleListInsertNodeAfter(&ch_linklist, &(ch->ch_link)); + + return ret; +} + +/** +* @Description: support to release ch pointer in linklist +* @param ch - ch pointer +* @return successful:EOK,failed:NONE +*/ +int ChannelRelease(struct Channel *ch) +{ + CHECK_CH_PARAM(ch); + + PrivMutexAbandon(&ch->ch_lock); + + ch->ch_cnt = 0; + ch->driver_cnt = 0; + ch->haldev_cnt = 0; + + ch->ch_link_flag = RET_FALSE; + ch->ch_drvlink_flag = RET_FALSE; + ch->ch_devlink_flag = RET_FALSE; + + return EOK; +} + +/** +* @Description: support to unregister ch pointer and delete its linklist node +* @param ch - ch pointer +* @return successful:EOK,failed:NONE +*/ +int ChannelUnregister(struct Channel *ch) +{ + CHECK_CH_PARAM(ch); + + ch->ch_cnt--; + + AppDoubleListRmNode(&(ch->ch_link)); + + return EOK; +} + +/** +* @Description: support to register driver pointer to ch pointer +* @param ch - ch pointer +* @param driver - driver pointer +* @return successful:EOK,failed:NONE +*/ +int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver) +{ + CHECK_CH_PARAM(ch); + CHECK_CH_PARAM(driver); + + driver->owner_ch = ch; + ch->driver_cnt++; + + AppDoubleListInsertNodeAfter(&ch->ch_drvlink, &(driver->driver_link)); + + return EOK; +} + +/** +* @Description: support to register dev pointer to ch pointer +* @param ch - ch pointer +* @param device - device pointer +* @return successful:EOK,failed:NONE +*/ +int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device) +{ + CHECK_CH_PARAM(ch); + CHECK_CH_PARAM(device); + + device->owner_ch = ch; + ch->haldev_cnt++; + + AppDoubleListInsertNodeAfter(&ch->ch_devlink, &(device->dev_link)); + + return EOK; +} + +/** +* @Description: support to delete driver pointer from ch pointer +* @param ch - ch pointer +* @param driver - driver pointer +* @return successful:EOK,failed:NONE +*/ +int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver) +{ + CHECK_CH_PARAM(ch); + CHECK_CH_PARAM(driver); + + ch->driver_cnt--; + + AppDoubleListRmNode(&(driver->driver_link)); + + free(driver); + + return EOK; +} + +/** +* @Description: support to delete dev pointer from ch pointer +* @param ch - ch pointer +* @param device - device pointer +* @return successful:EOK,failed:NONE +*/ +int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device) +{ + CHECK_CH_PARAM(ch); + CHECK_CH_PARAM(device); + + ch->haldev_cnt--; + + AppDoubleListRmNode(&(device->dev_link)); + + free(device); + + return EOK; +} + +/** +* @Description: support to find ch pointer by ch name +* @param ch_name - ch name +* @return successful:ch pointer,failed:NONE +*/ +ChannelType ChannelFind(const char *ch_name) +{ + struct Channel *ch = NONE; + + DoublelistType *node = NONE; + DoublelistType *head = &ch_linklist; + + for (node = head->node_next; node != head; node = node->node_next) + { + ch = DOUBLE_LIST_ENTRY(node, struct Channel, ch_link); + if(!strcmp(ch->ch_name, ch_name)) { + return ch; + } + } + + KPrintf("ChannelFind cannot find the %s ch.return NULL\n", ch_name); + return NONE; +} + +/** +* @Description: support to find driver pointer of certain ch by driver name +* @param ch - ch pointer +* @param driver_name - driver name +* @return successful:EOK,failed:NONE +*/ +ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name) +{ + CHECK_CH_PARAM(ch); + struct ChDrv *driver = NONE; + + DoublelistType *node = NONE; + DoublelistType *head = &ch->ch_drvlink; + + for (node = head->node_next; node != head; node = node->node_next) + { + driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link); + if(!strcmp(driver->drv_name, driver_name)) { + return driver; + } + } + + KPrintf("ChannelFindDriver cannot find the %s driver.return NULL\n", driver_name); + return NONE; +} + +/** +* @Description: support to find device pointer of certain ch by device name +* @param ch - ch pointer +* @param device_name - device name +* @return successful:EOK,failed:NONE +*/ +ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name) +{ + CHECK_CH_PARAM(ch); + struct ChDev *device = NONE; + + DoublelistType *node = NONE; + DoublelistType *head = &ch->ch_devlink; + + for (node = head->node_next; node != head; node = node->node_next) + { + device = DOUBLE_LIST_ENTRY(node, struct ChDev, dev_link); + + if(!strcmp(device->dev_name, device_name)) { + return device; + } + } + + KPrintf("ChannelFindDevice cannot find the %s device.return NULL\n", device_name); + return NONE; +} + +/** +* @Description: support to set dev receive function callback +* @param dev - dev pointer +* @param dev_recv_callback - callback function +* @return successful:EOK,failed:ERROR +*/ +uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length)) +{ + CHECK_CH_PARAM(dev ); + + dev->dev_recv_callback = dev_recv_callback; + + return EOK; +} + +/** +* @Description: support to open dev +* @param dev - dev pointer +* @return successful:EOK,failed:ERROR +*/ +uint32 ChannelDevOpen(struct ChDev *dev) +{ + CHECK_CH_PARAM(dev); + + int ret = EOK; + + if (dev->dev_done->open) { + ret = dev->dev_done->open(dev); + if(ret) { + KPrintf("ChannelDevOpen error ret %u\n", ret); + return ERROR; + } + } + + return ret; +} + +/** +* @Description: support to close dev +* @param dev - dev pointer +* @return successful:EOK,failed:ERROR +*/ +uint32 ChannelDevClose(struct ChDev *dev) +{ + CHECK_CH_PARAM(dev); + + int ret = EOK; + + if (dev->dev_done->close) { + ret = dev->dev_done->close(dev); + if(ret) { + KPrintf("ChannelDevClose error ret %u\n", ret); + return ERROR; + } + } + + return ret; +} + +/** +* @Description: support to write data to dev +* @param dev - dev pointer +* @param write_param - ChWriteParam +* @return successful:EOK,failed:NONE +*/ +uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param) +{ + CHECK_CH_PARAM(dev); + + if (dev->dev_done->write) { + return dev->dev_done->write(dev, write_param); + } + + return EOK; +} + +/** +* @Description: support to read data from dev +* @param dev - dev pointer +* @param read_param - ChReadParam +* @return successful:EOK,failed:NONE +*/ +uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param) +{ + CHECK_CH_PARAM(dev); + + if (dev->dev_done->read) { + return dev->dev_done->read(dev, read_param); + } + + return EOK; +} + +/** +* @Description: support to configure drv, include OPE_CFG and OPE_INT +* @param drv - drv pointer +* @param config - ChConfigInfo +* @return successful:EOK,failed:NONE +*/ +uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config) +{ + CHECK_CH_PARAM(drv); + CHECK_CH_PARAM(config); + + int ret = EOK; + + if (drv->configure) { + ret = drv->configure(drv, config); + if(ret) { + KPrintf("ChannelDrvCfg error, ret %u\n", ret); + return ERROR; + } + } + + return ret; +} diff --git a/APP_Framework/Framework/control/plc/shared/channel.h b/APP_Framework/Framework/control/plc/shared/channel.h new file mode 100755 index 000000000..c87134d03 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/channel.h @@ -0,0 +1,247 @@ +/* +* 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 channel.h +* @brief define ch driver framework function and common API +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-03-01 +*/ + +#ifndef __CHANNEL_H_ +#define __CHANNEL_H_ + +#include "list.h" + +#define x_OffPos uint32 +#define x_size_t size_t + +#ifdef __cplusplus +extern "C" { +#endif + +#define OPE_INT 0x0000 +#define OPE_CFG 0x0001 + +#define OPER_WDT_SET_TIMEOUT 0x0002 +#define OPER_WDT_KEEPALIVE 0x0003 + +#define CHECK_CH_PARAM(param) \ +do \ +{ \ + if(param == NONE) { \ + KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \ + while(RET_TRUE); \ + } \ +}while (0) + +typedef struct Channel *ChannelType; +typedef struct ChDev *ChDevType; +typedef struct ChDrv *ChDrvType; + +/* need to add new ch type in ../tool/shell/letter-shell/cmd.c, ensure ShowBus cmd supported*/ +enum ChType_e +{ + CH_PLC_TYPE, + CH_END_TYPE, +}; + +enum ChState_e +{ + CHANNEL_INIT = 0, + CHANNEL_INSTALL, + CHANNEL_UNINSTALL, +}; + +enum ChDevType_e +{ + CHDEV_PLC_TYPE, + CHDEV_END_TYPE, +}; + +enum ChDevState_e +{ + CHDEV_INIT = 0, + CHDEV_INSTALL, + CHDEV_UNINSTALL, +}; + +enum ChDrvType_e +{ + CHDRV_PLC_TYPE, + CHDRV_END_TYPE, +}; + +enum ChDrvState_e +{ + CHDRV_INIT = 0, + CHDRV_INSTALL, + CHDRV_UNINSTALL, +}; + +struct ChConfigInfo +{ + int configure_cmd; + void *private_data; +}; + +struct ChReadParam +{ + x_OffPos pos; + void* buffer; + x_size_t size; + x_size_t read_length; +}; + +struct ChWriteParam +{ + x_OffPos pos; + const void* buffer; + x_size_t size; +}; + +//struct ChHalDevBlockParam +//{ +// uint32 cmd; +////tst by wly +//// struct DeviceBlockArrange dev_block; +//// struct DeviceBlockAddr *dev_addr; +//}; + +struct ChHalDevDone +{ + uint32 (*open) (void *dev); + uint32 (*close) (void *dev); + uint32 (*write) (void *dev, struct ChWriteParam *write_param); + uint32 (*read) (void *dev, struct ChReadParam *read_param); +}; + +struct ChDev +{ + int8 dev_name[NAME_NUM_MAX]; + enum ChDevType_e dev_type; + enum ChDevState_e dev_state; + + const struct ChHalDevDone *dev_done; + + int (*dev_recv_callback) (void *dev, x_size_t length); +// int (*dev_block_control) (struct ChDev *dev, struct ChHalDevBlockParam *block_param); + + struct Channel *owner_ch; + void *private_data; + + int32 dev_sem; + + DoublelistType dev_link; +}; + +struct ChDrv +{ + int8 drv_name[NAME_NUM_MAX]; + enum ChDrvType_e driver_type; + enum ChDrvState_e driver_state; + + uint32 (*configure)(void *drv, struct ChConfigInfo *config); + + struct Channel *owner_ch; + void *private_data; + + DoublelistType driver_link; +}; + +struct Channel +{ + int8 ch_name[NAME_NUM_MAX]; + enum ChType_e ch_type; + enum ChState_e ch_state; + + int32 (*match)(struct ChDrv *driver, struct ChDev *device); + + int ch_lock; + + struct ChDev *owner_haldev; + struct ChDrv *owner_driver; + + void *private_data; + + /*manage the drv of the channel*/ + uint8 driver_cnt; + uint8 ch_drvlink_flag; + DoublelistType ch_drvlink; + + /*manage the dev of the channel*/ + uint8 haldev_cnt; + uint8 ch_devlink_flag; + DoublelistType ch_devlink; + + uint8 ch_cnt; + uint8 ch_link_flag; + DoublelistType ch_link; +}; + +/*Register the BUS,manage with the double linklist*/ +int ChannelRegister(struct Channel *ch); + +/*Release the BUS framework*/ +int ChannelRelease(struct Channel *ch); + +/*Unregister a certain kind of BUS*/ +int ChannelUnregister(struct Channel *ch); + +/*Register the driver to the channel*/ +int DriverRegisterToChannel(struct Channel *ch, struct ChDrv *driver); + +/*Register the device to the channel*/ +int DeviceRegisterToChannel(struct Channel *ch, struct ChDev *device); + +/*Delete the driver from the channel*/ +int DriverDeleteFromChannel(struct Channel *ch, struct ChDrv *driver); + +/*Delete the device from the channel*/ +int DeviceDeleteFromChannel(struct Channel *ch, struct ChDev *device); + +/*Find the ch with ch name*/ +ChannelType ChannelFind(const char *ch_name); + +/*Find the driver of cetain channel*/ +ChDrvType ChannelFindDriver(struct Channel *ch, const char *driver_name); + +/*Find the device of certain channel*/ +ChDevType ChannelFindDevice(struct Channel *ch, const char *device_name); + +/*Dev receive data callback function*/ +uint32 ChannelDevRecvCallback(struct ChDev *dev, int (*dev_recv_callback) (void *dev, x_size_t length)); + +/*Open the device of the channel*/ +uint32 ChannelDevOpen(struct ChDev *dev); + +/*Close the device of the channel*/ +uint32 ChannelDevClose(struct ChDev *dev); + +/*Write data to the device*/ +uint32 ChannelDevWriteData(struct ChDev *dev, struct ChWriteParam *write_param); + +/*Read data from the device*/ +uint32 ChannelDevReadData(struct ChDev *dev, struct ChReadParam *read_param); + +/*Configure the driver of the channel*/ +uint32 ChannelDrvConfigure(struct ChDrv *drv, struct ChConfigInfo *config); + +/*Obtain the ch using a certain dev*/ +int DeviceObtainChannel(struct Channel *ch, struct ChDev *dev, const char *drv_name, struct ChConfigInfo *config); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.c b/APP_Framework/Framework/control/plc/shared/plc_bus.c deleted file mode 100755 index 4eb5a3613..000000000 --- a/APP_Framework/Framework/control/plc/shared/plc_bus.c +++ /dev/null @@ -1,119 +0,0 @@ -/* -* Copyright (c) 2020 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 bus_plc.c -* @brief register plc bus function using bus driver framework -* @version 1.0 -* @author AIIT XUOS Lab -* @date 2022-01-24 -*/ - -#include "plc_bus.h" -#include "plc_dev.h" - -/******************************************************************************/ - -int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name) -{ - NULL_PARAM_CHECK(plc_bus); - NULL_PARAM_CHECK(bus_name); - - x_err_t ret = EOK; - - if (BUS_INSTALL != plc_bus->bus.bus_state) { - strncpy(plc_bus->bus.bus_name, bus_name, NAME_NUM_MAX); - plc_bus->bus.bus_type = TYPE_PLC_BUS; - plc_bus->bus.bus_state = BUS_INSTALL; - plc_bus->bus.private_data = plc_bus->private_data; - - ret = BusRegister(&plc_bus->bus); - if (EOK != ret) { - KPrintf("PlcBusInit BusRegister error %u\n", ret); - return ret; - } - } else { - KPrintf("PlcBusInit BusRegister bus has been register state%u\n", plc_bus->bus.bus_state); - } - - return ret; -} - -int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name) -{ - NULL_PARAM_CHECK(plc_driver); - NULL_PARAM_CHECK(driver_name); - - x_err_t ret = EOK; - - if (DRV_INSTALL != plc_driver->driver.driver_state) { - plc_driver->driver.driver_type = TYPE_PLC_DRV; - plc_driver->driver.driver_state = DRV_INSTALL; - - strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX); - - plc_driver->driver.configure = plc_driver->configure; - - ret = PlcDriverRegister(&plc_driver->driver); - if (EOK != ret) { - KPrintf("PlcDriverInit DriverRegister error %u\n", ret); - return ret; - } - } else { - KPrintf("PlcDriverInit DriverRegister driver has been register state%u\n", plc_driver->driver.driver_state); - } - - return ret; -} - -int PlcReleaseBus(struct PlcBus *plc_bus) -{ - NULL_PARAM_CHECK(plc_bus); - - return BusRelease(&plc_bus->bus); -} - -int PlcDriverAttachToBus(const char *drv_name, const char *bus_name) -{ - NULL_PARAM_CHECK(drv_name); - NULL_PARAM_CHECK(bus_name); - - x_err_t ret = EOK; - - struct Bus *bus; - struct Driver *driver; - - bus = BusFind(bus_name); - if (NONE == bus) { - KPrintf("PlcDriverAttachToBus find plc bus error!name %s\n", bus_name); - return ERROR; - } - - if (TYPE_PLC_BUS == bus->bus_type) { - driver = PlcDriverFind(drv_name, TYPE_PLC_DRV); - if (NONE == driver) { - KPrintf("PlcDriverAttachToBus find plc driver error!name %s\n", drv_name); - return ERROR; - } - - - if (TYPE_PLC_DRV == driver->driver_type) { - ret = DriverRegisterToBus(bus, driver); - if (EOK != ret) { - KPrintf("PlcDriverAttachToBus DriverRegisterToBus error %u\n", ret); - return ERROR; - } - } - } - - return ret; -} diff --git a/APP_Framework/Framework/control/plc/shared/plc_ch.c b/APP_Framework/Framework/control/plc/shared/plc_ch.c new file mode 100755 index 000000000..f2b83abd5 --- /dev/null +++ b/APP_Framework/Framework/control/plc/shared/plc_ch.c @@ -0,0 +1,129 @@ +/* +* 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 plc_ch.c +* @brief register plc channel function using channel driver framework +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-01-24 +*/ + +#include "string.h" +#include "plc_ch.h" +#include "plc_dev.h" + +/******************************************************************************/ + +int PlcChannelInit(struct PlcChannel* plc_ch, const char* ch_name) +{ + CHECK_CH_PARAM(plc_ch); + CHECK_CH_PARAM(ch_name); + int ret = EOK; + + if(CHANNEL_INSTALL != plc_ch->ch.ch_state) + { + strncpy(plc_ch->ch.ch_name, ch_name, NAME_NUM_MAX); + plc_ch->ch.ch_type = CH_PLC_TYPE; + plc_ch->ch.ch_state = CHANNEL_INSTALL; + plc_ch->ch.private_data = plc_ch->private_data; + ret = ChannelRegister(&plc_ch->ch); + + if(EOK != ret) + { + KPrintf("PlcChannelInit ChannelRegister error %u\n", ret); + return ret; + } + } + else + { + KPrintf("PlcChannelInit ChannelRegister channel has been register state %u\n", + plc_ch->ch.ch_state); + } + + return ret; +} + +int PlcDriverInit(struct PlcDriver* plc_driver, const char* driver_name) +{ + CHECK_CH_PARAM(plc_driver); + CHECK_CH_PARAM(driver_name); + int ret = EOK; + + if(CHDRV_INSTALL != plc_driver->driver.driver_state) + { + plc_driver->driver.driver_type = CHDRV_PLC_TYPE; + plc_driver->driver.driver_state = CHDRV_INSTALL; + strncpy(plc_driver->driver.drv_name, driver_name, NAME_NUM_MAX); + plc_driver->driver.configure = plc_driver->configure; + ret = PlcDriverRegister(&plc_driver->driver); + + if(EOK != ret) + { + KPrintf("PlcDriverInit DriverRegister error %u\n", ret); + return ret; + } + } + else + { + KPrintf("PlcDriverInit Driver %s has been register state %u\n", + driver_name, plc_driver->driver.driver_state); + } + + return ret; +} + +int PlcReleaseChannel(struct PlcChannel* plc_ch) +{ + CHECK_CH_PARAM(plc_ch); + return ChannelRelease(&plc_ch->ch); +} + +int PlcDriverAttachToChannel(const char* drv_name, const char* ch_name) +{ + CHECK_CH_PARAM(drv_name); + CHECK_CH_PARAM(ch_name); + int ret = EOK; + struct Channel* ch; + struct ChDrv* driver; + ch = ChannelFind(ch_name); + + if(NONE == ch) + { + KPrintf("PlcDriverAttachToChannel find plc channel error!name %s\n", ch_name); + return ERROR; + } + + if(CH_PLC_TYPE == ch->ch_type) + { + driver = PlcDriverFind(drv_name, CHDRV_PLC_TYPE); + + if(NONE == driver) + { + KPrintf("PlcDriverAttachToChannel find plc driver error!name %s\n", drv_name); + return ERROR; + } + + if(CHDRV_PLC_TYPE == driver->driver_type) + { + ret = DriverRegisterToChannel(ch, driver); + + if(EOK != ret) + { + KPrintf("PlcDriverAttachToChannel DriverRegisterToBus error %u\n", ret); + return ERROR; + } + } + } + + return ret; +} diff --git a/APP_Framework/Framework/control/plc/shared/plc_bus.h b/APP_Framework/Framework/control/plc/shared/plc_ch.h similarity index 67% rename from APP_Framework/Framework/control/plc/shared/plc_bus.h rename to APP_Framework/Framework/control/plc/shared/plc_ch.h index 0894a6caf..f32817138 100755 --- a/APP_Framework/Framework/control/plc/shared/plc_bus.h +++ b/APP_Framework/Framework/control/plc/shared/plc_ch.h @@ -11,17 +11,17 @@ */ /** -* @file plc_bus.h +* @file plc_ch.h * @brief define plc bus and drv function using bus driver framework * @version 1.0 * @author AIIT XUOS Lab * @date 2022-01-24 */ -#ifndef __PLC_BUS_H_ -#define __PLC_BUS_H_ +#ifndef __PLC_CH_H_ +#define __PLC_CH_H_ -#include "bus.h" +#include "channel.h" #ifdef __cplusplus extern "C" { @@ -29,33 +29,33 @@ extern "C" { struct PlcDriver { - struct Driver driver; - uint32 (*configure) (void *drv, struct BusConfigureInfo *configure_info); + struct ChDrv driver; + uint32 (*configure) (void *drv, struct ChConfigInfo *cfg); }; -struct PlcBus +struct PlcChannel { - struct Bus bus; + struct Channel ch; void *private_data; }; /*Register the plc bus*/ -int PlcBusInit(struct PlcBus *plc_bus, const char *bus_name); +int PlcChannelInit(struct PlcChannel *plc_ch, const char *ch_name); /*Register the plc driver*/ int PlcDriverInit(struct PlcDriver *plc_driver, const char *driver_name); /*Release the plc device*/ -int PlcReleaseBus(struct PlcBus *plc_bus); +int PlcReleaseChannel(struct PlcChannel *plc_ch); /*Register the plc driver to the plc bus*/ -int PlcDriverAttachToBus(const char *drv_name, const char *bus_name); +int PlcDriverAttachToChannel(const char *drv_name, const char *ch_name); /*Register the driver, manage with the double linklist*/ -int PlcDriverRegister(struct Driver *driver); +int PlcDriverRegister(struct ChDrv *driver); /*Find the register driver*/ -DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type); +ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type); #ifdef __cplusplus } diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.c b/APP_Framework/Framework/control/plc/shared/plc_dev.c index 6950e79b6..ed44b5b7b 100755 --- a/APP_Framework/Framework/control/plc/shared/plc_dev.c +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.c @@ -19,22 +19,22 @@ */ #include "ua_api.h" -#include "plc_bus.h" +#include "plc_ch.h" #include "plc_dev.h" -static DoubleLinklistType plcdev_list; +DoublelistType plcdev_list; /******************************************************************************/ /*Create the plc device linklist*/ static void PlcDeviceLinkInit() { - InitDoubleLinkList(&plcdev_list); + AppInitDoubleList(&plcdev_list); } static int PlcDeviceOpen(void *dev) { - NULL_PARAM_CHECK(dev); + CHECK_CH_PARAM(dev); struct PlcDevice *plc_dev = (struct PlcDevice *)dev; @@ -48,7 +48,7 @@ static int PlcDeviceOpen(void *dev) static void PlcDeviceClose(void *dev) { - NULL_PARAM_CHECK(dev); + CHECK_CH_PARAM(dev); struct PlcDevice *plc_dev = (struct PlcDevice *)dev; @@ -60,8 +60,7 @@ static void PlcDeviceClose(void *dev) static int PlcDeviceWrite(void *dev, const void *buf, size_t len) { - NULL_PARAM_CHECK(dev); - NULL_PARAM_CHECK(buf); + CHECK_CH_PARAM(dev); int ret; struct PlcDevice *plc_dev = (struct PlcDevice *)dev; @@ -76,8 +75,8 @@ static int PlcDeviceWrite(void *dev, const void *buf, size_t len) static int PlcDeviceRead(void *dev, void *buf, size_t len) { - NULL_PARAM_CHECK(dev); - NULL_PARAM_CHECK(buf); + CHECK_CH_PARAM(dev); + CHECK_CH_PARAM(buf); int ret; struct PlcDevice *plc_dev = (struct PlcDevice *)dev; @@ -99,18 +98,18 @@ static struct PlcOps plc_done = }; /* find PLC device with device name */ -struct HardwareDev *PlcDevFind(const char *dev_name) +struct ChDev *PlcDevFind(const char *dev_name) { - NULL_PARAM_CHECK(dev_name); + CHECK_CH_PARAM(dev_name); struct PlcDevice *device = NONE; - struct HardwareDev *haldev = NONE; + struct ChDev *haldev = NONE; - DoubleLinklistType *node = NONE; - DoubleLinklistType *head = &plcdev_list; + DoublelistType *node = NONE; + DoublelistType *head = &plcdev_list; for (node = head->node_next; node != head; node = node->node_next) { - device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct PlcDevice, link); + device = DOUBLE_LIST_ENTRY(node, struct PlcDevice, link); if (!strcmp(device->name, dev_name)) { haldev = &device->haldev; return haldev; @@ -123,61 +122,63 @@ struct HardwareDev *PlcDevFind(const char *dev_name) int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name) { - NULL_PARAM_CHECK(plc_device); - NULL_PARAM_CHECK(device_name); + CHECK_CH_PARAM(plc_device); + CHECK_CH_PARAM(device_name); - x_err_t ret = EOK; - static x_bool dev_link_flag = RET_FALSE; + int ret = EOK; + static uint8_t dev_link_flag = 0; if (!dev_link_flag) { PlcDeviceLinkInit(); - dev_link_flag = RET_TRUE; + dev_link_flag = 1; } - if (DEV_INSTALL != plc_device->state) { + if (CHDEV_INSTALL != plc_device->state) { strncpy(plc_device->haldev.dev_name, device_name, NAME_NUM_MAX); - plc_device->haldev.dev_type = TYPE_PLC_DEV; - plc_device->haldev.dev_state = DEV_INSTALL; + plc_device->haldev.dev_type = CHDEV_PLC_TYPE; + plc_device->haldev.dev_state = CHDEV_INSTALL; strncpy(plc_device->name, device_name, strlen(device_name)); plc_device->ops = &plc_done; - DoubleLinkListInsertNodeAfter(&plcdev_list, &(plc_device->link)); - plc_device->state = DEV_INSTALL; + AppDoubleListInsertNodeAfter(&plcdev_list, &(plc_device->link)); + plc_device->state = CHDEV_INSTALL; + } else { - KPrintf("PlcDevRegister device has been register state%u\n", plc_device->type); + KPrintf("PlcDevRegister device %s has been register state%u\n", device_name, plc_device->state); + ret = ERROR; } return ret; } -int PlcDeviceAttachToBus(const char *dev_name, const char *bus_name) +int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name) { - NULL_PARAM_CHECK(dev_name); - NULL_PARAM_CHECK(bus_name); + CHECK_CH_PARAM(dev_name); + CHECK_CH_PARAM(ch_name); - x_err_t ret = EOK; + int ret = EOK; - struct Bus *bus; - struct HardwareDev *device; + struct Channel *ch; + struct ChDev *device; - bus = BusFind(bus_name); - if (NONE == bus) { - KPrintf("PlcDeviceAttachToBus find plc bus error!name %s\n", bus_name); + ch = ChannelFind(ch_name); + if (NONE == ch) { + KPrintf("PlcDeviceAttachToChannel find plc ch error!name %s\n", ch_name); return ERROR; } - if (TYPE_PLC_BUS == bus->bus_type) { + if (CH_PLC_TYPE == ch->ch_type) { device = PlcDevFind(dev_name); if (NONE == device) { - KPrintf("PlcDeviceAttachToBus find plc device error!name %s\n", dev_name); + KPrintf("PlcDeviceAttachToChannel find plc device %s error!\n", dev_name); return ERROR; } - if (TYPE_PLC_DEV == device->dev_type) { - ret = DeviceRegisterToBus(bus, device); + if (CHDEV_PLC_TYPE == device->dev_type) { + ret = DeviceRegisterToChannel(ch, device); if (EOK != ret) { - KPrintf("PlcDeviceAttachToBus DeviceRegisterToBus error %u\n", ret); + KPrintf("PlcDeviceAttachToChannel DeviceRegisterToChannel error %u\n", ret); return ERROR; } } diff --git a/APP_Framework/Framework/control/plc/shared/plc_dev.h b/APP_Framework/Framework/control/plc/shared/plc_dev.h index b0d767805..f17b78f3b 100755 --- a/APP_Framework/Framework/control/plc/shared/plc_dev.h +++ b/APP_Framework/Framework/control/plc/shared/plc_dev.h @@ -21,8 +21,8 @@ #ifndef __PLC_DEV_H_ #define __PLC_DEV_H_ -#include "bus.h" -#include "xs_klist.h" +#include "list.h" +#include "plc_ch.h" #undef open #undef close @@ -33,15 +33,16 @@ #define PLC_NAME_SIZE 32 // PLC device information -struct PlcInfo { +typedef struct PlcInfo { uint32_t ability; // PLC ability uint32_t id; // PLC Device ID uint32_t soft_version; // software version uint32_t hard_version; // hardware version uint32_t date; // manufact date const char *vendor; // vendor - const char *model; // product model -}; + const char *model; // model + const char *product; // product +}PlcInfoType; enum PlcSerialType { PLC_SERIAL_232, @@ -64,13 +65,13 @@ union PlcCfg { struct PlcDevice; // operation API -struct PlcOps { +typedef struct PlcOps { int (*open)(void *dev); // open and connect PLC device void (*close)(void* dev); // close and disconnect PLC device int (*read)(void* dev, void *buf, size_t len); // read data from PLC int (*write)(void* dev, const void *buf, size_t len); // write data from PLC int (*ioctl)(void* dev, int cmd, void *arg); // send control command to PLC -}; +}PlcOpsType; enum PlcCtlType { PLC_CTRL_TYPE_HSC, @@ -78,12 +79,10 @@ enum PlcCtlType { PLC_CTRL_TYPE_PHASING }; - #define PLC_ABILITY_HSC ((uint32_t)(1 << PLC_CTRL_TYPE_HSC)) #define PLC_ABILITY_PID ((uint32_t)(1 << PLC_CTRL_TYPE_PID)) #define PLC_ABILITY_PHASING ((uint32_t)(1 << PLC_CTRL_TYPE_PHASING)) - enum PlcIndHybridNet { // PLC Field Bus @@ -112,18 +111,19 @@ enum PlcTransType }; //communication interface -struct PlcInterface +typedef struct PlcInterface { char ip_addr[IP_ADDR_SIZE]; char attrib; -}; +}PlcInterfaceType; // identify PLC device -struct PlcDevice { - struct HardwareDev haldev; /* hardware device driver for bus */ +typedef struct PlcDevice { + struct ChDev haldev; /* hardware device driver for channel */ + enum ChDevState_e state; + char name[PLC_NAME_SIZE]; /* name of the device */ enum PlcCtlType type; /* PLC Control Type */ - enum DevState state; enum PlcIndHybridNet net; enum PlcTransType trans; @@ -133,16 +133,20 @@ struct PlcDevice { struct PlcInterface interface; /* protocols used for transferring data from program to plc */ void *priv_data; /* private data for different PLC*/ - DoubleLinklistType link;/* link list node */ -}; + DoublelistType link;/* link list node */ +}PlcDeviceType; +typedef struct PlcCtrlParam { + void *node_id; // for node ID + int value; +}PlcCtrlParamType; #define plc_print KPrintf /******************************************************************************/ int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name); -int PlcDeviceAttachToBus(const char *dev_name, const char *bus_name); +int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name); /******************************************************************************/ diff --git a/APP_Framework/Framework/control/plc/shared/plc_drv.c b/APP_Framework/Framework/control/plc/shared/plc_drv.c index 129ba1b61..f58d3afb5 100755 --- a/APP_Framework/Framework/control/plc/shared/plc_drv.c +++ b/APP_Framework/Framework/control/plc/shared/plc_drv.c @@ -19,30 +19,30 @@ */ #include "transform.h" -#include "plc_bus.h" +#include "plc_ch.h" #include "plc_dev.h" -static DoubleLinklistType plcdrv_linklist; +static DoublelistType plcdrv_linklist; /******************************************************************************/ /*Create the driver linklist*/ static void PlcDrvLinkInit() { - InitDoubleLinkList(&plcdrv_linklist); + AppInitDoubleList(&plcdrv_linklist); } -DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type) +ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type) { - NULL_PARAM_CHECK(drv_name); + CHECK_CH_PARAM(drv_name); - struct Driver *driver = NONE; + struct ChDrv *driver = NONE; - DoubleLinklistType *node = NONE; - DoubleLinklistType *head = &plcdrv_linklist; + DoublelistType *node = NONE; + DoublelistType *head = &plcdrv_linklist; for (node = head->node_next; node != head; node = node->node_next) { - driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link); + driver = DOUBLE_LIST_ENTRY(node, struct ChDrv, driver_link); if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) { return driver; } @@ -52,19 +52,19 @@ DriverType PlcDriverFind(const char *drv_name, enum DriverType_e drv_type) return NONE; } -int PlcDriverRegister(struct Driver *driver) +int PlcDriverRegister(struct ChDrv *driver) { - NULL_PARAM_CHECK(driver); + CHECK_CH_PARAM(driver); - x_err_t ret = EOK; - static x_bool driver_link_flag = RET_FALSE; + int ret = EOK; + static uint8_t driver_link_flag = 0; if (!driver_link_flag) { PlcDrvLinkInit(); - driver_link_flag = RET_TRUE; + driver_link_flag = 1; } - DoubleLinkListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link)); + AppDoubleListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link)); return ret; } diff --git a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c index ce118fbd5..b6a35f2f0 100755 --- a/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c +++ b/Ubiquitous/XiUOS/board/ok1052-c/third_party_driver/i2c/connect_i2c.c @@ -1,14 +1,12 @@ /* -* 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. -*/ + * Copyright (c) 2020 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-04-25 weety first version + */ /** * @file connect_i2c.c