소스 검색

MQTT改造

zhangyang 1 년 전
부모
커밋
4571cc37aa

+ 0 - 3
lewaimai_pos_windows/lewaimai_pos_windows.vcxproj

@@ -236,13 +236,11 @@ 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="control\CWaimaiOrderInfoUI.h" />
     <ClInclude Include="control\CSettingUI.h" />
     <ClInclude Include="tool\CSetting.h" />
     <ClInclude Include="tool\CSqlite3.h" />
-    <ClInclude Include="network\CMessagePush.h" />
     <ClInclude Include="order\CWaimaiOrder.h" />
     <ClInclude Include="tool\CPosPrinter.h" />
     <ClInclude Include="control\CWaimaiOrderItemUI.h" />
@@ -275,7 +273,6 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
     <ClCompile Include="control\CSettingUI.cpp" />
     <ClCompile Include="tool\CSetting.cpp" />
     <ClCompile Include="tool\CSqlite3.cpp" />
-    <ClCompile Include="network\CMessagePush.cpp" />
     <ClCompile Include="order\CWaimaiOrder.cpp" />
     <ClCompile Include="tool\CPosPrinter.cpp" />
     <ClCompile Include="control\CWaimaiOrderItemUI.cpp" />

+ 0 - 9
lewaimai_pos_windows/lewaimai_pos_windows.vcxproj.filters

@@ -54,9 +54,6 @@
     <ClInclude Include="order\CWaimaiOrder.h">
       <Filter>头文件</Filter>
     </ClInclude>
-    <ClInclude Include="network\CMessagePush.h">
-      <Filter>头文件</Filter>
-    </ClInclude>
     <ClInclude Include="wnd\CMainWnd.h">
       <Filter>头文件</Filter>
     </ClInclude>
@@ -84,9 +81,6 @@
     <ClInclude Include="wnd\CChufangSettingWnd.h">
       <Filter>头文件</Filter>
     </ClInclude>
-    <ClInclude Include="network\PosMessage.h">
-      <Filter>头文件</Filter>
-    </ClInclude>
     <ClInclude Include="wnd\CWaimaiOrderFailReasonWnd.h">
       <Filter>头文件</Filter>
     </ClInclude>
@@ -146,9 +140,6 @@
     <ClCompile Include="order\CWaimaiOrder.cpp">
       <Filter>源文件</Filter>
     </ClCompile>
-    <ClCompile Include="network\CMessagePush.cpp">
-      <Filter>源文件</Filter>
-    </ClCompile>
     <ClCompile Include="lewaimai_pos_windows.cpp">
       <Filter>源文件</Filter>
     </ClCompile>

+ 0 - 635
lewaimai_pos_windows/network/CMessagePush.cpp

