| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- #include "../pch/pch.h"
- #include "CPosPrinterQueue.h"
- #include "../helper/CComHelper.h"
- CPosPrinterQueue::CPosPrinterQueue()
- {
- }
- void CPosPrinterQueue::StartWork()
- {
- m_is_work = true;
- m_nStopNum = 0;
- //处理收银打印
- std::thread(&CPosPrinterQueue::HandleShouyinPrinter, this).detach();
- //处理标签打印
- std::thread(&CPosPrinterQueue::HandleBiaoqianPrinter, this).detach();
- //处理厨房打印
- std::thread(&CPosPrinterQueue::HandleChufangPrinter, this).detach();
- }
- void CPosPrinterQueue::StopWork()
- {
- m_is_work = false;
- m_shouyin_printer_mutex.lock();
- while (!m_shouyin_printer_queue.empty())
- {
- m_shouyin_printer_queue.pop();
- }
- m_shouyin_printer_mutex.unlock();
- m_biaoqian_printer_mutex.lock();
- while (!m_biaoqian_printer_queue.empty())
- {
- m_biaoqian_printer_queue.pop();
- }
- m_biaoqian_printer_mutex.unlock();
- m_chufang_printer_mutex.lock();
- while (!m_chufang_printer_queue.empty())
- {
- m_chufang_printer_queue.pop();
- }
- m_chufang_printer_mutex.unlock();
- }
- void CPosPrinterQueue::AddShouyinPrinter(std::string chufang_data)
- {
- m_shouyin_printer_mutex.lock();
- m_shouyin_printer_queue.push(chufang_data);
- m_shouyin_printer_mutex.unlock();
- }
- void CPosPrinterQueue::AddBiaoqianPrinter(std::string data)
- {
- m_biaoqian_printer_mutex.lock();
- m_biaoqian_printer_queue.push(data);
- m_biaoqian_printer_mutex.unlock();
- }
- void CPosPrinterQueue::AddChufangPrinter(ChufangPrinterContent data)
- {
- m_chufang_printer_mutex.lock();
- m_chufang_printer_queue.push(data);
- m_chufang_printer_mutex.unlock();
- }
- void CPosPrinterQueue::HandleShouyinPrinter()
- {
- while (m_is_work)
- {
- m_shouyin_printer_mutex.lock();
- if (m_shouyin_printer_queue.empty())
- {
- m_shouyin_printer_mutex.unlock();
- CSystem::my_sleep(1);
- continue;
- }
- std::string data = m_shouyin_printer_queue.front();
- m_shouyin_printer_queue.pop();
- m_shouyin_printer_mutex.unlock();
- SendDataToShouyinPirnter(data);
- }
- AddStopNum();
- }
- void CPosPrinterQueue::HandleBiaoqianPrinter()
- {
- while (m_is_work)
- {
- m_biaoqian_printer_mutex.lock();
- if (m_biaoqian_printer_queue.empty())
- {
- m_biaoqian_printer_mutex.unlock();
- CSystem::my_sleep(1);
- continue;
- }
- std::string data = m_biaoqian_printer_queue.front();
- m_biaoqian_printer_queue.pop();
- m_biaoqian_printer_mutex.unlock();
- SendDataToBiaoqianPirnter(data);
- }
- AddStopNum();
- }
- void CPosPrinterQueue::HandleChufangPrinter()
- {
- while (m_is_work)
- {
- m_chufang_printer_mutex.lock();
- if (m_chufang_printer_queue.empty())
- {
- m_chufang_printer_mutex.unlock();
- CSystem::my_sleep(1);
- continue;
- }
- ChufangPrinterContent chufang_data = m_chufang_printer_queue.front();
- m_chufang_printer_queue.pop();
- m_chufang_printer_mutex.unlock();
- SendDataToChufangPirnter(chufang_data);
- }
- AddStopNum();
- }
- void CPosPrinterQueue::AddStopNum()
- {
- m_nStopNumMutex.lock();
- m_nStopNum++;
- m_nStopNumMutex.unlock();
- if (m_nStopNum == 8)
- {
- //确认所有子线程都退出了,再删除自己
- delete this;
- }
- }
- void CPosPrinterQueue::SendDataToShouyinPirnter(std::string data)
- {
- //默认是句柄模式
- int nType = 1;
- //用于厨房打印机和网口类型的收银小票打印
- boost::asio::io_service m_io;
- boost::asio::ip::tcp::socket m_socket(m_io);
- std::string printer_leixing = CSetting::GetInstance()->GetParam("setting_printer_leixing");
- if (printer_leixing == "auto")
- {
- InitUsb();
- if (m_hShouyinPorts.size() == 0)
- {
- return;
- }
- }
- else if (printer_leixing == "usb")
- {
- std::string printer_usb = CSetting::GetInstance()->GetParam("setting_printer_usb");
- std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb);
- bool ret = InitOneUsb(ws_printer_usb, 1);
- if (ret == false)
- {
- return;
- }
- }
- else if (printer_leixing == "bingkou")
- {
- bool ret = InitBingkou();
- if (ret == false)
- {
- return;
- }
- }
- else if (printer_leixing == "chuankou")
- {
- InitCom();
- }
- else if (printer_leixing == "wangkou")
- {
- //改为网口模式
- nType = 2;
- std::string wangkou_ip = CSetting::GetInstance()->GetParam("setting_printer_wangkou_ip");
- //初始化连接
- try
- {
- boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(wangkou_ip.c_str()), 9100);
- m_socket.connect(ep);
- }
- catch (std::exception& e)
- {
- std::string err = e.what();
- LOG_INFO("网口打印机连接失败,IP地址:" << wangkou_ip.c_str() << ",错误信息:" << err.c_str());
- MessageBoxW(NULL, (L"小票网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(wangkou_ip)).c_str(), L"打印机连接失败", MB_OK);
- return;
- }
- }
- //开始发送数据
- if (nType == 1)
- {
- //USB、串口、并口,走这里
- for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
- {
- HANDLE hPort = *it;
- //同步写数据
- DWORD dwWrite;
- BOOL ret = WriteFile(hPort, data.c_str(), data.length(), &dwWrite, NULL);
- if (!ret)
- {
- LOG_INFO("WriteFile Failed!, hPort:" << hPort);
- }
- }
- }
- else
- {
- //网口走这里
- try
- {
- m_socket.write_some(boost::asio::buffer(data.c_str(), data.length()));
- }
- catch (const std::exception& e)
- {
- LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
- }
- }
- //关闭设备
- for (std::vector<HANDLE>::iterator it = m_hShouyinPorts.begin(); it != m_hShouyinPorts.end(); it++)
- {
- CloseHandle(*it);
- }
- //删除之前旧的句柄
- m_hShouyinPorts.clear();
- if (nType == 2)
- {
- m_socket.close();
- }
- }
- void CPosPrinterQueue::SendDataToBiaoqianPirnter(std::string data)
- {
- std::string printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
- std::wstring ws_printer_usb = CLewaimaiString::UTF8ToUnicode(printer_usb);
- //连接usb端口
- bool ret = InitOneUsb(ws_printer_usb, 2);
- if (ret == false)
- {
- return;
- }
- //USB、串口、并口,走这里
- for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
- {
- HANDLE hPort = *it;
- //同步写数据
- DWORD dwWrite;
- BOOL ret = WriteFile(hPort, data.c_str(), data.length(), &dwWrite, NULL);
- if (!ret)
- {
- LOG_INFO("WriteFile Failed!, hPort:" << hPort);
- }
- }
- //关闭设备
- for (std::vector<HANDLE>::iterator it = m_hBiaoqianPorts.begin(); it != m_hBiaoqianPorts.end(); it++)
- {
- CloseHandle(*it);
- }
- m_hBiaoqianPorts.clear();
- }
- void CPosPrinterQueue::SendDataToChufangPirnter(ChufangPrinterContent chufang_data)
- {
- boost::asio::io_service m_io;
- boost::asio::ip::tcp::socket m_socket(m_io);
- //读取厨房打印机信息
- std::vector<ChufangPrinter> total_printers = CSetting::GetInstance()->getChufangPrints();
- std::string ip = chufang_data.ip;
- std::string data = chufang_data.data;
- //初始化连接
- try
- {
- boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string(ip.c_str()), 9100);
- m_socket.connect(ep);
- }
- catch (std::exception& e)
- {
- std::string err = e.what();
- LOG_INFO("厨房网口打印机连接失败,IP地址:" << ip.c_str() << ",错误信息:" << err.c_str());
- MessageBoxW(NULL, (L"厨房网口打印机连接失败,IP地址:" + CLewaimaiString::UTF8ToUnicode(ip)).c_str(), L"打印机连接失败", MB_OK);
- //连接失败了,处理下一个厨房打印机
- return;
- }
- //网口走这里
- try
- {
- m_socket.write_some(boost::asio::buffer(data.c_str(), data.length()));
- }
- catch (const std::exception& e)
- {
- LOG_INFO("网口打印机发送消息失败,错误信息:" << e.what());
- }
- m_socket.close();
- }
- //自动识别用于收银小票的USB打印机列表
- void CPosPrinterQueue::InitUsb()
- {
- //设置中文字符
- setlocale(LC_CTYPE, "chs");
- //取设备路径
- m_usb_devices.clear();
- int nDevice = GetDevicePath((LPGUID)&USB_GUID, m_usb_devices);
- LOG_INFO("可用的USB打印机数量:" << nDevice);
- //添加usb端口
- int i = 0;
- while (i < nDevice)
- {
- std::string setting_biaoqian_printer_usb = CSetting::GetInstance()->GetParam("setting_biaoqian_printer_usb");
- std::wstring ws_setting_biaoqian_printer_usb = CLewaimaiString::UTF8ToUnicode(setting_biaoqian_printer_usb);
- if (CSetting::GetInstance()->GetParam("setting_is_new_waimai_biaoqian_printer") == "1" && ws_setting_biaoqian_printer_usb == m_usb_devices[i])
- {
- //碰到了一个在设置中心明确设置的标签打印机,过滤掉
- i++;
- continue;
- }
- LOG_INFO("准备打开端口 Port = " << m_usb_devices[i].c_str());
- HANDLE hPort = CreateFile(m_usb_devices[i].c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开USB端口失败, Port = " << m_usb_devices[i].c_str());
- // 打开端口失败
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找对对应的usb端口");
- }
- else if (error == 5)
- {
- LOG_INFO("usb端口被占用!");
- }
- continue;
- }
- LOG_INFO("打开usb端口成功,准备进行打印机检测! hPort:" << hPort);
- m_hShouyinPorts.push_back(hPort);
- i++;
- }
- //清空usb集合,下一次调用这个函数的时候会重新设置
- m_usb_devices.clear();
- }
- bool CPosPrinterQueue::InitOneUsb(wstring usb_path, int nType)
- {
- if (usb_path == L"")
- {
- return false;
- }
- HANDLE hPort = CreateFile(usb_path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开USB端口失败, Port = " << usb_path.c_str());
- // 打开端口失败
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找对对应的usb端口");
- }
- else if (error == 5)
- {
- LOG_INFO("usb端口被占用!");
- }
- return false;
- }
- LOG_INFO("打开usb端口,准备进行打印机检测! hPort:" << hPort);
- if (nType == 1)
- {
- m_hShouyinPorts.push_back(hPort);
- }
- else
- {
- m_hBiaoqianPorts.push_back(hPort);
- }
- return true;
- }
- bool CPosPrinterQueue::InitBingkou()
- {
- std::wstring LptStr = L"lpt1";
- HANDLE hPort = CreateFile(LptStr.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("打开并口失败, Port = " << LptStr.c_str());
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("本机器没有并口!");
- }
- else if (error == 5)
- {
- LOG_INFO("并口被占用!");
- }
- return false;
- }
- else
- {
- //这个表示并口可以使用
- LOG_INFO("找到并口,准备进行打印机检测! hPort:" << hPort);
- m_hShouyinPorts.push_back(hPort);
- }
- return true;
- }
- void CPosPrinterQueue::InitCom()
- {
- CComHelper helper;
- std::vector<std::wstring> comVector = helper.getComPort();
- for (std::vector<std::wstring>::iterator it = comVector.begin(); it != comVector.end(); it++)
- {
- std::wstring com2Str = *it;
- HANDLE hPort = CreateFile(com2Str.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hPort == INVALID_HANDLE_VALUE)
- {
- DWORD error = GetLastError();
- if (error == 2)
- {
- //没有指定的文件
- LOG_INFO("没有找到对应的串口 " << com2Str.c_str());
- }
- else if (error == 5)
- {
- LOG_INFO("串口被占用 " << com2Str.c_str());
- }
- }
- else
- {
- LOG_INFO(com2Str.c_str() << " success, handle:" << hPort);
- //扎到了可用的串口,设置串口波特率
- DCB dcb;
- dcb.DCBlength = sizeof(dcb);
- GetCommState(hPort, &dcb);
- //佳博的串口打印机,默认是这个波特率
- dcb.BaudRate = 19200;
- if (!SetCommState(hPort, &dcb))
- {
- LOG_INFO("set baudRate failed!");
- CloseHandle(hPort);
- continue;
- }
- //设定通讯端口超时参数
- COMMTIMEOUTS tmouts;
- tmouts.ReadIntervalTimeout = 100;
- tmouts.ReadTotalTimeoutMultiplier = 100;
- tmouts.ReadTotalTimeoutConstant = 100;
- tmouts.WriteTotalTimeoutConstant = 100;
- tmouts.WriteTotalTimeoutMultiplier = 100;
- SetCommTimeouts(hPort, &tmouts);
- //设置端口缓冲
- SetupComm(hPort, 1024, 1024);
- //清除通讯端口缓存
- PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT);
- m_hShouyinPorts.push_back(hPort);
- }
- }
- }
- /*
- *获取CreateFile的USB端口号
- **/
- int CPosPrinterQueue::GetDevicePath(LPGUID lpGuid, std::vector<std::wstring>& usb_devices)
- {
- HDEVINFO hDevInfoSet;
- SP_DEVINFO_DATA spDevInfoData;
- SP_DEVICE_INTERFACE_DATA ifData;
- PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
- int nCount;
- int nTotle;
- BOOL bResult;
- //这2个字符串,用于根据usb的名字对比是否为打印机设备
- wstring strUSBPrint = TEXT("USB 打印支持");
- //xp上是英文
- wstring strUSBPrint_EN = L"USB Printing Support";
- // 取得一个该GUID相关的设备信息集句柄
- hDevInfoSet = ::SetupDiGetClassDevs(lpGuid, // class GUID
- NULL, // 无关键字
- NULL, // 不指定父窗口句柄
- DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
- // 失败...
- if (hDevInfoSet == INVALID_HANDLE_VALUE)
- {
- LOG_INFO("SetupDiGetClassDevs failed \r\n");
- return 0;
- }
- // 申请设备接口数据空间
- pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, INTERFACE_DETAIL_SIZE);
- pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- nTotle = -1;
- nCount = 0;
- bResult = TRUE;
- // 设备序号=0,1,2... 逐一测试设备接口,到失败为止
- while (bResult)
- {
- nTotle++;
- spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
- // 枚举符合该GUID的设备接口
- bResult = ::SetupDiEnumDeviceInfo(
- hDevInfoSet, // 设备信息集句柄
- (ULONG)nTotle, // 设备信息集里的设备序号
- &spDevInfoData); // 设备接口信息
- if (bResult)
- {
- DWORD DataT;
- TCHAR buf[MAX_PATH] = { 0 };
- DWORD nSize = 0;
- // get Friendly Name or Device Description
- if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
- SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize))
- {
- }
- else if (SetupDiGetDeviceRegistryProperty(hDevInfoSet, &spDevInfoData,
- SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize))
- {
- }
- else
- {
- lstrcpy(buf, _T("Unknown"));
- }
- wstring ws_buf = buf;
- //是否是要找的设备类型
- if (ws_buf != strUSBPrint && ws_buf != strUSBPrint_EN)
- {
- LOG_INFO("not good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str());
- continue;
- }
- LOG_INFO("good usb, buf:" << CLewaimaiString::UnicodeToANSI(ws_buf).c_str());
- ifData.cbSize = sizeof(ifData);
- // 枚舉符合該GUID的設備接口
- bResult = ::SetupDiEnumDeviceInterfaces(
- hDevInfoSet, // 設備信息集句柄
- NULL, // 不需額外的設備描述
- lpGuid, // GUID
- (ULONG)nTotle, // 設備信息集里的設備序號
- &ifData); // 設備接口信息
- if (bResult)
- {
- // 取得该设备接口的细节(设备路径)
- bResult = SetupDiGetInterfaceDeviceDetail(
- hDevInfoSet, // 设备信息集句柄
- &ifData, // 设备接口信息
- pDetail, // 设备接口细节(设备路径)
- INTERFACE_DETAIL_SIZE, // 输出缓冲区大小
- NULL, // 不需计算输出缓冲区大小(直接用设定值)
- NULL); // 不需额外的设备描述
- if (bResult)
- {
- wstring DevicePath = pDetail->DevicePath;
- wstring vid = DevicePath.substr(DevicePath.find(_T("vid_"), 0) + 4, 4);
- wstring pid = DevicePath.substr(DevicePath.find(_T("pid_"), 0) + 4, 4);
- LOG_INFO("Vid:" << vid.c_str() << ", Pid:" << pid.c_str());
- // 复制设备路径到输出缓冲区
- usb_devices.push_back(DevicePath);
- // 调整计数值
- nCount++;
- LOG_INFO("Cnt = " << nCount << ",pDetail->DevicePath =" << pDetail->DevicePath);
- }
- }
- }
- else
- {
- //LOG_INFO("SetupDiEnumDeviceInfo FAILED!@");
- }
- }
- // 释放设备接口数据空间
- ::GlobalFree(pDetail);
- // 关闭设备信息集句柄
- ::SetupDiDestroyDeviceInfoList(hDevInfoSet);
- return nCount;
- }
- std::vector<std::wstring> CPosPrinterQueue::getUsbDevices()
- {
- std::vector<std::wstring> usb_devices;
- int nDevice = GetDevicePath((LPGUID)&USB_GUID, usb_devices);
- return usb_devices;
- }
|