qxz_zhijian_new.py 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file '.\ui文件\气象站质检工具.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.15.4
  5. #
  6. # WARNING: Any manual changes made to this file will be lost when pyuic5 is
  7. # run again. Do not edit this file unless you know what you are doing.
  8. # pyinstaller -n "气象站(v3.2)" -D -w f:\image_down_code\qxz_zhijian.py -i .\LOGO.ico
  9. from PyQt5 import QtCore, QtGui, QtWidgets
  10. import os
  11. import sys
  12. import re
  13. import ast
  14. from urllib import parse
  15. import json
  16. import time
  17. import datetime
  18. import requests
  19. import uuid
  20. import pymongo
  21. import pymysql
  22. from collections import defaultdict, Counter
  23. from xlrd import open_workbook
  24. from xlsxwriter.workbook import Workbook
  25. import openpyxl
  26. save_filename = ""
  27. pwd_str = "yf6021"
  28. toji_format = {
  29. 'font_name' : '宋体',
  30. 'font_size': 14,
  31. 'font_color': 'black',
  32. 'text_wrap': True,
  33. 'bold': False,
  34. 'fg_color': '92D050',
  35. 'align': 'center',
  36. 'valign': 'vcenter',
  37. 'border': 1,
  38. 'top': 1,
  39. 'left': 1,
  40. 'right': 1,
  41. 'bottom': 1
  42. }
  43. title_format = {
  44. 'font_name' : '宋体',
  45. 'font_size': 12,
  46. 'bold': True,
  47. 'align': 'center',
  48. 'valign': 'vcenter',
  49. 'border': 1,
  50. 'top': 1,
  51. 'left': 1,
  52. 'right': 1,
  53. 'bottom': 1
  54. }
  55. merge_title_format = {
  56. 'font_name' : '宋体',
  57. 'font_size': 26,
  58. 'bold': True,
  59. 'align': 'center',
  60. 'valign': 'vcenter',
  61. "fg_color": "8DB4E2",
  62. 'border': 1,
  63. 'top': 1,
  64. 'left': 1,
  65. 'right': 1,
  66. 'bottom': 1
  67. }
  68. explain_formal = {
  69. 'font_name' : '宋体',
  70. 'font_size': 11,
  71. 'font_color': 'black',
  72. 'text_wrap': True,
  73. 'align': 'justify',
  74. 'valign': 'vcenter',
  75. 'border': 1,
  76. 'top': 1,
  77. 'left': 1,
  78. 'right': 1,
  79. 'bottom': 1
  80. }
  81. formal_format = {
  82. 'font_name' : '宋体',
  83. 'font_size': 11,
  84. 'font_color': 'black',
  85. 'fg_color': '77E88C',
  86. 'text_wrap': True,
  87. 'align': 'center',
  88. 'valign': 'vcenter',
  89. 'border': 1,
  90. 'top': 1,
  91. 'left': 1,
  92. 'right': 1,
  93. 'bottom': 1
  94. }
  95. common_format = {
  96. 'font_name' : '宋体',
  97. 'font_size': 11,
  98. 'font_color': 'black',
  99. "fg_color": 'E7EC73',
  100. 'text_wrap': True,
  101. 'align': 'center',
  102. 'valign': 'vcenter',
  103. 'border': 1,
  104. 'top': 1,
  105. 'left': 1,
  106. 'right': 1,
  107. 'bottom': 1
  108. }
  109. error_format = {
  110. 'font_name' : '宋体',
  111. 'font_size': 11,
  112. 'font_color': 'black',
  113. "fg_color": 'F4746A',
  114. 'text_wrap': True,
  115. 'align': 'center',
  116. 'valign': 'vcenter',
  117. 'border': 1,
  118. 'top': 1,
  119. 'left': 1,
  120. 'right': 1,
  121. 'bottom': 1
  122. }
  123. default_formal = {
  124. 'font_name': '宋体',
  125. 'font_size': 11,
  126. 'font_color': 'black',
  127. 'text_wrap': True,
  128. 'align': 'center',
  129. 'valign': 'vcenter',
  130. 'border': 1,
  131. 'top': 1,
  132. 'left': 1,
  133. 'right': 1,
  134. 'bottom': 1
  135. }
  136. class QxzCand:
  137. def __init__(self):
  138. self.func_dict = {
  139. "空气温度": self.get_cond_101,
  140. "空气湿度": self.get_cond_102,
  141. "土壤温度": self.get_cond_106,
  142. "土壤含水率": self.get_cond_107,
  143. "风速": self.get_cond_108,
  144. "风向": self.get_cond_109,
  145. "降雨量累计": self.get_cond_115,
  146. "光合有效辐射": self.get_cond_123,
  147. "气压": self.get_cond_127,
  148. "盐分": self.get_cond_154,
  149. "电导率": self.get_cond_211,
  150. "磷": self.get_cond_156,
  151. "日照时数": self.get_cond_113,
  152. "PM2.5": self.get_cond_145,
  153. "PM10": self.get_cond_146,
  154. "总辐射": self.get_cond_105,
  155. "负氧离子": self.get_cond_162,
  156. "二氧化碳": self.get_cond_120,
  157. "蒸发量": self.get_cond_110,
  158. "土壤PH": self.get_cond_128,
  159. "紫外辐射": self.get_cond_138,
  160. "水质pH": self.get_cond_228,
  161. "水位": self.get_cond_230,
  162. "水质电导率": self.get_cond_178,
  163. "光照度": self.get_cond_112,
  164. "硫化氢": self.get_cond_219,
  165. "水温": self.get_cond_144,
  166. "浊度": self.get_cond_151,
  167. "氨气": self.get_cond_153,
  168. "氧气": self.get_cond_220,
  169. "PM100": self.get_cond_203,
  170. "露点温度": self.get_cond_202,
  171. "氮": self.get_cond_155,
  172. "钾": self.get_cond_157,
  173. "溶解氧": self.get_cond_148,
  174. }
  175. self.cond_msg_dict = {}
  176. for k, v in self.func_dict.items():
  177. self.cond_msg_dict[k] = self.get_cond_msg
  178. self.head_dict = {
  179. "ID": "/",
  180. "检验项目": "判定标准",
  181. "经度": "合格条件(绿色):\n113°46′13″±30″范围内",
  182. "纬度": "合格条件(绿色):\n35°1′45″±30″范围内",
  183. "固件版本号": "合格条件(绿色):\n用检验时的输入作为导入的标准.\n/ 无法显示,替换为 -",
  184. "电压": "合格条件(绿色):\n11.5~12.5",
  185. "信号强度": "合格条件(绿色):\n>14",
  186. "上传数据条数": "合格条件(绿色):\n1、大于7条\n2、两条数据时间间隔小于20分钟的出现频次2次以内、两条数据间隔大于40分钟出现频率2次以内",
  187. "风速": "合格条件(绿色):\n1、0<示值<10\n2、有1条合格 即可",
  188. "风向": "合格条件(绿色):\n1、0<示值<360\n2、有1条合格即可",
  189. "降雨量累计": "合格条件(绿色):\n1、0<示值\n2、00:00示值归零\n3、有1条合格即可",
  190. "土壤含水率": "合格条件(绿色):\n1、0<示值<100\n2、有1条合格即可",
  191. "土壤温度": "合格条件(绿色):\n1.≠0且在-5~35°C之间\n2、有1条合格即可",
  192. "盐分": "合格条件(绿色):\n1、0<示值<1000#2、有1条合格即可",
  193. "电导率": "合格条件(绿色):\n1、0<示值\n2、有1条合格即",
  194. "氮": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  195. "磷": "合格条件(绿色):\n1、0<示值且不能为负值\n2、有1条合格即可",
  196. "光合有效辐射": "合格条件(绿色):\n1、0<示值且不能为负值\n2、有1条合格即可",
  197. "日照时数": "合格条件(绿色):\n1、0.1≤示值≤0.2且不能为负值2、有1条合格即可",
  198. "PM2.5": "合格条件(绿色):\n1、0<示值且不能为负值\n2、有1条合格即可",
  199. "PM10": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  200. "负氧离子": "合格条件(绿色):\n1、0<示值<1000\n2、有1条合格即可",
  201. "总辐射": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  202. "二氧化碳": "合格条件(绿色):\n1、400<示值<1500\n2、有1条合格即可",
  203. "蒸发量": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  204. "土壤PH": "合格条件(绿色):\n1、6~8\n2、有1条合格即可",
  205. "钾": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  206. "紫外辐射": "合格条件(绿色):\n1、0<示 值\n2、有1条合格即可",
  207. "空气温度": "合格条件(绿色):\n1.-10~35°C,但不允许为0°C\n2、有1条合格即可",
  208. "空气湿度": "合格条件(绿色):\n1、0<示值<100\n2、有1条合格即可",
  209. "水质pH": "合格条件(绿色):\n1、6≤示值≤8\n2、有1条合格即可",
  210. "水位": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  211. "水质电导率": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  212. "气压": "合格条件(绿色):\n1、1000<示值<1100\n2、有1条合格即可",
  213. "光照度": "合格条件(绿色):\n1、0<示值<200000\n2、有1条合格即可",
  214. "硫化氢": "合格条件(绿色):\n1、示值=0\n2、有1条合格即可",
  215. "水温": "合格条件(绿色):\n1.0~30°C,但不允许为0°C\n2、 有1条合格即可",
  216. "溶解氧": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  217. "浊度": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  218. "氨气": "合格条件(绿色):\n1、示值=0\n2、有1条合格即可",
  219. "氧气": "合格条件(绿色):\n1、0<示值\n2、有1条合格即可",
  220. "PM100": "合格条件(绿色):\n1、0<示值\n2 、有1条合格即可",
  221. "露点温度": "合格条件(绿色):\n1.-10~35°C,但不允许为0°C\n2、有1条合格即可",
  222. "sim卡信息": "合格条件(绿色):\n1、大于等于180天单元格显示绿色\n2、小于180天大于等于30天单元格显示黄色、\n3、小于30天单元格显示为红色",
  223. "单台合格数": "合格条件(绿色):\n所有显示数值全部在合格范围内,则判定为合格"
  224. }
  225. def get_cond_lat_msg(self, info):
  226. return {
  227. "status": int(info["status"]),
  228. "msg": f"纬度为: {info['lat']}"
  229. }
  230. def get_cond_lng_msg(self, info):
  231. return {
  232. "status": int(info["status"]),
  233. "msg": f"经度为: {info['lng']}"
  234. }
  235. def get_cond_volt_msg(self, info):
  236. return self.get_cond_msg(info)
  237. def get_cond_rssi_msg(self, info):
  238. return self.get_cond_msg(info)
  239. def get_cond_version_msg(self, info):
  240. status = info["status"]
  241. value = info["dver_num"]
  242. old_value = info["old_value"]
  243. device_version = value.replace('/', '-')
  244. old_version = old_value.replace('/', '-')
  245. return {
  246. "status": status,
  247. "msg": f"设备:{device_version}, 输入:{old_version}"
  248. }
  249. def get_cond_sim_msg(self, info):
  250. return info
  251. def get_time_uptime_msg(self, info):
  252. total_count = int(info["total_count"])
  253. uptime_20 = int(info["uptime_20"])
  254. uptime_40 = int(info["uptime_40"])
  255. msg = f"数据量:{total_count},间隔<20分钟:{uptime_20},间隔>40分钟:{uptime_40}"
  256. status = 0
  257. if total_count > 7 and uptime_20 <= 2 and uptime_40 <= 2:
  258. status = 1
  259. return {
  260. "status": status,
  261. "msg": msg
  262. }
  263. def get_cond_msg(self, info):
  264. """获取输出结果"""
  265. max_value = info['max_value']
  266. min_value = info['min_value']
  267. status = int(info['status'])
  268. msg = f"最大值:{max_value},最小值:{min_value}"
  269. return {"status": status, "msg": msg}
  270. def template_func(self, ek, cond_str):
  271. """获取模板函数"""
  272. cond = {
  273. "$function": {
  274. "args": [f"${ek}"],
  275. "lang": "js",
  276. "body": f"""
  277. function(values_list){{
  278. let max_value = Math.max(...values_list);
  279. let min_value = Math.min(...values_list);
  280. let status = 0;
  281. for (let i = 0; i < values_list.length; i++){{
  282. let v = values_list[i];
  283. if ({cond_str}){{
  284. status = 1;
  285. break;
  286. }}
  287. }}
  288. return {{"max_value": max_value, "min_value": min_value, "status": status}}
  289. }}
  290. """
  291. }
  292. }
  293. return cond
  294. def get_cond_101(self, ek):
  295. """获取空气温度条件"""
  296. cond = self.template_func(ek, "v != 0 && -10 <= v && v <= 35")
  297. return cond
  298. def get_cond_102(self, ek):
  299. """获取空气湿度条件"""
  300. cond = self.template_func(ek, "0 < v && v < 100")
  301. return cond
  302. def get_cond_106(self, ek):
  303. """获取土壤温度条件"""
  304. cond = self.template_func(ek, "v != 0 && -5 <= v && v <= 35")
  305. return cond
  306. def get_cond_107(self, ek):
  307. """获取土壤含水率条件"""
  308. cond = self.template_func(ek, "0 < v && v < 100")
  309. return cond
  310. def get_cond_108(self, ek):
  311. """获取风速条件"""
  312. cond = self.template_func(ek, "0 < v && v < 10")
  313. return cond
  314. def get_cond_109(self, ek):
  315. """获取风向条件"""
  316. cond = self.template_func(ek, "0 < v && v < 360")
  317. return cond
  318. def get_cond_115(self, ek):
  319. """获取降雨量累计条件"""
  320. cond = self.template_func(ek, "0 < v")
  321. return cond
  322. def get_cond_123(self, ek):
  323. """获取光合有效辐射条件"""
  324. cond = self.template_func(ek, "0 < v")
  325. return cond
  326. def get_cond_127(self, ek):
  327. """获取气压条件"""
  328. cond = self.template_func(ek, "1000 < v && v < 1100")
  329. return cond
  330. def get_cond_154(self, ek):
  331. """获取盐分条件"""
  332. cond = self.template_func(ek, "0 < v && v < 1000")
  333. return cond
  334. def get_cond_211(self, ek):
  335. """获取电导率条件"""
  336. cond = self.template_func(ek, "0 < v")
  337. return cond
  338. def get_cond_155(self, ek):
  339. """获取氮条件"""
  340. cond = self.template_func(ek, "0 < v")
  341. return cond
  342. def get_cond_156(self, ek):
  343. """获取磷条件"""
  344. cond = self.template_func(ek, "0 < v")
  345. return cond
  346. def get_cond_113(self, ek):
  347. """获取日照时数条件"""
  348. cond = self.template_func(ek, "0.1 <= v && v <= 0.2")
  349. return cond
  350. def get_cond_145(self, ek):
  351. """获取PM2.5条件"""
  352. cond = self.template_func(ek, "0 < v")
  353. return cond
  354. def get_cond_146(self, ek):
  355. """获取PM10条件"""
  356. cond = self.template_func(ek, "0 < v")
  357. return cond
  358. def get_cond_105(self, ek):
  359. """获取总辐射条件"""
  360. cond = self.template_func(ek, "0 < v")
  361. return cond
  362. def get_cond_162(self, ek):
  363. """获取负氧离子条件"""
  364. cond = self.template_func(ek, "0 < v && v < 1000")
  365. return cond
  366. def get_cond_120(self, ek):
  367. """获取二氧化碳条件"""
  368. cond = self.template_func(ek, "400 < v && v < 1500")
  369. return cond
  370. def get_cond_110(self, ek):
  371. """获取蒸发量条件"""
  372. cond = self.template_func(ek, "0 < v")
  373. return cond
  374. def get_cond_128(self, ek):
  375. """获取土壤PH条件"""
  376. cond = self.template_func(ek, "6 <= v && v <= 8")
  377. return cond
  378. def get_cond_157(self, ek):
  379. """获取钾条件"""
  380. cond = self.template_func(ek, "0 < v")
  381. return cond
  382. def get_cond_138(self, ek):
  383. """获取紫外辐射条件"""
  384. cond = self.template_func(ek, "0 < v")
  385. return cond
  386. def get_cond_228(self, ek):
  387. """获取水质pH条件"""
  388. cond = self.template_func(ek, "6 <= v && v <= 8")
  389. return cond
  390. def get_cond_230(self, ek):
  391. """获取水位条件"""
  392. cond = self.template_func(ek, "0 < v")
  393. return cond
  394. def get_cond_178(self, ek):
  395. """获取水质电导率条件"""
  396. cond = self.template_func(ek, "0 < v")
  397. return cond
  398. def get_cond_112(self, ek):
  399. """获取光照度条件"""
  400. cond = self.template_func(ek, "0 < v && v < 200000")
  401. return cond
  402. def get_cond_219(self, ek):
  403. """获取硫化氢条件"""
  404. cond = self.template_func(ek, "v == 0")
  405. return cond
  406. def get_cond_144(self, ek):
  407. """获取水温条件"""
  408. cond = self.template_func(ek, "0 < v && v <= 30")
  409. return cond
  410. def get_cond_148(self, ek):
  411. """获取溶解氧条件"""
  412. cond = self.template_func(ek, "0 < v")
  413. return cond
  414. def get_cond_151(self, ek):
  415. """获取浊度条件"""
  416. cond = self.template_func(ek, "0 < v")
  417. return cond
  418. def get_cond_153(self, ek):
  419. """获取氨气条件"""
  420. cond = self.template_func(ek, "v == 0")
  421. return cond
  422. def get_cond_220(self, ek):
  423. """获取氧气条件"""
  424. cond = self.template_func(ek, "0 < v")
  425. return cond
  426. def get_cond_203(self, ek):
  427. """获取PM100条件"""
  428. cond = self.template_func(ek, "0 < v")
  429. return cond
  430. def get_cond_202(self, ek):
  431. """获取露点温度条件"""
  432. cond = self.template_func(ek, "-10 < v && v < 35")
  433. return cond
  434. class Ui_MainWindow(object):
  435. """GUI界面"""
  436. def setupUi(self, MainWindow):
  437. MainWindow.setObjectName("MainWindow")
  438. MainWindow.resize(701, 644)
  439. font = QtGui.QFont()
  440. font.setFamily("Arial")
  441. font.setPointSize(12)
  442. MainWindow.setFont(font)
  443. icon = QtGui.QIcon("logo.ico")
  444. MainWindow.setWindowIcon(icon)
  445. self.centralwidget = QtWidgets.QWidget(MainWindow)
  446. self.centralwidget.setObjectName("centralwidget")
  447. self.pageTitleLabel = QtWidgets.QLabel(self.centralwidget)
  448. self.pageTitleLabel.setGeometry(QtCore.QRect(139, 50, 429, 42))
  449. font = QtGui.QFont()
  450. font.setFamily("楷体")
  451. font.setPointSize(28)
  452. self.pageTitleLabel.setFont(font)
  453. self.pageTitleLabel.setTextFormat(QtCore.Qt.AutoText)
  454. self.pageTitleLabel.setObjectName("pageTitleLabel")
  455. self.inputFileLabel = QtWidgets.QLabel(self.centralwidget)
  456. self.inputFileLabel.setGeometry(QtCore.QRect(180, 130, 121, 21))
  457. self.inputFileLabel.setObjectName("inputFileLabel")
  458. self.inputFileEdit = QtWidgets.QLineEdit(self.centralwidget)
  459. self.inputFileEdit.setGeometry(QtCore.QRect(310, 130, 151, 21))
  460. self.inputFileEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  461. font = QtGui.QFont()
  462. font.setFamily("Arial")
  463. font.setPointSize(8)
  464. self.inputFileEdit.setFont(font)
  465. self.inputFileEdit.setObjectName("inputFileEdit")
  466. self.inputFileTool = QtWidgets.QToolButton(self.centralwidget)
  467. self.inputFileTool.setGeometry(QtCore.QRect(470, 130, 71, 21))
  468. font = QtGui.QFont()
  469. font.setFamily("Arial")
  470. font.setPointSize(10)
  471. self.inputFileTool.setFont(font)
  472. self.inputFileTool.setObjectName("inputFileTool")
  473. self.savePathLabel = QtWidgets.QLabel(self.centralwidget)
  474. self.savePathLabel.setGeometry(QtCore.QRect(180, 170, 121, 21))
  475. self.savePathLabel.setObjectName("savePathLabel")
  476. self.savePathEdit = QtWidgets.QLineEdit(self.centralwidget)
  477. self.savePathEdit.setGeometry(QtCore.QRect(310, 170, 151, 21))
  478. self.savePathEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  479. font = QtGui.QFont()
  480. font.setFamily("Arial")
  481. font.setPointSize(8)
  482. self.savePathEdit.setFont(font)
  483. self.savePathEdit.setObjectName("savePathEdit")
  484. self.savePathTool = QtWidgets.QToolButton(self.centralwidget)
  485. self.savePathTool.setGeometry(QtCore.QRect(470, 170, 71, 21))
  486. font = QtGui.QFont()
  487. font.setFamily("Arial")
  488. font.setPointSize(10)
  489. self.savePathTool.setFont(font)
  490. self.savePathTool.setObjectName("savePathTool")
  491. self.startTimeLabel = QtWidgets.QLabel(self.centralwidget)
  492. self.startTimeLabel.setGeometry(QtCore.QRect(180, 210, 121, 21))
  493. self.startTimeLabel.setObjectName("startTimeLabel")
  494. self.startTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  495. self.startTimeEdit.setGeometry(QtCore.QRect(310, 210, 151, 21))
  496. self.startTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2025, 12, 31), QtCore.QTime(23, 59, 59)))
  497. self.startTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2023, 4, 24), QtCore.QTime(0, 0, 0)))
  498. self.startTimeEdit.setObjectName("startTimeEdit")
  499. self.endTimeLabel = QtWidgets.QLabel(self.centralwidget)
  500. self.endTimeLabel.setGeometry(QtCore.QRect(180, 250, 121, 21))
  501. self.endTimeLabel.setObjectName("endTimeLabel")
  502. self.endTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  503. self.endTimeEdit.setGeometry(QtCore.QRect(310, 250, 151, 21))
  504. self.endTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2025, 12, 31), QtCore.QTime(23, 59, 59)))
  505. self.endTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2023, 4, 25), QtCore.QTime(0, 0, 0)))
  506. self.endTimeEdit.setObjectName("endTimeEdit")
  507. self.platLabel = QtWidgets.QLabel(self.centralwidget)
  508. self.platLabel.setGeometry(QtCore.QRect(180, 290, 121, 21))
  509. self.platLabel.setObjectName("dianjiLabel")
  510. self.platBox = QtWidgets.QComboBox(self.centralwidget)
  511. self.platBox.setGeometry(QtCore.QRect(310, 290, 151, 21))
  512. self.platBox.addItems(['大数据平台','四情平台'])
  513. font = QtGui.QFont()
  514. font.setFamily("Arial")
  515. font.setPointSize(11)
  516. self.platBox.setFont(font)
  517. self.platBox.setObjectName("platBox")
  518. self.stm8vsLabel = QtWidgets.QLabel(self.centralwidget)
  519. self.stm8vsLabel.setGeometry(QtCore.QRect(180, 330, 121, 21))
  520. self.stm8vsLabel.setObjectName("stm8vsLabel")
  521. self.stm8vsEdit = QtWidgets.QLineEdit(self.centralwidget)
  522. self.stm8vsEdit.setGeometry(QtCore.QRect(310, 330, 151, 21))
  523. font = QtGui.QFont()
  524. font.setFamily("Arial")
  525. font.setPointSize(11)
  526. self.stm8vsEdit.setFont(font)
  527. self.stm8vsEdit.setObjectName("stm8vsEdit")
  528. font = QtGui.QFont()
  529. font.setFamily("Arial")
  530. font.setPointSize(11)
  531. self.orderLabel = QtWidgets.QLabel(self.centralwidget)
  532. self.orderLabel.setGeometry(QtCore.QRect(180, 370, 121, 21))
  533. self.orderLabel.setObjectName("dverLabel")
  534. self.orderEdit = QtWidgets.QLineEdit(self.centralwidget)
  535. self.orderEdit.setGeometry(QtCore.QRect(310, 370, 151, 21))
  536. font = QtGui.QFont()
  537. font.setFamily("Arial")
  538. font.setPointSize(11)
  539. self.orderEdit.setFont(font)
  540. self.orderEdit.setObjectName("dverEdit")
  541. self.pushButton = QtWidgets.QPushButton(self.centralwidget)
  542. self.pushButton.setGeometry(QtCore.QRect(300, 410, 111, 41))
  543. self.pushButton.setObjectName("pushButton")
  544. self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
  545. self.progressBar.setGeometry(QtCore.QRect(130, 470, 491, 31))
  546. self.progressBar.setProperty("value", 0)
  547. self.progressBar.setVisible(False)
  548. self.progressBar.setObjectName("progressBar")
  549. MainWindow.setCentralWidget(self.centralwidget)
  550. self.retranslateUi(MainWindow)
  551. self.inputFileTool.clicked.connect(self.input_file_path)
  552. self.savePathTool.clicked.connect(self.out_save_location)
  553. self.pushButton.clicked.connect(self.on_click)
  554. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  555. def retranslateUi(self, MainWindow):
  556. _translate = QtCore.QCoreApplication.translate
  557. MainWindow.setWindowTitle(_translate("MainWindow", "气象站质检工具"))
  558. self.savePathTool.setText(_translate("MainWindow", "选择文件夹"))
  559. self.inputFileTool.setText(_translate("MainWindow", "选择文件"))
  560. self.pageTitleLabel.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600; color:#3a45aa;\">云飞气象站设备质检工具</span></p></body></html>"))
  561. self.savePathLabel.setText(_translate("MainWindow", "|输出文件位置:"))
  562. self.inputFileLabel.setText(_translate("MainWindow", "|输入文件位置:"))
  563. self.startTimeLabel.setText(_translate("MainWindow", "|开始时间:"))
  564. self.endTimeLabel.setText(_translate("MainWindow", "|结束时间:"))
  565. self.platLabel.setText(_translate("MainWindow", "|检验平台:"))
  566. self.stm8vsLabel.setText(_translate("MainWindow", "|主板版本号:"))
  567. self.orderLabel.setText(_translate("MainWindow", "|任务单号:"))
  568. self.pushButton.setText(_translate("MainWindow", "开始导出"))
  569. def input_file_path(self):
  570. file_path = QtWidgets.QFileDialog.getOpenFileName(None,"选取文件","./","All Files (*.xlsx;*.xls);;Text Files (*.txt);;ALL(*)")
  571. self.inputFileEdit.setText(file_path[0])
  572. self.inputFileEdit.setStyleSheet("color:black;")
  573. def out_save_location(self):
  574. fname = QtWidgets.QFileDialog.getExistingDirectory(None, '选取文件夹', './')
  575. self.savePathEdit.setText(fname)
  576. self.savePathEdit.setStyleSheet("color:black;")
  577. def on_click(self):
  578. file_path = self.inputFileEdit.text()
  579. save_path = self.savePathEdit.text()
  580. start_time = self.startTimeEdit.dateTime().toPyDateTime()
  581. end_time = self.endTimeEdit.dateTime().toPyDateTime()
  582. set_plat = self.platBox.currentText()
  583. set_stm8vs = self.stm8vsEdit.text()
  584. set_order = self.orderEdit.text()
  585. if not all ([file_path,save_path,start_time,end_time,set_stm8vs,set_order]):
  586. QtWidgets.QMessageBox.information(None, "提示", "选项未填写完整")
  587. elif end_time < start_time:
  588. QtWidgets.QMessageBox.information(None, "提示", "结束日期应在开始日期之后")
  589. else:
  590. read_dict = {}
  591. if file_path.split(".")[-1] == "xlsx":
  592. wb = openpyxl.load_workbook(file_path)
  593. sheet = wb[wb.sheetnames[0]]
  594. row_num = sheet.max_row
  595. d_list = []
  596. for row in range(2, row_num + 1):
  597. cell = sheet.cell(row, 1)
  598. try:
  599. cell_value = cell.value.strip()
  600. if cell_value:
  601. d_list.append(cell.value)
  602. except Exception as e:
  603. continue
  604. read_dict["设备ID"] = d_list
  605. else:
  606. xls = open_workbook(file_path)
  607. sheet_object = xls.sheets()[0]
  608. ncols = sheet_object.ncols
  609. d_list = []
  610. col_value = sheet_object.col_values(0)
  611. for d_i in col_value[1:]:
  612. try:
  613. d_i_v = d_i.strip()
  614. d_list.append(d_i_v)
  615. except Exception as e:
  616. continue
  617. read_dict["设备ID"] = d_list
  618. device_list = read_dict.get("设备ID")
  619. if device_list:
  620. self.inputFileTool.setEnabled(False)
  621. self.savePathTool.setEnabled(False)
  622. self.startTimeEdit.setEnabled(False)
  623. self.endTimeEdit.setEnabled(False)
  624. self.platBox.setEnabled(False)
  625. self.stm8vsEdit.setEnabled(False)
  626. self.orderEdit.setEnabled(False)
  627. self.pushButton.setEnabled(False)
  628. self.pushButton.setText("执行中...")
  629. self.runThread = SCDThread(device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_order)
  630. self.runThread.proess_signal.connect(self.set_progressbar_value)
  631. self.runThread.start()
  632. self.progressBar.setVisible(True)
  633. else:
  634. QtWidgets.QMessageBox.information(None, "提示", "输入文件无'设备ID'列或该列无数据")
  635. def set_progressbar_value(self, value):
  636. self.progressBar.setValue(value)
  637. if value == 100:
  638. QtWidgets.QMessageBox.information(None, "提示", "文件导出完毕!导出文件名:\n{}".format(save_filename))
  639. self.inputFileTool.setEnabled(True)
  640. self.inputFileEdit.setText("")
  641. self.savePathTool.setEnabled(True)
  642. self.savePathEdit.setText("")
  643. self.startTimeEdit.setEnabled(True)
  644. self.endTimeEdit.setEnabled(True)
  645. self.platBox.setEnabled(True)
  646. self.stm8vsEdit.setEnabled(True)
  647. self.stm8vsEdit.setText("")
  648. self.orderEdit.setEnabled(True)
  649. self.orderEdit.setText("")
  650. self.pushButton.setEnabled(True)
  651. self.pushButton.setText("开始导出")
  652. self.progressBar.setVisible(False)
  653. self.progressBar.setValue(0)
  654. return
  655. class SCDThread(QtCore.QThread):
  656. """涉及进度条需主界面动态执行GUI,线程执行业务逻辑,避免主页面卡死"""
  657. proess_signal = QtCore.pyqtSignal(int)
  658. def __init__(self,device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_order):
  659. super(SCDThread, self).__init__()
  660. self.device_list = device_list
  661. self.save_path = save_path
  662. self.start_time = time.mktime(start_time.timetuple())
  663. self.end_time = time.mktime(end_time.timetuple())
  664. self.start_time_str = start_time.strftime("%y-%m-%d %H:%M:%S")
  665. self.end_time_str = end_time.strftime("%y-%m-%d %H:%M:%S")
  666. self.set_plat = set_plat
  667. self.set_stm8vs = set_stm8vs
  668. self.set_order = set_order
  669. self.user = parse.quote_plus("root")
  670. self.passwd = parse.quote_plus("yfkj@6020")
  671. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  672. self.db = self.myclient.smartfarming
  673. self.device_collection = self.db.sa_device
  674. self.qxz_collection = self.db.sa_device_qxz_data
  675. self.config = {
  676. 'host': '120.27.222.26',
  677. 'port': 3306,
  678. 'user': 'yfwlw',
  679. 'password': 'sql_yfkj_6019',
  680. 'db': 'yfwlw',
  681. 'charset': 'utf8mb4',
  682. 'cursorclass': pymysql.cursors.DictCursor,
  683. }
  684. self.connection = pymysql.connect(**self.config)
  685. self.cursor = self.connection.cursor()
  686. self.cond = QxzCand()
  687. self.mongo_ping()
  688. def mongo_ping(self):
  689. """mongo-ping预防连接失效"""
  690. # try:
  691. # self.myclient.admin.command('ping')
  692. # except: # "ConnectionFailure"
  693. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  694. self.db = self.myclient.smartfarming
  695. self.device_collection = self.db.sa_device
  696. self.qxz_collection = self.db.sa_qxz_data
  697. self.qxz_info_record_collection = self.db.sa_qxz_info_record
  698. self.qxz_base_info_collection = self.db.sa_qxz_base_info
  699. # self.sa_qxz_conf = self.db.
  700. def sql_ping(self):
  701. """mysql-ping 预防连接失效"""
  702. try:
  703. self.connection.ping()
  704. except:
  705. self.connection = pymysql.connect(**self.config)
  706. self.cursor = self.connection.cursor()
  707. def __time_dif(self,checkdatetime):
  708. """计算时间差"""
  709. nowdatetime = datetime.datetime.now()
  710. checkdatetime = datetime.datetime.strptime(checkdatetime, "%Y-%m-%d %H:%M:%S")
  711. timedif = checkdatetime - nowdatetime
  712. return timedif.days
  713. def device_their_platform(self,shortId):
  714. """确定设备所在平台以及完整设备号"""
  715. self.mongo_ping()
  716. self.sql_ping()
  717. regex = re.compile('.*{}$'.format(shortId))
  718. bd_device_dict = self.device_collection.find_one(
  719. filter = {"device_id":regex,"device_type_id":5},
  720. projection = {'_id': 0},
  721. sort = [('uptime', pymongo.DESCENDING)]
  722. )
  723. device_sql = "SELECT * FROM AppInfoManage_qxzstatus_new WHERE equip_id_id LIKE '%{}' ORDER BY upl_time DESC LIMIT 1;".format(shortId)
  724. self.cursor.execute(device_sql)
  725. sq_device_dict = self.cursor.fetchone()
  726. if bd_device_dict and sq_device_dict:
  727. bd_upltime = bd_device_dict["uptime"]
  728. sq_upltime = time.mktime(sq_device_dict["upl_time"].timetuple())
  729. if bd_upltime >= sq_upltime:
  730. d_id = bd_device_dict["id"]
  731. deviceId = bd_device_dict["device_id"]
  732. platform = "大数据平台"
  733. else:
  734. d_id = ""
  735. deviceId = sq_device_dict["equip_id_id"]
  736. platform = "四情平台"
  737. elif bd_device_dict and not sq_device_dict:
  738. d_id = bd_device_dict["id"]
  739. deviceId = bd_device_dict["device_id"]
  740. platform = "大数据平台"
  741. return d_id,deviceId,platform
  742. elif not bd_device_dict and sq_device_dict:
  743. d_id = ""
  744. deviceId = sq_device_dict["equip_id_id"]
  745. platform = "四情平台"
  746. else:
  747. d_id = ""
  748. deviceId = "平台无此设备"
  749. platform = "未知"
  750. print("deviceId:",deviceId)
  751. return d_id,deviceId,platform
  752. def sim_info(self, iccid):
  753. """查询卡信息"""
  754. url = "http://8.136.98.49:10001/iotcard/platsimview/inquiries/"
  755. try:
  756. response = requests.request("POST", url, data={"iccid": iccid})
  757. except:
  758. return [0, "查询卡信息异常稍后重试"]
  759. else:
  760. res_data = json.loads(response.text)
  761. if res_data["msg"] == "success" and res_data["data"]:
  762. expiry_date = res_data["data"]["expiry_date"]
  763. if expiry_date == "未知":
  764. return [0, "未查询到卡信息"]
  765. else:
  766. time_difference = self.__time_dif(expiry_date)
  767. if time_difference >= 180:
  768. return [1, "有效期剩余{}天".format(time_difference)]
  769. elif 30 <= time_difference < 180:
  770. return [2, "有效期剩余{}天".format(time_difference)]
  771. else:
  772. return [0, "有效期剩余{}天".format(time_difference)]
  773. else:
  774. return [0, "查询无结果"]
  775. def _get_data_new(self):
  776. """获取最新设备数据信息"""
  777. pipeline = [
  778. {
  779. "$match": {
  780. "device_id": {"$in": self.device_list}
  781. }
  782. },
  783. {
  784. "$group": {
  785. "_id": {"device_id": "$device_id"},
  786. "last_msg": {"$last": "$$ROOT"}
  787. }
  788. },
  789. {
  790. "$replaceRoot": {"newRoot": "$last_msg"}
  791. }
  792. ]
  793. cursor = self.db.sa_qxz_data.aggregate(pipeline, allowDiskUse=True)
  794. data_dict = {item['device_id']: item for item in cursor}
  795. return data_dict
  796. def _get_bigdata_qxz_conf(self):
  797. data_dict = self._get_data_new()
  798. cursor = self.db.sa_qxz_conf.find({"device_id": {"$in": self.device_list}})
  799. title_name_set = set()
  800. qxz_conf_dict = {}
  801. for item in cursor:
  802. device_id = item['device_id']
  803. qxz_data = data_dict[device_id]
  804. config_dict = {}
  805. counter = Counter()
  806. for k, v in item.items():
  807. if k.startswith('e') and v and qxz_data.get(k, None):
  808. t_name = v.split('#')[0]
  809. t_index = counter.get(t_name, "")
  810. config_dict[k] = f"{t_name}#{t_index}"
  811. counter[t_name] += 1
  812. n_list = list(config_dict.values())
  813. title_name_set.update(n_list)
  814. qxz_conf_dict[device_id] = config_dict
  815. title_name_list = sorted(list(title_name_set))
  816. for i in title_name_list:
  817. print(i)
  818. for k, v in qxz_conf_dict.items():
  819. print(k, v)
  820. return title_name_list, qxz_conf_dict
  821. def get_qxz_element_data(self, device_id, conf_dict):
  822. group_dict = {
  823. "_id": "$device_id",
  824. "total_count": {"$count": {}},
  825. "uptime_list": {"$push": "$uptime"}
  826. }
  827. project_dict = {
  828. "_id": 0,
  829. "device_id": "$_id",
  830. "total_count": "$total_count",
  831. "uptime_info": {
  832. "$function": {
  833. "args": ["$uptime_list"],
  834. "lang": "js",
  835. "body": """
  836. function(uptime_list){
  837. let old_uptime = uptime_list[0];
  838. let uptime_20 = 0;
  839. let uptime_40 = 0;
  840. for (let i = 1; i < uptime_list.length; i++) {
  841. let uptime = uptime_list[i];
  842. let diff_time = uptime - old_uptime;
  843. if (diff_time < 1200){
  844. uptime_20 += 1;
  845. } else if (diff_time > 2400){
  846. uptime_40 += 1;
  847. }
  848. old_uptime = uptime;
  849. }
  850. return {"uptime_20": uptime_20, "uptime_40": uptime_40}
  851. }
  852. """
  853. }
  854. }
  855. }
  856. for ek in conf_dict.keys():
  857. group_dict[ek] = {"$push": f"${ek}"}
  858. try:
  859. k = conf_dict[ek]
  860. func_name = self.get_conf_key(k)
  861. project_dict[ek] = self.cond.func_dict[func_name](ek)
  862. except KeyError as e:
  863. continue
  864. pipeline = [
  865. {
  866. "$match": {
  867. "device_id": device_id,
  868. "uptime": {
  869. "$gte": self.start_time,
  870. "$lt": self.end_time
  871. }
  872. }
  873. },
  874. {
  875. "$sort": {"uptime": 1}
  876. },
  877. {
  878. "$project": {
  879. "device_id": "$device_id",
  880. "uptime": "$uptime",
  881. "tmp_list": {
  882. "$filter": {
  883. "input": {"$objectToArray": "$$ROOT"},
  884. "as": "item",
  885. "cond": {
  886. "$and": [
  887. {
  888. "$regexMatch": {
  889. "input": "$$item.k",
  890. "regex": "^e\d+",
  891. "options": "i"
  892. }
  893. },
  894. {
  895. "$regexMatch": {
  896. "input": "$$item.v",
  897. "regex": ".*#.*",
  898. "options": "i"
  899. }
  900. }
  901. ]
  902. }
  903. }
  904. }
  905. }
  906. },
  907. {
  908. "$addFields": {
  909. "tmp_obj": {
  910. "$arrayToObject": {
  911. "$map": {
  912. "input": "$tmp_list",
  913. "as": "item",
  914. "in": {
  915. "k": "$$item.k",
  916. "v": {
  917. "$toInt": {
  918. "$toDouble": {"$arrayElemAt": [{"$split": ["$$item.v", "#"]}, 0]}
  919. }
  920. }
  921. }
  922. }
  923. }
  924. }
  925. }
  926. },
  927. {
  928. "$replaceRoot": {
  929. "newRoot": {
  930. "$mergeObjects": ["$tmp_obj", {"device_id": "$device_id", "uptime": "$uptime"}]
  931. }
  932. }
  933. },
  934. {
  935. "$group": group_dict
  936. },
  937. {
  938. "$project": project_dict
  939. }
  940. ]
  941. cursor = self.db.sa_qxz_data.aggregate(pipeline, allowDiskUse=True)
  942. result = {k: v for item in cursor for k, v in item.items()}
  943. return result
  944. def get_qxz_volt_or_rssi_data(self):
  945. pipeline = [
  946. {
  947. "$match": {
  948. "device_id": {
  949. "$in": self.device_list
  950. }
  951. },
  952. },
  953. {
  954. "$project": {
  955. "device_id": "$device_id",
  956. "volt": {
  957. "$toDouble": "$volt"
  958. },
  959. "rssi": {
  960. "$toDouble": "$rssi"
  961. }
  962. }
  963. },
  964. {
  965. "$group": {
  966. "_id": "$device_id",
  967. "max_volt": {
  968. "$max": "$volt"
  969. },
  970. "min_volt": {
  971. "$min": "$volt"
  972. },
  973. "max_rssi": {
  974. "$max": "$rssi"
  975. },
  976. "min_rssi": {
  977. "$min": "$rssi"
  978. }
  979. }
  980. },
  981. {
  982. "$project": {
  983. "_id": 0,
  984. "device_id": "$_id",
  985. "volt_info": {
  986. 'max_value': "$max_volt", 'min_value': "$min_volt",
  987. 'status': {
  988. "$cond": {
  989. "if": {
  990. "$and": [
  991. {"$lte": ["$max_volt", 12.5]},
  992. {"$gte": ["$min_volt", 11.5]}
  993. ]
  994. },
  995. "then": 1,
  996. "else": 0
  997. }
  998. }
  999. },
  1000. "rssi_info": {
  1001. 'max_value': "$max_rssi", 'min_value': "$min_rssi",
  1002. 'status': {
  1003. "$cond": {
  1004. "if": {
  1005. "$gte": ["$min_rssi", 14]
  1006. },
  1007. "then": 1,
  1008. "else": 0
  1009. }
  1010. }
  1011. }
  1012. }
  1013. }
  1014. ]
  1015. cursor = self.qxz_info_record_collection.aggregate(pipeline, allowDiskUse=True)
  1016. result = {item['device_id']: item for item in cursor}
  1017. return result
  1018. def get_qxz_device_data(self):
  1019. pipeline = [
  1020. {
  1021. "$match": {
  1022. "device_id": {
  1023. "$in": self.device_list
  1024. }
  1025. },
  1026. },
  1027. {
  1028. "$project": {
  1029. "device_id": "$device_id",
  1030. "dver_num": "$dver_num",
  1031. "lng": {
  1032. "$convert": {
  1033. "input": "$lng",
  1034. "to": "double",
  1035. "onError": 0,
  1036. "onNull": 0
  1037. }
  1038. },
  1039. "lat": {
  1040. "$convert": {
  1041. "input": "$lat",
  1042. "to": "double",
  1043. "onError": 0,
  1044. "onNull": 0
  1045. }
  1046. }
  1047. }
  1048. },
  1049. {
  1050. "$project": {
  1051. "_id": 0,
  1052. "device_id": "$device_id",
  1053. "dver_info": {
  1054. "status": {
  1055. "$cond": {
  1056. "if": {
  1057. "$eq": ["$dver_num", self.set_stm8vs]
  1058. },
  1059. "then": 1,
  1060. "else": 0
  1061. }
  1062. },
  1063. "dver_num": "$dver_num",
  1064. "old_value": self.set_stm8vs
  1065. },
  1066. "lng_info": {
  1067. "status": {
  1068. "$cond": {
  1069. "if": {
  1070. "$and": [
  1071. {"$lte": ["$lng", 113.7869444]},
  1072. {"$gte": ["$lng", 113.7536111]}
  1073. ]
  1074. },
  1075. "then": 1,
  1076. "else": 0
  1077. }
  1078. },
  1079. "lng": "$lng"
  1080. },
  1081. "lat_info": {
  1082. "status": {
  1083. "$cond": {
  1084. "if": {
  1085. "$and": [
  1086. {"$lte": ["$lat", 35.0458333]},
  1087. {"$gte": ["$lat", 35.0125]}
  1088. ]
  1089. },
  1090. "then": 1,
  1091. "else": 0
  1092. }
  1093. },
  1094. "lat": "$lat"
  1095. }
  1096. }
  1097. }
  1098. ]
  1099. cursor = self.device_collection.aggregate(pipeline, allowDiskUse=True)
  1100. result = {item['device_id']: item for item in cursor}
  1101. return result
  1102. def get_sim_data(self):
  1103. pipeline = [
  1104. {
  1105. "$match": {
  1106. "device_id": {
  1107. "$in": self.device_list
  1108. }
  1109. }
  1110. },
  1111. {
  1112. "$project": {
  1113. "_id": 0,
  1114. "device_id": "$device_id",
  1115. "iccid": "$iccid"
  1116. }
  1117. }
  1118. ]
  1119. cursor = self.qxz_base_info_collection.aggregate(pipeline, allowDiskUse=True)
  1120. result = {item['device_id']: item["iccid"] for item in cursor}
  1121. return result
  1122. def parse_data(self, device_id, qxz_conf_dict, vr_dict, device_data_dict, sim_data):
  1123. """解析获取元素数据"""
  1124. element_dict = {}
  1125. element_dict["ID#"] = device_id
  1126. element_dict["检验项目#"] = device_id
  1127. try:
  1128. conf_dict = qxz_conf_dict[device_id]
  1129. device_data = self.get_qxz_element_data(device_id, conf_dict)
  1130. element_dict.update({conf_dict[k]: v for k, v in device_data.items() if k in conf_dict})
  1131. vr_info = vr_dict[device_id]
  1132. dd_info = device_data_dict[device_id]
  1133. element_dict["经度#"] = dd_info["lng_info"]
  1134. element_dict["纬度#"] = dd_info["lat_info"]
  1135. element_dict["固件版本号#"] = dd_info["dver_info"]
  1136. element_dict["电压#"] = vr_info["volt_info"]
  1137. element_dict["信号强度#"] = vr_info["rssi_info"]
  1138. sim_info = self.sim_info(sim_data[device_id])
  1139. element_dict["sim卡信息#"] = {
  1140. "status": sim_info[0],
  1141. "msg": sim_info[1]
  1142. }
  1143. element_dict["上传数据条数#"] = {
  1144. "total_count": device_data['total_count'],
  1145. "uptime_20": device_data["uptime_info"]["uptime_20"],
  1146. "uptime_40": device_data["uptime_info"]["uptime_40"]
  1147. }
  1148. except KeyError as e:
  1149. pass
  1150. return element_dict
  1151. def get_conf_key(self, k):
  1152. key = k.split('#')[0]
  1153. if "土壤含水率" in key:
  1154. key = "土壤含水率"
  1155. if "土壤温度" in key:
  1156. key = "土壤温度"
  1157. return key
  1158. def run(self):
  1159. """主业务逻辑,涉及进度条不能模块化,慢慢捋"""
  1160. title_name_list = ["ID#", "检验项目#", "电压#", "信号强度#", "经度#", "纬度#", "固件版本号#", "sim卡信息#",
  1161. "上传数据条数#"]
  1162. default_func_dict = {
  1163. "电压": self.cond.get_cond_volt_msg,
  1164. "信号强度": self.cond.get_cond_rssi_msg,
  1165. "经度": self.cond.get_cond_lng_msg,
  1166. "纬度": self.cond.get_cond_lat_msg,
  1167. "固件版本号": self.cond.get_cond_version_msg,
  1168. "上传数据条数": self.cond.get_time_uptime_msg,
  1169. "sim卡信息": self.cond.get_cond_sim_msg
  1170. }
  1171. head_name_list, qxz_conf_dict = self._get_bigdata_qxz_conf()
  1172. for n in head_name_list:
  1173. if n not in title_name_list:
  1174. title_name_list.append(n)
  1175. title_name_list.append("单台合格数#")
  1176. device_data_dict = self.get_qxz_device_data()
  1177. vr_dict = self.get_qxz_volt_or_rssi_data()
  1178. sim_data = self.get_sim_data()
  1179. proess = 0
  1180. now_time = datetime.datetime.now()
  1181. global save_filename
  1182. save_filename = self.set_order + "_" + now_time.strftime("%m%d") + ".xlsx"
  1183. save_path = os.path.join(self.save_path,save_filename)
  1184. workbook = Workbook(save_path)
  1185. worksheet = workbook.add_worksheet()
  1186. merge_title_style = workbook.add_format(merge_title_format)
  1187. toji_style = workbook.add_format(toji_format)
  1188. default_style = workbook.add_format(default_formal)
  1189. red_style = workbook.add_format(error_format)
  1190. green_style = workbook.add_format(formal_format)
  1191. yellow_style = workbook.add_format(common_format)
  1192. style_dict = {
  1193. 0: red_style,
  1194. 1: green_style,
  1195. 2: yellow_style,
  1196. 3: default_style
  1197. }
  1198. head_list = [i.split("#")[0] for i in title_name_list]
  1199. worksheet.merge_range(0, 0, 0, len(head_list) - 1, "物联网气象站设备质检表格", merge_title_style)
  1200. for index, k in enumerate(title_name_list):
  1201. value = k.split('#')[0]
  1202. worksheet.write(2, index, value, default_style)
  1203. for index, k in enumerate(title_name_list):
  1204. key = self.get_conf_key(k)
  1205. try:
  1206. value = self.cond.head_dict[key]
  1207. except KeyError as e:
  1208. value = "无判定条件"
  1209. worksheet.write(3, index, value, default_style)
  1210. row_index = 4
  1211. qualified = 0
  1212. for device_id in self.device_list:
  1213. self.mongo_ping()
  1214. element_dict = self.parse_data(device_id, qxz_conf_dict, vr_dict, device_data_dict, sim_data)
  1215. not_qualified = 0
  1216. for index, k in enumerate(title_name_list):
  1217. status, msg = 3, "无数据"
  1218. try:
  1219. value = element_dict[k]
  1220. key = self.get_conf_key(k)
  1221. if key in ["ID", "检验项目"]:
  1222. rt = {"status": 1, "msg": value}
  1223. elif key in default_func_dict:
  1224. rt = default_func_dict[key](value)
  1225. else:
  1226. rt = self.cond.cond_msg_dict[key](value)
  1227. status, msg = rt['status'], rt['msg']
  1228. except Exception as e:
  1229. print('-----------', e)
  1230. pass
  1231. if status == 0:
  1232. not_qualified += 1
  1233. if k == "单台合格数#":
  1234. status, msg = 0, f"不合格: {not_qualified}"
  1235. if not_qualified == 0:
  1236. status, msg = 1, "合格"
  1237. column_style = style_dict[status]
  1238. worksheet.write(row_index, index, str(msg), column_style)
  1239. proess = (index + 1) / len(self.device_list) * 100
  1240. if int(proess) == 100:
  1241. self.proess_signal.emit(99)
  1242. else:
  1243. self.proess_signal.emit(int(proess))
  1244. if not_qualified == 0:
  1245. qualified += 1
  1246. row_index += 1
  1247. toji_data = [
  1248. "任务单号", self.set_order, "检验时间", self.start_time_str, self.end_time_str,
  1249. "报告日期", now_time.strftime("%y-%m-%d %H:%M:%S"), "合格数", qualified
  1250. ]
  1251. for i in range(len(head_list) - len(toji_data)):
  1252. toji_data.append(" ")
  1253. for index, k in enumerate(toji_data):
  1254. value = str(k)
  1255. worksheet.write(1, index, value, toji_style)
  1256. c_n = len(value) + 15
  1257. worksheet.set_column(index, index, c_n)
  1258. worksheet.protect(pwd_str)
  1259. workbook.close()
  1260. self.cursor.close()
  1261. self.connection.close()
  1262. self.myclient.close()
  1263. self.proess_signal.emit(100)
  1264. if __name__== "__main__":
  1265. QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
  1266. QtGui.QGuiApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
  1267. app = QtWidgets.QApplication(sys.argv)
  1268. MainWindow = QtWidgets.QMainWindow()
  1269. ui = Ui_MainWindow()
  1270. ui.setupUi(MainWindow)
  1271. MainWindow.show()
  1272. sys.exit(app.exec_())