张洋 недель назад: 2
Родитель
Сommit
722d443abb

+ 248 - 90
zhipuzi_pos_windows/ai/YoloClassName.h

@@ -6,98 +6,256 @@
 // 果蔬名称常量数组(索引对应英文名称)
 // 果蔬名称常量数组(索引对应英文名称)
 // 注释格式:[索引] 英文名称 // 中文名称
 // 注释格式:[索引] 英文名称 // 中文名称
 const std::string FRUIT_VEGETABLE_NAMES[] = {
 const std::string FRUIT_VEGETABLE_NAMES[] = {
-    "baixianguo",
-    "biandou",
-    "bingtangcheng",
-    "boluo",
-    "caomei",
-    "chelizi",
-    "fanlizhi",
-    "fanshiliu",
-    "fengshuili",
-    "haitangguo",
-    "hamigua",
-    "hongmaodan",
-    "hongti",
-    "huangguanli",
-    "huluobo",
-    "huolongguo",
-    "kuerlexiangli",
-    "kugua",
-    "lanmei",
-    "liulian",
-    "lizhi",
-    "longyan",
-    "mangguo",
-    "mihoutao",
-    "miju",
-    "mugua",
-    "nanguoli",
-    "niuyouguo",
-    "pingguo",
-    "qicheng",
-    "qiezi",
-    "qingti",
-    "renxingguo",
-    "shanzhu",
-    "shatangju",
-    "shiliu",
-    "tudou",
-    "wandou",
-    "wandoujia",
-    "xiangjiao",
-    "xigua",
-    "xueli",
-    "yali",
-    "yezi",
-    "yumi"
+    "apple_akosu",          // 0: 阿克苏苹果
+    "apple_gala",           // 1: 嘎啦苹果
+    "apple_green",          // 2: 青苹果
+    "apple_hua_niu",        // 3: 花牛苹果
+    "apple_red_fuji",       // 4: 红富士苹果
+    "apricot",              // 5: 杏
+    "asparagus",            // 6: 芦笋
+    "avocado",              // 7: 牛油果
+    "banana",               // 8: 香蕉
+    "bamboo_shoot",         // 9: 竹笋
+    "baby_cabbage",         // 10: 娃娃菜
+    "bean_green",           // 11: 四季豆
+    "bitter_gourd",         // 12: 苦瓜
+    "blueberry",            // 13: 蓝莓
+    "bokchoy",              // 14: 上海青
+    "broccoli",             // 15: 西兰花
+    "cabbage_chinese",      // 16: 大白菜
+    "cabbage_purple",       // 17: 紫甘蓝
+    "cabbage_round",        // 18: 圆白菜
+    "cabbage_small",        // 19: 小白菜
+    "cantaloupe",           // 20: 哈密瓜
+    "cantaloupe_nettle",    // 21: 网纹瓜
+    "cantaloupe_xizhou",    // 22: 西州蜜
+    "carrot",               // 23: 胡萝卜
+    "carrot_yellow",        // 24: 黄胡萝卜
+    "cauliflower",          // 25: 白花菜
+    "caixin",               // 26: 菜心
+    "celery",               // 27: 芹菜
+    "cherry",               // 28: 樱桃
+    "cherry_big",           // 29: 车厘子
+    "chili_small",          // 30: 小米辣
+    "chinese_yam",          // 31: 山药
+    "chives",               // 32: 韭菜
+    "coriander",            // 33: 香菜
+    "corn",                 // 34: 玉米
+    "cowpea",               // 35: 豇豆
+    "cucumber",             // 36: 黄瓜
+    "cucumber_fruit",       // 37: 水果黄瓜
+    "cucumber_white",       // 38: 白玉黄瓜
+    "durian",               // 39: 榴莲
+    "dragonfruit_red",      // 40: 红心火龙果
+    "dragonfruit_white",    // 41: 白心火龙果
+    "eggplant_long",        // 42: 长茄子
+    "eggplant_round",       // 43: 圆茄子
+    "garlic",               // 44: 大蒜
+    "garlic_scape",         // 45: 蒜苔
+    "ginger",               // 46: 生姜
+    "grape_black",          // 47: 夏黑
+    "grape_green",          // 48: 青提
+    "grape_kyoho",          // 49: 巨峰葡萄
+    "grape_red",            // 50: 红提
+    "grape_seedless",       // 51: 无籽葡萄
+    "grape_shine",          // 52: 阳光玫瑰
+    "grapefruit",           // 53: 西柚
+    "jujube_winter",        // 54: 冬枣
+    "kiwi_green",           // 55: 绿心猕猴桃
+    "kiwi_red",             // 56: 红心猕猴桃
+    "lemon",                // 57: 柠檬
+    "lime",                // 58: 青柠
+    "lettuce",              // 59: 生菜
+    "lettuce_romaine",      // 60: 罗马生菜
+    "litchi",               // 61: 荔枝
+    "loofah",               // 62: 丝瓜
+    "longan",               // 63: 龙眼
+    "lotus_root",           // 64: 莲藕
+    "mango_golden",         // 65: 金煌芒
+    "mango_guifei",         // 66: 贵妃芒
+    "mango_small",          // 67: 小台农芒果
+    "mangosteen",           // 68: 山竹
+    "muskmelon_common",     // 69: 香瓜
+    "muskmelon_green",      // 70: 绿宝甜瓜
+    "muskmelon_horn",       // 71: 羊角蜜
+    "mushroom_enoki",       // 72: 金针菇
+    "mushroom_king",        // 73: 杏鲍菇
+    "mushroom_oyster",      // 74: 平菇
+    "mushroom_shiitake",    // 75: 香菇
+    "okra",                 // 76: 秋葵
+    "oil_vegetable",        // 77: 油麦菜
+    "onion_purple",         // 78: 紫洋葱
+    "onion_white",          // 79: 白洋葱
+    "orange_mandarin",      // 80: 蜜橘
+    "orange_navel",         // 81: 脐橙
+    "orange_papa",          // 82: 耙耙柑
+    "orange_tangerine",     // 83: 砂糖橘
+    "orange_ugly",          // 84: 丑橘
+    "orange_wogan",         // 85: 沃柑
+    "papaya",               // 86: 木瓜
+    "peach_flat",           // 87: 蟠桃
+    "peach_honey",          // 88: 水蜜桃
+    "peach_nectarine",      // 89: 油桃
+    "peach_yellow",         // 90: 黄桃
+    "pear_kuerle",          // 91: 库尔勒香梨
+    "pear_qiuyue",          // 92: 秋月梨
+    "pear_snow",            // 93: 雪梨
+    "pear_ya",              // 94: 鸭梨
+    "pepper_bell_green",    // 95: 绿彩椒
+    "pepper_bell_red",      // 96: 红彩椒
+    "pepper_bell_yellow",   // 97: 黄彩椒
+    "pea",                  // 98: 豌豆
+    "pineapple",            // 99: 菠萝
+    "pineapple_yellow",     // 100: 凤梨
+    "plum",                 // 101: 李子
+    "plum_black",           // 102: 黑布林
+    "pomegranate",          // 103: 石榴
+    "potato",               // 104: 土豆
+    "pumpkin",              // 105: 南瓜
+    "pumpkin_baby",         // 106: 贝贝南瓜
+    "purple_potato",        // 107: 紫薯
+    "radish_cherry",        // 108: 樱桃萝卜
+    "radish_red",           // 109: 红萝卜
+    "radish_white",         // 110: 白萝卜
+    "spinach",              // 111: 菠菜
+    "strawberry",           // 112: 草莓
+    "sweet_potato",         // 113: 红薯
+    "tomato_big",           // 114: 大番茄
+    "tomato_cherry",        // 115: 圣女果
+    "tomato_qianxi",        // 116: 千禧果
+    "wax_gourd",            // 117: 冬瓜
+    "watermelon",           // 118: 西瓜
+    "watermelon_8424",      // 119: 8424西瓜
+    "watermelon_black_beauty", // 120: 黑美人西瓜
+    "watermelon_qilin",     // 121: 麒麟西瓜
+    "wood_ear",             // 122: 木耳
+    "zucchini"              // 123: 西葫芦
 };
 };
 
 
 // 果蔬英文名称 -> 中文名称 映射表(哈希表,查询效率O(1))
 // 果蔬英文名称 -> 中文名称 映射表(哈希表,查询效率O(1))
 const std::unordered_map<std::string, std::string> FRUIT_VEGETABLE_CN_MAP = {
 const std::unordered_map<std::string, std::string> FRUIT_VEGETABLE_CN_MAP = {
-    {"baixianguo", "百香果"},
-    {"biandou", "扁豆"},
-    {"bingtangcheng", "冰糖橙"},
-    {"boluo", "菠萝"},
-    {"caomei", "草莓"},
-    {"chelizi", "车厘子"},
-    {"fanlizhi", "番荔枝"},
-    {"fanshiliu", "番石榴"},
-    {"fengshuili", "凤梨"},
-    {"haitangguo", "海棠果"},
-    {"hamigua", "哈密瓜"},
-    {"hongmaodan", "红毛丹"},
-    {"hongti", "红提"},
-    {"huangguanli", "皇冠梨"},
-    {"huluobo", "胡萝卜"},
-    {"huolongguo", "火龙果"},
-    {"kuerlexiangli", "库尔勒香梨"},
-    {"kugua", "苦瓜"},
-    {"lanmei", "蓝莓"},
-    {"liulian", "榴莲"},
-    {"lizhi", "荔枝"},
-    {"longyan", "龙眼"},
-    {"mangguo", "芒果"},
-    {"mihoutao", "猕猴桃"},
-    {"miju", "蜜桔"},
-    {"mugua", "木瓜"},
-    {"nanguoli", "南国梨"},
-    {"niuyouguo", "牛油果"},
-    {"pingguo", "苹果"},
-    {"qicheng", "脐橙"},
-    {"qiezi", "茄子"},
-    {"qingti", "青提"},
-    {"renxingguo", "人参果"},
-    {"shanzhu", "山竹"},
-    {"shatangju", "砂糖橘"},
-    {"shiliu", "石榴"},
-    {"tudou", "土豆"},
-    {"wandou", "豌豆"},
-    {"wandoujia", "豌豆荚"},
-    {"xiangjiao", "香蕉"},
-    {"xigua", "西瓜"},
-    {"xueli", "雪梨"},
-    {"yali", "鸭梨"},
-    {"yezi", "椰子"},
-    {"yumi", "玉米"}
+    {"apple_akosu", "阿克苏苹果"},
+    {"apple_gala", "嘎啦苹果"},
+    {"apple_green", "青苹果"},
+    {"apple_hua_niu", "花牛苹果"},
+    {"apple_red_fuji", "红富士苹果"},
+    {"apricot", "杏"},
+    {"asparagus", "芦笋"},
+    {"avocado", "牛油果"},
+    {"banana", "香蕉"},
+    {"bamboo_shoot", "竹笋"},
+    {"baby_cabbage", "娃娃菜"},
+    {"bean_green", "四季豆"},
+    {"bitter_gourd", "苦瓜"},
+    {"blueberry", "蓝莓"},
+    {"bokchoy", "上海青"},
+    {"broccoli", "西兰花"},
+    {"cabbage_chinese", "大白菜"},
+    {"cabbage_purple", "紫甘蓝"},
+    {"cabbage_round", "圆白菜"},
+    {"cabbage_small", "小白菜"},
+    {"cantaloupe", "哈密瓜"},
+    {"cantaloupe_nettle", "网纹瓜"},
+    {"cantaloupe_xizhou", "西州蜜"},
+    {"carrot", "胡萝卜"},
+    {"carrot_yellow", "黄胡萝卜"},
+    {"cauliflower", "白花菜"},
+    {"caixin", "菜心"},
+    {"celery", "芹菜"},
+    {"cherry", "樱桃"},
+    {"cherry_big", "车厘子"},
+    {"chili_small", "小米辣"},
+    {"chinese_yam", "山药"},
+    {"chives", "韭菜"},
+    {"coriander", "香菜"},
+    {"corn", "玉米"},
+    {"cowpea", "豇豆"},
+    {"cucumber", "黄瓜"},
+    {"cucumber_fruit", "水果黄瓜"},
+    {"cucumber_white", "白玉黄瓜"},
+    {"durian", "榴莲"},
+    {"dragonfruit_red", "红心火龙果"},
+    {"dragonfruit_white", "白心火龙果"},
+    {"eggplant_long", "长茄子"},
+    {"eggplant_round", "圆茄子"},
+    {"garlic", "大蒜"},
+    {"garlic_scape", "蒜苔"},
+    {"ginger", "生姜"},
+    {"grape_black", "夏黑"},
+    {"grape_green", "青提"},
+    {"grape_kyoho", "巨峰葡萄"},
+    {"grape_red", "红提"},
+    {"grape_seedless", "无籽葡萄"},
+    {"grape_shine", "阳光玫瑰"},
+    {"grapefruit", "西柚"},
+    {"jujube_winter", "冬枣"},
+    {"kiwi_green", "绿心猕猴桃"},
+    {"kiwi_red", "红心猕猴桃"},
+    {"lemon", "柠檬"},
+    {"lime", "青柠"},
+    {"lettuce", "生菜"},
+    {"lettuce_romaine", "罗马生菜"},
+    {"litchi", "荔枝"},
+    {"loofah", "丝瓜"},
+    {"longan", "龙眼"},
+    {"lotus_root", "莲藕"},
+    {"mango_golden", "金煌芒"},
+    {"mango_guifei", "贵妃芒"},
+    {"mango_small", "小台农芒果"},
+    {"mangosteen", "山竹"},
+    {"muskmelon_common", "香瓜"},
+    {"muskmelon_green", "绿宝甜瓜"},
+    {"muskmelon_horn", "羊角蜜"},
+    {"mushroom_enoki", "金针菇"},
+    {"mushroom_king", "杏鲍菇"},
+    {"mushroom_oyster", "平菇"},
+    {"mushroom_shiitake", "香菇"},
+    {"okra", "秋葵"},
+    {"oil_vegetable", "油麦菜"},
+    {"onion_purple", "紫洋葱"},
+    {"onion_white", "白洋葱"},
+    {"orange_mandarin", "蜜橘"},
+    {"orange_navel", "脐橙"},
+    {"orange_papa", "耙耙柑"},
+    {"orange_tangerine", "砂糖橘"},
+    {"orange_ugly", "丑橘"},
+    {"orange_wogan", "沃柑"},
+    {"papaya", "木瓜"},
+    {"peach_flat", "蟠桃"},
+    {"peach_honey", "水蜜桃"},
+    {"peach_nectarine", "油桃"},
+    {"peach_yellow", "黄桃"},
+    {"pear_kuerle", "库尔勒香梨"},
+    {"pear_qiuyue", "秋月梨"},
+    {"pear_snow", "雪梨"},
+    {"pear_ya", "鸭梨"},
+    {"pepper_bell_green", "绿彩椒"},
+    {"pepper_bell_red", "红彩椒"},
+    {"pepper_bell_yellow", "黄彩椒"},
+    {"pea", "豌豆"},
+    {"pineapple", "菠萝"},
+    {"pineapple_yellow", "凤梨"},
+    {"plum", "李子"},
+    {"plum_black", "黑布林"},
+    {"pomegranate", "石榴"},
+    {"potato", "土豆"},
+    {"pumpkin", "南瓜"},
+    {"pumpkin_baby", "贝贝南瓜"},
+    {"purple_potato", "紫薯"},
+    {"radish_cherry", "樱桃萝卜"},
+    {"radish_red", "红萝卜"},
+    {"radish_white", "白萝卜"},
+    {"spinach", "菠菜"},
+    {"strawberry", "草莓"},
+    {"sweet_potato", "红薯"},
+    {"tomato_big", "大番茄"},
+    {"tomato_cherry", "圣女果"},
+    {"tomato_qianxi", "千禧果"},
+    {"wax_gourd", "冬瓜"},
+    {"watermelon", "西瓜"},
+    {"watermelon_8424", "8424西瓜"},
+    {"watermelon_black_beauty", "黑美人西瓜"},
+    {"watermelon_qilin", "麒麟西瓜"},
+    {"wood_ear", "木耳"},
+    {"zucchini", "西葫芦"}
 };
 };

