forked from xuos/xiuos
add CIP Protocol
This commit is contained in:
parent
242c7d66d2
commit
51299c6b79
|
@ -1,3 +1,3 @@
|
||||||
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence
|
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence ab
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
SRC_FILES := ab_l30.c
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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 ab_l30.c
|
||||||
|
* @brief PLC ABB L30 app
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2022.9.27
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <control.h>
|
||||||
|
|
||||||
|
void Controlabl30Test(void)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint16_t read_data_length = 0;
|
||||||
|
uint8_t read_data[1024] = {0};
|
||||||
|
ControlProtocolType CIP_protocol = ControlProtocolFind();
|
||||||
|
if (NULL == CIP_protocol) {
|
||||||
|
printf("%s get CIP protocol %p failed\n", __func__, CIP_protocol);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s get CIP protocol %p successfull\n", __func__, CIP_protocol);
|
||||||
|
if (CONTROL_REGISTERED == CIP_protocol->protocol_status) {
|
||||||
|
ControlProtocolOpen(CIP_protocol);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
read_data_length = ControlProtocolRead(CIP_protocol, read_data, sizeof(read_data));
|
||||||
|
printf("%s read [%d] CIP data %d using receipe file\n", __func__, i, read_data_length);
|
||||||
|
i++;
|
||||||
|
PrivTaskDelay(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ControlProtocolClose(CIP_protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(Controlabl30Test, Ab Plc CIP Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -27,3 +27,11 @@ config CONTROL_PROTOCOL_S7
|
||||||
if CONTROL_PROTOCOL_S7
|
if CONTROL_PROTOCOL_S7
|
||||||
source "$APP_DIR/Framework/control/plc_protocol/s7/Kconfig"
|
source "$APP_DIR/Framework/control/plc_protocol/s7/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
config CONTROL_PROTOCOL_CIP
|
||||||
|
bool "Using cip control protocol"
|
||||||
|
default n
|
||||||
|
select CONTROL_USING_SOCKET
|
||||||
|
if CONTROL_PROTOCOL_CIP
|
||||||
|
source "$APP_DIR/Framework/control/plc_protocol/cip/Kconfig"
|
||||||
|
endif
|
||||||
|
|
|
@ -14,4 +14,8 @@ ifeq ($(CONFIG_CONTROL_PROTOCOL_S7), y)
|
||||||
SRC_DIR := s7
|
SRC_DIR := s7
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_CONTROL_PROTOCOL_CIP), y)
|
||||||
|
SRC_DIR := cip
|
||||||
|
endif
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
SRC_FILES := $(wildcard ./*.c)
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,394 @@
|
||||||
|
#include "ab_cip_helper.h"
|
||||||
|
#include "ab_cip.h"
|
||||||
|
#include "ab_cip_private.h"
|
||||||
|
|
||||||
|
// #include "socket.h"
|
||||||
|
#include "cip_socket.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
// #include <sys/socket.h>
|
||||||
|
// #include <arpa/inet.h>
|
||||||
|
#include <sockets.h>
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int port = 102;
|
||||||
|
char ip_address[64] = {0};
|
||||||
|
bool ab_cip_connect(char *ip_addr, int port, int slot, int *fd)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
int temp_fd = -1;
|
||||||
|
g_plc_slot = slot;
|
||||||
|
|
||||||
|
temp_fd = socket_open_tcp_client_socket(ip_addr, port);
|
||||||
|
*fd = temp_fd;
|
||||||
|
|
||||||
|
printf("%d %s %d\n",temp_fd,__func__,__LINE__);
|
||||||
|
|
||||||
|
if (temp_fd >= 0)
|
||||||
|
ret = initialization_on_connect(temp_fd);
|
||||||
|
|
||||||
|
printf("%d %s %d\n",ret,__func__,__LINE__);
|
||||||
|
|
||||||
|
if (!ret && temp_fd > 0)
|
||||||
|
{
|
||||||
|
socket_close_tcp_socket(temp_fd);
|
||||||
|
*fd = -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
bool ab_cip_disconnect(int fd)
|
||||||
|
{
|
||||||
|
socket_close_tcp_socket(fd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
cip_error_code_e ab_cip_read_bool(int fd, const char *address, bool *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 1, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length > 0)
|
||||||
|
{
|
||||||
|
*val = (bool)read_data.data[0];
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_short(int fd, const char *address, short *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 1, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 2)
|
||||||
|
{
|
||||||
|
*val = bytes2short(read_data.data);
|
||||||
|
}
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_ushort(int fd, const char *address, ushort *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 1, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 2)
|
||||||
|
{
|
||||||
|
*val = bytes2ushort(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_int32(int fd, const char *address, int32 *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 4, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 4)
|
||||||
|
{
|
||||||
|
*val = bytes2int32(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_uint32(int fd, const char *address, uint32 *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 4, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 2)
|
||||||
|
{
|
||||||
|
*val = bytes2uint32(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_int64(int fd, const char *address, int64 *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 8, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 8)
|
||||||
|
{
|
||||||
|
*val = bytes2bigInt(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_uint64(int fd, const char *address, uint64 *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 8, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 8)
|
||||||
|
{
|
||||||
|
*val = bytes2ubigInt(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_float(int fd, const char *address, float *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 1, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 4)
|
||||||
|
{
|
||||||
|
*val = bytes2float(read_data.data);
|
||||||
|
}
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_double(int fd, const char *address, double *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, 8, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length >= 8)
|
||||||
|
{
|
||||||
|
*val = bytes2double(read_data.data);
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_read_string(int fd, const char *address, int *length, char **val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (length != NULL && *length > 0)
|
||||||
|
{
|
||||||
|
byte_array_info read_data;
|
||||||
|
memset(&read_data, 0, sizeof(read_data));
|
||||||
|
ret = read_value(fd, address, *length, &read_data);
|
||||||
|
if (ret == CIP_ERROR_CODE_OK && read_data.length > 6)
|
||||||
|
{
|
||||||
|
*length = 0;
|
||||||
|
uint32 str_length = bytes2uint32(read_data.data + 2);
|
||||||
|
if (str_length > 0)
|
||||||
|
{
|
||||||
|
*length = str_length;
|
||||||
|
char *ret_str = (char *)malloc(str_length + 1);
|
||||||
|
memset(ret_str, 0, str_length + 1);
|
||||||
|
memcpy(ret_str, read_data.data + 6, str_length);
|
||||||
|
*val = ret_str;
|
||||||
|
}
|
||||||
|
RELEASE_DATA(read_data.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_bool(int fd, const char *address, bool val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 2;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
{
|
||||||
|
write_data.data[0] = 0xFF;
|
||||||
|
write_data.data[1] = 0xFF;
|
||||||
|
}
|
||||||
|
ret = write_value(fd, address, 1, 0xC1, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_short(int fd, const char *address, short val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 2;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
short2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC3, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_ushort(int fd, const char *address, ushort val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 2;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
ushort2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC3, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_int32(int fd, const char *address, int32 val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 4;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
int2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC4, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_uint32(int fd, const char *address, uint32 val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 4;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
uint2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC4, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_int64(int fd, const char *address, int64 val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 8;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
bigInt2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC5, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_uint64(int fd, const char *address, uint64 val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 8;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
ubigInt2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xC5, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_float(int fd, const char *address, float val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 4;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
float2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xCA, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_double(int fd, const char *address, double val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL)
|
||||||
|
{
|
||||||
|
int write_len = 8;
|
||||||
|
byte_array_info write_data;
|
||||||
|
memset(&write_data, 0, sizeof(write_data));
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
double2bytes(val, write_data.data);
|
||||||
|
ret = write_value(fd, address, 1, 0xCB, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e ab_cip_write_string(int fd, const char *address, int length, const char *val)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
if (fd > 0 && address != NULL && val != NULL)
|
||||||
|
{
|
||||||
|
byte write_len = length + 1;
|
||||||
|
byte_array_info write_data = {0};
|
||||||
|
write_data.data = (byte *)malloc(write_len);
|
||||||
|
memset(write_data.data, 0, write_len);
|
||||||
|
memcpy(write_data.data, &write_len, 1);
|
||||||
|
memcpy(write_data.data + 1, val, length);
|
||||||
|
write_data.length = write_len;
|
||||||
|
|
||||||
|
char temp_addr[100] = {0};
|
||||||
|
sprintf(temp_addr, "%s", address);
|
||||||
|
ret = write_value(fd, temp_addr, 1, 0xD0, write_data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte get_plc_slot()
|
||||||
|
{
|
||||||
|
return g_plc_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_plc_slot(byte slot)
|
||||||
|
{
|
||||||
|
g_plc_slot = slot;
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef __H_AB_CIP_H__
|
||||||
|
#define __H_AB_CIP_H__
|
||||||
|
|
||||||
|
#include "typedef.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
byte get_plc_slot();
|
||||||
|
void set_plc_slot(byte slot);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool ab_cip_connect(char *ip_addr, int port, int slot, int *fd);
|
||||||
|
bool ab_cip_disconnect(int fd);
|
||||||
|
|
||||||
|
// read
|
||||||
|
cip_error_code_e ab_cip_read_bool(int fd, const char *address, bool *val);
|
||||||
|
cip_error_code_e ab_cip_read_short(int fd, const char *address, short *val);
|
||||||
|
cip_error_code_e ab_cip_read_ushort(int fd, const char *address, ushort *val);
|
||||||
|
cip_error_code_e ab_cip_read_int32(int fd, const char *address, int32 *val);
|
||||||
|
cip_error_code_e ab_cip_read_uint32(int fd, const char *address, uint32 *val);
|
||||||
|
cip_error_code_e ab_cip_read_int64(int fd, const char *address, int64 *val);
|
||||||
|
cip_error_code_e ab_cip_read_uint64(int fd, const char *address, uint64 *val);
|
||||||
|
cip_error_code_e ab_cip_read_float(int fd, const char *address, float *val);
|
||||||
|
cip_error_code_e ab_cip_read_double(int fd, const char *address, double *val);
|
||||||
|
cip_error_code_e ab_cip_read_string(int fd, const char *address, int *length, char **val); // need free val
|
||||||
|
|
||||||
|
// write
|
||||||
|
cip_error_code_e ab_cip_write_bool(int fd, const char *address, bool val);
|
||||||
|
cip_error_code_e ab_cip_write_short(int fd, const char *address, short val);
|
||||||
|
cip_error_code_e ab_cip_write_ushort(int fd, const char *address, ushort val);
|
||||||
|
cip_error_code_e ab_cip_write_int32(int fd, const char *address, int32 val);
|
||||||
|
cip_error_code_e ab_cip_write_uint32(int fd, const char *address, uint32 val);
|
||||||
|
cip_error_code_e ab_cip_write_int64(int fd, const char *address, int64 val);
|
||||||
|
cip_error_code_e ab_cip_write_uint64(int fd, const char *address, uint64 val);
|
||||||
|
cip_error_code_e ab_cip_write_float(int fd, const char *address, float val);
|
||||||
|
cip_error_code_e ab_cip_write_double(int fd, const char *address, double val);
|
||||||
|
cip_error_code_e ab_cip_write_string(int fd, const char *address, int length, const char *val);
|
||||||
|
|
||||||
|
#endif //__H_AB_CIP_H__
|
|
@ -0,0 +1,332 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "ab_cip_helper.h"
|
||||||
|
#include "cip_socket.h"
|
||||||
|
|
||||||
|
extern uint32 g_session;
|
||||||
|
extern byte g_plc_slot;
|
||||||
|
extern byte g_registered_command[28];
|
||||||
|
|
||||||
|
// 从地址构造核心报文
|
||||||
|
byte_array_info build_read_core_command(const char *address, int length)
|
||||||
|
{
|
||||||
|
size_t addr_length = strlen(address);
|
||||||
|
size_t addr_adjust_length = addr_length;
|
||||||
|
if (addr_adjust_length % 2 == 1)
|
||||||
|
addr_adjust_length += 1;
|
||||||
|
|
||||||
|
char *temp_address = (char *)malloc(addr_adjust_length);
|
||||||
|
memset(temp_address, 0, addr_adjust_length);
|
||||||
|
memcpy(temp_address, address, strlen(address));
|
||||||
|
|
||||||
|
const ushort command_len = 9 + 26 + (ushort)addr_adjust_length + 1 + 24;
|
||||||
|
byte *command = (byte *)malloc(command_len);
|
||||||
|
memset(command, 0, command_len);
|
||||||
|
|
||||||
|
command[0] = 0x6F; // 命令
|
||||||
|
command[2] = (byte)((command_len - 24) % 256);
|
||||||
|
command[3] = (byte)((command_len - 24) / 256); // 长度
|
||||||
|
|
||||||
|
char temp_session[4] = {0};
|
||||||
|
uint2bytes(g_session, temp_session);
|
||||||
|
command[4] = temp_session[0];
|
||||||
|
command[5] = temp_session[1];
|
||||||
|
command[6] = temp_session[2];
|
||||||
|
command[7] = temp_session[3]; // 会话句柄
|
||||||
|
|
||||||
|
command[0 + 24] = 0x00;
|
||||||
|
command[1 + 24] = 0x00;
|
||||||
|
command[2 + 24] = 0x00;
|
||||||
|
command[3 + 24] = 0x00; // 接口句柄,默认为0x00000000(CIP)
|
||||||
|
command[4 + 24] = 0x01;
|
||||||
|
command[5 + 24] = 0x0A; // 超时(0x000A)
|
||||||
|
command[6 + 24] = 0x02;
|
||||||
|
command[7 + 24] = 0x00; // 项数(0x0002)
|
||||||
|
command[8 + 24] = 0x00;
|
||||||
|
command[9 + 24] = 0x00; // 空地址项(0x0000)
|
||||||
|
command[10 + 24] = 0x00;
|
||||||
|
command[11 + 24] = 0x00; // 长度(0x0000)
|
||||||
|
command[12 + 24] = 0xB2;
|
||||||
|
command[13 + 24] = 0x00; // 未连接数据项(0x00b2)
|
||||||
|
command[14 + 24] = (byte)((command_len - 16 - 24) % 256); // 后面数据包的长度,等全部生成后在赋值
|
||||||
|
command[15 + 24] = (byte)((command_len - 16 - 24) / 256);
|
||||||
|
command[16 + 24] = 0x52; // 服务类型(0x03请求服务列表,0x52请求标签数据)
|
||||||
|
command[17 + 24] = 0x02; // 请求路径大小
|
||||||
|
command[18 + 24] = 0x20;
|
||||||
|
command[19 + 24] = 0x06; // 请求路径(0x0620)
|
||||||
|
command[20 + 24] = 0x24;
|
||||||
|
command[21 + 24] = 0x01; // 请求路径(0x0124)
|
||||||
|
command[22 + 24] = 0x0A;
|
||||||
|
command[23 + 24] = 0xF0;
|
||||||
|
command[24 + 24] = (byte)((6 + addr_adjust_length) % 256); // CIP指令长度
|
||||||
|
command[25 + 24] = (byte)((6 + addr_adjust_length) / 256);
|
||||||
|
|
||||||
|
command[0 + 24 + 26] = 0x4C; // 读取数据
|
||||||
|
command[1 + 24 + 26] = (byte)((addr_adjust_length + 2) / 2);
|
||||||
|
command[2 + 24 + 26] = 0x91;
|
||||||
|
command[3 + 24 + 26] = (byte)addr_length;
|
||||||
|
memcpy(command + 4 + 24 + 26, temp_address, addr_adjust_length);
|
||||||
|
command[4 + 24 + 26 + addr_adjust_length] = (byte)((length) % 256);
|
||||||
|
command[5 + 24 + 26 + addr_adjust_length] = (byte)((length) / 256);
|
||||||
|
|
||||||
|
command[6 + 24 + 26 + addr_adjust_length] = 0x01;
|
||||||
|
command[7 + 24 + 26 + addr_adjust_length] = 0x00;
|
||||||
|
command[8 + 24 + 26 + addr_adjust_length] = 0x01;
|
||||||
|
command[9 + 24 + 26 + addr_adjust_length] = g_plc_slot;
|
||||||
|
|
||||||
|
byte_array_info ret = {0};
|
||||||
|
ret.data = command;
|
||||||
|
ret.length = command_len;
|
||||||
|
free(temp_address);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_array_info build_write_core_command(const char *address, ushort typeCode, int length, byte_array_info value)
|
||||||
|
{
|
||||||
|
int val_len = 0;
|
||||||
|
if (value.data != NULL)
|
||||||
|
val_len = value.length;
|
||||||
|
|
||||||
|
size_t addr_length = strlen(address);
|
||||||
|
size_t addr_adjust_length = addr_length;
|
||||||
|
if (addr_adjust_length % 2 == 1)
|
||||||
|
addr_adjust_length += 1;
|
||||||
|
|
||||||
|
char *temp_address = (char *)malloc(addr_adjust_length);
|
||||||
|
memset(temp_address, 0, addr_adjust_length);
|
||||||
|
memcpy(temp_address, address, strlen(address));
|
||||||
|
|
||||||
|
const ushort command_len = 8 + 26 + (ushort)addr_adjust_length + val_len + 4 + 24;
|
||||||
|
byte *command = (byte *)malloc(command_len);
|
||||||
|
memset(command, 0, command_len);
|
||||||
|
|
||||||
|
command[0] = 0x6F; // 命令
|
||||||
|
command[2] = (byte)((command_len - 24) % 256);
|
||||||
|
command[3] = (byte)((command_len - 24) / 256); // 长度
|
||||||
|
|
||||||
|
char temp_session[4] = {0};
|
||||||
|
uint2bytes(g_session, temp_session);
|
||||||
|
command[4] = temp_session[0];
|
||||||
|
command[5] = temp_session[1];
|
||||||
|
command[6] = temp_session[2];
|
||||||
|
command[7] = temp_session[3]; // 会话句柄
|
||||||
|
|
||||||
|
command[0 + 24] = 0x00;
|
||||||
|
command[1 + 24] = 0x00;
|
||||||
|
command[2 + 24] = 0x00;
|
||||||
|
command[3 + 24] = 0x00; // 接口句柄,默认为0x00000000(CIP)
|
||||||
|
command[4 + 24] = 0x01;
|
||||||
|
command[5 + 24] = 0x0A; // 超时(0x0001)
|
||||||
|
command[6 + 24] = 0x02;
|
||||||
|
command[7 + 24] = 0x00; // 项数(0x0002)
|
||||||
|
command[8 + 24] = 0x00;
|
||||||
|
command[9 + 24] = 0x00;
|
||||||
|
command[10 + 24] = 0x00;
|
||||||
|
command[11 + 24] = 0x00; // 空地址项(0x0000)
|
||||||
|
command[12 + 24] = 0xB2;
|
||||||
|
command[13 + 24] = 0x00; // 未连接数据项(0x00b2)
|
||||||
|
command[14 + 24] = (byte)((command_len - 16 - 24) % 256);
|
||||||
|
; // 后面数据包的长度,等全部生成后在赋值
|
||||||
|
command[15 + 24] = (byte)((command_len - 16 - 24) / 256);
|
||||||
|
;
|
||||||
|
command[16 + 24] = 0x52; // 服务类型(0x03请求服务列表,0x52请求标签数据)
|
||||||
|
command[17 + 24] = 0x02; // 请求路径大小
|
||||||
|
command[18 + 24] = 0x20;
|
||||||
|
command[19 + 24] = 0x06; // 请求路径(0x0620)
|
||||||
|
command[20 + 24] = 0x24;
|
||||||
|
command[21 + 24] = 0x01; // 请求路径(0x0124)
|
||||||
|
command[22 + 24] = 0x0A;
|
||||||
|
command[23 + 24] = 0xF0;
|
||||||
|
command[24 + 24] = (byte)((8 + val_len + addr_adjust_length) % 256); // CIP指令长度
|
||||||
|
command[25 + 24] = (byte)((8 + val_len + addr_adjust_length) / 256);
|
||||||
|
|
||||||
|
command[0 + 26 + 24] = 0x4D; // 写数据
|
||||||
|
command[1 + 26 + 24] = (byte)((addr_adjust_length + 2) / 2);
|
||||||
|
command[2 + 26 + 24] = 0x91;
|
||||||
|
command[3 + 26 + 24] = (byte)addr_length;
|
||||||
|
memcpy(command + 4 + 26 + 24, temp_address, addr_adjust_length);
|
||||||
|
command[4 + 26 + 24 + addr_adjust_length] = (byte)(typeCode % 256);
|
||||||
|
command[5 + 26 + 24 + addr_adjust_length] = (byte)(typeCode) / 256;
|
||||||
|
command[6 + 26 + 24 + addr_adjust_length] = (byte)(length % 256); // TODO length ??
|
||||||
|
command[7 + 26 + 24 + addr_adjust_length] = (byte)(length / 256);
|
||||||
|
memcpy(command + 8 + 26 + 24 + addr_adjust_length, value.data, value.length);
|
||||||
|
|
||||||
|
command[8 + 26 + 24 + addr_adjust_length + val_len] = 0x01;
|
||||||
|
command[9 + 26 + 24 + addr_adjust_length + val_len] = 0x00;
|
||||||
|
command[10 + 26 + 24 + addr_adjust_length + val_len] = 0x01;
|
||||||
|
command[11 + 26 + 24 + addr_adjust_length + val_len] = g_plc_slot;
|
||||||
|
|
||||||
|
if (value.data != NULL)
|
||||||
|
free(value.data);
|
||||||
|
|
||||||
|
byte_array_info ret = {0};
|
||||||
|
ret.data = command;
|
||||||
|
ret.length = command_len;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e cip_analysis_read_byte(byte_array_info response, byte_array_info *ret)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret_code = CIP_ERROR_CODE_OK;
|
||||||
|
if (response.length == 0)
|
||||||
|
return CIP_ERROR_CODE_FAILED;
|
||||||
|
|
||||||
|
int temp_length = 0;
|
||||||
|
int data_length = 0;
|
||||||
|
if (response.length >= 40) // index 38 is count[ushort]
|
||||||
|
{
|
||||||
|
data_length = bytes2ushort(response.data + 38);
|
||||||
|
if (data_length > 6)
|
||||||
|
{
|
||||||
|
temp_length = data_length - 6;
|
||||||
|
ret->data = (byte *)malloc(temp_length);
|
||||||
|
memset(ret->data, 0, temp_length);
|
||||||
|
memcpy(ret->data, response.data + 46, temp_length);
|
||||||
|
ret->length = temp_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret_code = CIP_ERROR_CODE_UNKOWN;
|
||||||
|
}
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e cip_analysis_write_byte(byte_array_info response)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret_code = CIP_ERROR_CODE_OK;
|
||||||
|
if (response.length == 0)
|
||||||
|
return CIP_ERROR_CODE_FAILED;
|
||||||
|
|
||||||
|
return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
cip_error_code_e read_value(int fd, const char *address, int length, byte_array_info *out_bytes)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_UNKOWN;
|
||||||
|
byte_array_info core_cmd = build_read_core_command(address, length);
|
||||||
|
if (core_cmd.data != NULL)
|
||||||
|
{
|
||||||
|
int need_send = core_cmd.length;
|
||||||
|
int real_sends = socket_send_data(fd, core_cmd.data, need_send);
|
||||||
|
if (real_sends == need_send)
|
||||||
|
{
|
||||||
|
byte temp[BUFFER_SIZE] = {0};
|
||||||
|
memset(temp, 0, BUFFER_SIZE);
|
||||||
|
byte_array_info response = {0};
|
||||||
|
response.data = temp;
|
||||||
|
response.length = BUFFER_SIZE;
|
||||||
|
if (cip_read_response(fd, &response))
|
||||||
|
ret = cip_analysis_read_byte(response, out_bytes);
|
||||||
|
// printf("%s %hu\n",__func__,response.data);
|
||||||
|
}
|
||||||
|
free(core_cmd.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cip_error_code_e write_value(int fd, const char *address, int length, ushort type_code, byte_array_info in_bytes)
|
||||||
|
{
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_UNKOWN;
|
||||||
|
byte_array_info core_cmd = build_write_core_command(address, type_code, length, in_bytes);
|
||||||
|
if (core_cmd.data != NULL)
|
||||||
|
{
|
||||||
|
int need_send = core_cmd.length;
|
||||||
|
int real_sends = socket_send_data(fd, core_cmd.data, need_send);
|
||||||
|
if (real_sends == need_send)
|
||||||
|
{
|
||||||
|
byte temp[BUFFER_SIZE] = {0};
|
||||||
|
memset(temp, 0, BUFFER_SIZE);
|
||||||
|
byte_array_info response = {0};
|
||||||
|
response.data = temp;
|
||||||
|
response.length = BUFFER_SIZE;
|
||||||
|
|
||||||
|
if (cip_read_response(fd, &response))
|
||||||
|
ret = cip_analysis_write_byte(response);
|
||||||
|
}
|
||||||
|
free(core_cmd.data);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initialization_on_connect(int fd)
|
||||||
|
{
|
||||||
|
bool is_ok = false;
|
||||||
|
g_session = 0;
|
||||||
|
|
||||||
|
// First handshake -> send regiseter command
|
||||||
|
byte_array_info temp = {0};
|
||||||
|
int command_len = sizeof(g_registered_command);
|
||||||
|
temp.data = (byte *)malloc(command_len);
|
||||||
|
memcpy(temp.data, g_registered_command, command_len);
|
||||||
|
temp.length = command_len;
|
||||||
|
is_ok = read_data_from_server(fd, temp, &g_session);
|
||||||
|
|
||||||
|
// 返回成功的信号 -> Return a successful signal
|
||||||
|
return is_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cip_read_response(int fd, byte_array_info *response)
|
||||||
|
{
|
||||||
|
bool is_ok = false;
|
||||||
|
int nread = 0;
|
||||||
|
int content_size = 0;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
byte *content = NULL;
|
||||||
|
byte head[HEAD_SIZE];
|
||||||
|
memset(head, 0, HEAD_SIZE);
|
||||||
|
int recv_size = socket_recv_data_one_loop(fd, head, HEAD_SIZE);
|
||||||
|
if (recv_size >= HEAD_SIZE) // header size
|
||||||
|
{
|
||||||
|
content_size = bytes2ushort(head + 2);
|
||||||
|
if (content_size > 0)
|
||||||
|
{
|
||||||
|
content = (byte *)malloc(content_size);
|
||||||
|
memset(content, 0, content_size);
|
||||||
|
}
|
||||||
|
recv_size = socket_recv_data(fd, content, content_size);
|
||||||
|
if (recv_size == content_size)
|
||||||
|
{
|
||||||
|
response->length = HEAD_SIZE + content_size;
|
||||||
|
response->data = (byte *)malloc(response->length);
|
||||||
|
memset(response->data, 0, response->length);
|
||||||
|
memcpy(response->data, head, HEAD_SIZE);
|
||||||
|
memcpy(response->data + HEAD_SIZE, content, content_size);
|
||||||
|
|
||||||
|
is_ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(content);
|
||||||
|
}
|
||||||
|
return is_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read_data_from_server(int fd, byte_array_info send, int *session)
|
||||||
|
{
|
||||||
|
bool is_ok = false;
|
||||||
|
int need_send = send.length;
|
||||||
|
int real_sends = socket_send_data(fd, send.data, need_send);
|
||||||
|
if (real_sends == need_send)
|
||||||
|
{
|
||||||
|
byte_array_info response = {0};
|
||||||
|
is_ok = cip_read_response(fd, &response);
|
||||||
|
if (is_ok)
|
||||||
|
{
|
||||||
|
is_ok = false;
|
||||||
|
if (response.length > 8)
|
||||||
|
{
|
||||||
|
*session = bytes2uint32(response.data + 4);
|
||||||
|
is_ok = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.data != NULL)
|
||||||
|
free(response.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is_ok;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef __H_AB_CIP_HELPER_H__
|
||||||
|
#define __H_AB_CIP_HELPER_H__
|
||||||
|
#include "utill.h"
|
||||||
|
|
||||||
|
#define RELEASE_DATA(addr) \
|
||||||
|
{ \
|
||||||
|
if (addr != NULL) \
|
||||||
|
{ \
|
||||||
|
free(addr); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
#define HEAD_SIZE 24
|
||||||
|
|
||||||
|
byte_array_info build_read_core_command(const char *address, int length);
|
||||||
|
byte_array_info build_write_core_command(const char *address, ushort typeCode, int length, byte_array_info value);
|
||||||
|
|
||||||
|
cip_error_code_e cip_analysis_read_byte(byte_array_info response, byte_array_info *ret);
|
||||||
|
cip_error_code_e cip_analysis_write_byte(byte_array_info response);
|
||||||
|
|
||||||
|
bool read_data_from_server(int fd, byte_array_info send, int *session);
|
||||||
|
bool cip_read_response(int fd, byte_array_info *response);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
cip_error_code_e read_value(int fd, const char *address, int length, byte_array_info *out_bytes);
|
||||||
|
cip_error_code_e write_value(int fd, const char *address, int length, ushort type_code, byte_array_info in_bytes);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool initialization_on_connect(int fd);
|
||||||
|
|
||||||
|
#endif //__H_AB_CIP_HELPER_H__
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef __H_AB_CIP_PRIVATE_H__
|
||||||
|
#define __H_AB_CIP_PRIVATE_H__
|
||||||
|
#include "typedef.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册命令
|
||||||
|
/// </summary>
|
||||||
|
const byte g_registered_command[] =
|
||||||
|
{
|
||||||
|
0x65, 0x00, // 注册请求
|
||||||
|
0x04, 0x00, // 命令数据长度(单位字节)
|
||||||
|
0x00, 0x00, 0x00, 0x00, // 会话句柄,初始值为0x00000000
|
||||||
|
0x00, 0x00, 0x00, 0x00, // 状态,初始值为0x00000000(状态好)
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 请求通信一方的说明
|
||||||
|
0x00, 0x00, 0x00, 0x00, // 选项,默认为0x00000000
|
||||||
|
0x01, 0x00, // 协议版本(0x0001)
|
||||||
|
0x00, 0x00 // 选项标记(0x0000
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// 会话句柄(由AB PLC生成)
|
||||||
|
uint32 g_session;
|
||||||
|
|
||||||
|
byte g_plc_slot;
|
||||||
|
|
||||||
|
#endif //__H_AB_CIP_PRIVATE_H__
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.33027.164
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ab_plc_cip_net", "ab_plc_cip_net.vcxproj", "{181055E5-C375-4C97-84A2-90CD807A17FD}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Release|x64.Build.0 = Release|x64
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{181055E5-C375-4C97-84A2-90CD807A17FD}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0313BC2F-57C8-4606-B430-4861FF084853}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,177 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{181055E5-C375-4C97-84A2-90CD807A17FD}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>melsec_mc_net</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v142</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<DisableSpecificWarnings>4966</DisableSpecificWarnings>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<DisableSpecificWarnings>4966</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<DisableSpecificWarnings>4966</DisableSpecificWarnings>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<DisableSpecificWarnings>4966</DisableSpecificWarnings>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="ab_cip.c" />
|
||||||
|
<ClCompile Include="ab_cip_helper.c" />
|
||||||
|
<ClCompile Include="main.c" />
|
||||||
|
<ClCompile Include="socket.c" />
|
||||||
|
<ClCompile Include="utill.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="ab_cip.h" />
|
||||||
|
<ClInclude Include="ab_cip_helper.h" />
|
||||||
|
<ClInclude Include="ab_cip_private.h" />
|
||||||
|
<ClInclude Include="socket.h" />
|
||||||
|
<ClInclude Include="typedef.h" />
|
||||||
|
<ClInclude Include="utill.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
|
@ -0,0 +1,312 @@
|
||||||
|
/*
|
||||||
|
* 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 CIP.c
|
||||||
|
* @brief plc protocol CIP Ethernet/IP
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023-4-14
|
||||||
|
*/
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#include <cip.h>
|
||||||
|
#include "ab_cip.h"
|
||||||
|
|
||||||
|
|
||||||
|
CIPReadItem CIP_read_item[1024] = {0};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: S7 Receive Plc Data Task
|
||||||
|
* @param parameter - parameter pointer
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void *ReceivePlcDataTask(void *parameter)
|
||||||
|
{
|
||||||
|
struct ControlProtocol *control_protocol = (struct ControlProtocol *)parameter;
|
||||||
|
ReadPlcDataByRecipe(control_protocol->recipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: S7 Protocol Open
|
||||||
|
* @param control_protocol - control protocol pointer
|
||||||
|
* @return success : 0 error
|
||||||
|
*/
|
||||||
|
int CIPOpen(struct ControlProtocol *control_protocol)
|
||||||
|
{
|
||||||
|
ControlProtocolOpenDef(control_protocol);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: S7 Protocol Close
|
||||||
|
* @param control_protocol - control protocol pointer
|
||||||
|
* @return success : 0 error
|
||||||
|
*/
|
||||||
|
int CIPClose(struct ControlProtocol *control_protocol)
|
||||||
|
{
|
||||||
|
ControlProtocolCloseDef();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: S7 Protocol Read Data
|
||||||
|
* @param control_protocol - control protocol pointer
|
||||||
|
* @param buf - read data buffer pointer
|
||||||
|
* @param len - read data length
|
||||||
|
* @return success : data length error : 0
|
||||||
|
*/
|
||||||
|
int CIPRead(struct ControlProtocol *control_protocol, void *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||||
|
return CircularAreaAppRead(circular_area, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ControlDone CIP_protocol_done =
|
||||||
|
{
|
||||||
|
._open = CIPOpen,
|
||||||
|
._close = CIPClose,
|
||||||
|
._read = CIPRead,
|
||||||
|
._write = NULL,
|
||||||
|
._ioctl = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Push Data Onto a Stack One By One
|
||||||
|
* @param datastack - data stack pointer
|
||||||
|
* @param args - data pointer
|
||||||
|
* @param length - data length
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
void PushDataIntoStack(uint8_t *datastack,uint8_t* args,uint16_t length)
|
||||||
|
{
|
||||||
|
static int index = 8;
|
||||||
|
for(int i =0; i < length; i ++) {
|
||||||
|
datastack[index] = args[i];
|
||||||
|
index++;
|
||||||
|
if(index >= control_protocol->recipe->protocol_data.data_length){
|
||||||
|
index = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_RESULT(ret) \
|
||||||
|
{ \
|
||||||
|
if (ret != 0) \
|
||||||
|
faild_count++; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Read PLC Data By Recipe
|
||||||
|
* @param p_recipe - recipe pointer
|
||||||
|
* @return success : 0 error : -1
|
||||||
|
*/
|
||||||
|
int8_t ReadPlcDataByRecipe(struct ControlRecipe *p_recipe)
|
||||||
|
{
|
||||||
|
static BasicSocketPlc plc_socket = {0};
|
||||||
|
uint16_t data_length = control_protocol->recipe->protocol_data.data_length;
|
||||||
|
uint8_t *CIP_data = control_protocol->recipe->protocol_data.data;
|
||||||
|
struct CircularAreaApp *circular_area = (struct CircularAreaApp *)control_protocol->args;
|
||||||
|
memset(&plc_socket, 0, sizeof(BasicSocketPlc));
|
||||||
|
char plc_ip_string[15] = {0};
|
||||||
|
sprintf(plc_ip_string, "%u.%u.%u.%u",
|
||||||
|
p_recipe->socket_config.plc_ip[0],
|
||||||
|
p_recipe->socket_config.plc_ip[1],
|
||||||
|
p_recipe->socket_config.plc_ip[2],
|
||||||
|
p_recipe->socket_config.plc_ip[3]);
|
||||||
|
char *plc_ip = plc_ip_string;
|
||||||
|
plc_socket.port = control_protocol->recipe->socket_config.port;
|
||||||
|
int fd = -1;
|
||||||
|
int slot = 0;
|
||||||
|
bool ret_con = ab_cip_connect(plc_ip, plc_socket.port, 0, &fd);
|
||||||
|
cip_error_code_e ret = CIP_ERROR_CODE_FAILED;
|
||||||
|
int faild_count = 0;
|
||||||
|
char address[50] = {0};
|
||||||
|
int i = 0;
|
||||||
|
uint8_t val[8] = {0} ;
|
||||||
|
bool all_success = false;
|
||||||
|
bool b_val = true;
|
||||||
|
short s_val = 0;
|
||||||
|
ushort us_val = 0;
|
||||||
|
int i_val = 0;
|
||||||
|
uint32 ui_val = 0;
|
||||||
|
float f_val = 0;
|
||||||
|
double d_val = 0;
|
||||||
|
while (1){
|
||||||
|
if (ret_con || fd > 0)
|
||||||
|
{
|
||||||
|
faild_count = 0;
|
||||||
|
for (i = 0; i < p_recipe->read_item_count; i++)
|
||||||
|
{
|
||||||
|
printf("==============Test count: %d==============\n", i + 1);
|
||||||
|
strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
switch (CIP_read_item[i].value_type)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// strcpy(address, CIP_read_item[i].value_name);//
|
||||||
|
// ret = ab_cip_write_bool(fd, address, val);
|
||||||
|
// printf("Write\t %s \tbool:\t %d, \tret: %d\n", address, val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
b_val = false;
|
||||||
|
ret = ab_cip_read_bool(fd, address, &b_val);
|
||||||
|
// printf("Read\t %s \tbool:\t %d\n", address, b_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&b_val,sizeof(b_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// short w_s_val = 23;
|
||||||
|
// strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_short(fd, address, w_s_val);
|
||||||
|
// printf("Write\t %s \tshort:\t %d, \tret: %d\n", address, w_s_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
ret = ab_cip_read_short(fd, address, &s_val);
|
||||||
|
// printf("Read\t %s \tshort:\t %d\n", address, s_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&s_val,sizeof(s_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// int32 w_i_val = 12345;
|
||||||
|
strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_int32(fd, address, w_i_val);
|
||||||
|
// printf("Write\t %s \tint32:\t %d, \tret: %d\n", address, w_i_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
|
||||||
|
ret = ab_cip_read_int32(fd, address, &i_val);
|
||||||
|
// printf("Read\t %s \tint32:\t %d\n", address, i_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&i_val,sizeof(s_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// ushort w_us_val = 22;
|
||||||
|
strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_ushort(fd, address, w_us_val);
|
||||||
|
// printf("Write\t %s \tushort:\t %d, \tret: %d\n", address, w_us_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
ret = ab_cip_read_ushort(fd, address, &us_val);
|
||||||
|
// printf("Read\t %s \tushort:\t %d\n", address, us_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&us_val,sizeof(us_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
// //////////////////////////////////////////////////////////////////////////
|
||||||
|
// uint32 w_ui_val = 22345;
|
||||||
|
strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_uint32(fd, address, w_ui_val);
|
||||||
|
// printf("Write\t %s \tuint32:\t %d, \tret: %d\n", address, w_ui_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
ret = ab_cip_read_uint32(fd, address, &ui_val);
|
||||||
|
// printf("Read\t %s \tuint32:\t %d\n", address, ui_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&ui_val,sizeof(us_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// double w_d_val = 12345.6789;
|
||||||
|
strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_double(fd, address, w_d_val);
|
||||||
|
// printf("Write\t %s \tdouble:\t %lf, \tret: %d\n", address, w_d_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
ret = ab_cip_read_double(fd, address, &d_val);
|
||||||
|
// printf("Read\t %s \tdouble:\t %lf\n", address, d_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&d_val,sizeof(us_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// float w_f_val = 32.454f;
|
||||||
|
// strcpy(address, CIP_read_item[i].value_name);
|
||||||
|
// ret = ab_cip_write_float(fd, address, w_f_val);
|
||||||
|
// printf("Write\t %s \tfloat:\t %f, \tret: %d\n", address, w_f_val, ret);
|
||||||
|
// GET_RESULT(ret);
|
||||||
|
|
||||||
|
ret = ab_cip_read_float(fd, address, &f_val);
|
||||||
|
// printf("Read\t %s \tfloat:\t %f\n", address, f_val);
|
||||||
|
GET_RESULT(ret);
|
||||||
|
memcpy(val,&f_val,sizeof(us_val));
|
||||||
|
PushDataIntoStack(CIP_data,val,1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("value type no found!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ControlPrintfList("CIP RECV", CIP_data, data_length);
|
||||||
|
}
|
||||||
|
printf("All Failed count: %d\n", faild_count);
|
||||||
|
if(faild_count != 0)
|
||||||
|
{
|
||||||
|
ab_cip_disconnect(fd);
|
||||||
|
system("pause");
|
||||||
|
}
|
||||||
|
/*read all variable item data, put them into circular_area*/
|
||||||
|
printf("%s get %d item %d length\n", __func__, i, data_length);
|
||||||
|
CircularAreaAppWrite(circular_area, CIP_data, data_length, 0);
|
||||||
|
PrivTaskDelay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: CIP Protocol Cmd Generate
|
||||||
|
* @param p_recipe - recipe pointer
|
||||||
|
* @param protocol_format_info - protocol format info pointer
|
||||||
|
* @return success : 0 error : -1
|
||||||
|
*/
|
||||||
|
int CIPProtocolFormatCmd(struct ControlRecipe *p_recipe, ProtocolFormatInfo *protocol_format_info)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int i = protocol_format_info->read_item_index;
|
||||||
|
// CIPReadItem *CIP_read_item = (CIPReadItem *)p_recipe->read_item;
|
||||||
|
CIP_read_item[i].value_type = cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_type")->valueint;
|
||||||
|
strncpy(CIP_read_item[i].value_name, cJSON_GetObjectItem(protocol_format_info->read_single_item_json, "value_name")->valuestring, 20);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: CIP Protocol Init
|
||||||
|
* @param p_recipe - recipe pointer
|
||||||
|
* @return success : 0 error : -1
|
||||||
|
*/
|
||||||
|
int CipProtocolInit(struct ControlRecipe *p_recipe)
|
||||||
|
{
|
||||||
|
p_recipe->read_item = PrivMalloc(sizeof(CIPReadItem) * p_recipe->read_item_count);
|
||||||
|
if (NULL == p_recipe->read_item) {
|
||||||
|
PrivFree(p_recipe->read_item);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(p_recipe->read_item, 0, sizeof(CIPReadItem));
|
||||||
|
p_recipe->ControlProtocolFormatCmd = CIPProtocolFormatCmd;
|
||||||
|
p_recipe->done = &CIP_protocol_done;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
#include "cip_socket.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
|
||||||
|
#else
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
// #include <sys/socket.h>
|
||||||
|
#include <sockets.h>
|
||||||
|
// #include <arpa/inet.h>
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int socket_send_data(int fd, void *buf, int nbytes)
|
||||||
|
{
|
||||||
|
int nleft, nwritten;
|
||||||
|
char *ptr = (char *)buf;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nleft = nbytes;
|
||||||
|
while (nleft > 0)
|
||||||
|
{
|
||||||
|
nwritten = send(fd, ptr, nleft, 0);
|
||||||
|
if (nwritten <= 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nleft -= nwritten;
|
||||||
|
ptr += nwritten;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nbytes - nleft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_recv_data(int fd, void *buf, int nbytes)
|
||||||
|
{
|
||||||
|
int nleft, nread;
|
||||||
|
char *ptr = (char *)buf;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nleft = nbytes;
|
||||||
|
while (nleft > 0)
|
||||||
|
{
|
||||||
|
nread = recv(fd, ptr, nleft, 0);
|
||||||
|
if (nread == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (nread < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nleft -= nread;
|
||||||
|
ptr += nread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nbytes - nleft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_recv_data_one_loop(int fd, void *buf, int nbytes)
|
||||||
|
{
|
||||||
|
int nleft, nread;
|
||||||
|
char *ptr = (char *)buf;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
nleft = nbytes;
|
||||||
|
while (nleft > 0)
|
||||||
|
{
|
||||||
|
nread = recv(fd, ptr, nleft, 0);
|
||||||
|
if (nread == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (nread < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nleft -= nread;
|
||||||
|
ptr += nread;
|
||||||
|
|
||||||
|
// 目前只接收一次
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nbytes - nleft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int socket_open_tcp_client_socket(char *destIp, short destPort)
|
||||||
|
{
|
||||||
|
int sockFd = 0;
|
||||||
|
struct sockaddr_in serverAddr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //IPPROTO_TCP
|
||||||
|
|
||||||
|
printf("%d %s %d\n",sockFd ,__func__,__LINE__);
|
||||||
|
|
||||||
|
if (sockFd < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
}
|
||||||
|
|
||||||
|
memset((char *)&serverAddr, 0, sizeof(serverAddr));
|
||||||
|
serverAddr.sin_family = AF_INET;
|
||||||
|
serverAddr.sin_addr.s_addr = inet_addr(destIp);
|
||||||
|
serverAddr.sin_port = (uint16_t)htons((uint16_t)destPort);
|
||||||
|
|
||||||
|
ret = connect(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
socket_close_tcp_socket(sockFd);
|
||||||
|
sockFd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int timeout = 5000; // 5s
|
||||||
|
ret = setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout));
|
||||||
|
ret = setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));
|
||||||
|
#else
|
||||||
|
struct timeval timeout = {5, 0}; // 3s
|
||||||
|
ret = setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout));
|
||||||
|
ret = setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return sockFd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void socket_close_tcp_socket(int sockFd)
|
||||||
|
{
|
||||||
|
if (sockFd > 0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
closesocket(sockFd);
|
||||||
|
#else
|
||||||
|
close(sockFd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tinet_ntoa(char *ipstr, unsigned int ip)
|
||||||
|
{
|
||||||
|
sprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef __SOCKET_H_
|
||||||
|
#define __SOCKET_H_
|
||||||
|
|
||||||
|
#include "utill.h"
|
||||||
|
|
||||||
|
int socket_send_data(int fd, void *ptr, int nbytes);
|
||||||
|
int socket_recv_data(int fd, void *ptr, int nbytes);
|
||||||
|
int socket_recv_data_one_loop(int fd, void *ptr, int nbytes);
|
||||||
|
int socket_open_tcp_client_socket(char *ip, short port);
|
||||||
|
void socket_close_tcp_socket(int sockFd);
|
||||||
|
|
||||||
|
#endif //__SOCKET_H_
|
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef __H_TYPEDEF_H__
|
||||||
|
#define __H_TYPEDEF_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short ushort;
|
||||||
|
typedef signed int int32;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef long long int64;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
|
||||||
|
typedef enum _tag_cip_error_code
|
||||||
|
{
|
||||||
|
CIP_ERROR_CODE_OK = 0, // 成功
|
||||||
|
CIP_ERROR_CODE_FAILED = 1, // 错误
|
||||||
|
CIP_ERROR_CODE_UNKOWN = 99, // 未知错误
|
||||||
|
} cip_error_code_e;
|
||||||
|
|
||||||
|
#endif // !__H_TYPEDEF_H__
|
|
@ -0,0 +1,383 @@
|
||||||
|
#include "utill.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _WS2_32_WINSOCK_SWAP_LONG(l) \
|
||||||
|
((((l) >> 24) & 0x000000FFL) | \
|
||||||
|
(((l) >> 8) & 0x0000FF00L) | \
|
||||||
|
(((l) << 8) & 0x00FF0000L) | \
|
||||||
|
(((l) << 24) & 0xFF000000L))
|
||||||
|
|
||||||
|
#define _WS2_32_WINSOCK_SWAP_LONGLONG(l) \
|
||||||
|
((((l) >> 56) & 0x00000000000000FFLL) | \
|
||||||
|
(((l) >> 40) & 0x000000000000FF00LL) | \
|
||||||
|
(((l) >> 24) & 0x0000000000FF0000LL) | \
|
||||||
|
(((l) >> 8) & 0x00000000FF000000LL) | \
|
||||||
|
(((l) << 8) & 0x000000FF00000000LL) | \
|
||||||
|
(((l) << 24) & 0x0000FF0000000000LL) | \
|
||||||
|
(((l) << 40) & 0x00FF000000000000LL) | \
|
||||||
|
(((l) << 56) & 0xFF00000000000000LL))
|
||||||
|
|
||||||
|
void short2bytes(short i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 2;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)((0xff00 & i) >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
short bytes2short(byte *bytes)
|
||||||
|
{
|
||||||
|
short iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((short)bytes[1] << 8) & 0xFF00);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ushort2bytes(ushort i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 2;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)((0xff00 & i) >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort bytes2ushort(byte *bytes)
|
||||||
|
{
|
||||||
|
ushort iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((ushort)bytes[1] << 8) & 0xFF00);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void int2bytes(int32 i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 4;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)((0xff00 & i) >> 8);
|
||||||
|
bytes[2] = (byte)((0xff0000 & i) >> 16);
|
||||||
|
bytes[3] = (byte)((0xff000000 & i) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 bytes2int32(byte *bytes)
|
||||||
|
{
|
||||||
|
int32 iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((int32)bytes[1] << 8) & 0xFF00);
|
||||||
|
iRetVal |= (((int32)bytes[2] << 16) & 0xFF0000);
|
||||||
|
iRetVal |= (((int32)bytes[3] << 24) & 0xFF000000);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uint2bytes(uint32 i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 4;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)((0xff00 & i) >> 8);
|
||||||
|
bytes[2] = (byte)((0xff0000 & i) >> 16);
|
||||||
|
bytes[3] = (byte)((0xff000000 & i) >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 bytes2uint32(byte *bytes)
|
||||||
|
{
|
||||||
|
uint32 iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((uint32)bytes[1] << 8) & 0xFF00);
|
||||||
|
iRetVal |= (((uint32)bytes[2] << 16) & 0xFF0000);
|
||||||
|
iRetVal |= (((uint32)bytes[3] << 24) & 0xFF000000);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bigInt2bytes(int64 i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 8;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)(0xff & (i >> 8));
|
||||||
|
bytes[2] = (byte)(0xff & (i >> 16));
|
||||||
|
bytes[3] = (byte)(0xff & (i >> 24));
|
||||||
|
bytes[4] = (byte)(0xff & (i >> 32));
|
||||||
|
bytes[5] = (byte)(0xff & (i >> 40));
|
||||||
|
bytes[6] = (byte)(0xff & (i >> 48));
|
||||||
|
bytes[7] = (byte)(0xff & (i >> 56));
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 bytes2bigInt(byte *bytes)
|
||||||
|
{
|
||||||
|
int64 iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((int64)bytes[1] << 8) & 0xFF00);
|
||||||
|
iRetVal |= (((int64)bytes[2] << 16) & 0xFF0000);
|
||||||
|
iRetVal |= (((int64)bytes[3] << 24) & 0xFF000000);
|
||||||
|
iRetVal |= (((int64)bytes[4] << 32) & 0xFF00000000);
|
||||||
|
iRetVal |= (((int64)bytes[5] << 40) & 0xFF0000000000);
|
||||||
|
iRetVal |= (((int64)bytes[6] << 48) & 0xFF000000000000);
|
||||||
|
iRetVal |= (((int64)bytes[7] << 56) & 0xFF00000000000000);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ubigInt2bytes(uint64 i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 8;
|
||||||
|
memset(bytes, 0, sizeof(byte) * size);
|
||||||
|
bytes[0] = (byte)(0xff & i);
|
||||||
|
bytes[1] = (byte)(0xff & (i >> 8));
|
||||||
|
bytes[2] = (byte)(0xff & (i >> 16));
|
||||||
|
bytes[3] = (byte)(0xff & (i >> 24));
|
||||||
|
bytes[4] = (byte)(0xff & (i >> 32));
|
||||||
|
bytes[5] = (byte)(0xff & (i >> 40));
|
||||||
|
bytes[6] = (byte)(0xff & (i >> 48));
|
||||||
|
bytes[7] = (byte)(0xff & (i >> 56));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 bytes2ubigInt(byte *bytes)
|
||||||
|
{
|
||||||
|
uint64 iRetVal = bytes[0] & 0xFF;
|
||||||
|
iRetVal |= (((uint64)bytes[1] << 8) & 0xFF00);
|
||||||
|
iRetVal |= (((uint64)bytes[2] << 16) & 0xFF0000);
|
||||||
|
iRetVal |= (((uint64)bytes[3] << 24) & 0xFF000000);
|
||||||
|
iRetVal |= (((uint64)bytes[4] << 32) & 0xFF00000000);
|
||||||
|
iRetVal |= (((uint64)bytes[5] << 40) & 0xFF0000000000);
|
||||||
|
iRetVal |= (((uint64)bytes[6] << 48) & 0xFF000000000000);
|
||||||
|
iRetVal |= (((uint64)bytes[7] << 56) & 0xFF00000000000000);
|
||||||
|
return iRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void float2bytes(float i, byte *bytes)
|
||||||
|
{
|
||||||
|
int size = 4;
|
||||||
|
int temp = *(int *)&i;
|
||||||
|
int2bytes(temp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
float bytes2float(byte *bytes)
|
||||||
|
{
|
||||||
|
int temp = bytes2int32(bytes);
|
||||||
|
return *(float *)&temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void double2bytes(double i, byte *bytes)
|
||||||
|
{
|
||||||
|
int64 temp = *(int64 *)&i;
|
||||||
|
bigInt2bytes(temp, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
double bytes2double(byte *bytes)
|
||||||
|
{
|
||||||
|
int64 temp = bytes2bigInt(bytes);
|
||||||
|
return *(double *)&temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int str_to_int(const char *address)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
ret = (int)strtol(address, NULL, 10);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void str_toupper(char *input)
|
||||||
|
// {
|
||||||
|
// if (input == NULL)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// int32 len = strlen(input), i = 0;
|
||||||
|
// for (; i < len; i++)
|
||||||
|
// input[i] = toupper(input[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void str_tolower(char *input)
|
||||||
|
// {
|
||||||
|
// if (input == NULL)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// int32 len = strlen(input), i = 0;
|
||||||
|
// for (; i < len; i++)
|
||||||
|
// input[i] = tolower(input[i]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ×Ö·û´®originÒÔ×Ö·û´®prefix¿ªÍ·£¬·µ»Ø0£»·ñÔò·µ»Ø1£»Òì³£·µ»Ø-1
|
||||||
|
*/
|
||||||
|
int str_start_with(const char *origin, char *prefix)
|
||||||
|
{
|
||||||
|
if (origin == NULL ||
|
||||||
|
prefix == NULL ||
|
||||||
|
strlen(prefix) > strlen(origin))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = strlen(prefix), i;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (origin[i] != prefix[i])
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ×Ö·û´®originÒÔ×Ö·û´®end½á⣬·µ»Ø0£»·ñÔò·µ»Ø1£»Òì³£·µ»Ø-1
|
||||||
|
*/
|
||||||
|
int str_end_with(const char *origin, char *end)
|
||||||
|
{
|
||||||
|
if (origin == NULL ||
|
||||||
|
end == NULL ||
|
||||||
|
strlen(end) > strlen(origin))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = strlen(end);
|
||||||
|
int m = strlen(origin);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (origin[m - i - 1] != end[n - i - 1])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 htonf_(float value)
|
||||||
|
{
|
||||||
|
uint32 Tempval;
|
||||||
|
uint32 Retval;
|
||||||
|
Tempval = *(uint32 *)(&value);
|
||||||
|
Retval = _WS2_32_WINSOCK_SWAP_LONG(Tempval);
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ntohf_(uint32 value)
|
||||||
|
{
|
||||||
|
const uint32 Tempval = _WS2_32_WINSOCK_SWAP_LONG(value);
|
||||||
|
float Retval;
|
||||||
|
*((uint32 *)&Retval) = Tempval;
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 htond_(double value)
|
||||||
|
{
|
||||||
|
uint64 Tempval;
|
||||||
|
uint64 Retval;
|
||||||
|
Tempval = *(uint64 *)(&value);
|
||||||
|
Retval = _WS2_32_WINSOCK_SWAP_LONGLONG(Tempval);
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ntohd_(uint64 value)
|
||||||
|
{
|
||||||
|
const uint64 Tempval = _WS2_32_WINSOCK_SWAP_LONGLONG(value);
|
||||||
|
double Retval;
|
||||||
|
*((uint64 *)&Retval) = Tempval;
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 htonll_(uint64 Value)
|
||||||
|
{
|
||||||
|
const uint64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG(Value);
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 ntohll_(uint64 Value)
|
||||||
|
{
|
||||||
|
const uint64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG(Value);
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
itoa
|
||||||
|
|
||||||
|
Convert integer to string
|
||||||
|
|
||||||
|
PARAMS:
|
||||||
|
- value A 64-bit number to convert
|
||||||
|
- str Destination buffer; should be 66 characters long for radix2, 24 - radix8, 22 - radix10, 18 - radix16.
|
||||||
|
- radix Radix must be in range -36 .. 36. Negative values used for signed numbers.
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *cip_itoa(unsigned long long value, char str[], int radix)
|
||||||
|
{
|
||||||
|
char buf[66];
|
||||||
|
char *dest = buf + sizeof(buf);
|
||||||
|
bool sign = false;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
memcpy(str, "0", 2);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radix < 0)
|
||||||
|
{
|
||||||
|
radix = -radix;
|
||||||
|
if ((long long)value < 0)
|
||||||
|
{
|
||||||
|
value = -value;
|
||||||
|
sign = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*--dest = '\0';
|
||||||
|
|
||||||
|
switch (radix)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
while (value)
|
||||||
|
{
|
||||||
|
*--dest = '0' + (value & 0xF);
|
||||||
|
if (*dest > '9')
|
||||||
|
*dest += 'A' - '9' - 1;
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
while (value)
|
||||||
|
{
|
||||||
|
*--dest = '0' + (value % 10);
|
||||||
|
value /= 10;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
while (value)
|
||||||
|
{
|
||||||
|
*--dest = '0' + (value & 7);
|
||||||
|
value >>= 3;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
while (value)
|
||||||
|
{
|
||||||
|
*--dest = '0' + (value & 1);
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // The slow version, but universal
|
||||||
|
while (value)
|
||||||
|
{
|
||||||
|
*--dest = '0' + (value % radix);
|
||||||
|
if (*dest > '9')
|
||||||
|
*dest += 'A' - '9' - 1;
|
||||||
|
value /= radix;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sign)
|
||||||
|
*--dest = '-';
|
||||||
|
|
||||||
|
memcpy(str, dest, buf + sizeof(buf) - dest);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef __UTILL_H__
|
||||||
|
#define __UTILL_H__
|
||||||
|
|
||||||
|
#include "typedef.h"
|
||||||
|
|
||||||
|
typedef struct _tag_byte_array_info
|
||||||
|
{
|
||||||
|
byte *data; // 内容
|
||||||
|
int length; // 长度
|
||||||
|
} byte_array_info;
|
||||||
|
|
||||||
|
typedef struct _tag_bool_array_info
|
||||||
|
{
|
||||||
|
bool *data; // 内容
|
||||||
|
int length; // 长度
|
||||||
|
} bool_array_info;
|
||||||
|
|
||||||
|
void short2bytes(short i, byte *bytes);
|
||||||
|
short bytes2short(byte *bytes);
|
||||||
|
|
||||||
|
void ushort2bytes(ushort i, byte *bytes);
|
||||||
|
ushort bytes2ushort(byte *bytes);
|
||||||
|
|
||||||
|
void int2bytes(int32 i, byte *bytes);
|
||||||
|
int32 bytes2int32(byte *bytes);
|
||||||
|
|
||||||
|
void uint2bytes(uint32 i, byte *bytes);
|
||||||
|
uint32 bytes2uint32(byte *bytes);
|
||||||
|
|
||||||
|
void bigInt2bytes(int64 i, byte *bytes);
|
||||||
|
int64 bytes2bigInt(byte *bytes);
|
||||||
|
|
||||||
|
void ubigInt2bytes(uint64 i, byte *bytes);
|
||||||
|
uint64 bytes2ubigInt(byte *bytes);
|
||||||
|
|
||||||
|
void float2bytes(float i, byte *bytes);
|
||||||
|
float bytes2float(byte *bytes);
|
||||||
|
|
||||||
|
void double2bytes(double i, byte *bytes);
|
||||||
|
double bytes2double(byte *bytes);
|
||||||
|
|
||||||
|
int str_to_int(const char *address);
|
||||||
|
void str_toupper(char *input);
|
||||||
|
void str_tolower(char *input);
|
||||||
|
int str_start_with(const char *origin, char *prefix);
|
||||||
|
|
||||||
|
uint32 htonf_(float value);
|
||||||
|
float ntohf_(uint32 value);
|
||||||
|
uint64 htond_(double value);
|
||||||
|
double ntohd_(uint64 value);
|
||||||
|
uint64 htonll_(uint64 Value);
|
||||||
|
uint64 ntohll_(uint64 Value);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
char *cip_itoa(unsigned long long value, char str[], int radix);
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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 cip.h
|
||||||
|
* @brief plc protocol cip
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2022-10-08
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef Cip_H
|
||||||
|
#define Cip_H
|
||||||
|
|
||||||
|
#include <control_def.h>
|
||||||
|
|
||||||
|
#define BASE_PLC_RECV_BUFF_SIZE 1024
|
||||||
|
|
||||||
|
ControlProtocolType control_protocol;
|
||||||
|
|
||||||
|
int8_t ReadPlcDataByRecipe(struct ControlRecipe *p_recipe);
|
||||||
|
void voidpush(uint8_t *datastack,uint8_t* args,uint16_t length);
|
||||||
|
static uint8_t GetUniformValueTypeMemorySize(UniformValueType uniform_value_type);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UniformValueType value_type;
|
||||||
|
char value_name[20];
|
||||||
|
}CIPReadItem;
|
||||||
|
|
||||||
|
#endif
|
|
@ -56,6 +56,7 @@ typedef enum
|
||||||
PROTOCOL_MELSEC_1C,
|
PROTOCOL_MELSEC_1C,
|
||||||
PROTOCOL_MELSEC_3C,
|
PROTOCOL_MELSEC_3C,
|
||||||
PROTOCOL_FREEMODBUS_TCP_SERVER,
|
PROTOCOL_FREEMODBUS_TCP_SERVER,
|
||||||
|
PROTOCOL_CIP,
|
||||||
PROTOCOL_END
|
PROTOCOL_END
|
||||||
}ProtocolType;
|
}ProtocolType;
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,10 @@ extern int S7ProtocolInit(struct ControlRecipe *p_recipe);
|
||||||
extern int FreeModbusTcpServerInit(struct ControlRecipe *p_recipe);
|
extern int FreeModbusTcpServerInit(struct ControlRecipe *p_recipe);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONTROL_PROTOCOL_CIP
|
||||||
|
extern int CipProtocolInit(struct ControlRecipe *p_recipe);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CONTROL FRAMEWORK READ DATA FORMAT:
|
CONTROL FRAMEWORK READ DATA FORMAT:
|
||||||
| HEAD |device_id|read data length|read item count| data |
|
| HEAD |device_id|read data length|read item count| data |
|
||||||
|
@ -96,6 +100,9 @@ static struct ControlProtocolInitParam protocol_init[] =
|
||||||
{ PROTOCOL_FREEMODBUS_TCP_SERVER, FreeModbusTcpServerInit },
|
{ PROTOCOL_FREEMODBUS_TCP_SERVER, FreeModbusTcpServerInit },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONTROL_PROTOCOL_CIP
|
||||||
|
{ PROTOCOL_CIP, CipProtocolInit },
|
||||||
|
#endif
|
||||||
{ PROTOCOL_END, NULL },
|
{ PROTOCOL_END, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,7 +336,7 @@ int ControlProtocolOpenDef(struct ControlProtocol *control_protocol)
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
attr.schedparam.sched_priority = 19;
|
attr.schedparam.sched_priority = 19;
|
||||||
attr.stacksize = 2048;
|
attr.stacksize = 4096;
|
||||||
|
|
||||||
char task_name[] = "control_recv_data";
|
char task_name[] = "control_recv_data";
|
||||||
pthread_args_t args;
|
pthread_args_t args;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
|
export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
|
||||||
|
|
||||||
<<<<<<< HEAD
|
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror -Wuninitialized
|
||||||
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
|
||||||
=======
|
|
||||||
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror -Wuninitialized
|
|
||||||
>>>>>>> upstream/prepare_for_master
|
|
||||||
# export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
# export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
||||||
export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
|
export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
|
||||||
export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
|
export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
|
||||||
|
|
|
@ -536,6 +536,7 @@ KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protoc
|
||||||
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/opcua #
|
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/opcua #
|
||||||
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/s7 #
|
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/s7 #
|
||||||
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/ipc_protocol/freemodbustcpserver #
|
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/ipc_protocol/freemodbustcpserver #
|
||||||
|
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/control/plc_protocol/cip #
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_LIB_USING_CJSON), y)
|
ifeq ($(CONFIG_LIB_USING_CJSON), y)
|
||||||
|
|
Loading…
Reference in New Issue