change - 出入库逻辑修改

foamRearStore
wenjy 1 year ago
parent 40387b84c7
commit 2e07cfd49e

Binary file not shown.

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static Aucma.Scada.Business.InStoreTaskHandle;
namespace Aucma.Scada.Business namespace Aucma.Scada.Business
{ {
@ -95,7 +96,11 @@ namespace Aucma.Scada.Business
_baseBomInfoService = registerServices.GetService<IBaseBomInfoService>(); _baseBomInfoService = registerServices.GetService<IBaseBomInfoService>();
_recordInStoreService = registerServices.GetService<IRecordInStoreService>(); _recordInStoreService = registerServices.GetService<IRecordInStoreService>();
taskHandle.InStoreFinsihEvent += FoamTaskFeedback; //taskHandle.InStoreFinsihEvent += FoamTaskFeedback;
taskHandle.InStoreFinsihEvent += InStoreFinish;
taskHandle.InStoreAnswerEvent += InStoreAnswer;
grabImage.RefreshMaterialCodeStrEvent += InStore; grabImage.RefreshMaterialCodeStrEvent += InStore;
grabImage.RefreshLogMessageEvent += PrintLogInfoMessage; grabImage.RefreshLogMessageEvent += PrintLogInfoMessage;
StartPassDown(); StartPassDown();
@ -122,12 +127,13 @@ namespace Aucma.Scada.Business
PrintLogInfoMessage($"扫码成功,物料码:{materialCode}"); PrintLogInfoMessage($"扫码成功,物料码:{materialCode}");
string materialType = SubStringMaterialCode(materialCode); string materialType = SubStringMaterialCode(materialCode);
#region Delete By wenjy 2023-10-30 11:41:00 取消通过数据库获取货道数量、在途量改为通过PLC获取货道信息 #region Delete By wenjy 2023-10-30 11:41:00 取消通过数据库获取货道数量、在途量改为通过PLC获取货道信息
var spaceInfo = _spaceInfoService.InStoreGetSpaceInfoByMaterialType(appConfig.foamStoreCode, materialType); //var spaceInfo = _spaceInfoService.InStoreGetSpaceInfoByMaterialType(appConfig.foamStoreCode, materialType);
#endregion #endregion
//var spaceInfo = GetSpaceInfoByMaterialType(appConfig.foamStoreCode, materialType); var spaceInfo = GetSpaceInfoByMaterialType(appConfig.foamStoreCode, materialType);
if (spaceInfo != null) if (spaceInfo != null)
{ {
PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}"); PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}");
spaceInfo.materialType = materialType;
RefreshScanMateriaCodeEvent?.Invoke(materialCode, GetMaterialName(materialType), spaceInfo.spaceName, appConfig.foamStoreCode); //刷新界面扫码信息 RefreshScanMateriaCodeEvent?.Invoke(materialCode, GetMaterialName(materialType), spaceInfo.spaceName, appConfig.foamStoreCode); //刷新界面扫码信息
var result = CreateInStoreTask(spaceInfo, materialCode); //创建入库任务 var result = CreateInStoreTask(spaceInfo, materialCode); //创建入库任务
if (result) if (result)
@ -232,27 +238,16 @@ namespace Aucma.Scada.Business
if (taskHandle.SendFoamTask_InStore(taskInfo)) if (taskHandle.SendFoamTask_InStore(taskInfo))
{ {
PrintLogInfoMessage($"泡后入库任务:{taskInfo.taskCode}下发成功等待PLC执行反馈"); PrintLogInfoMessage($"泡后入库任务:{taskInfo.taskCode}下发成功等待PLC执行反馈");
taskInfo.taskStatus = 2;
_taskInfoService.UpdateTaskInfo(taskInfo); semaphore.Wait(); //一直堵塞直到信号量释放
RefreshInStoreTaskEvent?.Invoke(taskInfo);
//if (semaphore.Wait(TimeSpan.FromSeconds(20))) PrintLogInfoMessage($"泡后入库任务:{taskInfo.taskCode};开始执行");
//{
// // 收到反馈
// PrintLogInfoMessage("收到反馈,继续执行");
//}
//else
//{
// PrintLogInfoMessage("超时未反馈");
//}
semaphore.Wait(); //一直堵塞直到信号量释放 taskInfo.taskStatus = 2;
PrintLogInfoMessage($"泡后入库任务:{taskInfo.taskCode};执行完成"); _taskInfoService.UpdateTaskInfo(taskInfo);
RefreshInStoreTaskEvent?.Invoke(taskInfo,true); RefreshInStoreTaskEvent?.Invoke(taskInfo);
} }
else else
@ -265,7 +260,6 @@ namespace Aucma.Scada.Business
{ {
PrintLogInfoMessage("未获取到需要下发的泡后入库任务"); PrintLogInfoMessage("未获取到需要下发的泡后入库任务");
} }
Thread.Sleep(3000);
} }
/// <summary> /// <summary>
@ -311,17 +305,27 @@ namespace Aucma.Scada.Business
} }
/// <summary> /// <summary>
/// 泡后执行反馈 /// 入库应答PLC收到入库任务后进行应答
/// </summary> /// </summary>
private void FoamTaskFeedback(string taskCode) /// <param name="storeCode"></param>
/// <param name="taskCode"></param>
private void InStoreAnswer(string storeCode, string taskCode)
{ {
PrintLogInfoMessage("PLC应答成功自动释放信号量进行下发新任务");
PrintLogInfoMessage("泡后执行完成,自动释放信号量");
InStoreFinish(taskCode);
semaphore.Release(); semaphore.Release();
}
/// <summary>
/// 入库完成
/// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param>
private void InStoreFinish(string storeCode, string taskCode)
{
PrintLogInfoMessage($"出库任务:{taskCode};执行完成");
InStoreFinish(taskCode);
} }
#endregion #endregion
@ -343,7 +347,8 @@ namespace Aucma.Scada.Business
if (spaceInfo != null) if (spaceInfo != null)
{ {
spaceInfo.materialType = taskInfo.materialType; taskHandle.WritePlc(spaceInfo.storeCode, spaceInfo.spaceCode, true);
//spaceInfo.materialType = taskInfo.materialType;
spaceInfo.spaceStock = spaceInfo.spaceStock + 1; spaceInfo.spaceStock = spaceInfo.spaceStock + 1;
spaceInfo.onRouteAmount -= 1; spaceInfo.onRouteAmount -= 1;
@ -367,7 +372,7 @@ namespace Aucma.Scada.Business
_baseSpaceDetailService.InsertSpaceDetail(spaceDetail); _baseSpaceDetailService.InsertSpaceDetail(spaceDetail);
#endregion #endregion
#region 添加入库任务 #region 添加入库记录
RecordInstore recordInstore = new RecordInstore(); RecordInstore recordInstore = new RecordInstore();
recordInstore.storeCode = taskInfo.storeCode; recordInstore.storeCode = taskInfo.storeCode;
recordInstore.spaceCode = taskInfo.spaceCode; recordInstore.spaceCode = taskInfo.spaceCode;
@ -384,7 +389,7 @@ namespace Aucma.Scada.Business
//清除任务信息 //清除任务信息
_taskInfoService.DeleteTaskInfo(taskCode, appConfig.foamStoreCode); _taskInfoService.DeleteTaskInfo(taskCode, appConfig.foamStoreCode);
} }
RefreshInStoreTaskEvent?.Invoke(taskInfo, true);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -474,6 +479,8 @@ namespace Aucma.Scada.Business
return groups; return groups;
} }
#region 通过PLC读取货道信息在库、在途、货道状态
/// <summary>
/// 通过PLC读取货道信息在途数量、在库数量、货道状态) /// 通过PLC读取货道信息在途数量、在库数量、货道状态)
/// </summary> /// </summary>
/// <param name="storeCode"></param> /// <param name="storeCode"></param>
@ -491,15 +498,14 @@ namespace Aucma.Scada.Business
{ {
if (info.Count > 0) if (info.Count > 0)
{ {
foreach (BaseSpaceInfo item in info) result = GetSpaceInfosByPlc(info);
if (result == null)
{ {
var spaceInfo = taskHandle.ReadSpaceInfoByPlc(item); var list = _spaceInfoService.GetEmptySpaceInfo(storeCode);
item.spaceStock = spaceInfo.spaceStock;
item.onRouteAmount = spaceInfo.onRouteAmount;
item.spaceStatus = spaceInfo.spaceStatus;
}
result = info.Where(x => x.spaceStatus == 1 && x.spaceStock > 0 ? x.spaceCapacity > (x.spaceStock + x.onRouteAmount) : 1 == 1).OrderByDescending(x => x.spaceStock).OrderBy(x => x.spaceCode).First(); result = GetSpaceInfosByPlc(list);
}
} }
} }
@ -511,5 +517,41 @@ namespace Aucma.Scada.Business
return result; return result;
} }
/// <summary>
/// 读取PLC货道信息
/// </summary>
/// <param name="info"></param>
/// <returns></returns>
private BaseSpaceInfo GetSpaceInfosByPlc(List<BaseSpaceInfo> info)
{
BaseSpaceInfo result = null;
if (info != null)
{
if (info.Count > 0)
{
foreach (BaseSpaceInfo item in info)
{
var spaceInfo = taskHandle.ReadSpaceInfoByPlc(item);
item.spaceStock = spaceInfo.spaceStock;
item.onRouteAmount = spaceInfo.onRouteAmount;
item.spaceStatus = spaceInfo.spaceStatus;
PrintLogInfoMessage($"通过PLC读取货道信息货道{spaceInfo.spaceName};在库数量:{item.spaceStock};在途数量:{item.onRouteAmount};货道状态:{item.spaceStatus}");
}
var list = info.Where(x => x.spaceStock > 0 ? x.spaceCapacity > (x.spaceStock + x.onRouteAmount) : 1 == 1 && x.spaceStatus == 1).ToList();
if (list.Count > 0)
{
result = list.OrderByDescending(x => x.spaceStock).OrderBy(x => x.spaceCode).First();
}
}
}
return result;
}
#endregion
} }
} }

