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-自动化电池监测工具
开源第二篇,书接上回,上回的工具用起来着实不方便,功能也少,不能满足大部分需求,体现在:钉钉发送数据,数据处理,以及接收数据,定时任务等这部分。 随后对其进行了优化 数…...
Struts2一次请求参数问题的记录
最近,一次前端正常请求,但后台出现请求参数值的变化,导致报错,问题如下: 从入参request中查看请求参数,是一个Json字符串,其中有个description的键值对; 但是,接下来调用…...
ctfshow-web9
0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 拿到一个站的时候一定要看robots.txt文件 访问一下 看到一个phps,然后下载一下 看到md5,参考这个https://blog.csdn.net/HAI_WD/article/details/132345156?spm1001.2014.3001.5501 …...
网络安全(黑客)自学路线/笔记
想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全…...
Vim基本使用
Vim基本使用 概念模式类型常规模式编辑模式命令模式 概念 vim 是一款功能丰富、高度可定制和高效的文本编辑器,适用于处理各种文本文件和编程任务。熟练使用vim帮助提高编辑效率,并为用户提供更多的操作选项。 模式类型 常规模式 使用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. 作用 日志最主要的⽤途就是排除和定位问题。 除了发现和定位问题之外,我们还可以通过⽇志实现以下功能: 记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户。记录系统的…...
SpringBoot案例-部门管理-查询
查看页面原型,明确需求需求 页面原型 需求分析 阅读接口文档 接口文档链接如下: https://docs.qq.com/doc/DUkRiTWVaUmFVck9N 思路分析 用户发送请求,交由对应的Controller类进行处理,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客户投诉的安全问题
客户投诉: 客户为什么要投诉?实际上分为两种情况,一是客户被冒犯到不能容忍导致的投诉,二是恶意投诉。降低客户被冒犯投诉的概率,无非就是选择客户、规范用语、降低频度;减少恶意投诉,回避是实践证明最有效…...
JVM中判定对象是否回收的的方法
引用计数法 引用计数法是一种垃圾回收(Garbage Collection)算法,用于自动管理内存中的对象。在引用计数法中,每个对象都有一个关联的引用计数器,用于记录对该对象的引用数量。 当一个新的引用指向对象时,…...
macos 使用vscode 开发python 爬虫(开发二)
以下是一个示例,用于爬取一个公开的示例网站(http://books.toscrape.com),并提取书籍的标题和价格: import requests from bs4 import BeautifulSoup# 发起请求并获取网页内容 url 可以用上面的链接🔗 re…...
(已解决)redis.get报错com.alibaba.fastjson.JSONException: autoType is not support
redis存取值问题,存自定义实体对象; 第一次取的时候报错:com.alibaba.fastjson.JSONException: autoType is not support。 GenericFastJsonRedisSerializer序列化和反序列化redis的value值,需要bean对象含有无参构造方法。 解决…...
控价可以这样做
品牌为什么要做控价,因为渠道中的低价、假货、窜货链接不仅会影响品牌价值和发展,还会影响经销商的合作,长期销售受阻的经销商,会选择低价更价,或者不合作,这无疑是在使品牌渠道走向更为混乱的局面。同时低…...
Spring学习笔记之Spring IoC注解式开发
文章目录 声明Bean的注解Component注解Controller注解Service注解Repository Spring注解的使用选择性实例化Bean负责注入的注解ValueAutowired与QuaifierResource 全注解式开发 注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发 注解怎么定义,注解中的属性…...
C语言入门教程,C语言学习教程(非常详细)第二章 c语言初探
第一个C语言程序 我们有两种方式从计算机获得信息:一是看屏幕上的文字、图片、视频等,二是听从喇叭发出来的声音。让喇叭发出声音目前还比较麻烦,我们先来看看如何在屏幕上显示一些文字吧。 在屏幕上显示文字非常简单,只需要一个…...
HOT99-下一个排列
leetcode原题链接:下一个排列 题目描述 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[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 程序流程控制 流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。 其流程…...
mysql知识点+面试总结
目录 1 mysql介绍 2 数据库常见语法 3 数据库表的常见语法 4 其他常见语法(日期,查询表字段) 5 JDBC开发步骤 6 索引 6.1 索引常见语法 7 常见面试总结 8 java代码搭建监控页面 1 mysql介绍 数据库:存储在硬盘上的文件系统…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
针对药品仓库的效期管理问题,如何利用WMS系统“破局”
案例: 某医药分销企业,主要经营各类药品的批发与零售。由于药品的特殊性,效期管理至关重要,但该企业一直面临效期问题的困扰。在未使用WMS系统之前,其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...
