| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- // TKHS_SD.cpp : 定义 DLL 的初始化例程。
- //
- #include "stdafx.h"
- #include "TKHS_SD.h"
- #include "UdpClientSocket.h"
- #include <queue>
- #include <math.h>
- #include <algorithm>
- struct DataBuf
- {
- int TestType;
- BYTE pbTimeBuf[15];
- int TimeLen;
- BYTE *pbHJdataBuf;
- int HJdataLen;
- BYTE *pbYQdataBuf;
- int YQdataLen;
- };
- /*加油枪数据
- 内容 长度 数据说明
- A/L 1字节 1字节整型数据,单位%
- 回收油气浓度 2字节 2字节无符号整型,最后1位表示小数点后第1位,单位%
- 回收油气温度 2字节 2字节有符号整型,最后1位表示小数点后第1位,单位℃
- 油气流速 2字节 2字节整型数据,单位L/min
- 加油流速 2字节 2字节整型数据,单位L/min
- 油气流量 2字节 2字节整型数据,单位L
- 燃油流量 2字节 2字节整型数据,单位L
- 加油持续时间 2字节 2字节整型数据,单位S
- ex:
- 数据项目 真实数据值 表示数值
- A/L 62% 用整型数据62表示
- 回收油气浓度 21.6% 用整型数据216表示,个位实际表示小数点后第1位
- 回收油气温度 26.4℃ 用整型数据264表示,个位实际表示小数点后第1位
- 油气流速 70L/min 用整型数据70表示
- 加油流速 112L/min 用整型数据112表示
- 油气流量 50L 用整型数据50表示
- 燃油流量 81L 用整型数据81表示
- 加油持续时间 33S 用整型数据33表示
- 字节位置 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
- 数据(Hex) 3e 00 d8 01 08 00 46 00 70 00 32 00 51 00 21*/
- struct StructYQ
- {
- BYTE al; //A/L 62% 用整型数据62表示
- BYTE concentration[2]; //回收油气浓度 21.6% 用整型数据216表示,个位实际表示小数点后第1位
- BYTE temperature[2]; //回收油气温度 26.4℃ 用整型数据264表示,个位实际表示小数点后第1位
- BYTE vapflow[2]; //油气流速 70L/min 用整型数据70表示
- BYTE liqflow[2]; //加油流速 112L/min 用整型数据112表示
- BYTE vapvol[2]; //油气流量 50L 用整型数据50表示
- BYTE liqvol[2]; //燃油流量 81L 用整型数据81表示
- BYTE timespan[2]; //加油持续时间 33S 用整型数据33表示
- };
- /*
- int TestType 测试类型:1符合性测试,2报警测试
- BYTE *pbTimeBuf 时间数据
- int TimeLen 时间数据长度
- BYTE *pbHJdataBuf 环境数据
- int HJdataLen 环境数据长度
- BYTE *pbYQdataBuf 加油枪数据
- int YQdataLen 加油枪数据长度
- 时间数据 14字节 时间(24小时制)格式为:yyyyMMddhhmmss
- 用十进制数的ASCII表示
- ex:
- 2015年06月26日19时03分16秒。
- 字节位置 0 1 2 3 4 5 6 7 8 9 10 11 12 13
- 数据(Hex) 32 30 31 35 30 36 32 36 31 39 30 33 31 36
- 环境数据
- 内容 长度 数据说明
- 储罐压力 4字节 4字节有符号整型,个位实际表示小数点后第1位,单位Pa
- ex: 105.6Pa HEX BUFFER: 00 00 04 20
- */
- struct StructRecv
- {
- BYTE TestType;
- BYTE pbTimeBuf[14];
- BYTE pbHJdataBuf[4];
- StructYQ pbYQdataBuf;
- };
- /*(下传协议测试数据)
- 油机上送:(length: 23)
- 长度(2Byte) + 命令字 + 加油点(1byte) + 枪 + 加油结束时间(7) + 总油量(3)
- + 最大油流速(2) + 总气量(3) + 最大气流速(2) + 气液比(2) + 测试类型(1)
- 模拟数据:01 01 00 01 01 00 17 11 01 01 20 17 05 22 16 39 30 00 07 D0 00 15 00 03 e8 00 14 04 4c 01
- */
- struct StructSend
- {
- byte dest[2];
- byte source[2];
- byte frame;
- byte length[2];
- byte cmd;
- byte fip;
- byte noz;
- byte time[7];
- byte liqvol[3]; //油体积;
- byte liqflow[2]; //油流速;
- byte vapvol[3]; //气体积;
- byte vapflow[2]; //气流速;
- byte vlr[2]; //气液比;
- byte testtag;
- };
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
- //
- //TODO: 如果此 DLL 相对于 MFC DLL 是动态链接的,
- // 则从此 DLL 导出的任何调入
- // MFC 的函数必须将 AFX_MANAGE_STATE 宏添加到
- // 该函数的最前面。
- //
- // 例如:
- //
- // extern "C" BOOL PASCAL EXPORT ExportedFunction()
- // {
- // AFX_MANAGE_STATE(AfxGetStaticModuleState());
- // // 此处为普通函数体
- // }
- //
- // 此宏先于任何 MFC 调用
- // 出现在每个函数中十分重要。 这意味着
- // 它必须作为函数中的第一个语句
- // 出现,甚至先于所有对象变量声明,
- // 这是因为它们的构造函数可能生成 MFC
- // DLL 调用。
- //
- // 有关其他详细信息,
- // 请参阅 MFC 技术说明 33 和 58。
- //
- // CTKHS_SDApp
- BEGIN_MESSAGE_MAP(CTKHS_SDApp, CWinApp)
- END_MESSAGE_MAP()
- int sendUDPData(CString strData, UINT nPort, LPCTSTR lpszAddress);
- DWORD __stdcall ThreadRecv(LPVOID lparam);
- DWORD __stdcall ThreadTimer(LPVOID lparam);
- CString strIP = "127.0.0.1";//"192.168.1.10";////"166.166.16.16";
- //CUdpClientSocket m_udpClient;
- std::queue<CString> que;
- DWORD m_id;
- DWORD m_recvid;
- CRITICAL_SECTION lock;
- CUdpClientSocket* pUdp;
- int count1 = 0;
- int count2 = 0;
- int count3 = 0;
- BOOL waittag = FALSE;
- int sendtimes = 0;
- long tickcount = 0;
- int failedtimes = 0;
- int g_recvflag = FALSE;
- long g_timerTick = 0;
- //发送线程
- DWORD __stdcall ThreadHandle(LPVOID lparam)
- {
- MSG msg;
- while (GetMessage(&msg, 0, 0, 0))
- {
- while (!que.empty())
- {
- EnterCriticalSection(&lock);
- CString szInfo = que.front();
- if (waittag == FALSE) //第一次发送
- {
- que.pop();
- LeaveCriticalSection(&lock);
- waittag = TRUE;
- sendtimes = 1;
- tickcount = GetTickCount();
- //BYTE buff[1024];
- //memset(buff, 0, 1024);
- //CTime tm = CTime::GetCurrentTime();
- //CString strTime = tm.Format("%Y%m%d%H%M%S");
- //CString szInfo;
- //szInfo = "010100010100";
- //szInfo += "17";
- //szInfo += "11";
- //szInfo += "01";
- //szInfo += "01";
- //szInfo += strTime;
- //szInfo += "0003e8"; //1000 / 100.0
- //szInfo += "0015"; //21 / 10.0
- //szInfo += "0003e8"; //1000 / 100.0
- //szInfo += "0014"; //20 / 10.0
- //szInfo += "03e8"; //1000 / 1000.0
- //szInfo += "01";
- int rtn = sendUDPData(szInfo, 10000, strIP);
- if (rtn == 0)
- {
- //AfxMessageBox(_T("send error!"));
- }
- count2++;
- CString str;
- str.Format(_T("\ncount2: %d\n"), count2);
- TRACE(str);
- }
- else //没收到,发三次
- {
- LeaveCriticalSection(&lock);
- if (failedtimes > 30) //总失败次数超过30则放弃重传机制
- {
- waittag = FALSE;
- continue;
- }
- if (sendtimes < 3 && GetTickCount() - tickcount > 1000)
- {
- sendtimes++;
- failedtimes++;
- //BYTE buff[1024];
- //memset(buff, 0, 1024);
- //CTime tm = CTime::GetCurrentTime();
- //CString strTime = tm.Format("%Y%m%d%H%M%S");
- //CString szInfo;
- //szInfo = "010100010100";
- //szInfo += "17";
- //szInfo += "11";
- //szInfo += "01";
- //szInfo += "01";
- //szInfo += strTime;
- //szInfo += "0003e8"; //1000 / 100.0
- //szInfo += "0015"; //21 / 10.0
- //szInfo += "0003e8"; //1000 / 100.0
- //szInfo += "0014"; //20 / 10.0
- //szInfo += "03e8"; //1000 / 1000.0
- //szInfo += "01";
- sendUDPData(szInfo, 10000, strIP);
- Sleep(10);
- tickcount = GetTickCount();
- }
- else if (sendtimes >= 3) //发送三次都不会则不再管
- {
- g_recvflag = FALSE;
- waittag = FALSE;
- }
- }
- }
- }
- return 1;
- }
- /*
- DWORD __stdcall ThreadHandle(LPVOID lparam)
- {
- MSG msg;
- while (GetMessage(&msg, 0, 0, 0))
- {
- if (msg.message == WM_THREAD_HANDLE)
- {
- EnterCriticalSection(&lock);
- if (!que.empty())
- {
- que.front();
- que.pop();
- LeaveCriticalSection(&lock);
- BYTE buff[1024];
- memset(buff, 0, 1024);
- CTime tm = CTime::GetCurrentTime();
- CString strTime = tm.Format("%Y%m%d%H%M%S");
- CString szInfo;
- szInfo = "010100010100";
- szInfo += "17";
- szInfo += "11";
- szInfo += "01";
- szInfo += "01";
- szInfo += strTime;
- szInfo += "0003e8"; //1000 / 100.0
- szInfo += "0015"; //21 / 10.0
- szInfo += "0003e8"; //1000 / 100.0
- szInfo += "0014"; //20 / 10.0
- szInfo += "03e8"; //1000 / 1000.0
- szInfo += "01";
- sendUDPData(szInfo, 10000, strIP);
- //count2++;
- //CString str;
- //str.Format(_T("\ncount2: %d\n"), count2);
- //TRACE(str);
- }
- else
- {
- LeaveCriticalSection(&lock);
- }
- }
- else if (msg.message == WM_THREAD_CLOSE)
- {
- pUdp->Close();
- }
- }
- return 1;
- }
- */
- // CTKHS_SDApp 构造
- CTKHS_SDApp::CTKHS_SDApp()
- {
- // TODO: 在此处添加构造代码,
- // 将所有重要的初始化放置在 InitInstance 中
- }
- CTKHS_SDApp::~CTKHS_SDApp()
- {
- ::PostThreadMessage(m_id, WM_THREAD_CLOSE, 0, 0);
- }
- // 唯一的一个 CTKHS_SDApp 对象
- CTKHS_SDApp theApp;
- // CTKHS_SDApp 初始化
- BOOL CTKHS_SDApp::InitInstance()
- {
- CWinApp::InitInstance();
- if (!AfxSocketInit())
- {
- AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
- return FALSE;
- }
-
- InitializeCriticalSection(&lock);
- HANDLE h = ::CreateThread(NULL, 0, ThreadHandle, (LPVOID)this, NULL, &m_id);
- HANDLE hr = ::CreateThread(NULL, 0, ThreadRecv, (LPVOID)this, NULL, &m_recvid);
- HANDLE htimer = ::CreateThread(NULL, 0, ThreadTimer, (LPVOID)this, NULL, NULL);
- pUdp = new CUdpClientSocket();
- pUdp->Create(0, SOCK_DGRAM, NULL);
- //pUdp->SetDialog(this);
- g_timerTick = GetTickCount();
- return TRUE;
- }
- //计时器线程
- //通过发送心跳命令看有没有收到回复来判断有没有连接成功,这样在dll接口被调用时就可以返回相应的值
- //在Socket接收线程ThreadRecv收到回复后关闭
- DWORD __stdcall ThreadTimer(LPVOID lparam)
- {
- while (!g_recvflag)
- {
- if (GetTickCount() - g_timerTick > 100)
- {
- sendUDPData("010100010100080620170428170030", 10000, strIP);
- g_timerTick = GetTickCount();
- }
- }
- return 1;
- }
- //Socket接收线程
- DWORD __stdcall ThreadRecv(LPVOID lparam)
- {
- MSG msg;
- while (GetMessage(&msg, 0, 0, 0))
- {
- BYTE pBuffer2[1024] = { 0 };
- CString straddr;
- UINT port;
- pUdp->GetPeerName(straddr, port);
- int nRecvNum = pUdp->ReceiveFrom(pBuffer2, 1024, straddr, port);
- if (nRecvNum != -1)
- {
- waittag = FALSE;
- g_recvflag = TRUE;
- count3++;
- CString str;
- str.Format(_T("\ncount3: %d\n"), count3);
- TRACE(str);
- }
- }
- return 1;
- }
- int sendUDPData(CString strData, UINT nPort, LPCTSTR lpszAddress)
- {
- CString str;
- CString str1 = "";
- BYTE buff[1024];
- memset(buff, 0, 1024);
- str = strData;
- int interval = 2;
- if (strData.GetLength() > 3)
- {
- if (strData[2] == ' ')
- {
- interval = 3;
- }
- else
- {
- interval = 2;
- }
- }
- int extra = interval - 2;
- int len = (strData.GetLength() + extra) / interval;
- for (int i = 0; i < len; ++i)
- {
- CString str2 = strData.Mid(i*interval, 2);
- sscanf_s(str2, "%2x", &buff[i]);
- }
- int rtn = pUdp->SendTo(buff, len, nPort, lpszAddress);
- return rtn;
- }
- //srclen:源字节数 , times:相差倍数, dsclen: 目标字节数
- CString convert(BYTE* src, int srclen, int times,int dsclen)
- {
- int val = 0;
- for (int i = 0; i < srclen; ++i)
- {
- val += src[i] * pow(256, srclen - i - 1);
- }
- val *= times;
- CString str;
- str.Format("%x", val);
- while (str.GetLength() < dsclen * 2)
- {
- str = "0" + str;
- }
- return str;
- }
- time_t FormatTime2(char * szTime)
- {
- struct tm tm1;
- time_t time1;
- sscanf_s(szTime, "%4d%2d%2d%2d%2d%2d",
- &tm1.tm_year,
- &tm1.tm_mon,
- &tm1.tm_mday,
- &tm1.tm_hour,
- &tm1.tm_min,
- &tm1.tm_sec);
- tm1.tm_year -= 1900;
- tm1.tm_mon--;
- tm1.tm_isdst = -1;
- time1 = mktime(&tm1);
- return time1;
- }
- /*
- 方法名称:测试数据发送接口
- 功能描述 检测软件通过该接口向被测系统下发测试数据
- 输入 参数 说明
- int TestType 测试类型:1符合性测试,2报警测试
- BYTE *pbTimeBuf 时间数据
- int TimeLen 时间数据长度
- BYTE *pbHJdataBuf 环境数据
- int HJdataLen 环境数据长度
- BYTE *pbYQdataBuf 加油枪数据
- int YQdataLen 加油枪数据长度
- 返回值 0 :成功 1 :输入数据错误 2 :数据发送失败
- */
- extern "C" __declspec(dllexport) int TKHS_SendData(int TestType, BYTE *pbTimeBuf, int TimeLen, BYTE *pbHJdataBuf, int HJdataLen, BYTE *pbYQdataBuf, int YQdataLen)
- {
- EnterCriticalSection(&lock);
- StructRecv RecvBuf;
- RecvBuf.TestType = TestType;
- memcpy(RecvBuf.pbTimeBuf, pbTimeBuf, TimeLen);
- //buf.TimeLen = TimeLen;
- memcpy(RecvBuf.pbHJdataBuf, pbHJdataBuf, HJdataLen);
- //buf.HJdataLen = HJdataLen;
- memcpy(&RecvBuf.pbYQdataBuf, pbYQdataBuf, YQdataLen);
- //buf.YQdataLen = YQdataLen;
- CString szInfo;
- szInfo = "010100010100";
- szInfo += "22";
- szInfo += "11";
- szInfo += "01";
- szInfo += "01";
- szInfo += CString(pbTimeBuf);
- int time = RecvBuf.pbYQdataBuf.timespan[0]*256 + RecvBuf.pbYQdataBuf.timespan[1];
-
- time_t begtime = FormatTime2((char*)(pbTimeBuf));
- begtime += time;
- tm tm1;
- localtime_s(&tm1, &begtime);
- char chEndTime[15];
- sprintf_s(chEndTime, "%04d%02d%02d%02d%02d%02d",
- tm1.tm_year + 1900,
- tm1.tm_mon + 1,
- tm1.tm_mday,
- tm1.tm_hour,
- tm1.tm_min,
- tm1.tm_sec);
- szInfo += CString(chEndTime);
- //szInfo += "0003e8"; //1000 / 100.0 总油量(3) 下传协议: liqvol 2 燃油流量 81L 用整型数据81表示
- szInfo += convert(RecvBuf.pbYQdataBuf.liqvol, 2, 100,3);
- //szInfo += "0015"; //21 / 10.0 最大油流速(2) 下传协议: liqflow 2 加油流速 112L/min 用整型数据112表示
- szInfo += convert(RecvBuf.pbYQdataBuf.liqflow, 2, 10,2);
- //szInfo += "0003e8"; //1000 / 100.0 总气量(3) 下传协议: vapvol 2 油气流量 50L 用整型数据50表示
- szInfo += convert(RecvBuf.pbYQdataBuf.vapvol, 2, 100,3);
- //szInfo += "0014"; //20 / 10.0 最大气流速(2) 下传协议: vapflow 油气流速 70L/min 用整型数据70表示
- szInfo += convert(RecvBuf.pbYQdataBuf.vapflow, 2, 10,2);
- //szInfo += "03e8"; //1000 / 1000.0 气液比(2) 下传协议: al A/L 62% 用整型数据62表示
- szInfo += convert(&RecvBuf.pbYQdataBuf.al, 1, 10,2);
- //油罐压力(4) "000493e0" 300000 / 100.0 下传协议: 储罐压力 4字节 4字节有符号整型,个位实际表示小数点后第1位,单位Pa 00 00 04 20 --- 105.6Pa
- szInfo += convert(RecvBuf.pbHJdataBuf, 4, 10, 4);
- //szInfo += "01";
- szInfo += convert(&RecvBuf.TestType, 1, 1,1);
- que.push(szInfo);
- LeaveCriticalSection(&lock);
- ::PostThreadMessage(m_id, WM_THREAD_HANDLE, 0, 0);
- if ((TestType != 1 && TestType != 2)
- || ( TimeLen != 14 && TimeLen != 0)
- || (HJdataLen != 4 && HJdataLen != 0)
- || (YQdataLen != 15 && YQdataLen != 0))
- {
- return 1;
- }
- if (g_recvflag == 1)
- {
- return 0; //数据发送失败
- }
- else
- {
- return 2;
- }
- }
|