// IntervalToSendDlg.cpp : 实现文件 // #include "stdafx.h" #include "IntervalToSend.h" #include "IntervalToSendDlg.h" #include "afxdialogex.h" #include "define.h" #include #include #include #include #include #ifdef _DEBUG #define new DEBUG_NEW #endif // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx { public: CAboutDlg(); // 对话框数据 enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx) END_MESSAGE_MAP() // CIntervalToSendDlg 对话框 CIntervalToSendDlg::CIntervalToSendDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CIntervalToSendDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CIntervalToSendDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDT_DATA, m_data); DDX_Text(pDX, IDC_NET_ADDR, m_ip); DDX_Text(pDX, IDC_EDT_PORT, m_port); DDX_Control(pDX, IDC_CMB_TYPE, m_cmbType); DDX_Check(pDX, IDC_CHK_CYCLE, m_bCycle); DDX_Check(pDX, IDC_CHK_MODIFY, m_bModify); DDX_Check(pDX, IDC_CHK_HEX, m_bHex); } BEGIN_MESSAGE_MAP(CIntervalToSendDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BTN_START, &CIntervalToSendDlg::OnBnClickedBtnStart) ON_BN_CLICKED(IDC_BTN_CLEAR, &CIntervalToSendDlg::OnBnClickedBtnClear) ON_BN_CLICKED(IDC_BTN_IMPORT, &CIntervalToSendDlg::OnBnClickedBtnImport) ON_MESSAGE(WM_THREAD_STOP, &CIntervalToSendDlg::OnThreadStop) ON_MESSAGE(WM_THREAD_UPDATE_DATA, &CIntervalToSendDlg::OnUpdateData) END_MESSAGE_MAP() // CIntervalToSendDlg 消息处理程序 BOOL CIntervalToSendDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 UpdateData(FALSE); m_cmbType.InsertString((int)eSendType::ST_ONE_SECOND, "每秒发送一次"); m_cmbType.InsertString((int)eSendType::ST_TEN_SECOND, "每十秒发送一次"); m_cmbType.InsertString((int)eSendType::ST_ONE_MINITUE, "每分钟发送一次"); m_cmbType.InsertString((int)eSendType::ST_ONE_HOUR, "每小时发送一次"); m_cmbType.InsertString((int)eSendType::ST_ONE_100MILLI, "每100毫秒发送一次"); m_cmbType.InsertString((int)eSendType::ST_ACTUAL, "模拟实际发送"); m_cmbType.InsertString((int)eSendType::ST_ONE_10MILLI, "每10毫秒发送一次"); auto nPos = GetPrivateProfileInt("INFO", "sendtype",(int)eSendType::ST_ONE_SECOND, "IntervalToSend.ini"); m_cmbType.SetCurSel(nPos); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } void CIntervalToSendDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialogEx::OnSysCommand(nID, lParam); } } // 如果向对话框添加最小化按钮,则需要下面的代码 // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序, // 这将由框架自动完成。 void CIntervalToSendDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // 绘制图标 dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); } } //当用户拖动最小化窗口时系统调用此函数取得光标 //显示。 HCURSOR CIntervalToSendDlg::OnQueryDragIcon() { return static_cast(m_hIcon); } void CIntervalToSendDlg::OnBnClickedBtnStart() { UpdateData(TRUE); if (m_data.IsEmpty()) { MessageBox("数据不能为空", "提示", MB_ICONWARNING); return; } if (m_thread) { m_bwork = false; m_thread->join(); delete m_thread; m_thread = nullptr; GetDlgItem(IDC_BTN_START)->SetWindowText("开始"); GetDlgItem(IDC_BTN_IMPORT)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_CLEAR)->EnableWindow(TRUE); GetDlgItem(IDC_EDT_DATA)->EnableWindow(TRUE); } else { AfxMessageBox("解析需要一点时间, 请多一点点耐心等待结束..."); auto lst = new list; if (m_bHex) { if (checkData() == false) return; BYTE* pData = new BYTE[m_data.GetLength() / 2]; int nPos = 0; int nLen = m_data.GetLength(); char* p = m_data.GetBuffer(); for (int i = 0; i < nLen - 1; i += 2) { char a[3] = { m_data.GetAt(i), m_data.GetAt(i + 1), 0 }; pData[nPos++] = strtol(a, NULL, 16); } CLNBuffer buffer; buffer.AddData(pData, nPos); while (true) { int nPackLen = buffer.HasPack(); if (nPackLen == 0) break; SEND_DATA data; data.pData = new uint8_t[nPackLen]; memcpy(data.pData, buffer.GetBuffer(), nPackLen); buffer.Remove(nPackLen); data.nLen = nPackLen; lst->push_back(data); } buffer.Empty(); delete[] pData; pData = NULL; } else { CLNBuffer buffer; buffer.AddData((LPBYTE)(LPCSTR)m_data, m_data.GetLength()); while (true) { int nPackLen = buffer.HasPack(); if (nPackLen == 0) break; SEND_DATA data; data.pData = new uint8_t[nPackLen]; memcpy(data.pData, buffer.GetBuffer(), nPackLen); buffer.Remove(nPackLen); data.nLen = nPackLen; lst->push_back(data); } } if (lst->size() == 0) { MessageBox("未解析到数据包", "提示", MB_ICONWARNING); delete lst; return; } CString strLog; strLog.Format("解析完毕,一共解析 %d 道下载命令.开始发送.", lst->size()); AfxMessageBox(strLog); m_bwork = true; m_thread = new std::thread(ThreadProc, (DWORD_PTR)this, (DWORD_PTR)lst, (DWORD_PTR)0); GetDlgItem(IDC_BTN_START)->SetWindowText("停止"); GetDlgItem(IDC_BTN_IMPORT)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_CLEAR)->EnableWindow(FALSE); GetDlgItem(IDC_EDT_DATA)->EnableWindow(FALSE); } } void CIntervalToSendDlg::OnBnClickedBtnClear() { m_data.Empty(); UpdateData(FALSE); } void CIntervalToSendDlg::OnBnClickedBtnImport() { CString strFilter = _T("文件(*.txt)|*.txt||"); CFileDialog dlg(TRUE, _T(".txt"), NULL, NULL, strFilter); if (dlg.DoModal() == IDOK) { CString strOpenFile = dlg.GetPathName(); AfxMessageBox("解析需要一点时间, 请多一点点耐心等待结束..."); auto lst = new list; auto mapData = new map>; CFile file; if (file.Open(strOpenFile, CFile::modeRead) == FALSE) return ; int len = file.GetLength(); auto file_data = new uint8_t[len]; int l = file.Read(file_data, len); file.Close(); CLNBuffer buffer; buffer.AddData(file_data, len); while (true) { int nPackLen = buffer.HasPack(); if (nPackLen == 0) break; SEND_DATA data; data.pData = new uint8_t[nPackLen]; memcpy(data.pData, buffer.GetBuffer(), nPackLen); buffer.Remove(nPackLen); data.nLen = nPackLen; auto doc = yyjson_read((char*)data.pData, data.nLen, 0); if (doc) { auto root = yyjson_doc_get_root(doc); if (yyjson_is_obj(root) && yyjson_obj_get(root, "IMEI")) { lst->emplace_back(data); auto t = yyjson_get_str(yyjson_obj_get(root, "time")); if (t) { int year, month, day, hour, minute, second; TRACE("%s\r\n", t); auto n = sscanf_s(t, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); if (n == 6) { (*mapData)[hour * 3600 + minute * 60 + second].emplace_back(data); } else { int ii = 0; } } } else { delete[] data.pData; } yyjson_doc_free(doc); } else { delete[] data.pData; } } if (lst->size() == 0) { MessageBox("未解析到数据包", "提示", MB_ICONWARNING); delete lst; return; } CString strLog; strLog.Format("解析完毕,一共解析 %d 道下载命令.开始发送.", lst->size()); AfxMessageBox(strLog); delete[] file_data; file_data = nullptr; UpdateData(TRUE); //m_cmbType.SetCurSel((int)eSendType::ST_ONE_100MILLI); WritePrivateProfileString("INFO", "sendtype", std::to_string(m_cmbType.GetCurSel()).c_str(), "IntervalToSend.ini"); m_bwork = true; m_thread = new std::thread(ThreadProc, (DWORD_PTR)this, (DWORD_PTR)lst, (DWORD_PTR)mapData); GetDlgItem(IDC_BTN_START)->SetWindowText("停止"); GetDlgItem(IDC_BTN_IMPORT)->EnableWindow(FALSE); GetDlgItem(IDC_BTN_CLEAR)->EnableWindow(FALSE); GetDlgItem(IDC_EDT_DATA)->EnableWindow(FALSE); } } HRESULT CIntervalToSendDlg::OnThreadStop(WPARAM w, LPARAM l) { if (m_thread) { m_thread->join(); delete m_thread; } m_thread = nullptr; m_bwork = false; GetDlgItem(IDC_BTN_START)->SetWindowText("开始"); GetDlgItem(IDC_BTN_IMPORT)->EnableWindow(TRUE); GetDlgItem(IDC_BTN_CLEAR)->EnableWindow(TRUE); GetDlgItem(IDC_EDT_DATA)->EnableWindow(TRUE); MessageBox("发送结束", "提示", MB_ICONINFORMATION); return 0; } HRESULT CIntervalToSendDlg::OnUpdateData(WPARAM w, LPARAM l) { time_t tmNow = (time_t)w; if (w < m_tmLast) return 0; UpdateData(FALSE); return 0; } void CIntervalToSendDlg::ThreadProc(DWORD_PTR pThis, DWORD_PTR data, DWORD_PTR m) { CIntervalToSendDlg* pDlg = (CIntervalToSendDlg*)pThis; auto lst = (list*)data; auto mapData = (map>*)m; time_t lastSend = 0; eSendType type = (eSendType)pDlg->m_cmbType.GetCurSel(); auto it = lst->cbegin(); g_udpSocket.SendTo(pDlg->m_strInfo, pDlg->m_strInfo.GetLength(), pDlg->m_port, pDlg->m_ip); int nSleepTime = 100; do { Sleep(nSleepTime); time_t tmNow; time(&tmNow); pDlg->PostMessage(WM_THREAD_UPDATE_DATA, (DWORD_PTR)tmNow, 0); if (type == eSendType::ST_ONE_100MILLI) { if (nSleepTime != 100) nSleepTime = 100; if (it == lst->cend()) break; auto doc = yyjson_read((char*)it->pData, it->nLen, 0); do { auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { //yyjson_mut_obj_remove_str(root, "time"); //yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); yyjson_mut_obj_add_int(d_doc, root, "make_up", 1); //补传标记 } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); yyjson_doc_free(doc); } else if (type == eSendType::ST_ONE_10MILLI) { if (nSleepTime != 10) nSleepTime = 10; if (it == lst->cend()) break; auto doc = yyjson_read((char*)it->pData, it->nLen, 0); do { auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { //yyjson_mut_obj_remove_str(root, "time"); //yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); yyjson_mut_obj_add_int(d_doc, root, "make_up", 1); //补传标记 } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); } else if (type == eSendType::ST_ONE_SECOND) { if (nSleepTime != 100) nSleepTime = 100; if (tmNow > lastSend) { if (pDlg->m_bCycle) //循环发送 { if (it == lst->cend()) it = lst->cbegin(); } else { if (it == lst->cend()) break; } if (pDlg->m_bModify) //修正时间 { auto doc = yyjson_read((char*)it->pData, it->nLen, 0); do { COleDateTime dt(tmNow); auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { yyjson_mut_obj_remove_str(root, "time"); yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); yyjson_doc_free(doc); } else { g_udpSocket.SendTo(it->pData, it->nLen, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; } } } else if (type == eSendType::ST_TEN_SECOND) { if (nSleepTime != 100) nSleepTime = 100; if (tmNow > lastSend && (tmNow - lastSend) % 10 == 0) { if (pDlg->m_bCycle) //循环发送 { if (it == lst->cend()) it = lst->cbegin(); } else { if (it == lst->cend()) break; } if (pDlg->m_bModify) //修正时间 { auto doc = yyjson_read((char*)it->pData, it->nLen, 0); do { COleDateTime dt(tmNow); auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { yyjson_mut_obj_remove_str(root, "time"); yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); yyjson_doc_free(doc); } else { g_udpSocket.SendTo(it->pData, it->nLen, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; } } } else if (type == eSendType::ST_ONE_MINITUE) { if (nSleepTime != 100) nSleepTime = 100; if (tmNow != lastSend && (tmNow - lastSend) % 60 == 0) { if (pDlg->m_bCycle) //循环发送 { if (it == lst->cend()) it = lst->cbegin(); } else { if (it == lst->cend()) break; } if (pDlg->m_bModify) //修正时间 { auto doc = yyjson_read((char*)it->pData, it->nLen, 0); do { COleDateTime dt(tmNow); auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { yyjson_mut_obj_remove_str(root, "time"); yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); yyjson_doc_free(doc); } else { g_udpSocket.SendTo(it->pData, it->nLen, pDlg->m_port, pDlg->m_ip); lastSend = tmNow; ++it; } } } else if (type == eSendType::ST_ACTUAL) { if (nSleepTime != 100) nSleepTime = 100; if (mapData == nullptr) break; if (tmNow > lastSend) { COleDateTime dt(tmNow); auto tt = dt.GetHour() * 3600 + dt.GetMinute() * 60 + dt.GetSecond(); TRACE("%d:%d:%d %d\t\r", dt.GetHour(), dt.GetMinute(), dt.GetSecond(), tt); auto ik = mapData->find(tt); if (ik == mapData->end()) { lastSend = tmNow; continue; } for (auto& im : ik->second) { auto doc = yyjson_read((char*)im.pData, im.nLen, 0); do { auto d_doc = yyjson_doc_mut_copy(doc, 0); auto root = yyjson_mut_doc_get_root(d_doc); if (yyjson_mut_is_obj(root)) { yyjson_mut_obj_remove_str(root, "time"); yyjson_mut_obj_add_strcpy(d_doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); } size_t len = 0; auto json = yyjson_mut_write(d_doc, 0, &len); if (json) { g_udpSocket.SendTo(json, len, pDlg->m_port, pDlg->m_ip); TRACE("%s %d:%d:%d", pDlg->m_ip, dt.GetHour(), dt.GetMinute(), dt.GetSecond()); free((void*)json); } yyjson_mut_doc_free(d_doc); } while (false); yyjson_doc_free(doc); } lastSend = tmNow; } else if (lastSend > tmNow) lastSend = tmNow - 1; //系统修改了时间 } } while (pDlg->m_bwork); for (auto it = lst->begin(); it != lst->end(); it++) { delete it->pData; } lst->clear(); pDlg->PostMessage(WM_THREAD_STOP, 0, 0); } bool CIntervalToSendDlg::checkData() { UpdateData(TRUE); if (m_data.GetLength() > 50000) { MessageBox("长度请勿超过5W"); m_data = CString(); UpdateData(FALSE); return false; } static BYTE data[50000] = { 0 }; int nLen = 0; int nDataLen = m_data.GetLength(); for (int i = 0; i < nDataLen; i++) { char c = ((LPCSTR)m_data)[i]; if (c == ' ') { } else if (c == 0x0d) { } else if (c == 0x0a) { } else if (!(((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f')) || ((c >= 'A') && (c <= 'F')))) { MessageBox("请输入HEX数据"); m_data = CString(); UpdateData(FALSE); return false; } else { data[nLen++] = c; } } ASSERT(nLen % 2 == 0); if (nLen % 2 == 1) nLen--; m_data = CString((char*)data, nLen); UpdateData(FALSE); return true; }