Преглед изворни кода

准备开始调试推送了

zhangyang пре 4 година
родитељ
комит
fc75749a28

+ 57 - 0
zhipuzi_pos_windows/CAppEnv.cpp

@@ -0,0 +1,57 @@
+#include "pch/pch.h"
+#include "CAppEnv.h"
+
+#include "print/CPosPrinterQueue.h"
+#include "tool/CChengzhongWorker.h"
+#include "worker/CMessagePushWorker.h"
+#include "worker/CCommonWorker.h"
+#include "worker/CVoiceWorker.h"
+
+CAppEnv::CAppEnv()
+{
+}
+
+
+CAppEnv::~CAppEnv()
+{
+}
+
+void CAppEnv::Start()
+{
+	//初始化日志
+	CLewaimaiLog log;
+	log.Init();
+
+	//启动打印队列
+	CPosPrinterQueue::GetInstance()->StartWork();
+
+	//启动称重任务
+	CChengzhongWorker::GetInstance()->StartWork();
+
+	//启动声音任务
+	CVoiceWorker::GetInstance()->Start();
+
+	//启动通用任务
+	CCommonWorker::GetInstance()->Start();
+
+	//启动消息推送
+	CMessagePushWorker::GetInstance()->Start();
+}
+
+void CAppEnv::Stop()
+{
+	//停止打印任务
+	CPosPrinterQueue::GetInstance()->StopWork();
+
+	//停止称重任务
+	CChengzhongWorker::GetInstance()->StopWork();
+
+	//停止声音任务
+	CVoiceWorker::GetInstance()->Stop();
+
+	//停止通用任务
+	CCommonWorker::GetInstance()->Stop();
+
+	//停止消息推送
+	CMessagePushWorker::GetInstance()->Stop();
+}

+ 15 - 0
zhipuzi_pos_windows/CAppEnv.h

@@ -0,0 +1,15 @@
+#pragma once
+
+//´ŚŔíËůÓĐťˇžłłőĘźťŻ
+class CAppEnv
+{
+public:
+	CAppEnv();
+	~CAppEnv();
+
+	void Start();
+	void Stop();
+
+private:
+};
+

+ 4 - 4
zhipuzi_pos_windows/helper/CLewaimaiLog.cpp

@@ -29,20 +29,20 @@ void CLewaimaiLog::Init()
 		new RollingFileAppender(err_path.c_str(), 200 * 1024 * 1024, 100,
 			true, true));
 
-	append_1->setName(LOG4CPLUS_TEXT("lewaimai_dispatch"));
+	append_1->setName(LOG4CPLUS_TEXT("zhipuzi_pos"));
 	append_1->setLayout(std::auto_ptr<Layout>(new PatternLayout(LOG4CPLUS_TEXT("%D{%Y-%m-%d %H:%M:%S}[%p] - %m [%l]%n"))));
 	append_1->getloc();
 
-	append_2->setName(LOG4CPLUS_TEXT("lewaimai_dispatch_error"));
+	append_2->setName(LOG4CPLUS_TEXT("zhipuzi_pos_error"));
 	append_2->setLayout(std::auto_ptr<Layout>(new PatternLayout(LOG4CPLUS_TEXT("%D{%Y-%m-%d %H:%M:%S}[%p] - %m [%l]%n"))));
 	append_2->getloc();
 
-	Logger _Logger_info = Logger::getInstance(LOG4CPLUS_TEXT("lewaimai_dispatch"));
+	Logger _Logger_info = Logger::getInstance(LOG4CPLUS_TEXT("zhipuzi_pos"));
 	_Logger_info.addAppender(SharedAppenderPtr(append_1.get()));
 	//日志优先级从低到高ALL_LOG_LEVEL、TRACE_LOG_LEVEL、DEBUG_LOG_LEVEL、INFO_LOG_LEVEL、WARN_LOG_LEVEL、ERROR_LOG_LEVEL、FATAL_LOG_LEVEL、OFF_LOG_LEVEL
 	_Logger_info.setLogLevel(INFO_LOG_LEVEL);
 
-	Logger _Logger_error = Logger::getInstance(LOG4CPLUS_TEXT("lewaimai_dispatch_error"));
+	Logger _Logger_error = Logger::getInstance(LOG4CPLUS_TEXT("zhipuzi_pos_error"));
 	_Logger_error.addAppender(SharedAppenderPtr(append_2.get()));
 	//日志优先级从低到高ALL_LOG_LEVEL、TRACE_LOG_LEVEL、DEBUG_LOG_LEVEL、INFO_LOG_LEVEL、WARN_LOG_LEVEL、ERROR_LOG_LEVEL、FATAL_LOG_LEVEL、OFF_LOG_LEVEL
 	_Logger_error.setLogLevel(ERROR_LOG_LEVEL);

+ 109 - 1
zhipuzi_pos_windows/helper/CSystem.cpp

@@ -1,7 +1,8 @@
 #include "../pch/pch.h"
 #include "CSystem.h"
 
-#include<direct.h>
+#include <direct.h>
+#include "tlhelp32.h"
 
 CSystem::CSystem()
 {
@@ -199,3 +200,110 @@ void CSystem::CreateMultiLevel(string dir)
 		_mkdir(it.c_str());
 	}
 }
