import logging from utils.statepoint import * from utils.s7data import * from models.data_sender import * from models.batcher import * import queue class Trace_pusher: 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): self.billet_input = billet_input self.data_s7 = data_s7 self.logger = logger self.sender = sender self.strand_position = strand_position self.hostsend_flag = hostsend_flag self.hostmove_flag = hostmove_flag self.bed_left = [[], [], []] self.bed_right = [[], [], []] self.cool_bed_lock = threading.Lock() # 挡板事件 出坯到推钢区域 self.barrier_up_sig = [self.data_s7.make_point(f'L{i+1}挡板') for i in range(8)] self.barrier_checker = [False, False, False, False, False, False, False, False] for i in range(8): self.barrier_up_sig[i].set_convertor(lambda data: not bool(data)) self.barrier_up_sig[i].set_excite_action(lambda i=i: self.barrier_up_action(i)) self.barrier_up_sig[i].set_reset_action(lambda i=i: self.barrier_down_action(i)) # 推钢事件 推钢到南北小冷床 self.pusher_left = data_s7.make_point('推钢机激光') self.pusher_right = data_s7.make_point('推钢机激光') self.pusher_left.hmd_add(0) self.pusher_right.hmd_add(0) self.pusher_left_list: list[Billet] = [] self.pusher_right_list: list[Billet] = [] self.pusher_left.set_convertor(lambda data: data < min(self.strand_position)) self.pusher_right.set_convertor(lambda data: data > max(self.strand_position)) self.pusher_left.set_excite_action(lambda: self.arrive_cooling_bed('left')) self.pusher_right.set_excite_action(lambda: self.arrive_cooling_bed('right')) # 棒一热送事件(仅五号机) if self.hostsend_flag: self.hostsend_barrier = [self.data_s7.make_point(f'热送挡板[{i}]') for i in range(8)] for i in range(8): self.hostsend_barrier[i].set_convertor(lambda data: not bool(data)) self.hostsend_barrier[i].set_excite_action(lambda i=i: self.hostsend_barrier_up_action(i)) self.hostsend_barrier[i].set_reset_action(lambda i=i: self.logger.debug(f"[TRACE]{i+1}流热送挡板关闭")) # 热送副跨事件(仅六号机) if self.hostmove_flag: self.hostmove_sig = data_s7.make_point('热送辊道状态[1]') self.hostmove_sig.set_excite_action(lambda: self.billet_to_stack("步进冷床", self.get_billet('right'))) def barrier_up_action(self, i: int): self.logger.debug(f"[TRACE]{i+1}流挡板开启") while self.barrier_up_sig[i].converter(self.barrier_up_sig[i].data): if self.billet_input[i].empty() or datetime.datetime.now() - self.billet_input[i].queue[0].start_cutting_time < datetime.timedelta(seconds=25): time.sleep(0.5) continue billet = self.billet_input[i].get(False) self.barrier_checker[i] = True self.logger.debug(f"[TRACE]{i+1}流钢坯经过挡板") time.sleep(10) if self.strand_position[i] <= self.pusher_left.data: self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机北侧") self.pusher_left_list.append(billet) else: self.logger.info(f"[TRACE]{i+1}流钢坯通过挡板进入推钢区域,在推钢机南侧") self.pusher_right_list.append(billet) if self.hostsend_flag and self.hostsend_barrier[i].state: self.hostsend_barrier_up_action(i) time.sleep(5) def barrier_down_action(self, i: int): if self.barrier_checker[i]: self.logger.debug(f"[TRACE]{i+1}流挡板关闭") else: self.logger.error(f"[TRACE]{i+1}流挡板开启期间无钢坯流出") self.barrier_checker[i] = False def arrive_cooling_bed(self, direc): if direc == 'left': tmp = self.pusher_left_list self.pusher_left_list = [] tmp.sort(key=lambda obj: obj.strand_no) dst = self.bed_left elif direc == 'right': tmp = self.pusher_right_list self.pusher_right_list = [] tmp.sort(key=lambda obj: obj.strand_no, reverse=True) dst = self.bed_right else: return if tmp: self.billet_to_bed(tmp, dst, True if direc == "right" else False) def billet_to_bed(self, billets: list[Billet], dst: list[list[Billet]], union_reverse = False): with self.cool_bed_lock: len_count = len(billets) # 找到第一个空位 count = 0 while count < len(dst) and dst[count]: count += 1 if count == 0: dst[0].extend(billets) elif count == len(dst) and (len_count >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len_count > 4): self.logger.error(f"[TRACE]组坯异常!") tmp = dst.pop(0) dst.append(billets) # test 把无法组坯的不正常钢坯 直接上传服务器 if len(tmp) < 4: self.billet_union(tmp) count -= 1 elif len_count >= 4 or len(dst[count-1]) >= 4 or len(dst[count-1]) + len_count > 4: dst[count].extend(billets) else: count -= 1 dst[count].extend(billets) if len(dst[count]) >= 4: self.billet_union(dst[count], union_reverse) if not union_reverse: self.logger.info(f"[TRACE]北侧冷床上推入{len_count}根钢坯,目前情况:{len(self.bed_left[0])}根|{len(self.bed_left[1])}根|{len(self.bed_left[2])}根") else: self.logger.info(f"[TRACE]南侧冷床上推入{len_count}根钢坯,目前情况:{len(self.bed_right[2])}根|{len(self.bed_right[1])}根|{len(self.bed_right[0])}根") def billet_union(self, billets: list[Billet], reverse = False): if reverse: billets.reverse() if len(billets) < 4: for i in billets: if i.batch_strand(): 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, i.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", '', error=True) self.logger.warning(f"[TRACE]发送异常钢坯{len(billets)}根") return # 组坯时,定尺为此组内定尺最小值,炉次为最后一根加入此组的炉次 sizing = min(billets, key=lambda obj: obj.sizing).sizing heat = max(billets, key=lambda obj: obj.start_cutting_time).heat billet_unionNo = heat.heat_no + '{:0>5}'.format(int(sizing)) + '{:0>2}'.format(heat.claim_union_seq(sizing)) billetsNo = [] for i in billets: i.heat = heat i.batch_strand() billetsNo.append(i.billet_no) self.sender.billet_upload(heat.to_dict(), i.billet_no, i.heat_seq, i.sizing, i.drawing_speed, i.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", billet_unionNo) self.sender.billet_union(heat.to_dict(), billet_unionNo, billetsNo, sizing) self.logger.info(f"[TRACE]{heat.heat_no}炉组号{billet_unionNo}钢坯{len(billets)}根:\n {'、'.join(billetsNo)}") def hostsend_barrier_up_action(self, i: int): gp_tmp = None if self.strand_position[i] <= self.pusher_left.data: index = -1 for j in range(len(self.pusher_left_list)-1, -1, -1): if self.pusher_left_list[j].strand_no == i+1: index = j break if index == -1: self.logger.debug(f"[TRACE]推钢机北侧未找到{i+1}流的热送钢坯") else: gp_tmp = self.pusher_left_list[index] self.pusher_left_list = self.pusher_left_list[:index] + self.pusher_left_list[index+1:] else: index = -1 for j in range(len(self.pusher_right_list)-1, -1, -1): if self.pusher_right_list[j].strand_no == i+1: index = j break if index == -1: self.logger.debug(f"[TRACE]推钢机南侧未找到{i+1}流的热送钢坯") else: gp_tmp = self.pusher_right_list[index] self.pusher_right_list = self.pusher_right_list[:index] + self.pusher_right_list[index+1:] if gp_tmp: self.hostsend(gp_tmp) def hostsend(self, billet: Billet): billet.batch_strand() self.sender.billet_upload(billet.heat.to_dict(), billet.billet_no, billet.heat_seq, billet.sizing, billet.drawing_speed, billet.start_cutting_time.strftime("%Y-%m-%d %H:%M:%S"), "", '') self.logger.info(f"[TRACE]{billet.heat.heat_no}炉{billet.strand_no}流钢坯热送:{billet.billet_no}") self.sender.host_send(billet.ccm_no, billet.billet_no, "棒一") def show_coolbed(self): print(f"北侧冷床目前情况:{len(self.bed_left[0])}根|{len(self.bed_left[1])}根|{len(self.bed_left[2])}根") print(f"南侧冷床目前情况:{len(self.bed_right[2])}根|{len(self.bed_right[1])}根|{len(self.bed_right[0])}根") def clean_status(self): self.logger.debug(f"[TRACE]小冷床状态清空") self.pusher_left_list = [] self.pusher_right_list = [] self.bed_left = [[], [], []] self.bed_right = [[], [], []] def get_billet(self, direc) -> list[str]: if direc == "left": return self.get_billet_action(self.bed_left) if direc == "right": return self.get_billet_action(self.bed_right) def get_billet_action(self, src: list[list[Billet]]) -> list[str]: with self.cool_bed_lock: for i in range(len(src)-1, -1, -1): if len(src[i]) >= 4: tmp = [j.billet_no for j in src.pop(i)] src.append([]) return tmp return [] def billet_to_stack(self, stackNo, billets: list[str]): if billets: self.logger.info(f"[TRACE]有钢坯放入{stackNo}堆垛") self.sender.stack_add('6', billets, "", time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), "6#小冷床(南)", '步进冷床堆垛')