当前位置: 首页 > news >正文

Pyqt5-自动化电池监测工具

开源第二篇,书接上回,上回的工具用起来着实不方便,功能也少,不能满足大部分需求,体现在:钉钉发送数据,数据处理,以及接收数据,定时任务等这部分。

随后对其进行了优化

数据接收

首先是数据接收,为什么这么说?数据接收,存日志,实时处理,繁琐。

数据接收其实问题不是很大,利用Pyqt5的自定义信号槽机制可以优美的解决掉问题。对于实时数据处理,需要考虑到各种异常情况,所以也就伴随着很多个if-else,有些时候不得不嵌套3个左右的if-else。

如何解决?

实时数据照样拿,但是不做多的处理,只关注指标即可,指标达到,那就直接结束掉,从日志中将数据取出,统一做处理。

这样做,可以有效的减少if-else的使用,可以减少很多的不必要的判断,有些判断只需要一次即可。

数据处理

其次是数据处理,从实时数据修改成了读取日志数据。为什么这么做?

原因:实时数据需要考虑很多因素,处理起来极其麻烦,对于何时结束数据获取存在比较大的问题,尤其是代码书写的美观上。

解决:对于关键数据,分开来处理,分多个函数进行处理,可以有效的增加代码的可阅读性,对于不可避免的if-else也是有效的措施之一。对于数据组合,看个人情况使用,本次优化大部分采用的字典以及列表的的数据结构进行存储值的。保证数据的规范性,最后使用字典统一管理。

钉钉发送数据

在这之前,钉钉发送信息提示一直困扰着我,因为实时数据需要区分很多情况处理。在这之后,采用了关键数据甄别后,直接采用检测触发的方式进行即可,也就是检测到任务完成,我就读取数据,发送数据。避免了多种情况的发生。

定时任务

这个主要是拿来结束指令数据,当然也能拿来持续发送指令,但是鉴于设备端有持续返回数据的功能,我们就不是很需要发送指令了。

用途:数据满足要求后,直接执行自定义指令,来结束指令发送,不需要多余数据进行存储。对后续数据处理减少了判断逻辑以及简化了难易程度。

代码优化

这是本篇不会讲到的东西,因为代码并没有怎么优化出来。尤其是日志处理这块。有很多的冗余代码。是一下章会讲到的东西。先来预览一下:

