import sys import os sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import threading import time import queue from core.system_state import SystemState,FeedStatus from hardware.relay import RelayController from hardware.inverter import InverterController from hardware.transmitter import TransmitterController from config.ini_manager import ini_manager from hardware.upper_plc import OmronFinsPollingService from vision.visual_callback_dq import VisualCallback from opc.opcua_client_feed import OpcuaClientFeed from busisness.blls import ArtifactBll,PDRecordBll from busisness.models import ArtifactInfoModel,PDRecordModel class FeedingControlSystem: def __init__(self): print('FeedingControlSystem初始化') self.state = SystemState() # 初始化硬件控制器 self.relay_controller = RelayController( host=ini_manager.relay_host, port=ini_manager.relay_port ) self.inverter_controller = InverterController() self.transmitter_controller = TransmitterController(self.relay_controller) #小屏修改过屏幕 self.vf_auto_mode=True # 初始化 OPC UA 客户端 self.opcua_client_feed = OpcuaClientFeed() # 初始化 RFID 控制器 # self.rfid_controller = rfid_service( # host=app_set_config.rfid_host, # port=app_set_config.rfid_port # ) # self.plc_service = OmronFinsPollingService(ini_manager.upper_plc_ip, ini_manager.upper_plc_port) # 初始化下料控制器 self.feeding_controller = VisualCallback(self.state) # 初始化 OPC 队列监听线程 self.opc_queue_thread = None # 线程管理 self.monitor_thread = None self.visual_control_thread = None self.alignment_check_thread = None self.lower_feeding_thread = None self.led_thread = None def initialize(self): """初始化系统""" print("初始化控制系统...") # self.check_device_connectivity() # self.camera_controller.start_cameras() # self.start_monitoring() # 启动下料线程 # self.start_lower_feeding() # 启动OPC队列处理线程 # self.opcua_client_feed.start() # self.start_opc_queue_thread() #启用API线程 self.start_api_thread() self.start_vf_thread() # self.feeding_controller.get_current_mould() # self.feeding_controller._cur_mould_model.MouldCode='SHR2L1-5' # self.feeding_controller.send_pd_data() #启用派单线程 # self.start_pd_thread() print("控制系统初始化完成") def start_opc_queue_thread(self): """启动OPC队列处理线程""" print('启动OPC队列处理线程') self.opc_queue_thread = threading.Thread( target=self._process_opc_queue, daemon=True, name='opc_queue_processor' ) self.opc_queue_thread.start() def start_api_thread(self): """启动PD线程""" # print('启动API处理线程,从API获取未浇筑数据') self.api_thread = threading.Thread( target=self._process_api_db, daemon=True, name='api_thread' ) self.api_thread.start() def start_vf_thread(self): """启动变频器控制线程""" # print('启动API处理线程,从API获取未浇筑数据') self.vf_thread = threading.Thread( target=self._process_vf, daemon=True, name='vf_thread' ) self.vf_thread.start() def _process_vf(self): _begin_time=None _wait_times=300 _start_wait_seconds=None while self.state.running: try: # if self.feeding_controller._is_finish_ratio>=0.6: # self.inverter_controller.set_frequency(230) # else: # self.inverter_controller.set_frequency(220) if self.state.vf_status in [1,2]: if _begin_time is None : print("----浇筑即将启动-----") if _start_wait_seconds is None: #记录盖板对齐时间 _start_wait_seconds=time.time() if self.feeding_controller._is_finish_ratio>=0.02: _elasped_time=time.time()-_start_wait_seconds if _elasped_time<10: time.sleep(10-_elasped_time) self.inverter_controller.control('start',230) print("----振捣已经启动-----") _begin_time=time.time() self.state._mould_frequency=230 self.state._mould_vibrate_status=True if self.state.vf_status==2: print("----振捣270s-----") _wait_time=270 else: print("----振捣300秒-----") _wait_time=300 else: print("----下料重量小于46KG,暂时不振捣-----") # else: elif self.state.vf_status==3 and _begin_time is not None: if time.time()-_begin_time>=_wait_time: if self.vf_auto_mode: self.inverter_controller.control('stop') self.state._mould_vibrate_status=False _begin_time=None _start_wait_seconds=None except Exception as e: print(f"处理变频器数据时发生错误: {e}") time.sleep(2) def _process_api_db(self): from service.mould_service import app_web_service """处理API队列中的数据""" # 初始化三个列表用于跟踪ArtifactActionID processed_artifact_actions = [] # 已处理的ArtifactActionID列表 processed_artifact_ids = [] # 已处理的ArtifactActionID列表 processed_pd_records = [] # 已插入PDRecord表的ArtifactActionID列表 processed_pd_ids=[] _model_task=None artifact_bll=ArtifactBll() pdrecord_bll=PDRecordBll() print('启动API处理线程,从API获取未浇筑数据') while self.state.running: try: not_poured = app_web_service.get_not_pour_artifacts() if not_poured: for item in reversed(not_poured): if item.MouldCode is None or item.MouldCode == '': continue _is_artifactid=True # 检查MouldCode是否已处理 if item.MouldCode in processed_artifact_actions: #print(f"待浇筑:MouldCode {item.MouldCode} 已处理,跳过") #处理过了。判断是否更新 if item.ArtifactID is None or item.ArtifactID == '': _is_artifactid=False if item.ArtifactID in processed_artifact_ids: # print(f"待浇筑:ArtifactID {item.ArtifactID} 已处理,跳过") _is_artifactid=False if _is_artifactid: _model_data = ArtifactInfoModel(**item.__dict__) _ret=artifact_bll.save_artifact_task(_model_data) if _ret > 0: # 标记为已处理 processed_artifact_actions.append(item.MouldCode) if len(processed_artifact_actions) > 4: processed_artifact_actions.pop(0) if item.ArtifactID: processed_artifact_ids.append(item.ArtifactID) if len(processed_artifact_ids) > 4: processed_artifact_ids.pop(0) # 限制最多保存3条记录,删除最旧的 #print(f"待浇筑:已处理MouldCode {item.MouldCode} ArtifactID {item.ArtifactID}") if item.MouldCode in processed_pd_records: #print(f"派单:MouldCode {item.MouldCode} 已处理,跳过") if item.ArtifactID is None or item.ArtifactID == '': continue if item.ArtifactID in processed_pd_ids: #print(f"待浇筑:ArtifactID {item.ArtifactID} 已处理,跳过") continue _pd_record_data=None if item.ArtifactID: if item.BetonTaskID is not None and item.BetonTaskID != '': #获取taskid if _model_task is None or item.BetonTaskID != _model_task.TaskID: _model_task = app_web_service.get_task_info(item.BetonTaskID) if _model_task is None: print(f"异常:BetonTaskID {item.BetonTaskID} 不存在,跳过") continue _pd_record_data = PDRecordModel( ArtifactID=item.ArtifactID, ArtifactActionID=item.ArtifactActionID, TaskID=_model_task.TaskID, ProjectName=_model_task.ProjectName, ProduceMixID=_model_task.ProduceMixID, BetonGrade=_model_task.BetonGrade, BetonVolume=item.BetonVolume, MouldCode=item.MouldCode, SkeletonID=item.SkeletonID, RingTypeCode=item.RingTypeCode, SizeSpecification=item.SizeSpecification, BuriedDepth=item.BuriedDepth, BlockNumber=item.BlockNumber, PlannedVolume=_model_task.PlannedVolume ) else: _pd_record_data = PDRecordModel( MouldCode=item.MouldCode ) if _pd_record_data is None: continue _ret=pdrecord_bll.save_PD_record(_pd_record_data) if _ret > 0: # 标记为已处理 processed_pd_records.append(item.MouldCode) # 限制最多保存3条记录,删除最旧的 if len(processed_pd_records) > 4: processed_pd_records.pop(0) if item.ArtifactID: processed_pd_ids.append(item.ArtifactID) if len(processed_pd_ids) > 4: processed_pd_ids.pop(0) #print(f"派单:已处理MouldCode {item.MouldCode} ArtifactID {item.ArtifactID}") except Exception as e: print(f"处理MouldCode {item.MouldCode} 时发生错误: {e}") time.sleep(5) def _process_opc_queue(self): """处理OPC队列中的数据""" while self.state.running: try: # 从队列中获取数据,设置超时以允许线程退出 item = self.state.opc_queue.get(timeout=1) if item: public_name, value = item # 这里可以添加实际的OPC处理逻辑 print(f"Processing OPC update: {public_name} = {value}") self.opcua_client_feed.write_value_by_name(public_name, value) # 标记任务完成 self.state.opc_queue.task_done() except queue.Empty: # 队列为空,继续循环 continue except Exception as e: print(f"OPC队列处理错误: {e}") def angle_visual_callback(self, current_angle, overflow_detected, mould_aligned): """角度视觉回调""" self.feeding_controller.angle_visual_callback(current_angle, overflow_detected, mould_aligned) def diff_visual_callback(self, current_diff,current_area): """差异视觉回调""" self.feeding_controller.diff_visual_callback(current_diff,current_area) def shutdown(self): """关闭系统""" self.feeding_controller.shutdown() self.stop() def start_monitoring(self): """启动系统监控""" print('振动和要料监控线程启动') self.monitor_thread = threading.Thread( target=self._monitor_loop, daemon=True, name='monitor' ) self.monitor_thread.start() def _monitor_loop(self): """监控循环""" while self.state.running: try: # self.feeding_controller.check_upper_material_request() self.feeding_controller.check_arch_blocking() time.sleep(1) except Exception as e: print(f"监控线程错误: {e}") def start_lower_feeding(self): """启动下料流程""" self.lower_feeding_thread = threading.Thread( target=self._start_lower_feeding, name="Feeding", daemon=True ) self.lower_feeding_thread.start() def _start_lower_feeding(self): """启动下料流程""" while self.state.running: self.feeding_controller.start_feeding() time.sleep(app_set_config.lower_feeding_interval) def check_device_connectivity(self) -> bool: """检查关键设备连接状态""" try: # 检查网络继电器连接 test_response = self.relay_controller.send_command(self.relay_controller.read_status_command) if not test_response: print("网络继电器连接失败") return False # 检查变频器连接 if not self.relay_controller.modbus_client.connect(): print("无法连接到网络继电器Modbus服务") return False # 尝试读取变频器一个寄存器(测试连接) # test_result = self.relay_controller.modbus_client.read_holding_registers( # address=0x00, # count=1, # slave=self.inverter_controller.config['slave_id'] # ) # if isinstance(test_result, Exception): # print("变频器连接测试失败") # return False # 检查下料斗变送器连接 test_weight = self.transmitter_controller.read_data(2) if test_weight is None: print("下料斗变送器连接失败") return False self.relay_controller.modbus_client.close() return True except Exception as e: print(f"设备连接检查失败: {e}") return False def start_pd_thread(self): """启动PD线程""" print('启动派单处理线程,从API获取未浇筑数据') self.pd_jbl_thread = threading.Thread( target=self._process_pd_jbl, daemon=True, name='pd_jbl_thread' ) self.pd_jbl_thread.start() def _process_pd_jbl(self): # pass #根据当前浇筑块进行最近一块的派单 _isFinish=False _start_time=None while self.state.running: #增加生产阶段检测, if self.state._feed_status==FeedStatus.FCheckGB: if not _isFinish: if _start_time is None: _start_time=time.time() _isSuccess=self.feeding_controller.send_pd_data() if _isSuccess: _isFinish=True if time.time()-_start_time>60: print('派单超时,人工介入') _isFinish=True elif self.state._feed_status==FeedStatus.FFinished: _start_time=None _isFinish=False time.sleep(5) @property def _is_finish(self): """检查系统是否运行""" return self.feeding_controller._is_finish @property def _is_finish_ratio(self): """检查系统是否运行""" return self.feeding_controller._is_finish_ratio @property def vibrate_status(self): """检查系统是否运行""" return self.state._mould_vibrate_status def set_vf_mode(self,is_auto=False): """设置变频器为自动模式""" self.vf_auto_mode=is_auto def stop(self): """停止系统""" print("停止控制系统...") self.state.running = False # 等待线程结束 if self.monitor_thread: self.monitor_thread.join() if self.visual_control_thread: self.visual_control_thread.join() if self.alignment_check_thread: self.alignment_check_thread.join() if self.lower_feeding_thread: self.lower_feeding_thread.join() if self.opc_queue_thread: self.opc_queue_thread.join() if self.vf_thread: self.vf_thread.join() if self.api_thread: self.api_thread.join() # 释放摄像头资源 # self.camera_controller.release() print("控制系统已停止") if __name__ == "__main__": system = FeedingControlSystem() system.initialize() time.sleep(2) system.state._upper_weight=1000 while True: time.sleep(1)