check_command_XmSgj.py 19 KB

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