+
+BOOL CSystem::IsRunasAdmin()
+{
+	BOOL bElevated = FALSE;
+	HANDLE hToken = NULL;
+
+	// Get current process token
+	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+		return FALSE;
+
+	TOKEN_ELEVATION tokenEle;
+	DWORD dwRetLen = 0;
+
+	// Retrieve token elevation information
+	if (GetTokenInformation(hToken, TokenElevation, &tokenEle, sizeof(tokenEle), &dwRetLen))
+	{
+		if (dwRetLen == sizeof(tokenEle))
+		{
+			bElevated = tokenEle.TokenIsElevated;
+		}
+	}
+
+	CloseHandle(hToken);
+	return bElevated;
+}
+
+BOOL CSystem::processIdToName(LPTSTR lpszProcessName, DWORD PID)
+{
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	PROCESSENTRY32 pe;
+	pe.dwSize = sizeof(PROCESSENTRY32);
+	if (!Process32First(hSnapshot, &pe))
+	{
+		return FALSE;
+	}
+	while (Process32Next(hSnapshot, &pe))
+	{
+		if (pe.th32ProcessID == PID)
+		{
+			wcscpy(lpszProcessName, pe.szExeFile);
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+BOOL CSystem::IsAppRunning()
+{
+	PROCESSENTRY32 pe32;
+	//在使用这个结构前,先设置它的大小
+	pe32.dwSize = sizeof(pe32);
+	//给系统内所有的进程拍个快照
+	HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+	if (hProcessSnap == INVALID_HANDLE_VALUE)
+	{
+		return FALSE;
+	}
+
+	//遍历进程快照,轮流显示每个进程的信息
+	BOOL bMore = ::Process32First(hProcessSnap, &pe32);
+
+	int nCount = 0;
+
+	while (bMore)
+	{
+		//找到了进程
+		if (wstring(pe32.szExeFile) == L"zhipuzi_pos_windows.exe")
+		{
+			nCount++;
+		}
+
+		bMore = ::Process32Next(hProcessSnap, &pe32);
+	}
+
+	if (nCount > 1)
+	{
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+void CSystem::RunHotKey(int mod, int key)
+{
+	BYTE mod_key;
+
+	if (mod == 1)
+	{
+		mod_key = VK_MENU;
+	}
+	else if (mod == 2)
+	{
+		mod_key = VK_CONTROL;
+	}
+	else if (mod == 3)
+	{
+		mod_key = VK_SHIFT;
+	}
+
+	keybd_event(mod_key, (BYTE)0, 0, 0);
+	keybd_event((BYTE)key, (BYTE)0, 0, 0);
+
+	keybd_event((BYTE)key, (BYTE)0, KEYEVENTF_KEYUP, 0);
+	keybd_event(mod_key, (BYTE)0, KEYEVENTF_KEYUP, 0);
+}

+ 8 - 0
zhipuzi_pos_windows/helper/CSystem.h

@@ -37,5 +37,13 @@ public:
 	static std::string GetVersion();
 
 	static void CreateMultiLevel(string dir);
+
+	static BOOL IsRunasAdmin();
+
+	static BOOL processIdToName(LPTSTR lpszProcessName, DWORD PID);
+
+	static BOOL IsAppRunning();
+
+	static void RunHotKey(int mod, int key);
 };
 

+ 0 - 351
zhipuzi_pos_windows/network/CMessagePush.cpp

@@ -1,351 +0,0 @@
-#include "../pch/pch.h"
-#include "CMessagePush.h"
-
-#include "mmsystem.h"
-#include "PosMessage.h"
-
-#include "../print/CPosPrinter.h"
-
-CMessagePush::~CMessagePush()
-{
-
-}
-
-void CMessagePush::Start()
-{
-	m_is_work = true;
-
-	m_nStopNum = 0;
-
-    //心跳包
-	std::thread(&CMessagePush::KeepAlive, this).detach();
-
-	//接收消息
-	std::thread(&CMessagePush::ReceiveMessage, this).detach();
-
-    //处理声音提醒
-    std::thread(&CMessagePush::HandleVoice, this).detach();
-
-    //处理订单确认
-    std::thread(&CMessagePush::HandleConfirm, this).detach();
-}
-
-void CMessagePush::Stop()
-{
-	m_is_work = false;
-
-	socket_.close();
-
-	m_voice_mutex.lock();
-	while (!m_voice_queue.empty())
-	{
-		m_voice_queue.pop();
-	}
-	m_voice_mutex.unlock();
-
-	m_confirm_mutex.lock();
-	while (!m_confirm_queue.empty())
-	{
-		m_confirm_queue.pop();
-	}
-	m_confirm_mutex.unlock();
-}
-
-void CMessagePush::KeepAlive()
-{
-	while (m_is_work)
-	{
-		//生成心跳包
-		rapidjson::Document doc;
-		doc.SetObject();
-		rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); //获取分配器
-
-		std::string username = CSetting::getUsername();
-		std::string timestamp = to_string(time(NULL));
-		doc.AddMember("username", StringRef(username.c_str(), username.length()), allocator);
-		doc.AddMember("timestamp", StringRef(timestamp.c_str(), timestamp.length()), allocator);
-		doc.AddMember("is_login", "0", allocator);
-
-		rapidjson::StringBuffer buffer;
-		rapidjson::Writer<StringBuffer> writer(buffer);
-		doc.Accept(writer);
-
-		//返回给接入层的消息
-		std::string m_keepalive_msg = buffer.GetString();
-
-		PosMessage new_msg;
-		new_msg.m_length = m_keepalive_msg.length();
-		memcpy(new_msg.data, m_keepalive_msg.c_str(), m_keepalive_msg.length());
-		new_msg.data[new_msg.m_length] = '\0';
-
-		try
-		{
-			socket_.write_some(boost::asio::buffer(&new_msg, sizeof(PosMessage)));
-		}
-		catch (const std::exception& e)
-		{
-			//走到这里来说明心跳包发送失败了,socket失效了
-			std::string err = e.what();
-
-			//先把socket关闭掉
-			socket_.close();
-
-			try
-			{
-				//发送失败,重新建立连接
-				char host[] = "pushserver.lewaimai.com";
-				char port[] = "9001";
-
-				tcp::resolver resolver(m_io_context);
-				tcp::resolver::results_type endpoints =
-					resolver.resolve(tcp::v4(), host, port);
-
-				boost::asio::connect(socket_, endpoints);
-
-				//刚刚连接上,这是第一次登陆,发送登陆信息
-				rapidjson::Document doc_1;
-				doc_1.SetObject();
-				rapidjson::Document::AllocatorType& allocator_1 = doc_1.GetAllocator(); //获取分配器
-
-				std::string username_1 = CSetting::getUsername();
-				std::string timestamp_1 = to_string(time(NULL));
-				doc_1.AddMember("username", StringRef(username_1.c_str(), username_1.length()), allocator_1);
-				doc_1.AddMember("timestamp", StringRef(timestamp_1.c_str(), timestamp_1.length()), allocator_1);
-				doc_1.AddMember("is_login", "1", allocator_1);
-
-				rapidjson::StringBuffer buffer_1;
-				rapidjson::Writer<StringBuffer> writer_1(buffer_1);
-				doc_1.Accept(writer_1);
-
-				//返回给接入层的消息
-				std::string m_login_message = buffer_1.GetString();
-
-				PosMessage login_msg;
-				login_msg.m_length = m_login_message.length();
-				memcpy(login_msg.data, m_login_message.c_str(), m_login_message.length());
-				login_msg.data[login_msg.m_length] = '\0';
-
-				socket_.write_some(boost::asio::buffer(boost::asio::buffer(&login_msg, sizeof(PosMessage))));
-			}
-			catch (const std::exception& e)
-			{
-				//重新连接或者重新发送又失败了,可能是网络断了
-				std::string err = e.what();
-				LOG_INFO("write err info:" << err.c_str());
-
-				//关闭无效的连接
-				socket_.close();
-
-				//30秒后再重试
-				CSystem::my_sleep(30);
-
-				continue;
-			}
-		}
-
-		//走到这里,说明心跳包发送成功了,socket是连通的
-
-		//休眠30秒钟,之后再发心跳包
-		CSystem::my_sleep(30);
-	}
-
-	AddStopNum();
-}
-
-void CMessagePush::ReceiveMessage()
-{
-	while (m_is_work)
-	{
-		try
-		{
-			PosMessage new_msg;
-			
-			boost::asio::read(socket_, boost::asio::buffer(&new_msg, sizeof(PosMessage)));
-
-			std::string msg = new_msg.data;
-
-			//收到服务器的消息,对服务器的消息进行处理
-			rapidjson::Document document;
-			document.Parse(msg.c_str());
-			if (!document.IsObject())
-			{
-				LOG_INFO("message 非法!");
-				return;
-			}
-
-			std::string type;
-			if (document["msg_type"].IsInt())
-			{
-				type = to_string(document["msg_type"].GetInt());
-			}
-			else
-			{
-				type = document["msg_type"].GetString();
-			}
-
-			if (type == "1")
-			{
-				std::string order_id = document["waimai_order_id"].GetString();
-				std::string order_no = document["waimai_order_no"].GetString();
-
-				//新订单来了,首先判断是否要语音提醒
-				if (CSetting::GetParam("setting_is_new_waimai_voice") == "1")
-				{
-					if (CSetting::GetParam("setting_is_new_waimai_autoconfirm") == "1")
-					{
-						AddVoice(2);
-					}
-					else
-					{
-						AddVoice(1);
-					}
-				}
-
-				//判断是否要自动确认
-				if (CSetting::GetParam("setting_is_new_waimai_autoconfirm") == "1")
-				{
-					AddConfirm(order_id);
-				}
-
-				CPosPrinter printer;
-				printer.PrintWaimaiOrder(order_id, order_no);
-			}
-			else if (type == "2")
-			{
-				AddVoice(3);
-			}
-			else if (type == "3")
-			{
-				AddVoice(4);
-			}
-			else if (type == "0")
-			{
-				//这个表示被人挤下线了
-				PostMessage(m_hwnd, WM_LOGIN_AGAIN_OUT, 0, 0);
-			}
-
-			//处理完了,接着处理下一条
-			continue;
-		}
-		catch (std::exception& e)
-		{
-			std::string err = e.what();
-			//LOG_INFO("read err:" << err.c_str());
-
-			//如果这里异常了,说明socket失效了,等2秒重新读
-			CSystem::my_sleep(2);
-			continue;
-		}
-	}
-
-	AddStopNum();
-}
-
-/*
- *类型 1:新外卖订单 2:新外卖订单自动接单 3:外卖订单取消 4:外卖订单退款
- **/
-void CMessagePush::AddVoice(int voice_type)
-{
-    m_voice_mutex.lock();
-
-    m_voice_queue.push(voice_type);
-
-    m_voice_mutex.unlock();
-}
-
-void CMessagePush::AddConfirm(std::string order_id)
-{
-    m_confirm_mutex.lock();
-
-    m_confirm_queue.push(order_id);
-
-    m_confirm_mutex.unlock();
-}
-
-void CMessagePush::HandleVoice()
-{
-    while(m_is_work)
-    {
-        m_voice_mutex.lock();
-
-        if(m_voice_queue.empty())
-        {
-            m_voice_mutex.unlock();
-
-            CSystem::my_sleep(1);
-            continue;
-        }
-
-        int voice_type = m_voice_queue.front();
-        m_voice_queue.pop();
-
-        m_voice_mutex.unlock();
-
-		if (voice_type == 1)
-		{
-			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_new.wav";
-			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
-		}
-		else if (voice_type == 2)
-		{
-			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_new_auto.wav";
-			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
-		}
-		else if (voice_type == 3)
-		{
-			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_quxiao.wav";
-			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
-		}
-		else if (voice_type == 4)
-		{
-			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_tuikuan.wav";
-			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
-		}
-
-        //8秒内最多播放一次
-        CSystem::my_sleep(8);
-    }
-
-	AddStopNum();
-}
-
-void CMessagePush::HandleConfirm()
-{
-    while(m_is_work)
-    {
-        m_confirm_mutex.lock();
-
-        if(m_confirm_queue.empty())
-        {
-            m_confirm_mutex.unlock();
-
-            CSystem::my_sleep(1);
-            continue;
-        }
-
-        std::string order_id = m_confirm_queue.front();
-        m_confirm_queue.pop();
-
-        m_confirm_mutex.unlock();
-
-        CWaimaiOrder newOrder;
-        newOrder.ConfirmeOrder(order_id);
-    }
-
-	AddStopNum();
-}
-
-void CMessagePush::AddStopNum()
-{
-	m_nStopNumMutex.lock();
-
-	m_nStopNum++;
-
-	m_nStopNumMutex.unlock();
-
-	if (m_nStopNum == 8)
-	{
-		//确认所有子线程都退出了,再删除自己
-		delete this;
-	}
-}

+ 0 - 10
zhipuzi_pos_windows/network/PosMessage.h

@@ -1,10 +0,0 @@
-#pragma once
-
-class PosMessage
-{
-public:
-	enum { max_length = 1024 };
-	char data[max_length];
-
-	int m_length;
-};

+ 0 - 2
zhipuzi_pos_windows/page/CDianneiOrderInfoPageUI.cpp

@@ -5,8 +5,6 @@
 
 #include "../wnd/CMainWnd.h"
 
-#include "../network/CMessagePush.h"
-
 #include "../print/CPosPrinter.h"
 
 CDianneiOrderInfoPageUI::CDianneiOrderInfoPageUI()

+ 0 - 1
zhipuzi_pos_windows/page/CDianneiOrderListPageUI.cpp

@@ -5,7 +5,6 @@
 
 #include "../control/ControlEx.h"
 
-#include "../network/CMessagePush.h"
 #include "../wnd/CWaimaiOrderFailReasonWnd.h"
 
 #include "../print/CPosPrinter.h"

+ 0 - 2
zhipuzi_pos_windows/page/CWaimaiOrderInfoPageUI.cpp

@@ -5,8 +5,6 @@
 
 #include "../wnd/CWaimaiOrderFailReasonWnd.h"
 
-#include "../network/CMessagePush.h"
-
 #include "../print/CPosPrinter.h"
 
 CWaimaiOrderInfoPageUI::CWaimaiOrderInfoPageUI()

+ 0 - 1
zhipuzi_pos_windows/page/CWaimaiOrderListPageUI.cpp

@@ -5,7 +5,6 @@
 
 #include "../control/ControlEx.h"
 
-#include "../network/CMessagePush.h"
 #include "../wnd/CWaimaiOrderFailReasonWnd.h"
 
 #include "../print/CPosPrinter.h"

+ 7 - 17
zhipuzi_pos_windows/wnd/CMainWnd.cpp

@@ -6,14 +6,13 @@
 #include "../page/CWaimaiOrderInfoPageUI.h"
 #include "../page/CDianneiOrderInfoPageUI.h"
 
-#include "../network/CMessagePush.h"
 #include "../print/CPosPrinter.h"
 
 #include <urlmon.h>
 
 #include "../wnd/CToastWnd.h"
 
-#include "../tool/CChengzhongWorker.h"
+#include "../worker/CMessagePushWorker.h"
 
 void CMainWnd::Init()
 {
@@ -21,24 +20,23 @@ void CMainWnd::Init()
 	CLabelUI* pShopname = static_cast<CLabelUI*>(m_pm.FindControl(_T("main_shopname")));
 	pShopname->SetText(CLewaimaiString::UTF8ToUnicode(CShopinfo::m_shopinfo.m_shop_name).c_str());
 
+	//设置推送的消息窗口
+	CMessagePushWorker::GetInstance()->SetHWND(GetHWND());
+
+	//默认选择点单页面
 	m_curOptionName = L"main_diandan";
 	m_curOption = static_cast<CControlUI*>(m_pm.FindControl(_T("main_diandan")));
 
+	this->SwitchPage(DIANDAN);
+
     m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
     m_pMaxBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn")));
     m_pRestoreBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("restorebtn")));
     m_pMinBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn")));
 
-	//默认选择点单页面
-	this->SwitchPage(DIANDAN);
-
 	//开启键盘输入监听
 	RegKeyboardRawInput();
 
-    //登录成功,启动消息和任务处理
-    m_push = new CMessagePush(m_hWnd);
-    m_push->Start();
-
 	//启动一个线程,开始同步商品图片
 	std::thread(&CMainWnd::UpdateFoodImage, this).detach();
 }
@@ -579,9 +577,6 @@ LRESULT CMainWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle
  **/
 LRESULT CMainWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 {
-    //直接退出程序,或者退出登录都会执行这个
-    m_push->Stop();
-
     bHandled = FALSE;
     return 0;
 }
@@ -967,11 +962,6 @@ void CMainWnd::LoginOut(int mode)
     Close();
 }
 