class ReadLogThread(QThread):def __init__(self, Path, SelectText=None,OnelyIphone=None, Devices=None):super().__init__()self.Path = Pathself.SelectText = SelectTextself.dingding = DingTalkSendMsg()self.OnelyIphone = OnelyIphoneself.Devices = Devicesself.currentTime = datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%S")def run(self) -> None:info = self.Info()if info:self.SendDing(info)with open(sys_ + "\\" + "测试数据.json", "w") as json_file:json.dump(info, json_file, indent=4)  # 使用indent参数以漂亮的格式缩进数据@staticmethoddef dataTimes(value, stime, etime):if len(value) >= 12:start_time = datetime.datetime.strptime(stime, '%H:%M:%S.%f')end_time = datetime.datetime.strptime(etime, '%H:%M:%S.%f')else:start_time = datetime.datetime.strptime(stime, '%H:%M:%S')end_time = datetime.datetime.strptime(etime, '%H:%M:%S')over_time = end_time - start_timereturn str(over_time)def ReadLog(self):with open(self.Path, 'r', encoding="utf-8") as r:datas = r.read()return datasdef Info(self):datas = self.ReadLog()Infomations = self.VolCur()capValue = re.findall(r'\[(.*)\].*cap\s*:\s*(\d*)\s*%', datas)statusValue = re.findall(r'\[(.*)\].*status\s*:\s*(\w*)', datas)for key, value in zip(statusValue, capValue):if self.SelectText == '充电':# 充电时长ChargeTime = self.dataTimes(stime=statusValue[0][0],etime=statusValue[-1][0],value=statusValue[0][0])# 充电跳电情况ChargeInfo = self.ChargeInfoBatteryJump()ChargeBat = self.ChargeBatJump()return {"PutTime": ChargeTime, "Currentbattery":capValue[-1][1], "PutInfo": ChargeInfo, "PutBat": ChargeBat,"Infomations": Infomations}elif self.SelectText == "放电":  # 放电# 放电时长PutTime = self.dataTimes(stime=capValue[0][0],etime=capValue[-1][0],value=capValue[0][0])# 放电跳电情况PutInfo = self.PutInfoBatteryJump()PutBat = self.PutBatJump()return {"PutTime": PutTime, "Currentbattery":capValue[-1][1], "PutInfo": PutInfo, "PutBat": PutBat,"Infomations": Infomations}def ChargeInfoBatteryJump(self):"""info充电跳电"""datas = self.ReadLog()MaxNumber = []dictValue = {"JumpNum": 0, "JumpValue": [], "MaxJump": 0}Jump = re.findall(r'\[(.*)\].*cap\s*:\s*(\d*)\s*%', datas)for num in range(len(Jump) - 1):CountNumber = int(Jump[num + 1][1]) - int(Jump[num][1])if CountNumber > 1:  # 充电跳电dictValue["JumpNum"] += 1MaxNumber.append(CountNumber)dictValue["JumpValue"].append(Jump[num + 1])if CountNumber < 0:  # 充电掉电dictValue["JumpNum"] += 1MaxNumber.append(CountNumber)dictValue["JumpValue"].append(Jump[num + 1])if MaxNumber:dictValue["MaxJump"] = max(MaxNumber)# print("ChargeInfoBatteryJump",dictValue)return dictValuedef PutInfoBatteryJump(self):"""info放电跳电数据"""datas = self.ReadLog()MaxNumber = []dictValue = {"JumpNum": 0, "JumpValue": [], "MaxJump": 0}Jump = re.findall(r'\[(.*)\].*cap\s*:\s*(\d*)\s*%', datas)for num in range(len(Jump) - 1):CountNumber = int(Jump[num][1]) - int(Jump[num + 1][1])if CountNumber > 1:  # 放电回电dictValue["JumpNum"] += 1MaxNumber.append(CountNumber)dictValue["JumpValue"].append(Jump[num + 1])if CountNumber < 0:  # 放电跳电dictValue["JumpNum"] += 1MaxNumber.append(CountNumber)dictValue["JumpValue"].append(Jump[num + 1])if MaxNumber:dictValue["MaxJump"] = max(MaxNumber)return dictValuedef VolCur(self):"""单数是充电电流电压,双数是电池电流电压"""datas = self.ReadLog()ChargeDictValue = {"Start": {"vol": None, "cur": None}, "End": {"vol": None, "cur": None}}BatteryDictValue = {"Start": {"vol": None, "cur": None}, "End": {"vol": None, "cur": None}}volValue = re.findall(r"\[(.*)\].*vol\s*:\s*(\d*)", datas)curValue = re.findall(r"\[(.*)\].*cur\s*:\s*(\d*)", datas)ChargeDict = {"ChargeVol": [], "ChargeCur": []}BatteryDict = {"BatteryVol": [], "BatteryCur": []}if (volValue and curValue) is not False:for num in range(len(volValue)):if num % 2 == 0:  # 充电电流电压ChargeDict["ChargeVol"].append(volValue[num])ChargeDict["ChargeCur"].append(curValue[num])else:  # 电池电压电流BatteryDict["BatteryVol"].append(volValue[num])BatteryDict["BatteryCur"].append(curValue[num])"""充电电压电流数据"""ChargeDictValue["Start"].update({"vol": ChargeDict["ChargeVol"][0][1],"cur": ChargeDict["ChargeCur"][0][1]})ChargeDictValue["End"].update({"vol": ChargeDict["ChargeVol"][-1][1],"cur": ChargeDict["ChargeCur"][-1][1]})BatteryDictValue["Start"].update({"vol": BatteryDict["BatteryVol"][0][1],"cur": BatteryDict["BatteryCur"][0][1]})BatteryDictValue["End"].update({"vol": BatteryDict["BatteryVol"][-1][1],"cur": BatteryDict["BatteryCur"][-1][1]})# print("VolCur", ChargeDictValue)return {"ChargeDictValue": ChargeDictValue, "BatteryDictValue": BatteryDictValue}def PutBatJump(self):"""Bat放电"""BatPutValue = {"JumpNum": 0, "JumpValue": [], "MaxJump": 0}MaxNumber = []datas = self.ReadLog()values = re.findall('\[(.*)\].*cap\s*:.*,(.*)', datas)if values:for num in range(len(values) - 1):CountNumber = int(values[num][1]) - int(values[num + 1][1])if  CountNumber > 1:"""掉"""BatPutValue["JumpNum"] += 1MaxNumber.append(CountNumber)BatPutValue["JumpValue"].append(values[num + 1])if CountNumber < 0:"""回"""BatPutValue["JumpNum"] += 1MaxNumber.append(CountNumber)BatPutValue["JumpValue"].append(values[num + 1])if MaxNumber:BatPutValue["MaxJump"] = max(MaxNumber)return BatPutValuedef ChargeBatJump(self):"""Bat充电"""BatChargeValue = {"JumpNum": 0, "JumpValue": [], "MaxJump": 0}MaxNumber = []datas = self.ReadLog()values = re.findall('\[(.*)\].*cap\s*:.*,(.*)', datas)if values:for num in range(len(values) - 1):CountNumber = int(values[num + 1][1]) - int(values[num][1])if  CountNumber > 1:"""跳"""BatChargeValue["JumpNum"] += 1MaxNumber.append(CountNumber)BatChargeValue["JumpValue"].append(values[num + 1])if CountNumber < 0:"""掉"""BatChargeValue["JumpNum"] += 1MaxNumber.append(CountNumber)BatChargeValue["JumpValue"].append(values[num + 1])if MaxNumber:BatChargeValue["MaxJump"] = max(MaxNumber)return BatChargeValuedef SendDing(self, kwargs):message = f'\n --✉️ {self.Devices} Tests complete-- \n' \f'\n📌 测试人员:Aiper \n' \f'\n💡 当前电量:{kwargs["Currentbattery"]} % \n' \f'\n📆 测试日期:{self.currentTime} \n' \f'\n⌛ 跑机时长:{kwargs["PutTime"]} \n' \f'\n📝 跳电次数:{kwargs["PutInfo"]["JumpNum"]} 次 \n' \f'\n🚀 最大跳电:{kwargs["PutInfo"]["MaxJump"]}  \n' \f'\n ⚡ 开始电流:{kwargs["Infomations"]["ChargeDictValue"]["Start"]["cur"]} ma \n' \f'\n ⚡ 开始电压:{kwargs["Infomations"]["ChargeDictValue"]["Start"]["vol"]} mv \n' \f'\n ⚡ 结束电流:{kwargs["Infomations"]["ChargeDictValue"]["End"]["cur"]} ma \n' \f'\n ⚡ 结束电压:{kwargs["Infomations"]["ChargeDictValue"]["End"]["vol"]} ma \n'\f'\n📒 详细请参考"测试数据.json"文件。'mobiles = []if self.OnelyIphone:mobiles.append(self.OnelyIphone)self.dingding.send_ding_notification(message, mobiles)def JsonPath(self, data, path):"""取值"""return jsonpath.jsonpath(data, path)

这部分代码优化,下一章会讲到。感谢阅读。gitee地址:

https://gitee.com/qinganan_admin/Pyqt5_Battery_MONITOR_SYSTEM.git

相关文章:

Pyqt5-自动化电池监测工具

开源第二篇&#xff0c;书接上回&#xff0c;上回的工具用起来着实不方便&#xff0c;功能也少&#xff0c;不能满足大部分需求&#xff0c;体现在&#xff1a;钉钉发送数据&#xff0c;数据处理&#xff0c;以及接收数据&#xff0c;定时任务等这部分。 随后对其进行了优化 数…...

Struts2一次请求参数问题的记录

最近&#xff0c;一次前端正常请求&#xff0c;但后台出现请求参数值的变化&#xff0c;导致报错&#xff0c;问题如下&#xff1a; 从入参request中查看请求参数&#xff0c;是一个Json字符串&#xff0c;其中有个description的键值对&#xff1b; 但是&#xff0c;接下来调用…...

ctfshow-web9

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 拿到一个站的时候一定要看robots.txt文件 访问一下 看到一个phps&#xff0c;然后下载一下 看到md5&#xff0c;参考这个https://blog.csdn.net/HAI_WD/article/details/132345156?spm1001.2014.3001.5501 …...

网络安全(黑客)自学路线/笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…...

Vim基本使用

Vim基本使用 概念模式类型常规模式编辑模式命令模式 概念 vim 是一款功能丰富、高度可定制和高效的文本编辑器&#xff0c;适用于处理各种文本文件和编程任务。熟练使用vim帮助提高编辑效率&#xff0c;并为用户提供更多的操作选项。 模式类型 常规模式 使用vim打开一个文件…...

二 根据用户行为数据创建ALS模型并召回商品

二 根据用户行为数据创建ALS模型并召回商品 2.0 用户行为数据拆分 方便练习可以对数据做拆分处理 pandas的数据分批读取 chunk 厚厚的一块 相当大的数量或部分 import pandas as pd reader pd.read_csv(behavior_log.csv,chunksize100,iteratorTrue) count 0; for chunk in …...

SpringBoot ⽇志⽂件

日志 1. 作用2. 日志的使用3. 日志的级别4. 日志的持久化 1. 作用 日志最主要的⽤途就是排除和定位问题。 除了发现和定位问题之外&#xff0c;我们还可以通过⽇志实现以下功能&#xff1a; 记录⽤户登录⽇志&#xff0c;⽅便分析⽤户是正常登录还是恶意破解⽤户。记录系统的…...

SpringBoot案例-部门管理-查询

查看页面原型&#xff0c;明确需求需求 页面原型 需求分析 阅读接口文档 接口文档链接如下&#xff1a; https://docs.qq.com/doc/DUkRiTWVaUmFVck9N 思路分析 用户发送请求&#xff0c;交由对应的Controller类进行处理&#xff0c;Controller类调用service实现查询部门功…...

Java中处理表格

大家好 , 我是苏麟 , 也是很久没有更新了 , 今天带来一个很好使用的一个库 easyexcel. JAVA后端开发中可能会遇到一个问题 , 就是处理Execel表格 , 当然不一定非要用Java 我们在这里只说在Java里怎么去处理表格 . Easy Excel 我们今天要说到就是 Easy Excel , 这个是阿里的项…...

指静脉开集测试(OpenSet-test)代码(包含7个数据集)

七个数据集:sdu、mmc、hkpu、scut、utfvp、vera、nupt 一、SDU 80%用于训练,20%用于作为开集测试 1.数据集分割代码 ①先把636个类别提取出来 func: 创建temp_sdu,将636个类划分出来。下一个代码块将进行openset_sdu的分割import os from shutil import copy, rmtre…...

okcc对接ASR平台,okcc客户投诉的安全问题

客户投诉: 客户为什么要投诉&#xff1f;实际上分为两种情况&#xff0c;一是客户被冒犯到不能容忍导致的投诉&#xff0c;二是恶意投诉。降低客户被冒犯投诉的概率&#xff0c;无非就是选择客户、规范用语、降低频度&#xff1b;减少恶意投诉&#xff0c;回避是实践证明最有效…...

JVM中判定对象是否回收的的方法

引用计数法 引用计数法是一种垃圾回收&#xff08;Garbage Collection&#xff09;算法&#xff0c;用于自动管理内存中的对象。在引用计数法中&#xff0c;每个对象都有一个关联的引用计数器&#xff0c;用于记录对该对象的引用数量。 当一个新的引用指向对象时&#xff0c;…...

macos 使用vscode 开发python 爬虫(开发二)

以下是一个示例&#xff0c;用于爬取一个公开的示例网站&#xff08;http://books.toscrape.com&#xff09;&#xff0c;并提取书籍的标题和价格&#xff1a; import requests from bs4 import BeautifulSoup# 发起请求并获取网页内容 url 可以用上面的链接&#x1f517; re…...

(已解决)redis.get报错com.alibaba.fastjson.JSONException: autoType is not support

redis存取值问题&#xff0c;存自定义实体对象&#xff1b; 第一次取的时候报错&#xff1a;com.alibaba.fastjson.JSONException: autoType is not support。 GenericFastJsonRedisSerializer序列化和反序列化redis的value值&#xff0c;需要bean对象含有无参构造方法。 解决…...

控价可以这样做

品牌为什么要做控价&#xff0c;因为渠道中的低价、假货、窜货链接不仅会影响品牌价值和发展&#xff0c;还会影响经销商的合作&#xff0c;长期销售受阻的经销商&#xff0c;会选择低价更价&#xff0c;或者不合作&#xff0c;这无疑是在使品牌渠道走向更为混乱的局面。同时低…...

Spring学习笔记之Spring IoC注解式开发

文章目录 声明Bean的注解Component注解Controller注解Service注解Repository Spring注解的使用选择性实例化Bean负责注入的注解ValueAutowired与QuaifierResource 全注解式开发 注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发 注解怎么定义&#xff0c;注解中的属性…...

C语言入门教程,C语言学习教程(非常详细)第二章 c语言初探

第一个C语言程序 我们有两种方式从计算机获得信息&#xff1a;一是看屏幕上的文字、图片、视频等&#xff0c;二是听从喇叭发出来的声音。让喇叭发出声音目前还比较麻烦&#xff0c;我们先来看看如何在屏幕上显示一些文字吧。 在屏幕上显示文字非常简单&#xff0c;只需要一个…...

HOT99-下一个排列

leetcode原题链接&#xff1a;下一个排列 题目描述 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其…...

JAVA基础知识(二)——程序流程控制

程序流程控制 一、程序流程控制1.1 程序流程控制1.2 顺序结构1.3 分支结构1.4 循环结构1.5 嵌套循环1.6 return的使用 一、程序流程控制 1.1 程序流程控制 流程控制语句是用来控制程序中各语句执行顺序的语句&#xff0c;可以把语句组合成能完成一定功能的小逻辑模块。 其流程…...

mysql知识点+面试总结

目录 1 mysql介绍 2 数据库常见语法 3 数据库表的常见语法 4 其他常见语法&#xff08;日期&#xff0c;查询表字段&#xff09; 5 JDBC开发步骤 6 索引 6.1 索引常见语法 7 常见面试总结 8 java代码搭建监控页面 1 mysql介绍 数据库&#xff1a;存储在硬盘上的文件系统…...

Unity-MCP协议:可嵌入、可协商的AI上下文通信标准

1. 这不是又一个“AI插件”&#xff0c;而是Unity开发工作流的底层重定义你有没有过这样的时刻&#xff1a;在Unity里反复调整Animator Controller的过渡条件&#xff0c;只为让角色转身动画不穿模&#xff1b;写完一段NavMesh寻路逻辑&#xff0c;却要花两小时调试Agent卡在斜…...

UOS系统下WPS卸载不干净?手把手教你用命令行精准清理(附dpkg/apt组合拳)

UOS系统下WPS卸载不干净&#xff1f;手把手教你用命令行精准清理 在UOS系统日常使用中&#xff0c;WPS Office作为常用办公软件&#xff0c;有时因版本更新或功能调整需要彻底卸载。但不少用户发现&#xff0c;通过图形界面或简单命令卸载后&#xff0c;系统中仍残留配置文件、…...

学术写作创新突破!2026全流程AI论文工具精选指南

2026 年 AI 论文写作工具已进入全流程闭环 学术合规时代&#xff0c;千笔 AI&#xff08;综合评分 99 分&#xff09;中文学术场景标杆&#xff1b;Grammarly Academic与Elicit为英文论文写作首选&#xff1b;按需求匹配度 - 数据可信度 - 成本承受力三维模型选型&#xff0c;…...

独立站内容分层:一层给 SEO,一层给 GEO

你的内容在喂两个完全不同的"阅读者" 你的博客文章&#xff0c;从来都不只有一个读者。 传统认知里&#xff0c;独立站内容的读者只有两类&#xff1a;真人访客和搜索引擎爬虫。SEO 优化的一切工作&#xff0c;本质上都是在讨好后者&#xff0c;顺带服务前者。 但…...

巧用对称性与平均值原理:低成本实现高精度电阻分压器校准

1. 项目概述&#xff1a;用数学思维突破测量设备的精度极限在电子实验室里捣鼓精密电路&#xff0c;尤其是涉及到电压基准、信号调理或者高精度ADC前端时&#xff0c;一个绕不开的坎就是精密分压器。你可能在设计一个需要0.1%甚至更高精度的分压网络&#xff0c;但手头的万用表…...

超维计算(HDC)原理与ScalableHD架构优化实践

1. 超维计算&#xff08;HDC&#xff09;基础解析超维计算&#xff08;Hyperdimensional Computing, HDC&#xff09;是一种受大脑信息处理机制启发的计算范式&#xff0c;其核心思想是用高维随机向量&#xff08;通常称为超向量或HV&#xff09;来表示和处理信息。与传统神经网…...

机器学习驱动储氢材料发现:从特征工程到DFT/MD验证的完整指南

1. 项目概述与核心思路氢能被视为未来清洁能源体系的关键一环&#xff0c;但如何安全、高效、经济地储存氢气&#xff0c;一直是制约其大规模应用的瓶颈。在众多储氢技术路线中&#xff0c;固态储氢&#xff0c;特别是基于金属氢化物的储氢材料&#xff0c;因其高体积储氢密度和…...

同步带装配工艺要点与损伤防控策略

一、引言在工业精密传动系统中&#xff0c;盖茨同步带凭借高精度、高效率、无滑差的优势&#xff0c;成为自动化设备、精密机床、输送产线的核心传动部件。多数企业在运维中&#xff0c;普遍将同步带异常磨损、断齿、断带等故障归咎于工况恶劣或产品质量问题&#xff0c;却忽略…...

全球无障碍宣传日:iOS 26 辅助功能大升级,这些实用小功能你用过吗?

辅助功能发展与升级很多人对辅助功能的印象还停留在 "小白点"&#xff0c;但随着 iPhone 进入全面屏时代&#xff0c;它逐渐变得陌生。实际上&#xff0c;Apple 每年都会为其增添功能&#xff0c;方便身体有障人士使用 iPhone。而且&#xff0c;这些功能不仅惠及有障…...

CTF出题人视角:从NewStarCTF 2023的WEB题,聊聊PHP特性与Flask Debug的那些‘坑’

CTF出题艺术&#xff1a;从PHP特性到Flask Debug的攻防博弈 当一道精心设计的CTF题目被成功破解时&#xff0c;出题人与解题者之间往往存在一场无声的思维交锋。作为NewStarCTF 2023 WEB方向的出题人&#xff0c;我想通过复盘"Begin of PHP"和"ErrorFlask"…...