import asyncio import datetime import hashlib import json import sys import time from concurrent.futures import ThreadPoolExecutor import requests sys.path.append("..") import pymysql import uuid import chardet import message_pb2 as message import google.protobuf.text_format as tf import http_client import mytool.db_helper.db_operation as spmng MeasureStatu={"ok":0,"无数据":1,"噪声":2,"超界":3} class CommandChecker: def __init__(self, db_config): 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._dispatch_statu = {} self._measure_statu = {} self._in_url = 'http://szdy.xmsztc.cn/Api/CarInEntry' self._query_url = 'http://szdy.xmsztc.cn/Api/GetBill' self._out_url = 'http://szdy.xmsztc.cn/Api/CarOutEntry' self._secret_key = 'anzs74aph8ac8dy6tj48t05js6zpkgx5' self._parking_id = '2306041414159951342' self._app_id = 'blbc5zkpyymaicd3' self._http = 'https://sztc.smartcityxm.com/wechath5/#/pagesA/parkingBill/inrecord_parking?inRecordId=' self.chnnId_in = {12: '2306041439573931681'} self.chnnId_out = {12: '2306041441029631932'} self._plate_color = {'蓝色': '1', '黑色': '2', '黄色': '3', '白色': '4', '绿色': '5', '其他': '6'} def get_in_url(self): return self._in_url def receive_dispatch_statu(self, statu, ex, key): self._dispatch_statu[key] = statu def receive_measure_info(self, statu, ex, key): self._measure_statu[key] = statu def push_http_request(self, url, request): results = '' statu = message.eError tm = time.time() # 若推送失败就重试最多2s while time.time() - tm < 2: try: print(url) resp = requests.post(url, json=request).json() print(resp) if ('Tag' in resp.keys()) and resp['Tag'] == 1: statu = message.eNormal results = resp break else: statu = message.eError results = '收费系统反馈错误!message:%s' % resp except Exception as e: statu = message.eError results = '向收费系统推送请求失败! ERROR:%s' % (str(e.args)) time.sleep(0.2) return statu, results def entrance_isOK(self, park_body): # 停车表单 park_table = message.park_table() try: tf.Parse(park_body, park_table) except Exception as e: park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(停车表单错误)" + str(e.args) return park_table # 检查调度状态 dispatch_key = "dispatch_%d_statu_port" % park_table.unit_id if (dispatch_key in self._dispatch_statu) is False or self._dispatch_statu[dispatch_key].timeout(): park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(调度)" return park_table # 获取车高信息 dispatch_node_statu = message.dispatch_node_statu() try: tf.Parse(self._dispatch_statu[dispatch_key].statu, dispatch_node_statu) except Exception: park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(调度状态消息错误)" return park_table if dispatch_node_statu.plc_carrier_status == 0: park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(搬运器)" return park_table # elif dispatch_node_statu.plc_carrier_status == 4: # park_table.statu.execute_statu = message.eWarning # park_table.statu.statu_description = "该单元设备维护中!请前往其他入口!" # return park_table dispatch_plc_passway_status = dispatch_node_statu.dispatch_plc_passway_status_vector[park_table.import_id - 1] if dispatch_plc_passway_status.car_height == 0: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "未检测到车辆!" return park_table elif dispatch_plc_passway_status.car_height == 4: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆超高,请退出车库!" return park_table sensor_1 = dispatch_plc_passway_status.sensor_1 sensor_2 = dispatch_plc_passway_status.sensor_2 if park_table.unit_id != 31 and park_table.unit_id != 32: if (sensor_2 >> 3) & 0x01 != 1 or (sensor_2 >> 4) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆未停到位,请根据库内指示灯挪车!" return park_table if (sensor_1 >> 2) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆超限,请联系现场工作人员!" return park_table if (sensor_1 >> 3) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆后超界,请往前!" return park_table if (sensor_1 >> 4) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆前超界,请往后!" return park_table if (sensor_1 >> 5) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆左超界,请往右!" return park_table if (sensor_1 >> 6) & 0x01 != 1: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆右超界,请往左!" return park_table measure_info = message.measure_info() if park_table.unit_id == 31 or park_table.unit_id == 32: measure_key = "measure_%d_statu_port" % park_table.terminal_id if (measure_key in self._measure_statu) is False or self._measure_statu[measure_key].timeout(): park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(雷达)" return park_table # 获取车高信息 try: tf.Parse(self._measure_statu[measure_key].statu, measure_info) except Exception: park_table.statu.execute_statu = message.eError park_table.statu.statu_description = "设备故障,请联系管理员!" + "(雷达状态消息错误)" return park_table # 获取雷达信息 tm = time.time() while time.time() - tm < 2: # 没有超界。车为静止状态。 # if measure_info.border_statu == MeasureStatu["ok"] and measure_info.ground_status == 0 and measure_info.motion_statu == 1: if measure_info.border_statu == MeasureStatu["ok"] and measure_info.ground_status == 0: park_table.statu.execute_statu = message.eNormal break else: park_table.statu.execute_statu = message.eError if self._measure_statu[measure_key].statu is not None and self._measure_statu[measure_key].timeout() is False: try: measure_info = message.measure_info() tf.Parse(self._measure_statu[measure_key].statu, measure_info) print("check measure info again:", measure_info) except: print("parse exception:\n" + self._measure_statu[measure_key].statu) time.sleep(0.1) if park_table.statu.execute_statu == message.eError: park_table.statu.statu_description = "请按提示调整!" return park_table # 填写车高信息 height = 0 if dispatch_plc_passway_status.car_height == 1: height = 1.48 elif dispatch_plc_passway_status.car_height == 2: height = 1.50 elif dispatch_plc_passway_status.car_height == 3: height = 2.05 measure_info.height = height park_table.entrance_measure_info.CopyFrom(measure_info) # 赋值唯一码 uid = str(uuid.uuid1()) park_table.primary_key = uid # 查询车位表和指令表是否有该车 print(datetime.datetime.now()) space_res = self.db.query_space_in_car_number(park_table.car_number) space_count = len(space_res) if space_count > 0: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "车辆 :%s 已在库内!" % park_table.car_number return park_table command_res = self.db.query_command_in_car_number(park_table.car_number) command_count = len(command_res) if command_count > 0: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "指令正在执行中!请稍等!" return park_table # 车辆不在库内 查询是否有对应大小空车位 print(datetime.datetime.now()) space_empty_res = self.db.query_space_in_height_unit_and_empty(measure_info.height, park_table.unit_id) space_empty_count = len(space_empty_res) command_empty_res = self.db.query_command_in_height_unit_and_statu(measure_info.height, park_table.unit_id) command_empty_count = len(command_empty_res) print(datetime.datetime.now()) if space_empty_count - command_empty_count <= 0: park_table.statu.execute_statu = message.eWarning park_table.statu.statu_description = "没有空余车位,车牌号:%s 高度:%.3fm!" % ( park_table.car_number, measure_info.height) # else: # # 向收费系统推送入场信息 # request = self.get_request_data(park_table,'in') # statu,response = self.push_http_request(self._in_url,request) # if statu != message.eNormal: # park_table.statu.execute_statu = statu # park_table.statu.statu_description = response # else: # if ('Data' in response.keys()) and ('InPicUrl' in response['Data'].keys()): # park_table.car_number_info.plate_full_image = response['Data']['InPicUrl'] # park_table.car_number_info.plate_clip_image = response['Data']['InPlateUrl'] # else: # park_table.statu.execute_statu = message.eError # park_table.statu.statu_description = "收费系统答复错误!请联系管理员!" # cursor.close() return park_table # 创建车辆入场请求 def exit_isOK(self, pick_body): pick_table = message.pick_table() try: tf.Parse(pick_body, pick_table) except Exception as e: pick_table.statu.execute_statu = message.eError pick_table.statu.statu_description = "设备故障,请联系管理员!" + "(取车表单错误)" + str(e.args) return pick_table if pick_table.primary_key is None or pick_table.primary_key == '': pick_table.statu.execute_statu = message.eWarning pick_table.statu.statu_description = " 唯一码不能为空!" else: # 查询车位表和指令表是否有该车 print(datetime.datetime.now()) space_res = self.db.query_space_in_primary_key(pick_table.primary_key) space_count = len(space_res) print(datetime.datetime.now()) if space_count <= 0: pick_table.statu.execute_statu = message.eWarning pick_table.statu.statu_description = "车辆信息不存在!" return pick_table command_res = self.db.query_command_in_primary_key(pick_table.primary_key) command_count = len(command_res) print(datetime.datetime.now()) if command_count > 0: pick_table.statu.execute_statu = message.eWarning pick_table.statu.statu_description = "指令正在执行中!请稍等!" return pick_table pick_table.statu.execute_statu = message.eNormal pick_table.statu.statu_description = "取车成功,请观看大屏幕提示取车!" pick_table.car_number = space_res[0]['car_number'] pick_table.unit_id = space_res[0]['unit'] # 完善表单信息 try: pick_table.car_number_info.plate_color = space_res[0]['plate_color'] pick_table.car_number_info.plate_type = space_res[0]['plate_type'] pick_table.car_number_info.plate_confidence = space_res[0]['plate_confidence'] pick_table.car_number_info.recognition_time = space_res[0]['recognition_time'] pick_table.car_number_info.plate_full_image = '' pick_table.car_number_info.plate_clip_image = '' except Exception as e: print("数据库信息不全,缺失号牌颜色等信息!") # 强制取车 或 虚拟取车 if pick_table.statu.table_process_mod == message.PROCESS_ONLY_TO_DISPATCH or pick_table.statu.table_process_mod == message.PROCESS_ONLY_TO_PAY: if pick_table.unit_id != 31 and pick_table.unit_id != 32: # 直接向收费系统发送出场 request = self.get_request_data(pick_table, 'out') self.push_http_request(self._out_url, request) else: # 向收费系统查询缴费情况 request = self.get_request_data(pick_table, 'query') statu, response = self.push_http_request(self._query_url, request) print(datetime.datetime.now()) if statu == message.eNormal: if ('Data' in response.keys()) and ('UnpaidMoney' in response['Data'].keys()): if response['Data']['UnpaidMoney'] == 0: # 向收费系统推送车辆离场 request = self.get_request_data(pick_table, 'out') statu, response = self.push_http_request(self._out_url, request) print(datetime.datetime.now()) if statu != message.eNormal: pick_table.statu.execute_statu = statu pick_table.statu.statu_description = response else: unit_str = self.get_unit_str(pick_table.unit_id) pick_table.statu.execute_statu = message.eNormal pick_table.statu.statu_description = "取车成功,请前往%s单元出口等待车辆,观看大屏幕提示取车!" % unit_str else: pick_table.statu.execute_statu = message.eWarning pick_table.statu.statu_description = ("您有待缴费用,请您微信扫码缴费%.2f元;" % ( response['Data']['UnpaidMoney'])) + self._http + pick_table.primary_key else: pick_table.statu.execute_statu = message.eError pick_table.statu.statu_description = "收费系统答复错误!请联系管理员!" else: pick_table.statu.execute_statu = statu pick_table.statu.statu_description = response return pick_table def get_request_data(self, table, param): print(param + ":") # 创建请求 msgId = str(uuid.uuid1()) + '@' + table.car_number AppId = self._app_id time = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) sign = msgId + AppId + time + self._secret_key hl = hashlib.md5() hl.update(sign.encode(encoding='utf-8')) sign = hl.hexdigest() color = self._plate_color[ table.car_number_info.plate_color] if table.car_number_info.plate_color in self._plate_color.keys() else \ self._plate_color['其他'] if param == 'in': data = http_client.HttpRequest.InDate(self._parking_id, table.car_number, str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), self.chnnId_in[table.unit_id], table.car_number_info.plate_type, color, table.car_number_info.plate_full_image, table.car_number_info.plate_clip_image, table.primary_key) elif param == 'query': data = http_client.HttpRequest.QueryData(table.primary_key, self._parking_id) elif param == 'out': data = http_client.HttpRequest.OutDate(self._parking_id, table.car_number, table.primary_key, str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), self.chnnId_out[table.unit_id], table.car_number_info.plate_type, color, table.car_number_info.plate_full_image, table.car_number_info.plate_clip_image) request = http_client.HttpRequest(msgId, AppId, time, sign, data) return request.__dict__ def get_unit_str(self, unit): if unit == 11: return 'A1' elif unit == 12: return 'A2' elif unit == 13: return 'A3' elif unit == 14: return 'A4' elif unit == 21: return 'B1' 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' elif unit == 1: return 'A' elif unit == 2: return 'B' elif unit == 3: return 'C' return ''