+ 3 - 5
zhipuzi_pos_windows/page/CDiandanPageUI.cpp

@@ -4047,17 +4047,15 @@ void CDiandanPageUI::HandleChengzhongValueChange()
 	std::string weight = CChengzhongWorker::GetInstance()->GetWeight();
 	std::string weight = CChengzhongWorker::GetInstance()->GetWeight();
 
 
 	CControlUI* pWendingStatus = static_cast<CControlUI*>(this->FindSubControl(_T("diandan_page_status_chengzhong_wending")));
 	CControlUI* pWendingStatus = static_cast<CControlUI*>(this->FindSubControl(_T("diandan_page_status_chengzhong_wending")));
-	if (m_last_weight != weight)
+	if (CChengzhongWorker::GetInstance()->GetIsWending() == true)
 	{
 	{
-		pWendingStatus->SetBkImage(L"deng_off.png");
+		pWendingStatus->SetBkImage(L"deng_on.png");
 	}
 	}
 	else
 	else
 	{
 	{
-		pWendingStatus->SetBkImage(L"deng_on.png");
+		pWendingStatus->SetBkImage(L"deng_off.png");
 	}
 	}
 
 
-	m_last_weight = weight;
-
 	CLabelUI* pLabel = static_cast<CLabelUI*>(this->FindSubControl(_T("diandan_page_label_chengzhong_value")));
 	CLabelUI* pLabel = static_cast<CLabelUI*>(this->FindSubControl(_T("diandan_page_label_chengzhong_value")));
 	pLabel->SetText(CLewaimaiString::UTF8ToUnicode(weight).c_str());
 	pLabel->SetText(CLewaimaiString::UTF8ToUnicode(weight).c_str());
 }
 }

