forked from xuos/xiuos
modify XiUOS DIR : (1.add plc_demo in APP_Framework/control_app; 2.add industrial_network、industrial_fieldbus and industrial_wlan; 3.add XiZi_AIoT and modify XiZi as XiZi_IIoT.)
This commit is contained in:
@@ -4,5 +4,6 @@ menuconfig SUPPORT_CONTROL_FRAMEWORK
|
||||
select TRANSFORM_LAYER_ATTRIUBUTE
|
||||
|
||||
if SUPPORT_CONTROL_FRAMEWORK
|
||||
source "$APP_DIR/Framework/control/plc/interoperability/Kconfig"
|
||||
source "$APP_DIR/Framework/control/ipc_protocol/Kconfig"
|
||||
source "$APP_DIR/Framework/control/plc_protocol/Kconfig"
|
||||
endif
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
SRC_DIR := shared plc
|
||||
SRC_DIR := ipc_protocol plc_protocol shared
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
2
APP_Framework/Framework/control/ipc_protocol/Kconfig
Executable file
2
APP_Framework/Framework/control/ipc_protocol/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SRC_DIR := shared interoperability
|
||||
SRC_DIR := modbus_tcp modbus_uart
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
2
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/Kconfig
Executable file
2
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SRC_FILES := plc_socket.c
|
||||
SRC_FILES := modbus_tcp.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
20
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c
Executable file
20
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.c
Executable file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.c
|
||||
* @brief support modbus_tcp function
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.09.27
|
||||
*/
|
||||
|
||||
26
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h
Executable file
26
APP_Framework/Framework/control/ipc_protocol/modbus_tcp/modbus_tcp.h
Executable file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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
|
||||
2
APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig
Executable file
2
APP_Framework/Framework/control/ipc_protocol/modbus_uart/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
4
APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile
Executable file
4
APP_Framework/Framework/control/ipc_protocol/modbus_uart/Makefile
Executable file
@@ -0,0 +1,4 @@
|
||||
SRC_FILES :=
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
menuconfig USING_CONTROL_PLC_OPCUA
|
||||
bool "PLC support OPCUA"
|
||||
default y
|
||||
depends on RESOURCES_LWIP
|
||||
|
||||
menuconfig USING_CONTROL_PLC_SOCKET
|
||||
bool "PLC support SOCKET"
|
||||
default y
|
||||
depends on RESOURCES_LWIP
|
||||
@@ -1,17 +0,0 @@
|
||||
SRC_DIR :=
|
||||
|
||||
ifeq ($(CONFIG_RESOURCES_LWIP),y)
|
||||
|
||||
ifeq ($(CONFIG_USING_CONTROL_PLC_OPCUA), y)
|
||||
SRC_DIR += opcua
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USING_CONTROL_PLC_SOCKET), y)
|
||||
SRC_DIR += socket
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
SRC_FILES += interoperability.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
menuconfig USING_CONTROL_PLC_OPCUA
|
||||
bool "PLC support OPCUA"
|
||||
default y
|
||||
depends on RESOURCES_LWIP
|
||||
|
||||
menuconfig USING_CONTROL_PLC_SOCKET
|
||||
bool "PLC support SOCKET"
|
||||
default y
|
||||
depends on RESOURCES_LWIP
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# PLC SOCKET README
|
||||
|
||||
## 文件说明
|
||||
|
||||
用于测试PLC socket通信. 通过建立与制定IP的PLC设备的socket连接, 发送命令给PLC设备, 实现相关功能. 实现该功能需要开启LWIP, 同时需要扩大shell的栈大小和内存空间。
|
||||
|
||||
### 命令行
|
||||
|
||||
PLCSocket ip=[PLC IP] port=[PLC port] tcp=[1: TCP; 0: UDP] cmd=[相关命令] file=[制定配置文件]
|
||||
|
||||
配置文件支持json格式, 默认文件名为socket_param.json, 放置于plc目录下, 文件内容如下:
|
||||
|
||||
{
|
||||
"ip": "192.168.250.6",
|
||||
"port": 102,
|
||||
"tcp": 1,
|
||||
"cmd": [x, x, x]
|
||||
}
|
||||
@@ -1,360 +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 plc_socket.c
|
||||
* @brief Demo for PLC socket communication function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.03.16
|
||||
*/
|
||||
|
||||
#include "transform.h"
|
||||
#include "plc_socket.h"
|
||||
#include "sys_arch.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "control_file.h"
|
||||
|
||||
// max support plc socket test commands number
|
||||
#define PLC_SOCK_CMD_NUM CTL_CMD_NUM
|
||||
#define PLC_SOCK_TIMEOUT 50000
|
||||
|
||||
// for saving PLC command index
|
||||
int plc_cmd_index = 0;
|
||||
|
||||
// only for test
|
||||
#define SUPPORT_PLC_SIEMENS
|
||||
|
||||
//siemens test
|
||||
PlcBinCmdType TestPlcCmd[PLC_SOCK_CMD_NUM] = {0};
|
||||
|
||||
//Test information
|
||||
//SIEMENS ip: 192.168.250.9 port: 102
|
||||
//S7-200 ip: 192.168.250.8 port: 102
|
||||
//S7-1200 ip: 192.168.250.6 port: 102
|
||||
//OML ip: 192.168.250.3 port: 9600
|
||||
|
||||
PlcSocketParamType plc_socket_demo_data = {
|
||||
#ifdef SUPPORT_PLC_SIEMENS
|
||||
.ip = {192, 168, 250, 6},
|
||||
.port = 102,
|
||||
.device_type = PLC_DEV_TYPE_SIEMENS,
|
||||
.socket_type = SOCK_STREAM,
|
||||
.cmd_num = 3,
|
||||
#else
|
||||
.ip = {192, 168, 250, 3},
|
||||
.port = 9600,
|
||||
.device_type = PLC_DEV_TYPE_OML,
|
||||
.socket_type = SOCK_DGRAM,
|
||||
.cmd_num = 1,
|
||||
#endif
|
||||
.recv_len = PLC_RECV_BUF_LEN,
|
||||
.recv_buf = NULL,
|
||||
};
|
||||
|
||||
#define OML_HEADER_LEN 78
|
||||
#define CHECK_OML_HEADER(_s) ((0xC0 == *(_s)) && (0x00 == *(_s + 1)) && (0x02 == *(_s + 2)) && (0x00 == *(_s + 3)))
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static void plc_print_array(char *title, int size, uint8_t *cmd)
|
||||
{
|
||||
lw_notice("%s : %d - ", title, size);
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
lw_notice(" %#x", cmd[i]);
|
||||
}
|
||||
lw_notice("\n");
|
||||
}
|
||||
|
||||
static void *PlcSocketStart(void *arg)
|
||||
{
|
||||
int fd = -1;
|
||||
int timeout, recv_len;
|
||||
struct sockaddr_in sock_addr;
|
||||
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||
PlcSocketParamType *param = (PlcSocketParamType *)&plc_socket_demo_data;
|
||||
|
||||
plc_print("start %d.%d.%d.%d:%d dev %d sock %d\n",
|
||||
param->ip[0],
|
||||
param->ip[1],
|
||||
param->ip[2],
|
||||
param->ip[3],
|
||||
param->port,
|
||||
param->device_type,
|
||||
param->socket_type);
|
||||
|
||||
param->recv_len = PLC_RECV_BUF_LEN;
|
||||
|
||||
//malloc memory
|
||||
param->recv_buf = (char *)malloc(param->recv_len);
|
||||
if (param->recv_buf == NULL)
|
||||
{
|
||||
plc_error("No memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, param->socket_type, 0);
|
||||
if (fd < 0)
|
||||
{
|
||||
plc_error("Socket error %d\n", param->socket_type);
|
||||
free(param->recv_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
plc_print("start %d.%d.%d.%d:%d\n", param->ip[0], param->ip[1], param->ip[2], param->ip[3], param->port);
|
||||
|
||||
sock_addr.sin_family = AF_INET;
|
||||
sock_addr.sin_port = htons(param->port);
|
||||
sock_addr.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(param->ip[0], param->ip[1], param->ip[2], param->ip[3]));
|
||||
memset(&(sock_addr.sin_zero), 0, sizeof(sock_addr.sin_zero));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&sock_addr, sizeof(struct sockaddr)) < 0)
|
||||
{
|
||||
plc_error("Unable to connect\n");
|
||||
closesocket(fd);
|
||||
free(param->recv_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lw_notice("client %s connected\n", inet_ntoa(sock_addr.sin_addr));
|
||||
|
||||
for(int i = 0; i < param->cmd_num; i ++)
|
||||
{
|
||||
PlcBinCmdType *cmd = &TestPlcCmd[i];
|
||||
sendto(fd, cmd->cmd, cmd->cmd_len, 0, (struct sockaddr*)&sock_addr, addr_len);
|
||||
plc_print_array("Send cmd", cmd->cmd_len, cmd->cmd);
|
||||
|
||||
MdelayKTask(cmd->delay_ms);
|
||||
timeout = PLC_SOCK_TIMEOUT;
|
||||
memset(param->recv_buf, 0, param->recv_len);
|
||||
while(timeout --)
|
||||
{
|
||||
recv_len = recvfrom(fd, param->recv_buf, param->recv_len, 0, (struct sockaddr *)&sock_addr, &addr_len);
|
||||
if(recv_len > 0)
|
||||
{
|
||||
if(param->device_type == PLC_DEV_TYPE_OML)
|
||||
{
|
||||
if((recv_len == OML_HEADER_LEN) && (CHECK_OML_HEADER(param->recv_buf)))
|
||||
{
|
||||
lw_notice("This is Oml package!!!\n");
|
||||
}
|
||||
}
|
||||
lw_notice("Receive from : %s\n", inet_ntoa(sock_addr.sin_addr));
|
||||
plc_print_array("Receive data", recv_len, param->recv_buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closesocket(fd);
|
||||
free(param->recv_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PlcGetParamCmd(char *cmd)
|
||||
{
|
||||
const char s[2] = ",";
|
||||
char *token;
|
||||
uint16_t cmd_index = 0;
|
||||
char bin_cmd[PLC_BIN_CMD_LEN] = {0};
|
||||
token = strtok(cmd, s);
|
||||
while(token != NULL)
|
||||
{
|
||||
sscanf(token, "%x", &bin_cmd[cmd_index]);
|
||||
plc_print("%d - %s %d\n", cmd_index, token, bin_cmd[cmd_index]);
|
||||
token = strtok(NULL, s);
|
||||
cmd_index ++;
|
||||
}
|
||||
TestPlcCmd[plc_cmd_index].cmd_len = cmd_index;
|
||||
memcpy(TestPlcCmd[plc_cmd_index].cmd, bin_cmd, cmd_index);
|
||||
plc_print("get %d cmd len %d\n", plc_cmd_index, TestPlcCmd[plc_cmd_index].cmd_len);
|
||||
plc_cmd_index ++;
|
||||
plc_socket_demo_data.cmd_num = plc_cmd_index;
|
||||
}
|
||||
|
||||
void PlcShowUsage(void)
|
||||
{
|
||||
plc_notice("------------------------------------\n");
|
||||
plc_notice("PlcSocket [ip].[ip].[ip].[ip]:[port]\n");
|
||||
plc_notice("PlcSocket support other param:\n");
|
||||
plc_notice("plc=[] 0: OML 1:SIEMENS\n");
|
||||
plc_notice("tcp=[] 0: udp 1:tcp\n");
|
||||
plc_notice("ip=[ip.ip.ip.ip]\n");
|
||||
plc_notice("port=port\n");
|
||||
plc_notice("file: use %s\n", PLC_SOCK_FILE_NAME);
|
||||
plc_notice("------------------------------------\n");
|
||||
}
|
||||
|
||||
#if defined(MOUNT_SDCARD) && defined(LIB_USING_CJSON)
|
||||
void PlcGetParamFromFile(char *file_name)
|
||||
{
|
||||
PlcSocketParamType *param = &plc_socket_demo_data;
|
||||
|
||||
char *file_buf = malloc(CTL_FILE_LEN);
|
||||
if(file_buf == NULL)
|
||||
{
|
||||
plc_error("No enough buffer %d\n", CTL_FILE_LEN);
|
||||
return;
|
||||
}
|
||||
memset(file_buf, 0, CTL_FILE_LEN);
|
||||
|
||||
if(CtlFileReadWithFilename(file_name, CTL_FILE_LEN, file_buf) != EOK)
|
||||
{
|
||||
plc_error("Can't open file %s\n", file_name);
|
||||
//try again default file
|
||||
if(strcmp(file_name, PLC_SOCK_FILE_NAME) != 0)
|
||||
{
|
||||
if(CtlFileReadWithFilename(PLC_SOCK_FILE_NAME, CTL_FILE_LEN, file_buf) != EOK)
|
||||
{
|
||||
plc_error("Can't open file %s\n", file_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
CtlParseJsonData(file_buf);
|
||||
|
||||
memcpy(param->ip, ctl_file_param.ip, 4);
|
||||
param->port = ctl_file_param.port;
|
||||
param->cmd_num = ctl_file_param.cmd_num;
|
||||
param->socket_type = ctl_file_param.tcp ? SOCK_STREAM : SOCK_DGRAM;
|
||||
|
||||
for(int i = 0; i < param->cmd_num; i++)
|
||||
{
|
||||
TestPlcCmd[i].cmd_len = ctl_file_param.cmd_len[i];
|
||||
memcpy(TestPlcCmd[i].cmd, ctl_file_param.cmd[i], TestPlcCmd[i].cmd_len);
|
||||
}
|
||||
|
||||
plc_print("ip: %d.%d.%d.%d\n", param->ip[0], param->ip[1], param->ip[2], param->ip[3]);
|
||||
plc_print("port: %d", param->port);
|
||||
plc_print("tcp: %d", param->socket_type);
|
||||
plc_print("cmd number: %d\n", param->cmd_num);
|
||||
|
||||
for(int i = 0; i < param->cmd_num; i++)
|
||||
{
|
||||
plc_print_array("cmd", TestPlcCmd[i].cmd_len, TestPlcCmd[i].cmd);
|
||||
}
|
||||
free(file_buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void PlcCheckParam(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
PlcSocketParamType *param = &plc_socket_demo_data;
|
||||
plc_cmd_index = 0;
|
||||
|
||||
for(i = 0; i < argc; i++)
|
||||
{
|
||||
char *str = argv[i];
|
||||
int is_tcp = 0;
|
||||
char cmd_str[PLC_BIN_CMD_LEN] = {0};
|
||||
|
||||
plc_print("check %d %s\n", i, str);
|
||||
|
||||
#if defined(MOUNT_SDCARD) && defined(LIB_USING_CJSON)
|
||||
if(strncmp(str, "file", 4) == 0)
|
||||
{
|
||||
char file_name[CTL_FILE_NAME_LEN] = {0};
|
||||
if(sscanf(str, "file=%s", file_name) == EOF)
|
||||
{
|
||||
strcpy(file_name, PLC_SOCK_FILE_NAME);
|
||||
}
|
||||
plc_notice("get %s parameter file %s\n", str, file_name);
|
||||
PlcGetParamFromFile(file_name);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(sscanf(str, "ip=%d.%d.%d.%d",
|
||||
¶m->ip[0],
|
||||
¶m->ip[1],
|
||||
¶m->ip[2],
|
||||
¶m->ip[3]) == 4)
|
||||
{
|
||||
plc_print("find ip %d %d %d %d\n", param->ip[0], param->ip[1], param->ip[2], param->ip[3]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sscanf(str, "port=%d", ¶m->port) == 1)
|
||||
{
|
||||
plc_print("find port %d\n", param->port);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sscanf(str, "tcp=%d", &is_tcp) == 1)
|
||||
{
|
||||
plc_print("find tcp %d\n", is_tcp);
|
||||
param->socket_type = is_tcp ? SOCK_STREAM:SOCK_DGRAM;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sscanf(str, "plc=%d", ¶m->device_type) == 1)
|
||||
{
|
||||
plc_print("find device %d\n", param->device_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sscanf(str, "cmd=%s", cmd_str) == 1)
|
||||
{
|
||||
plc_print("find cmd %s\n", cmd_str);
|
||||
PlcGetParamCmd(cmd_str);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(argc >= 2)
|
||||
{
|
||||
if(sscanf(argv[1], "%d.%d.%d.%d:%d",
|
||||
¶m->ip[0],
|
||||
¶m->ip[1],
|
||||
¶m->ip[2],
|
||||
¶m->ip[3],
|
||||
¶m->port) != EOF)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(argv[1], "%d.%d.%d.%d",
|
||||
¶m->ip[0],
|
||||
¶m->ip[1],
|
||||
¶m->ip[2],
|
||||
¶m->ip[3]) != EOF)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PlcShowUsage();
|
||||
}
|
||||
}
|
||||
|
||||
void PlcSocketTask(int argc, char *argv[])
|
||||
{
|
||||
int result = 0;
|
||||
pthread_t th_id;
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = LWIP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TASK_STACK_SIZE;
|
||||
PlcSocketParamType *param = &plc_socket_demo_data;
|
||||
|
||||
PlcCheckParam(argc, argv);
|
||||
|
||||
lwip_config_net(lwip_ipaddr, lwip_netmask, param->ip);
|
||||
PrivTaskCreate(&th_id, &attr, PlcSocketStart, param);
|
||||
}
|
||||
@@ -1,66 +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 plc_socket.h
|
||||
* @brief Demo for PLC socket communication function
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022.03.16
|
||||
*/
|
||||
|
||||
#ifndef __PLC_SOCKET_H_
|
||||
#define __PLC_SOCKET_H_
|
||||
|
||||
#define PLC_BIN_CMD_LEN 512
|
||||
|
||||
// for plc socket test bin commands
|
||||
typedef struct
|
||||
{
|
||||
uint16_t delay_ms;
|
||||
uint8_t cmd_len;
|
||||
uint8_t cmd[PLC_BIN_CMD_LEN];
|
||||
}PlcBinCmdType;
|
||||
|
||||
enum PlcDeviceType {
|
||||
PLC_DEV_TYPE_OML = 0,
|
||||
PLC_DEV_TYPE_IPC,
|
||||
PLC_DEV_TYPE_BRL,
|
||||
PLC_DEV_TYPE_SIEMENS,
|
||||
PLC_DEV_TYPE_SIEMENS_1200,
|
||||
PLC_DEV_TYPE_JF_IPC,
|
||||
PLC_DEV_TYPE_HG,
|
||||
/* ...... */
|
||||
PLC_DEV_TYPE_END,
|
||||
};
|
||||
|
||||
#define PLC_IP_LEN 16
|
||||
#define PLC_DEV_NAME_LEN 32
|
||||
#define PLC_RECV_BUF_LEN CTL_FILE_LEN
|
||||
|
||||
typedef struct PlcSocketParamStruct{
|
||||
char ip[PLC_IP_LEN];
|
||||
uint32_t port;
|
||||
uint32_t device_type; //PlcDeviceType
|
||||
uint32_t socket_type; //UDP or TCP
|
||||
char device[PLC_DEV_NAME_LEN];
|
||||
uint32_t cmd_num; // command number
|
||||
uint32_t recv_len; // receive length
|
||||
uint8_t *recv_buf; // receive buffer
|
||||
}PlcSocketParamType;
|
||||
|
||||
//debug command
|
||||
#define plc_print //KPrintf
|
||||
#define plc_error KPrintf
|
||||
#define plc_notice KPrintf
|
||||
|
||||
#endif
|
||||
@@ -1,4 +0,0 @@
|
||||
menuconfig USING_CONTROL_PLC_COMMON
|
||||
bool "PLC common"
|
||||
default y
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
SRC_FILES := plc_device.c plc_channel.c plc_driver.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -1,538 +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 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 "plc_channel.h"
|
||||
#include "plc_device.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, 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,266 +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 plc_channel.h
|
||||
* @brief define channel driver framework function and common API
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-01
|
||||
*/
|
||||
|
||||
#ifndef __PLC_CHANNEL_H_
|
||||
#define __PLC_CHANNEL_H_
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#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
|
||||
{
|
||||
uint32 pos;
|
||||
void* buffer;
|
||||
size_t size;
|
||||
size_t read_length;
|
||||
};
|
||||
|
||||
struct ChWriteParam
|
||||
{
|
||||
uint32 pos;
|
||||
const void* buffer;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
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, size_t length);
|
||||
|
||||
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, 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);
|
||||
|
||||
|
||||
struct PlcDriver
|
||||
{
|
||||
struct ChDrv driver;
|
||||
uint32 (*configure) (void *drv, struct ChConfigInfo *cfg);
|
||||
};
|
||||
|
||||
struct PlcChannel
|
||||
{
|
||||
struct Channel ch;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/*Register the plc bus*/
|
||||
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 PlcReleaseChannel(struct PlcChannel *plc_ch);
|
||||
|
||||
/*Register the plc driver to the plc bus*/
|
||||
int PlcDriverAttachToChannel(const char *drv_name, const char *ch_name);
|
||||
|
||||
/*Register the driver, manage with the double linklist*/
|
||||
int PlcDriverRegister(struct ChDrv *driver);
|
||||
|
||||
/*Find the register driver*/
|
||||
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,189 +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 plc.c
|
||||
* @brief plc relative activities
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021.12.15
|
||||
*/
|
||||
|
||||
#include "ua_api.h"
|
||||
#include "plc_channel.h"
|
||||
#include "plc_device.h"
|
||||
|
||||
DoublelistType plcdev_list;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*Create the plc device linklist*/
|
||||
static void PlcDeviceLinkInit()
|
||||
{
|
||||
AppInitDoubleList(&plcdev_list);
|
||||
}
|
||||
|
||||
static int PlcDeviceOpen(void *dev)
|
||||
{
|
||||
CHECK_CH_PARAM(dev);
|
||||
|
||||
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
|
||||
|
||||
if(plc_dev->net == PLC_IND_ENET_OPCUA)
|
||||
{
|
||||
return UaDevOpen(plc_dev->priv_data);
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static void PlcDeviceClose(void *dev)
|
||||
{
|
||||
CHECK_CH_PARAM(dev);
|
||||
|
||||
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
|
||||
|
||||
if(plc_dev->net == PLC_IND_ENET_OPCUA)
|
||||
{
|
||||
UaDevClose(plc_dev->priv_data);
|
||||
}
|
||||
}
|
||||
|
||||
static int PlcDeviceWrite(void *dev, const void *buf, size_t len)
|
||||
{
|
||||
CHECK_CH_PARAM(dev);
|
||||
|
||||
int ret;
|
||||
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
|
||||
|
||||
if(plc_dev->net == PLC_IND_ENET_OPCUA)
|
||||
{
|
||||
ret = UaDevWrite(plc_dev->priv_data, buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int PlcDeviceRead(void *dev, void *buf, size_t len)
|
||||
{
|
||||
CHECK_CH_PARAM(dev);
|
||||
CHECK_CH_PARAM(buf);
|
||||
|
||||
int ret;
|
||||
struct PlcDevice *plc_dev = (struct PlcDevice *)dev;
|
||||
|
||||
if(plc_dev->net == PLC_IND_ENET_OPCUA)
|
||||
{
|
||||
ret = UaDevRead(plc_dev->priv_data, buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct PlcOps plc_done =
|
||||
{
|
||||
.open = PlcDeviceOpen,
|
||||
.close = PlcDeviceClose,
|
||||
.write = PlcDeviceWrite,
|
||||
.read = PlcDeviceRead,
|
||||
};
|
||||
|
||||
/* find PLC device with device name */
|
||||
struct ChDev *PlcDevFind(const char *dev_name)
|
||||
{
|
||||
CHECK_CH_PARAM(dev_name);
|
||||
|
||||
struct PlcDevice *device = NONE;
|
||||
struct ChDev *haldev = NONE;
|
||||
|
||||
DoublelistType *node = NONE;
|
||||
DoublelistType *head = &plcdev_list;
|
||||
|
||||
for (node = head->node_next; node != head; node = node->node_next) {
|
||||
device = DOUBLE_LIST_ENTRY(node, struct PlcDevice, link);
|
||||
if (!strcmp(device->name, dev_name)) {
|
||||
haldev = &device->haldev;
|
||||
return haldev;
|
||||
}
|
||||
}
|
||||
|
||||
plc_print("plc: [%s] cannot find the %s device\n", __func__, dev_name);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
int PlcDevRegister(struct PlcDevice *plc_device, void *plc_param, const char *device_name)
|
||||
{
|
||||
CHECK_CH_PARAM(plc_device);
|
||||
CHECK_CH_PARAM(device_name);
|
||||
|
||||
int ret = EOK;
|
||||
static uint8_t dev_link_flag = 0;
|
||||
|
||||
if (!dev_link_flag) {
|
||||
PlcDeviceLinkInit();
|
||||
dev_link_flag = 1;
|
||||
}
|
||||
|
||||
if (CHDEV_INSTALL != plc_device->state) {
|
||||
strncpy(plc_device->haldev.dev_name, device_name, NAME_NUM_MAX);
|
||||
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;
|
||||
|
||||
AppDoubleListInsertNodeAfter(&plcdev_list, &(plc_device->link));
|
||||
plc_device->state = CHDEV_INSTALL;
|
||||
|
||||
} else {
|
||||
KPrintf("PlcDevRegister device %s has been register state%u\n", device_name, plc_device->state);
|
||||
ret = ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name)
|
||||
{
|
||||
CHECK_CH_PARAM(dev_name);
|
||||
CHECK_CH_PARAM(ch_name);
|
||||
|
||||
int ret = EOK;
|
||||
|
||||
struct Channel *ch;
|
||||
struct ChDev *device;
|
||||
|
||||
ch = ChannelFind(ch_name);
|
||||
if (NONE == ch) {
|
||||
KPrintf("PlcDeviceAttachToChannel find plc ch error!name %s\n", ch_name);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (CH_PLC_TYPE == ch->ch_type) {
|
||||
device = PlcDevFind(dev_name);
|
||||
if (NONE == device) {
|
||||
KPrintf("PlcDeviceAttachToChannel find plc device %s error!\n", dev_name);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (CHDEV_PLC_TYPE == device->dev_type) {
|
||||
ret = DeviceRegisterToChannel(ch, device);
|
||||
if (EOK != ret) {
|
||||
KPrintf("PlcDeviceAttachToChannel DeviceRegisterToChannel error %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
@@ -1,153 +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 plc_dev.h
|
||||
* @brief plc relative definition and structure
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-01-24
|
||||
*/
|
||||
|
||||
#ifndef __PLC_DEV_H_
|
||||
#define __PLC_DEV_H_
|
||||
|
||||
#include "list.h"
|
||||
#include "plc_channel.h"
|
||||
|
||||
#undef open
|
||||
#undef close
|
||||
#undef read
|
||||
#undef write
|
||||
|
||||
#define IP_ADDR_SIZE 32
|
||||
#define PLC_NAME_SIZE 32
|
||||
|
||||
// PLC device information
|
||||
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; // model
|
||||
const char *product; // product
|
||||
}PlcInfoType;
|
||||
|
||||
enum PlcSerialType {
|
||||
PLC_SERIAL_232,
|
||||
PLC_SERIAL_485,
|
||||
PLC_SERIAL_CAN
|
||||
};
|
||||
|
||||
union PlcCfg {
|
||||
struct {
|
||||
char ip_addr[IP_ADDR_SIZE];
|
||||
uint32_t ip_port;
|
||||
} PlcIpCfg;
|
||||
struct {
|
||||
enum PlcSerialType serial_type;
|
||||
char station_id;
|
||||
char serial_port;
|
||||
} PlcSerialCfg;
|
||||
};
|
||||
|
||||
struct PlcDevice;
|
||||
|
||||
// operation API
|
||||
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,
|
||||
PLC_CTRL_TYPE_PID,
|
||||
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
|
||||
PLC_IND_FIELD_MODBUS_485,
|
||||
PLC_IND_FIELD_PROFIBUS,
|
||||
PLC_IND_FIELD_CANOPEN,
|
||||
PLC_IND_FIELD_DEVICENET,
|
||||
PLC_IND_FIELD_CONTROLNET,
|
||||
|
||||
// PLC ETHERNET
|
||||
PLC_IND_ENET_ETHERNET_IP,
|
||||
PLC_IND_ENET_PROFINET,
|
||||
PLC_IND_ENET_ETHERCAT,
|
||||
PLC_IND_ENET_SERCOS,
|
||||
PLC_IND_ENET_OPCUA,
|
||||
|
||||
// PLC wireless net
|
||||
PLC_IND_WIRELESS
|
||||
};
|
||||
|
||||
enum PlcTransType
|
||||
{
|
||||
PLC_TRANS_TCP,
|
||||
PLC_TRANS_UDP,
|
||||
PLC_TRANS_SERIAL
|
||||
};
|
||||
|
||||
//communication interface
|
||||
typedef struct PlcInterface
|
||||
{
|
||||
char ip_addr[IP_ADDR_SIZE];
|
||||
char attrib;
|
||||
}PlcInterfaceType;
|
||||
|
||||
// identify PLC device
|
||||
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 PlcIndHybridNet net;
|
||||
enum PlcTransType trans;
|
||||
|
||||
struct PlcInfo info;/* Plc info, such as vendor name and model name */
|
||||
union PlcCfg cfg;
|
||||
struct PlcOps *ops; /* filesystem-like APIs for data transferring */
|
||||
struct PlcInterface interface; /* protocols used for transferring data from program to plc */
|
||||
|
||||
void *priv_data; /* private data for different PLC*/
|
||||
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 PlcDeviceAttachToChannel(const char *dev_name, const char *ch_name);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#endif
|
||||
@@ -1,71 +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 drv_plc.c
|
||||
* @brief register plc drv function using bus driver framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-01-24
|
||||
*/
|
||||
|
||||
#include "transform.h"
|
||||
#include "plc_channel.h"
|
||||
#include "plc_device.h"
|
||||
|
||||
static DoublelistType plcdrv_linklist;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*Create the driver linklist*/
|
||||
static void PlcDrvLinkInit()
|
||||
{
|
||||
AppInitDoubleList(&plcdrv_linklist);
|
||||
}
|
||||
|
||||
ChDrvType PlcDriverFind(const char *drv_name, enum ChDrvType_e drv_type)
|
||||
{
|
||||
CHECK_CH_PARAM(drv_name);
|
||||
|
||||
struct ChDrv *driver = NONE;
|
||||
|
||||
DoublelistType *node = NONE;
|
||||
DoublelistType *head = &plcdrv_linklist;
|
||||
|
||||
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, drv_name)) && (drv_type == driver->driver_type)) {
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
|
||||
KPrintf("PlcDriverFind cannot find the %s driver.return NULL\n", drv_name);
|
||||
return NONE;
|
||||
}
|
||||
|
||||
int PlcDriverRegister(struct ChDrv *driver)
|
||||
{
|
||||
CHECK_CH_PARAM(driver);
|
||||
|
||||
int ret = EOK;
|
||||
static uint8_t driver_link_flag = 0;
|
||||
|
||||
if (!driver_link_flag) {
|
||||
PlcDrvLinkInit();
|
||||
driver_link_flag = 1;
|
||||
}
|
||||
|
||||
AppDoubleListInsertNodeAfter(&plcdrv_linklist, &(driver->driver_link));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
2
APP_Framework/Framework/control/plc_protocol/Kconfig
Executable file
2
APP_Framework/Framework/control/plc_protocol/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
4
APP_Framework/Framework/control/plc_protocol/Makefile
Executable file
4
APP_Framework/Framework/control/plc_protocol/Makefile
Executable file
@@ -0,0 +1,4 @@
|
||||
SRC_DIR := fins melsec opcua s7
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
2
APP_Framework/Framework/control/plc_protocol/fins/Kconfig
Executable file
2
APP_Framework/Framework/control/plc_protocol/fins/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
4
APP_Framework/Framework/control/plc_protocol/fins/Makefile
Executable file
4
APP_Framework/Framework/control/plc_protocol/fins/Makefile
Executable file
@@ -0,0 +1,4 @@
|
||||
SRC_FILES :=
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
2
APP_Framework/Framework/control/plc_protocol/melsec/Kconfig
Executable file
2
APP_Framework/Framework/control/plc_protocol/melsec/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
4
APP_Framework/Framework/control/plc_protocol/melsec/Makefile
Executable file
4
APP_Framework/Framework/control/plc_protocol/melsec/Makefile
Executable file
@@ -0,0 +1,4 @@
|
||||
SRC_FILES :=
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
2
APP_Framework/Framework/control/plc_protocol/s7/Kconfig
Executable file
2
APP_Framework/Framework/control/plc_protocol/s7/Kconfig
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
4
APP_Framework/Framework/control/plc_protocol/s7/Makefile
Executable file
4
APP_Framework/Framework/control/plc_protocol/s7/Makefile
Executable file
@@ -0,0 +1,4 @@
|
||||
SRC_FILES :=
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
/**
|
||||
* @file control.c
|
||||
* @brief control framework code
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
|
||||
void control_init(void)
|
||||
{
|
||||
|
||||
//to do
|
||||
}
|
||||
|
||||
void control_read_file()
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
26
APP_Framework/Framework/control/plc/interoperability/interoperability.c → APP_Framework/Framework/control/shared/control.h
Executable file → Normal file
26
APP_Framework/Framework/control/plc/interoperability/interoperability.c → APP_Framework/Framework/control/shared/control.h
Executable file → Normal file
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* 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:
|
||||
@@ -10,21 +10,15 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file control.h
|
||||
* @brief control framework code
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
void ctrl_interop_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ctrl_interop_connect(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ctrl_interop_enable(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ctrl_interop_disable(void)
|
||||
{
|
||||
}
|
||||
#include <control_file.h>
|
||||
#include <cJSON.h>
|
||||
|
||||
|
||||
@@ -13,194 +13,9 @@
|
||||
/**
|
||||
* @file control_file.c
|
||||
* @brief control relative file operation
|
||||
* @version 1.0
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
* @date 2022-09-37
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cJSON.h"
|
||||
#include "transform.h"
|
||||
#include "control_file.h"
|
||||
|
||||
//json file parameter for PLC socket communication as below:
|
||||
//{
|
||||
// "ip": "192.168.250.6",
|
||||
// "port": 102,
|
||||
// "cmd": [3, 0, 0, 22, 17, 224, 0, 0, 2, 200, 0, 193, 2, 2, 1, 194, 2, 2, 1, 192, 1, 10],
|
||||
// "cmd1": [3, 0, 0, 25, 2, 240, 128, 50, 1, 0, 0, 0, 13, 0, 8, 0, 0, 240, 0, 0, 1, 0, 1, 0, 240], \r\n" \
|
||||
// "cmd2": [3, 0, 0, 31, 2, 240, 128, 50, 1, 0, 0, 51, 1, 0, 14, 0, 0, 4, 1, 18, 10, 16, 2, 0, 210, 0, 52, 132, 0, 0, 0]\r\n" \
|
||||
//}"
|
||||
|
||||
#define TEST_PLC_JSON_TXT \
|
||||
"{ \r\n"\
|
||||
" \"ip\": \"192.168.250.6\", \r\n"\
|
||||
" \"port\": 102, \r\n"\
|
||||
" \"tcp\": 1, \r\n"\
|
||||
" \"cmd\": [3, 0, 0, 22, 17, 224, 0, 0, 2, 200, 0, 193, 2, 2, 1, 194, 2, 2, 1, 192, 1, 10], \r\n"\
|
||||
" \"cmd1\": [3, 0, 0, 25, 2, 240, 128, 50, 1, 0, 0, 0, 13, 0, 8, 0, 0, 240, 0, 0, 1, 0, 1, 0, 240], \r\n" \
|
||||
" \"cmd2\": [3, 0, 0, 31, 2, 240, 128, 50, 1, 0, 0, 51, 1, 0, 14, 0, 0, 4, 1, 18, 10, 16, 2, 0, 210, 0, 52, 132, 0, 0, 0]\r\n" \
|
||||
"}"
|
||||
|
||||
|
||||
CtlPlcSockParamType ctl_file_param;
|
||||
|
||||
FILE *CtlFileInit(char *file)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
|
||||
#ifdef MOUNT_SDCARD
|
||||
// SD card mount flag 1: OK
|
||||
if(sd_mount_flag == 0)
|
||||
{
|
||||
ctl_error("SD card mount failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = fopen(file, "a+");
|
||||
if(fd == NULL)
|
||||
{
|
||||
ctl_error("open file %s failed\n", file);
|
||||
}
|
||||
|
||||
#endif
|
||||
return fd;
|
||||
}
|
||||
|
||||
void CtlFileClose(FILE *fd)
|
||||
{
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
void CtlFileRead(FILE *fd, int size, char *buf)
|
||||
{
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
fread(buf, size, 1, fd);
|
||||
ctl_print("read file %d: %.100s\n", size, buf);
|
||||
}
|
||||
|
||||
void CtlFileWrite(FILE *fd, int size, char *buf)
|
||||
{
|
||||
size_t write_size = 0;
|
||||
write_size = fwrite(buf, strlen(buf) + 1, 1, fd);
|
||||
ctl_print("write size %d: %s\n", size, buf);
|
||||
}
|
||||
|
||||
int CtlFileReadWithFilename(char *file, int size, char *buf)
|
||||
{
|
||||
FILE *fd;
|
||||
fd = fopen(file, "r");
|
||||
if(fd == NULL)
|
||||
{
|
||||
ctl_error("open file %s failed\n", file);
|
||||
return EEMPTY;
|
||||
}
|
||||
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
fread(buf, size, 1, fd);
|
||||
ctl_print("read file %d: %.100s\n", size, buf);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
void CtlCreateFileTest(void)
|
||||
{
|
||||
FILE *fd = CtlFileInit(PLC_SOCK_FILE_NAME);
|
||||
if(fd == NULL)
|
||||
return;
|
||||
char *file_buf = TEST_PLC_JSON_TXT;
|
||||
CtlFileWrite(fd, strlen(file_buf), file_buf);
|
||||
CtlFileClose(fd);
|
||||
}
|
||||
|
||||
#ifdef LIB_USING_CJSON
|
||||
|
||||
void CtlParseJsonArray(cJSON *dat, int *cmd_len, char *cmd)
|
||||
{
|
||||
int len, i;
|
||||
if(cJSON_IsArray(dat))
|
||||
{
|
||||
len = cJSON_GetArraySize(dat);
|
||||
ctl_print("json cmd %d\n", len);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
cJSON *cmd_val = cJSON_GetArrayItem(dat, i);
|
||||
if(NULL == cmd_val)
|
||||
continue;
|
||||
ctl_print("0x%x ", cmd_val->valueint);
|
||||
cmd[i] = cmd_val->valueint;
|
||||
}
|
||||
*cmd_len = len;
|
||||
ctl_print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CtlParseJsonData(char *buf)
|
||||
{
|
||||
cJSON *file_dat = NULL;
|
||||
cJSON *ip_dat = NULL;
|
||||
cJSON *port_dat = NULL;
|
||||
cJSON *tcp_dat = NULL;
|
||||
cJSON *cmd_dat = NULL;
|
||||
char cmd_title[10] = {"cmd"};
|
||||
CtlPlcSockParamType *file_param = &ctl_file_param;
|
||||
|
||||
file_dat = cJSON_Parse(buf);
|
||||
if(file_dat == NULL)
|
||||
{
|
||||
ctl_error("ctrl parse failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ip_dat = cJSON_GetObjectItem(file_dat, "ip");
|
||||
port_dat = cJSON_GetObjectItem(file_dat, "port");
|
||||
tcp_dat = cJSON_GetObjectItem(file_dat, "tcp");
|
||||
|
||||
ctl_print(" ip : %s\n", ip_dat->valuestring);
|
||||
sscanf(ip_dat->valuestring, "%d.%d.%d.%d", &file_param->ip[0],
|
||||
&file_param->ip[1],
|
||||
&file_param->ip[2],
|
||||
&file_param->ip[3]);
|
||||
|
||||
ctl_print(" port: %s %d\n", ip_dat->string, port_dat->valueint);
|
||||
file_param->port = port_dat->valueint;
|
||||
file_param->tcp = tcp_dat->valueint;
|
||||
file_param->cmd_num = 0;
|
||||
|
||||
for(int i = 0; i < CTL_CMD_NUM; i++)
|
||||
{
|
||||
cmd_dat = cJSON_GetObjectItem(file_dat, cmd_title);
|
||||
if(!cmd_dat)
|
||||
break;
|
||||
CtlParseJsonArray(cmd_dat, &file_param->cmd_len[i], file_param->cmd[i]);
|
||||
snprintf(cmd_title, sizeof(cmd_title), "cmd%d", ++file_param->cmd_num);
|
||||
}
|
||||
|
||||
cJSON_Delete(file_dat);
|
||||
}
|
||||
|
||||
void CtlParseFileTest(void)
|
||||
{
|
||||
//for PLC socket parameter file
|
||||
FILE *fd = CtlFileInit(PLC_SOCK_FILE_NAME);
|
||||
if(fd == NULL)
|
||||
{
|
||||
ctl_error("ctl get file %s failed\n", PLC_SOCK_FILE_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
char *file_buf = malloc(CTL_FILE_LEN);
|
||||
|
||||
if(file_buf == NULL)
|
||||
{
|
||||
ctl_error("ctl malloc failed\n");
|
||||
return;
|
||||
}
|
||||
memset(file_buf, 0, CTL_FILE_LEN);
|
||||
CtlFileRead(fd, CTL_FILE_LEN, file_buf);
|
||||
CtlFileClose(fd);
|
||||
CtlParseJsonData(file_buf);
|
||||
free(file_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -12,48 +12,15 @@
|
||||
|
||||
/**
|
||||
* @file control_file.h
|
||||
* @brief control relative API
|
||||
* @version 1.0
|
||||
* @brief control file function relative API
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-17
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
#ifndef __CONTROL_FILE_H_
|
||||
#define __CONTROL_FILE_H_
|
||||
#ifndef CONTROL_FILE_H
|
||||
#define CONTROL_FILE_H
|
||||
|
||||
#define CTL_FILE_LEN 1000 // control file size
|
||||
#define CTL_CMD_NUM 10 // support command number
|
||||
#define CTL_CMD_LEN 100 // control command length
|
||||
#define CTL_IP_LEN 32 // IP address length
|
||||
#define CTL_FILE_NAME_LEN 100 // file name length
|
||||
|
||||
#define PLC_SOCK_FILE_NAME "/plc/socket_param.json"
|
||||
|
||||
#define ctl_print //KPrintf
|
||||
#define ctl_error KPrintf
|
||||
|
||||
// for running plc socket
|
||||
typedef struct CtlPlcSockParamStruct
|
||||
{
|
||||
char ip[CTL_IP_LEN];
|
||||
int port;
|
||||
int tcp; // 1: TCP 0: UDP
|
||||
int cmd_num; //command number
|
||||
int cmd_len[CTL_CMD_NUM]; // command length
|
||||
char cmd[CTL_CMD_NUM][CTL_CMD_LEN];
|
||||
}CtlPlcSockParamType;
|
||||
|
||||
extern CtlPlcSockParamType ctl_file_param;
|
||||
extern int sd_mount_flag;
|
||||
|
||||
FILE *CtlFileInit(char *file);
|
||||
void CtlFileClose(FILE *fd);
|
||||
void CtlFileRead(FILE *fd, int size, char *buf);
|
||||
void CtlFileWrite(FILE *fd, int size, char *buf);
|
||||
int CtlFileReadWithFilename(char *file_name, int size, char *buf);
|
||||
|
||||
#ifdef LIB_USING_CJSON
|
||||
void CtlParseJsonData(char *buf);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user