@@ -1,635 +0,0 @@
-#include "../pch/pch.h"
-#include "CMessagePush.h"
-
-#include "../tool/CPosPrinter.h"
-#include "../order/CWaimaiOrder.h"
-
-#include "mmsystem.h"
-
-#include "PosMessage.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();
-
-	//处理打印
-	std::thread(&CMessagePush::HandlePrinter, this).detach();
-
-    //处理收银打印
-    std::thread(&CMessagePush::HandleShouyinPrinter, this).detach();
-
-	//处理标签打印
-	std::thread(&CMessagePush::HandleBiaoqianPrinter, this).detach();
-
-    //处理厨房打印
-    std::thread(&CMessagePush::HandleChufangPrinter, 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();
-
-	m_printer_mutex.lock();
-	while (!m_printer_queue.empty())
-	{
-		m_printer_queue.pop();
-	}
-	m_printer_mutex.unlock();
-
-	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 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);
-				}
-
-				//判断是否右下角弹框提醒
-				if (CSetting::GetParam("setting_is_new_waimai_dialog") == "1")
-				{
-
-				}
-
-				AddPinter(order_id, order_no, 1);
-			}
-			else if (type == "2")
-			{
-				AddVoice(3);
-			}
-			else if (type == "3")
-			{
-				AddVoice(4);
-
-				std::string order_id = document["waimai_order_id"].GetString();
-				std::string order_no = document["waimai_order_no"].GetString();
-
-				AddPinter(order_id, order_no, 1, 3);
-			}
-			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::AddPinter(std::string order_id, std::string order_no, int print_type, int order_type)
-{
-    m_printer_mutex.lock();
-
-    WaimaiPinterInfo newPrinter;
-    newPrinter.order_id = order_id;
-    newPrinter.order_no = order_no;
-	newPrinter.print_type = print_type;
-	newPrinter.order_type = order_type;
-
-    m_printer_queue.push(newPrinter);
-
-    m_printer_mutex.unlock();
-}
-
-void CMessagePush::AddShouyinPrinter(CWaimaiOrder order)
-{
-    m_shouyin_printer_mutex.lock();
-
-    m_shouyin_printer_queue.push(order);
-
-    m_shouyin_printer_mutex.unlock();
-}
-
-void CMessagePush::AddBiaoqianPrinter(CWaimaiOrder order)
-{
-	m_biaoqian_printer_mutex.lock();
-
-	m_biaoqian_printer_queue.push(order);
-
-	m_biaoqian_printer_mutex.unlock();
-}
-
-void CMessagePush::AddChufangPrinter(CWaimaiOrder order)
-{
-    m_chufang_printer_mutex.lock();
-
-    m_chufang_printer_queue.push(order);
-
-    m_chufang_printer_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::HandlePrinter()
-{
-    while(m_is_work)
-    {
-        m_printer_mutex.lock();
-
-        if(m_printer_queue.empty())
-        {
-            m_printer_mutex.unlock();
-
-            CSystem::my_sleep(1);
-            continue;
-        }
-
-        WaimaiPinterInfo printerInfo = m_printer_queue.front();
-        std::string order_id = printerInfo.order_id;
-        std::string order_no = printerInfo.order_no;
-		int print_type = printerInfo.print_type;
-		int order_type = printerInfo.order_type;
-
-        m_printer_queue.pop();
-
-        m_printer_mutex.unlock();
-
-		if (order_type == 1)
-		{
-			CWaimaiOrder order;
-			if (print_type == 1)
-			{
-				if (CSetting::GetParam("setting_is_new_waimai_printer") == "1" || CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1" || CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
-				{
-					bool ret = order.InitData(order_id, order_no);
-
-					if (ret == false)
-					{
-						this->AddPinter(order_id, order_no, print_type);
-						continue;
-					}
-				}
-
-				//判断是否自动打印收银小票
-				if (CSetting::GetParam("setting_is_new_waimai_printer") == "1")
-				{
-					AddShouyinPrinter(order);
-				}
-
-				//判断是否自动打印标签小票
-				if (CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1")
-				{
-					AddBiaoqianPrinter(order);
-				}
-
-				//判断是否进行自动的厨房打印
-				if (CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
-				{
-					AddChufangPrinter(order);
-				}
-			}
-			else
-			{
-				bool ret = order.InitData(order_id, order_no);
-
-				if (ret == false)
-				{
-					this->AddPinter(order_id, order_no, print_type);
-					continue;
-				}
-
-				//手动打印的模式下,收银小票一定打印,标签如果没开就不打印
-				AddShouyinPrinter(order);
-
-				//手动打印的模式下,厨房小票一定打印
-				AddChufangPrinter(order);
-
-				//判断是否进行自动的厨房打印
-				/*
-				if (CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
-				{
-					AddChufangPrinter(order);
-				}
-				}*/
-
-				//判断是否自动打印标签小票
-				if (CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1")
-				{
-					AddBiaoqianPrinter(order);
-				}
-			}
-		}
-		else if (order_type == 3)
-		{
-			//顾客申请退款的
-			CWaimaiOrder order;
-			bool ret = order.InitData(order_id, order_no);
-
-			if (ret == false)
-			{
-				this->AddPinter(order_id, order_no, print_type, order_type);
-				continue;
-			}
-
-			CPosPrinter printer;
-			printer.PrintWaimaiOrderTuikuan(order);
-		}
-    }
-
-	AddStopNum();
-}
-
-void CMessagePush::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;
-        }
-
-        CWaimaiOrder order = m_shouyin_printer_queue.front();
-
-        m_shouyin_printer_queue.pop();
-
-        m_shouyin_printer_mutex.unlock();
-
-        CPosPrinter printer;
-        printer.PrintWaimaiOrderShouyin(order);
-    }
-
-	AddStopNum();
-}
-
-void CMessagePush::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;
-		}
-
-		CWaimaiOrder order = m_biaoqian_printer_queue.front();
-
-		m_biaoqian_printer_queue.pop();
-
-		m_biaoqian_printer_mutex.unlock();
-
-		CPosPrinter printer;
-		printer.PrintWaimaiOrderBiaoqian(order);
-	}
-
-	AddStopNum();
-}
-
-void CMessagePush::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;
-        }
-
-        CWaimaiOrder order = m_chufang_printer_queue.front();
-
-        m_chufang_printer_queue.pop();
-
-        m_chufang_printer_mutex.unlock();
-
-        CPosPrinter printer;
-        printer.PrintWaimaiOrderChufang(order);
-    }
-
-	AddStopNum();
-}
-
-void CMessagePush::AddStopNum()
-{
-	m_nStopNumMutex.lock();
-
-	m_nStopNum++;
-
-	m_nStopNumMutex.unlock();
-
-	if (m_nStopNum == 8)
-	{
-		//确认所有子线程都退出了,再删除自己
-		delete this;
-	}
-}

+ 0 - 97
lewaimai_pos_windows/network/CMessagePush.h

@@ -1,97 +0,0 @@
-#pragma once
-
-#include "../pch/pch.h"
-#include "../order/CWaimaiOrder.h"
-
-using boost::asio::ip::tcp;
-
-class CClientMessage
-{
-public:
-	int m_type; //消息类型 0:新的外卖订单
-
-	std::string m_username;
-	std::string m_order_id;
-	std::string m_order_no;
-};
-
-class WaimaiPinterInfo
-{
-public:
-	std::string order_id;
-	std::string order_no;
-	int print_type; //打印类型 1:新订单自动打印 2:手动打印
-	int order_type = 1; // 订单类型:1 新订单 2 顾客取消订单 3顾客主动退款
-};
-
-class CMessagePush
-{
-public:
-	CMessagePush(HWND hwnd)
-		: socket_(m_io_context)
-	{
-		m_hwnd = hwnd;
-	}
-
-	~CMessagePush();
-
-	//开始工作
-	void Start();
-
-	//停止工作
-	void Stop();
-
-	//发送心跳包
-	void KeepAlive();
-
-	//专门处理推送消息
-	void ReceiveMessage();
-
-	//队列处理
-	void HandleVoice();
-	void HandleConfirm();
-	void HandlePrinter();
-	void HandleShouyinPrinter();
-	void HandleBiaoqianPrinter();
-	void HandleChufangPrinter();
-
-
-	void AddVoice(int voice_type);
-	void AddConfirm(std::string order_id);
-	void AddPinter(std::string order_id, std::string order_no, int print_type, int order_type = 1);
-	void AddShouyinPrinter(CWaimaiOrder order);
-	void AddBiaoqianPrinter(CWaimaiOrder order);
-	void AddChufangPrinter(CWaimaiOrder order);
-
-private:
-	void AddStopNum();
-
-private:
-	bool m_is_work;
-
-	int m_nStopNum = 0;
-	std::mutex m_nStopNumMutex;
-
-	boost::asio::io_context m_io_context;
-	tcp::socket socket_;
-
-	enum { max_length = 1024 };
-	char data_[max_length];
-
-	std::queue<int> m_voice_queue;
-	std::queue<std::string> m_confirm_queue;
-	std::queue<WaimaiPinterInfo> m_printer_queue;
-	std::queue<CWaimaiOrder> m_shouyin_printer_queue;
-	std::queue<CWaimaiOrder> m_biaoqian_printer_queue;
-	std::queue<CWaimaiOrder> m_chufang_printer_queue;
-
-	std::mutex m_voice_mutex;
-	std::mutex m_confirm_mutex;
-	std::mutex m_printer_mutex;
-	std::mutex m_shouyin_printer_mutex;
-	std::mutex m_biaoqian_printer_mutex;
-	std::mutex m_chufang_printer_mutex;
-
-	HWND m_hwnd;
-};
-