+ 0 - 2
zhipuzi_pos_windows/page/CDiandanPageUI.h

@@ -369,7 +369,5 @@ private:
 	bool m_is_yincangyouhui = false;
 	bool m_is_yincangyouhui = false;
 
 
 	//与称重显示相关的
 	//与称重显示相关的
-	std::string m_last_weight = "0.000";
-
 	bool m_is_dianzicheng_lianjie = false;
 	bool m_is_dianzicheng_lianjie = false;
 };
 };

+ 5 - 0
zhipuzi_pos_windows/page/CSettingPageUI.cpp

@@ -6,6 +6,7 @@
 #include "../print/CPosPrinter.h"
 #include "../print/CPosPrinter.h"
 #include "../helper/CComHelper.h"
 #include "../helper/CComHelper.h"
 #include "../worker/CChengzhongWorker.h"
 #include "../worker/CChengzhongWorker.h"
+#include "../worker/CDiandanAIShibieWorker.h"
 
 
 #include <boost/array.hpp>
 #include <boost/array.hpp>
 
 
@@ -1588,10 +1589,14 @@ void CSettingPageUI::HandleClickMsg(TNotifyUI& msg)
 		if (box->IsSelected())
 		if (box->IsSelected())
 		{
 		{
 			CSetting::GetInstance()->SetParam("setting_is_ai_recognition_open", "0");
 			CSetting::GetInstance()->SetParam("setting_is_ai_recognition_open", "0");
+
+			CDiandanAIShibieWorker::GetInstance()->StopAIShibie();
 		}
 		}
 		else
 		else
 		{
 		{
 			CSetting::GetInstance()->SetParam("setting_is_ai_recognition_open", "1");
 			CSetting::GetInstance()->SetParam("setting_is_ai_recognition_open", "1");
+
+			CDiandanAIShibieWorker::GetInstance()->StartAIShibie();
 		}
 		}
 	}
 	}
 	else if (name == _T("setting_logout"))
 	else if (name == _T("setting_logout"))

