billet_trace_pusher.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import logging
  2. from utils.statepoint import *
  3. from utils.s7data import *
  4. from models.data_sender import *
  5. from models.batcher import *
  6. import queue
  7. class Trace_pusher:
  8. def __init__(self, billet_input: list[queue.Queue[Billet]], data_s7: S7data, logger: logging.Logger, sender: Sender, strand_position: list, hostsend_flag=False, hostmove_flag=False):
  9. self.billet_input = billet_input
  10. self.data_s7 = data_s7
  11. self.logger = logger
  12. self.sender = sender
  13. self.strand_position = strand_position
  14. self.hostsend_flag = hostsend_flag
  15. self.hostmove_flag = hostmove_flag
  16. self.bed_left = [[], [], []]
  17. self.bed_right = [[], [], []]
  18. self.cool_bed_lock = threading.Lock()
  19. # 挡板事件 出坯到推钢区域
  20. self.barrier_up_sig = [self.data_s7.make_point(f'L{i+1}挡板') for i in range(8)]
  21. self.barrier_checker = [False, False, False, False, False, False, False, False]
  22. for i in range(8):
  23. self.barrier_up_sig[i].set_convertor(lambda data: not bool(data))
  24. self.barrier_up_sig[i].set_excite_action(lambda i=i: self.barrier_up_action(i))
  25. self.barrier_up_sig[i].set_reset_action(lambda i=i: self.barrier_down_action(i))
  26. # 推钢事件 推钢到南北小冷床
  27. self.pusher_left = data_s7.make_point('推钢机激光')
  28. self.pusher_right = data_s7.make_point('推钢机激光')
  29. self.pusher_left.hmd_add(0)
  30. self.pusher_right.hmd_add(0)
  31. self.pusher_left_list: list[Billet] = []
  32. self.pusher_right_list: list[Billet] = []
  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. # 棒一热送事件(仅五号机)
  38. if self.hostsend_flag:
  39. self.hostsend_barrier = [self.data_s7.make_point(f'热送挡板[{i}]') for i in range(8)]
  40. for i in range(8):
  41. self.hostsend_barrier[i].set_convertor(lambda data: not bool(data))
  42. self.hostsend_barrier[i].set_excite_action(lambda i=i: self.hostsend_barrier_up_action(i))
  43. self.hostsend_barrier[i].set_reset_action(lambda i=i: self.logger.debug(f"[TRACE]{i+1}流热送挡板关闭"))
  44. # 热送副跨事件(仅六号机)
  45. if self.hostmove_flag:
  46. self.hostmove_sig = data_s7.make_point('热送辊道状态[1]')
  47. self.hostmove_sig.set_excite_action(lambda: self.billet_to_stack("步进冷床", self.get_billet('right')))
  48. def barrier_up_action(self, i: int):
  49. self.logger.debug(f"[TRACE]{i+1}流挡板开启")
  50. while self.barrier_up_sig[i].converter(self.barrier_up_sig[i].data):
  51. if self.billet_input[i].empty() or datetime.datetime.now() - self.billet_input[i].queue[0].start_cutting_time < datetime.timedelta(seconds=25):
  52. time.sleep(0.5)
  53. continue
  54. billet = self.billet_input[i].get(False)
  55. self.barrier_checker[i] = True
  56. self.logger.debug(f"[TRACE]{i+1}流钢坯经过挡板")
  57. time.sleep(10)
  58. if self.strand_position[i] <= self.pusher_left.data:
  59. self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机北侧")
  60. self.pusher_left_list.append(billet)
  61. else:
  62. self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机南侧")
  63. self.pusher_right_list.append(billet)
  64. if self.hostsend_flag and self.hostsend_barrier[i].state:
  65. self.hostsend_barrier_up_action(i)
  66. time.sleep(5)
  67. def barrier_down_action(self, i: int):
  68. if self.barrier_checker[i]:
  69. self.logger.debug(f"[TRACE]{i+1}流挡板关闭")
  70. else:
  71. self.logger.error(f"[TRACE]{i+1}流挡板开启期间无钢坯流出")
  72. self.barrier_checker[i] = False
  73. def arrive_cooling_bed(self, direc):
  74. if direc == 'left':
  75. tmp = self.pusher_left_list
  76. self.pusher_left_list = []
  77. tmp.sort(key=lambda obj: obj.strand_no)
  78. dst = self.bed_left
  79. elif direc == 'right':
  80. tmp = self.pusher_right_list
  81. self.pusher_right_list = []
  82. tmp.sort(key=lambda obj: obj.strand_no, reverse=True)
  83. dst = self.bed_right
  84. else:
  85. return
  86. if tmp:
  87. self.billet_to_bed(tmp, dst, True if direc == "right" else False)
  88. def billet_to_bed(self, billets: list[Billet], dst: list[list[Billet]], union_reverse = False):
  89. with self.cool_bed_lock:
  90. len_count = len(billets)
  91. # 找到第一个空位
  92. count = 0
  93. while count < len(dst) and dst[count]:
  94. count += 1
  95. if count == 0:
  96. dst[0].extend(billets)
  97. elif count == len(dst) and (len_count >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len_count > 4):
  98. self.logger.error(f"[TRACE]组坯异常!")
  99. tmp = dst.pop(0)
  100. dst.append(billets)
  101. # test 把无法组坯的不正常钢坯 直接上传服务器
  102. if len(tmp) < 4:
  103. self.billet_union(tmp)
  104. count -= 1
  105. elif len_count >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len_count > 4:
  106. dst[count].extend(billets)
  107. else:
  108. count -= 1
  109. dst[count].extend(billets)
  110. if len(dst[count]) >= 4:
  111. self.billet_union(dst[count], union_reverse)
  112. if not union_reverse:
  113. self.logger.info(f"[TRACE]北侧冷床上推入{len_count}根钢坯,目前情况:{len(self.bed_left[0])}根|{len(self.bed_left[1])}根|{len(self.bed_left[2])}根")
  114. else:
  115. self.logger.info(f"[TRACE]南侧冷床上推入{len_count}根钢坯,目前情况:{len(self.bed_right[2])}根|{len(self.bed_right[1])}根|{len(self.bed_right[0])}根")
  116. def billet_union(self, billets: list[Billet], reverse = False):
  117. if reverse:
  118. billets.reverse()
  119. if len(billets) < 4:
  120. for i in billets:
  121. if i.batch_strand():
  122. self.sender.billet_upload(i.heat.to_dict(), i.heat_no + i.ccm_no + str(i.strand_no) + "99", 0, i.sizing, i.drawing_speed,
  123. i.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", '', error=True)
  124. self.logger.warning(f"[TRACE]发送异常钢坯{len(billets)}根")
  125. return
  126. # 组坯时,定尺为此组内定尺最小值,炉次为最后一根加入此组的炉次
  127. sizing = min(billets, key=lambda obj: obj.sizing).sizing
  128. heat = max(billets, key=lambda obj: obj.start_cutting_time).heat
  129. billet_unionNo = heat.heat_no + '{:0>5}'.format(int(sizing)) + '{:0>2}'.format(heat.claim_union_seq(sizing))
  130. billetsNo = []
  131. for i in billets:
  132. i.heat = heat
  133. i.batch_strand()
  134. billetsNo.append(i.billet_no)
  135. self.sender.billet_upload(heat.to_dict(), i.billet_no, i.heat_seq, i.sizing, i.drawing_speed,
  136. i.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", billet_unionNo)
  137. self.sender.billet_union(heat.to_dict(), billet_unionNo, billetsNo, sizing)
  138. self.logger.info(f"[TRACE]{heat.heat_no}炉组号{billet_unionNo}钢坯{len(billets)}根:\n {'、'.join(billetsNo)}")
  139. def hostsend_barrier_up_action(self, i: int):
  140. gp_tmp = None
  141. if self.strand_position[i] <= self.pusher_left.data:
  142. index = -1
  143. for j in range(len(self.pusher_left_list)-1, -1, -1):
  144. if self.pusher_left_list[j].strand_no == i+1:
  145. index = j
  146. break
  147. if index == -1:
  148. self.logger.debug(f"[TRACE]推钢机北侧未找到{i+1}流的热送钢坯")
  149. else:
  150. gp_tmp = self.pusher_left_list[index]
  151. self.pusher_left_list = self.pusher_left_list[:index] + self.pusher_left_list[index+1:]
  152. else:
  153. index = -1
  154. for j in range(len(self.pusher_right_list)-1, -1, -1):
  155. if self.pusher_right_list[j].strand_no == i+1:
  156. index = j
  157. break
  158. if index == -1:
  159. self.logger.debug(f"[TRACE]推钢机南侧未找到{i+1}流的热送钢坯")
  160. else:
  161. gp_tmp = self.pusher_right_list[index]
  162. self.pusher_right_list = self.pusher_right_list[:index] + self.pusher_right_list[index+1:]
  163. if gp_tmp:
  164. self.hostsend(gp_tmp)
  165. def hostsend(self, billet: Billet):
  166. billet.batch_strand()
  167. self.sender.billet_upload(billet.heat.to_dict(), billet.billet_no, billet.heat_seq, billet.sizing, billet.drawing_speed,
  168. billet.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", '')
  169. self.logger.info(f"[TRACE]{billet.heat.heat_no}炉{billet.strand_no}流钢坯热送:{billet.billet_no}")
  170. self.sender.host_send(billet.ccm_no, billet.billet_no, "棒一")
  171. def show_coolbed(self):
  172. print(f"北侧冷床目前情况:{len(self.bed_left[0])}根|{len(self.bed_left[1])}根|{len(self.bed_left[2])}根")
  173. print(f"南侧冷床目前情况:{len(self.bed_right[2])}根|{len(self.bed_right[1])}根|{len(self.bed_right[0])}根")
  174. def clean_status(self):
  175. self.logger.debug(f"[TRACE]小冷床状态清空")
  176. self.pusher_left_list = []
  177. self.pusher_right_list = []
  178. self.bed_left = [[], [], []]
  179. self.bed_right = [[], [], []]
  180. def get_billet(self, direc) -> list[str]:
  181. if direc == "left":
  182. return self.get_billet_action(self.bed_left)
  183. if direc == "right":
  184. return self.get_billet_action(self.bed_right)
  185. def get_billet_action(self, src: list[list[Billet]]) -> list[str]:
  186. with self.cool_bed_lock:
  187. for i in range(len(src)-1, -1, -1):
  188. if len(src[i]) >= 4:
  189. tmp = [j.billet_no for j in src.pop(i)]
  190. src.append([])
  191. return tmp
  192. return []
  193. def billet_to_stack(self, stackNo, billets: list[str]):
  194. if billets:
  195. self.logger.info(f"[TRACE]有钢坯放入{stackNo}堆垛")
  196. self.sender.stack_add('6', billets, "", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), "6#小冷床(南)", '步进冷床堆垛')