PushCommand.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. # 导入pymysql
  2. import pymysql as psql
  3. from retry import retry
  4. import message_pb2 as message
  5. import google.protobuf.text_format as tf
  6. import threading
  7. import datetime
  8. import uuid
  9. import math
  10. class CommandInfo:
  11. def __init__(self,type,table):
  12. self.type=type
  13. self.table=table
  14. class DBCommand():
  15. def __init__(self,ip,port,database,user,password):
  16. self.ip=ip
  17. self.port=port
  18. self.database=database
  19. self.user=user
  20. self.password=password
  21. self.lock=threading.Lock()
  22. self.conn=psql.connect(host=ip,
  23. port=port,
  24. database=database,
  25. charset="utf8",
  26. user=user,
  27. passwd=password)
  28. def push_command(self,cmd_table):
  29. #判断指令类型
  30. if self.table_type(cmd_table)=="park":
  31. ret_table=self.enqueue_parkcmd(cmd_table)
  32. elif self.table_type(cmd_table)=="pick":
  33. ret_table=self.enqueue_pickcmd(cmd_table)
  34. else:
  35. print(" 入队指令格式错误")
  36. return None
  37. return ret_table
  38. def enqueue_parkcmd(self,table):
  39. with self.lock:
  40. cmd=message.park_table()
  41. tf.Parse(table,cmd)
  42. self.conn.ping()
  43. self.conn.begin()
  44. cursor = self.conn.cursor()
  45. #检查车辆是否在库内
  46. SQL="select * from vehicle where car_number='%s'"%(cmd.car_number)
  47. exist_vehicle=cursor.execute(SQL)
  48. SQL="select * from command_queue where car_number='%s'"%(cmd.car_number)
  49. exist_command=cursor.execute(SQL)
  50. if exist_command>0 or exist_vehicle>0:
  51. ts=message.table_statu()
  52. ts.execute_statu=message.eError
  53. ts.statu_description="车辆 :%s 已在库内!"%(cmd.car_number)
  54. cmd.statu.CopyFrom(ts)
  55. self.conn.commit()
  56. cursor.close()
  57. return tf.MessageToString(cmd,as_utf8=True)
  58. #检查车位是否够
  59. elif cmd.entrance_measure_info.height<1.55:
  60. #小轿车, 总车位数-队列等待数>0即可
  61. SQL="select * from space where car_number IS NULL and unit=%d and statu=0"%(cmd.unit_id)
  62. idle_space_count=cursor.execute(SQL)
  63. SQL="select * from command_queue where unit=%d and statu=0 and type=1"%(cmd.unit_id)
  64. wait_park_count=cursor.execute(SQL)
  65. if not idle_space_count-wait_park_count>0:
  66. ts=message.table_statu()
  67. ts.execute_statu=message.eError
  68. ts.statu_description="没有空余车位,车牌号:%s 高度:%.3fm!"%(cmd.car_number,cmd.entrance_measure_info.height)
  69. cmd.statu.CopyFrom(ts)
  70. self.conn.commit()
  71. cursor.close()
  72. return tf.MessageToString(cmd,as_utf8=True)
  73. elif cmd.entrance_measure_info.height<1.75:
  74. #suv ,空闲suv车位-队列suv 在(队列空闲轿车-空闲轿车位)>0时,需要减去这个
  75. SQL="select * from space where car_number IS NULL and unit=%d and height>1.55 and height<=1.75 and statu=0"%(cmd.unit_id)
  76. suv_idl_count=cursor.execute(SQL) #空闲suv车位数
  77. SQL="select * from space where car_number IS NULL and unit=%d and height<=1.55 and statu=0"%(cmd.unit_id)
  78. mini_idle_count=cursor.execute(SQL) #轿车位数
  79. SQL="select * from command_queue where unit=%d and statu=0 and type=1"%(cmd.unit_id)
  80. cursor.execute(SQL)
  81. queue_cmd=cursor.fetchall() #所有等待指令
  82. queue_car_count=0 #队列轿车指令计数
  83. for qc in queue_cmd:
  84. info=message.measure_info()
  85. tf.Parse(qc[7],info)
  86. if info.height<=1.55: #队列轿车停车指令
  87. queue_car_count=queue_car_count+1
  88. queue_suv_count=len(queue_cmd)-queue_car_count
  89. space_scarcity=0
  90. if mini_idle_count<queue_car_count:
  91. space_scarcity=queue_car_count-mini_idle_count
  92. if not (suv_idl_count-queue_suv_count-space_scarcity)>0:
  93. ts=message.table_statu()
  94. ts.execute_statu=message.eError
  95. ts.statu_description="没有SUV车位,车牌号:%s,高度:%.3fm!"%(cmd.car_number,cmd.entrance_measure_info.height)
  96. cmd.statu.CopyFrom(ts)
  97. self.conn.commit()
  98. cursor.close()
  99. return tf.MessageToString(cmd,as_utf8=True)
  100. elif cmd.entrance_measure_info.height<2.0:
  101. SQL = "select * from space where car_number IS NULL and unit=%d and height>1.75 and height<=2.0 and statu=0" % (cmd.unit_id)
  102. big_idl_count = cursor.execute(SQL) # 空闲 big 车位数
  103. SQL = "select * from space where car_number IS NULL and unit=%d and height>1.55 and height<=1.75 and statu=0" % (cmd.unit_id)
  104. suv_idle_count = cursor.execute(SQL) # suv位数
  105. SQL = "select * from space where car_number IS NULL and unit=%d and height<=1.55 and statu=0" % (cmd.unit_id)
  106. small_idle_count = cursor.execute(SQL) # 轿车位数
  107. if big_idl_count>=1:
  108. cmd_small_count=0
  109. cmd_suv_count=0
  110. cmd_big_count=0
  111. SQL = "select * from command_queue where unit=%d and statu=0 and type=1" % (cmd.unit_id)
  112. cursor.execute(SQL)
  113. queue_cmd = cursor.fetchall() # 所有等待指令
  114. for qc in queue_cmd:
  115. info = message.measure_info()
  116. tf.Parse(qc[7], info)
  117. if info.height <1.55: # 队列轿车停车指令
  118. cmd_small_count = cmd_small_count + 1
  119. elif info.height<1.75:
  120. cmd_suv_count=cmd_suv_count+1
  121. elif info.height<2.0:
  122. cmd_big_count=cmd_big_count+1
  123. else:
  124. pass
  125. suv_space_scarcity = 0
  126. if small_idle_count < cmd_small_count:
  127. suv_space_scarcity = cmd_small_count - small_idle_count
  128. suv_idle_count=suv_idle_count-suv_space_scarcity
  129. if cmd_suv_count-suv_idle_count>0:
  130. big_idl_count=big_idl_count-(cmd_suv_count-suv_idle_count)
  131. if big_idl_count<0:
  132. ts = message.table_statu()
  133. ts.execute_statu = message.eError
  134. ts.statu_description = "没有SUV车位,车牌号:%s,高度:%.3fm!" % (
  135. cmd.car_number, cmd.entrance_measure_info.height)
  136. cmd.statu.CopyFrom(ts)
  137. self.conn.commit()
  138. cursor.close()
  139. return tf.MessageToString(cmd, as_utf8=True)
  140. else:
  141. ts = message.table_statu()
  142. ts.execute_statu = message.eError
  143. ts.statu_description = "没有SUV车位,车牌号:%s,高度:%.3fm!" % (
  144. cmd.car_number, cmd.entrance_measure_info.height)
  145. cmd.statu.CopyFrom(ts)
  146. self.conn.commit()
  147. cursor.close()
  148. return tf.MessageToString(cmd, as_utf8=True)
  149. else:
  150. ts = message.table_statu()
  151. ts.execute_statu = message.eError
  152. ts.statu_description = "车辆超高,车牌号:%s,高度:%.3fm!" % (
  153. cmd.car_number, cmd.entrance_measure_info.height)
  154. cmd.statu.CopyFrom(ts)
  155. self.conn.commit()
  156. cursor.close()
  157. return tf.MessageToString(cmd, as_utf8=True)
  158. #指令允许入队,填写唯一码
  159. if not cmd.statu.execute_statu==message.eError:
  160. uid=str(uuid.uuid1())
  161. cmd.primary_key=uid
  162. #查询队列指令以及最后一次指令编号及时间
  163. cursor.execute("select * from command_queue,queue_number_data FOR UPDATE") #锁表
  164. SQL="select * from command_queue where unit=%d and statu=0"%(cmd.unit_id)
  165. cursor.execute(SQL)
  166. cmd_queue=cursor.fetchall()
  167. queue_id=0
  168. #计算当前指令编号
  169. if len(cmd_queue)>0:
  170. SQL="select * from queue_number_data where unit=%d"%cmd.unit_id
  171. cursor.execute(SQL)
  172. record=cursor.fetchall()
  173. last_num=0
  174. last_time=datetime.datetime.now()
  175. if len(record)==1:
  176. last_num=record[0][1]
  177. last_time=record[0][2]
  178. elif len(record)==0:
  179. SQL="insert into queue_number_data values(%d,0,NULL)"%(cmd.unit_id)
  180. cursor.execute(SQL)
  181. diff=datetime.datetime.now()-last_time
  182. time_mns=diff.total_seconds()/60
  183. queue_id=int(last_num+1+ time_mns*1)
  184. #停车入队前,按照库内轴距更新测量轴距值 --------------------------------------------
  185. database_wheelbase=self.get_wheelbase(cursor,cmd.car_number)
  186. new_wheelbase=cmd.entrance_measure_info.wheelbase
  187. if database_wheelbase is not None:
  188. [wheelbase,delta]=database_wheelbase
  189. entrance_wheelbase=cmd.entrance_measure_info.wheelbase
  190. if abs(entrance_wheelbase-wheelbase)>0.1: #与入口测量偏差过大,不更新
  191. print("车辆:%s 测量轴距与数据库相差太大(测量:%f 数据库:%f),不做融合,以测量为准"%(cmd.car_number,entrance_wheelbase,wheelbase))
  192. else:
  193. sum=(delta*delta)+0.05*0.05
  194. new_wheelbase=entrance_wheelbase*delta*delta/sum+wheelbase*(0.05*0.05)/sum
  195. print("车辆:%s 停车更新轴距:%f ,测量:%f,数据库:%f"%(cmd.car_number,new_wheelbase,entrance_wheelbase,wheelbase))
  196. new_measure_info=message.measure_info()
  197. new_measure_info.CopyFrom(cmd.entrance_measure_info)
  198. new_measure_info.wheelbase=new_wheelbase
  199. cmd.entrance_measure_info.CopyFrom(new_measure_info)
  200. else:
  201. print("车辆:%s 不存在数据库轴距,使用测量轴距:%f"%(cmd.car_number,cmd.entrance_measure_info.wheelbase))
  202. #-----------------------------------
  203. SQL="insert into command_queue values('%s','%s',%d,%d,1,0,NULL,'%s', %d , NULL)"%(
  204. cmd.car_number,cmd.primary_key,cmd.unit_id,queue_id
  205. ,tf.MessageToString(cmd.entrance_measure_info,as_utf8=True), cmd.terminal_id )
  206. cursor.execute(SQL)
  207. #更新指令时间表,
  208. dt=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  209. SQL="update queue_number_data set last_number=%d,input_time=str_to_date('%s','%%Y-%%m-%%d %%H:%%i:%%S') where unit=%d"%(queue_id,dt,cmd.unit_id)
  210. cursor.execute(SQL)
  211. self.conn.commit()
  212. cursor.close()
  213. return tf.MessageToString(cmd,as_utf8=True)
  214. def enqueue_pickcmd(self,table):
  215. with self.lock:
  216. cmd=message.pick_table()
  217. tf.Parse(table,cmd)
  218. #检查车辆是否在车位表,查找对应车位,找到即入队
  219. self.conn.ping()
  220. self.conn.begin()
  221. cursor = self.conn.cursor()
  222. SQL="select * from vehicle where primary_key='%s'"%(cmd.primary_key)
  223. cursor.execute(SQL)
  224. car_info=cursor.fetchall()
  225. if not len(car_info)>=1:
  226. ts=message.table_statu()
  227. ts.execute_statu=message.eError
  228. ts.statu_description="车辆信息不存在!"
  229. cmd.statu.CopyFrom(ts)
  230. else:
  231. SQL="select * from command_queue where primary_key='%s'"%(cmd.primary_key)
  232. num=cursor.execute(SQL)
  233. if num>0: #取车指令在对哦中,不能执行
  234. ts=message.table_statu()
  235. ts.execute_statu=message.eError
  236. ts.statu_description="指令正在执行中,请稍等!"
  237. cmd.statu.CopyFrom(ts)
  238. else:
  239. car_number=car_info[0][0]
  240. cmd.car_number=car_number
  241. #查询车位
  242. SQL="select * from space where car_number='%s'"%(car_number)
  243. cursor.execute(SQL)
  244. space=cursor.fetchall()
  245. #找不到,将指令表单状态修改为error
  246. if not len(space)==1:
  247. ts=message.table_statu()
  248. ts.execute_statu=message.eError
  249. ts.statu_description="没有找到车辆信息,请联系管理员!"
  250. cmd.statu.CopyFrom(ts)
  251. else:
  252. #查询到单元号,给指令表单单元号赋值
  253. unit_id=space[0][5]
  254. cmd.unit_id=unit_id
  255. ts = message.table_statu()
  256. ts.execute_statu=message.eNormal
  257. if unit_id == 1:
  258. ch = "A"
  259. elif unit_id == 2:
  260. ch = "B"
  261. elif unit_id == 3:
  262. ch = "C"
  263. ts.statu_description="%s 取车成功,请前往%s单元出口取车!"%(car_number,ch)
  264. cmd.statu.CopyFrom(ts)
  265. #给指令表单车位信息赋值
  266. space_info=message.parkspace_info()
  267. space_info.id=space[0][0]
  268. space_info.unit_id=unit_id
  269. space_info.floor=space[0][1]
  270. space_info.room_id=space[0][2]
  271. cmd.actually_space_info.CopyFrom(space_info)
  272. #赋值真实测量信息
  273. measure_info=message.measure_info()
  274. tf.Parse(car_info[0][2],measure_info)
  275. cmd.actually_measure_info.CopyFrom(measure_info)
  276. #指令入库
  277. cursor.execute("select * from command_queue,queue_number_data FOR UPDATE") #锁表
  278. SQL="select * from command_queue where unit=%d and statu=0"%(unit_id)
  279. cursor.execute(SQL)
  280. cmd_queue=cursor.fetchall()
  281. queue_id=0
  282. if len(cmd_queue)>0:
  283. SQL="select * from queue_number_data where unit=%d"%unit_id
  284. cursor.execute(SQL)
  285. record=cursor.fetchall()
  286. last_num=0
  287. last_time=datetime.datetime.now()
  288. if len(record)==1:
  289. last_num=record[0][1]
  290. last_time=record[0][2]
  291. elif len(record)==0:
  292. SQL="insert into queue_number_data values(%d,0,NULL)"%(cmd.unit_id)
  293. cursor.execute(SQL)
  294. diff=datetime.datetime.now()-last_time
  295. time_mns=diff.total_seconds()/60
  296. queue_id=int(last_num+1+ time_mns*1)
  297. SQL="insert into command_queue values('%s','%s',%d,%d,2,0,'%s','%s',NULL, NULL)"%(
  298. cmd.car_number,cmd.primary_key,unit_id,queue_id,tf.MessageToString(cmd.actually_space_info,as_utf8=True)
  299. ,tf.MessageToString(cmd.actually_measure_info,as_utf8=True))
  300. cursor.execute(SQL)
  301. #更新指令时间表,
  302. dt=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  303. SQL="update queue_number_data set last_number=%d,input_time=str_to_date('%s','%%Y-%%m-%%d %%H:%%i:%%S') where unit=%d"%(queue_id,dt,unit_id)
  304. cursor.execute(SQL)
  305. #取车指令入队完成,记录轴距信息
  306. self.update_wheelbase(cursor,cmd.car_number)
  307. self.conn.commit()
  308. cursor.close()
  309. return tf.MessageToString(cmd,as_utf8=True)
  310. def update_wheelbase(self,cursor,car_number):
  311. #取车指令入队成功,此处将车辆夹持杆轴距偏差按照 delta=0.03 更新 ----------------------------
  312. #获取车辆表中的轴距信息
  313. SQL="select actually_measure_info,plc_measure_info from vehicle where car_number='%s'"%car_number
  314. cursor.execute(SQL)
  315. records=cursor.fetchall()
  316. act_info=message.measure_info() #入口测量数据
  317. plc_info=message.measure_info() #plc反馈数据(夹持杆雷达)
  318. clamp_wheelbase=None
  319. if len(records)==1: #找到记录
  320. if records[0][0] is not None and records[0][1] is not None:
  321. tf.Parse(records[0][0],act_info)
  322. tf.Parse(records[0][1],plc_info)
  323. if abs(act_info.wheelbase-plc_info.wheelbase)<0.05: #入口数据与夹持数据相近,可靠,
  324. clamp_wheelbase=plc_info.wheelbase
  325. #夹持数据存在,且可靠数据,存库,
  326. if(clamp_wheelbase is not None):
  327. SQL="select * from car_parameter where car_number='%s'"%car_number
  328. cursor.execute(SQL)
  329. records=cursor.fetchall()
  330. update_wheelbase=clamp_wheelbase
  331. update_delta=0.03
  332. SQL="insert into car_parameter values('%s',%f,%f,%f,0.03)"%(car_number,update_wheelbase,update_delta,plc_info.width)
  333. if len(records)==1:#有历史数据
  334. wheel_base=float(records[0][1])
  335. wheel_base_delta=float(records[0][2])
  336. if abs(clamp_wheelbase-wheel_base)>0.05: #可能存在改装或者换牌,重置delta
  337. print("车辆:%s 可能存在换牌或者改装,重置轴距信息"%(car_number))
  338. else: #计算新值
  339. dcdc=update_delta*update_delta
  340. dd=wheel_base_delta*wheel_base_delta
  341. update_wheelbase=clamp_wheelbase*dd/(dcdc+dd)+wheel_base*dcdc/(dd+dcdc)
  342. update_delta=math.sqrt(dcdc*dd/(dcdc+dd))
  343. print("车辆:%s 更新数据库轴距:%.5f,标准差:%.5f"%(car_number,update_wheelbase,update_delta))
  344. SQL="update car_parameter set wheelbase=%f,var_wheelbase=%f where car_number='%s'"%(update_wheelbase,update_delta,car_number)
  345. else:
  346. print("新车:%s 第一次光临,存入轴距:%f"%(car_number,update_wheelbase))
  347. cursor.execute(SQL)
  348. def get_wheelbase(self,cursor,car_number):
  349. SQL="select * from car_parameter where car_number='%s'"%(car_number)
  350. cursor.execute(SQL)
  351. records=cursor.fetchall()
  352. if len(records)==1:
  353. wheelbase=float(records[0][1])
  354. delta=float(records[0][2])
  355. return [wheelbase,delta]
  356. else:
  357. return None
  358. @staticmethod
  359. def table_type(table):
  360. if table.find("entrance_measure_info")>=0:
  361. return "park"
  362. elif table.find("primary_key")>=0:
  363. return "pick"