Files
Feeding_control_system/core/system.py

458 lines
18 KiB
Python
Raw Normal View History

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:
2025-11-21 14:55:52 +08:00
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)
2025-11-17 00:05:40 +08:00
# 初始化 OPC 队列监听线程
self.opc_queue_thread = None
2025-11-01 17:33:26 +08:00
# 线程管理
self.monitor_thread = None
self.visual_control_thread = None
self.alignment_check_thread = None
2025-11-01 17:33:26 +08:00
self.lower_feeding_thread = None
2025-11-21 14:55:52 +08:00
self.led_thread = None
def initialize(self):
"""初始化系统"""
print("初始化控制系统...")
2025-11-17 00:05:40 +08:00
# self.check_device_connectivity()
2025-11-21 14:55:52 +08:00
# self.camera_controller.start_cameras()
# self.start_monitoring()
# 启动下料线程
# self.start_lower_feeding()
# 启动OPC队列处理线程
# self.opcua_client_feed.start()
2025-11-17 00:05:40 +08:00
# self.start_opc_queue_thread()
2025-11-17 00:05:40 +08:00
#启用API线程
self.start_api_thread()
2025-11-01 17:33:26 +08:00
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):
"""启动系统监控"""
2025-11-21 14:55:52 +08:00
print('振动和要料监控线程启动')
self.monitor_thread = threading.Thread(
target=self._monitor_loop,
2025-11-21 14:55:52 +08:00
daemon=True,
name='monitor'
)
self.monitor_thread.start()
def _monitor_loop(self):
"""监控循环"""
while self.state.running:
try:
2025-11-21 14:55:52 +08:00
# 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):
"""启动下料流程"""
2025-11-01 17:33:26 +08:00
self.lower_feeding_thread = threading.Thread(
target=self._start_lower_feeding,
2025-11-12 09:22:21 +08:00
name="Feeding",
2025-11-01 17:33:26 +08:00
daemon=True
)
self.lower_feeding_thread.start()
def _start_lower_feeding(self):
"""启动下料流程"""
while self.state.running:
self.feeding_controller.start_feeding()
2025-11-21 14:55:52 +08:00
time.sleep(app_set_config.lower_feeding_interval)
2025-11-01 17:33:26 +08:00
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
# 尝试读取变频器一个寄存器(测试连接)
2025-11-21 14:55:52 +08:00
# test_result = self.relay_controller.modbus_client.read_holding_registers(
# address=0x00,
# count=1,
# slave=self.inverter_controller.config['slave_id']
# )
2025-11-01 17:33:26 +08:00
2025-11-21 14:55:52 +08:00
# if isinstance(test_result, Exception):
# print("变频器连接测试失败")
# return False
2025-11-01 17:33:26 +08:00
# 检查下料斗变送器连接
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()
2025-11-01 17:33:26 +08:00
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)