+ 2 - 1
zhipuzi_pos_windows/tool/CAppEnv.cpp

@@ -46,9 +46,10 @@ void CAppEnv::Start()
 	CVideoCaptureWorker::GetInstance()->Start();
 	CVideoCaptureWorker::GetInstance()->Start();
 	AddWorkerNum();
 	AddWorkerNum();
 
 
-	//启动AI识别任务
+	//启动AI识别任务(有2个工作线程)
 	CDiandanAIShibieWorker::GetInstance()->StartWork();
 	CDiandanAIShibieWorker::GetInstance()->StartWork();
 	AddWorkerNum();
 	AddWorkerNum();
+	AddWorkerNum();
 
 
 	//启动通用任务
 	//启动通用任务
 	CCommonWorker::GetInstance()->Start();
 	CCommonWorker::GetInstance()->Start();

+ 1 - 1
zhipuzi_pos_windows/wnd/CMainWnd.cpp

@@ -183,7 +183,7 @@ void CMainWnd::SwitchPage(MainPageName name, bool is_init_show)
 
 
 	//根据AI识别的设置,启动或者暂停AI识别【在进入点单页面的时候设置刚好合适】
 	//根据AI识别的设置,启动或者暂停AI识别【在进入点单页面的时候设置刚好合适】
 	std::string is_ai_shibie = CSetting::GetInstance()->GetParam("setting_is_ai_recognition_open");
 	std::string is_ai_shibie = CSetting::GetInstance()->GetParam("setting_is_ai_recognition_open");
-	if (is_ai_shibie == "1" && m_curPageName == CMainWnd::DIANDAN)
+	if (is_ai_shibie == "1")
 	{
 	{
 		CDiandanAIShibieWorker::GetInstance()->StartAIShibie();
 		CDiandanAIShibieWorker::GetInstance()->StartAIShibie();
 	}
 	}

+ 113 - 115
zhipuzi_pos_windows/worker/CChengzhongWorker.cpp

@@ -1,6 +1,8 @@
 #include "../pch/pch.h"
 #include "../pch/pch.h"
 #include "CChengzhongWorker.h"
 #include "CChengzhongWorker.h"
 
 
+#include "CDiandanAIShibieWorker.h"
+
 CChengzhongWorker::CChengzhongWorker()
 CChengzhongWorker::CChengzhongWorker()
 {
 {
 }
 }
