diff --git a/app/api/api.py b/app/api/api.py index 089e802..703bef7 100644 --- a/app/api/api.py +++ b/app/api/api.py @@ -7,6 +7,8 @@ import datetime import os import sys from utils.utils import send_notifycation +import collections +from utils.utils import doNotMove,mouseClick def getFile(ruleFile): if getattr(sys, 'frozen', False): @@ -25,6 +27,10 @@ def get_settings_status_name(data, settings,setting_name): # 使用 filter() 和 map() 函数提取信息 names = list(map(lambda x: x["name"], filter(lambda x: x["status"], setting["status"]))) return names[0] +def get_settings_status_root(data, settings): + # 访问指定 "setting" 的信息 + names = list(map(lambda x: x["name"], filter(lambda x: x["status"], data[settings]))) + return names[0] def get_setting_status(data, settings,setting_name): # 使用 filter() 和 map() 函数提取信息 status = list(map(lambda x: x["status"], filter(lambda x: x["name"] == setting_name, data[settings]))) @@ -82,6 +88,30 @@ def getModelSetting(args): model["status"] = False args["ModelSetting"][0]["status"] = model_dict return args +def checkAction(queue,type,action,tip): + print(type,action,queue[2]["time"]-queue[0]["time"]) + # 输入一个长度为3的队列,根据情况判断是否执行动作 + if(queue[0]["status"]==0 and queue[1]["status"]==1 and queue[2]["status"]==0 and type=="张开持续1S" and (queue[2]["time"]-queue[0]["time"])>1): + if(action=="悬停鼠标"): + doNotMove() + if(tip): + send_notifycation("触发悬停鼠标","EMC") + elif(action=="单击按钮"): + mouseClick() + if(tip): + send_notifycation("触发单击按钮","EMC") + return True + elif(queue[0]["status"]==1 and queue[1]["status"]==0 and queue[2]["status"]==1 and type=="闭上持续1S" and (queue[2]["time"]-queue[0]["time"])>1): + if(action=="悬停鼠标"): + doNotMove() + if(tip): + send_notifycation("触发悬停鼠标","EMC") + elif(action=="单击按钮"): + mouseClick() + if(tip): + send_notifycation("触发单击按钮","EMC") + return True + return False class API: '''本地API,供前端JS调用''' @@ -89,6 +119,8 @@ class API: net = None cap = None args = None + # 状态队列 + queue = None def __init__(self): @@ -108,9 +140,55 @@ class API: # cv2.namedWindow('Video Cam', cv2.WINDOW_NORMAL) if(self.args['toggle'] and self.args['tip']): - send_notifycation("功能触发:鼠标悬停","EMC[嘴控]") + send_notifycation("EMC程序已启动","EMC") + + self.queue = collections.deque(maxlen=3) + + def detectThreading(self): + if self.args['toggle']==False: + pass + result = get_photo_detect(self.cap,self.net) + eye = -1 + mouth = -1 + for i in result: + if i["classid"] == "closed_eye": + eye = 0 + elif i["classid"] == "open_eye": + eye = 1 + elif i["classid"] == "closed_mouth": + mouth = 0 + elif i["classid"] == "open_mouth": + mouth = 1 + + + status = -1 + + if get_settings_status_root(self.args,"control") == "嘴控": + if(mouth==0): + status = 0 + elif(mouth==1): + status = 1 + elif get_settings_status_root(self.args,"control") == "眼控": + if(eye==0): + status = 0 + elif(eye==1): + status = 1 + elif get_settings_status_root(self.args,"control") == "嘴/眼控": + if(mouth==0 or eye==0): + status = 0 + elif(mouth==1 or eye==1): + status = 1 + + if(status!=-1): + if(len(self.queue)<3 or status!=self.queue[-1]["status"]): + self.queue.append({"status":status,"time":time.time()}) + if(len(self.queue)==3): + if(checkAction(self.queue,get_settings_status_name(self.args,"ControlSetting","控制设置"),get_settings_status_name(self.args,"ControlSetting","控制功能"),self.args['tip'])): + self.queue.clear()#执行动作则清空队列 + else: + self.queue[-1]["time"]=time.time() + print(self.queue) - def getPrimaryImg(self,type="不裁剪"): # 三种处理图片的方式:不裁剪、居中裁剪成224*224、居中裁剪成320*320。 diff --git a/app/api/config.json b/app/api/config.json index b9fade8..6703317 100644 --- a/app/api/config.json +++ b/app/api/config.json @@ -7,11 +7,11 @@ "control": [ { "name": "嘴控", - "status": false + "status": true }, { "name": "眼控", - "status": true + "status": false }, { "name": "嘴/眼控", @@ -23,19 +23,11 @@ "name": "控制设置", "status": [ { - "name": "开/关/开", - "status": false - }, - { - "name": "关/开/关", - "status": false - }, - { - "name": "闭上持续2S", + "name": "闭上持续1S", "status": false }, { - "name": "张开持续2S", + "name": "张开持续1S", "status": true } ], diff --git a/app/config/config.py b/app/config/config.py index e4d624b..ddd6dae 100644 --- a/app/config/config.py +++ b/app/config/config.py @@ -5,6 +5,6 @@ class Config: '''配置文件''' appName = 'EMC' # 应用名称 - appVersion = "1.0.0" # 应用版本号 + appVersion = "1.1.0" # 应用版本号 appSystem = platform.system() # 本机系统类型 diff --git a/app/main.py b/app/main.py index 3a0aa04..15957c2 100644 --- a/app/main.py +++ b/app/main.py @@ -7,6 +7,16 @@ from api.api import API from config.config import Config from utils.utils import send_notifycation +from pystray import MenuItem as item +import pystray +from PIL import Image +import threading +import time + + + + + # 前端页面目录 if sys.flags.dev_mode: MAIN_DIR = os.path.join("..", "dist") # 开发环境 @@ -19,14 +29,36 @@ else: def WebViewApp(port,dev=False): api = API() # 本地接口 cfg = Config() # 配置文件 - if(dev): - window = webview.create_window(cfg.appName, 'http://localhost:'+str(port)+'/',js_api=api) - webview.start(debug=True, http_server=True) # 启动窗口 - else: - template = os.path.join(MAIN_DIR, "index.html") # 设置页面,可以指向远程或本地 - window = webview.create_window(title=cfg.appName, url=template, js_api=api) # 创建窗口 - api.window=window # 本地接口 - webview.start(debug=DEBUG, http_server=True) # 启动窗口 + def detect(): + api.detectThreading() + global timer + timer = threading.Timer(0.25, detect) # 在回调函数中再次启动定时器 + timer.start() # 启动定时器 + def exitProgram(): + icon.stop() + print("exitProgram") + global timer + timer.cancel() + def action(): + global timer + timer.cancel() + icon.stop() + # icon.visible = False + if(dev): + window = webview.create_window(cfg.appName, 'http://localhost:'+str(port)+'/',js_api=api) + webview.start(debug=True, http_server=True) # 启动窗口 + else: + template = os.path.join(MAIN_DIR, "index.html") # 设置页面,可以指向远程或本地 + window = webview.create_window(title=cfg.appName, url=template, js_api=api) # 创建窗口 + api.window=window # 本地接口 + webview.start(debug=DEBUG, http_server=True) # 启动窗口 + timer = threading.Timer(0.25, detect) # 在回调函数中再次启动定时器 + timer.start() # 启动定时器 + image = Image.open("C:/Users/16775/Pictures/head.jpg") + menu = (item('打开主页面', action), item('退出', exitProgram)) + icon = pystray.Icon("name", image, "title", menu) + icon.run() + if __name__ == "__main__": diff --git a/app/utils/utils.py b/app/utils/utils.py index a84e110..65e4e72 100644 --- a/app/utils/utils.py +++ b/app/utils/utils.py @@ -1,5 +1,8 @@ import subprocess import os,sys +import pyautogui as pg #没别的作用就单纯换个名字 +import threading + def getFile(ruleFile): if getattr(sys, 'frozen', False): absPath = os.path.dirname(os.path.abspath(sys.executable)) @@ -38,3 +41,20 @@ def send_notifycation (content: str = '', title: str = 'New notifycation', "".join([d.get(c, c) for c in (s)]) % ( content, title, tip_type, duration)) ]) + +mouseX = False +def doNotMove(): + global mouseX + mouseX = (mouseX==False) #取反 + x,y=pg.position() #核心函数pg.position() + def mouseMove(): + pg.moveTo(x,y) + if(mouseX): + global timer + timer = threading.Timer(0.05, mouseMove) # 设定定时器,每 5 秒执行一次 periodic_function + timer.start() # 启动定时器 + timer = threading.Timer(0.05, mouseMove) # 设定定时器,每 5 秒执行一次 periodic_function + timer.start() # 启动定时器 + +def mouseClick(): + pg.click()