This commit is contained in:
2026-04-07 09:51:38 +08:00
parent ecba4d726a
commit 00dcd6b6cc
36 changed files with 2857 additions and 505 deletions

View File

@ -5,7 +5,8 @@ import threading
import time
import queue
import json
from core.system_state import SystemState,FeedStatus,Upper_Door_Position
import math
from core.system_state import SystemState,FeedStatus,Upper_Door_Position,PD_StatusEnum
from hardware.relay import RelayController
from hardware.inverter import InverterController
from hardware.transmitter import TransmitterController
@ -16,12 +17,16 @@ from opc.opcua_client_feed import OpcuaClientFeed
from busisness.blls import ArtifactBll,PDRecordBll,FreqRecordBll
from busisness.models import ArtifactInfoModel,PDRecordModel,FreqRecordModel
from core.pd_task_service import PD_TaskService
from vision.charge_3cls.charge_utils import run_stable_charge_loop
from core.pd_volume import PdVolume
from core.core_utils import CoreUtils
from datetime import datetime, timedelta
class FeedingControlSystem:
def __init__(self):
print('FeedingControlSystem初始化')
self.state = SystemState()
self.prev_pd_volume=0.0
self.pd_task_service = PD_TaskService()
self.pd_record_bll=PDRecordBll()
self.freq_record_bll=FreqRecordBll()
@ -154,9 +159,14 @@ class FeedingControlSystem:
#记录盖板对齐时间
_start_wait_seconds=time.time()
if self.state._mould_finish_ratio>=0.05:
_elasped_time=time.time()-_start_wait_seconds
if _elasped_time<10:
time.sleep(10-_elasped_time)
_is_charge= run_stable_charge_loop()
if _is_charge is not None:
print(f'------------已插好振捣棒: {_is_charge}-------------')
time.sleep(2)
# _elasped_time=time.time()-_start_wait_seconds
# if _elasped_time<10:
# time.sleep(10-_elasped_time)
self.inverter_controller.control('start',230)
_is_start=True
print("----浇筑已经启动-----")
@ -172,10 +182,10 @@ class FeedingControlSystem:
else:
print("----下料重量小于46KG,暂时不振捣-----")
else:
if self.state._mould_finish_ratio>=0.3:
if self.state._mould_frequency!=220:
self.inverter_controller.set_frequency(220)
self.state._mould_frequency=220
if self.state._mould_finish_ratio>=0.3 and self.state._mould_finish_ratio<0.4:
if self.state._mould_frequency!=230:
self.inverter_controller.set_frequency(230)
self.state._mould_frequency=230
elif self.state._mould_finish_ratio>=0.4:
if self.state._mould_frequency!=230:
self.inverter_controller.set_frequency(230)
@ -208,6 +218,7 @@ class FeedingControlSystem:
try:
not_poured = app_web_service.get_not_pour_artifacts()
if not_poured:
_is_refresh=False
for item in reversed(not_poured):
if item.MouldCode is None or item.MouldCode == '':
@ -228,13 +239,14 @@ class FeedingControlSystem:
_ret=artifact_bll.save_artifact_task(_model_data)
if _ret > 0:
# 标记为已处理
self.state._sys_segment_refresh=1
_is_refresh=True
# self.state._sys_segment_refresh=1
processed_artifact_actions.append(item.MouldCode)
if len(processed_artifact_actions) > 4:
if len(processed_artifact_actions) > 10:
processed_artifact_actions.pop(0)
if item.ArtifactID:
processed_artifact_ids.append(item.ArtifactID)
if len(processed_artifact_ids) > 4:
if len(processed_artifact_ids) > 10:
processed_artifact_ids.pop(0)
# 限制最多保存3条记录删除最旧的
@ -266,6 +278,7 @@ class FeedingControlSystem:
ProduceMixID=_model_task.ProduceMixID,
BetonGrade=_model_task.BetonGrade,
BetonVolume=item.BetonVolume,
BetonVolume2=PdVolume.get_volume_expect(item.MouldCode),
MouldCode=item.MouldCode,
SkeletonID=item.SkeletonID,
RingTypeCode=item.RingTypeCode,
@ -276,25 +289,30 @@ class FeedingControlSystem:
)
else:
_pd_record_data = PDRecordModel(
MouldCode=item.MouldCode
MouldCode=item.MouldCode,
BetonVolume2=PdVolume.get_volume_expect(item.MouldCode),
)
if _pd_record_data is None:
continue
_ret=pdrecord_bll.save_PD_record(_pd_record_data)
if _ret > 0:
self.state._sys_segment_refresh=1
# self.state._sys_segment_refresh=1
_is_refresh=True
# 标记为已处理
processed_pd_records.append(item.MouldCode)
# 限制最多保存3条记录删除最旧的
if len(processed_pd_records) > 4:
if len(processed_pd_records) > 10:
processed_pd_records.pop(0)
if item.ArtifactID:
processed_pd_ids.append(item.ArtifactID)
if len(processed_pd_ids) > 4:
if len(processed_pd_ids) > 10:
processed_pd_ids.pop(0)
#print(f"派单:已处理MouldCode {item.MouldCode} ArtifactID {item.ArtifactID}")
if _is_refresh:
self.state._sys_segment_refresh=1
except Exception as e:
print(f"处理MouldCode {item.MouldCode} 时发生错误: {e}")
@ -382,41 +400,73 @@ class FeedingControlSystem:
def _process_pd_jbl(self):
# pass
#根据当前浇筑块进行最近一块的派单
_isFinish=False
_start_time=None
# _start_time=None
while self.state.running:
#设置的派单模式
if self.state.pd_set_mode==1:
#增加生产阶段检测,
if self.state._feed_status==FeedStatus.FCheckGB:
if not _isFinish:
if _start_time is None:
_start_time=time.time()
#增加生产阶段检测,
try:
if self.state.pd_status==PD_StatusEnum.PD_Ready:
#L1对齐排L2和F的。L2对齐派F块,L2完成派B1块
# if _start_time is None:
# _start_time=time.time()
_isSuccess=self.send_pd_data()
if _isSuccess:
_isFinish=True
if time.time()-_start_time>60:
print('派单超时,人工介入')
_isFinish=True
elif self.state._feed_status==FeedStatus.FFinished:
self.state.pd_status=PD_StatusEnum.PD_Send_Finish
# _start_time=None
# elif time.time()-_start_time>60:
# print('派单超时,人工介入')
# self.pd_record_bll.start_pd(PD_StatusEnum.PD_TimeOut.value,_pdrecord.MouldCode,0)
# self.state.pd_status=PD_StatusEnum.PD_TimeOut
# _start_time=None
elif self.state.pd_status==PD_StatusEnum.PD_TimeOut:
self.pd_record_bll.start_pd(PD_StatusEnum.PD_TimeOut.value,self.state.pd_mould_code,-1)
self.state.pd_status=PD_StatusEnum.PD_Not
except Exception as e:
print(f"派单处理错误: {e}")
self.state.pd_status=PD_StatusEnum.PD_Error
_start_time=None
_isFinish=False
else:
print('已开启手动派单,或未设置派单模式')
print('已开启手动派单,或未设置派单模式')
time.sleep(5)
def send_pd_data(self):
"""
发送PD数据到OPC队列
:param _pd_status: PD状态
"""
# 构建PD数据
# print("send_pd_data1")
_cur_mould=self.state.current_mould
if _cur_mould is not None:
# print("send_pd_data2")
if _cur_mould.MouldCode:
_pdrecords = self.pd_record_bll.get_last_pds(_cur_mould.MouldCode,3)
if _pdrecords:
_pdrecord=_pdrecords[0]
_pdrecords = self.pd_record_bll.get_last_pds(_cur_mould.MouldCode,2)
if _pdrecords and len(_pdrecords)>1:
_pdrecord=_pdrecords[1]
# print(f"send_pd_data3,{_pdrecord.MouldCode}")
_block_number=CoreUtils.get_number_by_mould_code(_pdrecord.MouldCode)
_size=CoreUtils.get_size_by_mould_code(_pdrecord.MouldCode)
self.state.pd_mould_code=_pdrecord.MouldCode
_pd_flag=1
if not _pdrecord.TaskID:
#查找最近的未浇筑块
print(f"未扫描,使用最近的未浇筑块,{_size}")
_nearrecord=self.pd_record_bll.get_near_pd_scan(_size)
if _nearrecord is not None:
_pd_flag=2
_pdrecord.ArtifactActionID=0
_pdrecord.TaskID=_nearrecord.TaskID
_pdrecord.ProduceMixID=_nearrecord.ProduceMixID
_pdrecord.PlannedVolume=_nearrecord.PlannedVolume
print(f"未扫描,使用最近的未浇筑块,{_size},派单:{_pdrecord.TaskID},配比号:{_pdrecord.ProduceMixID}")
# print(f"send_pd_data5,{_pdrecord.TaskID}")
if _pdrecord.TaskID:
if _pdrecord.Status==1:
tasks, artifact_list, send_list, half_volume = self.pd_task_service.process_not_pour_info(_pdrecords)
# print(f"send_pd_data6,{_pdrecord.TaskID}")
# tasks, artifact_list, send_list, half_volume = self.pd_task_service.process_not_pour_info(_pdrecords)
# if tasks and len(tasks)>0:
# task=tasks[0]
# # task['MouldCode']=_pdrecord.MouldCode
@ -433,22 +483,39 @@ class FeedingControlSystem:
# }
# print(f"{self.state.current_mould.MouldCode}派单:{_pdrecord.MouldCode},数据:{_opc_pd}")
# self.state.opc_queue.put_nowait(('pd_data', json.dumps(_opc_pd)))
if _pdrecord.BlockNumber=='F':
_fact_volumn=0
if _pdrecord.BetonVolumeUpd>0.8:
#当前已经修改过方量
_fact_volumn=_pdrecord.BetonVolumeUpd
print(f"当前已经修改过方量,方量:{_fact_volumn}")
if _block_number=='F' and _fact_volumn<0.8:
print(f'{_pdrecord.MouldCode} F块不发送派单数据')
self.pd_record_bll.start_pd(_pdrecord.MouldCode,0)
self.pd_record_bll.start_pd(PD_StatusEnum.PD_Send_Finish.value,_pdrecord.MouldCode,0)
else:
_fact_volumn=self.get_fact_volumn(_pdrecord.MouldCode,_pdrecord.BlockNumber)
if _fact_volumn>0:
if _fact_volumn<0.8:
# _fact_volumn=0
if _size=='6600*1500':
_fact_volumn=PdVolume.get_fact_volume(self.transmitter_controller,_pdrecord.MouldCode)
elif _size=='6600*1200':
_fact_volumn=PdVolume.get_fact_volume_12(self.transmitter_controller,_pdrecord.MouldCode)
if _fact_volumn is not None and _fact_volumn>0:
#更新派单表
_ret_flag=self.pd_record_bll.start_pd(_pdrecord.MouldCode,_fact_volumn)
# print(f"send_pd_data7,{_pdrecord.MouldCode},{_fact_volumn}")
_ret_flag=self.pd_record_bll.start_pd(PD_StatusEnum.PD_Send_Finish.value,_pdrecord.MouldCode,_fact_volumn)
_cur_code=_pdrecords[0].MouldCode
if _ret_flag:
_opc_pd={
"ID":_pdrecord.ID,
"ArtifactActionID":_pdrecord.ArtifactActionID,
"MouldCodePD":_pdrecord.MouldCode,
"MouldCode":_cur_code,
"TaskID":_pdrecord.TaskID,
"ProduceMixID":_pdrecord.ProduceMixID,
"BetonVolume":_fact_volumn,
"PlannedVolume":_pdrecord.PlannedVolume
"BetonVolume":round(_fact_volumn,1),
"PlannedVolume":round(_pdrecord.PlannedVolume,1),
"Flag":_pd_flag,
"Msg":"已扫码" if _pd_flag==1 else "未扫码",
"Time":time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
}
print(f"{self.state.current_mould.MouldCode}派单:{_pdrecord.MouldCode}-{_pdrecord.BlockNumber},数据:{_opc_pd}")
self.state.opc_queue.put_nowait(('pd_data', json.dumps(_opc_pd)))
@ -456,66 +523,19 @@ class FeedingControlSystem:
return True
else:
print(f'{_pdrecord.MouldCode} 未派单,当前状态为:{_pdrecord.Status}')
return False
return True
else:
print(f'{_pdrecord.MouldCode} 未获取到数据-(等待扫码)')
return False
else:
print(f'接口数据为空')
return False
else:
print(f'当前浇筑模具为空')
return False
else:
return None
return False
def get_fact_volumn(self,mould_code:str,block_number:str='') -> float:
"""获取实际派单发量"""
# _now_volume=0
_pd_volume=0
_init_lower_weight=100#self.transmitter_controller.read_data(2)
if _init_lower_weight is None:
print(f'获取重量异常,上料斗传感器错误')
print(f'获取重量异常,上料斗传感器错误')
return None
print(f'get_fact_volumn当前重量{_init_lower_weight}')
_per_volume=2480
_left_volume=_init_lower_weight/_per_volume
if not block_number and '-' in mould_code:
block_number = mould_code.split('-')[0][-2:]
if block_number=='B1':
_left_volume=_left_volume-0.54
if _left_volume>0:
_pd_volume=1.9-_left_volume
_pd_volume=math.ceil(_pd_volume*10)/10
else:
_pd_volume=1.9
elif block_number in ['B2','B3']:
_pd_volume=1.9
elif block_number=='L1':
#浇B3
_pd_volume=2
self.prev_pd_volume=2
#调整
elif block_number=='L2':
#2.4方大约L2和F的量
_pd_volume=2.4
# if _weight>1300:
#留0.15 math.floor(_now_volume*10)/10 保留一位小数,丢掉其他的
if self.prev_pd_volume>0:
_pd_volume=_pd_volume-(_left_volume+self.prev_pd_volume-1.86)
else:
#不知道上一块叫的多少
_pd_volume=_pd_volume-(_left_volume+2-1.86)
_pd_volume=math.ceil(_pd_volume*10)/10+0.1
if _pd_volume>2.1:
_pd_volume=2.1
elif _pd_volume<0.8:
_pd_volume=0.8
return _pd_volume
def start_led(self):
"""启动LED流程"""
self.led_thread = threading.Thread(
@ -540,33 +560,62 @@ class FeedingControlSystem:
#发送到LED屏
time.sleep(app_set_config.led_interval)
time.sleep(2)
def on_opcua_notify(self,var_name,val):
"""OPC UA通知回调"""
if var_name=='pd_set_mode':
self.state.pd_set_mode=val
elif var_name=='pd_set_volume' and val:
_notify=json.loads(val)
_ret=self.pd_record_bll.update_PD_record_byid(_notify['ID'],{'FBetonVolume':_notify['Volume']})
if _ret:
#刷新派单表
self.state.opc_queue.put_nowait(('sys_pd_refresh',1))
# self.state._db_pd_set_volume=val
elif var_name=='pd_notify' and val:
# self.state._db_pd_notify=val
_notify=json.loads(val)
if _notify['ID']:
if _notify['Flag']==3:
#生产完毕
_ret=self.pd_record_bll.update_PD_record_byid(_notify['ID'],{'GStatus':3,'Status':5})
# if _ret:
#发送命令
# if self.state._upper_door_position==Upper_Door_Position.JBL:
# self.relay_controller.control_upper_to_zd()
try:
if var_name=='pd_set_mode':
self.state.pd_set_mode=val
elif var_name=='pd_set_volume' and val:
if self.state.pd_status!=PD_StatusEnum.PD_Ready:
_notify=json.loads(val)
_ret=self.pd_record_bll.update_PD_record_byid(_notify['ID'],{'BetonVolumeUpd':_notify['Volume']})
if _ret:
#刷新派单表
try:
self.state.opc_queue.put_nowait(('sys_pd_refresh',1))
except queue.Full:
pass
else:
self.pd_record_bll.update_PD_record_byid(_notify['ID'],{'GStatus':_notify['Flag']})
print(f'on_opcua_notify收到,var_name:{var_name},val:{val}')
print('当前状态为派单中,不能修改方量')
print('当前状态为派单中,不能修改方量')
# self.state._db_pd_set_volume=val
elif (var_name=='pd_notify_finish' or var_name=='pd_notify') and val:
# self.state._db_pd_notify=val
_notify=json.loads(val)
if 'ID' in _notify and 'Time' in _notify and _notify['ID'] and _notify['Time']:
if _notify['Flag']==5:
#搅拌楼下料完毕
_ret=self.pd_record_bll.update_pd_notify(_notify['ID'],{'GStatus':5,'Status':5,'FBetonVolume':_notify['BetonVolume'],'ErpID':_notify['ErpID'],'EndTime':time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
if _ret:
_time=datetime.strptime(_notify['Time'], '%Y-%m-%d %H:%M:%S')
if _time+timedelta(seconds=10)>=datetime.now():
# 发送命令
# from service.jbl_service import app_jbl_service
# _is_jb_finished=app_jbl_service.is_finish_jb()
if self.state._upper_door_position==Upper_Door_Position.JBL:
print("发送命令:搅拌楼--->振捣室")
print("发送命令:搅拌楼--->振捣室")
time.sleep(3)
self.relay_controller.control_upper_to_zd()
else:
print("搅拌楼下料未完成,或者料斗未在搅拌楼")
print("搅拌楼下料未完成,或者料斗未在搅拌楼")
else:
print("pd_notify:时间已过期")
print("pd_notify:时间已过期")
else:
print("pd_notify:更新失败")
print("pd_notify:更新失败")
else:
self.pd_record_bll.update_pd_notify(_notify['ID'],{'GStatus':_notify['Flag'],'ErpID':_notify['ErpID']})
else:
print(f'pd_notify:ID数据为空或Time数据为空')
print(f'pd_notify:ID数据为空或Time数据为空')
print(f'on_opcua_notify收到,var_name:{var_name},val:{val}')
except Exception as e:
print(f'on_opcua_notify处理异常,var_name:{var_name},val:{val},e:{e}')
def start_freq_thread(self):
"""启动频率上传线程"""
@ -588,7 +637,8 @@ class FeedingControlSystem:
_id=_cur_mould.ArtifactActionID
_mcode=_cur_mould.MouldCode
# freq=self.inverter_controller.read_frequency()
freq=self.state._mould_frequency
# freq=self.state._mould_frequency
freq=0
if freq>0:
self.freq_record_bll.insert_freq_record(FreqRecordModel(ArtifactID=_code,ArtifactActionID=_id,MouldCode=_mcode,Freq=freq))
else: