main.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. # encoding=utf-8
  2. from PyQt5 import QtCore, QtGui, QtWidgets
  3. import os
  4. import sys
  5. import datetime
  6. from xlrd import open_workbook
  7. from xlsxwriter.workbook import Workbook
  8. import openpyxl
  9. from mongoclient import (
  10. get_qxz_conf,
  11. device_detail_deivce_id,
  12. get_sa_qxz_info_record,
  13. get_sa_qxz_data,
  14. get_conf_data,
  15. get_sim_info
  16. )
  17. from utils import (
  18. merge_title_format,
  19. toji_format,
  20. formal_format,
  21. error_format,
  22. common_format,
  23. default_formal,
  24. get_excel_content,
  25. head_dict,
  26. sim_info
  27. )
  28. save_filename = ""
  29. class Ui_MainWindow(object):
  30. """GUI界面"""
  31. def setupUi(self, MainWindow):
  32. MainWindow.setObjectName("MainWindow")
  33. MainWindow.resize(701, 644)
  34. font = QtGui.QFont()
  35. font.setFamily("Arial")
  36. font.setPointSize(12)
  37. MainWindow.setFont(font)
  38. icon = QtGui.QIcon("logo.ico")
  39. MainWindow.setWindowIcon(icon)
  40. self.centralwidget = QtWidgets.QWidget(MainWindow)
  41. self.centralwidget.setObjectName("centralwidget")
  42. self.pageTitleLabel = QtWidgets.QLabel(self.centralwidget)
  43. self.pageTitleLabel.setGeometry(QtCore.QRect(139, 50, 429, 42))
  44. font = QtGui.QFont()
  45. font.setFamily("楷体")
  46. font.setPointSize(28)
  47. self.pageTitleLabel.setFont(font)
  48. self.pageTitleLabel.setTextFormat(QtCore.Qt.AutoText)
  49. self.pageTitleLabel.setObjectName("pageTitleLabel")
  50. self.inputFileLabel = QtWidgets.QLabel(self.centralwidget)
  51. self.inputFileLabel.setGeometry(QtCore.QRect(180, 130, 121, 21))
  52. self.inputFileLabel.setObjectName("inputFileLabel")
  53. self.inputFileEdit = QtWidgets.QLineEdit(self.centralwidget)
  54. self.inputFileEdit.setGeometry(QtCore.QRect(310, 130, 151, 21))
  55. self.inputFileEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  56. font = QtGui.QFont()
  57. font.setFamily("Arial")
  58. font.setPointSize(8)
  59. self.inputFileEdit.setFont(font)
  60. self.inputFileEdit.setObjectName("inputFileEdit")
  61. self.inputFileTool = QtWidgets.QToolButton(self.centralwidget)
  62. self.inputFileTool.setGeometry(QtCore.QRect(470, 130, 71, 21))
  63. font = QtGui.QFont()
  64. font.setFamily("Arial")
  65. font.setPointSize(10)
  66. self.inputFileTool.setFont(font)
  67. self.inputFileTool.setObjectName("inputFileTool")
  68. self.savePathLabel = QtWidgets.QLabel(self.centralwidget)
  69. self.savePathLabel.setGeometry(QtCore.QRect(180, 170, 121, 21))
  70. self.savePathLabel.setObjectName("savePathLabel")
  71. self.savePathEdit = QtWidgets.QLineEdit(self.centralwidget)
  72. self.savePathEdit.setGeometry(QtCore.QRect(310, 170, 151, 21))
  73. self.savePathEdit.setFocusPolicy(QtCore.Qt.NoFocus)
  74. font = QtGui.QFont()
  75. font.setFamily("Arial")
  76. font.setPointSize(8)
  77. self.savePathEdit.setFont(font)
  78. self.savePathEdit.setObjectName("savePathEdit")
  79. self.savePathTool = QtWidgets.QToolButton(self.centralwidget)
  80. self.savePathTool.setGeometry(QtCore.QRect(470, 170, 71, 21))
  81. font = QtGui.QFont()
  82. font.setFamily("Arial")
  83. font.setPointSize(10)
  84. self.savePathTool.setFont(font)
  85. self.savePathTool.setObjectName("savePathTool")
  86. self.startTimeLabel = QtWidgets.QLabel(self.centralwidget)
  87. self.startTimeLabel.setGeometry(QtCore.QRect(180, 210, 121, 21))
  88. self.startTimeLabel.setObjectName("startTimeLabel")
  89. self.startTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  90. self.startTimeEdit.setGeometry(QtCore.QRect(310, 210, 151, 21))
  91. self.startTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2028, 12, 31), QtCore.QTime(23, 59, 59)))
  92. self.startTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2024, 1, 1), QtCore.QTime(18, 0, 0)))
  93. self.startTimeEdit.setObjectName("startTimeEdit")
  94. self.endTimeLabel = QtWidgets.QLabel(self.centralwidget)
  95. self.endTimeLabel.setGeometry(QtCore.QRect(180, 250, 121, 21))
  96. self.endTimeLabel.setObjectName("endTimeLabel")
  97. self.endTimeEdit = QtWidgets.QDateTimeEdit(self.centralwidget)
  98. self.endTimeEdit.setGeometry(QtCore.QRect(310, 250, 151, 21))
  99. self.endTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2025, 12, 31), QtCore.QTime(23, 59, 59)))
  100. self.endTimeEdit.setMinimumDateTime(QtCore.QDateTime(QtCore.QDate(2024, 2, 1), QtCore.QTime(20, 0, 0)))
  101. self.endTimeEdit.setObjectName("endTimeEdit")
  102. self.platLabel = QtWidgets.QLabel(self.centralwidget)
  103. self.platLabel.setGeometry(QtCore.QRect(180, 290, 121, 21))
  104. self.platLabel.setObjectName("dianjiLabel")
  105. self.platBox = QtWidgets.QComboBox(self.centralwidget)
  106. self.platBox.setGeometry(QtCore.QRect(310, 290, 151, 21))
  107. self.platBox.addItems(['大数据平台','四情平台'])
  108. font = QtGui.QFont()
  109. font.setFamily("Arial")
  110. font.setPointSize(11)
  111. self.platBox.setFont(font)
  112. self.platBox.setObjectName("platBox")
  113. self.stm8vsLabel = QtWidgets.QLabel(self.centralwidget)
  114. self.stm8vsLabel.setGeometry(QtCore.QRect(180, 330, 121, 21))
  115. self.stm8vsLabel.setObjectName("stm8vsLabel")
  116. self.stm8vsEdit = QtWidgets.QLineEdit(self.centralwidget)
  117. self.stm8vsEdit.setGeometry(QtCore.QRect(310, 330, 151, 21))
  118. font = QtGui.QFont()
  119. font.setFamily("Arial")
  120. font.setPointSize(11)
  121. self.stm8vsEdit.setFont(font)
  122. self.stm8vsEdit.setObjectName("stm8vsEdit")
  123. font = QtGui.QFont()
  124. font.setFamily("Arial")
  125. font.setPointSize(11)
  126. self.orderLabel = QtWidgets.QLabel(self.centralwidget)
  127. self.orderLabel.setGeometry(QtCore.QRect(180, 370, 121, 21))
  128. self.orderLabel.setObjectName("dverLabel")
  129. self.orderEdit = QtWidgets.QLineEdit(self.centralwidget)
  130. self.orderEdit.setGeometry(QtCore.QRect(310, 370, 151, 21))
  131. font = QtGui.QFont()
  132. font.setFamily("Arial")
  133. font.setPointSize(11)
  134. self.orderEdit.setFont(font)
  135. self.orderEdit.setObjectName("dverEdit")
  136. self.pushButton = QtWidgets.QPushButton(self.centralwidget)
  137. self.pushButton.setGeometry(QtCore.QRect(300, 410, 111, 41))
  138. self.pushButton.setObjectName("pushButton")
  139. self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
  140. self.progressBar.setGeometry(QtCore.QRect(130, 470, 491, 31))
  141. self.progressBar.setProperty("value", 0)
  142. self.progressBar.setVisible(False)
  143. self.progressBar.setObjectName("progressBar")
  144. MainWindow.setCentralWidget(self.centralwidget)
  145. self.retranslateUi(MainWindow)
  146. self.inputFileTool.clicked.connect(self.input_file_path)
  147. self.savePathTool.clicked.connect(self.out_save_location)
  148. self.pushButton.clicked.connect(self.on_click)
  149. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  150. def retranslateUi(self, MainWindow):
  151. _translate = QtCore.QCoreApplication.translate
  152. MainWindow.setWindowTitle(_translate("MainWindow", "气象站质检工具"))
  153. self.savePathTool.setText(_translate("MainWindow", "选择文件夹"))
  154. self.inputFileTool.setText(_translate("MainWindow", "选择文件"))
  155. self.pageTitleLabel.setText(_translate("MainWindow", "<html><head/><body><p><span style=\" font-weight:600; color:#3a45aa;\">云飞气象站设备质检工具</span></p></body></html>"))
  156. self.savePathLabel.setText(_translate("MainWindow", "|输出文件位置:"))
  157. self.inputFileLabel.setText(_translate("MainWindow", "|输入文件位置:"))
  158. self.startTimeLabel.setText(_translate("MainWindow", "|开始时间:"))
  159. self.endTimeLabel.setText(_translate("MainWindow", "|结束时间:"))
  160. self.platLabel.setText(_translate("MainWindow", "|检验平台:"))
  161. self.stm8vsLabel.setText(_translate("MainWindow", "|主板版本号:"))
  162. self.orderLabel.setText(_translate("MainWindow", "|任务单号:"))
  163. self.pushButton.setText(_translate("MainWindow", "开始导出"))
  164. def input_file_path(self):
  165. file_path = QtWidgets.QFileDialog.getOpenFileName(None,"选取文件","./","All Files (*.xlsx;*.xls);;Text Files (*.txt);;ALL(*)")
  166. self.inputFileEdit.setText(file_path[0])
  167. self.inputFileEdit.setStyleSheet("color:black;")
  168. def out_save_location(self):
  169. fname = QtWidgets.QFileDialog.getExistingDirectory(None, '选取文件夹', './')
  170. self.savePathEdit.setText(fname)
  171. self.savePathEdit.setStyleSheet("color:black;")
  172. def on_click(self):
  173. file_path = self.inputFileEdit.text()
  174. save_path = self.savePathEdit.text()
  175. start_time = self.startTimeEdit.dateTime().toPyDateTime()
  176. end_time = self.endTimeEdit.dateTime().toPyDateTime()
  177. set_plat = self.platBox.currentText()
  178. set_stm8vs = self.stm8vsEdit.text()
  179. set_order = self.orderEdit.text()
  180. if not all ([file_path,save_path,start_time,end_time,set_stm8vs,set_order]):
  181. QtWidgets.QMessageBox.information(None, "提示", "选项未填写完整")
  182. elif end_time < start_time:
  183. QtWidgets.QMessageBox.information(None, "提示", "结束日期应在开始日期之后")
  184. else:
  185. read_dict = {}
  186. if file_path.split(".")[-1] == "xlsx":
  187. wb = openpyxl.load_workbook(file_path)
  188. sheet = wb[wb.sheetnames[0]]
  189. row_num = sheet.max_row
  190. d_list = []
  191. for row in range(2, row_num + 1):
  192. cell = sheet.cell(row, 1)
  193. try:
  194. cell_value = str(cell.value).strip()
  195. if cell_value:
  196. d_list.append(cell.value)
  197. except Exception as e:
  198. continue
  199. read_dict["设备ID"] = d_list
  200. else:
  201. xls = open_workbook(file_path)
  202. sheet_object = xls.sheets()[0]
  203. ncols = sheet_object.ncols
  204. d_list = []
  205. col_value = sheet_object.col_values(0)
  206. for d_i in col_value[1:]:
  207. try:
  208. d_i_v = str(d_i).strip()
  209. if d_i_v:
  210. d_list.append(d_i_v)
  211. except Exception as e:
  212. continue
  213. read_dict["设备ID"] = d_list
  214. device_list = read_dict.get("设备ID")
  215. if device_list:
  216. self.inputFileTool.setEnabled(False)
  217. self.savePathTool.setEnabled(False)
  218. self.startTimeEdit.setEnabled(False)
  219. self.endTimeEdit.setEnabled(False)
  220. self.platBox.setEnabled(False)
  221. self.stm8vsEdit.setEnabled(False)
  222. self.orderEdit.setEnabled(False)
  223. self.pushButton.setEnabled(False)
  224. self.pushButton.setText("执行中...")
  225. self.runThread = SCDThread(device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_order)
  226. self.runThread.proess_signal.connect(self.set_progressbar_value)
  227. self.runThread.start()
  228. self.progressBar.setVisible(True)
  229. else:
  230. QtWidgets.QMessageBox.information(None, "提示", "输入文件无'设备ID'列或该列无数据")
  231. def set_progressbar_value(self, value):
  232. self.progressBar.setValue(value)
  233. if value == 100:
  234. QtWidgets.QMessageBox.information(None, "提示", "文件导出完毕!导出文件名:\n{}".format(save_filename))
  235. self.inputFileTool.setEnabled(True)
  236. # self.inputFileEdit.setText("")
  237. self.savePathTool.setEnabled(True)
  238. # self.savePathEdit.setText("")
  239. self.startTimeEdit.setEnabled(True)
  240. self.endTimeEdit.setEnabled(True)
  241. self.platBox.setEnabled(True)
  242. self.stm8vsEdit.setEnabled(True)
  243. # self.stm8vsEdit.setText("")
  244. self.orderEdit.setEnabled(True)
  245. # self.orderEdit.setText("")
  246. self.pushButton.setEnabled(True)
  247. self.pushButton.setText("开始导出")
  248. self.progressBar.setVisible(False)
  249. self.progressBar.setValue(0)
  250. return
  251. class SCDThread(QtCore.QThread):
  252. """涉及进度条需主界面动态执行GUI,线程执行业务逻辑,避免主页面卡死"""
  253. proess_signal = QtCore.pyqtSignal(int)
  254. def __init__(self,device_list,save_path,start_time,end_time,set_plat,set_stm8vs,set_order):
  255. super(SCDThread, self).__init__()
  256. self.save_path = save_path
  257. # self.start_time = time.mktime(start_time.timetuple())
  258. # self.end_time = time.mktime(end_time.timetuple())
  259. # self.start_time_str = start_time.strftime("%y-%m-%d %H:%M:%S")
  260. # self.end_time_str = end_time.strftime("%y-%m-%d %H:%M:%S")
  261. self.device_list = device_list
  262. self.start_time = start_time
  263. self.end_time = end_time
  264. self.set_plat = set_plat
  265. self.set_stm8vs = set_stm8vs
  266. self.set_order = set_order
  267. def run(self):
  268. # start = "2023-08-28 10:00:00"
  269. # end = "2023-08-31 20:00:00"
  270. start = self.start_time.strftime("%Y-%m-%d %H:%M:%S")
  271. end = self.end_time.strftime("%Y-%m-%d %H:%M:%S")
  272. dever_num = self.set_stm8vs
  273. # 获取所有的device_id
  274. # device_list = get_excel_content("F:\\scripting_tools\\热通量增加测试.xlsx")
  275. save_filename = self.set_order + "_" + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + ".xlsx"
  276. save_path = os.path.join(self.save_path,save_filename)
  277. workbook = Workbook(save_path)
  278. device_list = self.device_list
  279. worksheet = workbook.add_worksheet()
  280. merge_title_style = workbook.add_format(merge_title_format)
  281. toji_style = workbook.add_format(toji_format)
  282. default_style = workbook.add_format(default_formal)
  283. red_style = workbook.add_format(error_format)
  284. green_style = workbook.add_format(formal_format)
  285. yellow_style = workbook.add_format(common_format)
  286. style_dict = {
  287. 2: red_style,
  288. 1: green_style,
  289. 3: yellow_style,
  290. 4: default_style
  291. }
  292. title_name_list = [
  293. "ID",
  294. "检验项目",
  295. "电压",
  296. "信号强度",
  297. "经度",
  298. "纬度",
  299. "固件版本号",
  300. "sim卡信息",
  301. "位置信息"
  302. ]
  303. # 查找第一台设备的配置文件,获取配置项
  304. device_id, _, _, _, _ = device_detail_deivce_id(device_list[0])
  305. conf = get_qxz_conf(device_id)
  306. title_name_list += [v.split("#")[0] for k, v in conf.items()]
  307. title_name_list.append("单台合格数")
  308. head_list = [i.split("#")[0] for i in title_name_list]
  309. worksheet.merge_range(0, 0, 0, len(head_list) - 1, "物联网气象站设备质检表格", merge_title_style)
  310. toji_data = [
  311. "任务单号",
  312. self.set_order,
  313. "检验时间",
  314. start,
  315. end,
  316. "报告日期",
  317. (datetime.datetime.now()).strftime("%y-%m-%d %H:%M:%S"),
  318. "合格数"
  319. ]
  320. # 生成Excel表格第2行, 本次数据概要
  321. for index, k in enumerate(toji_data):
  322. value = str(k)
  323. worksheet.write(1, index, value, toji_style)
  324. # 生成Excel表格第3行, 检测标题
  325. for index, k in enumerate(title_name_list):
  326. worksheet.write(2, index, k, default_style)
  327. # 生成Excel表格第4行, 检测标准
  328. for index, k in enumerate(title_name_list):
  329. value = (head_dict.get(k, ["无判定条件", ""]))[0]
  330. worksheet.write(3, index, value, default_style)
  331. plus = 12 if index in [0, 1] else 8
  332. c_n = len(value) / 2 + plus
  333. worksheet.set_column(index, index, c_n)
  334. # 输入数据
  335. is_pass_count = 0
  336. for index, id in enumerate(device_list):
  337. device_id, dver_num, lng, lat, position = device_detail_deivce_id(id)
  338. # 获取电压,信号强度历史数据
  339. valt_rssi = get_sa_qxz_info_record(device_id, start, end)
  340. # 获取sim卡信息
  341. sim = get_sim_info(device_id, start, end)
  342. sim_in = sim_info(sim)
  343. # 第一部分拼接 表头及数据
  344. org_data = {
  345. "id_1": {"data": id, "explan": "ID"},
  346. "id_2": {"data": device_id, "explan": "检验项目"},
  347. "id_3": valt_rssi.get("volt"), # 电压
  348. "id_4": valt_rssi.get("rssi"), # 信号强度
  349. "id_5": {"data": lng, "explan": "经度"},
  350. "id_6": {"data": lat, "explan": "纬度"},
  351. "id_7": {"data": [dver_num.replace("/", "-"), dever_num], "explan": "固件版本号"},
  352. "id_8": {"data": sim_in, "explan": "sim卡信息"},
  353. "id_9": {"data": position, "explan": "位置信息"},
  354. }
  355. conf = get_qxz_conf(device_id)
  356. # 获取数据
  357. qx_data = get_sa_qxz_data(device_id, start, end, conf)
  358. # 第二部分拼接 表头及数据 获取气象与数据结合
  359. conf_data = get_conf_data(conf, qx_data)
  360. org_data.update(conf_data)
  361. i = 0
  362. is_right = 0
  363. for t, v in org_data.items():
  364. # 执行方法
  365. name = v.get("explan")
  366. print(name)
  367. data = v.get("data")
  368. func = head_dict.get(name)[1]
  369. if data:
  370. temp = func(data)
  371. if temp[0] == 1:
  372. is_right += 1
  373. else:
  374. temp = [2, "没有数据"]
  375. worksheet.write(index + 4, i, temp[1], style_dict[temp[0]])
  376. i += 1
  377. last = []
  378. if is_right == len(title_name_list) - 1:
  379. last = [1, "合格"]
  380. is_pass_count += 1
  381. else:
  382. last = [2, "不合格"]
  383. worksheet.write(index + 4, i, last[1], style_dict[last[0]])
  384. self.proess_signal.emit(int((index + 1)/len(device_list) * 100))
  385. worksheet.write(1, 8, is_pass_count, toji_style)
  386. worksheet.protect("yfkj")
  387. workbook.close()
  388. # self.proess_signal.emit(100)
  389. if __name__== "__main__":
  390. QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
  391. QtGui.QGuiApplication.setAttribute(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
  392. app = QtWidgets.QApplication(sys.argv)
  393. MainWindow = QtWidgets.QMainWindow()
  394. ui = Ui_MainWindow()
  395. ui.setupUi(MainWindow)
  396. MainWindow.show()
  397. sys.exit(app.exec_())