scd_zhijian.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  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\scd_zhijian.py -i .\LOGO.ico
  9. from aliyunsdkcore.vendored.requests.auth import HTTPBasicAuth
  10. from PyQt5 import QtCore, QtGui, QtWidgets
  11. import hashlib
  12. import os
  13. import sys
  14. import re
  15. import ast
  16. from urllib import parse
  17. import json
  18. import time
  19. import datetime
  20. import requests
  21. import uuid
  22. import pymongo
  23. import pymysql
  24. from xlrd import open_workbook
  25. from xlsxwriter.workbook import Workbook
  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. class Ui_MainWindow(object):
  124. """GUI界面"""
  125. def setupUi(self, MainWindow):
  126. MainWindow.setObjectName("MainWindow")
  127. MainWindow.resize(701, 644)
  128. font = QtGui.QFont()
  129. font.setFamily("Arial")
  130. font.setPointSize(12)
  131. MainWindow.setFont(font)
  132. icon = QtGui.QIcon("logo.ico")
  133. MainWindow.setWindowIcon(icon)
  134. self.centralwidget = QtWidgets.QWidget(MainWindow)
  135. self.centralwidget.setObjectName("centralwidget")
  136. self.pageTitleLabel = QtWidgets.QLabel(self.centralwidget)
  137. self.pageTitleLabel.setGeometry(QtCore.QRect(139, 50, 429, 42))
  138. font = QtGui.QFont()
  139. font.setFamily("楷体")
  140. font.setPointSize(28)
  141. self.pageTitleLabel.setFont(font)
  142. self.pageTitleLabel.setTextFormat(QtCore.Qt.AutoText)
  143. self.pageTitleLabel.setObjectName("pageTitleLabel")
  144. self.inputFileLabel = QtWidgets.QLabel(self.centralwidget)
  145. self.inputFileLabel.setGeometry(QtCore.QRect(180, 130, 121, 21))
  146. self.inputFileLabel.setObjectName("inputFileLabel")
  147. self.inputFileEdit = QtWidgets.QLineEdit(self.centralwidget)
  148. self.inputFileEdit.setGeometry(QtCore.QRect(310, 130, 151, 21))
  149. self.inputFileEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  150. font = QtGui.QFont()
  151. font.setFamily("Arial")
  152. font.setPointSize(8)
  153. self.inputFileEdit.setFont(font)
  154. self.inputFileEdit.setObjectName("inputFileEdit")
  155. self.inputFileTool = QtWidgets.QToolButton(self.centralwidget)
  156. self.inputFileTool.setGeometry(QtCore.QRect(470, 130, 71, 21))
  157. font = QtGui.QFont()
  158. font.setFamily("Arial")
  159. font.setPointSize(10)
  160. self.inputFileTool.setFont(font)
  161. self.inputFileTool.setObjectName("inputFileTool")
  162. self.savePathLabel = QtWidgets.QLabel(self.centralwidget)
  163. self.savePathLabel.setGeometry(QtCore.QRect(180, 170, 121, 21))
  164. self.savePathLabel.setObjectName("savePathLabel")
  165. self.savePathEdit = QtWidgets.QLineEdit(self.centralwidget)
  166. self.savePathEdit.setGeometry(QtCore.QRect(310, 170, 151, 21))
  167. self.savePathEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  168. font = QtGui.QFont()
  169. font.setFamily("Arial")
  170. font.setPointSize(8)
  171. self.savePathEdit.setFont(font)
  172. self.savePathEdit.setObjectName("savePathEdit")
  173. self.savePathTool = QtWidgets.QToolButton(self.centralwidget)
  174. self.savePathTool.setGeometry(QtCore.QRect(470, 170, 71, 21))
  175. font = QtGui.QFont()
  176. font.setFamily("Arial")
  177. font.setPointSize(10)
  178. self.savePathTool.setFont(font)
  179. self.savePathTool.setObjectName("savePathTool")
  180. self.startTimeLabel = QtWidgets.QLabel(self.centralwidget)
  181. self.startTimeLabel.setGeometry(QtCore.QRect(180, 210, 121, 21))
  182. self.startTimeLabel.setObjectName("startTimeLabel")
  183. self.startTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  184. self.startTimeEdit.setGeometry(QtCore.QRect(310, 210, 151, 21))
  185. self.startTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2025, 12, 31), QtCore.QTime(23, 59, 59)))
  186. self.startTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2024, 3, 29), QtCore.QTime(1, 0, 0)))
  187. self.startTimeEdit.setObjectName("startTimeEdit")
  188. self.endTimeLabel = QtWidgets.QLabel(self.centralwidget)
  189. self.endTimeLabel.setGeometry(QtCore.QRect(180, 250, 121, 21))
  190. self.endTimeLabel.setObjectName("endTimeLabel")
  191. self.endTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  192. self.endTimeEdit.setGeometry(QtCore.QRect(310, 250, 151, 21))
  193. self.endTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2025, 12, 31), QtCore.QTime(23, 59, 59)))
  194. self.endTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2024, 3, 30), QtCore.QTime(1, 0, 0)))
  195. self.endTimeEdit.setObjectName("endTimeEdit")
  196. self.platLabel = QtWidgets.QLabel(self.centralwidget)
  197. self.platLabel.setGeometry(QtCore.QRect(180, 290, 121, 21))
  198. self.platLabel.setObjectName("dianjiLabel")
  199. self.platBox = QtWidgets.QComboBox(self.centralwidget)
  200. self.platBox.setGeometry(QtCore.QRect(310, 290, 151, 21))
  201. self.platBox.addItems(['大数据平台','四情平台'])
  202. font = QtGui.QFont()
  203. font.setFamily("Arial")
  204. font.setPointSize(11)
  205. self.platBox.setFont(font)
  206. self.platBox.setObjectName("platBox")
  207. self.stm8vsLabel = QtWidgets.QLabel(self.centralwidget)
  208. self.stm8vsLabel.setGeometry(QtCore.QRect(180, 330, 121, 21))
  209. self.stm8vsLabel.setObjectName("stm8vsLabel")
  210. self.stm8vsEdit = QtWidgets.QLineEdit(self.centralwidget)
  211. self.stm8vsEdit.setGeometry(QtCore.QRect(310, 330, 151, 21))
  212. font = QtGui.QFont()
  213. font.setFamily("Arial")
  214. font.setPointSize(11)
  215. self.stm8vsEdit.setFont(font)
  216. self.stm8vsEdit.setObjectName("stm8vsEdit")
  217. self.dverLabel = QtWidgets.QLabel(self.centralwidget)
  218. self.dverLabel.setGeometry(QtCore.QRect(180, 370, 121, 21))
  219. self.dverLabel.setObjectName("dverLabel")
  220. self.dverEdit = QtWidgets.QLineEdit(self.centralwidget)
  221. self.dverEdit.setGeometry(QtCore.QRect(310, 370, 151, 21))
  222. font = QtGui.QFont()
  223. font.setFamily("Arial")
  224. font.setPointSize(11)
  225. self.dverEdit.setFont(font)
  226. self.dverEdit.setObjectName("dverEdit")
  227. self.orderLabel = QtWidgets.QLabel(self.centralwidget)
  228. self.orderLabel.setGeometry(QtCore.QRect(180, 410, 121, 21))
  229. self.orderLabel.setObjectName("dverLabel")
  230. self.orderEdit = QtWidgets.QLineEdit(self.centralwidget)
  231. self.orderEdit.setGeometry(QtCore.QRect(310, 410, 151, 21))
  232. font = QtGui.QFont()
  233. font.setFamily("Arial")
  234. font.setPointSize(11)
  235. self.orderEdit.setFont(font)
  236. self.orderEdit.setObjectName("dverEdit")
  237. self.pushButton = QtWidgets.QPushButton(self.centralwidget)
  238. self.pushButton.setGeometry(QtCore.QRect(300, 450, 111, 41))
  239. self.pushButton.setObjectName("pushButton")
  240. self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
  241. self.progressBar.setGeometry(QtCore.QRect(130, 510, 491, 31))
  242. self.progressBar.setProperty("value", 0)
  243. self.progressBar.setVisible(False)
  244. self.progressBar.setObjectName("progressBar")
  245. MainWindow.setCentralWidget(self.centralwidget)
  246. self.retranslateUi(MainWindow)
  247. self.inputFileTool.clicked.connect(self.input_file_path)
  248. self.savePathTool.clicked.connect(self.out_save_location)
  249. self.pushButton.clicked.connect(self.on_click)
  250. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  251. def retranslateUi(self, MainWindow):
  252. _translate = QtCore.QCoreApplication.translate
  253. MainWindow.setWindowTitle(_translate("MainWindow", "杀虫灯质检工具"))
  254. self.savePathTool.setText(_translate("MainWindow", "选择文件夹"))
  255. self.inputFileTool.setText(_translate("MainWindow", "选择文件"))
  256. self.pageTitleLabel.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600; color:#3a45aa;\">云飞杀虫灯设备质检工具</span></p></body></html>"))
  257. self.savePathLabel.setText(_translate("MainWindow", "|输出文件位置:"))
  258. self.inputFileLabel.setText(_translate("MainWindow", "|输入文件位置:"))
  259. self.startTimeLabel.setText(_translate("MainWindow", "|开始时间:"))
  260. self.endTimeLabel.setText(_translate("MainWindow", "|结束时间:"))
  261. self.platLabel.setText(_translate("MainWindow", "|检验平台:"))
  262. self.stm8vsLabel.setText(_translate("MainWindow", "|主板版本号:"))
  263. self.dverLabel.setText(_translate("MainWindow", "|联网模块版本号:"))
  264. self.orderLabel.setText(_translate("MainWindow", "|任务单号:"))
  265. self.pushButton.setText(_translate("MainWindow", "开始导出"))
  266. def input_file_path(self):
  267. file_path = QtWidgets.QFileDialog.getOpenFileName(None,"选取文件","./","All Files (*.xlsx;*.xls);;Text Files (*.txt)")
  268. self.inputFileEdit.setText(file_path[0])
  269. self.inputFileEdit.setStyleSheet("color:black;")
  270. def out_save_location(self):
  271. fname = QtWidgets.QFileDialog.getExistingDirectory(None, '选取文件夹', './')
  272. self.savePathEdit.setText(fname)
  273. self.savePathEdit.setStyleSheet("color:black;")
  274. def on_click(self):
  275. file_path = self.inputFileEdit.text()
  276. save_path = self.savePathEdit.text()
  277. start_time = self.startTimeEdit.dateTime().toPyDateTime()
  278. end_time = self.endTimeEdit.dateTime().toPyDateTime()
  279. set_plat = self.platBox.currentText()
  280. set_stm8vs = self.stm8vsEdit.text()
  281. set_dver = self.dverEdit.text()
  282. set_order = self.orderEdit.text()
  283. if not all ([file_path,save_path,start_time,end_time,set_stm8vs,set_dver,set_order]):
  284. QtWidgets.QMessageBox.information(None, "提示", "选项未填写完整")
  285. elif end_time < start_time:
  286. QtWidgets.QMessageBox.information(None, "提示", "结束日期应在开始日期之后")
  287. else:
  288. xls = open_workbook(file_path)
  289. sheet_object = xls.sheets()[0]
  290. ncols = sheet_object.ncols
  291. read_dict = {}
  292. for i in range(ncols):
  293. col_value = sheet_object.col_values(i)
  294. read_dict[col_value[0]] = col_value[1:]
  295. device_list = read_dict.get("设备ID")
  296. if device_list:
  297. self.inputFileTool.setEnabled(False)
  298. self.savePathTool.setEnabled(False)
  299. self.startTimeEdit.setEnabled(False)
  300. self.endTimeEdit.setEnabled(False)
  301. self.platBox.setEnabled(False)
  302. self.stm8vsEdit.setEnabled(False)
  303. self.dverEdit.setEnabled(False)
  304. self.orderEdit.setEnabled(False)
  305. self.pushButton.setEnabled(False)
  306. self.pushButton.setText("执行中...")
  307. self.runThread = SCDThread(device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_dver,set_order)
  308. self.runThread.proess_signal.connect(self.set_progressbar_value)
  309. self.runThread.start()
  310. self.progressBar.setVisible(True)
  311. else:
  312. QtWidgets.QMessageBox.information(None, "提示", "输入文件无'设备ID'列或该列无数据")
  313. def set_progressbar_value(self, value):
  314. self.progressBar.setValue(value)
  315. if value == 100:
  316. QtWidgets.QMessageBox.information(None, "提示", "文件导出完毕!导出文件名:\n{}".format(save_filename))
  317. self.inputFileTool.setEnabled(True)
  318. self.inputFileEdit.setText("")
  319. self.savePathTool.setEnabled(True)
  320. self.savePathEdit.setText("")
  321. self.startTimeEdit.setEnabled(True)
  322. self.endTimeEdit.setEnabled(True)
  323. self.platBox.setEnabled(True)
  324. self.stm8vsEdit.setEnabled(True)
  325. self.stm8vsEdit.setText("")
  326. self.dverEdit.setEnabled(True)
  327. self.dverEdit.setText("")
  328. self.orderEdit.setEnabled(True)
  329. self.orderEdit.setText("")
  330. self.pushButton.setEnabled(True)
  331. self.pushButton.setText("开始导出")
  332. self.progressBar.setVisible(False)
  333. self.progressBar.setValue(0)
  334. return
  335. class SCDThread(QtCore.QThread):
  336. """涉及进度条需主界面动态执行GUI,线程执行业务逻辑,避免主页面卡死"""
  337. proess_signal = QtCore.pyqtSignal(int)
  338. def __init__(self,device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_dver,set_order):
  339. super(SCDThread, self).__init__()
  340. self.device_list = device_list
  341. self.save_path = save_path
  342. self.start_time = time.mktime(start_time.timetuple())
  343. self.end_time = time.mktime(end_time.timetuple())
  344. self.start_time_str = start_time.strftime("%y-%m-%d %H:%M:%S")
  345. self.end_time_str = end_time.strftime("%y-%m-%d %H:%M:%S")
  346. self.set_plat = set_plat
  347. self.set_stm8vs = set_stm8vs
  348. self.set_dver = set_dver
  349. self.set_order = set_order
  350. self.user = parse.quote_plus("root")
  351. self.passwd = parse.quote_plus("yfkj@6020")
  352. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  353. self.db = self.myclient.smartfarming
  354. self.device_collection = self.db.sa_device
  355. self.scd_collection = self.db.sa_device_scd_data
  356. self.config = {
  357. 'host': '120.27.222.26',
  358. 'port': 3306,
  359. 'user': 'yfwlw',
  360. 'password': 'sql_yfkj_6019',
  361. 'db': 'yfwlw',
  362. 'charset': 'utf8mb4',
  363. 'cursorclass': pymysql.cursors.DictCursor,
  364. }
  365. self.connection = pymysql.connect(**self.config)
  366. self.cursor = self.connection.cursor()
  367. device_list_tp = []
  368. for d in device_list:
  369. d_id, device_id, platform = self.device_their_platform(d)
  370. device_list_tp.append(device_id)
  371. self.device_list = device_list_tp
  372. def mongo_ping(self):
  373. """mongo-ping预防连接失效"""
  374. try:
  375. self.myclient.admin.command('ping')
  376. except: # "ConnectionFailure"
  377. self.myclient = pymongo.MongoClient("mongodb://{0}:{1}@8.136.98.49:57017/".format(self.user,self.passwd))
  378. self.db = self.myclient.smartfarming
  379. self.device_collection = self.db.sa_device
  380. self.scd_collection = self.db.sa_device_scd_data
  381. def sql_ping(self):
  382. """mysql-ping 预防连接失效"""
  383. try:
  384. self.connection.ping()
  385. except:
  386. self.connection = pymysql.connect(**self.config)
  387. self.cursor = self.connection.cursor()
  388. def __time_dif(self,checkdatetime):
  389. """计算时间差"""
  390. nowdatetime = datetime.datetime.now()
  391. checkdatetime = datetime.datetime.strptime(checkdatetime, "%Y-%m-%d %H:%M:%S")
  392. timedif = checkdatetime - nowdatetime
  393. return timedif.days
  394. def device_their_platform(self,shortId):
  395. """确定设备所在平台已经完整设备号"""
  396. self.mongo_ping()
  397. self.sql_ping()
  398. regex = re.compile('.*{}$'.format(shortId))
  399. bd_device_dict = self.device_collection.find_one(
  400. filter = {"device_id":regex,"device_type_id":2},
  401. projection = {'_id': 0},
  402. sort = [('uptime', pymongo.DESCENDING)]
  403. )
  404. device_sql = "SELECT * FROM AppInfoManage_scdstatus WHERE equip_id_id LIKE '%{}' ORDER BY upl_time DESC LIMIT 1;".format(shortId)
  405. self.cursor.execute(device_sql)
  406. sq_device_dict = self.cursor.fetchone()
  407. if bd_device_dict and sq_device_dict:
  408. bd_upltime = bd_device_dict["uptime"]
  409. sq_upltime = time.mktime(sq_device_dict["upl_time"].timetuple())
  410. if bd_upltime >= sq_upltime:
  411. d_id = bd_device_dict["id"]
  412. deviceId = bd_device_dict["device_id"]
  413. platform = "大数据平台"
  414. else:
  415. d_id = ""
  416. deviceId = sq_device_dict["equip_id_id"]
  417. platform = "四情平台"
  418. elif bd_device_dict and not sq_device_dict:
  419. d_id = bd_device_dict["id"]
  420. deviceId = bd_device_dict["device_id"]
  421. platform = "大数据平台"
  422. return d_id,deviceId,platform
  423. elif not bd_device_dict and sq_device_dict:
  424. d_id = ""
  425. deviceId = sq_device_dict["equip_id_id"]
  426. platform = "四情平台"
  427. else:
  428. d_id = ""
  429. deviceId = "平台无此设备"
  430. platform = "未知"
  431. return d_id,deviceId,platform
  432. def sim_info(self,iccid):
  433. # 时间戳 用于获取sign
  434. timestamp = int(time.time())
  435. current_milli_time = lambda: int(round(time.time() * 1000))
  436. data_1 = "appid=%s&iccid=%s&timestamp=%s%s"%("102420177762",iccid,current_milli_time(),"6397d7e6a56589f1d93284e9800493e1")
  437. sign = hashlib.sha256(data_1.encode('utf-8')).hexdigest()
  438. data = {"appid": "102420177762", "iccid": iccid, "timestamp":current_milli_time(),"sign":sign}
  439. url = "https://api.simboss.com/2.0/device/detail"
  440. try:
  441. status = 1
  442. ret = requests.post(url, data=data)
  443. code = json.loads(ret.text)["code"]
  444. if code == "0":
  445. status = 1
  446. else:
  447. url = 'http://sim.brlink.cn/api/open/iotcard/card'
  448. appkey = "iaO2DKgS8KdlnVgU"
  449. appsecret = "qzKgO4sBdzMrjRwv9H22S9ufepNv8Hl5ehPqkYVD31DCICjyKwqUdj7zihQQKfgx"
  450. status = 2
  451. ret = requests.post(url,json={'iccid':iccid},auth=HTTPBasicAuth(appkey,appsecret),timeout=(5,10))
  452. codes = json.loads(ret.text)["code"]
  453. if codes == 0:
  454. status = 2
  455. else:
  456. url = "https://jsnl.xmnengjia.com/open/api/module/cards"
  457. data = {"iccids":[iccid]}
  458. data = json.dumps(data)
  459. ret = requests.post(url,data=data,timeout=(10,30))
  460. print(ret.text)
  461. status = 3
  462. except:
  463. status = 0
  464. ret = 0
  465. day = 0
  466. if ret:
  467. try:
  468. result = json.loads(ret.text)
  469. expiry_date = result.get("data", {}).get("expiry_date")
  470. now_date = int(time.time())
  471. time_difference = int((expiry_date - now_date) / 3600 / 24)
  472. print(time_difference)
  473. if time_difference < 30:
  474. return [0,"有效期剩余{}天".format(time_difference)]
  475. elif time_difference >= 181:
  476. return [1,"有效期剩余{}天".format(time_difference)]
  477. else:
  478. return [2,"有效期剩余{}天".format(time_difference)]
  479. except:
  480. return [0, "查询无结果"]
  481. else:
  482. return [0, "查询无结果"]
  483. def __bigdata_verify(self,data_cursor,proess):
  484. ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"]
  485. tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"]
  486. ws_list,ws_count = [],0
  487. iccid = ""
  488. # 经纬度展示不合格条数
  489. lng_lst = []
  490. lat_lst = []
  491. for index,i in enumerate(data_cursor):
  492. addtime = i["addtime"]
  493. data_strftime = datetime.datetime.fromtimestamp(addtime).strftime("%Y-%m-%d %H:%M:%S")
  494. device_data = i["device_data"]
  495. device_data = ast.literal_eval(device_data)
  496. if device_data.get("ds","0") == "0":
  497. ds_verify[0], ds_verify[1] = 0, data_strftime + "为关机状态"
  498. ws = device_data.get("ws","0")
  499. ws_list.append(ws)
  500. if ws == "1":
  501. ws_count += 1
  502. elif ws == "2":
  503. if float(device_data.get("cv","0")) >= 7 and float(device_data.get("cv","0")) <= 23:
  504. if "电压异常" in cv_verify[1]:
  505. pass
  506. else:
  507. cv_verify[0],cv_verify[1] = 1,"合格"
  508. else:
  509. cv_verify[0],cv_verify[1] = 0,"{}电压异常:{}v".format(data_strftime,float(device_data.get("cv","0")))
  510. dianji_count = int(device_data.get("ct","0"))
  511. if dianji_count != 0:
  512. if dianji_count > 1000:
  513. ct_verify[0],ct_verify[1] = 0, "{}电击数超限:{}".format(data_strftime,str(dianji_count))
  514. else:
  515. if "电击数超限" not in ct_verify[1]:
  516. ct_verify[0],ct_verify[1] = 1,"合格"
  517. if float(device_data.get("bv","0")) == 12 or float(device_data.get("bv","0")) > 15:
  518. bv_verify[0], bv_verify[1] = 0, "{}电压异常:{}v".format(data_strftime,float(device_data.get("bv","0")))
  519. if device_data.get("rps","0") == "1":
  520. rps_verify[0], rps_verify[1] = 1, data_strftime+"进入雨控"
  521. if device_data.get("ts","0") == "0":
  522. if device_data.get("tt","0") != "4":
  523. tt_verify[0], tt_verify[1] = 0, "光控定时时长为{}小时".format(device_data.get("tt","0"))
  524. else:
  525. tt_verify[0], tt_verify[1] = 0, "为时控模式"
  526. if device_data.get("stm8vs","0") != self.set_stm8vs:
  527. stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0")
  528. if device_data.get("iccid",""):
  529. iccid = device_data.get("iccid","")
  530. if device_data.get("dver","0") != self.set_dver:
  531. dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0")
  532. # if float(device_data.get("lng","0")) < 113.7536111 or float(device_data.get("lng","0")) > 113.7869444:
  533. # lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围"
  534. # if float(device_data.get("lat","0")) < 35.0125 or float(device_data.get("lat","0")) > 35.0458333:
  535. # lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围"
  536. try:
  537. lng_lst.append(float(device_data.get("lng")))
  538. except Exception as e:
  539. lng_lst.append(0)
  540. try:
  541. lat_lst.append(float(device_data.get("lat")))
  542. except Exception as e:
  543. lat_lst.append(0)
  544. prosee = proess + ((index+1)/data_cursor.count()*(1/len(self.device_list))*100)
  545. if int(prosee) == 100:
  546. self.proess_signal.emit(99)
  547. else:
  548. self.proess_signal.emit(int(prosee))
  549. if "0" in ws_list:
  550. if "1" in ws_list:
  551. if "2" in ws_list:
  552. stamp_diff = self.end_time - self.start_time
  553. day_diff = round(stamp_diff / (12*60*60))
  554. if day_diff <= 1:
  555. low_limit, high_limit = 20, 30
  556. else:
  557. low_limit, high_limit = 20*day_diff, 30*day_diff
  558. if ws_count>low_limit and ws_count<high_limit:
  559. ws_verify=[1,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  560. else:
  561. ws_verify=[0,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  562. else:
  563. ws_verify=[0,"缺少充电状态"]
  564. else:
  565. ws_verify=[0,"缺少工作状态"]
  566. else:
  567. ws_verify=[0,"缺少待机状态"]
  568. if iccid:
  569. print("iccid", iccid)
  570. sim_verify = self.sim_info(iccid)
  571. else:
  572. sim_verify = [0,"数据内无iccid"]
  573. # 经纬度处理
  574. lg = 0
  575. lt = 0
  576. for i in lng_lst:
  577. if i < 113.7536111 or i > 113.7869444:
  578. lg += 1
  579. for k in lat_lst:
  580. if k < 35.0125 or k > 35.0458333:
  581. lt += 1
  582. if lg != 0:
  583. lng_verify = [0, f"{str(min(lng_lst))}~{str(max(lng_lst))},不合格条数{str(lg)}"]
  584. if lt != 0:
  585. lat_verify = [0, f"{str(min(lat_lst))}~{str(max(lat_lst))},不合格条数{str(lt)}"]
  586. return [ds_verify,ws_verify,ct_verify,cv_verify,bv_verify,rps_verify,tt_verify,stm8vs_verify,sim_verify,dver_verify,lng_verify,lat_verify]
  587. def __siqing_verify(self,data_result,status_result,proess):
  588. ds_verify,ct_verify,cv_verify,bv_verify,rps_verify = [1,"合格"],[0,"无电击数据"],[0,"不存在充电状态"],[1,"合格"],[0,"无雨控数据"]
  589. tt_verify,stm8vs_verify,dver_verify,lng_verify,lat_verify = [1,"合格"],[1,self.set_stm8vs],[1,self.set_dver],[1,"合格"],[1,"合格"]
  590. ws_list,ws_count = [],0
  591. iccid = ""
  592. for i in status_result:
  593. data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S")
  594. device_data = i["scd_status"]
  595. device_data = ast.literal_eval(device_data)
  596. if device_data.get("stm8vs","0") != self.set_stm8vs:
  597. stm8vs_verify[0],stm8vs_verify[1] = 0, device_data.get("stm8vs","0")
  598. if device_data.get("iccid",""):
  599. iccid = device_data.get("iccid","")
  600. if device_data.get("dver","0") != self.set_dver:
  601. dver_verify[0],dver_verify[1] = 0, device_data.get("dver","0")
  602. for index,i in enumerate(data_result):
  603. data_strftime = i["upl_time"].strftime("%Y-%m-%d %H:%M:%S")
  604. device_data = i["scd_data"]
  605. device_data = ast.literal_eval(device_data)
  606. if str(device_data.get("ds",0)) == "0":
  607. ds_verify[0], ds_verify[1] = 0, data_strftime + "为关机状态"
  608. ws = str(device_data.get("ws",0))
  609. ws_list.append(ws)
  610. if ws == "1":
  611. ws_count += 1
  612. elif ws == "2":
  613. if device_data.get("cv",0)/1000 >= 7 and device_data.get("cv",0)/1000 <= 23:
  614. if "电压异常" in cv_verify[1]:
  615. pass
  616. else:
  617. cv_verify[0],cv_verify[1] = 1,"合格"
  618. else:
  619. cv_verify[0],cv_verify[1] = 0,"{}电压异常:{}v".format(data_strftime,device_data.get("cv",0)/1000)
  620. dianji_count = device_data.get("ct",0)
  621. if dianji_count != 0:
  622. if dianji_count > 1000:
  623. ct_verify[0],ct_verify[1] = 0, "{}电击数超限:{}".format(data_strftime,dianji_count)
  624. else:
  625. if "电击数超限" not in ct_verify[1]:
  626. ct_verify[0],ct_verify[1] = 1,"合格"
  627. if device_data.get("bv",0)/1000 == 12 or device_data.get("bv",0)/1000 > 15:
  628. bv_verify[0], bv_verify[1] = 0, "{}电压异常:{}v".format(data_strftime,device_data.get("bv",0)/1000)
  629. if str(device_data.get("rps",0)) == "1":
  630. rps_verify[0], rps_verify[1] = 1, data_strftime+"进入雨控"
  631. if str(device_data.get("tcs",0)) == "0":
  632. if str(device_data.get("tt",0)) != "4":
  633. tt_verify[0], tt_verify[1] = 0, "光控定时时长为{}小时".format(str(device_data.get("tt",0)))
  634. else:
  635. tt_verify[0], tt_verify[1] = 0, "为时控模式"
  636. if float(device_data.get("lng","0")) < 113.7536111 and float(device_data.get("lng","0")) > 113.7869444:
  637. lng_verify[0],lng_verify[1] = 0, data_strftime+"超出范围"
  638. if float(device_data.get("lat","0")) < 35.0125 and float(device_data.get("lat","0")) > 35.0458333:
  639. lat_verify[0],lat_verify[1] = 0, data_strftime+"超出范围"
  640. prosee = proess + ((index+1)/len(data_result)*(1/len(self.device_list))*100)
  641. if int(prosee) == 100:
  642. self.proess_signal.emit(99)
  643. else:
  644. self.proess_signal.emit(int(prosee))
  645. if "0" in ws_list:
  646. if "1" in ws_list:
  647. if "2" in ws_list:
  648. stamp_diff = self.end_time - self.start_time
  649. day_diff = round(stamp_diff / (12*60*60))
  650. if day_diff <= 1:
  651. low_limit, high_limit = 20, 30
  652. else:
  653. low_limit, high_limit = 20*day_diff, 30*day_diff
  654. if ws_count>low_limit and ws_count<high_limit:
  655. ws_verify=[1,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  656. else:
  657. ws_verify=[0,"理论数据量区间({},{}),实际工作状态数据量为{}".format(low_limit,high_limit,ws_count)]
  658. else:
  659. ws_verify=[0,"缺少充电状态"]
  660. else:
  661. ws_verify=[0,"缺少工作状态"]
  662. else:
  663. ws_verify=[0,"缺少待机状态"]
  664. if iccid:
  665. sim_verify = self.sim_info(iccid)
  666. else:
  667. sim_verify = [0,"数据内无iccid"]
  668. return [ds_verify,ws_verify,ct_verify,cv_verify,bv_verify,rps_verify,tt_verify,stm8vs_verify,sim_verify,dver_verify,lng_verify,lat_verify]
  669. def run(self):
  670. """主业务逻辑,涉及进度条不能模块化,慢慢捋"""
  671. proess = 0
  672. now_time = datetime.datetime.now()
  673. global save_filename
  674. save_filename = self.set_order + "_" + now_time.strftime("%m%d") + "杀虫灯检验.xlsx"
  675. save_path = os.path.join(self.save_path,save_filename)
  676. workbook = Workbook(save_path)
  677. worksheet = workbook.add_worksheet()
  678. worksheet.set_row(0, 50)
  679. worksheet.set_row(1, 37.5)
  680. worksheet.set_row(2, 30)
  681. worksheet.set_row(3, 100)
  682. for i in range(len(self.device_list)):
  683. worksheet.set_row(i+4, 30)
  684. worksheet.set_column(0, 16, 24)
  685. toji_style = workbook.add_format(toji_format)
  686. title_style = workbook.add_format(title_format)
  687. explain_style = workbook.add_format(explain_formal)
  688. formal_style = workbook.add_format(formal_format)
  689. error_style = workbook.add_format(error_format)
  690. common_style = workbook.add_format(common_format)
  691. merge_title_style = workbook.add_format(merge_title_format)
  692. worksheet.merge_range('A1:Q1',"物联网杀虫灯设备质检表格",merge_title_style)
  693. title_data = [
  694. "文档ID","完整设备ID","开关机状态","工作状态","电击次数","充电电压","电池电压","雨控保护","光控定时时长",
  695. "主板版本号","物联网卡有效期","联网模块版本号","经度坐标","纬度坐标","数据来源","单机判定","批判定"]
  696. worksheet.write_row(row = 2 ,col = 0, data = title_data,cell_format=title_style)
  697. explain_data = [
  698. "/",
  699. "/",
  700. "合格条件(绿色):\n查询时间内,设备开关均为开机",
  701. "合格条件(绿色):\n1.查询时间内,存在待机、充电、工作三个类型的工作状态;\n2.24小时周期内工作状态的数据量大于20小于30",
  702. "合格条件(绿色):\n查询时间内,存在击杀数据且单次上报击虫数小于1000",
  703. "合格条件(绿色):\n1.存在充电状态;\n2.充电状态下电压值在7-23v之间",
  704. "合格条件(绿色):\n查询时间内上报数据电池电压不能等于12v,也不能大于15v",
  705. "合格条件(绿色):\n查询时间内存在雨控即雨控上报数据量大于0",
  706. "合格条件(绿色):\n1.必须是光控模式\n2.工作时长配置为4小时",
  707. "合格条件(绿色):\n数据上报主板版本号和输入主板版本号一致",
  708. "合格条件(绿色):剩余有效期大于等于181天\n可接受(黄色):大于等于30天,小于181天\n不合格(红色):小于30天或查询异常。",
  709. "合格条件(绿色):\n数据上报联网模块版本号和输入联网模块版本号一致",
  710. "合格条件(绿色):\n113°46′13″±60″范围内,转为十进度为:(113.7536111,113.7869444)区间内",
  711. "合格条件(绿色):\n35°1′45″±60″范围内,转为十进度为:(35.0125,35.0458333)区间内",
  712. "合格条件(绿色):\n输入校验平台和设备所在平台一致",
  713. "合格条件(绿色):\n所有单项检测合格即为单机判定合格",
  714. "合格条件(绿色):\n1.总量大于8台,单机合格量需>=8,不合格允许DF两列出现异常;\n2.若不超8台要求单机判定全部合格。"
  715. ]
  716. worksheet.write_row(row = 3 ,col = 0, data = explain_data,cell_format=explain_style)
  717. formal_counts = 0
  718. verify_list = []
  719. for index,shortId in enumerate(self.device_list):
  720. if isinstance(shortId,int) or isinstance(shortId, float):
  721. shortId = str(int(shortId))
  722. else:
  723. shortId = shortId.strip()
  724. d_id,deviceId,platform = self.device_their_platform(shortId)
  725. worksheet.write(index+4,0,shortId,formal_style)
  726. if platform == "大数据平台":
  727. try:
  728. worksheet.write(index+4,1,deviceId,formal_style)
  729. if platform==self.set_plat:
  730. worksheet.write(index+4,14,platform,formal_style)
  731. else:
  732. worksheet.write(index+4,14,platform,error_style)
  733. self.mongo_ping()
  734. data_cursor = self.scd_collection.find({"device_id":d_id,'addtime': {"$gte":self.start_time ,"$lte":self.end_time}})
  735. data_counts = data_cursor.count()
  736. if data_counts == 0:
  737. for i in range(2,14):
  738. worksheet.write(index+4,i,"搜索时间内无数据",error_style)
  739. worksheet.write(index+4,15,"不合格",error_style)
  740. danji_verify = []
  741. for i in range(12):
  742. danji_verify.append(0)
  743. verify_list.append(danji_verify)
  744. else:
  745. verify_data = self.__bigdata_verify(data_cursor,proess)
  746. danji_verify = []
  747. for clo_index, verify_ in enumerate(verify_data):
  748. danji_verify.append(verify_[0])
  749. if verify_[0] == 0:
  750. worksheet.write(index+4,clo_index+2,verify_[1],error_style)
  751. elif verify_[0] == 1:
  752. worksheet.write(index+4,clo_index+2,verify_[1],formal_style)
  753. else:
  754. worksheet.write(index+4,clo_index+2,verify_[1],common_style)
  755. if 0 in danji_verify:
  756. worksheet.write(index+4,15,"不合格",error_style)
  757. else:
  758. formal_counts += 1
  759. worksheet.write(index+4,15,"合格",formal_style)
  760. verify_list.append(danji_verify)
  761. except Exception as e:
  762. print(e)
  763. elif platform == "四情平台":
  764. worksheet.write(index+4,1,deviceId,formal_style)
  765. if platform==self.set_plat:
  766. worksheet.write(index+4,14,platform,formal_style)
  767. else:
  768. worksheet.write(index+4,14,platform,error_style)
  769. self.sql_ping()
  770. 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)
  771. self.cursor.execute(data_sql)
  772. data_result = self.cursor.fetchall()
  773. 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)
  774. self.cursor.execute(status_sql)
  775. status_result = self.cursor.fetchall()
  776. if len(data_result) == 0 or len(status_result) == 0:
  777. for i in range(2,14):
  778. worksheet.write(index+4,i,"搜索时间内无数据",error_style)
  779. worksheet.write(index+4,15,"不合格",error_style)
  780. danji_verify = []
  781. for i in range(12):
  782. danji_verify.append(0)
  783. verify_list.append(danji_verify)
  784. else:
  785. verify_data = self.__siqing_verify(data_result,status_result,proess)
  786. danji_verify = []
  787. for clo_index, verify_ in enumerate(verify_data):
  788. danji_verify.append(verify_[0])
  789. if verify_[0] == 0:
  790. worksheet.write(index+4,clo_index+2,verify_[1],error_style)
  791. elif verify_[0] == 1:
  792. worksheet.write(index+4,clo_index+2,verify_[1],formal_style)
  793. else:
  794. worksheet.write(index+4,clo_index+2,verify_[1],common_style)
  795. if 0 in danji_verify:
  796. worksheet.write(index+4,15,"不合格",error_style)
  797. else:
  798. formal_counts += 1
  799. worksheet.write(index+4,15,"合格",formal_style)
  800. verify_list.append(danji_verify)
  801. else:
  802. danji_verify = []
  803. for i in range(12):
  804. danji_verify.append(0)
  805. verify_list.append(danji_verify)
  806. worksheet.write(index+4,1,deviceId,error_style)
  807. worksheet.write(index+4,14,platform,error_style)
  808. proess = (index+1)/len(self.device_list) * 100
  809. if int(proess) == 100:
  810. self.proess_signal.emit(99)
  811. else:
  812. self.proess_signal.emit(int(proess))
  813. toji_data = [
  814. "任务单号",self.set_order,"检验时间",'{}\n{}'.format(self.start_time_str,self.end_time_str),
  815. "检验数量",len(self.device_list),"合格数",formal_counts,"检验平台",self.set_plat,
  816. "主板版本",self.set_stm8vs,"联网版本",self.set_dver,"报告日期",now_time.strftime("%y-%m-%d %H:%M:%S"),""
  817. ]
  818. worksheet.write_row(row = 1 ,col = 0, data = toji_data,cell_format=toji_style)
  819. # 批判定
  820. if len(self.device_list) > 8:
  821. batch_verify = [1,"设备量超8台,单机合格数量存在8台及以上,排除DF两列后其他列均合格"]
  822. if formal_counts >= 8:
  823. for danji_data in verify_list:
  824. for index,element_data in enumerate(danji_data):
  825. if index == 1 or index == 3:
  826. pass
  827. else:
  828. if element_data == 0:
  829. batch_verify = [0,"设备量超8台,单机合格数量存在8台及以上,排除DF两列后其他列出现异常"]
  830. else:
  831. batch_verify = [0,"设备量超8台,单机合格数量不足8台"]
  832. else:
  833. if formal_counts == len(self.device_list):
  834. batch_verify = [1,"设备量不超8台,单机判定全部合格"]
  835. else:
  836. batch_verify = [0,"设备量不超8台,单机判定存在不合格"]
  837. worksheet.merge_range("Q5:Q13",batch_verify[1],formal_style if batch_verify[0]==1 else error_style)
  838. worksheet.protect(pwd_str)
  839. workbook.close()
  840. self.cursor.close()
  841. self.connection.close()
  842. self.myclient.close()
  843. self.proess_signal.emit(100)
  844. if __name__== "__main__":
  845. QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
  846. QtGui.QGuiApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
  847. app = QtWidgets.QApplication(sys.argv)
  848. MainWindow = QtWidgets.QMainWindow()
  849. ui = Ui_MainWindow()
  850. ui.setupUi(MainWindow)
  851. MainWindow.show()
  852. sys.exit(app.exec_())