|
|
|
|
using HslCommunication.Secs.Types;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Npgsql.Replication.TestDecoding;
|
|
|
|
|
using SlnMesnac.Business.@base;
|
|
|
|
|
using SlnMesnac.Common;
|
|
|
|
|
using SlnMesnac.Common.Model;
|
|
|
|
|
using SlnMesnac.Config;
|
|
|
|
|
using SlnMesnac.Model.domain;
|
|
|
|
|
using SlnMesnac.Model.dto;
|
|
|
|
|
using SlnMesnac.Model.enums;
|
|
|
|
|
using SlnMesnac.Plc;
|
|
|
|
|
using SlnMesnac.Repository.service;
|
|
|
|
|
using SlnMesnac.Repository.service.Impl;
|
|
|
|
|
using SlnMesnac.Rfid;
|
|
|
|
|
using SlnMesnac.Rfid.Dto;
|
|
|
|
|
using SlnMesnac.TouchSocket;
|
|
|
|
|
using SqlSugar;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Transactions;
|
|
|
|
|
using TouchSocket.Core;
|
|
|
|
|
using TouchSocket.Sockets;
|
|
|
|
|
|
|
|
|
|
#region << 版 本 注 释 >>
|
|
|
|
|
/*--------------------------------------------------------------------
|
|
|
|
|
* 版权所有 (c) 2024 WenJY 保留所有权利。
|
|
|
|
|
* CLR版本:4.0.30319.42000
|
|
|
|
|
* 机器名称:LAPTOP-E0N2L34V
|
|
|
|
|
* 命名空间:SlnMesnac.Business
|
|
|
|
|
* 唯一标识:655997bf-2bdb-4426-bc49-6fd8def3b395
|
|
|
|
|
*
|
|
|
|
|
* 创建者:WenJY
|
|
|
|
|
* 电子邮箱:wenjy@mesnac.com
|
|
|
|
|
* 创建时间:2024-04-07 16:58:59
|
|
|
|
|
* 版本:V1.0.0
|
|
|
|
|
* 描述:
|
|
|
|
|
*
|
|
|
|
|
*--------------------------------------------------------------------
|
|
|
|
|
* 修改人:
|
|
|
|
|
* 时间:
|
|
|
|
|
* 修改说明:
|
|
|
|
|
*
|
|
|
|
|
* 版本:V1.0.0
|
|
|
|
|
*--------------------------------------------------------------------*/
|
|
|
|
|
#endregion << 版 本 注 释 >>
|
|
|
|
|
namespace SlnMesnac.Business
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 设备生产管理业务类 -3F
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class ProdMgmtBusiness : BaseBusiness
|
|
|
|
|
{
|
|
|
|
|
public readonly IMesProductPlanService _mesProductPlanService;
|
|
|
|
|
|
|
|
|
|
public readonly IBasePalletInfoService _basePalletInfoService;
|
|
|
|
|
|
|
|
|
|
public readonly IMesPrdBarCodeService _mesPrdBarCodeService;
|
|
|
|
|
|
|
|
|
|
public readonly IBaseRealTaskService _baseRealTaskService;
|
|
|
|
|
|
|
|
|
|
public readonly IWmsOutStockService _wmsOutStockService;
|
|
|
|
|
|
|
|
|
|
private readonly ConfigInfoBusiness _configInfoBusiness;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 消息弹框提示
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="msg"></param>
|
|
|
|
|
public delegate void MsgHandler(string message, int msgtype, int outTime = 3);
|
|
|
|
|
public static event MsgHandler MsgHandlerEvent;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private ISqlSugarClient sqlSugarClient;
|
|
|
|
|
private DebugConfig debugConfig = DebugConfig.Instance;
|
|
|
|
|
|
|
|
|
|
public ProdMgmtBusiness(ISqlSugarClient _sqlSugarClient, IWmsOutStockService wmsOutStockService, ILogger<ProdMgmtBusiness> logger, AppConfig appConfig, List<PlcAbsractFactory> plcFactories, List<RfidAbsractFactory> rfidFactories, IMesProductPlanService mesProductPlanService, IBasePalletInfoService basePalletInfoService, IBaseRealTaskService baseRealTaskService, IServiceProvider serviceProvider, ConfigInfoBusiness configInfoBusiness) : base(logger, appConfig, plcFactories, rfidFactories, serviceProvider)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
sqlSugarClient = _sqlSugarClient;
|
|
|
|
|
_wmsOutStockService = wmsOutStockService;
|
|
|
|
|
_mesProductPlanService = mesProductPlanService;
|
|
|
|
|
_basePalletInfoService = basePalletInfoService;
|
|
|
|
|
_baseRealTaskService = baseRealTaskService;
|
|
|
|
|
_mesPrdBarCodeService = serviceProvider.GetRequiredService<IMesPrdBarCodeService>();
|
|
|
|
|
_configInfoBusiness = configInfoBusiness;
|
|
|
|
|
|
|
|
|
|
// TestTran();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void TestTran()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//try
|
|
|
|
|
//{
|
|
|
|
|
// sqlSugarClient.AsTenant().BeginTran();
|
|
|
|
|
// BaseRealTask localPlan = _baseRealTaskService.GetExeTask();
|
|
|
|
|
// localPlan.Status = 2;
|
|
|
|
|
// sqlSugarClient.AsTenant().GetConnection("local").Updateable(localPlan).ExecuteCommand();
|
|
|
|
|
// GenerateBarcode(40);
|
|
|
|
|
// // throw new Exception("事务测试");
|
|
|
|
|
// sqlSugarClient.AsTenant().CommitTran();
|
|
|
|
|
// Console.WriteLine("提交事务");
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
//catch (Exception ex)
|
|
|
|
|
//{
|
|
|
|
|
// sqlSugarClient.AsTenant().RollbackTran();
|
|
|
|
|
// Console.WriteLine(ex.Message);
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void testRFID()
|
|
|
|
|
{
|
|
|
|
|
//TcpClient tcpClient = new TcpClient();
|
|
|
|
|
|
|
|
|
|
//var waitClient = tcpClient.CreateWaitingClient(new WaitingOptions()
|
|
|
|
|
//{
|
|
|
|
|
// FilterFunc = response =>
|
|
|
|
|
// {
|
|
|
|
|
// return true;
|
|
|
|
|
// }
|
|
|
|
|
//});
|
|
|
|
|
//tcpClient.Setup(new TouchSocketConfig().SetRemoteIPHost($"192.168.2.51:3000"));
|
|
|
|
|
//tcpClient.Connect();
|
|
|
|
|
// byte[] reciveBuffer = await waitClient.SendThenReturnAsync(pMessagePack.m_pData, timeout);
|
|
|
|
|
string aaa = await ReadEpcStrByRfidKeyAsync("secondFloorPallet");
|
|
|
|
|
// ReadEpcStrByRfidKey("test", out string epcStr);
|
|
|
|
|
Console.WriteLine(aaa);
|
|
|
|
|
//RefreshMessage($"投料校验RFID标签读取成功,标签信息:{epcStr}");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 委托事件
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新计划列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
public delegate void RefreshProdPlanList(List<MesProductPlanDto> list);
|
|
|
|
|
public event RefreshProdPlanList? RefreshProdPlanListEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新执行计划
|
|
|
|
|
/// </summary>
|
|
|
|
|
public delegate void RefreshProdPlanExec(MesProductPlan productPlan);
|
|
|
|
|
public event RefreshProdPlanExec? RefreshProdPlanExecEvent;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 投料确认,validType确认类型:1-读取失败重新读取;2-校验失败是否投料
|
|
|
|
|
/// </summary>
|
|
|
|
|
public delegate bool MatPutInValid(int validType, MesProductPlan productPlan, string materialName, string msg);
|
|
|
|
|
public event MatPutInValid? MatPutInValidEvent;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void InitProdPlan()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
RefreshMesProdList();
|
|
|
|
|
Task.Run(() => { ProdPlanExecHandle(); });
|
|
|
|
|
Task.Run(() => { MaterialPutInCheck(); });
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 刷新计划执行列表
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void RefreshMesProdList()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// var aaa = _mesProductPlanService.GetMesProductPlans();
|
|
|
|
|
var info = _mesProductPlanService.GetPlanDtos();
|
|
|
|
|
RefreshProdPlanListEvent?.Invoke(info);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"MES生产计划获取异常:{ex.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 计划执行,叫料逻辑处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void ProdPlanExecHandle()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
//每5秒执行一次,获取是否有已开始的计划,获取已开始的计划下发给WCS进行叫料,获取货架到位信息进行投料校验,持续获取设备要料信号
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
RefreshMesProdList();
|
|
|
|
|
var plc = base.GetPlcByKey("plc");
|
|
|
|
|
|
|
|
|
|
if (plc == null)
|
|
|
|
|
{
|
|
|
|
|
//throw new ArgumentException($"PLC连接信息为空");
|
|
|
|
|
RefreshMessage($"PLC连接信息为空");
|
|
|
|
|
Thread.Sleep(3000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!plc.readBoolByAddress(GetPlcAddressByConfigKey("设备叫料")))
|
|
|
|
|
{
|
|
|
|
|
// RefreshMessage("3F等待设备叫料信号触发......");
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_mesProductPlanService.GetStartedProdPlan(out MesProductPlanDto productPlanDto);
|
|
|
|
|
if (productPlanDto == null)
|
|
|
|
|
{
|
|
|
|
|
//throw new ArgumentException($"未获取到需要执行的生产计划");
|
|
|
|
|
RefreshMessage($"3F未获取到需要执行的生产计划");
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WcsTaskManual wcsTaskManual = sqlSugarClient.AsTenant().GetConnection("mes").Queryable<WcsTaskManual>().Where(x=>x.TaskType==999).First();
|
|
|
|
|
WcsTask wcsTask = sqlSugarClient.AsTenant().GetConnection("mes").Queryable<WcsTask>().Where(x=>x.NextPointId==9 && x.TaskType==41).First();
|
|
|
|
|
if(wcsTaskManual!=null || wcsTask != null)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("3F已经叫料,请等待AGV送料......");
|
|
|
|
|
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//BaseRealTask task = _baseRealTaskService.GetExeTask();
|
|
|
|
|
//if (task != null)
|
|
|
|
|
//{
|
|
|
|
|
// RefreshMessage("已经叫料,请等待AGV送料......");
|
|
|
|
|
|
|
|
|
|
// Thread.Sleep(5000);
|
|
|
|
|
// continue;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RefreshMessage("3F设备要料信号触发成功");
|
|
|
|
|
|
|
|
|
|
// RefreshProdPlanExecEvent?.Invoke(prodPlan);
|
|
|
|
|
|
|
|
|
|
// string palletCode = GetPalletInfoByTask();
|
|
|
|
|
|
|
|
|
|
RefreshMessage($"执行计划:{productPlanDto.PlanCode};计划数量:{Math.Round(productPlanDto.PlanAmount, 2)};完成数量:{Math.Round(productPlanDto.CompleteAmount, 2)};发起叫料申请");
|
|
|
|
|
|
|
|
|
|
//查询下发agv的主键
|
|
|
|
|
WmsRawOutstock wmsRaw = _wmsOutStockService.GetProdPlanByPlanCode(productPlanDto.PlanCode);
|
|
|
|
|
if (wmsRaw == null && debugConfig.ProductMode != "1") //不是手动模式,没有申请单
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("自动模式,查询不到该计划出库申请单,请先创建...");
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//进行叫料
|
|
|
|
|
if (ApplyDeliveryHandle(wmsRaw))
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("3F根据计划自动申请叫料成功");
|
|
|
|
|
#region 本地创建一个叫料任务
|
|
|
|
|
//BaseRealTask realTask = new BaseRealTask();
|
|
|
|
|
//realTask.PlanCode = prodPlan.PlanCode;
|
|
|
|
|
//realTask.PlanAmount = prodPlan.PlanAmount;
|
|
|
|
|
//realTask.PlanComplete = prodPlan.CompleteAmount;
|
|
|
|
|
//realTask.MaterialId = prodPlan.MaterialId;
|
|
|
|
|
//realTask.Status = 1;
|
|
|
|
|
//realTask.CreateTime = DateTime.Now;
|
|
|
|
|
//realTask.UpdateTime = DateTime.Now;
|
|
|
|
|
//_baseRealTaskService.InsertTask(realTask);
|
|
|
|
|
#endregion
|
|
|
|
|
plc.writeBoolByAddress(GetPlcAddressByConfigKey("设备叫料"), false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("根据计划自动申请叫料失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"计划执行逻辑处理异常:{e.Message}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 投料校验:轮询物料到位信号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <exception cref="ArgumentException"></exception>
|
|
|
|
|
public void MaterialPutInCheck()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
var plc = base.GetPlcByKey("plc");
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
//mes计划
|
|
|
|
|
// MesProductPlan prodPlan = null;
|
|
|
|
|
//本地叫料任务
|
|
|
|
|
// BaseRealTask localPlan = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// localPlan = _baseRealTaskService.GetExeTask();
|
|
|
|
|
|
|
|
|
|
//if (localPlan == null)
|
|
|
|
|
//{
|
|
|
|
|
// RefreshMessage("本地未获取到叫料任务......");
|
|
|
|
|
// Thread.Sleep(3000);
|
|
|
|
|
// continue;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (plc == null)
|
|
|
|
|
{
|
|
|
|
|
// RefreshMessage("读取物料到位信号,PLC连接信息为空......");
|
|
|
|
|
Thread.Sleep(3000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
//判断请求翻转信号
|
|
|
|
|
if (!plc.readBoolByAddress(GetPlcAddressByConfigKey("物料到位")))
|
|
|
|
|
{
|
|
|
|
|
// RefreshMessage("等待物料到位信号触发......");
|
|
|
|
|
Thread.Sleep(3000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WcsTask wcsTask = sqlSugarClient.AsTenant().GetConnection("mes").Queryable<WcsTask>().Where(x => x.NextPointId == 9 && (x.TaskType == 41 || x.TaskType == 42)).First();
|
|
|
|
|
if (wcsTask == null)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("3F到位信号触发,但是未检测到有原材料出库任务......");
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO 投料时间校验
|
|
|
|
|
bool timeCheck = JudgeProductTime();
|
|
|
|
|
if (!timeCheck)
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(1000 * 15);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
RefreshMessage($"3F投料时间校验通过");
|
|
|
|
|
|
|
|
|
|
// 调用调度接口,判断AGV小车是否已经离开到位,否则不允许投料
|
|
|
|
|
bool positionCheck = JudgeAgvPosition();
|
|
|
|
|
if (!positionCheck)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage($"3F收到物料到位信号,但是AGV还未离开,禁止投料");
|
|
|
|
|
Thread.Sleep(1000 * 5);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO根据本地叫料计划查询对应的mes计划,完成
|
|
|
|
|
_mesProductPlanService.GetStartedProdPlan(out MesProductPlanDto productPlanDto);
|
|
|
|
|
|
|
|
|
|
if (productPlanDto == null)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage($"3F收到物料到位信号,未获取到正在执行的生产计划,请开始执行计划");
|
|
|
|
|
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region 物料校验 -- TODO 如果计划暂停,开启新计划,校验当前滞留物料是与前一条计划判断,还是当前开始的计划判断
|
|
|
|
|
//RefreshMessage("物料到位信号触发成功,读取托盘RFID信息进行投料校验");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//ReadEpcStrByRfidKey("test", out string epcStr);
|
|
|
|
|
//RefreshMessage($"投料校验RFID标签读取成功,标签信息:{epcStr}");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////获取物料托盘上的物料信息
|
|
|
|
|
//BasePalletInfo palletInfo = _basePalletInfoService.GetPalletInfoByPalletCode(epcStr);
|
|
|
|
|
//if (palletInfo == null)
|
|
|
|
|
//{
|
|
|
|
|
// result = MatPutInValidTriggerEvent(2, prodPlan, string.Empty, "投料校验失败,未获取到托盘信息,是否继续投料");
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
//{
|
|
|
|
|
// if (palletInfo.MaterialId != prodPlan.MaterialId)
|
|
|
|
|
// {
|
|
|
|
|
// result = MatPutInValidTriggerEvent(2, prodPlan, string.Empty, "投料校验失败,物料信息不匹配,是否继续投料");
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
// result = true;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
//if (result)
|
|
|
|
|
//{
|
|
|
|
|
// bool isRes = _basePalletInfoService.UnBindPalletInfo(palletInfo);
|
|
|
|
|
// RefreshMessage($"物料校验通过,托盘信息解绑{(isRes ? "成功" : "失败")}");
|
|
|
|
|
//}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
if (productPlanDto != null)
|
|
|
|
|
{
|
|
|
|
|
// 下发翻转信号
|
|
|
|
|
plc.writeBoolByAddress(GetPlcAddressByConfigKey("设备投料"), true);
|
|
|
|
|
Thread.Sleep(300);
|
|
|
|
|
plc.writeBoolByAddress(GetPlcAddressByConfigKey("设备投料"), false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sqlSugarClient.AsTenant().BeginTran();
|
|
|
|
|
//1.完成本地计划
|
|
|
|
|
//if (localPlan != null)
|
|
|
|
|
//{
|
|
|
|
|
// List<BaseRealTask> localList = _baseRealTaskService.Query(x => x.Status != 2);
|
|
|
|
|
// foreach (var item in localList)
|
|
|
|
|
// {
|
|
|
|
|
// item.Status = 2;
|
|
|
|
|
// item.UpdateTime = DateTime.Now;
|
|
|
|
|
// }
|
|
|
|
|
// sqlSugarClient.AsTenant().GetConnection("local").Updateable(localList).ExecuteCommand();
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
//2.生成小包条码
|
|
|
|
|
GenerateBarcode(40);
|
|
|
|
|
|
|
|
|
|
//BaseConfigInfo configInfo = _configInfoBusiness.GetConfigInfos().Where(x => x.ConfigKey == "系统运行时长").FirstOrDefault();
|
|
|
|
|
//configInfo.ConfigValue = "0";
|
|
|
|
|
//sqlSugarClient.AsTenant().GetConnection("local").Updateable(configInfo).ExecuteCommand();
|
|
|
|
|
//_configInfoBusiness.RefreshConfigInfo();
|
|
|
|
|
|
|
|
|
|
sqlSugarClient.AsTenant().CommitTran();
|
|
|
|
|
//3.清空投料系统运行时间
|
|
|
|
|
BaseConfigInfo configInfo = _configInfoBusiness.GetConfigInfos().Where(x => x.ConfigKey == "系统运行时长").FirstOrDefault();
|
|
|
|
|
configInfo.ConfigValue = "0";
|
|
|
|
|
_configInfoBusiness.UpdateConfigInfo(configInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
sqlSugarClient.AsTenant().RollbackTran();
|
|
|
|
|
_logger.LogInformation($"投料流程异常:{e.Message}");
|
|
|
|
|
Thread.Sleep(5000);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thread.Sleep(3000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 投料结果处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="prodPlan"></param>
|
|
|
|
|
/// <param name="isRes"></param>
|
|
|
|
|
private void PutInResutlHandle(MesProductPlan prodPlan, bool isRes)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (isRes)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("投料校验完成,允许投料,更新生产计划");
|
|
|
|
|
prodPlan.CompleteAmount += 1;
|
|
|
|
|
if (prodPlan.CompleteAmount >= prodPlan.PlanAmount)
|
|
|
|
|
{
|
|
|
|
|
prodPlan.PlanStatus = PlanStatusEnum.已完成;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_mesProductPlanService.Update(prodPlan);
|
|
|
|
|
|
|
|
|
|
RefreshMesProdList();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("投料校验失败,人工确认不许投料");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"投料结果处理异常:{e.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 投料校验失败,人工确认是否继续投料
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="validType"></param>
|
|
|
|
|
/// <param name="productPlan"></param>
|
|
|
|
|
/// <param name="materialName"></param>
|
|
|
|
|
/// <param name="msg"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private bool MatPutInValidTriggerEvent(int validType, MesProductPlan productPlan, string materialName, string msg)
|
|
|
|
|
{
|
|
|
|
|
return MatPutInValidEvent.Invoke(validType, productPlan, materialName, msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 申请叫料,等待调度接口
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="materialCode"></param>
|
|
|
|
|
/// <param name="result"></param>
|
|
|
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
|
|
|
public bool ApplyDeliveryHandle(WmsRawOutstock wmsRaw)
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//判断当前模式,手动需从出库队列叫料,如果没有出库队列,弹框提醒;自动模式,库位参数为Null
|
|
|
|
|
string targetLocationCode = null;
|
|
|
|
|
if(debugConfig.ProductMode== "1")
|
|
|
|
|
{
|
|
|
|
|
// 手动模式出库队列
|
|
|
|
|
WmsRawPreferredOut? PreferredOut = sqlSugarClient.AsTenant().GetConnection("mes").Queryable<WmsRawPreferredOut>().OrderBy(x=>x.RawPreferredOutId).First();
|
|
|
|
|
if (PreferredOut == null)
|
|
|
|
|
{
|
|
|
|
|
MsgHandlerEvent?.Invoke("当前投料手动模式,无出库队列,请在投料管理添加出库队列,或修改为自动投料模式", 2, 4);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
targetLocationCode = PreferredOut.LocationCode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//if (debugConfig.ProductMode == "1")
|
|
|
|
|
//{ //标记手工叫料
|
|
|
|
|
// taskId = "-1";
|
|
|
|
|
//}
|
|
|
|
|
var content = new
|
|
|
|
|
{
|
|
|
|
|
rawOutstockId = wmsRaw==null?"-1": wmsRaw.rawOutstockId.ToString(),
|
|
|
|
|
locationCode = targetLocationCode,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string message = JsonConvert.SerializeObject(content);
|
|
|
|
|
//询问小车是否离开接口 0已经离开
|
|
|
|
|
string httpResult = HttpHelper.SendPostMessage("172.16.12.100", 5001, "wcs/RecieveRcs/callMaterial", message, "application/Json");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var reponseMessage = JsonConvert.DeserializeObject<ReponseMessage>(httpResult);
|
|
|
|
|
if (reponseMessage != null && reponseMessage.code == "0")
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("Agv叫料成功");
|
|
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage($"申请叫料处理异常:{ex.Message}");
|
|
|
|
|
result = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 投料后产生小包条码存储到数据库等待绑定
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void GenerateBarcode(int amount)
|
|
|
|
|
{
|
|
|
|
|
// JY2408271423CF015
|
|
|
|
|
List<MesPrdBarcodeInfo> list = new List<MesPrdBarcodeInfo>();
|
|
|
|
|
string baseDate = DateTime.Now.ToString("yyyyMMddHHmm"); // 当前日期和时间到分钟
|
|
|
|
|
baseDate = "JY" + baseDate.Substring(2);
|
|
|
|
|
for (int i = 1; i <= amount; i++)
|
|
|
|
|
{
|
|
|
|
|
MesPrdBarcodeInfo record = new MesPrdBarcodeInfo();
|
|
|
|
|
record = new MesPrdBarcodeInfo();
|
|
|
|
|
record.PrdBarcodeInfo = baseDate + "CF" + i.ToString("D3"); // 将序号格式化为三位数
|
|
|
|
|
record.PrintFlag = "0";
|
|
|
|
|
record.CreatTime = DateTime.Now;
|
|
|
|
|
record.BindStatus = 0;
|
|
|
|
|
list.Add(record);
|
|
|
|
|
}
|
|
|
|
|
sqlSugarClient.AsTenant().GetConnection("mes").Insertable(list).ExecuteCommand();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 更新生产计划
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="planInfo"></param>
|
|
|
|
|
public void UpdateProdPlan(MesProductPlanDto planInfo)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (planInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("更新生产计划异常:参数为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var info = _mesProductPlanService.GetProdPlanByPlanCode(planInfo.PlanCode);
|
|
|
|
|
|
|
|
|
|
if (info == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException("更新生产计划异常:根据计划编号获取计划信息为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info.PlanStatus = planInfo.PlanStatus;
|
|
|
|
|
if (!_mesProductPlanService.UpdateProdPlan(info))
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException("生产计划更新失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RefreshMesProdList();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
throw new InvalidOperationException($"生产计划更新异常:{e.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
/// <summary
|
|
|
|
|
/// 距离上次投料时间合格判断
|
|
|
|
|
/// </summary
|
|
|
|
|
private bool JudgeProductTime()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
int IntervalMin = int.Parse(GetPlcAddressByConfigKey("投料时间间隔")); // 单位分钟
|
|
|
|
|
int systemRunTime = int.Parse(GetPlcAddressByConfigKey("系统运行时长")); // 单位分钟
|
|
|
|
|
|
|
|
|
|
if (systemRunTime > IntervalMin)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage($"收到物料到位请求投料信号,投料间隔:{IntervalMin}min,距上次投料:{systemRunTime}min,禁止投料");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"距离上次投料时间合格判断异常JudgeProductTime:{ex.Message}");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool JudgeAgvPosition()
|
|
|
|
|
{
|
|
|
|
|
bool result = false;
|
|
|
|
|
//询问小车是否离开接口 0已经离开
|
|
|
|
|
string httpResult = HttpHelper.SendPostMessage("172.16.12.100", 5001, "wcs/RecieveRcs/AgvTaskComplete", "", "application/Json");
|
|
|
|
|
|
|
|
|
|
var reponseMessage = JsonConvert.DeserializeObject<ReponseMessage>(httpResult);
|
|
|
|
|
if (reponseMessage != null && reponseMessage.code == "0")
|
|
|
|
|
{
|
|
|
|
|
RefreshMessage("Agv已经离开...");
|
|
|
|
|
result = true;
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|