-CMessagePush* CMainWnd::getMessagePush()
-{
-	return m_push;
-}
-
 void CMainWnd::SetInfopageWaimaiorderParam(std::string order_id, std::string order_no)
 {
 	m_infopage_waimaiorder_id = order_id;

+ 0 - 4
zhipuzi_pos_windows/wnd/CMainWnd.h

@@ -100,8 +100,6 @@ public:
 	//退出登陆
 	void LoginOut(int mode);
 
-	CMessagePush* getMessagePush();
-
 	void SetInfopageWaimaiorderParam(std::string order_id, std::string order_no);
 
 	void SetInfopageDianneiorderParam(std::string order_id);
@@ -124,8 +122,6 @@ private:
     //定义托盘图标对象
     NOTIFYICONDATA m_trayIcon;
 
-    CMessagePush* m_push = NULL;
-
 	//当前页面类型
 	MainPageName m_curPageName = NOPAGE;
 

+ 70 - 0
zhipuzi_pos_windows/worker/CCommonWorker.cpp

@@ -0,0 +1,70 @@
+#include "../pch/pch.h"
+#include "CCommonWorker.h"
+
+#include "../zhipuzi/CWaimaiOrder.h"
+
+void CCommonWorker::Start()
+{
+	m_is_work = true;
+
+	m_nStopNum = 0;
+
+	//´¦Àí¶©µ¥È·ÈÏ
+	std::thread(&CCommonWorker::HandleConfirm, this).detach();
+}
+
+void CCommonWorker::Stop()
+{
+	m_is_work = false;
+
+	m_confirm_mutex.lock();
+	while (!m_confirm_queue.empty())
+	{
+		m_confirm_queue.pop();
+	}
+	m_confirm_mutex.unlock();
+}
+
+void CCommonWorker::AddConfirm(std::string order_id)
+{
+	m_confirm_mutex.lock();
+
+	m_confirm_queue.push(order_id);
+
+	m_confirm_mutex.unlock();
+}
+
+void CCommonWorker::HandleConfirm()
+{
+	while (m_is_work)
+	{
+		m_confirm_mutex.lock();
+
+		if (m_confirm_queue.empty())
+		{
+			m_confirm_mutex.unlock();
+
+			CSystem::my_sleep(1);
+			continue;
+		}
+
+		std::string order_id = m_confirm_queue.front();
+		m_confirm_queue.pop();
+
+		m_confirm_mutex.unlock();
+
+		CWaimaiOrder newOrder;
+		newOrder.ConfirmeOrder(order_id);
+	}
+
+	AddStopNum();
+}
+
+void CCommonWorker::AddStopNum()
+{
+	m_nStopNumMutex.lock();
+
+	m_nStopNum++;
+
+	m_nStopNumMutex.unlock();
+}

+ 44 - 0
zhipuzi_pos_windows/worker/CCommonWorker.h

@@ -0,0 +1,44 @@
+#pragma once
+
+#include "../pch/pch.h"
+
+//这个类专门用于接收服务器端的消息推送
+class CCommonWorker
+{
+public:
+	static CCommonWorker* GetInstance()
+	{
+		static CCommonWorker instance;
+
+		return &instance;
+	}
+
+	//开始工作
+	void Start();
+
+	//停止工作
+	void Stop();
+
+	//队列处理
+	void HandleConfirm();
+
+	void AddConfirm(std::string order_id);
+
+private:
+	CCommonWorker()
+	{
+
+	}
+
+	void AddStopNum();
+
+private:
+	bool m_is_work;
+
+	int m_nStopNum = 0;
+	std::mutex m_nStopNumMutex;
+
+	std::queue<std::string> m_confirm_queue;
+
+	std::mutex m_confirm_mutex;
+};

+ 235 - 0
zhipuzi_pos_windows/worker/CMessagePushWorker.cpp

@@ -0,0 +1,235 @@
+#include "../pch/pch.h"
+#include "CMessagePushWorker.h"
+
+#include "mmsystem.h"
+
+#include "../worker/CVoiceWorker.h"
+#include "../worker/CCommonWorker.h"
+
+#include "../print/CPosPrinter.h"
+
+void CMessagePushWorker::Start()
+{
+	m_is_work = true;
+
+	m_nStopNum = 0;
+
+    //心跳包
+	std::thread(&CMessagePushWorker::KeepAlive, this).detach();
+
+	//接收消息
+	std::thread(&CMessagePushWorker::ReceiveMessage, this).detach();
+}
+
+void CMessagePushWorker::Stop()
+{
+	m_is_work = false;
+
+	socket_.close();
+}
+
+void CMessagePushWorker::KeepAlive()
+{
+	while (m_is_work)
+	{
+		//生成心跳包
+		rapidjson::Document doc;
+		doc.SetObject();
+		rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); //获取分配器
+
+		std::string username = CSetting::getUsername();
+		std::string timestamp = to_string(time(NULL));
+		doc.AddMember("username", StringRef(username.c_str(), username.length()), allocator);
+		doc.AddMember("timestamp", StringRef(timestamp.c_str(), timestamp.length()), allocator);
+		doc.AddMember("is_login", "0", allocator);
+
+		rapidjson::StringBuffer buffer;
+		rapidjson::Writer<StringBuffer> writer(buffer);
+		doc.Accept(writer);
+
+		//返回给接入层的消息
+		std::string m_keepalive_msg = buffer.GetString();
+
+		PosMessage new_msg;
+		new_msg.m_length = m_keepalive_msg.length();
+		memcpy(new_msg.data, m_keepalive_msg.c_str(), m_keepalive_msg.length());
+		new_msg.data[new_msg.m_length] = '\0';
+
+		try
+		{
+			socket_.write_some(boost::asio::buffer(&new_msg, sizeof(PosMessage)));
+		}
+		catch (const std::exception& e)
+		{
+			//走到这里来说明心跳包发送失败了,socket失效了
+			std::string err = e.what();
+
+			//先把socket关闭掉
+			socket_.close();
+
+			try
+			{
+				//发送失败,重新建立连接
+				char host[] = "pushserver.lewaimai.com";
+				char port[] = "9001";
+
+				tcp::resolver resolver(m_io_context);
+				tcp::resolver::results_type endpoints =
+					resolver.resolve(tcp::v4(), host, port);
+
+				boost::asio::connect(socket_, endpoints);
+
+				//刚刚连接上,这是第一次登陆,发送登陆信息
+				rapidjson::Document doc_1;
+				doc_1.SetObject();
+				rapidjson::Document::AllocatorType& allocator_1 = doc_1.GetAllocator(); //获取分配器
+
+				std::string username_1 = CSetting::getUsername();
+				std::string timestamp_1 = to_string(time(NULL));
+				doc_1.AddMember("username", StringRef(username_1.c_str(), username_1.length()), allocator_1);
+				doc_1.AddMember("timestamp", StringRef(timestamp_1.c_str(), timestamp_1.length()), allocator_1);
+				doc_1.AddMember("is_login", "1", allocator_1);
+
+				rapidjson::StringBuffer buffer_1;
+				rapidjson::Writer<StringBuffer> writer_1(buffer_1);
+				doc_1.Accept(writer_1);
+
+				//返回给接入层的消息
+				std::string m_login_message = buffer_1.GetString();
+
+				PosMessage login_msg;
+				login_msg.m_length = m_login_message.length();
+				memcpy(login_msg.data, m_login_message.c_str(), m_login_message.length());
+				login_msg.data[login_msg.m_length] = '\0';
+
+				socket_.write_some(boost::asio::buffer(boost::asio::buffer(&login_msg, sizeof(PosMessage))));
+			}
+			catch (const std::exception& e)
+			{
+				//重新连接或者重新发送又失败了,可能是网络断了
+				std::string err = e.what();
+				LOG_INFO("write err info:" << err.c_str());
+
+				//关闭无效的连接
+				socket_.close();
+
+				//30秒后再重试
+				CSystem::my_sleep(30);
+
+				continue;
+			}
+		}
+
+		//走到这里,说明心跳包发送成功了,socket是连通的
+
+		//休眠30秒钟,之后再发心跳包
+		CSystem::my_sleep(30);
+	}
+
+	AddStopNum();
+}
+
+void CMessagePushWorker::ReceiveMessage()
+{
+	while (m_is_work)
+	{
+		try
+		{
+			PosMessage new_msg;
+			
+			boost::asio::read(socket_, boost::asio::buffer(&new_msg, sizeof(PosMessage)));
+
+			std::string msg = new_msg.data;
+
+			HandelMessage(msg);
+		}
+		catch (std::exception& e)
+		{
+			std::string err = e.what();
+			//LOG_INFO("read err:" << err.c_str());
+
+			//如果这里异常了,说明socket失效了,等2秒重新读
+			CSystem::my_sleep(2);
+			continue;
+		}
+	}
+
+	AddStopNum();
+}
+
+void CMessagePushWorker::AddStopNum()
+{
+	m_nStopNumMutex.lock();
+
+	m_nStopNum++;
+
+	m_nStopNumMutex.unlock();
+}
+
+void CMessagePushWorker::SetHWND(HWND hwnd)
+{
+	m_hwnd = hwnd;
+}
+
+void CMessagePushWorker::HandelMessage(std::string msg)
+{
+	//收到服务器的消息,对服务器的消息进行处理
+	rapidjson::Document document;
+	document.Parse(msg.c_str());
+	if (!document.IsObject())
+	{
+		LOG_INFO("message 非法!");
+		return;
+	}
+
+	int type;
+	if (document["msg_type"].IsInt())
+	{
+		type = document["msg_type"].GetInt();
+	}
+	else
+	{
+		type = atoi(document["msg_type"].GetString());
+	}
+
+	if (type == MESSAGE_TYPE::NEW_WAIMAI_ORDER)
+	{
+		std::string order_id = document["waimai_order_id"].GetString();
+		std::string order_no = document["waimai_order_no"].GetString();
+
+		//新订单来了,首先判断是否要语音提醒
+		if (CSetting::GetParam("setting_is_new_waimai_voice") == "1")
+		{
+			if (CSetting::GetParam("setting_is_new_waimai_autoconfirm") == "1")
+			{
+				CVoiceWorker::GetInstance()->AddVoice(2);
+			}
+			else
+			{
+				CVoiceWorker::GetInstance()->AddVoice(1);
+			}
+		}
+
+		//判断是否要自动确认
+		if (CSetting::GetParam("setting_is_new_waimai_autoconfirm") == "1")
+		{
+			CCommonWorker::GetInstance()->AddConfirm(order_id);
+		}
+
+		CPosPrinter printer;
+		printer.PrintWaimaiOrder(order_id, order_no);
+	}
+	else if (type == MESSAGE_TYPE::QUXIAO_WAIMAI_ORDER)
+	{
+		CVoiceWorker::GetInstance()->AddVoice(3);
+	}
+	else if (type == MESSAGE_TYPE::REFUND_WAIMAI_ORDER)
+	{
+		CVoiceWorker::GetInstance()->AddVoice(4);
+	}
+	else if (type == MESSAGE_TYPE::LOGIN_OFFLINE)
+	{
+		//这个表示被人挤下线了
+		PostMessage(m_hwnd, WM_LOGIN_AGAIN_OUT, 0, 0);
+	}
+}

