using Aucma.Scada.Model.domain;
using HighWayIot.Config;
using HighWayIot.Log4net;
using HighWayIot.Plc;
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;
#endregion
#region 私有变量
///
/// 字典存放PLC连接
///
private Dictionary _plcDictionary = new Dictionary();
///
/// 泡后任务编号,PLC反馈后进行赋值
///
private string foamRearTaskCode = string.Empty;
///
/// 已下传的任务信息
///
private List foamRearTaskInfos = new List();
#endregion
#region 委托事件
///
/// 出库完成
///
///
///
public delegate void OutStoreFinsih(string storeCode, string taskCode);
public event OutStoreFinsih OutStoreFinsihEvent;
///
/// PLC应答
///
///
///
public delegate void OutStoreAnswer(string storeCode, string taskCode);
public event OutStoreAnswer OutStoreAnswerEvent;
#endregion
private OutStoreTaskHandle()
{
_plcDictionary = _pool.GetAll();
RealReadShellFinish();
}
#region 泡后出库任务下发处理
///
/// 泡后出库任务下发
///
///
public bool SendFoamTask_OutStore(RealTaskInfo taskInfo)
{
bool result = false;
try
{
IPlc _plc = _plcDictionary[taskInfo.storeCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_foam_spaceCode, taskInfo.spaceCode);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_foam_amount, taskInfo.planAmount);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_foam_answer, 1);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_foam_task, taskInfo.taskCode);
//写入完成后读取应答字进行复位
ReadShellAnswer_OutStore(taskInfo);
result = true;
}
else
{
logHelper.Info($"仓库{taskInfo.storeCode};PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("泡后出库任务下发异常", ex);
}
return result;
}
///
/// 读取泡后出库应答
///
private void ReadShellAnswer_OutStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.foamStoreCode];
try
{
Task.Run(() =>
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC应答字为2时,上位机清空写入的出库内容
if (_plc.readInt32ByAddress(plcConfig.out_foam_answer) == 2)
{
//写入货道号
_plc.writeStringByAddress(plcConfig.out_foam_spaceCode, string.Empty);
//写入出库数量
_plc.writeInt32ByAddress(plcConfig.out_foam_amount, 0);
//写入应答字
_plc.writeInt32ByAddress(plcConfig.out_foam_answer, 0);
//写入任务号
_plc.writeStringByAddress(plcConfig.out_foam_task, string.Empty);
isFlag = false;
//ReadShellFinish_OutStore(taskInfo.taskCode);
OutStoreAnswerEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
foamRearTaskInfos.Add(taskInfo);
}
Thread.Sleep(1000);
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.foamStoreCode};PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取泡后出库应答字异常", ex);
}
}
}
///
/// 读取泡后出库完成
///
private void ReadShellFinish_OutStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.foamStoreCode];
foamRearTaskCode = taskInfo.taskCode;
try
{
Task.Run(() =>
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC出库任务完成
if (_plc.readInt32ByAddress(plcConfig.out_foam_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.out_foam_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
isFlag = false;
}
Thread.Sleep(1000);
} while (isFlag);
}
else
{
logHelper.Info($"仓库{appConfig.foamStoreCode};PLC未连接");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取泡后出库出库完成异常", ex);
}
}
}
#endregion
#region 出库完成
///
/// 实时读取箱壳出库完成
///
private void RealReadShellFinish()
{
Task.Run(() =>
{
while (true)
{
var info = foamRearTaskInfos.Where(x => x.taskStatus != 3).ToList();
for (int i = 0; i < info.Count; i++)
{
var item = info[i];
ReadShellFinish_OutStore(item);
Console.WriteLine($"泡后库任务:{item.taskCode};物料:{item.materialCode};出库完成");
item.taskStatus = 3;
foamRearTaskInfos.Remove(item);
}
Thread.Sleep(1000);
};
});
}
#endregion
///
/// 通过PLC获取货道信息
///
///
///
public BaseSpaceInfo ReadSpaceInfoByPlc(BaseSpaceInfo spaceInfo)
{
var spaceAddress = spaceConfig.GetSpaceAddress(spaceInfo.storeCode, spaceInfo.spaceCode);
IPlc _plc = _plcDictionary[spaceInfo.storeCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
spaceInfo.spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore);
spaceInfo.onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute);
spaceInfo.spaceStatus = _plc.readInt32ByAddress(spaceAddress.spaceStatus);
}
}
return spaceInfo;
}
///
/// 测试方法,联调时不用
///
///
///
///
public void WritePlc(string storeCode, string spaceCode)
{
var spaceAddress = spaceConfig.GetSpaceAddress(storeCode, spaceCode);
IPlc _plc = _plcDictionary[storeCode];
if (_plc != null)
{
if (_plc.IsConnected)
{
var spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore);
//var onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute);
_plc.writeInt32ByAddress(spaceAddress.onStore, spaceStock - 1);
}
}
}
}
}