check_command_XmSgj.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. import asyncio
  2. import datetime
  3. import hashlib
  4. import json
  5. import sys
  6. import time
  7. from concurrent.futures import ThreadPoolExecutor
  8. import requests
  9. sys.path.append("..")
  10. import pymysql
  11. import uuid
  12. import chardet
  13. import message_pb2 as message
  14. import google.protobuf.text_format as tf
  15. import http_client
  16. import mytool.db_helper.db_operation as spmng
  17. MeasureStatu={"ok":0,"无数据":1,"噪声":2,"超界":3,"故障":4}
  18. class CommandChecker:
  19. def __init__(self, db_config):
  20. self.db = spmng.DBOperation(db_config['db_ip'], db_config['db_port'], db_config['db_name'],
  21. db_config['db_user'], db_config['db_password'])
  22. self._dispatch_statu = {}
  23. self._measure_statu = {}
  24. self._in_url = 'http://szdy.xmsztc.cn/Api/CarInEntry'
  25. self._query_url = 'http://szdy.xmsztc.cn/Api/GetBill'
  26. self._out_url = 'http://szdy.xmsztc.cn/Api/CarOutEntry'
  27. self._secret_key = 'anzs74aph8ac8dy6tj48t05js6zpkgx5'
  28. self._parking_id = '2306041414159951342'
  29. self._app_id = 'blbc5zkpyymaicd3'
  30. self._http = 'https://sztc.smartcityxm.com/wechath5/#/pagesA/parkingBill/inrecord_parking?inRecordId='
  31. self.chnnId_in = {11: '2307241522121721333',12: '2306041439573931681',13: '2307241531240571925',14: '2307241534030091638'
  32. ,21: '2307241536315471441',22: '2307211200055462502',23: '2307241540369691638',24: '2307241549404491178',25: '2307211153450762758'
  33. ,31: '2307241552306981925',32: '2307241554369581606'}
  34. self.chnnId_out = {11: '2307241523438171745',12: '2306041441029631932',13: '2307241532575281334',14: '2307241534536081930'
  35. ,21: '2307241538324701014',22: '2307211201229402651',23: '2307241542527281313',24: '2307241550388621477',25: '2307211155130692935'
  36. ,31: '2307241553191751202',32: '2307241555230551872'}
  37. self._plate_color = {'蓝色': '1', '黑色': '2', '黄色': '3', '白色': '4', '绿色': '5', '其他': '6'}
  38. def get_in_url(self):
  39. return self._in_url
  40. def receive_dispatch_statu(self, statu, ex, key):
  41. self._dispatch_statu[key] = statu
  42. def receive_measure_info(self, statu, ex, key):
  43. self._measure_statu[key] = statu
  44. def push_http_request(self, url, request):
  45. results = ''
  46. statu = message.eError
  47. tm = time.time()
  48. # 若推送失败就重试最多2s
  49. while time.time() - tm < 2:
  50. try:
  51. print(url)
  52. resp = requests.post(url, json=request).json()
  53. print(resp)
  54. if ('Tag' in resp.keys()) and resp['Tag'] == 1:
  55. statu = message.eNormal
  56. results = resp
  57. break
  58. else:
  59. statu = message.eError
  60. results = '收费系统反馈错误!message:%s' % resp
  61. except Exception as e:
  62. statu = message.eError
  63. results = '向收费系统推送请求失败! ERROR:%s' % (str(e.args))
  64. time.sleep(0.2)
  65. return statu, results
  66. def entrance_isOK(self, park_body):
  67. # 停车表单
  68. park_table = message.park_table()
  69. try:
  70. tf.Parse(park_body, park_table)
  71. except Exception as e:
  72. park_table.statu.execute_statu = message.eError
  73. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(停车表单错误)" + str(e.args)
  74. return park_table
  75. # 检查调度状态
  76. dispatch_key = "dispatch_%d_statu_port" % park_table.unit_id
  77. if (dispatch_key in self._dispatch_statu) is False or self._dispatch_statu[dispatch_key].timeout():
  78. park_table.statu.execute_statu = message.eError
  79. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(调度)"
  80. return park_table
  81. # 获取车高信息
  82. dispatch_node_statu = message.dispatch_node_statu()
  83. try:
  84. tf.Parse(self._dispatch_statu[dispatch_key].statu, dispatch_node_statu)
  85. except Exception:
  86. park_table.statu.execute_statu = message.eError
  87. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(调度状态消息错误)"
  88. return park_table
  89. if dispatch_node_statu.plc_carrier_status == 0:
  90. park_table.statu.execute_statu = message.eError
  91. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(搬运器)"
  92. return park_table
  93. # elif dispatch_node_statu.plc_carrier_status == 4:
  94. # park_table.statu.execute_statu = message.eWarning
  95. # park_table.statu.statu_description = "该单元设备维护中!请前往其他入口!"
  96. # return park_table
  97. dispatch_plc_passway_status = dispatch_node_statu.dispatch_plc_passway_status_vector[park_table.import_id - 1]
  98. if dispatch_plc_passway_status.car_height == 0:
  99. park_table.statu.execute_statu = message.eWarning
  100. park_table.statu.statu_description = "未检测到车辆!"
  101. return park_table
  102. elif dispatch_plc_passway_status.car_height == 4:
  103. park_table.statu.execute_statu = message.eWarning
  104. park_table.statu.statu_description = "车辆超高,请退出车库!"
  105. return park_table
  106. sensor_1 = dispatch_plc_passway_status.sensor_1
  107. sensor_2 = dispatch_plc_passway_status.sensor_2
  108. if park_table.unit_id != 31 and park_table.unit_id != 32:
  109. if (sensor_2 >> 3) & 0x01 != 1 or (sensor_2 >> 4) & 0x01 != 1:
  110. park_table.statu.execute_statu = message.eWarning
  111. park_table.statu.statu_description = "车辆未停到位,请根据库内指示灯挪车!"
  112. return park_table
  113. if (sensor_1 >> 2) & 0x01 != 1:
  114. park_table.statu.execute_statu = message.eWarning
  115. park_table.statu.statu_description = "车辆超限,请联系现场工作人员!"
  116. return park_table
  117. if (sensor_1 >> 3) & 0x01 != 1:
  118. park_table.statu.execute_statu = message.eWarning
  119. park_table.statu.statu_description = "车辆后超界,请往前!"
  120. return park_table
  121. if (sensor_1 >> 4) & 0x01 != 1:
  122. park_table.statu.execute_statu = message.eWarning
  123. park_table.statu.statu_description = "车辆前超界,请往后!"
  124. return park_table
  125. if (sensor_1 >> 5) & 0x01 != 1:
  126. park_table.statu.execute_statu = message.eWarning
  127. park_table.statu.statu_description = "车辆左超界,请往右!"
  128. return park_table
  129. if (sensor_1 >> 6) & 0x01 != 1:
  130. park_table.statu.execute_statu = message.eWarning
  131. park_table.statu.statu_description = "车辆右超界,请往左!"
  132. return park_table
  133. measure_buffer = message.measure_buffer()
  134. measure_info = message.measure_info()
  135. if park_table.unit_id == 31 or park_table.unit_id == 32:
  136. measure_key = "measure_%d_statu_port" % park_table.terminal_id
  137. if (measure_key in self._measure_statu) is False or self._measure_statu[measure_key].timeout():
  138. park_table.statu.execute_statu = message.eError
  139. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(雷达)"
  140. return park_table
  141. # 获取车高信息
  142. try:
  143. tf.Parse(self._measure_statu[measure_key].statu, measure_buffer)
  144. measure_info.CopyFrom(measure_buffer.measure_info_to_terminal)
  145. except Exception:
  146. park_table.statu.execute_statu = message.eError
  147. park_table.statu.statu_description = "设备故障,请联系管理员!" + "(雷达状态消息错误)"
  148. return park_table
  149. # 获取雷达信息
  150. tm = time.time()
  151. while time.time() - tm < 2:
  152. # 没有超界。车为静止状态。
  153. # if measure_info.border_statu == MeasureStatu["ok"] and measure_info.ground_status == 0 and measure_info.motion_statu == 1:
  154. if measure_info.border_statu == MeasureStatu["ok"] and measure_info.ground_status == 0:
  155. park_table.statu.execute_statu = message.eNormal
  156. park_table.entrance_measure_info.CopyFrom(measure_buffer)
  157. break
  158. else:
  159. park_table.statu.execute_statu = message.eError
  160. if self._measure_statu[measure_key].statu is not None and self._measure_statu[measure_key].timeout() is False:
  161. try:
  162. measure_buffer = message.measure_buffer()
  163. measure_info = message.measure_info()
  164. tf.Parse(self._measure_statu[measure_key].statu, measure_buffer)
  165. measure_info.CopyFrom(measure_buffer.measure_info_to_terminal)
  166. # print("check measure info again:", measure_info)
  167. except:
  168. print("parse exception:\n" + self._measure_statu[measure_key].statu)
  169. time.sleep(0.1)
  170. if park_table.statu.execute_statu == message.eError:
  171. if measure_info.border_statu == MeasureStatu["超界"]:
  172. park_table.statu.statu_description = "请按提示调整!"
  173. elif measure_info.border_statu == MeasureStatu["故障"]:
  174. park_table.statu.statu_description = "设备故障,请联系管理员! (雷达)"
  175. else:
  176. park_table.statu.statu_description = "请检查库内是否有异物!"
  177. return park_table
  178. # 填写车高信息
  179. height = dispatch_plc_passway_status.car_height
  180. # 赋值唯一码
  181. uid = str(uuid.uuid1())
  182. park_table.primary_key = uid
  183. # 查询车位表和指令表是否有该车
  184. print(datetime.datetime.now())
  185. space_res = self.db.query_space_in_car_number(park_table.car_number)
  186. space_count = len(space_res)
  187. if space_count > 0:
  188. park_table.statu.execute_statu = message.eWarning
  189. park_table.statu.statu_description = "车辆 :%s 已在库内!" % park_table.car_number
  190. return park_table
  191. command_res = self.db.query_command_in_car_number(park_table.car_number)
  192. command_count = len(command_res)
  193. if command_count > 0:
  194. park_table.statu.execute_statu = message.eWarning
  195. park_table.statu.statu_description = "指令正在执行中!请稍等!"
  196. return park_table
  197. # 车辆不在库内 查询是否有对应大小空车位
  198. print(datetime.datetime.now())
  199. space_empty_res = self.db.query_space_in_height_level_wheel_base_unit_and_empty(height,measure_info.wheelbase,park_table.unit_id)
  200. space_empty_count = len(space_empty_res)
  201. print(datetime.datetime.now())
  202. if space_empty_count <= 0:
  203. park_table.statu.execute_statu = message.eWarning
  204. park_table.statu.statu_description = "没有空余的合适车位,车牌号:%s 高度等级:%d 轴距:%.3fm!" % (
  205. park_table.car_number, height,measure_info.wheelbase)
  206. # else:
  207. # # 向收费系统推送入场信息
  208. # request = self.get_request_data(park_table,'in')
  209. # statu,response = self.push_http_request(self._in_url,request)
  210. # if statu != message.eNormal:
  211. # park_table.statu.execute_statu = statu
  212. # park_table.statu.statu_description = response
  213. # else:
  214. # if ('Data' in response.keys()) and ('InPicUrl' in response['Data'].keys()):
  215. # park_table.car_number_info.plate_full_image = response['Data']['InPicUrl']
  216. # park_table.car_number_info.plate_clip_image = response['Data']['InPlateUrl']
  217. # else:
  218. # park_table.statu.execute_statu = message.eError
  219. # park_table.statu.statu_description = "收费系统答复错误!请联系管理员!"
  220. # cursor.close()
  221. return park_table
  222. # 创建车辆入场请求
  223. def exit_isOK(self, pick_body):
  224. pick_table = message.pick_table()
  225. try:
  226. tf.Parse(pick_body, pick_table)
  227. except Exception as e:
  228. pick_table.statu.execute_statu = message.eError
  229. pick_table.statu.statu_description = "设备故障,请联系管理员!" + "(取车表单错误)" + str(e.args)
  230. return pick_table
  231. if pick_table.primary_key is None or pick_table.primary_key == '':
  232. pick_table.statu.execute_statu = message.eWarning
  233. pick_table.statu.statu_description = " 唯一码不能为空!"
  234. else:
  235. # 查询车位表和指令表是否有该车
  236. print(datetime.datetime.now())
  237. space_res = self.db.query_space_in_primary_key(pick_table.primary_key)
  238. space_count = len(space_res)
  239. print(datetime.datetime.now())
  240. if space_count <= 0:
  241. pick_table.statu.execute_statu = message.eWarning
  242. pick_table.statu.statu_description = "车辆信息不存在!"
  243. return pick_table
  244. command_res = self.db.query_command_in_primary_key(pick_table.primary_key)
  245. command_count = len(command_res)
  246. print(datetime.datetime.now())
  247. if command_count > 0:
  248. pick_table.statu.execute_statu = message.eWarning
  249. pick_table.statu.statu_description = "指令正在执行中!请稍等!"
  250. return pick_table
  251. pick_table.statu.execute_statu = message.eNormal
  252. pick_table.statu.statu_description = "取车成功,请观看大屏幕提示取车!"
  253. pick_table.car_number = space_res[0]['car_number']
  254. pick_table.unit_id = space_res[0]['unit']
  255. # 完善表单信息
  256. try:
  257. pick_table.car_number_info.plate_color = space_res[0]['plate_color']
  258. pick_table.car_number_info.plate_type = space_res[0]['plate_type']
  259. pick_table.car_number_info.plate_confidence = space_res[0]['plate_confidence']
  260. pick_table.car_number_info.recognition_time = space_res[0]['recognition_time']
  261. pick_table.car_number_info.plate_full_image = ''
  262. pick_table.car_number_info.plate_clip_image = ''
  263. except Exception as e:
  264. print("数据库信息不全,缺失号牌颜色等信息!")
  265. # 强制取车 或 虚拟取车
  266. if pick_table.statu.table_process_mod == message.PROCESS_ONLY_TO_DISPATCH or pick_table.statu.table_process_mod == message.PROCESS_ONLY_TO_PAY:
  267. # if pick_table.unit_id != 31 and pick_table.unit_id != 32:
  268. # 直接向收费系统发送出场
  269. request = self.get_request_data(pick_table, 'out')
  270. self.push_http_request(self._out_url, request)
  271. print('强制取车')
  272. else:
  273. # 向收费系统查询缴费情况
  274. request = self.get_request_data(pick_table, 'query')
  275. statu, response = self.push_http_request(self._query_url, request)
  276. print(datetime.datetime.now())
  277. if statu == message.eNormal:
  278. if ('Data' in response.keys()) and ('UnpaidMoney' in response['Data'].keys()):
  279. if response['Data']['UnpaidMoney'] == 0:
  280. # 向收费系统推送车辆离场
  281. request = self.get_request_data(pick_table, 'out')
  282. statu, response = self.push_http_request(self._out_url, request)
  283. print(datetime.datetime.now())
  284. if statu != message.eNormal:
  285. pick_table.statu.execute_statu = statu
  286. pick_table.statu.statu_description = response
  287. else:
  288. unit_str = self.get_unit_str(pick_table.unit_id)
  289. pick_table.statu.execute_statu = message.eNormal
  290. pick_table.statu.statu_description = "取车成功,请前往%s单元出口等待车辆,观看大屏幕提示取车!" % unit_str
  291. else:
  292. pick_table.statu.execute_statu = message.eWarning
  293. pick_table.statu.statu_description = ("您有待缴费用,请您微信扫码缴费%.2f元;" % (
  294. response['Data']['UnpaidMoney'])) + self._http + pick_table.primary_key
  295. else:
  296. pick_table.statu.execute_statu = message.eError
  297. pick_table.statu.statu_description = "收费系统答复错误!请联系管理员!"
  298. else:
  299. pick_table.statu.execute_statu = statu
  300. pick_table.statu.statu_description = response
  301. return pick_table
  302. def get_request_data(self, table, param):
  303. print(param + ":")
  304. # 创建请求
  305. msgId = str(uuid.uuid1()) + '@' + table.car_number
  306. AppId = self._app_id
  307. time = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
  308. sign = msgId + AppId + time + self._secret_key
  309. hl = hashlib.md5()
  310. hl.update(sign.encode(encoding='utf-8'))
  311. sign = hl.hexdigest()
  312. color = self._plate_color[
  313. table.car_number_info.plate_color] if table.car_number_info.plate_color in self._plate_color.keys() else \
  314. self._plate_color['其他']
  315. if param == 'in':
  316. data = http_client.HttpRequest.InDate(self._parking_id, table.car_number,
  317. str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
  318. self.chnnId_in[table.unit_id],
  319. table.car_number_info.plate_type, color,
  320. table.car_number_info.plate_full_image,
  321. table.car_number_info.plate_clip_image, table.primary_key)
  322. elif param == 'query':
  323. data = http_client.HttpRequest.QueryData(table.primary_key, self._parking_id)
  324. elif param == 'out':
  325. data = http_client.HttpRequest.OutDate(self._parking_id, table.car_number,
  326. table.primary_key,
  327. str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
  328. self.chnnId_out[table.unit_id],
  329. table.car_number_info.plate_type, color,
  330. table.car_number_info.plate_full_image,
  331. table.car_number_info.plate_clip_image)
  332. request = http_client.HttpRequest(msgId, AppId, time, sign, data)
  333. return request.__dict__
  334. def get_unit_str(self, unit):
  335. if unit == 11:
  336. return 'A1'
  337. elif unit == 12:
  338. return 'A2'
  339. elif unit == 13:
  340. return 'A3'
  341. elif unit == 14:
  342. return 'A4'
  343. elif unit == 21:
  344. return 'B1'
  345. elif unit == 22:
  346. return 'B2'
  347. elif unit == 23:
  348. return 'B3'
  349. elif unit == 24:
  350. return 'B4'
  351. elif unit == 25:
  352. return 'B5'
  353. elif unit == 31:
  354. return 'C1'
  355. elif unit == 32:
  356. return 'C2'
  357. elif unit == 1:
  358. return 'A'
  359. elif unit == 2:
  360. return 'B'
  361. elif unit == 3:
  362. return 'C'
  363. return ''