from msilib import OpenDatabase from turtle import st from PyQt5 import QtCore, QtGui, QtWidgets import os import sys import re import ast from urllib import parse import json import time import datetime import requests import uuid import pymongo import pymysql from xlrd import open_workbook from xlsxwriter.workbook import Workbook save_filename = "" pwd_str = "yf6021" toji_format = { 'font_name' : '宋体', 'font_size': 14, 'font_color': 'black', 'text_wrap': True, 'bold': False, 'fg_color': '92D050', 'align': 'center', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } title_format = { 'font_name' : '宋体', 'font_size': 12, 'bold': True, 'align': 'center', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } merge_title_format = { 'font_name' : '宋体', 'font_size': 26, 'bold': True, 'align': 'center', 'valign': 'vcenter', "fg_color": "8DB4E2", 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } explain_formal = { 'font_name' : '宋体', 'font_size': 11, 'font_color': 'black', 'text_wrap': True, 'align': 'justify', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } formal_format = { 'font_name' : '宋体', 'font_size': 11, 'font_color': 'black', 'fg_color': '77E88C', 'text_wrap': True, 'align': 'center', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } common_format = { 'font_name' : '宋体', 'font_size': 11, 'font_color': 'black', "fg_color": 'E7EC73', 'text_wrap': True, 'align': 'center', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } error_format = { 'font_name' : '宋体', 'font_size': 11, 'font_color': 'black', "fg_color": 'F4746A', 'text_wrap': True, 'align': 'center', 'valign': 'vcenter', 'border': 1, 'top': 1, 'left': 1, 'right': 1, 'bottom': 1 } class SCDThread(QtCore.QThread): """涉及进度条需主界面动态执行GUI,线程执行业务逻辑,避免主页面卡死""" proess_signal = QtCore.pyqtSignal(int) def __init__(self,device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_dver,set_order): super(SCDThread, self).__init__() self.device_list = device_list self.save_path = save_path self.start_time = time.mktime(start_time.timetuple()) self.end_time = time.mktime(end_time.timetuple()) self.start_time_str = start_time.strftime("%y-%m-%d %H:%M:%S") self.end_time_str = end_time.strftime("%y-%m-%d %H:%M:%S") self.set_plat = set_plat self.set_stm8vs = set_stm8vs self.set_dver = set_dver self.set_order = set_order self.user = parse.quote_plus("root") self.passwd = parse.quote_plus("yfkj@6020") self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd)) self.db = self.myclient.smartfarming self.device_collection = self.db.sa_device self.scd_collection = self.db.sa_device_scd_data self.config = { 'host': '120.27.222.26', 'port': 3306, 'user': 'yfwlw', 'password': 'sql_yfkj_6019', 'db': 'yfwlw', 'charset': 'utf8mb4', 'cursorclass': pymysql.cursors.DictCursor, } self.connection = pymysql.connect(**self.config) self.cursor = self.connection.cursor() def mongo_ping(self): """mongo-ping预防连接失效""" try: self.myclient.admin.command('ping') except: # "ConnectionFailure" self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd)) self.db = self.myclient.smartfarming self.device_collection = self.db.sa_device self.scd_collection = self.db.sa_device_scd_data def sql_ping(self): """mysql-ping 预防连接失效""" try: self.connection.ping() except: self.connection = pymysql.connect(**self.config) self.cursor = self.connection.cursor() def __time_dif(self,checkdatetime): """计算时间差""" nowdatetime = datetime.datetime.now() checkdatetime = datetime.datetime.strptime(checkdatetime, "%Y-%m-%d %H:%M:%S") timedif = checkdatetime - nowdatetime return timedif.days def device_their_platform(self,shortId): """确定设备所在平台已经完整设备号""" self.mongo_ping() self.sql_ping() regex = re.compile('.*{}$'.format(shortId)) bd_device_dict = self.device_collection.find_one( filter = {"device_id":regex,"device_type_id":2}, projection = {'_id': 0}, sort = [('uptime', pymongo.DESCENDING)] ) device_sql = "SELECT * FROM AppInfoManage_scdstatus WHERE equip_id_id LIKE '%{}' ORDER BY upl_time DESC LIMIT 1;".format(shortId) self.cursor.execute(device_sql) sq_device_dict = self.cursor.fetchone() if bd_device_dict and sq_device_dict: bd_upltime = bd_device_dict["uptime"] sq_upltime = time.mktime(sq_device_dict["upl_time"].timetuple()) if bd_upltime >= sq_upltime: d_id = bd_device_dict["id"] deviceId = bd_device_dict["device_id"] platform = "大数据平台" else: d_id = "" deviceId = sq_device_dict["equip_id_id"] platform = "四情平台" elif bd_device_dict and not sq_device_dict: d_id = bd_device_dict["id"] deviceId = bd_device_dict["device_id"] platform = "大数据平台" return d_id,deviceId,platform elif not bd_device_dict and sq_device_dict: d_id = "" deviceId = sq_device_dict["equip_id_id"] platform = "四情平台" else: d_id = "" deviceId = "平台无此设备" platform = "未知" return d_id,deviceId,platform def sim_info(self,iccid): """查询卡信息""" url = "http://8.136.98.49:10001/iotcard/platsimview/inquiries/" try: response = requests.request("POST", url, data={"iccid":iccid}) except: return [0,"查询卡信息异常稍后重试"] else: res_data = json.loads(response.text) if res_data["msg"]=="success" and res_data["data"]: expiry_date = res_data["data"]["expiry_date"] if expiry_date == "未知": return [0,"未查询到卡信息"] elif expiry_date == "未激活": return [3, "未激活"] else: time_difference = self.__time_dif(expiry_date) if time_difference < 30: return [0,"有效期剩余{}天".format(time_difference)] elif time_difference >= 181: return [1,"有效期剩余{}天".format(time_difference)] else: return [2,"有效期剩余{}天".format(time_difference)] else: return [0,"查询无结果"] def __bigdata_verify(self,data_cursor,proess): """获取大数据平台查询结果""" ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"] tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"] ws_list, ws_count = [],0 iccid = "" # 开关机状态 open_close_device = { "open": 0, "close": 0 } # 电击次数 dianji = { "count": 0, "single_count_gte": False } # 充电电压 chongdian_dianya = [] # 电池电压 dianchi_dianya = [] # 雨控保护 yukong_protect = { "count": 0, "datetime": [] } # 光控定时时长 guangkong = [] for index,i in enumerate(data_cursor): addtime = i["addtime"] data_strftime = datetime.datetime.fromtimestamp(addtime).strftime("%Y-%m-%d %H:%M:%S") device_data = i["device_data"] device_data = ast.literal_eval(device_data) # 设备开关机 open_close = device_data.get("ds","0") if open_close == "0": open_close_device["close"] += 1 if open_close == "1": open_close_device["open"] += 1 # 工作状态 ws = device_data.get("ws","0") ws_list.append(ws) if ws == "1": ws_count += 1 elif ws == "2": # 在工作状态 充电电压 chongdian_dianya.append(float(device_data.get("cv","0"))) # 电池电压 dianchi_dianya.append(float(device_data.get("bv","0"))) # 电击次数 dianji_count = int(device_data.get("ct","0")) dianji['count'] += dianji_count # 雨控保护 if device_data.get("rps","0") == "1": yukong_protect["count"] += 1 yukong_protect["datetime"].append(data_strftime) # 光控定时时长 if device_data.get("ts","0") == "0": guangkong.append(int(device_data.get("tt","0"))) # 主板代码版本号 (不用展示) if device_data.get("stm8vs","0") != self.set_stm8vs: stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0") # SIM 卡卡号 if device_data.get("iccid",""): iccid = device_data.get("iccid","") # 4G 物联网模块代码版本号 if device_data.get("dver","0") != self.set_dver: dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0") # 经纬度 if float(device_data.get("lng","0")) < 113.7536111 and float(device_data.get("lng","0")) > 113.7869444: lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围" if float(device_data.get("lat","0")) < 35.0125 and float(device_data.get("lat","0")) > 35.0458333: lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围" prosee = proess + ((index+1)/data_cursor.count()*(1/len(self.device_list))*100) if int(prosee) == 100: self.proess_signal.emit(99) else: self.proess_signal.emit(int(prosee)) # 开关机状态 确认 设备开关均为开机 if open_close_device["open"] != 0 and open_close_device["close"] == 0: ds_verify = [1, f'{str(open_close_device["open"])}条数据均为开机'] else: ds_verify = [0, f'{str(open_close_device["open"])}条数据为开机, {str(open_close_device["close"])}条数据为关机'] # 工作状态 if "0" in ws_list: if "1" in ws_list: if "2" in ws_list: stamp_diff = self.end_time - self.start_time day_diff = round(stamp_diff / (12*60*60)) if day_diff <= 1: low_limit, high_limit = 20, 30 else: low_limit, high_limit = 20*day_diff, 30*day_diff if ws_count>low_limit and ws_count 7: cv_verify = [1, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"] else: cv_verify = [0, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"] else: cv_verify = [0, "不存在充电状态"] # 电池电压 if dianchi_dianya: dian_max = max(dianchi_dianya) dian_min = min(dianchi_dianya) if dian_max < 15 and dian_min > 12: bv_verify = [1, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"] else: bv_verify = [0, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"] else: bv_verify = [0, "不存在充电状态"] # 雨控保护 if yukong_protect["count"] > 0: rps_verify = [1, f'上报{str(yukong_protect["count"])}条雨控数据首条雨控时间:{yukong_protect["datetime"][0]}'] # 光控定时时长 guangkong_count = list(set(guangkong)) if len(guangkong_count) == 1 and 4 in guangkong_count: tt_verify = [1, '光控定时时长为4小时'] else: tt_verify = [0, '光控定时时长异常'] if iccid: sim_verify = self.sim_info(iccid) else: sim_verify = [0,"数据内无iccid"] return [ ds_verify, # 开关机状态 ws_verify, # 工作状态 ct_verify, # 电击次数 cv_verify, # 充电电压 bv_verify, # 电池电压 rps_verify, # 雨控保护 tt_verify, # 光控定时时长 stm8vs_verify, # 主板代码版本号 sim_verify, # SIM 卡卡号 dver_verify, # 4G 物联网模块代码版本号 lng_verify, # 经度 lat_verify # 纬度 ] def __siqing_verify(self,data_result,status_result,proess): """获取四情平台查询结果""" ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"] tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"] ws_list,ws_count = [],0 iccid = "" for i in status_result: data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S") device_data = i["scd_status"] device_data = ast.literal_eval(device_data) if device_data.get("stm8vs","0") != self.set_stm8vs: stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0") if device_data.get("iccid",""): iccid = device_data.get("iccid","") if device_data.get("dver","0") != self.set_dver: dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0") # 开关机状态 open_close_device = { "open": 0, "close": 0 } # 电击次数 dianji = { "count": 0, "single_count_gte": False } # 充电电压 chongdian_dianya = [] # 电池电压 dianchi_dianya = [] # 雨控保护 yukong_protect = { "count": 0, "datetime": [] } # 光控定时时长 guangkong = [] for index,i in enumerate(data_result): data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S") device_data = i["scd_data"] device_data = ast.literal_eval(device_data) # 设备开关机 open_close = device_data.get("ds","0") if open_close == "0": open_close_device["close"] += 1 if open_close == "1": open_close_device["open"] += 1 # 工作状态 ws = device_data.get("ws","0") ws_list.append(ws) if ws == "1": ws_count += 1 elif ws == "2": chongdian_dianya.append(device_data.get("cv",0)/1000) dianchi_dianya.append(float(device_data.get("bv",0)/1000)) # 电击次数 dianji_count = int(device_data.get("ct","0")) dianji['count'] += dianji_count # 雨控保护 if device_data.get("rps","0") == "1": yukong_protect["count"] += 1 yukong_protect["datetime"].append(data_strftime) # 光控定时时长 if device_data.get("ts","0") == "0": guangkong.append(int(device_data.get("tt","0"))) # 经纬度 if float(device_data.get("lng","0")) < 113.7536111 and float(device_data.get("lng","0")) > 113.7869444: lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围" if float(device_data.get("lat","0")) < 35.0125 and float(device_data.get("lat","0")) > 35.0458333: lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围" prosee = proess + ((index+1)/len(data_result)*(1/len(self.device_list))*100) if int(prosee) == 100: self.proess_signal.emit(99) else: self.proess_signal.emit(int(prosee)) # 开关机状态 确认 设备开关均为开机 if open_close_device["open"] != 0 and open_close_device["close"] == 0: ds_verify = [1, f'{str(open_close_device["open"])}条数据均为开机'] else: ds_verify = [0, f'{str(open_close_device["open"])}条数据为开机, {str(open_close_device["close"])}条数据为关机'] # 电击次数 if not dianji["single_count_gte"]: ct_verify = [1, f'击杀总数:{str(dianji["count"])},且单条数据均没有超1000'] else: ct_verify = [0, f'击杀总数:{str(dianji["count"])},均在单条数据超1000情况'] # 充电电压 if chongdian_dianya: chong_max = max(chongdian_dianya) chong_min = max(chongdian_dianya) if chong_max < 23 and chong_min > 7: cv_verify = [1, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"] else: cv_verify = [0, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"] else: cv_verify = [0, "不存在充电状态"] # 电池电压 if dianchi_dianya: dian_max = max(dianchi_dianya) dian_min = min(dianchi_dianya) if dian_max < 15 and dian_min > 12: bv_verify = [1, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"] else: bv_verify = [0, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"] else: bv_verify = [0, "电池电压异常"] # 雨控保护 if yukong_protect["count"] > 0: rps_verify = [1, f'上报{str(yukong_protect["count"])}'] # 光控定时时长 guangkong_count = list(set(guangkong)) if len(guangkong_count) == 1 and 4 in guangkong_count: tt_verify = [1, '光控定时时长为4小时'] else: tt_verify = [0, '光控定时时长异常'] # 工作状态 if "0" in ws_list: if "1" in ws_list: if "2" in ws_list: stamp_diff = self.end_time - self.start_time day_diff = round(stamp_diff / (12*60*60)) if day_diff <= 1: low_limit, high_limit = 20, 30 else: low_limit, high_limit = 20*day_diff, 30*day_diff if ws_count>low_limit and ws_count=5,不合格允许CF两列出现异常;\n2.若不超5台要求单机判定全部合格。" ] worksheet.write_row(row = 3 ,col = 0, data = explain_data,cell_format=explain_style) formal_counts = 0 verify_list = [] for index,shortId in enumerate(self.device_list): if isinstance(shortId,int) or isinstance(shortId, float): shortId = str(int(shortId)) else: shortId = shortId.strip() d_id,deviceId,platform = self.device_their_platform(shortId) worksheet.write(index+4,0,shortId,formal_style) if platform == "大数据平台": try: worksheet.write(index+4,1,deviceId,formal_style) if platform==self.set_plat: worksheet.write(index+4,14,platform,formal_style) else: worksheet.write(index+4,14,platform,error_style) self.mongo_ping() data_cursor = self.scd_collection.find({"device_id":d_id,'addtime': {"$gte":self.start_time ,"$lte":self.end_time}}) data_counts = data_cursor.count() if data_counts == 0: for i in range(2,14): worksheet.write(index+4,i,"搜索时间内无数据",error_style) worksheet.write(index+4,15,"不合格",error_style) danji_verify = [] for i in range(12): danji_verify.append(0) verify_list.append(danji_verify) else: verify_data = self.__bigdata_verify(data_cursor,proess) danji_verify = [] for clo_index, verify_ in enumerate(verify_data): danji_verify.append(verify_[0]) if verify_[0] == 0: worksheet.write(index+4,clo_index+2,verify_[1],error_style) elif verify_[0] == 1: worksheet.write(index+4,clo_index+2,verify_[1],formal_style) else: worksheet.write(index+4,clo_index+2,verify_[1],common_style) if 0 in danji_verify: worksheet.write(index+4,15,"不合格",error_style) else: formal_counts += 1 worksheet.write(index+4,15,"合格",formal_style) verify_list.append(danji_verify) except Exception as e: print(e) elif platform == "四情平台": worksheet.write(index+4,1,deviceId,formal_style) if platform==self.set_plat: worksheet.write(index+4,14,platform,formal_style) else: worksheet.write(index+4,14,platform,error_style) self.sql_ping() data_sql = "SELECT * FROM AppInfoManage_scddata WHERE equip_id_id='{}' AND upl_time BETWEEN '{}' AND '{}';".format(deviceId,self.start_time_str,self.end_time_str) self.cursor.execute(data_sql) data_result = self.cursor.fetchall() status_sql = "SELECT * FROM AppInfoManage_scdstatus_all WHERE equip_id_id='{}' AND upl_time BETWEEN '{}' AND '{}';".format(deviceId,self.start_time_str,self.end_time_str) self.cursor.execute(status_sql) status_result = self.cursor.fetchall() if len(data_result) == 0 or len(status_result) == 0: for i in range(2,14): worksheet.write(index+4,i,"搜索时间内无数据",error_style) worksheet.write(index+4,15,"不合格",error_style) danji_verify = [] for i in range(12): danji_verify.append(0) verify_list.append(danji_verify) else: verify_data = self.__siqing_verify(data_result,status_result,proess) danji_verify = [] for clo_index, verify_ in enumerate(verify_data): danji_verify.append(verify_[0]) if verify_[0] == 0: worksheet.write(index+4,clo_index+2,verify_[1],error_style) elif verify_[0] == 1: worksheet.write(index+4,clo_index+2,verify_[1],formal_style) else: worksheet.write(index+4,clo_index+2,verify_[1],common_style) if 0 in danji_verify: worksheet.write(index+4,15,"不合格",error_style) else: formal_counts += 1 worksheet.write(index+4,15,"合格",formal_style) verify_list.append(danji_verify) else: danji_verify = [] for i in range(12): danji_verify.append(0) verify_list.append(danji_verify) worksheet.write(index+4,1,deviceId,error_style) worksheet.write(index+4,14,platform,error_style) proess = (index+1)/len(self.device_list) * 100 if int(proess) == 100: self.proess_signal.emit(99) else: self.proess_signal.emit(int(proess)) toji_data = [ "任务单号",self.set_order,"检验时间",'{}\n{}'.format(self.start_time_str,self.end_time_str), "检验数量",len(self.device_list),"合格数",formal_counts,"检验平台",self.set_plat, "主板版本",self.set_stm8vs,"联网版本",self.set_dver,"报告日期",now_time.strftime("%y-%m-%d %H:%M:%S"),"" ] worksheet.write_row(row = 1 ,col = 0, data = toji_data,cell_format=toji_style) # 批判定 if len(self.device_list) > 5: batch_verify = [1,"设备量超5台,单机合格数量存在5台及以上,排除CF两列后其他列均合格"] if formal_counts >= 5: for danji_data in verify_list: for index,element_data in enumerate(danji_data): if index == 1 or index == 3: pass else: if element_data == 0: batch_verify = [0,"设备量超5台,单机合格数量存在5台及以上,排除CF两列后其他列出现异常"] else: batch_verify = [0,"设备量超5台,单机合格数量不足5台"] else: if formal_counts == len(self.device_list): batch_verify = [1,"设备量不超5台,单机判定全部合格"] else: batch_verify = [0,"设备量不超5台,单机判定存在不合格"] worksheet.merge_range(f"Q5:Q{str(len(self.device_list) + 4)}",batch_verify[1],formal_style if batch_verify[0]==1 else error_style) worksheet.protect(pwd_str) workbook.close() self.cursor.close() self.connection.close() self.myclient.close() self.proess_signal.emit(100) if __name__ == "__main__": device_list = [ "861658061862515", "861658061825595", "861658061876911", "861658061698109", "861658061862879", "861658061824663", "861658061825520", "861658061698034", "861658061712421", "861658061861947", "861658061809474", "861658061825348", "861658061861681", "861658061825298", "861658061801166", "861658061821396", "861658061697812", "861658061825504", "861658061813765", "861658061697788", "861658061876721", "861658061575059", "861658061861657", "861658061862598" ] save_path = "F:\\质检工具处理文件\\新版临时处理" start_time = "2023-06-09 12:00:00" end_time = "2023-06-12 06:00:00" set_plat = "大数据平台" start_time = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") end_time = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") SCDThread(device_list,save_path,start_time,end_time,set_plat,"1","1","1").run()