+ 700 - 73
lewaimai_pos_windows/network/CMqttClient.cpp

@@ -1,109 +1,736 @@
+#include "../pch/pch.h"
 #include "CMqttClient.h"
 
 #include <openssl/hmac.h>
 #include <openssl/bio.h>
 
+#include "../tool/CPosPrinter.h"
+#include "../order/CWaimaiOrder.h"
 
-CMqttClient::CMqttClient()
+#include "mmsystem.h"
+
+CMqttClient::CMqttClient(HWND hwnd)
 {
-}
+    m_hwnd = hwnd;
 
+    m_async_client = new mqtt::async_client(SERVER_ADDRESS, CLIENT_ID);
+}
 
 CMqttClient::~CMqttClient()
 {
+    delete m_async_client;
 }
 
 void CMqttClient::Start()
 {
-	std::thread(&CMqttClient::Run, this).detach();
+    m_nStopNum = 0;
+
+    //处理Mqtt消息接收
+    std::thread(&CMqttClient::Run, this).detach();
+
+    //处理声音提醒
+    std::thread(&CMqttClient::HandleVoice, this).detach();
+
+    //处理订单确认
+    std::thread(&CMqttClient::HandleConfirm, this).detach();
+
+    //处理打印
+    std::thread(&CMqttClient::HandlePrinter, this).detach();
+
+    //处理收银打印
+    std::thread(&CMqttClient::HandleShouyinPrinter, this).detach();
+
+    //处理标签打印
+    std::thread(&CMqttClient::HandleBiaoqianPrinter, this).detach();
+
+    //处理厨房打印
+    std::thread(&CMqttClient::HandleChufangPrinter, this).detach();
+}
+
+void CMqttClient::Stop()
+{
+    m_is_running = false;
+
+    m_voice_mutex.lock();
+    while(!m_voice_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_voice_mutex.unlock();
+
+    m_confirm_mutex.lock();
+    while(!m_confirm_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_confirm_mutex.unlock();
+
+    m_printer_mutex.lock();
+    while(!m_printer_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_printer_mutex.unlock();
+
+    m_shouyin_printer_mutex.lock();
+    while(!m_shouyin_printer_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_shouyin_printer_mutex.unlock();
+
+    m_biaoqian_printer_mutex.lock();
+    while(!m_biaoqian_printer_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_biaoqian_printer_mutex.unlock();
+
+    m_chufang_printer_mutex.lock();
+    while(!m_chufang_printer_queue.empty())
+    {
+        CSystem::my_sleep(1);
+    }
+    m_chufang_printer_mutex.unlock();
 }
 
 void CMqttClient::Run()
 {
-	// A subscriber often wants the server to remember its messages when its
-	// disconnected. In that case, it needs a unique ClientID and a
-	// non-clean session.
+    // A subscriber often wants the server to remember its messages when its
+    // disconnected. In that case, it needs a unique ClientID and a
+    // non-clean session.
+    m_connOpts.set_clean_session(false);
+
+    //计算用户名和密码
+    this->CalUserInfo();
+
+    m_connOpts.set_user_name(m_UserName.c_str());
+    m_connOpts.set_password(m_Password.c_str());
 
-	mqtt::async_client cli(SERVER_ADDRESS, CLIENT_ID);
+    // Install the callback(s) before connecting.
+    m_async_client->set_callback(*this);
 
-	mqtt::connect_options connOpts;
-	connOpts.set_clean_session(false);
+    // Start the connection.
+    // When completed, the callback will subscribe to topic.
 
-	this->CalUserInfo();
+    try
+    {
+        LOG_INFO("Connecting to the MQTT server...");
+        m_async_client->connect(m_connOpts, nullptr, *this);
+    }
+    catch(const mqtt::exception& exc)
+    {
+        std::string info = "ERROR: Unable to connect to MQTT server:" + SERVER_ADDRESS + exc.get_message();
 
-	connOpts.set_user_name(m_UserName.c_str());
-	connOpts.set_password(m_Password.c_str());
+        LOG_INFO(info.c_str());
+        return;
+    }
 
-	// Install the callback(s) before connecting.
-	callback cb(cli, connOpts);
-	cli.set_callback(cb);
+    m_is_running = true;
+    while(m_is_running)
+    {
+		//一直循环,一直工作,等待接收消息
+    }
 
-	// Start the connection.
-	// When completed, the callback will subscribe to topic.
+	//代码走到这里,说明退出登录了,要暂停推送了
+    try
+    {
+        LOG_INFO("Disconnecting from the MQTT server...");
+        m_async_client->disconnect()->wait();
+        LOG_INFO("OK...");
+    }
+    catch(const mqtt::exception& exc)
+    {
+        LOG_INFO(("disconnect error, exc:" + exc.get_message()).c_str());
+        return;
+    }
+
+    AddStopNum();
+
+    return;
+}
 
-	try {
-		std::cout << "Connecting to the MQTT server..." << std::flush;
-		cli.connect(connOpts, nullptr, cb);
+void CMqttClient::reconnect()
+{
+	//暂停10秒后重连
+    std::this_thread::sleep_for(std::chrono::milliseconds(10000));
+    try
+    {
+        m_async_client->connect(m_connOpts, nullptr, *this);
+    }
+    catch(const mqtt::exception& exc)
+    {
+		//重连异常了
+        std::string err = "Error: ";
+        err += exc.what();
+        LOG_INFO(err.c_str());
+    }
+}
+
+// Re-connection failure
+void CMqttClient::on_failure(const mqtt::token& tok)
+{
+	if (m_is_mqtt_connected == false)
+	{
+		//连接失败了
+		LOG_INFO("Connection attempt failed");
+		if (++nretry_ > N_RETRY_ATTEMPTS)
+		{
+			//重连次数超过了最大重连试错的次数,暂时不做任何处理,还是继续重连
+		}
+
+		reconnect();
 	}
-	catch (const mqtt::exception& exc) {
-		std::cerr << "\nERROR: Unable to connect to MQTT server: '"
-			<< SERVER_ADDRESS << "'" << exc << std::endl;
-		return;
+	else
+	{
+		//已经连接,那就是订阅失败了
+		std::string info = "Subscription failure";
+		if (tok.get_message_id() != 0)
+		{
+			info += " for token: [" + to_string(tok.get_message_id()) + "]";
+		}
+
+		LOG_INFO(info.c_str());
 	}
+}
 
-	// Just block till user tells us to quit.
+void CMqttClient::on_success(const mqtt::token& tok)
+{
+	if (m_is_mqtt_connected == false)
+	{
+		//连接成功了,再connected里面处理
+		
+		int a = 1;
+	}
+	else
+	{
+		//订阅成功了
+		std::string info = "Subscription success";
+		if (tok.get_message_id() != 0)
+		{
+			info += " for token: [" + to_string(tok.get_message_id()) + "]";
+		}
+		auto top = tok.get_topics();
+		if (top && !top->empty())
+		{
+			info += ",token topic: '" + (*top)[0] + "', ...";
+		}
 
-	while (true)
-		;
+		LOG_INFO(info.c_str());
+	}
+}
 
-	return;
+void CMqttClient::connected(const std::string& cause)
+{
+	m_is_mqtt_connected = true;
+
+    std::string info = "Connection success, nSubscribing to topic " + TOPIC + " for client " + CLIENT_ID + " using QoS" + to_string(MQTT_QOS);
+    LOG_INFO(info.c_str());
+
+	//不管是第一次连接,还是重连,都订阅一次
+    m_async_client->subscribe(TOPIC, MQTT_QOS, nullptr, *this);
+}
+
+void CMqttClient::connection_lost(const std::string& cause)
+{
+	m_is_mqtt_connected = false;
+
+    std::string info = "Connection lost";
+    if(!cause.empty())
+    {
+        info += ", cause: " + cause;
+    }
+
+    info += ",Reconnecting...";
+
+    LOG_INFO(info.c_str());
+
+    nretry_ = 0;
+    reconnect();
+}
+
+// Callback for when a message arrives.
+void CMqttClient::message_arrived(mqtt::const_message_ptr msg)
+{
+    std::string info = "Message arrived, ttopic: '" + msg->get_topic() + "', payload: '" + msg->to_string();
+
+    LOG_INFO(info.c_str());
+
+    //要的就是这个,收到消息了
+    std::string content = msg->to_string();
+
+	//对接收到的消息进行处理
+	this->HandleMessage(content);
+}
+
+void CMqttClient::delivery_complete(mqtt::delivery_token_ptr token)
+{
 }
 
 void CMqttClient::CalUserInfo()
 {
-	//实例 ID,购买后从控制台获取
-	char * instanceId = "post-cn-x0r3kjlsy02";
-	//测试收发消息的 Topic
-	char* topic = "lewaimai_windows_pos";
-	//接入点域名,从控制台获取
-	char *host = "post-cn-x0r3kjlsy02.mqtt.aliyuncs.com";
-	//客户端使用的 GroupID,从控制台申请
-	char *groupId = "GID_LEWAIMAI_WINDOWS_POS";
-	//客户端 ClientID 的后缀,由业务自行指定,只需要保证全局唯一即可
-	char *deviceId = "abcde";
-	/**
-	  * 账号 accesskey,从账号系统控制台获取
-	  * 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
-	  * 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
-	  * 可以把AccessKey ID和AccessKey Secret保存在环境变量。运行本代码示例之前,请先配置环境变量MQTT_AK_ENV和MQTT_SK_ENV
-	  * 例如:export MQTT_AK_ENV=<access_key_id>
-	  *      export MQTT_SK_ENV=<access_key_secret>
-	  * 需要将<access_key_id>替换为已准备好的AccessKey ID,<access_key_secret>替换为AccessKey Secret。
-	*/
-	char *accessKey = "LTAI4G5oikJPMfhq5PuW26qu";
-	//账号 SecretKey,从账号控制台获取
-	char *secretKey = "LsIxqepi2o3X0b17FSa7JaANfIMDVY";
-	//使用的协议端口,默认 tcp 协议使用1883,如果需要使用 SSL 加密,端口设置成8883,具体协议和端口参考文档链接https://help.aliyun.com/document_detail/44867.html?spm=a2c4g.11186623.6.547.38d81cf7XRnP0C
-	int port = 1883;
-	int qos = 0;
-	int cleanSession = 1;
-	int rc = 0;
-	unsigned char tempData[100];
-	unsigned int len = 0;
-	//ClientID要求使用 GroupId 和 DeviceId 拼接而成,长度不得超过64个字符
-	char clientIdUrl[64];
-	sprintf(clientIdUrl, "%s@@@%s", groupId, deviceId);
-
-	const unsigned char*abc = (unsigned char*)clientIdUrl;
-
-	//username和 Password 签名模式下的设置方法,参考文档 https://help.aliyun.com/document_detail/48271.html?spm=a2c4g.11186623.6.553.217831c3BSFry7
-	HMAC(EVP_sha1(), secretKey, strlen(secretKey), abc, strlen(clientIdUrl), tempData, &len);
-	char resultData[100];
-	int passWordLen = EVP_EncodeBlock((unsigned char *)resultData, tempData, len);
-	resultData[passWordLen] = '\0';
-	printf("passWord is %s", resultData);
-	char userNameData[128];
-	sprintf(userNameData, "Signature|%s|%s", accessKey, instanceId);
-	m_UserName = userNameData;
-	m_Password = resultData;
+    //实例 ID,购买后从控制台获取
+    char* instanceId = "post-cn-x0r3kjlsy02";
+
+    //测试收发消息的 Topic
+    char* topic = "lewaimai_windows_pos";
+
+    //接入点域名,从控制台获取
+    char* host = "post-cn-x0r3kjlsy02.mqtt.aliyuncs.com";
+
+    //客户端使用的 GroupID,从控制台申请
+    char* groupId = "GID_LEWAIMAI_WINDOWS_POS";
+
+    //客户端 ClientID 的后缀,由业务自行指定,只需要保证全局唯一即可
+    char* deviceId = "abcde";
+
+    /**
+      * 账号 accesskey,从账号系统控制台获取
+      * 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
+      * 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
+      * 可以把AccessKey ID和AccessKey Secret保存在环境变量。运行本代码示例之前,请先配置环境变量MQTT_AK_ENV和MQTT_SK_ENV
+      * 例如:export MQTT_AK_ENV=<access_key_id>
+      *      export MQTT_SK_ENV=<access_key_secret>
+      * 需要将<access_key_id>替换为已准备好的AccessKey ID,<access_key_secret>替换为AccessKey Secret。
+    */
+    char* accessKey = "LTAI4G5oikJPMfhq5PuW26qu";
+    //账号 SecretKey,从账号控制台获取
+    char* secretKey = "LsIxqepi2o3X0b17FSa7JaANfIMDVY";
+
+    unsigned char tempData[100];
+    unsigned int len = 0;
+
+    //ClientID要求使用 GroupId 和 DeviceId 拼接而成,长度不得超过64个字符
+    char clientIdUrl[64];
+    sprintf(clientIdUrl, "%s@@@%s", groupId, deviceId);
+
+    const unsigned char* abc = (unsigned char*)clientIdUrl;
+
+    //username和 Password 签名模式下的设置方法,参考文档 https://help.aliyun.com/document_detail/48271.html?spm=a2c4g.11186623.6.553.217831c3BSFry7
+    HMAC(EVP_sha1(), secretKey, strlen(secretKey), abc, strlen(clientIdUrl), tempData, &len);
+
+    char resultData[100];
+    int passWordLen = EVP_EncodeBlock((unsigned char*)resultData, tempData, len);
+    resultData[passWordLen] = '\0';
+    printf("passWord is %s", resultData);
+
+    char userNameData[128];
+    sprintf(userNameData, "Signature|%s|%s", accessKey, instanceId);
+
+    m_UserName = userNameData;
+    m_Password = resultData;
+}
+
+void CMqttClient::HandleMessage(std::string message)
+{
+    //收到服务器的消息,对服务器的消息进行处理
+    rapidjson::Document document;
+    document.Parse(message.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);
+        }
+
+        //判断是否右下角弹框提醒
+        if(CSetting::GetParam("setting_is_new_waimai_dialog") == "1")
+        {
+
+        }
+
+        AddPinter(order_id, order_no, 1);
+    }
+    else if(type == "2")
+    {
+        AddVoice(3);
+    }
+    else if(type == "3")
+    {
+        AddVoice(4);
+
+        std::string order_id = document["waimai_order_id"].GetString();
+        std::string order_no = document["waimai_order_no"].GetString();
+
+        AddPinter(order_id, order_no, 1, 3);
+    }
+    else if(type == "0")
+    {
+        //这个表示被人挤下线了
+        PostMessage(m_hwnd, WM_LOGIN_AGAIN_OUT, 0, 0);
+    }
+}
+
+/*
+ *类型 1:新外卖订单 2:新外卖订单自动接单 3:外卖订单取消 4:外卖订单退款
+ **/
+void CMqttClient::AddVoice(int voice_type)
+{
+    m_voice_mutex.lock();
+
+    m_voice_queue.push(voice_type);
+
+    m_voice_mutex.unlock();
+}
+
+void CMqttClient::AddConfirm(std::string order_id)
+{
+    m_confirm_mutex.lock();
+
+    m_confirm_queue.push(order_id);
+
+    m_confirm_mutex.unlock();
+}
+
+void CMqttClient::AddPinter(std::string order_id, std::string order_no, int print_type, int order_type)
+{
+    m_printer_mutex.lock();
+
+    WaimaiPinterInfo newPrinter;
+    newPrinter.order_id = order_id;
+    newPrinter.order_no = order_no;
+    newPrinter.print_type = print_type;
+    newPrinter.order_type = order_type;
+
+    m_printer_queue.push(newPrinter);
+
+    m_printer_mutex.unlock();
+}
+
+void CMqttClient::AddShouyinPrinter(CWaimaiOrder order)
+{
+    m_shouyin_printer_mutex.lock();
+
+    m_shouyin_printer_queue.push(order);
+
+    m_shouyin_printer_mutex.unlock();
+}
+
+void CMqttClient::AddBiaoqianPrinter(CWaimaiOrder order)
+{
+    m_biaoqian_printer_mutex.lock();
+
+    m_biaoqian_printer_queue.push(order);
+
+    m_biaoqian_printer_mutex.unlock();
+}
+
+void CMqttClient::AddChufangPrinter(CWaimaiOrder order)
+{
+    m_chufang_printer_mutex.lock();
+
+    m_chufang_printer_queue.push(order);
+
+    m_chufang_printer_mutex.unlock();
+}
+
+void CMqttClient::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 CMqttClient::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 CMqttClient::HandlePrinter()
+{
+    while(m_is_work)
+    {
+        m_printer_mutex.lock();
+
+        if(m_printer_queue.empty())
+        {
+            m_printer_mutex.unlock();
+
+            CSystem::my_sleep(1);
+            continue;
+        }
+
+        WaimaiPinterInfo printerInfo = m_printer_queue.front();
+        std::string order_id = printerInfo.order_id;
+        std::string order_no = printerInfo.order_no;
+        int print_type = printerInfo.print_type;
+        int order_type = printerInfo.order_type;
+
+        m_printer_queue.pop();
+
+        m_printer_mutex.unlock();
+
+        if(order_type == 1)
+        {
+            CWaimaiOrder order;
+            if(print_type == 1)
+            {
+                if(CSetting::GetParam("setting_is_new_waimai_printer") == "1" || CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1" || CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
+                {
+                    bool ret = order.InitData(order_id, order_no);
+
+                    if(ret == false)
+                    {
+                        this->AddPinter(order_id, order_no, print_type);
+                        continue;
+                    }
+                }
+
+                //判断是否自动打印收银小票
+                if(CSetting::GetParam("setting_is_new_waimai_printer") == "1")
+                {
+                    AddShouyinPrinter(order);
+                }
+
+                //判断是否自动打印标签小票
+                if(CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1")
+                {
+                    AddBiaoqianPrinter(order);
+                }
+
+                //判断是否进行自动的厨房打印
+                if(CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
+                {
+                    AddChufangPrinter(order);
+                }
+            }
+            else
+            {
+                bool ret = order.InitData(order_id, order_no);
+
+                if(ret == false)
+                {
+                    this->AddPinter(order_id, order_no, print_type);
+                    continue;
+                }
+
+                //手动打印的模式下,收银小票一定打印,标签如果没开就不打印
+                AddShouyinPrinter(order);
+
+                //手动打印的模式下,厨房小票一定打印
+                AddChufangPrinter(order);
+
+                //判断是否进行自动的厨房打印
+                /*
+                if (CSetting::GetParam("setting_is_new_waimai_chufang_printer") == "1")
+                {
+                	AddChufangPrinter(order);
+                }
+                }*/
+
+                //判断是否自动打印标签小票
+                if(CSetting::GetParam("setting_is_new_waimai_biaoqian_printer") == "1")
+                {
+                    AddBiaoqianPrinter(order);
+                }
+            }
+        }
+        else if(order_type == 3)
+        {
+            //顾客申请退款的
+            CWaimaiOrder order;
+            bool ret = order.InitData(order_id, order_no);
+
+            if(ret == false)
+            {
+                this->AddPinter(order_id, order_no, print_type, order_type);
+                continue;
+            }
+
+            CPosPrinter printer;
+            printer.PrintWaimaiOrderTuikuan(order);
+        }
+    }
+
+    AddStopNum();
+}
+
+void CMqttClient::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;
+        }
+
+        CWaimaiOrder order = m_shouyin_printer_queue.front();
+
+        m_shouyin_printer_queue.pop();
+
+        m_shouyin_printer_mutex.unlock();
+
+        CPosPrinter printer;
+        printer.PrintWaimaiOrderShouyin(order);
+    }
+
+    AddStopNum();
+}
+
+void CMqttClient::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;
+        }
+
+        CWaimaiOrder order = m_biaoqian_printer_queue.front();
+
+        m_biaoqian_printer_queue.pop();
+
+        m_biaoqian_printer_mutex.unlock();
+
+        CPosPrinter printer;
+        printer.PrintWaimaiOrderBiaoqian(order);
+    }
+
+    AddStopNum();
+}
+
+void CMqttClient::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;
+        }
+
+        CWaimaiOrder order = m_chufang_printer_queue.front();
+
+        m_chufang_printer_queue.pop();
+
+        m_chufang_printer_mutex.unlock();
+
+        CPosPrinter printer;
+        printer.PrintWaimaiOrderChufang(order);
+    }
+
+    AddStopNum();
+}
+
+void CMqttClient::AddStopNum()
+{
+    m_nStopNumMutex.lock();
+
+    m_nStopNum++;
+
+    m_nStopNumMutex.unlock();
+
+    if(m_nStopNum == 7)
+    {
+        //确认所有子线程都退出了,再删除自己
+        delete this;
+    }
 }