@@ -57,6 +59,8 @@ void CChengzhongWorker::HandleWork()
 
 
 	while (m_is_work)
 	while (m_is_work)
 	{
 	{
+		std::string new_weight;
+
 		//不同型号的电子秤,数据格式可能不一样,处理方式不一样
 		//不同型号的电子秤,数据格式可能不一样,处理方式不一样
 		if (setting_dianzicheng_xinghao == "dahua_acs")
 		if (setting_dianzicheng_xinghao == "dahua_acs")
 		{
 		{
@@ -68,91 +72,73 @@ void CChengzhongWorker::HandleWork()
 			DWORD nReaded = 0;
 			DWORD nReaded = 0;
 
 
 			m_serial.readFromComm(a, 100, &nReaded);
 			m_serial.readFromComm(a, 100, &nReaded);
-
-			if (nReaded > 0)
+			if (nReaded <= 0)
 			{
 			{
-				//把所有读到的内容,拼接到m_chuankou_string后面,避免有的数据中间截断导致格式混乱
-				m_chuankou_string += a;
-
-				std::string show_command = "\n\r";
-
-				size_t nPos = m_chuankou_string.find(show_command);
-				if (nPos == m_chuankou_string.npos)
-				{
-					//没有读到足够的长度,继续读
-					continue;
-				}
-
-				std::string weight;
+				Sleep(200);
+				continue;
+			}
 
 
-				//如果前2个不是标志符,那么就判断标志符后面的数字长度够不够5个
-				if (m_chuankou_string.length() >= nPos + 7)
-				{
-					//这个情况是,标志符后面有5个数字
-					weight = m_chuankou_string.substr(nPos + 2, 5);
+			//把所有读到的内容,拼接到m_chuankou_string后面,避免有的数据中间截断导致格式混乱
+			m_chuankou_string += a;
 
 
-					//然后把前面的字符都删掉
-					m_chuankou_string = m_chuankou_string.substr(nPos + 7);
-				}
-				else if (nPos >= 20)
-				{
-					//说明前面有20个字符,首先肯定不是稳定模式而是极速模式,另外在极速模式下可以直接得到重量了
-					weight = m_chuankou_string.substr(nPos - 20, 5);
+			std::string show_command = "\n\r";
 
 
-					m_chuankou_string = m_chuankou_string.substr(nPos + 2);
-				}
-				else
-				{
-					//标志符后面前面都不够读取重量,继续读取串口
-					continue;
-				}
+			size_t nPos = m_chuankou_string.find(show_command);
+			if (nPos == m_chuankou_string.npos)
+			{
+				//没有读到足够的长度,继续读
+				continue;
+			}
 
 
-				if (weight.at(0) == ' ')
-				{
-					weight = weight.substr(1);
-				}
+			std::string weight;
 
 
-				std::string zhengshu;
-				std::string xiaoshu;
-				if (weight.length() == 4)
-				{
-					//重量小于10公斤,第一个数字为空
-					zhengshu = weight.substr(0, 1);
-					xiaoshu = weight.substr(1, 3);
-				}
-				else if (weight.length() == 5)
-				{
-					//重量大于10公斤,第一个数字为空
-					zhengshu = weight.substr(0, 2);
-					xiaoshu = weight.substr(2, 3);
-				}
-				else
-				{
-					continue;
-				}
+			//如果前2个不是标志符,那么就判断标志符后面的数字长度够不够5个
+			if (m_chuankou_string.length() >= nPos + 7)
+			{
+				//这个情况是,标志符后面有5个数字
+				weight = m_chuankou_string.substr(nPos + 2, 5);
 
 
-				std::string new_weight = zhengshu + "." + xiaoshu;
+				//然后把前面的字符都删掉
+				m_chuankou_string = m_chuankou_string.substr(nPos + 7);
+			}
+			else if (nPos >= 20)
+			{
+				//说明前面有20个字符,首先肯定不是稳定模式而是极速模式,另外在极速模式下可以直接得到重量了
+				weight = m_chuankou_string.substr(nPos - 20, 5);
 
 
-				if (m_weight != new_weight)
-				{
-					//说明重量有变化了
-					m_weight = new_weight;
-				}
+				m_chuankou_string = m_chuankou_string.substr(nPos + 2);
+			}
+			else
+			{
+				//标志符后面前面都不够读取重量,继续读取串口
+				continue;
+			}
 
 
-				if (m_hwnd != NULL)
-				{
-					PostMessage(m_hwnd, WM_CHENGZHONG_SUCCESS, 0, 0);
-				}
+			if (weight.at(0) == ' ')
+			{
+				weight = weight.substr(1);
+			}
 
 
-				if (m_MainHWND != NULL)
-				{
-					PostMessage(m_MainHWND, WM_CHENGZHONG_SUCCESS, 0, 0);
-				}
+			std::string zhengshu;
+			std::string xiaoshu;
+			if (weight.length() == 4)
+			{
+				//重量小于10公斤,第一个数字为空
+				zhengshu = weight.substr(0, 1);
+				xiaoshu = weight.substr(1, 3);
+			}
+			else if (weight.length() == 5)
+			{
+				//重量大于10公斤,第一个数字为空
+				zhengshu = weight.substr(0, 2);
+				xiaoshu = weight.substr(2, 3);
 			}
 			}
 			else
 			else
 			{
 			{
-				Sleep(100);
+				continue;
 			}
 			}
+
+			new_weight = zhengshu + "." + xiaoshu;
 		}
 		}
 		else if (setting_dianzicheng_xinghao == "dingjian_os2x")
 		else if (setting_dianzicheng_xinghao == "dingjian_os2x")
 		{
 		{
@@ -164,66 +150,78 @@ void CChengzhongWorker::HandleWork()
 			DWORD nReaded = 0;
 			DWORD nReaded = 0;
 
 
 			m_serial.readFromComm(a, 16, &nReaded);
 			m_serial.readFromComm(a, 16, &nReaded);
-
-			if (nReaded > 0)
+			if (nReaded <= 0)
 			{
 			{
-				//把所有读到的内容,拼接到m_chuankou_string后面,避免有的数据中间截断导致格式混乱
-				m_chuankou_string = a;
-
-				if (a[0] != 0x01 || a[1] != 0x02 || a[13] != 0x03 || a[14] != 0x04)
-				{
-					//说明这16个字节的数据不是完整的,这个时候处理方式是把错误数据全部读完,但是不处理,然后下次接着处理
-					std::string show_command = "\x01\x02";
+				Sleep(200);
+				continue;
+			}
 
 
-					size_t nPos = m_chuankou_string.find(show_command);
-					if (nPos == m_chuankou_string.npos)
-					{
-						//不存在标志符,数据错误
-						m_chuankou_string = "";
-						continue;
-					}
+			//把所有读到的内容,拼接到m_chuankou_string后面,避免有的数据中间截断导致格式混乱
+			m_chuankou_string = a;
 
 
-					//把废数据读出来,不处理,下次重新读16个完整的
-					m_serial.readFromComm(a, nPos, &nReaded);
+			if (a[0] != 0x01 || a[1] != 0x02 || a[13] != 0x03 || a[14] != 0x04)
+			{
+				//说明这16个字节的数据不是完整的,这个时候处理方式是把错误数据全部读完,但是不处理,然后下次接着处理
+				std::string show_command = "\x01\x02";
 
 
+				size_t nPos = m_chuankou_string.find(show_command);
+				if (nPos == m_chuankou_string.npos)
+				{
+					//不存在标志符,数据错误
 					m_chuankou_string = "";
 					m_chuankou_string = "";
 					continue;
 					continue;
 				}
 				}
 
 
-				std::string new_weight = m_chuankou_string.substr(4, 6);
-
-				if (new_weight.at(0) == '0')
-				{
-					new_weight = new_weight.substr(1);
-				}
+				//把废数据读出来,不处理,下次重新读16个完整的
+				m_serial.readFromComm(a, nPos, &nReaded);
 
 
-				if (m_weight != new_weight)
-				{
-					//说明重量有变化了,才更新界面
-					m_weight = new_weight;
-
-					
-				}
+				m_chuankou_string = "";
+				continue;
+			}
 
 
-				if (m_hwnd != NULL)
-				{
-					PostMessage(m_hwnd, WM_CHENGZHONG_SUCCESS, 0, 0);
-				}
+			std::string new_weight = m_chuankou_string.substr(4, 6);
 
 
-				if (m_MainHWND != NULL)
-				{
-					PostMessage(m_MainHWND, WM_CHENGZHONG_SUCCESS, 0, 0);
-				}
-			}
-			else
+			if (new_weight.at(0) == '0')
 			{
 			{
-				Sleep(100);
+				new_weight = new_weight.substr(1);
 			}
 			}
 		}
 		}
 		else
 		else
 		{
 		{
 			//暂时不支持的其他型号
 			//暂时不支持的其他型号
-			Sleep(100);
+			Sleep(200);
+
+			continue;
+		}
+
+		//开始更新重量显示
+		if (m_weight != new_weight)
+		{
+			//说明重量有变化了
+			m_weight = new_weight;
+
+			m_is_wending = false;
+		}
+		else
+		{
+			//重量没有变化了,说明稳定了
+			if (m_is_wending == false)
+			{
+				//说明目前是从不稳定变为稳定,那么这里可以发起AI识别
+				CDiandanAIShibieWorker::GetInstance()->AddAIShibieTask();
+			}
+
+			m_is_wending = true;
+		}
+
+		if (m_hwnd != NULL)
+		{
+			PostMessage(m_hwnd, WM_CHENGZHONG_SUCCESS, 0, 0);
+		}
+
+		if (m_MainHWND != NULL)
+		{
+			PostMessage(m_MainHWND, WM_CHENGZHONG_SUCCESS, 0, 0);
 		}
 		}
 	}
 	}
 }
 }
