using Common; using Common.HTTPModels; using Common.Models; using CommunityToolkit.Mvvm.Messaging; using Dm.filter.log; using MegaRobo.C00225155.ControlDevices; using MegaRobo.C00225155.ControlDevices.Scanner; using MegaRobo.C00225155.ControlDevices.WeightDevice; using MegaRobo.C00225155.Entities; using MegaRobo.C00225155.Entities.Entity_DB; using MegaRobo.C00225155.Entities.Enums; using MegaRobo.C00225155.Entities.FromWeb; using MegaRobo.C00225155.Entities.ToWeb; using MegaRobo.Contract; using MegaRobo.Contract.Servers; using MegaRobo.ControlDevices; using MegaRobo.ControlDevices.Models; using MegaRobo.Entities; using MegaRobo.Entities.ViewTT; using MegaRobo.Logger; using MegaRobo.PipetteTool.HamiltonConsole; using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices; using NetTaste; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Nito.AsyncEx; using SqlSugar; using System; using System.CodeDom; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Linq; using System.Net.Http; using System.Reflection; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Threading; using static System.Net.Mime.MediaTypeNames; using JsonSerializer = System.Text.Json.JsonSerializer; using Pipette1ml = MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices; using Pipette5ml = MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.Hamilton5mlDevices; namespace MegaRobo.C00225155.AppServer.ExecuteWorks { public partial class StationService_MaterialDosing : StationServiceBase { public bool TestMode = false; //测试模式 /// /// 作为客户端 和BS做回复 /// private IHttpClientFactory _httpClientFactory; protected WeightService_Ts02 preWeight; private LabxService labxService; private List labxPowderInstrument; public StationProperty StationProp = new StationProperty(); /// /// 扫码枪服务 /// protected ScannerService scannerService; protected ScannerService scannerService_Powder; private Pipette1ml.PipetteService pipetteService_1ml { get; set; } /// /// 从传送平台上料取载具工装 线程 /// private Task TaskBoxFromTransferPlateTask { get; set; } = null; /// /// 下载具工装到传送平台 线程 /// private Task DownloadBoxToTransferPlateTask { get; set; } = null; /// /// 投料线程,根据当前投料物 /// private Task DoseTask_BasedOnCurrentDoseFlow { get; set; } = null; /// /// 当前正在投料的流程 /// private MaterialDoseFunctionFlow _currentDoseFlow { get; set; } = null; /// /// 当前使用的原液瓶,以及原液瓶所在的FixturePosPro /// private UseLiquidBottle _currentUseSourceLiquidBottle { get; set; } = null; /// /// 当前使用粉末瓶,以及粉末瓶所在的FixturePosPro /// private SourcePowderBottleModel _currentUsePowderBottle { get; set; } = null; #region event /// /// 更新试剂事件 /// public event EventHandler> UpdateAdditiveEvent; private List OngoingDoseDataResultList = new List(); public event EventHandler UpdateDeviceStatusEvent; #endregion public StationService_MaterialDosing(ICoreService coreService, WorkService workService, DeviceNames plcName, string station) : base(coreService, workService, plcName, station) { StationProp = new StationProperty() { cancellationToken = new CancellationTokenSource(), ManualResetEvent = new ManualResetEvent(true), StationNum = 1, StationName = "投料工站", bStartButtonTrigger = false, bStopButtonTrigger = false, bRunFinish = false, bHaveReset = false, CTWatch = new Stopwatch(), }; StationProp.ObstructFlagList = new ConcurrentDictionary(); StationProp.ObstructFlagList.TryAdd("传送平台收到准备上料信号", new ObstructFlag() { strName = "传送平台收到准备上料信号", flag = false }); StationProp.ObstructFlagList.TryAdd("四轴机械手运行中", new ObstructFlag() { strName = "四轴机械手运行中", flag = false }); StationProp.ObstructFlagList.TryAdd("四轴机械手正在使用传送平台", new ObstructFlag() { strName = "四轴机械手正在使用传送平台", flag = false }); _ = Task.Run(ProcessDispatcherEx); _ = Task.Run(DownLoadDispatcherEx); } #region BS相关 public async Task ChangeDeviceStatus(Entities.DeviceStatus deviceStatus) { try { StationProp.deviceStatus = deviceStatus; UpdateDeviceStatusEvent?.Invoke(this, deviceStatus); } catch (Exception ex) { //MessageBox.Show(ex.Message); } finally { //todo:此处回调BS var status = new { status = deviceStatus.ToString() }; var res = await SendJson(new Guid().ToString(), "status", JsonConvert.SerializeObject(status)); } } public async Task OpenDoor(bool isChangeDeviceState = true) { //if (isChangeDeviceState) UpdateDeviceStatusEvent?.Invoke(this, Entities.DeviceStatus.CarryOn); if (TestMode) { await Task.Delay(5000); } else { //await this.TransferPlateformMoveTo(PlateformPos.TransferIn, new System.Threading.CancellationToken()); await this.TransferPlateformMoveTo(PlateformPos.TransferOut, new System.Threading.CancellationToken()); } await ChangeDeviceStatus(Entities.DeviceStatus.Idel); } public async Task CloseDoor(bool isClose, bool isChangeDeviceState = true) { if (isChangeDeviceState) UpdateDeviceStatusEvent?.Invoke(this, Entities.DeviceStatus.CarryOn); if (isClose) { await this.TransferPlateformMoveTo(PlateformPos.TransferIn, new System.Threading.CancellationToken()); } if (isChangeDeviceState) { await ChangeDeviceStatus(Entities.DeviceStatus.Idel); } } public async Task StartLoad() { //await ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); #region 开始搬运 //await Task.Delay(10_000); var powderlist = new ObservableCollection(); for (int i = 0; i < 4; i++) { powderlist.Add(new SourcePowderBottleModel() { PosId_InBox = i + 1, HaveBottle = false, RemainWeight = 0, SNCode = string.Empty, PowderBottleType = PowderBottleTypeEnum._16mL, SourcePowderBottleState = SourceBottleStateEnum.Idl, }); } var powderlist_125 = new ObservableCollection(); for (int i = 0; i < 2; i++) { powderlist_125.Add(new SourcePowderBottleModel() { PosId_InBox = i + 1, HaveBottle = false, RemainWeight = 0, SNCode = string.Empty, PowderBottleType = PowderBottleTypeEnum._125mL, SourcePowderBottleState = SourceBottleStateEnum.Idl, }); } //await TransferPlateformMoveTo(PlateformPos.TransferIn, _cts.Token); // 1. 粉末瓶:从粉末工装 → 粉末缓存区(逐个处理)先处理粉末,放置干涉 while (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || f.FixtureType == BoxTypeEnum._125mL粉末瓶工装)) && workService.ProjectPro.PowderHeaderCacheArea.Any(f => !f.HaveBottle)) { // 检查是否存在任何有瓶子的粉末工装,如果不存在则跳出循环 bool hasPowderHeader = workService.ProjectPro.TransferArea .Where(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || f.FixtureType == BoxTypeEnum._125mL粉末瓶工装)) .Any(f => (f is SourcePowderBottleBoxModel box16 && box16.SourcePowderBottleCollection.Any(s => s.HaveBottle)) || (f is SourcePowderBottleBoxModel_125ml box125 && box125.SourcePowderBottleCollection.Any(s => s.HaveBottle))); if (!hasPowderHeader) break; await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferPlateformMoveTo(PlateformPos.GloveBox1, _cts.Token); //先去2再去1 var powderFixture = workService.ProjectPro.TransferArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || f.FixtureType == BoxTypeEnum._125mL粉末瓶工装)); SourcePowderBottleBoxModel powderBox = null; SourcePowderBottleBoxModel_125ml powderBox_125 = null; if (powderFixture is SourcePowderBottleBoxModel) { powderBox = powderFixture as SourcePowderBottleBoxModel; } else if (powderFixture is SourcePowderBottleBoxModel_125ml) { powderBox_125 = powderFixture as SourcePowderBottleBoxModel_125ml; } if (powderBox == null && powderBox_125 == null) return; int powderTransferIndex = workService.ProjectPro.TransferArea.IndexOf(powderFixture); if (powderBox != null) { for (int i = 0; i < powderBox.SourcePowderBottleCollection.Count; i++) { // 处理每个有瓶的粉末瓶(只处理一个,避免一次搬多个) var powderBottle = powderBox.SourcePowderBottleCollection[i]; if (powderBottle == null || !powderBottle.HaveBottle) continue; // 找到粉末缓存区的空位置 var aimPowderBottle = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(f => !f.HaveBottle); if (aimPowderBottle == null) { MessageBox.Show("粉末缓存区已满,无法继续上料!"); return; } int aimPowderIndex = workService.ProjectPro.PowderHeaderCacheArea.IndexOf(aimPowderBottle); // 执行机械手操作 await FourAxisTakePowderHeader((int)BoxAreaEnum._手套箱传送平台, powderFixture.BoxId_inDoseUpload, powderBottle.PosId_InBox, powderBox.PowderBottleType, _cts.Token,1); await FourAxisGoToScannPos_powder(_cts.Token, powderBottle); // 称重 //if (!TestMode) await preWeight.Peel(); //var powderWeight = await FourAxisPutPowderHeaderToPreWeight(_cts.Token); //powderBottle.OriginWeight = powderBottle.RemainWeight = powderWeight; // 放入缓存区 await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, aimPowderBottle.Pos_InDosePowderHC, powderBox.PowderBottleType, _cts.Token,1); // 更新粉末缓存区(替换集合元素) var newPowderBottle = File_Operator.DeepCopy(powderBottle); newPowderBottle.HaveBottle = true; newPowderBottle.Pos_InDosePowderHC = aimPowderBottle.Pos_InDosePowderHC; App.Current.Dispatcher.Invoke(() => { powderBottle.HaveBottle = false; workService.ProjectPro.PowderHeaderCacheArea[aimPowderIndex] = newPowderBottle; powderBox.SourcePowderBottleCollection[i] = new SourcePowderBottleModel(); powderBox.SourcePowderBottleCollection[i].HaveBottle = false; }); // 标记原粉末瓶为空 //var updatedBottle = powderBox.SourcePowderBottleCollection.FirstOrDefault(b => b.PosId_InBox == powderBottle.PosId_InBox); //updatedBottle.HaveBottle = false; } App.Current.Dispatcher.Invoke(() => { workService.ProjectPro.TransferArea[powderTransferIndex] = new SourcePowderBottleBoxModel() { BoxId_inDoseUpload = powderTransferIndex + 1, IsEmpty = false, IsDoseFinish = false, BoxArea = BoxAreaEnum._手套箱传送平台, FixtureType = BoxTypeEnum._16mL粉末瓶工装, PowderBottleType = PowderBottleTypeEnum._16mL, SourcePowderBottleCollection = powderlist, BoxSNCode = powderBox.BoxSNCode }; }); } else if (powderBox_125 != null) { for (int i = 0; i < powderBox_125.SourcePowderBottleCollection.Count; i++) { // 处理每个有瓶的粉末瓶(只处理一个,避免一次搬多个) var powderBottle = powderBox_125.SourcePowderBottleCollection[i]; if (powderBottle == null || !powderBottle.HaveBottle) continue; // 找到粉末缓存区的空位置 var aimPowderBottle = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(f => !f.HaveBottle); if (aimPowderBottle == null) { MessageBox.Show("粉末缓存区已满,无法继续上料!"); return; } int aimPowderIndex = workService.ProjectPro.PowderHeaderCacheArea.IndexOf(aimPowderBottle); // 执行机械手操作 await FourAxisTakePowderHeader((int)BoxAreaEnum._手套箱传送平台, powderFixture.BoxId_inDoseUpload, powderBottle.PosId_InBox, powderBox_125.PowderBottleType, _cts.Token,1); await FourAxisGoToScannPos_powder(_cts.Token, powderBottle); // 称重 //if (!TestMode) await preWeight.Peel(); //double powderWeight = await FourAxisPutPowderHeaderToPreWeight(_cts.Token); //powderBottle.OriginWeight = powderBottle.RemainWeight = powderWeight; // 放入缓存区 await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, aimPowderBottle.Pos_InDosePowderHC, powderBox_125.PowderBottleType, _cts.Token,1); // 更新粉末缓存区(替换集合元素) var newPowderBottle = File_Operator.DeepCopy(powderBottle); newPowderBottle.HaveBottle = true; newPowderBottle.Pos_InDosePowderHC = aimPowderBottle.Pos_InDosePowderHC; App.Current.Dispatcher.Invoke(() => { powderBottle.HaveBottle = false; workService.ProjectPro.PowderHeaderCacheArea[aimPowderIndex] = newPowderBottle; powderBox.SourcePowderBottleCollection[i] = new SourcePowderBottleModel(); powderBox.SourcePowderBottleCollection[i].HaveBottle = false; }); // 标记原粉末瓶为空 //var updatedBottle = powderBox_125.SourcePowderBottleCollection.FirstOrDefault(b => b.PosId_InBox == powderBottle.PosId_InBox); //updatedBottle.HaveBottle = false; } App.Current.Dispatcher.Invoke(() => { workService.ProjectPro.TransferArea[powderTransferIndex] = new SourcePowderBottleBoxModel_125ml() { BoxId_inDoseUpload = powderTransferIndex + 1, IsEmpty = false, IsDoseFinish = false, FixtureType = BoxTypeEnum._125mL粉末瓶工装, PowderBottleType = PowderBottleTypeEnum._125mL, SourcePowderBottleCollection = powderlist_125, BoxSNCode = powderBox_125.BoxSNCode }; }); } } // 2. Tip头工装:从传送平台 → Tip头区域 while (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._50uLTip头工装 || f.FixtureType == BoxTypeEnum._300uLTip头工装 || f.FixtureType == BoxTypeEnum._1000uLTip头工装)) && workService.ProjectPro.TipHeadArea.Any(f => !f.HaveBox && f.IsEmpty)) { await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); //OrderByDescending var tipFixture = workService.ProjectPro.TransferArea.LastOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._50uLTip头工装 || f.FixtureType == BoxTypeEnum._300uLTip头工装 || f.FixtureType == BoxTypeEnum._1000uLTip头工装)); int tipTransferIndex = workService.ProjectPro.TransferArea.IndexOf(tipFixture); // 找到Tip头区域的空位置 var aimTipBox = workService.ProjectPro.TipHeadArea.FirstOrDefault(f => !f.HaveBox && f.IsEmpty); int aimTipIndex = workService.ProjectPro.TipHeadArea.IndexOf(aimTipBox); // 执行机械手操作 await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, tipFixture.FixtureType, (ushort)tipFixture.BoxId_inDoseUpload, _cts.Token); ushort aimPos = (ushort)aimTipBox.BoxId_inDosingStation; if (aimPos == 1) { aimPos = 3; } else if (aimPos == 3) { aimPos = 1; } await FourAxisPutBox((int)BoxAreaEnum._Tip托盘存放平台, tipFixture.FixtureType, aimPos, _cts.Token); App.Current.Dispatcher.Invoke(() => { // 复制Tip头工装到Tip区域(替换集合元素) BaseBottleBox TipBox = File_Operator.DeepCopy(tipFixture); if (TipBox is TipBoxModel newTipBox) { newTipBox.BoxId_inDosingStation = aimTipBox.BoxId_inDosingStation; newTipBox.HaveBox = true; newTipBox.IsEmpty = false; newTipBox.IsUseFinsh = false; newTipBox.BoxArea = BoxAreaEnum._Tip托盘存放平台; workService.ProjectPro.TipHeadArea[aimTipIndex] = newTipBox; // 关键:更新集合元素 } else { MessageBox.Show("error"); } // 重置传送平台 workService.ProjectPro.TransferArea[tipTransferIndex] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseUpload = tipFixture.BoxId_inDoseUpload, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台 }; }); } // 3. 原液工装:从传送平台 → 工装缓存区(任意空位置 改为 0,4号位置) while (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && f.FixtureType == BoxTypeEnum._40mL原液工装) && workService.ProjectPro.FixtureCacheArea.Any(a => a.IsEmpty && (a.BoxId_inDosingStation == 1 || a.BoxId_inDosingStation == 5))) { await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); var liquidFixture = workService.ProjectPro.TransferArea.First(f => !f.IsEmpty && f.FixtureType == BoxTypeEnum._40mL原液工装); int liquidTransferIndex = workService.ProjectPro.TransferArea.IndexOf(liquidFixture); var aimFixture = workService.ProjectPro.FixtureCacheArea.First(a => a.IsEmpty && (a.BoxId_inDosingStation == 1 || a.BoxId_inDosingStation == 5)); //原液只能放置在1,5 int aimCacheIndex = workService.ProjectPro.FixtureCacheArea.IndexOf(aimFixture); // 执行机械手操作(传入原工装类型) await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, liquidFixture.FixtureType, (ushort)liquidFixture.BoxId_inDoseUpload, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._托盘存放平台, liquidFixture.FixtureType, (ushort)aimFixture.BoxId_inDosingStation, _cts.Token); // 复制原液工装到缓存区 var newCacheFixture = File_Operator.DeepCopy(liquidFixture); newCacheFixture.BoxId_inDosingStation = aimFixture.BoxId_inDosingStation; newCacheFixture.IsDoseFinish = false; newCacheFixture.IsEmpty = false; newCacheFixture.IsUseFinsh = false; newCacheFixture.BoxArea = BoxAreaEnum._托盘存放平台; App.Current.Dispatcher.Invoke(() => { workService.ProjectPro.FixtureCacheArea[aimCacheIndex] = newCacheFixture; // 重置传送平台 workService.ProjectPro.TransferArea[liquidTransferIndex] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseDnload = liquidFixture.BoxId_inDoseUpload, BoxId_inDoseUpload = liquidFixture.BoxId_inDoseUpload, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台 }; }); } // 4. 样品工装:从传送平台 → 工装缓存区(排除1、5号位置) while (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._5mL样品工装 || f.FixtureType == BoxTypeEnum._12mL样品工装)) && workService.ProjectPro.FixtureCacheArea.Any(a => a.IsEmpty && a.BoxId_inDosingStation != 1 && a.BoxId_inDosingStation != 5)) { await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); // 找到传送平台中的样品工装(取第一个非空) var sampleFixture = workService.ProjectPro.TransferArea.First(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._5mL样品工装 || f.FixtureType == BoxTypeEnum._12mL样品工装)); int sampleTransferIndex = workService.ProjectPro.TransferArea.IndexOf(sampleFixture); // 获取集合索引 // 找到缓存区的空位置 var aimFixture = workService.ProjectPro.FixtureCacheArea.First(a => a.IsEmpty && a.BoxId_inDosingStation != 1 && a.BoxId_inDosingStation != 5 && a.BoxId_inDosingStation != 2 && a.BoxId_inDosingStation != 6); int aimCacheIndex = workService.ProjectPro.FixtureCacheArea.IndexOf(aimFixture); // 获取集合索引 // 执行机械手操作(传入原工装类型,而非空工装类型) await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, sampleFixture.FixtureType, (ushort)sampleFixture.BoxId_inDoseUpload, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._托盘存放平台, sampleFixture.FixtureType, (ushort)aimFixture.BoxId_inDosingStation, _cts.Token); App.Current.Dispatcher.Invoke(() => { // 复制样品工装到缓存区(替换集合元素) var newCacheFixture = File_Operator.DeepCopy(sampleFixture); newCacheFixture.BoxId_inDosingStation = aimFixture.BoxId_inDosingStation; newCacheFixture.IsDoseFinish = false; newCacheFixture.IsEmpty = false; newCacheFixture.IsUseFinsh = false; newCacheFixture.BoxArea = BoxAreaEnum._托盘存放平台; workService.ProjectPro.FixtureCacheArea[aimCacheIndex] = newCacheFixture; // 重置传送平台位置为空工装 workService.ProjectPro.TransferArea[sampleTransferIndex] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseDnload = sampleFixture.BoxId_inDoseUpload, BoxId_inDoseUpload = sampleFixture.BoxId_inDoseUpload, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台 }; }); } await TransferPlateformMoveTo(PlateformPos.GloveBox1, _cts.Token); //最终停留在这个位置最安全 // 无符合条件的工装可上料 if (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && f.FixtureType != BoxTypeEnum._16mL粉末瓶工装 && f.FixtureType != BoxTypeEnum._125mL粉末瓶工装)) { MessageBox.Show("无可用工装或目标区域已满,无法上料!"); } #endregion this.StationProp.deviceStatus = Entities.DeviceStatus.Idel; UpdateDeviceStatusEvent?.Invoke(this, Entities.DeviceStatus.Idel); } #endregion #region qrbian 按目标瓶配置液体 private CancellationTokenSource _cts = new CancellationTokenSource(); private async Task ProcessDispatcherEx() { while (!_cts.Token.IsCancellationRequested) { if (workService.stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Runing) { await Task.Delay(2000); continue; } var hasAnyUsableBox = workService.ProjectPro.FixtureCacheArea .OfType() .Where(b => b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装) .Any(box => box.SampleBottleList.Any(bottle => bottle.HaveBottle && !bottle.bDoseFinish && bottle.MaterialDoseFlowList.Count > 0)); if (!hasAnyUsableBox) { await ChangeDeviceStatus(Entities.DeviceStatus.Idel); continue; } var FixtureCacheAreas = workService.ProjectPro.FixtureCacheArea.Where(b => b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装).OrderBy(s => s.BoxId_inDosingStation).ToList(); bool IsPowderInMachine = false; //加粉头是否在梅特勒称上 bool IsMotherLiquidInMachine = false; //母液是否已经在母液开盖位 for (int i = 0; i < FixtureCacheAreas.Count(); i++) { await TransferPlateformMoveTo(PlateformPos.GloveBox1, _cts.Token); if (StationProp.deviceStatus == Entities.DeviceStatus.Abort) break; var FixtureCacheArea = FixtureCacheAreas.ElementAt(i); SampleBottleBoxModel sampleBox = FixtureCacheArea as SampleBottleBoxModel; var samplebottles = sampleBox.SampleBottleList.Where(b => b.HaveBottle && !b.bDoseFinish && b.MaterialDoseFlowList.Count() > 0).OrderBy(b => b.PosId_InBox).ToList(); if (samplebottles.Count() > 0) { if (FixtureCacheArea.BoxId_inDosingStation == 4 || FixtureCacheArea.BoxId_inDosingStation == 8) { //干涉,先搬到前面一位 await FourAxisTakeBox((int)BoxAreaEnum._托盘存放平台, FixtureCacheArea.FixtureType, (ushort)FixtureCacheArea.BoxId_inDosingStation, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._托盘存放平台, FixtureCacheArea.FixtureType, (ushort)(FixtureCacheArea.BoxId_inDosingStation - 1), _cts.Token); App.Current.Dispatcher.Invoke(() => { FixtureCacheArea.BoxId_inDosingStation -= 1; workService.ProjectPro.FixtureCacheArea[FixtureCacheArea.BoxId_inDosingStation] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseDnload = FixtureCacheArea.BoxId_inDoseUpload, BoxId_inDoseUpload = FixtureCacheArea.BoxId_inDoseUpload, BoxId_inDosingStation = FixtureCacheArea.BoxId_inDosingStation + 1, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._托盘存放平台 }; workService.ProjectPro.FixtureCacheArea[FixtureCacheArea.BoxId_inDosingStation - 1] = FixtureCacheArea; }); } for (int j = 0; j < samplebottles.Count(); j++) { if (StationProp.deviceStatus == Entities.DeviceStatus.Abort) break; var samplebottle = samplebottles.ElementAt(j); //查找下一个目标瓶,用来判断母液或者粉末头是否一样,一样则不搬回去 SampleBottleModel samplebottleNext = null; if (j < samplebottles.Count() - 1) { samplebottleNext = samplebottles.ElementAt(j + 1); } else { if (i < FixtureCacheAreas.Count() - 1) { var nextFixtureCacheArea = FixtureCacheAreas.ElementAt(i + 1); SampleBottleBoxModel sampleBoxNext = nextFixtureCacheArea as SampleBottleBoxModel; var samplebottlesNext = sampleBoxNext.SampleBottleList.Where(b => b.HaveBottle && !b.bDoseFinish && b.MaterialDoseFlowList.Count() > 0).OrderBy(b => b.PosId_InBox); if (samplebottlesNext != null && samplebottlesNext.Any()) { samplebottleNext = samplebottlesNext.FirstOrDefault(); } } } var res = await MixForSampleBottle(samplebottle, sampleBox, IsPowderInMachine, IsMotherLiquidInMachine, samplebottleNext); IsPowderInMachine = res._isPowderInMachine; IsMotherLiquidInMachine = res._isMotherLiquidInMachine; } } //搬运到转运区域,只能是1~3 var aimTransferFixture = GetAvaliableTransferArea(1); if (aimTransferFixture != null) //&& !workService.ProjectPro.bNoUseBS { await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferFixtureFromCacheToTransfer(FixtureCacheArea, aimTransferFixture, _cts.Token); //搬运回物料区域 暂时屏蔽 } } WeakReferenceMessenger.Default.Send(new DesktopAlertMessage() { Header = $"提示", Content = $"工单已完成" }); #region 粉末取回演示使用 if (false && !TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakePowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, PowderBottleTypeEnum._16mL, _cts.Token); //Task task1 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); //多余的 await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, 1, PowderBottleTypeEnum._16mL, _cts.Token); //await Task.WhenAll(task1, task2); await SetObstructFlag("四轴机械手运行中", false); IsPowderInMachine = false; } #endregion await ChangeDeviceStatus(Entities.DeviceStatus.Finish); //if (workService.ProjectPro.bNoUseBS) //{ // #region //todo:测试使用,后期一定要屏蔽 // await ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); // await TransferPlateformMoveTo( PlateformPos.TransferIn,_cts.Token); // await TransferPlateformMoveTo(PlateformPos.TransferOut, _cts.Token); // /* // try // { // var res = await SendJson(new Guid().ToString(), "test", ""); // Logger.LogInformation($"向BS发送完成接收到-{res.Item2}"); // } // catch (Exception ex) // { // MessageBox.Show(ex.Message); // } // ProjectProperty project = new ProjectProperty(); // bool readOk = false; // project = File_Operator.Xml_Serialize("C:\\Users\\CTOS\\Desktop\\empty.pro", false, project, out readOk); // if (readOk) // { // workService.ProjectPro = project; // workService.ProjectPro.LastOpenProject = "C:\\Users\\CTOS\\Desktop\\empty.pro"; // workService.ProjectPro.NowOpenProjectFile = "C:\\Users\\CTOS\\Desktop\\empty.pro".Substring("C:\\Users\\CTOS\\Desktop\\empty.pro".LastIndexOf("\\") + 1).Trim(); // //WeakReferenceMessenger.Default.Send(new DesktopAlertMessage { Content = "打开项目文件成功!" }); // } // */ // #endregion // await ChangeDeviceStatus(Entities.DeviceStatus.Idel); //} //else //{ // await ChangeDeviceStatus(Entities.DeviceStatus.Finish); //} } } //下料流程 private async Task DownLoadDispatcherEx() { while (!_cts.Token.IsCancellationRequested) { if (workService.stationService_Dose.StationProp.deviceStatus != Entities.DeviceStatus.Finish) { await Task.Delay(2000); continue; } if (workService.ProjectPro.TransferArea.All(t => t.IsEmpty)) { await ChangeDeviceStatus(Entities.DeviceStatus.Idel); continue; } await ChangeDeviceStatus(Entities.DeviceStatus.CarryOn); #region 搬目标、母液、tip、 粉头 for (int i = 1; i <= 3; i++) //1~3是样品载具 { if (workService.ProjectPro.TransferArea.Count < i) break; var transferArea = workService.ProjectPro.TransferArea[i - 1]; if (!transferArea.IsEmpty) continue; //寻找是否有样品载具待搬运 var sampleFixture = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._12mL样品工装 || f.FixtureType == BoxTypeEnum._5mL样品工装)); if (sampleFixture == null) break; await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferFixtureFromCacheToTransfer(sampleFixture, transferArea, _cts.Token); } for (int i = 4; i <= 5; i++) //4~5是母液载具 { if (workService.ProjectPro.TransferArea.Count < i) break; var transferArea = workService.ProjectPro.TransferArea[i - 1]; if (!transferArea.IsEmpty) continue; //寻找是否有母液载具待搬运 var targetFixture = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._40mL原液工装)); if (targetFixture == null) break; await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferFixtureFromCacheToTransfer(targetFixture, transferArea, _cts.Token); } for (int i = 6; i <= 7; i++) //6~7是tip/粉末 { if (workService.ProjectPro.TransferArea.Count < i) break; var transferArea = workService.ProjectPro.TransferArea[i - 1]; if (!transferArea.IsEmpty && (transferArea.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || transferArea.FixtureType == BoxTypeEnum._125mL粉末瓶工装) ) { //找粉末放进去 await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferPlateformMoveTo(PlateformPos.GloveBox1, _cts.Token); if (transferArea.FixtureType == BoxTypeEnum._16mL粉末瓶工装) { var samplePowderBox = transferArea as SourcePowderBottleBoxModel; for (int j = 0;j< samplePowderBox.SourcePowderBottleCollection.Count;j++) { var sourcePowderBottleHome = samplePowderBox.SourcePowderBottleCollection[j]; if (!sourcePowderBottleHome.HaveBottle) { //搬运粉末头 var powderHeader = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(p =>(p.PosId_InBox == j + 1) && p.BoxSNCode.Equals(samplePowderBox.BoxSNCode) && p.HaveBottle && p.PowderBottleType == sourcePowderBottleHome.PowderBottleType); if (powderHeader == null) break; await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, powderHeader.Pos_InDosePowderHC, powderHeader.PowderBottleType, _cts.Token,1); await FourAxisPutPowderHeader((int)BoxAreaEnum._手套箱传送平台, samplePowderBox.BoxId_inDoseUpload, sourcePowderBottleHome.PosId_InBox, powderHeader.PowderBottleType, _cts.Token,1); var newPowderBottle = File_Operator.DeepCopy(powderHeader); newPowderBottle.PosId_InBox = sourcePowderBottleHome.PosId_InBox; newPowderBottle.HaveBottle = true; App.Current.Dispatcher.Invoke(() => { samplePowderBox.SourcePowderBottleCollection[j] = newPowderBottle; powderHeader.HaveBottle = false; powderHeader.SourcePowderName = ""; powderHeader.OriginWeight = powderHeader.RemainWeight = 0; }); } } } else { var samplePowderBox = transferArea as SourcePowderBottleBoxModel_125ml; for (int j = 0; j < samplePowderBox.SourcePowderBottleCollection.Count; j++) { var sourcePowderBottleHome = samplePowderBox.SourcePowderBottleCollection[j]; if (!sourcePowderBottleHome.HaveBottle) { //搬运粉末头 var powderHeader = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(p => p.HaveBottle && p.PowderBottleType == sourcePowderBottleHome.PowderBottleType); if (powderHeader == null) break; await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, powderHeader.Pos_InDosePowderHC, powderHeader.PowderBottleType, _cts.Token, 1); await FourAxisPutPowderHeader((int)BoxAreaEnum._手套箱传送平台, samplePowderBox.BoxId_inDoseUpload, sourcePowderBottleHome.PosId_InBox, powderHeader.PowderBottleType, _cts.Token, 1); var newPowderBottle = File_Operator.DeepCopy(powderHeader); newPowderBottle.PosId_InBox = sourcePowderBottleHome.PosId_InBox; newPowderBottle.HaveBottle = true; App.Current.Dispatcher.Invoke(() => { powderHeader.HaveBottle = false; powderHeader.SourcePowderName = ""; powderHeader.OriginWeight = powderHeader.RemainWeight = 0; samplePowderBox.SourcePowderBottleCollection[j] = newPowderBottle; }); } } } } else if (transferArea.IsEmpty) { //找tip放进去 var targetFixture = workService.ProjectPro.TipHeadArea.FirstOrDefault(f => !f.IsEmpty); if (targetFixture == null) continue; await TransferPlateformMoveTo(PlateformPos.GloveBox2, _cts.Token); await TransferFixtureFromCacheToTransfer(targetFixture, transferArea, _cts.Token); } } //await TransferPlateformMoveTo(PlateformPos.TransferIn, _cts.Token); await TransferPlateformMoveTo(PlateformPos.TransferOut, _cts.Token); //MessageBox.Show("通知AGV取料-需要判断是否需要空粉末治具及个数"); //var testJson = new { test="1" }; //var res = await SendJson((new Guid()).ToString(), "unload" , testJson.ToJson()); #region 打包请求BS数据 ToBsUnLoadData toBsUnLoadData = new ToBsUnLoadData() { SampleSeqs = new List(), Config = new ToBsConfig(), NeedFixture = new List() }; toBsUnLoadData.Config.BoxInfo = new List(); for (int i = 0; i < 7; i++) { var transferArea = workService.ProjectPro.TransferArea[i]; if (transferArea.IsEmpty) continue; ToBsBoxInfo boxInfo = new ToBsBoxInfo() { FixtureType = (int)transferArea.FixtureType, SnCode = transferArea.BoxSNCode, PosInUpload = transferArea.BoxId_inDoseUpload, Detail = new List() }; //如果是原液或者粉末需要将数据写入boxInfo.details,如果是5、12ml瓶子则写入toBsUnLoadData.SampleSeqs if (transferArea is TipBoxModel) { var tipBox = transferArea as TipBoxModel; boxInfo.RemainCount = tipBox.TipItems.Count(t => t.IsAvailable); } else if (transferArea is SourceLiquidBottleBoxModel) { var sourceBox = transferArea as SourceLiquidBottleBoxModel; var allBottles = sourceBox.SourceLiquidBottleCollection.Where(s => s.HaveBottle); foreach (var bottle in allBottles) { var detail = new Detail() { Code = bottle.SourceLiquidName, Pos = bottle.PosId_InBox.ToString(), RemainWeight = bottle.RemainVolume }; boxInfo.Detail.Add(detail); } } else if (transferArea is SourcePowderBottleBoxModel) { var sourceBox = transferArea as SourcePowderBottleBoxModel; var allBottles = sourceBox.SourcePowderBottleCollection.Where(s => s.HaveBottle); foreach (var bottle in allBottles) { var detail = new Detail() { Code = bottle.SourcePowderName, Pos = bottle.PosId_InBox.ToString(), RemainWeight = bottle.RemainWeight }; boxInfo.Detail.Add(detail); } } else if (transferArea is SourcePowderBottleBoxModel_125ml) { var sourceBox = transferArea as SourcePowderBottleBoxModel_125ml; var allBottles = sourceBox.SourcePowderBottleCollection.Where(s => s.HaveBottle); foreach (var bottle in allBottles) { var detail = new Detail() { Code = bottle.SourcePowderName, Pos = bottle.PosId_InBox.ToString(), RemainWeight = bottle.RemainWeight }; boxInfo.Detail.Add(detail); } } else if (transferArea is SampleBottleBoxModel) { var sourceBox = transferArea as SampleBottleBoxModel; var allBottles = sourceBox.SampleBottleList.Where(s => s.HaveBottle); foreach (var bottle in allBottles) { var sampleSeq = new ToBsSampleSeq() { Area = "A1", Carrier = transferArea.BoxId_inDoseUpload.ToString(), Code = bottle.SampleContentName, Pos = bottle.PosId_InBox.ToString(), SampleConfig = new ToBsSampleConfig(), OriginSeqIds = new List() { bottle.SampleSeqId } }; sampleSeq.SampleConfig.SnCode = transferArea.BoxSNCode; sampleSeq.SampleConfig.MaterialDoseFunctionFlow = new List(); if (bottle.MaterialDoseFlowList != null && bottle.MaterialDoseFlowList.Count > 0) { foreach (var item in bottle.MaterialDoseFlowList) { ToBsMaterialDoseFunctionFlow sampleFunction = new ToBsMaterialDoseFunctionFlow() { FunctionFlowType = (int)item.FunctionFlowType, TargetVolumn = item.TargetVolume, UserMaterialName = item.UseMaterialName, RealVolumn = item.ActualVolume }; sampleSeq.SampleConfig.MaterialDoseFunctionFlow.Add(sampleFunction); } toBsUnLoadData.SampleSeqs.Add(sampleSeq); } sampleSeq.SampleType = bottle.SampleBottleType == SampleBottleTypeEnum._5mL ? "5mL" : "12mL"; } } toBsUnLoadData.Config.BoxInfo.Add(boxInfo); } var toBsFixtureInfo = new List(); var allPowderBottles = workService.ProjectPro.PowderHeaderCacheArea.Where(p => p.HaveBottle); List remainTransferPos = new List() { 6,7}; foreach (var PowderBottle in allPowderBottles) { if (toBsFixtureInfo.All(s => !s.SnCode.Equals(PowderBottle.BoxSNCode))) { var pos = remainTransferPos.FirstOrDefault(); if (pos != 6 && pos != 7) continue; remainTransferPos.Remove(pos); toBsFixtureInfo.Add(new ToBsFixtureInfo() { FixtureType = PowderBottle.PowderBottleType == PowderBottleTypeEnum._16mL ? (int)BoxTypeEnum._16mL粉末瓶工装 : (int)BoxTypeEnum._125mL粉末瓶工装, BoxIdInDoseUpload = pos, SnCode = PowderBottle.BoxSNCode }); } } toBsUnLoadData.NeedFixture = toBsFixtureInfo; if (toBsUnLoadData.NeedFixture.Count > 0) { WeakReferenceMessenger.Default.Send(new DesktopAlertMessage() { Header = "提示", Content = $"向BS请求治具{JsonConvert.SerializeObject(toBsUnLoadData.NeedFixture)}" }); } #endregion if (!workService.ProjectPro.bNoUseBS) { var res = await SendJson((new Guid()).ToString(), "unload", toBsUnLoadData.ToJson()); while (!res.Item1) { WeakReferenceMessenger.Default.Send(new DesktopAlertMessage() { Header = "提示", Content = "调用BS-unload方法失败" }); await Task.Delay(1000); res = await SendJson((new Guid()).ToString(), "unload", toBsUnLoadData.ToJson()); } } else { //todo:不启用bs给出个弹窗,拿完之后清空传递仓数据,并将状态置为Finish } #endregion } } /// /// 返回转移区域的空位置 /// /// 1表示目标瓶在1-3找,2表示原液瓶在4-5找,3表示tip载具4表示粉末载具在6-7找 private BaseBottleBox GetAvaliableTransferArea(int type) { BaseBottleBox baseBottleBox = null; int startIndex = 0; int endIndex = 0; switch (type) { case 1: //目标瓶在1-3 startIndex = 0; endIndex = 3; break; case 2: //原液瓶载具在4-5 startIndex = 3; endIndex = 5; break; case 3: //tip case 4: //粉末在6-7 startIndex = 5; endIndex = 7; break; default: break; } for (int i = startIndex; i < endIndex; i++) { if (workService.ProjectPro.TransferArea[i].IsEmpty) { baseBottleBox = workService.ProjectPro.TransferArea[i]; break; } } return baseBottleBox; } private async Task TransferFixtureFromPowderCacheToTransfer(SourcePowderBottleModel sourcePowderBottleModel, CancellationToken token) { var fixture = sourcePowderBottleModel.PowderBottleType == PowderBottleTypeEnum._16mL ? BoxTypeEnum._16mL粉末瓶工装 : BoxTypeEnum._125mL粉末瓶工装; var powderFixtures = workService.ProjectPro.TransferArea.Where(f => !f.IsEmpty && f.FixtureType == fixture); SourcePowderBottleBoxModel powderBox = null; SourcePowderBottleBoxModel_125ml powderBox_125 = null; BaseBottleBox powderFixture1 = null; foreach (var powderFixture in powderFixtures) { if (powderFixture is SourcePowderBottleBoxModel) { powderBox = powderFixture as SourcePowderBottleBoxModel; if (powderBox.SourcePowderBottleCollection.Any(s => !s.HaveBottle)) break; } else if (powderFixture is SourcePowderBottleBoxModel_125ml) { powderBox_125 = powderFixture as SourcePowderBottleBoxModel_125ml; if (powderBox_125.SourcePowderBottleCollection.Any(s => !s.HaveBottle)) break; } powderFixture1 = powderFixture; } if (powderBox.SourcePowderBottleCollection.All(s => s.HaveBottle) && powderBox_125.SourcePowderBottleCollection.All(s => s.HaveBottle)) return false; int powderTransferIndex = workService.ProjectPro.TransferArea.IndexOf(powderFixture1);//治具位置 int sourceIndex = workService.ProjectPro.PowderHeaderCacheArea.IndexOf(sourcePowderBottleModel); //缓存位置位置 if (powderBox != null) { var aimPowderBottle = powderBox.SourcePowderBottleCollection.First(s => !s.HaveBottle); //目标位置 await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, sourceIndex, powderBox.PowderBottleType, token); await FourAxisPutPowderHeader((int)BoxAreaEnum._手套箱传送平台, powderFixture1.BoxId_inDoseUpload, aimPowderBottle.PosId_InBox, powderBox.PowderBottleType, token); var newPowderBottle = File_Operator.DeepCopy(sourcePowderBottleModel); newPowderBottle.HaveBottle = true; newPowderBottle.Pos_InDosePowderHC = aimPowderBottle.Pos_InDosePowderHC; powderBox.SourcePowderBottleCollection[aimPowderBottle.PosId_InBox - 1] = newPowderBottle; workService.ProjectPro.PowderHeaderCacheArea[sourceIndex - 1] = new SourcePowderBottleModel() { HaveBottle = false }; } else if (powderBox_125 != null) { var aimPowderBottle = powderBox_125.SourcePowderBottleCollection.First(s => !s.HaveBottle); //目标位置 await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, sourceIndex, powderBox_125.PowderBottleType, token); await FourAxisPutPowderHeader((int)BoxAreaEnum._手套箱传送平台, powderFixture1.BoxId_inDoseUpload, aimPowderBottle.PosId_InBox, powderBox_125.PowderBottleType, token); // 更新粉末缓存区(替换集合元素) var newPowderBottle = File_Operator.DeepCopy(sourcePowderBottleModel); newPowderBottle.HaveBottle = true; newPowderBottle.Pos_InDosePowderHC = aimPowderBottle.Pos_InDosePowderHC; powderBox_125.SourcePowderBottleCollection[aimPowderBottle.PosId_InBox - 1] = newPowderBottle; workService.ProjectPro.PowderHeaderCacheArea[sourceIndex - 1] = new SourcePowderBottleModel() { HaveBottle = false }; } return true; } /// /// 搬运治具从tip缓存位到搬运位 /// /// /// private async Task TransferFixtureFromTipCacheToTransfer(TipBoxModel FixtureCacheArea, CancellationToken token) { var aimFixture = workService.ProjectPro.TransferArea.OrderBy(a => a.BoxId_inDosingStation).First(f => f.IsEmpty); if (aimFixture is null) { return false; } int aimFixtureIndex = workService.ProjectPro.TransferArea.IndexOf(aimFixture); await FourAxisTakeBox((int)BoxAreaEnum._Tip托盘存放平台, FixtureCacheArea.FixtureType, (ushort)FixtureCacheArea.BoxId_inDosingStation, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._手套箱传送平台, aimFixture.FixtureType, (ushort)aimFixture.BoxId_inDosingStation, _cts.Token); var newCacheFixture = File_Operator.DeepCopy(FixtureCacheArea); newCacheFixture.BoxId_inDosingStation = aimFixture.BoxId_inDosingStation; newCacheFixture.IsDoseFinish = true; newCacheFixture.IsEmpty = false; newCacheFixture.IsUseFinsh = true; try { App.Current.Dispatcher.Invoke(() => { workService.ProjectPro.TransferArea[aimFixtureIndex] = newCacheFixture; workService.ProjectPro.TipHeadArea[FixtureCacheArea.BoxId_inDosingStation - 1] = new TipBoxModel() { IsEmpty = true, BoxId_inDoseDnload = FixtureCacheArea.BoxId_inDoseUpload, BoxId_inDoseUpload = FixtureCacheArea.BoxId_inDoseUpload, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台 }; }); } catch (Exception ex) { MessageBox.Show(ex.Message); } return true; } /// /// 搬运治具从缓存位到搬运位 /// /// /// private async Task TransferFixtureFromCacheToTransfer(BaseBottleBox FixtureCacheArea, BaseBottleBox aimFixture, CancellationToken token) { //var aimFixture = workService.ProjectPro.TransferArea.OrderBy(a => a.BoxId_inDosingStation).First(f => f.IsEmpty); if (aimFixture is null) { return false; } var aimFixtureIndex = workService.ProjectPro.TransferArea.IndexOf(aimFixture); if (FixtureCacheArea is TipBoxModel) { var fixtnew = FixtureCacheArea as TipBoxModel; var pos = (ushort)fixtnew.BoxId_inDosingStation; pos = (ushort)(3 - pos + 1); await FourAxisTakeBox((ushort)BoxAreaEnum._Tip托盘存放平台, fixtnew.FixtureType, (ushort)pos, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._手套箱传送平台, fixtnew.FixtureType, (ushort)aimFixture.BoxId_inDoseUpload, _cts.Token); } else { await FourAxisTakeBox((ushort)BoxAreaEnum._托盘存放平台, FixtureCacheArea.FixtureType, (ushort)FixtureCacheArea.BoxId_inDosingStation, _cts.Token); await FourAxisPutBox((int)BoxAreaEnum._手套箱传送平台, FixtureCacheArea.FixtureType, (ushort)aimFixture.BoxId_inDoseUpload, _cts.Token); } var newCacheFixture = File_Operator.DeepCopy(FixtureCacheArea); newCacheFixture.BoxId_inDoseUpload = aimFixture.BoxId_inDoseUpload; newCacheFixture.BoxId_inDosingStation = aimFixture.BoxId_inDosingStation; newCacheFixture.IsDoseFinish = true; newCacheFixture.IsEmpty = false; newCacheFixture.IsUseFinsh = true; try { App.Current.Dispatcher.Invoke(() => { workService.ProjectPro.TransferArea[aimFixtureIndex] = newCacheFixture; if (FixtureCacheArea.BoxArea == BoxAreaEnum._托盘存放平台) { workService.ProjectPro.FixtureCacheArea[FixtureCacheArea.BoxId_inDosingStation - 1] = new BaseBottleBox() { IsEmpty = true, BoxId_inDoseDnload = FixtureCacheArea.BoxId_inDoseUpload, BoxId_inDoseUpload = FixtureCacheArea.BoxId_inDoseUpload, BoxId_inDosingStation = FixtureCacheArea.BoxId_inDosingStation, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._托盘存放平台 }; } else if (FixtureCacheArea.BoxArea == BoxAreaEnum._Tip托盘存放平台) { var fixTipModel = FixtureCacheArea as TipBoxModel; var tipBox = new TipBoxModel() { IsEmpty = true, BoxId_inDosingStation = fixTipModel.BoxId_inDosingStation, BoxArea = BoxAreaEnum._Tip托盘存放平台, FixtureType = fixTipModel.FixtureType, HaveBox = false, UseIndex = 96, TipItems = new ObservableCollection() }; for (int i = 0; i < 96; i++) { tipBox.TipItems.Add(new TipHeadItem() { IsAvailable = false, UseIndex = i + 1}); } workService.ProjectPro.TipHeadArea[fixTipModel.BoxId_inDosingStation - 1] = tipBox; } }); } catch (Exception ex) { MessageBox.Show(ex.Message); } return true; } public async Task TransferPlateformMoveTo(PlateformPos plateformPos, CancellationToken token) { if (token.IsCancellationRequested || TestMode) return; var _modbusClient_Plc1 = this.CoreService.GetServiceInstance(DeviceNames.Plc1.ToString()); var transferPlatePos = await ReadScannedValueAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_BoxPos); if (transferPlatePos > 0 && transferPlatePos < 5) //需要先读取当前的位置,如果当前位置是 { PlateformPos currentPos = PlateformPos.TransferOut; //1:外面 2:里面 3:加粉头 4:载具位置 switch (transferPlatePos) { case 1: currentPos = PlateformPos.TransferOut; break; case 2: currentPos = PlateformPos.TransferIn; break; case 3: currentPos = PlateformPos.GloveBox1; break; case 4: currentPos = PlateformPos.GloveBox2; break; default: break; } if ((plateformPos == PlateformPos.TransferOut && (currentPos == PlateformPos.GloveBox1 || currentPos == PlateformPos.GloveBox2)) || (currentPos == PlateformPos.TransferOut && (plateformPos == PlateformPos.GloveBox1 || plateformPos == PlateformPos.GloveBox2)) ) { //目标是过渡舱外面,且当前是过渡舱内部 或者当前是过渡舱外面,且目标是过渡舱内部 需要先将过渡舱到舱内 _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, (ushort)PlateformPos.TransferIn); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token); _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); } } transferPlatePos = await ReadScannedValueAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_BoxPos); if (transferPlatePos > 0 && transferPlatePos < 5) { PlateformPos currentPos = PlateformPos.TransferOut; switch (transferPlatePos) { case 1: currentPos = PlateformPos.TransferOut; break; case 2: currentPos = PlateformPos.TransferIn; break; case 3: currentPos = PlateformPos.GloveBox1; break; case 4: currentPos = PlateformPos.GloveBox2; break; default: break; } if (currentPos != PlateformPos.GloveBox1 && currentPos != PlateformPos.GloveBox2 && plateformPos == PlateformPos.GloveBox1) { //目标是粉末位置,当前位置如果 _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, (ushort)PlateformPos.GloveBox2); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token); _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); } } _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, (ushort)plateformPos); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token); _modbusClient_Plc1.Command.WriteValue(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0); await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); } public async Task WriteCmdToPlc(string cmd) { ushort plcAddress = 0; ushort value = 1; bool needReset = true; //是否需要200ms复位 bool needMaunalMode = false; //是否需要自动 bool needChangeMode = false; switch (cmd) { case "start": plcAddress = PlcPoints_MaterialDose.W_PCRunStatus; needChangeMode = true; value = 2; break; case "pause": plcAddress = PlcPoints_MaterialDose.W_PCRunStatus; value = 1; //1:停止中,2:运行中 break; case "reset": plcAddress = PlcPoints_MaterialDose.W_InformationConfirm; value = 1; break; case "init": plcAddress = PlcPoints_MaterialDose.W_Initial; value = 1; needMaunalMode = true; break; default: break; } if (plcAddress != 0 && !TestMode) { if (needChangeMode) { ushort plcMode = needMaunalMode ? (ushort)1 : (ushort)2; //1切成手动 2切成自动 await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_PCMode, plcMode); await Task.Delay(200); await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_PCMode, 0); await Task.Delay(200); } await WriteCommandAsync_FourAxis(plcAddress, value); if (needReset) { await Task.Delay(1000); await WriteCommandAsync_FourAxis(plcAddress, 0); } } } private int GetBottleId(SampleBottleTypeEnum sampleType) { int res = 3; switch (sampleType) { case SampleBottleTypeEnum._5mL: res = 3; break; case SampleBottleTypeEnum._12mL: res = 2; break; default: break; } return res; } /// /// 目标瓶一次加完全部的需要的液体及固体 /// /// /// /// private async Task<(bool _isPowderInMachine,bool _isMotherLiquidInMachine)> MixForSampleBottle(SampleBottleModel sampleBottle, SampleBottleBoxModel sampleBox,bool IsPowderInMachine, bool IsMotherLiquidInMachine, SampleBottleModel samplebottleNext = null) { #region 搬运目标瓶到目标区域开盖 await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, sampleBox.BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); if (string.IsNullOrEmpty(sampleBottle.SNCode)) { await FourAxisGoToScannPos_liquid(_cts.Token, GetBottleId(sampleBottle.SampleBottleType), null, sampleBottle); if (TestMode) sampleBottle.SNCode = DateTime.Now.ToString(); } await FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); await OpenBottleLid(_cts.Token, null, sampleBottle); if (!TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } } //固定加一个粉末,演示使用,0317粉末载具搬运干涉,客户想看只能固定1号位置加16ml的演示了 if (false && !TestMode) { #region 搬运粉末加样头去梅特勒称上 SourcePowderBottleModel powderBottle = new SourcePowderBottleModel() { Pos_InDosePowderHC = 1, PowderBottleType = PowderBottleTypeEnum._16mL }; if (!IsPowderInMachine) { if (!TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取粉末加样头 放到称重模块中 await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, powderBottle.Pos_InDosePowderHC, powderBottle.PowderBottleType, _cts.Token); //将粉末头放到梅特勒称重模块中 labxPowderInstrument = await labxService.GetInstruments("自动天平XPR105"); await labxService.StartWaitingForHead(labxPowderInstrument.FirstOrDefault(), "Dosing Head", "Dosing Head"); await FourAxisPutPowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, powderBottle.PowderBottleType, _cts.Token); await SetObstructFlag("四轴机械手运行中", false); await labxService.AbortWaitingForHead(); } } IsPowderInMachine = true; #endregion #region 目标瓶从开盖位去称重位 while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); var task1 = FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); var task2 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1);//开门 await Task.WhenAll(task1, task2); await FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); #endregion #region 加粉末 //梅特勒模块关门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); double addPowderWeight = 0; //大99,小125 2~200mg +-0.297mg 200mg-5g 0.297% decimal dosHeight = sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL ? 99m : 125m; double TargetVolume = 30; decimal upT = Math.Round(TargetVolume < 200 ? (decimal)(0.297 / TargetVolume * 100) : 0.297m,13); Logger.LogInformation($"请求加样的粉末数量-{TargetVolume},上下限为{upT}"); addPowderWeight = await labxService.MTPowderModuleAddPowder(labxPowderInstrument.FirstOrDefault(), "Dosing2", "Dosing2", 4, dosHeight, (decimal)TargetVolume, (decimal)upT, (decimal)upT); //梅特勒模块开门 //await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1); #endregion #region 目标瓶放回开盖位 while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1);//开门 await FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); Task task11 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); //关门 Task task22 = FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await Task.WhenAll(task11, task22); await SetObstructFlag("四轴机械手运行中", false); #endregion } #endregion bool SampleHasOpened = false; for (int i = 0; i < sampleBottle.MaterialDoseFlowList.Count; i++) { var addSample = sampleBottle.MaterialDoseFlowList[i]; if (addSample.FunctionFlowType!= FunctionTypeEnum.震荡摇匀 && (string.IsNullOrEmpty(addSample.UseMaterialName) || addSample.TargetVolume <= 0)) { MessageBox.Show("数据错误!"); } if (addSample.FunctionFlowType == FunctionTypeEnum.加固体原料) { #region 搬运粉末加样头去梅特勒称上 var powderBottle = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(ph => !string.IsNullOrEmpty(addSample.UseMaterialName) && addSample.UseMaterialName.Equals(ph.SourcePowderName)); if (powderBottle is null) { Logger.LogError($"找不到{sampleBox.BoxId_inDosingStation}-{sampleBottle.PosId_InBox}需要的{addSample.UseMaterialName}固体"); continue; } powderBottle.SourcePowderBottleState = SourceBottleStateEnum.Using; if (!IsPowderInMachine) { if (!TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取粉末加样头 放到称重模块中 await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, powderBottle.Pos_InDosePowderHC, powderBottle.PowderBottleType, _cts.Token); //将粉末头放到梅特勒称重模块中 labxPowderInstrument = await labxService.GetInstruments("自动天平XPR105"); await labxService.StartWaitingForHead(labxPowderInstrument.FirstOrDefault(), "Dosing Head", "Dosing Head"); await FourAxisPutPowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, powderBottle.PowderBottleType, _cts.Token); await SetObstructFlag("四轴机械手运行中", false); await labxService.AbortWaitingForHead(); } } IsPowderInMachine = false; #endregion #region 目标瓶从开盖位去称重位 if (!TestMode && (i == 0 || sampleBottle.MaterialDoseFlowList[i - 1].FunctionFlowType != FunctionTypeEnum.加固体原料)) { //第一个加样或者上一个加样不是固体,则取目标瓶开盖位到称重位 while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); var task1 = FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); var task2 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1);//开门 await Task.WhenAll(task1,task2); await FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); } #endregion #region 加粉末 if (!TestMode) { //梅特勒模块关门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); double addPowderWeight = 0; //大99,小125 2~200mg +-0.297mg 200mg-5g 0.297% decimal dosHeight = sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL ? 96m : 122m; //99m : 125m decimal upT = Math.Round((decimal)addSample.TargetVolume < 200 ? (decimal)(0.297 / addSample.TargetVolume * 100) : 0.297m, 11); Logger.LogInformation($"(decimal)addSample.TargetVolume-{addSample.TargetVolume},上下限为{upT}"); addPowderWeight = await labxService.MTPowderModuleAddPowder(labxPowderInstrument.FirstOrDefault(), "Dosing2", "Dosing2", 4, dosHeight, (decimal)addSample.TargetVolume, (decimal)upT, (decimal)upT); powderBottle.RemainWeight -= addPowderWeight / 1000; addSample.ActualVolume = addPowderWeight; } else { addSample.ActualVolume = addSample.TargetVolume; } Logger.LogInformation($"粉末目标:{addSample.TargetVolume}实际:{addSample.ActualVolume}"); addSample.IsDoseFinish = true; //梅特勒模块开门 //await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1); #endregion #region 粉末取回 if (powderBottle != null && !TestMode) { //判断是不是最后一个粉末,如果是的话判断下一瓶是不是用的该粉末 bool IsLastPowder = true; for (int j = i + 1; j < sampleBottle.MaterialDoseFlowList.Count; j++) { if (sampleBottle.MaterialDoseFlowList[j].FunctionFlowType == FunctionTypeEnum.加固体原料) { IsLastPowder = false; IsPowderInMachine = sampleBottle.MaterialDoseFlowList[j].UseMaterialName.Equals(powderBottle.SourcePowderName); break; } } if (IsLastPowder && samplebottleNext != null) { var nextMotherLiquid = samplebottleNext.MaterialDoseFlowList.FirstOrDefault(s => s.FunctionFlowType == FunctionTypeEnum.加固体原料); IsPowderInMachine = nextMotherLiquid != null && nextMotherLiquid.UseMaterialName.Equals(powderBottle.SourcePowderName); } if (!IsPowderInMachine) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakePowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, powderBottle.PowderBottleType, _cts.Token); //Task task1 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); //多余的 await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, powderBottle.Pos_InDosePowderHC, powderBottle.PowderBottleType, _cts.Token); //await Task.WhenAll(task1, task2); await SetObstructFlag("四轴机械手运行中", false); } powderBottle.SourcePowderBottleState = SourceBottleStateEnum.Idl; } #endregion #region 目标瓶放回开盖位 if (!TestMode && (i == sampleBottle.MaterialDoseFlowList.Count - 1 || sampleBottle.MaterialDoseFlowList[i+1].FunctionFlowType != FunctionTypeEnum.加固体原料)) { //最后一个加样或者下一个加样不是固体,则取回目标瓶到开盖位 while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1);//开门 await FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); Task task1 = labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); //关门 Task task2 = FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await Task.WhenAll(task1, task2); await SetObstructFlag("四轴机械手运行中", false); } #endregion } else if (addSample.FunctionFlowType == FunctionTypeEnum.加液体原料) { #region 搬运母液去开盖 // 筛选40mL原液工装并转换为SourceLiquidBottleBoxModel类型 var targetBoxAndBottle = workService.ProjectPro.FixtureCacheArea .Where(b => b.FixtureType == BoxTypeEnum._40mL原液工装) .OfType() .SelectMany(box => box.SourceLiquidBottleCollection .Select(bottle => new { Box = box, Bottle = bottle })) .FirstOrDefault(item => !string.IsNullOrEmpty(item.Bottle.SourceLiquidName) && item.Bottle.SourceLiquidName.Equals(addSample.UseMaterialName) && item.Bottle.RemainVolume > 3); var sourceLiquidBox = targetBoxAndBottle?.Box; var sourceBottle = targetBoxAndBottle?.Bottle; if (sourceBottle is null) { Logger.LogError($"找不到{sampleBox.BoxId_inDosingStation}-{sampleBottle.PosId_InBox}需要的{addSample.UseMaterialName}液体"); continue; } sourceBottle.SourceLiquidBottleState = SourceBottleStateEnum.Using; if (!IsMotherLiquidInMachine) { await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, sourceLiquidBox.BoxId_inDosingStation, sourceBottle.PosId_InBox, sourceBottle); if (string.IsNullOrEmpty(sourceBottle.SNCode)) { await FourAxisGoToScannPos_liquid(_cts.Token, 1, sourceBottle, null); } await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceBottle); await SetObstructFlag("四轴机械手运行中", false); await OpenBottleLid(_cts.Token, sourceBottle, null); } else { //说明母液在开盖位,则开假盖子 await OpenCloseBottleFakeCap(_cts.Token,isOpen:true, sourceBottle,null); } IsMotherLiquidInMachine = false; #endregion #region 加液 await XZ_TakeTip_Absorb_Dispense_DiscardTip(_cts.Token, addSample.UseMaterialName, addSample.TargetVolume, sourceBottle, sampleBottle); //更新原液瓶剩余量 sourceBottle.RemainVolume -= addSample.TargetVolume / 1000; addSample.IsDoseFinish = true; #endregion #region 搬回当前原液 if (sourceBottle != null) { //判断是不是最后一个母液,如果是的话判断下一瓶是不是用的该母液 bool IsLastLiquid = true; for (int j = i + 1; j < sampleBottle.MaterialDoseFlowList.Count; j++) { if (sampleBottle.MaterialDoseFlowList[j].FunctionFlowType == FunctionTypeEnum.加液体原料) { IsLastLiquid = false; IsMotherLiquidInMachine = sampleBottle.MaterialDoseFlowList[j].UseMaterialName.Equals(sourceBottle.SourceLiquidName); break; } } if (IsLastLiquid && samplebottleNext != null) { var nextMotherLiquid = samplebottleNext.MaterialDoseFlowList.FirstOrDefault(s => s.FunctionFlowType == FunctionTypeEnum.加液体原料); IsMotherLiquidInMachine = nextMotherLiquid != null && nextMotherLiquid.UseMaterialName.Equals(sourceBottle.SourceLiquidName); if (sourceBottle.RemainVolume < 3) { IsMotherLiquidInMachine = false; } } //四轴机械手取回原液瓶 放到托盘存放平台 //关盖 if (!IsMotherLiquidInMachine) { await CloseBottleLid(_cts.Token, sourceBottle, null); if (!TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } } await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceBottle); await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, sourceLiquidBox.BoxId_inDosingStation, sourceBottle.PosId_InBox, sourceBottle); await SetObstructFlag("四轴机械手运行中", false); } else { //说明下一瓶还需要用,关假盖子 await OpenCloseBottleFakeCap(_cts.Token, isOpen: false, sourceBottle, null); } sourceBottle.SourceLiquidBottleState = SourceBottleStateEnum.Idl; } #endregion } else { //震荡摇匀 await CloseBottleLid(_cts.Token, null, sampleBottle); await ShakeSampleBottle(_cts.Token, sampleBottle); if (i != sampleBottle.MaterialDoseFlowList.Count - 1) { //不是最后一次摇匀,需要开盖 await OpenBottleLid(_cts.Token, null, sampleBottle); } else { //最后一次摇匀,则需要标志下已经关盖了 SampleHasOpened = true; } } } sampleBottle.bDoseFinish = true; //关盖震荡摇匀并放回 #region 关盖震荡摇匀 if (!SampleHasOpened) { await CloseBottleLid(_cts.Token, null, sampleBottle); } if (!TestMode) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } } var isShakeMix = await dataAccessService.LoadEntityAsync(s => s.Key.Equals("IsShakeMix") && s.Group.Equals("Setting")); if (isShakeMix != null && !isShakeMix.Context.Equals("0")) { await SetObstructFlag("四轴机械手运行中", true); await ShakeSampleBottle(_cts.Token, sampleBottle); } await FourAxisTakeSampleBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await FourAxisPutSampleBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, sampleBox.BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); #endregion return (IsPowderInMachine, IsMotherLiquidInMachine); } #endregion protected override void LoadServices() { base.LoadServices();//复用父类通用逻辑 + 子类扩展 appConfigService = this.CoreService.GetServiceInstance(); labxService = this.CoreService.GetServiceInstance(); preWeight = this.CoreService.GetServiceInstance(DeviceNames.PreWeight.ToString()); scannerService = this.CoreService.GetServiceInstance(DeviceNames.Scanner.ToString()); scannerService_Powder = this.CoreService.GetServiceInstance(DeviceNames.Scanner_Powder.ToString()); pipetteService_1ml = this.CoreService.GetServiceInstance(DeviceNames.Pipette_Dose_1ml.ToString()); this._httpClientFactory = this.CoreService.GetServiceInstance(); if (this.ModbusClient != null) { //清除信号 } this.workService.PrepareUploadBox += WorkService_PrepareUploadBox; this.workService.UpdateBoxInfo_BS += WorkService_UpdateBoxInfo_BS; } protected override void LoadDatas() { base.LoadDatas(); InitialData(); } private async Task InitialStationControlState() { if (this.StationProp.cancellationToken != null) this.StationProp.cancellationToken.Cancel(); this.StationProp.cancellationToken = new CancellationTokenSource(); this.StationProp.ManualResetEvent = new ManualResetEvent(true); await SetObstructFlag("传送平台收到准备上料信号", false); await SetObstructFlag("四轴机械手运行中", false); await SetObstructFlag("四轴机械手正在使用传送平台", false); _currentDoseFlow = null; _currentUseSourceLiquidBottle = null; _currentUsePowderBottle = null; } private async Task InitialProjectProState() { for (int i = 0; i < workService.ProjectPro.FixtureCacheArea.Count; i++) { if (workService.ProjectPro.FixtureCacheArea[i] is SampleBottleBoxModel) { SampleBottleBoxModel samplebottleBox = workService.ProjectPro.FixtureCacheArea[i] as SampleBottleBoxModel; samplebottleBox.IsDoseFinish = false; samplebottleBox.IsEmpty = false; samplebottleBox.IsUseFinsh = false; for (int j = 0; j < samplebottleBox.SampleBottleList.Count; j++) { samplebottleBox.SampleBottleList[j].SNCode = string.Empty; samplebottleBox.SampleBottleList[j].bDoseFinish = false; samplebottleBox.SampleBottleList[j].SampleBottleLidState = SampleBottleLidStateEnum.Close; samplebottleBox.SampleBottleList[j].SampleBoxState = SampleBottleStateEnum.Empty; foreach (var doseflow in samplebottleBox.SampleBottleList[j].MaterialDoseFlowList) { doseflow.IsDoseFinish = false; doseflow.ActualVolume = 0; } } } else if (workService.ProjectPro.FixtureCacheArea[i] is SourceLiquidBottleBoxModel) { SourceLiquidBottleBoxModel sourceliquidbox = workService.ProjectPro.FixtureCacheArea[i] as SourceLiquidBottleBoxModel; sourceliquidbox.IsDoseFinish = false; for (int j = 0; j < sourceliquidbox.SourceLiquidBottleCollection.Count; j++) { sourceliquidbox.SourceLiquidBottleCollection[j].SNCode = string.Empty; sourceliquidbox.SourceLiquidBottleCollection[j].LiquidBottleLidState = SourceBottleLidStateEnum.Close; sourceliquidbox.SourceLiquidBottleCollection[j].SourceLiquidBottleState = SourceBottleStateEnum.Idl; sourceliquidbox.SourceLiquidBottleCollection[j].RemainVolume = sourceliquidbox.SourceLiquidBottleCollection[j].OriginVolume; } } else { workService.ProjectPro.FixtureCacheArea[i].IsDoseFinish = false; workService.ProjectPro.FixtureCacheArea[i].IsUseFinsh = false; workService.ProjectPro.FixtureCacheArea[i].IsEmpty = true; } } for (int i = 0; i < workService.ProjectPro.PowderHeaderCacheArea.Count; i++) { workService.ProjectPro.PowderHeaderCacheArea[i].SourcePowderBottleState = SourceBottleStateEnum.Idl; } } public ushort GetInitStatus() { if (TestMode) { return (ushort)3; } return this.ModbusClient.Command.ReadValue(PlcPoints_MaterialDose.R_PLCInitialStatus); } private void InitialData() { //加载传送平台 7个工装 workService.ProjectPro.TransferArea.Clear(); for (int i = 0; i < 7; i++) { workService.ProjectPro.TransferArea.Add(new BaseBottleBox() { BoxId_inDoseDnload = i + 1, BoxId_inDoseUpload = i + 1, IsEmpty = true, IsDoseFinish = false, IsUseFinsh = false, BoxArea = BoxAreaEnum._手套箱传送平台, }); } workService.ProjectPro.FixtureCacheArea.Clear(); //加载工装暂存区域 8个工装 for (int i = 0; i < 8; i++) { workService.ProjectPro.FixtureCacheArea.Add(new BaseBottleBox() { //FixtureType = BoxTypeEnum._40mL原液工装, BoxId_inDosingStation = i + 1, BoxArea = BoxAreaEnum._托盘存放平台, IsEmpty = true, IsDoseFinish = false, IsUseFinsh = false, }); } workService.ProjectPro.PowderHeaderCacheArea.Clear(); //加载粉末加样头暂存区域 10个位置 for (int i = 0; i < 10; i++) { workService.ProjectPro.PowderHeaderCacheArea.Add( new SourcePowderBottleModel() { HaveBottle = false, Pos_InDosePowderHC = i + 1, SNCode = string.Empty, PowderBottleType = PowderBottleTypeEnum._125mL, SourcePowderBottleState = SourceBottleStateEnum.Idl, OriginWeight =0, }); } // 3个tip头工装 workService.ProjectPro.TipHeadArea.Clear(); for (int i = 0; i < 3; i++) { TipBoxModel tipBox = new TipBoxModel() { TipType = i switch { 0 => TipTypeEnum._1000UL, 1 => TipTypeEnum._300UL, 2 => TipTypeEnum._50UL, _ => TipTypeEnum._300UL }, HaveBox = false, UseIndex = 0, BoxId_inDosingStation = i + 1, IsEmpty = true, // 初始无工装(可根据需求调整) }; // 添加96个可用Tip头(避免序列化空引用) for (int j = 0; j < 8 * 12; j++) { tipBox.TipItems.Add(new TipHeadItem { IsAvailable = false, UseIndex = j + 1 }); } workService.ProjectPro.TipHeadArea.Add(tipBox); } _currentDoseFlow = null; _currentUseSourceLiquidBottle = null; _currentUsePowderBottle = null; } private bool bInitial_Z = false; private bool bInitial = false; private ushort lastInitStatus = 999; private async Task InitDown() { var point1 = this.ModbusClient.Command.ReadValue(PlcPoints_MaterialDose.R_PLCInitialStatus); if (point1 != lastInitStatus) { lastInitStatus = point1; if (lastInitStatus != 999 && point1 == 3) //不是开机第一次读取 { _ = Task.Run(async () => { await ChangeDeviceStatus(Entities.DeviceStatus.Idel); WeakReferenceMessenger.Default.Send(new DesktopAlertMessage() { Content = "设备已完成初始化" }); }); } } } /// /// 重写,,每间隔200ms,就会进入这个函数 /// /// /// protected override async void ModbusClientBaseOnScannedEvent(object sender, EventArgs e) { base.ModbusClientBaseOnScannedEvent(sender, e); this.StationProp.ManualResetEvent.WaitOne(); //暂停标志 await InitDown(); //if (!workService.ProjectPro.bNoUseBS && (TaskBoxFromTransferPlateTask == null || TaskBoxFromTransferPlateTask.IsCanceled || TaskBoxFromTransferPlateTask.IsFaulted || TaskBoxFromTransferPlateTask.IsCompleted)) //{ // TaskBoxFromTransferPlateTask = Task.Run(async () => // { // await UploadBoxFromTransferPlateToHCBox(this.StationProp.cancellationToken.Token); // }); //} //if (!workService.ProjectPro.bNoUseBS && (DownloadBoxToTransferPlateTask == null || DownloadBoxToTransferPlateTask.IsCanceled || DownloadBoxToTransferPlateTask.IsFaulted || DownloadBoxToTransferPlateTask.IsCompleted)) //{ // DownloadBoxToTransferPlateTask = Task.Run(async () => // { // await DownloadFixtueBox(this.StationProp.cancellationToken.Token); // }); //} #region 1ml移液枪初始化 //1ml移液枪Z轴初始化 if (ReadScannedValueAsync_FourAxis(PlcPoints_MaterialDose.R_1mlPipetteZInit).Result == 1 && !bInitial_Z) //1ml移液枪Z轴初始化 { bInitial_Z = true; await GunZAxisInit_M1(DeviceNames.Pipette_Dose_1ml_1, pipetteService_1ml); await GunZAxisInit_M1(DeviceNames.Pipette_Dose_1ml_2, pipetteService_1ml); await GunZAxisInit_M1(DeviceNames.Pipette_Dose_1ml_3, pipetteService_1ml); await GunZAxisInit_M1(DeviceNames.Pipette_Dose_1ml_4, pipetteService_1ml); //Z轴初始化成功,回复给机械手 await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_1mlPipetteZInitResult, 1); //等待PLC清除Z初始化信号 await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_1mlPipetteZInit, 0, this.StationProp.cancellationToken.Token); await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_1mlPipetteZInitResult, 0); //清除信号 bInitial_Z = false; } //1ml移液枪初始化 if (ReadScannedValueAsync_FourAxis(PlcPoints_MaterialDose.R_1mlPipetteInit).Result == 1 && !bInitial) //1ml移液枪初始化 { bInitial = true; await GunAllInit_M1(DeviceNames.Pipette_Dose_1ml_1, pipetteService_1ml); await GunAllInit_M1(DeviceNames.Pipette_Dose_1ml_2, pipetteService_1ml); await GunAllInit_M1(DeviceNames.Pipette_Dose_1ml_3, pipetteService_1ml); await GunAllInit_M1(DeviceNames.Pipette_Dose_1ml_4, pipetteService_1ml); //Z轴初始化成功,回复给机械手 await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_1mlPipetteInitResult, 1); //等待PLC清除Z初始化信号 await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_1mlPipetteInit, 0, this.StationProp.cancellationToken.Token); await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_1mlPipetteInitResult, 0); //清除信号 bInitial = false; } #endregion //if (!this.StationProp.bStartButtonTrigger) //没有收到启动信号或者没有按下启动按钮 //{ // //若按下复位按钮,则清除所有状态 // if (this.StationProp.bResetButtonTrigger) //按下复位按钮 // { // this.StationProp.bResetButtonTrigger = false; // await Application.Current.Dispatcher.InvokeAsync(async () => // { // await DialogManager.ShowDialogAsync( // owner: Application.Current.MainWindow, // 尽量传MainWindow作为Owner,避免弹窗无归属 // message: "投料站复位中,正在清除状态,请稍等...\r\n这需要几秒钟时间", // operation: async () => // { // await InitialStationControlState(); // await InitialProjectProState(); // }); // }); // //await InitialStationControlState(); // //await InitialProjectProState(); // } // return; //} //else //按下启动按钮 //{ // if (this.StationProp.bStopButtonTrigger) //收到BS的停止信号或者按下停止按钮 // { // this.StationProp.bStopButtonTrigger = false; // this.StationProp.cancellationToken.Cancel(); // TimeSpan totalCt = this.StationProp.CTWatch.Elapsed; // workService.ProjectPro.Dose_CT = $"{totalCt.Hours}时{totalCt.Minutes}分{totalCt.Seconds}秒"; // this.StationProp.CTWatch.Reset(); // //await magneticStirService.StirringSwitchContriol(TimeSpan.FromSeconds(3), false); // //await ClearReactBottleAndRotaterState(); // this.StationProp.bStartButtonTrigger = false; // this.StationProp.bResetButtonTrigger = false; // this.StationProp.bRunFinish = false; // await InitialStationControlState(); // return; // } // if (this.StationProp.bRunFinish) //如果配置完成了,就不再执行了 // { // this.StationProp.bRunFinish = false; // //this.StationProp.cancellationToken.Cancel(); // TimeSpan totalCt = this.StationProp.CTWatch.Elapsed; // workService.ProjectPro.Dose_CT = $"{totalCt.Hours}时{totalCt.Minutes}分{totalCt.Seconds}秒"; // this.StationProp.CTWatch.Reset(); // WeakReferenceMessenger.Default.Send(new SingleBoolMessage(true)); // WeakReferenceMessenger.Default.Send(new SingleBoolPeifangMessage(true)); // this.StationProp.bStartButtonTrigger = false; // this.StationProp.bStopButtonTrigger = false; // this.StationProp.bResetButtonTrigger = false; // //await InitialStationControlState(); // return; // } //} //切换投料物 //await SwitchCurrentDoseFlow(this.StationProp.cancellationToken.Token); } /// /// 收到BS 告诉的准备上工装信息 ,触发事件 /// /// /// /// private async void WorkService_PrepareUploadBox(object sender, EventArgs e) { while (await ReadObstructFlag("四轴机械手正在使用传送平台") || await ReadObstructFlag("传送平台收到准备上料信号")) { await Task.Delay(300); } await SetObstructFlag("传送平台收到准备上料信号", true); //传送平台到过渡舱外准备上载具 await TransferUploadBox(this.StationProp.cancellationToken.Token); //回复BS准备好上料 //_httpClientFactory. } /// /// BS放好载具到传送平台上,触发更新事件 /// /// /// private async void WorkService_UpdateBoxInfo_BS(object sender, BaseBottleBox e) { try { //收到BS放工装完成信号 //先让PLC将传送平台运行到设备内部 await TransferToDeviceInner(this.StationProp.cancellationToken.Token); await SetObstructFlag("传送平台收到准备上料信号", false); //读取BS告诉CS的工装在传动平台的位置 int pos = e.BoxId_inDoseUpload; BaseBottleBox fixture = workService.ProjectPro.TransferArea.FirstOrDefault(c => c.BoxId_inDoseUpload == pos); fixture = File_Operator.DeepCopy(e); //BS更新序列后 switch (e.FixtureType) { case BoxTypeEnum._40mL原液工装: SourceLiquidBottleBoxModel sourceLiquidBottleBox = e as SourceLiquidBottleBoxModel; sourceLiquidBottleBox.FixtureType = BoxTypeEnum._40mL原液工装; for (int i = 0; i < sourceLiquidBottleBox.SourceLiquidBottleCollection.Count; i++) { sourceLiquidBottleBox.SourceLiquidBottleCollection[i].BoxSNCode = sourceLiquidBottleBox.BoxSNCode; sourceLiquidBottleBox.SourceLiquidBottleCollection[i].LiquidBottleLidState = SourceBottleLidStateEnum.Close; sourceLiquidBottleBox.SourceLiquidBottleCollection[i].SNCode = string.Empty; sourceLiquidBottleBox.SourceLiquidBottleCollection[i].HaveBottle = true; } //将工装信息更新到传送平台对应位置 fixture = File_Operator.DeepCopy(sourceLiquidBottleBox); fixture.IsEmpty = false; fixture.IsUseFinsh = false; fixture.IsDoseFinish = false; break; case BoxTypeEnum._12mL样品工装: SampleBottleBoxModel sampleBottleBox = e as SampleBottleBoxModel; sampleBottleBox.SampleBottleType = SampleBottleTypeEnum._12mL; for (int i = 0; i < sampleBottleBox.SampleBottleList.Count; i++) { sampleBottleBox.SampleBottleList[i].SampleBottleType = SampleBottleTypeEnum._12mL; sampleBottleBox.SampleBottleList[i].bDoseFinish = false; sampleBottleBox.SampleBottleList[i].HaveBottle = true; sampleBottleBox.SampleBottleList[i].SampleBottleLidState = SampleBottleLidStateEnum.Close; sampleBottleBox.SampleBottleList[i].SNCode = string.Empty; sampleBottleBox.SampleBottleList[i].BoxSNCode = sampleBottleBox.BoxSNCode; foreach (var doseflow in sampleBottleBox.SampleBottleList[i].MaterialDoseFlowList) { doseflow.IsDoseFinish = false; } } //将工装信息更新到传送平台对应位置 fixture = File_Operator.DeepCopy(sampleBottleBox); fixture.IsEmpty = false; fixture.IsUseFinsh = false; fixture.IsDoseFinish = false; break; case BoxTypeEnum._5mL样品工装: SampleBottleBoxModel sampleBottleBox_5 = e as SampleBottleBoxModel; sampleBottleBox_5.SampleBottleType = SampleBottleTypeEnum._5mL; for (int i = 0; i < sampleBottleBox_5.SampleBottleList.Count; i++) { sampleBottleBox_5.SampleBottleList[i].SampleBottleType = SampleBottleTypeEnum._5mL; sampleBottleBox_5.SampleBottleList[i].bDoseFinish = false; sampleBottleBox_5.SampleBottleList[i].HaveBottle = true; sampleBottleBox_5.SampleBottleList[i].SampleBottleLidState = SampleBottleLidStateEnum.Close; sampleBottleBox_5.SampleBottleList[i].SNCode = string.Empty; sampleBottleBox_5.SampleBottleList[i].BoxSNCode = sampleBottleBox_5.BoxSNCode; foreach (var doseflow in sampleBottleBox_5.SampleBottleList[i].MaterialDoseFlowList) { doseflow.IsDoseFinish = false; } } //将工装信息更新到传送平台对应位置 fixture = File_Operator.DeepCopy(sampleBottleBox_5); fixture.IsEmpty = false; fixture.IsUseFinsh = false; fixture.IsDoseFinish = false; break; case BoxTypeEnum._16mL粉末瓶工装: SourcePowderBottleBoxModel powderbox = e as SourcePowderBottleBoxModel; powderbox.PowderBottleType = PowderBottleTypeEnum._16mL; for (int i = 0; i < powderbox.SourcePowderBottleCollection.Count; i++) { powderbox.SourcePowderBottleCollection[i].PowderBottleType = PowderBottleTypeEnum._16mL; powderbox.SourcePowderBottleCollection[i].BoxSNCode = powderbox.BoxSNCode; powderbox.SourcePowderBottleCollection[i].SNCode = string.Empty; powderbox.SourcePowderBottleCollection[i].HaveBottle = true; } //将工装信息更新到传送平台对应位置 fixture = File_Operator.DeepCopy(powderbox); fixture.IsEmpty = false; fixture.IsUseFinsh = false; fixture.IsDoseFinish = false; break; case BoxTypeEnum._125mL粉末瓶工装: SourcePowderBottleBoxModel powderbox_125 = e as SourcePowderBottleBoxModel; powderbox_125.PowderBottleType = PowderBottleTypeEnum._125mL; for (int i = 0; i < powderbox_125.SourcePowderBottleCollection.Count; i++) { powderbox_125.SourcePowderBottleCollection[i].PowderBottleType = PowderBottleTypeEnum._125mL; powderbox_125.SourcePowderBottleCollection[i].BoxSNCode = powderbox_125.BoxSNCode; powderbox_125.SourcePowderBottleCollection[i].SNCode = string.Empty; powderbox_125.SourcePowderBottleCollection[i].HaveBottle = true; } fixture = File_Operator.DeepCopy(powderbox_125); fixture.IsEmpty = false; fixture.IsUseFinsh = false; fixture.IsDoseFinish = false; break; case BoxTypeEnum._50uLTip头工装: TipBoxModel tipBoxModel = e as TipBoxModel; tipBoxModel.TipType = TipTypeEnum._50UL; tipBoxModel.BoxId_inDosingStation = pos; tipBoxModel.HaveBox = true; for (var i = 0; i < tipBoxModel.TipItems.Count; i++) { tipBoxModel.TipItems[i].IsAvailable = true; } fixture = File_Operator.DeepCopy(tipBoxModel); fixture.IsEmpty = false; fixture.IsUseFinsh = false; break; case BoxTypeEnum._300uLTip头工装: TipBoxModel tipBoxModel_300 = e as TipBoxModel; tipBoxModel_300.TipType = TipTypeEnum._300UL; tipBoxModel_300.BoxId_inDosingStation = pos; tipBoxModel_300.HaveBox = true; for (var i = 0; i < tipBoxModel_300.TipItems.Count; i++) { tipBoxModel_300.TipItems[i].IsAvailable = true; } fixture = File_Operator.DeepCopy(tipBoxModel_300); fixture.IsEmpty = false; fixture.IsUseFinsh = false; break; case BoxTypeEnum._1000uLTip头工装: TipBoxModel tipBoxModel_1000 = e as TipBoxModel; tipBoxModel_1000.TipType = TipTypeEnum._1000UL; tipBoxModel_1000.BoxId_inDosingStation = pos; tipBoxModel_1000.HaveBox = true; for (var i = 0; i < tipBoxModel_1000.TipItems.Count; i++) { tipBoxModel_1000.TipItems[i].IsAvailable = true; } fixture = File_Operator.DeepCopy(tipBoxModel_1000); fixture.IsEmpty = false; fixture.IsUseFinsh = false; break; } } catch (Exception) { } } private async Task SwitchCurrentDoseFlowEx(CancellationToken token) { try { if (this.StationProp.bRunFinish) return; var FixtureCacheAreas = workService.ProjectPro.FixtureCacheArea.Where(b => b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装); if (_currentDoseFlow == null) { //找到第一个没有配置完成的样品工装 BaseBottleBox fixturePosPro = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(b => !b.IsDoseFinish && !b.IsEmpty && (b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装)); if (fixturePosPro == null) //所有治具工装配置完成 { this.StationProp.bRunFinish = true; //当前工单配置完成 await RunFinishTaskBackSourceLiquidBottleOrCurrentUsePowderBottle(_currentDoseFlow, token); _currentDoseFlow = null; return; } else { SampleBottleBoxModel sampleBox = fixturePosPro as SampleBottleBoxModel; //找到工装中 第一个没有配置完成的样品瓶子 SampleBottleModel samplebottle = sampleBox.SampleBottleList.FirstOrDefault(f => f.HaveBottle && !f.bDoseFinish); if (samplebottle == null) { sampleBox.IsDoseFinish = true; _currentDoseFlow = null; return; } else { if (samplebottle.MaterialDoseFlowList.Count == 0) { samplebottle.bDoseFinish = true; _currentDoseFlow = null; return; } MaterialDoseFunctionFlow doseflow = samplebottle.MaterialDoseFlowList.FirstOrDefault(f => !f.IsDoseFinish && f.TargetVolume > 0); if (doseflow != null) { _currentDoseFlow = doseflow; if (DoseTask_BasedOnCurrentDoseFlow == null || DoseTask_BasedOnCurrentDoseFlow.IsFaulted || DoseTask_BasedOnCurrentDoseFlow.IsCanceled || DoseTask_BasedOnCurrentDoseFlow.IsCompleted) { DoseTask_BasedOnCurrentDoseFlow = Task.Run(async () => { await OneMaterialDose(token); }); } } else { samplebottle.bDoseFinish = true; _currentDoseFlow = null; } } } } } catch (Exception) { throw; } finally { await Task.Delay(2000); } } /// /// 切换当前投料流程 /// /// /// private async Task SwitchCurrentDoseFlow(CancellationToken token) { try { if (this.StationProp.bRunFinish) return; if (_currentDoseFlow == null) { //找到第一个没有配置完成的样品工装 BaseBottleBox fixturePosPro = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(b => !b.IsDoseFinish && !b.IsEmpty && (b.FixtureType == BoxTypeEnum._12mL样品工装 || b.FixtureType == BoxTypeEnum._5mL样品工装)); if (fixturePosPro == null) //所有治具工装配置完成 { this.StationProp.bRunFinish = true; //当前工单配置完成 await RunFinishTaskBackSourceLiquidBottleOrCurrentUsePowderBottle(_currentDoseFlow, token); _currentDoseFlow = null; return; } else { SampleBottleBoxModel sampleBox = fixturePosPro as SampleBottleBoxModel; //找到工装中 第一个没有配置完成的样品瓶子 SampleBottleModel samplebottle = sampleBox.SampleBottleList.FirstOrDefault(f => f.HaveBottle && !f.bDoseFinish); if (samplebottle == null) { sampleBox.IsDoseFinish = true; _currentDoseFlow = null; return; } else { if (samplebottle.MaterialDoseFlowList.Count == 0) { samplebottle.bDoseFinish = true; _currentDoseFlow = null; return; } MaterialDoseFunctionFlow doseflow = samplebottle.MaterialDoseFlowList.FirstOrDefault(f => !f.IsDoseFinish && f.TargetVolume > 0); if (doseflow != null) { _currentDoseFlow = doseflow; if (DoseTask_BasedOnCurrentDoseFlow == null || DoseTask_BasedOnCurrentDoseFlow.IsFaulted || DoseTask_BasedOnCurrentDoseFlow.IsCanceled || DoseTask_BasedOnCurrentDoseFlow.IsCompleted) { DoseTask_BasedOnCurrentDoseFlow = Task.Run(async () => { await OneMaterialDose(token); }); } } else { samplebottle.bDoseFinish = true; _currentDoseFlow = null; } } } } } catch (Exception) { throw; } finally { await Task.Delay(2000); } } /// /// 从传动平台取工装到 治具缓存区 线程 /// /// /// private async Task UploadBoxFromTransferPlateToHCBox(CancellationToken token) { while (true) { if (workService.ProjectPro.bNoUseBS) break; if (token.IsCancellationRequested) break; //从传送平台取样品工装到工装缓存区 if (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._5mL样品工装 || f.FixtureType == BoxTypeEnum._12mL样品工装)) && workService.ProjectPro.FixtureCacheArea.Any(a => a.IsEmpty && a.BoxId_inDosingStation != 1 && a.BoxId_inDosingStation != 5)) //治具缓存区的 位置1和位置5 只给放原液瓶工装 { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台") || await ReadObstructFlag("传送平台收到准备上料信号")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await SetObstructFlag("四轴机械手正在使用传送平台", true); //找到可以搬运的样品工装 BaseBottleBox samplefixture = workService.ProjectPro.TransferArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._5mL样品工装 || f.FixtureType == BoxTypeEnum._12mL样品工装)); await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, samplefixture.FixtureType, (ushort)samplefixture.BoxId_inDoseUpload, token); await SetObstructFlag("四轴机械手正在使用传送平台", false); //找到可以放置的工装缓存位置 BaseBottleBox aimfixture = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(a => a.IsEmpty && a.BoxId_inDosingStation != 1 && a.BoxId_inDosingStation != 5); await FourAxisPutBox((int)BoxAreaEnum._托盘存放平台, aimfixture.FixtureType, (ushort)aimfixture.BoxId_inDosingStation, token); //更新信息 aimfixture.IsEmpty = false; aimfixture.FixtureType = samplefixture.FixtureType; aimfixture = File_Operator.DeepCopy(samplefixture); aimfixture.IsDoseFinish = false; aimfixture.IsUseFinsh = false; samplefixture.IsEmpty = true; samplefixture = null; await SetObstructFlag("四轴机械手运行中", false); } //从传送平台取原液工装到工装缓存区 else if (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && f.FixtureType == BoxTypeEnum._40mL原液工装) && workService.ProjectPro.FixtureCacheArea.Any(a => a.IsEmpty)) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台") || await ReadObstructFlag("传送平台收到准备上料信号")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await SetObstructFlag("四轴机械手正在使用传送平台", true); //找到可以搬运的原液工装 BaseBottleBox liquidfixture = workService.ProjectPro.TransferArea.FirstOrDefault(f => !f.IsEmpty && f.FixtureType == BoxTypeEnum._40mL原液工装); await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, liquidfixture.FixtureType, (ushort)liquidfixture.BoxId_inDoseUpload, token); await SetObstructFlag("四轴机械手正在使用传送平台", false); //找到可以放置的工装缓存位置 BaseBottleBox aimfixture = workService.ProjectPro.FixtureCacheArea.FirstOrDefault(a => a.IsEmpty); await FourAxisPutBox((int)BoxAreaEnum._托盘存放平台, aimfixture.FixtureType, (ushort)aimfixture.BoxId_inDosingStation, token); //更新信息 aimfixture.IsEmpty = false; aimfixture.FixtureType = liquidfixture.FixtureType; aimfixture = File_Operator.DeepCopy(liquidfixture); aimfixture.IsDoseFinish = false; aimfixture.IsUseFinsh = false; liquidfixture.IsEmpty = true; liquidfixture = null; await SetObstructFlag("四轴机械手运行中", false); } //从传送平台的粉末工装中 一个一个取粉末瓶 ---扫码---称重---放到缓存料架上 else if (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || f.FixtureType == BoxTypeEnum._125mL粉末瓶工装)) && workService.ProjectPro.PowderHeaderCacheArea.Any(f => !f.HaveBottle)) { BaseBottleBox powderfixture = workService.ProjectPro.TransferArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._16mL粉末瓶工装 || f.FixtureType == BoxTypeEnum._125mL粉末瓶工装)); SourcePowderBottleBoxModel powderBox = powderfixture as SourcePowderBottleBoxModel; for (int i = 0; i < powderBox.SourcePowderBottleCollection.Count; i++) { SourcePowderBottleModel powderbottle = powderBox.SourcePowderBottleCollection[i]; if (powderbottle.HaveBottle) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台") || await ReadObstructFlag("传送平台收到准备上料信号")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await SetObstructFlag("四轴机械手正在使用传送平台", true); //四轴机械手从传送平台取粉末加样头 await FourAxisTakePowderHeader((int)BoxAreaEnum._手套箱传送平台, powderfixture.BoxId_inDoseUpload, powderbottle.PosId_InBox, powderBox.PowderBottleType, token); //四轴机械手运行到扫码位置 await FourAxisGoToScannPos_powder(token, powderbottle); await SetObstructFlag("四轴机械手正在使用传送平台", false); //称重 await FourAxisPutPowderHeaderToPreWeight(token); await preWeight.Peel(); double powderweight = await preWeight.ReadWeightValue(); powderbottle.OriginWeight = powderbottle.RemainWeight = powderweight; await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_PreWeightFinish, 1);//回复预称重完成 //四轴机械手放粉末加样头到10个缓存区 SourcePowderBottleModel aimpowderbottle_inhc = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(f => !f.HaveBottle); powderbottle.Pos_InDosePowderHC = aimpowderbottle_inhc.Pos_InDosePowderHC; await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, aimpowderbottle_inhc.Pos_InDosePowderHC, powderBox.PowderBottleType, token); //更新信息 aimpowderbottle_inhc = File_Operator.DeepCopy(powderbottle); aimpowderbottle_inhc.HaveBottle = true; powderbottle.HaveBottle = false; await SetObstructFlag("四轴机械手运行中", false); } } } //从传送平台取Tip头工装放到投料站中 else if (workService.ProjectPro.TransferArea.Any(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._50uLTip头工装 || f.FixtureType == BoxTypeEnum._300uLTip头工装 || f.FixtureType == BoxTypeEnum._1000uLTip头工装)) && workService.ProjectPro.TipHeadArea.Any(f => !f.HaveBox)) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台") || await ReadObstructFlag("传送平台收到准备上料信号")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await SetObstructFlag("四轴机械手正在使用传送平台", true); //找到可以搬运的Tip头工装 BaseBottleBox tipfixture = workService.ProjectPro.TransferArea.FirstOrDefault(f => !f.IsEmpty && (f.FixtureType == BoxTypeEnum._50uLTip头工装 || f.FixtureType == BoxTypeEnum._300uLTip头工装 || f.FixtureType == BoxTypeEnum._1000uLTip头工装)); await FourAxisTakeBox((int)BoxAreaEnum._手套箱传送平台, tipfixture.FixtureType, (ushort)tipfixture.BoxId_inDoseUpload, token); await SetObstructFlag("四轴机械手正在使用传送平台", false); //放到Tip缓存区域 1-3 TipBoxModel aimtipbox = workService.ProjectPro.TipHeadArea.FirstOrDefault(f => !f.HaveBox); await FourAxisPutBox((int)BoxAreaEnum._Tip托盘存放平台, tipfixture.FixtureType, (ushort)aimtipbox.BoxId_inDosingStation, token); //更新信息 aimtipbox.HaveBox = true; aimtipbox = File_Operator.DeepCopy(tipfixture as TipBoxModel); if (tipfixture.FixtureType == BoxTypeEnum._50uLTip头工装) { aimtipbox.TipType = TipTypeEnum._50UL; } else if (tipfixture.FixtureType == BoxTypeEnum._300uLTip头工装) { aimtipbox.TipType = TipTypeEnum._300UL; } else if (tipfixture.FixtureType == BoxTypeEnum._1000uLTip头工装) { aimtipbox.TipType = TipTypeEnum._1000UL; } tipfixture.IsEmpty = true; tipfixture = null; await SetObstructFlag("四轴机械手运行中", false); } else { if (!token.IsCancellationRequested) await Task.Delay(2000); } } } /// /// 从载具工装缓存区域 下载具到传送平台 /// /// /// private async Task DownloadFixtueBox(CancellationToken token) { while (true) { if (workService.ProjectPro.bNoUseBS) break; if (token.IsCancellationRequested) break; } } private async Task RunFinishTaskBackSourceLiquidBottleOrCurrentUsePowderBottle(MaterialDoseFunctionFlow flow, CancellationToken token) { #region 搬回当前原液或者粉末瓶 if (_currentUseSourceLiquidBottle != null && _currentUseSourceLiquidBottle.liquidbottle != null) { //四轴机械手取回原液瓶 放到托盘存放平台 //关盖 await CloseBottleLid(token, _currentUseSourceLiquidBottle.liquidbottle, null); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取原液瓶 await FourAxisTakeLiquidBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, _currentUseSourceLiquidBottle.liquidbottle); //四轴机械手放原液瓶到托盘存放平台 await FourAxisPutLiquidBottle(token, (int)BoxAreaEnum._托盘存放平台, _currentUseSourceLiquidBottle.liquidbottleFixture.BoxId_inDosingStation, _currentUseSourceLiquidBottle.liquidbottle.PosId_InBox, _currentUseSourceLiquidBottle.liquidbottle); _currentUseSourceLiquidBottle = null; await SetObstructFlag("四轴机械手运行中", false); } if (_currentUsePowderBottle != null) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取回粉末瓶 放到托盘存放平台 await FourAxisTakePowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, _currentUsePowderBottle.PowderBottleType, token); await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, _currentUsePowderBottle.Pos_InDosePowderHC, _currentUsePowderBottle.PowderBottleType, token); _currentUsePowderBottle = null; await SetObstructFlag("四轴机械手运行中", false); } #endregion } private async Task GetCurrentUseSourceLiquidBottleOrCurrentUsePowderBottle(MaterialDoseFunctionFlow flow, CancellationToken token) { #region 根据当前物料配置流程,搬运当前原液或者粉末瓶 //根据当前物料配置流程,搬运当前原液或者粉末瓶 if (_currentDoseFlow.FunctionFlowType == FunctionTypeEnum.加液体原料) { if (_currentUseSourceLiquidBottle != null && _currentUseSourceLiquidBottle.liquidbottle != null) { //四轴机械手取回原液瓶 放到托盘存放平台 //关盖 await CloseBottleLid(token, _currentUseSourceLiquidBottle.liquidbottle, null); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取原液瓶 await FourAxisTakeLiquidBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, _currentUseSourceLiquidBottle.liquidbottle); //四轴机械手放原液瓶到托盘存放平台 await FourAxisPutLiquidBottle(token, (int)BoxAreaEnum._托盘存放平台, _currentUseSourceLiquidBottle.liquidbottleFixture.BoxId_inDosingStation, _currentUseSourceLiquidBottle.liquidbottle.PosId_InBox, _currentUseSourceLiquidBottle.liquidbottle); _currentUseSourceLiquidBottle.liquidbottle.SourceLiquidBottleState = SourceBottleStateEnum.Idl; _currentUseSourceLiquidBottle = null; await SetObstructFlag("四轴机械手运行中", false); } //查找液体原料瓶 _currentUseSourceLiquidBottle = new UseLiquidBottle() { liquidbottleFixture = null, liquidbottle = null, }; _currentUseSourceLiquidBottle.liquidbottle = workService.ProjectPro.FixtureCacheArea.Where(pos => pos.FixtureType == BoxTypeEnum._40mL原液工装 && pos is SourceLiquidBottleBoxModel) .Select(pos => (SourceLiquidBottleBoxModel)pos) .SelectMany(box => box.SourceLiquidBottleCollection) .FirstOrDefault(bottle => bottle.HaveBottle && bottle.SourceLiquidName.Equals(_currentDoseFlow.UseMaterialName) && bottle.RemainVolume > 2 && bottle.SourceLiquidBottleState == SourceBottleStateEnum.Idl); if (_currentUseSourceLiquidBottle.liquidbottle == null) { } //跟BS要原液瓶 _currentUseSourceLiquidBottle.liquidbottleFixture = workService.ProjectPro.FixtureCacheArea .Where(pos => pos is SourceLiquidBottleBoxModel && ((SourceLiquidBottleBoxModel)pos).SourceLiquidBottleCollection != null && ((SourceLiquidBottleBoxModel)pos).SourceLiquidBottleCollection.Contains(_currentUseSourceLiquidBottle.liquidbottle)).FirstOrDefault(); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); _currentUseSourceLiquidBottle.liquidbottle.SourceLiquidBottleState = SourceBottleStateEnum.Using; //四轴机械手取原液瓶 await FourAxisTakeLiquidBottle(token, (int)BoxAreaEnum._托盘存放平台, _currentUseSourceLiquidBottle.liquidbottleFixture.BoxId_inDosingStation, _currentUseSourceLiquidBottle.liquidbottle.PosId_InBox, _currentUseSourceLiquidBottle.liquidbottle); if (_currentUseSourceLiquidBottle.liquidbottle.SNCode.Equals(string.Empty)) { await FourAxisGoToScannPos_liquid(token, 1, _currentUseSourceLiquidBottle.liquidbottle, null); } //四轴机械手放原液瓶到开关盖区域 await FourAxisPutLiquidBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, _currentUseSourceLiquidBottle.liquidbottle); await SetObstructFlag("四轴机械手运行中", false); //开盖 await OpenBottleLid(token, _currentUseSourceLiquidBottle.liquidbottle, null); } else if (_currentDoseFlow.FunctionFlowType == FunctionTypeEnum.加固体原料) { if (_currentUsePowderBottle != null) { while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取回粉末瓶 放到托盘存放平台 await FourAxisTakePowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, _currentUsePowderBottle.PowderBottleType, token); await FourAxisPutPowderHeader((int)BoxAreaEnum._加样头存放平台, 1, _currentUsePowderBottle.Pos_InDosePowderHC, _currentUsePowderBottle.PowderBottleType, token); _currentUsePowderBottle.SourcePowderBottleState = SourceBottleStateEnum.Idl; _currentUsePowderBottle = null; await SetObstructFlag("四轴机械手运行中", false); } //查找可用的粉末瓶 _currentUsePowderBottle = workService.ProjectPro.PowderHeaderCacheArea.FirstOrDefault(f => f.HaveBottle && f.SourcePowderName == _currentDoseFlow.UseMaterialName && f.RemainWeight > 1); if (_currentUsePowderBottle == null) { } //跟BS要粉末 while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); _currentUsePowderBottle.SourcePowderBottleState = SourceBottleStateEnum.Using; //四轴机械手取粉末加样头 放到称重模块中 await FourAxisTakePowderHeader((int)BoxAreaEnum._加样头存放平台, 1, _currentUsePowderBottle.Pos_InDosePowderHC, _currentUsePowderBottle.PowderBottleType, token); //将粉末头放到梅特勒称重模块中 labxPowderInstrument = await labxService.GetInstruments("自动天平XPR105"); await labxService.StartWaitingForHead(labxPowderInstrument.FirstOrDefault(), "Dosing Head", "Dosing Head"); await FourAxisPutPowderHeader((int)BoxAreaEnum._自动加样模块内, 1, 1, _currentUsePowderBottle.PowderBottleType, token); await SetObstructFlag("四轴机械手运行中", false); await labxService.AbortWaitingForHead(); } #endregion } /// /// 配置流程,由找到的_currentDoseFlow决定具体执行哪个物料的投料流程 /// /// /// private async Task OneMaterialDose(CancellationToken token) { //找到所有未完成投料的样品工装 List sampleBoxList = workService.ProjectPro.FixtureCacheArea.Where(f => (f.FixtureType == BoxTypeEnum._12mL样品工装 || f.FixtureType == BoxTypeEnum._5mL样品工装) && !f.IsDoseFinish && !f.IsEmpty).ToList(); for (int i = 0; i < sampleBoxList.Count; i++) //对每个未配置完成的样品工装进行投料 { SampleBottleBoxModel sampleBox = sampleBoxList[i] as SampleBottleBoxModel; for (int j = 0; j < sampleBox.SampleBottleList.Count; j++) { if (!sampleBox.SampleBottleList[j].HaveBottle || sampleBox.SampleBottleList[j].bDoseFinish) continue; SampleBottleModel sampleBottle = sampleBox.SampleBottleList[j]; MaterialDoseFunctionFlow doseflow = new MaterialDoseFunctionFlow(); doseflow = sampleBottle.MaterialDoseFlowList.FirstOrDefault(f => !f.IsDoseFinish && f.FunctionFlowType == _currentDoseFlow.FunctionFlowType && f.UseMaterialName == _currentDoseFlow.UseMaterialName && f.TargetVolume > 0); if (doseflow == null) continue; if (_currentDoseFlow.FunctionFlowType == FunctionTypeEnum.加液体原料) { if (_currentUseSourceLiquidBottle == null || (_currentUseSourceLiquidBottle.liquidbottle != null && (!_currentUseSourceLiquidBottle.liquidbottle.SourceLiquidName.Equals(_currentDoseFlow.UseMaterialName) || _currentUseSourceLiquidBottle.liquidbottle.RemainVolume < 0.5)) ) { await GetCurrentUseSourceLiquidBottleOrCurrentUsePowderBottle(_currentDoseFlow, token); } while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取样品瓶 await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._托盘存放平台, sampleBoxList[i].BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); //如果这个样品瓶 还没有扫过码 四轴机械手到扫码位置,暂时屏蔽 //if (string.IsNullOrEmpty(sampleBottle.SNCode)) //{ // if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL) // { // await FourAxisGoToScannPos_liquid(token, 3, null, sampleBottle); // } // else // { // await FourAxisGoToScannPos_liquid(token, 2, null, sampleBottle); // } //} //四轴机械手放样品瓶到开关盖区域 await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); //开盖 await OpenBottleLid(token, null, sampleBottle); //执行移液枪取Tip头-吸液-分液-丢Tip头流程 await XZ_TakeTip_Absorb_Dispense_DiscardTip(token, doseflow.UseMaterialName, doseflow.TargetVolume, null, sampleBottle); //更新原液瓶剩余量 _currentUseSourceLiquidBottle.liquidbottle.RemainVolume -= doseflow.TargetVolume / 1000; doseflow.IsDoseFinish = true; //关盖 await CloseBottleLid(token, null, sampleBottle); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //如果这个样品瓶的配置流程没有配置完成 if (sampleBottle.MaterialDoseFlowList.Any(f => !f.IsDoseFinish)) { //四轴机械手取样品瓶 await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); } else //配置完成 摇匀 { await ShakeSampleBottle(token, sampleBottle); sampleBottle.bDoseFinish = true; //四轴机械手取样品瓶 await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); } //四轴机械手放样品瓶到托盘存放平台 await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._托盘存放平台, sampleBoxList[i].BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); } else if (_currentDoseFlow.FunctionFlowType == FunctionTypeEnum.加固体原料) { //执行加固体原料流程 if (_currentUsePowderBottle == null || (_currentUsePowderBottle != null && (!_currentUsePowderBottle.SourcePowderName.Equals(_currentDoseFlow.UseMaterialName) || _currentUsePowderBottle.RemainWeight < 0.1)) ) { await GetCurrentUseSourceLiquidBottleOrCurrentUsePowderBottle(_currentDoseFlow, token); } while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //四轴机械手取样品瓶 await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._托盘存放平台, sampleBoxList[i].BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); //如果这个样品瓶 还没有扫过码 四轴机械手到扫码位置 //todo:屏蔽扫码 //if (string.IsNullOrEmpty(sampleBottle.SNCode)) //{ // if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL) // { // await FourAxisGoToScannPos_liquid(token, 3, null, sampleBottle); // } // else // { // await FourAxisGoToScannPos_liquid(token, 2, null, sampleBottle); // } //} //四轴机械手放样品瓶到开关盖区域 await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); //开盖 await OpenBottleLid(token, null, sampleBottle); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); //梅特勒模块开门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1); await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); //梅特勒模块关门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); double addPowderWeight = 0; //大99,小125 2~200mg +-0.297mg 200mg-5g 0.297% addPowderWeight = await labxService.MTPowderModuleAddPowder(labxPowderInstrument.FirstOrDefault(), "Dosing2", "Dosing2", 4, 99m, (decimal)_currentDoseFlow.TargetVolume, (decimal)10, (decimal)10); _currentUsePowderBottle.RemainWeight -= addPowderWeight / 1000; //梅特勒模块开门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 1); while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._自动加样模块内, 1, 1, sampleBottle); //梅特勒模块关门 await labxService.MTPowderModuleControlStep(labxPowderInstrument.FirstOrDefault(), "Balance Step", "Balance Step", 0); await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); //关盖 await CloseBottleLid(token, null, sampleBottle); doseflow.IsDoseFinish = true; while (await ReadObstructFlag("四轴机械手运行中") || await ReadObstructFlag("四轴机械手正在使用传送平台")) { await Task.Delay(300); } await SetObstructFlag("四轴机械手运行中", true); //如果这个样品瓶的配置流程没有配置完成 if (sampleBottle.MaterialDoseFlowList.Any(f => !f.IsDoseFinish)) { //四轴机械手取样品瓶 await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); } else //配置完成 摇匀 { await ShakeSampleBottle(token, sampleBottle); sampleBottle.bDoseFinish = true; await FourAxisTakeSampleBottle(token, (int)BoxAreaEnum._开关盖区域, 0, 0, sampleBottle); } //四轴机械手放样品瓶到托盘存放平台 await FourAxisPutSampleBottle(token, (int)BoxAreaEnum._托盘存放平台, sampleBoxList[i].BoxId_inDosingStation, sampleBottle.PosId_InBox, sampleBottle); await SetObstructFlag("四轴机械手运行中", false); } } } //这种液体或者粉末 全部样品瓶配置完成 _currentDoseFlow.IsDoseFinish = true; _currentDoseFlow = null; } private async Task SetObstructFlag(string name, bool value) { try { if (this.StationProp.ObstructFlagList.TryGetValue(name, out var targetFlag)) { if (targetFlag != null) { lock (targetFlag) { targetFlag.flag = value; } } } } catch (Exception) { //throw; } } private async Task ReadObstructFlag(string name, bool value = true, bool bAny = false) { try { if (!bAny) { if (this.StationProp.ObstructFlagList.TryGetValue(name, out var targetFlag)) { if (targetFlag != null) { lock (targetFlag) { return targetFlag.flag == value; } } } } else if (bAny) { foreach (var pair in this.StationProp.ObstructFlagList) { if (pair.Key.Contains(name)) { lock (pair.Value) { if (pair.Value.flag == value) { return true; } } } } } } catch (Exception) { return false; } return false; } #region 和Web 通讯 public async Task<(bool, string)> SendJson_old(string guid, string methodName, string outJson, LogLevel logLevel = LogLevel.Info) { var webApiUrl = await this.dataAccessService.LoadEntityAsync(x => x.MethodName == methodName); var url = webApiUrl?.URL; if (string.IsNullOrEmpty(url)) { return (false, ""); } if (!webApiUrl.IsEnable) { return (false, ""); } try { DateTime startTime = DateTime.Now; // *** 关键修改:将 JSON 字符串解析并重新序列化为标准格式 *** string finalJsonToSend; // 尝试将传入的 outJson (一个JSON字符串) 解析为 JsonDocument using (JsonDocument parsedDoc = JsonDocument.Parse(outJson)) { // 将解析后的文档重新序列化为标准、格式良好的 JSON 字符串 // 这一步确保了发送的是标准的 JSON 对象格式,而不是一个被当作字符串的JSON finalJsonToSend = JsonSerializer.Serialize(parsedDoc.RootElement, new JsonSerializerOptions { WriteIndented = false }); } HttpContent httpContent = new StringContent(finalJsonToSend, Encoding.UTF8, "application/json"); var client = this._httpClientFactory.CreateClient(guid); HttpResponseMessage response = null; if (webApiUrl.RequestType == HttpRequestTypeEnum.Post) response = await client.PostAsync(url, httpContent); else response = await client.GetAsync(url); var content = await response.Content.ReadAsStringAsync(); DateTime endTime = DateTime.Now; if (!methodName.Equals("error")) //报警信息回调不写入 { Logger.LogInformation($"{url}发送{finalJsonToSend}返回{content}"); } return (true, content); } catch (Exception ex) { this.Logger.LogError(logEvent: LogEvent.Error, message: $"编号:{guid} 方法:{methodName} 站: 发送失败,{ex.Message}", exception: ex); return (false, ""); } } public async Task<(bool, string)> SendJson(string guid, string methodName, string outJson, LogLevel logLevel = LogLevel.Info) { var webApiUrl = await this.dataAccessService.LoadEntityAsync(x => x.MethodName == methodName); var url = webApiUrl?.URL; if (string.IsNullOrEmpty(url)) { return (false, ""); } if (!webApiUrl.IsEnable) { return (false, ""); } try { DateTime starTime = DateTime.Now; HttpContent httpContent = new StringContent(outJson,Encoding.UTF8, "application/json"); var client = this._httpClientFactory.CreateClient(guid); HttpResponseMessage response = null; if (webApiUrl.RequestType == HttpRequestTypeEnum.Post) response = await client.PostAsync(url, httpContent); else response = await client.GetAsync(url); var content = await response.Content.ReadAsStringAsync(); DateTime endTime = DateTime.Now; if (!methodName.Equals("error")) //报警信息回调不写入 { Logger.LogInformation($"{url}发送{outJson}返回{content}"); } return (true, content); } catch (Exception ex) { this.Logger.LogError(logEvent: LogEvent.Error, message: $"编号:{guid} 方法:{methodName} 站: 发送失败,{ex.Message}", exception: ex); return (false, ""); } } #endregion } }