From a75775c869997d6ac32bd73c38069fffb44cce82 Mon Sep 17 00:00:00 2001 From: gitea Date: Tue, 25 Jun 2024 21:40:27 +0800 Subject: [PATCH] =?UTF-8?q?v0.1.7.0(2024/06/25)-=E6=9C=AA=E5=8F=91?= =?UTF-8?q?=E5=B8=83=201.=20[aio.py]=20=E5=8F=96=E6=B6=88=E4=BA=86?= =?UTF-8?q?=E5=9C=A8=E6=9C=AC=E6=96=87=E4=BB=B6=E4=B8=AD=E5=BC=80=E5=90=AF?= =?UTF-8?q?openapi=E7=BA=BF=E7=A8=8B=E7=9A=84=E5=81=9A=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E6=94=B9=E5=A6=82=E4=B8=8B=EF=BC=9A=20=09-?= =?UTF-8?q?=20=E9=80=9A=E8=BF=87=E5=8C=85=E7=9A=84=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=85=B6=E4=BB=96=E6=A8=A1=E5=9D=97=20=20=20?= =?UTF-8?q?=20=20-=20=E4=BD=BF=E7=94=A8current=5Fpath=E6=9D=A5=E8=A7=84?= =?UTF-8?q?=E9=81=BF=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20=20=20=20=20-=20=E5=A3=B0=E5=90=8D=E4=BA=86=20self.hr=20?= =?UTF-8?q?=E5=8F=98=E9=87=8F=EF=BC=8C=E7=94=A8=E6=9D=A5=E6=8E=A5=E6=94=B6?= =?UTF-8?q?openapi=E7=9A=84=E5=AE=9E=E4=BE=8B=E5=8C=96=20=20=20=20=20-=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E5=AF=B9=E4=BA=8Esegment=20button?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF=E8=B0=83=E7=94=A8=20=20=20=20=20-?= =?UTF-8?q?=20=E8=AE=BE=E5=AE=9Aprogress=20bar=E7=9A=84=E9=95=BF=E5=BA=A6?= =?UTF-8?q?=E6=98=AF10=20=20=20=20=20-=20=E5=AE=8C=E5=96=84=E4=BA=86segmen?= =?UTF-8?q?ted=5Fbutton=5Fcallback=E5=87=BD=E6=95=B0=20=20=20=20=20-=20?= =?UTF-8?q?=E5=9C=A8detect=5Fnetwork=E5=87=BD=E6=95=B0=E4=B8=AD=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0heartbeat=E5=88=9D=E5=A7=8B=E5=8C=96=20=20=20=20=20-?= =?UTF-8?q?=20tabview=5Fclick=E5=87=BD=E6=95=B0=E4=B8=AD=E6=96=B0=E5=A2=9E?= =?UTF-8?q?textbox=E6=B8=85=E5=B1=8F=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E5=AE=9E=E4=BE=8B=E5=8C=96openapi=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E5=81=9A=E6=A3=80=E6=B5=8B=202.=20[openapi.py]=20=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E4=BA=86=E5=88=9D=E5=A7=8B=E5=8C=96=E4=B8=AD=E6=97=A0?= =?UTF-8?q?=E9=99=90=E5=BE=AA=E7=8E=AF=E6=A3=80=E6=B5=8B=EF=BC=8C=E5=9B=A0?= =?UTF-8?q?=E4=B8=BA=E9=98=BB=E5=A1=9E=E4=BA=86aio=E4=B8=BB=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E8=BF=9B=E7=A8=8B=EF=BC=81=EF=BC=81=EF=BC=81socket?= =?UTF-8?q?=E4=B9=9F=E6=97=A0=E6=B3=95=E5=A4=9A=E6=AC=A1=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=EF=BC=81=EF=BC=81=EF=BC=81=E6=B5=AA=E8=B4=B9=E4=BA=86=E5=A5=BD?= =?UTF-8?q?=E5=A4=9A=E6=97=B6=E9=97=B4=EF=BC=81=EF=BC=81=EF=BC=81=E5=BE=88?= =?UTF-8?q?=E7=94=9F=E6=B0=94=EF=BC=81=EF=BC=81=EF=BC=81=EF=BC=81=20=09-?= =?UTF-8?q?=20=E9=80=9A=E8=BF=87tabview=E5=88=87=E6=8D=A2=E6=9D=A5?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=87=8D=E6=96=B0=E8=BF=9E=E6=8E=A5=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=BF=9D=E7=95=99=E4=BA=86=E5=BC=82=E5=B8=B8=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=83=A8=E5=88=86=20=20=20=20=20-=20=E5=B0=86?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=9A=84=20=5F=5Fxxxx=20=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E9=83=BD=E6=9B=BF=E6=8D=A2=E6=88=90=20xxxx=20=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E5=8E=BB=E6=8E=89=E4=BA=86=20=5F=5F=20=20=20?= =?UTF-8?q?=20=20-=20=E4=BD=BF=E7=94=A8current=5Fpath=E6=9D=A5=E8=A7=84?= =?UTF-8?q?=E9=81=BF=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=203.=20[do=5Fbrake.py]=20=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E4=BA=86=E6=9C=BA=E5=99=A8=E7=8A=B6=E6=80=81=E6=94=B6=E9=9B=86?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C=E8=BF=98=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=AE=8C=E5=96=84=20=20=20=20=20-=20=E4=BD=BF=E7=94=A8current?= =?UTF-8?q?=5Fpath=E6=9D=A5=E8=A7=84=E9=81=BF=E6=96=87=E4=BB=B6=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=97=AE=E9=A2=98=20=20=20=20=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9Evalidate=5Fresp=E5=87=BD=E6=95=B0=EF=BC=8C=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=E6=95=B0=E6=8D=AE=20=20=20=20=20-=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E4=BA=86=E8=B0=83=E7=94=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio/README.md | 47 ++++++++--- aio/assets/templates/heartbeat | 2 +- aio/code/__init__.py | 1 + aio/code/aio.py | 94 +++++++++++++--------- aio/code/automatic_test/__init__.py | 1 + aio/code/automatic_test/do_brake.py | 69 +++++++++++++--- aio/code/automatic_test/openapi.py | 119 +++++++++++++--------------- aio/code/data_process/__init__.py | 1 + 8 files changed, 212 insertions(+), 122 deletions(-) create mode 100644 aio/code/__init__.py create mode 100644 aio/code/automatic_test/__init__.py create mode 100644 aio/code/data_process/__init__.py diff --git a/aio/README.md b/aio/README.md index 7954e1a..fa65a1e 100644 --- a/aio/README.md +++ b/aio/README.md @@ -246,24 +246,49 @@ v0.1.6.3(2024/06/18) > !!WARNING:目前版本的电机电流程序还支持DriverMaster采集的数据处理,等明确后,将不再支持,也即所有的电机电流数据(工业+协作),都是用诊断曲线来采集 -v0.1.7.0(2024/06/29) +v0.1.7.0(2024/06/19)-未发布 1. [openapi.py] 初步搭建起框架,完成了新老协议的封包/解包/异步采集日志的操作(未充分测试,但基本无问题) 2. [openapi.py] 修改了封包的规则,使之更加明晰,封包操作没有实现分包功能,目前看实际场景用不到 -3. [openapi.py] 定义 MAX_FRAME_SIZE 常量(1024),替换socket接收以及响应数据处理相关部分 -4. [openapi.py] 使用 int.to_bytes 和 int.from_bytes 替换 binascii 模块的功能 -5. [aio.py] 修改了Data Process中初始化的动作,使得初始化时的状态统一成程序刚启动时的样子 -6. [aio.py] 增加了tabview的点击行为函数,每次点击tab都会初始化 -7. [aio.py] 增加了Automatic Test界面元素,包括如下,并完成了功能框架的搭建 + +v0.1.7.0(2024/06/21)-未发布 +1. [openapi.py] 定义 MAX_FRAME_SIZE 常量(1024),替换socket接收以及响应数据处理相关部分 +2. [openapi.py] 使用 int.to_bytes 和 int.from_bytes 替换 binascii 模块的功能 +3. [aio.py] 修改了Data Process中初始化的动作,使得初始化时的状态统一成程序刚启动时的样子 + +v0.1.7.0(2024/06/23)-未发布 +1. [aio.py] 增加了tabview的点击行为函数,每次点击tab都会初始化 +2. [aio.py] 增加了Automatic Test界面元素,包括如下,并完成了功能框架的搭建 - 标签:文件/角速度/减速比 - 按钮:急停及恢复 - 输入框:文件路径/角速度/减速比 - OptionMenu:负载 - 进度条 -8. [openapi.py] 增加心跳检测函数,并开启线程执行;取消在该文件中生成实例 -9. [aio.py] 完成detect_network,并在main函数开启线程 -10. 将templates文件夹移动到assets内 -11. [openapi.py] 建联部分做容错逻辑,并将读写文件做自适应处理 -12. [aio.py] 将读写文件做自适应处理,引入openapi模块并生成实例,做心跳检测,将socket超时时间修改为3s +3. [openapi.py] 增加心跳检测函数,并开启线程执行;取消在该文件中生成实例 +4. [aio.py] 完成detect_network,并在main函数开启线程 +5. 将templates文件夹移动到assets内 + +v0.1.7.0(2024/06/24)-未发布 +1. [openapi.py] 建联部分做容错逻辑,并将读写文件做自适应处理 +2. [aio.py] 将读写文件做自适应处理,引入openapi模块并生成实例,做心跳检测,将socket超时时间修改为3s + +v0.1.7.0(2024/06/25)-未发布 +1. [aio.py] 取消了在本文件中开启openapi线程的做法,并修改如下: + - 通过包的方式导入其他模块 + - 使用current_path来规避文件路径问题 + - 声名了 self.hr 变量,用来接收openapi的实例化 + - 修改了对于segment button的错误调用 + - 设定progress bar的长度是10 + - 完善了segmented_button_callback函数 + - 在detect_network函数中增加heartbeat初始化 + - tabview_click函数中新增textbox清屏功能,以及实例化openapi,并做检测 +2. [openapi.py] 取消了初始化中无限循环检测,因为阻塞了aio主界面进程!!!socket也无法多次连接!!!浪费了好多时间!!!很生气!!!! + - 通过tabview切换来实现重新连接,并保留了异常处理部分 + - 将所有的 __xxxx 函数都替换成 xxxx 函数,去掉了 __ + - 使用current_path来规避文件路径问题 +3. [do_brake.py] 初步完成了机器状态收集的功能,还需要完善 + - 使用current_path来规避文件路径问题 + - 新增validate_resp函数,校验数据 + - 完善了调用接口 > **关于HMI接口** > - 封包解包顺序:帧长度二字节/包长度四字节/协议二字节/预留二字节,\x04\x00:\x00\x00\tR:\x02:\x00 diff --git a/aio/assets/templates/heartbeat b/aio/assets/templates/heartbeat index c227083..56a6051 100644 --- a/aio/assets/templates/heartbeat +++ b/aio/assets/templates/heartbeat @@ -1 +1 @@ -0 \ No newline at end of file +1 \ No newline at end of file diff --git a/aio/code/__init__.py b/aio/code/__init__.py new file mode 100644 index 0000000..e6e51aa --- /dev/null +++ b/aio/code/__init__.py @@ -0,0 +1 @@ +__all__ = ['automatic_test', 'data_process'] \ No newline at end of file diff --git a/aio/code/aio.py b/aio/code/aio.py index 0951ac3..6d05882 100644 --- a/aio/code/aio.py +++ b/aio/code/aio.py @@ -1,3 +1,4 @@ +import sys import tkinter from os.path import exists, dirname from os import getcwd @@ -7,12 +8,10 @@ import customtkinter from time import time, strftime, localtime, sleep from urllib.request import urlopen from socket import setdefaulttimeout -import data_process.brake as brake -import data_process.current as current -import data_process.iso as iso -import data_process.wavelogger as wavelogger -import automatic_test.openapi as openapi +from data_process import * +from automatic_test import * +current_path = dirname(__file__) customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light" customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue" customtkinter.set_widget_scaling(1.1) # widget dimensions and text size @@ -73,6 +72,7 @@ class App(customtkinter.CTk): super().__init__() self.my_font = customtkinter.CTkFont(family="Consolas", size=16, weight="bold") self.w_param = 84 + self.hr = None # ===================================================================== # configure window self.title("AIO - All in one automatic toolbox") @@ -142,7 +142,7 @@ class App(customtkinter.CTk): # For data process tab END ===================================================================== # For automatic test tab START ===================================================================== # create buttons - self.seg_button = customtkinter.CTkSegmentedButton(self.tabview.tab('Automatic Test'), font=self.my_font, command=lambda value='机器状态': self.thread_it(self.segmented_button_callback())) + self.seg_button = customtkinter.CTkSegmentedButton(self.tabview.tab('Automatic Test'), font=self.my_font, command=lambda value='机器状态': self.thread_it(self.segmented_button_callback)) self.seg_button.grid(row=1, column=2, columnspan=12, padx=(20, 10), pady=(10, 10), sticky="ew") self.seg_button.configure(values=["无效功能", "触发急停", "停止运动", "继续运动", "零点位姿", "机器状态", "告警信息"]) self.seg_button.set("无效功能") @@ -150,7 +150,7 @@ class App(customtkinter.CTk): # create progress bar self.progressbar = customtkinter.CTkProgressBar(self.tabview.tab('Automatic Test')) self.progressbar.grid(row=5, column=1, padx=5, pady=5, sticky="ew") - self.progressbar.configure(mode="determinnate") + self.progressbar.configure(mode="determinnate", width=10) self.progressbar.start() # create widgits_at for widgit in widgits_at: @@ -189,44 +189,70 @@ class App(customtkinter.CTk): tkinter.messagebox.showwarning(title="版本更新", message="连接服务器失败,无法确认当前是否是最新版本......") # functions below ↓ ---------------------------------------------------------------------------------------- - def segmented_button_callback(self): - value = self.seg_button.get() - print(f"segment button is triggered: {value}") - match value: - case '触发急停': - pass - case '停止运动': - pass - case '继续运动': - pass - case '零点位姿': - pass - case '机器状态': - pass - case '告警信息': - pass - - def detect_network(self): - current_path = dirname(__file__) - while True: - with open(f'{current_path}/../assets/templates/heartbeat', 'r', encoding='utf-8') as f_h: - pb_color = 'green' if f_h.read().strip() == '1' else 'red' - self.progressbar.configure(progress_color=pb_color) - sleep(3) - def thread_it(self, func, *args): """ 将函数打包进线程 """ self.myThread = Thread(target=func, args=args) self.myThread.daemon = True # 主线程退出就直接让子线程跟随退出,不论是否运行完成。 self.myThread.start() + def segmented_button_callback(self): + value = self.seg_button.get() + self.textbox.configure(state='normal') + + match value: + case '触发急停': + self.textbox.delete(index1='1.0', index2='end') + self.write2textbox(f"segment button is triggered: {value}") + case '停止运动': + self.textbox.delete(index1='1.0', index2='end') + self.write2textbox(f"segment button is triggered: {value}") + case '继续运动': + self.textbox.delete(index1='1.0', index2='end') + self.write2textbox(f"segment button is triggered: {value}") + case '零点位姿': + self.textbox.delete(index1='1.0', index2='end') + self.write2textbox(f"segment button is triggered: {value}") + case '机器状态': + self.textbox.configure(state='normal') + self.textbox.delete(index1='1.0', index2='end') + with open(f'{current_path}/../assets/templates/heartbeat', 'r', encoding='utf-8') as f_h: + connection_state = f_h.read().strip() + + if connection_state == '0': + self.write2textbox("无法连接机器人,检查是否已经使用Robot Assist软件连接机器,重试中...") + else: + do_brake.main(self.hr, 'get_state', self.write2textbox) + + case '告警信息': + self.textbox.delete(index1='1.0', index2='end') + self.write2textbox(f"segment button is triggered: {value}") + + self.textbox.configure(state='disable') + + def detect_network(self): + with open(f"{current_path}/../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: + f_h.write('0') + while True: + with open(f'{current_path}/../assets/templates/heartbeat', 'r', encoding='utf-8') as f_h: + pb_color = 'green' if f_h.read().strip() == '1' else 'red' + self.progressbar.configure(progress_color=pb_color) + sleep(3) + def tabview_click(self): self.initialization() + self.textbox.configure(state='normal') + self.textbox.delete(index1='1.0', index2='end') + self.textbox.configure(state='disabled') + tab_name = self.tabview.get() if tab_name == 'Data Process': self.menu_main_dp.set("Start Here!") elif tab_name == 'Automatic Test': self.menu_main_at.set("Start Here!") + with open(f"{current_path}/../assets/templates/heartbeat", "r", encoding='utf-8') as f_h: + connection_state = f_h.read().strip() + if connection_state == '0' or self.hr is None: + self.hr = openapi.HmiRequest() def initialization(self): tab_name = self.tabview.get() @@ -492,10 +518,6 @@ class App(customtkinter.CTk): if __name__ == "__main__": - t_hr = Thread(target=openapi.HmiRequest) - t_hr.daemon = True - t_hr.start() - aio = App() aio.net_detect = Thread(target=aio.detect_network) aio.net_detect.daemon = True diff --git a/aio/code/automatic_test/__init__.py b/aio/code/automatic_test/__init__.py new file mode 100644 index 0000000..24a4de0 --- /dev/null +++ b/aio/code/automatic_test/__init__.py @@ -0,0 +1 @@ +__all__ = ['openapi', 'do_brake'] \ No newline at end of file diff --git a/aio/code/automatic_test/do_brake.py b/aio/code/automatic_test/do_brake.py index 854fe7d..aecb565 100644 --- a/aio/code/automatic_test/do_brake.py +++ b/aio/code/automatic_test/do_brake.py @@ -1,6 +1,61 @@ -import openapi +import json +from os.path import dirname +from sys import argv + +current_path = dirname(__file__) + + +def validate_resp(_id, response, w2t): + match _id: + case 'DATA ERR': + w2t(f"数据处理错误,需要确认", 0, 4, 'red') + case 'DATA READ ERR': + w2t(f"无法读取数据,需要确认", 0, 3, 'red') + case 'NOT SUPPORT': + w2t(f"不支持的功能,需要确认", 0, 2, 'red') + if not response: + w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red') + + +def get_state(hr, w2t): + # 获取机器状态 + _id = hr.excution('state.get_state') + _msg = hr.get_from_id(_id) + if not _msg: + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') + else: + _response = json.loads(_msg)['data'] + validate_resp(_id, _response, w2t) + + stat_desc = {'engine': '上电状态', 'operate': '操作模式', 'rc_state': '控制器状态', 'robot_action': '机器人动作', 'safety_mode': '安全模式', 'servo_mode': '伺服工作模式', 'task_space': '工作任务空间'} + for component, state in _response.items(): + w2t(f"{stat_desc[component]}: {state}") + + _id = hr.excution('device.get_params') + _msg = hr.get_from_id(_id) + if not _msg: + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') + else: + _response = json.loads(_msg)['data']['devices'] + validate_resp(_id, _response, w2t) + dev_desc = {0: '伺服版本', 1: '伺服参数', 2: '安全板固件', 3: '控制器', 4: '通讯总线', 5: '解释器', 6: '运动控制', 8: '力控版本', 9: '末端固件', 10: '机型文件', 11: '环境包'} + dev_vers = {} + for device in _response: + dev_vers[device['type']] = device['version'] + for i in sorted(dev_desc.keys()): + w2t(f"{dev_desc[i]}: {dev_vers[i]}") + + +def main(hr, func, w2t): + # func: get_state/ + match func: + case 'get_state': + get_state(hr, w2t) + + +if __name__ == '__main__': + main(*argv[1:]) -hr = openapi.HmiRequest() # 一、设置/检测机器人状态: # 1. 上电 @@ -19,13 +74,3 @@ hr = openapi.HmiRequest() # 四 - -# _id = hr.excution("state.get_state") -# print(hr.get_from_id(_id)) -# _id = hr.excution('state.set_tp_mode', tp_mode='without') -# print(hr.get_from_id(_id)) - -_id = hr.excution('device.get_params') -print(hr.get_from_id(_id)) -# _id = hr.excution('state.switch_manual') -# print(hr.get_from_id(_id)) diff --git a/aio/code/automatic_test/openapi.py b/aio/code/automatic_test/openapi.py index 7ca1b25..51fe979 100644 --- a/aio/code/automatic_test/openapi.py +++ b/aio/code/automatic_test/openapi.py @@ -3,52 +3,51 @@ import socket import threading import selectors import time -import os +from os.path import dirname MAX_FRAME_SIZE = 1024 socket.setdefaulttimeout(3) +current_path = dirname(__file__) class HmiRequest(object): def __init__(self): super().__init__() - while True: - try: - self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # self.c.connect(('192.168.0.160', 5050)) - self.c.connect(('192.168.84.129', 5050)) - self.c.setblocking(False) - self.c_msg = [] - self.c_xs = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # self.c_xs.connect(('192.168.0.160', 6666)) - self.c_xs.connect(('192.168.84.129', 6666)) - self.c_xs.setblocking(False) - self.c_msg_xs = [] - break - except Exception as Err: - current_path = os.path.dirname(__file__) - with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: - f_h.write('0') + try: + self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c.connect(('192.168.0.160', 5050)) + # self.c.connect(('192.168.84.129', 5050)) + self.c.setblocking(False) + self.c_xs = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c_xs.connect(('192.168.0.160', 6666)) + # self.c_xs.connect(('192.168.84.129', 6666)) + self.c_xs.setblocking(False) + with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: + f_h.write('1') + except Exception as Err: + with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: + f_h.write('0') + print("Connection failed, please try to re-connect via switching tabs...") - print("Connection failed, will try again after 2 seconds...") - time.sleep(2) - - self.t_heartbeat = threading.Thread(target=self.__heartbeat) - self.t_heartbeat.daemon = True - self.t_heartbeat.start() - self.t_unpackage = threading.Thread(target=self.__unpackage, args=(self.c, )) - self.t_unpackage.daemon = True - self.t_unpackage.start() - self.t_unpackage_xs = threading.Thread(target=self.__unpackage_xs, args=(self.c_xs, )) - self.t_unpackage_xs.daemon = True - self.t_unpackage_xs.start() + self.c_msg = [] + self.c_msg_xs = [] self.flag = 0 self.response = '' self.leftover = 0 self.flag_xs = 0 self.response_xs = '' - def __header_check(self, index, data): + self.t_heartbeat = threading.Thread(target=self.heartbeat) + self.t_heartbeat.daemon = True + self.t_heartbeat.start() + self.t_unpackage = threading.Thread(target=self.unpackage, args=(self.c, )) + self.t_unpackage.daemon = True + self.t_unpackage.start() + self.t_unpackage_xs = threading.Thread(target=self.unpackage_xs, args=(self.c_xs, )) + self.t_unpackage_xs.daemon = True + self.t_unpackage_xs.start() + + def header_check(self, index, data): try: _frame_size = int.from_bytes(data[index:index+2], byteorder='big') _pkg_size = int.from_bytes(data[index+2:index+6], byteorder='big') @@ -59,22 +58,21 @@ class HmiRequest(object): return index+8, _frame_size, _pkg_size else: print("数据有误,需要确认") - exit(9) + return 'DATA ERR' except Exception as Err: print(f"Err = {Err}") print("无法读取数据,需要确认") - exit(10) + return 'DATA READ ERR' - def __heartbeat(self): - current_path = os.path.dirname(__file__) + def heartbeat(self): while True: _id = self.excution('controller.heart') _flag = 1 if self.get_from_id(_id) else 0 with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: f_h.write(str(_flag)) - time.sleep(10) + time.sleep(3) - def __msg_storage(self, response, flag=0): + def msg_storage(self, response, flag=0): messages = self.c_msg if flag == 0 else self.c_msg_xs if len(messages) < 1000: messages.insert(0, response) @@ -83,15 +81,15 @@ class HmiRequest(object): while len(messages) > 1000: messages.pop() - def __get_response(self, data): + def get_response(self, data): _index = 0 while _index < len(data): if self.flag == 0: - _index, _frame_size, _pkg_size = self.__header_check(_index, data) + _index, _frame_size, _pkg_size = self.header_check(_index, data) if _pkg_size <= len(data) - _index: # 说明剩余部分的数据正好就是完整的包数据 self.response = data[_index:_index+_pkg_size].decode() - self.__msg_storage(flag=0, response=self.response) + self.msg_storage(flag=0, response=self.response) _index += _pkg_size self.flag = 0 self.response = '' @@ -111,7 +109,7 @@ class HmiRequest(object): _frame_size = int.from_bytes(data[_index - 2:_index], byteorder='big') if _frame_size == 0: - self.__msg_storage(flag=0, response=self.response) + self.msg_storage(flag=0, response=self.response) self.flag = 0 self.response = '' self.leftover = 0 @@ -124,7 +122,7 @@ class HmiRequest(object): else: if _index+_frame_size <= MAX_FRAME_SIZE: self.response += data[_index:_index+_frame_size].decode() - self.__msg_storage(flag=0, response=self.response) + self.msg_storage(flag=0, response=self.response) self.flag = 0 self.response = '' self.leftover = 0 @@ -134,19 +132,19 @@ class HmiRequest(object): self.leftover = _index + _frame_size - MAX_FRAME_SIZE break - def __get_response_xs(self, data): + def get_response_xs(self, data): if self.flag_xs == 0: if data[-1].decode() == '\r': _responses = data.decode().split('\r') for _response in _responses: - self.__msg_storage(flag=1, response=_response) + self.msg_storage(flag=1, response=_response) else: _responses = data.decode().split('\r') for _response in _responses[:-1]: if not _response: break - self.__msg_storage(flag=1, response=_response) + self.msg_storage(flag=1, response=_response) self.response_xs = _responses[-1] self.flag_xs = 1 @@ -154,7 +152,7 @@ class HmiRequest(object): if data[-1].decode() == '\r': _responses = (self.response_xs.encode() + data).decode().split('\r') for _response in _responses: - self.__msg_storage(flag=1, response=_response) + self.msg_storage(flag=1, response=_response) self.response_xs = '' self.flag_xs = 0 @@ -163,7 +161,7 @@ class HmiRequest(object): for _response in _responses[:-1]: if not _response: break - self.__msg_storage(flag=1, response=_response) + self.msg_storage(flag=1, response=_response) self.response_xs = _responses[-1] self.flag_xs = 1 @@ -176,25 +174,24 @@ class HmiRequest(object): return msg time.sleep(1) else: - # print(f'无法查询到{msg_id}对应的响应') return None - def __package(self, cmd): + def package(self, cmd): _frame_head = (len(cmd)+6).to_bytes(length=2, byteorder='big') _pkg_head = len(cmd).to_bytes(length=4, byteorder='big') _protocol = int(2).to_bytes(length=1, byteorder='big') _reserved = int(0).to_bytes(length=1, byteorder='big') return _frame_head + _pkg_head + _protocol + _reserved + cmd.encode() - def __package_xs(self, cmd): + def package_xs(self, cmd): return f"{json.dumps(cmd, separators=(',', ':'))}\r".encode() - def __unpackage(self, sock): + def unpackage(self, sock): def to_read(conn): data = conn.recv(MAX_FRAME_SIZE) if data: # print(data) - self.__get_response(data) + self.get_response(data) else: print('closing', sock) sel.unregister(conn) @@ -209,12 +206,12 @@ class HmiRequest(object): callback = key.data callback(key.fileobj) - def __unpackage_xs(self, sock): + def unpackage_xs(self, sock): def to_read(conn): data = conn.recv(1024) # Should be ready if data: # print(data) - self.__get_response_xs(data) + self.get_response_xs(data) else: print('closing', sock) sel.unregister(conn) @@ -229,32 +226,30 @@ class HmiRequest(object): callback = key.data callback(key.fileobj) - def __gen_id(self, command): + def gen_id(self, command): _now = time.time() _id = f"{command}-{_now}" return _id - def excution(self, command, flag=0, **kwargs): - current_path = os.path.dirname(__file__) - - if flag == 0: # for old protocols + def excution(self, command, flg=0, **kwargs): + if flg == 0: # for old protocols req = None try: with open(f'{current_path}/../../assets/templates/{command}.json', encoding='utf-8', mode='r') as f_json: req = json.load(f_json) except: print(f"暂不支持 {command} 功能,或确认该功能存在...") - exit(1) + return 'NOT SUPPORT' match command: case 'state.set_tp_mode': req['data']['tp_mode'] = kwargs['tp_mode'] case 1: pass - req['id'] = self.__gen_id(command) + req['id'] = self.gen_id(command) print(f"req = {req}") cmd = json.dumps(req, separators=(',', ':')) - self.c.send(self.__package(cmd)) + self.c.send(self.package(cmd)) time.sleep(2) return req['id'] else: # for xService diff --git a/aio/code/data_process/__init__.py b/aio/code/data_process/__init__.py new file mode 100644 index 0000000..3913f0e --- /dev/null +++ b/aio/code/data_process/__init__.py @@ -0,0 +1 @@ +__all__ = ['brake', 'current', 'iso', 'wavelogger'] \ No newline at end of file