@@ -246,4 +244,4 @@ void CChengzhongWorker::Qupi()
 	bool ret = m_serial.writeToComm(qupiCmd, sizeof(qupiCmd));
 	bool ret = m_serial.writeToComm(qupiCmd, sizeof(qupiCmd));
 
 
 	int a = 1;
 	int a = 1;
-}
+}

+ 8 - 0
zhipuzi_pos_windows/worker/CChengzhongWorker.h

@@ -45,6 +45,11 @@ public:
 		return m_is_work;
 		return m_is_work;
 	}
 	}
 
 
+	bool GetIsWending()
+	{
+		return m_is_wending;
+	}
+
 	void Zhiling();
 	void Zhiling();
 
 
 	void Qupi();
 	void Qupi();
@@ -67,4 +72,7 @@ private:
 	HWND m_MainHWND = NULL;
 	HWND m_MainHWND = NULL;
 
 
 	CSerialPort m_serial;
 	CSerialPort m_serial;
+
+	//称重金额是否稳定
+	bool m_is_wending = false;
 };
 };

+ 140 - 111
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.cpp

@@ -19,12 +19,12 @@ CDiandanAIShibieWorker::~CDiandanAIShibieWorker()
 //启动工作线程
 //启动工作线程
 void CDiandanAIShibieWorker::StartWork()
 void CDiandanAIShibieWorker::StartWork()
 {
 {
-	long int threadId = GetCurrentThreadId();
-
 	m_is_work = true;
 	m_is_work = true;
 
 
 	//创建一个新线程,专门处理AI识别的结果,避免因为AI识别的结果处理比较慢,导致界面卡顿
 	//创建一个新线程,专门处理AI识别的结果,避免因为AI识别的结果处理比较慢,导致界面卡顿
 	std::thread(&CDiandanAIShibieWorker::HandleDiandanAIShibie, this).detach();
 	std::thread(&CDiandanAIShibieWorker::HandleDiandanAIShibie, this).detach();
+
+	std::thread(&CDiandanAIShibieWorker::HandleDiandanAIShibieQueue, this).detach();
 }
 }
 
 
 //结束工作线程
 //结束工作线程
@@ -33,137 +33,105 @@ void CDiandanAIShibieWorker::StopWork()
 	m_is_work = false;
 	m_is_work = false;
 }
 }
 
 