+ 120 - 128
lewaimai_pos_windows/network/CMqttClient.h

@@ -1,5 +1,8 @@
 #pragma once
 
+#include "../pch/pch.h"
+#include "../order/CWaimaiOrder.h"
+
 #include <iostream>
 #include <cstdlib>
 #include <string>
@@ -9,149 +12,138 @@
 #include <chrono>
 #include "mqtt/async_client.h"
 
-const int MQTT_QOS = 1;
-const int N_RETRY_ATTEMPTS = 5;
-
-/////////////////////////////////////////////////////////////////////////////
+class CClientMessage
+{
+public:
+    int m_type; //消息类型 0:新的外卖订单
 
-// Callbacks for the success or failures of requested actions.
-// This could be used to initiate further action, but here we just log the
-// results to the console.
+    std::string m_username;
+    std::string m_order_id;
+    std::string m_order_no;
+};
 
-class action_listener : public virtual mqtt::iaction_listener
+class WaimaiPinterInfo
 {
-	std::string name_;
-
-	void on_failure(const mqtt::token& tok) override {
-		std::cout << name_ << " failure";
-		if (tok.get_message_id() != 0)
-			std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
-		std::cout << std::endl;
-	}
-
-	void on_success(const mqtt::token& tok) override {
-		std::cout << name_ << " success";
-		if (tok.get_message_id() != 0)
-			std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
-		auto top = tok.get_topics();
-		if (top && !top->empty())
-			std::cout << "\ttoken topic: '" << (*top)[0] << "', ..." << std::endl;
-		std::cout << std::endl;
-	}
-
 public:
-	action_listener(const std::string& name) : name_(name) {}
+    std::string order_id;
+    std::string order_no;
+    int print_type; //打印类型 1:新订单自动打印 2:手动打印
+    int order_type = 1; // 订单类型:1 新订单 2 顾客取消订单 3顾客主动退款
 };
 