@ -4,6 +4,7 @@ using HighWayIot.Log4net;
using HighWayIot.Plc; using HighWayIot.Plc;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -39,26 +40,43 @@ namespace Aucma.Scada.Business
#region 私有变量 #region 私有变量
private Dictionary<string, IPlc> _plcDictionary = new Dictionary<string, IPlc>(); private Dictionary<string, IPlc> _plcDictionary = new Dictionary<string, IPlc>();
private Dictionary<string, int> foamRearKeyValuePairs = new Dictionary<string, int>();
/// <summary> /// <summary>
/// 泡后任务编号,PLC反馈后进行赋值 /// 泡后任务编号,PLC反馈后进行赋值
/// </summary> /// </summary>
private string foamTaskCode = string.Empty; private string foamTaskCode = string.Empty;
/// <summary>
/// 已下传的任务信息
/// </summary>
private List<RealTaskInfo> foamRearTaskInfos = new List<RealTaskInfo>();
#endregion #endregion
#region 委托事件 #region 委托事件
/// <summary> /// <summary>
/// 入库完成 /// 入库完成
/// </summary> /// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param> /// <param name="taskCode"></param>
public delegate void InStoreFinsih( string taskCode); public delegate void InStoreFinsih(string storeCode, string taskCode);
public event InStoreFinsih InStoreFinsihEvent; 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;
#endregion #endregion
private InStoreTaskHandle() private InStoreTaskHandle()
{ {
_plcDictionary = _pool.GetAll(); _plcDictionary = _pool.GetAll();
RealReadPlcSpace();
} }
#region 泡后入库任务下发处理 #region 泡后入库任务下发处理
@ -81,7 +99,7 @@ namespace Aucma.Scada.Business
_plc.writeStringByAddress(plcConfig.in_foam_task, taskInfo.taskCode); _plc.writeStringByAddress(plcConfig.in_foam_task, taskInfo.taskCode);
//写入完成后读取应答字进行复位 //写入完成后读取应答字进行复位
ReadShellAnswer_InStore(taskInfo.taskCode); ReadShellAnswer_InStore(taskInfo);
result = true; result = true;
} }
@ -106,7 +124,7 @@ namespace Aucma.Scada.Business
/// <summary> /// <summary>
/// 读取泡后入库应答 /// 读取泡后入库应答
/// </summary> /// </summary>
private void ReadShellAnswer_InStore(string taskCode) private void ReadShellAnswer_InStore(RealTaskInfo taskInfo)
{ {
lock (string.Empty) lock (string.Empty)
{ {
@ -133,7 +151,12 @@ namespace Aucma.Scada.Business
_plc.writeStringByAddress(plcConfig.in_foam_task, string.Empty); _plc.writeStringByAddress(plcConfig.in_foam_task, string.Empty);
isFlag = false; isFlag = false;
ReadShellFinish_InStore(taskCode); WritePlc(taskInfo.storeCode, taskInfo.spaceCode, false);
//ReadShellFinish_InStore(taskCode);
InStoreAnswerEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
foamRearTaskInfos.Add(taskInfo);
} }
Thread.Sleep(1000); Thread.Sleep(1000);
@ -157,60 +180,136 @@ namespace Aucma.Scada.Business
} }
} }
#endregion
#region 读取PLC入库完成 Delete By Wenjy 2023-11-08 15:05:00经讨论入库完成改为监测在途数量变化
/// <summary> /// <summary>
/// 读取泡后入库完成 /// 读取泡后入库完成
/// </summary> /// </summary>
private void ReadShellFinish_InStore(string taskCode) //private void ReadShellFinish_InStore(string taskCode)
//{
// lock (string.Empty)
// {
// bool isFlag = true;
// IPlc _plc = _plcDictionary[appConfig.foamStoreCode];
// foamTaskCode = taskCode;
// try
// {
// Task.Run(() =>
// {
// if (_plc != null)
// {
// if (_plc.IsConnected)
// {
// do
// {
// //读取PLC入库任务完成
// if (_plc.readInt32ByAddress(plcConfig.in_foam_finish) == 1)
// {
// _plc.writeInt32ByAddress(plcConfig.in_foam_finish, 0);
// //string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10);
// InStoreFinsihEvent?.Invoke(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 监测PLC在途数量变化完成入库任务
private void RealReadPlcSpace()
{ {
lock (string.Empty) Thread.Sleep(5000);
Task.Run(() =>
{ {
bool isFlag = true; while (true)
IPlc _plc = _plcDictionary[appConfig.foamStoreCode];
foamTaskCode = taskCode;
try
{ {
Task.Run(() => RealReadShellPlcSpace();
{
if (_plc != null)
{
if (_plc.IsConnected)
{
do
{
//读取PLC入库任务完成
if (_plc.readInt32ByAddress(plcConfig.in_foam_finish) == 1)
{
_plc.writeInt32ByAddress(plcConfig.in_foam_finish, 0);
//string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10); Thread.Sleep(500);
}
});
InStoreFinsihEvent?.Invoke(taskCode); }
isFlag = false; /// <summary>
} /// 读取箱壳已下发任务的货道信息读取后将货道编号及在途数量写入Dictionary进行比较在途数减少则入库完成
/// </summary>
private void RealReadShellPlcSpace()
{
if (foamRearTaskInfos != null)
{
List<string> spaceCodes = foamRearTaskInfos.Select(x => x.spaceCode).Distinct().ToList();
Thread.Sleep(1000); for (int i = 0; i < spaceCodes.Count; i++)
} while (isFlag); {
}
else string spaceCode = spaceCodes[i];
BaseSpaceInfo spaceInfo = new BaseSpaceInfo() { storeCode = appConfig.shellStoreCode, spaceCode = spaceCode };
spaceInfo = ReadSpaceInfoByPlc(spaceInfo);
if (foamRearKeyValuePairs.ContainsKey(spaceInfo.spaceCode))
{
foamRearKeyValuePairs.TryGetValue(spaceInfo.spaceCode, out int value);
//判断前次读取的数据和当前数据,如果前次数据大于当前数据则代表入库完成,然后筛选任务中对应货道的首个任务进行完成
//如果前次数据不大于当前数据则更新字典中存放的数据
if (value > spaceInfo.onRouteAmount)
{
//筛选任务
var list = foamRearTaskInfos.Where(x => x.spaceCode == spaceInfo.spaceCode).ToList();
if (list.Count > 0)
{ {
logHelper.Info($"仓库{appConfig.foamStoreCode}PLC未连接"); RealTaskInfo taskInfo = list.OrderBy(x => x.createTime).First();
InStoreFinsihEvent?.Invoke(taskInfo.storeCode, taskInfo.taskCode);
foamRearTaskInfos.Remove(taskInfo);
} }
foamRearKeyValuePairs.Remove(spaceInfo.spaceCode);
} }
else else
{ {
logHelper.Info($"PLC信息为空通过{appConfig.foamStoreCode}未获取到该仓库对应的PLC信息"); foamRearKeyValuePairs[spaceInfo.spaceCode] = spaceInfo.onRouteAmount;
} }
});
} }
catch (Exception ex) else
{ {
logHelper.Error("读取泡后入库完成异常", ex); foamRearKeyValuePairs.Add(spaceInfo.spaceCode, spaceInfo.onRouteAmount);
}
} }
} }
} }
#endregion #endregion
/// <summary> /// <summary>
/// 通过PLC获取货道信息 /// 通过PLC获取货道信息
/// </summary> /// </summary>
@ -233,5 +332,38 @@ namespace Aucma.Scada.Business
return spaceInfo; return spaceInfo;
} }
/// <summary>
/// 测试方法,联调时不用
/// </summary>
/// <param name="storeCode"></param>
/// <param name="spaceCode"></param>
/// <param name="flag"></param>
public void WritePlc(string storeCode, string spaceCode, bool flag)
{
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);
if (flag)
{
_plc.writeInt32ByAddress(spaceAddress.onStore, spaceStock + 1);
//_plc.writeInt32ByAddress(spaceAddress.onRoute, onRouteAmount - 1);
}
else
{
_plc.writeInt32ByAddress(spaceAddress.onRoute, onRouteAmount + 1);
}
}
}
}
} }
} }

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using static Aucma.Scada.Business.OutStoreTaskHandle;
namespace Aucma.Scada.Business namespace Aucma.Scada.Business
{ {
@ -113,7 +114,11 @@ namespace Aucma.Scada.Business
_recordOutStoreService = registerServices.GetService<IRecordOutStoreService>(); _recordOutStoreService = registerServices.GetService<IRecordOutStoreService>();
_recordProductfinishService = registerServices.GetService<IRecordProductfinishService>(); _recordProductfinishService = registerServices.GetService<IRecordProductfinishService>();
assemblyPlanBusiness.NextPassExecutePlanInfoEvent += PlanHandle; assemblyPlanBusiness.NextPassExecutePlanInfoEvent += PlanHandle;
taskHandleBusiness.OutStoreFinsihEvent += TaskFeedback;
//taskHandleBusiness.OutStoreFinsihEvent += TaskFeedback;
taskHandleBusiness.OutStoreAnswerEvent += OutStoreAnswer;
taskHandleBusiness.OutStoreFinsihEvent += OutStoreFinish;
StartPassDown(); StartPassDown();
} }
@ -161,7 +166,15 @@ namespace Aucma.Scada.Business
{ {
PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}"); PrintLogInfoMessage($"匹配货道:{spaceInfo.spaceName}");
// RefreshScanMateriaCodeEvent?.Invoke(materiaclCode, materialType, spaceInfo.spaceName, storeCode); //刷新界面扫码信息 // RefreshScanMateriaCodeEvent?.Invoke(materiaclCode, materialType, spaceInfo.spaceName, storeCode); //刷新界面扫码信息
CreateOutStoreTask(spaceInfo, planCode, taskCode); //创建出库任务 bool result = CreateOutStoreTask(spaceInfo, planCode, taskCode); //创建出库任务
if (result)
{
PrintLogInfoMessage("出库任务创建成功");
}
else
{
PrintLogInfoMessage("出库任务创建失败");
}
} }
else else
{ {
@ -304,134 +317,183 @@ namespace Aucma.Scada.Business
/// <summary> /// <summary>
/// 依次获取任务队列进行下发 /// 依次获取任务队列进行下发
/// </summary> /// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
private void PassDownTaskInfo() private void PassDownTaskInfo()
{ {
string taskCode = string.Empty; try
string executePlanCode = string.Empty;
int iFlag = 0;
completedTasks = 0;
//获取待执行的出库任务下发至PLC,并将任务状态改为执行中
var taskInfoList = GetAwaitSendTask();
if (taskInfoList.Count > 0)
{ {
taskAmount = taskInfoList.Count; //下发的任务数量默认2泡后、内胆泡后、内胆均执行完成后才会释放信号量 RealTaskInfo taskInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.foamStoreCode, appConfig.outstoreTaskType);
if (taskInfo != null)
foreach (var item in taskInfoList)
{
taskCode = item.taskCode;
executePlanCode = item.planCode;
if (taskHandleBusiness.SendFoamTask_OutStore(item))
{
PrintLogInfoMessage($"下发泡后出库任务:{item.taskCode};仓库{item.storeCode};货道:{item.spaceCode}等待PLC执行反馈");
item.taskStatus = 2;
iFlag++;
}
else
{
PrintLogInfoMessage($"泡后出库任务:{item.taskCode}下发失败请排除PLC连接");
continue;
}
_taskInfoService.UpdateTaskInfo(item);
RefreshScanMateriaCodeEvent?.Invoke(item.materialCode, item.materialType, item.spaceName, item.storeCode);
}
if (iFlag == taskInfoList.Count)
{ {
inStoreBusiness.IssueOutTask(); PrintLogInfoMessage($"下发出库任务:{taskInfo.taskCode};仓库{taskInfo.storeCode};货道:{taskInfo.spaceCode}");
semaphore.Wait(); //一直堵塞直到信号量释放 if (taskHandleBusiness.SendFoamTask_OutStore(taskInfo))
{
PrintLogInfoMessage($"出库任务:{taskInfo.taskCode}下发成功等待PLC执行反馈");
inStoreBusiness.IssueInTask(); semaphore.Wait(); //一直堵塞直到信号量释放
PrintLogInfoMessage($"出库任务:{taskCode};执行完成"); PrintLogInfoMessage($"出库任务:{taskInfo.taskCode};开始执行");
UpdatePlanInfo(executePlanCode); taskInfo.taskStatus = 2;
RefreshStoreStockEvent?.Invoke(); _taskInfoService.UpdateTaskInfo(taskInfo);
}
}
else
{
PrintLogInfoMessage("未获取到需要下发的出库任务");
}
Thread.Sleep(3000);
}
RefreshScanMateriaCodeEvent?.Invoke(taskInfo.materialCode, taskInfo.materialType, taskInfo.spaceName, taskInfo.storeCode);
/// <summary> }
/// 获取待执行的出库任务 else
/// </summary> {
/// <returns></returns> PrintLogInfoMessage($"出库任务:{taskInfo.taskCode}下发失败请排除PLC连接");
private List<RealTaskInfo> GetAwaitSendTask() }
{
List<RealTaskInfo> taskInfos = new List<RealTaskInfo>();
try
{
RealTaskInfo foamTaskInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.foamStoreCode, 2);
if (foamTaskInfo != null)
{
taskInfos.Add(foamTaskInfo);
//获取与泡后任务匹配的内胆任务
RealTaskInfo linerTaskInfo = _taskInfoService.GetTaskInfoByTaskCode(foamTaskInfo.taskCode, appConfig.linerStoreCode);
if (linerTaskInfo != null) taskInfos.Add(linerTaskInfo);
} }
else else
{ {
RealTaskInfo linerInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.linerStoreCode, 2); PrintLogInfoMessage("未获取到需要下发的内胆出库任务");
if (linerInfo != null) taskInfos.Add(linerInfo);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
PrintLogErrorMessage("获取待执行的出库任务异常", ex); PrintLogErrorMessage("下传出库任务逻辑处理异常", ex);
} }
return taskInfos;
} }
#region 原下发逻辑 Delete By wenjy 2023-11-15 15:54:00
/// <summary> /// <summary>
/// PLC任务执行反馈 /// 依次获取任务队列进行下发
/// </summary> /// </summary>
/// <param name="storeCode"></param> /// <param name="source"></param>
/// <param name="taskCode"></param> /// <param name="e"></param>
private void TaskFeedback(string storeCode, string taskCode) //private void PassDownTaskInfo()
{ //{
FoamTaskFeedback(taskCode); // try
} // {
// string taskCode = string.Empty;
// string executePlanCode = string.Empty;
// int iFlag = 0;
// completedTasks = 0;
// //获取待执行的出库任务下发至PLC,并将任务状态改为执行中
// var taskInfoList = GetAwaitSendTask();
// if (taskInfoList.Count > 0)
// {
// taskAmount = taskInfoList.Count; //下发的任务数量默认2泡后、内胆泡后、内胆均执行完成后才会释放信号量
// foreach (var item in taskInfoList)
// {
// taskCode = item.taskCode;
// executePlanCode = item.planCode;
// if (taskHandleBusiness.SendFoamTask_OutStore(item))
// {
// PrintLogInfoMessage($"下发泡后出库任务:{item.taskCode};仓库{item.storeCode};货道:{item.spaceCode}等待PLC执行反馈");
// iFlag++;
// item.taskStatus = 2;
// }
// else
// {
// PrintLogInfoMessage($"泡后出库任务:{item.taskCode}下发失败请排除PLC连接");
// continue;
// }
// _taskInfoService.UpdateTaskInfo(item);
// RefreshScanMateriaCodeEvent?.Invoke(item.materialCode, item.materialType, item.spaceName, item.storeCode);
// }
// if (iFlag == taskInfoList.Count)
// {
// inStoreBusiness.IssueOutTask();
// semaphore.Wait(); //一直堵塞直到信号量释放
// inStoreBusiness.IssueInTask();
// PrintLogInfoMessage($"出库任务:{taskCode};执行完成");
// UpdatePlanInfo(executePlanCode);
// RefreshStoreStockEvent?.Invoke();
// }
// }
// else
// {
// PrintLogInfoMessage("未获取到需要下发的出库任务");
// }
// }catch(Exception ex)
// {
// PrintLogErrorMessage("下传出库任务逻辑处理异常", ex);
// }
// Thread.Sleep(3000);
//}
///// <summary>
///// 获取待执行的出库任务
///// </summary>
///// <returns></returns>
//private List<RealTaskInfo> GetAwaitSendTask()
//{
// List<RealTaskInfo> taskInfos = new List<RealTaskInfo>();
// try
// {
// RealTaskInfo foamTaskInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.foamStoreCode, 2);
// if (foamTaskInfo != null)
// {
// taskInfos.Add(foamTaskInfo);
// //获取与泡后任务匹配的内胆任务
// RealTaskInfo linerTaskInfo = _taskInfoService.GetTaskInfoByTaskCode(foamTaskInfo.taskCode, appConfig.linerStoreCode);
// if (linerTaskInfo != null) taskInfos.Add(linerTaskInfo);
// }
// else
// {
// RealTaskInfo linerInfo = _taskInfoService.GetTaskInfoByStoreCode(appConfig.linerStoreCode, 2);
// if (linerInfo != null) taskInfos.Add(linerInfo);
// }
// }
// catch (Exception ex)
// {
// PrintLogErrorMessage("获取待执行的出库任务异常", ex);
// }
// return taskInfos;
//}
#endregion
#region PLC应答反馈
/// <summary> /// <summary>
/// 泡后执行反馈 /// 出库应答
/// </summary> /// </summary>
private void FoamTaskFeedback(string taskCode) /// <param name="storeCode"></param>
/// <param name="taskCode"></param>
private void OutStoreAnswer(string storeCode, string taskCode)
{ {
Interlocked.Increment(ref completedTasks); PrintLogInfoMessage("PLC应答成功自动释放信号量进行下发新任务");
CheckCompletedTasks();
PrintLogInfoMessage("泡后执行完成,自动释放信号量"); semaphore.Release();
OutStoreFinish(taskCode, appConfig.foamStoreCode); inStoreBusiness.IssueOutTask();//阻塞入库
} }
/// <summary> /// <summary>
/// 信号量释放,根据任务完成数量,执行完成后进行释放 /// 出库完成
/// </summary> /// </summary>
private void CheckCompletedTasks() /// <param name="storeCode"></param>
/// <param name="taskCode"></param>
private void OutStoreFinish(string storeCode, string taskCode)
{ {
if (completedTasks == taskAmount) PrintLogInfoMessage($"出库任务:{taskCode};执行完成");
{ OutStoreFinishHandle(taskCode, appConfig.linerStoreCode);
// 释放信号量
semaphore.Release(); inStoreBusiness.IssueInTask(); //释放入库
}
} }
#endregion
#endregion #endregion
@ -442,7 +504,7 @@ namespace Aucma.Scada.Business
/// <param name="storeCode"></param> /// <param name="storeCode"></param>
/// <param name="spaceCode"></param> /// <param name="spaceCode"></param>
/// <param name="materialType"></param> /// <param name="materialType"></param>
private void OutStoreFinish(string taskCode, string storeCode) private void OutStoreFinishHandle(string taskCode, string storeCode)
{ {
try try
{ {
@ -453,6 +515,7 @@ namespace Aucma.Scada.Business
if (spaceInfo != null) if (spaceInfo != null)
{ {
taskHandleBusiness.WritePlc(spaceInfo.storeCode, spaceInfo.spaceCode);
//读取PLC获取货道信息存放数量、在途数量 //读取PLC获取货道信息存放数量、在途数量
spaceInfo.spaceStock -= 1; spaceInfo.spaceStock -= 1;
spaceInfo.outRouteAmount -= 1; spaceInfo.outRouteAmount -= 1;
@ -470,8 +533,6 @@ namespace Aucma.Scada.Business
} }
_spaceInfoService.UpdateSpaceInfo(spaceInfo); _spaceInfoService.UpdateSpaceInfo(spaceInfo);
//读取PLC获取物料类型进行绑定
#region 添加出库记录 #region 添加出库记录
RecordOutstore recordOutstore = new RecordOutstore(); RecordOutstore recordOutstore = new RecordOutstore();
recordOutstore.storeCode = taskInfo.storeCode; recordOutstore.storeCode = taskInfo.storeCode;
@ -484,6 +545,12 @@ namespace Aucma.Scada.Business
_recordOutStoreService.InsertReocrdOutStoreService(recordOutstore); _recordOutStoreService.InsertReocrdOutStoreService(recordOutstore);
#endregion #endregion
} }
//更新计划信息
UpdatePlanInfo(taskInfo.planCode);
RefreshStoreStockEvent?.Invoke();
//清除任务信息 //清除任务信息
_taskInfoService.DeleteTaskInfo(taskCode, storeCode); _taskInfoService.DeleteTaskInfo(taskCode, storeCode);
@ -679,6 +746,8 @@ namespace Aucma.Scada.Business
return materialName; return materialName;
} }
#region 通过PLC读取货道信息
/// <summary>
/// 通过PLC读取货道信息在库数量、货道状态) /// 通过PLC读取货道信息在库数量、货道状态)
/// </summary> /// </summary>
/// <param name="storeCode"></param> /// <param name="storeCode"></param>
@ -690,7 +759,7 @@ namespace Aucma.Scada.Business
try try
{ {
List<BaseSpaceInfo> info = _spaceInfoService.GetBaseSpaceInfosByMaterialType(storeCode, materialType); List<BaseSpaceInfo> info = _spaceInfoService.OutStoreGetSpaceInfoByMaterialCode(storeCode, materialType);
if (info != null) if (info != null)
{ {
@ -702,9 +771,21 @@ namespace Aucma.Scada.Business
item.spaceStock = spaceInfo.spaceStock; item.spaceStock = spaceInfo.spaceStock;
item.onRouteAmount = spaceInfo.onRouteAmount; item.onRouteAmount = spaceInfo.onRouteAmount;
item.spaceStatus = spaceInfo.spaceStatus; item.spaceStatus = spaceInfo.spaceStatus;
PrintLogInfoMessage($"通过PLC读取货道信息货道{spaceInfo.spaceName};在库数量:{item.spaceStock};货道状态:{item.spaceStatus}");
} }
result = info.Where(x => x.spaceStatus == 1 && x.spaceStock > 0).OrderBy(x => x.spaceStock).OrderBy(x => x.spaceCode).First(); //result = info.Where(x => x.spaceStatus == 1 && x.spaceStock > 0).OrderBy(x => x.spaceStock).OrderBy(x => x.spaceCode).First();
var list = info.Where(x => x.spaceStatus == 1 && x.spaceStock > 0).ToList();
if (list.Count > 0)
{
result = info.OrderBy(x => x.spaceStock).OrderBy(x => x.spaceCode).First();
}
else
{
PrintLogInfoMessage("未获取到匹配的货道,请排查货道库存及货道状态是否可用");
}
} }
} }
@ -716,5 +797,6 @@ namespace Aucma.Scada.Business
return result; return result;
} }
#endregion
} }
} }

