12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082 |
- import ctypes
- import inspect
- import os
- import signal
- import sys
- sys.path.append('..')
- import datetime
- import json
- import threading
- import time
- import traceback
- from functools import partial
- from django.core.serializers.json import DjangoJSONEncoder
- import requests
- from PyQt5.QtCore import QSize, QDateTime
- from PyQt5.QtCore import pyqtSignal, QTimer, Qt
- from PyQt5.QtGui import QFont, QIcon, QPixmap, QCursor, QColor
- from PyQt5.QtWidgets import QMessageBox, QListWidgetItem, QMainWindow, QMenu, QPushButton, QGridLayout, QListWidget, \
- QLabel, QHeaderView, QTableWidgetItem, QAbstractItemView, QSizePolicy, QApplication
- import google.protobuf.text_format as tf
- import ui.spaceUi as sui
- from window_controller.pickup_passwd_window import PickupWindow, ResultReturn
- import message.message_pb2 as message
- from window_controller.reparking_window import ReparkingWindow
- from window_controller.full_car_window import FullcarWindow
- from window_controller.led import Led
- import copy
- import async_communication as cmt
- import mytool.db_helper.db_operation as spmng
- class MainWindow(QMainWindow, sui.Ui_MainWindow):
- # # 取车界面信号
- # signal_dict = pyqtSignal(dict)
- def __init__(self, parking_config, mq_config, db_config, parent=None):
- super(MainWindow, self).__init__(parent)
- self.command_dict = {}
- self.unit_space_dict = None
- self.setupUi(self)
- self.parking_config = parking_config
- self.label.setText(self.parking_config['process_title'])
- # 数据存储
- # 全矩阵
- self.btn_positions = [(i, j) for i in range(self.parking_config['row'] - 1, -1, -1) for j in
- range(self.parking_config['column'])]
- # # 奇数矩阵
- # self.btn_positions1 = [(i, j) for i in range(self.parking_config['row']-1, -1, -1) for j in
- # range(1,self.parking_config['column'],2)]
- # # 偶数矩阵
- # self.btn_positions2 = [(i, j) for i in range(self.parking_config['row']-1, -1, -1) for j in
- # range(2,self.parking_config['column']+2,2)]
- self._dispatch_statu = {}
- self.unit_space_is_init = False
- self.process_is_init = False
- self.parking_unit_list = self.parking_config['parking_unit_list']
- self.process_unit_list = self.parking_config['process_unit_list']
- self.db_unit_list = self.parking_config['db_unit_list']
- self.label_dict = {}
- self.list_widget_dict = {}
- self.setWindowTitle(self.parking_config['window_title'])
- # 锁
- self.data_lock = threading.Lock()
- # 配置导入初始化数据库和rabbitmq
- self.db = spmng.DBOperation(db_config['db_ip'], db_config['db_port'], db_config['db_name'],
- db_config['db_user'], db_config['db_password'])
- self.rabbitmq = cmt.RabbitAsyncCommunicator(mq_config['mq_ip'], mq_config['mq_port'], mq_config['mq_user'],
- mq_config['mq_password'])
- try:
- self.rabbitmq.Init(None, mq_config['mq_statu_exchange_keys'])
- for ex, key in mq_config['mq_statu_exchange_keys']:
- self.rabbitmq.bind_statu_callback(ex, key, self.receive_dispatch_statu)
- self.rabbitmq.start()
- except Exception as e:
- print('rabbitmq启动失败!' + str(e.args))
- self.out_date = None
- self.in_date = None
- # 拓展功能
- self.action_queryBlacklist.triggered.connect(self.btn_query_blacklist)
- self.action_addBlacklist.triggered.connect(self.btn_add_blacklist)
- self.action_deleteBlacklist.triggered.connect(self.btn_delete_blacklist)
- self.action_queryWhitelist.triggered.connect(self.btn_query_whitelist)
- self.action_addWhitelist.triggered.connect(self.btn_add_whitelist)
- self.action_deleteWhitelist.triggered.connect(self.btn_delete_whitelist)
- # 记录表单元号,流程表单元号,车位表单元号
- self.unit_comboBox.addItems(list(self.parking_unit_list.keys()))
- self.process_comboBox.addItems(list(self.process_unit_list.keys()))
- self.db_comboBox.addItems(list(self.db_unit_list.keys()))
- self.parking_unit = self.parking_config['init_parking_unit']
- self.process_unit = self.parking_config['init_process_unit']
- self.db_unit = self.parking_config['init_db_unit_list']
- self.unit_comboBox.setCurrentText(self.parking_unit)
- self.process_comboBox.setCurrentText(self.process_unit)
- self.db_comboBox.setCurrentText(self.db_unit)
- self.updata_record_btn.clicked.connect(self.updata_record)
- # 调度状态指示灯
- self.plc_statu_led = Led()
- self.plc_statu_led.setEnabled(False) # 设置为不使能状态,如果需要切换可以设置为True。则可以实现点击切换指示灯颜色的效果
- self.plc_statu_led.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
- self.plc_statu_led.setChecked(False) # 设置状态
- self.dispatch_heart_timer = cmt.TimeStatu(1, 0.1)
- self.horizontalLayout_11.addWidget(self.plc_statu_led)
- self.db_statu_led = Led()
- self.db_statu_led.setEnabled(False) # 设置为不使能状态,如果需要切换可以设置为True。则可以实现点击切换指示灯颜色的效果
- self.db_statu_led.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
- self.db_statu_led.setChecked(False) # 设置状态
- self.horizontalLayout_11.addWidget(self.db_statu_led)
- # 是否输入过密码 密码保护默认五分钟
- self.t_time = time.time()
- self.is_pwd = False
- # 数据历史记录默认设置
- self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
- self.tableWidget.itemClicked.connect(self.show_car_image)
- self.tableWidget.setHorizontalHeaderLabels(self.parking_config['record_title'])
- now = datetime.datetime.now()
- zero_today = now - datetime.timedelta(hours=now.hour, minutes=now.minute, seconds=now.second,
- microseconds=now.microsecond)
- last_today = zero_today + datetime.timedelta(hours=23, minutes=59, seconds=59)
- self.in_dateTimeEdit.setDateTime(zero_today)
- self.out_dateTimeEdit.setDateTime(last_today)
- self.in_dateTimeEdit_2.setDateTime(zero_today)
- self.out_dateTimeEdit_2.setDateTime(last_today)
- self.db_find_Button.clicked.connect(self.db_record_find)
- # 车位显示模式
- self.show_model = self.car_number_rbtn_2.isChecked()
- # 切换库位按钮关联函数
- self.find_btn.clicked.connect(self.find_btn_click)
- self.update_unit_btn.clicked.connect(self.update_btn_click)
- self.update_unit_btn_2.clicked.connect(self.update_process_unit_btn_click)
- # 初始化显示库位高度
- font = QFont()
- font.setFamily('宋体')
- font.setBold(False)
- font.setPointSize(15)
- self.parking_listWidget.setFont(font)
- # 数据缓存
- self.space_dict = {}
- self.record_all_unit_park_dict = {}
- self.record_all_unit_pick_dict = {}
- self.db_unit_park_dict = {}
- self.db_unit_pick_dict = {}
- self.record_total_unit_park_dict = {11: {}, 12: {}, 13: {}, 14: {}, 21: {}, 22: {}, 23: {}, 24: {}, 25: {},
- 31: {}, 32: {}}
- self.record_total_unit_pick_dict = {11: {}, 12: {}, 13: {}, 14: {}, 21: {}, 22: {}, 23: {}, 24: {}, 25: {},
- 31: {}, 32: {}}
- self.last_command_dict = {}
- self.unit_label.setText(self.parking_unit)
- self.pushButton_grade1.setIcon(QIcon(QPixmap("./images/grade1.png")))
- self.pushButton_grade2.setIcon(QIcon(QPixmap("./images/grade2.png")))
- self.pushButton_grade3.setIcon(QIcon(QPixmap("./images/grade3.png")))
- self.pushButton_grade1.setText("车高等级:" + str(self.parking_config['grade1']))
- self.pushButton_grade2.setText("车高等级:" + str(self.parking_config['grade2']))
- self.pushButton_grade3.setText("车高等级:" + str(self.parking_config['grade3']))
- # 数据库更新时间
- self.db_update_time = time.time() - 3
- self.db_connect_statu = False
- # 数据库查询线程
- self.db_query = threading.Thread(target=self.db_query)
- self.db_query_isClose = False
- self.db_query.start()
- # 启动界面刷新定时器
- self.timer = QTimer()
- self.timer.timeout.connect(self.Switch)
- self.timer.start(200)
- # # 临时
- # self.show_unit_box.setVisible(False)
- # self.groupBox_2.setVisible(False)
- # self.db_unit_label.setVisible(False)
- # self.db_comboBox.setVisible(False)
- def receive_dispatch_statu(self, statu, ex, key):
- # 调度状态接收
- self._dispatch_statu[key] = statu
- def db_query(self):
- while self.db_query_isClose is False:
- # 查询车位
- self.data_lock.acquire()
- self.space_dict = self.db.query_space_in_unit(self.parking_unit_list[self.parking_unit])
- # 查询指令表
- for unit in self.process_unit_list[self.process_unit]:
- self.last_command_dict[unit] = self.db.query_command_all_in_unit_and_sort(unit)
- self.data_lock.release()
- # 数据库更新时间
- self.db_update_time = time.time()
- time.sleep(0.1)
- # 界面刷新定时器
- def Switch(self):
- # 200毫秒刷新一次,同时检查密码定时器是否超过五分钟
- time_now = time.time()
- if self.is_pwd is True and time_now - self.t_time > 300:
- self.is_pwd = False
- self.t_time = time_now
- self.in_date = self.in_dateTimeEdit_2.dateTime().toPyDateTime().strftime("%Y-%m-%d %H:%M:%S")
- self.out_date = self.out_dateTimeEdit_2.dateTime().toPyDateTime().strftime("%Y-%m-%d %H:%M:%S")
- # 更新记录表单元号,流程表单元号,车位表单元号
- self.db_unit = self.db_comboBox.currentText()
- # 检查连接
- self.db_connect_statu = self.check_connect_statu()
- if self.db_connect_statu:
- self.data_lock.acquire()
- unit = self.parking_unit_list[self.parking_unit]
- # 车位管理
- self.parkspace_show(self.parking_unit, self.parking_config["in_occupy_space"][str(unit)],
- self.parking_config["out_occupy_space"][str(unit)],
- self.parking_config["controlroom_occupy_space"][str(unit)])
- # # 流程监控
- self.process_monitoring(self.process_unit_list[self.process_unit])
- self.data_lock.release()
- def updata_record(self):
- # 当前选中时间段内所有单元记录表数据
- self.data_lock.acquire()
- self.record_all_unit_park_dict = self.db.query_park_count_in_time(self.in_date, self.out_date)
- self.record_all_unit_pick_dict = self.db.query_pick_count_out_time(self.in_date, self.out_date)
- # 当前选中时间内指定单元记录数据
- if len(self.db_unit) != 1 and self.db_unit_list[self.db_unit] is not None:
- self.db_unit_park_dict = self.db.query_park_count_in_time_and_unit(self.in_date, self.out_date,
- self.db_unit_list[self.db_unit])
- self.db_unit_pick_dict = self.db.query_pick_count_out_time_and_unit(self.in_date, self.out_date,
- self.db_unit_list[
- self.db_unit])
- # 当前选中时间内指定总单元记录数据
- if len(self.db_unit) == 1:
- for unit in self.db_unit_list[self.db_unit]:
- self.record_total_unit_park_dict[unit] = self.db.query_park_count_in_time_and_unit(self.in_date,
- self.out_date,
- unit)
- self.record_total_unit_pick_dict[unit] = self.db.query_pick_count_out_time_and_unit(self.in_date,
- self.out_date,
- unit)
- # # 停车数量记录
- self.show_parkingData()
- self.data_lock.release()
- # 检查数据库连接
- def check_connect_statu(self):
- # 检查调度连接
- key = "dispatch_%d_statu_port" % self.parking_unit_list[self.parking_unit]
- if (key in self._dispatch_statu) is False or self._dispatch_statu[key].timeout():
- self.plc_statu_led.setChecked(False)
- else:
- statu = self._dispatch_statu[key].statu
- dispatch_node_statu = message.dispatch_node_statu()
- try:
- tf.Parse(statu, dispatch_node_statu)
- except Exception:
- pass
- if self.dispatch_heart_timer.statu != dispatch_node_statu.plc_heartbeat:
- self.dispatch_heart_timer = cmt.TimeStatu(dispatch_node_statu.plc_heartbeat)
- self.plc_statu_led.setChecked(True)
- if self.dispatch_heart_timer.timeout():
- self.plc_statu_led.setChecked(False)
- # 检查数据库连接
- if time.time() - self.db_update_time > 3:
- self.db_statu_led.setChecked(False)
- else:
- self.db_statu_led.setChecked(True)
- return self.db_statu_led.isChecked()
- # 车位显示
- def parkspace_show(self, unit, in_occupy_space, out_occupy_space, controlroom_occupy_space):
- # 绘制车位按钮
- if self.space_dict is None:
- return
- is_show_car_number = self.car_number_rbtn_2.isChecked()
- if self.unit_space_dict != self.space_dict:
- self.unit_label.setText(unit)
- print('有修改')
- if self.unit_space_is_init == False:
- self.unit_space_dict = copy.deepcopy(self.space_dict)
- self.unit_space_is_init = True
- is_drawIn = False
- is_drawOut = False
- is_drawControlRoom = False
- for park, position in zip(self.space_dict, self.btn_positions):
- btn = QPushButton()
- font, text_str, stylesheet, tool_tip = self.get_btn_show(park)
- btn.setFont(font)
- btn.setLayout(QGridLayout())
- btn.setText(text_str)
- btn.setStyleSheet(stylesheet)
- btn.setToolTip(tool_tip)
- btn.setObjectName(str(park["table_id"]))
- if text_str == "入 口" and is_drawIn is False:
- self.unit_gridLayout.addWidget(btn, *position, 1, in_occupy_space)
- is_drawIn = True
- elif text_str == "出 口" and is_drawOut is False:
- self.unit_gridLayout.addWidget(btn, *position, 1, out_occupy_space)
- is_drawOut = True
- elif text_str == " 控制室 " and is_drawControlRoom is False:
- self.unit_gridLayout.addWidget(btn, *position, 1, controlroom_occupy_space)
- is_drawControlRoom = True
- elif text_str != "出 口" and text_str != "入 口" and text_str != " 控制室 ":
- btn.setContextMenuPolicy(Qt.CustomContextMenu)
- btn.customContextMenuRequested.connect(self.park_btn_right_click)
- btn.clicked.connect(self.park_btn_left_click)
- self.unit_gridLayout.addWidget(btn, *position)
- else:
- temp1 = copy.deepcopy(self.unit_space_dict)
- temp2 = copy.deepcopy(self.space_dict)
- merged = zip(temp1, temp2)
- for last_space,space in merged:
- if last_space.values() != space.values():
- font, text_str, stylesheet, tool_tip = self.get_btn_show(space)
- results = self.findChild(QPushButton, str(space["table_id"]))
- if results is None:
- return
- results.setFont(font)
- results.setText(text_str)
- results.setStyleSheet(stylesheet)
- results.setToolTip(tool_tip)
- self.unit_space_dict = copy.deepcopy(self.space_dict)
- if self.show_model != is_show_car_number:
- self.show_model = is_show_car_number
- for park in self.unit_space_dict:
- if park["statu"] == 2:
- font, text_str, stylesheet, tool_tip = self.get_btn_show(park)
- results = self.findChild(QPushButton, str(park["table_id"]))
- results.setFont(font)
- results.setText(text_str)
- results.setStyleSheet(stylesheet)
- results.setToolTip(tool_tip)
- # 流程监控
- def process_monitoring(self, process_unit_list):
- if self.process_is_init is False:
- for i in process_unit_list:
- self.list_widget_dict[i] = QListWidget(self)
- self.list_widget_dict[i].setContextMenuPolicy(Qt.CustomContextMenu)
- self.list_widget_dict[i].customContextMenuRequested.connect(self.custom_right_menu)
- self.list_widget_dict[i].setStyleSheet("border:5px solid #014F84;")
- self.list_widget_dict[i].setObjectName(('list_widget_%d' % (i + 1)))
- self.process_horizontalLayout.addWidget(self.list_widget_dict[i])
- self.label_dict[i] = QLabel(self)
- # 临时
- # self.label_dict[i].setText(unit_char + "-" + str((i % 10)))
- self.label_dict[i].setText(self.get_unit(i))
- # self.label_dict[i].setText("停取流程")
- self.label_dict[i].setAlignment(Qt.AlignCenter)
- self.label_dict[i].setFont(QFont("华文楷体", 60, QFont.Bold))
- self.command_dict[i] = []
- self.unit_horizontalLayout.addWidget(self.label_dict[i])
- self.process_is_init = True
- for i in process_unit_list:
- if (i in self.last_command_dict.keys()) is False or self.last_command_dict[i] is None:
- return
- else:
- last_command_dict = copy.deepcopy(self.last_command_dict[i])
- if self.command_dict[i] != last_command_dict:
- self.command_dict[i] = copy.deepcopy(last_command_dict)
- self.list_widget_dict[i].clear()
- for dict in self.command_dict[i]:
- if dict['statu'] != 3:
- self.list_widget_dict[i].addItem(self.get_listWidget_item(dict))
- for dict in self.command_dict[i]:
- if dict['statu'] == 3:
- self.list_widget_dict[i].addItem(self.get_listWidget_item(dict))
- # 刷新停车数据
- def show_parkingData(self):
- # 有一个数据是空就直接返回
- if self.record_all_unit_park_dict is None or self.record_all_unit_pick_dict is None or self.db_unit_park_dict is None or \
- self.db_unit_pick_dict is None or self.record_total_unit_park_dict is None or self.record_total_unit_pick_dict is None:
- return
- record_all_unit_park_dict, record_all_unit_pick_dict, db_unit_park_dict, db_unit_pick_dict, record_total_unit_park_dict, record_total_unit_pick_dict = \
- copy.deepcopy(self.record_all_unit_park_dict), copy.deepcopy(self.record_all_unit_pick_dict), copy.deepcopy(
- self.db_unit_park_dict), copy.deepcopy(self.db_unit_pick_dict), copy.deepcopy(
- self.record_total_unit_park_dict), copy.deepcopy(self.record_total_unit_pick_dict)
- unit_park_count = unit_pick_count = 0
- all_park_count, all_pick_count = record_all_unit_park_dict[0]['count(*)'], record_all_unit_pick_dict[0]['count(*)']
- # 当前选中时间内指定总单元记录数据
- if len(self.db_unit) == 1:
- for unit in self.db_unit_list[self.db_unit]:
- unit_park_count = unit_park_count + record_total_unit_park_dict[unit][0]['count(*)']
- unit_pick_count = unit_pick_count + record_total_unit_pick_dict[unit][0]['count(*)']
- # 当前选中时间内指定单元记录数据
- elif len(self.db_unit) != 1 and isinstance(self.db_unit_list[self.db_unit],list) is False:
- unit_park_count, unit_pick_count = db_unit_park_dict[0]['count(*)'], db_unit_pick_dict[0]['count(*)']
- else:
- unit_park_count, unit_pick_count = all_park_count, all_pick_count
- self.unit_park_count_label.setText("该单元停车{value}次".format(value=unit_park_count))
- self.unit_pick_count_label.setText("该单元取车{value}次".format(value=unit_pick_count))
- self.all_park_count_label.setText("所有库停车{value}次".format(value=all_park_count))
- self.all_pick_count_label.setText("所有库取车{value}次".format(value=all_pick_count))
- def show_parking_details(self, park_dict):
- self.parking_listWidget.clear()
- for poit in park_dict.items():
- item = QListWidgetItem()
- item.setSizeHint(QSize(50, 39))
- name = self.get_name(poit[0])
- if name == '未知':
- continue
- value = poit[1]
- if name == '楼层':
- value = value - self.parking_config['floor_minus']
- item.setText(name + ":" + str(value))
- item.setToolTip(str(value))
- self.parking_listWidget.addItem(item)
- res = self.db.query_space_in_car_number(park_dict['car_number'])
- self.plate_full_image_label.setPixmap(QPixmap(""))
- self.plate_clip_image_label.setPixmap(QPixmap(""))
- if len(res) > 0:
- try:
- rep = requests.get(res[0]['plate_full_image'])
- pix = QPixmap()
- pix.loadFromData(rep.content)
- pix = pix.scaled(self.plate_full_image_label.size(), Qt.KeepAspectRatio)
- self.plate_full_image_label.setPixmap(pix)
- except Exception as e:
- print('全景图:' + str(e.args))
- try:
- rep = requests.get(res[0]['plate_clip_image'])
- pix = QPixmap()
- pix.loadFromData(rep.content)
- pix = pix.scaled(self.plate_clip_image_label.size(), Qt.KeepAspectRatio)
- self.plate_clip_image_label.setPixmap(pix)
- except Exception as e:
- print('特写图:' + str(e.args))
- def find_btn_click(self):
- text = self.find_lineEdit.text()
- if text == '':
- QMessageBox.question(None, "提示", "请输入要查询的内容",
- QMessageBox.Ok)
- return
- if self.car_number_rbtn.isChecked():
- park_dict = self.db.query_space_in_car_number(text)
- if len(park_dict) > 0:
- self.show_parking_details(park_dict[0])
- else:
- QMessageBox.question(None, "查询结果", "车牌号:" + text + " 未查询到数据!",
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- elif self.key_rbtn.isChecked():
- park_dict = self.db.query_space_in_primary_key(text)
- if len(park_dict) > 0:
- self.show_parking_details(park_dict[0])
- else:
- QMessageBox.question(None, "查询结果", "唯一码:" + text + " 未查询到数据!",
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- # elif self.parking_rbtn.isChecked():
- # park_dict = self.db.query_space_in_unit_and_table_id(self.unit, text)
- # if len(park_dict) > 0:
- # self.show_parking_details(park_dict[0])
- #
- # else:
- # QMessageBox.question(None, "查询结果", "车位id:" + text + " 未查询到数据!",
- # QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- return
- def update_process_unit_btn_click(self):
- self.process_unit = self.process_comboBox.currentText()
- for i in range(self.process_horizontalLayout.count()):
- self.process_horizontalLayout.itemAt(i).widget().deleteLater()
- for i in range(self.unit_horizontalLayout.count()):
- self.unit_horizontalLayout.itemAt(i).widget().deleteLater()
- self.process_is_init = False
- def update_btn_click(self):
- parking_unit = self.unit_comboBox.currentText()
- if self.parking_unit_list[self.parking_unit] == self.parking_unit_list[parking_unit]:
- return
- self.parking_unit = parking_unit
- unit = self.parking_unit_list[self.parking_unit]
- for i in range(self.unit_gridLayout.count()):
- self.unit_gridLayout.itemAt(i).widget().deleteLater()
- self.data_lock.acquire()
- self.space_dict = self.db.query_space_in_unit(unit)
- self.data_lock.release()
- self.unit_space_is_init = False
- def park_btn_left_click(self):
- if self.db_connect_statu:
- sender = self.sender()
- tool_tip = sender.toolTip()
- dict = json.loads(tool_tip)
- self.show_parking_details(dict)
- else:
- QMessageBox.critical(None, "提示", "数据库连接断开!", QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def park_btn_right_click(self):
- if self.db_connect_statu:
- menu = QMenu(self)
- sender = self.sender()
- tool_tip = sender.toolTip()
- dict = json.loads(tool_tip)
- action = menu.addAction('启用车位')
- action.triggered.connect(partial(self.btn_opeSpace, dict, 0))
- action = menu.addAction('停用车位')
- action.triggered.connect(partial(self.btn_disableSpace, dict, 10))
- action = menu.addAction('清除车位')
- action.triggered.connect(partial(self.btn_clearSpace, dict))
- action = menu.addAction('正常取车')
- action.triggered.connect(partial(self.btn_pickUp, dict, message.PROCESS_NORMAL))
- action = menu.addAction('强制取车')
- action.triggered.connect(partial(self.btn_pickUp, dict, message.PROCESS_ONLY_TO_DISPATCH))
- action = menu.addAction('虚拟取车')
- action.triggered.connect(partial(self.btn_pickUp, dict, message.PROCESS_ONLY_TO_PAY))
- # action = menu.addAction('更换车位')
- # action.triggered.connect(partial(self.btn_replace_parking, dict))
- action = menu.addAction('填充车位')
- action.triggered.connect(partial(self.btn_fill_parking, dict))
- action = menu.addAction('增加备注')
- action.triggered.connect(partial(self.btn_add_remarks, dict))
- menu.exec_(QCursor.pos())
- else:
- QMessageBox.critical(None, "提示", "数据库连接断开!", QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_disableSpace(self, dict, statu):
- if self.is_input_pwd() is True:
- res = self.db.update_space_status_in_space_id(dict["id"], statu)
- if res == 0:
- QMessageBox.question(None, '提示', '更新车位失败!请检查是否点击错误!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_opeSpace(self, dict, statu):
- if self.is_input_pwd() is True:
- res = self.db.update_space_status_in_space_id(dict["id"], statu)
- if res == 0:
- QMessageBox.question(None, '提示', '更新车位失败!请检查是否点击错误!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_clearSpace(self, dict):
- if self.is_input_pwd() is True:
- res = self.db.clear_space_data(dict["id"])
- if res == 0:
- QMessageBox.question(None, '提示', '更新车位失败!请检查是否点击错误!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_pickUp(self, dict, table_process_mod):
- if self.is_input_pwd() is True:
- table = message.pick_table()
- table.statu.table_process_mod = table_process_mod
- table.primary_key = dict["primary_key"]
- self.rabbitmq.publish("command_ex", "user_pick_command_request_port",
- tf.MessageToString(table, as_utf8=True))
- QMessageBox.question(None, '提示', '取车消息发送成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- # def btn_replace_parking(self, dict):
- # if self.is_input_pwd() is True:
- # if dict['car_number'] == 'None' or dict['primary_key'] == 'None':
- # QMessageBox.question(None, '提示', '没有车牌号或唯一码,不符合更换车位条件!',
- # QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- # return
- # repwind = ReparkingWindow()
- # repwind.exec()
- # res = repwind.get_results()
- # if res is True:
- # target_parking = self.db.query_parking_in_unit_tableid(dict['unit'], repwind.get_park_tableid())[0]
- # if target_parking['car_number'] is not None:
- # QMessageBox.question(None, '提示', '目标车位不为空!',
- # QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- # return
- # parking = self.db.query_space_in_car_number(dict['car_number'])[0]
- #
- # space_info_sql = "NULL"
- # measure_info_sql = "NULL"
- # plate_color_sql = "NULL"
- # plate_type_sql = "NULL"
- # plate_confidence_sql = "NULL"
- # recognition_time_sql = "NULL"
- # plate_full_image_sql = "NULL"
- # plate_clip_image_sql = "NULL"
- #
- # if parking['space_info'] is not None:
- # space_info_sql = "'%s'" % parking['space_info']
- #
- # if parking['measure_info'] is not None:
- # measure_info_sql = "'%s'" % parking['measure_info']
- #
- # if parking['plate_color'] is not None:
- # plate_color_sql = "'%s'" % parking['plate_color']
- #
- # if parking['plate_type'] is not None:
- # plate_type_sql = "'%s'" % parking['plate_type']
- #
- # if parking['plate_confidence'] is not None:
- # plate_confidence_sql = "%d" % parking['plate_confidence']
- #
- # if parking['recognition_time'] is not None:
- # recognition_time_sql = "'%s'" % parking['recognition_time']
- #
- # if parking['plate_full_image'] is not None:
- # plate_full_image_sql = "'%s'" % parking['plate_full_image']
- #
- # if parking['plate_clip_image'] is not None:
- # plate_clip_image_sql = "'%s'" % parking['plate_clip_image']
- #
- # sql2 = "update space set car_number='%s', primary_key='%s', statu=%d , space_info=%s , measure_info=%s ,\
- # plate_color=%s , plate_type=%s , plate_confidence=%s , recognition_time=%s , plate_full_image=%s , plate_clip_image=%s where id=%d" \
- # % (parking['car_number'], parking['primary_key'], parking['statu'], space_info_sql,
- # measure_info_sql,
- # plate_color_sql, \
- # plate_type_sql, plate_confidence_sql, recognition_time_sql, plate_full_image_sql,
- # plate_clip_image_sql, target_parking['id'])
- # # print(sql2)
- #
- # res = self.db.update(sql2)
- # if res == 0:
- # QMessageBox.question(None, '提示', '执行失败!',
- # QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- # return
- # res = self.db.clear_space_data(parking['id'])
- # if res > 0:
- # QMessageBox.question(None, '提示', '车位交换成功!',
- # QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_fill_parking(self, dict):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- car_number = fullcar.get_text()
- res = self.db.update_space_status_car_number_in_space_id(dict['id'], car_number, 2)
- if res > 0:
- QMessageBox.question(None, '提示', '车位填充成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_query_blacklist(self):
- if self.is_input_pwd() is True:
- res = self.db.query_blacklist()
- if res is not None and len(res) > 0:
- blacklist = ""
- for dict in res:
- blacklist = blacklist + str(dict) + "\n\n"
- QMessageBox.question(None, '提示', blacklist,
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '没有黑名单!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_add_blacklist(self):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- car_number = fullcar.get_text()
- res = self.db.add_blacklist_in_car_number(car_number, datetime.datetime.now(), None, None)
- if res is not None and res > 0:
- QMessageBox.question(None, '提示', '黑名单添加成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '黑名单添加失败!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_delete_blacklist(self):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- car_number = fullcar.get_text()
- res = self.db.delete_blacklist_in_car_number(car_number)
- if res is not None and res > 0:
- QMessageBox.question(None, '提示', '黑名单删除成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '黑名单删除失败!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_query_whitelist(self):
- if self.is_input_pwd() is True:
- res = self.db.query_whitelist()
- if res is not None and len(res) > 0:
- whitelist = ""
- for dict in res:
- whitelist = whitelist + str(dict) + "\n\n"
- QMessageBox.question(None, '提示', whitelist,
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '没有白名单!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_add_whitelist(self):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- car_number = fullcar.get_text()
- res = self.db.add_whitelist_in_car_number(car_number, datetime.datetime.now(), None, None)
- if res is not None and res > 0:
- QMessageBox.question(None, '提示', '白名单添加成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '黑名单删除失败!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_delete_whitelist(self):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- car_number = fullcar.get_text()
- res = self.db.delete_whitelist_in_car_number(car_number)
- if res is not None and res > 0:
- QMessageBox.question(None, '提示', '白名单删除成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- else:
- QMessageBox.question(None, '提示', '黑名单删除失败!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def btn_add_remarks(self, dict):
- if self.is_input_pwd() is True:
- fullcar = FullcarWindow()
- fullcar.exec()
- if fullcar.get_results() is True:
- remark = fullcar.get_text()
- res = self.db.update_space_remark_in_space_id(dict['id'], remark)
- if res > 0:
- QMessageBox.question(None, '提示', '车位添加备注成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- def get_btn_show(self, park):
- font = QFont()
- font.setFamily('宋体')
- font.setPointSize(21)
- if park["statu"] == 6:
- text_str = "入 口"
- font.setBold(True)
- elif park["statu"] == 7:
- text_str = "出 口"
- font.setBold(True)
- elif park["statu"] == 8:
- text_str = " 控制室 "
- font.setBold(True)
- # elif park["statu"] == 10 and park["remark"] is not None:
- # text_str = park["remark"][0:4]
- # font.setPointSize(20)
- elif 0 < park["statu"] < 6 and park["car_number"] is not None and self.car_number_rbtn_2.isChecked():
- text_str = park["car_number"]
- font.setPointSize(20)
- else:
- text_str = "车位:%d\n楼层:%d" % (park["table_id"], (park["floor"] - self.parking_config['floor_minus']))
- font.setPointSize(10)
- background_color = ""
- background_image = ""
- # 设置背景图
- if park["height_level"] == self.parking_config['grade1']:
- background_image = "background-image: url(./images/grade1.png);"
- elif park["height_level"] == self.parking_config['grade2']:
- background_image = "background-image: url(./images/grade2.png);"
- elif park["height_level"] == self.parking_config['grade3']:
- background_image = "background-image: url(./images/grade3.png);"
- elif park["height_level"] == self.parking_config['grade4']:
- background_image = "background-image: url(./images/grade1.png);"
- # 故障
- if park["statu"] == 10:
- background_color = "background-color:rgb(255,130,130);"
- # 空闲
- elif park["statu"] == 0:
- background_color = "background-color:rgb(195,195,195);"
- # 存车中
- elif park["statu"] == 1:
- background_color = "background-color:rgb(140,100,220);"
- # 占用
- elif park["statu"] == 2:
- background_color = "background-color:rgb(248,239,71);"
- # 已锁定
- elif park["statu"] == 3:
- background_color = "background-color:rgb(0,100,255);"
- # 取车中
- elif park["statu"] == 4:
- background_color = "background-color:rgb(102,255,255);"
- # 已预约
- elif park["statu"] == 5:
- background_color = "background-color:rgb(0,255,0);"
- # 出入口
- elif park["statu"] == 6 or park["statu"] == 7 or park["statu"] == 8:
- background_color = "background-color:rgb(0,162,232);"
- background_image = ""
- # elif park["statu"] == 0 and park["remark"] is not None:
- # background_color = "background-color:rgb(255,130,130);"
- stylesheet = background_color + "pressed{padding-top:2px;padding-left:2px;};" + background_image + "background-repeat:no-repeat;"
- for key in park.keys():
- if park[key] is None:
- park[key] = ''
- tool_tip = json.dumps(park, cls=DjangoJSONEncoder)
- return font, text_str, stylesheet, tool_tip
- # 显示车辆图片
- def show_car_image(self, Item):
- try:
- row = Item.row() # 获取行数
- col = self.tableWidget.columnCount() # 获取列数 注意是column而不是col哦
- plate_full_image = self.tableWidget.item(row, col - 2)
- plate_clip_image = self.tableWidget.item(row, col - 1)
- self.plate_full_image_label_2.setPixmap(QPixmap(""))
- self.plate_clip_image_label_2.setPixmap(QPixmap(""))
- if plate_full_image is not None:
- rep = requests.get(plate_full_image.text())
- pix = QPixmap()
- pix.loadFromData(rep.content)
- pix = pix.scaled(self.plate_full_image_label_2.size(), Qt.KeepAspectRatio)
- self.plate_full_image_label_2.setPixmap(pix)
- if plate_clip_image is not None:
- rep = requests.get(plate_clip_image.text())
- pix = QPixmap()
- pix.loadFromData(rep.content)
- pix = pix.scaled(self.plate_clip_image_label_2.size(), Qt.KeepAspectRatio)
- self.plate_clip_image_label_2.setPixmap(pix)
- except Exception as e:
- traceback.print_exc()
- # 查询历史记录
- def db_record_find(self):
- if self.db_connect_statu is False:
- QMessageBox.critical(None, "提示", "数据库连接断开!", QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- return
- if self.db_unit_list[self.db_unit] == 0:
- unit_sql = ""
- elif type(self.db_unit_list[self.db_unit]) != int:
- unit_sql = "and ("
- for i in self.db_unit_list[self.db_unit]:
- unit_sql = unit_sql + "unit_id=%d or " % i
- unit_sql = unit_sql[:-3] + ")"
- else:
- unit_sql = "and (unit_id = %s)" % self.db_unit_list[self.db_unit]
- in_datatime = self.in_dateTimeEdit.dateTime().toPyDateTime()
- out_datatime = self.out_dateTimeEdit.dateTime().toPyDateTime()
- car_number = self.car_number_lineEdit.text()
- in_time_sql = "(in_time_start >= '%s' and in_time_start <= '%s') " % (in_datatime, out_datatime)
- out_time_sql = "(out_time_start >= '%s' and out_time_start <= '%s') " % (in_datatime, out_datatime)
- in_and_out_time_sql = "(" + in_time_sql + " or " + out_time_sql + ")"
- if self.park_radioButton.isChecked():
- time_sql = in_time_sql
- elif self.pick_radioButton.isChecked():
- time_sql = out_time_sql
- else:
- time_sql = in_and_out_time_sql
- car_number_sql = ""
- if car_number != "":
- car_number_sql = "and car_number like '%{}%'".format(car_number)
- sql = "select * from record where %s %s %s " % (time_sql, unit_sql, car_number_sql)
- print(sql)
- results = self.db.query(sql)
- self.tableWidget.clearContents()
- self.tableWidget.setRowCount(0)
- for i in range(len(results)):
- row_count = self.tableWidget.rowCount() # 返回当前行数(尾部)
- self.tableWidget.insertRow(row_count) # 尾部插入一行
- for j, value in zip(range(0, len(results[i])), results[i].values()):
- self.tableWidget.setItem(i, j, QTableWidgetItem(str(value)))
- # print(results)
- def custom_right_menu(self, pos):
- sender = self.sender()
- menu = QMenu()
- opt1 = menu.addAction("恢复排队")
- opt2 = menu.addAction("设为故障")
- opt3 = menu.addAction("删除任务")
- try:
- hitIndex = sender.indexAt(pos).row()
- # print(hitIndex)
- if hitIndex > -1:
- # 获取item内容
- car_number = sender.item(hitIndex).toolTip()
- action = menu.exec_(sender.mapToGlobal(pos))
- if action is None:
- return
- if self.is_input_pwd() is True:
- self.is_pwd = False
- if self.is_input_pwd('该操作存在风险,请再次输入密码!') is True:
- if action == opt1:
- res = self.db.update_command_status_in_car_number(car_number, 0)
- if action == opt2:
- res = self.db.update_command_status_in_car_number(car_number, 3)
- if action == opt3:
- res = self.db.delete_command(car_number)
- if res > 0:
- QMessageBox.question(None, '提示', '指令修改成功!',
- QMessageBox.Ok) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- except Exception as e:
- pass
- def is_input_pwd(self, tipstr=None):
- if self.is_pwd is False:
- # 组装显示信息
- # 实例取车窗口,并以模态窗口形式显示
- pickup_window = PickupWindow(tipstr,self.parking_config['passwd'])
- pickup_window.exec_()
- res = pickup_window.getResult()
- if res is ResultReturn.OK:
- self.is_pwd = True
- self.t_time = time.time()
- return True
- else:
- return False
- return True
- def get_listWidget_item(self, dict):
- item = QListWidgetItem()
- item.setFont(QFont('微软雅黑', 14, QFont.Bold))
- item.setToolTip(dict['car_number'])
- parkspace = message.parkspace_info()
- try:
- tf.Parse(dict['space_info'], parkspace)
- except Exception:
- parkspace.table_id = -1
- show_str = ""
- if dict['type'] == 1: # 存车指令
- item.setBackground(QColor(185, 240, 240))
- if (dict['statu'] == 0): # 排队
- item.setForeground(QColor(80, 80, 80))
- show_str = dict['car_number'] + " 排队中"
- elif (dict['statu'] == 1): # 工作
- item.setForeground(QColor('blue'))
- show_str = dict['car_number'] + " 存车中"
- elif (dict['statu'] == 2): # 已完成
- item.setForeground(QColor('green'))
- show_str = dict['car_number'] + " 已完成"
- elif (dict['statu'] == 3): # 已完成
- item.setForeground(QColor('red'))
- show_str = dict['car_number'] + " 故障!"
- show_str = "存 %d入 %d出 %d号车位 %s %s " % (
- dict["import_id"], dict["export_id"], parkspace.table_id, show_str, str(dict["queue_time"].time()))
- elif dict['type'] == 2: # 取车指令
- item.setBackground(QColor(250, 240, 200))
- if (dict['statu'] == 0): # 排队
- item.setForeground(QColor(80, 80, 80))
- show_str = dict['car_number'] + " 排队中"
- elif (dict['statu'] == 1): # 工作
- item.setForeground(QColor('blue'))
- show_str = dict['car_number'] + " 取车中"
- elif (dict['statu'] == 2): # 已完成
- item.setForeground(QColor('green'))
- show_str = dict['car_number'] + " 已完成"
- elif (dict['statu'] == 3): # 已完成
- item.setForeground(QColor('red'))
- show_str = dict['car_number'] + " 故障!"
- show_str = "取 %d入 %d出 %d号车位 %s %s " % (
- dict["import_id"], dict["export_id"], parkspace.table_id, show_str, str(dict["queue_time"].time()))
- item.setText(show_str)
- return item
- def closeEvent(self, event):
- results = QMessageBox.question(self, '退出', '你确定要退出吗?', QMessageBox.Yes | QMessageBox.No,
- QMessageBox.No) # "退出"代表的是弹出框的标题,"你确认退出.."表示弹出框的内容
- if results == QMessageBox.Yes:
- self.db_query_isClose = True
- self.db_query.join()
- self.rabbitmq.close()
- event.accept() # 接受关闭事件
- # 强制结束进程
- pid = os.getpid()
- os.kill(pid, signal.SIGTERM)
- else:
- event.ignore() # 忽略关闭事件
- def get_name(self, key):
- if key == 'id':
- return '总车位号'
- elif key == 'table_id':
- return '表编号'
- elif key == 'floor':
- return '楼层'
- elif key == 'height_level':
- return '限高等级'
- elif key == 'height':
- return '限高'
- elif key == 'wheel_base_level':
- return '限制轴距等级'
- elif key == 'wheel_base':
- return '限制轴距'
- elif key == 'car_number':
- return '车牌号'
- elif key == 'statu':
- return '车位状态'
- elif key == 'plate_color':
- return '号牌颜色'
- elif key == 'plate_type':
- return '号牌类型'
- elif key == 'plate_confidence':
- return '号牌可信度'
- elif key == 'recognition_time':
- return '识别时间'
- elif key == 'primary_key':
- return '唯一码'
- elif key == 'plate_full_image':
- return '号牌全景图'
- elif key == 'plate_clip_image':
- return '号牌特写图'
- elif key == 'remark':
- return '备注'
- elif key == 'remark_time':
- return '备注时间'
- elif key == 'apply_end_time':
- return '预约结束时间'
- else:
- return '未知'
- def get_unit(self, unit):
- if unit == 1:
- return 'A'
- elif unit == 2:
- return 'B'
- elif unit == 11:
- return 'A'
- elif unit == 12:
- return 'A2'
- elif unit == 13:
- return 'A3'
- elif unit == 14:
- return 'A4'
- elif unit == 21:
- return 'B'
- elif unit == 22:
- return 'B2'
- elif unit == 23:
- return 'B3'
- elif unit == 24:
- return 'B4'
- elif unit == 25:
- return 'B5'
- elif unit == 31:
- return 'C1'
- elif unit == 32:
- return 'C2'
- return '未知'
|