+ 32 - 18
zhipuzi_pos_windows/network/CMessagePush.h

@@ -4,17 +4,34 @@
 
 using boost::asio::ip::tcp;
 
+//跟服务器消息交互的格式,每次读写都是按这个报文来
+class PosMessage
+{
+public:
+	enum { max_length = 1024 };
+	char data[max_length];
+
+	int m_length;
+};
+
+enum MESSAGE_TYPE
+{
+	LOGIN_OFFLINE = 0,
+	NEW_WAIMAI_ORDER = 1,
+	QUXIAO_WAIMAI_ORDER = 2,
+	REFUND_WAIMAI_ORDER = 3,
+};
+
 //这个类专门用于接收服务器端的消息推送
-class CMessagePush
+class CMessagePushWorker
 {
 public:
-	CMessagePush(HWND hwnd)
-		: socket_(m_io_context)
+	static CMessagePushWorker* GetInstance()
 	{
-		m_hwnd = hwnd;
-	}
+		static CMessagePushWorker instance;
 
-	~CMessagePush();
+		return &instance;
+	}
 
 	//开始工作
 	void Start();
@@ -28,16 +45,19 @@ public:
 	//专门处理推送消息
 	void ReceiveMessage();
 
-	//队列处理
-	void HandleVoice();
-	void HandleConfirm();
-
-	void AddVoice(int voice_type);
-	void AddConfirm(std::string order_id);
+	void SetHWND(HWND hwnd);
 
 private:
