import asyncio
import datetime
import hashlib
import json
import sys
import threading
import time
from collections import namedtuple
from concurrent.futures import ThreadPoolExecutor

import requests

sys.path.append("..")
import pymysql
import logging

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": message.MeasureStatu.Value('Measure_OK'),
                "无数据": message.MeasureStatu.Value('Measure_Empty_Clouds'),
                "噪声": message.MeasureStatu.Value('Measure_Failture'),
                "PLC超界": message.MeasureStatu.Value('Measure_Border'),
                "终端超界": message.MeasureStatu.Value('Measure_Terminal_Border'),
                "失去连接": message.MeasureStatu.Value('Lidar_Disconnect')
                }
Range_status = {"未超界": message.Range_status.Value('Range_correct'),
                "前超界": message.Range_status.Value('Range_front'),
                "后超界": message.Range_status.Value('Range_back'),
                "左超界": message.Range_status.Value('Range_left'),
                "右超界": message.Range_status.Value('Range_right'),
                "底盘超界": message.Range_status.Value('Range_bottom'),
                "车顶超界": message.Range_status.Value('Range_top'),
                "车宽超界": message.Range_status.Value('Range_car_width'),
                "轴距超界": message.Range_status.Value('Range_car_wheelbase'),
                "左旋转超界": message.Range_status.Value('Range_angle_anti_clock'),
                "右旋转超界": message.Range_status.Value('Range_angle_clock'),
                "方向盘未回正": message.Range_status.Value('Range_steering_wheel_nozero'),
                "车辆移动": message.Range_status.Value('Range_car_moving')
                }


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.push_pickqueue_thread = threading.Thread(target=self.push_pickqueue)

        # 入场推送地址
        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._out_url_phone = 'https://sztc.xmsztc.cn/api/operateOutScene/sgjOutSceneRecord'
        # self._out_url_phone = 'https://sztc.smartcityxm.com/api/operateOutScene/sgjOutSceneRecord'  #测试环境
        # 余位
        # self._park_surplus_url = 'https://sztc.xmsztc.cn/api/basicPark/sgjParkSurplus'
        self._park_surplus_url = 'https://sztc.smartcityxm.com/api/basicPark/sgjParkSurplus'  # 测试环境
        # 公众号
        # self._queue_url = 'https://sztc.xmsztc.cn/api/operateOutScene/sgjSendPickUpMsg'
        self._queue_url = 'https://sztc.smartcityxm.com/api/operateOutScene/sgjSendPickUpMsg'  # 测试环境
        # 手机端appid
        self._app_id_phone = '20230412151327035'
        # 手机端app秘钥
        self._appSecret_phone = 'Dl8gh4GGspOu9UU7YW00b55wE93ga6aF'
        # 云端秘钥
        self._secret_key = 'anzs74aph8ac8dy6tj48t05js6zpkgx5'
        # 车场ID
        self._parking_id = '2306041414159951342'
        # 云端appid
        self._app_id = 'blbc5zkpyymaicd3'
        # 云端主地址
        self._http = 'https://sztc.smartcityxm.com/wechath5/#/pagesA/parkingBill/inrecord_parking?inRecordId='

        self.chnnId_in = {11: '2307241522121721333', 12: '2306041439573931681', 13: '2307241531240571925',
                          14: '2307241534030091638'
            , 21: '2307241536315471441', 22: '2307211200055462502', 23: '2307241540369691638',
                          24: '2307241549404491178', 25: '2307211153450762758'
            , 31: '2307241552306981925', 32: '2307241554369581606'}
        self.chnnId_out = {11: '2307241523438171745', 12: '2306041441029631932', 13: '2307241532575281334',
                           14: '2307241534536081930'
            , 21: '2307241538324701014', 22: '2307211201229402651', 23: '2307241542527281313',
                           24: '2307241550388621477', 25: '2307211155130692935'
            , 31: '2307241553191751202', 32: '2307241555230551872'}

        self._plate_color = {'蓝色': '1', '黑色': '2', '黄色': '3', '白色': '4', '绿色': '5', '其他': '6'}

        self.push_pickqueue_thread.start()

    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, headers=None):
        results = ''
        statu = message.eError
        tm = time.time()
        # 若推送失败就重试最多2s
        while time.time() - tm < 2:
            try:
                print("请求地址:" + url)
                if url != self._in_url:
                    print("请求内容:" + str(request))
                resp = requests.post(url, json=request, headers=headers, timeout=2).json()
                print("请求答复:" + str(resp) + '\n')

                if (('Tag' in resp.keys()) and resp['Tag'] == 1) or \
                        (('code' in resp.keys()) and resp['code'] == 0):
                    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

        dispatch_plc_passway_status = dispatch_node_statu.dispatch_plc_passway_status_vector[park_table.import_id - 1]
        # 检查入口状态
        if dispatch_node_statu.plc_carrier_status == 4 or dispatch_plc_passway_status.plc_passway_enable == 2:
            park_table.statu.execute_statu = message.eWarning
            park_table.statu.statu_description = "该单元设备维护中!请前往其他入口！"
            return park_table

        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_buffer = message.measure_buffer()
        measure_info_to_terminal = message.measure_info()
        measure_info_to_plc_reverse = message.measure_info()
        measure_info_to_plc_forward = 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_buffer)
                measure_info_to_terminal.CopyFrom(measure_buffer.measure_info_to_terminal)
                measure_info_to_plc_reverse.CopyFrom(measure_buffer.measure_info_to_plc_reverse)
                measure_info_to_plc_forward.CopyFrom(measure_buffer.measure_info_to_plc_forward)

            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:
                park_table.entrance_measure_info.CopyFrom(measure_buffer)
                # 没有超界。车为静止状态。
                # if measure_info.border_statu == MeasureStatu["ok"] and measure_info.ground_status == 0 and measure_info.motion_statu == 1:
                if measure_info_to_terminal.border_statu == Range_status["未超界"] and \
                        measure_info_to_terminal.ground_status == MeasureStatu["ok"] and \
                        measure_info_to_plc_reverse.border_statu == Range_status["未超界"] and \
                        measure_info_to_plc_reverse.ground_status == MeasureStatu["ok"] and \
                        measure_info_to_plc_forward.border_statu == Range_status["未超界"] and \
                        measure_info_to_plc_forward.ground_status == MeasureStatu["ok"]:
                    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_buffer = message.measure_buffer()
                            measure_info_to_terminal = message.measure_info()
                            tf.Parse(self._measure_statu[measure_key].statu, measure_buffer)
                            measure_info_to_terminal.CopyFrom(measure_buffer.measure_info_to_terminal)
                            measure_info_to_plc_reverse.CopyFrom(measure_buffer.measure_info_to_plc_reverse)
                            measure_info_to_plc_forward.CopyFrom(measure_buffer.measure_info_to_plc_forward)
                            # 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:
                if measure_info_to_terminal.ground_status == MeasureStatu["ok"] or \
                        measure_info_to_plc_reverse.ground_status == MeasureStatu["ok"] or \
                        measure_info_to_plc_forward.ground_status == MeasureStatu["ok"]:
                    park_table.statu.statu_description = "雷达状态异常！"
                elif measure_info_to_terminal.ground_status == MeasureStatu["终端超界"] or \
                        measure_info_to_plc_reverse.ground_status == MeasureStatu["PLC超界"] or \
                        measure_info_to_plc_forward.ground_status == MeasureStatu["PLC超界"]:
                    park_table.statu.statu_description = "请按提示调整！"
                elif measure_info_to_terminal.ground_status == MeasureStatu["失去连接"] or \
                        measure_info_to_plc_reverse.ground_status == MeasureStatu["失去连接"] or \
                        measure_info_to_plc_forward.ground_status == MeasureStatu["失去连接"]:
                    park_table.statu.statu_description = "设备故障，请联系管理员! (雷达)"
                else:
                    park_table.statu.statu_description = "请检查库内是否有异物！"
                    print(" MeasureInfo:\n " + tf.MessageToString(measure_info_to_terminal, as_utf8=True))

                return park_table
        # 填写车高信息
        height = dispatch_plc_passway_status.car_height

        # 赋值唯一码
        uid = str(uuid.uuid1())
        park_table.primary_key = uid
        # 查询黑名单
        print("----------------------------查询黑名单-----------------------------" + str(datetime.datetime.now()))
        blacklist_res = self.db.query_blacklist_in_car_number(park_table.car_number)
        blacklist_count = len(blacklist_res)
        if blacklist_count > 0:
            park_table.statu.execute_statu = message.eWarning
            park_table.statu.statu_description = "车辆 :%s 车辆超限，请退出!" % park_table.car_number
            return park_table

        # 查询车位表和指令表是否有该车
        print("----------------------------查询车位表-----------------------------" + str(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
        print("----------------------------查询指令表-----------------------------" + str(datetime.datetime.now()))
        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("----------------------------查询空车位-----------------------------" + str(datetime.datetime.now()))
        space_empty_res = self.db.query_space_in_height_level_wheel_base_unit_and_empty(height,
                                                                                        measure_info_to_terminal.wheelbase,
                                                                                        park_table.unit_id)
        space_empty_count = len(space_empty_res)
        if space_empty_count <= 0:
            park_table.statu.execute_statu = message.eWarning
            park_table.statu.statu_description = "没有空余的合适车位,车牌号:%s 高度等级:%d 轴距:%.3fm!" % (
                park_table.car_number, height, measure_info_to_terminal.wheelbase)
        else:
            # 查询是否在白名单
            print("----------------------------查询白名单-----------------------------" + str(datetime.datetime.now()))

            whitelist_res = self.db.query_whitelist_in_car_number(park_table.car_number)
            if len(whitelist_res) <= 0:
                # 向收费系统推送入场信息
                print(
                    "----------------------------推送入场-----------------------------" + str(datetime.datetime.now()))
                in_dict = self.get_cloud_request_data(park_table, 'in')
                headers_dict, park_surplus_dict, pickup_queue_dict, phone_out_dict = self.get_phone_request_data(
                    park_table.car_number, park_table.primary_key, park_table.unit_id, 'in')
                statu, response = self.push_http_request(self._in_url, in_dict)
                print(
                    "----------------------------推送余位-----------------------------" + str(datetime.datetime.now()))
                self.push_http_request(self._park_surplus_url, park_surplus_dict, headers_dict)

                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 = "收费系统答复错误！请联系管理员!"
            else:
                print("----------------------------白名单车辆-----------------------------" + str(
                    datetime.datetime.now()))
        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("****************************查询车位表****************************" + str(datetime.datetime.now()))
            space_res = self.db.query_space_in_primary_key(pick_table.primary_key)
            space_count = len(space_res)
            print(
                "****************************查询停车指令表****************************" + str(datetime.datetime.now()))
            command_res_park = self.db.query_park_command_in_primary_key(pick_table.primary_key)
            command_count_park = len(command_res_park)
            if space_count <= 0 and command_count_park <= 0:
                pick_table.statu.execute_statu = message.eWarning
                pick_table.statu.statu_description = "车辆信息不存在!"
                return pick_table
            print(
                "****************************查询取车指令表****************************" + str(datetime.datetime.now()))
            command_res = self.db.query_pick_command_in_primary_key(pick_table.primary_key)
            command_count = len(command_res)
            if command_count > 0:
                pick_table.unit_id = space_res[0]['unit']
                t_unit_str = self.get_unit_str(pick_table.unit_id)
                # 重复取车，提示成功，流程失败！
                pick_table.statu.execute_statu = message.eWarning
                pick_table.statu.statu_description = "取车成功！请前往 << %s >> 单元出口等待车辆，观看大屏幕提示取车！" % t_unit_str
                return pick_table
            pick_table.statu.execute_statu = message.eNormal
            pick_table.statu.statu_description = "取车成功，请观看大屏幕提示取车！"

            # 完善表单信息
            try:
                try:
                    pick_table.car_number = space_res[0]['car_number']
                    pick_table.unit_id = space_res[0]['unit']
                except Exception as e:
                    pick_table.car_number = command_res_park[0]['car_number']
                    pick_table.unit_id = command_res_park[0]['unit']
                    print("车为表未找到，使用指令表结果")
                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:
                # 直接向收费系统发送出场
                print("****************************收费系统推送出场****************************" + str(
                    datetime.datetime.now()))
                out_dict = self.get_cloud_request_data(pick_table, 'out')
                headers_dict, park_surplus_dict, pickup_queue_dict, phone_out_dict = self.get_phone_request_data(
                    pick_table.car_number, pick_table.primary_key, pick_table.unit_id, 'out')
                self.push_http_request(self._out_url, out_dict)
                print("\n")
                print("****************************手机端推送出场****************************" + str(
                    datetime.datetime.now()))
                self.push_http_request(self._out_url_phone, phone_out_dict, headers_dict)
                print("\n")
                print("****************************推送余位****************************" + str(datetime.datetime.now()))
                self.push_http_request(self._park_surplus_url, park_surplus_dict, headers_dict)
                print("\n")
                print("****************************推送排队****************************" + str(datetime.datetime.now()))
                self.push_http_request(self._queue_url, pickup_queue_dict, headers_dict)
                print("\n")
                print('强制取车')
            else:
                print(
                    "****************************查询白名单****************************" + str(datetime.datetime.now()))
                whitelist_res = self.db.query_whitelist_in_car_number(pick_table.car_number)
                if len(whitelist_res) <= 0:
                    # 向收费系统查询缴费情况
                    print("****************************查询缴费情况****************************" + str(
                        datetime.datetime.now()))
                    request = self.get_cloud_request_data(pick_table, 'query')
                    statu, response = self.push_http_request(self._query_url, request)
                    if statu == message.eNormal:
                        if ('Data' in response.keys()) and ('UnpaidMoney' in response['Data'].keys()):
                            if response['Data']['UnpaidMoney'] == 0:
                                # 向收费系统推送车辆离场
                                print("****************************收费系统推送出场****************************" + str(
                                    datetime.datetime.now()))
                                out_dict = self.get_cloud_request_data(pick_table, 'out')
                                headers_dict, park_surplus_dict, pickup_queue_dict, phone_out_dict = self.get_phone_request_data(
                                    pick_table.car_number, pick_table.primary_key, pick_table.unit_id, 'out')
                                self.push_http_request(self._out_url, out_dict)
                                print("\n")
                                print("****************************手机端推送出场****************************" + str(
                                    datetime.datetime.now()))
                                self.push_http_request(self._out_url_phone, phone_out_dict, headers_dict)
                                print("\n")
                                print("****************************推送余位****************************" + str(
                                    datetime.datetime.now()))
                                self.push_http_request(self._park_surplus_url, park_surplus_dict, headers_dict)
                                print("\n")
                                print("****************************推送排队****************************" + str(
                                    datetime.datetime.now()))
                                self.push_http_request(self._queue_url, pickup_queue_dict, headers_dict)
                                print("\n")
                                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
                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

        return pick_table

    def get_cloud_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_phone_request_data(self, car_number, primary_key, unit_id, param):
        print(param + ":")
        # 创建请求
        appid_iphone = self._app_id_phone
        time_iphone = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        sign_iphone = appid_iphone + time_iphone + self._appSecret_phone
        hl_iphone = hashlib.md5()
        hl_iphone.update(sign_iphone.encode(encoding='utf-8'))
        sign_iphone = hl_iphone.hexdigest()
        headers_dict = {
            "Appid": appid_iphone,
            "Time": time_iphone,
            "Sign": sign_iphone

        }
        total = large = small = 0
        if param == 'queue 1':
            command_count = 1
        else:
            print("****************************查询余位*******************************" + str(datetime.datetime.now()))
            total = self.db.query_total_empty_space()[0]['count(*)']
            large = self.db.query_large_empty_space()[0]['count(*)']
            small = self.db.query_small_empty_space()[0]['count(*)']

            print("****************************查询排队信息****************************" + str(datetime.datetime.now()))
            command_count = self.db.query_command_queue_count_in_unit(unit_id)[0]['count(*)']

        park_surplus_dict = {
            "parkId": self._parking_id,
            "totalParkSurplus": total,
            "largeParkSurplus": large,
            "smallParkSurplus": small
        }

        pickup_queue_dict = {
            "licenesePlate": car_number,
            "inRecordId": primary_key,
            "garageNo": self.get_unit_str(unit_id),
            "waitNum": command_count,
            "remainingTime": command_count * 2
        }

        phone_out_dict = {
            "parkId": self._parking_id,
            "licenesePlate": car_number,
            "inRecordId": primary_key
        }
        return headers_dict, park_surplus_dict, pickup_queue_dict, phone_out_dict

    def push_pickqueue(self):
        while True:
            for unit in self.chnnId_in.keys():
                res = self.db.query_queue_condition_in_unit(unit)
                for dict in res:
                    if dict['upload_statu'] is None and dict['row_number() over(order by queue_time)'] == 2:
                        print("===============================排队为1 推送排队详情=========================" + str(datetime.datetime.now()))
                        headers_dict, park_surplus_dict, pickup_queue_dict, phone_out_dict = self.get_phone_request_data(
                            dict['car_number'], dict['primary_key'], dict['unit'], 'queue 1')
                        self.push_http_request(self._queue_url, pickup_queue_dict, headers_dict)
                        self.db.update_command_queue_upload_statu_in_car_number(dict['car_number'])
                        print("\n")
            time.sleep(1)

    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 ''

    def get_unit_int(self, unit):
        if unit == 'A1':
            return 11
        elif unit == 'A2':
            return 12
        elif unit == 'A3':
            return 13
        elif unit == 'A4':
            return 14
        elif unit == 'B1':
            return 21
        elif unit == 'B2':
            return 22
        elif unit == 'B3':
            return 23
        elif unit == 'B4':
            return 24
        elif unit == 'B5':
            return 25
        elif unit == 'C1':
            return 31
        elif unit == 'C2':
            return 32
        return 0
