using Aucma.Scada.Model.domain;
using HighWayIot.Config;
using HighWayIot.Log4net;
using HighWayIot.Plc;
using HighWayIot.Repository.service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Aucma.Scada.Business
{
///
/// 出库任务处理
///
internal sealed class OutStoreTaskHandle
{
#region 单例实现
private static readonly Lazy lazy = new Lazy(() => new OutStoreTaskHandle());
public static OutStoreTaskHandle Instance
{
get
{
return lazy.Value;
}
}
#endregion
#region 对象引用
private LogHelper logHelper = LogHelper.Instance;
private AppConfig appConfig = AppConfig.Instance;
private PlcConfig plcConfig = PlcConfig.Instance;
private PlcPool _pool = PlcPool.Instance;
private PlcSpaceConfig spaceConfig = PlcSpaceConfig.Instance;
private RegisterServices registerServices = RegisterServices.Instance;
private IRealTaskInfoService _taskInfoService;
private ICodeBindingRecordServices _codeBindingRecordServices;
#endregion
#region 私有变量
///
/// 字典存放PLC连接
///
private Dictionary _plcDictionary = new Dictionary();
///
/// 箱壳任务编号,PLC反馈后进行赋值
///
private string shellTaskCode = string.Empty;
///
/// 内胆任务编号,PLC反馈后进行赋值
///
private string linerTaskCode = string.Empty;
///
/// 已下传的任务信息
///
private List shellTaskInfos = new List();
private List linerTaskInfos = new List();
#endregion
#region 委托事件
///
/// 出库完成
///
///
///
public delegate void OutStoreFinsih(string storeCode, string taskCode);
public event OutStoreFinsih OutStoreFinsihEvent;
///
/// 条码绑定以后更新mes计划
///
///
///
public delegate void UpdateMesPlanComplete(string taskCode);
public event UpdateMesPlanComplete UpdateMesPlanCompleteEvent;
///
/// PLC应答
///
///
///
public delegate void OutStoreAnswer(string storeCode, string taskCode);
public event OutStoreAnswer OutStoreAnswerEvent;
#endregion
private OutStoreTaskHandle()
{
try
{
_plcDictionary = _pool.GetAll();
_taskInfoService = registerServices.GetService();
_codeBindingRecordServices = registerServices.GetService();
RealReadShellFinish();
RealReadLinerFinish();
//RealBindMaterialCode();
}
catch (Exception ex)
{
Console.WriteLine($"OutStoreTaskHandle异常:{ex.Message}");
logHelper.Error("OutStoreTaskHandle异常", ex);
Console.ReadLine();
}
}
#region 箱壳出库任务下发处理
///
/// 箱壳出库任务下发
///
///
public int SendShellTask_OutStore(RealTaskInfo taskInfo)
{
int result = 0;
try
{
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
if (_plc != null)
{
if (_plc.readInt32ByAddress(plcConfig.out_shell_answer) == 1)
{
logHelper.Info("箱壳出库应答字为1,货道号:" + plcConfig.out_shell_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入货道号
_plc.writeInt32ByAddress(plcConfig.out_shell_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入出库数量
// _plc.writeInt32ByAddress(plcConfig.out_shell_amount, taskInfo.planAmount);
//写入完成后读取应答字进行复位
ReadShellAnswer_OutStore(taskInfo);
result = 1;
}
else
{
result = 2;
logHelper.Info("应答字为2,下发新任务plc未就绪");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("箱壳出库任务下发异常", ex);
}
return result;
}
///
/// 读取箱壳出库应答
///
private void ReadShellAnswer_OutStore(RealTaskInfo taskInfo)
{
bool isFlag = true;
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
try
{
if (_plc != null)
{
DateTime startTime = DateTime.Now;
do
{
//读取PLC应答字为2时,上位机清空写入的出库内容
if (_plc.readInt32ByAddress(plcConfig.out_shell_answer) == 2)
{
logHelper.Info("出库应答字为2,货道号:" + plcConfig.out_shell_spaceCode + ";复位写0");
//写入货道号
_plc.writeInt32ByAddress(plcConfig.out_shell_spaceCode, 0);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_shell_amount, 0);
isFlag = false;
OutStoreAnswerEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
}
Thread.Sleep(500);
// 检查是否超过15秒,如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 8)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取箱壳出库应答字异常", ex);
}
}
///
/// 读取箱壳出库完成
///
private void ReadShellFinish_OutStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
shellTaskCode = taskInfo.taskCode;
try
{
if (_plc != null)
{
DateTime startTime = DateTime.Now;
do
{
//读取PLC出库任务完成
if (_plc.readInt32ByAddress(plcConfig.out_shell_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.out_shell_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_shell_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
isFlag = false;
}
Thread.Sleep(500);
// 检查是否超过30秒,如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 20)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取箱壳出库出库完成异常", ex);
}
}
}
#endregion
#region 内胆出库任务处理
///
/// 内胆出库任务下发
///
///
public int SendLinerTask_OutStore(RealTaskInfo taskInfo)
{
int result = 0;
try
{
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
if (_plc != null)
{
if (_plc.readInt32ByAddress(plcConfig.out_liner_answer) == 1)
{
logHelper.Info("内胆出库应答字为1,货道号:" + plcConfig.out_shell_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入货道号
_plc.writeInt32ByAddress(plcConfig.out_liner_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_liner_amount, taskInfo.planAmount);
//写入完成后读取应答字进行复位
ReadLinerAnswer_OutStore(taskInfo);
result = 1;
}
else
{
result = 2;
logHelper.Info("内胆应答字为2,下发新任务plc未就绪");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("内胆出库任务下发异常", ex);
}
return result;
}
///
/// 读取内胆出库应答
///
private void ReadLinerAnswer_OutStore(RealTaskInfo taskInfo)
{
bool isFlag = true;
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
try
{
if (_plc != null)
{
DateTime startTime = DateTime.Now;
do
{
//读取PLC应答字为2时,上位机清空写入的出库内容
if (_plc.readInt32ByAddress(plcConfig.out_liner_answer) == 2)
{
logHelper.Info("出库应答字为2,货道号:" + plcConfig.out_liner_spaceCode + ";复位写0");
//写入货道号
_plc.writeInt32ByAddress(plcConfig.out_liner_spaceCode, 0);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_liner_amount, 0);
isFlag = false;
OutStoreAnswerEvent?.Invoke(appConfig.linerStoreCode, taskInfo.taskCode);
}
Thread.Sleep(500);
// 检查是否超过30秒,如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 8)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取内胆出库应答字异常", ex);
}
}
///
/// 读取内胆出库完成
///
private void ReadLinerFinish_OutStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
try
{
bool isFlag = true;
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
if (_plc != null)
{
DateTime startTime = DateTime.Now;
do
{
//读取PLC出库任务完成
if (_plc.readInt32ByAddress(plcConfig.out_liner_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.out_liner_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_liner_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.linerStoreCode, taskInfo.taskCode);
isFlag = false;
//linerTaskInfos.Remove(taskInfo);
}
Thread.Sleep(1000);
// 检查是否超过30秒,如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 20)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取内胆出库完成异常", ex);
}
}
}
#endregion
#region 出库完成
///
/// 实时读取箱壳出库完成
///
private void RealReadShellFinish()
{
Task.Run(() =>
{
while (true)
{
//var info = shellTaskInfos.Where(x => x.taskStatus != 3).ToList();
var info = GetTaskInfoByTaskStatus(appConfig.shellStoreCode);
if (info != null)
{
for (int i = 0; i < info.Count; i++)
{
var item = info[i];
ReadShellFinish_OutStore(item);
Console.WriteLine($"箱壳任务:{item.taskCode};物料:{item.materialCode};出库完成");
// item.taskStatus = 3;
// shellTaskInfos.Add(item);
}
}
Thread.Sleep(1000);
};
});
}
///
/// 实时读取内胆出库完成
///
private void RealReadLinerFinish()
{
Task.Run(() =>
{
while (true)
{
//var info = linerTaskInfos.Where(x => x.taskStatus != 3).ToList();
var info = GetTaskInfoByTaskStatus(appConfig.linerStoreCode);
if (info != null)
{
for (int i = 0; i < info.Count; i++)
{
var item = info[i];
ReadLinerFinish_OutStore(item);
Console.WriteLine($"内胆任务:{item.taskCode};物料:{item.materialCode};出库完成");
// item.taskStatus = 3;
// linerTaskInfos.Add(item);
}
}
Thread.Sleep(1000);
};
});
}
///
/// 实时绑定箱壳内胆
/// Delete By wenjy 2024-03-16 11:40:00 更改壳胆绑定逻辑,添加扫码器进行绑定
///
//private void RealBindMaterialCode()
//{
// Task.Run(() =>
// {
// while (true)
// {
// try
// {
// var shellTasks = GetTaskInfoByTaskStatus(appConfig.shellStoreCode, 3);
// var linerTasks = GetTaskInfoByTaskStatus(appConfig.linerStoreCode, 3);
// if (shellTasks == null || linerTasks == null) continue;
// RealTaskInfo shellTask = null;
// RealTaskInfo linerTask = null;
// if (shellTasks.Count > 0)
// {
// shellTask = shellTasks.First();
// }
// if (linerTasks.Count > 0)
// {
// linerTask = linerTasks.First();
// }
// if (shellTask != null && linerTask != null)
// {
// Console.WriteLine($"绑定箱壳:{shellTask.materialCode};内胆:{linerTask.materialCode};条码");
// _codeBindingRecordServices.BindingCode(shellTask.materialCode, linerTask.materialCode);
// 更新mes完成计划数
/// UpdateMesPlanCompleteEvent?.Invoke(shellTask.planCode);
// _taskInfoService.DeleteTaskInfoById(shellTask.objId);
// _taskInfoService.DeleteTaskInfoById(linerTask.objId);
// }
// Thread.Sleep(2000);
// }
// catch (Exception ex)
// {
// logHelper.Error(ex.Message.ToString());
// }
// }
// });
//}
#endregion
#region 私有方法
///
/// 根据任务状态获取执行中的任务
///
///
/// s
private List GetTaskInfoByTaskStatus(string storeCode, int taskStatus = 2)
{
List result = null;
try
{
result = _taskInfoService.GetTaskInfosByTaskStatus(new string[] { storeCode }, appConfig.outstoreTaskType, taskStatus);
}
catch (Exception ex)
{
logHelper.Error("根据任务状态获取执行中的任务异常", ex);
}
return result;
}
///
/// 通过PLC获取货道信息
///
///
///
public BaseSpaceInfo ReadSpaceInfoByPlc(BaseSpaceInfo spaceInfo)
{
var spaceAddress = spaceConfig.GetSpaceAddress(spaceInfo.storeCode, spaceInfo.spaceCode);
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[spaceInfo.storeCode];
if (_plc != null)
{
spaceInfo.spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore);
//spaceInfo.onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute);
// spaceInfo.spaceStatus = _plc.readInt32ByAddress(spaceAddress.spaceStatus);
}
return spaceInfo;
}
#endregion
}
}