-void CDiandanAIShibieWorker::HandleDiandanAIShibie()
+void CDiandanAIShibieWorker::DoAIShibie()
 {
 {
-	while (m_is_work == true)
+	try
 	{
 	{
-		try
+		if (m_is_ai_shibie == false)
 		{
 		{
-			if (m_is_ai_shibie == false)
-			{
-				//说明没开启AI识别,就等着
-				if (m_ai_shibie_foodname != "Unknown")
-				{
-					m_ai_shibie_foodname = "Unknown";
-
-					//主线程里面去处理界面刷新
-					if (m_hwnd != NULL)
-					{
-						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-					}
-				}
-
-				Sleep(2000);
-
-				continue;
-			}
-
-			float weight = atof(CChengzhongWorker::GetInstance()->GetWeight().c_str());
-			if (weight < -0.01)
+			//说明没开启AI识别
+			if (m_ai_shibie_foodname != "Unknown")
 			{
 			{
-				//说明没有重量,没放东西到秤上面,那么就不识别
-				if (m_ai_shibie_foodname != "Unknown")
-				{
-					m_ai_shibie_foodname = "Unknown";
-
-					//主线程里面去处理界面刷新
-					if (m_hwnd != NULL)
-					{
-						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-					}
-				}
+				m_ai_shibie_foodname = "Unknown";
 
 
-				Sleep(100);
-
-				continue;
+				//AI识别都没开启,没必要更新界面了,直接返回就好了
 			}
 			}
 
 
-			cv::Mat image;
-			CVideoCaptureWorker::GetInstance()->GetFrame(image);
-			if (image.empty())
-			{
-				//从摄像头获取帧失败
-				if (m_ai_shibie_foodname != "Unknown")
-				{
-					m_ai_shibie_foodname = "Unknown";
-
-					//主线程里面去处理界面刷新
-					if (m_hwnd != NULL)
-					{
-						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-					}
-				}
-
-				Sleep(2000);
-
-				continue;
-			}
+			return;
+		}
 
 
-			m_ai_shibie_foodname = YoloFeatureManager::GetInstance()->Class(image);
+		cv::Mat image;
+		CVideoCaptureWorker::GetInstance()->GetFrame(image);
+		if (image.empty())
+		{
+			//从摄像头获取帧失败
 			if (m_ai_shibie_foodname != "Unknown")
 			if (m_ai_shibie_foodname != "Unknown")
 			{
 			{
-				std::cout << "检测到类别: " << m_ai_shibie_foodname << std::endl;
-
-				m_ai_shibie_foodname = CLewaimaiString::ANSIToUTF8(m_ai_shibie_foodname);
+				m_ai_shibie_foodname = "Unknown";
 
 
 				//主线程里面去处理界面刷新
 				//主线程里面去处理界面刷新
 				if (m_hwnd != NULL)
 				if (m_hwnd != NULL)
 				{
 				{
 					::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 					::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 				}
 				}
+			}
+
+			return;
+		}
+
+		m_ai_shibie_foodname = YoloFeatureManager::GetInstance()->Class(image);
+		if (m_ai_shibie_foodname != "Unknown")
+		{
+			std::cout << "检测到类别: " << m_ai_shibie_foodname << std::endl;
 
 
-				Sleep(30);
-				continue;
+			m_ai_shibie_foodname = CLewaimaiString::ANSIToUTF8(m_ai_shibie_foodname);
+
+			//主线程里面去处理界面刷新
+			if (m_hwnd != NULL)
+			{
+				::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 			}
 			}
-			else
+		}
+		else
+		{
+			//开始调用向量数据库检索
+			if (SQLiteVecManager::GetInstance()->getFeatureCount() > 0)
 			{
 			{
-				//开始调用向量数据库检索
-				if (SQLiteVecManager::GetInstance()->getFeatureCount() > 0)
-				{
-					std::vector<float> feature_vector = YoloFeatureManager::GetInstance()->extractFeatures(image);
-					std::vector<FeatureRecord> searchResults = SQLiteVecManager::GetInstance()->searchSimilarVectors(feature_vector, 5);
+				std::vector<float> feature_vector = YoloFeatureManager::GetInstance()->extractFeatures(image);
+				std::vector<FeatureRecord> searchResults = SQLiteVecManager::GetInstance()->searchSimilarVectors(feature_vector, 5);
 
 
-					if (!searchResults.empty())
+				if (!searchResults.empty())
+				{
+					std::cout << "向量数据库检索结果:" << std::endl;
+					for (const auto& result : searchResults)
 					{
 					{
-						std::cout << "向量数据库检索结果:" << std::endl;
-						for (const auto& result : searchResults)
-						{
-							std::string food_id = result.foodId;
-							std::string food_name = result.foodName;
-							std::string image_name = result.imageName;
-							std::string image_path = result.imagePath;
-							float similarity = result.similarity;
+						std::string food_id = result.foodId;
+						std::string food_name = result.foodName;
+						std::string image_name = result.imageName;
+						std::string image_path = result.imagePath;
+						float similarity = result.similarity;
 
 
-							std::cout << "食品ID: " << food_id << ", 食品名称: " << food_name << ", 图片名称: " << image_name << ", 图片路径: " << image_path << ", 相似度: " << similarity << std::endl;
+						std::cout << "食品ID: " << food_id << ", 食品名称: " << food_name << ", 图片名称: " << image_name << ", 图片路径: " << image_path << ", 相似度: " << similarity << std::endl;
 
 
-							CSqlite3 sqlite;
+						CSqlite3 sqlite;
 
 
-							CFood newFood;
-							bool ret = sqlite.GetFoodById(food_id, newFood);
-							if (!ret)
-							{
-								std::cout << "该相似的商品已被删除" << std::endl;
-								Sleep(100);
+						CFood newFood;
+						bool ret = sqlite.GetFoodById(food_id, newFood);
+						if (!ret)
+						{
+							std::cout << "该相似的商品已被删除" << std::endl;
 
 
-								continue;
-							}
+							//这个商品都被删除了,说明这个商品对应的图片也不应该在向量数据库里了,所以把这个图片对应的向量也删除掉
+							SQLiteVecManager::GetInstance()->DeleteFeatureVectorByImageName(image_name);
 
 
-							//UTF8格式,sqlite里面存的都是UTF8格式的字符串
-							m_ai_shibie_foodname = newFood.name;
+							continue;
+						}
 
 
-							//主线程里面去处理界面刷新
-							if (m_hwnd != NULL)
-							{
-								::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
-							}
+						//UTF8格式,sqlite里面存的都是UTF8格式的字符串
+						m_ai_shibie_foodname = newFood.name;
 
 
-							Sleep(30);
-							continue;
+						//主线程里面去处理界面刷新
+						if (m_hwnd != NULL)
+						{
+							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 						}
 						}
+
+						return;
 					}
 					}
-					else
+
+					//代码走到这里来,说明虽然向量数据库里有相似的特征,但是这些特征对应的商品都被删除了,所以最终的结果也是没有识别出来的					
+					if (m_ai_shibie_foodname != "Unknown")
 					{
 					{
-						//向量数据库中没有相似的特征						
 						m_ai_shibie_foodname = "Unknown";
 						m_ai_shibie_foodname = "Unknown";
 
 
 						//主线程里面去处理界面刷新
 						//主线程里面去处理界面刷新
@@ -171,13 +139,32 @@ void CDiandanAIShibieWorker::HandleDiandanAIShibie()
 						{
 						{
 							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 						}
 						}
-
-						Sleep(100);
 					}
 					}
+
+					return;
 				}
 				}
 				else
 				else
 				{
 				{
-					//向量数据库中没有任何特征					
+					//向量数据库中没有相似的特征						
+					if (m_ai_shibie_foodname != "Unknown")
+					{
+						m_ai_shibie_foodname = "Unknown";
+
+						//主线程里面去处理界面刷新
+						if (m_hwnd != NULL)
+						{
+							::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
+						}
+					}
+
+					return;
+				}
+			}
+			else
+			{
+				//向量数据库中没有任何特征	
+				if (m_ai_shibie_foodname != "Unknown")
+				{
 					m_ai_shibie_foodname = "Unknown";
 					m_ai_shibie_foodname = "Unknown";
 
 
 					//主线程里面去处理界面刷新
 					//主线程里面去处理界面刷新
@@ -185,17 +172,59 @@ void CDiandanAIShibieWorker::HandleDiandanAIShibie()
 					{
 					{
 						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 						::PostMessage(m_hwnd, WM_AI_RECOGNITION_SUCCESS, 0, 0);
 					}
 					}
-
-					Sleep(100);
 				}
 				}
+
+				return;
 			}
 			}
 		}
 		}
-		catch (const std::exception& e)
+	}
+	catch (const std::exception& e)
+	{
+		std::string aa = std::string(e.what());
+		DEBUG_LOG(("AI识别失败: " + std::string(e.what())).c_str());
+	}
+}
+
+void CDiandanAIShibieWorker::HandleDiandanAIShibie()
+{
+	while (m_is_work == true)
+	{
+		if (m_is_ai_shibie == false)
 		{
 		{
-			std::string aa = std::string(e.what());
-			DEBUG_LOG(("提取特征失败: " + std::string(e.what())).c_str());
+			Sleep(1000);
 			continue;
 			continue;
-		}	
+		}
+
+		//暂时不做循环识别模式
+		//this->DoAIShibie();
+
+		Sleep(100);
+	}
+
+	//走到这里说明线程要退出了,做一些清理工作
+	CAppEnv::GetInstance()->DelWorkerNum();
+}
+
+void CDiandanAIShibieWorker::HandleDiandanAIShibieQueue()
+{
+	while (m_is_work == true)
+	{
+		m_mutex.lock();
+
+		if (!m_queue_ai_shibie.empty())
+		{
+			m_queue_ai_shibie.pop();
+
+			m_mutex.unlock();
+
+			this->DoAIShibie();
+		}
+		else
+		{
+			m_mutex.unlock();
+
+			Sleep(200);
+		}
 	}
 	}
 
 
 	//走到这里说明线程要退出了,做一些清理工作
 	//走到这里说明线程要退出了,做一些清理工作

+ 17 - 3
zhipuzi_pos_windows/worker/CDiandanAIShibieWorker.h

@@ -42,18 +42,32 @@ public:
 		m_is_ai_shibie = false;
 		m_is_ai_shibie = false;
 	}
 	}
 
 
+	void AddAIShibieTask()
+	{
+		std::lock_guard<std::mutex> lock(m_mutex);
+		m_queue_ai_shibie.push(1);
+	}
+
+	//执行一次AI识别,包括从摄像头获取一帧,进行AI识别,调用界面刷新等一系列操作
+	void DoAIShibie();
+
 private:
 private:
+	//这个是循环进行AI识别
 	void HandleDiandanAIShibie();
 	void HandleDiandanAIShibie();
 
 
+	//这个是接到识别任务才进行识别,识别完了就不继续识别了
+	void HandleDiandanAIShibieQueue();
+
 private:
 private:
 	bool m_is_work = false;
 	bool m_is_work = false;
 
 
-	std::mutex m_worker_mutex;
-
 	bool m_is_ai_shibie = false;
 	bool m_is_ai_shibie = false;
 
 
 	std::string m_ai_shibie_foodname;
 	std::string m_ai_shibie_foodname;
 
 
 	HWND m_hwnd = NULL;
 	HWND m_hwnd = NULL;
-};
 
 
+	std::mutex m_mutex;
+
+	std::queue<int> m_queue_ai_shibie;
+};