using Common.Models; using CommunityToolkit.Mvvm.Messaging; using MegaRobo.C00225155.Entities; using MegaRobo.C00225155.Entities.Entity_DB; using MegaRobo.Contract; using MegaRobo.ControlDevices; using MegaRobo.Entities; using MegaRobo.Logger; using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.Hamilton5mlDevices; using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Management; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Xml.Linq; namespace MegaRobo.C00225155.AppServer.ExecuteWorks { /// /// 这里主要是针对配置站服务,控制1ml移液枪的逻辑 /// public partial class StationService_MaterialDosing: StationServiceBase { /// /// 1ml枪头 Z轴初始化 /// /// private async Task GunZAxisInit_M1(DeviceNames pipetteDevice, PipetteService pipetteService) { this.Logger.LogInformation($"{pipetteDevice}Z轴初始化"); IDictionary dictResult = new Dictionary(); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } pipetteService.Disconnect(); await pipetteService.ConnectionAsync(); dictResult = await pipetteService.InitZaxis(IdList.ToArray()); if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); this.Logger.LogError($"{pipetteDevice}Z轴初始化失败,{PipetteErrorDic[errorkey]}"); } } /// /// 1ml枪头 总初始化 /// /// private async Task GunAllInit_M1(DeviceNames pipetteDevice, PipetteService pipetteService) { this.Logger.LogInformation($"{pipetteDevice}总初始化"); IDictionary dictResult = new Dictionary(); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } dictResult = await pipetteService.InitZaxis(IdList.ToArray()); if (dictResult != null) { dictResult = await pipetteService.InitPump(); } if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); this.Logger.LogError($"{pipetteDevice}总初始化失败,{PipetteErrorDic[errorkey]}"); } } /// /// 1ml枪头 取TIP头 /// /// private async Task GunPickUpTip_M1(DeviceNames pipetteDevice, PipetteService pipetteService, TipTypeEnum tipVolume) { if (TestMode) return true; ushort tipType = 7; uint go = 0; if (tipVolume.Equals(TipTypeEnum._300UL))//300ul slim的有滤芯的、导电的枪头 { tipType = 9; go = 0; } else if (tipVolume.Equals(TipTypeEnum._50UL)) //50ul的有滤芯的、导电的枪头 { tipType = 3; } else if (tipVolume.Equals(TipTypeEnum._1000UL)) { tipType = 7;//1000ul的有滤芯的、导电的枪头 } this.Logger.LogInformation($"{pipetteDevice}取Tip-tipType(9:300,3:50,7:1000):{tipType}"); IDictionary dictResult = new Dictionary(); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } dictResult = await pipetteService.TipInstall(tipType: tipType, go, IdList.ToArray()); await pipetteService.InitZaxis(); //Z轴带动泵模块向上运动到最高处 if (dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00") || dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "76")) { this.Logger.LogInformation($"{pipetteDevice}取Tip成功"); return true; } else if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); //WeakReferenceMessenger.Default.Send(new ConfirmMessage() //{ // Header = $"{pipetteDevice}取Tip失败", // Content = $"{PipetteErrorDic[errorkey]}", // OkButtonContent = "继续", // CancelButtonContent = "取消", //}); WeakReferenceMessenger.Default.Send(new DesktopAlertMessage() { Header = $"{pipetteDevice}取Tip失败" , Content = $"{PipetteErrorDic[errorkey]}" }); this.Logger.LogError($"{pipetteDevice}取Tip失败,{PipetteErrorDic[errorkey]}"); await GunAllInit_M1(pipetteDevice, pipetteService); return false; } return false; } //public async Task ZMove(uint pos) //{ // IEnumerable pipetteIdList = new List { 1 }; // pipetteIdList = pipetteService_1ml.PipetteList.Select(x => x.Id); // foreach (var id in pipetteIdList) // { // var dictRes = await pipetteService_1ml.MoveZaxis(0, id); // } //} /// /// 1ml枪头 丢弃Tip头 /// /// private async Task GunDiscardTip_M1(DeviceNames pipetteDevice, PipetteService pipetteService) { if (TestMode) return; this.Logger.LogInformation($"{pipetteDevice}丢Tip"); IDictionary dictResult = new Dictionary(); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } //var dictResult = await pipetteService_1ml.TipUninstall(1); //await pipetteService_1ml.InitZaxis(); //if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) //{ // this.Logger.LogError($"{DeviceNames.Pipette_Config_1ml}丢Tip失败,{dictResult.LastOrDefault().Value}"); //} dictResult = await pipetteService.InitPump(IdList.ToArray()); await pipetteService.InitZaxis(); if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); WeakReferenceMessenger.Default.Send(new ConfirmMessage() { Header = $"{pipetteDevice}丢Tip失败", Content = $"{PipetteErrorDic[errorkey]}", OkButtonContent = "继续", CancelButtonContent = "取消", }); this.Logger.LogError($"{pipetteDevice}丢Tip失败,{PipetteErrorDic[errorkey]}"); await GunAllInit_M1(pipetteDevice, pipetteService); } } private async Task GunAbsorb_M1(DeviceNames pipetteDevice, PipetteService pipetteService, string liquidName, int tiporder, double absorbVolumn, SourceLiquidBottleModel sourceLiquidBottleModel) { if (TestMode) return; IDictionary dictResult = new Dictionary(); var curLiqud = await this.dataAccessService.LoadEntitiesAsync(x => x.LiquidName == liquidName && x.TipType == tiporder); //&& x.TipType == tiporder 暂时屏蔽 if (curLiqud == null || curLiqud.Count == 0) { curLiqud = await this.dataAccessService.LoadEntitiesAsync(x => x.TipType == tiporder); } var curLiqud_M1 = curLiqud.FirstOrDefault(); curLiqud_M1.TipType = tiporder; curLiqud_M1.LiquidVolume = (int)Math.Abs(absorbVolumn * curLiqud_M1.Ratio); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } this.Logger.LogInformation($"{pipetteDevice}开始吸液,吸液量{curLiqud_M1.LiquidVolume}ul"); dictResult = await OnSuckFluid(pipetteService, IdList, curLiqud_M1, 1, 1, sourceLiquidBottleModel); //for (int i = 1; i < 3; i++) //若吸液失败,二次吸液 { if (dictResult != null) { if (dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { this.Logger.LogInformation($"{pipetteDevice}吸液成功"); await pipetteService.InitZaxis(); } else { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); this.Logger.LogError($"{pipetteDevice}吸液失败,{PipetteErrorDic[errorkey]}"); WeakReferenceMessenger.Default.Send(new ConfirmMessage() { Header = $"{pipetteDevice}吸液失败", Content = $"{PipetteErrorDic[errorkey]}", OkButtonContent = "继续", CancelButtonContent = "取消", }); await pipetteService.InitZaxis(); } } else { await pipetteService.InitZaxis(); } } } /// /// 1ml枪头 分液 /// /// 液体名称 /// 分液体积 /// private async Task GunDispensing_M1(DeviceNames pipetteDevice, PipetteService pipetteService, string liquidName, int tipOrder,uint vol, SampleBottleModel sampleBottleModel) { if (TestMode) return; IDictionary dictResult = new Dictionary(); //IList listId = new List(); Liquid_lml_Dose curLiqud_M1 = new Liquid_lml_Dose(); IList IdList = new List(); switch (pipetteDevice) { case DeviceNames.Pipette_Dose_1ml_1: IdList = new List { 1 }; break; case DeviceNames.Pipette_Dose_1ml_2: IdList = new List { 2 }; break; case DeviceNames.Pipette_Dose_1ml_3: IdList = new List { 3 }; break; case DeviceNames.Pipette_Dose_1ml_4: IdList = new List { 4 }; break; default: break; } this.Logger.LogInformation($"{pipetteDevice}开始分液"); var curLiqud = await this.dataAccessService.LoadEntitiesAsync(x => x.LiquidName == liquidName && x.TipType == tipOrder); // if (curLiqud == null || curLiqud.Count == 0) { curLiqud = await this.dataAccessService.LoadEntitiesAsync(x => x.TipType == tipOrder); } curLiqud_M1 = curLiqud.FirstOrDefault(); if (sampleBottleModel.SampleBottleType == SampleBottleTypeEnum._12mL) { curLiqud_M1.DispenHeight -= 300; //12ml样品瓶比5ml高约3cm } dictResult = await OnDispenFluid(pipetteService, IdList, curLiqud_M1, vol);//(uint)Math.Abs(volumn) if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00")) { string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value); this.Logger.LogError($"{pipetteDevice}分液失败,{PipetteErrorDic[errorkey]}"); WeakReferenceMessenger.Default.Send(new ConfirmMessage() { Header = $"{pipetteDevice}分液失败", Content = $"{PipetteErrorDic[errorkey]}", OkButtonContent = "继续", CancelButtonContent = "取消", }); await pipetteService.InitZaxis(); } else { this.Logger.LogInformation($"{pipetteDevice}分液成功"); await pipetteService.InitZaxis(); } } private async Task> OnSuckFluid(PipetteService pipetteService, IList listId, Liquid_lml_Dose liquidProduct, int subid, int asperIndex = 1, SourceLiquidBottleModel sourceLiquidBottleModel = null) { IDictionary resultData; try { if (liquidProduct == null) return null; uint platformCode = (uint)liquidProduct.PlatformCode;//平台平台编号 uint liquidReagentCode = (uint)liquidProduct.LiquidParamId; //移液枪液体编号 uint vol = (uint)liquidProduct.LiquidVolume;//吸液体积 uint ge = (uint)liquidProduct.ContainerPlateIndex;//容器编号 uint lld = (uint)liquidProduct.LiqLedetec;//是否液面探测 uint pos = (uint)liquidProduct.AspireHeight; //液面探测其实高度 或者固定吸液高度 if (lld == 0) //qrbian todo:需要区分1000μl,300μl,50μl,计算余量对应的吸液高度 根据sourceLiquidBottleModel sourceLiquidBottleModel.RemainVolume { //底部高度(三种tip不一样) = 底部高度 - 液体剩余高度 + 浸入高度(三种tip不一样) //int heightMax = liquidProduct.TipType == 3 ? 1000 : (liquidProduct.TipType == 2 ? 300 : 50); //tip到底部高度最大值 int heightMax = 2220; //int inHeight = liquidProduct.TipType == 3 ? 1000 : (liquidProduct.TipType == 2 ? 300 : 50); //浸入高度 int inHeight = 50; //浸入高度 if (sourceLiquidBottleModel.RemainVolume > 40) { sourceLiquidBottleModel.RemainVolume = 40; } int liquidRemainHeight = (int)(100 * sourceLiquidBottleModel.RemainVolume / (Math.PI * 1.25 * 1.25)); int realHeight = heightMax - liquidRemainHeight + inHeight; //底部高度向上抬升液体高度再浸入液面高度 realHeight = realHeight > heightMax ? heightMax : realHeight; //确保不能超过底部高度 //pos = 1700; //todo:将上面的heightMax、inHeight修改,这个替换成realHeight pos = (uint)realHeight; } IList<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)> idArrayParams = new List<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)>(); foreach (var id in listId) { idArrayParams.Add((id, vol, liquidReagentCode, pos, ge, platformCode, lld)); } resultData = await pipetteService.SuckFluid(idArrayParams); } catch (Exception ex) { this.Logger.LogError($"{DeviceNames.Pipette_Dose_1ml_1}吸液异常:{ex}"); throw; } return resultData; } private async Task> OnDispenFluid1(PipetteService pipetteService, IList listId, Liquid_lml_Dose liquidProduct, uint dispos) { IDictionary resultData = new Dictionary(); try { if (liquidProduct == null) return null; uint platformCode = (uint)liquidProduct.PlatformCode;//平台平台编号 uint liquidReagentCode = (uint)liquidProduct.LiquidParamId; //移液枪液体编号 uint vol = (uint)liquidProduct.LiquidVolume;//吸液体积 uint ge = (uint)liquidProduct.ContainerPlateIndex;//容器编号 uint lld = (uint)liquidProduct.LiqLedetec;//是否液面探测 uint pos = dispos;//吸液高度 IList<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)> idArrayParams = new List<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)>(); foreach (var id in listId) { idArrayParams.Add((id, vol, liquidReagentCode, pos, ge, platformCode, 0)); } resultData = await pipetteService.DrainageFluid(idArrayParams); } catch (Exception ex) { this.Logger.LogError($"{DeviceNames.Pipette_Dose_1ml_1}分液异常,异常原因:{ex}"); } return resultData; } private async Task> OnDispenFluid(PipetteService pipetteService, IList listId, Liquid_lml_Dose liquidProduct, uint volume) { IDictionary resultData = new Dictionary(); try { if (liquidProduct == null) return null; uint platformCode = (uint)liquidProduct.PlatformCode;//平台平台编号 uint liquidReagentCode = (uint)liquidProduct.LiquidParamId;//移液枪液体编号 uint ge = (uint)liquidProduct.ContainerPlateIndex;//容器编号 uint lld = (uint)liquidProduct.LiqLedetec;//是否液面探测 uint pos = (uint)liquidProduct.DispenHeight;//分液高度 uint vol = volume; IList<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)> idArrayParams = new List<(uint id, uint vol, uint lq, uint pos, uint ge, uint go, uint lb)>(); foreach (var id in listId) { idArrayParams.Add((id, vol, liquidReagentCode, pos, ge, platformCode, 0)); } resultData = await pipetteService.DrainageFluid(idArrayParams); } catch (Exception ex) { this.Logger.LogError($"{DeviceNames.Pipette_Dose_1ml_1}分液异常,异常原因:{ex.ToString()}"); } return resultData; } } }