773 lines
35 KiB
C#
773 lines
35 KiB
C#
|
|
using Cowain.Bake.BLL;
|
|||
|
|
using Cowain.Bake.Common;
|
|||
|
|
using Cowain.Bake.Common.Core;
|
|||
|
|
using Cowain.Bake.Common.Enums;
|
|||
|
|
using Cowain.Bake.Common.Interface;
|
|||
|
|
using Cowain.Bake.Common.Models;
|
|||
|
|
using Cowain.Bake.Communication.Interface;
|
|||
|
|
using Cowain.Bake.Communication.MOM;
|
|||
|
|
using Cowain.Bake.Main.ViewModels;
|
|||
|
|
using Cowain.Bake.Main.Views;
|
|||
|
|
using Cowain.Bake.Model;
|
|||
|
|
using Cowain.Bake.Model.Entity;
|
|||
|
|
using Cowain.Bake.Model.Models;
|
|||
|
|
using Cowain.Bake.UI.CsvMap;
|
|||
|
|
using HslCommunication;
|
|||
|
|
using Newtonsoft.Json;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Threading;
|
|||
|
|
using System.Threading.Tasks;
|
|||
|
|
using System.Windows;
|
|||
|
|
using Unity;
|
|||
|
|
using static Cowain.Bake.Common.Models.MESModel;
|
|||
|
|
using JSON = Newtonsoft.Json.JsonConvert;
|
|||
|
|
|
|||
|
|
namespace Cowain.Bake.Main.Station
|
|||
|
|
{
|
|||
|
|
public class UnLoadingStation : IServerManager
|
|||
|
|
{
|
|||
|
|
IPLCDevice PLC { get; set; }
|
|||
|
|
const int DUMMY_POS_SIZE = 3;
|
|||
|
|
private int _batteryCodeLen = 0;
|
|||
|
|
List<IScanCodeBase> _deviceScann = new List<IScanCodeBase>();
|
|||
|
|
List<TBatteryInfo> _tempList = new List<TBatteryInfo>();
|
|||
|
|
public string Name { get; set; }
|
|||
|
|
public IUnityContainer _unityContainer { get; set; }
|
|||
|
|
private readonly Prism.Events.IEventAggregator _eventAggregator;
|
|||
|
|
public UnLoadingStation(IUnityContainer unityContainer, Prism.Events.IEventAggregator eventAggregator)
|
|||
|
|
{
|
|||
|
|
_unityContainer = unityContainer;
|
|||
|
|
_eventAggregator = eventAggregator;
|
|||
|
|
TDeviceConfig config = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.PLC, EDeviceName.Loading)[0]; //上下料一个PLC
|
|||
|
|
Name = config.Name;
|
|||
|
|
SetBatteryCodeLen();
|
|||
|
|
Start();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool IsConnectPLC()
|
|||
|
|
{
|
|||
|
|
if (null == PLC || !PLC.IsConnect)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"PalletVirtualId:{PLC.Name},PLC为空!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
public void Start()
|
|||
|
|
{
|
|||
|
|
var configScann = _unityContainer.Resolve<DeviceConfigService>().GetConfig(EDeviceType.SCANNER).OrderByDescending(x => x.Id).Take(8).ToList();
|
|||
|
|
foreach (var item in configScann)
|
|||
|
|
{
|
|||
|
|
IScanCodeBase device = _unityContainer.Resolve<IScanCodeBase>(item.Name);
|
|||
|
|
_deviceScann.Add(device);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PLC = _unityContainer.Resolve<IPLCDevice>(Name); //下料PLC
|
|||
|
|
System.Threading.Tasks.Task.Run(() => BuildRecordFile());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void BuildRecordFile()
|
|||
|
|
{
|
|||
|
|
string dateFile = "";
|
|||
|
|
string filePath = "";
|
|||
|
|
string path = _unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DataFilePath.ToString());//
|
|||
|
|
path += "\\出站";
|
|||
|
|
while (true)
|
|||
|
|
{
|
|||
|
|
Thread.Sleep(1000 * 60);
|
|||
|
|
|
|||
|
|
if (!Directory.Exists(path))
|
|||
|
|
{
|
|||
|
|
Directory.CreateDirectory(path);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dateFile = DateTime.Now.ToString("yyyyMMdd");
|
|||
|
|
filePath = path + $"\\{dateFile}.csv";
|
|||
|
|
var batteryList = _unityContainer.Resolve<BatteryInfoService>().GetOutbound();
|
|||
|
|
|
|||
|
|
if (null == batteryList)
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
CSVHelper.WriteMap<BatteryInfoEntity, BatteryInfoDetailMap>(batteryList, filePath);
|
|||
|
|
foreach (var item in batteryList)
|
|||
|
|
{
|
|||
|
|
if (0 == _unityContainer.Resolve<BatteryInfoService>().UpdateStatus(item.Id, (int)EBatteryStatus.OutBoundRecord))
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Fatal("修改记录出站状态失败!");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Fatal($"BuildRecordFile:{ex.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
void SetDummyToWaterPlatform(string param)
|
|||
|
|
{
|
|||
|
|
int number = int.Parse(param);
|
|||
|
|
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
|||
|
|
_unityContainer.Resolve<BLL.BatteryInfoService>().SetDummyToWaterPlatform(palletId);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//开始下料 ,,验证数据库OK (分二次执行,一次取假电芯,一次取正常电芯)
|
|||
|
|
public void ExecuteUnLoading(int curValue, string param, Variable node)
|
|||
|
|
{
|
|||
|
|
//Int16 batteryType = 1; //1:假电芯, 0:正常电芯
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
|||
|
|
|
|||
|
|
if (!IsConnectPLC()) return;
|
|||
|
|
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (GetUnloadBattery(param, node.Json, out bool isUnLodingDummy, out TPalletInfo palletInfo))
|
|||
|
|
{
|
|||
|
|
_unityContainer.Resolve<LogService>().AddLog("ExecuteUnLoading:下料写入托盘电池信息!", E_LogType.Info.ToString());
|
|||
|
|
WriteBatteryPostionToPLC(palletInfo, node.Json, isUnLodingDummy);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//SetEmptyPallet(node.Json); //如果上料中写了下料电芯数据,此时再重启上位机,状态为“下料中”,会清除,所以注释
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
|||
|
|
if (!writeResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"ExecuteScanPallet-写数据失败:{(string)d.WriteResult}:{writeResult.Message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"ExecuteUnLoading,出错,{ex.Message},param{param},{node.Json}");
|
|||
|
|
}
|
|||
|
|
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 结果数据上传到MOM,烘烤开始时间,烘烤结束时间,烘烤温度,真空值,出炉冷却后温度
|
|||
|
|
/// </summary>BakingOutputCmd,MESReturnCmdModel
|
|||
|
|
/// <param name="batterys"></param>
|
|||
|
|
/// <param name="palletInfo"></param>
|
|||
|
|
public MESReturnCmdModel MesOutUnBinding(TPalletInfo palletInfo, List<TBatteryInfo> betterys, bool realTimeSend = false)
|
|||
|
|
{
|
|||
|
|
if (0 == palletInfo.BakingPosition.Value)
|
|||
|
|
{
|
|||
|
|
palletInfo.BakingPosition = 1; //防呆
|
|||
|
|
LogHelper.Instance.Error("手动触发烘烤完成,没有烘烤位置!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
TCavityInfo cavityInfo = _unityContainer.Resolve<CavityInfoService>().GetStationDetailById(palletInfo.BakingPosition.Value);
|
|||
|
|
if (null == cavityInfo)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.GetCurrentClassError("通过烘烤位置查找托盘位置失败");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return _unityContainer.Resolve<MESProcess>().MESBakingOutput(cavityInfo.Name, palletInfo, betterys, true, realTimeSend);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//请求下料,出现异常处理
|
|||
|
|
TPalletInfo DealStartUnloadFail(int number)
|
|||
|
|
{
|
|||
|
|
//去机器人上获取夹具信息,此时没有转移。
|
|||
|
|
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetRobotPallet();
|
|||
|
|
if (null != palletInfo)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error("请求下料的夹具在机器人上面!");
|
|||
|
|
return palletInfo;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//如果还没有,再到下料获取。
|
|||
|
|
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
|||
|
|
return _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
|||
|
|
}
|
|||
|
|
private bool GetUnloadBattery(string param, string reply, out bool isUnLodingDummy, out TPalletInfo palletInfo)
|
|||
|
|
{
|
|||
|
|
isUnLodingDummy = false;
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
OperateResult operateResultX = null, operateResultY = null;
|
|||
|
|
OperateResult operateResult = null;
|
|||
|
|
List<TBatteryInfo> batterys = null;
|
|||
|
|
TBatteryInfo dummy;
|
|||
|
|
Int16 batteryType = 1; //1:假电芯, 0:正常电芯
|
|||
|
|
int number = int.Parse(param);
|
|||
|
|
Int16[] dummyPos = new Int16[DUMMY_POS_SIZE];
|
|||
|
|
int[] batteryVirtualId = new int[Global.PALLET_MAX_BATTERYS];
|
|||
|
|
Array.Clear(batteryVirtualId, 0, Global.PALLET_MAX_BATTERYS);
|
|||
|
|
|
|||
|
|
int palletId = _unityContainer.Resolve<CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
|||
|
|
palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
|||
|
|
//要求PLC必须在上位机反馈任务完成之后再请求托盘参数
|
|||
|
|
|
|||
|
|
if (null == palletInfo) //会出现异常(发触发下料,再告诉上位机放)
|
|||
|
|
{
|
|||
|
|
palletInfo = DealStartUnloadFail(number);
|
|||
|
|
if (null == palletInfo) //
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"接收到下料信号,但获取不到下料工站{param}的夹具信息!", true);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
batterys = _unityContainer.Resolve<BLL.BatteryInfoService>().GetBatteryInfos(palletInfo.VirtualId);
|
|||
|
|
|
|||
|
|
if (0 == batterys.Count)
|
|||
|
|
{
|
|||
|
|
_unityContainer.Resolve<LogService>().AddLog($"下料工站{param},找不到电池位置数据!", E_LogType.Info.ToString());
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//要满足下料条件
|
|||
|
|
if (palletInfo.PalletStatus != (int)EPalletStatus.BakeOver
|
|||
|
|
&& palletInfo.PalletStatus != (int)EPalletStatus.TestOK)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Fatal($"下料夹具状态不对,请人为处理,要求状态:{EPalletStatus.BakeOver.GetDescription()},{EPalletStatus.TestOK.GetDescription()},实际状态:" +
|
|||
|
|
$"{((EPalletStatus)palletInfo.PalletStatus).GetDescription()}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (palletInfo.PalletStatus == (int)EPalletStatus.BakeOver
|
|||
|
|
&& _unityContainer.Resolve<BLL.BatteryInfoService>().IsPalletDummy(palletInfo.VirtualId)) //带水含量电芯,要测试
|
|||
|
|
{
|
|||
|
|
dummy = _unityContainer.Resolve<BLL.BatteryInfoService>().FindDummy(palletInfo, batterys);
|
|||
|
|
isUnLodingDummy = true;
|
|||
|
|
if (null == dummy)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Fatal("获取假电芯信息失败!");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
dummyPos[1] = (Int16)dummy.PositionX.Value;
|
|||
|
|
dummyPos[2] = (Int16)dummy.PositionY.Value;
|
|||
|
|
operateResultX = PLC.Write<Int16>((string)d.WriteDummyX, dummyPos[1]); //托盘假电池行列数
|
|||
|
|
operateResultY = PLC.Write<Int16>((string)d.WriteDummyY, dummyPos[2]); //托盘假电池行列数
|
|||
|
|
if (!operateResultX.IsSuccess
|
|||
|
|
|| !operateResultY.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Debug($"设置托盘假电池行列数失败:{operateResultX.Message},{operateResultY.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
batteryType = 0; //正常电芯
|
|||
|
|
_unityContainer.Resolve<BLL.PalletInfoService>().UpdateUnLoadingBegingTime(palletInfo.Id);
|
|||
|
|
List<TBatteryInfo> normalBatterys = (from b in batterys
|
|||
|
|
where b.BatteryStatus <= (int)EBatteryStatus.ToPallet
|
|||
|
|
select b).ToList();
|
|||
|
|
if (Global.PALLET_ROWS < Global.PALLET_COLS) //7行,24列:行少列多
|
|||
|
|
{
|
|||
|
|
foreach (var item in normalBatterys)
|
|||
|
|
{
|
|||
|
|
batteryVirtualId[(item.PositionX.Value - 1) * Global.PALLET_COLS + item.PositionY.Value] = item.Id;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else//48行,2列,: 行少列多
|
|||
|
|
{
|
|||
|
|
foreach (var item in normalBatterys)
|
|||
|
|
{
|
|||
|
|
batteryVirtualId[(item.PositionY.Value - 1) * Global.PALLET_ROWS + item.PositionX.Value] = item.Id;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
LogHelper.Instance.Info("下料写入电芯位置:" + JSON.SerializeObject(batteryVirtualId));
|
|||
|
|
}
|
|||
|
|
//水含量电芯时,全为0
|
|||
|
|
operateResult = PLC.Write<int[]>((string)d.WriteVirtualIds, batteryVirtualId); //托盘_有无电池[1-120]
|
|||
|
|
if (!operateResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"设置托盘_有无电池失败:{operateResult.Message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//电芯类型
|
|||
|
|
operateResult = PLC.Write<Int16>((string)d.WriteType, batteryType); //托盘1正常电芯下料
|
|||
|
|
if (!operateResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"写下料电芯类型失败:{(string)d.WriteType},{operateResult.Message}");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
//写下料位置的电池位置信息给PLC
|
|||
|
|
private void WriteBatteryPostionToPLC(TPalletInfo palletInfo, string reply, bool isUnLodingDummy)
|
|||
|
|
{
|
|||
|
|
Int16 lastValue = 0;
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
OperateResult operateResult = null;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
////水含量电芯时,全为0
|
|||
|
|
//operateResult = PLC.Write<int[]>((string)d.WriteVirtualIds, batteryVirtualId); //托盘_有无电池[1-120]
|
|||
|
|
//if (!operateResult.IsSuccess)
|
|||
|
|
//{
|
|||
|
|
// LogHelper.Instance.Error($"设置托盘_有无电池失败:{operateResult.Message}");
|
|||
|
|
//}
|
|||
|
|
if (!isUnLodingDummy)
|
|||
|
|
{
|
|||
|
|
lastValue = (Int16)(palletInfo.LastFlag ? 1 : 0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
operateResult = PLC.Write<Int16>((string)d.WriteLastFlag, lastValue); //最后一盘
|
|||
|
|
if (!operateResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"设置托盘最后一盘失败:{operateResult.Message},{operateResult.Message}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//在给下料参数成功之后,再更新托盘状态。
|
|||
|
|
if (0 == _unityContainer.Resolve<BLL.PalletInfoService>().UpdatePalletStatus(palletInfo.Id, (int)EPalletStatus.Blank))
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"在给下料参数成功之后,再更新托盘状态:{operateResult.Message},{operateResult.Message}");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetEmptyPallet(string reply)
|
|||
|
|
{
|
|||
|
|
_unityContainer.Resolve<LogService>().AddLog("SetEmptyPallet:设置空托盘", E_LogType.Info.ToString());
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
List<AddrValue> makeAddrValues = new List<AddrValue>();
|
|||
|
|
int[] batteryVirtualId = new int[Global.PALLET_MAX_BATTERYS];
|
|||
|
|
Array.Clear(batteryVirtualId, 0, Global.PALLET_MAX_BATTERYS);
|
|||
|
|
|
|||
|
|
makeAddrValues.Add(new AddrValue()
|
|||
|
|
{
|
|||
|
|
Addr = (string)d.WriteDummyX,
|
|||
|
|
Value = (Int16)0
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
makeAddrValues.Add(new AddrValue()
|
|||
|
|
{
|
|||
|
|
Addr = (string)d.WriteDummyY,
|
|||
|
|
Value = (Int16)0
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
makeAddrValues.Add(new AddrValue()
|
|||
|
|
{
|
|||
|
|
Addr = (string)d.WriteType,
|
|||
|
|
Value = (Int16)0
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
makeAddrValues.Add(new AddrValue()
|
|||
|
|
{
|
|||
|
|
Addr = (string)d.WriteVirtualIds,
|
|||
|
|
Value = batteryVirtualId
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
makeAddrValues.Add(new AddrValue()
|
|||
|
|
{
|
|||
|
|
Addr = (string)d.WriteResult,
|
|||
|
|
Value = true
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
OperateResult result = PLC.Writes(makeAddrValues.Select(x => x.Addr).ToArray(), makeAddrValues.Select(x => x.Value).ToArray());
|
|||
|
|
|
|||
|
|
if (!result.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.GetCurrentClassError("清空托盘失败!");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void ExecuteUnLoadingFinish(int curValue, string param, Variable node)
|
|||
|
|
{
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
|||
|
|
|
|||
|
|
//-----------------------------------------------------------------------------
|
|||
|
|
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0为测试模式,1为正式模式
|
|||
|
|
|
|||
|
|
if (!IsConnectPLC()) return;
|
|||
|
|
|
|||
|
|
//得到这个工站的夹具,通过夹具得到电芯
|
|||
|
|
int number = int.Parse(param);
|
|||
|
|
int palletId = _unityContainer.Resolve<BLL.CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
|||
|
|
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
|||
|
|
|
|||
|
|
if (null == palletInfo)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"托盘为空, 下料{number}#工站,palletId:{palletId}");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_unityContainer.Resolve<BLL.PalletInfoService>().UpdateUnLoadingOverTime(palletInfo.Id);
|
|||
|
|
|
|||
|
|
if (0 == palletInfo.VirtualId
|
|||
|
|
|| 1 == palletInfo.Id)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"下料夹具异常, 下料托盘的虚拟码为0,或下料托盘为【新夹具】");
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_unityContainer.Resolve<BLL.PalletInfoService>().PalletInfoToHistory(palletInfo.VirtualId,
|
|||
|
|
(int)EPalletStatus.BlankOver, (int)EBatteryStatus.Over, (int)EStationType.UnLoading, number);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
|||
|
|
if (!writeResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Warn($"ExecuteUnLoadingFinish-{(string)d.WriteResult}:{writeResult.Message}");
|
|||
|
|
}
|
|||
|
|
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 核对电芯条码,下料扫码
|
|||
|
|
/// </summary>
|
|||
|
|
//void VerifyBatteryCode(int curValue, string param, string reply)
|
|||
|
|
//{
|
|||
|
|
// dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
// var result = DealVerify(reply);
|
|||
|
|
|
|||
|
|
// var writeResult = PLC.Write<bool[]>((string)d.WriteResult, result.Result);//
|
|||
|
|
// if (!writeResult.IsSuccess)
|
|||
|
|
// {
|
|||
|
|
// LogHelper.Instance.GetCurrentClassWarn($"{(string)d.WriteResult}:{writeResult.Message}");
|
|||
|
|
// }
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
//async Task<bool[]> DealVerify(string reply)
|
|||
|
|
//{
|
|||
|
|
// int index = 0, j = 0;
|
|||
|
|
// bool[] results = new bool[Global.ONCE_SCAN_BATTERY];
|
|||
|
|
// Array.Clear(results, 0, Global.ONCE_SCAN_BATTERY);
|
|||
|
|
// List<Task<OperateResult<string>>> scannTasks = new List<Task<OperateResult<string>>>();
|
|||
|
|
// dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
// if (!IsConnectPLC()) return results;
|
|||
|
|
|
|||
|
|
// OperateResult<Int32[]> batterys = PLC.Read<Int32[]>((string)d.ReadVirtualIds); //下料处电芯虚拟码 读取下料温度[1..8]
|
|||
|
|
// if (!batterys.IsSuccess)
|
|||
|
|
// {
|
|||
|
|
// LogHelper.Instance.Warn($"核对电芯条码时,读取电芯虚拟码错误:{batterys.Message}");
|
|||
|
|
// return results;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// if (batterys.Content.All(x => x == 0)) //True 全部为0
|
|||
|
|
// {
|
|||
|
|
// LogHelper.Instance.Warn($"核对电芯条码时,读取电芯虚拟码异常,全部虚拟码都为0");
|
|||
|
|
// return results;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// //读条码
|
|||
|
|
// for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
|||
|
|
// {
|
|||
|
|
// if (0 == batterys.Content[index])
|
|||
|
|
// {
|
|||
|
|
// continue;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == s.ToString());
|
|||
|
|
|
|||
|
|
// if (!scanDevice.IsConnect)
|
|||
|
|
// {
|
|||
|
|
// string msg = $"获取{s.GetDescription()}失败,请检测线路!";
|
|||
|
|
// LogHelper.Instance.Error(msg, true); //弹屏,人为处理好后,再次触发
|
|||
|
|
// _unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
|||
|
|
// scanDevice.Connect();
|
|||
|
|
// --s; //再次获取
|
|||
|
|
// continue;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// scannTasks.Add(Task.Run(() => scanDevice.ReadCode())); // 启动并行任务
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// await Task.WhenAll(scannTasks); //等待所有任务(扫码)完成
|
|||
|
|
// index = 0;
|
|||
|
|
// var batteryCodes = GetBatteryCode(batterys.Content);//获取PLC传过来的虚拟码
|
|||
|
|
|
|||
|
|
// //比较条码
|
|||
|
|
// for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, j++)
|
|||
|
|
// {
|
|||
|
|
// if (0 == batterys.Content[index])
|
|||
|
|
// {
|
|||
|
|
// continue;
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// if (!batteryCodes.Contains(scannTasks[index++].Result.Content)) //没有用等于号,是因为这样兼容更好一点
|
|||
|
|
// {
|
|||
|
|
// LogHelper.Instance.Warn($"下料核对电芯异常,PLC电芯:{string.Join(",", batteryCodes)},扫码电芯:{JSON.SerializeObject(scannTasks)}");
|
|||
|
|
// //continue; //异常
|
|||
|
|
// }
|
|||
|
|
// else
|
|||
|
|
// {
|
|||
|
|
// results[j] = true;
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
// _unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
|||
|
|
// return results;
|
|||
|
|
//}
|
|||
|
|
|
|||
|
|
//取假电芯完成,验证数据库OK
|
|||
|
|
public void ExecuteTakeDummyFinish(int curValue, string param, Variable node)
|
|||
|
|
{
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
|||
|
|
if (!IsConnectPLC()) return;
|
|||
|
|
_unityContainer.Resolve<LogService>().AddLog("UnLoadingStation:ExecuteTakeDummyFinish:取假电池开始:" + param, E_LogType.Info.ToString());
|
|||
|
|
int number = int.Parse(param);
|
|||
|
|
int palletId = _unityContainer.Resolve<BLL.CavityInfoService>().GetPalletId((int)EStationType.UnLoading, number);
|
|||
|
|
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfo(palletId);
|
|||
|
|
|
|||
|
|
if (null == palletInfo)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"接收下料{number}工站取假电芯完成信号,但获取不到下料夹具!", true);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//这里再改假电芯状态
|
|||
|
|
SetDummyToWaterPlatform(param);
|
|||
|
|
|
|||
|
|
//重启后,可能再次收到1#托盘取假电池完成信号(待水含量测试),此时状态可能测试OK或NG
|
|||
|
|
if (palletInfo.PalletStatus == (int)EPalletStatus.BakeOver
|
|||
|
|
|| palletInfo.PalletStatus == (int)EPalletStatus.Blank) //取水含量电芯时,也是下料中状态
|
|||
|
|
{
|
|||
|
|
_unityContainer.Resolve<BLL.PalletInfoService>().UpdatePalletStatus(palletInfo.Id, (int)EPalletStatus.WaitTest);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var writeResult = PLC.Write<Int16>((string)d.WriteResult, 1);
|
|||
|
|
if (!writeResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Warn($"ExecuteTakeDummyFinish-{(string)d.WriteResult}:{writeResult.Message}");
|
|||
|
|
}
|
|||
|
|
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void SetBatteryCodeLen()
|
|||
|
|
{
|
|||
|
|
_batteryCodeLen = int.Parse(_unityContainer.Resolve<Cowain.Bake.BLL.SysSetupService>().GetValueByParaID(ESysSetup.BatteryCodeLen.ToString()));
|
|||
|
|
}
|
|||
|
|
public async Task<List<OperateResult<string>>> GetScannResult(int curValue)
|
|||
|
|
{
|
|||
|
|
int index = 1;
|
|||
|
|
List<string> batteryCodes = new List<string>();
|
|||
|
|
List<OperateResult<string>> scannList = new List<OperateResult<string>>();
|
|||
|
|
List<Task<OperateResult<string>>> scannTasks = new List<Task<OperateResult<string>>>();
|
|||
|
|
|
|||
|
|
OperateResult<string> scanResult = new OperateResult<string>()
|
|||
|
|
{
|
|||
|
|
IsSuccess = false,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
|||
|
|
{
|
|||
|
|
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IScanCodeBase scanDevice = _deviceScann.Find(x => x.Name == s.ToString());
|
|||
|
|
|
|||
|
|
if (!scanDevice.IsConnect)
|
|||
|
|
{
|
|||
|
|
string msg = $"获取{s.GetDescription()}失败,请检测线路!";
|
|||
|
|
LogHelper.Instance.Error(msg, true); //弹屏,人为处理好后,再次触发
|
|||
|
|
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
|||
|
|
scanDevice.Connect();
|
|||
|
|
--s; //再次获取
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scannTasks.Add(Task.Run(() => scanDevice.ReadCode())); // 启动并行任务
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await Task.WhenAll(scannTasks); //等待所有任务(扫码)完成
|
|||
|
|
foreach (var task in scannTasks)
|
|||
|
|
{
|
|||
|
|
scannList.Add(task.Result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return scannList;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public async Task<bool[]> DealTemp(IPLCDevice plc, int curValue, string reply)
|
|||
|
|
{
|
|||
|
|
string msg = "";
|
|||
|
|
int index = 1;
|
|||
|
|
int scannIndex = 0;
|
|||
|
|
bool[] repResults = new bool[Global.ONCE_SCAN_BATTERY + 1];
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(reply);
|
|||
|
|
List<string> batteryCodes = null;
|
|||
|
|
List<OperateResult<string>> scannList;
|
|||
|
|
MESReturnCmdModel result = null;
|
|||
|
|
bool isDummy = false;
|
|||
|
|
Array.Clear(repResults, 0, Global.ONCE_SCAN_BATTERY + 1);
|
|||
|
|
int debugMode = int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.DebugMode.ToString())); //0为测试模式,1为正式模式
|
|||
|
|
_tempList.Clear();
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
if (!IsConnectPLC()) return null;
|
|||
|
|
|
|||
|
|
OperateResult<float[]> readTemps = plc.Read<float[]>((string)d.ReadTemp); //下料处电芯温度,读取下料温度[1..4]
|
|||
|
|
if (!readTemps.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Warn("读取下料温度失败");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if ((int)EProductionMode.Debug == debugMode) //调试模式
|
|||
|
|
{
|
|||
|
|
repResults[1] = true;
|
|||
|
|
return repResults;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scannList = await GetScannResult(curValue); //
|
|||
|
|
for (EScanCode s = EScanCode.UnLoadingBatteryScan1; s <= EScanCode.UnLoadingBatteryScan8; s++, index++)
|
|||
|
|
{
|
|||
|
|
if (((curValue >> index) & 1) != 1) //第index位不是1,就是不需要扫码
|
|||
|
|
{
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
repResults[index] = true;
|
|||
|
|
|
|||
|
|
if (scannList[scannIndex].IsSuccess)
|
|||
|
|
{
|
|||
|
|
_tempList.Add(new TBatteryInfo()
|
|||
|
|
{
|
|||
|
|
BatteryCode = scannList[scannIndex].Content, //实际要扫码
|
|||
|
|
CoolTemp = readTemps.Content[index] //1...8排序
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (MessageBoxResult.Yes == HandyControl.Controls.MessageBox.Show($"[{s.GetDescription()}]扫码失败,您确定此位置是否有电芯?", "提示", MessageBoxButton.YesNo, MessageBoxImage.Information))
|
|||
|
|
{
|
|||
|
|
_tempList.Add(new TBatteryInfo()
|
|||
|
|
{
|
|||
|
|
BatteryCode = GetBatteryCode(s.GetDescription()), //弹屏,输入电芯条码
|
|||
|
|
CoolTemp = readTemps.Content[index] //1...8排序
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else //无电芯
|
|||
|
|
{
|
|||
|
|
repResults[index] = false; //扫码NG,并人为确认无电芯
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
scannIndex++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
batteryCodes = _tempList.Select(x => x.BatteryCode).ToList();
|
|||
|
|
LogHelper.Instance.Info($"读取下料PLC的电芯虚拟码:{string.Join(",", batteryCodes)}");
|
|||
|
|
List<TBatteryInfo> currentBatterys = _unityContainer.Resolve<BatteryInfoService>().GetBatterys(batteryCodes); //8个电芯(最多),可能会来自多个托盘
|
|||
|
|
if (null == currentBatterys
|
|||
|
|
|| currentBatterys.Count == 0) //PLC有BUG,有时为0,导致上位机没办法回复,会PLC超时
|
|||
|
|
{
|
|||
|
|
msg = $"下发温度读取失败,{Global.ONCE_SCAN_BATTERY}个电池虚拟码为0!";
|
|||
|
|
LogHelper.Instance.Error("下发温度读取完成失败,电池虚拟码为0!");
|
|||
|
|
_unityContainer.Resolve<LogService>().AddLog("下发温度读取完成失败,电池虚拟码为0!", E_LogType.Fatal.ToString());
|
|||
|
|
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
|||
|
|
return repResults;
|
|||
|
|
}
|
|||
|
|
else if (currentBatterys.Count == 1) //一个电芯,判断是否是假电芯
|
|||
|
|
{
|
|||
|
|
if (_unityContainer.Resolve<BatteryInfoService>().IsDummy(currentBatterys[0].Id))
|
|||
|
|
{
|
|||
|
|
isDummy = true;
|
|||
|
|
return repResults; //假电芯就不上传了
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_unityContainer.Resolve<BatteryInfoService>().UpdateCoolTempAndUnBindingTime(currentBatterys, _tempList);// temps);
|
|||
|
|
if (int.Parse(_unityContainer.Resolve<SysSetupService>().GetValueByParaID(ESysSetup.MOMEnable.ToString())) == (int)EMOMEnable.Enable)
|
|||
|
|
{
|
|||
|
|
var batterySort = currentBatterys.GroupBy(p => new { p.PalletVirtualId }).Select(s => s.FirstOrDefault()).ToList(); //获取一个托盘中的一个电芯
|
|||
|
|
|
|||
|
|
foreach (var item in batterySort) //一个托盘只返回第一个电芯
|
|||
|
|
{
|
|||
|
|
var palletBatterys = currentBatterys.Where(x => batteryCodes.Contains(x.BatteryCode) && x.PalletVirtualId == item.PalletVirtualId).ToList(); //获取一个托盘中的电芯
|
|||
|
|
TPalletInfo palletInfo = _unityContainer.Resolve<BLL.PalletInfoService>().GetPalletInfoByBatteryVirtualId(item.PalletVirtualId); //此时托盘可能已经转历史盘托了
|
|||
|
|
|
|||
|
|
if (null == palletInfo)
|
|||
|
|
{
|
|||
|
|
msg = $"MOM上传冷却温度时,找不到电芯所在托盘,电芯:{string.Join(",", palletBatterys.Select(x => x.BatteryCode).ToList())}!";
|
|||
|
|
LogHelper.Instance.Fatal(msg);
|
|||
|
|
_unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var mesResult = MesOutUnBinding(palletInfo, palletBatterys);//组装数据 发送
|
|||
|
|
//因为没有等MOM,所以注掉下面代码
|
|||
|
|
//if (mesResult == null)
|
|||
|
|
//{
|
|||
|
|
// LogHelper.Instance.Error($"自动出站,MOM返回超时,电芯条码:{string.Join(",", palletBatterys.Select(x => x.BatteryCode).ToList())}"); //偶尔会返回空,导致人为要处理,麻烦,所以只保存到日志
|
|||
|
|
//}
|
|||
|
|
//else if (mesResult.Info.ResultFlag.ToUpper() == "NG" && (!isDummy))
|
|||
|
|
//{
|
|||
|
|
// msg = $"自动出站,MOM返回信息异常,信息:{JSON.SerializeObject(result)}";
|
|||
|
|
// LogHelper.Instance.Error(msg);
|
|||
|
|
// _unityContainer.Resolve<MainWindowViewModel>().AddPromptContent(msg);
|
|||
|
|
//}
|
|||
|
|
//else
|
|||
|
|
//{
|
|||
|
|
// _unityContainer.Resolve<MainWindowViewModel>().DeletePromptContent();
|
|||
|
|
//}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
catch (Exception e)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Fatal($"读温失败:{e.Message},{e.StackTrace}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return repResults;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public string GetBatteryCode(string desc)
|
|||
|
|
{
|
|||
|
|
string batteryCode = "";
|
|||
|
|
while (string.IsNullOrEmpty(batteryCode))
|
|||
|
|
{
|
|||
|
|
Application.Current.Dispatcher.Invoke((Action)(() =>
|
|||
|
|
{
|
|||
|
|
PalletIdInputWindow f = new PalletIdInputWindow("电芯码输入框", $"{desc}扫码失败," + "请输入电芯条码", "确定输入电芯条码?")
|
|||
|
|
{
|
|||
|
|
WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen,
|
|||
|
|
};
|
|||
|
|
f.ShowDialog();
|
|||
|
|
batteryCode = f.PalletId;
|
|||
|
|
}));
|
|||
|
|
|
|||
|
|
if (!_unityContainer.Resolve<BatteryInfoService>().IsBatteryCodeRepeat(batteryCode))
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error($"【{batteryCode}】,不存在,请重新输入!", true);
|
|||
|
|
batteryCode = "";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return batteryCode;
|
|||
|
|
}
|
|||
|
|
//获取下料温度
|
|||
|
|
public async Task GetTemp(int curValue, string param, Variable node)
|
|||
|
|
{
|
|||
|
|
OperateResult operateResult = null;
|
|||
|
|
dynamic d = JsonConvert.DeserializeObject<dynamic>(node.Json);
|
|||
|
|
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>((string)d.PLCName); //上料PLC
|
|||
|
|
var result = await DealTemp(plc, curValue, node.Json);
|
|||
|
|
|
|||
|
|
if (result == null)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
operateResult = plc.Write<bool[]>((string)d.WriteResult, result); //MOM没有返回数据,导致
|
|||
|
|
if (!operateResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
LogHelper.Instance.Error("下发温度读取完成失败!");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_unityContainer.Resolve<BasicInfoViewModel>().SetEvent("结束:" + node.VarDesc);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void Stop()
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|