@ -4,6 +4,7 @@ using HighWayIot.Log4net;
using HighWayIot.Plc; using HighWayIot.Plc;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -47,12 +48,12 @@ namespace Aucma.Scada.Business
/// <summary> /// <summary>
/// 泡后任务编号,PLC反馈后进行赋值 /// 泡后任务编号,PLC反馈后进行赋值
/// </summary> /// </summary>
private string shellTaskCode = string.Empty; private string foamRearTaskCode = string.Empty;
/// <summary> /// <summary>
/// 内胆任务编号,PLC反馈后进行赋值 /// 已下传的任务信息
/// </summary> /// </summary>
private string linerTaskCode = string.Empty; private List<RealTaskInfo> foamRearTaskInfos = new List<RealTaskInfo>();
#endregion #endregion
#region 委托事件 #region 委托事件
@ -63,12 +64,21 @@ namespace Aucma.Scada.Business
/// <param name="taskCode"></param> /// <param name="taskCode"></param>
public delegate void OutStoreFinsih(string storeCode, string taskCode); public delegate void OutStoreFinsih(string storeCode, string taskCode);
public event OutStoreFinsih OutStoreFinsihEvent; public event OutStoreFinsih OutStoreFinsihEvent;
/// <summary>
/// PLC应答
/// </summary>
/// <param name="storeCode"></param>
/// <param name="taskCode"></param>
public delegate void OutStoreAnswer(string storeCode, string taskCode);
public event OutStoreAnswer OutStoreAnswerEvent;
#endregion #endregion
private OutStoreTaskHandle() private OutStoreTaskHandle()
{ {
_plcDictionary = _pool.GetAll(); _plcDictionary = _pool.GetAll();
RealReadShellFinish();
} }
#region 泡后出库任务下发处理 #region 泡后出库任务下发处理
@ -97,7 +107,7 @@ namespace Aucma.Scada.Business
_plc.writeStringByAddress(plcConfig.out_foam_task, taskInfo.taskCode); _plc.writeStringByAddress(plcConfig.out_foam_task, taskInfo.taskCode);
//写入完成后读取应答字进行复位 //写入完成后读取应答字进行复位
ReadShellAnswer_OutStore(taskInfo.taskCode); ReadShellAnswer_OutStore(taskInfo);
result = true; result = true;
} }
@ -122,7 +132,7 @@ namespace Aucma.Scada.Business
/// <summary> /// <summary>
/// 读取泡后出库应答 /// 读取泡后出库应答
/// </summary> /// </summary>
private void ReadShellAnswer_OutStore(string taskCode) private void ReadShellAnswer_OutStore(RealTaskInfo taskInfo)
{ {
lock (string.Empty) lock (string.Empty)
{ {
@ -151,7 +161,11 @@ namespace Aucma.Scada.Business
_plc.writeStringByAddress(plcConfig.out_foam_task, string.Empty); _plc.writeStringByAddress(plcConfig.out_foam_task, string.Empty);
isFlag = false; isFlag = false;
ReadShellFinish_OutStore(taskCode); //ReadShellFinish_OutStore(taskInfo.taskCode);
OutStoreAnswerEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
foamRearTaskInfos.Add(taskInfo);
} }
Thread.Sleep(1000); Thread.Sleep(1000);
@ -178,13 +192,13 @@ namespace Aucma.Scada.Business
/// <summary> /// <summary>
/// 读取泡后出库完成 /// 读取泡后出库完成
/// </summary> /// </summary>
private void ReadShellFinish_OutStore(string taskCode) private void ReadShellFinish_OutStore(RealTaskInfo taskInfo)
{ {
lock (string.Empty) lock (string.Empty)
{ {
bool isFlag = true; bool isFlag = true;
IPlc _plc = _plcDictionary[appConfig.foamStoreCode]; IPlc _plc = _plcDictionary[appConfig.foamStoreCode];
shellTaskCode = taskCode; foamRearTaskCode = taskInfo.taskCode;
try try
{ {
Task.Run(() => Task.Run(() =>
@ -202,7 +216,7 @@ namespace Aucma.Scada.Business
//string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10); //string taskCode = _plc.readStringByAddress(plcConfig.out_foam_task, 10);
OutStoreFinsihEvent?.Invoke(appConfig.foamStoreCode, taskCode); OutStoreFinsihEvent?.Invoke(appConfig.shellStoreCode, taskInfo.taskCode);
isFlag = false; isFlag = false;
} }
@ -229,6 +243,34 @@ namespace Aucma.Scada.Business
} }
#endregion #endregion
#region 出库完成
/// <summary>
/// 实时读取箱壳出库完成
/// </summary>
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
/// <summary> /// <summary>
/// 通过PLC获取货道信息 /// 通过PLC获取货道信息
/// </summary> /// </summary>
@ -251,5 +293,29 @@ namespace Aucma.Scada.Business
return spaceInfo; return spaceInfo;
} }
/// <summary>
/// 测试方法,联调时不用
/// </summary>
/// <param name="storeCode"></param>
/// <param name="spaceCode"></param>
/// <param name="flag"></param>
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);
}
}
}
} }
} }

