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/InStoreBusiness.cs

345 lines
11 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.Config;
using HighWayIot.Log4net;
using HighWayIot.Repository.service;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Aucma.Scada.Business
{
/// <summary>
/// 入库业务逻辑
/// </summary>
public sealed class InStoreBusiness
{
#region 单例实现
private static readonly Lazy<InStoreBusiness> lazy = new Lazy<InStoreBusiness>(() => new InStoreBusiness());
public static InStoreBusiness Instance
{
get
{
return lazy.Value;
}
}
#endregion
#region 对象引用
private LogHelper logHelper = LogHelper.Instance;
private AppConfig appConfig = AppConfig.Instance;
private RegisterServices registerServices = RegisterServices.Instance;
#endregion
#region 接口引用
/// <summary>
/// 货道信息
/// </summary>
private IBaseSpaceInfoService _spaceInfoService;
/// <summary>
/// 实时任务
/// </summary>
private IRealTaskInfoService _taskInfoService;
#endregion
#region 委托事件
/// <summary>
/// 初始化入库任务
/// </summary>
/// <param name="message"></param>
public delegate void RefreshInStoreTask(RealTaskInfo taskInfos);
public event RefreshInStoreTask RefreshInStoreTaskEvent;
/// <summary>
/// 扫码信息刷新
/// </summary>
/// <param name="materialCode"></param>
/// <param name="materialName"></param>
/// <param name="spaceName"></param>
/// <param name="materialType"></param>
public delegate void RefreshScanMateriaCode(string materialCode, string materialName, string spaceName, string materialType);
public event RefreshScanMateriaCode RefreshScanMateriaCodeEvent;
/// <summary>
/// 日志信息刷新
/// </summary>
/// <param name="message"></param>
public delegate void RefreshLogMessage(string message);
public event RefreshLogMessage RefreshLogMessageEvent;
#endregion
private InStoreBusiness()
{
_spaceInfoService = registerServices.GetService<IBaseSpaceInfoService>();
_taskInfoService = registerServices.GetService<IRealTaskInfoService>();
StartPassDown();
}
private void HandleTimer()
{
InStore("X-001", "SC232");
}
/// <summary>
/// 入库
/// </summary>
/// <param name="storeCode"></param>
/// <param name="materialType"></param>
private void InStore(string storeCode, string materialCode)
{
try
{
PrintLogInfoMessage($"扫码成功,物料码:{materialCode}");
string materialType = materialCode;
var spaceInfo = _spaceInfoService.InStoreGetSpaceInfoByMaterialType(storeCode, materialType);
if (spaceInfo != null)
{
PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}");
RefreshScanMateriaCodeEvent?.Invoke(materialCode, materialType, spaceInfo.spaceName, storeCode); //刷新界面扫码信息
CreateInStoreTask(spaceInfo, materialCode); //创建入库任务
}
else
{
//报警停线
}
}
catch (Exception ex)
{
PrintLogErrorMessage("入库业务异常", ex);
}
}
/// <summary>
/// 创建入库任务
/// </summary>
/// <param name="spaceInfo"></param>
private void CreateInStoreTask(BaseSpaceInfo spaceInfo, string materialCode)
{
//生成入库任务依次下发至PLC
RealTaskInfo realTaskInfo = new RealTaskInfo();
realTaskInfo.taskType = 1;
realTaskInfo.taskCode = System.Guid.NewGuid().ToString("N").Substring(0, 6);
realTaskInfo.storeCode = spaceInfo.storeCode;
realTaskInfo.spaceCode = spaceInfo.spaceCode;
realTaskInfo.materialType = spaceInfo.materialType;
realTaskInfo.materialCode = System.Guid.NewGuid().ToString("N").Substring(0, 6); ;
realTaskInfo.planAmount = 1;
realTaskInfo.taskStatus = 1;
realTaskInfo.createTime = DateTime.Now;
bool result = _taskInfoService.AddTaskInfo(realTaskInfo);
if (result)
{
PrintLogInfoMessage("入库任务创建成功");
RefreshInStoreTaskEvent?.Invoke(realTaskInfo);
}
else
{
PrintLogInfoMessage("入库任务创建失败");
}
}
#region 轮询获取入库任务下发至PLC等待PLC执行反馈完成后再次下发
private SemaphoreSlim shellSemaphore = new SemaphoreSlim(0);
private SemaphoreSlim linerSemaphore = new SemaphoreSlim(0);
private void StartPassDown()
{
Task.Run(() =>
{
while (true)
{
PassDownShellTask();
Thread.Sleep(1000);
}
});
Task.Run(() =>
{
while (true)
{
PassDownLinerTask();
Thread.Sleep(1000);
}
});
}
/// <summary>
/// 依次获取箱壳任务队列进行下发
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private void PassDownShellTask()
{
RealTaskInfo taskInfo = GetAwaitSendTask(appConfig.shellStoreCode);
if (taskInfo != null)
{
PrintLogInfoMessage($"下发箱壳入库任务:{taskInfo.taskCode};仓库{taskInfo.storeCode};货道:{taskInfo.spaceCode}");
if (shellSemaphore.Wait(TimeSpan.FromSeconds(10)))
{
// 收到反馈
PrintLogInfoMessage("箱壳收到反馈,继续执行");
}
else
{
PrintLogInfoMessage("超时未反馈");
}
//shellSemaphore.Wait(); //一直堵塞直到信号量释放
}
else
{
PrintLogInfoMessage("未获取到需要下发的箱壳入库任务");
Thread.Sleep(5000);
}
}
/// <summary>
/// 依次获取内胆任务队列进行下发
/// </summary>
private void PassDownLinerTask()
{
RealTaskInfo taskInfo = GetAwaitSendTask(appConfig.linerStoreCode);
if (taskInfo != null)
{
PrintLogInfoMessage($"下发内胆入库任务:{taskInfo.taskCode};仓库{taskInfo.storeCode};货道:{taskInfo.spaceCode}");
if (linerSemaphore.Wait(TimeSpan.FromSeconds(10)))
{
// 收到反馈
PrintLogInfoMessage("内胆收到反馈,继续执行");
}
else
{
PrintLogInfoMessage("超时未反馈");
}
//semaphore.Wait(); //一直堵塞直到信号量释放
}
else
{
PrintLogInfoMessage("未获取到需要下发的内胆入库任务");
Thread.Sleep(5000);
}
}
/// <summary>
/// 获取待执行的入库任务
/// </summary>
/// <param name="storeCode"></param>
/// <returns></returns>
private RealTaskInfo GetAwaitSendTask(string storeCode)
{
RealTaskInfo taskInfo = null;
try
{
taskInfo = _taskInfoService.GetTaskInfoByStoreCode(storeCode, 1);
if (taskInfo != null)
{
taskInfo.taskStatus = 2;
_taskInfoService.UpdateTaskInfo(taskInfo);
}
}
catch (Exception ex)
{
PrintLogErrorMessage("获取待执行的入库任务异常", ex);
}
return taskInfo;
}
/// <summary>
/// 箱壳执行反馈
/// </summary>
private void ShellTaskFeedback()
{
Thread.Sleep(4000);
PrintLogInfoMessage("箱壳执行完成,自动释放信号量");
shellSemaphore.Release();
}
/// <summary>
/// 内胆执行反馈
/// </summary>
private void LinerTaskFeedback()
{
Thread.Sleep(8000);
PrintLogInfoMessage("内胆执行完成,自动释放信号量");
linerSemaphore.Release();
}
#endregion
/// <summary>
/// 入库完成
/// </summary>
/// <param name="storeCode"></param>
/// <param name="spaceCode"></param>
/// <param name="materialType"></param>
private void InStoreFinish(string taskCode, string storeCode)
{
try
{
var taskInfo = _taskInfoService.GetTaskInfoByTaskCode(taskCode, storeCode);
if (taskInfo != null)
{
var spaceInfo = _spaceInfoService.GetSpaceInfoBySpaceCode(taskInfo.storeCode, taskInfo.spaceCode);
if (spaceInfo != null)
{
//读取PLC获取货道信息存放数量、在途数量
spaceInfo.materialType = taskInfo.materialType;
_spaceInfoService.UpdateSpaceInfo(spaceInfo);
}
//清除任务信息
_taskInfoService.DeleteTaskInfo(taskCode, storeCode);
}
}
catch (Exception ex)
{
PrintLogErrorMessage("入库完成逻辑处理异常", ex);
}
}
/// <summary>
/// 日志输出,界面刷新同时记录文件
/// </summary>
/// <param name="message"></param>
private void PrintLogInfoMessage(string message)
{
RefreshLogMessageEvent?.Invoke(message);
logHelper.Info(message);
}
/// <summary>
/// 异常日志输出
/// </summary>
/// <param name="message"></param>
/// <param name="ex"></param>
private void PrintLogErrorMessage(string message, Exception ex = null)
{
RefreshLogMessageEvent?.Invoke(message);
logHelper.Error(message, ex);
}
}
}