feat add control_framework, support fins protocol, compile OK
This commit is contained in:
@@ -1,8 +1,4 @@
|
||||
SRC_FILES := control.c
|
||||
|
||||
ifeq ($(CONFIG_MOUNT_SDCARD),y)
|
||||
SRC_FILES += control_file.c
|
||||
endif
|
||||
SRC_FILES := control.c control_def.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"siemens plc":
|
||||
{
|
||||
"device type": "PLC",
|
||||
"control type": "HSC",
|
||||
"info":
|
||||
{
|
||||
"plc ability" : 1,
|
||||
"plc device id": 1,
|
||||
"soft version" : 1,
|
||||
"hardware version": 1,
|
||||
"date": "2022-1-28",
|
||||
"vendor": "siemens",
|
||||
"model":"S300"
|
||||
},
|
||||
|
||||
"serial config":
|
||||
{
|
||||
"serial type":"485",
|
||||
"station id" : "station1",
|
||||
"serial port" : 1
|
||||
},
|
||||
|
||||
"network config":
|
||||
{
|
||||
"ip addr" : "192.168.250.5",
|
||||
"ip port" : 4840
|
||||
},
|
||||
|
||||
"interface":
|
||||
{
|
||||
"inhybridnet":"OPCUA",
|
||||
"transport":"TCP",
|
||||
"ip address": "192.168.250.5",
|
||||
"attribute" : "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,16 +12,239 @@
|
||||
|
||||
/**
|
||||
* @file control.c
|
||||
* @brief control framework code
|
||||
* @brief code for control framework app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
#include <control.h>
|
||||
#include <control_def.h>
|
||||
|
||||
void control_init(void)
|
||||
ControlProtocolType control_protocol;
|
||||
|
||||
/**
|
||||
* @description: Control Framework Find certain Protocol
|
||||
* @param
|
||||
* @return Control Protocol pointer
|
||||
*/
|
||||
ControlProtocolType ControlProtocolFind(void)
|
||||
{
|
||||
//to do
|
||||
return control_protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Protocol Init
|
||||
* @param control_protocol - control protocol pointer
|
||||
* @return success: 0 error : -1
|
||||
*/
|
||||
static int ControlProtocolInit(ControlProtocolType control_protocol)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
int ret = -1;
|
||||
|
||||
control_protocol->protocol_status = CONTROL_INIT;
|
||||
|
||||
ret = PrivMutexCreate(&control_protocol->lock, 0);
|
||||
if(ret < 0) {
|
||||
printf("ControlProtocolInit mutex create failed.\n");
|
||||
goto _out;
|
||||
}
|
||||
|
||||
ret = PrivSemaphoreCreate(&control_protocol->sem, 0, 0);
|
||||
if (ret < 0) {
|
||||
printf("ControlProtocolInit create sem error\n");
|
||||
goto _out;
|
||||
}
|
||||
|
||||
_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Analyze Recipe
|
||||
* @param control_protocol - Control Protocol pointer
|
||||
* @param recipe_name - recipe name
|
||||
* @return success: 0 error : -1
|
||||
*/
|
||||
static int ControlAnalyzeRecipe(ControlProtocolType control_protocol, const char *recipe_name)
|
||||
{
|
||||
int recipe_file_fd = -1;
|
||||
struct stat recipe_file_status;
|
||||
uint16_t recipe_file_length = 0;
|
||||
char *recipe_file_buf;
|
||||
|
||||
//Step1 : read recipe file data from SD card or other store device
|
||||
recipe_file_fd = PrivOpen(recipe_name, O_RDONLY);
|
||||
if (recipe_file_fd < 0) {
|
||||
printf("Open recipe file %s failed\n", recipe_name);
|
||||
PrivClose(recipe_file_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != fstat(recipe_file_fd, &recipe_file_status)) {
|
||||
printf("Get recipe file information failed!\n");
|
||||
PrivClose(recipe_file_fd);
|
||||
return -1;
|
||||
} else {
|
||||
recipe_file_length = recipe_file_status.st_size;
|
||||
}
|
||||
|
||||
recipe_file_buf = PrivMalloc(recipe_file_length);
|
||||
if (NULL == recipe_file_buf) {
|
||||
printf("Get recipe file memory failed!\n");
|
||||
PrivFree(recipe_file_buf);
|
||||
PrivClose(recipe_file_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PrivRead(recipe_file_fd, recipe_file_buf, recipe_file_length) < 0) {
|
||||
printf("Read recipe file failed!\n");
|
||||
PrivFree(recipe_file_buf);
|
||||
PrivClose(recipe_file_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PrivClose(recipe_file_fd);
|
||||
|
||||
//Step2 : CJSON analyze
|
||||
#ifdef LIB_USING_CJSON
|
||||
cJSON *recipe_file_json = cJSON_Parse(recipe_file_buf);
|
||||
PrivFree(recipe_file_buf);
|
||||
if (NULL == recipe_file_json) {
|
||||
printf("Parse recipe_file_buf failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
control_protocol->recipe = (struct ControlRecipe *)PrivMalloc(sizeof(struct ControlRecipe));
|
||||
memset(control_protocol->recipe, 0, sizeof(struct ControlRecipe));
|
||||
|
||||
/*Get basic information from recipe file*/
|
||||
if (RecipeBasicInformation(control_protocol->recipe, control_protocol->protocol_type, recipe_file_json) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*Get the variable need to read from recipe file*/
|
||||
RecipeReadVariableItem(control_protocol->recipe, control_protocol->protocol_type, recipe_file_json);
|
||||
|
||||
cJSON_Delete(recipe_file_json);
|
||||
printf("Read and parse recipe file done!\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Control Framework Protocol Open*/
|
||||
int ControlProtocolOpen(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
CONTROL_PARAM_CHECK(control_protocol->done);
|
||||
int ret = -1;
|
||||
|
||||
if (control_protocol->done->_open) {
|
||||
ret = control_protocol->done->_open(control_protocol);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control Framework Protocol Close*/
|
||||
int ControlProtocolClose(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
CONTROL_PARAM_CHECK(control_protocol->done);
|
||||
int ret = -1;
|
||||
|
||||
if (control_protocol->done->_close) {
|
||||
ret = control_protocol->done->_close(control_protocol);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control Framework Protocol Read Date*/
|
||||
int ControlProtocolRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
CONTROL_PARAM_CHECK(control_protocol->done);
|
||||
int ret = -1;
|
||||
|
||||
if (control_protocol->done->_read) {
|
||||
ret = control_protocol->done->_read(control_protocol, buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control Framework Protocol Write Cmd*/
|
||||
int ControlProtocolWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
CONTROL_PARAM_CHECK(control_protocol->done);
|
||||
int ret = -1;
|
||||
|
||||
if (control_protocol->done->_write) {
|
||||
ret = control_protocol->done->_write(control_protocol, buf, len);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Control Framework Protocol Ioctl*/
|
||||
int ControlProtocolIoctl(struct ControlProtocol *control_protocol, int cmd, void *args)
|
||||
{
|
||||
CONTROL_PARAM_CHECK(control_protocol);
|
||||
CONTROL_PARAM_CHECK(control_protocol->done);
|
||||
int ret = -1;
|
||||
|
||||
if (control_protocol->done->_ioctl) {
|
||||
ret = control_protocol->done->_ioctl(control_protocol, cmd, args);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Init
|
||||
* @return success: 0 error : -1
|
||||
*/
|
||||
int ControlFrameworkInit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
control_protocol = (struct ControlProtocol *)PrivMalloc(sizeof(struct ControlProtocol));
|
||||
if (NULL == control_protocol) {
|
||||
printf("%s malloc control protocol failed!\n", __func__);
|
||||
PrivFree(control_protocol);
|
||||
ret = -1;
|
||||
goto _out;
|
||||
}
|
||||
|
||||
//Control Protocol Struct Init
|
||||
ret = ControlProtocolInit(control_protocol);
|
||||
if (ret < 0) {
|
||||
printf("%s failed!\n", __func__);
|
||||
PrivFree(control_protocol);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
//Read Recipe File, Get Control Protocol Configure Param
|
||||
ret = ControlAnalyzeRecipe(control_protocol, CONTROL_RECIPE_FILE);
|
||||
if (ret < 0) {
|
||||
printf("%s failed!\n", __func__);
|
||||
PrivFree(control_protocol);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
control_protocol->protocol_status = CONTROL_REGISTERED;
|
||||
|
||||
ret = ControlPeripheralInit(control_protocol->recipe);
|
||||
if (ret < 0) {
|
||||
printf("%s failed!\n", __func__);
|
||||
PrivFree(control_protocol);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -12,13 +12,103 @@
|
||||
|
||||
/**
|
||||
* @file control.h
|
||||
* @brief control framework code
|
||||
* @brief DEFINE code for control framework app
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
#include <control_file.h>
|
||||
#include <cJSON.h>
|
||||
#ifndef CONTROL_H
|
||||
#define CONTROL_H
|
||||
|
||||
#include <transform.h>
|
||||
#include <list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ControlProtocol;
|
||||
typedef struct ControlProtocol *ControlProtocolType;
|
||||
typedef struct ControlData *ControlDataType;
|
||||
|
||||
struct ControlDone
|
||||
{
|
||||
int (*_open)(struct ControlProtocol *control_protocol);
|
||||
int (*_close)(struct ControlProtocol *control_protocol);
|
||||
int (*_read)(struct ControlProtocol *control_protocol, void *buf, size_t len);
|
||||
int (*_write)(struct ControlProtocol *control_protocol, const void *buf, size_t len);
|
||||
int (*_ioctl)(struct ControlProtocol *control_protocol, int cmd, void *args);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROTOCOL_S7 = 1,
|
||||
PROTOCOL_MODBUS_TCP,
|
||||
PROTOCOL_MODBUS_UART,
|
||||
PROTOCOL_OPC_UA,
|
||||
PROTOCOL_FINS,
|
||||
PROTOCOL_MELSEC_1E,
|
||||
PROTOCOL_MELSEC_3E_Q_L,
|
||||
PROTOCOL_MELSEC_3E_IQ_R,
|
||||
PROTOCOL_MELSEC_1C,
|
||||
PROTOCOL_MELSEC_3C,
|
||||
PROTOCOL_END
|
||||
}ProtocolType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONTROL_INIT,
|
||||
CONTROL_REGISTERED,
|
||||
CONTROL_UNREGISTERED,
|
||||
}ProtocolStatus;
|
||||
|
||||
struct ControlProtocol
|
||||
{
|
||||
char *name;
|
||||
ProtocolType protocol_type;
|
||||
ProtocolStatus protocol_status;
|
||||
|
||||
struct ControlRecipe *recipe;
|
||||
struct ControlDone *done;
|
||||
|
||||
void *args;
|
||||
|
||||
sem_t sem;
|
||||
pthread_mutex_t lock;
|
||||
//struct DoublelistNode link;
|
||||
};
|
||||
|
||||
/*Control Framework Protocol Init*/
|
||||
int ControlFrameworkInit(void);
|
||||
|
||||
/*Control Framework Find certain Protocol*/
|
||||
ControlProtocolType ControlProtocolFind(void);
|
||||
|
||||
// /*Control Framework Protocol Register*/
|
||||
// int ControlProtocolRegister(struct ControlProtocol *control_protocol);
|
||||
|
||||
// /*Control Framework Protocol Unregister*/
|
||||
// int ControlProtocolUnregister(struct ControlProtocol *control_protocol);
|
||||
|
||||
/*Control Framework Protocol Open*/
|
||||
int ControlProtocolOpen(struct ControlProtocol *control_protocol);
|
||||
|
||||
/*Control Framework Protocol Close*/
|
||||
int ControlProtocolClose(struct ControlProtocol *control_protocol);
|
||||
|
||||
/*Control Framework Protocol Read*/
|
||||
int ControlProtocolRead(struct ControlProtocol *control_protocol, void *buf, size_t len);
|
||||
|
||||
/*Control Framework Protocol Write*/
|
||||
int ControlProtocolWrite(struct ControlProtocol *control_protocol, const void *buf, size_t len);
|
||||
|
||||
/*Control Framework Protocol Ioctl*/
|
||||
int ControlProtocolIoctl(struct ControlProtocol *control_protocol, int cmd, void *args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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 control_def.c
|
||||
* @brief code for control framework
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-9
|
||||
*/
|
||||
|
||||
#include <control_def.h>
|
||||
|
||||
/*using cirtular area to receive data*/
|
||||
#define PLC_DATA_LENGTH 1024
|
||||
struct CircularAreaApp *g_circular_area;
|
||||
static pthread_t recv_plc_data_task;
|
||||
|
||||
/*extern function*/
|
||||
extern void *ReceivePlcDataTask(void *parameter);
|
||||
|
||||
#ifdef CONTROL_PROTOCOL_FINS
|
||||
extern int FinsProtocolInit(struct ControlRecipe *p_recipe);
|
||||
#endif
|
||||
|
||||
/*
|
||||
CONTROL FRAMEWORK READ DATA FORMAT:
|
||||
| HEAD |device_id|read data length|read item count| data |
|
||||
|2 Bytes| 2 Bytes | 2 Bytes | 2 Bytes |read data length Bytes|
|
||||
*/
|
||||
#define CONTROL_DATA_HEAD_LENGTH 8
|
||||
#define CONTROL_DATA_HEAD_1 0xAA
|
||||
#define CONTROL_DATA_HEAD_2 0xBB
|
||||
|
||||
typedef int (*ControlProtocolInitFunc)(struct ControlRecipe *p_recipe);
|
||||
|
||||
struct ControlProtocolInitParam
|
||||
{
|
||||
int protocol_type;
|
||||
const ControlProtocolInitFunc fn;
|
||||
};
|
||||
|
||||
static struct ControlProtocolInitParam protocol_init[] =
|
||||
{
|
||||
#ifdef CONTROL_PROTOCOL_FINS
|
||||
{ PROTOCOL_FINS, FinsProtocolInit },
|
||||
#endif
|
||||
|
||||
{ PROTOCOL_END, NULL },
|
||||
};
|
||||
|
||||
static int ControlProtocolInitDesc(struct ControlRecipe *p_recipe, struct ControlProtocolInitParam sub_protocol_desc[])
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
for( i = 0; sub_protocol_desc[i].fn != NULL; i++ ) {
|
||||
if (p_recipe->protocol_type == sub_protocol_desc[i].protocol_type) {
|
||||
ret = sub_protocol_desc[i].fn(p_recipe);
|
||||
printf("control protocol initialize %d %s\n", sub_protocol_desc[i].protocol_type, ret == 0 ? "success" : "failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void FormatDataHeader(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
uint16_t plc_read_data_length = CONTROL_DATA_HEAD_LENGTH + p_recipe->total_data_length;//Head length is CONTROL_DATA_HEAD_LENGTH
|
||||
uint8_t *data = p_recipe->protocol_data->data;
|
||||
|
||||
data[0] = CONTROL_DATA_HEAD_1;
|
||||
data[1] = CONTROL_DATA_HEAD_2;
|
||||
data[2] = (p_recipe->device_id) >> 8;
|
||||
data[3] = p_recipe->device_id;
|
||||
data[4] = (plc_read_data_length) >> 8;
|
||||
data[5] = plc_read_data_length;
|
||||
data[6] = (p_recipe->read_item_count) >> 8;
|
||||
data[7] = p_recipe->read_item_count;
|
||||
}
|
||||
|
||||
static uint16_t GetRecipeTotalDataLength(cJSON* read_item_list_json)
|
||||
{
|
||||
uint16_t read_item_count = cJSON_GetArraySize(read_item_list_json);
|
||||
uint16_t total_data_length = 0;
|
||||
for (uint16_t read_item_index = 0; read_item_index < read_item_count; read_item_index++) {
|
||||
cJSON* read_item_json = cJSON_GetArrayItem(read_item_list_json, read_item_index);
|
||||
UniformValueType value_type = cJSON_GetObjectItem(read_item_json, "value_type")->valueint;
|
||||
total_data_length += GetValueTypeMemorySize(value_type);
|
||||
}
|
||||
return total_data_length;
|
||||
}
|
||||
|
||||
static void ControlBasicSerialConfig(struct ControlRecipe *p_recipe, cJSON *p_recipe_file_json)
|
||||
{
|
||||
cJSON *p_serial_config_json = cJSON_GetObjectItem(p_recipe_file_json, "serial_config");
|
||||
p_recipe->serial_config.baud_rate = cJSON_GetObjectItem(p_serial_config_json, "baud_rate")->valueint;
|
||||
p_recipe->serial_config.data_bits = cJSON_GetObjectItem(p_serial_config_json, "data_bits")->valueint;
|
||||
p_recipe->serial_config.stop_bits = cJSON_GetObjectItem(p_serial_config_json, "stop_bits")->valueint;
|
||||
p_recipe->serial_config.check_mode = cJSON_GetObjectItem(p_serial_config_json, "check_mode")->valueint;
|
||||
printf("Serial_config: baud_rate: %d, data_bits: %d, stop_bits: %d, check_mode is %d\n",
|
||||
p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits, p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
}
|
||||
|
||||
static void ControlBasicSocketConfig(struct ControlRecipe *p_recipe, cJSON *p_recipe_file_json)
|
||||
{
|
||||
cJSON *p_socket_address_json = cJSON_GetObjectItem(p_recipe_file_json, "socket_config");
|
||||
char *plc_ip_string = cJSON_GetObjectItem(p_socket_address_json, "plc_ip")->valuestring;
|
||||
sscanf(plc_ip_string, "%d.%d.%d.%d",
|
||||
p_recipe->socket_config.plc_ip,
|
||||
p_recipe->socket_config.plc_ip + 1,
|
||||
p_recipe->socket_config.plc_ip + 2,
|
||||
p_recipe->socket_config.plc_ip + 3);
|
||||
|
||||
char *local_ip_string = cJSON_GetObjectItem(p_socket_address_json, "local_ip")->valuestring;
|
||||
sscanf(local_ip_string, "%d.%d.%d.%d",
|
||||
p_recipe->socket_config.local_ip,
|
||||
p_recipe->socket_config.local_ip + 1,
|
||||
p_recipe->socket_config.local_ip + 2,
|
||||
p_recipe->socket_config.local_ip + 3);
|
||||
|
||||
char *gateway_ip_string = cJSON_GetObjectItem(p_socket_address_json, "gateway")->valuestring;
|
||||
sscanf(gateway_ip_string, "%d.%d.%d.%d",
|
||||
p_recipe->socket_config.gateway,
|
||||
p_recipe->socket_config.gateway + 1,
|
||||
p_recipe->socket_config.gateway + 2,
|
||||
p_recipe->socket_config.gateway + 3);
|
||||
|
||||
char *netmask_string = cJSON_GetObjectItem(p_socket_address_json, "netmask")->valuestring;
|
||||
sscanf(netmask_string, "%d.%d.%d.%d",
|
||||
p_recipe->socket_config.netmask,
|
||||
p_recipe->socket_config.netmask + 1,
|
||||
p_recipe->socket_config.netmask + 2,
|
||||
p_recipe->socket_config.netmask + 3);
|
||||
|
||||
p_recipe->socket_config.port = cJSON_GetObjectItem(p_socket_address_json, "port")->valueint;
|
||||
printf("Socket_config: local ip is %s, plc ip is %s, gateway is %s, port is %d.\n",
|
||||
local_ip_string, plc_ip_string, gateway_ip_string, p_recipe->socket_config.port);
|
||||
}
|
||||
|
||||
void ControlPrintList(char name[5], uint8_t *number_list, uint16_t length)
|
||||
{
|
||||
printf("\n******************%5s****************\n", name);
|
||||
for (int32_t i = 0;i < length;i ++) {
|
||||
printf("%03x ", number_list[i]);
|
||||
}
|
||||
printf("\n**************************************\n");
|
||||
}
|
||||
|
||||
int ControlConnectSocket(BasicSocketPlc *p_plc)
|
||||
{
|
||||
if (p_plc->socket >= 0)
|
||||
return 0;
|
||||
|
||||
struct sockaddr_in plc_addr_in;
|
||||
plc_addr_in.sin_family = AF_INET;
|
||||
plc_addr_in.sin_port = htons(p_plc->port);
|
||||
|
||||
char ip_string[20] = {0};
|
||||
sprintf(ip_string, "%u.%u.%u.%u", p_plc->ip[0], p_plc->ip[1], p_plc->ip[2], p_plc->ip[3]);
|
||||
plc_addr_in.sin_addr.s_addr = inet_addr(ip_string);
|
||||
memset(&(plc_addr_in.sin_zero), 0, sizeof(plc_addr_in.sin_zero));
|
||||
|
||||
int plc_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int flag = 1;
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
if (setsockopt(plc_socket, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag)) < 0) {
|
||||
printf("Error setting TCP_NODELAY function!\n");
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(plc_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, (socklen_t)sizeof(struct timeval)) < 0) {
|
||||
printf("Error setting SO_SNDTIMEO function!\n");
|
||||
return -2;
|
||||
}
|
||||
if (setsockopt(plc_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, (socklen_t)sizeof(struct timeval)) < 0) {
|
||||
printf("Error setting SO_RCVTIMEO function!\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (plc_socket < 0) {
|
||||
printf("Get socket error!\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (connect(plc_socket, (struct sockaddr*)&plc_addr_in, sizeof(struct sockaddr)) == -1) {
|
||||
printf("Connect plc socket failed!\n");
|
||||
closesocket(plc_socket);
|
||||
return -5;
|
||||
} else {
|
||||
p_plc->socket = plc_socket;
|
||||
printf("Connect plc socket success!\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ControlDisconnectSocket(BasicSocketPlc *p_plc)
|
||||
{
|
||||
if (p_plc->socket < 0)
|
||||
return -1;
|
||||
|
||||
int error = closesocket(p_plc->socket);
|
||||
if (0 == error)
|
||||
p_plc->socket = -1;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int ControlProtocolOpenDef(struct ControlProtocol *control_protocol)
|
||||
{
|
||||
g_circular_area = CircularAreaAppInit(PLC_DATA_LENGTH);
|
||||
if (NULL == g_circular_area) {
|
||||
printf("%s CircularAreaInit error\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
control_protocol->args = (void *)g_circular_area;
|
||||
|
||||
pthread_attr_t attr;
|
||||
attr.schedparam.sched_priority = 19;
|
||||
attr.stacksize = 2048;
|
||||
|
||||
PrivTaskCreate(&recv_plc_data_task, &attr, &ReceivePlcDataTask, control_protocol);
|
||||
PrivTaskStartup(&recv_plc_data_task);
|
||||
}
|
||||
|
||||
int ControlProtocolCloseDef(void)
|
||||
{
|
||||
CircularAreaAppRelease(g_circular_area);
|
||||
|
||||
PrivTaskDelete(recv_plc_data_task, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t GetValueTypeMemorySize(UniformValueType uniform_value_type)
|
||||
{
|
||||
switch (uniform_value_type)
|
||||
{
|
||||
case UNIFORM_BOOL:
|
||||
case UNIFORM_INT8:
|
||||
case UNIFORM_UINT8:
|
||||
return 1;
|
||||
break;
|
||||
case UNIFORM_INT16:
|
||||
case UNIFORM_UINT16:
|
||||
return 2;
|
||||
break;
|
||||
case UNIFORM_INT32:
|
||||
case UNIFORM_UINT32:
|
||||
case UNIFORM_FLOAT:
|
||||
return 4;
|
||||
break;
|
||||
case UNIFORM_DOUBLE:
|
||||
return 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ControlPeripheralInit(struct ControlRecipe *p_recipe)
|
||||
{
|
||||
switch (p_recipe->communication_type)
|
||||
{
|
||||
case 0://Socket Init
|
||||
lwip_config_tcp(0, p_recipe->socket_config.local_ip, p_recipe->socket_config.netmask, p_recipe->socket_config.gateway);
|
||||
break;
|
||||
case 1://Serial Init
|
||||
// Uart485Init(p_recipe->serial_config.baud_rate, p_recipe->serial_config.data_bits,
|
||||
// p_recipe->serial_config.stop_bits, p_recipe->serial_config.check_mode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RecipeBasicInformation(struct ControlRecipe *p_recipe, int protocol_type, cJSON *p_recipe_file_json)
|
||||
{
|
||||
if (protocol_type != (ProtocolType)(cJSON_GetObjectItem(p_recipe_file_json, "protocol_type")->valueint)) {
|
||||
printf("protocol type not match!\n");
|
||||
return -1;
|
||||
}
|
||||
p_recipe->protocol_type = protocol_type;
|
||||
|
||||
p_recipe->device_id = cJSON_GetObjectItem(p_recipe_file_json, "device_id")->valueint;
|
||||
strncpy(p_recipe->device_name, cJSON_GetObjectItem(p_recipe_file_json, "device_name")->valuestring, 20);
|
||||
p_recipe->read_period = cJSON_GetObjectItem(p_recipe_file_json, "read_period")->valueint;
|
||||
p_recipe->communication_type = cJSON_GetObjectItem(p_recipe_file_json, "communication_type")->valueint;
|
||||
|
||||
printf("\n**************** RECIPE BASIC INFORMATION ******************\n");
|
||||
printf("\nprotocol_type: %d, communication_type: %d, device_id: %d, device_name: %s, read_period is %d\n",
|
||||
p_recipe->protocol_type, p_recipe->communication_type, p_recipe->device_id, p_recipe->device_name, p_recipe->read_period);
|
||||
|
||||
switch (p_recipe->communication_type)
|
||||
{
|
||||
case 0://Socket Config
|
||||
ControlBasicSocketConfig(p_recipe, p_recipe_file_json);
|
||||
break;
|
||||
case 1://Serial Config
|
||||
ControlBasicSerialConfig(p_recipe, p_recipe_file_json);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n************************************************************\n");
|
||||
}
|
||||
|
||||
void RecipeReadVariableItem(struct ControlRecipe *p_recipe, int protocol_type, cJSON *p_recipe_file_json)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ProtocolFormatInfo protocol_format_info;
|
||||
memset(&protocol_format_info, 0, sizeof(ProtocolFormatInfo));
|
||||
|
||||
cJSON *read_item_list_json = cJSON_GetObjectItem(p_recipe_file_json, "read_item_list");
|
||||
if (cJSON_IsArray(read_item_list_json)) {
|
||||
/*Get Recipe Variable Item Count and total length*/
|
||||
p_recipe->read_item_count = cJSON_GetArraySize(read_item_list_json);
|
||||
p_recipe->total_data_length = GetRecipeTotalDataLength(read_item_list_json);
|
||||
|
||||
/*Malloc Read Data Pointer, Reference "CONTROL FRAMEWORK READ DATA FORMAT"*/
|
||||
p_recipe->protocol_data = PrivMalloc(sizeof(struct ProtocolData));
|
||||
p_recipe->protocol_data->data = PrivMalloc(CONTROL_DATA_HEAD_LENGTH + p_recipe->total_data_length);
|
||||
p_recipe->protocol_data->data_length = CONTROL_DATA_HEAD_LENGTH + p_recipe->total_data_length;
|
||||
memset(p_recipe->protocol_data->data, 0, p_recipe->protocol_data->data_length);
|
||||
|
||||
/*Init The Control Protocol*/
|
||||
ControlProtocolInitDesc(p_recipe, protocol_init);
|
||||
|
||||
/*Format Data Header, Reference "CONTROL FRAMEWORK READ DATA FORMAT"*/
|
||||
FormatDataHeader(p_recipe);
|
||||
|
||||
for (uint16_t read_item_index = 0; read_item_index < p_recipe->read_item_count; read_item_index ++) {
|
||||
cJSON *read_single_item_json = cJSON_GetArrayItem(read_item_list_json, read_item_index);
|
||||
|
||||
protocol_format_info.read_single_item_json = read_single_item_json;
|
||||
protocol_format_info.read_item_index = read_item_index;
|
||||
|
||||
/*Format Protocol Cmd By Analyze Variable Item One By One*/
|
||||
ret = p_recipe->ControlProtocolFormatCmd(p_recipe, &protocol_format_info);
|
||||
if (ret < 0) {
|
||||
printf("%s read %d item failed!\n", __func__, read_item_index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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_def.h
|
||||
* @brief DEFINE code for control framework
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-10-08
|
||||
*/
|
||||
|
||||
#ifndef CONTROL_DEF_H
|
||||
#define CONTROL_DEF_H
|
||||
|
||||
#include <transform.h>
|
||||
#include <list.h>
|
||||
#include <circular_area_app.h>
|
||||
#include <control.h>
|
||||
|
||||
#ifdef LIB_USING_CJSON
|
||||
#include <cJSON.h>
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_LWIP
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/sockets.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CONTROL_PARAM_CHECK(param) \
|
||||
do \
|
||||
{ \
|
||||
if(NULL == param) { \
|
||||
KPrintf("CONTROL CHECK FAILED ...%s %d %s is NULL.\n", __FUNCTION__, __LINE__, #param); \
|
||||
return -1; \
|
||||
} \
|
||||
}while (0)
|
||||
|
||||
#ifdef BSP_USING_LWIP
|
||||
#define socket_write lwip_write
|
||||
#define socket_read lwip_read
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNIFORM_BOOL = 1,
|
||||
UNIFORM_INT8,
|
||||
UNIFORM_INT16,
|
||||
UNIFORM_INT32,
|
||||
UNIFORM_UINT8,
|
||||
UNIFORM_UINT16,
|
||||
UNIFORM_UINT32,
|
||||
UNIFORM_DOUBLE,
|
||||
UNIFORM_FLOAT
|
||||
}UniformValueType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t ip[4];
|
||||
uint16_t port;
|
||||
int32_t socket;
|
||||
int8_t secondary_connect_flag;//0: enble, no connected; 1: enable, connected; -1: disable
|
||||
}BasicSocketPlc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t command_length;
|
||||
uint16_t data_size;
|
||||
uint8_t *p_command;
|
||||
uint8_t *p_data;
|
||||
}BasicPlcDataInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cJSON *read_single_item_json;
|
||||
uint16_t read_item_index;//Variable item index(1 ++)
|
||||
}ProtocolFormatInfo;
|
||||
|
||||
struct ProtocolData
|
||||
{
|
||||
uint8_t *data;
|
||||
uint16_t data_length;
|
||||
};
|
||||
|
||||
struct SerialConfig
|
||||
{
|
||||
uint32_t baud_rate;
|
||||
uint8_t data_bits;
|
||||
uint8_t stop_bits;
|
||||
uint8_t check_mode;
|
||||
};
|
||||
|
||||
struct SocketConfig
|
||||
{
|
||||
uint16_t port;
|
||||
uint8_t plc_ip[4];
|
||||
uint8_t local_ip[4];
|
||||
uint8_t gateway[4];
|
||||
uint8_t netmask[4];
|
||||
};
|
||||
|
||||
struct ControlRecipe
|
||||
{
|
||||
char device_name[20];
|
||||
uint16_t device_id;
|
||||
uint16_t read_period;
|
||||
uint16_t read_item_count;
|
||||
uint16_t total_data_length;
|
||||
uint8_t communication_type;
|
||||
|
||||
ProtocolType protocol_type;
|
||||
|
||||
void *read_item;
|
||||
|
||||
struct SerialConfig serial_config;
|
||||
struct SocketConfig socket_config;
|
||||
|
||||
struct ProtocolData *protocol_data;
|
||||
|
||||
int (*ControlProtocolFormatCmd)(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info);
|
||||
};
|
||||
|
||||
/*Get Value Type Memory Size*/
|
||||
uint8_t GetValueTypeMemorySize(UniformValueType uniform_value_type);
|
||||
|
||||
/*Get basic information from recipe file*/
|
||||
int RecipeBasicInformation(struct ControlRecipe *p_recipe, int protocol_type, cJSON *p_recipe_file_json);
|
||||
|
||||
/*Get the variable need to read from recipe file*/
|
||||
void RecipeReadVariableItem(struct ControlRecipe *p_recipe, int protocol_type, cJSON *p_recipe_file_json);
|
||||
|
||||
int ControlPeripheralInit(struct ControlRecipe *p_recipe);
|
||||
|
||||
void ControlPrintList(char name[5], uint8_t *number_list, uint16_t length);
|
||||
|
||||
int ControlConnectSocket(BasicSocketPlc *p_plc);
|
||||
|
||||
int ControlDisconnectSocket(BasicSocketPlc *p_plc);
|
||||
|
||||
int ControlProtocolOpenDef(struct ControlProtocol *control_protocol);
|
||||
|
||||
int ControlProtocolCloseDef(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,21 +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 control_file.c
|
||||
* @brief control relative file operation
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-37
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file control_file.h
|
||||
* @brief control file function relative API
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-09-27
|
||||
*/
|
||||
|
||||
#ifndef CONTROL_FILE_H
|
||||
#define CONTROL_FILE_H
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user