-/////////////////////////////////////////////////////////////////////////////
+class CMqttClient : public virtual mqtt::callback,
+    public virtual mqtt::iaction_listener
+{
+private:
+    //定义一些常量
+    std::string SERVER_ADDRESS = "post-cn-x0r3kjlsy02.mqtt.aliyuncs.com";
+    std::string CLIENT_ID = "GID_LEWAIMAI_WINDOWS_POS@@@abcde";
+    std::string TOPIC = "lewaimai_windows_pos";
 
-/**
- * Local callback & listener class for use with the client connection.
- * This is primarily intended to receive messages, but it will also monitor
- * the connection to the broker. If the connection is lost, it will attempt
- * to restore the connection and re-subscribe to the topic.
- */
-class callback : public virtual mqtt::callback,
-	public virtual mqtt::iaction_listener
+    //要保证可靠传输
+    int MQTT_QOS = 2;
 
-{
-	std::string SERVER_ADDRESS = "post-cn-x0r3kjlsy02.mqtt.aliyuncs.com";
-	std::string CLIENT_ID = "GID_LEWAIMAI_WINDOWS_POS@@@abcde";
-	std::string TOPIC = "lewaimai_windows_pos";
-
-	// Counter for the number of connection retries
-	int nretry_;
-	// The MQTT client
-	mqtt::async_client& cli_;
-	// Options to use if we need to reconnect
-	mqtt::connect_options& connOpts_;
-	// An action listener to display the result of actions.
-	action_listener subListener_;
-
-	// This deomonstrates manually reconnecting to the broker by calling
-	// connect() again. This is a possibility for an application that keeps
-	// a copy of it's original connect_options, or if the app wants to
-	// reconnect with different options.
-	// Another way this can be done manually, if using the same options, is
-	// to just call the async_client::reconnect() method.
-	void reconnect() {
-		std::this_thread::sleep_for(std::chrono::milliseconds(2500));
-		try {
-			cli_.connect(connOpts_, nullptr, *this);
-		}
-		catch (const mqtt::exception& exc) {
-			std::cerr << "Error: " << exc.what() << std::endl;
-			exit(1);
-		}
-	}
-
-	// Re-connection failure
-	void on_failure(const mqtt::token& tok) override {
-		std::cout << "Connection attempt failed" << std::endl;
-		if (++nretry_ > N_RETRY_ATTEMPTS)
-			exit(1);
-		reconnect();
-	}
-
-	// (Re)connection success
-	// Either this or connected() can be used for callbacks.
-	void on_success(const mqtt::token& tok) override {}
-
-	// (Re)connection success
-	void connected(const std::string& cause) override {
-		std::cout << "\nConnection success" << std::endl;
-		std::cout << "\nSubscribing to topic '" << TOPIC << "'\n"
-			<< "\tfor client " << CLIENT_ID
-			<< " using QoS" << MQTT_QOS << "\n"
-			<< "\nPress Q<Enter> to quit\n" << std::endl;
-
-		cli_.subscribe(TOPIC, MQTT_QOS, nullptr, subListener_);
-	}
-
-	// Callback for when the connection is lost.
-	// This will initiate the attempt to manually reconnect.
-	void connection_lost(const std::string& cause) override {
-		std::cout << "\nConnection lost" << std::endl;
-		if (!cause.empty())
-			std::cout << "\tcause: " << cause << std::endl;
-
-		std::cout << "Reconnecting..." << std::endl;
-		nretry_ = 0;
-		reconnect();
-	}
-
-	// Callback for when a message arrives.
-	void message_arrived(mqtt::const_message_ptr msg) override {
-		std::cout << "Message arrived" << std::endl;
-		std::cout << "\ttopic: '" << msg->get_topic() << "'" << std::endl;
-		std::cout << "\tpayload: '" << msg->to_string() << "'\n" << std::endl;
-	}
-
-	void delivery_complete(mqtt::delivery_token_ptr token) override {}
+    //一直重试
+    int N_RETRY_ATTEMPTS = 1000000;
+
+    //工作状态
+    bool m_is_running = false;
+
+    //连接阿里云的用户身份,计算出来的
+    std::string m_UserName;
+    std::string m_Password;
+
+    // Counter for the number of connection retries
+    int nretry_ = 0;
+
+    // The MQTT client
+    mqtt::async_client* m_async_client;
+
+    // Options to use if we need to reconnect
+    mqtt::connect_options m_connOpts;
+
+	bool m_is_mqtt_connected = false;
+
+    //下面是消息处理相关的
+    bool m_is_work;
+
+    int m_nStopNum = 0;
+    std::mutex m_nStopNumMutex;
+
+    std::queue<int> m_voice_queue;
+    std::queue<std::string> m_confirm_queue;
+    std::queue<WaimaiPinterInfo> m_printer_queue;
+    std::queue<CWaimaiOrder> m_shouyin_printer_queue;
+    std::queue<CWaimaiOrder> m_biaoqian_printer_queue;
+    std::queue<CWaimaiOrder> m_chufang_printer_queue;
+
+    std::mutex m_voice_mutex;
+    std::mutex m_confirm_mutex;
+    std::mutex m_printer_mutex;
+    std::mutex m_shouyin_printer_mutex;
+    std::mutex m_biaoqian_printer_mutex;
+    std::mutex m_chufang_printer_mutex;
+
+    HWND m_hwnd;
 
 public:
-	callback(mqtt::async_client& cli, mqtt::connect_options& connOpts)
-		: nretry_(0), cli_(cli), connOpts_(connOpts), subListener_("Subscription") {}
-};
+    CMqttClient(HWND hwnd);
+
+    ~CMqttClient();
+
+    void Start();
+
+    void Stop();
+
+	void AddPinter(std::string order_id, std::string order_no, int print_type, int order_type = 1);
 
-class CMqttClient
-{
 private:
-	std::string m_UserName;
-	std::string m_Password;
+    void Run();
 
-	std::string SERVER_ADDRESS = "post-cn-x0r3kjlsy02.mqtt.aliyuncs.com";
-	std::string CLIENT_ID = "GID_LEWAIMAI_WINDOWS_POS@@@abcde";
-	std::string TOPIC = "lewaimai_windows_pos";
+    void CalUserInfo();
 
-public:
-	CMqttClient();
-	~CMqttClient();
+    //处理接收到的MQTT消息推送
+    void HandleMessage(std::string message);
 
-	void Start();
+    // This deomonstrates manually reconnecting to the broker by calling
+    // connect() again. This is a possibility for an application that keeps
+    // a copy of it's original connect_options, or if the app wants to
+    // reconnect with different options.
+    // Another way this can be done manually, if using the same options, is
+    // to just call the async_client::reconnect() method.
+    void reconnect();
 
-	void Run();
+    // 连接、重连、发布、订阅失败回调
+    void on_failure(const mqtt::token& tok) override;
 
-	void CalUserInfo();
-};
+    // 连接、重连、发布、订阅成功回调
+    void on_success(const mqtt::token& tok) override;
+
+    // 第1次连接成功,或者重连成功,都会调用这个函数
+    void connected(const std::string& cause) override;
+
+    // 连接丢失,重新连接
+    void connection_lost(const std::string& cause) override;
+
+    // 接收到了消息,进行处理
+    void message_arrived(mqtt::const_message_ptr msg) override;
+
+    void delivery_complete(mqtt::delivery_token_ptr token) override;
+
+    //队列处理
+    void HandleVoice();
+    void HandleConfirm();
+    void HandlePrinter();
+    void HandleShouyinPrinter();
+    void HandleBiaoqianPrinter();
+    void HandleChufangPrinter();
+
+
+    void AddVoice(int voice_type);
+    void AddConfirm(std::string order_id);
+    void AddShouyinPrinter(CWaimaiOrder order);
+    void AddBiaoqianPrinter(CWaimaiOrder order);
+    void AddChufangPrinter(CWaimaiOrder order);
 
+    void AddStopNum();
+};

