billet_trace_pusher.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. import logging
  2. from utils.statepoint import *
  3. from utils.s7data import *
  4. from models.data_sender import *
  5. class Trace_pusher:
  6. def __init__(self, data_s7: S7data, logger: logging.Logger, sender: Sender, strand_position: list, hostsend_flag=False, hostmove_flag=False):
  7. self.data_s7 = data_s7
  8. self.logger = logger
  9. self.sender = sender
  10. self.strands_cutting = [[], [], [], [], [], [], [], []]
  11. self.strands_buffer = [[], [], [], [], [], [], [], []]
  12. self.locks = [threading.Lock() for i in range(8)]
  13. self.strand_position = strand_position
  14. self.hostsend_flag = hostsend_flag
  15. self.hostmove_flag = hostmove_flag
  16. self.old_heatNo = "00000000"
  17. self.current_heatNo = "00000000"
  18. self.old_heatData = {}
  19. self.current_heatData = {}
  20. self.total = 0
  21. self.strand = [0, 0, 0, 0, 0, 0, 0, 0]
  22. self.count_lock = threading.Lock()
  23. self.sizing_count_heatNo = "00000000"
  24. self.sizing_count = {}
  25. self.pusher_left_list = []
  26. self.pusher_right_list = []
  27. self.bed_left = [[], [], []]
  28. self.bed_right = [[], [], []]
  29. self.pusher_left = data_s7.make_point('推钢机激光')
  30. self.pusher_right = data_s7.make_point('推钢机激光')
  31. self.pusher_left.hmd_add(0)
  32. self.pusher_right.hmd_add(0)
  33. self.pusher_left.set_convertor(lambda data: data < min(self.strand_position))
  34. self.pusher_right.set_convertor(lambda data: data > max(self.strand_position))
  35. self.pusher_left.set_excite_action(lambda: self.arrive_cooling_bed('left'))
  36. self.pusher_right.set_excite_action(lambda: self.arrive_cooling_bed('right'))
  37. self.billet_out = [[], [], [], [], [], [], [], []]
  38. self.length_cutting = []
  39. for i in range(8):
  40. self.length_cutting.append(self.data_s7.make_point(f'L{i+1}定尺'))
  41. self.drawing_speed = []
  42. for i in range(8):
  43. self.drawing_speed.append(self.data_s7.make_point(f'L{i+1}拉速'))
  44. if self.hostsend_flag:
  45. # self.billet_position = [
  46. # Through_state_continues3(data_s7.make_point('集群限位L1_1[3]'), data_s7.make_point('集群限位L1_1[4]'), data_s7.make_point('集群限位L1_1[5]')),
  47. # Through_state_continues3(data_s7.make_point('集群限位L2_1[3]'), data_s7.make_point('集群限位L2_1[4]'), data_s7.make_point('集群限位L2_1[5]')),
  48. # Through_state_continues3(data_s7.make_point('集群限位L3_1[3]'), data_s7.make_point('集群限位L3_1[4]'), data_s7.make_point('集群限位L3_1[5]')),
  49. # Through_state_continues3(data_s7.make_point('集群限位L4_1[3]'), data_s7.make_point('集群限位L4_1[4]'), data_s7.make_point('集群限位L4_1[5]')),
  50. # Through_state_continues3(data_s7.make_point('集群限位L5_1[3]'), data_s7.make_point('集群限位L5_1[4]'), data_s7.make_point('集群限位L5_1[5]')),
  51. # Through_state_continues3(data_s7.make_point('集群限位L6_1[3]'), data_s7.make_point('集群限位L6_1[4]'), data_s7.make_point('集群限位L6_1[5]')),
  52. # Through_state_separation2(data_s7.make_point('集群限位L7_1[4]'), data_s7.make_point('集群限位L7_1[5]')),
  53. # Through_state_continues3(data_s7.make_point('集群限位L8_1[3]'), data_s7.make_point('集群限位L8_1[4]'), data_s7.make_point('集群限位L8_1[5]'))
  54. # ]
  55. # self.billet_out_sig = [
  56. # data_s7.make_point('集群限位L1_2[1]'),
  57. # data_s7.make_point('集群限位L2_2[1]'),
  58. # data_s7.make_point('集群限位L3_2[1]'),
  59. # data_s7.make_point('集群限位L4_2[1]'),
  60. # data_s7.make_point('集群限位L5_2[1]'),
  61. # data_s7.make_point('集群限位L6_2[1]'),
  62. # data_s7.make_point('集群限位L7_2[1]'),
  63. # data_s7.make_point('集群限位L8_2[1]')
  64. # ]
  65. self.billet_position = [
  66. self.data_s7.make_point('L1切割信号[1]'),
  67. self.data_s7.make_point('L2切割信号[1]'),
  68. self.data_s7.make_point('L3切割信号[1]'),
  69. self.data_s7.make_point('L4切割信号[1]'),
  70. self.data_s7.make_point('L5切割信号[1]'),
  71. self.data_s7.make_point('L6切割信号[1]'),
  72. self.data_s7.make_point('L7切割信号[1]'),
  73. self.data_s7.make_point('L8切割信号[1]')
  74. ]
  75. self.billet_out_sig = [
  76. self.data_s7.make_point('L1切割信号[0]'),
  77. self.data_s7.make_point('L2切割信号[0]'),
  78. self.data_s7.make_point('L3切割信号[0]'),
  79. self.data_s7.make_point('L4切割信号[0]'),
  80. self.data_s7.make_point('L5切割信号[0]'),
  81. self.data_s7.make_point('L6切割信号[0]'),
  82. self.data_s7.make_point('L7切割信号[0]'),
  83. self.data_s7.make_point('L8切割信号[0]')
  84. ]
  85. else:
  86. self.billet_position = [
  87. self.data_s7.make_point('L1坯头位置'),
  88. self.data_s7.make_point('L2坯头位置'),
  89. self.data_s7.make_point('L3坯头位置'),
  90. self.data_s7.make_point('L4坯头位置'),
  91. self.data_s7.make_point('L5坯头位置'),
  92. self.data_s7.make_point('L6坯头位置'),
  93. self.data_s7.make_point('L7坯头位置'),
  94. self.data_s7.make_point('L8坯头位置')
  95. ]
  96. self.barrier = [
  97. self.data_s7.make_point('L1挡板'),
  98. self.data_s7.make_point('L2挡板'),
  99. self.data_s7.make_point('L3挡板'),
  100. self.data_s7.make_point('L4挡板'),
  101. self.data_s7.make_point('L5挡板'),
  102. self.data_s7.make_point('L6挡板'),
  103. self.data_s7.make_point('L7挡板'),
  104. self.data_s7.make_point('L8挡板')
  105. ]
  106. self.barrier_checker = [False, False, False, False, False, False, False, False]
  107. if self.hostsend_flag:
  108. self.hostsend_barrier = [
  109. self.data_s7.make_point('热送挡板[0]'),
  110. self.data_s7.make_point('热送挡板[1]'),
  111. self.data_s7.make_point('热送挡板[2]'),
  112. self.data_s7.make_point('热送挡板[3]'),
  113. self.data_s7.make_point('热送挡板[4]'),
  114. self.data_s7.make_point('热送挡板[5]'),
  115. self.data_s7.make_point('热送挡板[6]'),
  116. self.data_s7.make_point('热送挡板[7]'),
  117. ]
  118. if self.hostmove_flag:
  119. self.hostmove_sig = data_s7.make_point('推钢机激光')
  120. self.hostmove_sig.hmd_add(0)
  121. self.hostmove_sig.set_convertor(lambda data: data > 19000)
  122. self.hostmove_sig.set_excite_action(lambda: self.billet_to_stack("步进冷床", self.get_billet('right')))
  123. for i in range(8):
  124. # 坯子出现
  125. self.billet_position[i].allow_update(False)
  126. self.billet_position[i].set_state(False)
  127. if not self.hostsend_flag:
  128. self.billet_position[i].set_convertor(lambda data: 12000 < data < 20000)
  129. self.billet_position[i].set_excite_action(lambda i=i: self.billet_out_action(i))
  130. self.billet_position[i].set_reset_action(lambda i=i: self.billet_in_buffer_action(i))
  131. else:
  132. self.billet_position[i].set_excite_action(lambda i=i: self.billet_in_buffer_action(i))
  133. self.billet_out_sig[i].set_excite_action(lambda i=i: self.billet_out_action(i))
  134. self.billet_position[i].allow_update()
  135. # 挡板抬起
  136. self.barrier[i].allow_update(False)
  137. self.barrier[i].set_state(False)
  138. self.barrier[i].set_convertor(lambda data: not bool(data))
  139. self.barrier[i].set_excite_action(lambda i=i: self.barrier_up_action(i))
  140. self.barrier[i].set_reset_action(lambda i=i: self.barrier_down_action(i))
  141. self.barrier[i].allow_update()
  142. # 直轧挡板抬起
  143. if self.hostsend_flag:
  144. self.hostsend_barrier[i].allow_update(False)
  145. self.hostsend_barrier[i].set_state(False)
  146. self.hostsend_barrier[i].set_convertor(lambda data: not bool(data))
  147. self.hostsend_barrier[i].set_excite_action(lambda i=i: self.hostsend_barrier_up_action(i))
  148. self.hostsend_barrier[i].set_reset_action(lambda i=i: self.logger.debug(f"{i+1}流热送挡板关闭"))
  149. self.hostsend_barrier[i].allow_update()
  150. def billet_out_action(self, i):
  151. # [坯号, 炉次信息, 定尺, 拉速, 开切时间, 停切时间]
  152. billetNo = self.current_heatNo + '0' + str(i+1) + '99'
  153. sizing = self.length_cutting[i].data
  154. speed = self.drawing_speed[i].data
  155. self.billet_out[i] = [billetNo, self.current_heatData, sizing, speed, time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '']
  156. def billet_in_buffer_action(self, i):
  157. with self.locks[i]:
  158. if self.strands_cutting[i]:
  159. self.logger.info(f"[TRACE]{i+1}流新增钢坯存储")
  160. self.strands_buffer[i] = self.strands_cutting[i]
  161. self.strands_cutting[i] = []
  162. elif self.billet_out[i]:
  163. self.logger.info(f"[TRACE]{i+1}流开切漏钢,算法补入")
  164. self.strands_buffer[i] = self.billet_out[i]
  165. else:
  166. self.logger.info(f"[TRACE]{i+1}流开切漏钢,但未检测到可补入钢坯的信息")
  167. self.billet_out[i] = []
  168. if self.barrier[i].state and self.barrier_checker[i] == False:
  169. self.barrier_up_action(i)
  170. def barrier_up_action(self, i):
  171. with self.locks[i]:
  172. if self.strands_buffer[i]:
  173. self.barrier_checker[i] = True
  174. time.sleep(12)
  175. billetData = self.strands_buffer[i]
  176. self.strands_buffer[i] = []
  177. if self.strand_position[i] <= self.pusher_left.data:
  178. self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机左侧")
  179. self.pusher_left_list.append(billetData)
  180. else:
  181. self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机右侧")
  182. self.pusher_right_list.append(billetData)
  183. if self.hostsend_flag and self.hostsend_barrier[i].state:
  184. self.hostsend_barrier_up_action(i)
  185. def barrier_down_action(self, i):
  186. if self.barrier_checker[i]:
  187. self.logger.debug(f"[TRACE]{i+1}流挡板关闭")
  188. else:
  189. self.logger.error(f"[TRACE]{i+1}流挡板关闭,期间无钢坯流出")
  190. self.barrier_checker[i] = False
  191. def hostsend_barrier_up_action(self, i):
  192. with self.count_lock:
  193. gp_tmp = []
  194. if self.strand_position[i] <= self.pusher_left.data:
  195. index = -1
  196. for j in range(len(self.pusher_left_list)-1, -1, -1):
  197. if self.pusher_left_list[j][0][-3] == str(i+1):
  198. index = j
  199. break
  200. if index == -1:
  201. pass
  202. #self.logger.warning(f"[TRACE]推钢机左侧未找到{i+1}流的热送钢坯")
  203. else:
  204. gp_tmp = self.pusher_left_list[index]
  205. self.pusher_left_list = self.pusher_left_list[:index] + self.pusher_left_list[index+1:]
  206. else:
  207. index = -1
  208. for j in range(len(self.pusher_right_list)-1, -1, -1):
  209. if self.pusher_right_list[j][0][-3] == str(i+1):
  210. index = j
  211. break
  212. if index == -1:
  213. pass
  214. #self.logger.warning(f"[TRACE]推钢机右侧未找到{i+1}流的热送钢坯")
  215. else:
  216. gp_tmp = self.pusher_right_list[index]
  217. self.pusher_right_list = self.pusher_right_list[:index] + self.pusher_right_list[index+1:]
  218. if gp_tmp:
  219. self.logger.info(f"[TRACE]{i+1}流钢坯热送")
  220. if not (gp_tmp[0].startswith(self.current_heatNo) or gp_tmp[0].startswith(self.old_heatNo)):
  221. self.change_heat(gp_tmp)
  222. if not gp_tmp[0].startswith('0'):
  223. self.hostsend(gp_tmp)
  224. def change_heat(self, data):
  225. # 换炉代码
  226. self.old_heatNo = self.current_heatNo
  227. self.old_heatData = self.current_heatData
  228. self.current_heatNo = data[0][:8]
  229. self.current_heatData = data[1]
  230. # 上一炉终止信号在这里发
  231. self.total = 0
  232. self.strand = [0, 0, 0, 0, 0, 0, 0, 0]
  233. def arrive_cooling_bed(self, direc):
  234. with self.count_lock:
  235. if direc == 'left':
  236. self.logger.debug(f"左侧冷床上推入{len(self.pusher_left_list)}根钢坯")
  237. tmp = self.pusher_left_list
  238. self.pusher_left_list = []
  239. elif direc == 'right':
  240. self.logger.debug(f"右侧冷床上推入{len(self.pusher_right_list)}根钢坯")
  241. tmp = self.pusher_right_list
  242. self.pusher_right_list = []
  243. for i in tmp:
  244. if not (i[0].startswith(self.current_heatNo) or i[0].startswith(self.old_heatNo)):
  245. self.change_heat(i)
  246. break
  247. self.billet_to_bed(tmp, direc)
  248. def billet_to_bed(self, billets, direc):
  249. if direc == 'left':
  250. if len(billets):
  251. self.billet_to_bed_impl(billets, self.bed_left)
  252. self.logger.debug(f"左侧冷床目前情况:{len(self.bed_left[0])}根|{len(self.bed_left[1])}根|{len(self.bed_left[2])}根")
  253. elif direc == 'right':
  254. if len(billets):
  255. self.billet_to_bed_impl(billets, self.bed_right)
  256. self.logger.debug(f"右侧冷床目前情况:{len(self.bed_right[2])}根|{len(self.bed_right[1])}根|{len(self.bed_right[0])}根")
  257. def billet_to_bed_impl(self, billets: list, dst: list):
  258. i = 0
  259. count = 0
  260. while i < len(dst) and dst[i]:
  261. count += 1
  262. i += 1
  263. if count == 0:
  264. dst[0].extend(billets)
  265. # elif count == 3 and (len(billets) >= 4 or len(dst[count-1]) >= 4):
  266. # self.logger.error(f"组坯异常!")
  267. # flag = False
  268. # for j in dst:
  269. # if len(j) < 4:
  270. # flag = True
  271. # dst.remove(j)
  272. # break
  273. # if flag:
  274. # dst.append(billets)
  275. # else:
  276. # dst.remove(dst[0])
  277. # dst.append(billets)
  278. # count -= 1
  279. # elif count == 3 and len(dst[count-1]) + len(billets) > 4:
  280. # self.logger.error(f"组坯异常!")
  281. # dst[count-1].extend(billets)
  282. # count -= 1
  283. elif count == 3 and (len(billets) >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len(billets) > 4):
  284. self.logger.error(f"组坯异常!")
  285. dst.remove(dst[0])
  286. dst.append(billets)
  287. count -= 1
  288. elif len(billets) >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len(billets) > 4:
  289. dst[count].extend(billets)
  290. else:
  291. dst[count-1].extend(billets)
  292. count -= 1
  293. if len(dst[count]) >= 4:
  294. self.billet_union(dst[count])
  295. def billet_union(self, billets):
  296. if self.sizing_count_heatNo != self.current_heatNo:
  297. self.sizing_count_heatNo = self.current_heatNo
  298. self.sizing_count = {}
  299. if billets[0][2] not in self.sizing_count:
  300. self.sizing_count[billets[0][2]] = 0
  301. self.sizing_count[billets[0][2]] += 1
  302. billet_unionNo = self.current_heatNo + '{:0>5}'.format(int(billets[0][2])) + '{:0>2}'.format(self.sizing_count[billets[0][2]])
  303. billetsNo = []
  304. ccmNo = self.current_heatData['ccmNo'] if self.current_heatData else '0'
  305. for i in billets:
  306. strandNo = i[0][9]
  307. self.total += 1
  308. self.strand[int(strandNo)-1] += 1
  309. billetNo = self.current_heatNo + ccmNo + strandNo + '{:0>2}'.format(self.strand[int(strandNo)-1])
  310. billetsNo.append(billetNo)
  311. i[0] = billetNo
  312. i[1] = self.current_heatData
  313. if self.current_heatData:
  314. self.sender.billet_upload(self.current_heatData, billetNo, self.total, i[2], i[3], i[4], i[5], billet_unionNo)
  315. if self.current_heatData:
  316. self.sender.billet_union(self.current_heatData, billet_unionNo, billetsNo, int(billets[0][2]))
  317. self.logger.info(f"{self.current_heatNo}炉组号{billet_unionNo}钢坯{len(billets)}根:\n {'、'.join(billetsNo)}")
  318. def data_from_casting(self, i, data, extend=False):
  319. with self.locks[i]:
  320. if extend:
  321. if self.strands_cutting[i] and self.strands_cutting[i][0] == data[0]:
  322. self.logger.info(f"{i+1}流补充了钢坯停切时间")
  323. self.strands_cutting[i] = data
  324. elif self.strands_buffer[i] and self.strands_buffer[i][0] == data[0]:
  325. self.logger.info(f"{i+1}流补充了钢坯停切时间")
  326. self.strands_buffer[i] = data
  327. else:
  328. self.logger.warning(f"{i+1}流对已经离开的钢坯补充停切时间,无效")
  329. else:
  330. if self.strands_cutting[i]:
  331. self.logger.warning(f"{i+1}流有钢坯开切冲突")
  332. self.strands_cutting[i] = data
  333. self.strands_cutting[i].append('')
  334. else:
  335. self.logger.info(f"{i+1}流钢坯开切")
  336. self.strands_cutting[i] = data
  337. self.strands_cutting[i].append('')
  338. def hostsend(self, i):
  339. ccmNo = self.current_heatData['ccmNo']
  340. strandNo = i[0][9]
  341. self.total += 1
  342. self.strand[int(strandNo)-1] += 1
  343. billetNo = self.current_heatNo + ccmNo + strandNo + '{:0>2}'.format(self.strand[int(strandNo)-1])
  344. i[0] = billetNo
  345. i[1] = self.current_heatData
  346. self.sender.billet_upload(self.current_heatData, billetNo, self.total, i[2], i[3], i[4], i[5], '')
  347. self.logger.info(f"{self.current_heatNo}炉钢坯热送:{billetNo}")
  348. self.sender.host_send(ccmNo, billetNo, "棒一")
  349. def clean_status(self):
  350. self.logger.debug(f"[TRACE]小冷床状态清空")
  351. with self.count_lock:
  352. self.pusher_left_list = []
  353. self.pusher_right_list = []
  354. self.bed_left = [[], [], []]
  355. self.bed_right = [[], [], []]
  356. def get_billet(self, direc):
  357. with self.count_lock:
  358. if direc == "left":
  359. return self.get_billet_action(self.bed_left)
  360. if direc == "right":
  361. return self.get_billet_action(self.bed_right)
  362. def get_billet_action(self, src: list):
  363. for i in range(len(src)-1, -1, -1):
  364. if len(src[i]) >= 4:
  365. tmp = [j[0] for j in src.pop(i)]
  366. src.append([])
  367. return tmp
  368. return []
  369. def billet_to_stack(self, stackNo, billets):
  370. self.logger.info(f"有钢坯放入{stackNo}堆垛")
  371. # [坯号, 炉次信息, 定尺, 拉速, 开切时间, 停切时间]