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:
Liu_Weichao
2022-09-27 20:39:52 +08:00
parent dbca22a1a6
commit e14fa6ff8e
5009 changed files with 1019 additions and 3084 deletions

View File

@@ -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

View File

@@ -1,3 +1,3 @@
SRC_DIR := shared plc
SRC_DIR := ipc_protocol plc_protocol shared
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,2 @@

View File

@@ -1,4 +1,4 @@
SRC_DIR := shared interoperability
SRC_DIR := modbus_tcp modbus_uart
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,2 @@

View File

@@ -1,4 +1,4 @@
SRC_FILES := plc_socket.c
SRC_FILES := modbus_tcp.c
include $(KERNEL_ROOT)/compiler.mk

View 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
*/

View 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

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,4 @@
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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]
}

View File

@@ -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",
&param->ip[0],
&param->ip[1],
&param->ip[2],
&param->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", &param->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", &param->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",
&param->ip[0],
&param->ip[1],
&param->ip[2],
&param->ip[3],
&param->port) != EOF)
{
return;
}
if(sscanf(argv[1], "%d.%d.%d.%d",
&param->ip[0],
&param->ip[1],
&param->ip[2],
&param->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);
}

View File

@@ -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

View File

@@ -1,4 +0,0 @@
menuconfig USING_CONTROL_PLC_COMMON
bool "PLC common"
default y

View File

@@ -1,4 +0,0 @@
SRC_FILES := plc_device.c plc_channel.c plc_driver.c
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,4 @@
SRC_DIR := fins melsec opcua s7
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,4 @@
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,4 @@
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,2 @@

View File

@@ -0,0 +1,4 @@
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -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()
{
}

View 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>

View File

@@ -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

View File

@@ -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