#pragma once // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SCF_EXPORTS // 符号编译的。在使用此 DLL 的 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 // SCF_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 // 符号视为是被导出的。 #ifndef SCF_EXPORTS #ifdef _WIN64 #ifdef _DEBUG #pragma comment(lib, "SCFX64D.lib") #else #pragma comment(lib, "SCFX64.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "SCFD.lib") #else #pragma comment(lib, "SCF.lib") #endif #endif #endif #ifdef SCF_EXPORTS #define SCF_API __declspec(dllexport) #define SCF_C_API extern "C" __declspec(dllexport) #else #define SCF_API __declspec(dllimport) #define SCF_C_API extern "C" __declspec(dllimport) #endif #include "ResDataObject.h" #include "DiosLock.h" #include "logger.h" #include "DiosThread.h" typedef enum _SCF_Error { SCF_UNKNOWN=-99, SCF_NOMEMORY, SCF_OPEN_FAILED,//打开端口失败 SCF_READ_FAILED,//读失败 SCF_WRITE_FAILED,//写失败 SCF_DISCONNETED,//连接断开 SCF_LOCK_FAILED,//锁失败 SCF_BUSY,//被占用 SCF_PARAMETER_ERR,//连接参数不对 SCF_OVERFLOW, SCF_NOPACKET , SCF_TIMEOUT, SCF_FAILED = 0, SCF_SUCCEED }SCF_ERR; typedef enum _Packet_Result { PACKET_USELESS = -1,//不需要的数据包,直接丢弃 PACKET_NOPACKET,//没有数据包 PACKET_ISPACKET//有数据包 }PACKET_RET; typedef enum _SCF_Transfertype { SCF_PACKET_TRANSFER = 0,//使用DeQueNotifyPacket&QueNotifyPacket SCF_NORMAL_TRANSFER //使用通用读取方式 }SCF_TRANSFERTYPE; typedef PACKET_RET(*PacketParser)(const char * pRecData, DWORD nLength, DWORD & PacketLength); SCF_C_API PVOID MallocSCFPacket();//申请SCFPACKET SCF_C_API void ReleaseSCFPacket(PVOID pObj);//释放SCFPACKET // 此类是从 SCF.dll 导出的 class SCF_API SCFPacket { protected: char* m_PacketBuff; DWORD m_PacketBuffLen; DWORD m_PacketLength; bool ReAlloc(DWORD BaseLen); public: SCFPacket(); SCFPacket(char* pData, DWORD Length); virtual ~SCFPacket(); bool SetBuffLen(DWORD Len); DWORD GetBuffLen(); SCFPacket& operator = (const SCFPacket &tValue); int SetPacket(const char* pData, DWORD Length); int AddTail(const char* pData, DWORD Length); void SetPacketLen(DWORD Len); DWORD GetPacketLen(); operator char*(); int GetPacket(char* pData, DWORD Length); }; class SCF_API SCFBuffer : public DiosLock { DWORD m_CurPacketIdx; SCFPacket *m_pPacket[2]; public: SCFBuffer(); ~SCFBuffer(); bool SetBuff(DWORD Len); int Add(const char * data, DWORD len); int Del(DWORD len); const char *GetBuff(); DWORD GetPacketLen(); void ClearData(); }; class SCF_API SCF : public DiosLock, public Dios_Thread { public: SCF(void); virtual ~SCF(); HMODULE m_LibHandle; Logger *m_pSCFLogger; PacketParser m_pPacketParser; SCF_TRANSFERTYPE m_TransferType; //根路径是SCF路径,pFileName是偏移值,如 "COM\COM2.log" void InitSCF(const char *pLogFileName = NULL); //设置本地属性 特定通信情况下需要,串口,网络,USB的连接不需要设置 bool SetSourceAttribute(ResDataObject & Sourceprameters) ; //设置连接,参数也由json传过来 /* -- 串口类型 { "type":"COM", "port":"COM1", "baudrate":"3200", "bytesize":"8", "parity":"1", "stopbits":"1" } */ /* -- 网络类型 { "type":"TCPIP", "ip":"192.168.2.77", "port":"2020" } */ void SetBuffersize(DWORD NormalPackSize, DWORD MaxBuffLimit); virtual int Connect(ResDataObject & Connectprameters, PacketParser callback, SCF_TRANSFERTYPE TransferType = SCF_NORMAL_TRANSFER, DWORD CommunicateTimeout = 0); //断开连接 virtual void Disconnect(); //判断是否连接 virtual bool isConnected() ; //获取连接类型,由继承类实现 virtual const char* GetConnectionType(); //获取连接参数 ResDataObject GetConnectionAttributes(); //发数据 virtual int SendPacket(const char *pPacket, DWORD length, DWORD timeout); virtual int SendPacket(SCFPacket *pPacket, DWORD timeout); //读数据 int ReceivePacket(char *pPacket, DWORD length, DWORD timeout); int ReceivePacket(SCFPacket *pPacket, DWORD timeout); DWORD GetReceivePacketSize(); DWORD GetNotifyPacketSize(); HANDLE GetScfNotifyHandle() ;//获取SCF收到Notify后通知的事件句柄 ////将不需要的数据包存入Notify数据缓存队列 int QueNotifyPacket(const char *pPacket, DWORD length); int QueNotifyPacket(SCFPacket *pPacket); //读取Notify数据缓存中的数据包,当SCF处于解锁状态下接收的数据都会放入Notify缓存中,需要调用DeQueNotifyPacket来读取缓存中的数据包,读取成功返回接收数据的实际长度,失败返回SCF_ERR int DeQueNotifyPacket(char *pPacket, DWORD length, DWORD timeout); int DeQueNotifyPacket(SCFPacket *pPacket, DWORD timeout); //SCF的锁 DWORD SCFLock(DWORD timeout); void SCFUnLock(); //被动掉线事件 void SetPassiveDisconnectEvt(HANDLE evt); void PassiveDisconnected(); DWORD GetCommunicateTimeout(); protected: HANDLE m_PassiveDisconEvt; OVERLAPPED m_osRead; OVERLAPPED m_osWrite; // TODO: 在此添加您的方法。 virtual int ReadData(char *pPacket, DWORD length, DWORD timeout); //virtual int ReadData(SCFPacket *pPacket, DWORD timeout); DWORD m_CommunicateTimeout; ResDataObject m_ConnectionParams; //---------------server part DWORD MaxComLen; DWORD NormalPackLen; DWORD ReadWaitTime; SCFBuffer m_RawBuffer; SCFPacket* m_pTransferBuffer;//将Receive数据转入Notify SCFPacket* m_pRtoNBuffer;//将Receive数据转入Notify bool StartSCFServer();//开启读线程 void StopSCFServer();//关闭读线程 int ProcessCmd(const char * data, int datalength); int ReceivetoNotify(); int ReceivetoNotify_Ex(); int WritetoNotify(const char *pPacket, int length); virtual bool Exec(); PVOID m_pNotifybuffer; PVOID m_pReceivebuffer; HANDLE m_hNotifyhandle; HANDLE m_hReceivehandle; HANDLE EventHandleWrite; // 当命令写入时,发送事件 HANDLE EventHandleRead; // 当读取到命令时,发送事件 HANDLE ThreadHandleRead; DWORD ThreadIDRead; // 读线程ID }; SCF_C_API SCF* LoadScf(const char *pFilename); SCF_C_API void UnLoadScf(SCF* pHandle); typedef SCF * (*GetSCF_Proc)(); typedef void (*ReleaseSCF_Proc)(SCF *);