using Aucma.Scada.Model.domain;
using HighWayIot.Common;
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
{
///
/// 入库任务处理
///
public sealed class InStoreTaskHandle
{
#region 单例实现
private static readonly Lazy lazy = new Lazy(() => new InStoreTaskHandle());
public static InStoreTaskHandle 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 JsonChange jsonChange = JsonChange.Instance;
///
/// 实时任务
///
private IRealTaskInfoService _taskInfoService;
private RegisterServices registerServices = RegisterServices.Instance;
///
/// 货道信息
///
private IBaseSpaceInfoService _spaceInfoService;
#endregion
#region 私有变量
private Dictionary _plcDictionary = new Dictionary();
private Dictionary shellKeyValuePairs = new Dictionary();
private Dictionary linerKeyValuePairs = 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 RefreshShellStock();
public event RefreshShellStock RefreshShellStockEvent;
///
/// 内胆实时库存刷新
///
///
public delegate void RefreshLinerStock();
public event RefreshLinerStock RefreshLinerStockEvent;
///
/// 入库完成
///
///
///
public delegate void InStoreFinsih(string storeCode, string taskCode);
public event InStoreFinsih InStoreFinsihEvent;
///
/// 入库应答,PLC收到下发的入库任务后进行应答
///
///
///
public delegate void InStoreAnswer(string storeCode, string taskCode);
public event InStoreAnswer InStoreAnswerEvent;
public delegate void BareBoardHandle(string storeCode, bool isFlag = true);
public event BareBoardHandle BareBoardHandleEvent;
///
/// 库容告警
///
public delegate void SpaceCapacityAlarm(string storeCode, string spaceName);
public event SpaceCapacityAlarm SpaceCapacityAlarmEvent;
#endregion
private InStoreTaskHandle()
{
_taskInfoService = registerServices.GetService();
_spaceInfoService = registerServices.GetService();
_plcDictionary = _pool.GetAll();
// RealReadFinish();
RealUpdateSpaceInfoByPlc();
ShellBareBoardHandle();
LinerBareBoardHandle();
}
///
/// 实时读取plc更新数据库货道数量及在途
///
private void RealUpdateSpaceInfoByPlc()
{
Task.Run(() =>
{
Thread.Sleep(2000);
while (true)
{
List spaceList = _spaceInfoService.GetSpaceInfosByStoreCode(appConfig.shellStoreCode, appConfig.linerStoreCode);
if (spaceList != null && spaceList.Count > 0)
{
List ShellAlarmSpaceName = new List();
List LinerAlarmSpaceName = new List();
foreach (BaseSpaceInfo spaceInfo in spaceList)
{
int Stock = spaceInfo.spaceStock;
int OnAmount = spaceInfo.onRouteAmount;
ReadSpaceInfoByPlc(spaceInfo);
// 更新库存
if (Stock != spaceInfo.spaceStock || OnAmount != spaceInfo.onRouteAmount)
{
_spaceInfoService.UpdateSpaceInfo(spaceInfo);
RefreshShellStockEvent?.Invoke();
RefreshLinerStockEvent?.Invoke();
if ((spaceInfo.spaceCapacity - spaceInfo.spaceStock) <= 5)
{
if (spaceInfo.storeCode == appConfig.shellStoreCode)
{
ShellAlarmSpaceName.Add(spaceInfo.spaceName);
}
else
{
LinerAlarmSpaceName.Add(spaceInfo.spaceName);
}
}
}
}
if (ShellAlarmSpaceName.Count > 0)
{
SpaceCapacityAlarmEvent?.Invoke(appConfig.shellStoreCode, jsonChange.ModeToJson(ShellAlarmSpaceName));
}
if (LinerAlarmSpaceName.Count > 0)
{
SpaceCapacityAlarmEvent?.Invoke(appConfig.linerStoreCode, jsonChange.ModeToJson(LinerAlarmSpaceName));
}
}
Thread.Sleep(3000);
}
});
}
#region 重新扫码时再次清除货道号,防止串货道任务
///
/// 重新扫码时再次清除货道号
///
///
///
public bool ClearSpaceCode(string storeCode)
{
bool result = false;
try
{
IPlc _plc = null;
if (storeCode == appConfig.shellStoreCode)
{
_plc = _plcDictionary[appConfig.shellStoreCode];
if (_plc != null)
{
result = _plc.writeInt32ByAddress(plcConfig.in_shell_spaceCode, 0);
_plc.writeInt32ByAddress(plcConfig.in_shell_bare_board, 0);
}
}
else if (storeCode == appConfig.linerStoreCode)
{
_plc = _plcDictionary[appConfig.linerStoreCode];
if (_plc != null)
{
result = _plc.writeInt32ByAddress(plcConfig.in_liner_spaceCode, 0);
_plc.writeInt32ByAddress(plcConfig.in_liner_bare_board, 0);
}
}
}
catch (Exception ex)
{
logHelper.Error("读取箱壳应答字异常:" + ex.Message.ToString());
}
return result;
}
#endregion
#region 箱壳入库任务下发处理
public int SendShellTask_InStore(RealTaskInfo taskInfo)
{
int result = 0;
try
{
IPlc _plc = _plcDictionary[taskInfo.storeCode];
if (_plc != null)
{
if (_plc.readInt32ByAddress(plcConfig.in_shell_answer) == 1)
{
Console.WriteLine(plcConfig.in_shell_answer + " 应答字读 1");
logHelper.Info("箱壳入库应答字为1,货道号:" + plcConfig.in_shell_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入货道号
_plc.writeInt32ByAddress(plcConfig.in_shell_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1)));
Console.WriteLine(plcConfig.in_shell_spaceCode + " 货道号写 " + short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入完成后读取应答字进行复位
ReadShellAnswer_InStore(taskInfo);
result = 1;
}
else
{
result = 2;
logHelper.PlcLog("应答字为2,下发新任务plc未就绪");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("箱壳入库任务下发异常", ex);
}
return result;
}
///
/// 读取箱壳入库应答
///
private void ReadShellAnswer_InStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
try
{
Task.Run(() =>
{
if (_plc != null)
{
do
{
//读取PLC应答字为2时,上位机清空写入的入库内容
if (_plc.readInt32ByAddress(plcConfig.in_shell_answer) == 2)
{
Console.WriteLine(plcConfig.in_shell_answer + " 应答字读 2");
logHelper.PlcLog("箱壳入库应答字为2,货道号:" + plcConfig.in_shell_spaceCode + ";复位写0");
//写入货道号
_plc.writeInt32ByAddress(plcConfig.in_shell_spaceCode, 0);
Console.WriteLine(plcConfig.in_shell_spaceCode + " 货道号写 0");
//写入应答字
// _plc.writeInt32ByAddress(plcConfig.in_foam_answer, 0);
_plc.writeInt32ByAddress(plcConfig.in_shell_bare_board, 0);
isFlag = false;
InStoreAnswerEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
// shellTaskInfos.Add(taskInfo);
}
Thread.Sleep(500);
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取箱壳入库应答字异常", ex);
}
}
}
#endregion
#region 内胆入库任务处理
///
/// 内胆入库任务下发
///
///
public int SendLinerTask_InStore(RealTaskInfo taskInfo)
{
int result = 0;
try
{
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
if (_plc != null)
{
if (_plc.readInt32ByAddress(plcConfig.in_liner_answer) == 1)
{
logHelper.PlcLog("内胆入库应答字为1,货道号:" + plcConfig.in_liner_spaceCode + ";写" + short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入货道号
_plc.writeInt32ByAddress(plcConfig.in_liner_spaceCode, short.Parse(taskInfo.spaceCode.Substring(5, 1)));
//写入应答字
// _plc.writeInt32ByAddress(plcConfig.in_foam_answer, 1);
//写入任务号
// _plc.writeStringByAddress(plcConfig.in_foam_task, taskInfo.taskCode);
//写入完成后读取应答字进行复位
ReadLinerAnswer_InStore(taskInfo);
result = 1;
}
else
{
result = 2;
logHelper.PlcLog("内胆应答字为2,下发新任务plc未就绪");
}
}
else
{
logHelper.Info($"PLC信息为空,通过{taskInfo.storeCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("内胆入库任务下发异常", ex);
}
return result;
}
///
/// 读取内胆入库应答
///
private void ReadLinerAnswer_InStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
try
{
Task.Run(() =>
{
if (_plc != null)
{
do
{
//读取PLC应答字为2时,上位机清空写入的入库内容
if (_plc.readInt32ByAddress(plcConfig.in_liner_answer) == 2)
{
logHelper.PlcLog("内胆入库应答字为2,货道号:" + plcConfig.in_liner_spaceCode + ";复位写0");
//写入货道号
_plc.writeInt32ByAddress(plcConfig.in_liner_spaceCode, 0);
//写入应答字
// _plc.writeInt32ByAddress(plcConfig.in_foam_answer, 0);
_plc.writeInt32ByAddress(plcConfig.in_liner_bare_board, 0);
isFlag = false;
InStoreAnswerEvent?.Invoke(appConfig.linerStoreCode, taskInfo.taskCode);
//ReadLinerFinish_InStore(taskCode);
// WritePlc(taskInfo.storeCode, taskInfo.spaceCode, false);
// linerTaskInfos.Add(taskInfo);
}
Thread.Sleep(1000);
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空,通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
});
}
catch (Exception ex)
{
logHelper.Error("读取内胆入库应答字异常", ex);
}
}
}
#endregion
#region 空板入库处理
private void ShellBareBoardHandle()
{
try
{
IPlc _plc = _plcDictionary[appConfig.shellStoreCode];
Task.Run(() =>
{
if (_plc != null)
{
int i = 0;
while (true)
{
int isFlag = _plc.readInt32ByAddress(plcConfig.in_shell_bare_board);
if (isFlag == 1)
{
i++;
if (i == 20)
{
_plc.writeInt32ByAddress(plcConfig.in_shell_bare_board, 0);
BareBoardHandleEvent?.Invoke(appConfig.shellStoreCode, false);
}
}
else if (isFlag == 2)
{
_plc.writeInt32ByAddress(plcConfig.in_shell_bare_board, 0);
BareBoardHandleEvent?.Invoke(appConfig.shellStoreCode);
Thread.Sleep(1000);
}
else if (isFlag == 0)
{
i = 0;
}
Thread.Sleep(500);
}
}
});
}
catch (Exception ex)
{
logHelper.Error($"ShellBareBoardHandle异常:{ex.Message}");
}
}
private void LinerBareBoardHandle()
{
try
{
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
Task.Run(() =>
{
if (_plc != null)
{
int i = 0;
while (true)
{
int isFlag = _plc.readInt32ByAddress(plcConfig.in_liner_bare_board);
if (isFlag == 1)
{
i++;
if (i == 30)
{
_plc.writeInt32ByAddress(plcConfig.in_liner_bare_board, 0);
BareBoardHandleEvent?.Invoke(appConfig.linerStoreCode, false);
}
}
else if (isFlag == 2)
{
_plc.writeInt32ByAddress(plcConfig.in_liner_bare_board, 0);
BareBoardHandleEvent?.Invoke(appConfig.linerStoreCode);
Thread.Sleep(1000);
}
else if (isFlag == 0)
{
i = 0;
}
Thread.Sleep(500);
}
}
});
}
catch (Exception ex)
{
logHelper.Error($"LinerBareBoardHandle异常:{ex.Message}");
}
}
#endregion
///
/// 通过PLC获取货道信息
///
///
///
public BaseSpaceInfo ReadSpaceInfoByPlc(BaseSpaceInfo spaceInfo)
{
try
{
var spaceAddress = spaceConfig.GetSpaceAddress(spaceInfo.storeCode, spaceInfo.spaceCode);
IPlc _plc = _plcDictionary[spaceInfo.storeCode];
// int i = _plc.readInt32ByAddress(plcConfig.in_shell_spaceCode);
if (_plc != null)
{
spaceInfo.spaceStock = _plc.readInt32ByAddress(spaceAddress.onStore);
spaceInfo.onRouteAmount = _plc.readInt32ByAddress(spaceAddress.onRoute);
// spaceInfo.spaceStatus = _plc.readInt32ByAddress(spaceAddress.spaceStatus);
}
return spaceInfo;
}
catch (Exception ex)
{
logHelper.Error(ex.Message.ToString());
return spaceInfo;
}
}
}
}