+	CMessagePushWorker()
+		: socket_(m_io_context)
+	{
+
+	}
+
 	void AddStopNum();
 
+	void HandelMessage(std::string msg);
+
 private:
 	bool m_is_work;
 
@@ -50,11 +70,5 @@ private:
 	enum { max_length = 1024 };
 	char data_[max_length];
 
-	std::queue<int> m_voice_queue;
-	std::queue<std::string> m_confirm_queue;
-
-	std::mutex m_voice_mutex;
-	std::mutex m_confirm_mutex;
-
 	HWND m_hwnd;
 };

+ 94 - 0
zhipuzi_pos_windows/worker/CVoiceWorker.cpp

@@ -0,0 +1,94 @@
+#include "../pch/pch.h"
+#include "CVoiceWorker.h"
+
+#include "mmsystem.h"
+
+void CVoiceWorker::Start()
+{
+	m_is_work = true;
+
+	m_nStopNum = 0;
+
+	//处理声音提醒
+	std::thread(&CVoiceWorker::HandleVoice, this).detach();
+}
+
+void CVoiceWorker::Stop()
+{
+	m_is_work = false;
+
+	m_voice_mutex.lock();
+	while (!m_voice_queue.empty())
+	{
+		m_voice_queue.pop();
+	}
+	m_voice_mutex.unlock();
+}
+
+/*
+ *类型 1:新外卖订单 2:新外卖订单自动接单 3:外卖订单取消 4:外卖订单退款
+ **/
+void CVoiceWorker::AddVoice(int voice_type)
+{
+	m_voice_mutex.lock();
+
+	m_voice_queue.push(voice_type);
+
+	m_voice_mutex.unlock();
+}
+
+void CVoiceWorker::HandleVoice()
+{
+	while (m_is_work)
+	{
+		m_voice_mutex.lock();
+
+		if (m_voice_queue.empty())
+		{
+			m_voice_mutex.unlock();
+
+			CSystem::my_sleep(1);
+			continue;
+		}
+
+		int voice_type = m_voice_queue.front();
+		m_voice_queue.pop();
+
+		m_voice_mutex.unlock();
+
+		if (voice_type == 1)
+		{
+			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_new.wav";
+			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
+		}
+		else if (voice_type == 2)
+		{
+			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_new_auto.wav";
+			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
+		}
+		else if (voice_type == 3)
+		{
+			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_quxiao.wav";
+			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
+		}
+		else if (voice_type == 4)
+		{
+			wstring path = CSystem::GetProgramDir() + L"\\music\\waimai_tuikuan.wav";
+			PlaySound(path.c_str(), NULL, SND_FILENAME | SND_ASYNC);
+		}
+
+		//8秒内最多播放一次
+		CSystem::my_sleep(8);
+	}
+
+	AddStopNum();
+}
+
+void CVoiceWorker::AddStopNum()
+{
+	m_nStopNumMutex.lock();
+
+	m_nStopNum++;
+
+	m_nStopNumMutex.unlock();
+}

