You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Aucma.Scada/Aucma.Scada.Business/InStoreTaskHandle.cs

602 lines
22 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>
/// 入库任务处理
/// </summary>
public sealed class InStoreTaskHandle
{
#region 单例实现
private static readonly Lazy<InStoreTaskHandle> lazy = new Lazy<InStoreTaskHandle>(() => 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;
/// <summary>
/// 实时任务
/// </summary>
private IRealTaskInfoService _taskInfoService;
private RegisterServices registerServices = RegisterServices.Instance;
/// <summary>
/// 货道信息
/// </summary>
private IBaseSpaceInfoService _spaceInfoService;
#endregion
#region 私有变量
private Dictionary<string, IPlc> _plcDictionary = new Dictionary<string, IPlc>();
private Dictionary<string, int> shellKeyValuePairs = new Dictionary<string, int>();
private Dictionary<string, int> linerKeyValuePairs = new Dictionary<string, int>();
/// <summary>
/// 箱壳任务编号,PLC反馈后进行赋值
/// </summary>
private string shellTaskCode = string.Empty;
/// <summary>
/// 内胆任务编号,PLC反馈后进行赋值
/// </summary>
private string linerTaskCode = string.Empty;
/// <summary>
/// 已下传的任务信息
/// </summary>
// private List<RealTaskInfo> shellTaskInfos = new List<RealTaskInfo>();
// private List<RealTaskInfo> linerTaskInfos = new List<RealTaskInfo>();
#endregion
#region 委托事件
/// <summary>
/// 箱壳实时库存刷新
/// </summary>
/// <param name="message"></param>
public delegate Task RefreshShellStock();
public event RefreshShellStock RefreshShellStockEvent;
/// <summary>
/// 内胆实时库存刷新
/// </summary>
/// <param name="message"></param>
public delegate Task RefreshLinerStock();
public event RefreshLinerStock RefreshLinerStockEvent;
/// <summary>
/// 入库完成
/// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param>
public delegate void InStoreFinsih(string storeCode, string taskCode);
public event InStoreFinsih InStoreFinsihEvent;
/// <summary>
/// 入库应答PLC收到下发的入库任务后进行应答
/// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param>
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;
/// <summary>
/// 库容告警
/// </summary>
public delegate void SpaceCapacityAlarm(string storeCode, string spaceName);
public event SpaceCapacityAlarm SpaceCapacityAlarmEvent;
#endregion
private InStoreTaskHandle()
{
_taskInfoService = registerServices.GetService<IRealTaskInfoService>();
_spaceInfoService = registerServices.GetService<IBaseSpaceInfoService>();
_plcDictionary = _pool.GetAll();
// RealReadFinish();
RealUpdateSpaceInfoByPlc();
ShellBareBoardHandle();
LinerBareBoardHandle();
}
/// <summary>
/// 实时读取plc更新数据库货道数量及在途
/// </summary>
private void RealUpdateSpaceInfoByPlc()
{
Task.Run(() =>
{
Thread.Sleep(2000);
while (true)
{
List<BaseSpaceInfo> spaceList = _spaceInfoService.GetSpaceInfosByStoreCode(appConfig.shellStoreCode, appConfig.linerStoreCode);
if (spaceList != null && spaceList.Count > 0)
{
List<string> ShellAlarmSpaceName = new List<string>();
List<string> LinerAlarmSpaceName = new List<string>();
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);
}
}
}
string str = string.Empty;
if (ShellAlarmSpaceName.Count > 0)
{
str +=$"箱壳库货道:{jsonChange.ModeToJson(ShellAlarmSpaceName)}";
}
if (LinerAlarmSpaceName.Count > 0)
{
str += $"内胆库货道:{jsonChange.ModeToJson(LinerAlarmSpaceName)}";
}
if(!string.IsNullOrEmpty(str))
{
SpaceCapacityAlarmEvent?.Invoke(appConfig.shellStoreCode, str);
}
}
Thread.Sleep(3000);
}
});
}
#region 重新扫码时再次清除货道号,防止串货道任务
/// <summary>
/// 重新扫码时再次清除货道号
/// </summary>
/// <param name="storeCode"></param>
/// <returns></returns>
public bool ClearSpaceCode(string storeCode)
{
bool result = false;
try
{
IPlc _plc = null;
_plcDictionary = _pool.GetAll();
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
{
_plcDictionary = _pool.GetAll();
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;
}
/// <summary>
/// 读取箱壳入库应答
/// </summary>
private void ReadShellAnswer_InStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
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.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);
// 检查是否超过15秒如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 10)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.shellStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取箱壳入库应答字异常", ex);
}
}
}
#endregion
#region 内胆入库任务处理
/// <summary>
/// 内胆入库任务下发
/// </summary>
/// <param name="taskInfo"></param>
public int SendLinerTask_InStore(RealTaskInfo taskInfo)
{
int result = 0;
try
{
_plcDictionary = _pool.GetAll();
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;
}
/// <summary>
/// 读取内胆入库应答
/// </summary>
private void ReadLinerAnswer_InStore(RealTaskInfo taskInfo)
{
lock (string.Empty)
{
bool isFlag = true;
_plcDictionary = _pool.GetAll();
IPlc _plc = _plcDictionary[appConfig.linerStoreCode];
try
{
DateTime startTime = DateTime.Now;
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(500);
// 检查是否超过30秒如果超过则跳出循环
if ((DateTime.Now - startTime).TotalSeconds >= 10)
{
isFlag = false; // 设置标志结束循环
}
} while (isFlag);
}
else
{
logHelper.Info($"PLC信息为空通过{appConfig.linerStoreCode}未获取到该仓库对应的PLC信息");
}
}
catch (Exception ex)
{
logHelper.Error("读取内胆入库应答字异常", ex);
}
}
}
#endregion
#region 空板入库处理
private void ShellBareBoardHandle()
{
try
{
_plcDictionary = _pool.GetAll();
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 == 35)
{
_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
{
_plcDictionary = _pool.GetAll();
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
/// <summary>
/// 通过PLC获取货道信息
/// </summary>
/// <param name="spaceInfo"></param>
/// <returns></returns>
public BaseSpaceInfo ReadSpaceInfoByPlc(BaseSpaceInfo spaceInfo)
{
try
{
var spaceAddress = spaceConfig.GetSpaceAddress(spaceInfo.storeCode, spaceInfo.spaceCode);
_plcDictionary = _pool.GetAll();
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;
}
}
}
}