+ 0 - 10
lewaimai_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;
-};

+ 7 - 9
lewaimai_pos_windows/wnd/CMainWnd.cpp

@@ -7,7 +7,6 @@
 #include "../control/ControlEx.h"
 #include "../control/CWaimaiOrderInfoUI.h"
 
-#include "../network/CMessagePush.h"
 #include "../network/CMqttClient.h"
 #include "CWaimaiOrderFailReasonWnd.h"
 
@@ -30,11 +29,8 @@ void CMainWnd::Init()
     //初始化设置中心的状态
     InitSettingStatus();
 
-    //登录成功,启动消息和任务处理
-    m_push = new CMessagePush(m_hWnd);
-    m_push->Start();
-
-	m_mqttClient = new CMqttClient();
+    //登录成功,启动MQTT客户端来接收和处理服务器推送的消息
+	m_mqttClient = new CMqttClient(m_hWnd);
 	m_mqttClient->Start();
 }
 
@@ -122,7 +118,8 @@ void CMainWnd::HandleClickMsg(TNotifyUI& msg)
         CWaimaiOrderItemUI* item = static_cast<CWaimaiOrderItemUI*>(msg.pSender->GetParent()->GetParent());
         std::string waimai_order_id = item->getOrderID();
         std::string waimai_order_no = item->getOrderNo();
