test_scd.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. from msilib import OpenDatabase
  2. from turtle import st
  3. from PyQt5 import QtCore, QtGui, QtWidgets
  4. import os
  5. import sys
  6. import re
  7. import ast
  8. from urllib import parse
  9. import json
  10. import time
  11. import datetime
  12. import requests
  13. import uuid
  14. import pymongo
  15. import pymysql
  16. from xlrd import open_workbook
  17. from xlsxwriter.workbook import Workbook
  18. save_filename = ""
  19. pwd_str = "yf6021"
  20. toji_format = {
  21. 'font_name' : '宋体',
  22. 'font_size': 14,
  23. 'font_color': 'black',
  24. 'text_wrap': True,
  25. 'bold': False,
  26. 'fg_color': '92D050',
  27. 'align': 'center',
  28. 'valign': 'vcenter',
  29. 'border': 1,
  30. 'top': 1,
  31. 'left': 1,
  32. 'right': 1,
  33. 'bottom': 1
  34. }
  35. title_format = {
  36. 'font_name' : '宋体',
  37. 'font_size': 12,
  38. 'bold': True,
  39. 'align': 'center',
  40. 'valign': 'vcenter',
  41. 'border': 1,
  42. 'top': 1,
  43. 'left': 1,
  44. 'right': 1,
  45. 'bottom': 1
  46. }
  47. merge_title_format = {
  48. 'font_name' : '宋体',
  49. 'font_size': 26,
  50. 'bold': True,
  51. 'align': 'center',
  52. 'valign': 'vcenter',
  53. "fg_color": "8DB4E2",
  54. 'border': 1,
  55. 'top': 1,
  56. 'left': 1,
  57. 'right': 1,
  58. 'bottom': 1
  59. }
  60. explain_formal = {
  61. 'font_name' : '宋体',
  62. 'font_size': 11,
  63. 'font_color': 'black',
  64. 'text_wrap': True,
  65. 'align': 'justify',
  66. 'valign': 'vcenter',
  67. 'border': 1,
  68. 'top': 1,
  69. 'left': 1,
  70. 'right': 1,
  71. 'bottom': 1
  72. }
  73. formal_format = {
  74. 'font_name' : '宋体',
  75. 'font_size': 11,
  76. 'font_color': 'black',
  77. 'fg_color': '77E88C',
  78. 'text_wrap': True,
  79. 'align': 'center',
  80. 'valign': 'vcenter',
  81. 'border': 1,
  82. 'top': 1,
  83. 'left': 1,
  84. 'right': 1,
  85. 'bottom': 1
  86. }
  87. common_format = {
  88. 'font_name' : '宋体',
  89. 'font_size': 11,
  90. 'font_color': 'black',
  91. "fg_color": 'E7EC73',
  92. 'text_wrap': True,
  93. 'align': 'center',
  94. 'valign': 'vcenter',
  95. 'border': 1,
  96. 'top': 1,
  97. 'left': 1,
  98. 'right': 1,
  99. 'bottom': 1
  100. }
  101. error_format = {
  102. 'font_name' : '宋体',
  103. 'font_size': 11,
  104. 'font_color': 'black',
  105. "fg_color": 'F4746A',
  106. 'text_wrap': True,
  107. 'align': 'center',
  108. 'valign': 'vcenter',
  109. 'border': 1,
  110. 'top': 1,
  111. 'left': 1,
  112. 'right': 1,
  113. 'bottom': 1
  114. }
  115. class SCDThread(QtCore.QThread):
  116. """涉及进度条需主界面动态执行GUI,线程执行业务逻辑,避免主页面卡死"""
  117. proess_signal = QtCore.pyqtSignal(int)
  118. def __init__(self,device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_dver,set_order):
  119. super(SCDThread, self).__init__()
  120. self.device_list = device_list
  121. self.save_path = save_path
  122. self.start_time = time.mktime(start_time.timetuple())
  123. self.end_time = time.mktime(end_time.timetuple())
  124. self.start_time_str = start_time.strftime("%y-%m-%d %H:%M:%S")
  125. self.end_time_str = end_time.strftime("%y-%m-%d %H:%M:%S")
  126. self.set_plat = set_plat
  127. self.set_stm8vs = set_stm8vs
  128. self.set_dver = set_dver
  129. self.set_order = set_order
  130. self.user = parse.quote_plus("root")
  131. self.passwd = parse.quote_plus("yfkj@6020")
  132. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  133. self.db = self.myclient.smartfarming
  134. self.device_collection = self.db.sa_device
  135. self.scd_collection = self.db.sa_device_scd_data
  136. self.config = {
  137. 'host': '120.27.222.26',
  138. 'port': 3306,
  139. 'user': 'yfwlw',
  140. 'password': 'sql_yfkj_6019',
  141. 'db': 'yfwlw',
  142. 'charset': 'utf8mb4',
  143. 'cursorclass': pymysql.cursors.DictCursor,
  144. }
  145. self.connection = pymysql.connect(**self.config)
  146. self.cursor = self.connection.cursor()
  147. def mongo_ping(self):
  148. """mongo-ping预防连接失效"""
  149. try:
  150. self.myclient.admin.command('ping')
  151. except: # "ConnectionFailure"
  152. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  153. self.db = self.myclient.smartfarming
  154. self.device_collection = self.db.sa_device
  155. self.scd_collection = self.db.sa_device_scd_data
  156. def sql_ping(self):
  157. """mysql-ping 预防连接失效"""
  158. try:
  159. self.connection.ping()
  160. except:
  161. self.connection = pymysql.connect(**self.config)
  162. self.cursor = self.connection.cursor()
  163. def __time_dif(self,checkdatetime):
  164. """计算时间差"""
  165. nowdatetime = datetime.datetime.now()
  166. checkdatetime = datetime.datetime.strptime(checkdatetime, "%Y-%m-%d %H:%M:%S")
  167. timedif = checkdatetime - nowdatetime
  168. return timedif.days
  169. def device_their_platform(self,shortId):
  170. """确定设备所在平台已经完整设备号"""
  171. self.mongo_ping()
  172. self.sql_ping()
  173. regex = re.compile('.*{}$'.format(shortId))
  174. bd_device_dict = self.device_collection.find_one(
  175. filter = {"device_id":regex,"device_type_id":2},
  176. projection = {'_id': 0},
  177. sort = [('uptime', pymongo.DESCENDING)]
  178. )
  179. device_sql = "SELECT * FROM AppInfoManage_scdstatus WHERE equip_id_id LIKE '%{}' ORDER BY upl_time DESC LIMIT 1;".format(shortId)
  180. self.cursor.execute(device_sql)
  181. sq_device_dict = self.cursor.fetchone()
  182. if bd_device_dict and sq_device_dict:
  183. bd_upltime = bd_device_dict["uptime"]
  184. sq_upltime = time.mktime(sq_device_dict["upl_time"].timetuple())
  185. if bd_upltime >= sq_upltime:
  186. d_id = bd_device_dict["id"]
  187. deviceId = bd_device_dict["device_id"]
  188. platform = "大数据平台"
  189. else:
  190. d_id = ""
  191. deviceId = sq_device_dict["equip_id_id"]
  192. platform = "四情平台"
  193. elif bd_device_dict and not sq_device_dict:
  194. d_id = bd_device_dict["id"]
  195. deviceId = bd_device_dict["device_id"]
  196. platform = "大数据平台"
  197. return d_id,deviceId,platform
  198. elif not bd_device_dict and sq_device_dict:
  199. d_id = ""
  200. deviceId = sq_device_dict["equip_id_id"]
  201. platform = "四情平台"
  202. else:
  203. d_id = ""
  204. deviceId = "平台无此设备"
  205. platform = "未知"
  206. return d_id,deviceId,platform
  207. def sim_info(self,iccid):
  208. """查询卡信息"""
  209. url = "http://8.136.98.49:10001/iotcard/platsimview/inquiries/"
  210. try:
  211. response = requests.request("POST", url, data={"iccid":iccid})
  212. except:
  213. return [0,"查询卡信息异常稍后重试"]
  214. else:
  215. res_data = json.loads(response.text)
  216. if res_data["msg"]=="success" and res_data["data"]:
  217. expiry_date = res_data["data"]["expiry_date"]
  218. if expiry_date == "未知":
  219. return [0,"未查询到卡信息"]
  220. elif expiry_date == "未激活":
  221. return [3, "未激活"]
  222. else:
  223. time_difference = self.__time_dif(expiry_date)
  224. if time_difference < 30:
  225. return [0,"有效期剩余{}天".format(time_difference)]
  226. elif time_difference >= 181:
  227. return [1,"有效期剩余{}天".format(time_difference)]
  228. else:
  229. return [2,"有效期剩余{}天".format(time_difference)]
  230. else:
  231. return [0,"查询无结果"]
  232. def __bigdata_verify(self,data_cursor,proess):
  233. """获取大数据平台查询结果"""
  234. ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"]
  235. tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"]
  236. ws_list, ws_count = [],0
  237. iccid = ""
  238. # 开关机状态
  239. open_close_device = {
  240. "open": 0,
  241. "close": 0
  242. }
  243. # 电击次数
  244. dianji = {
  245. "count": 0,
  246. "single_count_gte": False
  247. }
  248. # 充电电压
  249. chongdian_dianya = []
  250. # 电池电压
  251. dianchi_dianya = []
  252. # 雨控保护
  253. yukong_protect = {
  254. "count": 0,
  255. "datetime": []
  256. }
  257. # 光控定时时长
  258. guangkong = []
  259. for index,i in enumerate(data_cursor):
  260. addtime = i["addtime"]
  261. data_strftime = datetime.datetime.fromtimestamp(addtime).strftime("%Y-%m-%d %H:%M:%S")
  262. device_data = i["device_data"]
  263. device_data = ast.literal_eval(device_data)
  264. # 设备开关机
  265. open_close = device_data.get("ds","0")
  266. if open_close == "0":
  267. open_close_device["close"] += 1
  268. if open_close == "1":
  269. open_close_device["open"] += 1
  270. # 工作状态
  271. ws = device_data.get("ws","0")
  272. ws_list.append(ws)
  273. if ws == "1":
  274. ws_count += 1
  275. elif ws == "2":
  276. # 在工作状态 充电电压
  277. chongdian_dianya.append(float(device_data.get("cv","0")))
  278. # 电池电压
  279. dianchi_dianya.append(float(device_data.get("bv","0")))
  280. # 电击次数
  281. dianji_count = int(device_data.get("ct","0"))
  282. dianji['count'] += dianji_count
  283. # 雨控保护
  284. if device_data.get("rps","0") == "1":
  285. yukong_protect["count"] += 1
  286. yukong_protect["datetime"].append(data_strftime)
  287. # 光控定时时长
  288. if device_data.get("ts","0") == "0":
  289. guangkong.append(int(device_data.get("tt","0")))
  290. # 主板代码版本号 (不用展示)
  291. if device_data.get("stm8vs","0") != self.set_stm8vs:
  292. stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0")
  293. # SIM 卡卡号
  294. if device_data.get("iccid",""):
  295. iccid = device_data.get("iccid","")
  296. # 4G 物联网模块代码版本号
  297. if device_data.get("dver","0") != self.set_dver:
  298. dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0")
  299. # 经纬度
  300. if float(device_data.get("lng","0")) < 113.7536111 and float(device_data.get("lng","0")) > 113.7869444:
  301. lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围"
  302. if float(device_data.get("lat","0")) < 35.0125 and float(device_data.get("lat","0")) > 35.0458333:
  303. lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围"
  304. prosee = proess + ((index+1)/data_cursor.count()*(1/len(self.device_list))*100)
  305. if int(prosee) == 100:
  306. self.proess_signal.emit(99)
  307. else:
  308. self.proess_signal.emit(int(prosee))
  309. # 开关机状态 确认 设备开关均为开机
  310. if open_close_device["open"] != 0 and open_close_device["close"] == 0:
  311. ds_verify = [1, f'{str(open_close_device["open"])}条数据均为开机']
  312. else:
  313. ds_verify = [0, f'{str(open_close_device["open"])}条数据为开机, {str(open_close_device["close"])}条数据为关机']
  314. # 工作状态
  315. if "0" in ws_list:
  316. if "1" in ws_list:
  317. if "2" in ws_list:
  318. stamp_diff = self.end_time - self.start_time
  319. day_diff = round(stamp_diff / (12*60*60))
  320. if day_diff <= 1:
  321. low_limit, high_limit = 20, 30
  322. else:
  323. low_limit, high_limit = 20*day_diff, 30*day_diff
  324. if ws_count>low_limit and ws_count<high_limit:
  325. ws_verify=[1,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  326. else:
  327. ws_verify=[0,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  328. else:
  329. ws_verify=[0,"缺少充电状态"]
  330. else:
  331. ws_verify=[0,"缺少工作状态"]
  332. else:
  333. ws_verify=[0,"缺少待机状态"]
  334. # 电击次数
  335. if not dianji["single_count_gte"]:
  336. ct_verify = [1, f'击杀总数:{str(dianji["count"])},且单条数据均没有超1000']
  337. else:
  338. ct_verify = [0, f'击杀总数:{str(dianji["count"])},均在单条数据超1000情况']
  339. # 充电电压
  340. if chongdian_dianya:
  341. chong_max = max(chongdian_dianya)
  342. chong_min = max(chongdian_dianya)
  343. if chong_max < 23 and chong_min > 7:
  344. cv_verify = [1, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"]
  345. else:
  346. cv_verify = [0, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"]
  347. else:
  348. cv_verify = [0, "不存在充电状态"]
  349. # 电池电压
  350. if dianchi_dianya:
  351. dian_max = max(dianchi_dianya)
  352. dian_min = min(dianchi_dianya)
  353. if dian_max < 15 and dian_min > 12:
  354. bv_verify = [1, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"]
  355. else:
  356. bv_verify = [0, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"]
  357. else:
  358. bv_verify = [0, "不存在充电状态"]
  359. # 雨控保护
  360. if yukong_protect["count"] > 0:
  361. rps_verify = [1, f'上报{str(yukong_protect["count"])}条雨控数据首条雨控时间:{yukong_protect["datetime"][0]}']
  362. # 光控定时时长
  363. guangkong_count = list(set(guangkong))
  364. if len(guangkong_count) == 1 and 4 in guangkong_count:
  365. tt_verify = [1, '光控定时时长为4小时']
  366. else:
  367. tt_verify = [0, '光控定时时长异常']
  368. if iccid:
  369. sim_verify = self.sim_info(iccid)
  370. else:
  371. sim_verify = [0,"数据内无iccid"]
  372. return [
  373. ds_verify, # 开关机状态
  374. ws_verify, # 工作状态
  375. ct_verify, # 电击次数
  376. cv_verify, # 充电电压
  377. bv_verify, # 电池电压
  378. rps_verify, # 雨控保护
  379. tt_verify, # 光控定时时长
  380. stm8vs_verify, # 主板代码版本号
  381. sim_verify, # SIM 卡卡号
  382. dver_verify, # 4G 物联网模块代码版本号
  383. lng_verify, # 经度
  384. lat_verify # 纬度
  385. ]
  386. def __siqing_verify(self,data_result,status_result,proess):
  387. """获取四情平台查询结果"""
  388. ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"]
  389. tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"]
  390. ws_list,ws_count = [],0
  391. iccid = ""
  392. for i in status_result:
  393. data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S")
  394. device_data = i["scd_status"]
  395. device_data = ast.literal_eval(device_data)
  396. if device_data.get("stm8vs","0") != self.set_stm8vs:
  397. stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0")
  398. if device_data.get("iccid",""):
  399. iccid = device_data.get("iccid","")
  400. if device_data.get("dver","0") != self.set_dver:
  401. dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0")
  402. # 开关机状态
  403. open_close_device = {
  404. "open": 0,
  405. "close": 0
  406. }
  407. # 电击次数
  408. dianji = {
  409. "count": 0,
  410. "single_count_gte": False
  411. }
  412. # 充电电压
  413. chongdian_dianya = []
  414. # 电池电压
  415. dianchi_dianya = []
  416. # 雨控保护
  417. yukong_protect = {
  418. "count": 0,
  419. "datetime": []
  420. }
  421. # 光控定时时长
  422. guangkong = []
  423. for index,i in enumerate(data_result):
  424. data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S")
  425. device_data = i["scd_data"]
  426. device_data = ast.literal_eval(device_data)
  427. # 设备开关机
  428. open_close = device_data.get("ds","0")
  429. if open_close == "0":
  430. open_close_device["close"] += 1
  431. if open_close == "1":
  432. open_close_device["open"] += 1
  433. # 工作状态
  434. ws = device_data.get("ws","0")
  435. ws_list.append(ws)
  436. if ws == "1":
  437. ws_count += 1
  438. elif ws == "2":
  439. chongdian_dianya.append(device_data.get("cv",0)/1000)
  440. dianchi_dianya.append(float(device_data.get("bv",0)/1000))
  441. # 电击次数
  442. dianji_count = int(device_data.get("ct","0"))
  443. dianji['count'] += dianji_count
  444. # 雨控保护
  445. if device_data.get("rps","0") == "1":
  446. yukong_protect["count"] += 1
  447. yukong_protect["datetime"].append(data_strftime)
  448. # 光控定时时长
  449. if device_data.get("ts","0") == "0":
  450. guangkong.append(int(device_data.get("tt","0")))
  451. # 经纬度
  452. if float(device_data.get("lng","0")) < 113.7536111 and float(device_data.get("lng","0")) > 113.7869444:
  453. lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围"
  454. if float(device_data.get("lat","0")) < 35.0125 and float(device_data.get("lat","0")) > 35.0458333:
  455. lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围"
  456. prosee = proess + ((index+1)/len(data_result)*(1/len(self.device_list))*100)
  457. if int(prosee) == 100:
  458. self.proess_signal.emit(99)
  459. else:
  460. self.proess_signal.emit(int(prosee))
  461. # 开关机状态 确认 设备开关均为开机
  462. if open_close_device["open"] != 0 and open_close_device["close"] == 0:
  463. ds_verify = [1, f'{str(open_close_device["open"])}条数据均为开机']
  464. else:
  465. ds_verify = [0, f'{str(open_close_device["open"])}条数据为开机, {str(open_close_device["close"])}条数据为关机']
  466. # 电击次数
  467. if not dianji["single_count_gte"]:
  468. ct_verify = [1, f'击杀总数:{str(dianji["count"])},且单条数据均没有超1000']
  469. else:
  470. ct_verify = [0, f'击杀总数:{str(dianji["count"])},均在单条数据超1000情况']
  471. # 充电电压
  472. if chongdian_dianya:
  473. chong_max = max(chongdian_dianya)
  474. chong_min = max(chongdian_dianya)
  475. if chong_max < 23 and chong_min > 7:
  476. cv_verify = [1, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"]
  477. else:
  478. cv_verify = [0, f"最小电压值:{str(chong_min)} 最大电压值:{str(chong_max)}"]
  479. else:
  480. cv_verify = [0, "不存在充电状态"]
  481. # 电池电压
  482. if dianchi_dianya:
  483. dian_max = max(dianchi_dianya)
  484. dian_min = min(dianchi_dianya)
  485. if dian_max < 15 and dian_min > 12:
  486. bv_verify = [1, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"]
  487. else:
  488. bv_verify = [0, f"最小电压值:{str(dian_min)} 最大电压值:{str(dian_max)}"]
  489. else:
  490. bv_verify = [0, "电池电压异常"]
  491. # 雨控保护
  492. if yukong_protect["count"] > 0:
  493. rps_verify = [1, f'上报{str(yukong_protect["count"])}']
  494. # 光控定时时长
  495. guangkong_count = list(set(guangkong))
  496. if len(guangkong_count) == 1 and 4 in guangkong_count:
  497. tt_verify = [1, '光控定时时长为4小时']
  498. else:
  499. tt_verify = [0, '光控定时时长异常']
  500. # 工作状态
  501. if "0" in ws_list:
  502. if "1" in ws_list:
  503. if "2" in ws_list:
  504. stamp_diff = self.end_time - self.start_time
  505. day_diff = round(stamp_diff / (12*60*60))
  506. if day_diff <= 1:
  507. low_limit, high_limit = 20, 30
  508. else:
  509. low_limit, high_limit = 20*day_diff, 30*day_diff
  510. if ws_count>low_limit and ws_count<high_limit:
  511. ws_verify=[1,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  512. else:
  513. ws_verify=[0,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  514. else:
  515. ws_verify=[0,"缺少充电状态"]
  516. else:
  517. ws_verify=[0,"缺少工作状态"]
  518. else:
  519. ws_verify=[0,"缺少待机状态"]
  520. if iccid:
  521. sim_verify = self.sim_info(iccid)
  522. else:
  523. sim_verify = [0,"数据内无iccid"]
  524. return [
  525. ds_verify, # 开关机状态
  526. ws_verify, # 工作状态
  527. ct_verify, # 电击次数
  528. cv_verify, # 充电电压
  529. bv_verify, # 电池电压
  530. rps_verify, # 雨控保护
  531. tt_verify, # 光控定时时长
  532. stm8vs_verify, # 主板代码版本号
  533. sim_verify,
  534. dver_verify,
  535. lng_verify,
  536. lat_verify
  537. ]
  538. def run(self):
  539. """主业务逻辑,涉及进度条不能模块化,慢慢捋"""
  540. proess = 0
  541. now_time = datetime.datetime.now()
  542. global save_filename
  543. save_filename = self.set_order + "_" + now_time.strftime("%m%d") + "杀虫灯检验.xlsx"
  544. save_path = os.path.join(self.save_path,save_filename)
  545. workbook = Workbook(save_path)
  546. worksheet = workbook.add_worksheet()
  547. worksheet.set_row(0, 50)
  548. worksheet.set_row(1, 37.5)
  549. worksheet.set_row(2, 30)
  550. worksheet.set_row(3, 100)
  551. for i in range(len(self.device_list)):
  552. worksheet.set_row(i+4, 30)
  553. worksheet.set_column(0, 16, 24)
  554. toji_style = workbook.add_format(toji_format)
  555. title_style = workbook.add_format(title_format)
  556. explain_style = workbook.add_format(explain_formal)
  557. formal_style = workbook.add_format(formal_format)
  558. error_style = workbook.add_format(error_format)
  559. common_style = workbook.add_format(common_format)
  560. merge_title_style = workbook.add_format(merge_title_format)
  561. worksheet.merge_range('A1:Q1',"物联网杀虫灯在线检验原始表格",merge_title_style)
  562. title_data = [
  563. "文档ID","完整设备ID","开关机状态","工作状态","电击次数","充电电压","电池电压","雨控保护","光控定时时长",
  564. "主板版本号","物联网卡有效期","联网模块版本号","经度坐标","纬度坐标","数据来源","单机判定","批判定"]
  565. worksheet.write_row(row = 2 ,col = 0, data = title_data,cell_format=title_style)
  566. explain_data = [
  567. "/",
  568. "/",
  569. "合格条件(绿色):\n查询时间内,设备开关均为开机",
  570. "合格条件(绿色):\n1.查询时间内,存在待机、充电、工作三个类型的工作状态;\n2.单周期内工作状态的数据量大于(20,30)区间内",
  571. "合格条件(绿色):\n查询时间内,存在击杀数据且单次上报击虫数小于1000",
  572. "合格条件(绿色):\n1.存在充电状态;\n2.充电状态下电压值在7-23v之间",
  573. "合格条件(绿色):\n查询时间内上报数据电池电压不能等于12v,也不能大于15v",
  574. "合格条件(绿色):\n查询时间内存在雨控即雨控上报数据量大于0",
  575. "合格条件(绿色):\n1.必须是光控模式\n2.工作时长配置为4小时",
  576. "合格条件(绿色):\n数据上报主板版本号和输入主板版本号一致",
  577. "合格条件(绿色):剩余有效期大于等于181天\n可接受(黄色):大于等于30天,小于181天\n不合格(红色):小于30天或查询异常。",
  578. "合格条件(绿色):\n数据上报联网模块版本号和输入联网模块版本号一致",
  579. "合格条件(绿色):\n113°46′13″±60″范围内,转为十进度为:(113.7536111,113.7869444)区间内",
  580. "合格条件(绿色):\n35°1′45″±60″范围内,转为十进度为:(35.0125,35.0458333)区间内",
  581. "合格条件(绿色):\n输入校验平台和设备所在平台一致",
  582. "合格条件(绿色):\n所有单项检测合格即为单机判定合格",
  583. "合格条件(绿色):\n1.总量大于5台,单机合格量需>=5,不合格允许CF两列出现异常;\n2.若不超5台要求单机判定全部合格。"
  584. ]
  585. worksheet.write_row(row = 3 ,col = 0, data = explain_data,cell_format=explain_style)
  586. formal_counts = 0
  587. verify_list = []
  588. for index,shortId in enumerate(self.device_list):
  589. if isinstance(shortId,int) or isinstance(shortId, float):
  590. shortId = str(int(shortId))
  591. else:
  592. shortId = shortId.strip()
  593. d_id,deviceId,platform = self.device_their_platform(shortId)
  594. worksheet.write(index+4,0,shortId,formal_style)
  595. if platform == "大数据平台":
  596. try:
  597. worksheet.write(index+4,1,deviceId,formal_style)
  598. if platform==self.set_plat:
  599. worksheet.write(index+4,14,platform,formal_style)
  600. else:
  601. worksheet.write(index+4,14,platform,error_style)
  602. self.mongo_ping()
  603. data_cursor = self.scd_collection.find({"device_id":d_id,'addtime': {"$gte":self.start_time ,"$lte":self.end_time}})
  604. data_counts = data_cursor.count()
  605. if data_counts == 0:
  606. for i in range(2,14):
  607. worksheet.write(index+4,i,"搜索时间内无数据",error_style)
  608. worksheet.write(index+4,15,"不合格",error_style)
  609. danji_verify = []
  610. for i in range(12):
  611. danji_verify.append(0)
  612. verify_list.append(danji_verify)
  613. else:
  614. verify_data = self.__bigdata_verify(data_cursor,proess)
  615. danji_verify = []
  616. for clo_index, verify_ in enumerate(verify_data):
  617. danji_verify.append(verify_[0])
  618. if verify_[0] == 0:
  619. worksheet.write(index+4,clo_index+2,verify_[1],error_style)
  620. elif verify_[0] == 1:
  621. worksheet.write(index+4,clo_index+2,verify_[1],formal_style)
  622. else:
  623. worksheet.write(index+4,clo_index+2,verify_[1],common_style)
  624. if 0 in danji_verify:
  625. worksheet.write(index+4,15,"不合格",error_style)
  626. else:
  627. formal_counts += 1
  628. worksheet.write(index+4,15,"合格",formal_style)
  629. verify_list.append(danji_verify)
  630. except Exception as e:
  631. print(e)
  632. elif platform == "四情平台":
  633. worksheet.write(index+4,1,deviceId,formal_style)
  634. if platform==self.set_plat:
  635. worksheet.write(index+4,14,platform,formal_style)
  636. else:
  637. worksheet.write(index+4,14,platform,error_style)
  638. self.sql_ping()
  639. 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)
  640. self.cursor.execute(data_sql)
  641. data_result = self.cursor.fetchall()
  642. 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)
  643. self.cursor.execute(status_sql)
  644. status_result = self.cursor.fetchall()
  645. if len(data_result) == 0 or len(status_result) == 0:
  646. for i in range(2,14):
  647. worksheet.write(index+4,i,"搜索时间内无数据",error_style)
  648. worksheet.write(index+4,15,"不合格",error_style)
  649. danji_verify = []
  650. for i in range(12):
  651. danji_verify.append(0)
  652. verify_list.append(danji_verify)
  653. else:
  654. verify_data = self.__siqing_verify(data_result,status_result,proess)
  655. danji_verify = []
  656. for clo_index, verify_ in enumerate(verify_data):
  657. danji_verify.append(verify_[0])
  658. if verify_[0] == 0:
  659. worksheet.write(index+4,clo_index+2,verify_[1],error_style)
  660. elif verify_[0] == 1:
  661. worksheet.write(index+4,clo_index+2,verify_[1],formal_style)
  662. else:
  663. worksheet.write(index+4,clo_index+2,verify_[1],common_style)
  664. if 0 in danji_verify:
  665. worksheet.write(index+4,15,"不合格",error_style)
  666. else:
  667. formal_counts += 1
  668. worksheet.write(index+4,15,"合格",formal_style)
  669. verify_list.append(danji_verify)
  670. else:
  671. danji_verify = []
  672. for i in range(12):
  673. danji_verify.append(0)
  674. verify_list.append(danji_verify)
  675. worksheet.write(index+4,1,deviceId,error_style)
  676. worksheet.write(index+4,14,platform,error_style)
  677. proess = (index+1)/len(self.device_list) * 100
  678. if int(proess) == 100:
  679. self.proess_signal.emit(99)
  680. else:
  681. self.proess_signal.emit(int(proess))
  682. toji_data = [
  683. "任务单号",self.set_order,"检验时间",'{}\n{}'.format(self.start_time_str,self.end_time_str),
  684. "检验数量",len(self.device_list),"合格数",formal_counts,"检验平台",self.set_plat,
  685. "主板版本",self.set_stm8vs,"联网版本",self.set_dver,"报告日期",now_time.strftime("%y-%m-%d %H:%M:%S"),""
  686. ]
  687. worksheet.write_row(row = 1 ,col = 0, data = toji_data,cell_format=toji_style)
  688. # 批判定
  689. if len(self.device_list) > 5:
  690. batch_verify = [1,"设备量超5台,单机合格数量存在5台及以上,排除CF两列后其他列均合格"]
  691. if formal_counts >= 5:
  692. for danji_data in verify_list:
  693. for index,element_data in enumerate(danji_data):
  694. if index == 1 or index == 3:
  695. pass
  696. else:
  697. if element_data == 0:
  698. batch_verify = [0,"设备量超5台,单机合格数量存在5台及以上,排除CF两列后其他列出现异常"]
  699. else:
  700. batch_verify = [0,"设备量超5台,单机合格数量不足5台"]
  701. else:
  702. if formal_counts == len(self.device_list):
  703. batch_verify = [1,"设备量不超5台,单机判定全部合格"]
  704. else:
  705. batch_verify = [0,"设备量不超5台,单机判定存在不合格"]
  706. 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)
  707. worksheet.protect(pwd_str)
  708. workbook.close()
  709. self.cursor.close()
  710. self.connection.close()
  711. self.myclient.close()
  712. self.proess_signal.emit(100)
  713. if __name__ == "__main__":
  714. device_list = [
  715. "861658061862515",
  716. "861658061825595",
  717. "861658061876911",
  718. "861658061698109",
  719. "861658061862879",
  720. "861658061824663",
  721. "861658061825520",
  722. "861658061698034",
  723. "861658061712421",
  724. "861658061861947",
  725. "861658061809474",
  726. "861658061825348",
  727. "861658061861681",
  728. "861658061825298",
  729. "861658061801166",
  730. "861658061821396",
  731. "861658061697812",
  732. "861658061825504",
  733. "861658061813765",
  734. "861658061697788",
  735. "861658061876721",
  736. "861658061575059",
  737. "861658061861657",
  738. "861658061862598"
  739. ]
  740. save_path = "F:\\质检工具处理文件\\新版临时处理"
  741. start_time = "2023-06-09 12:00:00"
  742. end_time = "2023-06-12 06:00:00"
  743. set_plat = "大数据平台"
  744. start_time = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
  745. end_time = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")
  746. SCDThread(device_list,save_path,start_time,end_time,set_plat,"1","1","1").run()