当前位置: 首页 > 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;存储在硬盘上的文件系统…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...