-        m_push->AddPinter(waimai_order_id, waimai_order_no, 2);
+
+        m_mqttClient->AddPinter(waimai_order_id, waimai_order_no, 2);
     }
     else if(name == _T("waimai_order_list_confirme"))
     {
@@ -266,7 +263,7 @@ void CMainWnd::HandleClickMsg(TNotifyUI& msg)
     else if(name == _T("waimai_order_info_page_print"))
     {
         CWaimaiOrderInfoUI* order_info_page = static_cast<CWaimaiOrderInfoUI*>(m_pm.FindControl(_T("waimaiorder_info_page")));
-        m_push->AddPinter(order_info_page->m_order.m_order_id, order_info_page->m_order.m_order_no, 2);
+        m_mqttClient->AddPinter(order_info_page->m_order.m_order_id, order_info_page->m_order.m_order_no, 2);
     }
     else if(name == _T("waimai_order_info_page_confirme"))
     {
@@ -1462,7 +1459,8 @@ 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();
+    m_mqttClient->Stop();
+
     bHandled = FALSE;
     return 0;
 }

+ 1 - 3
lewaimai_pos_windows/wnd/CMainWnd.h

@@ -13,7 +13,7 @@ class CMainWnd : public CWindowWnd, public INotifyUI, public IMessageFilterUI
 {
 public:
     CMainWnd() { };
-
+	
     LPCTSTR GetWindowClassName() const
     {
         return _T("UIMainFrame");
@@ -93,7 +93,5 @@ private:
     //定义托盘图标对象
     NOTIFYICONDATA m_trayIcon;
 
-    CMessagePush* m_push = NULL;
-
 	CMqttClient* m_mqttClient = NULL;
 };

+ 2 - 0
lewaimai_pos_windows_server/obj/x86/Release/lewaimai_pos_windows_server_linux.log

@@ -0,0 +1,2 @@
+  Cleaning remote project directory
+D:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Application Type\Linux\1.0\Linux.targets(210,6): error : Could not connect to the remote system. Please verify your connection settings, and that your machine is on the network and reachable.