| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 | #ifndef C315_PROTOCOL_H#define C315_PROTOCOL_H#pragma once#include "GlobalHead.h"#include "AlarmDefine.h"#include <set>#include <vector>#pragma pack(push, 1)#define FRAME_HEADER_315		"qknet"		//帧头#define FRAME_TYPE_HEARTBEAT	0x0F		//心跳帧#define FRAME_TYPE_DATA			0x8F		//数据帧#define FRAME_TAIL_315			0xFFFFFFFF	//帧尾//与JHD系统的通信协议#define PROTOCAL_CODE			0x02			//协议码#define PROTOCAL_DATAVERSION	0x01			//数据版本//命令帧 应答帧 主动上送帧 回执帧等enum FRAME_KIND {	CMD = 0,	RECV,	SEND,	BACK,	GENERAL};//scz 2022.11.09 新增 待补全enum class E_315_PROTOCOL_TYPE : uint8_t{	ACTIVE_KEEP = 0,			//心跳包	E_315_PROTOCOL_0x23 = 0x23,		//缺口配置	道岔缺口	E_315_PROTOCOL_0x26 = 0x26,		//道岔缺口数值	 	E_315_PROTOCOL_0x27 = 0x27,		//道岔缺口报警、预警及图像视频信息	 	E_315_PROTOCOL_0x29 = 0x29,		//道岔缺口最新图像	 	E_315_PROTOCOL_0x32 = 0x32,		//历史图像信息列表	 	E_315_PROTOCOL_0x2A = 0x2A,		//历史图像信息	 	E_315_PROTOCOL_0x2E = 0x2E,		//视频信息列表	 	E_315_PROTOCOL_0x2F = 0x2F,		//视频文件	 	E_315_PROTOCOL_0x22 = 0x22,		//1DQJ、区段状态信息	 	E_315_PROTOCOL_0x25 = 0x25,		//油压曲线	 	E_315_PROTOCOL_0x24 = 0x24,		//油位及缺口采集设备状态信息	 	E_315_PROTOCOL_0x30 = 0x30,		//视频流信息	 	E_315_PROTOCOL_0x31 = 0x31,		//请求命令时转辙机的定反位状态	 	//E_315_PROTOCOL_0x40 = 0x40,		//全行程受力信息	全行程子系统占用	//E_315_PROTOCOL_0x41 = 0x41,		//全行程最新值	 	//E_315_PROTOCOL_0x42 = 0x42,		//服务端回执主动推送的全行程最新值.	 	//E_315_PROTOCOL_0x43 = 0x43,		//全行程预报警信息	 	//E_315_PROTOCOL_0x44 = 0x44,		//服务端回执主动推送预报警信息	 	//E_315_PROTOCOL_0x45 = 0x45,		//测试历史数据	 	//E_315_PROTOCOL_0x46 = 0x46,		//查询曲线时间信息	 	//E_315_PROTOCOL_0x47 = 0x47,		//查询曲线数据	 	//E_315_PROTOCOL_0x48 = 0x48,		//服务端回执主动推送曲线数据	 	E_315_PROTOCOL_0x50 = 0x50,		//受力配置信息	受力监测子系统	E_315_PROTOCOL_0x51 = 0x51,		//受力最新值	 	E_315_PROTOCOL_0x52 = 0x52,		//服务端回执主动推送的受力最新值	 	E_315_PROTOCOL_0x53 = 0x53,		//受力预报警信息	 	E_315_PROTOCOL_0x54 = 0x54,		//服务端回执主动推送预报警信息	 	E_315_PROTOCOL_0x55 = 0x55,		//测试历史数据	 	E_315_PROTOCOL_0x56 = 0x56,		//查询曲线时间信息	 	E_315_PROTOCOL_0x57 = 0x57,		//查询曲线数据	 	E_315_PROTOCOL_0x58 = 0x58,		//服务端回执主动推送曲线数据	 	//E_315_PROTOCOL_0x60 = 0x60,		//框架配置信息	道岔框架系统	//E_315_PROTOCOL_0x61 = 0x61,		//框架最新值	 	//E_315_PROTOCOL_0x62 = 0x62,		//服务端回执主动推送的框架最新值	 	//E_315_PROTOCOL_0x63 = 0x63,		//框架预报警信息	 	//E_315_PROTOCOL_0x64 = 0x64,		//服务端回执主动推送预报警信息	 	//E_315_PROTOCOL_0x65 = 0x65,		//测试历史数据	 	//E_315_PROTOCOL_0x66 = 0x66,		//查询曲线时间信息	 	//E_315_PROTOCOL_0x67 = 0x67,		//查询曲线数据	 	//E_315_PROTOCOL_0x68 = 0x68,		//服务端回执主动推送曲线数据	 };//协议头typedef struct CPTL_Head{	BYTE sHead[5];										//帧头5B	BYTE byProtocolCode;								//协议码1B	BYTE byDataVersion;									//数据版本1B	BYTE byFrameType;									//帧类型1B	DWORD dwFrameLen;								//帧内容长度4B}CPTL_HEAD, * PCPTL_HEAD;enum class TIEDA_VAL_STATE : uint8_t{	TVS_POLL = 0x00,//为轮询值,日常采集	TVS_MOVEING = 0x01,//扳动过程采集值	TVS_AFTER_MOVE = 0x02,  //为扳动后采集值	TVS_PASSING = 0x03, //过车过程中采集值	TVS_AFTER_PASS = 0x04, //过车后采集值};enum class TIEDA_VAL_SYMBOL : uint8_t{	TVS_POSITIVE_NUMBER = 0x00,	TVS_MINUS_NUMBER = 0x01,};//铁大采集值/*采用3字节定义一个采集值,D0~D15:采集数值,D16~D19:采集精度,D20~D22:值状态,D23:值正负。采集精度:1=表示精度为1,即采集数值为实际的采集值.		  2=表示精度为10,表示采集数值为实际采集值*10.		  3=表示精度为100,表示表示采集数值为实际采集值*100.		  4=表示精度为1000,表示表示采集数值为实际采集值*1000.		  5=表示精度为0.1,表示表示采集数值为实际采集值/10.		  6=表示精度为0.01,表示表示采集数值为实际采集值/100.		  7=表示精度为0.001,表示表示采集数值为实际采集值/1000.值状态:0=表示为轮询值,日常采集		1=表示扳动过程采集值		2=表示为扳动后采集值		3=表示过车过程中采集值		4=表示过车后采集值值正负:0=正值		1=负值.0xFFFFFF表示无效值,采集传感器故障、超量程异常、通讯丢失等;当处于某状态时(例如扳动中,此时缺口值无效),状态值为1,精度不变,采集值填0xFFFF,表示在该状态下,采集值无意义;例如: 采集值 byte val[3]={ 0x81,0x00,0x23}; 表示采集值为0x0081, 精度为3(100),状态为2(扳动后),正负为0(正值),实际值为(1.29f);采集值 byte val[3]={ 0x81,0x00,0xA5}; 表示值为0x0081, 精度为5(0.1),状态为2(扳动后),正负为1(负值),实际值为-1290;*/union TIEDA_ACQ_VALUE{	//uint8_t value[3];	struct {		uint16_t v;					//值  默认 实际采集值/10		uint8_t precision : 4;   //精度  默认5		TIEDA_VAL_STATE state : 3;    //状态		TIEDA_VAL_SYMBOL symbol : 1;   //符号	};	TIEDA_ACQ_VALUE(int32_t a, TIEDA_VAL_STATE b, uint8_t d = 5)	{		symbol = TIEDA_VAL_SYMBOL::TVS_POSITIVE_NUMBER;		if (a <= -INVLID_VAL || a >= INVLID_VAL)		{			v = USHORT_MAX;		}		else if (a < 0)		{			a = -a;			symbol = TIEDA_VAL_SYMBOL::TVS_MINUS_NUMBER;		}		precision = d;		if (d == 5)			v = a / 10;		else			v = a;		state = b;	}	TIEDA_ACQ_VALUE(int a)	{		if (a == INT_MIN)			memset(this, 0xff, 3);	}	TIEDA_ACQ_VALUE()	{		v = 0;		precision = 5;		state = TIEDA_VAL_STATE::TVS_POLL;		symbol = TIEDA_VAL_SYMBOL::TVS_POSITIVE_NUMBER;	}	float tovalue()	{		BYTE* val = (BYTE*)this;		if (val[0] == 0xFF && val[1] == 0xFF && val[2] == 0xFF)			return INT_MIN;		float n = v;		if (symbol == TIEDA_VAL_SYMBOL::TVS_MINUS_NUMBER) n *= -1;		switch (precision)		{		case 2:			n /= 10.0;			break;		case 3:			n /= 100.0;			break;		case 4:			n /= 1000.0;			break;		case 5:			n *= 10.0;			break;		case 6:			n *= 100.0;			break;		case 7:			n *= 1000.0;			break;		default:			break;		}		return n;	}	string tostring()	{		float n = tovalue();		if (n == INT_MIN)			return "无效值";		string msg;		switch (state)		{		case TIEDA_VAL_STATE::TVS_POLL:			msg = "日常采集:";			break;		case TIEDA_VAL_STATE::TVS_MOVEING:			msg = "扳动过程采集:";			break;		case TIEDA_VAL_STATE::TVS_AFTER_MOVE:			msg = "扳动后采集:";			break;		case TIEDA_VAL_STATE::TVS_PASSING:			msg = "过车中采集:";			break;		case TIEDA_VAL_STATE::TVS_AFTER_PASS:			msg = "过车后采集:";			break;		default:			break;		}		msg += to_string(n);		return msg;	}};//道岔缺口配置信息(315) 命令码:0x23typedef struct{	BYTE cmdid;			//命令码:0x23	WORD cfgcnt;		//配置数	LPVOID lpcfg;		//转辙机配置i}StGapCfgRes;//转辙机配置typedef struct{	BYTE nlen;		//转辙机名称长度	LPSTR lpname;	//转辙机名称	BYTE stype;		//转辙机类型	WORD sid;		//转辙机ID	WORD cnt;		//采集信息个数	LPWORD lpinfo;	//采集信息类型}StSwitchCfg;//道岔缺口配置信息 end//曲线信息typedef struct{	BYTE cmdid;			//命令码:0x46/0x56/0x66	DWORD starttime;	//开始时间	DWORD endtime;		//结束时间	WORD  cnt;			//牵引点数目	LPVOID lpcfg;		//牵引点配置}StCurveCfgRes;//配置typedef struct{	WORD sid;		//转辙机ID}StTractionCfg;//配置typedef struct{	WORD sid;		//转辙机ID	WORD  cnt;		//记录数目	LPVOID lpcrecord;//记录}StTractionCfg1;//配置typedef struct{	DWORD time;		//结束时间}StTractionCfg11;//配置信息 end//配置信息typedef struct{	BYTE cmdid;			//命令码:0x40/0x50/0x60	WORD  cnt;			//配置个数	LPVOID lpcfg;		//配置信息}StNodeCfgRes;typedef struct {	BYTE namelen;		//牵引点名称长度	LPSTR lpname;		//牵引点名称	WORD sid;			//牵引点ID	BYTE cnt;			//采集信息个数	WORD lpinfo[0];		//采集信息类型}StNodeInfo;//配置typedef struct{	WORD acqTypeID;		//采集信息类型码}StNodeAcqCfg;struct NodeConfig{	CString strNodeName;	WORD	wNodeID;	std::vector<WORD> vecAcqTypeID;};struct NodeRealData{	DWORD	dwAcqTime;	WORD	wNodeID;	BYTE	byFixInvert;	//定反位	std::vector<WORD> vecAcqTypeID;	std::vector<BYTE> vecStatus;	std::vector<int>  vecAcqData;};struct stQueryAlarm{	BYTE cmdid;			//命令码:0x43/0x53/0x63	DWORD starttime;	//开始时间	DWORD endtime;		//结束时间	WORD	wNodeID;	//牵引点ID =0xffff时表示查询所有设备	WORD	wAlarmType;	//报警类型 =0xffff时表示查询所有报警};struct stAlarmItem{	WORD	wNodeID;	BYTE	byAlarmType;	//报警状态	DWORD	time;			//报警时间	DWORD	dwRestoreTime;	//恢复时间	WORD	wAlarmType;		//报警类型	//BYTE	cbAlarmValue[3];//报警值	TIEDA_ACQ_VALUE sAlarmValue; //报警值	//BYTE	cbRefValue[3];	//参考值	TIEDA_ACQ_VALUE sRefValue; //参考值	WORD	wSuggestID;		//维护建议ID};//配置struct stQueryHisDataItem{	WORD	wNodeID;	//牵引点ID	WORD acqTypeID;		//采集信息类型码};struct stQueryHisData{	BYTE cmdid;			//命令码:0x45/0x55/0x65	DWORD starttime;	//开始时间	DWORD endtime;		//结束时间	WORD  cnt;			//数量	WORD lpinfo[0];		//采集信息类型};struct stQueryHisCurveList{	BYTE cmdid;			//命令码:0x46/0x56/0x66	DWORD starttime;	//开始时间	DWORD endtime;		//结束时间	WORD  cnt;			//数量	WORD lpinfo[0];		//采集信息类型};struct stQueryHisCurve{	BYTE cmdid;			//命令码:0x46/0x56/0x66	WORD	wNodeID;	//牵引点ID	DWORD	time;	//时间};struct stHisStaticValue{	DWORD dwStartTime;				  //起始时间	std::vector<std::pair<WORD, int>> vctAcqData;};//心跳数据typedef struct{	DWORD hbtime;		//时间: 4B的unix时间用于时钟同步	BYTE filldata[3];	//填充3个字节的0xFF}StHeartBeat315;#pragma pack(pop)typedef std::map<time_t, int> MapTimeInt;typedef MapTimeInt::iterator MapTimeIntItor;class CCSM315Protocol{public:	CCSM315Protocol(int nDataVersion/*CLinkAdmin* pLinkAdmin, const char* strLogName*/);	virtual ~CCSM315Protocol();	static void InitFrmHead12B(BYTE* pBuf, BYTE frmtype, BYTE datVer);	static void InitFrmHead12B(CPTL_HEAD* pHead, BYTE frmtype, BYTE datVer);	static void InitFrmHead12B(C315CommData& CommData, BYTE frmtype, BYTE datVer);	//buf:缓冲区   size:缓冲区大小   len:取出的数据长度	static BOOL GetFrameData(LPBYTE& buf, int& size, int& len);	static std::string GetStrFromData(const BYTE* buf, int dwLen);public:	static E_315_PROTOCOL_TYPE  GetProtocolType(BYTE* pBuf, WORD wDataSize);	static BOOL IsReceiptProtocol(E_315_PROTOCOL_TYPE e);	static BOOL GetResendProtocol(E_315_PROTOCOL_TYPE e, int& nReSendCount, int& nReSendInterval);public:	static BOOL Parse(StHeartBeat315&, LPVOID, int);	//接收解析public:	static BOOL RecvParse(StGapCfgRes& data, LPVOID buf, int len);	static BOOL RecvParse(StCurveCfgRes& data, LPVOID buf, int len, FRAME_KIND&e);	//组装数据public:	static BOOL DataSerialize(BYTE byProtocalCMD, const std::vector<NodeConfig>& vecConfig, C315CommData& CommData);	static BOOL DataSerialize(BYTE byProtocalCMD, const std::vector<NodeRealData>& vecConfig, C315CommData& CommData);	static BOOL DataSerialize(BYTE byProtocalCMD, bool bPush, 		WORD wEqpNO, BYTE byFixOrNot, const std::vector<WORD>& vctAcqType,		const std::vector<TIEDA_ACQ_VALUE>& vctData, const std::vector<BYTE>& vctStatus,		const CTime& atime, C315CommData& CommData);	//static BOOL DataSerialize(BYTE byProtocalCMD, bool bPush, int no,	//	WORD wIdx, int num, const std::vector<int>& vctData0,	//	const std::vector<int>& vctData1, const std::vector<int>& vctData2,	//	DWORD atime, C315CommData& CommData);	//static BOOL DataSerialize(BYTE byProtocalCMD, BYTE byFixOrNot, bool bPush, int no, WORD wEqpNO, int num,	//	const MapTimeIntItor& map00, const MapTimeIntItor& map01,	//	const MapTimeIntItor& map10, const MapTimeIntItor& map11,	//	const MapTimeIntItor& map20, const MapTimeIntItor& map21,	//	time_t time, C315CommData& CommData);	static BOOL DataSerialize(BYTE byProtocalCMD, BYTE byFixOrNot, bool bPush, int no, WORD wEqpNO, int num,		std::map<time_t, int>* mapData[], time_t tmStartSecond, time_t tmEndSecond, C315CommData& CommData);		static BOOL DataSerialize(BYTE byProtocalCMD, bool bPush, int no, const std::vector<stAlarmItem>& vctAlarm, C315CommData& CommData);	static BOOL DataSerialize(BYTE byProtocalCMD, const std::map<WORD, std::vector<DWORD>>& mapData, C315CommData& CommData);	////first:makelong(牵引点, 采集码) second.first:采集时间 vector:采集数据列表 pair:偏移时间和采集值	static BOOL DataSerialize(BYTE byProtocalCMD, const std::map<DWORD, stHisStaticValue>& mapData, C315CommData& CommData);public:	static BOOL Release(StGapCfgRes&);	static BOOL Release(StCurveCfgRes&, FRAME_KIND& e);private:	static int	m_CSMCmdRegion_DataVersion;};#endif // !C315_PROTOCOL_H
 |