@ -22,7 +22,7 @@ namespace HighWayIot.Repository.service
/// <param name="store"></param> /// <param name="store"></param>
/// <param name="materialType"></param> /// <param name="materialType"></param>
/// <returns></returns> /// <returns></returns>
BaseSpaceInfo OutStoreGetSpaceInfoByMaterialCode(string store, string materialCode); List<BaseSpaceInfo> OutStoreGetSpaceInfoByMaterialCode(string store, string materialCode);
/// <summary> /// <summary>
/// 通过货道编号获取货道信息 /// 通过货道编号获取货道信息
@ -53,5 +53,11 @@ namespace HighWayIot.Repository.service
/// <param name="spaceInfo"></param> /// <param name="spaceInfo"></param>
/// <returns></returns> /// <returns></returns>
bool UpdateSpaceInfo(BaseSpaceInfo spaceInfo); bool UpdateSpaceInfo(BaseSpaceInfo spaceInfo);
/// <summary>
/// 获取空货道:未分配物料型号的空白货道
/// </summary>
/// <returns></returns>
List<BaseSpaceInfo> GetEmptySpaceInfo(string store);
} }
} }

@ -81,7 +81,7 @@ namespace HighWayIot.Repository.service.Impl
/// 获取空货道:未分配物料型号的空白货道 /// 获取空货道:未分配物料型号的空白货道
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private List<BaseSpaceInfo> GetEmptySpaceInfo(string store) public List<BaseSpaceInfo> GetEmptySpaceInfo(string store)
{ {
List<BaseSpaceInfo> spaceInfos = null; List<BaseSpaceInfo> spaceInfos = null;
try try
@ -103,26 +103,25 @@ namespace HighWayIot.Repository.service.Impl
/// <param name="store"></param> /// <param name="store"></param>
/// <param name="materialType"></param> /// <param name="materialType"></param>
/// <returns></returns> /// <returns></returns>
public BaseSpaceInfo OutStoreGetSpaceInfoByMaterialCode(string store, string materialType) public List<BaseSpaceInfo> OutStoreGetSpaceInfoByMaterialCode(string store, string materialType)
{ {
BaseSpaceInfo spaceInfo = null; List<BaseSpaceInfo> spaceInfos = null;
List<BaseSpaceInfo> spaceInfos;
try try
{ {
Expression<Func<BaseSpaceInfo, bool>> exp = s1 => true; Expression<Func<BaseSpaceInfo, bool>> exp = s1 => true;
exp = exp.And(x => x.storeCode == store && x.materialType == materialType && x.spaceStatus == 1 && x.spaceStock - x.outRouteAmount > 0); //相同型号、启用状态、库存不为空的货道信息 exp = exp.And(x => x.storeCode == store && x.materialType == materialType && x.spaceStatus == 1); //相同型号、启用状态、库存不为空的货道信息
spaceInfos = _mesRepository.GetList(exp); spaceInfos = _mesRepository.GetList(exp);
logHelper.Info($"根据仓库{store};物料:{materialType};获取到的货道信息:{jsonChange.ModeToJson(spaceInfos)}"); logHelper.Info($"根据仓库{store};物料:{materialType};获取到的货道信息:{jsonChange.ModeToJson(spaceInfos)}");
spaceInfo = outStoreFilter(spaceInfos); //spaceInfo = outStoreFilter(spaceInfos);
logHelper.Info($"仓库{store};物料:{materialType};匹配的入库货道信息:{jsonChange.ModeToJson(spaceInfo)}"); //logHelper.Info($"仓库{store};物料:{materialType};匹配的入库货道信息:{jsonChange.ModeToJson(spaceInfo)}");
} }
catch (Exception ex) catch (Exception ex)
{ {
logHelper.Error("出库通过物料类型获取货道信息异常", ex); logHelper.Error("出库通过物料类型获取货道信息异常", ex);
} }
return spaceInfo; return spaceInfos;
} }
/// <summary> /// <summary>

Loading…
Cancel
Save