C00225155-02/C00225155/MegaRobo.C00225155/MegaRobo.C00225155.AppServer/ExecuteWorks/StationService_MaterialDosi...

1482 lines
72 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Common;
using Common.Models;
using CommunityToolkit.Mvvm.Messaging;
using MegaRobo.C00225155.ControlDevices;
using MegaRobo.C00225155.ControlDevices.WeightDevice;
using MegaRobo.C00225155.Entities;
using MegaRobo.C00225155.Entities.Entity_DB;
using MegaRobo.Contract;
using MegaRobo.Contract.Abstractions;
using MegaRobo.ControlDevices;
using MegaRobo.Entities;
using MegaRobo.Logger;
using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices;
using Microsoft.VisualBasic;
using NetTaste;
using Newtonsoft.Json.Linq;
using Nito.AsyncEx;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Xml.Serialization;
namespace MegaRobo.C00225155.AppServer.ExecuteWorks
{
/// <summary>
/// 这里主要写配置工站上位机和PLC通讯的函数
/// </summary>
public partial class StationService_MaterialDosing : StationServiceBase
{
// /// <summary>
// /// 下工装---等待信号的锁
// /// </summary>
// private static readonly AsyncLock _lockWaitSignal_Dnload = new AsyncLock();
// /// <summary>
// /// 上工装---等待信号的锁
// /// </summary>
// private static readonly AsyncLock _lockWaitSignal_Upload = new AsyncLock();
// /// <summary>
// /// 四轴机械手---等待信号的锁
// /// </summary>
// private static readonly AsyncLock _lockWaitSignal_FourAxis = new AsyncLock();
// /// <summary>
// /// 粉末原液瓶---等待信号的锁
// /// </summary>
// private static readonly AsyncLock _lockWaitSignal_Powder = new AsyncLock();
// /// <summary>
// /// 六轴机械手下反应瓶工装线程的信号锁,防止多线程同时操作
// /// </summary>
// private static readonly AsyncLock _lockBoxDn_SixAxis = new AsyncLock();
// /// <summary>
// /// 六轴机械手上反应瓶缓存工装线程的信号锁,防止多线程同时操作
// /// </summary>
// private static readonly AsyncLock _lockBoxUp_SixAxis = new AsyncLock();
// /// <summary>
// /// 冷却平台 是否有瓶子 更新属性的锁
// /// </summary>
// private static readonly SemaphoreSlim _lockColdStateTrace = new SemaphoreSlim(1, 1);
// /// <summary>
// /// 磁力搅拌 是否有瓶子 更新属性的锁
// /// </summary>
// private static readonly SemaphoreSlim _lockMagneticStirStateTrace = new SemaphoreSlim(1, 1);
#region PLC点位写/
/// <summary>
/// 下料
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public async Task<ushort> ReadScannedValueAsync_Dnload(ushort address)
{
await Task.Delay(0);
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
return this.ModbusClient.Command.ReadValue<ushort>(address);
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站读取PLC信号异常",
Content = $"ReadScannedValueAsync_Dnload读取 {address} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"ReadScannedValueAsync_Dnload读取 {address} 时发生错误: {ex.Message}");
}
return 0;
}
/// <summary>
/// 上料
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public async Task<ushort> ReadScannedValueAsync_Upload(ushort address)
{
await Task.Delay(0);
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
return this.ModbusClient.Command.ReadValue<ushort>(address);
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站读取PLC信号异常",
Content = $"ReadScannedValueAsync_Upload读取 {address} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"ReadScannedValueAsync_Upload读取 {address} 时发生错误: {ex.Message}");
}
return 0;
}
public async Task<ushort> ReadScannedValueAsync_FourAxis(ushort address)
{
await Task.Delay(0);
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
return this.ModbusClient.Command.ReadValue<ushort>(address);
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站读取PLC信号异常",
Content = $"ReadSixAxis读取 {address} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"ReadScannedValueAsync_SixAxis读取 {address} 时发生错误: {ex.Message}");
}
return 0;
}
public async Task<ushort> ReadScannedValueAsync_XZ(ushort address)
{
await Task.Delay(0);
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
return this.ModbusClient.Command.ReadValue<ushort>(address);
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站读取PLC信号异常",
Content = $"ReadPowder读取 {address} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"ReadScannedValueAsync_Powder读取 {address} 时发生错误: {ex.Message}");
}
return 0;
}
public async Task WriteCommandAsync_Dnload(ushort address, ushort value)
{
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
//await Task.Delay(30);
while (await ReadScannedValueAsync_Dnload(address) != value)
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
await Task.Delay(30);
}
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站写入PLC信号异常",
Content = $"WriteDnload写入 {address}值{value} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WriteCommandAsync_Dnload写入 {address}值{value} 时发生错误: {ex.Message}");
return;
}
}
public async Task WriteCommandAsync_Upload(ushort address, ushort value)
{
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
//await Task.Delay(30);
while (await ReadScannedValueAsync_Upload(address) != value)
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
await Task.Delay(30);
}
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站写入PLC信号异常",
Content = $"WriteUpload写入 {address}值{value} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WriteCommandAsync_Upload写入 {address}值{value} 时发生错误: {ex.Message}");
return;
}
}
public async Task WriteCommandAsync_FourAxis(ushort address, ushort value)
{
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
//await Task.Delay(30);
while (await ReadScannedValueAsync_FourAxis(address) != value)
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
await Task.Delay(30);
}
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站写入PLC信号异常",
Content = $"WriteFourAxis写入 {address}值{value} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WriteCommandAsync_FourAxis写入 {address}值{value} 时发生错误: {ex.Message}");
return;
}
}
public async Task WriteCommandAsync_XZ(ushort address, ushort value)
{
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
try
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
//await Task.Delay(30);
while (await ReadScannedValueAsync_XZ(address) != value)
{
this.ModbusClient.Command.WriteValue<ushort>(address, value);
await Task.Delay(30);
}
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站写入PLC信号异常",
Content = $"WritePowder写入 {address}值{value} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WriteCommandAsync_Powder写入 {address}值{value} 时发生错误: {ex.Message}");
return;
}
}
public async Task WaitForActionFinishAsync_Dnload(ushort point, ushort waitValue, CancellationToken token)
{
//using (await _lockWaitSignal_Dnload.LockAsync(token))
{
try
{
ushort result = 0;
do
{
token.ThrowIfCancellationRequested();
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
result = await ReadScannedValueAsync_Dnload(point);
await Task.Delay(100, token);
} while (result != waitValue && !token.IsCancellationRequested);
}
catch (OperationCanceledException)
{
return;
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站等待PLC信号异常",
Content = $"WaitForDnload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WaitForActionFinishAsync_Dnload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
return;
}
}
}
public async Task WaitForActionFinishAsync_Upload(ushort point, ushort waitValue, CancellationToken token)
{
//using (await _lockWaitSignal_Upload.LockAsync(token))
{
try
{
ushort result = 0;
do
{
token.ThrowIfCancellationRequested();
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
result = await ReadScannedValueAsync_Upload(point);
await Task.Delay(100, token);
} while (result != waitValue && !token.IsCancellationRequested);
}
catch (OperationCanceledException)
{
return;
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站等待PLC信号异常",
Content = $"WaitForUpload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WaitForActionFinishAsync_Upload等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
return;
}
}
}
public async Task WaitForActionFinishAsync_FourAxis(ushort point, ushort waitValue, CancellationToken cancellationToken)
{
//using (await _lockWaitSignal_FourAxis.LockAsync(cancellationToken))
{
try
{
ushort result = 0;
do
{
cancellationToken.ThrowIfCancellationRequested();
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
result = await ReadScannedValueAsync_FourAxis(point);
await Task.Delay(100, cancellationToken);
} while (result != waitValue && !cancellationToken.IsCancellationRequested);
}
catch (OperationCanceledException)
{
return;
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站等待PLC信号异常",
Content = $"WaitForFourAxis等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WaitForActionFinishAsync_FourAxis等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
return;
}
}
}
public async Task WaitForActionFinishAsync_XZ(ushort point, ushort waitValue, CancellationToken cancellationToken)
{
//using (await _lockWaitSignal_Powder.LockAsync(cancellationToken))
{
try
{
ushort result = 0;
do
{
cancellationToken.ThrowIfCancellationRequested();
this.StationProp.ManualResetEvent.WaitOne(); // 暂停标志
result = await ReadScannedValueAsync_XZ(point);
await Task.Delay(100, cancellationToken);
} while (result != waitValue && !cancellationToken.IsCancellationRequested);
}
catch (OperationCanceledException)
{
return;
}
catch (Exception ex)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"投料站等待PLC信号异常",
Content = $"WaitForPowder等待 {point}是否为{waitValue} 时发生错误: {ex.Message}",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
this.Logger.LogError($"WaitForActionFinishAsync_Powder等待 {point}是否为{waitValue} 时发生错误: {ex.Message}");
return;
}
}
}
#endregion
#region
/// <summary>
/// 传送平台到过渡舱外准备上载具
/// </summary>
/// <param name="reactBottleModel"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task TransferUploadBox(CancellationToken token)
{
if (token.IsCancellationRequested) return;
//传送平台到过渡舱外
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 1);
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token);
//清除信号
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0);
//await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 0, token);
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); //等待PLC 准备就绪 等待空闲中
}
/// <summary>
/// 传送平台到手套箱内部
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
private async Task TransferToDeviceInner(CancellationToken token)
{
if (token.IsCancellationRequested) return;
//传送平台到手套箱内部
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 3);
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 22, token);
//清除信号
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_TransferPlate_TaskNo, 0);
await WaitForActionFinishAsync_Upload(PlcPoints_MaterialDose.R_TransferPlate_RunResult, 5, token); //等待PLC 准备就绪 等待空闲中
}
#endregion
#region
/// <summary>
/// 四轴机械手取托盘
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="boxType">托盘类型</param>
/// <param name="pos">目标托盘位置号</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisTakeBox(ushort aimarea, BoxTypeEnum boxType, ushort pos, CancellationToken token)
{
///// 目标区域
///// 1手套箱传送平台 2Tip托盘存放平台12托盘存放平台
///// </summary>
//public readonly static ushort W_Robot_AimArea = 2202;
///// <summary>
///// 目标托盘位置号
///// </summary>
//public readonly static ushort W_Robot_AimAreaBoxPosid = 2203;
///// <summary>
///// 托盘类型1:40mL瓶; 2:12mL瓶; 3:5mL瓶; 4:TIP头;
///// </summary>
//public readonly static ushort W_Robot_BoxType = 2204;
if (token.IsCancellationRequested || TestMode) return;
ushort fixtureType = 0;
switch (boxType)
{
case BoxTypeEnum._40mL原液工装:
fixtureType = 1;
break;
case BoxTypeEnum._12mL样品工装:
fixtureType = 2;
break;
case BoxTypeEnum._5mL样品工装:
fixtureType = 3;
break;
case BoxTypeEnum._50uLTip头工装:
fixtureType = 4;
break;
case BoxTypeEnum._300uLTip头工装:
fixtureType = 4;
break;
case BoxTypeEnum._1000uLTip头工装:
fixtureType = 4;
break;
}
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, pos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, fixtureType);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 11);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手放托盘
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="boxType">托盘类型</param>
/// <param name="pos">目标托盘位置号</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisPutBox(ushort aimarea, BoxTypeEnum boxType, ushort pos, CancellationToken token)
{
///// 目标区域
///// 1手套箱传送平台 2Tip托盘存放平台12托盘存放平台
///// </summary>
//public readonly static ushort W_Robot_AimArea = 2202;
///// <summary>
///// 目标托盘位置号
///// </summary>
//public readonly static ushort W_Robot_AimAreaBoxPosid = 2203;
///// <summary>
///// 托盘类型1:40mL瓶; 2:12mL瓶; 3:5mL瓶; 4:TIP头;
///// </summary>
//public readonly static ushort W_Robot_BoxType = 2204;
if (token.IsCancellationRequested || TestMode) return;
ushort fixtureType = 0;
switch (boxType)
{
case BoxTypeEnum._40mL原液工装:
fixtureType = 1;
break;
case BoxTypeEnum._12mL样品工装:
fixtureType = 2;
break;
case BoxTypeEnum._5mL样品工装:
fixtureType = 3;
break;
case BoxTypeEnum._50uLTip头工装:
fixtureType = 4;
break;
case BoxTypeEnum._300uLTip头工装:
fixtureType = 4;
break;
case BoxTypeEnum._1000uLTip头工装:
fixtureType = 4;
break;
}
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, pos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, fixtureType);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 12);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手取粉末加样头
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="aimarea_box">目标托盘号</param>
/// <param name="bottlepos">目标位置号</param>
/// <param name="powderbottletype">粉末类型</param>
/// <param name="token"></param>
/// <param name="point">plc点位起始或终点是传递仓到缓存位的话开始取最终放需要写1</param>
/// <returns></returns>
private async Task FourAxisTakePowderHeader(int aimarea, int aimarea_box, int bottlepos, PowderBottleTypeEnum powderbottletype, CancellationToken token, ushort point = 0)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, powderbottletype == PowderBottleTypeEnum._16mL ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, point);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 1);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手放粉末加样头
/// </summary>
/// <param name="aimarea"></param>
/// <param name="aimarea_box"></param>
/// <param name="bottlepos"></param>
/// <param name="powderbottletype"></param>
/// <param name="token"></param>
/// <param name="point">plc点位起始或终点是传递仓到缓存位的话开始取最终放需要写1</param>
/// <returns></returns>
private async Task FourAxisPutPowderHeader(int aimarea, int aimarea_box, int bottlepos, PowderBottleTypeEnum powderbottletype, CancellationToken token, ushort point = 0)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, powderbottletype == PowderBottleTypeEnum._16mL ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, point);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 2);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴运行到扫码位置
/// </summary>
/// <param name="liquidBottle">bottle : 1:40 2:12 3:5</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisGoToScannPos_liquid(CancellationToken token, int liquidBottle, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)liquidBottle);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 23); //goto scan pos
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveScanPos, 1, token);
string sn = await scannerService.ReadAsnyc(TimeSpan.FromSeconds(5));
if (sourceLiquidBottle != null)
{
sourceLiquidBottle.SNCode = sn;
}
if (sampleBottle != null)
{
sampleBottle.SNCode = sn;
}
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_ScanResult, 1);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveScanPos, 0, token);
//清除信号
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_ScanResult, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴运行到粉末瓶扫码位置
/// </summary>
/// <param name="ispowder">是否是粉末瓶子</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisGoToScannPos_powder(CancellationToken token, SourcePowderBottleModel powderbottle)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 3);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveSideScanPos, 1, token);
//触发扫码
string snCode = await scannerService_Powder.ReadAsnyc(TimeSpan.FromSeconds(5));
powderbottle.SNCode = snCode;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_SideScanResult, 1); //回复扫码完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArriveSideScanPos, 0, token);
//清除信号
await WriteCommandAsync_Upload(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_SideScanResult, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
private async Task<double> FourAxisPutPowderHeaderToPreWeight(CancellationToken token)
{
if (token.IsCancellationRequested || TestMode) return 16;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 4);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 2);
//等待PLC回复到预称重位
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_ArrivePreWeightPos, 1, token);
//这边需要称重并返回PLC完成
double powderWeight = TestMode ? 16 : (await preWeight.ReadWeightValue());
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_PreWeightFinish, 1);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
return powderWeight;
}
/// <summary>
/// 四轴机械手拿液体瓶子
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="aimarea_box">目标托盘位置号</param>
/// <param name="bottlepos">目标孔编号</param>
/// <param name="powderbottletype">瓶类型</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisTakeLiquidBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SourceLiquidBottleModel sourceLiquidBottle)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 1);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sourceLiquidBottle.LiquidBottleLidState == SourceBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 21);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手放液体瓶子
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="aimarea_box">目标托盘位置号</param>
/// <param name="bottlepos">目标孔编号</param>
/// <param name="powderbottletype">瓶类型</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisPutLiquidBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SourceLiquidBottleModel sourceLiquidBottle)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 1);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sourceLiquidBottle.LiquidBottleLidState == SourceBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 22);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手取样品瓶子
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="aimarea_box">目标托盘位置号</param>
/// <param name="bottlepos">目标孔编号</param>
/// <param name="powderbottletype">瓶类型</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisTakeSampleBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SampleBottleModel sampleBottle)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL ? (ushort)3 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sampleBottle.SampleBottleLidState == SampleBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 21);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
/// <summary>
/// 四轴机械手放样品瓶子
/// </summary>
/// <param name="aimarea">目标区域编号</param>
/// <param name="aimarea_box">目标托盘位置号</param>
/// <param name="bottlepos">目标孔编号</param>
/// <param name="powderbottletype">瓶类型</param>
/// <param name="token"></param>
/// <returns></returns>
private async Task FourAxisPutSampleBottle(CancellationToken token, int aimarea, int aimarea_box, int bottlepos, SampleBottleModel sampleBottle)
{
if (token.IsCancellationRequested || TestMode) return;
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, (ushort)aimarea);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, (ushort)aimarea_box);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, (ushort)bottlepos);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, sampleBottle.SampleBottleType == SampleBottleTypeEnum._5mL ? (ushort)3 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, sampleBottle.SampleBottleLidState == SampleBottleLidStateEnum.Close ? (ushort)1 : (ushort)2);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 22);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 22, token);
//信号清零
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param1, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param2, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param3, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param4, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_Param5, 0);
await WriteCommandAsync_FourAxis(PlcPoints_MaterialDose.W_Robot_TaskNo, 0);
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_Robot_RunResult, 5, token);
}
#endregion
#region XZ模组
/// <summary>
/// 假盖子开关盖
/// </summary>
/// <param name="token"></param>
/// <param name="isOpen"></param>
/// <param name="sourceLiquidBottle"></param>
/// <param name="sampleBottle"></param>
/// <returns></returns>
private async Task OpenCloseBottleFakeCap(CancellationToken token,bool isOpen, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
{
if (token.IsCancellationRequested || TestMode) return;
int bottletype = 0;
if (sourceLiquidBottle != null)
{
bottletype = 1;
}
if (sampleBottle != null)
{
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
{
bottletype = 2;
}
else
{
bottletype = 3;
}
}
ushort taskNo = isOpen ? (ushort)1 : (ushort)2;
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)2);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, taskNo);
//等待PLC回复执行完成
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
if (sourceLiquidBottle != null)
{
sourceLiquidBottle.LiquidBottleLidState = isOpen ? SourceBottleLidStateEnum.Open : SourceBottleLidStateEnum.Close;
}
if (sampleBottle != null)
{
sampleBottle.SampleBottleLidState = isOpen ? SampleBottleLidStateEnum.Open : SampleBottleLidStateEnum.Close;
}
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// XZ模组开盖
/// </summary>
/// <param name="token"></param>
/// <param name="sourceLiquidBottle"></param>
/// <param name="sampleBottle"></param>
/// <returns></returns>
private async Task OpenBottleLid(CancellationToken token, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
{
if (token.IsCancellationRequested || TestMode) return;
int bottletype = 0;
if (sourceLiquidBottle != null)
{
bottletype = 1;
}
if (sampleBottle != null)
{
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
{
bottletype = 2;
}
else
{
bottletype = 3;
}
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)1);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 1);
//等待PLC回复执行完成
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
if (sourceLiquidBottle != null)
{
sourceLiquidBottle.LiquidBottleLidState = SourceBottleLidStateEnum.Open;
}
if (sampleBottle != null)
{
sampleBottle.SampleBottleLidState = SampleBottleLidStateEnum.Open;
}
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// XZ模组关盖
/// </summary>
/// <param name="token"></param>
/// <param name="sourceLiquidBottle"></param>
/// <param name="sampleBottle"></param>
/// <returns></returns>
private async Task CloseBottleLid(CancellationToken token, SourceLiquidBottleModel sourceLiquidBottle = null, SampleBottleModel sampleBottle = null)
{
if (token.IsCancellationRequested || TestMode) return;
int bottletype = 0;
if (sourceLiquidBottle != null)
{
bottletype = 1;
}
if (sampleBottle != null)
{
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
{
bottletype = 2;
}
else
{
bottletype = 3;
}
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)1);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 2);
//等待PLC回复执行完成
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
if (sourceLiquidBottle != null)
{
sourceLiquidBottle.LiquidBottleLidState = SourceBottleLidStateEnum.Close;
}
if (sampleBottle != null)
{
sampleBottle.SampleBottleLidState = SampleBottleLidStateEnum.Close;
}
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// XZ摇匀
/// </summary>
/// <param name="token"></param>
/// <param name="sampleBottle"></param>
/// <returns></returns>
private async Task ShakeSampleBottle(CancellationToken token, SampleBottleModel sampleBottle)
{
if (token.IsCancellationRequested || TestMode) return;
int bottletype = 0;
if (sampleBottle != null)
{
if (sampleBottle.SampleBottleType == SampleBottleTypeEnum._12mL)
{
bottletype = 2;
}
else
{
bottletype = 3;
}
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, (ushort)bottletype);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)10);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 3);
//等待PLC回复执行完成
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
//public async Task TestSuckVolume(CancellationToken token, double targetVolume,bool isFirst)
//{
// SourceLiquidBottleModel sourceLiquidBottleModel = new SourceLiquidBottleModel()
// {
// LiquidBottleLidState = SourceBottleLidStateEnum.Close
// };
// if (isFirst)
// {
// await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, 1, 1, sourceLiquidBottleModel);
// await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceLiquidBottleModel);
// await OpenBottleLid(_cts.Token, sourceLiquidBottleModel, null);
// }
// else
// {
// await CloseBottleLid(_cts.Token, sourceLiquidBottleModel, null);
// await FourAxisTakeLiquidBottle(_cts.Token, (int)BoxAreaEnum._开关盖区域, 0, 0, sourceLiquidBottleModel);
// await FourAxisPutLiquidBottle(_cts.Token, (int)BoxAreaEnum._托盘存放平台, 1, 1, sourceLiquidBottleModel);
// }
// List<(int tipVolume, List<double> countlists)> selectedTips = new List<(int tipVolume, List<double> countlists)>();
// (int tipVolume, List<double> countlists) selectedTip = (50,new List<double>() { 30});
// selectedTips.Add(selectedTip);
// for (int i = 0; i < selectedTips.Count; i++)
// {
// TipTypeEnum tipType = TipTypeEnum._1000UL;
// DeviceNames deviceName = DeviceNames.Pipette_Dose_1ml_1;
// if (selectedTips[i].tipVolume == 1000)
// {
// tipType = TipTypeEnum._1000UL; deviceName = DeviceNames.Pipette_Dose_1ml_1;
// }
// else if (selectedTips[i].tipVolume == 300)
// {
// tipType = TipTypeEnum._300UL; deviceName = DeviceNames.Pipette_Dose_1ml_2;
// }
// else if (selectedTips[i].tipVolume == 50)
// {
// tipType = TipTypeEnum._50UL; deviceName = DeviceNames.Pipette_Dose_1ml_3;
// }
// this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Ongoing) { Tag = "使用中" });
// while (true)
// {
// List<TipBoxModel> targetTipBoxes = workService.ProjectPro.TipHeadArea.Where(tipBox => (tipBox.TipType == tipType) && tipBox.TipItems != null && tipBox.TipItems.Any(item => item.IsAvailable)).ToList();
// //告诉PLC到取Tip头位置
// if (targetTipBoxes == null)
// {
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
// {
// Header = $"取Tip失败",
// Content = $"没有tip了",
// OkButtonContent = "继续",
// CancelButtonContent = "取消",
// });
// continue;
// }
// if (isFirst)
// {
// await PipetteTakeTip(token, targetTipBoxes.FirstOrDefault(), deviceName);
// //取Tip
// var restip = await GunPickUpTip_M1(deviceName, pipetteService_1ml, tipType);
// if (restip)
// {
// break;
// }
// }
// else
// {
// await PipetteDiscardTip(token, deviceName);
// await GunDiscardTip_M1(deviceName, pipetteService_1ml);
// return;
// }
// }
// for (int j = 0; j < selectedTips[i].countlists.Count; j++)//用这种枪头要吸液排液多少次
// {
// //告诉PLC到吸液位置
// await PipetteAbsorb(token, deviceName);
// }
// //告诉PLC到丢弃Tip头位置
// //await PipetteDiscardTip(token, deviceName);
// //await GunDiscardTip_M1(deviceName, pipetteService_1ml);
// //this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Done));
// }
//}
private async Task XZ_TakeTip_Absorb_Dispense_DiscardTip(CancellationToken token, string sourceliquidname, double targetVolume, SourceLiquidBottleModel sourceLiquidBottleModel, SampleBottleModel sampleBottleModel)
{
if (TestMode) return;
List<(int tipVolume, List<double> countlists)> selectedTips = new List<(int tipVolume, List<double> countlists)>();
selectedTips = SelectTipsEx(targetVolume);
for (int i = 0; i < selectedTips.Count; i++)
{
TipTypeEnum tipType = TipTypeEnum._1000UL;
DeviceNames deviceName = DeviceNames.Pipette_Dose_1ml_1;
if (selectedTips[i].tipVolume == 1000)
{
tipType = TipTypeEnum._1000UL; deviceName = DeviceNames.Pipette_Dose_1ml_1;
}
else if (selectedTips[i].tipVolume == 300)
{
tipType = TipTypeEnum._300UL; deviceName = DeviceNames.Pipette_Dose_1ml_2;
}
else if (selectedTips[i].tipVolume == 50)
{
tipType = TipTypeEnum._50UL; deviceName = DeviceNames.Pipette_Dose_1ml_3;
}
this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Ongoing) { Tag = "使用中" });
while (true)
{
List<TipBoxModel> targetTipBoxes = workService.ProjectPro.TipHeadArea.Where(tipBox => (tipBox.TipType == tipType) && tipBox.TipItems != null && tipBox.TipItems.Any(item => item.IsAvailable)).ToList();
//告诉PLC到取Tip头位置
if (targetTipBoxes == null)
{
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
{
Header = $"取Tip失败",
Content = $"没有tip了",
OkButtonContent = "继续",
CancelButtonContent = "取消",
});
continue;
}
await PipetteTakeTip(token, targetTipBoxes.FirstOrDefault(), deviceName);
//取Tip
var restip = await GunPickUpTip_M1(deviceName, pipetteService_1ml, tipType);
if (restip)
{
break;
}
}
for (int j = 0; j < selectedTips[i].countlists.Count; j++)//用这种枪头要吸液排液多少次
{
//告诉PLC到吸液位置
await PipetteAbsorb(token, deviceName);
int bottletype = workService.ProjectPro.SampleBottleType == SampleBottleTypeEnum._12mL ? 1 : 2;
await GunAbsorb_M1(deviceName, pipetteService_1ml, sourceliquidname, (int)tipType, selectedTips[i].countlists[j] * 10,sourceLiquidBottleModel);
//告诉PLC到排液位置
await PipetteDispense(token, deviceName);
await GunDispensing_M1(deviceName, pipetteService_1ml, sourceliquidname, (int)tipType, (uint)(selectedTips[i].countlists[j] * 10), sampleBottleModel);
}
//告诉PLC到丢弃Tip头位置
await PipetteDiscardTip(token,deviceName);
await GunDiscardTip_M1(deviceName, pipetteService_1ml);
this.OnWorkStatusChanged(new ControlWorkStatus(deviceName.ToString(), ExecuteStatus.Done));
}
}
public async Task UpdateTipBox(TipBoxModel tipBoxModel)
{
var tipInStation = await dataAccessService.LoadEntityAsync<TipBoxModel>(t => t.BoxId_inDosingStation == tipBoxModel.BoxId_inDosingStation);
if (tipInStation == null)
{
var tipaddres = await dataAccessService.AddEntityAsync(tipBoxModel);
}
else
{
await dataAccessService.UpdateEntityAsync(tipBoxModel);
}
}
public List<(int tipVolume, List<double> absorbVolumnList)> SelectTipsEx(double targetVolumn)
{
List<(int tipVolume, List<double> absorbVolumnList)> selectedTips = new List<(int tipVolume, List<double> absorbVolumnList)>();
bool has50Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._50UL && t.TipItems.Any(ti => ti.IsAvailable));
bool has300Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._300UL && t.TipItems.Any(ti => ti.IsAvailable));
bool has1000Tip = workService.ProjectPro.TipHeadArea.Any(t => t.HaveBox && t.TipType == TipTypeEnum._1000UL && t.TipItems.Any(ti => ti.IsAvailable));
if (!has50Tip && !has300Tip && !has1000Tip) return selectedTips;
TipTypeEnum tipType = TipTypeEnum._1000UL;
if (targetVolumn <= 50)
{
tipType = has50Tip ? TipTypeEnum._50UL : (has300Tip ? TipTypeEnum._300UL : TipTypeEnum._1000UL); //优先50 30 1000
}
else if (targetVolumn <= 300)
{
tipType = has300Tip ? TipTypeEnum._300UL : (has1000Tip ? TipTypeEnum._1000UL : TipTypeEnum._50UL); //优先30 1000 50
}
else
{
tipType = has1000Tip ? TipTypeEnum._1000UL : (has300Tip ? TipTypeEnum._300UL : TipTypeEnum._50UL); //优先1000 50 30
}
(int tipVolume, List<double> absorbVolumnList) volumeInfo;
volumeInfo.tipVolume = tipType == TipTypeEnum._50UL ? 50 : (tipType == TipTypeEnum._300UL ? 300 : 1000);
volumeInfo.absorbVolumnList = new List<double>();
while (targetVolumn > 0)
{
if (targetVolumn > volumeInfo.tipVolume)
{
volumeInfo.absorbVolumnList.Add(volumeInfo.tipVolume);
targetVolumn -= volumeInfo.tipVolume;
}
else
{
volumeInfo.absorbVolumnList.Add(targetVolumn);
targetVolumn = 0;
}
}
selectedTips.Add(volumeInfo);
return selectedTips;
}
/// <summary>
/// 选择Tip头的函数
/// </summary>
/// <param name="targetVolumn"></param>
/// <returns></returns>
public List<(double tipVolume, List<double> absorbVolumnList)> SelectTips(double targetVolumn)
{
List<(double tipVolume, List<double> absorbVolumnList)> selectedTips = new List<(double tipVolume, List<double> absorbVolumnList)>();
// 1. 查找「存在且有可用Tip头」的工装判断是否有对应类型的Tip
TipBoxModel _1000ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
tipBox.TipType == TipTypeEnum._1000UL &&
tipBox.TipItems != null &&
tipBox.TipItems.Any(item => item.IsAvailable));
TipBoxModel _300ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
tipBox.TipType == TipTypeEnum._300UL &&
tipBox.TipItems != null &&
tipBox.TipItems.Any(item => item.IsAvailable));
TipBoxModel _50ulTip = workService.ProjectPro.TipHeadArea.FirstOrDefault(tipBox =>
tipBox.TipType == TipTypeEnum._50UL &&
tipBox.TipItems != null &&
tipBox.TipItems.Any(item => item.IsAvailable));
// 2. 整理「可用的Tip容量」按「从大到小」排序确保优先用大容量
var availableTipVolumes = new List<double>();
if (_1000ulTip != null) availableTipVolumes.Add(1000); // 有1000UL Tip则加入
if (_300ulTip != null) availableTipVolumes.Add(300); // 有300UL Tip则加入
if (_50ulTip != null) availableTipVolumes.Add(50); // 有10UL Tip则加入
// 无可用Tip时直接返回空列表可根据业务需求抛异常
if (!availableTipVolumes.Any())
{
//跟BS要Tip头
return selectedTips;
}
// 3. 初始化剩余体积保留3位小数避免精度问题
double remainingVolume = Math.Round(targetVolumn, 3, MidpointRounding.ToPositiveInfinity);
while (remainingVolume > 0)
{
double currentVolumn = 0;
double tipvolumn = 1000;
if (remainingVolume > 1000)
{
currentVolumn = 1000;
remainingVolume -= 1000;
tipvolumn = 1000;
}
else if (remainingVolume > 300)
{
tipvolumn = 1000;
currentVolumn = remainingVolume;
remainingVolume = 0;
}
else if (remainingVolume > 50)
{
tipvolumn = 300;
currentVolumn = remainingVolume;
remainingVolume = 0;
}
else
{
tipvolumn = 50;
currentVolumn = remainingVolume;
remainingVolume = 0;
}
var st = selectedTips.FirstOrDefault(s => s.tipVolume == tipvolumn);
if (st.tipVolume > 0)
{
st.absorbVolumnList.Add(currentVolumn);
}
else
{
List<double> absorbVolumes = new List<double>();
absorbVolumes.Add(currentVolumn);
selectedTips.Add((tipvolumn, absorbVolumes));
}
}
// 4. 优先用「最大可用Tip」处理剩余体积
//foreach (var tipVolume in availableTipVolumes)
//{
// if (remainingVolume <= 0) break; // 体积处理完则退出循环
// List<double> absorbVolumes = new List<double>();
// // 步骤1用当前Tip处理「尽可能多的满容量体积」
// if (remainingVolume >= tipVolume)
// {
// int fullTipCount = (int)(remainingVolume / tipVolume); // 需要的满容量Tip数量
// absorbVolumes.AddRange(Enumerable.Repeat(tipVolume, fullTipCount)); // 记录满容量吸液
// remainingVolume -= tipVolume * fullTipCount; // 扣除已处理的体积
// remainingVolume = Math.Round(remainingVolume, 3, MidpointRounding.ToPositiveInfinity); // 重新校准精度
// }
// // 步骤2处理「剩余的少量体积」不足一个满容量Tip
// if (remainingVolume > 0)
// {
// absorbVolumes.Add(remainingVolume); // 用当前Tip处理剩余体积
// remainingVolume = 0; // 体积处理完成
// }
// // 将当前Tip的选择结果加入列表
// selectedTips.Add((tipVolume, absorbVolumes));
//}
return selectedTips;
}
/// <summary>
/// 移液枪取Tip头
/// </summary>
/// <param name="token"></param>
/// <param name="tipType"></param>
/// <returns></returns>
private async Task PipetteTakeTip(CancellationToken token, TipBoxModel tipBox, DeviceNames deviceName)
{
if (token.IsCancellationRequested || TestMode) return;
ushort pipteId = 1;
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
{
pipteId = (ushort)((int)deviceName - 6);
}
TipHeadItem tipHead = tipBox.TipItems.FirstOrDefault(f => f.IsAvailable);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, (ushort)(3 - tipBox.BoxId_inDosingStation + 1));//(ushort)tipBox.BoxId_inDosingStation);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param3, (ushort)tipHead.UseIndex);//
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 11);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param2, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param3, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
tipHead.IsAvailable = false;
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// 移液枪吸液
/// </summary>
/// <param name="token"></param>
/// <param name="tipType"></param>
/// <returns></returns>
private async Task PipetteAbsorb(CancellationToken token, DeviceNames deviceName)
{
if (token.IsCancellationRequested || TestMode) return;
ushort pipteId = 1;
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
{
pipteId = (ushort)((int)deviceName - 6);
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 12);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// 移液枪分液
/// </summary>
/// <param name="token"></param>
/// <param name="tipType"></param>
/// <returns></returns>
private async Task PipetteDispense(CancellationToken token, DeviceNames deviceName)
{
if (token.IsCancellationRequested || TestMode) return;
ushort pipteId = 1;
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
{
pipteId = (ushort)((int)deviceName - 6);
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 13);
//等待PLC回复执行完成
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
/// <summary>
/// 移液枪丢弃Tip头
/// </summary>
/// <param name="token"></param>
/// <param name="tipType"></param>
/// <returns></returns>
private async Task PipetteDiscardTip(CancellationToken token, DeviceNames deviceName)
{
if (token.IsCancellationRequested || TestMode) return;
ushort pipteId = 1;
if (deviceName >= DeviceNames.Pipette_Dose_1ml_1 && deviceName <= DeviceNames.Pipette_Dose_1ml_4)
{
pipteId = (ushort)((int)deviceName - 6);
}
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, pipteId); //移液枪编号 1-4
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 14);
//等待PLC回复执行完成
await WaitForActionFinishAsync_FourAxis(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 22, token);
//信号清零
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_Param1, 0);
await WriteCommandAsync_XZ(PlcPoints_MaterialDose.W_BottleLidAndPipette_TaskNo, 0);
await WaitForActionFinishAsync_XZ(PlcPoints_MaterialDose.R_BottleLidAndPipette_RunResult, 5, token);
}
#endregion
private async Task RefreshReactBottleState(int boxId, int posId, SampleBottleStateEnum state)
{
await Task.Delay(0);
}
}
}