Merge branch 'prepare_for_master' of https://git.trustie.net/xuos/xiuos into wgz

This commit is contained in:
wgzAIIT
2022-03-23 15:16:11 +08:00
114 changed files with 6991 additions and 1190 deletions

View File

@@ -2,5 +2,9 @@
menuconfig USING_CONTROL_PLC_OPCUA
bool "PLC support OPCUA"
default y
depends on RESOURCES_LWIP
depends on RESOURCES_LWIP
menuconfig USING_CONTROL_PLC_SOCKET
bool "PLC support SOCKET"
default y
depends on RESOURCES_LWIP

View File

@@ -6,6 +6,10 @@ 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

View File

@@ -68231,11 +68231,11 @@ UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category,
// (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level], logCategoryNames[category]);
// vprintf(msg, args);
KPrintf("%s/%s" ANSI_COLOR_RESET "\t",
ua_print("%s/%s" ANSI_COLOR_RESET "\t",
logLevelNames[level], logCategoryNames[category]);
vsnprintf(str, sizeof(str) - 1, msg, args);
KPrintf(msg, str);
KPrintf("\n");
ua_print(msg, str);
ua_print("\n");
// printf("\n");
fflush(stdout);

View File

@@ -28,7 +28,7 @@ int ua_open(void *dev)
param->client = UA_Client_new();
ua_pr_info("ua: [%s] start ...\n", __func__);
ua_notice("ua: [%s] start ...\n", __func__);
if (param->client == NULL)
{
@@ -39,11 +39,11 @@ int ua_open(void *dev)
UA_ClientConfig *config = UA_Client_getConfig(param->client);
UA_ClientConfig_setDefault(config);
ua_pr_info("ua: [%s] %d %s\n", __func__, strlen(param->ua_remote_ip), param->ua_remote_ip);
ua_notice("ua: [%s] %d %s\n", __func__, strlen(param->ua_remote_ip), param->ua_remote_ip);
UA_StatusCode retval = UA_Client_connect(param->client, param->ua_remote_ip);
if(retval != UA_STATUSCODE_GOOD) {
ua_pr_info("ua: [%s] deleted ret %x!\n", __func__, retval);
ua_notice("ua: [%s] deleted ret %x!\n", __func__, retval);
return (int)retval;
}
return EOK;
@@ -52,7 +52,6 @@ int ua_open(void *dev)
void ua_close(void *dev)
{
UaParamType *param = (UaParamType *)dev;
UA_Client_disconnect(param->client);
UA_Client_delete(param->client); /* Disconnects the client internally */
}

View File

@@ -43,8 +43,9 @@ typedef struct UaParam
#define ua_print //KPrintf
#define ua_trace() //KPrintf("ua: [%s] line %d checked!\n", __func__, __LINE__)
#define ua_pr_info KPrintf
#define ua_notice KPrintf
#define ua_debug //KPrintf
#define ua_error KPrintf
extern const char *opc_server_url;
extern char test_ua_ip[];

View File

@@ -42,7 +42,7 @@ static UA_StatusCode nodeIter(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId
}
UA_NodeId* parent = (UA_NodeId*)handle;
ua_pr_info("%d, %d --- %d ---> NodeId %d, %d\n",
ua_notice("%d, %d --- %d ---> NodeId %d, %d\n",
parent->namespaceIndex, parent->identifier.numeric,
referenceTypeId.identifier.numeric, childId.namespaceIndex,
childId.identifier.numeric);
@@ -81,38 +81,38 @@ void ua_print_value(UA_Variant* val)
if(val->type == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT])
{
UA_LocalizedText* ptr = (UA_LocalizedText*)val->data;
ua_pr_info("%.*s (Text)\n", ptr->text.length, ptr->text.data);
ua_notice("%.*s (Text)\n", ptr->text.length, ptr->text.data);
}
else if(val->type == &UA_TYPES[UA_TYPES_UINT32])
{
UA_UInt32* ptr = (UA_UInt32*)val->data;
ua_pr_info("%d (UInt32)\n", *ptr);
ua_notice("%d (UInt32)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_BOOLEAN])
{
UA_Boolean* ptr = (UA_Boolean*)val->data;
ua_pr_info("%i (BOOL)\n", *ptr);
ua_notice("%i (BOOL)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_INT32])
{
UA_Int32* ptr = (UA_Int32*)val->data;
ua_pr_info("%d (Int32)\n", *ptr);
ua_notice("%d (Int32)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_INT16])
{
UA_Int16* ptr = (UA_Int16*)val->data;
ua_pr_info("%d (Int16)\n", *ptr);
ua_notice("%d (Int16)\n", *ptr);
}
else if(val->type == &UA_TYPES[UA_TYPES_STRING])
{
UA_String* ptr = (UA_String*)val->data;
ua_pr_info("%*.s (String)\n", ptr->length, ptr->data);
ua_notice("%*.s (String)\n", ptr->length, ptr->data);
}
else if(val->type == &UA_TYPES[UA_TYPES_DATETIME])
{
UA_DateTime* ptr = (UA_DateTime*)val->data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(*ptr);
ua_pr_info("%d-%d-%d %d:%d:%d.%03d (Time)\n",
ua_notice("%d-%d-%d %d:%d:%d.%03d (Time)\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}
}
@@ -144,14 +144,14 @@ void ua_print_nodeid(UA_NodeId *node_id)
switch(node_id->identifierType)
{
case UA_NODEIDTYPE_NUMERIC:
ua_pr_info(" NodeID n%d,%d ", node_id->namespaceIndex, node_id->identifier.numeric);
ua_notice(" NodeID n%d,%d ", node_id->namespaceIndex, node_id->identifier.numeric);
break;
case UA_NODEIDTYPE_STRING:
ua_pr_info(" NodeID n%d,%.*s ", node_id->namespaceIndex, node_id->identifier.string.length,
ua_notice(" NodeID n%d,%.*s ", node_id->namespaceIndex, node_id->identifier.string.length,
node_id->identifier.string.data);
break;
case UA_NODEIDTYPE_BYTESTRING:
ua_pr_info(" NodeID n%d,%s ", node_id->namespaceIndex, node_id->identifier.byteString.data);
ua_notice(" NodeID n%d,%s ", node_id->namespaceIndex, node_id->identifier.byteString.data);
break;
default:
break;
@@ -160,7 +160,7 @@ void ua_print_nodeid(UA_NodeId *node_id)
void ua_print_object(UA_BrowseResponse* res)
{
ua_pr_info("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
ua_notice("%-9s %-16s %-16s %-16s\n", "NAMESPACE", "NODEID", "BROWSE NAME", "DISPLAY NAME");
for(size_t i = 0; i < res->resultsSize; ++i)
{
@@ -170,14 +170,14 @@ void ua_print_object(UA_BrowseResponse* res)
if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC)
{
ua_pr_info("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
ua_notice("%-9d %-16d %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
ref->nodeId.nodeId.identifier.numeric, (int)ref->browseName.name.length,
ref->browseName.name.data, (int)ref->displayName.text.length,
ref->displayName.text.data);
}
else if(ref->nodeId.nodeId.identifierType == UA_NODEIDTYPE_STRING)
{
ua_pr_info("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
ua_notice("%-9d %-16.*s %-16.*s %-16.*s\n", ref->nodeId.nodeId.namespaceIndex,
(int)ref->nodeId.nodeId.identifier.string.length,
ref->nodeId.nodeId.identifier.string.data,
(int)ref->browseName.name.length, ref->browseName.name.data,
@@ -188,7 +188,7 @@ void ua_print_object(UA_BrowseResponse* res)
}
}
ua_pr_info("\n");
ua_notice("\n");
}
UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValueId* array)
@@ -203,7 +203,7 @@ UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValu
|| (response.resultsSize != array_size))
{
UA_ReadResponse_clear(&response);
ua_pr_info("ua: [%s] read failed 0x%x\n", __func__,
ua_notice("ua: [%s] read failed 0x%x\n", __func__,
response.responseHeader.serviceResult);
return UA_STATUSCODE_BADUNEXPECTEDERROR;
}
@@ -215,11 +215,11 @@ UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValu
if((response.results[i].status == UA_STATUSCODE_GOOD)
&& (response.results[i].hasValue))
{
ua_pr_info("node %s: ", ua_get_nodeid_str(&array[i].nodeId));
ua_notice("node %s: ", ua_get_nodeid_str(&array[i].nodeId));
ua_print_value(&response.results[i].value);
}
}
ua_pr_info("\n");
ua_notice("\n");
free(arr_ret);
UA_ReadResponse_clear(&response);
@@ -229,7 +229,7 @@ UA_StatusCode ua_read_array_value(UA_Client* client, int array_size, UA_ReadValu
void ua_browser_id(UA_Client* client, UA_NodeId id)
{
/* Browse some objects */
ua_pr_info("Browsing nodes in objects folder:\n");
ua_notice("Browsing nodes in objects folder:\n");
UA_BrowseRequest bReq;
UA_BrowseRequest_init(&bReq);
bReq.requestedMaxReferencesPerNode = 0;
@@ -327,7 +327,7 @@ void ua_write_nodeid_value(UA_Client* client, UA_NodeId id, char* value)
if(wResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
{
ua_pr_info("write new value is: %s\n", value);
ua_notice("write new value is: %s\n", value);
}
UA_WriteRequest_clear(&wReq);
@@ -489,7 +489,7 @@ void ua_read_time(UA_Client* client)
{
UA_DateTime raw_date = *(UA_DateTime*) value.data;
UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
ua_pr_info("date is: %d-%d-%d %d:%d:%d.%03d\n",
ua_notice("date is: %d-%d-%d %d:%d:%d.%03d\n",
dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
}

View File

@@ -53,7 +53,7 @@ void ua_test_browser_objects(UA_Client *client)
ua_browser_id(client, UA_TEST_BROWSER_NODEID);
ua_browser_id(client, UA_TEST_BROWSER_NODEID1);
test_id = UA_TEST_BROWSER_NODEID1;
ua_pr_info("Show values in %s:\n", ua_get_nodeid_str(&test_id));
ua_notice("Show values in %s:\n", ua_get_nodeid_str(&test_id));
ua_test_read_array(client);
return;
}
@@ -64,11 +64,11 @@ void ua_test_write_attr(UA_Client *client)
char val_str[UA_NODE_LEN];
UA_NodeId id = UA_TEST_WRITE_NODEID;
ua_pr_info("--- Test write %s ---\n", ua_get_nodeid_str(&id));
ua_notice("--- Test write %s ---\n", ua_get_nodeid_str(&id));
ua_read_nodeid_value(client, id, &value);
ua_write_nodeid_value(client, id, itoa(value + 1, val_str, 10));
ua_read_nodeid_value(client, id, &value);
ua_pr_info("\n");
ua_notice("\n");
}
int ua_test_interact_server(UA_Client *client)

View File

@@ -0,0 +1,11 @@
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

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

View File

@@ -0,0 +1,18 @@
# 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

@@ -0,0 +1,364 @@
/*
* 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);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3),
PlcSocket, PlcSocketTask, Test PLC Socket);

View File

@@ -0,0 +1,66 @@
/*
* 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,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:

View File

@@ -1,4 +1,8 @@
SRC_FILES := control.c
ifeq ($(CONFIG_MOUNT_SDCARD),y)
SRC_FILES += control_file.c
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@@ -0,0 +1,213 @@
/*
* 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 control_file.c
* @brief control relative file operation
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-17
*/
#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);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
CtlCreateFile, CtlCreateFileTest, Test control file);
#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);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0),
CtlParseFile, CtlParseFileTest, Parse control file);
#endif

View File

@@ -0,0 +1,59 @@
/*
* 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 control_file.h
* @brief control relative API
* @version 1.0
* @author AIIT XUOS Lab
* @date 2022-03-17
*/
#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

View File

@@ -43,6 +43,23 @@ config SENSOR_AS830
endif
if ADD_RTTHREAD_FETURES
config SENSOR_AS830_DRIVER_EXTUART
bool "Using extra uart to support as830"
default y
config SENSOR_DEVICE_AS830_DEV
string "as830 device uart path"
default "/dev/uart2"
depends on !SENSOR_AS830_DRIVER_EXTUART
if SENSOR_AS830_DRIVER_EXTUART
config SENSOR_DEVICE_AS830_DEV
string "as830 device extra uart path"
default "/dev/extuart_dev4"
config SENSOR_DEVICE_AS830_DEV_EXT_PORT
int "if AS830 device using extuart, choose port"
default "4"
endif
endif
endif

View File

@@ -0,0 +1,14 @@
import os
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(path, 'SConscript'))
Return('objs')

View File

@@ -0,0 +1,10 @@
from building import *
import os
cwd = GetCurrentDir()
src = []
if GetDepend(['SENSOR_AS830']):
src += ['as830.c']
group = DefineGroup('sensor ch4 as830', src, depend = [], CPPPATH = [cwd])
Return('group')

View File

@@ -43,7 +43,24 @@ config SENSOR_ZG09
endif
if ADD_RTTHREAD_FETURES
config SENSOR_ZG09_DRIVER_EXTUART
bool "Using extra uart to support zg09"
default y
config SENSOR_DEVICE_ZG09_DEV
string "zg09 device uart path"
default "/dev/uart2_dev2"
depends on !SENSOR_ZG09_DRIVER_EXTUART
if SENSOR_ZG09_DRIVER_EXTUART
config SENSOR_DEVICE_ZG09_DEV
string "zg09 device extra uart path"
default "/dev/extuart_dev4"
config SENSOR_DEVICE_ZG09_DEV_EXT_PORT
int "if ZG09 device using extuart, choose port"
default "4"
endif
endif
endif

View File

@@ -0,0 +1,10 @@
from building import *
import os
cwd = GetCurrentDir()
src = []
if GetDepend(['SENSOR_ZG09']):
src += ['zg09.c']
group = DefineGroup('sensor co2 zg09', src, depend = [], CPPPATH = [cwd])
Return('group')

View File

@@ -43,6 +43,23 @@ config SENSOR_TB600B_WQ_HCHO1OS
endif
if ADD_RTTHREAD_FETURES
config SENSOR_TB600B_WQ_HCHO1OS_DRIVER_EXTUART
bool "Using extra uart to support tb600b wq_hcho1os"
default y
config SENSOR_DEVICE_TB600B_WQ_HCHO1OS_DEV
string "tb600b wq_hcho1os device uart path"
default "/dev/uart2"
depends on !SENSOR_TB600B_WQ_HCHO1OS_DRIVER_EXTUART
if SENSOR_TB600B_WQ_HCHO1OS_DRIVER_EXTUART
config SENSOR_DEVICE_TB600B_WQ_HCHO1OS_DEV
string "tb600b wq_hcho1os device extra uart path"
default "/dev/extuart_dev1"
config SENSOR_DEVICE_TB600B_WQ_HCHO1OS_DEV_EXT_PORT
int "if TB600B_WQ_HCHO1OS device using extuart, choose port"
default "1"
endif
endif
endif

View File

@@ -0,0 +1,14 @@
import os
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(path, 'SConscript'))
Return('objs')

View File

@@ -0,0 +1,10 @@
from building import *
import os
cwd = GetCurrentDir()
src = []
if GetDepend(['SENSOR_TB600B_WQ_HCHO1OS']):
src += ['tb600b_wq_hcho1os.c']
group = DefineGroup('sensor hcho', src, depend = [], CPPPATH = [cwd])
Return('group')

View File

@@ -43,6 +43,23 @@ config SENSOR_D124
endif
if ADD_RTTHREAD_FETURES
config SENSOR_D124_DRIVER_EXTUART
bool "Using extra uart to support D124"
default y
config SENSOR_DEVICE_D124_DEV
string "D124 device name"
default "/dev/uart2_dev2"
depends on !SENSOR_D124_DRIVER_EXTUART
if SENSOR_D124_DRIVER_EXTUART
config SENSOR_DEVICE_D124_DEV
string "D124 device extra uart path"
default "/dev/extuart_dev4"
config SENSOR_DEVICE_D124_DEV_EXT_PORT
int "if D124 device using extuart, choose port"
default "4"
endif
endif
endif