每家PLC厂商都有自己的通讯协议,三菱有MC、倍福有ADS,然而没有统一性的接口协议。
为适应每一家通讯,每一家设备商、MES和工厂等都需要针对每款产品开发相应的通讯接口。
OneConnectAPI为实现统一的接口,去适配每一家厂商的协议。为中国工控行业快速发展而贡献,每一家公司都需要重新制造轮子,这是非常浪费时间和金钱,同时也不能保证稳定性以及持续的维护。
我们采取高效的多线程处理方案,保证极其高效的读写性能,对电脑性能要求极其低,一直进行读写操作,CPU使用率不超过1%(Atom E3940下测试)。
用户可以在一台工控机上进行对上百台的PLC主动读写操作,我们在光伏行业大量应用和测试过。
我们在半导体行业深耕多年,积累大量的经验,实现功能的同时,也需要保证极其严格的稳定性,晶圆生成设备7*24小时不能出任何故障。
下载地址软件及资料书www.secsgemc.om
下边 /secsgem/one-api-connect/tree/master/
/SECSGEM/Fins
#pragma once#include <string>#include "InterfaceExport.h"#include "ModuleDevelopH.h"// 欧姆龙Fins协议class CFins{public:CFins();virtual ~CFins();// 参数CResult SetIP(std::string pIP);// 设置地址CResult SetPort(int nPort);// 设置端口号CResult SetTimeout(int nTimeMs);// 设置超时// 读出CResult Read(std::string pAddr, char& pData); CResult Read(std::string pAddr, __int16& pData); CResult Read(std::string pAddr, __int32& pData); CResult Read(std::string pAddr, __int64& pData);CResult Read(std::string pAddr, char* pData, int nSize); CResult Read(std::string pAddr, __int16* pData, int nSize); CResult Read(std::string pAddr, __int32* pData, int nSize); CResult Read(std::string pAddr, __int64* pData, int nSize); // 写入CResult Write(std::string pAddr, char& pData); CResult Write(std::string pAddr, __int16& pData); CResult Write(std::string pAddr, __int32& pData); CResult Write(std::string pAddr, __int64& pData); CResult Write(std::string pAddr, char* pData, __int32 nSize); CResult Write(std::string pAddr, __int16* pData, __int32 nSize); CResult Write(std::string pAddr, __int32* pData, __int32 nSize); CResult Write(std::string pAddr, __int64* pData, __int32 nSize); private:CResult SetParament(std::string pName, std::string pValue); CResult SetParament(std::string pName, int nValue); private:CInterfaceExport* m_pFins;CMgrDllDelegate m_pLoadInterface;};
#include "stdafx.h"#include "FinsHandle.h"CFinsHandle::CFinsHandle(){m_bEstablishCommunicationByFins = false;m_nIpNode = 0;}// 重写数据接收,用于协议识别void CFinsHandle::OnDataRecv(char* pData, int nSize){if (nSize > 0){m_pRecvData.Append(pData, nSize);if (m_pRecvData.Size() >= FINS_TCP_HEAD_SIZE){FINS_TCP_HEAD pHead;pHead.SetData(m_pRecvData.GetString());int nAllSize = pHead.GetLength();if (m_pRecvData.Size() >= nAllSize){SetRecvComplete(nAllSize);}}}}// 重写数据接收,开始接收数据,用于协议识别void CFinsHandle::OnBeginRecv(){m_pRecvData.SetSize(0);}// 通讯关闭void CFinsHandle::OnCloseConnect(){m_bEstablishCommunicationByFins = false;}long CFinsHandle::ReadMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData){long nCode = 0;if(nCode = EstablishCommunicationByFins()){return nCode;}CMyString pSendData;// 获取发送内存int nAllSize;nAllSize = FINS_TCP_HEAD_SIZE;nAllSize += FINS_CONTROL_HEAD_SIZE;nAllSize += FINS_MEMORY_AREA_READ_SIZE; pSendData.SetSize(nAllSize);char* pBuff = pSendData.GetString();// 头部信息FINS_TCP_HEAD pHead;pHead.nCommand = FINS_TCP_CMD_DATA;pHead.SetLength(nAllSize);//长度pHead.GetData(pBuff);// control部分FINS_CONTROL_HEAD pControlHead;pControlHead.nDA1 = 0; pControlHead.nSA1 = m_nIpNode;pControlHead.nCmd1 = 0x01;pControlHead.nCmd2 = 0x01;pControlHead.GetData(pBuff + FINS_TCP_HEAD_SIZE);// 数据部分FINS_MEMORY_AREA_READ pMemory;pMemory.nAreaCode = nType;pMemory.nAddr = nAddr;pMemory.nBitNo = 0;pMemory.nLength = nSize;pMemory.GetData(pBuff + FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE);//// 发送数据CMyString pRecvData;nCode = SendSyncData(pSendData, pRecvData);if (nCode == 0){// 先判断答复数据的头数据是否正确if(nCode = CheckReplyDataIsError(pRecvData.GetString(), pRecvData.Size())){return nCode;}// 数据头FINS_TCP_HEAD pHeadReply;pHeadReply.SetData(pRecvData.GetString());// 答复长度要求int nMinSize = FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE + FINS_MEMORY_AREA_READ_FIX_R_SIZE + nSize * 2;if(pHeadReply.GetLength() < nMinSize){return FINS_REPLY_READ_DATA_TOO_SHORT;}else{// FINS协议部分FINS_CONTROL_HEAD pControlHeadReply;pControlHeadReply.SetData(pRecvData.GetString());if (pControlHeadReply.nCmd1 != pControlHead.nCmd1 ||pControlHeadReply.nCmd2 != pControlHead.nCmd2){// 命令不一致return FINS_REPLY_CMD_NO_IS_REQUST_CMD;}// 答复数据FINS_MEMORY_AREA_READ_REPLY pReplyData;pReplyData.SetData(pRecvData.GetString(), pRecvData.Size());if(pReplyData.nEndCode != 0){return FINS_REPLY_READ_DATA_FAIL;}// 拷贝数据int nReadByte = nSize * 2;if (pReplyData.GetDataBytsSize() == nReadByte){memcpy(pData, pReplyData.GetData(), nReadByte);}else{return FINS_REPLY_READ_DATA_TOO_SHORT;}}}return nCode;}long CFinsHandle::WriteMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData){long nCode = 0;if(nCode = EstablishCommunicationByFins()){return nCode;}CMyString pSendData;int nBytsSize = nSize * 2;// 获取发送内存int nAllSize;nAllSize = FINS_TCP_HEAD_SIZE;nAllSize += FINS_CONTROL_HEAD_SIZE;nAllSize += FINS_MEMORY_AREA_READ_SIZE; nAllSize += nBytsSize;pSendData.SetSize(nAllSize);char* pBuff = pSendData.GetString();// 头部信息FINS_TCP_HEAD pHead;pHead.nCommand = FINS_TCP_CMD_DATA;pHead.SetLength(nAllSize);//长度pHead.GetData(pBuff);// control部分FINS_CONTROL_HEAD pControlHead;pControlHead.nDA1 = 0; pControlHead.nSA1 = m_nIpNode;pControlHead.nCmd1 = 0x01;pControlHead.nCmd2 = 0x02;pControlHead.GetData(pBuff + FINS_TCP_HEAD_SIZE);// 数据部分FINS_MEMORY_AREA_WRITE pMemory;pMemory.nAreaCode = nType;pMemory.nAddr = nAddr;pMemory.nBitNo = 0;pMemory.nLength = nSize;pMemory.pData.Append((char*)pData, nBytsSize);pMemory.GetData(pBuff + FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE);//// 发送数据CMyString pRecvData;nCode = SendSyncData(pSendData, pRecvData);if (nCode == 0){// 先判断答复数据的头数据是否正确if(nCode = CheckReplyDataIsError(pRecvData.GetString(), pRecvData.Size())){return nCode;}// 数据头FINS_TCP_HEAD pHeadReply;pHeadReply.SetData(pRecvData.GetString());// 答复长度要求int nMinSize = FINS_TCP_HEAD_SIZE + FINS_CONTROL_HEAD_SIZE + FINS_MEMORY_AREA_WRITE_R_SIZE;if(pHeadReply.GetLength() < nMinSize){return FINS_REPLY_READ_DATA_TOO_SHORT;}else{// FINS协议部分FINS_CONTROL_HEAD pControlHeadReply;pControlHeadReply.SetData(pRecvData.GetString());if (pControlHeadReply.nCmd1 != pControlHead.nCmd1 ||pControlHeadReply.nCmd2 != pControlHead.nCmd2){// 命令不一致return FINS_REPLY_CMD_NO_IS_REQUST_CMD;}// 答复数据FINS_MEMORY_AREA_WRITE_REPLY pReplyData;pReplyData.SetData(pRecvData.GetString());if(pReplyData.nEndCode != 0){return FINS_REPLY_WRITE_DATA_FAIL;}}}return nCode;}// 获取fins节点地址long CFinsHandle::GetFinsNodeAddress(){return 0;}// 检查答复数据是否错误long CFinsHandle::CheckReplyDataIsError(char* pData, int nSize){if (nSize < FINS_TCP_HEAD_SIZE){// 小于最小要求数据return FINS_REPLY_DATA_TOO_SHORT;}// 消息错误FINS_TCP_HEAD pHeadReply;pHeadReply.SetData(pData);if (pHeadReply.nErrorCode){return FINS_REPLY_ERROR_BY_MESSAGE;}return 0;}// 建立通讯long CFinsHandle::EstablishCommunicationByFins(){if (m_bEstablishCommunicationByFins){// 已经建立通讯连接了return 0;}long nCode = 0;CMyString pSendData;// 获取发送内存int nAllSize;nAllSize = FINS_TCP_HEAD_SIZE;nAllSize += FINS_CONNECT_REQUST_SIZE;pSendData.SetSize(nAllSize);char* pBuff = pSendData.GetString();// 头部信息FINS_TCP_HEAD pHead;pHead.nCommand = FINS_TCP_CMD_CONNECT_REQUST;pHead.SetLength(nAllSize);//长度pHead.GetData(pBuff);// IP地址FINS_CONNECT_REQUST pConnectRequst;pConnectRequst.GetData(pBuff + FINS_TCP_HEAD_SIZE);// 发送数据CMyString pRecvData;if(nCode = SendSyncData(pSendData, pRecvData)){return nCode;}// 处理返回值FINS_TCP_HEAD pHeadReply;pHeadReply.SetData(pRecvData.GetString());// 检查头信息if (pHeadReply.nErrorCode == 0 &&pHeadReply.nCommand == FINS_TCP_CMD_CONNECT_RESPONSE){// 提取 IP Node信息if (pHeadReply.GetLength() == FINS_TCP_HEAD_SIZE + FINS_CONNECT_RESPONS_SIZE){// 提取FINS_CONNECT_RESPONSE pConnectResponse;pConnectResponse.SetData(pRecvData.GetString());m_nIpNode = pConnectResponse.pClientAddrss[3];// 建立通讯成功m_bEstablishCommunicationByFins = true;return 0;}}return FINS_REQUST_CONNECT_FAIL;}
#pragma once
// 用于TCP/IP通讯
class CCommunication
{
public:
CCommunication();
virtual ~CCommunication();
// 释放
void Release();
void SetTimeout(int nMs);// 设置超时
void SetMode(bool bLongConnect); // 长连接或者短连接模式
void SetTcpIP(const char* pIP); // socket参数
void SetTcpPort(int nPort);// socket参数
int GetTimeout();
long SendSyncData(CMyString pSendData, CMyString& pRecvData); // 数据发读
void Disconnect(); // 断开通讯
protected:
// 数据接收
void SetRecvComplete(int nSize); // 告诉通讯,数据接收完成
virtual void OnBeginRecv(); // 重写数据接收,开始接收数据,用于协议识别
virtual void OnDataRecv(char* pData, int nSize) = 0; // 重写数据接收,用于协议识别
virtual void OnCloseConnect(); // 通讯关闭
private:
long Connect(); // TCP连接
void CloseConnect(); // TCP关闭连接
void InitSockWSA();
void ReleaseSockWSA();
// 接收数据线程
void CreateRecvThread(); // 创建接收线程
void ExitRecvThread(); // 退出接收线程
static void RunRecvThread(void* lp);
void RecvHandle();
bool IsExitThread();
void OneRecvData(); // 一次接收数据
void StartRecvData(); // 开始接收数据
void StopRecvData();
// 数据读取,从缓存内读取
long RecvData(CMyString& pRecvData);
private:
bool m_bLongConnect; // 长连接
int m_nRecvTimeout; // 接收超时
// socket
SOCKET m_hSock;
struct sockaddr_in m_pSA;
vCritical m_syncLock; // 每次只能单个tcp读写
vCritical m_syncLockTcp; // soekct操作
HANDLE m_hRecvTimeoutEvent; // 接收线程超时
HANDLE m_hRecvExitFinish; // 定时器线程退出完毕
HANDLE m_hRecvExit; // 接收退出
HANDLE m_hRecvStartData; // 开始接收数据
CMyString m_pRecvData; // 接收到的数据
long m_nRecvCode; // 读取错误代码
// 临时缓
int m_nSize;
int m_nRecvSize;
char m_pBuff[200];
};
#pragma once
#include "Communication.h"
class CFinsHandle : public CCommunication
{
public:
CFinsHandle();
long ReadMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData);
long WriteMemoryData(int nAddr, int nSize, FINS_DATA_TYPE::ENUM nType, __int16* pData);
private:
virtual void OnBeginRecv(); // 重写数据接收,开始接收数据
virtual void OnDataRecv(char* pData, int nSize); // 重写数据接收,用于协议识别
virtual void OnCloseConnect();// 通讯关闭
// 检查答复数据是否错误
long CheckReplyDataIsError(char* pData, int nSize); // 检查答复数据是否错误
long GetFinsNodeAddress(); // 获取fins节点地址
long EstablishCommunicationByFins(); // 建立Fins通讯
private:
CMyString m_pRecvData;
bool m_bEstablishCommunicationByFins; // 与Fins建立通讯
int m_nIpNode; // IP节点
};
#pragma once
#include "Export/InterfaceExport.h"
#include "FinsHandle.h"
class CFinsReadWrite : public CInterfaceExport
{
public:
// 参数
virtual CResult SetParament(const char* pName, const char* pValue);
// 初始化模块
virtual CResult Connect();
virtual CResult Disconnect();
// 释放
virtual void Release();
public:
// 读出
virtual CResult Read(const char* pAddr, char* pData, __int32 size, char* pCtrlData);
virtual CResult Read(const char* pAddr, __int16* pData, __int32 size, char* pCtrlData);
virtual CResult Read(const char* pAddr, __int32* pData, __int32 size, char* pCtrlData);
virtual CResult Read(const char* pAddr, __int64* pData, __int32 size, char* pCtrlData);
// 写入
virtual CResult Write(const char* pAddr, char* pData, __int32 size, char* pCtrlData);
virtual CResult Write(const char* pAddr, __int16* pData, __int32 size, char* pCtrlData);
virtual CResult Write(const char* pAddr, __int32* pData, __int32 size, char* pCtrlData);
virtual CResult Write(const char* pAddr, __int64* pData, __int32 size, char* pCtrlData);
private:
long ReadData(int nAddr, __int16* pData, int nSize, int nDataType); // 读取2字节一次
long WriteData(int nAddr, __int16* pData, int nSize, int nDataType); // 读取2字节一次
void GetDataTypeAndAddr(string pAddr, int& nDataType, int& nAddr); // 获取数据地址
int GetDataArea(string pArea); // 获取数据区
private:
CFinsHandle m_pHandle;
};
#include "stdafx.h"
#include "Communication.h"
CCommunication::CCommunication()
{
m_nRecvTimeout = 5000;
m_bLongConnect = true;
m_hSock = INVALID_SOCKET;
InitSockWSA();
memset(&m_pSA, 0, sizeof(struct sockaddr_in));
m_hRecvExit = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hRecvExitFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hRecvTimeoutEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hRecvStartData = CreateEvent(NULL, TRUE, FALSE, NULL);
CreateRecvThread();
}
CCommunication::~CCommunication()
{
ExitRecvThread();
ReleaseSockWSA();
CloseHandle(m_hRecvExit);
CloseHandle(m_hRecvExitFinish);
CloseHandle(m_hRecvTimeoutEvent);
CloseHandle(m_hRecvStartData);
}
void CCommunication::InitSockWSA()
{
// 必须的
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
}
}
void CCommunication::ReleaseSockWSA()
{
// 必须的
if(WSACleanup() != 0)
{
}
}
// 释放
void CCommunication::Release()
{
}
// TCP连接
long CCommunication::Connect()
{
if(m_hSock == INVALID_SOCKET)
{
m_hSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(m_hSock != INVALID_SOCKET)
{
if(connect(m_hSock, (struct sockaddr*)&m_pSA, sizeof(m_pSA)) < 0)
{
closesocket(m_hSock);
m_hSock = INVALID_SOCKET;
return FINS_SOCKET_CONNECT_FAIL;
}
}
else
{
return FINS_SOCKET_CREATE_FAIL;
}
}
return 0;
}
// TCP关闭连接
void CCommunication::CloseConnect()
{
vLocker lock(&m_syncLockTcp);
if (m_hSock != INVALID_SOCKET)
{
shutdown(m_hSock, 2);
closesocket(m_hSock);
m_hSock = INVALID_SOCKET;
OnCloseConnect();
}
}
// 设置超时
void CCommunication::SetTimeout(__int32 nMs)
{
if(nMs < 100)
{
nMs = 100;
}
m_nRecvTimeout = nMs;
}
int CCommunication::GetTimeout()
{
return m_nRecvTimeout;
}
// 长连接或者短连接模式
void CCommunication::SetMode(bool bLongConnect)
{
m_bLongConnect = bLongConnect;
}
// socket参数
void CCommunication::SetTcpIP(const char* pIP)
{
m_pSA.sin_family = AF_INET;
m_pSA.sin_addr.s_addr = inet_addr(pIP);
}
// socket参数
void CCommunication::SetTcpPort(__int32 nPort)
{
m_pSA.sin_family = AF_INET;
m_pSA.sin_port = htons(nPort);
}
// 数据发读
long CCommunication::SendSyncData(CMyString pSendData, CMyString& pRecvData)
{
vLocker lock(&m_syncLock);
long nCode = Connect();
if(nCode != 0)
{
return nCode;
}
// 清空原来的数据
m_pRecvData.SetSize(0);
// 发送数据
int res = send(m_hSock, pSendData.GetString(), pSendData.Size(), 0);
if(res == SOCKET_ERROR)
{
CloseConnect();
return FINS_SEND_FAIL;
}
// 数据读取
nCode = RecvData(pRecvData);
// 短连接每次都关闭
if(!m_bLongConnect)
{
CloseConnect();
}
return nCode;
}
// 数据读取
// 带超时处理
long CCommunication::RecvData(CMyString& pRecvData)
{
long nCode = 0;
StartRecvData();
// 等待接收
ResetEvent(m_hRecvTimeoutEvent);
DWORD rs = WaitForSingleObject(m_hRecvTimeoutEvent, m_nRecvTimeout);
// 成功返回值
if (rs == WAIT_OBJECT_0)
{
pRecvData = m_pRecvData;
}
// 超时等其他错误
else
{
StopRecvData();
CloseConnect();
nCode = FINS_RECV_WAIT_TIMEOUT;
}
return nCode;
}
// 创建接收线程
//
void CCommunication::CreateRecvThread()
{
ResetEvent(m_hRecvExitFinish);
_beginthread(RunRecvThread, 0, this);
}
// 退出接收线程
//
void CCommunication::ExitRecvThread()
{
CloseConnect();
SetEvent(m_hRecvExit);
SetEvent(m_hRecvStartData);
WaitForSingleObject(m_hRecvExitFinish, INFINITE);
}
// 定时器线程
void CCommunication::RunRecvThread(void* lp)
{
CCommunication* pMC = (CCommunication*)lp;
pMC->RecvHandle();
SetEvent(pMC->m_hRecvExitFinish); // 处理完毕
}
// 定时器
void CCommunication::RecvHandle()
{
while (!IsExitThread())
{
WaitForSingleObject(m_hRecvStartData, INFINITE);
if (IsExitThread())
{
break;
}
OneRecvData();
}
}
// 一次接收数据
void CCommunication::OneRecvData()
{
m_nSize = 200;
m_nRecvSize = recv(m_hSock, m_pBuff, m_nSize, 0);
if(m_nRecvSize == SOCKET_ERROR)
{
CloseConnect();
m_nRecvCode = FINS_SOCKET_CONNECT_ERR;
}
else
{
m_pRecvData.Append(m_pBuff, m_nRecvSize);
m_nRecvCode = 0;
OnDataRecv(m_pBuff, m_nRecvSize);
}
}
// 告诉通讯,数据接收完成
void CCommunication::SetRecvComplete(int nSize)
{
ResetEvent(m_hRecvStartData); // 复位接收
SetEvent(m_hRecvTimeoutEvent); // 接收成功
}
// 重写数据接收,开始接收数据,用于协议识别
void CCommunication::OnBeginRecv()
{
}
// 通讯关闭
void CCommunication::OnCloseConnect()
{
}
bool CCommunication::IsExitThread()
{
if(WaitForSingleObject(m_hRecvExit, 0) == WAIT_OBJECT_0)
{
return true;
}
return false;
}
// 开始接收数据
void CCommunication::StartRecvData()
{
OnBeginRecv();
SetEvent(m_hRecvStartData);
}
// 停止接收数据
void CCommunication::StopRecvData()
{
ResetEvent(m_hRecvStartData);
}
// 断开通讯
void CCommunication::Disconnect()
{
}
#include "stdafx.h"
#include "FinsReadWrite.h"
// 参数
CResult CFinsReadWrite::SetParament(const char* pName, const char* pValue)
{
if(pName == nullptr ||
pValue == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
string pNameString = pName;
if (pNameString == "IP")
{
m_pHandle.SetTcpIP(pValue);
}
else if (pNameString == "PORT")
{
int nPort = ::atoi(pValue);
m_pHandle.SetTcpPort(nPort);
}
else if (pNameString == "TIMEOUT")
{
int nTimerOut = ::atoi(pValue);
m_pHandle.SetTimeout(nTimerOut);
}
return CResult(0);
}
// 初始化模块
CResult CFinsReadWrite::Connect()
{
return CResult(0);
}
CResult CFinsReadWrite::Disconnect()
{
return CResult(0);
}
// 释放
void CFinsReadWrite::Release()
{
delete this;
}
// 1字节
CResult CFinsReadWrite::Read(const char* pAddr, char* pData, __int32 nSize, char* pCtrlData)
{
if (pAddr == nullptr ||
pData == nullptr ||
pCtrlData == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
int nDataType; // 数据类型
int nAddr; // 数据地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
long nCode = 0;
if(nSize % 2)
{
// 奇数处理
int nReadSize = nSize;
nReadSize++;
__int16* pReadData = (__int16*)malloc(nReadSize);
if (pReadData == nullptr)
{
return FINS_MALLOC_FAIL;
}
// 读取数据
nCode = ReadData(nAddr, pReadData, nReadSize / 2, nDataType);
if(nCode == 0)
{
memcpy(pData, pReadData, nSize);
}
free(pReadData);
}
else
{
nCode = ReadData(nAddr, (__int16*)pData, nSize / 2, nDataType);
}
return nCode;
}
// 2字节
CResult CFinsReadWrite::Read(const char* pAddr, __int16* pData, __int32 nSize, char* pCtrlData)
{
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = ReadData(nAddr, pData, nSize, nDataType);
return CResult(nCode);
}
// 4字节
CResult CFinsReadWrite::Read(const char* pAddr, __int32* pData, __int32 nSize, char* pCtrlData)
{
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = ReadData(nAddr, (__int16*)pData, nSize * 2, nDataType);
return CResult(nCode);
}
// 8字节
CResult CFinsReadWrite::Read(const char* pAddr, __int64* pData, __int32 nSize, char* pCtrlData)
{
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = ReadData(nAddr, (__int16*)pData, nSize * 2, nDataType);
return CResult(nCode);
}
// 读取2字节一次
long CFinsReadWrite::ReadData(int nAddr, __int16* pData, int nSize, int nDataType)
{
FINS_DATA_TYPE::ENUM nType = (FINS_DATA_TYPE::ENUM)nDataType;
switch(nType)
{
case FINS_DATA_TYPE::DM:
{
return m_pHandle.ReadMemoryData(nAddr, nSize, nType, pData);
}
break;
}
return FINS_NOT_DATA_AREA;
}
// 1字节
CResult CFinsReadWrite::Write(const char* pAddr, char* pData, __int32 nSize, char* pCtrlData)
{
if (pAddr == nullptr ||
pData == nullptr ||
pCtrlData == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
// 获取PLC区域和地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
if(nSize % 2)
{
// 奇数处理
int nReadSize = nSize;
nReadSize++;
__int8* pReadData = (__int8*)malloc(nReadSize);
if (pReadData == nullptr)
{
return FINS_MALLOC_FAIL;
}
memset(pReadData, 0, nReadSize);
memcpy(pReadData, pData, nSize);
// 读取数据
nCode = WriteData(nAddr, (__int16*)pReadData, nReadSize / 2, nDataType);
free(pReadData);
}
else
{
nCode = WriteData(nAddr, (__int16*)pData, nSize / 2, nDataType);
}
return nCode;
}
// 2字节
CResult CFinsReadWrite::Write(const char* pAddr, __int16* pData, __int32 nSize, char* pCtrlData)
{
if (pAddr == nullptr ||
pData == nullptr ||
pCtrlData == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
// 获取PLC区域和地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = WriteData(nAddr, pData, nSize, nDataType);
return nCode;
}
// 4字节
CResult CFinsReadWrite::Write(const char* pAddr, __int32* pData, __int32 nSize, char* pCtrlData)
{
if (pAddr == nullptr ||
pData == nullptr ||
pCtrlData == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
// 获取PLC区域和地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = WriteData(nAddr, (__int16*)pData, nSize * 2, nDataType);
return nCode;
}
// 8字节
CResult CFinsReadWrite::Write(const char* pAddr, __int64* pData, __int32 nSize, char* pCtrlData)
{
if (pAddr == nullptr ||
pData == nullptr ||
pCtrlData == nullptr)
{
return CResult(FINS_PARAM_POINT_ENTPY, "FINS 参数指针为空");
}
long nCode = 0;
int nDataType; // 数据类型
int nAddr; // 数据地址
// 获取PLC区域和地址
GetDataTypeAndAddr(pAddr, nDataType, nAddr);
nCode = WriteData(nAddr, (__int16*)pData, nSize * 4, nDataType);
return nCode;
}
// 读取2字节一次
long CFinsReadWrite::WriteData(int nAddr, __int16* pData, int nSize, int nDataType)
{
FINS_DATA_TYPE::ENUM nType = (FINS_DATA_TYPE::ENUM)nDataType;
switch(nType)
{
case FINS_DATA_TYPE::DM:
{
return m_pHandle.WriteMemoryData(nAddr, nSize, nType, pData);
}
break;
}
return FINS_NOT_DATA_AREA;
}
// 获取数据地址
void CFinsReadWrite::GetDataTypeAndAddr(string pAddr, int& nDataType, int& nAddr)
{
unsigned int i = 0;
for (; i < pAddr.size(); i++)
{
if(pAddr[i] >= '0' && pAddr[i] <= '9')
{
break;
}
}
// 数据类型
string pType = pAddr.substr(0, i);
nDataType = GetDataArea(pType);
// 数据地址
string pStartAddr = pAddr.substr(i, pAddr.size() - i);
nAddr = ::atol(pStartAddr.c_str());
}
// 获取数据区
int CFinsReadWrite::GetDataArea(string pArea)
{
int nDataType = 0;
if (pArea == "DM") { nDataType = FINS_DATA_TYPE::DM; }
else if (pArea == "dm") { nDataType = FINS_DATA_TYPE::DM; }
else { nDataType = FINS_DATA_TYPE::ERR; }
return nDataType;
}