Files
6098/Cowain.Bake.Main/Station/TaskStation.cs

583 lines
24 KiB
C#
Raw Normal View History

using Cowain.Bake.BLL;
using Cowain.Bake.Common;
using Cowain.Bake.Common.Core;
using Cowain.Bake.Common.Enums;
using Cowain.Bake.Common.Interface;
using Cowain.Bake.Common.Models;
using Cowain.Bake.Communication.Interface;
using Cowain.Bake.Communication.MOM;
using Cowain.Bake.Main.ViewModels;
using Cowain.Bake.Model;
using Cowain.Bake.Model.Entity;
using Cowain.Bake.Model.Models;
using HslCommunication;
using Newtonsoft.Json;
using Opc.Ua;
using Prism.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Unity;
using JSON = Newtonsoft.Json.JsonConvert;
namespace Cowain.Bake.Main.Station
{
public class TaskStation: IServerManager
{
public string Name { get; set; }
static Int16 _lastStepId = 0;
public IUnityContainer _unityContainer { get; set; }
readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly TDeviceConfig config;
IPLCDevice agv = null;
readonly List<CavityInfoModel> _stationCavity;
public List<TStation> _station = null;
public AutoResetEvent _newTaskEvent = new AutoResetEvent(true);
public TaskStation(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
_station = _unityContainer.Resolve<MemoryDataProvider>().AllStation;
config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.AGV)[0];
_stationCavity = _unityContainer.Resolve<CavityInfoService>().GetAllStation();
Start();
StartNewTask();
}
public void Start()
{
var task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == task)
{
_lastStepId = (int)ETaskStep.None;
}
else
{
_lastStepId = (short)task.StepId;
}
agv = _unityContainer.Resolve<IPLCDevice>(config.Name);
//TTaskRecord task = await GenerateTask(); #测试
}
public async Task DealTask(DataValue data, Variable node)
{
bool dealResult = false; //进去这里,看会不会触发别的
LogHelper.Instance.Info($"开始任务--------------信号,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId},{node.VarDesc}");
do
{
// 启动任务并等待结果
//dealResult = await Task.Run(() => ThreadDealTask(data, node));
dealResult = ThreadDealTask(data, node);
if (!dealResult)
{
LogHelper.Instance.Error("-------------------------处理任务异常!");
await Task.Delay(2 * 1000);
}
} while(!dealResult);
LogHelper.Instance.Info($"完成任务--------------信号,线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId}");
}
void StartNewTask()
{
Task.Run( () =>
{
agv = _unityContainer.Resolve<IPLCDevice>(config.Name);
while (!cts.Token.IsCancellationRequested)
{
if (Global.AppExit)
{
return;
}
DealNewTask();
}
});
}
public void DealNewTask()
{
_newTaskEvent.WaitOne(10*1000);
Variable nodeTemp = (from secondaryList in agv.Storages //不能做触发,因为没有任务。要地直运行里面,来检测是否有任务
from item in secondaryList.VariableList
where item.ParamName == EAgvPLC.RetCount.ToString()
select item).FirstOrDefault();
Variable node = BasicFramework.DeepCopy<Variable>(nodeTemp);
if (null == node || !node.Quality || null == node.CurValue) //无值,退出
{
return;
}
TTaskRecord oldTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
//1.有任务 + 自动 ,退出
//2.有任务 + 手动 + 任务执行中: 退出
if (null != oldTask)
{
if (oldTask.Status != (int)ETaskStatus.UnExecute)
{
return;
}
}
TaskEntity task = GetTask();
if (null == task)
{
return;
}
CommonCoreHelper.Instance.BlockTask.Add(task); //更新界面(任务未执行)
SetCount(node);
_lastStepId = (int)ETaskStep.MoveFrom; //StepId手动第一次为1自动第一次为10
if (!SendNextStep(task, node.Json, false)) //发送第一步
{
return; //发送失败
}
//一条任务第一次发任务时
if (!_unityContainer.Resolve<TaskRecordService>().ModifyTaskStatus(ETaskStatus.Executing)) //更新任务状态为执行中
{
LogHelper.Instance.Fatal("更改任务状态失败");
}
CommonCoreHelper.Instance.BlockTask.Add(task); //任务没有执行完。所以不需要更新界面
}
void SetCount(Variable node)
{
var model = agv.Read<Int16>(node.Address + node.VarName);
if (!model.IsSuccess
|| 1 != model.Content)
{
SettingProvider.Instance.CountCmd = 0; //每条任务从1开始
}
else
{
SettingProvider.Instance.CountCmd = 100;
}
}
private TaskEntity GetTask()
{
if (SettingProvider.Instance.DispMode == EDispatchMode.Auto)
{
var oldTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (oldTask != null)
{
return GetStationManualTask(oldTask);
}
//看到过有任务还生成
return _unityContainer.Resolve<TaskRecordService>().GetTask(); //获得调度任务,并插入一条任务进任务记录表
}
else //手动从数据库获取
{
TTaskRecord manualTask = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == manualTask)
{
return null; //没有任务(手动任务),就退出
}
return GetStationManualTask(manualTask);
}
}
/*
//1.执行中:机器人正在执行任务中, 如果上位机重启,会触发,
//2.无务任或任务执行完成:计命令计算为0或最后一步执行完成更新状态(无任务不需要),生成任务,下发下一步指令
//3.一步任务完成: 更新状态, 下发下一步指令
*/
public bool ThreadDealTask(DataValue data, Variable node)
{
string msg = "";
LogHelper.Instance.Error("开始接收调度机器人信息!");
Int16 countValue ;
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.TrigJson);
if (null == agv || !agv.IsConnect)
{
msg = "连接机器人的PLC断开!";
LogHelper.Instance.Error(msg);
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
return false;
}
try
{
var stepValue = agv.Read<Int16>((string)d.ReadCmd); //可以改成直接读PLC [命令地址]
var resultValue = agv.Read<int>((string)d.ReadResult); //这是直接读PLC [执行命令结果]
if (!stepValue.IsSuccess || !resultValue.IsSuccess)
{
LogHelper.Instance.Error($"PLC反馈任务时读取失败!,失败原因:{stepValue.Message},{stepValue.Message}");
return false;
}
if (data.WrappedValue.TypeInfo.BuiltInType == Opc.Ua.BuiltInType.Int16)
{
countValue = (Int16)data.WrappedValue.Value;
LogHelper.Instance.Debug($"接收任务信息:计数:{countValue},命令步:{stepValue.Content},结果:{resultValue.Content},当前命令步:{_lastStepId},当前计数:{SettingProvider.Instance.CountCmd}");
}
else
{
LogHelper.Instance.Warn($"没有找到这个数据类型,节点名为{node.VarDesc}", true);
return false;
}
if (!EnumHelper.IsDefined<ETaskStep>(stepValue.Content)) //不在范围内
{
LogHelper.Instance.Warn($"获取PLC的命令有问题值:{countValue}", true);
return false;
}
_unityContainer.Resolve<EquipmentMonitorViewModel>().SetAgvImage(resultValue.Content);
if (resultValue.Content == (int)EAgvMoveStatus.Error) // -1:表示没有完成
{
//if (countValue > SettingProvider.Instance.CountCmd) 此时上位机是1PLC是3。 如果执行下面后续PLC执行1就不会任务了
//{
// SettingProvider.Instance.CountCmd = countValue;
// LogHelper.Instance.Debug($"更改当前计数:{SettingProvider.Instance.CountCmd}");
//}
return false;
}
//1.机器人正在执行任务中, 如果上位机重启,此时又有任务
//如果:countValue=3000,Instance.CountCmd=1,时,到下面退出,也不影响。
if (countValue == SettingProvider.Instance.CountCmd - 1) //(重启上位机,任务在执行中)
{
LogHelper.Instance.Warn($"重启上位机,此时又有任务在执行中!");
return true;
}
if (_lastStepId == (int)ETaskStep.None)
{
LogHelper.Instance.Warn($"重启上位机, 没有任务在执行!");
return true;
}
//表示执行完成了,执行下一个; 或无任务
if (
countValue >= SettingProvider.Instance.CountCmd
&& stepValue.Content == _lastStepId
)
{
SettingProvider.Instance.CountCmd = countValue; //PLC跳步
TTaskRecord task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == task) //无任务:不需要做什么,有任务:更新状态
{
LogHelper.Instance.Fatal($"此时应该数据库中要有未执行的任务,计数:{countValue},命令:{stepValue}");
return true;
}
TaskEntity detailTask = GetStationManualTask(task); //通过任务,获取工站信息
detailTask.StepId = (sbyte)stepValue.Content;
if (!DealFinishCmd(detailTask, _lastStepId))
{
return false;
}
if (_lastStepId == (int)ETaskStep.Place //表示当前是一个任务的最后一条命令
/* || 0 == countCmd*/) //PLC重启为0一条完整的任务完成了,将获取最后一条指令
{
detailTask.StepId = (int)ETaskStep.Finish;
CommonCoreHelper.Instance.BlockTask.Add(detailTask); //机器人界面显示
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
_newTaskEvent.Set();
return true; //完成了一条完整的任务,另外一个方法生成新的任务
}
//发送下一步命令
if (!SendNextStep(detailTask, node.Json))
{
return false;
}
CommonCoreHelper.Instance.BlockTask.Add(detailTask); //机器人界面显示
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
LogHelper.Instance.Error("处理完接收调度机器人信息!");
}
else
{
LogHelper.Instance.Error($"接收到的信息PLC的调试任务异常,plc cmd:{stepValue},plc 计数:{countValue};\r" +
$"上位机 cmd:{_lastStepId},上位机 计数:{SettingProvider.Instance.CountCmd},正常不会执行到这里!");
}
}
catch(Exception ex)
{
LogHelper.Instance.GetCurrentClassError($"{ex.Message}-{ex.StackTrace}");
return false;
}
return true;
}
public bool SendNextStep(TaskEntity detailTask, string json, bool next = true)
{
LogHelper.Instance.Info($"发送步骤:{detailTask.StepId},命令计数:{SettingProvider.Instance.CountCmd}");
detailTask = SetNextStep(detailTask, next); //会设置CountCmd StepId
if (!SendTask(detailTask, json)) //发送任务
{
LogHelper.Instance.Error($"发送任务信息失败,{JsonConvert.SerializeObject(detailTask)}!");
return false;
}
_lastStepId = detailTask.StepId;
SettingProvider.Instance.CountCmd = detailTask.CountCmd;
LogHelper.Instance.Debug($"计数改变:{SettingProvider.Instance.CountCmd}");
return StartStep(detailTask);
}
public bool ManualTaskCmd(TTaskRecord task, short stepId) //界面上指定再发送一次时,
{
Variable nodeCountCmd = (from secondaryList in agv.Storages //不能做触发,因为没有任务。要地直运行里面,来检测是否有任务
from item in secondaryList.VariableList
where item.ParamName == EAgvPLC.RetCount.ToString()
select item).FirstOrDefault();
_lastStepId = (short)stepId;
TaskEntity detailTask = GetStationManualTask(task); //通过任务,获取工站信息
return SendNextStep(detailTask, nodeCountCmd.Json, false);
}
bool DealFinishCmd(TaskEntity detailTask, Int16 cmdValue)
{
if (0 >= _unityContainer.Resolve<TaskStepService>().UpdateEndTime(detailTask.Id, (ETaskStep)cmdValue))
{
LogHelper.Instance.Error($"修改命令结束时间失败任务ID:{detailTask.Id},命令:{_lastStepId}");
}
return UpdateFinishStep(detailTask);
}
bool StartStep(TaskEntity detailTask)
{
if (0 >= _unityContainer.Resolve<TaskStepService>().UpdateStartTime((int)detailTask.Id, detailTask.CountCmd, detailTask.StepId))
{
LogHelper.Instance.Error($"修改命令开始时间失败任务ID:{detailTask.Id},命令:{detailTask.StepId},命令计算:{detailTask.CountCmd}");
return false;
}
return true;
}
bool UpdateFinishStep(TaskEntity stationTask)
{
int result = 0;
switch (stationTask.StepId)
{
case (int)ETaskStep.MoveFrom:
//修改机器人的位置,给界面发信号
result =_unityContainer.Resolve<CavityInfoService>().SetRobotPos(stationTask.FromStationNumber);
break;
case (int)ETaskStep.Pick:
UpdateOutStoveTime(stationTask); //更改出炉时间
result = _unityContainer.Resolve<TaskRecordService>().BindPalletToRobot(); //将夹具绑定在机器人上
break;
case (int)ETaskStep.MoveTo:
result = _unityContainer.Resolve<CavityInfoService>().SetRobotPos(stationTask.ToStationNumber);
break;
case (int)ETaskStep.Place:
result = _unityContainer.Resolve<TaskRecordService>().UpdateTask(); //1.加锁解锁2.绑定解绑夹具3.更新机器人的位置,4.更新任务状态完成,
SendIntoStove(stationTask); //如果是满载夹具,要将调用烘烤进站接口
_unityContainer.Resolve<TaskRecordService>().UpdateFinishStepId(stationTask.Id); //修改任务步为完成
break;
default:
break;
}
if (result <= 0)
{
LogHelper.Instance.Error($"接到任务完成,但处理异常:{result},cmd:{stationTask.StepId}");
//return false;
}
return true;
}
void UpdateOutStoveTime(TaskEntity stationTask)
{
var cavityStove = _stationCavity.Where(x => x.Id == stationTask.Source && x.Type == (int)EStationType.Stove).FirstOrDefault();
if (null != cavityStove) //更改出炉时间
{
_unityContainer.Resolve<PalletInfoService>().UpdateOutStoveTime(cavityStove.PalletId);
}
}
void SendIntoStove(TaskEntity stationTask)
{
//if (!_unityContainer.Resolve<TaskTypeService>().IsPullInBaker(stationTask.TaskTypeId))
if (1 != stationTask.TaskTypeId)// 1: 上料满夹具->烤箱
{
return ;
}
var cavityInfo = _stationCavity.Where(x=>x.Id == stationTask.Target).FirstOrDefault();
var palletInfo = _unityContainer.Resolve<PalletInfoService>().GetPalletInfo(stationTask.PalletId);
List<string> batteryCodes = _unityContainer.Resolve<BatteryInfoService>().GetBatteryInfos(palletInfo.VirtualId).Select(x=>x.BatteryCode).ToList();
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable
&& 0 != batteryCodes.Count)
{
_unityContainer.Resolve<MESProcess>().MESBakingInput(cavityInfo.CavityName, palletInfo.PalletCode, batteryCodes, _unityContainer.Resolve<BasicInfoViewModel>().CurrentOperation);
}
}
public TaskEntity GetStationManualTask(TTaskRecord task)
{
TaskEntity taskEn = JSON.DeserializeObject<TaskEntity>(JSON.SerializeObject(task));
var sourceDetail = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(task.Source);
var targetDetail = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(task.Target);
var stationTask = MakeManualTask(taskEn, sourceDetail, targetDetail);
//stationTask.Copy(task, stationTask);
return stationTask;
}
TaskEntity SetNextStep(TaskEntity task, bool isNext = true)
{
sbyte nextStepId = (sbyte)_lastStepId;
if (isNext)
{
nextStepId = (sbyte)_unityContainer.Resolve<RgvActionService>().GetNext(_lastStepId); //下一步
}
task.CountCmd = SettingProvider.Instance.CountCmd + 1; //下一个计数
task.StepId = (sbyte)nextStepId;
return task;
}
public TaskEntity MakeManualTask(TaskEntity taskEn, TCavityInfo src, TCavityInfo desc)
{
taskEn.FromStationNumber = src.StationNumber;
taskEn.FromRow = src.Layer;
taskEn.FromColumn = src.Column;
taskEn.ToStationNumber = desc.StationNumber;
taskEn.ToRow = desc.Layer;
taskEn.ToColumn = desc.Column;
return taskEn;
}
public bool SendTask(TaskEntity task, string json)
{
LogHelper.Instance.Info($"发送任务开始");
List<AddrValue> makeAddrValues = new List<AddrValue>();
dynamic d = JsonConvert.DeserializeObject<dynamic>(json);
string fromStation = d.FromStation;
string fromLayer = d.FromRow;
string fromColumn = d.FromColumn;
string toStation = d.ToStation;
string toLayer = d.ToRow;
string toColumn = d.ToColumn;
string cmd = d.Cmd;
string countAddr = d.Count;
makeAddrValues.Add(new AddrValue()
{
Addr = fromStation,
Value = (int)task.FromStationNumber,
});
var from = _station.Where(p => p.Id == (int)task.FromStationNumber).FirstOrDefault();
if (from.Type == (int)EStationType.Loading
|| from.Type == (int)EStationType.UnLoading)
{
makeAddrValues.Add(new AddrValue()
{
Addr = fromLayer,
Value = (int)task.FromRow,
});
makeAddrValues.Add(new AddrValue()
{
Addr = fromColumn,
Value = (int)task.FromColumn,
});
}
else
{
makeAddrValues.Add(new AddrValue()
{
Addr = fromLayer,
Value = (int)task.FromColumn,
});
makeAddrValues.Add(new AddrValue()
{
Addr = fromColumn,
Value = (int)task.FromRow,
});
}
makeAddrValues.Add(new AddrValue()
{
Addr = toStation,
Value = (int)task.ToStationNumber,
});
var to = _station.Where(p => p.Id == (int)task.ToStationNumber).FirstOrDefault();
if (to.Type == (int)EStationType.Loading
|| to.Type == (int)EStationType.UnLoading)
{
makeAddrValues.Add(new AddrValue()
{
Addr = toLayer,
Value = (int)task.ToRow,
});
makeAddrValues.Add(new AddrValue()
{
Addr = toColumn,
Value = (int)task.ToColumn,
});
}
else
{
makeAddrValues.Add(new AddrValue()
{
Addr = toLayer,
Value = (int)task.ToColumn,
});
makeAddrValues.Add(new AddrValue()
{
Addr = toColumn,
Value = (int)task.ToRow,
});
}
makeAddrValues.Add(new AddrValue()
{
Addr = cmd,
Value = (Int16)task.StepId,
});
//makeAddrValues.Add(new AddrValue()
//{
// Addr = countAddr,
// Value = (Int16)task.CountCmd, //必须最后一个写
//});
OperateResult result = agv.Writes(makeAddrValues.Select(x => x.Addr).ToArray(), makeAddrValues.Select(x => x.Value).ToArray());
if (!result.IsSuccess)
{
LogHelper.Instance.Fatal($"写任务步骤失败:{JsonConvert.SerializeObject(makeAddrValues)},{JsonConvert.SerializeObject(makeAddrValues)}");
}
result = agv.Write<Int16>(countAddr, (Int16)task.CountCmd);
if (!result.IsSuccess)
{
LogHelper.Instance.Fatal($"写任务计数失败:{JsonConvert.SerializeObject(makeAddrValues)},{JsonConvert.SerializeObject(makeAddrValues)}");
}
LogHelper.Instance.Debug($"发送任务:{JsonConvert.SerializeObject(makeAddrValues)}");
LogHelper.Instance.Debug($"发送计数:{countAddr}:{(Int16)task.CountCmd}");
//_unityContainer.Resolve<LogService>().AddLog("TaskStation:SendTask:发送任务结束", E_LogType.Info.ToString());
return result.IsSuccess;
}
public void Stop()
{
// 在需要取消任务的时候,调用以下代码:
cts.Cancel();
}
}
}