+ 46 - 0
zhipuzi_pos_windows/worker/CVoiceWorker.h

@@ -0,0 +1,46 @@
+#pragma once
+
+#include "../pch/pch.h"
+
+using boost::asio::ip::tcp;
+
+//这个类专门用于处理声音的播报
+class CVoiceWorker
+{
+public:
+	static CVoiceWorker* GetInstance()
+	{
+		static CVoiceWorker instance;
+
+		return &instance;
+	}
+
+	//开始工作
+	void Start();
+
+	//停止工作
+	void Stop();
+
+	//队列处理
+	void HandleVoice();
+
+	void AddVoice(int voice_type);
+
+private:
+	CVoiceWorker()
+	{
+
+	}
+
+	void AddStopNum();
+
+private:
+	bool m_is_work;
+
+	int m_nStopNum = 0;
+	std::mutex m_nStopNumMutex;
+
+	std::queue<int> m_voice_queue;
+
+	std::mutex m_voice_mutex;
+};

+ 12 - 15
zhipuzi_pos_windows/zhipuzi_pos_windows.cpp

@@ -4,23 +4,24 @@
 
 #include <curl/curl.h>
 
-#include "print/CPosPrinterQueue.h"
-#include "tool/CChengzhongWorker.h"
+#include "CAppEnv.h"
+
+
 
 int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                       _In_opt_ HINSTANCE hPrevInstance,
                       _In_ LPWSTR    lpCmdLine,
                       _In_ int       nCmdShow)
 {
-    //初始化日志
-    CLewaimaiLog log;
-    log.Init();
+	//如果进程已经在运行了,直接返回,也就是不支持进程多开
+	if (CSystem::IsAppRunning())
+	{
+		return -1;
+	}
 
-	//启动打印队列
-	CPosPrinterQueue::GetInstance()->StartWork();
-
-	//启动称重任务
-	CChengzhongWorker::GetInstance()->StartWork();
+	//初始化所有配置,启动所有异步worker
+	CAppEnv app;
+	app.Start();	
 
     //开始展示窗口
     CPaintManagerUI::SetInstance(hInstance);
@@ -52,11 +53,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
 
     CPaintManagerUI::MessageLoop();
 
-	//停止打印任务
-	CPosPrinterQueue::GetInstance()->StopWork();
-
-	//停止称重任务
-	CChengzhongWorker::GetInstance()->StopWork();
+	app.Stop();
 
     ::CoUninitialize();
 

+ 8 - 3
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj

@@ -227,6 +227,9 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     </PostBuildEvent>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClInclude Include="CAppEnv.h" />
+    <ClInclude Include="worker\CCommonWorker.h" />
+    <ClInclude Include="worker\CVoiceWorker.h" />
     <ClInclude Include="page\CJiaobanPageUI.h" />
     <ClInclude Include="page\CBaobiaoPageUI.h" />
     <ClInclude Include="wnd\CHuiyuanAddWnd.h" />
@@ -278,13 +281,12 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="wnd\CMessageboxWnd.h" />
     <ClInclude Include="wnd\CUpdateWnd.h" />
     <ClInclude Include="wnd\CWaimaiOrderFailReasonWnd.h" />
-    <ClInclude Include="network\PosMessage.h" />
     <ClInclude Include="wnd\CChufangSettingWnd.h" />
     <ClInclude Include="page\CWaimaiOrderInfoPageUI.h" />
     <ClInclude Include="page\CSettingPageUI.h" />
     <ClInclude Include="tool\CSetting.h" />
     <ClInclude Include="tool\CSqlite3.h" />
-    <ClInclude Include="network\CMessagePush.h" />
+    <ClInclude Include="worker\CMessagePushWorker.h" />
     <ClInclude Include="zhipuzi\CDiandanOrder.h" />
     <ClInclude Include="zhipuzi\CFood.h" />
     <ClInclude Include="zhipuzi\CFoodpackage.h" />
@@ -308,6 +310,9 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClInclude Include="helper\CSystem.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="CAppEnv.cpp" />
+    <ClCompile Include="worker\CCommonWorker.cpp" />
+    <ClCompile Include="worker\CVoiceWorker.cpp" />
     <ClCompile Include="page\CJiaobanPageUI.cpp" />
     <ClCompile Include="page\CBaobiaoPageUI.cpp" />
     <ClCompile Include="wnd\CHuiyuanAddWnd.cpp" />
@@ -361,7 +366,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClCompile Include="page\CSettingPageUI.cpp" />
     <ClCompile Include="tool\CSetting.cpp" />
     <ClCompile Include="tool\CSqlite3.cpp" />
-    <ClCompile Include="network\CMessagePush.cpp" />
+    <ClCompile Include="worker\CMessagePushWorker.cpp" />
     <ClCompile Include="zhipuzi\CDiandanOrder.cpp" />
     <ClCompile Include="zhipuzi\CWaimaiOrder.cpp" />
     <ClCompile Include="print\CPosPrinterData.cpp" />

+ 24 - 9
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj.filters

@@ -75,18 +75,12 @@
     <ClInclude Include="network\CHttpClient.h">
       <Filter>头文件</Filter>
     </ClInclude>
-    <ClInclude Include="network\CMessagePush.h">
-      <Filter>头文件</Filter>
-    </ClInclude>
     <ClInclude Include="network\CZhipuziHttpClient.h">
       <Filter>头文件</Filter>
     </ClInclude>
     <ClInclude Include="network\CZhipuziHttpProxy.h">
       <Filter>头文件</Filter>
     </ClInclude>
-    <ClInclude Include="network\PosMessage.h">
-      <Filter>头文件</Filter>
-    </ClInclude>
     <ClInclude Include="helper\CLewaimaiJson.h">
       <Filter>头文件</Filter>
     </ClInclude>
@@ -252,6 +246,18 @@
     <ClInclude Include="zhipuzi\CJiaobanOrder.h">
       <Filter>头文件</Filter>
     </ClInclude>
+    <ClInclude Include="CAppEnv.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="worker\CVoiceWorker.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="worker\CCommonWorker.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="worker\CMessagePushWorker.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="pch\pch.cpp">
@@ -308,9 +314,6 @@
     <ClCompile Include="network\CHttpClient.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
-    <ClCompile Include="network\CMessagePush.cpp">
-      <Filter>源文件</Filter>
-    </ClCompile>
     <ClCompile Include="network\CZhipuziHttpClient.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
@@ -464,6 +467,18 @@
     <ClCompile Include="page\CJiaobanPageUI.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
+    <ClCompile Include="CAppEnv.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="worker\CVoiceWorker.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="worker\CCommonWorker.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="worker\CMessagePushWorker.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <Image Include="resource\zhipuzi.ico">