2026-05-28 22:11:13 +08:00
|
|
|
|
using Cowain.Preheat.BLL;
|
|
|
|
|
|
using Cowain.Preheat.Common.Core;
|
2026-05-30 14:36:40 +08:00
|
|
|
|
using Cowain.Preheat.Common.CsvMap;
|
2026-05-28 22:11:13 +08:00
|
|
|
|
using Cowain.Preheat.Common.Enums;
|
|
|
|
|
|
using Cowain.Preheat.Common.Interface;
|
|
|
|
|
|
using Cowain.Preheat.Communication.Interface;
|
|
|
|
|
|
using Cowain.Preheat.Communication.MOM;
|
|
|
|
|
|
using Cowain.Preheat.Main.ViewModels;
|
|
|
|
|
|
using Cowain.Preheat.Model;
|
|
|
|
|
|
using Cowain.Preheat.Model.Models;
|
|
|
|
|
|
using HslCommunication;
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
using Prism.Ioc;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Unity;
|
|
|
|
|
|
using static Cowain.Preheat.Common.Models.MESModel;
|
|
|
|
|
|
using JSON = Newtonsoft.Json.JsonConvert;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Cowain.Preheat.Main.Station
|
|
|
|
|
|
{
|
|
|
|
|
|
public class UnLoadingStation : IServerManager
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Name { get; set; }
|
|
|
|
|
|
public IUnityContainer _unityContainer { get; set; }
|
|
|
|
|
|
IPLCDevice PLC { get; set; }
|
2026-05-30 14:36:40 +08:00
|
|
|
|
public readonly object _lockObj = new object();
|
2026-05-28 22:11:13 +08:00
|
|
|
|
public List<BtnInfoModel> WindowBtnInfo = new List<BtnInfoModel>();
|
|
|
|
|
|
public UnLoadingStation(IUnityContainer unityContainer)
|
|
|
|
|
|
{
|
|
|
|
|
|
_unityContainer = unityContainer;
|
|
|
|
|
|
Start();
|
|
|
|
|
|
|
|
|
|
|
|
Task.Run(async() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
var models = _unityContainer.Resolve<BatteryInfoService>().GetAutoUnLoading();
|
|
|
|
|
|
if (0 == models.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
await Task.Delay(20 * 1000);
|
|
|
|
|
|
LogHelper.Instance.Warn("自动上传电芯-----无");
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
var ids = models.Select(x => x.Id).ToArray();
|
|
|
|
|
|
LogHelper.Instance.Warn($"自动上传电芯:{JSON.SerializeObject(ids)}");
|
|
|
|
|
|
UploadMom(ids);
|
|
|
|
|
|
await Task.Delay(1000);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool IsConnectPLC()
|
|
|
|
|
|
{
|
|
|
|
|
|
PLC = _unityContainer.ResolveAll<IPLCDevice>().FirstOrDefault();
|
|
|
|
|
|
if (null == PLC || !PLC.IsConnect)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Error($"{PLC.Name},PLC为空!");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
public void Start()
|
|
|
|
|
|
{
|
|
|
|
|
|
var stations = _unityContainer.Resolve<StationDetailService>().GetStations(EStationType.UnLoading);
|
|
|
|
|
|
foreach (var item in stations)
|
|
|
|
|
|
{
|
|
|
|
|
|
WindowBtnInfo.Add(new BtnInfoModel
|
|
|
|
|
|
{
|
|
|
|
|
|
Id = item.Number,
|
|
|
|
|
|
StationId = item.StationId,
|
|
|
|
|
|
Name = item.Name,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//int[] aa = new int[10]; aa[1] = 100;
|
|
|
|
|
|
//SetBtnContent(aa);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SetBtnContent(int[] batterys)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 1; i < batterys.Count(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var battery = _unityContainer.Resolve<BatteryInfoService>().GetBattery((uint)batterys[i]);
|
|
|
|
|
|
var item = WindowBtnInfo.Where(x => x.Id == i).FirstOrDefault();
|
|
|
|
|
|
item.StartTime = DateTime.Now;
|
|
|
|
|
|
if (null == battery)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (0 != batterys[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
item.BatteryCode = "无,虚拟码:" + batterys[i].ToString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
item.Desc = "无电芯!";
|
|
|
|
|
|
LogHelper.Instance.Debug($"无电芯,虚拟码:{batterys[i]}");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
item.BatteryCode = battery.BatteryCode;
|
|
|
|
|
|
item.Desc = "正常下料";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CommonCoreHelper.BlockBtnInfo.Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//开始下料 ,,验证数据库OK (分二次执行,一次取假电芯,一次取正常电芯)
|
|
|
|
|
|
public void ExecuteUnLoading(int curValue, string param, Variable node)
|
|
|
|
|
|
{
|
|
|
|
|
|
Int16 replyResult = (int)EResult.OK;
|
|
|
|
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
|
|
|
|
|
if (!IsConnectPLC()) return;
|
|
|
|
|
|
|
|
|
|
|
|
OperateResult<int[]> resultBatterys = PLC.Read<int[]>((string)d.ReadVirtualIds); //可以改成直接读PLC
|
|
|
|
|
|
|
|
|
|
|
|
var writeResult = PLC.Write<Int16>((string)d.WriteResult, replyResult); //回复PLC
|
|
|
|
|
|
if (!writeResult.IsSuccess)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Warn($"ExecutScanBattery-{(string)d.WriteResult}:{writeResult.Message}"); //提高效率
|
|
|
|
|
|
} //会导致没有回复NG(MOM)
|
|
|
|
|
|
|
|
|
|
|
|
if (!resultBatterys.IsSuccess) //读取失败
|
|
|
|
|
|
{
|
|
|
|
|
|
replyResult = (Int16)EResult.NG;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int x = 1; x < resultBatterys.Content.Count(); ++x) //日志异常,里面有0
|
|
|
|
|
|
{
|
|
|
|
|
|
if (0 == resultBatterys.Content[x])
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Fatal($"下料数组中有为0,{JSON.SerializeObject(resultBatterys.Content)}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (resultBatterys.Content.All(n => n == 0))
|
|
|
|
|
|
{
|
|
|
|
|
|
replyResult = (Int16)EResult.NG;
|
|
|
|
|
|
LogHelper.Instance.Warn($"出站电芯虚拟码全部为0,请检查");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SetBtnContent(resultBatterys.Content);
|
|
|
|
|
|
List<TBatteryInfo> batterys = _unityContainer.Resolve<BatteryInfoService>().GetUnLoadingBattery(resultBatterys.Content);
|
|
|
|
|
|
var ids = batterys.Select(x => x.Id).ToArray();
|
|
|
|
|
|
|
|
|
|
|
|
if (0 == batterys.Count) //没有可出站的电芯
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Info($"信号出站:{JSON.SerializeObject(resultBatterys.Content)},已经出过站!");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!SetUnLoading(ids)) //没有出站
|
|
|
|
|
|
{
|
|
|
|
|
|
replyResult = (Int16)EResult.NG;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//var writeResult = PLC.Write<Int16>((string)d.WriteResult, replyResult); //回复PLC,如果全是OK,就在上面回复
|
|
|
|
|
|
//if (!writeResult.IsSuccess)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// LogHelper.Instance.Warn($"ExecutScanBattery-{(string)d.WriteResult}:{writeResult.Message}");
|
|
|
|
|
|
//}
|
|
|
|
|
|
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//正常电芯才可,因为会出现MOM拦截的也出站,(还不能拦截,因为第一次MOM NG,第二次OK,就会出问题)
|
|
|
|
|
|
//下料,上料调用这里
|
|
|
|
|
|
public bool SetUnLoading(int[] batteryIds, bool isOutBound = true)
|
|
|
|
|
|
{
|
|
|
|
|
|
TBatteryInfo model = _unityContainer.Resolve<BatteryInfoService>().GetFristBattery(batteryIds); //只要一个电芯,为的就是知道在哪一层
|
|
|
|
|
|
float controlTemp = _unityContainer.Resolve<ICommonFun>().GetControlTemp(GetLayer(model)); //下料温度
|
|
|
|
|
|
float preheatTemp = GetPreheatTemp(controlTemp); //预热温度
|
|
|
|
|
|
string preheatTime = GetPreheatTime(model); //预热时间
|
|
|
|
|
|
//更新数据库
|
|
|
|
|
|
var taskAsy = _unityContainer.Resolve<BatteryInfoService>().UpdateOutbound(batteryIds, controlTemp, preheatTemp, preheatTime);
|
|
|
|
|
|
LogHelper.Instance.Info($"出站电芯,电芯ID:{JSON.SerializeObject(batteryIds)}");
|
|
|
|
|
|
//上传到Mom
|
|
|
|
|
|
return UploadMom(batteryIds);
|
|
|
|
|
|
}
|
|
|
|
|
|
int GetLayer(TBatteryInfo model)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (null == model)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
return model.Layer ?? 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float GetPreheatTemp(float temp)
|
|
|
|
|
|
{
|
|
|
|
|
|
Random random = new Random();
|
|
|
|
|
|
return temp + (float)Math.Round(random.NextDouble(), 2) - 0.5f;
|
|
|
|
|
|
}
|
|
|
|
|
|
string GetPreheatTime(TBatteryInfo model)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (null == model)
|
|
|
|
|
|
{
|
|
|
|
|
|
return "50分钟1秒";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var diff = DateTime.Now - (model.LoadingTime ?? DateTime.Now);
|
|
|
|
|
|
return $"{(int)(diff.TotalSeconds / 60)}分钟{(int)(diff.TotalSeconds % 60) }秒";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-30 14:36:40 +08:00
|
|
|
|
|
2026-05-28 22:11:13 +08:00
|
|
|
|
|
|
|
|
|
|
//public void GetSuccessBattery(ref int[] batteryIds)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// List<TBatteryNG> failList = _unityContainer.Resolve<BatteryNGService>().GetBatteryInfo(batteryIds);
|
|
|
|
|
|
// if (0 == failList.Count) //全部是正常电芯
|
|
|
|
|
|
// {
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// foreach(var failBattery in failList)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// int index = Array.IndexOf(batteryIds, failBattery.BatteryId); //找到NG电芯位置
|
|
|
|
|
|
// if (-1 == index)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// batteryIds[index] = 0; //NG电芯清0
|
|
|
|
|
|
// LogHelper.Instance.Fatal($"NG不出站1:{failBattery.BatteryId}");
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// LogHelper.Instance.Fatal($"NG不出站2:{JSON.SerializeObject(batteryIds)}");
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//下料,定时检测,上料都会调用这里
|
|
|
|
|
|
private bool UploadMom(int[] batteryIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
//GetSuccessBattery(ref batteryIds); //去掉NG电芯
|
|
|
|
|
|
List<TBatteryInfo> batterys = _unityContainer.Resolve<BatteryInfoService>().GetBatterys(batteryIds);
|
|
|
|
|
|
|
|
|
|
|
|
if (0 == batterys.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Error($"上传出站信息失败,没有找到电芯条码,电芯ID:{string.Join(",", batteryIds)}");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
List<TBatteryInfo> batteryList = batterys
|
|
|
|
|
|
.GroupBy(x => x.BatteryCode)
|
|
|
|
|
|
.Select(g => g.First())
|
|
|
|
|
|
.ToList(); //电芯去重
|
|
|
|
|
|
|
|
|
|
|
|
if (batterys.Count != batteryList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Error($"上传出站电芯有重码,电芯ID:{string.Join(",", batteryIds)}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (11 < batteryIds.Count())
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Fatal($"出站数据大于11,电芯ID:{string.Join(",", batteryIds)}");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-30 14:36:40 +08:00
|
|
|
|
BuildRecordFile(batteryList); //记录出站
|
2026-05-28 22:11:13 +08:00
|
|
|
|
|
|
|
|
|
|
//真实上传MOM
|
|
|
|
|
|
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
|
|
|
|
|
{
|
|
|
|
|
|
MESReturnOutputModel mesResult = _unityContainer.Resolve<MESProcess>().CellOutput(batteryList, "OK", "", "", new List<MaterialInfoModel>());
|
|
|
|
|
|
if (null == mesResult) //是先存到数据库,另外一个线程发,所以一直为null
|
|
|
|
|
|
{
|
|
|
|
|
|
//LogHelper.Instance.Error($"上传出站信息,请求MOM失败,电芯条码:{JSON.SerializeObject(batteryList.Select(x => x.BatteryCode).ToList())}");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mesResult.Info.ResultFlag != EResultFlag.OK.ToString())
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.Error($"上传出站信息,MOM返回NG,返回信息:{JSON.SerializeObject(mesResult)}");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-30 14:36:40 +08:00
|
|
|
|
public void BuildRecordFile(List<TBatteryInfo> batterys)
|
|
|
|
|
|
{
|
|
|
|
|
|
string dateFile = "";
|
|
|
|
|
|
string filePath = "";
|
|
|
|
|
|
string path = _unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DataFilePath.ToString());//
|
|
|
|
|
|
if (null == batterys
|
|
|
|
|
|
|| batterys.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!Directory.Exists(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
dateFile = DateTime.Now.ToString("yyyyMMdd");
|
|
|
|
|
|
filePath = path + $"\\{dateFile}.csv";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// CSVHelper.WriteDataTableToCsv(batteryList, new List<string> { "Id","BatteryCode",
|
|
|
|
|
|
//"PositionX", "PositionY", "Layer", "ScanTime","LoadingTime", "UnLoadingTime", "LodingTemperature",
|
|
|
|
|
|
// "PreheatTemperature","UnLoadingTemperature","PreheatTime"}, new List<string>
|
|
|
|
|
|
//{ "序号", "电芯条码", "行号", "列号", "层号","扫码时间", "上料时间", "下料时间"
|
|
|
|
|
|
//,"上料温度","预热温度","下料温度","预热时长" }, filePath);
|
|
|
|
|
|
|
|
|
|
|
|
//foreach (var item in batteryList)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// if (0 == _unityContainer.Resolve<BatteryInfoService>().UpdateStatus(item.Id, (int)EBatteryStatus.OutBoundRecord))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// LogHelper.Instance.Fatal("修改记录出站状态失败!");
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
lock (_lockObj)
|
|
|
|
|
|
{
|
|
|
|
|
|
CSVHelper.WriteMap<TBatteryInfo, BatteryInfoMap>(batterys, filePath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogHelper.Instance.GetCurrentClassFatal($"{ex.Message},{ex.StackTrace}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-28 22:11:13 +08:00
|
|
|
|
public void Stop()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|