Compare commits
No commits in common. "98d34acbb1be76832c97a6889078b525cd230d10" and "main" have entirely different histories.
98d34acbb1
...
main
|
|
@ -1,63 +0,0 @@
|
||||||
###############################################################################
|
|
||||||
# Set default behavior to automatically normalize line endings.
|
|
||||||
###############################################################################
|
|
||||||
* text=auto
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set default behavior for command prompt diff.
|
|
||||||
#
|
|
||||||
# This is need for earlier builds of msysgit that does not have it on by
|
|
||||||
# default for csharp files.
|
|
||||||
# Note: This is only used by command line
|
|
||||||
###############################################################################
|
|
||||||
#*.cs diff=csharp
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set the merge driver for project and solution files
|
|
||||||
#
|
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
|
||||||
# these files as binary and thus will always conflict and require user
|
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
|
||||||
###############################################################################
|
|
||||||
#*.sln merge=binary
|
|
||||||
#*.csproj merge=binary
|
|
||||||
#*.vbproj merge=binary
|
|
||||||
#*.vcxproj merge=binary
|
|
||||||
#*.vcproj merge=binary
|
|
||||||
#*.dbproj merge=binary
|
|
||||||
#*.fsproj merge=binary
|
|
||||||
#*.lsproj merge=binary
|
|
||||||
#*.wixproj merge=binary
|
|
||||||
#*.modelproj merge=binary
|
|
||||||
#*.sqlproj merge=binary
|
|
||||||
#*.wwaproj merge=binary
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# behavior for image files
|
|
||||||
#
|
|
||||||
# image files are treated as binary by default.
|
|
||||||
###############################################################################
|
|
||||||
#*.jpg binary
|
|
||||||
#*.png binary
|
|
||||||
#*.gif binary
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# diff behavior for common document formats
|
|
||||||
#
|
|
||||||
# Convert binary document formats to text before diffing them. This feature
|
|
||||||
# is only available from the command line. Turn it on by uncommenting the
|
|
||||||
# entries below.
|
|
||||||
###############################################################################
|
|
||||||
#*.doc diff=astextplain
|
|
||||||
#*.DOC diff=astextplain
|
|
||||||
#*.docx diff=astextplain
|
|
||||||
#*.DOCX diff=astextplain
|
|
||||||
#*.dot diff=astextplain
|
|
||||||
#*.DOT diff=astextplain
|
|
||||||
#*.pdf diff=astextplain
|
|
||||||
#*.PDF diff=astextplain
|
|
||||||
#*.rtf diff=astextplain
|
|
||||||
#*.RTF diff=astextplain
|
|
||||||
|
|
@ -1,365 +0,0 @@
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
##
|
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.rsuser
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.userosscache
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
|
||||||
*.userprefs
|
|
||||||
|
|
||||||
# Mono auto generated files
|
|
||||||
mono_crash.*
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug/
|
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
|
||||||
[Rr]eleases/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
[Ww][Ii][Nn]32/
|
|
||||||
[Aa][Rr][Mm]/
|
|
||||||
[Aa][Rr][Mm]64/
|
|
||||||
bld/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
[Oo]ut/
|
|
||||||
[Ll]og/
|
|
||||||
[Ll]ogs/
|
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
|
||||||
.vs/
|
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
|
||||||
#wwwroot/
|
|
||||||
|
|
||||||
# Visual Studio 2017 auto generated files
|
|
||||||
Generated\ Files/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
# NUnit
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
nunit-*.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
# Benchmark Results
|
|
||||||
BenchmarkDotNet.Artifacts/
|
|
||||||
|
|
||||||
# .NET Core
|
|
||||||
project.lock.json
|
|
||||||
project.fragment.lock.json
|
|
||||||
artifacts/
|
|
||||||
|
|
||||||
# ASP.NET Scaffolding
|
|
||||||
ScaffoldingReadMe.txt
|
|
||||||
|
|
||||||
# StyleCop
|
|
||||||
StyleCopReport.xml
|
|
||||||
|
|
||||||
# Files built by Visual Studio
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_h.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.iobj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.ipdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*_wpftmp.csproj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opendb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
*.VC.db
|
|
||||||
*.VC.VC.opendb
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
*.sap
|
|
||||||
|
|
||||||
# Visual Studio Trace Files
|
|
||||||
*.e2e
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# AxoCover is a Code Coverage Tool
|
|
||||||
.axoCover/*
|
|
||||||
!.axoCover/settings.json
|
|
||||||
|
|
||||||
# Coverlet is a free, cross platform Code Coverage Tool
|
|
||||||
coverage*.json
|
|
||||||
coverage*.xml
|
|
||||||
coverage*.info
|
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
|
||||||
*.coverage
|
|
||||||
*.coveragexml
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
nCrunchTemp_*
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
|
||||||
# in these scripts will be unencrypted
|
|
||||||
PublishScripts/
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# NuGet Symbol Packages
|
|
||||||
*.snupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/[Pp]ackages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/[Pp]ackages/build/
|
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
|
||||||
#!**/[Pp]ackages/repositories.config
|
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
|
||||||
*.nuget.props
|
|
||||||
*.nuget.targets
|
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
|
||||||
ecf/
|
|
||||||
rcf/
|
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
|
||||||
AppPackages/
|
|
||||||
BundleArtifacts/
|
|
||||||
Package.StoreAssociation.xml
|
|
||||||
_pkginfo.txt
|
|
||||||
*.appx
|
|
||||||
*.appxbundle
|
|
||||||
*.appxupload
|
|
||||||
|
|
||||||
# Visual Studio cache files
|
|
||||||
# files ending in .cache can be ignored
|
|
||||||
*.[Cc]ache
|
|
||||||
# but keep track of directories ending in .cache
|
|
||||||
!?*.[Cc]ache/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
ClientBin/
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.jfm
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
orleans.codegen.cs
|
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
|
||||||
#*.snk
|
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
|
||||||
#bower_components/
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
ServiceFabricBackup/
|
|
||||||
*.rptproj.bak
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
*.ndf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
*.rptproj.rsuser
|
|
||||||
*- [Bb]ackup.rdl
|
|
||||||
*- [Bb]ackup ([0-9]).rdl
|
|
||||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
|
||||||
*.GhostDoc.xml
|
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
|
||||||
.ntvs_analysis.dat
|
|
||||||
node_modules/
|
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
|
||||||
*.plg
|
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
|
||||||
*.opt
|
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
|
||||||
*.vbw
|
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
|
||||||
**/*.Server/GeneratedArtifacts
|
|
||||||
**/*.Server/ModelManifest.xml
|
|
||||||
_Pvt_Extensions
|
|
||||||
|
|
||||||
# Paket dependency manager
|
|
||||||
.paket/paket.exe
|
|
||||||
paket-files/
|
|
||||||
|
|
||||||
# FAKE - F# Make
|
|
||||||
.fake/
|
|
||||||
|
|
||||||
# CodeRush personal settings
|
|
||||||
.cr/personal
|
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
|
||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
|
||||||
# tools/**
|
|
||||||
# !tools/packages.config
|
|
||||||
|
|
||||||
# Tabs Studio
|
|
||||||
*.tss
|
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
|
||||||
*.jmconfig
|
|
||||||
|
|
||||||
# BizTalk build output
|
|
||||||
*.btp.cs
|
|
||||||
*.btm.cs
|
|
||||||
*.odx.cs
|
|
||||||
*.xsd.cs
|
|
||||||
|
|
||||||
# OpenCover UI analysis results
|
|
||||||
OpenCover/
|
|
||||||
|
|
||||||
# Azure Stream Analytics local run output
|
|
||||||
ASALocalRun/
|
|
||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
|
||||||
*.binlog
|
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
|
||||||
*.nvuser
|
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
|
||||||
.mfractor/
|
|
||||||
|
|
||||||
# Local History for Visual Studio
|
|
||||||
.localhistory/
|
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
|
||||||
healthchecksdb
|
|
||||||
|
|
||||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
|
||||||
MigrationBackup/
|
|
||||||
|
|
||||||
# Ionide (cross platform F# VS Code tools) working folder
|
|
||||||
.ionide/
|
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
|
||||||
FodyWeavers.xsd
|
|
||||||
# 忽略 common 文件夹及其所有内容
|
|
||||||
/common/
|
|
||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
||||||
2个路由器串联下级路由器LAN口设置的方法:连接第2个路由器网络进设置页面,先修改IP(例如:上级路由的IP为192.168.0.1,则将第2个路由修改为192.168.0.2),然后在上网设置那WAN口数量设置成1.再点击路由设置--高级设置--修改路由器地址---DHCP服务器修改为OFF。 进行以上的操作之后,请将路由器电源拔掉再插一次,等待路由器重启完毕之后看是否能正常上网。
|
|
||||||
|
|
||||||
连接LAN口 关闭DHCP服务
|
|
||||||
|
|
||||||
192.168.50.99
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
<Window x:Class="Common.AlarmPopUpWindow"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:local="clr-namespace:Common"
|
|
||||||
mc:Ignorable="d" ResizeMode="NoResize" Topmost="True" WindowStartupLocation="CenterScreen"
|
|
||||||
Title="系统报警" Height="450" Width="800">
|
|
||||||
<Grid Margin="10">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<!-- 标题区域 -->
|
|
||||||
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">
|
|
||||||
<TextBlock Text="PLC报警信息" FontSize="16" FontWeight="Bold" Foreground="Red"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- 报警信息列表 -->
|
|
||||||
<ScrollViewer Grid.Row="1" Margin="20,5,10,0">
|
|
||||||
<ItemsControl x:Name="AlarmItems">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<StackPanel Margin="5">
|
|
||||||
<TextBlock Text="{Binding Key}"/>
|
|
||||||
<TextBlock Text="{Binding Value}" FontWeight="Bold" Margin="10,5,0,0"/>
|
|
||||||
<Separator Margin="0,5"/>
|
|
||||||
</StackPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</ScrollViewer>
|
|
||||||
|
|
||||||
<!-- 按钮区域 -->
|
|
||||||
<Button Grid.Row="2" Content="确认" Width="100" Height="30"
|
|
||||||
HorizontalAlignment="Center" Click="OkButton_Click" Style="{StaticResource okBtnStyle}"/>
|
|
||||||
</Grid>
|
|
||||||
</Window>
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// AlarmPopUpWindow.xaml 的交互逻辑
|
|
||||||
/// </summary>
|
|
||||||
public partial class AlarmPopUpWindow : Window
|
|
||||||
{
|
|
||||||
public AlarmPopUpWindow(Dictionary<string,string> alarmInfo)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
AlarmItems.ItemsSource = alarmInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OkButton_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
this.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 工装位置区域划分
|
|
||||||
/// </summary>
|
|
||||||
public enum BoxAreaEnum
|
|
||||||
{
|
|
||||||
_手套箱传送平台 = 1,
|
|
||||||
_Tip托盘存放平台 = 2,
|
|
||||||
_开关盖区域 = 3,
|
|
||||||
_称重模块 = 4,
|
|
||||||
_扫码区域 = 6,
|
|
||||||
_加样头存放平台 = 10,
|
|
||||||
_托盘存放平台 = 12,
|
|
||||||
_自动加样模块内 = 11,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工装类型
|
|
||||||
/// </summary>
|
|
||||||
public enum BoxTypeEnum
|
|
||||||
{
|
|
||||||
_40mL原液工装 = 1,
|
|
||||||
_12mL样品工装 = 2,
|
|
||||||
_5mL样品工装 = 3,
|
|
||||||
//_2mL外瓶工装 = 4,
|
|
||||||
//_滤芯瓶工装 = 5,
|
|
||||||
_16mL粉末瓶工装=6,
|
|
||||||
_125mL粉末瓶工装,
|
|
||||||
_50uLTip头工装,
|
|
||||||
_300uLTip头工装,
|
|
||||||
_1000uLTip头工装,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
[XmlInclude(typeof(SourcePowderBottleBoxModel))]
|
|
||||||
[XmlInclude(typeof(SourcePowderBottleBoxModel_125ml))]
|
|
||||||
[XmlInclude(typeof(SampleBottleBoxModel))]
|
|
||||||
[XmlInclude(typeof(SourceLiquidBottleBoxModel))]
|
|
||||||
[XmlInclude(typeof(TipBoxModel))]
|
|
||||||
public class BaseBottleBox : ObservableObject
|
|
||||||
{
|
|
||||||
private BoxAreaEnum boxarea = BoxAreaEnum._手套箱传送平台;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装所在的工装区域
|
|
||||||
/// </summary>
|
|
||||||
public BoxAreaEnum BoxArea
|
|
||||||
{
|
|
||||||
get { return boxarea; }
|
|
||||||
set { SetProperty(ref boxarea, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private BoxTypeEnum fixturetype = BoxTypeEnum._40mL原液工装;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装类型
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public BoxTypeEnum FixtureType
|
|
||||||
{
|
|
||||||
get => fixturetype;
|
|
||||||
set => SetProperty(ref fixturetype, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _boxsn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 载具的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string BoxSNCode
|
|
||||||
{
|
|
||||||
get => _boxsn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxsn, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isEmpty = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否是空位置。true:表示空,可以放置工装 false:表示位置有工装
|
|
||||||
/// </summary>
|
|
||||||
public bool IsEmpty
|
|
||||||
{
|
|
||||||
get => _isEmpty;
|
|
||||||
set => SetProperty(ref _isEmpty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isDoseFinish = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否配置完成,针对样品工装来说
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDoseFinish
|
|
||||||
{
|
|
||||||
get => _isDoseFinish;
|
|
||||||
set => SetProperty(ref _isDoseFinish, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isuseFinish = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否用完成 针对tip头工装或者原液瓶工装
|
|
||||||
/// </summary>
|
|
||||||
public bool IsUseFinsh
|
|
||||||
{
|
|
||||||
get => _isuseFinish;
|
|
||||||
set => SetProperty(ref _isuseFinish, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int boxid_indoseupload = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装在投料站 上料时位置(1-7)
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("boxIdInDoseUpload")]
|
|
||||||
public int BoxId_inDoseUpload
|
|
||||||
{
|
|
||||||
get => boxid_indoseupload;
|
|
||||||
set => SetProperty(ref boxid_indoseupload, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inDoseDnload = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装在投料站 下料时的位置(1-7)
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inDoseDnload
|
|
||||||
{
|
|
||||||
get => _boxid_inDoseDnload;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inDoseDnload, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inDosingStation = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装在投料站中位置(1-8)
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inDosingStation
|
|
||||||
{
|
|
||||||
get => _boxid_inDosingStation;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inDosingStation, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶工装的模型
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class SampleBottleBoxModel : BaseBottleBox
|
|
||||||
{
|
|
||||||
private SampleBottleTypeEnum sampleBottleType = SampleBottleTypeEnum._5mL;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶类型 5ML/12ML
|
|
||||||
/// </summary>
|
|
||||||
public SampleBottleTypeEnum SampleBottleType
|
|
||||||
{
|
|
||||||
get { return sampleBottleType; }
|
|
||||||
set { SetProperty(ref sampleBottleType, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<SampleBottleModel> sampleBottleList = new ObservableCollection<SampleBottleModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 一个样品工装中样品瓶的集合(12个样品瓶)
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<SampleBottleModel> SampleBottleList
|
|
||||||
{
|
|
||||||
get { return sampleBottleList; }
|
|
||||||
set { SetProperty(ref sampleBottleList, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 投料站
|
|
||||||
|
|
||||||
//private bool haveBox = false;
|
|
||||||
///// <summary>
|
|
||||||
///// 投料站中放样品工装1-4个位置中 是否有样品瓶工装
|
|
||||||
///// </summary>
|
|
||||||
//public bool HaveBox
|
|
||||||
//{
|
|
||||||
// get => haveBox;
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref haveBox, value);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 反应站
|
|
||||||
|
|
||||||
private int _boxid_inReactUpload = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品工装在反应站中的上料时位置(1-6)
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inReactUpload
|
|
||||||
{
|
|
||||||
get => _boxid_inReactUpload;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inReactUpload, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inhightempHC = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品工装在反应站中高温缓存位置(1-3),在高温模块上的缓存位置
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inhightempHC
|
|
||||||
{
|
|
||||||
get => _boxid_inhightempHC;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inhightempHC, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inReactRack_layer = 3;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品工装在反应站中料架中的第几层 默认三层或者四层
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inReactRack_Layer
|
|
||||||
{
|
|
||||||
get => _boxid_inReactRack_layer;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inReactRack_layer, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inReactRack_pos = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品工装在反应站中料架中的第几层第几个位置(1-10)
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inReactRack_Pos
|
|
||||||
{
|
|
||||||
get => _boxid_inReactRack_pos;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inReactRack_pos, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SampleBottleBoxModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,519 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶状态
|
|
||||||
/// </summary>
|
|
||||||
public enum SampleBottleStateEnum
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 0:还未投料
|
|
||||||
/// </summary>
|
|
||||||
Empty = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// 正在投料中
|
|
||||||
/// </summary>
|
|
||||||
IsDosing = 1,
|
|
||||||
|
|
||||||
DoseFinish = 2,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1:高温反应中
|
|
||||||
/// </summary>
|
|
||||||
HighTemperaturReact = 3,
|
|
||||||
/// <summary>
|
|
||||||
/// 2:低温反应中
|
|
||||||
/// </summary>
|
|
||||||
LowTemperaturReact = 4,
|
|
||||||
/// <summary>
|
|
||||||
///穿刺取样中
|
|
||||||
/// </summary>
|
|
||||||
PunctureSampling = 5,
|
|
||||||
/// <summary>
|
|
||||||
/// 开盖取样中
|
|
||||||
/// </summary>
|
|
||||||
OpenLidSampling = 6,
|
|
||||||
/// <summary>
|
|
||||||
/// 穿刺补液
|
|
||||||
/// </summary>
|
|
||||||
PunctureAddLiquid = 7,
|
|
||||||
/// <summary>
|
|
||||||
/// 开盖补液
|
|
||||||
/// </summary>
|
|
||||||
OpenLidAddLiquid = 8,
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释中
|
|
||||||
/// </summary>
|
|
||||||
Dilute = 9,
|
|
||||||
/// <summary>
|
|
||||||
/// 过滤中
|
|
||||||
/// </summary>
|
|
||||||
Filter = 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反应温度选择
|
|
||||||
/// </summary>
|
|
||||||
public enum SampleBottleReactTemperatureEnum
|
|
||||||
{
|
|
||||||
高温反应,
|
|
||||||
低温反应,
|
|
||||||
无,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反应模块的操作类型
|
|
||||||
/// </summary>
|
|
||||||
public enum ReactOperationEnum
|
|
||||||
{
|
|
||||||
取样,
|
|
||||||
补液,
|
|
||||||
无,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取样方式
|
|
||||||
/// </summary>
|
|
||||||
public enum SampleMethod
|
|
||||||
{
|
|
||||||
穿刺取样,
|
|
||||||
开盖取样,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 补液方式
|
|
||||||
/// </summary>
|
|
||||||
public enum AddLiquidMethod
|
|
||||||
{
|
|
||||||
穿刺补液,
|
|
||||||
开盖补液,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释方式
|
|
||||||
/// </summary>
|
|
||||||
public enum DiluteMethod
|
|
||||||
{
|
|
||||||
移液枪稀释,
|
|
||||||
穿刺针稀释,
|
|
||||||
加样针稀释,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶盖子的状态
|
|
||||||
/// </summary>
|
|
||||||
public enum SampleBottleLidStateEnum
|
|
||||||
{
|
|
||||||
Close,
|
|
||||||
Open,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶类型
|
|
||||||
/// </summary>
|
|
||||||
public enum SampleBottleTypeEnum
|
|
||||||
{
|
|
||||||
_5mL = 1,
|
|
||||||
_12mL = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶属性
|
|
||||||
/// </summary>
|
|
||||||
public class SampleBottleModel : ObservableObject
|
|
||||||
{
|
|
||||||
private long sampleSeqId;
|
|
||||||
public long SampleSeqId
|
|
||||||
{
|
|
||||||
get { return sampleSeqId; }
|
|
||||||
set { SetProperty(ref sampleSeqId, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleBottleTypeEnum sampleBottleType = SampleBottleTypeEnum._5mL;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶类型 5ML/12ML
|
|
||||||
/// </summary>
|
|
||||||
public SampleBottleTypeEnum SampleBottleType
|
|
||||||
{
|
|
||||||
get { return sampleBottleType; }
|
|
||||||
set { SetProperty(ref sampleBottleType, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _boxsn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶所在的工装的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string BoxSNCode
|
|
||||||
{
|
|
||||||
get => _boxsn;
|
|
||||||
set { SetProperty(ref _boxsn, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _sn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string SNCode
|
|
||||||
{
|
|
||||||
get => _sn;
|
|
||||||
set { SetProperty(ref _sn, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _haveBottle = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否有样品瓶子
|
|
||||||
/// </summary>
|
|
||||||
public bool HaveBottle
|
|
||||||
{
|
|
||||||
get => _haveBottle;
|
|
||||||
set { SetProperty(ref _haveBottle, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool bdosefinish = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否配置完成
|
|
||||||
/// </summary>
|
|
||||||
public bool bDoseFinish
|
|
||||||
{
|
|
||||||
get { return bdosefinish; }
|
|
||||||
set { bdosefinish = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _posId_inbox = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶在工装中的第几个位置(1-12)
|
|
||||||
/// </summary>
|
|
||||||
public int PosId_InBox
|
|
||||||
{
|
|
||||||
get => _posId_inbox;
|
|
||||||
set { SetProperty(ref _posId_inbox, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 投料站
|
|
||||||
private string _sampleContentName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶投料结果内容名称
|
|
||||||
/// </summary>
|
|
||||||
public string SampleContentName
|
|
||||||
{
|
|
||||||
get { return _sampleContentName; }
|
|
||||||
set { SetProperty(ref _sampleContentName, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleBottleStateEnum _sampleBottleState = SampleBottleStateEnum.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶状态 正在哪一步操作中
|
|
||||||
/// </summary>
|
|
||||||
public SampleBottleStateEnum SampleBoxState
|
|
||||||
{
|
|
||||||
get => _sampleBottleState;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_sampleBottleState != value)
|
|
||||||
{
|
|
||||||
_sampleBottleState = value;
|
|
||||||
OnPropertyChanged(nameof(SampleBoxState));
|
|
||||||
OnPropertyChanged(nameof(DisplayColor_Dose));
|
|
||||||
OnPropertyChanged(nameof(DisplayColor_React));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶状态,在投料站中展示颜色
|
|
||||||
/// </summary>
|
|
||||||
public Brush DisplayColor_Dose
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (SampleBoxState)
|
|
||||||
{
|
|
||||||
case SampleBottleStateEnum.Empty:
|
|
||||||
if (HaveBottle) return (Brush)new BrushConverter().ConvertFrom("#aff0b3");
|
|
||||||
else return (Brush)new BrushConverter().ConvertFrom("#dcd8d8"); //return "#d1caca".FromHex(); // 未配置:白色
|
|
||||||
case SampleBottleStateEnum.IsDosing:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#f6ee73"); // 状态:黄色
|
|
||||||
case SampleBottleStateEnum.HighTemperaturReact:
|
|
||||||
case SampleBottleStateEnum.LowTemperaturReact:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#e3612e"); // 状态:橘色
|
|
||||||
case SampleBottleStateEnum.OpenLidSampling:
|
|
||||||
case SampleBottleStateEnum.PunctureSampling:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#5f84ee"); // 紫色
|
|
||||||
case SampleBottleStateEnum.Dilute:
|
|
||||||
case SampleBottleStateEnum.Filter:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#61b2f5"); // 蓝色
|
|
||||||
default:
|
|
||||||
if (HaveBottle) return (Brush)new BrushConverter().ConvertFrom("#aff0b3");
|
|
||||||
else return (Brush)new BrushConverter().ConvertFrom("#dcd8d8");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶状态,在反应站展示颜色
|
|
||||||
/// </summary>
|
|
||||||
public Brush DisplayColor_React
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
switch (SampleBoxState)
|
|
||||||
{
|
|
||||||
case SampleBottleStateEnum.Empty:
|
|
||||||
if (HaveBottle) return (Brush)new BrushConverter().ConvertFrom("#aff0b3");
|
|
||||||
else return (Brush)new BrushConverter().ConvertFrom("#dcd8d8"); //return "#d1caca".FromHex(); // 未配置:白色
|
|
||||||
//case SampleBottleStateEnum.IsDosing:
|
|
||||||
// return (Brush)new BrushConverter().ConvertFrom("#f6ee73"); // 状态:黄色
|
|
||||||
case SampleBottleStateEnum.HighTemperaturReact:
|
|
||||||
case SampleBottleStateEnum.LowTemperaturReact:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#e3612e"); // 状态:橘色
|
|
||||||
case SampleBottleStateEnum.OpenLidSampling:
|
|
||||||
case SampleBottleStateEnum.PunctureSampling:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#5f84ee"); // 紫色
|
|
||||||
case SampleBottleStateEnum.Dilute:
|
|
||||||
case SampleBottleStateEnum.Filter:
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#61b2f5"); // 蓝色
|
|
||||||
default:
|
|
||||||
if (HaveBottle) return (Brush)new BrushConverter().ConvertFrom("#aff0b3");
|
|
||||||
else return (Brush)new BrushConverter().ConvertFrom("#dcd8d8");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleBottleLidStateEnum _sampleBottleLidState = SampleBottleLidStateEnum.Close;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶盖子的状态
|
|
||||||
/// </summary>
|
|
||||||
public SampleBottleLidStateEnum SampleBottleLidState
|
|
||||||
{
|
|
||||||
get => _sampleBottleLidState;
|
|
||||||
set => _sampleBottleLidState = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<MaterialDoseFunctionFlow> _materialDoseFlowList = new ObservableCollection<MaterialDoseFunctionFlow>();
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶中投料站流程集合,用于显示datagridView控件中
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<MaterialDoseFunctionFlow> MaterialDoseFlowList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _materialDoseFlowList;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
// 设置新值
|
|
||||||
if (value != null && SetProperty(ref _materialDoseFlowList, value))
|
|
||||||
{
|
|
||||||
// 先取消旧集合的事件订阅
|
|
||||||
_materialDoseFlowList.CollectionChanged -= LiquidFlowList_CollectionChanged;
|
|
||||||
// 订阅新集合的事件
|
|
||||||
_materialDoseFlowList.CollectionChanged += LiquidFlowList_CollectionChanged;
|
|
||||||
// 手动触发一次计算
|
|
||||||
LiquidFlowList_CollectionChanged(this, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 预估时间相关
|
|
||||||
|
|
||||||
private double _estimatedDuration = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 预估投料耗时时间,单位min
|
|
||||||
/// </summary>
|
|
||||||
public double EstimatedDuration
|
|
||||||
{
|
|
||||||
get => _estimatedDuration;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _estimatedDuration, value, nameof(EstimatedDuration));
|
|
||||||
{
|
|
||||||
if (remainDuration == 0) // 假设初始值为0,代表未初始化
|
|
||||||
{
|
|
||||||
remainDuration = value;
|
|
||||||
OnPropertyChanged(nameof(RemainDuration));
|
|
||||||
}
|
|
||||||
OnPropertyChanged(nameof(ProgressPercentage));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 液体流程集合项变化时更新时间
|
|
||||||
private void LiquidFlowList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
EstimatedDuration = 1 * _materialDoseFlowList.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private double remainDuration = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 预估原样瓶配置剩余时间,单位min
|
|
||||||
/// </summary>
|
|
||||||
public double RemainDuration
|
|
||||||
{
|
|
||||||
get { return remainDuration; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref remainDuration, value);
|
|
||||||
OnPropertyChanged(nameof(ProgressPercentage));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用于进度绑定的属性
|
|
||||||
/// </summary>
|
|
||||||
public double ProgressPercentage
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (EstimatedDuration <= 0) return 1.0;
|
|
||||||
double usedRatio = 1.0 - (RemainDuration / (EstimatedDuration)); // 注意单位转换
|
|
||||||
return Math.Max(0, Math.Min(1, usedRatio));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public SampleBottleModel()
|
|
||||||
{
|
|
||||||
// ObservableCollection 会在项添加 / 删除时触发 CollectionChanged 事件,需在 ReactBottleModel 中订阅该事件,确保集合项变化时重新计算时间。
|
|
||||||
// 初始化集合时订阅 CollectionChanged 事件
|
|
||||||
_materialDoseFlowList.CollectionChanged += LiquidFlowList_CollectionChanged;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 反应站
|
|
||||||
private int _highTempModuleNo = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶在高温模块的编号(1-4)
|
|
||||||
/// </summary>
|
|
||||||
public int HighTempModuleNo
|
|
||||||
{
|
|
||||||
get => _highTempModuleNo;
|
|
||||||
set => _highTempModuleNo = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _pos_inhightemperatur = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶在高温模块中的位置(1-24)
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_InHighTemperatur
|
|
||||||
{
|
|
||||||
get => _pos_inhightemperatur;
|
|
||||||
set => _pos_inhightemperatur = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _lowTempModuleNo = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶在低温模块的编号(1-2)
|
|
||||||
/// </summary>
|
|
||||||
public int LowTempModuleNo
|
|
||||||
{
|
|
||||||
get => _lowTempModuleNo;
|
|
||||||
set => _lowTempModuleNo = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _pos_inlowtemperatur = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶在低温模块中的位置(1-24)
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_InLowTemperatur
|
|
||||||
{
|
|
||||||
get => _pos_inlowtemperatur;
|
|
||||||
set => _pos_inlowtemperatur = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleBottleReactTemperatureEnum reactTemperatureType = SampleBottleReactTemperatureEnum.高温反应;
|
|
||||||
/// <summary>
|
|
||||||
/// 反应温度方式
|
|
||||||
/// </summary>
|
|
||||||
public SampleBottleReactTemperatureEnum ReactTemperatureType
|
|
||||||
{
|
|
||||||
get { return reactTemperatureType; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref reactTemperatureType, value);
|
|
||||||
OnPropertyChanged(nameof(CurrentTemperatureModel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleBottleTemperatureModel tempmodel = new SampleBottleTemperatureModel();
|
|
||||||
public SampleBottleTemperatureModel CurrentTemperatureModel
|
|
||||||
{
|
|
||||||
get => tempmodel;
|
|
||||||
set => SetProperty(ref tempmodel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SampleMethod samplemethod = SampleMethod.穿刺取样;
|
|
||||||
/// <summary>
|
|
||||||
/// 取样方式
|
|
||||||
/// </summary>
|
|
||||||
public SampleMethod SampleMethod
|
|
||||||
{
|
|
||||||
get { return samplemethod; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref samplemethod, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AddLiquidMethod addliquidmethod = AddLiquidMethod.穿刺补液;
|
|
||||||
/// <summary>
|
|
||||||
/// 补液方式
|
|
||||||
/// </summary>
|
|
||||||
public AddLiquidMethod AddLiquidType
|
|
||||||
{
|
|
||||||
get { return addliquidmethod; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref addliquidmethod, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double height = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 穿刺取样高度
|
|
||||||
/// </summary>
|
|
||||||
public double PunchHeight
|
|
||||||
{
|
|
||||||
get { return height; }
|
|
||||||
set { SetProperty(ref height, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private ObservableCollection<ReactSampleFunctionFlow> sampleFunctionFlowList = new ObservableCollection<ReactSampleFunctionFlow>();
|
|
||||||
/// <summary>
|
|
||||||
/// 取样流程
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<ReactSampleFunctionFlow> SampleFunctionFlowList
|
|
||||||
{
|
|
||||||
get { return sampleFunctionFlowList; }
|
|
||||||
set { SetProperty(ref sampleFunctionFlowList, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<AddLiquidFunctionFlow> _addLiquidFlowList = new ObservableCollection<AddLiquidFunctionFlow>();
|
|
||||||
/// <summary>
|
|
||||||
/// 加液流程集合,用于显示datagridView控件中
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<AddLiquidFunctionFlow> AddLiquidFunctionFlowList
|
|
||||||
{
|
|
||||||
get { return _addLiquidFlowList; }
|
|
||||||
set { SetProperty(ref _addLiquidFlowList, value); }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class SourceLiquidBottleBoxModel : BaseBottleBox
|
|
||||||
{
|
|
||||||
//private bool havebox = false;
|
|
||||||
///// <summary>
|
|
||||||
///// 是否有原液瓶工装
|
|
||||||
///// </summary>
|
|
||||||
//public bool HaveBox
|
|
||||||
//{
|
|
||||||
// get { return havebox; }
|
|
||||||
// set { SetProperty(ref havebox, value); }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private ObservableCollection<SourceLiquidBottleModel> sourceliquidbottlecollection;
|
|
||||||
/// <summary>
|
|
||||||
/// 一个原液瓶工装中的原液瓶集合(8个原液瓶)
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<SourceLiquidBottleModel> SourceLiquidBottleCollection
|
|
||||||
{
|
|
||||||
get { return sourceliquidbottlecollection; }
|
|
||||||
set { SetProperty(ref sourceliquidbottlecollection, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceLiquidBottleBoxModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.TextFormatting;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 原液瓶的状态
|
|
||||||
/// </summary>
|
|
||||||
public enum SourceBottleStateEnum
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 空闲,没有在使用
|
|
||||||
/// </summary>
|
|
||||||
Idl = 0,
|
|
||||||
/// <summary>
|
|
||||||
/// 使用中
|
|
||||||
/// </summary>
|
|
||||||
Using,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 原液瓶盖子的状态
|
|
||||||
/// </summary>
|
|
||||||
public enum SourceBottleLidStateEnum
|
|
||||||
{
|
|
||||||
Close,
|
|
||||||
Open,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class SourceLiquidBottleModel : ObservableObject
|
|
||||||
{
|
|
||||||
private bool _haveBottle = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否有液体瓶子
|
|
||||||
/// </summary>
|
|
||||||
public bool HaveBottle
|
|
||||||
{
|
|
||||||
get => _haveBottle;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _haveBottle, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _posId = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶在工装中的位置(1-8)
|
|
||||||
/// </summary>
|
|
||||||
public int PosId_InBox
|
|
||||||
{
|
|
||||||
get => _posId;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _posId, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _boxsn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶所在载具的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string BoxSNCode
|
|
||||||
{
|
|
||||||
get => _boxsn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxsn, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _sn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string SNCode
|
|
||||||
{
|
|
||||||
get => _sn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _sn, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _sourceLiquidName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶中液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string SourceLiquidName
|
|
||||||
{
|
|
||||||
get => _sourceLiquidName;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_sourceLiquidName != value)
|
|
||||||
{
|
|
||||||
_sourceLiquidName = value;
|
|
||||||
OnPropertyChanged(nameof(SourceLiquidName));
|
|
||||||
OnPropertyChanged(nameof(LiquidDisplayColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Brush LiquidDisplayColor
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(SourceLiquidName)) //没有有名称
|
|
||||||
{
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#dcd8d8");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#cab2ec");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _originVolume = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 初始体积
|
|
||||||
/// </summary>
|
|
||||||
public double OriginVolume
|
|
||||||
{
|
|
||||||
get => _originVolume;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_originVolume != value)
|
|
||||||
{
|
|
||||||
_originVolume = value;
|
|
||||||
_remainVolume = value;
|
|
||||||
OnPropertyChanged(nameof(OriginVolume));
|
|
||||||
OnPropertyChanged(nameof(RemainVolume));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _remainVolume = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 剩余体积 单位ML
|
|
||||||
/// </summary>
|
|
||||||
public double RemainVolume
|
|
||||||
{
|
|
||||||
get => _remainVolume;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _remainVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//private double _density = 1.00;
|
|
||||||
///// <summary>
|
|
||||||
///// 密度,单位g/mL
|
|
||||||
///// </summary>
|
|
||||||
//public double Density
|
|
||||||
//{
|
|
||||||
// get => _density;
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref _density, value);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private SourceBottleStateEnum _sourceBottleState = SourceBottleStateEnum.Idl;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶状态
|
|
||||||
/// </summary>
|
|
||||||
public SourceBottleStateEnum SourceLiquidBottleState
|
|
||||||
{
|
|
||||||
get => _sourceBottleState;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _sourceBottleState, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SourceBottleLidStateEnum _LiquidBottleLidState = SourceBottleLidStateEnum.Close;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体原液瓶盖子的状态
|
|
||||||
/// </summary>
|
|
||||||
public SourceBottleLidStateEnum LiquidBottleLidState
|
|
||||||
{
|
|
||||||
get => _LiquidBottleLidState;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _LiquidBottleLidState, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceLiquidBottleModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class SourcePowderBottleBoxModel : BaseBottleBox
|
|
||||||
{
|
|
||||||
private PowderBottleTypeEnum powderbottletype = PowderBottleTypeEnum._16mL;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末瓶类型
|
|
||||||
/// </summary>
|
|
||||||
public PowderBottleTypeEnum PowderBottleType
|
|
||||||
{
|
|
||||||
get { return powderbottletype; }
|
|
||||||
set { SetProperty(ref powderbottletype, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
//private bool havebox;
|
|
||||||
///// <summary>
|
|
||||||
///// 是否有 粉末瓶工装
|
|
||||||
///// </summary>
|
|
||||||
//public bool HaveBox
|
|
||||||
//{
|
|
||||||
// get { return havebox; }
|
|
||||||
// set { SetProperty(ref havebox, value); }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private int boxId;
|
|
||||||
///// <summary>
|
|
||||||
///// 粉末瓶工装的位置号(1-6)
|
|
||||||
///// </summary>
|
|
||||||
//public int BoxId
|
|
||||||
//{
|
|
||||||
// get { return boxId; }
|
|
||||||
// set { SetProperty(ref boxId, value); }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private ObservableCollection<SourcePowderBottleModel> sourcepowderbottlecollection = new ObservableCollection<SourcePowderBottleModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 一个粉末瓶工装中的粉末瓶集合(4个粉末瓶)
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<SourcePowderBottleModel> SourcePowderBottleCollection
|
|
||||||
{
|
|
||||||
get { return sourcepowderbottlecollection; }
|
|
||||||
set { SetProperty(ref sourcepowderbottlecollection, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourcePowderBottleBoxModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class SourcePowderBottleBoxModel_125ml : BaseBottleBox
|
|
||||||
{
|
|
||||||
private PowderBottleTypeEnum powderbottletype = PowderBottleTypeEnum._125mL;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末瓶类型
|
|
||||||
/// </summary>
|
|
||||||
public PowderBottleTypeEnum PowderBottleType
|
|
||||||
{
|
|
||||||
get { return powderbottletype; }
|
|
||||||
set { SetProperty(ref powderbottletype, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
//private bool havebox;
|
|
||||||
///// <summary>
|
|
||||||
///// 是否有 粉末瓶工装
|
|
||||||
///// </summary>
|
|
||||||
//public bool HaveBox
|
|
||||||
//{
|
|
||||||
// get { return havebox; }
|
|
||||||
// set { SetProperty(ref havebox, value); }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private int boxId;
|
|
||||||
///// <summary>
|
|
||||||
///// 粉末瓶工装的位置号(1-6)
|
|
||||||
///// </summary>
|
|
||||||
//public int BoxId
|
|
||||||
//{
|
|
||||||
// get { return boxId; }
|
|
||||||
// set { SetProperty(ref boxId, value); }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private ObservableCollection<SourcePowderBottleModel> sourcepowderbottlecollection = new ObservableCollection<SourcePowderBottleModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 一个粉末瓶工装中的粉末瓶集合(4个粉末瓶)
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<SourcePowderBottleModel> SourcePowderBottleCollection
|
|
||||||
{
|
|
||||||
get { return sourcepowderbottlecollection; }
|
|
||||||
set { SetProperty(ref sourcepowderbottlecollection, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourcePowderBottleBoxModel_125ml()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,193 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末瓶类型
|
|
||||||
/// </summary>
|
|
||||||
public enum PowderBottleTypeEnum
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 如果是16ml 一个工装放4个
|
|
||||||
/// </summary>
|
|
||||||
_16mL,
|
|
||||||
/// <summary>
|
|
||||||
/// 如果是125ml, 一个工装放2个
|
|
||||||
/// </summary>
|
|
||||||
_125mL,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class SourcePowderBottleModel : ObservableObject
|
|
||||||
{
|
|
||||||
private PowderBottleTypeEnum powderbottletype = PowderBottleTypeEnum._125mL;
|
|
||||||
public PowderBottleTypeEnum PowderBottleType
|
|
||||||
{
|
|
||||||
get { return powderbottletype; }
|
|
||||||
set { SetProperty(ref powderbottletype, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _haveBottle = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否有粉末瓶子
|
|
||||||
/// </summary>
|
|
||||||
public bool HaveBottle
|
|
||||||
{
|
|
||||||
get => _haveBottle;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _haveBottle, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _sourceInde = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶在工装中的原本位置
|
|
||||||
/// </summary>
|
|
||||||
public int SourceIndex
|
|
||||||
{
|
|
||||||
get => _sourceInde;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _sourceInde, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _pos = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶在工装中的位置(1-4 对于125ml的粉末,位置对应1-2)
|
|
||||||
/// </summary>
|
|
||||||
public int PosId_InBox
|
|
||||||
{
|
|
||||||
get => _pos;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _pos, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _sn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末瓶的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string SNCode
|
|
||||||
{
|
|
||||||
get => _sn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _sn, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _boxsn = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末瓶所在载具的二维码信息
|
|
||||||
/// </summary>
|
|
||||||
public string BoxSNCode
|
|
||||||
{
|
|
||||||
get => _boxsn;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxsn, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _sourcePowderName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶中粉末名称
|
|
||||||
/// </summary>
|
|
||||||
public string SourcePowderName
|
|
||||||
{
|
|
||||||
get => _sourcePowderName;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_sourcePowderName != value)
|
|
||||||
{
|
|
||||||
_sourcePowderName = value;
|
|
||||||
OnPropertyChanged(nameof(SourcePowderName));
|
|
||||||
OnPropertyChanged(nameof(PowderDisplayColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Brush PowderDisplayColor
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(SourcePowderName)) //没有有名称
|
|
||||||
{
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#dcd8d8");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (Brush)new BrushConverter().ConvertFrom("#b9cbf5"); //#FFFAFAF7
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _originWeight = 0.00;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶初始重量
|
|
||||||
/// </summary>
|
|
||||||
public double OriginWeight
|
|
||||||
{
|
|
||||||
get => _originWeight;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_originWeight != value)
|
|
||||||
{
|
|
||||||
_originWeight = value;
|
|
||||||
_remainWeight = value;
|
|
||||||
OnPropertyChanged(nameof(OriginWeight));
|
|
||||||
OnPropertyChanged(nameof(RemainWeight));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _remainWeight = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 剩余重量 单位g
|
|
||||||
/// </summary>
|
|
||||||
public double RemainWeight
|
|
||||||
{
|
|
||||||
get => _remainWeight;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _remainWeight, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SourceBottleStateEnum _state = SourceBottleStateEnum.Idl;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶状态
|
|
||||||
/// </summary>
|
|
||||||
public SourceBottleStateEnum SourcePowderBottleState
|
|
||||||
{
|
|
||||||
get => _state;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _state, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _pos_inDosePowderHC = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末原液瓶在投料工站中的10个粉末瓶缓存的位置(1-10)
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_InDosePowderHC
|
|
||||||
{
|
|
||||||
get => _pos_inDosePowderHC;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _pos_inDosePowderHC, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
public enum TipTypeEnum
|
|
||||||
{
|
|
||||||
_50UL = 1,
|
|
||||||
_300UL = 2,
|
|
||||||
_1000UL = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class TipHeadItem : ObservableObject
|
|
||||||
{
|
|
||||||
private bool _isAvailable;
|
|
||||||
public bool IsAvailable
|
|
||||||
{
|
|
||||||
get => _isAvailable;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _isAvailable, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int useindex = 0;
|
|
||||||
|
|
||||||
public int UseIndex
|
|
||||||
{
|
|
||||||
get { return useindex; }
|
|
||||||
set { SetProperty(ref useindex, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public TipHeadItem()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class TipBoxModel : BaseBottleBox
|
|
||||||
{
|
|
||||||
private TipTypeEnum tipType;
|
|
||||||
/// <summary>
|
|
||||||
/// Tip头类型
|
|
||||||
/// </summary>
|
|
||||||
public TipTypeEnum TipType
|
|
||||||
{
|
|
||||||
get { return tipType; }
|
|
||||||
set { SetProperty(ref tipType, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _havebox = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否有工装
|
|
||||||
/// </summary>
|
|
||||||
public bool HaveBox
|
|
||||||
{
|
|
||||||
get => _havebox;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _havebox, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<TipHeadItem> tipHeadItems = new ObservableCollection<TipHeadItem>();
|
|
||||||
public ObservableCollection<TipHeadItem> TipItems
|
|
||||||
{
|
|
||||||
get => tipHeadItems;
|
|
||||||
set => SetProperty(ref tipHeadItems, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int useIndex;
|
|
||||||
/// <summary>
|
|
||||||
/// 使用的索引位置(1-96)
|
|
||||||
/// </summary>
|
|
||||||
public int UseIndex
|
|
||||||
{
|
|
||||||
get { return useIndex; }
|
|
||||||
set { SetProperty(ref useIndex, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _boxid_inDosingStation = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 工装在投料站中位置(1-3)
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId_inDosingStation
|
|
||||||
{
|
|
||||||
get => _boxid_inDosingStation;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _boxid_inDosingStation, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int pos_inReactStation;
|
|
||||||
/// <summary>
|
|
||||||
/// 在反应站Tip头工装位置(1-6中某几个)
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_inReactStation
|
|
||||||
{
|
|
||||||
get { return pos_inReactStation; }
|
|
||||||
set { SetProperty(ref pos_inReactStation, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private int layer_inRack = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// Tip头工装在反应站中的料架的层号 ,默认放置第一层
|
|
||||||
/// </summary>
|
|
||||||
public int Layer_inRack
|
|
||||||
{
|
|
||||||
get => layer_inRack;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref layer_inRack, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int pos_inRack = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// Tip头工装在反应站中的料架的位置(1-8)
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_inRack
|
|
||||||
{
|
|
||||||
get => pos_inRack;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref pos_inRack, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public TipBoxModel()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 2ml瓶-滤芯工装
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class _2mlBottleBox_Inner : BaseBottleBox
|
|
||||||
{
|
|
||||||
private int _box_inReactRack_layer = 4;
|
|
||||||
/// <summary>
|
|
||||||
/// 在设备内部料架的第4层
|
|
||||||
/// </summary>
|
|
||||||
public int Box_inReactRack_Layer
|
|
||||||
{
|
|
||||||
get { return _box_inReactRack_layer; }
|
|
||||||
set { SetProperty(ref _box_inReactRack_layer, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _box_inReactRack_pos;
|
|
||||||
/// <summary>
|
|
||||||
/// 在设备内部料架的第几层的第几个位置(1-10)
|
|
||||||
/// </summary>
|
|
||||||
public int Boxd_inReactRack_Pos
|
|
||||||
{
|
|
||||||
get { return _box_inReactRack_pos; }
|
|
||||||
set { SetProperty(ref _box_inReactRack_pos, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int pos_inReactStation;
|
|
||||||
/// <summary>
|
|
||||||
/// 在反应工站放料区的6个位置中的其中一个
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_InReactStation
|
|
||||||
{
|
|
||||||
get { return pos_inReactStation; }
|
|
||||||
set { SetProperty(ref pos_inReactStation, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从位置1开始使用
|
|
||||||
/// </summary>
|
|
||||||
private int useIndex = 1;
|
|
||||||
public int UseIndex
|
|
||||||
{
|
|
||||||
get { return useIndex; }
|
|
||||||
set { SetProperty(ref useIndex, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public _2mlBottleBox_Inner()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 2ml瓶-外瓶工装
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class _2mlBottleBox_Outer : BaseBottleBox
|
|
||||||
{
|
|
||||||
private int _box_inReactRack_layer = 1;
|
|
||||||
/// <summary>
|
|
||||||
/// 在设备内部料架的第1层
|
|
||||||
/// </summary>
|
|
||||||
public int Box_inReactRack_Layer
|
|
||||||
{
|
|
||||||
get { return _box_inReactRack_layer; }
|
|
||||||
set { SetProperty(ref _box_inReactRack_layer, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _box_inReactRack_pos;
|
|
||||||
/// <summary>
|
|
||||||
/// 在设备内部料架的第几层的第几个位置(1-10)
|
|
||||||
/// </summary>
|
|
||||||
public int Box_inReactRack_Pos
|
|
||||||
{
|
|
||||||
get { return _box_inReactRack_pos; }
|
|
||||||
set { SetProperty(ref _box_inReactRack_pos, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private int pos_inReactStation;
|
|
||||||
/// <summary>
|
|
||||||
/// 在反应工站放料区的6个位置中的其中一个
|
|
||||||
/// </summary>
|
|
||||||
public int Pos_InReactStation
|
|
||||||
{
|
|
||||||
get { return pos_inReactStation; }
|
|
||||||
set { SetProperty(ref pos_inReactStation, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从位置1开始使用
|
|
||||||
/// </summary>
|
|
||||||
private int useIndex = 1;
|
|
||||||
public int UseIndex
|
|
||||||
{
|
|
||||||
get { return useIndex; }
|
|
||||||
set { SetProperty(ref useIndex, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public _2mlBottleBox_Outer()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Media;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public static class ColorExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 将十六进制颜色字符串转换为 System.Windows.Media.Color 对象
|
|
||||||
/// 支持格式: #RGB, #RGBA, #RRGGBB, #RRGGBBAA
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hex">十六进制颜色字符串</param>
|
|
||||||
/// <returns>转换后的 Color 对象</returns>
|
|
||||||
/// <exception cref="ArgumentException">当输入格式无效时抛出</exception>
|
|
||||||
public static Color FromHex(this string hex)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(hex))
|
|
||||||
throw new ArgumentException("颜色字符串不能为空", nameof(hex));
|
|
||||||
|
|
||||||
// 移除前缀(如果有)
|
|
||||||
hex = hex.TrimStart('#');
|
|
||||||
if (hex.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
|
||||||
hex = hex.Substring(2);
|
|
||||||
|
|
||||||
// 根据长度解析不同格式
|
|
||||||
switch (hex.Length)
|
|
||||||
{
|
|
||||||
case 3: // RGB
|
|
||||||
return Color.FromRgb(
|
|
||||||
ParseComponent(hex[0], hex[0]),
|
|
||||||
ParseComponent(hex[1], hex[1]),
|
|
||||||
ParseComponent(hex[2], hex[2]));
|
|
||||||
|
|
||||||
case 4: // RGBA
|
|
||||||
return Color.FromArgb(
|
|
||||||
ParseComponent(hex[3], hex[3]),
|
|
||||||
ParseComponent(hex[0], hex[0]),
|
|
||||||
ParseComponent(hex[1], hex[1]),
|
|
||||||
ParseComponent(hex[2], hex[2]));
|
|
||||||
|
|
||||||
case 6: // RRGGBB
|
|
||||||
return Color.FromRgb(
|
|
||||||
ParseComponent(hex[0], hex[1]),
|
|
||||||
ParseComponent(hex[2], hex[3]),
|
|
||||||
ParseComponent(hex[4], hex[5]));
|
|
||||||
|
|
||||||
case 8: // RRGGBBAA
|
|
||||||
return Color.FromArgb(
|
|
||||||
ParseComponent(hex[6], hex[7]),
|
|
||||||
ParseComponent(hex[0], hex[1]),
|
|
||||||
ParseComponent(hex[2], hex[3]),
|
|
||||||
ParseComponent(hex[4], hex[5]));
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ArgumentException($"无效的十六进制颜色格式: {hex}", nameof(hex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析两个十六进制字符为一个字节值
|
|
||||||
/// </summary>
|
|
||||||
private static byte ParseComponent(char c1, char c2)
|
|
||||||
{
|
|
||||||
return byte.Parse(new string(new[] { c1, c2 }), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 将 Color 对象转换为十六进制字符串表示(默认格式: #RRGGBB)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="color">要转换的颜色</param>
|
|
||||||
/// <param name="includeAlpha">是否包含透明度通道</param>
|
|
||||||
/// <returns>十六进制颜色字符串</returns>
|
|
||||||
public static string ToHexString(this Color color, bool includeAlpha = false)
|
|
||||||
{
|
|
||||||
return includeAlpha
|
|
||||||
? $"#{color.A:X2}{color.R:X2}{color.G:X2}{color.B:X2}"
|
|
||||||
: $"#{color.R:X2}{color.G:X2}{color.B:X2}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
<UseWPF>true</UseWPF>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.ControlDevices\MegaRobo.ControlDevices.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.Entities\MegaRobo.C00225155.Entities.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="MegaRobo.Entities">
|
|
||||||
<HintPath>..\..\..\Common\MegaRobo.Common\MegaRobo.Entities\obj\Debug\net7.0\ref\MegaRobo.Entities.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.WpfInfrastructure">
|
|
||||||
<HintPath>bin\Debug\net7.0-windows\MegaRobo.WpfInfrastructure.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.DevicesModels
|
|
||||||
{
|
|
||||||
public abstract class DrainageFluidBaseProp
|
|
||||||
{
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "分液Z轴驱动位置")]
|
|
||||||
public uint za { get; set; } = 33700;
|
|
||||||
|
|
||||||
//33700 15100..33700 液体出现的绝对位置
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "离开液面时的绝对位置")]
|
|
||||||
public uint zb { get; set; } = 33700;
|
|
||||||
|
|
||||||
// 00000..20000 此参数根据所提供的步骤数定义下面的液体。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Default = 200, Descr = "液面跟随步长(Z轴驱动[增量])")]
|
|
||||||
public uint ze { get; set; } = 200;
|
|
||||||
|
|
||||||
// 00000..20000 容器底部的高度,从“zh”[增量]测量
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Default = 0, Descr = "容器底部的高度,从“zh”[增量]测量")]
|
|
||||||
public uint zk { get; set; }
|
|
||||||
|
|
||||||
// 00000..10000 容器底部部分此参数描述了管底部的几何形状(图11)。gx=10‘000为平底gx=0为圆锥形底部gx=6’180为圆底
|
|
||||||
[Numeric(Minimum = 0, Maximum = 10000, Default = 10000, Descr = "容器底部几何形状 gx = 10000为平底 0为圆锥形底部 6180为圆底")]
|
|
||||||
public uint gx { get; set; } = 10000;
|
|
||||||
|
|
||||||
//15100 15100..33700 此参数定义了容器底部的z形位置。它对应于最大的浸泡位置。如果LLD模式处于激活状态,则将搜索液位直到此位置(图12)。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "容器底部Z值")]
|
|
||||||
public uint zh { get; set; } = 15200;
|
|
||||||
|
|
||||||
//33700 15100..33700 结束遍历位置。在命令结尾处的横向位置。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "结束遍历位置")]
|
|
||||||
public uint zg { get; set; } = 33700;
|
|
||||||
|
|
||||||
// 0000..9999 运输空气量[增量]空气在吸入或分配结束时被吸入,并在接下来的分配步骤中自动作为额外的量再次分配。它受到尖端几何形状和液体蒸汽压的影响。防止在运输过程中产生液滴的形成。这个参数在移液挥发性物质时很有用。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Default = 200, Descr = "运输空气量[增量]")]
|
|
||||||
public uint dg { get; set; } = 200;
|
|
||||||
|
|
||||||
//public uint zq { get; set; } = 280;
|
|
||||||
// 000..999 吸入后在液体中停留的时间[1/10秒]此参数设置吸入后尖端或离开液体前在液体中停留的时间。在设置该参数时,考虑了尖端的几何形状和液体粘度。如果沉淀时间太短,液体没有足够的时间来填充尖端,一旦尖端离开液体,不需要的空气就会被吸入。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 999, Default = 10, Name = "ML", Index = 9, Descr = "吸入后在液体中停留的时间[1/10秒]")]
|
|
||||||
public uint to { get; set; } = 10;
|
|
||||||
|
|
||||||
//22350 00020..56000 流量,【增加量/秒】。该参数对应于吸入或分配期间的柱塞速度。流量是最关键的参数,受尖端几何形状,液体粘度、密度和蒸汽压力:小尖端开放->慢流速,高粘度->慢流速,高密度->慢流速,高蒸汽压->快速流速
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 22350, Name = "ML", Index = 10, Descr = "分液速度,流量,【增加量/秒】")]
|
|
||||||
public uint dv { get; set; } = 22350;
|
|
||||||
|
|
||||||
//5600 00000..56000 停止流量停止分配的柱塞的分配速度。如果等于“流量”,则柱塞突然停止而不减速。如果设置为最小值,柱塞的运动会逐渐减慢,直到停止。移液粘性液体如甘油时,建议逐步停止(缓慢停止流量)以完成分配。
|
|
||||||
//[Numeric(Minimum = 00, Maximum = 56000, Default = 5600, Name = "MH", Index = 21, Descr = "停止流量停止分配的柱塞的分配速度")]
|
|
||||||
[Numeric(Minimum = 00, Maximum = 56000, Default = 5600, Name = "ML", Index = 11, Descr = "停止流量,停止分配的柱塞的分配速度")]
|
|
||||||
public uint du { get; set; } = 5600;
|
|
||||||
|
|
||||||
//400 005..600 加速分配驱动器[1000增量/秒2]设置分配期间柱塞的加速度。需要控制流量切断。防止在尖端孔口处形成液滴
|
|
||||||
//[Numeric(Minimum = 5, Maximum = 600, Default = 400, Name = "MH", Index = 22, Descr = "加速分配驱动器[1000增量/秒2]")]
|
|
||||||
[Numeric(Minimum = 5, Maximum = 600, Default = 400, Name = "ML", Index = 12, Descr = "加速分配驱动器[1000增量/秒2]")]
|
|
||||||
public uint dr { get; set; } = 400;
|
|
||||||
|
|
||||||
//1000 00020..15000 交换速度[增量/秒]决定了抽吸或分配后尖端从液体中抽出的速度。该参数是根据液体的粘度和蒸汽压来选择的。使用较慢的速度可以防止粘性液体粘附在尖端的外部。
|
|
||||||
//[Numeric(Minimum = 20, Maximum = 15000, Default = 1000, Name = "MH", Index = 23, Descr = "抽吸或分配后尖端从液体中抽出的速度交换速度[增量/秒]")]
|
|
||||||
[Numeric(Minimum = 20, Maximum = 15000, Default = 5000, Name = "ML", Index = 13, Descr = "抽吸或分配后尖端从液体中抽出的速度交换速度[增量/秒]")]
|
|
||||||
public uint zu { get; set; } = 5000;
|
|
||||||
}
|
|
||||||
|
|
||||||
//分液(清空用ML,一吸多分用MH)
|
|
||||||
/// <summary>
|
|
||||||
/// 分液清空
|
|
||||||
/// </summary>
|
|
||||||
public class DrainageFluidByML : DrainageFluidBaseProp
|
|
||||||
{
|
|
||||||
public string CmdCode = "ML";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 一吸多分
|
|
||||||
/// </summary>
|
|
||||||
public class DrainageFluidByMH : DrainageFluidBaseProp
|
|
||||||
{
|
|
||||||
public string CmdCode = "MH";
|
|
||||||
|
|
||||||
// 000000..125400 分液量
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Default = 0, Name = "MH", Index = 1, Descr = "分液量")]
|
|
||||||
public uint db { get; set; }
|
|
||||||
|
|
||||||
// 000..999 停止后退容积【增量】分配后立即再次吸入该空气量,以突然切断液体流动(仅限喷射部分模式)。移液乙醇等挥发性液体时防止液滴形成。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 999, Default = 0, Name = "MH", Index = 2, Descr = "停止后退容积")]
|
|
||||||
public uint dd { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
//0..1 防液滴控制(ADC;0=关闭,1=开启)。在使用具有低粘度和高蒸汽压的移液液体时,应使用ADC,如乙醇。如果压力达到可能发生液滴的临界值,则尽可能多地抽出柱塞,以降低压力并防止液滴的形成。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Default = 0, Name = "MH", Index = 12, Descr = "防液滴控制(ADC;0=关闭,1=开启)")]
|
|
||||||
public uint bl { get; set; } = 1;
|
|
||||||
|
|
||||||
// 000000..125400 混合体积[增量】这是混合探头所需的体积。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Default = 0, Name = "MH", Index = 13, Descr = "混合体积[增量】这是混合探头所需的体积。")]
|
|
||||||
public uint dm { get; set; }
|
|
||||||
|
|
||||||
// 00..99 混合循环。混合循环次数。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 99, Default = 0, Name = "MH", Index = 14, Descr = "混合循环。混合循环次数。")]
|
|
||||||
public uint dn { get; set; }
|
|
||||||
|
|
||||||
// 00000..20000 表面进行混合体积的以下步骤。请参见“zd”参数的说明
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Default = 0, Name = "MH", Index = 15, Descr = "表面进行混合体积的以下步骤。请参见“zd”参数的说明")]
|
|
||||||
public uint zy { get; set; }
|
|
||||||
|
|
||||||
//22350 00020..56000 混合流量这是混合探头时的流量。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 0, Name = "MH", Index = 16, Descr = "混合流量这是混合探头时的流量。")]
|
|
||||||
public uint _do { get; set; } = 22350;
|
|
||||||
|
|
||||||
//0..1 设置搜索底部模式 (zm0 = off, zm1 = on)
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Default = 0, Name = "MH", Index = 17, Descr = "设置搜索底部模式 (zm0 = off, zm1 = on)")]
|
|
||||||
public uint zm { get; set; } = 0;
|
|
||||||
|
|
||||||
//186 000..500 开始高度底部搜索开始位置=参数zh+参数zx
|
|
||||||
[Numeric(Minimum = 0, Maximum = 500, Default = 0, Name = "MH", Index = 18, Descr = "开始高度底部搜索开始位置=参数zh+参数zx")]
|
|
||||||
public uint zx { get; set; } = 186;
|
|
||||||
|
|
||||||
// 0000..9999 底部搜索后的分配高度
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Default = 0, Name = "MH", Index = 19, Descr = "底部搜索后的分配高度")]
|
|
||||||
public uint zo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.DevicesModels
|
|
||||||
{
|
|
||||||
public class PropertyItem : ObservableObject
|
|
||||||
{
|
|
||||||
private object _value;
|
|
||||||
public object Value
|
|
||||||
{
|
|
||||||
get => _value;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (SetProperty(ref _value, value)) // SetProperty 会触发 PropertyChanged
|
|
||||||
{
|
|
||||||
// 值变化时,更新 SuckFluidProp 对应属性
|
|
||||||
PropertyInfo?.SetValue(TargetObject, Convert.ChangeType(value, Type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 其他属性(保持不变)
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
|
|
||||||
public Type Type { get; set; }
|
|
||||||
public NumericAttribute NumericAttribute { get; set; }
|
|
||||||
public object TargetObject { get; set; }
|
|
||||||
public PropertyInfo PropertyInfo { get; set; }
|
|
||||||
|
|
||||||
//// 通知属性变化
|
|
||||||
//public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
//protected void OnPropertyChanged([CallerMemberName] string propName = null)
|
|
||||||
//{
|
|
||||||
// PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,232 +0,0 @@
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.DevicesModels
|
|
||||||
{
|
|
||||||
public enum SuckMode
|
|
||||||
{
|
|
||||||
[Description("电容式")]
|
|
||||||
MA,
|
|
||||||
[Description("电压式")]
|
|
||||||
ME,
|
|
||||||
[Description("固定高度")]
|
|
||||||
MG,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DrainageMode
|
|
||||||
{
|
|
||||||
[Description("排空")]
|
|
||||||
ML,
|
|
||||||
[Description("一吸多分")]
|
|
||||||
MH,
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class SuckFluidBaseProp
|
|
||||||
{
|
|
||||||
// 000000-125400 吸液量
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Descr = "吸液量ul")]
|
|
||||||
public uint da { get; set; }
|
|
||||||
|
|
||||||
// 0000-9999 过度吸气量[增量]
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Descr = "过度吸气量")]
|
|
||||||
public uint dc { get; set; } = 100;
|
|
||||||
|
|
||||||
// 00000-20000 液面以下高度
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Descr = "吸液跟随下降高度")]
|
|
||||||
public uint zd { get; set; } = 200;
|
|
||||||
|
|
||||||
// 00000..20000 容器底部的高度
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Descr = "容器底部几何形状的高度 平底为 0 ")]
|
|
||||||
public uint zk { get; set; } = 0; //600
|
|
||||||
|
|
||||||
// 00000..10000 容器底部的部分。此参数描述了管底部的几何形状(图11)。gx=10‘000为平底gx=0为圆锥形底部gx=6’180为圆底。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 10000, Default =10000, Descr = "容器底部的部分 gx=10000为平底 0为圆锥形底部 6180为圆底")]
|
|
||||||
public uint gx { get; set; } = 10000; //6180;
|
|
||||||
|
|
||||||
//15200 15100..33700 容器底部的位置。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Descr = "容器底部位置")]
|
|
||||||
public uint zh { get; set; } = 15200;
|
|
||||||
|
|
||||||
//33700 15100..33700 LLD搜索位置
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "LLD搜索位置,吸液位置")]
|
|
||||||
public uint zc { get; set; } = 26000;
|
|
||||||
|
|
||||||
// 0000..9999 渗透深度增加了液体表面以下尖端的渗透深度。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Default =8, Descr = "浸入液面高度")]
|
|
||||||
public uint zi { get; set; } = 8U; //探入液面高度,Tip头进入液面
|
|
||||||
|
|
||||||
//33700 15100..33700 结束遍历位置。在命令结尾处的横向位置。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "结束遍历位置")]
|
|
||||||
public uint zg { get; set; } = 33700;
|
|
||||||
|
|
||||||
//0 000000..125400 排气空气量在吸入过程中首先吸收该空气量。它在分配结束时被吹掉。它受到液体粘度和蒸气压的影响。爆裂的体积有助于完全清空尖端
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Default = 0, Descr = "排气空气量在吸入过程中首先吸收该空气量")]
|
|
||||||
public uint df { get; set; } = 500;
|
|
||||||
|
|
||||||
//0 0000..9999 运输空气量[增量]空气在吸入或分配结束时被吸入,并在接下来的分配步骤中自动作为额外的量再次分配。它受到尖端几何形状和液体蒸汽压的影响。防止在运输过程中产生液滴的形成。这个参数在移液挥发性物质时很有用。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Descr = "转移空气量")]
|
|
||||||
public uint dg { get; set; } = 200;
|
|
||||||
|
|
||||||
//280 0000..9999 离开高度[增加*]高度超过液体表面,在此期间,宙斯驱动缓慢地穿透或离开液体。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Default = 280, Descr = "离开液面高度")]
|
|
||||||
public uint zq { get; set; } = 280;
|
|
||||||
|
|
||||||
// 000..999 吸入后的液体中沉淀时间[1/10秒]。该参数设置抽吸或离开液体前在液体中停留的时间。在设置该参数时,考虑了尖端的几何形状和液体粘度。如果沉淀时间太短,液体没有足够的时间来填充尖端,一旦尖端离开液体,不需要的空气就会被吸入。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 999, Descr = "吸入后的液体中沉淀时间[1/10秒]")]
|
|
||||||
public uint to { get; set; } = 10;
|
|
||||||
|
|
||||||
//0..1 吸气模式(dj0=简单,dj1=空杯)
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "吸气模式(dj0=简单,dj1=空杯)")]
|
|
||||||
public uint dj { get; set; } = 0;
|
|
||||||
|
|
||||||
//0..1 防液滴控制(ADC;0=关闭,1=开启)。在使用具有低粘度和高蒸汽压的移液液体时,应使用ADC,如乙醇。如果压力达到可能发生滴落的临界值,则尽可能多地抽出柱塞,以降低压力并防止液滴的形成。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "防液滴控制(ADC;0=关闭,1=开启)")]
|
|
||||||
public uint bl { get; set; } = 0;
|
|
||||||
|
|
||||||
//0..1 堵塞检测
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "堵塞检测")]
|
|
||||||
public uint gq { get; set; } = 0;
|
|
||||||
|
|
||||||
//1..4 CLLD灵敏度(1=非常高,高2=,3=培养基,低4=)。灵敏度可以调整到容器尺寸和要检测的液体体积(小体积->高灵敏度)。
|
|
||||||
//public uint cs ps {get;set;}
|
|
||||||
|
|
||||||
// 000000..125400 混合体积的增量。这是混合探针所需的体积。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Descr = "混合体积的增量")]
|
|
||||||
public uint dm { get; set; }
|
|
||||||
|
|
||||||
//00..99 混合循环。混合循环次数。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 99, Descr = "混合循环次数")]
|
|
||||||
public uint dn { get; set; }
|
|
||||||
|
|
||||||
// 00000..20000 表面进行混合体积的以下步骤。请参见“zd”参数的描述。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Descr = "表面进行混合体积的以下步骤")]
|
|
||||||
public uint zy { get; set; }
|
|
||||||
|
|
||||||
//22350 00020..56000 混合流量。这是探头混合时的流量。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 22350, Descr = "混合流量")]
|
|
||||||
public uint _do { get; set; } = 22350; //22350
|
|
||||||
|
|
||||||
//22350 00020..56000 该参数对应于吸入或分配期间的柱塞速度。流量是最关键的参数,受尖端几何形状,液体粘度、密度和蒸汽压力:小尖端开放->慢流速,高粘度->慢流速,高密度->慢流速,高蒸汽压->快速流速。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 22350, Descr = "吸入速度1,该参数对应于吸入或分配期间的柱塞速度")]
|
|
||||||
public uint dv { get; set; } = 22350;
|
|
||||||
|
|
||||||
//1000 00020..15000 交换速度[增量/秒]决定了抽吸或分配后尖端从液体中抽出的速度。该参数是根据液体的粘度和蒸汽压来选择的。使用较慢的速度可以防止粘性液体粘附在尖端的外部。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 15000, Default = 1000, Descr = "抽吸或分配后尖端从液体中抽出的速度交换速度[增量/秒]")]
|
|
||||||
public uint zu { get; set; } = 1000; // 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 通过电容式LLD在液体表面进行搜索的抽吸液体
|
|
||||||
/// </summary>
|
|
||||||
public class SuckFluidByMA : SuckFluidBaseProp
|
|
||||||
{
|
|
||||||
public string CmdCode => "MA";
|
|
||||||
|
|
||||||
//1..4 CLLD灵敏度(1=非常高,高2=,3=培养基,低4=)。灵敏度可以调整到容器尺寸和要检测的液体体积(小体积->高灵敏度)。
|
|
||||||
[Numeric(Minimum = 1, Maximum = 4, Default = 2, Descr = "CLLD灵敏度")]
|
|
||||||
public uint cs { get; set; } = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 通过压力式LLD在液体表面进行搜索的抽吸液体
|
|
||||||
/// </summary>
|
|
||||||
public class SuckFluidByME : SuckFluidBaseProp
|
|
||||||
{
|
|
||||||
public string CmdCode => "ME";
|
|
||||||
|
|
||||||
//1..4 pLLD灵敏度(1=非常高,高2=,3=一般,低4=)。灵敏度可以调整到容器尺寸和要检测的液体体积(小体积->高灵敏度)。
|
|
||||||
[Numeric(Minimum = 1, Maximum = 4, Default = 2, Descr = "pLLD灵敏度(压力探测灵敏度)")]
|
|
||||||
public uint ps { get; set; } = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 固定位置吸液
|
|
||||||
/// </summary>
|
|
||||||
public class SuckFluidByMG
|
|
||||||
{
|
|
||||||
public string CmdCode => "MG";
|
|
||||||
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Descr = "吸液量")]
|
|
||||||
public uint da { get; set; }
|
|
||||||
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999, Default =100, Descr = "过度吸气量")]
|
|
||||||
public uint dc { get; set; } = 100;
|
|
||||||
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "吸液时Z轴高度")]
|
|
||||||
public uint za { get; set; } = 33700;
|
|
||||||
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "离开液面时的绝对位置")]
|
|
||||||
public uint zb { get; set; } = 33700;
|
|
||||||
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Default = 200, Descr = "吸液跟随下降高度")]
|
|
||||||
public uint zd { get; set; } = 200;
|
|
||||||
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Default = 0, Descr = "容器尾部几何形状与底部的高度 平底为0")]
|
|
||||||
public uint zk { get; set; } = 0;
|
|
||||||
|
|
||||||
//00000..10000 容器底部的部分。此参数描述了管底部的几何形状(图11)。gx=10‘000为平底gx=0为圆锥形底部gx=6’180为圆底。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 10000,Default =10000, Descr = "容器底部的部分 gx=10000为平底 0为圆锥形底部 6180为圆底")]
|
|
||||||
public uint gx { get; set; } = 10000; //6180;
|
|
||||||
|
|
||||||
//15200 15100..33700 容器底部的位置。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Descr = "容器底部位置")]
|
|
||||||
public uint zh { get; set; } = 15200;
|
|
||||||
|
|
||||||
//33700 15100..33700 结束遍历位置。在命令结尾处的横向位置。
|
|
||||||
[Numeric(Minimum = 15200, Maximum = 33700, Default = 33700, Descr = "结束遍历位置")]
|
|
||||||
public uint zg { get; set; } = 33700;
|
|
||||||
|
|
||||||
//0 000000..125400 排气空气量在吸入过程中首先吸收该空气量。它在分配结束时被吹掉。它受到液体粘度和蒸气压的影响。爆裂的体积有助于完全清空尖端
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Default = 500, Descr = "排气空气量在吸入过程中首先吸收该空气量")]
|
|
||||||
public uint df { get; set; } = 500;
|
|
||||||
|
|
||||||
//0 0000..9999 运输空气量[增量]空气在吸入或分配结束时被吸入,并在接下来的分配步骤中自动作为额外的量再次分配。它受到尖端几何形状和液体蒸汽压的影响。防止在运输过程中产生液滴的形成。这个参数在移液挥发性物质时很有用。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 9999,Default =200, Descr = "转移空气量")]
|
|
||||||
public uint dg { get; set; } = 200;
|
|
||||||
|
|
||||||
// 000..999 吸入后的液体中沉淀时间[1/10秒]。该参数设置抽吸或离开液体前在液体中停留的时间。在设置该参数时,考虑了尖端的几何形状和液体粘度。如果沉淀时间太短,液体没有足够的时间来填充尖端,一旦尖端离开液体,不需要的空气就会被吸入。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 999,Default =10, Descr = "吸入后的液体中沉淀时间[1/10秒]")]
|
|
||||||
public uint to { get; set; } = 10;
|
|
||||||
|
|
||||||
//0..1 吸气模式(dj0=简单,dj1=空杯)
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "吸气模式(dj0=简单,dj1=空杯)")]
|
|
||||||
public uint dj { get; set; } = 0;
|
|
||||||
|
|
||||||
//0..1 防液滴控制(ADC;0=关闭,1=开启)。在使用具有低粘度和高蒸汽压的移液液体时,应使用ADC,如乙醇。如果压力达到可能发生滴落的临界值,则尽可能多地抽出柱塞,以降低压力并防止液滴的形成。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "防液滴控制(ADC;0=关闭,1=开启)")]
|
|
||||||
public uint bl { get; set; } = 0;
|
|
||||||
|
|
||||||
//0..1 堵塞检测
|
|
||||||
[Numeric(Minimum = 0, Maximum = 1, Descr = "堵塞检测")]
|
|
||||||
public uint gq { get; set; }
|
|
||||||
|
|
||||||
// 000000..125400 混合体积的增量。这是混合探针所需的体积。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 125400, Descr = "混合体积的增量")]
|
|
||||||
public uint dm { get; set; }
|
|
||||||
|
|
||||||
//00..99 混合循环。混合循环次数。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 99, Descr = "混合循环次数")]
|
|
||||||
public uint dn { get; set; }
|
|
||||||
|
|
||||||
// 00000..20000 表面进行混合体积的以下步骤。请参见“zd”参数的描述。
|
|
||||||
[Numeric(Minimum = 0, Maximum = 20000, Descr = "表面进行混合体积的以下步骤")]
|
|
||||||
public uint zy { get; set; }
|
|
||||||
|
|
||||||
//22350 00020..56000 混合流量。这是探头混合时的流量。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 22350, Descr = "混合流量")]
|
|
||||||
public uint _do { get; set; } = 22350; //22350
|
|
||||||
|
|
||||||
//22350 00020..56000 该参数对应于吸入或分配期间的柱塞速度。流量是最关键的参数,受尖端几何形状,液体粘度、密度和蒸汽压力:小尖端开放->慢流速,高粘度->慢流速,高密度->慢流速,高蒸汽压->快速流速。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 56000, Default = 22350, Descr = "该参数对应于吸入或分配期间的柱塞速度")]
|
|
||||||
public uint dv { get; set; } = 22350;
|
|
||||||
|
|
||||||
//1000 00020..15000 交换速度[增量/秒]决定了抽吸或分配后尖端从液体中抽出的速度。该参数是根据液体的粘度和蒸汽压来选择的。使用较慢的速度可以防止粘性液体粘附在尖端的外部。
|
|
||||||
[Numeric(Minimum = 20, Maximum = 15000, Default = 5000, Descr = "抽吸或分配后尖端从液体中抽出的速度交换速度[增量/秒]")]
|
|
||||||
public uint zu { get; set; } = 5000; // 2000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,438 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using Microsoft.Win32;
|
|
||||||
using Newtonsoft;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public class File_Operator
|
|
||||||
{
|
|
||||||
private static readonly object _lock = new object();
|
|
||||||
|
|
||||||
public static T Xml_Serialize<T>(string strFile, bool bSave, T param, out bool bReadOK) where T : class
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
bReadOK = true;
|
|
||||||
XmlSerializer xs = null;
|
|
||||||
|
|
||||||
// 针对 BaseBottleBox 集合,显式指定所有派生类
|
|
||||||
if (typeof(T) == typeof(ProjectProperty))
|
|
||||||
{
|
|
||||||
Type[] extraTypes = new Type[]
|
|
||||||
{
|
|
||||||
typeof(BaseBottleBox),
|
|
||||||
typeof(SampleBottleBoxModel),
|
|
||||||
typeof(SourceLiquidBottleBoxModel),
|
|
||||||
typeof(SourcePowderBottleBoxModel),
|
|
||||||
typeof(SourcePowderBottleBoxModel_125ml),
|
|
||||||
typeof(TipBoxModel),
|
|
||||||
typeof(SourcePowderBottleModel),
|
|
||||||
typeof(TipHeadItem)
|
|
||||||
};
|
|
||||||
xs = new XmlSerializer(typeof(ProjectProperty), extraTypes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xs = new XmlSerializer(param.GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 使用 using 自动释放流(避免资源泄漏)
|
|
||||||
if (bSave)
|
|
||||||
{
|
|
||||||
using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
||||||
{
|
|
||||||
xs.Serialize(stream, param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (File.Exists(strFile))
|
|
||||||
{
|
|
||||||
using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read))
|
|
||||||
{
|
|
||||||
param = xs.Deserialize(stream) as T;
|
|
||||||
}
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 文件不存在时,先创建并序列化默认值
|
|
||||||
using (Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read))
|
|
||||||
{
|
|
||||||
xs.Serialize(stream, param);
|
|
||||||
}
|
|
||||||
// 重新读取
|
|
||||||
using (Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read))
|
|
||||||
{
|
|
||||||
param = xs.Deserialize(stream) as T;
|
|
||||||
}
|
|
||||||
return param;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
bReadOK = false;
|
|
||||||
MessageBox.Show($"序列化失败:{ex.Message}\n{ex.StackTrace}", "错误");
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// XML文件读写
|
|
||||||
/// 保存配置参数 bReadOK==false为发生异常
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">类类型</typeparam>
|
|
||||||
/// <param name="strFile">完整文件路径名</param>
|
|
||||||
/// <param name="bSave">true:保存;false:读取</param>
|
|
||||||
/// <param name="param">要进行序列化或反序列化的对象实例</param>
|
|
||||||
/// <param name="bReadOK">是否读写成功,有异常</param>
|
|
||||||
/// <returns>读取的数据</returns>
|
|
||||||
//public static T Xml_Serialize<T>(string strFile, bool bSave, T param, out bool bReadOK) where T : class
|
|
||||||
//{
|
|
||||||
// lock (_lock)
|
|
||||||
// {
|
|
||||||
// bReadOK = true;
|
|
||||||
// XmlSerializer xs = new XmlSerializer(param.GetType());
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (bSave)
|
|
||||||
// {
|
|
||||||
// //创建一个 FileStream 对象,以 FileMode.Create 模式打开文件,用于写入数据。
|
|
||||||
// //使用 xs.Serialize 方法将 param 对象序列化为 XML 数据,并写入文件。
|
|
||||||
// //关闭文件流。
|
|
||||||
// Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);
|
|
||||||
// xs.Serialize(stream, param);
|
|
||||||
// stream.Close();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// //检查文件是否存在。
|
|
||||||
// //如果文件存在,创建一个 FileStream 对象,以 FileMode.Open 模式打开文件,用于读取数据。
|
|
||||||
// //使用 xs.Deserialize 方法将文件中的 XML 数据反序列化为 T 类型的对象,并赋值给 param。
|
|
||||||
// //关闭文件流,并返回反序列化后的对象。
|
|
||||||
|
|
||||||
// if (File.Exists(strFile))
|
|
||||||
// {
|
|
||||||
// Stream stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
// param = xs.Deserialize(stream) as T;
|
|
||||||
// stream.Close();
|
|
||||||
// return param;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// //如果文件不存在,先创建一个 FileStream 对象,以 FileMode.Create 模式打开文件,将 param 对象序列化为 XML 数据并写入文件。
|
|
||||||
// //再次打开文件,读取其中的 XML 数据进行反序列化,并返回反序列化后的对象。
|
|
||||||
// Stream stream = new FileStream(strFile, FileMode.Create, FileAccess.Write, FileShare.Read);
|
|
||||||
// xs.Serialize(stream, param);
|
|
||||||
// stream.Close();
|
|
||||||
|
|
||||||
// stream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
||||||
// param = xs.Deserialize(stream) as T;
|
|
||||||
// stream.Close();
|
|
||||||
// return param;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// bReadOK = false;
|
|
||||||
// MessageBox.Show(ex.Message);
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 通过文件名寻找同目录下的其他同类型文件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="file">文件的绝对路径名</param>
|
|
||||||
public static List<string> GetFile(string file)
|
|
||||||
{
|
|
||||||
List<string> listFile = new List<string>();
|
|
||||||
if (!string.IsNullOrEmpty(file) && File.Exists(file))
|
|
||||||
{
|
|
||||||
int index = file.LastIndexOf("\\");
|
|
||||||
if (-1 == index) return null;
|
|
||||||
string path = file.Substring(0, index);//文件所在文件夹路径
|
|
||||||
string name = file.Substring(index);//文件名
|
|
||||||
string postfix = "";//取出后缀名
|
|
||||||
if (name.Contains("."))
|
|
||||||
{
|
|
||||||
postfix = name.Substring(name.LastIndexOf('.'));//例: .txt
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
string[] files = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
files = Directory.GetFiles(path);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show(ex.Message);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
foreach (var item in files)
|
|
||||||
{
|
|
||||||
int nIndex = item.IndexOf(postfix);
|
|
||||||
if (nIndex != -1)
|
|
||||||
{
|
|
||||||
listFile.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return listFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region 对注册表进行读写
|
|
||||||
//public static void CreatRegistryPath(string strPathName)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistryKey key = Registry.LocalMachine;
|
|
||||||
// //RegistryKey software = key.CreateSubKey("software\\test");
|
|
||||||
// RegistryKey software = key.CreateSubKey("software\\" + strPathName);
|
|
||||||
// key.Close();
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("对注册表创建路径时出现异常!" + ex.Message);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static void DeleteRegistryPath(string strPathName)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistryKey key = Registry.LocalMachine;
|
|
||||||
// //key.DeleteSubKey("software\\test", true);
|
|
||||||
// key.DeleteSubKey("software\\" + strPathName, true);
|
|
||||||
// key.Close();
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("对注册表删除路径时出现异常!" + ex.Message);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static void SetRegistryValue(string strPathName, string strKey, string strValue)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistryKey key = Registry.LocalMachine;
|
|
||||||
// RegistryKey software = key.OpenSubKey("software\\" + strPathName, true);
|
|
||||||
// //software.SetValue("test", "博客园");
|
|
||||||
// software.SetValue(strKey, strValue);
|
|
||||||
// key.Close();
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("对注册表设置键值时出现异常!" + ex.Message);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static string GetRegistryValue(string strPathName, string strKey)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistryKey Key = Registry.LocalMachine;
|
|
||||||
// RegistryKey myreg = Key.OpenSubKey("software\\" + strPathName, true);
|
|
||||||
// //info = myreg.GetValue("test").ToString();
|
|
||||||
// string strValue = myreg.GetValue(strKey).ToString();
|
|
||||||
// myreg.Close();
|
|
||||||
// return strValue;
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("对注册表获取值时出现异常!" + ex.Message);
|
|
||||||
// return "";
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public static void DeleteRegistryKey(string strPathName, string strKey)
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// RegistryKey delKey = Registry.LocalMachine.OpenSubKey("Software\\" + strPathName, true);
|
|
||||||
// //delKey.DeleteValue("test");
|
|
||||||
// delKey.DeleteValue(strKey);
|
|
||||||
// delKey.Close();
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// MessageBox.Show("对注册表删除键值时出现异常!" + ex.Message);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 深度拷贝
|
|
||||||
public static T DeepCopy<T>(T obj)
|
|
||||||
{
|
|
||||||
if (obj == null) return default;
|
|
||||||
//var json = JsonConvert.SerializeObject(obj);
|
|
||||||
//return JsonConvert.DeserializeObject<T>(json);
|
|
||||||
|
|
||||||
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
|
|
||||||
string json = JsonConvert.SerializeObject(obj, settings);
|
|
||||||
return JsonConvert.DeserializeObject<T>(json, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("弃用,使用上面的DeepCopy方法")]
|
|
||||||
public static T DeepCopy_1<T>(T obj)
|
|
||||||
{
|
|
||||||
if (obj == null) return default;
|
|
||||||
|
|
||||||
Type actualType = obj.GetType();
|
|
||||||
|
|
||||||
// 处理值类型和字符串
|
|
||||||
// 处理值类型和字符串
|
|
||||||
if (actualType.IsValueType || actualType == typeof(string))
|
|
||||||
return obj;
|
|
||||||
|
|
||||||
// 处理数组
|
|
||||||
if (actualType.IsArray)
|
|
||||||
{
|
|
||||||
var elementType = typeof(T).GetElementType();
|
|
||||||
var sourceArray = (Array)(object)obj;
|
|
||||||
var copiedArray = Array.CreateInstance(elementType, sourceArray.Length);
|
|
||||||
for (int i = 0; i < sourceArray.Length; i++)
|
|
||||||
{
|
|
||||||
copiedArray.SetValue(DeepCopy((dynamic)sourceArray.GetValue(i)), i);
|
|
||||||
}
|
|
||||||
return (T)(object)copiedArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理集合(如 List, ObservableCollection)
|
|
||||||
// 处理集合(优先直接创建目标类型,避免冗余转换)
|
|
||||||
if (typeof(IEnumerable).IsAssignableFrom(actualType) && actualType != typeof(string))
|
|
||||||
{
|
|
||||||
return DeepCopyCollection<T>(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理普通对象(核心修改)
|
|
||||||
// 关键修改2:按“实际类型”创建实例(而非 T 的声明类型)
|
|
||||||
object copy = Activator.CreateInstance(actualType);
|
|
||||||
// 关键修改3:拷贝所有字段(包括私有字段+派生类特有字段)
|
|
||||||
FieldInfo[] fields = actualType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
|
|
||||||
foreach (var field in fields)
|
|
||||||
{
|
|
||||||
if (field.IsStatic) continue; // 跳过静态字段
|
|
||||||
|
|
||||||
var value = field.GetValue(obj);
|
|
||||||
// 递归深拷贝字段值(保持原逻辑)
|
|
||||||
var copiedValue = DeepCopy((dynamic)value);
|
|
||||||
field.SetValue(copy, copiedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 强制转换为 T(因为实际类型是 T 的派生类,转换安全)
|
|
||||||
return (T)copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 专门处理 ObservableCollection 类型属性(支持只读属性)
|
|
||||||
/// </summary>
|
|
||||||
private static void DeepCopyObservableCollectionProperty(PropertyInfo property, object sourceObj, object targetObj)
|
|
||||||
{
|
|
||||||
// 获取源集合和元素类型
|
|
||||||
var sourceCollection = property.GetValue(sourceObj) as IEnumerable;
|
|
||||||
var elementType = property.PropertyType.GetGenericArguments()[0];
|
|
||||||
|
|
||||||
// 创建新的 ObservableCollection 实例(匹配原属性类型)
|
|
||||||
var targetCollection = Activator.CreateInstance(property.PropertyType) as IList;
|
|
||||||
if (targetCollection == null)
|
|
||||||
throw new InvalidOperationException($"无法创建 {property.PropertyType.Name} 实例");
|
|
||||||
|
|
||||||
// 深拷贝集合元素并添加到新集合
|
|
||||||
foreach (var item in sourceCollection)
|
|
||||||
{
|
|
||||||
var copiedItem = DeepCopy((dynamic)item);
|
|
||||||
targetCollection.Add(copiedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 给目标对象赋值:可写属性直接 SetValue,只读属性通过底层字段赋值
|
|
||||||
if (property.CanWrite)
|
|
||||||
{
|
|
||||||
property.SetValue(targetObj, targetCollection);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 匹配只读属性的底层字段(常见命名规范:_propertyName 或 m_propertyName)
|
|
||||||
var fieldName = $"_{char.ToLower(property.Name[0])}{property.Name.Substring(1)}";
|
|
||||||
var field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
|
|
||||||
// 若未匹配到,尝试 mPropertyName 规范
|
|
||||||
if (field == null)
|
|
||||||
{
|
|
||||||
fieldName = $"m{property.Name}";
|
|
||||||
field = targetObj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field != null && field.FieldType == property.PropertyType)
|
|
||||||
{
|
|
||||||
field.SetValue(targetObj, targetCollection);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"无法给只读属性 {property.DeclaringType.Name}.{property.Name} 赋值,请检查字段命名(预期:{fieldName})");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 优化集合深拷贝:直接创建目标类型集合,避免 List 中转
|
|
||||||
/// </summary>
|
|
||||||
private static T DeepCopyCollection<T>(T sourceCollection)
|
|
||||||
{
|
|
||||||
var sourceType = typeof(T);
|
|
||||||
var elementType = sourceType.IsGenericType ? sourceType.GetGenericArguments()[0] : typeof(object);
|
|
||||||
|
|
||||||
// 直接创建目标类型的集合实例(如 ObservableCollection<SampleBottleModel>)
|
|
||||||
var targetCollection = Activator.CreateInstance(sourceType) as IList;
|
|
||||||
if (targetCollection == null)
|
|
||||||
throw new InvalidOperationException($"无法创建集合类型 {sourceType.Name} 实例");
|
|
||||||
|
|
||||||
// 深拷贝每个元素并添加到新集合
|
|
||||||
foreach (var item in (IEnumerable)sourceCollection)
|
|
||||||
{
|
|
||||||
var copiedItem = DeepCopy((dynamic)item);
|
|
||||||
targetCollection.Add(copiedItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (T)targetCollection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ObservableCollection<T> DeepCopyObservableCollection<T>(ObservableCollection<T> source)
|
|
||||||
{
|
|
||||||
// 序列化为 JSON 字符串
|
|
||||||
var json = JsonConvert.SerializeObject(source);
|
|
||||||
// 从 JSON 字符串反序列化为新对象
|
|
||||||
return JsonConvert.DeserializeObject<ObservableCollection<T>>(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
public class UseLiquidBottle
|
|
||||||
{
|
|
||||||
public BaseBottleBox liquidbottleFixture { get; set; } = null;
|
|
||||||
public SourceLiquidBottleModel liquidbottle { get; set; } = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public class ObstructFlag
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 命名
|
|
||||||
/// </summary>
|
|
||||||
public string strName = "功能描述";
|
|
||||||
/// <summary>
|
|
||||||
/// true/false
|
|
||||||
/// </summary>
|
|
||||||
public bool flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
using Common.DevicesModels;
|
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Ink;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class ProjectProperty : ObservableObject
|
|
||||||
{
|
|
||||||
private SampleBottleTypeEnum sampleBottleType = SampleBottleTypeEnum._5mL;
|
|
||||||
public SampleBottleTypeEnum SampleBottleType
|
|
||||||
{
|
|
||||||
get => sampleBottleType;
|
|
||||||
set => SetProperty(ref sampleBottleType, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<BaseBottleBox> _tansferArea = new ObservableCollection<BaseBottleBox>();
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站 7个传送工装位置
|
|
||||||
/// </summary>
|
|
||||||
[XmlArray("TransferArea")] // 序列化后的XML节点名
|
|
||||||
[XmlArrayItem("BaseBottleBox", Type = typeof(BaseBottleBox))] // 基类元素
|
|
||||||
[XmlArrayItem("SampleBottleBoxModel", Type = typeof(SampleBottleBoxModel))] // 派生类元素
|
|
||||||
[XmlArrayItem("SourceLiquidBottleBoxModel", Type = typeof(SourceLiquidBottleBoxModel))]
|
|
||||||
[XmlArrayItem("SourcePowderBottleBoxModel", Type = typeof(SourcePowderBottleBoxModel))]
|
|
||||||
[XmlArrayItem("SourcePowderBottleBoxModel_125ml", Type = typeof(SourcePowderBottleBoxModel_125ml))]
|
|
||||||
[XmlArrayItem("TipBoxModel", Type = typeof(TipBoxModel))]
|
|
||||||
public ObservableCollection<BaseBottleBox> TransferArea
|
|
||||||
{
|
|
||||||
get => _tansferArea;
|
|
||||||
set => SetProperty(ref _tansferArea, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<BaseBottleBox> _fixtureCacheArea=new ObservableCollection<BaseBottleBox>();
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站8个治具缓存区 ,目前2,6由于干涉取消,但是程序里还保留
|
|
||||||
/// </summary>
|
|
||||||
[XmlArray("FixtureCacheArea")] // 序列化后的XML节点名
|
|
||||||
[XmlArrayItem("BaseBottleBox", Type = typeof(BaseBottleBox))] // 基类元素
|
|
||||||
[XmlArrayItem("SampleBottleBoxModel", Type = typeof(SampleBottleBoxModel))] // 派生类元素
|
|
||||||
[XmlArrayItem("SourceLiquidBottleBoxModel", Type = typeof(SourceLiquidBottleBoxModel))]
|
|
||||||
[XmlArrayItem("SourcePowderBottleBoxModel", Type = typeof(SourcePowderBottleBoxModel))]
|
|
||||||
[XmlArrayItem("SourcePowderBottleBoxModel_125ml", Type = typeof(SourcePowderBottleBoxModel_125ml))]
|
|
||||||
[XmlArrayItem("TipBoxModel", Type = typeof(TipBoxModel))]
|
|
||||||
public ObservableCollection<BaseBottleBox> FixtureCacheArea
|
|
||||||
{
|
|
||||||
get => _fixtureCacheArea;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _fixtureCacheArea, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<SourcePowderBottleModel> powderheadcacheArea = new ObservableCollection<SourcePowderBottleModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站粉末头缓存区 10个位置
|
|
||||||
/// </summary>
|
|
||||||
[XmlArray("PowderHeaderCacheArea")]
|
|
||||||
[XmlArrayItem("SourcePowderBottleModel")]
|
|
||||||
public ObservableCollection<SourcePowderBottleModel> PowderHeaderCacheArea
|
|
||||||
{
|
|
||||||
get { return powderheadcacheArea; }
|
|
||||||
set { SetProperty(ref powderheadcacheArea, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<TipBoxModel> tipHeadArea = new ObservableCollection<TipBoxModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站 TIP头放置区域 3个位置
|
|
||||||
/// </summary>
|
|
||||||
[XmlArray("TipHeadArea")]
|
|
||||||
[XmlArrayItem("TipBoxModel")]
|
|
||||||
public ObservableCollection<TipBoxModel> TipHeadArea
|
|
||||||
{
|
|
||||||
get { return tipHeadArea; }
|
|
||||||
set { SetProperty(ref tipHeadArea, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool bnouseBS;
|
|
||||||
/// <summary>
|
|
||||||
/// 不启用BS false:启用BS true:不启用BS
|
|
||||||
/// </summary>
|
|
||||||
public bool bNoUseBS
|
|
||||||
{
|
|
||||||
get { return bnouseBS; }
|
|
||||||
set { SetProperty(ref bnouseBS, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 反应工站料架
|
|
||||||
|
|
||||||
private List<_2mlBottleBox_Outer> _2mlbottlebox_outer = new List<_2mlBottleBox_Outer>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第五层的 2ml外瓶工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<_2mlBottleBox_Outer> Rack_2mlBottleBox_OuterList
|
|
||||||
{
|
|
||||||
get { return _2mlbottlebox_outer; }
|
|
||||||
set { _2mlbottlebox_outer = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<_2mlBottleBox_Inner> _2mlbottlebox_inner = new List<_2mlBottleBox_Inner>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第四层的 2ml滤芯工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<_2mlBottleBox_Inner> Rack_2mlBottleBox_InnerList
|
|
||||||
{
|
|
||||||
get { return _2mlbottlebox_inner; }
|
|
||||||
set { _2mlbottlebox_inner = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SampleBottleBoxModel> _5mlsamplebottlebox = new List<SampleBottleBoxModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第三层的 5ml样品工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<SampleBottleBoxModel> Rack_5mlSampleBottleBoxList
|
|
||||||
{
|
|
||||||
get { return _5mlsamplebottlebox; }
|
|
||||||
set { _5mlsamplebottlebox = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SampleBottleBoxModel> _12mlsamplebottlebox = new List<SampleBottleBoxModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第二层的 12ml样品工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<SampleBottleBoxModel> Rack_12mlSampleBottleBoxList
|
|
||||||
{
|
|
||||||
get { return _12mlsamplebottlebox; }
|
|
||||||
set { _12mlsamplebottlebox = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<TipBoxModel> _tipbox = new List<TipBoxModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第一层的 Tip工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<TipBoxModel> Rack_TipBoxList
|
|
||||||
{
|
|
||||||
get { return _tipbox; }
|
|
||||||
set { _tipbox = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<SourceLiquidBottleBoxModel> sourceLiquidBottleBoxs = new List<SourceLiquidBottleBoxModel>();
|
|
||||||
/// <summary>
|
|
||||||
/// 料架上第一层的 原液工装集合
|
|
||||||
/// </summary>
|
|
||||||
public List<SourceLiquidBottleBoxModel> Rack_SourceLiquidBottlesBoxList
|
|
||||||
{
|
|
||||||
get { return sourceLiquidBottleBoxs; }
|
|
||||||
set { sourceLiquidBottleBoxs = value; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private string lastOpenProject = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭软件最后一次打开的项目
|
|
||||||
/// </summary>
|
|
||||||
public string LastOpenProject
|
|
||||||
{
|
|
||||||
get => lastOpenProject;
|
|
||||||
set => SetProperty(ref lastOpenProject, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string nowOpenProjectFile;
|
|
||||||
public string NowOpenProjectFile
|
|
||||||
{
|
|
||||||
get => nowOpenProjectFile;
|
|
||||||
set => SetProperty(ref nowOpenProjectFile, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Dose_ct = string.Empty;
|
|
||||||
[XmlIgnore]
|
|
||||||
public string Dose_CT
|
|
||||||
{
|
|
||||||
get => Dose_ct;
|
|
||||||
set => SetProperty(ref Dose_ct, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string react_ct = string.Empty;
|
|
||||||
[XmlIgnore]
|
|
||||||
public string React_CT
|
|
||||||
{
|
|
||||||
get => react_ct;
|
|
||||||
set => SetProperty(ref react_ct, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProjectProperty()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
using MegaRobo.C00225155.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Media.Animation;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public class StationProperty
|
|
||||||
{
|
|
||||||
private CancellationTokenSource cancellation = new CancellationTokenSource();
|
|
||||||
/// <summary>
|
|
||||||
/// 工站线程取消标志
|
|
||||||
/// </summary>
|
|
||||||
public CancellationTokenSource cancellationToken
|
|
||||||
{
|
|
||||||
get { return cancellation; }
|
|
||||||
set { cancellation = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消 暂停标志
|
|
||||||
/// </summary>
|
|
||||||
public ManualResetEvent ManualResetEvent { get; set; } = new ManualResetEvent(true);
|
|
||||||
|
|
||||||
//private Task stationtask;
|
|
||||||
//public Task stationTask
|
|
||||||
//{
|
|
||||||
// get { return stationtask; }
|
|
||||||
// set { stationtask = value; }
|
|
||||||
//}
|
|
||||||
|
|
||||||
private int stationnum;
|
|
||||||
/// <summary>
|
|
||||||
/// 工站编号
|
|
||||||
/// </summary>
|
|
||||||
public int StationNum
|
|
||||||
{
|
|
||||||
get { return stationnum; }
|
|
||||||
set { stationnum = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string stationname = string.Empty;
|
|
||||||
public string StationName
|
|
||||||
{
|
|
||||||
get { return stationname; }
|
|
||||||
set { stationname = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否启动按钮触发
|
|
||||||
/// </summary>
|
|
||||||
public bool bStartButtonTrigger = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否停止按钮触发
|
|
||||||
/// </summary>
|
|
||||||
public bool bStopButtonTrigger = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否复位按钮触发
|
|
||||||
/// </summary>
|
|
||||||
public bool bResetButtonTrigger = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工站是否运行结束
|
|
||||||
/// </summary>
|
|
||||||
public bool bRunFinish = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工站是否已经复位,只有复位过才能启动
|
|
||||||
/// </summary>
|
|
||||||
public bool bHaveReset = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工站计时CT
|
|
||||||
/// <summary>
|
|
||||||
public Stopwatch CTWatch = new Stopwatch();
|
|
||||||
|
|
||||||
public DeviceStatus deviceStatus = DeviceStatus.Idel;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 阻塞信号集合
|
|
||||||
/// </summary>
|
|
||||||
public ConcurrentDictionary<string,ObstructFlag> ObstructFlagList { get; set; } = new ConcurrentDictionary<string, ObstructFlag>();
|
|
||||||
|
|
||||||
//private CancellationTokenSource cancellationUpDn = new CancellationTokenSource();
|
|
||||||
///// <summary>
|
|
||||||
///// 上下工装线程取消标志(不控制工站线程)
|
|
||||||
///// </summary>
|
|
||||||
//public CancellationTokenSource cancellationTokenUpDn
|
|
||||||
//{
|
|
||||||
// get { return cancellationUpDn; }
|
|
||||||
// set { cancellationUpDn = value; }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
///// <summary>
|
|
||||||
///// 取样接口
|
|
||||||
///// </summary>
|
|
||||||
//public interface ISamplingModel
|
|
||||||
//{
|
|
||||||
// double Height { get; set; }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 穿刺取样模型
|
|
||||||
///// </summary>
|
|
||||||
//[Serializable]
|
|
||||||
//public class PunctureSamplingModel : ObservableObject, ISamplingModel
|
|
||||||
//{
|
|
||||||
|
|
||||||
// private double height;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 取样高度
|
|
||||||
// /// </summary>
|
|
||||||
// public double Height
|
|
||||||
// {
|
|
||||||
// get { return height; }
|
|
||||||
// set { SetProperty(ref height, value); }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 开盖取样模型
|
|
||||||
///// </summary>
|
|
||||||
//[Serializable]
|
|
||||||
//public class OpenLidSamplingModel : ObservableObject, ISamplingModel
|
|
||||||
//{
|
|
||||||
// private double intervalTime;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 取样间隔时间,单位min
|
|
||||||
// /// </summary>
|
|
||||||
// public double IntervalTime
|
|
||||||
// {
|
|
||||||
// get { return intervalTime; }
|
|
||||||
// set { SetProperty(ref intervalTime, value); }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private double height;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 取样高度
|
|
||||||
// /// </summary>
|
|
||||||
// public double Height
|
|
||||||
// {
|
|
||||||
// get { return height; }
|
|
||||||
// set { SetProperty(ref height, value); }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private int count;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 取样次数
|
|
||||||
// /// </summary>
|
|
||||||
// public int Count
|
|
||||||
// {
|
|
||||||
// get { return count; }
|
|
||||||
// set { SetProperty(ref count, value); }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
public class SampleBottleTemperatureModel : ObservableObject
|
|
||||||
{
|
|
||||||
private double rate = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 震荡频率
|
|
||||||
/// </summary>
|
|
||||||
public double Speed
|
|
||||||
{
|
|
||||||
get { return rate; }
|
|
||||||
set => SetProperty(ref rate, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double time = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 时间(设备到目标温度后,再开始算时间),单位是min
|
|
||||||
/// </summary>
|
|
||||||
public double Time
|
|
||||||
{
|
|
||||||
get => time;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref time, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetTemperature = 150;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标温度
|
|
||||||
/// </summary>
|
|
||||||
public double TargetTemperature
|
|
||||||
{
|
|
||||||
get => targetTemperature;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref targetTemperature, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,354 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace Common.Models
|
|
||||||
{
|
|
||||||
public enum FunctionTypeEnum
|
|
||||||
{
|
|
||||||
[Description("添加液体原料")]
|
|
||||||
加液体原料,
|
|
||||||
[Description("添加固体原料")]
|
|
||||||
加固体原料,
|
|
||||||
[Description("震荡摇匀")]
|
|
||||||
震荡摇匀,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class MaterialDoseFunctionFlow : ObservableObject
|
|
||||||
{
|
|
||||||
private bool bisdosefinish = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否配置完成
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDoseFinish
|
|
||||||
{
|
|
||||||
get { return bisdosefinish; }
|
|
||||||
set { SetProperty(ref bisdosefinish, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private FunctionTypeEnum functionType = FunctionTypeEnum.加液体原料;
|
|
||||||
public FunctionTypeEnum FunctionFlowType
|
|
||||||
{
|
|
||||||
get => functionType;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref functionType, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string useMaterialName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 使用的试剂名称
|
|
||||||
/// </summary>
|
|
||||||
public string UseMaterialName
|
|
||||||
{
|
|
||||||
get { return useMaterialName; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref useMaterialName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetVolume = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标体积(μl)/目标重量(mg)
|
|
||||||
/// </summary>
|
|
||||||
public double TargetVolume
|
|
||||||
{
|
|
||||||
get { return targetVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref targetVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double actualVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 实际加入体积/重量
|
|
||||||
/// </summary>
|
|
||||||
public double ActualVolume
|
|
||||||
{
|
|
||||||
get { return actualVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref actualVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//private double liquidprecision = 1;
|
|
||||||
///// <summary>
|
|
||||||
///// 液体加液最大精度,单位g
|
|
||||||
///// </summary>
|
|
||||||
//public double LiquidPrecision
|
|
||||||
//{
|
|
||||||
// get { return liquidprecision; }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref liquidprecision, value);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
//[Serializable]
|
|
||||||
//public class SampleBottlePowderFunctionFlow : ObservableObject
|
|
||||||
//{
|
|
||||||
// private FunctionTypeEnum functionType = FunctionTypeEnum.加固体原料;
|
|
||||||
// public FunctionTypeEnum FunctionFlowType
|
|
||||||
// {
|
|
||||||
// get => functionType;
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref functionType, value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private string useSourcePowderName = string.Empty;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 使用的粉末试剂名称
|
|
||||||
// /// </summary>
|
|
||||||
// public string UsePowderName
|
|
||||||
// {
|
|
||||||
// get { return useSourcePowderName; }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref useSourcePowderName, value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private double targetPowderAmount;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 粉末目标加入量,单位g
|
|
||||||
// /// </summary>
|
|
||||||
// public double TargetPowderAmount
|
|
||||||
// {
|
|
||||||
// get { return targetPowderAmount; }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// if (targetPowderAmount != value)
|
|
||||||
// {
|
|
||||||
// targetPowderAmount = value;
|
|
||||||
// PowderPrecision = PrecisionRuleHelper.GetPowderPrecision(value); // 根据目标量获取精度g
|
|
||||||
// OnPropertyChanged(nameof(TargetPowderAmount));
|
|
||||||
// OnPropertyChanged(nameof(PowderPrecision));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private double actualPowderAmount;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 粉末实际加入量,单位g
|
|
||||||
// /// </summary>
|
|
||||||
// public double ActualPowderAmount
|
|
||||||
// {
|
|
||||||
// get { return actualPowderAmount; }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref actualPowderAmount, value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private double powderprecision = 1;
|
|
||||||
// /// <summary>
|
|
||||||
// /// 粉末加量最大精度,单位g
|
|
||||||
// /// </summary>
|
|
||||||
// public double PowderPrecision
|
|
||||||
// {
|
|
||||||
// get { return powderprecision; }
|
|
||||||
// set
|
|
||||||
// {
|
|
||||||
// SetProperty(ref powderprecision, value);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public enum ReactFunctionTypeEnum
|
|
||||||
{
|
|
||||||
[Description("取样")]
|
|
||||||
取样,
|
|
||||||
[Description("补液")]
|
|
||||||
补液,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取样操作类
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class ReactSampleFunctionFlow : ObservableObject
|
|
||||||
{
|
|
||||||
private double time;
|
|
||||||
/// <summary>
|
|
||||||
/// 操作时间
|
|
||||||
/// </summary>
|
|
||||||
public double OperateTime
|
|
||||||
{
|
|
||||||
get { return time; }
|
|
||||||
set { time = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetVolume = 0;
|
|
||||||
/// <summary>
|
|
||||||
/// 取样体积
|
|
||||||
/// </summary>
|
|
||||||
public double TargetAddVolume
|
|
||||||
{
|
|
||||||
get { return targetVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref targetVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool bAddLiquid = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 取样后是否紧接着加样
|
|
||||||
/// </summary>
|
|
||||||
public bool bAfterAddLiquid
|
|
||||||
{
|
|
||||||
get { return bAddLiquid; }
|
|
||||||
set { SetProperty(ref bAddLiquid, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<AddLiquidFunctionFlow> addLiquidList = new ObservableCollection<AddLiquidFunctionFlow>();
|
|
||||||
/// <summary>
|
|
||||||
/// 加液集合
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<AddLiquidFunctionFlow> AddLiquidList
|
|
||||||
{
|
|
||||||
get { return addLiquidList; }
|
|
||||||
set { SetProperty(ref addLiquidList, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isDuilte = false;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否稀释,默认都会稀释
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDulite
|
|
||||||
{
|
|
||||||
get => _isDuilte;
|
|
||||||
set => SetProperty(ref _isDuilte, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<AddDiluentFunction> diluentList = new ObservableCollection<AddDiluentFunction>();
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释剂集合
|
|
||||||
/// </summary>
|
|
||||||
public ObservableCollection<AddDiluentFunction> DiluentFunctionFlowList
|
|
||||||
{
|
|
||||||
get { return diluentList; }
|
|
||||||
set { SetProperty(ref diluentList, value); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public class AddLiquidFunctionFlow : ObservableObject
|
|
||||||
{
|
|
||||||
private double time;
|
|
||||||
/// <summary>
|
|
||||||
/// 操作时间
|
|
||||||
/// </summary>
|
|
||||||
public double OperateTime
|
|
||||||
{
|
|
||||||
get { return time; }
|
|
||||||
set { time = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string liquidName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName
|
|
||||||
{
|
|
||||||
get { return liquidName; }
|
|
||||||
set { SetProperty(ref liquidName, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetVolume;
|
|
||||||
/// <summary>
|
|
||||||
///目标加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double TargetAddVolume
|
|
||||||
{
|
|
||||||
get { return targetVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref targetVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double actualVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 实际加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double ActualVolume
|
|
||||||
{
|
|
||||||
get { return actualVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref actualVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加稀释剂
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class AddDiluentFunction : ObservableObject
|
|
||||||
{
|
|
||||||
private string diluentName = string.Empty;
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释剂名称
|
|
||||||
/// </summary>
|
|
||||||
public string DiluentName
|
|
||||||
{
|
|
||||||
get { return diluentName; }
|
|
||||||
set { SetProperty(ref diluentName, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetDiluentVolume = 0.00;
|
|
||||||
/// <summary>
|
|
||||||
///稀释剂目标加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double TargetDiluentVolume
|
|
||||||
{
|
|
||||||
get { return targetDiluentVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref targetDiluentVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double actualDiluentVolume = 0.00;
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释剂实际加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double ActualDiluentVolume
|
|
||||||
{
|
|
||||||
get { return actualDiluentVolume; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref actualDiluentVolume, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double diluentfactor = 1.00;
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释倍数,自动计算
|
|
||||||
/// </summary>
|
|
||||||
public double DiluentFactor
|
|
||||||
{
|
|
||||||
get { return diluentfactor; }
|
|
||||||
set { SetProperty(ref diluentfactor, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public static class EnumHelper
|
|
||||||
{
|
|
||||||
// 获取枚举所有值(可在 XAML 中直接引用)
|
|
||||||
public static IEnumerable<FunctionTypeEnum> FunctionTypes =>
|
|
||||||
Enum.GetValues(typeof(FunctionTypeEnum)).Cast<FunctionTypeEnum>();
|
|
||||||
|
|
||||||
//反应功能枚举
|
|
||||||
public static IEnumerable<ReactFunctionTypeEnum> ReactFunctionTypes =>
|
|
||||||
Enum.GetValues(typeof(ReactFunctionTypeEnum)).Cast<ReactFunctionTypeEnum>();
|
|
||||||
|
|
||||||
//SampleBottleTypeEnum
|
|
||||||
public static IEnumerable<SampleBottleTypeEnum> SampleBottleTypes =>
|
|
||||||
Enum.GetValues(typeof(SampleBottleTypeEnum)).Cast<SampleBottleTypeEnum>();
|
|
||||||
|
|
||||||
public static IEnumerable<PowderBottleTypeEnum> PowderBottleTypes =>
|
|
||||||
Enum.GetValues(typeof(PowderBottleTypeEnum)).Cast<PowderBottleTypeEnum>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 高温反应 低温反应
|
|
||||||
/// </summary>
|
|
||||||
public static IEnumerable<SampleBottleReactTemperatureEnum> ReactTemperatureEnums =>
|
|
||||||
Enum.GetValues(typeof(SampleBottleReactTemperatureEnum)).Cast<SampleBottleReactTemperatureEnum>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 操作类型 取样/加液
|
|
||||||
/// </summary>
|
|
||||||
public static IEnumerable<ReactOperationEnum> ReactOperateTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(ReactOperationEnum)).Cast<ReactOperationEnum>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反应取样方式枚举 穿刺取样/开盖取样
|
|
||||||
/// </summary>
|
|
||||||
public static IEnumerable<SampleMethod> ReactSampleTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(SampleMethod)).Cast<SampleMethod>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加液方式 穿刺加液/开盖加液
|
|
||||||
/// </summary>
|
|
||||||
public static IEnumerable<AddLiquidMethod> AddLiquidTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(AddLiquidMethod)).Cast<AddLiquidMethod>();
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 稀释方式
|
|
||||||
/// </summary>
|
|
||||||
public static IEnumerable<DiluteMethod> DiluteTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(DiluteMethod)).Cast<DiluteMethod>();
|
|
||||||
|
|
||||||
public static IEnumerable<TipTypeEnum> TipHeadTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(TipTypeEnum)).Cast<TipTypeEnum>();
|
|
||||||
|
|
||||||
public static IEnumerable<BoxTypeEnum> BoxTypeEnums =>
|
|
||||||
Enum.GetValues(typeof(BoxTypeEnum)).Cast<BoxTypeEnum>();
|
|
||||||
|
|
||||||
public static IEnumerable<BoxTypeEnum> BoxTypeEnumsSampleSource = new ObservableCollection<BoxTypeEnum>() { BoxTypeEnum._40mL原液工装, BoxTypeEnum._12mL样品工装, BoxTypeEnum._5mL样品工装 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.HTTPModels
|
|
||||||
{
|
|
||||||
public class ControlCmd
|
|
||||||
{
|
|
||||||
public string command { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("params")]
|
|
||||||
[JsonProperty("params")]
|
|
||||||
public object Params { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UnLoadModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否继续上料
|
|
||||||
/// </summary>
|
|
||||||
public bool isContinueLoad { get; set; }
|
|
||||||
|
|
||||||
public bool isBSRequest { get; set; }
|
|
||||||
|
|
||||||
public List<SourcePowderBottleBoxModel> sourcePowderBottleBoxModel { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UploadBoxModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 工装类型
|
|
||||||
/// </summary>
|
|
||||||
public BoxTypeEnum fixtureType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 盒子码
|
|
||||||
/// </summary>
|
|
||||||
public string boxSNCode { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 位置1~7
|
|
||||||
/// </summary>
|
|
||||||
public int boxId_inDoseUpload { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 剩余tip个数(如果fixtureType == 8~10需要)
|
|
||||||
/// </summary>
|
|
||||||
public int RemainCount { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶
|
|
||||||
/// </summary>
|
|
||||||
public List<SampleBottleModel> sampleBottles { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 原液瓶
|
|
||||||
/// </summary>
|
|
||||||
public List<SourceLiquidBottleModel> sourceLiquidBottles { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末
|
|
||||||
/// </summary>
|
|
||||||
public List<SourcePowderBottleModel> sourcePowderBottles { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using MegaRobo.C00225155.Entities.FromWeb;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common.HTTPModels
|
|
||||||
{
|
|
||||||
public class ToBsUnLoadData
|
|
||||||
{
|
|
||||||
[JsonProperty("sampleSeqs")]
|
|
||||||
public List<ToBsSampleSeq> SampleSeqs { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("config")]
|
|
||||||
public ToBsConfig Config { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("needFixture")]
|
|
||||||
public List<ToBsFixtureInfo> NeedFixture { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#region SampleSeq类
|
|
||||||
public class ToBsSampleSeq
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 手套箱是A1
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("area")]
|
|
||||||
public string Area { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具位置1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("carrier")]
|
|
||||||
public string Carrier { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样本瓶名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("code")]
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("order")]
|
|
||||||
public object Order { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品编号
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("originSeqIds")]
|
|
||||||
public List<long> OriginSeqIds { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 在载具中的位置
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("pos")]
|
|
||||||
public string Pos { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sampleConfig")]
|
|
||||||
public ToBsSampleConfig SampleConfig { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// _5mL = 1,_12mL = 2,其它 = 0
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("sampleType")]
|
|
||||||
public string SampleType { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ToBsSampleConfig
|
|
||||||
{
|
|
||||||
[JsonProperty("materialDoseFunctionFlow")]
|
|
||||||
public List<ToBsMaterialDoseFunctionFlow> MaterialDoseFunctionFlow { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// box 二维码匹配下面的boxinfo
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ToBsMaterialDoseFunctionFlow
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 0液1固
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("functionFlowType")]
|
|
||||||
public int FunctionFlowType { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("realVolumn")]
|
|
||||||
public double RealVolumn { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 实际添加量
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("targetVolumn")]
|
|
||||||
public double TargetVolumn { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加物名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("userMaterialName")]
|
|
||||||
public string UserMaterialName { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region config类
|
|
||||||
public class ToBsConfig
|
|
||||||
{
|
|
||||||
[JsonProperty("boxInfo")]
|
|
||||||
public List<ToBsBoxInfo> BoxInfo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ToBsBoxInfo
|
|
||||||
{
|
|
||||||
[JsonProperty("detail")]
|
|
||||||
public List<Detail> Detail { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public int FixtureType { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("posInUpload")]
|
|
||||||
public int PosInUpload { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("remainCount")]
|
|
||||||
public int RemainCount { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region NeedFixture类
|
|
||||||
public class ToBsFixtureInfo
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 放到转移位置1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("boxIdInDoseUpload")]
|
|
||||||
public int BoxIdInDoseUpload { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 治具类型
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public int FixtureType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 治具二维码
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public class IniHelper
|
|
||||||
{
|
|
||||||
[DllImport("kernel32")]
|
|
||||||
public static extern bool WritePrivateProfileString(string lpapplication, string lpkeyname, string lpstring, string lpfilename);
|
|
||||||
|
|
||||||
[DllImport("kernel32")]
|
|
||||||
public static extern int GetPrivateProfileString(string lpszSection, string lpszKey, string lpszDefault, System.Text.StringBuilder lpReturnedString, int cchReturnBuffer, string lpsFile);
|
|
||||||
|
|
||||||
public static string IniRead(string _filePath, string _section, string _key, string _default)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder _builder = new System.Text.StringBuilder(1024);
|
|
||||||
int len = GetPrivateProfileString(_section, _key, _default, _builder, 1024, _filePath);
|
|
||||||
string str = Convert.ToString(_builder).Trim();
|
|
||||||
int num = str.IndexOf(Convert.ToChar(0));
|
|
||||||
if (num >= 0) str = str.Substring(0, num - 1);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IniWrite(string _filePath, string _section, string _key, string _value)
|
|
||||||
{
|
|
||||||
return WritePrivateProfileString(_section, _key, _value, _filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EnumItem<TEnum> where TEnum : struct, Enum
|
|
||||||
{
|
|
||||||
public TEnum Value { get; set; } // 枚举值(如MA)
|
|
||||||
public string DisplayName { get; set; } // 显示文本(如“电容式”)
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EnumHelperr
|
|
||||||
{
|
|
||||||
public static string GetDescription(Enum value)
|
|
||||||
{
|
|
||||||
Type type = value.GetType();
|
|
||||||
MemberInfo[] memberInfo = type.GetMember(value.ToString());
|
|
||||||
if (memberInfo.Length > 0)
|
|
||||||
{
|
|
||||||
object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
|
||||||
if (attributes.Length > 0)
|
|
||||||
{
|
|
||||||
return ((DescriptionAttribute)attributes[0]).Description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<EnumItem<TEnum>> GetEnumDescriptionList<TEnum>() where TEnum : struct, Enum
|
|
||||||
{
|
|
||||||
var list =new List<EnumItem<TEnum>>();
|
|
||||||
foreach (TEnum enumValue in Enum.GetValues(typeof(TEnum)))
|
|
||||||
{
|
|
||||||
list.Add(new EnumItem<TEnum>
|
|
||||||
{
|
|
||||||
Value = enumValue, // 存储原始枚举值
|
|
||||||
DisplayName = GetDescription(enumValue) // 存储显示文本
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public static class PrecisionRuleHelper
|
|
||||||
{
|
|
||||||
// 液体加量对应的精度规则,key为加量区间下限(包含),value为精度计算方式
|
|
||||||
public static Dictionary<double, Func<double, double>> LiquidPrecisionRules = new Dictionary<double, Func<double, double>>
|
|
||||||
{
|
|
||||||
{1, (target) => target * 0.015}, // 1~5ml 对应 ±1.5%,这里简单示例返回目标值*0.015作为精度值(实际可根据需求调整存储和计算)
|
|
||||||
{0.2, (target) => target * 0.02}, // 0.2~1ml 对应 ±1%-2%,这里简单取2%示例
|
|
||||||
{0.02, (target) => target * 0.02} // 0.02~0.2ml 对应 ±1%-2%,这里简单取2%示例
|
|
||||||
};
|
|
||||||
|
|
||||||
// 粉末加量对应的精度规则,key为加量区间下限(包含),value为精度计算方式
|
|
||||||
public static Dictionary<double, Func<double, double>> PowderPrecisionRules = new Dictionary<double, Func<double, double>>
|
|
||||||
{
|
|
||||||
{5, (target) => target * 0.01}, // 5~10g 对应 ±1%
|
|
||||||
{1, (target) => target * 0.015}, // 1~5g 对应 ±1.5%
|
|
||||||
{0.1, (target) => target * 0.02}, // 0.1~1g 对应 ±1%-2%,这里简单取2%示例
|
|
||||||
{0.05, (target) => target * 0.02}, // 0.05~0.1g 对应不低于±2%
|
|
||||||
{0.005, (target) => 0.00025} // 0.005~0.05g 对应±0.25mg
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取液体加量对应的精度值
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="targetAmount">液体目标加量</param>
|
|
||||||
/// <returns>计算后的精度值</returns>
|
|
||||||
public static double GetLiquidPrecision(double targetAmount)
|
|
||||||
{
|
|
||||||
foreach (var rule in LiquidPrecisionRules)
|
|
||||||
{
|
|
||||||
if (targetAmount >= rule.Key)
|
|
||||||
{
|
|
||||||
return rule.Value(targetAmount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1; // 默认精度,可根据实际需求调整
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取粉末加量对应的精度值
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="targetAmount">粉末目标加量</param>
|
|
||||||
/// <returns>计算后的精度值</returns>
|
|
||||||
public static double GetPowderPrecision(double targetAmount)
|
|
||||||
{
|
|
||||||
foreach (var rule in PowderPrecisionRules)
|
|
||||||
{
|
|
||||||
if (targetAmount >= rule.Key)
|
|
||||||
{
|
|
||||||
return rule.Value(targetAmount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1; // 默认精度,可根据实际需求调整
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
public class TipMessageEventArgs:EventArgs
|
|
||||||
{
|
|
||||||
// 提示信息
|
|
||||||
public string Message { get; set; }
|
|
||||||
|
|
||||||
// 操作ID,用于区分不同的操作
|
|
||||||
public bool IsCompleted { get; set; }
|
|
||||||
|
|
||||||
public TipMessageEventArgs(string message, bool isCompleted)
|
|
||||||
{
|
|
||||||
Message = message;
|
|
||||||
IsCompleted = isCompleted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public delegate void OperationCompletedHandler(object sender, TipMessageEventArgs e);
|
|
||||||
|
|
||||||
// 操作进度更新委托
|
|
||||||
public delegate void OperationProgressHandler(int progress, string message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
<Window x:Class="Common.TipMessageWindow"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:local="clr-namespace:Common"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
WindowStartupLocation="CenterScreen" Topmost="True" WindowStyle="None"
|
|
||||||
Height="250" Width="480">
|
|
||||||
<Grid>
|
|
||||||
<StackPanel Margin="20,10">
|
|
||||||
<TextBlock x:Name="MessageTextBlock" HorizontalAlignment="Center" FontSize="16" Height="80" Width="400" TextWrapping="Wrap" TextAlignment="Left" Margin="0,40,0,20" />
|
|
||||||
<ProgressBar IsIndeterminate="True" Height="30" Width="320" Margin="20"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</Window>
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// TipMessageWindow.xaml 的交互逻辑
|
|
||||||
/// </summary>
|
|
||||||
public partial class TipMessageWindow : Window
|
|
||||||
{
|
|
||||||
public TipMessageWindow(string message)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
MessageTextBlock.Text = message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DialogManager
|
|
||||||
{
|
|
||||||
// 事件:操作完成通知
|
|
||||||
public static event Action OperationCompleted;
|
|
||||||
|
|
||||||
// 显示提示窗口并等待操作完成
|
|
||||||
public static async Task ShowDialogAsync(Window owner, string message, Func<Task> operation)
|
|
||||||
{
|
|
||||||
var dialog = new TipMessageWindow(message);
|
|
||||||
dialog.Owner = owner;
|
|
||||||
|
|
||||||
// 步骤1:先订阅事件(确保操作触发事件前已订阅)
|
|
||||||
var closeTask = WaitForDialogCloseAsync(dialog);
|
|
||||||
|
|
||||||
// 步骤2:启动耗时操作(此时事件已订阅)
|
|
||||||
var task = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await operation?.Invoke();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// 操作完成(无论成功/失败)都触发关闭事件
|
|
||||||
OperationCompleted?.Invoke();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 步骤3:显示弹窗
|
|
||||||
dialog.Show();
|
|
||||||
|
|
||||||
// 步骤4:等待弹窗关闭 + 操作完成
|
|
||||||
await closeTask;
|
|
||||||
await task;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task WaitForDialogCloseAsync(Window dialog)
|
|
||||||
{
|
|
||||||
var tcs = new TaskCompletionSource<bool>();
|
|
||||||
// 定义事件处理方法(方便后续取消订阅)
|
|
||||||
Action operationCompletedHandler = null;
|
|
||||||
|
|
||||||
// 事件触发时关闭弹窗
|
|
||||||
operationCompletedHandler = () =>
|
|
||||||
{
|
|
||||||
// 必须在UI线程操作弹窗
|
|
||||||
dialog.Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
if (dialog.IsVisible)
|
|
||||||
dialog.Close();
|
|
||||||
});
|
|
||||||
// 取消订阅(避免重复触发)
|
|
||||||
OperationCompleted -= operationCompletedHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 订阅事件
|
|
||||||
OperationCompleted += operationCompletedHandler;
|
|
||||||
|
|
||||||
// 弹窗关闭时完成Task + 取消订阅
|
|
||||||
dialog.Closed += (s, e) =>
|
|
||||||
{
|
|
||||||
OperationCompleted -= operationCompletedHandler;
|
|
||||||
tcs.SetResult(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return tcs.Task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 配置站启动按钮状态更新
|
|
||||||
/// </summary>
|
|
||||||
public class SingleBoolMessage : ValueChangedMessage<bool>
|
|
||||||
{
|
|
||||||
public SingleBoolMessage(bool bfinish) : base(bfinish)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测站启动按钮状态更新
|
|
||||||
/// </summary>
|
|
||||||
public class SingleBoolMessage1 : ValueChangedMessage<bool>
|
|
||||||
{
|
|
||||||
|
|
||||||
public SingleBoolMessage1(bool bfinish) : base(bfinish)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 配方流程导航栏选项是否可以点击
|
|
||||||
/// </summary>
|
|
||||||
public class SingleBoolPeifangMessage : ValueChangedMessage<bool>
|
|
||||||
{
|
|
||||||
public SingleBoolPeifangMessage(bool bfinish) : base(bfinish)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 更新拉曼参数
|
|
||||||
/// </summary>
|
|
||||||
public class UpdateRamanParamMessage : ValueChangedMessage<(int laservalue, int expvalue, int testCount, string fileName)>
|
|
||||||
{
|
|
||||||
public UpdateRamanParamMessage((int laserpowderrate, int expvalue, int testCount, string fileName) value) : base(value) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using MegaRobo.C00225155.Entities;
|
|
||||||
using MegaRobo.Entities.ViewTT;
|
|
||||||
using MegaRobo.C00225155.Entities.Enums;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Common;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer;
|
|
||||||
|
|
||||||
public class AppConfigService
|
|
||||||
{
|
|
||||||
public AppConfigService()
|
|
||||||
{
|
|
||||||
ReadConfig();
|
|
||||||
}
|
|
||||||
public ProjectInfo ProjectInfo { get; set; }
|
|
||||||
public IList<Setting> SettingList { get; set; }
|
|
||||||
//public IList<WebApiUrl> WebApiUrlList { get; set; }
|
|
||||||
|
|
||||||
public readonly string ApiName = "C00225155";
|
|
||||||
|
|
||||||
public readonly string globalOrderId = "0";
|
|
||||||
|
|
||||||
public List<string> BlockKeywords { get; set; } = new List<string>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 配置站、检测站公用的访问数据库的锁
|
|
||||||
/// </summary>
|
|
||||||
public readonly SemaphoreSlim databaseSemaphoreSlim = new SemaphoreSlim(1, 1);
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 工站属性列表
|
|
||||||
///// </summary>
|
|
||||||
//public List<StationProperty> StationPropList = new List<StationProperty>();
|
|
||||||
|
|
||||||
public IDictionary<ViewNames, AuthLevel> ViewNameAuthLevelsDic = new Dictionary<ViewNames, AuthLevel>();
|
|
||||||
|
|
||||||
private void ReadConfig()
|
|
||||||
{
|
|
||||||
ViewNameAuthLevelsDic.Clear();
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.HomeView, AuthLevel.None);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.SettingView, AuthLevel.Operator);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.CommunicationDebugView, AuthLevel.None);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.FlowConfigView, AuthLevel.None);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.AdditivePipetteConfigView, AuthLevel.None);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.LoggerView, AuthLevel.None);
|
|
||||||
ViewNameAuthLevelsDic.Add(ViewNames.UserView, AuthLevel.Instructor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,357 +0,0 @@
|
||||||
using Common;
|
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using MegaRobo.C00225155.DataAccess;
|
|
||||||
using MegaRobo.C00225155.Entities;
|
|
||||||
using MegaRobo.C00225155.Entities.Entity_DB;
|
|
||||||
using MegaRobo.C00225155.Entities.ToWeb;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.ControlDevices.Models;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices;
|
|
||||||
using MegaRobo.Utility.Files;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer.ExecuteWorks;
|
|
||||||
|
|
||||||
public abstract class StationServiceBase : ModbusWorkServiceBase
|
|
||||||
{
|
|
||||||
#region 服务字段
|
|
||||||
protected WorkService workService { get; set; }
|
|
||||||
protected AppConfigService appConfigService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PLC通讯的ModbusClient
|
|
||||||
/// </summary>
|
|
||||||
protected IModbusClientExtend ModbusClient;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// PLC 名称
|
|
||||||
/// </summary>
|
|
||||||
protected DeviceNames PlcName;
|
|
||||||
|
|
||||||
protected IDataAccessService dataAccessService;
|
|
||||||
|
|
||||||
protected IDictionary<string, string> PipetteErrorDic = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
//protected StationProperty StationProp = new StationProperty();
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Field\Property
|
|
||||||
/// <summary>
|
|
||||||
/// 从数据库中加载的所有PLC报警点位
|
|
||||||
/// </summary>
|
|
||||||
protected IList<PlcPoint> WarnPointList { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 从CSV文件中加载的所有报警点位、报警信息
|
|
||||||
/// </summary>
|
|
||||||
protected List<PLCErrorPoint> PLCErrorInfoList { get; set; } = new List<PLCErrorPoint>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 当前报警信息,触发事件
|
|
||||||
/// </summary>
|
|
||||||
protected List<PLCErrorPoint> PLCErrorLists { get; set; } = new List<PLCErrorPoint>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///扫描PLC 错误信息集合事件
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<List<PLCErrorPoint>> OnScanPlcErrorListEvent;
|
|
||||||
|
|
||||||
protected bool Runing = false;
|
|
||||||
|
|
||||||
protected string stationName = string.Empty;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
protected StationServiceBase(ICoreService coreService, WorkService workService, DeviceNames plcName, string stationName)
|
|
||||||
{
|
|
||||||
this.PlcName = plcName;
|
|
||||||
this.stationName = stationName;
|
|
||||||
this.CoreService = coreService;
|
|
||||||
this.workService = workService;// 关联上级WorkService(便于跨工站交互)
|
|
||||||
appConfigService = this.CoreService.GetServiceInstance<AppConfigService>();// 配置服务
|
|
||||||
dataAccessService = this.CoreService.GetServiceInstance<IDataAccessService>();// 数据访问服务
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadServices()
|
|
||||||
{
|
|
||||||
this.ModbusClient = this.CoreService.GetServiceInstance<IModbusClientExtend>(this.PlcName.ToString());
|
|
||||||
if (this.ModbusClient is not null)
|
|
||||||
{
|
|
||||||
this.ModbusClient.ScannedEvent += this.ModbusClientBaseOnScannedEvent;
|
|
||||||
this.ModbusClient.PulseTickAction += this.OnPulseTick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadDatas()
|
|
||||||
{
|
|
||||||
base.LoadDatas();
|
|
||||||
RegisterPipetteErrorCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async void RegisterPoints()
|
|
||||||
{
|
|
||||||
//转移至 StartupService 统一注册
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void RegisterPipetteErrorCode()
|
|
||||||
{
|
|
||||||
PipetteErrorDic = new Dictionary<string, string>()
|
|
||||||
{
|
|
||||||
{ "00", "执行成功" },
|
|
||||||
{ "20", "硬件问题,请联系Hamilton"},
|
|
||||||
{ "30", "未知命令,请参考命令表"},
|
|
||||||
{ "31", "未知参数,请参考命令表"},
|
|
||||||
{ "32", "发送的参数值超出预定范围,请参考命令表"},
|
|
||||||
{ "35", "电源电压超出运行范围,请确保电源电压是48V+-5%"},
|
|
||||||
{ "36", "关闭紧急停止"},
|
|
||||||
{ "38", "空液体类型"},
|
|
||||||
{ "39", "液体类型写保护"},
|
|
||||||
{ "40", "一次只能发送一个命令"},
|
|
||||||
{ "50", "Z轴初始化失败,硬件问题,请联系Hamilton"},
|
|
||||||
{ "51", "请初始化泵驱动"},
|
|
||||||
{ "52", "泵驱动初始化失败,硬件问题,请联系Hamilton"},
|
|
||||||
{ "53", "tip 头容量不够,无法吸入ai 值得液体,改变ai值或更改tip 头"},
|
|
||||||
{ "54", "达到泵的最大值"},
|
|
||||||
{ "55", "吸液体积校验失败,吸液量不满足当前Tip头的最小值"},
|
|
||||||
{ "56", "选择的液体类型要求用导电tip 头,请确认液体类型和tip 头类型编号一致"},
|
|
||||||
{ "57", "确定液体类型一致和tip 头类型编号"},
|
|
||||||
{ "60", "ZI初始化失败,硬件未工作,请联系Hamilton"},
|
|
||||||
{ "61", "Z轴驱动初始化失败"},
|
|
||||||
{ "62", "Z 轴驱动移动错误 硬件未工作,请联系Hamilton"},
|
|
||||||
{ "63", "移动碰触到试管底部"},
|
|
||||||
{ "64", "Z 轴,驱动达不到gy(要移动到的位置) 值,请检查参数"},
|
|
||||||
{ "65", "Z 轴,驱动达不到te(转移高度)值,请检查参数"},
|
|
||||||
{ "66", "Z 轴,驱动达不到ce(容器底部高度) 值,请检查参数"},
|
|
||||||
{ "67", "Z 轴,驱动达不到cf(液面的高度) 值,请检查参数"},
|
|
||||||
{ "68", "Z 轴,驱动达不到zp(开始探测液面的位置) 值,请检查参数"},
|
|
||||||
{ "69", "Z 轴,驱动达不到tr(丢弃Tip头位置) 值,请检查参数"},
|
|
||||||
{ "70", "在zp 和ce 两个值之间未检测到液面,请检查参数设置"},
|
|
||||||
{ "71", "液体不足"},
|
|
||||||
{ "72", "压力传感器自动校准失效,硬件未工作,请联系Hamilton"},
|
|
||||||
{ "74", "提前检测到液面"},
|
|
||||||
{ "75", "未取到tip 头"},
|
|
||||||
{ "76", "tip 头已经取到"},
|
|
||||||
{ "80", "吸液过程中检测到堵塞"},
|
|
||||||
{ "81", "吸液过程中检测到吸空"},
|
|
||||||
{ "82", "吸液过程中检测到气泡"},
|
|
||||||
{ "83", "分配过程中检测到堵塞"},
|
|
||||||
{ "84", "分配过程中检测到气泡"},
|
|
||||||
{ "85", "未与数字电平通信上,硬件问题,请联系Hamilton"},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadPlcWarnInfoSetting()
|
|
||||||
{
|
|
||||||
base.LoadPlcWarnInfoSetting();
|
|
||||||
this.PLCErrorInfoList.Clear();
|
|
||||||
WarnPointList = new List<PlcPoint>();
|
|
||||||
string filePath = string.Empty;
|
|
||||||
if (this.PlcName == DeviceNames.Plc1)//投料站
|
|
||||||
{
|
|
||||||
filePath = "DataBox\\PlcWarnSetting_Dose.csv";
|
|
||||||
}
|
|
||||||
else if (this.PlcName.Equals(DeviceNames.Plc2)) //反应站
|
|
||||||
{
|
|
||||||
filePath = "DataBox\\PlcWarnSetting_React.csv";
|
|
||||||
}
|
|
||||||
string[] lines = File.ReadAllLines(filePath, System.Text.Encoding.GetEncoding("utf-8"));
|
|
||||||
|
|
||||||
foreach (string line in lines)
|
|
||||||
{
|
|
||||||
string key = string.Empty;
|
|
||||||
string[] columns = line.Split(',');
|
|
||||||
if (columns.Length != 2)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = columns[0].Replace("MX", "");
|
|
||||||
string value = columns[1];
|
|
||||||
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) continue;
|
|
||||||
if (!double.TryParse(key, out double _point)) continue;
|
|
||||||
|
|
||||||
PLCErrorPoint point = new PLCErrorPoint() { ErrorAddress = key, ErrorInfo = value };
|
|
||||||
this.PLCErrorInfoList.Add(point);
|
|
||||||
}
|
|
||||||
var alladdress = PLCErrorInfoList.Select(x => x.ErrorAddress.Split(".")[0]).Distinct().ToList();
|
|
||||||
var client = this.CoreService.GetServiceInstance<IModbusClientExtend>("Plc1");
|
|
||||||
foreach (var addr in alladdress)
|
|
||||||
{
|
|
||||||
client.Register<System.Drawing.Point>(ushort.Parse(addr), $"报警点位-{addr}", FunType.ReadHoldingRegisters);
|
|
||||||
PlcPoint plcPoint = new PlcPoint()
|
|
||||||
{
|
|
||||||
Address = ushort.Parse(addr), Descr = $"报警点位-{addr}", FunType = FunType.ReadHoldingRegisters
|
|
||||||
};
|
|
||||||
WarnPointList.Add(plcPoint);
|
|
||||||
}
|
|
||||||
//this.WarnPointList =
|
|
||||||
//this.WarnPointList = this.dataAccessService.LoadEntitiesAsync<PlcPoint>(x => x.Name == this.PlcName.ToString() && x.Level == 2).Result;
|
|
||||||
this.Runing = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string GetMethodName([CallerMemberName] string memberName = "")
|
|
||||||
{
|
|
||||||
return memberName;
|
|
||||||
}
|
|
||||||
|
|
||||||
//protected virtual async Task InitPreAsync()
|
|
||||||
//{
|
|
||||||
// await Task.Delay(0);
|
|
||||||
//}
|
|
||||||
|
|
||||||
#region PLC读取/写入值操作
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private ushort _lastTickValue = 1; //先缓存, 尽量减少通讯次数
|
|
||||||
protected override void OnPulseTick()
|
|
||||||
{
|
|
||||||
var currValue = (ushort)(DateTime.Now.Second % 2); //间隔两秒给一次心跳
|
|
||||||
if (currValue == 0)
|
|
||||||
{
|
|
||||||
//this._lastTickValue = currValue;
|
|
||||||
this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_MaterialDose.W_PCHeartPluse[(ushort)this.PlcName], 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region ModBus
|
|
||||||
|
|
||||||
protected async void LoadPlcAlarmInfoSetting()
|
|
||||||
{
|
|
||||||
//注册提示点位
|
|
||||||
// this.WarnPointList = await this.DataAccessService.LoadEntitiesAsync<PlcPoint>(x =>
|
|
||||||
// x.Name == this.PlcName.ToString() && x.Level == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
//protected IList<PlcPoint> ScanPlcAlarmInfoList(int? takeCount = null)
|
|
||||||
//{
|
|
||||||
// return new List<PlcPoint>();
|
|
||||||
//}
|
|
||||||
|
|
||||||
private DateTime lastWarnDateTime = DateTime.Now;
|
|
||||||
|
|
||||||
//public Dictionary<ushort, ushort> WarnDictionary = new Dictionary<ushort, ushort>();
|
|
||||||
|
|
||||||
protected virtual void ModbusClientBaseOnScannedEvent(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (!this.Runing)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DateTime now = DateTime.Now;
|
|
||||||
if ((now - this.lastWarnDateTime).Seconds >= 5)
|
|
||||||
{
|
|
||||||
this.lastWarnDateTime = now;
|
|
||||||
ScanPLCWarnList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IList<PlcPoint> ScanPlcWarnInfoList(int? takeCount = null)
|
|
||||||
{
|
|
||||||
IList<PlcPoint> warnPointList = new List<PlcPoint>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (var plcPoint in this.WarnPointList)
|
|
||||||
{
|
|
||||||
//这里的错误报警信息都是1个字,2个字节,16位
|
|
||||||
var pointInfo = this.ModbusClient.ReadScannedValue<ushort>(plcPoint.Address);
|
|
||||||
if (pointInfo.Value != 0)
|
|
||||||
{
|
|
||||||
//if (!this.WarnDictionary.ContainsKey(pointInfo.Address) || this.WarnDictionary[pointInfo.Address] != pointInfo.Value)
|
|
||||||
//{
|
|
||||||
// this.Logger.LogError($"{this.stationName}异常点位[{pointInfo.Address}]值[{pointInfo.Value}]");
|
|
||||||
// this.WarnDictionary[pointInfo.Address] = pointInfo.Value;
|
|
||||||
//}
|
|
||||||
//pointInfo.LastValue = pointInfo.Value.ToString();
|
|
||||||
warnPointList.Add(pointInfo);
|
|
||||||
}
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// //复位直接清空 不处理
|
|
||||||
// if(this.WranDictionary.ContainsKey(pointInfo.Address))
|
|
||||||
// this.WranDictionary.Remove(pointInfo.Address);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogError($"{this.stationName}异常信息[{ex.Message}]");
|
|
||||||
}
|
|
||||||
return warnPointList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 扫描PLC报警信息,触发事件
|
|
||||||
/// </summary>
|
|
||||||
private void ScanPLCWarnList()
|
|
||||||
{
|
|
||||||
PLCErrorLists.Clear();
|
|
||||||
foreach (var plcPoint in WarnPointList)
|
|
||||||
{
|
|
||||||
var pointInfo = this.ModbusClient.ReadScannedValue<ushort>(plcPoint.Address);
|
|
||||||
bool isError = false;
|
|
||||||
if (pointInfo.Value != 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if (((pointInfo.Value >> i) & 1) == 1)
|
|
||||||
{
|
|
||||||
var addr = plcPoint.Address.ToString() + "." + i.ToString();
|
|
||||||
var point = PLCErrorInfoList.FirstOrDefault(p => p.ErrorAddress.Equals(addr));
|
|
||||||
if (point != null)
|
|
||||||
{
|
|
||||||
isError = !point.ErrorInfo.Contains("提示");
|
|
||||||
PLCErrorLists.Add(point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isError)
|
|
||||||
{
|
|
||||||
//给BS那边只需要给报警信息
|
|
||||||
PLCErrorLists.Add(new PLCErrorPoint() { ErrorAddress = plcPoint.Address.ToString(), ErrorInfo = pointInfo.Value.ToString() }); //这边定义好传给BS的值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PLCErrorLists.Count > 0)
|
|
||||||
{
|
|
||||||
this.OnScanPlcErrorListEvent?.Invoke(this, PLCErrorLists);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 用于移液枪取运行状态值
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="resultString"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected string GetPipetteReturnCode(string resultString)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string pattern = @"er(\d{2})";
|
|
||||||
MatchCollection matches = Regex.Matches(resultString, pattern);
|
|
||||||
return matches[0].Groups[1].Value;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return resultString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,461 +0,0 @@
|
||||||
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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 这里主要是针对配置站服务,控制1ml移液枪的逻辑
|
|
||||||
/// </summary>
|
|
||||||
public partial class StationService_MaterialDosing: StationServiceBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 Z轴初始化
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunZAxisInit_M1(DeviceNames pipetteDevice, PipetteService pipetteService)
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{pipetteDevice}Z轴初始化");
|
|
||||||
IDictionary<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 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]}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 总初始化
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunAllInit_M1(DeviceNames pipetteDevice, PipetteService pipetteService)
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{pipetteDevice}总初始化");
|
|
||||||
IDictionary<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 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]}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 取TIP头
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task<bool> 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<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 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<uint> pipetteIdList = new List<uint> { 1 };
|
|
||||||
// pipetteIdList = pipetteService_1ml.PipetteList.Select(x => x.Id);
|
|
||||||
// foreach (var id in pipetteIdList)
|
|
||||||
// {
|
|
||||||
// var dictRes = await pipetteService_1ml.MoveZaxis(0, id);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 丢弃Tip头
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunDiscardTip_M1(DeviceNames pipetteDevice, PipetteService pipetteService)
|
|
||||||
{
|
|
||||||
if (TestMode) return;
|
|
||||||
this.Logger.LogInformation($"{pipetteDevice}丢Tip");
|
|
||||||
IDictionary<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 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<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
|
|
||||||
var curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_Dose>(x => x.LiquidName == liquidName && x.TipType == tiporder); //&& x.TipType == tiporder 暂时屏蔽
|
|
||||||
if (curLiqud == null || curLiqud.Count == 0)
|
|
||||||
{
|
|
||||||
curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_Dose>(x => x.TipType == tiporder);
|
|
||||||
}
|
|
||||||
var curLiqud_M1 = curLiqud.FirstOrDefault();
|
|
||||||
curLiqud_M1.TipType = tiporder;
|
|
||||||
curLiqud_M1.LiquidVolume = (int)Math.Abs(absorbVolumn * curLiqud_M1.Ratio);
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 分液
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="liquidName">液体名称</param>
|
|
||||||
/// <param name="volumn">分液体积</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunDispensing_M1(DeviceNames pipetteDevice, PipetteService pipetteService, string liquidName, int tipOrder,uint vol, SampleBottleModel sampleBottleModel)
|
|
||||||
{
|
|
||||||
if (TestMode) return;
|
|
||||||
IDictionary<uint, string> dictResult = new Dictionary<uint, string>();
|
|
||||||
|
|
||||||
//IList<uint> listId = new List<uint>();
|
|
||||||
Liquid_lml_Dose curLiqud_M1 = new Liquid_lml_Dose();
|
|
||||||
IList<uint> IdList = new List<uint>();
|
|
||||||
switch (pipetteDevice)
|
|
||||||
{
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_1:
|
|
||||||
IdList = new List<uint> { 1 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_2:
|
|
||||||
IdList = new List<uint> { 2 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_3:
|
|
||||||
IdList = new List<uint> { 3 };
|
|
||||||
break;
|
|
||||||
case DeviceNames.Pipette_Dose_1ml_4:
|
|
||||||
IdList = new List<uint> { 4 };
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Logger.LogInformation($"{pipetteDevice}开始分液");
|
|
||||||
var curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_Dose>(x => x.LiquidName == liquidName && x.TipType == tipOrder); //
|
|
||||||
if (curLiqud == null || curLiqud.Count == 0)
|
|
||||||
{
|
|
||||||
curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_Dose>(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<IDictionary<uint, string>> OnSuckFluid(PipetteService pipetteService, IList<uint> listId, Liquid_lml_Dose liquidProduct, int subid, int asperIndex = 1, SourceLiquidBottleModel sourceLiquidBottleModel = null)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> 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<IDictionary<uint, string>> OnDispenFluid1(PipetteService pipetteService, IList<uint> listId, Liquid_lml_Dose liquidProduct, uint dispos)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> resultData = new Dictionary<uint, string>();
|
|
||||||
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<IDictionary<uint, string>> OnDispenFluid(PipetteService pipetteService, IList<uint> listId, Liquid_lml_Dose liquidProduct, uint volume)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> resultData = new Dictionary<uint, string>();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,167 +0,0 @@
|
||||||
using Common;
|
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
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.Contract;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices;
|
|
||||||
|
|
||||||
using SqlSugar;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using Pipette1ml = MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.HamiltonDevices;
|
|
||||||
using Pipette5ml = MegaRobo.PipetteTool.HamiltonConsole.PipetteDevices.Hamilton5mlDevices;
|
|
||||||
using Task = System.Threading.Tasks.Task;
|
|
||||||
using MegaRobo.ControlDevices.Models;
|
|
||||||
using NetTaste;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Contract.Abstractions;
|
|
||||||
using MegaRobo.ControlDevices;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using Nito.AsyncEx;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer.ExecuteWorks
|
|
||||||
{
|
|
||||||
public partial class StationService_ReactionProcessing : StationServiceBase
|
|
||||||
{
|
|
||||||
private IModbusClientExtend _modbusClient_Plc2;
|
|
||||||
public StationProperty StationProp = new StationProperty();
|
|
||||||
|
|
||||||
#region 服务模组
|
|
||||||
|
|
||||||
protected ScannerService scannerService_react;
|
|
||||||
private PipetteDictionary pipetteDictionary { get; set; }
|
|
||||||
private Pipette1ml.PipetteService pipetteService_1ml { get; set; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region events
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public StationService_ReactionProcessing(ICoreService coreService, WorkService workService, DeviceNames plcName, string station) : base(coreService, workService, plcName, station)
|
|
||||||
{
|
|
||||||
//Initial();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadServices()
|
|
||||||
{
|
|
||||||
base.LoadServices();
|
|
||||||
scannerService_react = this.CoreService.GetServiceInstance<ScannerService>(DeviceNames.Scanner_ReactRack.ToString());
|
|
||||||
pipetteService_1ml = this.CoreService.GetServiceInstance<Pipette1ml.PipetteService>(DeviceNames.Pipette_React_1ml.ToString());
|
|
||||||
pipetteDictionary = new PipetteDictionary();
|
|
||||||
|
|
||||||
//_modbusClient_Plc2 = this.CoreService.GetServiceInstance<IModbusClientExtend>(DeviceNames.Plc2.ToString());
|
|
||||||
if (this.ModbusClient != null)
|
|
||||||
{
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_BoxPlateUploadFinish, 0);
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_DnLoad, 0);
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_BoxPlatePos, 0);
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_BoxPlatePutFinish, 0);
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_BoxPlateCave1have, 0);
|
|
||||||
//this.ModbusClient.Command.WriteValue<ushort>(PlcPoints_React.W_BoxPlateCave2have, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async void ModbusClientBaseOnScannedEvent(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
base.ModbusClientBaseOnScannedEvent(sender, e);
|
|
||||||
|
|
||||||
this.StationProp.ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 计算枪头吸液次数
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="volumn"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private List<double> CalculateAbsorbCount(double volumn)
|
|
||||||
{
|
|
||||||
List<double> counts = new List<double>();
|
|
||||||
int count = (int)(volumn / 5000);
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
counts.Add(5000);
|
|
||||||
}
|
|
||||||
if (volumn % 5000 > 0)
|
|
||||||
{
|
|
||||||
counts.Add(volumn % 5000);
|
|
||||||
}
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
|
|
||||||
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<bool> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,302 +0,0 @@
|
||||||
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.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer.ExecuteWorks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 这里主要是针对配置站服务,控制1ml移液枪的逻辑
|
|
||||||
/// </summary>
|
|
||||||
public partial class StationService_ReactionProcessing : StationServiceBase
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 Z轴初始化
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunZAxisInit_M1()
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}Z轴初始化");
|
|
||||||
|
|
||||||
//莫名其妙的每次初始化都需要重新连接一次,不知道为什么
|
|
||||||
pipetteService_1ml.Disconnect();
|
|
||||||
await pipetteService_1ml.ConnectionAsync();
|
|
||||||
|
|
||||||
var dictResult = await pipetteService_1ml.InitZaxis();
|
|
||||||
if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00"))
|
|
||||||
{
|
|
||||||
string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value);
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}Z轴初始化失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 总初始化
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunAllInit_M1()
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}总初始化");
|
|
||||||
var dictResult = await pipetteService_1ml.InitZaxis();
|
|
||||||
if (dictResult != null)
|
|
||||||
{
|
|
||||||
dictResult = await pipetteService_1ml.InitPump();
|
|
||||||
}
|
|
||||||
if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00"))
|
|
||||||
{
|
|
||||||
string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value);
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}总初始化失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 取TIP头
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task<bool> GunPickUpTip_M1(double tipVolumn)
|
|
||||||
{
|
|
||||||
ushort tipType = 7;
|
|
||||||
if (tipVolumn == 300)//300ul slim的有滤芯的、导电的枪头
|
|
||||||
{
|
|
||||||
tipType = 9;
|
|
||||||
}
|
|
||||||
else if (tipVolumn == 50) //50ul的有滤芯的、导电的枪头
|
|
||||||
{
|
|
||||||
tipType = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tipType = 7;//1000ul的有滤芯的、导电的枪头
|
|
||||||
}
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}取Tip");
|
|
||||||
var dictResult = await pipetteService_1ml.TipInstall(tipType: tipType);
|
|
||||||
await pipetteService_1ml.InitZaxis(); //Z轴带动泵模块向上运动到最高处
|
|
||||||
if (dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00") || dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "76"))
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}取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 = $"{DeviceNames.Pipette_React_1ml}取Tip失败",
|
|
||||||
Content = $"{PipetteErrorDic[errorkey]}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}取Tip失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
await GunAllInit_M1();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ZMove(uint pos)
|
|
||||||
{
|
|
||||||
IEnumerable<uint> pipetteIdList = new List<uint> { 1 };
|
|
||||||
pipetteIdList = pipetteService_1ml.PipetteList.Select(x => x.Id);
|
|
||||||
foreach (var id in pipetteIdList)
|
|
||||||
{
|
|
||||||
var dictRes = await pipetteService_1ml.MoveZaxis(0, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 丢弃Tip头
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunDiscardTip_M1()
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}丢Tip");
|
|
||||||
//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}");
|
|
||||||
//}
|
|
||||||
var dictResult = await pipetteService_1ml.InitPump();
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00"))
|
|
||||||
{
|
|
||||||
string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value);
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"{DeviceNames.Pipette_React_1ml}丢Tip失败",
|
|
||||||
Content = $"{PipetteErrorDic[errorkey]}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}丢Tip失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
await GunAllInit_M1();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task GunAbsorb_M1(string funcType, string liquidName, int tiporder, double absorbVolumn)
|
|
||||||
{
|
|
||||||
IList<uint> listId = new List<uint>() { 1 };
|
|
||||||
var curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_React>(x => x.FuncType == funcType && x.LiquidName == liquidName && (x.TipType == tiporder));
|
|
||||||
var curLiqud_M1 = curLiqud.FirstOrDefault();
|
|
||||||
curLiqud_M1.LiquidVolume = (int)Math.Abs(absorbVolumn * curLiqud_M1.Ratio);
|
|
||||||
//for (int i = 1; i < 3; i++) //若吸液失败,二次吸液
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}开始吸液,吸液量{curLiqud_M1.LiquidVolume}ul");
|
|
||||||
var dictResult = await OnSuckFluid(pipetteService_1ml, listId, curLiqud_M1, 1, 1);
|
|
||||||
if (dictResult != null)
|
|
||||||
{
|
|
||||||
if (dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00"))
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}吸液成功");
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value);
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}吸液失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"{DeviceNames.Pipette_React_1ml}吸液失败",
|
|
||||||
Content = $"{PipetteErrorDic[errorkey]}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml枪头 分液
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="liquidName">液体名称</param>
|
|
||||||
/// <param name="volumn">分液体积</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task GunDispensing_M1(string funcType, string liquidName, int tipOrder, double volumn)
|
|
||||||
{
|
|
||||||
Liquid_lml_React curLiqud_M1 = new Liquid_lml_React();
|
|
||||||
IList<uint> listId = new List<uint>() { 1 };
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}开始分液,分液量{volumn}ul");
|
|
||||||
var curLiqud = await this.dataAccessService.LoadEntitiesAsync<Liquid_lml_React>(x => x.FuncType == funcType && x.LiquidName == liquidName && (x.TipType == tipOrder));
|
|
||||||
curLiqud_M1 = curLiqud.FirstOrDefault();
|
|
||||||
var dictResult = await OnDispenFluid(pipetteService_1ml, listId, curLiqud_M1, 100);//(uint)Math.Abs(volumn)
|
|
||||||
if (!dictResult.All(x => this.GetPipetteReturnCode(x.Value) == "00"))
|
|
||||||
{
|
|
||||||
string errorkey = this.GetPipetteReturnCode(dictResult.LastOrDefault().Value);
|
|
||||||
this.Logger.LogError($"{DeviceNames.Pipette_React_1ml}分液失败,{PipetteErrorDic[errorkey]}");
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"{DeviceNames.Pipette_React_1ml}分液失败",
|
|
||||||
Content = $"{PipetteErrorDic[errorkey]}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"{DeviceNames.Pipette_React_1ml}分液成功");
|
|
||||||
await pipetteService_1ml.InitZaxis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IDictionary<uint, string>> OnSuckFluid(PipetteService pipetteService, IList<uint> listId, Liquid_lml_React liquidProduct, int subid, int asperIndex = 1)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> 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;
|
|
||||||
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_React_1ml}吸液异常:{ex}");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
return resultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IDictionary<uint, string>> OnDispenFluid1(PipetteService pipetteService, IList<uint> listId, Liquid_lml_React liquidProduct, uint dispos)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> resultData = new Dictionary<uint, string>();
|
|
||||||
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_React_1ml}分液异常,异常原因:{ex}");
|
|
||||||
}
|
|
||||||
return resultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private async Task<IDictionary<uint, string>> OnDispenFluid(PipetteService pipetteService, IList<uint> listId, Liquid_lml_React liquidProduct, uint volume)
|
|
||||||
{
|
|
||||||
IDictionary<uint, string> resultData = new Dictionary<uint, string>();
|
|
||||||
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_React_1ml}分液异常,异常原因:{ex.ToString()}");
|
|
||||||
}
|
|
||||||
return resultData;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,582 +0,0 @@
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Nito.AsyncEx;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Automation.Text;
|
|
||||||
using System.Windows.Data;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer.ExecuteWorks
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 这里主要写检测工站的和PLC通讯的函数
|
|
||||||
/// </summary>
|
|
||||||
public partial class StationService_ReactionProcessing : StationServiceBase
|
|
||||||
{
|
|
||||||
//#region PLC点位写/读
|
|
||||||
///// <summary>
|
|
||||||
///// 旋转平台---等待信号的锁
|
|
||||||
///// </summary>
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_Rotater = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_SixAxis = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_XYZ = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_XZ = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_Upload = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockWaitSignal_Dnload = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockDetect_Electricty = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockDetect_Acid = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockDetect_Moisture = new AsyncLock();
|
|
||||||
//private static readonly AsyncLock _lockSixAxisDoAction = new AsyncLock();
|
|
||||||
|
|
||||||
//public async Task<ushort> ReadScannedValueAsync_Upload(ushort address)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// return this.ModbusClient.Command.ReadValue<ushort>(address);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站读取PLC信号异常",
|
|
||||||
// Content = $"ReadUpload读取 {address} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"ReadScannedValueAsync_Upload读取 {address} 时发生错误: {ex.Message}");
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task<ushort> ReadScannedValueAsync_Dnload(ushort address)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// return this.ModbusClient.Command.ReadValue<ushort>(address);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站读取PLC信号异常",
|
|
||||||
// Content = $"ReadDnload读取 {address} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"ReadScannedValueAsync_Dnload读取 {address} 时发生错误: {ex.Message}");
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task<ushort> ReadScannedValueAsync_SixAxis(ushort address)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].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_XYZ(ushort address)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// return this.ModbusClient.Command.ReadValue<ushort>(address);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站读取PLC信号异常",
|
|
||||||
// Content = $"ReadXYZ读取 {address} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"ReadScannedValueAsync_XYZ读取 {address} 时发生错误: {ex.Message}");
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task<ushort> ReadScannedValueAsync_XZ(ushort address)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// return this.ModbusClient.Command.ReadValue<ushort>(address);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站读取PLC信号异常",
|
|
||||||
// Content = $"ReadXZ读取 {address} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"ReadScannedValueAsync_XZ读取 {address} 时发生错误: {ex.Message}");
|
|
||||||
// }
|
|
||||||
// return 0;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WriteCommandAsync_Upload(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].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_Dnload(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].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_Six(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
|
||||||
// //await Task.Delay(30);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站写入PLC信号异常",
|
|
||||||
// Content = $"WriteSix写入 {address}值{value} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WriteCommandAsync_Six写入 {address}值{value} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WriteCommandAsync_SixAxis(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
|
||||||
// //await Task.Delay(30);
|
|
||||||
// while (await ReadScannedValueAsync_SixAxis(address) != value)
|
|
||||||
// {
|
|
||||||
// this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
|
||||||
// await Task.Delay(30);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站写入PLC信号异常",
|
|
||||||
// Content = $"WriteSixAxis写入 {address}值{value} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WriteCommandAsync_SixAxis写入 {address}值{value} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WriteCommandAsync_XYZ(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
|
||||||
// //await Task.Delay(30);
|
|
||||||
// while (await ReadScannedValueAsync_XYZ(address) != value)
|
|
||||||
// {
|
|
||||||
// this.ModbusClient.Command.WriteValue<ushort>(address, value);
|
|
||||||
// await Task.Delay(30);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站写入PLC信号异常",
|
|
||||||
// Content = $"WriteXYZ写入 {address}值{value} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WriteCommandAsync_XYZ写入 {address}值{value} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WriteCommandAsync_XZ(ushort address, ushort value)
|
|
||||||
//{
|
|
||||||
// appConfigService.StationPropList[1].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 = $"WriteXZ写入 {address}值{value} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WriteCommandAsync_XZ写入 {address}值{value} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_Upload(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockWaitSignal_Upload.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// 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_DnLoad(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockWaitSignal_Dnload.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// 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_SixAxis(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockWaitSignal_SixAxis.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForSixAxis等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_SixAxis等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_Electricty(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockDetect_Electricty.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForElectricty等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_Electricty等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_Acid(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockDetect_Acid.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForAcid等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_Acid等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_Moisture(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockDetect_Moisture.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_SixAxis(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForMoisture等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_Moisture等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_XYZ(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockWaitSignal_XYZ.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_XYZ(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForXYZ等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_XYZ等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public async Task WaitForActionFinishAsync_XZ(ushort point, ushort waitValue, CancellationToken cancellationToken)
|
|
||||||
//{
|
|
||||||
// using (await _lockWaitSignal_XZ.LockAsync(cancellationToken))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// ushort result = 0;
|
|
||||||
// do
|
|
||||||
// {
|
|
||||||
// appConfigService.StationPropList[1].ManualResetEvent.WaitOne(); //暂停标志
|
|
||||||
// result = await ReadScannedValueAsync_XZ(point);
|
|
||||||
// await Task.Delay(100, cancellationToken);
|
|
||||||
// } while (result != waitValue && !cancellationToken.IsCancellationRequested);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
// {
|
|
||||||
// Header = $"检测站等待PLC信号异常",
|
|
||||||
// Content = $"WaitForXZ等待{point}是否是{waitValue} 时发生错误: {ex.Message}",
|
|
||||||
// OkButtonContent = "继续",
|
|
||||||
// CancelButtonContent = "取消",
|
|
||||||
// });
|
|
||||||
// this.Logger.LogError($"WaitForActionFinishAsync_XZ等待{point}是否是{waitValue} 时发生错误: {ex.Message}");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
private async Task RefreshReactBottleState(int boxId, int posId, SampleBottleStateEnum state)
|
|
||||||
{
|
|
||||||
//if (workService.ProjectPro.ReactBottleBoxList.FirstOrDefault(f => f.BoxId == boxId) != null)
|
|
||||||
//{
|
|
||||||
// SampleBottleBoxModel reactBottleBoxModel = workService.ProjectPro.ReactBottleBoxList.FirstOrDefault(f => f.BoxId == boxId);
|
|
||||||
// if (reactBottleBoxModel.ReactBottleList.FirstOrDefault(f => f.PosId_InBox - 1 == posId) != null)
|
|
||||||
// {
|
|
||||||
// reactBottleBoxModel.ReactBottleList.FirstOrDefault(f => f.PosId_InBox - 1 == posId).ReactBoxState = state;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
////更新界面显示结果
|
|
||||||
//SampleBottleModel bottleModel = null;
|
|
||||||
//bottleModel = workService.ProjectPro.ReactBottleBoxListByOrder[boxId - 1].ReactBottleList.FirstOrDefault(f => f.PosId_InBox - 1 == posId);
|
|
||||||
//if (state == ReactBottleStateEnum.Detecting)
|
|
||||||
//{
|
|
||||||
// if (!OngoingDetectResultList.Any(f => f.BoxId == bottleModel.BoxId && f.BottleId == bottleModel.PosId_InBox))
|
|
||||||
// {
|
|
||||||
// ReactBottleResult_Show result = new ReactBottleResult_Show
|
|
||||||
// {
|
|
||||||
// Guid = bottleModel.reactBottleResult.Guid,
|
|
||||||
// BoxId = bottleModel.reactBottleResult.BoxId,
|
|
||||||
// BottleId = bottleModel.reactBottleResult.BottleId,
|
|
||||||
// SampleName = bottleModel.reactBottleResult.SampleName,
|
|
||||||
// bDetectFinish = false
|
|
||||||
// };
|
|
||||||
// OngoingDetectResultList.Add(result);
|
|
||||||
// UpdateResultEvent?.Invoke(this, OngoingDetectResultList);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//else if (state == ReactBottleStateEnum.FinishDetect)
|
|
||||||
//{
|
|
||||||
// if (OngoingDetectResultList.Any(f => f.BoxId == bottleModel.BoxId && f.BottleId == bottleModel.PosId_InBox))
|
|
||||||
// {
|
|
||||||
// ReactBottleResult_Show result = OngoingDetectResultList.FirstOrDefault(f => f.BoxId == bottleModel.BoxId && f.BottleId == bottleModel.PosId_InBox && f.Guid == bottleModel.reactBottleResult.Guid);
|
|
||||||
// if (result != null)
|
|
||||||
// {
|
|
||||||
// result.bDetectFinish = true;
|
|
||||||
// //OngoingDetectResultList.Add(result);
|
|
||||||
// UpdateResultEvent?.Invoke(this, OngoingDetectResultList);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
await Task.Delay(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
|
|
||||||
<PackageReference Include="NETStandard.HttpListener" Version="1.0.3.5" />
|
|
||||||
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.ControlDevices\MegaRobo.ControlDevices.csproj" />
|
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.ControlDevices\MegaRobo.C00225155.ControlDevices.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.DataAccess\MegaRobo.C00225155.DataAccess.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.Entities\MegaRobo.C00225155.Entities.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.RRQuartz\MegaRobo.RRQuartz.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="MegaRobo.Contract">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Contract.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.DataAccess">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.DataAccess.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Entities">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Entities.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Logger">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Logger.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.PipetteTool.HamiltonConsole">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.PipetteTool.HamiltonConsole.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Utility">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Utility.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,100 +0,0 @@
|
||||||
using Common;
|
|
||||||
using Common.Models;
|
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using LightInject;
|
|
||||||
using MegaRobo.C00225155.AppServer.ExecuteWorks;
|
|
||||||
using MegaRobo.C00225155.ControlDevices;
|
|
||||||
using MegaRobo.C00225155.DataAccess;
|
|
||||||
using MegaRobo.C00225155.Entities;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.Contract.Abstractions;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using MegaRobo.RRQuartz;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.AppServer;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 这里面管理所有的StationServices
|
|
||||||
/// </summary>
|
|
||||||
public partial class WorkService : WorkServiceBase
|
|
||||||
{
|
|
||||||
// 当ProjectPro变更时触发的事件
|
|
||||||
public event Action ProjectProChanged;
|
|
||||||
|
|
||||||
public event EventHandler TickEvent;
|
|
||||||
|
|
||||||
private AppConfigService _appConfigService;
|
|
||||||
//private IDataAccessService _dataAccessService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 工站集合
|
|
||||||
/// </summary>
|
|
||||||
public IList<StationServiceBase> stationList;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站
|
|
||||||
/// </summary>
|
|
||||||
public StationService_MaterialDosing stationService_Dose;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反应站
|
|
||||||
/// </summary>
|
|
||||||
public StationService_ReactionProcessing stationService_React;
|
|
||||||
|
|
||||||
|
|
||||||
private ProjectProperty _projectPro = new ProjectProperty();
|
|
||||||
public ProjectProperty ProjectPro
|
|
||||||
{
|
|
||||||
get { return _projectPro; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (_projectPro != value)
|
|
||||||
{
|
|
||||||
_projectPro = value;
|
|
||||||
ProjectProChanged?.Invoke(); //触发事件
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
base.Initialize(coreService, args);
|
|
||||||
|
|
||||||
#region webapi相关
|
|
||||||
HttpListenerProvider _httpListenerProvider = this.CoreService.GetServiceInstance<HttpListenerProvider>();
|
|
||||||
this._httpListenerService = _httpListenerProvider.GetOrAdd(this._appConfigService.ProjectInfo.Code, null);
|
|
||||||
this.RegiondRoute("A1");
|
|
||||||
this.AddSwaggerSupport();
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
stationService_Dose = new StationService_MaterialDosing(CoreService, this, DeviceNames.Plc1, "Station_Dose");
|
|
||||||
stationService_Dose.Initialize(this.CoreService);
|
|
||||||
|
|
||||||
//stationService_React = new StationService_ReactionProcessing(CoreService, this, DeviceNames.Plc2, "Station_React");
|
|
||||||
//stationService_React.Initialize(this.CoreService);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadServices()
|
|
||||||
{
|
|
||||||
this._appConfigService = this.CoreService.GetServiceInstance<AppConfigService>();
|
|
||||||
//this._dataAccessService = this.CoreService.GetServiceInstance<IDataAccessService>();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadDatas()
|
|
||||||
{
|
|
||||||
base.LoadDatas();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void AttachEvents()
|
|
||||||
{
|
|
||||||
base.AttachEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,939 +0,0 @@
|
||||||
using MegaRobo.C00225155.Entities.Enums;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.ServiceModel;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class AACWebApiService
|
|
||||||
{
|
|
||||||
public string _baseUrl { get; set; }
|
|
||||||
public string AuthToken { get; set; }
|
|
||||||
public HttpOperateHelper httpClient { get; set; }
|
|
||||||
|
|
||||||
public JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions()
|
|
||||||
{
|
|
||||||
PropertyNameCaseInsensitive = true
|
|
||||||
};
|
|
||||||
|
|
||||||
#region Authentication
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 登录系统并获取Token
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userName">用户名</param>
|
|
||||||
/// <param name="userPassword">密码</param>
|
|
||||||
/// <returns>包含Token的响应模型</returns>
|
|
||||||
public async Task<Response<LoginResponse>> Login(string userName, string userPassword)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Authentication?userName={userName}&userPassword={userPassword}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<LoginResponse>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Instrument
|
|
||||||
/// <summary>
|
|
||||||
/// 开启/关闭模块相关启用状态
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid">仪器Id</param>
|
|
||||||
/// <param name="moduleIdentity">仪器模块Id</param>
|
|
||||||
/// <param name="state">要设置的状态 0: Standby/off ,1: on</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> State(int instrumentid, string moduleIdentity,int state)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/Module/State?cdsId={instrumentid}&moduleIdentity={moduleIdentity}&state={state}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重置LC馏分收集器容器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="containerName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<string>> LCContainerReset(int instrumentid, string containerName)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/SubDevice/Drawer/Container/Volume/Reset?cdsId={instrumentid}&containerName={containerName}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<string>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重置LC馏分收集器子设备
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="containerName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<string>> LCSubDeviceReset(int instrumentid, string subDeviceName)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/SubDevice/Volume/Reset?cdsId={instrumentid}&subDeviceName={subDeviceName}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<string>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重置进样器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> InjectorReset(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Injector/Reset?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// LC G7167全部复位
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> HomeAll(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/G7167/HomeAll?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重置LC馏分收集器子设备下单某个抽屉
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="subDeviceName"></param>
|
|
||||||
/// <param name="drawerIndex">抽屉序号,从1开始,如果传小于等于0的值表示重置整个子设备.对于回收收集器只支持1</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<string>> LCSubDeviceDrawerReset(int instrumentid, string subDeviceName,int drawerIndex)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/SubDevice/Drawer/Volume/Reset?cdsId={instrumentid}&subDeviceName={subDeviceName}&drawerIndex={drawerIndex}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
return await httpClient.PutAsync<string>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// 处理网络异常(如连接失败、超时等)
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC馏分收集器溶剂体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="subDeviceName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<LCContainerVolume>> GetLCContainerVolume(int instrumentid, string subDeviceName)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/SubDevice/Volume?cdsId={instrumentid}&subDeviceName={subDeviceName}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<LCContainerVolume>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取LC馏分收集器主设备的子模块列表
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<Features>> GetLCFeature(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/SubDevices?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<Features>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC馏分模块抽屉状态
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="deviceType"></param>
|
|
||||||
/// <param name="deviceSN"></param>
|
|
||||||
/// <param name="moduleId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<DrawerState>> GetLCDrawerStatus(int instrumentid, string deviceType,string deviceSN,string moduleId)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/ModuleDrawerStatus?cdsId={instrumentid}&deviceType={deviceType}&deviceSN={deviceSN}&moduleId={moduleId}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<DrawerState>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取收集器模块的模块类型
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<List<string>>> GetModuleTypes()
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/ModuleTypes";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<List<string>>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Response<LCG7167DrawerState>> GetLCG7167DrawerState(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/G7167/DrawerState?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<LCG7167DrawerState>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取GC模块常用信息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<GCModuleInfo>> GetGCModuleInfo(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/GC/Module/Info?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<GCModuleInfo>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// 处理网络异常(如连接失败、超时等)
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC模块常用信息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<LCModuleInfo>> GetLCModuleInfo(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Module/Info?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<LCModuleInfo>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// 处理网络异常(如连接失败、超时等)
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 取消当前仪器运行的job
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> CancelCurrentJob(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/Action/Cancel/CurrentJob?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 暂停仪器运行
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> PauseCurrentJob(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/Action/Pause?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 恢复仪器重新运行
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> ResumeCurrentJob(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/Action/Resume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Response<EmptyData>> ShutDownJob(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/Job/Shutdown?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<EmptyData>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC泵溶剂体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<BottleVolumesResponse>> BottleVolume(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/BottleVolume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<BottleVolumesResponse>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置LC泵溶剂体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> SetBottleVolume(int instrumentid, BottleVolumesResponse data)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/BottleVolume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl, data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC泵准备状态信息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<purgeState>> PreparationState(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/PreparationState?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<purgeState>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始LC泵清洗
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> PumpClean(int instrumentid, purgeCleaningParam data)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Purge?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<bool>(requestUrl, data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭LC泵清洗
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> StopPumpClean(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Purge?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<bool>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始LC泵调节
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="conditionTime"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> PumpCondition(int instrumentid,double conditionTime)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Condition?cdsId={instrumentid}&conditionTime={conditionTime}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<bool>(requestUrl, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭LC泵调节
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> StopPumpCondition(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Condition?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<bool>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始LC泵注入
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> PumpPrime(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Prime?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<bool>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭LC泵注入
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> StopPumpPrime(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/Prime?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<bool>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC泵废液体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<wasteVolume>> WasteBottleVolume(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Pump/WasteBottleVolume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<wasteVolume>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取LC进样器溶剂体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<List<bottleVolume>>> PrepSampleBottleVolume(int instrumentid)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/PrepSampler/BottleVolume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<List<bottleVolume>>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置LC进样器溶剂体积
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> SetPrepSampleBottleVolume(int instrumentid, List<bottleVolume> data)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/PrepSampler/BottleVolume?cdsId={instrumentid}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl,data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取样品盘信息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="injectorPlateName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<PlateInfo>> GetPlateExtraInfo(int instrumentid,string injectorPlateName)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Injector/Plate/ExtraInfo?cdsId={instrumentid}&injectorPlateName={injectorPlateName}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<PlateInfo>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 替换进样器盘子
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="injectorPlateName"></param>
|
|
||||||
/// <param name="openLabContainerDisplayName"></param>
|
|
||||||
/// <param name="keepAnalysisTargets"></param>
|
|
||||||
/// <param name="replaceFCFlag"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<List<platePlacement>>> PutPlatePlacement(int instrumentid, string injectorPlateName, string openLabContainerDisplayName, bool keepAnalysisTargets, bool replaceFCFlag)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Injector/Plate/Replacement?cdsId={instrumentid}&injectorPlateName={injectorPlateName}&keepAnalysisTargets={keepAnalysisTargets}&replaceFCFlag={replaceFCFlag}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<List<platePlacement>>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 替换馏分收集器盘子
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid"></param>
|
|
||||||
/// <param name="fractionCollectorPlateName"></param>
|
|
||||||
/// <param name="openLabContainerDisplayName"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<List<platePlacement>>> PutLCPlatePlacement(int instrumentid, string fractionCollectorPlateName, string openLabContainerDisplayName)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/FractionCollector/Plate/Replacement?cdsId={instrumentid}&fractionCollectorPlateName={fractionCollectorPlateName}&openLabContainerDisplayName={openLabContainerDisplayName}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<List<platePlacement>>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开启/关闭模块相关启用状态
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrumentid">仪器Id</param>
|
|
||||||
/// <param name="moduleIdentity">仪器模块Id</param>
|
|
||||||
/// <param name="state">要设置的状态 0: Standby/off ,1: on</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<bool>> LCModuleState(int instrumentid, string moduleIdentity, int state)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Instrument/LC/Module/State?cdsId={instrumentid}&moduleIdentity={moduleIdentity}&state={state}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<bool>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Sample
|
|
||||||
/// <summary>
|
|
||||||
/// 按批次设置Sample数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<int>> Sample(List<limsSamples> data)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/batch";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<int>(requestUrl,data);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 增加一个新样品
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sample"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<int>> AddOneSample(limsSamples sample)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<int>(requestUrl, sample);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据id删除大样品数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<int>> DeleteBigSample(string id)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample?id={id}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<int>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据id获取Sample数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<limsSamples>> GetSampleById(string id)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/id?id={id}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<limsSamples>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 根据id更新Sample数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <param name="sample"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<int>> RefreshSampleById(string id,limsSamples sample)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/id?id={id}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<int>(requestUrl, sample);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 根据barcode查询大样品数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="barcode"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<limsSamples>> ReserchSampleByBarcode(string barcode)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<limsSamples>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Response<limsSamples>> RefreshSampleByBarcode(string barcode)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<limsSamples>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Response<int>> DeleteSampleByBarcode(string barcode)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<int>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据BatchId获取Sample数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<limsSamples>> GetSampleByBatchId(string batchId)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/Sample/batchId?batchId={batchId}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<limsSamples>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region SampleTestItem
|
|
||||||
public async Task<Response<SampleItem>> GetSampleItemByBarcode(string barcode)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/SampleTestItem/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.GetAsync<SampleItem>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async Task<Response<int>> RefreshSampleItemByBarcode(string barcode,SampleItem sampleItem)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/SampleTestItem/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PutAsync<int>(requestUrl,sampleItem);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async Task<Response<int>> DeleteSampleItemByBarcode(string barcode)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/SampleTestItem/barcode?barcode={barcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.DeleteAsync<int>(requestUrl);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 增加测试瓶数据
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sampleBarcode"></param>
|
|
||||||
/// <param name="sampleItem"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="Exception"></exception>
|
|
||||||
public async Task<Response<int>> AddSampleItemByBarcode(string sampleBarcode,SampleItem sampleItem)
|
|
||||||
{
|
|
||||||
var requestUrl = $"{_baseUrl}/api/v1/SampleTestItem?sampleBarcode={sampleBarcode}";
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await httpClient.PostAsync<int>(requestUrl,sampleItem);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"{ex.Message}", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Store
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region SystemInfo
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region WorkPlan
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region InstrumentAnalysisRun
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region EventHandler
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
using MegaRobo.Contract;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class Response<T>
|
|
||||||
{
|
|
||||||
public int statusCode { get; set; }
|
|
||||||
public string errorCode { get; set; }
|
|
||||||
public string errorMessage { get; set; }
|
|
||||||
public string message { get; set; }
|
|
||||||
public T data { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HttpOperateHelper : IDisposable
|
|
||||||
{
|
|
||||||
private readonly HttpClient httpClient;
|
|
||||||
|
|
||||||
private bool _disposed = false;
|
|
||||||
|
|
||||||
public HttpOperateHelper()
|
|
||||||
{
|
|
||||||
// 初始化HttpClient,设置默认超时和请求头
|
|
||||||
httpClient = new HttpClient();
|
|
||||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
|
||||||
httpClient.Timeout = TimeSpan.FromSeconds(30); // 设置超时时间
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用的POST请求方法(适用于[HttpPost]接口)
|
|
||||||
public async Task<Response<T?>> PostAsync<T>(string url, object data = null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string jsonData = data != null ? JsonConvert.SerializeObject(data) : "{}";
|
|
||||||
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
|
||||||
var response = await httpClient.PostAsync(url, content);
|
|
||||||
response.EnsureSuccessStatusCode(); // 抛出HTTP错误状态码异常
|
|
||||||
string responseJson = await response.Content.ReadAsStringAsync();
|
|
||||||
return JsonConvert.DeserializeObject<Response<T>>(responseJson);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new Response<T>
|
|
||||||
{
|
|
||||||
statusCode = 1,
|
|
||||||
errorMessage = $"请求失败:{ex.Message}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用的PUT请求方法(适用于[HttpPut]接口)
|
|
||||||
public async Task<Response<T>> PutAsync<T>(string url, object data = null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string jsonData = data != null ? JsonConvert.SerializeObject(data) : "{}";
|
|
||||||
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
|
|
||||||
var response = await httpClient.PutAsync(url, content);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
string responseJson = await response.Content.ReadAsStringAsync();
|
|
||||||
return JsonConvert.DeserializeObject<Response<T>>(responseJson);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new Response<T>
|
|
||||||
{
|
|
||||||
statusCode = 1,
|
|
||||||
errorMessage = $"请求失败:{ex.Message}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用的DELETE请求方法(适用于[HttpDelete]接口)
|
|
||||||
public async Task<Response<T>> DeleteAsync<T>(string url)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await httpClient.DeleteAsync(url);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
string responseJson = await response.Content.ReadAsStringAsync();
|
|
||||||
return JsonConvert.DeserializeObject<Response<T>>(responseJson);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new Response<T>
|
|
||||||
{
|
|
||||||
statusCode = 1,
|
|
||||||
errorMessage = $"请求失败:{ex.Message}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用的GET请求方法(适用于[HttpGet]接口)
|
|
||||||
public async Task<Response<T>> GetAsync<T>(string url)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var response = await httpClient.GetAsync(url);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
string responseJson = await response.Content.ReadAsStringAsync();
|
|
||||||
return JsonConvert.DeserializeObject<Response<T>>(responseJson);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new Response<T>
|
|
||||||
{
|
|
||||||
statusCode = 1,
|
|
||||||
errorMessage = $"请求失败:{ex.Message}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 释放资源(实现IDisposable接口)
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (_disposed) return;
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
httpClient?.Dispose(); // 释放HttpClient
|
|
||||||
}
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,284 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class LoginResponse
|
|
||||||
{
|
|
||||||
public string id { get; set; }
|
|
||||||
public string name { get; set; }
|
|
||||||
public string account { get; set; }
|
|
||||||
public string role { get; set; }
|
|
||||||
public string password { get; set; }
|
|
||||||
public int pwdSaltFlag { get; set; }
|
|
||||||
public string authenticationToken { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LCContainerVolume
|
|
||||||
{
|
|
||||||
public int tray { get; set; }
|
|
||||||
public int rack { get; set; }
|
|
||||||
public int rows { get; set; }
|
|
||||||
public int cols { get; set; }
|
|
||||||
public int units { get; set; }
|
|
||||||
public int max { get; set; }
|
|
||||||
public List<List<VolumeInfo>> volumes { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class VolumeInfo
|
|
||||||
{
|
|
||||||
public int max { get; set; } // 最大体积
|
|
||||||
public int vol { get; set; } // 当前体积
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Features
|
|
||||||
{
|
|
||||||
public string name { get; set; }
|
|
||||||
public string type { get; set; }
|
|
||||||
public string sn { get; set; }
|
|
||||||
public List<string> features { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DrawerState
|
|
||||||
{
|
|
||||||
public string type { get; set; }
|
|
||||||
public string sn { get; set; }
|
|
||||||
public DrawersOpen drawersOpen { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DrawersOpen
|
|
||||||
{
|
|
||||||
public bool additionalProp1 { get; set; }
|
|
||||||
public bool additionalProp2 { get; set; }
|
|
||||||
public bool additionalProp3 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LCG7167DrawerState
|
|
||||||
{
|
|
||||||
public string drawer { get; set; }
|
|
||||||
public bool drawerOpen { get; set; }
|
|
||||||
public int plateStateFront { get; set; }
|
|
||||||
public int plateStateBack { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GCModuleInfo
|
|
||||||
{
|
|
||||||
public int doorOpen { get; set; }
|
|
||||||
public int methodRuntime { get; set; }
|
|
||||||
public int runTime { get; set; }
|
|
||||||
public int methodPostTime { get; set; }
|
|
||||||
public int postTime { get; set; }
|
|
||||||
public int status { get; set; }
|
|
||||||
public int ready { get; set; }
|
|
||||||
public List<string> notReadyInfo { get; set; }
|
|
||||||
public List<string> errorInfo { get; set; }
|
|
||||||
public int hostReady { get; set; }
|
|
||||||
public int connectionState { get; set; }
|
|
||||||
public string alsRunStatus { get; set; }
|
|
||||||
|
|
||||||
public AlsFront alsFront { get; set; }
|
|
||||||
public AlsBack alsBack { get; set; }
|
|
||||||
public AlsTray alsTray { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AlsFront
|
|
||||||
{
|
|
||||||
public int capacity { get; set; }
|
|
||||||
public string model { get; set; }
|
|
||||||
public int doorOpen { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public state state { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AlsBack
|
|
||||||
{
|
|
||||||
public int capacity { get; set; }
|
|
||||||
public string model { get; set; }
|
|
||||||
public int doorOpen { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public state state { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AlsTray
|
|
||||||
{
|
|
||||||
public int capacity { get; set; }
|
|
||||||
public string model { get; set; }
|
|
||||||
public int doorOpen { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public state state { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class state
|
|
||||||
{
|
|
||||||
public int key { get; set; }
|
|
||||||
public string description { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LCModuleInfo
|
|
||||||
{
|
|
||||||
List<LCModule> modules { get; set; } // 模块列表
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LCModule
|
|
||||||
{
|
|
||||||
public string moduleId { get; set; } // 模块ID
|
|
||||||
public string moduleName { get; set; } // 模块名称
|
|
||||||
public state emfSummary { get; set; } // EMF摘要状态
|
|
||||||
public state error { get; set; } // 错误状态
|
|
||||||
public state notReady { get; set; } // 未就绪状态
|
|
||||||
public state connection { get; set; } // 连接状态
|
|
||||||
public long postTime { get; set; } // 发布时间(时间戳)
|
|
||||||
public long methodPostTime { get; set; } // 方法发布时间(时间戳)
|
|
||||||
public long runtime { get; set; } // 运行时间(可能是毫秒)
|
|
||||||
public long methodRuntime { get; set; } // 方法运行时间(可能是毫秒)
|
|
||||||
public string runState { get; set; } // 运行状态(如"Running"、"Stopped")
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EmptyData
|
|
||||||
{
|
|
||||||
// 无需任何属性,仅作为占位符匹配JSON中的空对象
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BottleVolumesResponse
|
|
||||||
{
|
|
||||||
public List<bottleVolume> bottleVolumes { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class bottleVolume
|
|
||||||
{
|
|
||||||
public string name { get; set; }
|
|
||||||
public int current { get; set; }
|
|
||||||
public int maximum { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class compose
|
|
||||||
{
|
|
||||||
public int additionalProp1 { get; set; }
|
|
||||||
public int additionalProp2 { get; set; }
|
|
||||||
public int additionalProp3 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class purgeParameters
|
|
||||||
{
|
|
||||||
public int duration { get; set; }
|
|
||||||
public int flow { get; set; }
|
|
||||||
public compose drawersOpen { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class purgeState
|
|
||||||
{
|
|
||||||
public bool isPurging { get; set; }
|
|
||||||
public int remainingPurgeTime { get; set; }
|
|
||||||
public purgeParameters purgeParameters { get; set; }
|
|
||||||
public bool isConditioning { get; set; }
|
|
||||||
public int remainingConditionTime { get; set; }
|
|
||||||
public int conditionTime { get; set; }
|
|
||||||
public bool isPriming { get; set; }
|
|
||||||
public int elapsedPrimeTime { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class purgeCleaningParam
|
|
||||||
{
|
|
||||||
public int duration { get; set; }
|
|
||||||
public int flow { get; set; }
|
|
||||||
public compose compositions { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class wasteVolume
|
|
||||||
{
|
|
||||||
public int current { get; set; }
|
|
||||||
public int maximum { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PlateInfo
|
|
||||||
{
|
|
||||||
public string id { get; set; }
|
|
||||||
public string displayName { get; set; }
|
|
||||||
public bool isPlate { get; set; }
|
|
||||||
public int numLocation { get; set; }
|
|
||||||
[JsonPropertyName("readonly")]
|
|
||||||
public bool rreadonly { get; set; }
|
|
||||||
public string xml { get; set; }
|
|
||||||
public int numRows { get; set; }
|
|
||||||
public int numCols { get; set; }
|
|
||||||
public int isLinear { get; set; }
|
|
||||||
public int rowStart { get; set; }
|
|
||||||
public int colStart { get; set; }
|
|
||||||
public int start { get; set; }
|
|
||||||
public string original1 { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class platePlacement
|
|
||||||
{
|
|
||||||
public string moduleId { get; set; }
|
|
||||||
public string moduleName { get; set; }
|
|
||||||
public string state { get; set; }
|
|
||||||
public string summary { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class limsSamples
|
|
||||||
{
|
|
||||||
public string id { get; set; }
|
|
||||||
public string barCode { get; set; }
|
|
||||||
public string type { get; set; }
|
|
||||||
public string collectDate { get; set; }
|
|
||||||
public string name { get; set; }
|
|
||||||
public string equipment { get; set; }
|
|
||||||
public string sampleSite { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public string batchId { get; set; }
|
|
||||||
public string addDateTime { get; set; }
|
|
||||||
public List<viaParam> vialList { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class viaParam
|
|
||||||
{
|
|
||||||
public string id { get; set; }
|
|
||||||
public string type { get; set; }
|
|
||||||
public string barCode { get; set; }
|
|
||||||
public string sampleBarCode { get; set; }
|
|
||||||
public string sampleId { get; set; }
|
|
||||||
public string labName { get; set; }
|
|
||||||
public string analysisProject { get; set; }
|
|
||||||
public string analysisMethod { get; set; }
|
|
||||||
public int analysisTimeInSecond { get; set; }
|
|
||||||
public string testCode { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public int priority { get; set; }
|
|
||||||
public string addDateTime { get; set; }
|
|
||||||
public string placeOnInstrumentDateTime { get; set; }
|
|
||||||
public int detReportFlag { get; set; }
|
|
||||||
public string limsId1 { get; set; }
|
|
||||||
public string limsId2 { get; set; }
|
|
||||||
public string limsId3 { get; set; }
|
|
||||||
public string desription { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleItem
|
|
||||||
{
|
|
||||||
public string id { get; set; }
|
|
||||||
public string type { get; set; }
|
|
||||||
public string barCode { get; set; }
|
|
||||||
public string sampleBarCode { get; set; }
|
|
||||||
public string sampleId { get; set; }
|
|
||||||
public string labName { get; set; }
|
|
||||||
public string analysisProject { get; set; }
|
|
||||||
public string analysisMethod { get; set; }
|
|
||||||
public int analysisTimeInSecond { get; set; }
|
|
||||||
public string testCode { get; set; }
|
|
||||||
public string status { get; set; }
|
|
||||||
public int priority { get; set; }
|
|
||||||
public string addDateTime { get; set; }
|
|
||||||
public string placeOnInstrumentDateTime { get; set; }
|
|
||||||
public int detReportFlag { get; set; }
|
|
||||||
public string limsId1 { get; set; }
|
|
||||||
public string limsId2 { get; set; }
|
|
||||||
public string limsId3 { get; set; }
|
|
||||||
public string desription { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,305 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Web;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// http://192.168.50.20:8888/swagger/index.html
|
|
||||||
/// </summary>
|
|
||||||
public sealed class AgvService : ConnectorBase, IConnection, IDisposable, IConnectionAsync
|
|
||||||
{
|
|
||||||
public AgvService()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(args is [string hostname, ..])
|
|
||||||
{
|
|
||||||
this._hostname = hostname.Trim('/');
|
|
||||||
this._httpService = new HttpClientEx { StringEncoder = Encoding.UTF8, BaseAddress = new Uri(this._hostname) };
|
|
||||||
this._httpService.Timeout = TimeSpan.FromSeconds(5);
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
await Task.Delay(0);
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _hostname = "";
|
|
||||||
|
|
||||||
private HttpClientEx _httpService;
|
|
||||||
public decimal ChargeVolume { get; set; } // 电量 0-1 即为 100%为满电
|
|
||||||
public string CurrentStationName { get; set; } = string.Empty;
|
|
||||||
public bool IsInChargeLocation => false;
|
|
||||||
public bool IsInWaitLocation => false;
|
|
||||||
|
|
||||||
public string ChargeLocationCode { get; set; }
|
|
||||||
public string WaitLocationCode { get; set; }
|
|
||||||
|
|
||||||
public string TargetLocation = "";
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Status
|
|
||||||
|
|
||||||
public async Task<bool> CheckMoveDone()
|
|
||||||
{
|
|
||||||
var currStation= await this.ReadCurrentStation();
|
|
||||||
if(string.IsNullOrWhiteSpace(currStation) || string.IsNullOrWhiteSpace(this.TargetLocation))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return string.Equals(currStation, this.TargetLocation, StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
}
|
|
||||||
public async Task<bool> CheckMoveing()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.CurrentStationName = await this.ReadCurrentStation();
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Status
|
|
||||||
|
|
||||||
#region Init
|
|
||||||
|
|
||||||
public async void Comfirmloc()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = "/RobotControl/Comfirmloc";
|
|
||||||
var response = await this._httpService.PostJsonAsync(apiName, string.Empty);
|
|
||||||
this.Logger.LogDebug(response);
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Lock(string name = "mega")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = this._hostname + "/RobotConfig/Lock";
|
|
||||||
// var args = new { nick_name = name };
|
|
||||||
//var response = await this._httpService.PostJsonAsync(apiName, args.ToJson());
|
|
||||||
IDictionary<string, string> argdict = new Dictionary<string, string>();
|
|
||||||
argdict.Add("nick_name", name);
|
|
||||||
apiName = this._httpService.UrlCombine(apiName, argdict);
|
|
||||||
var response = await this._httpService.PostJsonAsync(apiName, string.Empty);
|
|
||||||
this.Logger.LogInformation(response);
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Unlock()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = "/RobotConfig/Unlock";
|
|
||||||
var response = await this._httpService.PutAsync(apiName, null);
|
|
||||||
|
|
||||||
if(response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
this.Logger.LogInformation($"释放控制权");
|
|
||||||
}
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Init
|
|
||||||
|
|
||||||
#region 状态
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// AGV电量
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<string> ReadBattery()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = this._hostname + "/RobotStatus/Battery";
|
|
||||||
IDictionary<string, string> argdict = new Dictionary<string, string>();
|
|
||||||
argdict.Add("simple", false.ToString());
|
|
||||||
apiName = this._httpService.UrlCombine(apiName, argdict);
|
|
||||||
var response = await this._httpService.GetStringAsync(apiName);
|
|
||||||
var batteryLevel = response.GetJsonValueByToken<string>("data.battery_level");
|
|
||||||
return batteryLevel;
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReadCurrentStation()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = this._hostname + "/RobotStatus/Loc";
|
|
||||||
IDictionary<string, string> argDict = new Dictionary<string, string>();
|
|
||||||
argDict.Add("simple", false.ToString());
|
|
||||||
apiName = this._httpService.UrlCombine(apiName, argDict);
|
|
||||||
var response = await this._httpService.GetStringAsync(apiName);
|
|
||||||
var currentStation = response.GetJsonValueByToken<string>("data.current_station");
|
|
||||||
return currentStation;
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> ReadTaskStatus()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//https://support.seer-group.com/d/1674676593139699713.html
|
|
||||||
string apiName = this._hostname + "/RobotStatus/Task";
|
|
||||||
// IDictionary<string, string> argdict = new Dictionary<string, string>();
|
|
||||||
// argdict.Add("simple", false.ToString());
|
|
||||||
apiName = this._httpService.UrlCombine(apiName, null);
|
|
||||||
var response = await this._httpService.GetStringAsync(apiName);
|
|
||||||
var taskStatus = response.GetJsonValueByToken<string>("data.task_status");
|
|
||||||
return new[] { "2", "3" }.Contains(taskStatus);
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ClearAllErrors()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = this._hostname + "/RobotConfig/Clearallerrors";
|
|
||||||
// IDictionary<string, string> argdict = new Dictionary<string, string>();
|
|
||||||
// argdict.Add("simple", false.ToString());
|
|
||||||
apiName = this._httpService.UrlCombine(apiName, null);
|
|
||||||
var response = await this._httpService.GetStringAsync(apiName);
|
|
||||||
response.GetJsonValueByToken<string>("data.ret_code");
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Move
|
|
||||||
|
|
||||||
private async Task<string> LoadCurrentLocationAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string apiName = this._hostname + "/RobotStatus/Loc";
|
|
||||||
var response = await this._httpService.GetStringAsync(apiName);
|
|
||||||
var currentStation = response.GetJsonValueByToken<string>("data.current_station");
|
|
||||||
return currentStation;
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void MoveToLocation(string location)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.TargetLocation = location;
|
|
||||||
this.Comfirmloc();
|
|
||||||
string apiName = this._hostname + "/RobotTask/Gotarget";
|
|
||||||
string sourceId = "SELF_POSITION";
|
|
||||||
|
|
||||||
// sourceId = await this.LoadCurrentLocationAsync();
|
|
||||||
var locationItem = new { id = location, source_id = sourceId, task_id = $"goto_{DateTime.Now:yyyyMMdd_HHmmssfff}_{location}" };
|
|
||||||
var jsonRaw = locationItem.ToJson(true);
|
|
||||||
var response = await this._httpService.PostJsonAsync(apiName, jsonRaw);
|
|
||||||
this.Logger.LogInformation(response);
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 指定路过某点到某点
|
|
||||||
/// 优点: 会按照任务发送队列执行
|
|
||||||
/// 缺点: 假如同命令连续发送多次,可能会造成首次命令执行后原地掉头导致碰撞风险;
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="locations"></param>
|
|
||||||
public async void MoveToLocation(IList<string> locations)
|
|
||||||
{
|
|
||||||
if(locations == null || !locations.Any())
|
|
||||||
return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.Comfirmloc();
|
|
||||||
string apiName = this._hostname + "/RobotTask/Gotargetlist";
|
|
||||||
string sourceId = "SELF_POSITION";
|
|
||||||
|
|
||||||
sourceId = await this.LoadCurrentLocationAsync();
|
|
||||||
IList<object> orderList = new List<object>();
|
|
||||||
for(var index = 0; index < locations.Count; index++)
|
|
||||||
{
|
|
||||||
string item = locations[index];
|
|
||||||
if(index > 0)
|
|
||||||
{
|
|
||||||
sourceId = locations[index - 1];
|
|
||||||
}
|
|
||||||
var locationItem = new { id = item, source_id = sourceId, task_id = $"goto_{DateTime.Now:yyyyMMdd_HHmmssfff}_{item}" };
|
|
||||||
orderList.Add(locationItem);
|
|
||||||
}
|
|
||||||
var args = new { move_task_list = orderList };
|
|
||||||
var jsonRaw = args.ToJson(true);
|
|
||||||
var response = await this._httpService.PostJsonAsync(apiName, jsonRaw);
|
|
||||||
this.Logger.LogInformation(response);
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Move
|
|
||||||
|
|
||||||
#region Watcher
|
|
||||||
|
|
||||||
#endregion Watcher
|
|
||||||
}
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.Contract.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices;
|
|
||||||
|
|
||||||
public class CameraLightService : DeviceBase, IConnection, IDisposable, IConnectionAsync
|
|
||||||
{
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string portName = "COM1";
|
|
||||||
if(args is [string portIndex, ..])
|
|
||||||
{
|
|
||||||
portName = portIndex;
|
|
||||||
}
|
|
||||||
this.CoreService = coreService;
|
|
||||||
this.SerialPortManger = new SerialPortManger();
|
|
||||||
bool isSuccess = this.SerialPortManger.Open(portName);
|
|
||||||
this.SerialPortManger.SetPort(portName, 19200, DataBits.Eight, StopBits.One, Parity.None);
|
|
||||||
// bool isSuccess = this.SerialPortManger.Open();
|
|
||||||
// int retCode = ControllerDllCSharp.ClassLibControllerDll.CreateSerialPort(3, ref this._controllerHandle); //创建串口
|
|
||||||
this.Logger.LogDebug($"打开串口Com3{(isSuccess ? "成功" : "失败")}");
|
|
||||||
} catch(Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region properties
|
|
||||||
public SerialPortManger SerialPortManger { get; set; }
|
|
||||||
public ConnectionState ConnectionState { get; set; }
|
|
||||||
public event EventHandler<ConnectionState> ConnectChanged;
|
|
||||||
|
|
||||||
public TimeSpan Timeout { get; set; }
|
|
||||||
|
|
||||||
public bool IsConnected => SerialPortManger?.IsOpen ?? false;
|
|
||||||
|
|
||||||
#endregion properties
|
|
||||||
|
|
||||||
#region functions
|
|
||||||
|
|
||||||
public async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetValue(byte value, params int[] channelIndexs)
|
|
||||||
{
|
|
||||||
if(channelIndexs.Length == 0)
|
|
||||||
channelIndexs = new[] { 1, 2, 3, 4 };
|
|
||||||
var channelChars = new[] { "0", "A", "B", "C", "D" };
|
|
||||||
List<string> cmds = channelIndexs.Select(index => $"S{channelChars[index]}{value:D4}#").ToList();
|
|
||||||
string cmdLine = string.Join("", cmds);
|
|
||||||
var code = await this.SerialPortManger.WriteAndGetReplyAsync(cmdLine, TimeSpan.FromSeconds(1.5));
|
|
||||||
this.Logger.LogDebug($"设置光源cmd:{cmds} result:{code}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
this.SerialPortManger.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// TODO release managed resources here
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion functions
|
|
||||||
|
|
||||||
#region events
|
|
||||||
|
|
||||||
#endregion events
|
|
||||||
}
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Modbus;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class CameraTcpClientService : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null)
|
|
||||||
return;
|
|
||||||
var msg = tcpMsg.ParseStirng();
|
|
||||||
if (string.IsNullOrEmpty(msg)) return;
|
|
||||||
this.Logger.LogInformation($"接收到配置站相机_{this.Name}数据:{msg?.Trim()}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 触发相机拍照
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeout"></param>
|
|
||||||
/// <param name="runSwitch"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> TriggerCamera(string sn, string bottleType, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string command = $"S,{sn},{bottleType},Start,T";
|
|
||||||
var tcpMessage =await ConnectorAdapter.WriteAndGetReplyAsync(command, timeout);
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return false;
|
|
||||||
if (tcpMessage.ParseStirng() == "S,End,T") return true;
|
|
||||||
else return false;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
base.Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService", "Reset", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class CentreControlService
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
{
|
|
||||||
"ExtendedData": {
|
|
||||||
"inputs": [
|
|
||||||
"http://192.168.5.11:51156/LabX/SystemIntegrationService/mex"
|
|
||||||
],
|
|
||||||
"collectionTypes": [
|
|
||||||
"System.Array",
|
|
||||||
"System.Collections.Generic.Dictionary`2"
|
|
||||||
],
|
|
||||||
"namespaceMappings": [
|
|
||||||
"*, ServiceReference1"
|
|
||||||
],
|
|
||||||
"references": [
|
|
||||||
"CommunityToolkit.Mvvm, {CommunityToolkit.Mvvm, 8.4.0}",
|
|
||||||
"CsvHelper, {CsvHelper, 33.1.0}",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\Common.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.C00225155.DataAccess.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.C00225155.Entities.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.Connections.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.Contract.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.ControlDevices.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.DataAccess.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.Entities.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.Logger.dll",
|
|
||||||
"D:\\C00225155_20260319\\C00225155\\C00225155\\MegaRobo.C00225155\\MegaRobo.C00225155.ControlDevices\\bin\\Debug\\net7.0-windows\\MegaRobo.Utility.dll",
|
|
||||||
"DmProvider, {SqlSugarCore.Dm, 1.2.0}",
|
|
||||||
"Kdbndp, {SqlSugarCore.Kdbndp, 7.4.0}",
|
|
||||||
"LightInject, {LightInject, 6.6.4}",
|
|
||||||
"Microsoft.Data.SqlClient, {Microsoft.Data.SqlClient, 2.1.4}",
|
|
||||||
"Microsoft.Data.Sqlite, {Microsoft.Data.Sqlite.Core, 7.0.5}",
|
|
||||||
"Microsoft.Extensions.ObjectPool, {Microsoft.Extensions.ObjectPool, 6.0.16}",
|
|
||||||
"Microsoft.IdentityModel.JsonWebTokens, {Microsoft.IdentityModel.JsonWebTokens, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Logging, {Microsoft.IdentityModel.Logging, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Protocols, {Microsoft.IdentityModel.Protocols, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect, {Microsoft.IdentityModel.Protocols.OpenIdConnect, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Protocols.WsTrust, {Microsoft.IdentityModel.Protocols.WsTrust, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Tokens, {Microsoft.IdentityModel.Tokens, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Tokens.Saml, {Microsoft.IdentityModel.Tokens.Saml, 6.8.0}",
|
|
||||||
"Microsoft.IdentityModel.Xml, {Microsoft.IdentityModel.Xml, 6.8.0}",
|
|
||||||
"Microsoft.Win32.Primitives, {Microsoft.Win32.Primitives, 4.3.0}",
|
|
||||||
"Microsoft.Win32.SystemEvents, {Microsoft.Win32.SystemEvents, 6.0.0}",
|
|
||||||
"Modbus, {NModbus4.NetCore, 3.0.0}",
|
|
||||||
"MySqlConnector, {MySqlConnector, 2.2.5}",
|
|
||||||
"NETStandard.HttpListener, {NETStandard.HttpListener, 1.0.3.5}",
|
|
||||||
"Newtonsoft.Json, {Newtonsoft.Json, 13.0.3}",
|
|
||||||
"Npgsql, {Npgsql, 5.0.7}",
|
|
||||||
"Oracle.ManagedDataAccess, {Oracle.ManagedDataAccess.Core, 3.21.100}",
|
|
||||||
"SQLitePCLRaw.batteries_v2, {SQLitePCLRaw.bundle_e_sqlite3, 2.1.4}",
|
|
||||||
"SQLitePCLRaw.core, {SQLitePCLRaw.core, 2.1.4}",
|
|
||||||
"SQLitePCLRaw.provider.e_sqlite3, {SQLitePCLRaw.provider.e_sqlite3, 2.1.4}",
|
|
||||||
"SqlSugar, {SqlSugarCore, 5.1.4.110}",
|
|
||||||
"System.AppContext, {System.AppContext, 4.3.0}",
|
|
||||||
"System.CodeDom, {System.CodeDom, 8.0.0}",
|
|
||||||
"System.Collections, {System.Collections, 4.3.0}",
|
|
||||||
"System.Collections.Concurrent, {System.Collections.Concurrent, 4.3.0}",
|
|
||||||
"System.ComponentModel.Annotations, {System.ComponentModel.Annotations, 5.0.0}",
|
|
||||||
"System.Configuration.ConfigurationManager, {System.Configuration.ConfigurationManager, 6.0.0}",
|
|
||||||
"System.Console, {System.Console, 4.3.0}",
|
|
||||||
"System.Data.Common, {System.Data.Common, 4.3.0}",
|
|
||||||
"System.Diagnostics.Debug, {System.Diagnostics.Debug, 4.3.0}",
|
|
||||||
"System.Diagnostics.PerformanceCounter, {System.Diagnostics.PerformanceCounter, 6.0.1}",
|
|
||||||
"System.Diagnostics.Tools, {System.Diagnostics.Tools, 4.3.0}",
|
|
||||||
"System.Diagnostics.Tracing, {System.Diagnostics.Tracing, 4.3.0}",
|
|
||||||
"System.DirectoryServices, {System.DirectoryServices, 6.0.1}",
|
|
||||||
"System.DirectoryServices.Protocols, {System.DirectoryServices.Protocols, 6.0.1}",
|
|
||||||
"System.Drawing.Common, {System.Drawing.Common, 6.0.0}",
|
|
||||||
"System.Formats.Asn1, {System.Formats.Asn1, 6.0.0}",
|
|
||||||
"System.Globalization, {System.Globalization, 4.3.0}",
|
|
||||||
"System.Globalization.Calendars, {System.Globalization.Calendars, 4.3.0}",
|
|
||||||
"System.IdentityModel.Tokens.Jwt, {System.IdentityModel.Tokens.Jwt, 6.8.0}",
|
|
||||||
"System.IO, {System.IO, 4.3.0}",
|
|
||||||
"System.IO.Compression, {System.IO.Compression, 4.3.0}",
|
|
||||||
"System.IO.Compression.ZipFile, {System.IO.Compression.ZipFile, 4.3.0}",
|
|
||||||
"System.IO.FileSystem, {System.IO.FileSystem, 4.3.0}",
|
|
||||||
"System.IO.FileSystem.Primitives, {System.IO.FileSystem.Primitives, 4.3.0}",
|
|
||||||
"System.IO.Ports, {System.IO.Ports, 7.0.0}",
|
|
||||||
"System.Linq, {System.Linq, 4.3.0}",
|
|
||||||
"System.Linq.Expressions, {System.Linq.Expressions, 4.3.0}",
|
|
||||||
"System.Management, {System.Management, 8.0.0}",
|
|
||||||
"System.Net.Http, {System.Net.Http, 4.3.0}",
|
|
||||||
"System.Net.Primitives, {System.Net.Primitives, 4.3.0}",
|
|
||||||
"System.Net.Sockets, {System.Net.Sockets, 4.3.0}",
|
|
||||||
"System.ObjectModel, {System.ObjectModel, 4.3.0}",
|
|
||||||
"System.Reflection, {System.Reflection, 4.3.0}",
|
|
||||||
"System.Reflection.DispatchProxy, {System.Reflection.DispatchProxy, 4.7.1}",
|
|
||||||
"System.Reflection.Emit.ILGeneration, {System.Reflection.Emit.ILGeneration, 4.3.0}",
|
|
||||||
"System.Reflection.Emit.Lightweight, {System.Reflection.Emit.Lightweight, 4.3.0}",
|
|
||||||
"System.Reflection.Extensions, {System.Reflection.Extensions, 4.3.0}",
|
|
||||||
"System.Reflection.Primitives, {System.Reflection.Primitives, 4.3.0}",
|
|
||||||
"System.Resources.ResourceManager, {System.Resources.ResourceManager, 4.3.0}",
|
|
||||||
"System.Runtime, {System.Runtime, 4.3.0}",
|
|
||||||
"System.Runtime.Extensions, {System.Runtime.Extensions, 4.3.0}",
|
|
||||||
"System.Runtime.Handles, {System.Runtime.Handles, 4.3.0}",
|
|
||||||
"System.Runtime.InteropServices, {System.Runtime.InteropServices, 4.3.0}",
|
|
||||||
"System.Runtime.InteropServices.RuntimeInformation, {System.Runtime.InteropServices.RuntimeInformation, 4.3.0}",
|
|
||||||
"System.Runtime.Numerics, {System.Runtime.Numerics, 4.3.0}",
|
|
||||||
"System.Security.AccessControl, {System.Security.AccessControl, 6.0.0}",
|
|
||||||
"System.Security.Cryptography.Algorithms, {System.Security.Cryptography.Algorithms, 4.3.0}",
|
|
||||||
"System.Security.Cryptography.Cng, {System.Security.Cryptography.Cng, 4.5.0}",
|
|
||||||
"System.Security.Cryptography.Encoding, {System.Security.Cryptography.Encoding, 4.3.0}",
|
|
||||||
"System.Security.Cryptography.Pkcs, {System.Security.Cryptography.Pkcs, 6.0.1}",
|
|
||||||
"System.Security.Cryptography.Primitives, {System.Security.Cryptography.Primitives, 4.3.0}",
|
|
||||||
"System.Security.Cryptography.ProtectedData, {System.Security.Cryptography.ProtectedData, 6.0.0}",
|
|
||||||
"System.Security.Cryptography.X509Certificates, {System.Security.Cryptography.X509Certificates, 4.3.0}",
|
|
||||||
"System.Security.Cryptography.Xml, {System.Security.Cryptography.Xml, 6.0.1}",
|
|
||||||
"System.Security.Permissions, {System.Security.Permissions, 6.0.0}",
|
|
||||||
"System.Security.Principal.Windows, {System.Security.Principal.Windows, 5.0.0}",
|
|
||||||
"System.ServiceModel.Duplex, {System.ServiceModel.Duplex, 6.0.0}",
|
|
||||||
"System.ServiceModel.Federation, {System.ServiceModel.Federation, 6.0.0}",
|
|
||||||
"System.ServiceModel.Http, {System.ServiceModel.Http, 6.0.0}",
|
|
||||||
"System.ServiceModel.NetFramingBase, {System.ServiceModel.NetFramingBase, 6.0.0}",
|
|
||||||
"System.ServiceModel.NetTcp, {System.ServiceModel.NetTcp, 6.0.0}",
|
|
||||||
"System.ServiceModel.Primitives, {System.ServiceModel.Primitives, 6.0.0}",
|
|
||||||
"System.ServiceModel.Security, {System.ServiceModel.Security, 6.0.0}",
|
|
||||||
"System.Text.Encoding, {System.Text.Encoding, 4.3.0}",
|
|
||||||
"System.Text.Encoding.CodePages, {System.Text.Encoding.CodePages, 5.0.0}",
|
|
||||||
"System.Text.Encoding.Extensions, {System.Text.Encoding.Extensions, 4.3.0}",
|
|
||||||
"System.Text.RegularExpressions, {System.Text.RegularExpressions, 4.3.0}",
|
|
||||||
"System.Threading, {System.Threading, 4.3.0}",
|
|
||||||
"System.Threading.Tasks, {System.Threading.Tasks, 4.3.0}",
|
|
||||||
"System.Threading.Timer, {System.Threading.Timer, 4.3.0}",
|
|
||||||
"System.Windows.Extensions, {System.Windows.Extensions, 6.0.0}",
|
|
||||||
"System.Xml.ReaderWriter, {System.Xml.ReaderWriter, 4.3.0}",
|
|
||||||
"System.Xml.XDocument, {System.Xml.XDocument, 4.3.0}",
|
|
||||||
"System.Xml.XmlDocument, {System.Xml.XmlDocument, 4.3.0}"
|
|
||||||
],
|
|
||||||
"targetFramework": "net7.0-windows",
|
|
||||||
"typeReuseMode": "All"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,45 +0,0 @@
|
||||||
using MegaRobo.Connections.Web;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class HttpListenerProvider
|
|
||||||
{
|
|
||||||
public HttpListenerProvider(ILogger logger)
|
|
||||||
{
|
|
||||||
this._Logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private ILogger _Logger;
|
|
||||||
private readonly IDictionary<string, HttpListenerService> _sources = new ConcurrentDictionary<string, HttpListenerService>(StringComparer.CurrentCultureIgnoreCase);
|
|
||||||
|
|
||||||
public HttpListenerService GetOrAdd(string name, IPEndPoint host)
|
|
||||||
{
|
|
||||||
return this._sources.TryGetValue(name, out HttpListenerService service) ? service : this.Create(name, host);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpListenerService Create(string name, IPEndPoint host)
|
|
||||||
{
|
|
||||||
var service = new HttpListenerService();
|
|
||||||
service.Start(host);
|
|
||||||
if (this._sources.ContainsKey(name))
|
|
||||||
{
|
|
||||||
this._sources[name] = service;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this._sources.TryAdd(name, service);
|
|
||||||
}
|
|
||||||
this._Logger?.LogInformation($"已开启端口为[{host}]的Web请求监听");
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public sealed class HuichuanAc801Service : ModbusBase
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,301 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
|
||||||
using CsvHelper;
|
|
||||||
using CsvHelper.Configuration;
|
|
||||||
using Dm;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using ServiceReference1;
|
|
||||||
using SqlSugar;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using Task = System.Threading.Tasks.Task;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class LabxService
|
|
||||||
{
|
|
||||||
public Guid abortWaitingHeadTaskId = new Guid();
|
|
||||||
public BasicSystemIntegrationServiceClient _serviceClient;
|
|
||||||
public List<Instrument> Instruments { get; set; }
|
|
||||||
public Dictionary<Guid, Instrument> CurTaskID { get; set; }
|
|
||||||
public LabxService()
|
|
||||||
{
|
|
||||||
_serviceClient = new BasicSystemIntegrationServiceClient();
|
|
||||||
}
|
|
||||||
public async Task<List<Instrument>> GetInstruments(string instrumentName)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var instrument = await _serviceClient.GetThisInstrumentsByNameAsync(instrumentName);
|
|
||||||
return instrument.ToList();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"labx获取设备发生异常\r\n请联系供应商!!",
|
|
||||||
Content = $"{ex.ToString()}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void CreateNewTask(string methodName, string taskName)
|
|
||||||
{
|
|
||||||
//Get the method based on method user ID
|
|
||||||
Method method = await _serviceClient.GetThisMethodByUserDefinedIdAsync(methodName);
|
|
||||||
var taskId = _serviceClient.CreateTaskAsync(
|
|
||||||
method.BusinessId, taskName, false, new TaskParameterSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<TaskResultSet> CreateAndStartNewTaskMove(string methodName, string taskName, int holeNum, Instrument instrument)
|
|
||||||
{
|
|
||||||
Method method = await _serviceClient.GetThisMethodByUserDefinedIdAsync(methodName);
|
|
||||||
var methodparameter = await _serviceClient.GetMethodMetaDataAsync(method.BusinessId);
|
|
||||||
TaskParameterSet taskParameterSet = new TaskParameterSet();
|
|
||||||
IntegerTypeMethodParameter parameter = new IntegerTypeMethodParameter();
|
|
||||||
parameter.MethodFunctionName = methodparameter.MethodParameters[0].MethodFunctionName;
|
|
||||||
parameter.MethodFunctionPropertyName = methodparameter.MethodParameters[0].MethodFunctionPropertyName;
|
|
||||||
parameter.Value = holeNum;
|
|
||||||
taskParameterSet.GlobalMethodParameters = new MethodParameter[1];
|
|
||||||
taskParameterSet.GlobalMethodParameters[0] = parameter;
|
|
||||||
|
|
||||||
Guid taskId = await _serviceClient.CreateTaskAsync(method.BusinessId, taskName, false, taskParameterSet);
|
|
||||||
await _serviceClient.StartTaskAsync(taskId, instrument.InstrumentId);
|
|
||||||
//CurTaskID.Add( taskId, instrument );
|
|
||||||
TaskState taskState;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
taskState = await _serviceClient.GetTaskStateAsync(taskId);
|
|
||||||
if (taskState.State != TaskStateType.Aborted && taskState.State != TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
} while (taskState.State != TaskStateType.Completed && taskState.State != TaskStateType.Aborted);
|
|
||||||
if (taskState.State == TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
var result = await _serviceClient.GetTaskResultsAsync(taskId);
|
|
||||||
//CurTaskID.Remove(taskId);
|
|
||||||
//var RE= result.Samples[0].Results[0].Scalar.ValueMember;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 等待放置加样头
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrument"></param>
|
|
||||||
/// <param name="methodName"></param>
|
|
||||||
/// <param name="taskName"></param>
|
|
||||||
/// <param name="defaultvalue"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<TaskResultSet> StartWaitingForHead(Instrument instrument, string methodName = "Dosing Head", string taskName = "Dosing Head", decimal defaultvalue = 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Method method = await _serviceClient.GetThisMethodByUserDefinedIdAsync(methodName);
|
|
||||||
var methodparameter = await _serviceClient.GetMethodMetaDataAsync(method.BusinessId);
|
|
||||||
|
|
||||||
TaskParameterSet taskParameterSet = new TaskParameterSet
|
|
||||||
{
|
|
||||||
GlobalMethodParameters = new MethodParameter[4]
|
|
||||||
{
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Number1",MethodFunctionPropertyName = "DefaultValue",Value = defaultvalue},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "TargetWeight",Value = 5000m}, //单位是mg
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingUpperTolerance",Value = 1m},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingLowerTolerance",Value = 1m}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Guid taskId = await _serviceClient.CreateTaskAsync(method.BusinessId, taskName, false, taskParameterSet);
|
|
||||||
abortWaitingHeadTaskId = taskId;
|
|
||||||
await _serviceClient.StartTaskAsync(taskId, instrument.InstrumentId);
|
|
||||||
TaskState taskState;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
taskState = await _serviceClient.GetTaskStateAsync(taskId);
|
|
||||||
if (taskState.State != TaskStateType.Running)
|
|
||||||
{
|
|
||||||
await Task.Delay(2000);
|
|
||||||
}
|
|
||||||
} while (taskState.State != TaskStateType.Running);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"梅特勒粉末研磨模块异常",
|
|
||||||
Content = $"{ex.ToString()}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停止等待加样头
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task AbortWaitingForHead()
|
|
||||||
{
|
|
||||||
await _serviceClient.AbortTaskAsync(abortWaitingHeadTaskId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 梅特勒粉末天平模块步骤
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrument"></param>
|
|
||||||
/// <param name="methodName"></param>
|
|
||||||
/// <param name="taskName"></param>
|
|
||||||
/// <param name="defaultvalue"></param>
|
|
||||||
/// <param name="targetweight">目标重量,单位mg</param>
|
|
||||||
/// <param name="upT"></param>
|
|
||||||
/// <param name="dnT"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<double> MTPowderModuleControlStep(Instrument instrument, string methodName, string taskName, decimal defaultvalue = 0, decimal targetweight = 0, decimal upT = 0, decimal dnT = 0)
|
|
||||||
{
|
|
||||||
double addResult = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
Method method = await _serviceClient.GetThisMethodByUserDefinedIdAsync(methodName);
|
|
||||||
var methodparameter = await _serviceClient.GetMethodMetaDataAsync(method.BusinessId);
|
|
||||||
//defaultvalue= 0 关门 =1开门 =2置零 =3去皮 =4 开始加样 =5 粉末头复位
|
|
||||||
TaskParameterSet taskParameterSet = new TaskParameterSet
|
|
||||||
{
|
|
||||||
GlobalMethodParameters = new MethodParameter[4]
|
|
||||||
{
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Number1",MethodFunctionPropertyName = "DefaultValue",Value = defaultvalue},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "TargetWeight",Value = targetweight}, //单位是mg
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingUpperTolerance",Value = upT},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingLowerTolerance",Value = dnT}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Guid taskId = await _serviceClient.CreateTaskAsync(method.BusinessId, taskName, false, taskParameterSet);
|
|
||||||
await _serviceClient.StartTaskAsync(taskId, instrument.InstrumentId);
|
|
||||||
TaskState taskState;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
taskState = await _serviceClient.GetTaskStateAsync(taskId);
|
|
||||||
if (taskState.State != TaskStateType.Aborted && taskState.State != TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
await Task.Delay(2000);
|
|
||||||
}
|
|
||||||
} while (taskState.State != TaskStateType.Completed && taskState.State != TaskStateType.Aborted);
|
|
||||||
if (defaultvalue == 4 && taskState.State == TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
var result = await _serviceClient.GetTaskResultsAsync(taskId);
|
|
||||||
//CurTaskID.Remove(taskId);
|
|
||||||
decimal RE = result.TaskResults[1].Scalar.ValueMember;
|
|
||||||
addResult = (double)RE;
|
|
||||||
return addResult;
|
|
||||||
}
|
|
||||||
return addResult;
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"梅特勒粉末研磨模块异常",
|
|
||||||
Content = $"{ex.ToString()}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
return addResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加粉控制
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instrument"></param>
|
|
||||||
/// <param name="methodName"></param>
|
|
||||||
/// <param name="taskName"></param>
|
|
||||||
/// <param name="defaultValue"></param>
|
|
||||||
/// <param name="height"></param>
|
|
||||||
/// <param name="targetweight"></param>
|
|
||||||
/// <param name="upT"></param>
|
|
||||||
/// <param name="dnT"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<double> MTPowderModuleAddPowder(Instrument instrument, string methodName, string taskName, decimal defaultValue, decimal height = 140.8m, decimal targetweight = 0, decimal upT = 0, decimal dnT = 0)
|
|
||||||
{
|
|
||||||
double addResult = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
Method method = await _serviceClient.GetThisMethodByUserDefinedIdAsync(methodName);
|
|
||||||
var methodparameter = await _serviceClient.GetMethodMetaDataAsync(method.BusinessId);
|
|
||||||
//defaultvalue= 0 关门 =1开门 =2置零 =3去皮 =4 开始加样 =5 粉末头复位
|
|
||||||
TaskParameterSet taskParameterSet = new TaskParameterSet
|
|
||||||
{
|
|
||||||
GlobalMethodParameters = new MethodParameter[4]
|
|
||||||
{
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosingsettings1",MethodFunctionPropertyName = "AbsoluteDosingPositionSpan",Value = height},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "TargetWeight",Value = targetweight}, //单位是mg
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingUpperTolerance",Value = upT},
|
|
||||||
new DecimalTypeMethodParameter{MethodFunctionName = "Dosing1",MethodFunctionPropertyName = "DosingLowerTolerance",Value = dnT}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Guid taskId = await _serviceClient.CreateTaskAsync(method.BusinessId, taskName, false, taskParameterSet);
|
|
||||||
await _serviceClient.StartTaskAsync(taskId, instrument.InstrumentId);
|
|
||||||
TaskState taskState;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
taskState = await _serviceClient.GetTaskStateAsync(taskId);
|
|
||||||
if (taskState.State != TaskStateType.Aborted && taskState.State != TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
await Task.Delay(2000);
|
|
||||||
}
|
|
||||||
} while (taskState.State != TaskStateType.Completed && taskState.State != TaskStateType.Aborted);
|
|
||||||
if (defaultValue == 4 && taskState.State == TaskStateType.Completed)
|
|
||||||
{
|
|
||||||
var result = await _serviceClient.GetTaskResultsAsync(taskId);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//CurTaskID.Remove(taskId);
|
|
||||||
decimal RE = result.TaskResults[0].Scalar.ValueMember;
|
|
||||||
addResult = (double)RE;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
//MessageBox.Show($"加粉异常-{ex.Message}");
|
|
||||||
addResult = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addResult;
|
|
||||||
}
|
|
||||||
return addResult;
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
WeakReferenceMessenger.Default.Send(new ConfirmMessage()
|
|
||||||
{
|
|
||||||
Header = $"梅特勒粉末研磨模块异常",
|
|
||||||
Content = $"{ex.ToString()}",
|
|
||||||
OkButtonContent = "继续",
|
|
||||||
CancelButtonContent = "取消",
|
|
||||||
});
|
|
||||||
return addResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.Connections\MegaRobo.Connections.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.ControlDevices\MegaRobo.ControlDevices.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.LS60141.Entities\MegaRobo.LS60141.Entities.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="HansRobotLibrarys">
|
|
||||||
<HintPath>libs\HansRobotLibrarys.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Contract">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Contract.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Entities">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Entities.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Logger">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Logger.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Utility">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Utility.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="JodellTool\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="libs\jodellTool.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\jodellTool.lib">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\jodellTool_x64.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\jodellTool_x64.lib">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\x64\jodellTool.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\x64\jodellTool.lib">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\x86\jodellTool.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="libs\x86\jodellTool.lib">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.Connections\MegaRobo.Connections.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\Common\MegaRobo.Common\MegaRobo.ControlDevices\MegaRobo.ControlDevices.csproj" />
|
|
||||||
<ProjectReference Include="..\Common\Common.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.DataAccess\MegaRobo.C00225155.DataAccess.csproj" />
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.Entities\MegaRobo.C00225155.Entities.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="MegaRobo.Contract">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Contract.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Entities">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Entities.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Logger">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Logger.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Utility">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Utility.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CsvHelper" Version="33.1.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.ApiDescription.Client" Version="7.0.2">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
|
||||||
<PackageReference Include="NSwag.ApiDescription.Client" Version="13.18.2">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="System.Management" Version="8.0.0" />
|
|
||||||
<PackageReference Include="System.ServiceModel.Duplex" Version="6.0.*" />
|
|
||||||
<PackageReference Include="System.ServiceModel.Federation" Version="6.0.*" />
|
|
||||||
<PackageReference Include="System.ServiceModel.Http" Version="6.0.*" />
|
|
||||||
<PackageReference Include="System.ServiceModel.NetTcp" Version="6.0.*" />
|
|
||||||
<PackageReference Include="System.ServiceModel.Security" Version="6.0.*" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
using MegaRobo.Connections.Adapters;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices.Scanner
|
|
||||||
{
|
|
||||||
public abstract class ScannerCodeBase<TConnectorAdapter> : ConnectorBase<TConnectorAdapter>, IScannerCode where TConnectorAdapter : ConnectorAdapter
|
|
||||||
{
|
|
||||||
public string Code { get; protected set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开始的指令
|
|
||||||
/// </summary>
|
|
||||||
protected virtual string StartCommandLine { get; set; } = "Start";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 停止指令
|
|
||||||
/// </summary>
|
|
||||||
protected virtual string StopCommandLine { get; set; } = "Stop";
|
|
||||||
|
|
||||||
public virtual event EventHandler<string> ScannedEvent;
|
|
||||||
public event EventHandler<TcpMessage> DataReceived;
|
|
||||||
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
switch (args.Length)
|
|
||||||
{
|
|
||||||
case >= 1 when args[0] is TConnectorAdapter connector:
|
|
||||||
this.ConnectorAdapter = connector;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await this.ReconnectAsync();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
return ex.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Task<string> ReadAsnyc(TimeSpan timeout);
|
|
||||||
|
|
||||||
public virtual void Start()
|
|
||||||
{
|
|
||||||
byte[] sendBytes = this.ConnectorAdapter.StringEncoder.GetBytes(this.StartCommandLine);
|
|
||||||
this.Write(sendBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Stop()
|
|
||||||
{
|
|
||||||
byte[] sendBytes = this.ConnectorAdapter.StringEncoder.GetBytes(this.StopCommandLine);
|
|
||||||
this.Write(sendBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Write(byte[] data)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (this.ConnectorAdapter)
|
|
||||||
{
|
|
||||||
case MegaTcpClient megaTcpClient:
|
|
||||||
megaTcpClient.Connector.GetStream().Write(data, 0, data.Length);
|
|
||||||
break;
|
|
||||||
// case MegaTcpClientBase tcpClientBase:
|
|
||||||
// tcpClientBase.Connector.Write(data);
|
|
||||||
// break;
|
|
||||||
// case UdpClientBase udpClientBase:
|
|
||||||
// udpClientBase.Connector.Send(data, data.Length);
|
|
||||||
// break;
|
|
||||||
// case SerialPortBase serialPortBase:
|
|
||||||
// serialPortBase.Connector.Write(data, 0, data.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void OnScannedEvent(string code)
|
|
||||||
{
|
|
||||||
this.ScannedEvent?.Invoke(this, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnDataReceived(object sender, TcpMessage msg)
|
|
||||||
{
|
|
||||||
this.DataReceived?.Invoke(sender, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract string ParseMessage(object data, byte[] sourceData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices.Scanner
|
|
||||||
{
|
|
||||||
public abstract class ScannerCodeOfTcpClientBase : ScannerCodeBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
switch (args.Length)
|
|
||||||
{
|
|
||||||
case >= 1 when args[0] is IPEndPoint remoteHost:
|
|
||||||
this.ConnectorAdapter = new MegaTcpClient { Logger = coreService.Logger, Name = this.Name };
|
|
||||||
if (this.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
this.ConnectorAdapter.DataReceived += this.ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
this.ConnectionState = await this.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
return ex.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage e)
|
|
||||||
{
|
|
||||||
var msg = e.ParseStirng();
|
|
||||||
if (string.IsNullOrEmpty(msg)) return;
|
|
||||||
this.Logger.LogInformation($"接收到扫码枪{this.Name}数据:{msg}");
|
|
||||||
this.OnDataReceived(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<string> ReadAsnyc(TimeSpan timeout)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.Stop();
|
|
||||||
await Task.Delay(20);
|
|
||||||
byte[] sendBytes = this.ConnectorAdapter.StringEncoder.GetBytes(this.StartCommandLine);
|
|
||||||
var tcpMessage = await this.ConnectorAdapter.WriteAndGetReplyAsync(sendBytes, timeout);
|
|
||||||
if (tcpMessage is null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Code = this.ParseMessage(tcpMessage.ParseStirng(), tcpMessage.Data).TrimEnd();
|
|
||||||
this.Stop();
|
|
||||||
this.OnScannedEvent(this.Code);
|
|
||||||
return this.Code;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.Logger.LogException(ex);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Connections;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices.Scanner
|
|
||||||
{
|
|
||||||
public class ScannerService: ScannerCodeOfTcpClientBase
|
|
||||||
{
|
|
||||||
public override bool IsConnected => this.ConnectionState == ConnectionState.IsConnected;
|
|
||||||
|
|
||||||
|
|
||||||
public override Task<string> ReadAsnyc(TimeSpan timeout)
|
|
||||||
{
|
|
||||||
return base.ReadAsnyc(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string ParseMessage(object data, byte[] sourceData)
|
|
||||||
{
|
|
||||||
return data?.ToString() ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
return base.CheckConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,798 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO.Ports;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public enum SerialPortDataFormat
|
|
||||||
{
|
|
||||||
Char,
|
|
||||||
Hex
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SerialPortService : IDisposable
|
|
||||||
{
|
|
||||||
private SerialPort serialPort;
|
|
||||||
|
|
||||||
private bool isCloseing = false;
|
|
||||||
|
|
||||||
private int tryReadNumber = 3;
|
|
||||||
|
|
||||||
public SerialConfigOptions SerialConfigOptions => new SerialConfigOptions
|
|
||||||
{
|
|
||||||
BaudRate = BaudRate,
|
|
||||||
DataBits = DataBits,
|
|
||||||
Handshake = Handshake,
|
|
||||||
Parity = Parity,
|
|
||||||
PortName = PortName,
|
|
||||||
StopBits = StopBits
|
|
||||||
};
|
|
||||||
|
|
||||||
public Stream BaseStream => serialPort.BaseStream;
|
|
||||||
|
|
||||||
public int BaudRate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.BaudRate;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.BaudRate = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool BreakState
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.BreakState;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.BreakState = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int BytesToRead => serialPort.BytesToRead;
|
|
||||||
|
|
||||||
public int BytesToWrite => serialPort.BytesToWrite;
|
|
||||||
|
|
||||||
public bool CDHolding => serialPort.CDHolding;
|
|
||||||
|
|
||||||
public bool CtsHolding => serialPort.CtsHolding;
|
|
||||||
|
|
||||||
public int DataBits
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.DataBits;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.DataBits = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DiscardNull
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.DiscardNull;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.DiscardNull = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DsrHolding => serialPort.DsrHolding;
|
|
||||||
|
|
||||||
public bool DtrEnable
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.DtrEnable;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.DtrEnable = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Encoding Encoding
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.Encoding;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.Encoding = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Handshake Handshake
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.Handshake;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.Handshake = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsOpen => serialPort?.IsOpen ?? false;
|
|
||||||
|
|
||||||
public string NewLine
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.NewLine;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.NewLine = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Parity Parity
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.Parity;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.Parity = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte ParityReplace
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.ParityReplace;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.ParityReplace = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string PortName
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.PortName;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.PortName = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadBufferSize
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.ReadBufferSize;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.ReadBufferSize = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.ReadTimeout;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.ReadTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReceivedBytesThreshold
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.ReceivedBytesThreshold;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.ReceivedBytesThreshold = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RtsEnable
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.RtsEnable;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.RtsEnable = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StopBits StopBits
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.StopBits;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.StopBits = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int WriteBufferSize
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.WriteBufferSize;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.WriteBufferSize = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int WriteTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return serialPort.WriteTimeout;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
serialPort.WriteTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int TryReadSpanTime { get; set; } = 10;
|
|
||||||
|
|
||||||
|
|
||||||
public string Terminator { get; set; } = null;
|
|
||||||
|
|
||||||
|
|
||||||
public SerialPortDataFormat DataFormat { get; set; } = SerialPortDataFormat.Char;
|
|
||||||
|
|
||||||
|
|
||||||
public int TryReadNumber
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return tryReadNumber;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException("TryReadNumber", "TryReadNumber must be equal or greater than 1.");
|
|
||||||
}
|
|
||||||
|
|
||||||
tryReadNumber = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler<Message> DataReceived;
|
|
||||||
|
|
||||||
public static string[] GetPortNames()
|
|
||||||
{
|
|
||||||
return SerialPort.GetPortNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialPortService()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialPortService(string portName)
|
|
||||||
: this(portName, 9600, 8, StopBits.One, Parity.None, Handshake.None)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialPortService(string portName, int baudRate)
|
|
||||||
: this(portName, baudRate, 8, StopBits.One, Parity.None, Handshake.None)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialPortService(string portName, int baudRate = 9600, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, Handshake handshake = Handshake.None)
|
|
||||||
{
|
|
||||||
if (portName == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("portName");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataBits < 7 || dataBits > 8)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("dataBits", "only 7,8");
|
|
||||||
}
|
|
||||||
|
|
||||||
serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits)
|
|
||||||
{
|
|
||||||
Handshake = handshake,
|
|
||||||
WriteTimeout = 3000,
|
|
||||||
ReadTimeout = 4000
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialPortService(SerialConfigOptions options)
|
|
||||||
: this(options.PortName, options.BaudRate, options.DataBits, options.StopBits, options.Parity, options.Handshake)
|
|
||||||
{
|
|
||||||
if (options == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("options");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Open()
|
|
||||||
{
|
|
||||||
if (serialPort == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serialPort.IsOpen)
|
|
||||||
{
|
|
||||||
serialPort.Open();
|
|
||||||
serialPort.DataReceived += SerialPort_DataReceived;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
if (IsOpen)
|
|
||||||
{
|
|
||||||
isCloseing = true;
|
|
||||||
Thread.Sleep(TryReadSpanTime + 5);
|
|
||||||
serialPort.DataReceived -= SerialPort_DataReceived;
|
|
||||||
Thread.Sleep(TryReadSpanTime + 5);
|
|
||||||
serialPort.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DiscardInBuffer()
|
|
||||||
{
|
|
||||||
serialPort.DiscardInBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DiscardOutBuffer()
|
|
||||||
{
|
|
||||||
serialPort.DiscardOutBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
serialPort = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadByte()
|
|
||||||
{
|
|
||||||
return serialPort.ReadByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ReadChar()
|
|
||||||
{
|
|
||||||
return serialPort.ReadChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadLine()
|
|
||||||
{
|
|
||||||
return serialPort.ReadLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadExisting()
|
|
||||||
{
|
|
||||||
return serialPort.ReadExisting();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadTo(string value)
|
|
||||||
{
|
|
||||||
return serialPort.ReadTo(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadString()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string result = null;
|
|
||||||
byte[] array = TryRead();
|
|
||||||
if (array != null && array.Length != 0)
|
|
||||||
{
|
|
||||||
switch (DataFormat)
|
|
||||||
{
|
|
||||||
case SerialPortDataFormat.Char:
|
|
||||||
result = serialPort.Encoding.GetString(array);
|
|
||||||
break;
|
|
||||||
case SerialPortDataFormat.Hex:
|
|
||||||
result = array.ToHexString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Read()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return TryRead();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] TryRead()
|
|
||||||
{
|
|
||||||
int num = 0;
|
|
||||||
int num2 = 0;
|
|
||||||
bool flag = false;
|
|
||||||
List<byte> list = new List<byte>();
|
|
||||||
byte[] array = null;
|
|
||||||
if (Terminator != null)
|
|
||||||
{
|
|
||||||
array = Terminator.HexToByte();
|
|
||||||
num2 = array.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((serialPort.BytesToRead > 0 || !flag) && num < tryReadNumber)
|
|
||||||
{
|
|
||||||
int num3 = ((serialPort.BytesToRead < serialPort.ReadBufferSize) ? serialPort.BytesToRead : serialPort.ReadBufferSize);
|
|
||||||
byte[] array2 = new byte[num3];
|
|
||||||
serialPort.Read(array2, 0, array2.Length);
|
|
||||||
list.AddRange(array2);
|
|
||||||
if (array != null && num2 > 0)
|
|
||||||
{
|
|
||||||
byte[] array3 = new byte[num2];
|
|
||||||
if (array2.Length >= num2)
|
|
||||||
{
|
|
||||||
Buffer.BlockCopy(array2, array2.Length - num2, array3, 0, num2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (list.ToArray().Length < num2)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] array4 = list.ToArray();
|
|
||||||
Buffer.BlockCopy(array4, array4.Length - num2, array3, 0, num2);
|
|
||||||
}
|
|
||||||
|
|
||||||
flag = array.Length != 0 && array3.SequenceEqual(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TryReadSpanTime > 0)
|
|
||||||
{
|
|
||||||
Thread.Sleep(TryReadSpanTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (list.Count > 0) ? list.ToArray() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int WriteHexString(string str)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] array = str.HexToByte();
|
|
||||||
return Write(array, 0, array.Length);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int WriteAsciiString(string str)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
byte[] bytes = serialPort.Encoding.GetBytes(str);
|
|
||||||
return Write(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Write(byte[] bytes)
|
|
||||||
{
|
|
||||||
return Write(bytes, 0, bytes.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(string text)
|
|
||||||
{
|
|
||||||
serialPort.Write(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Write(byte[] bytes, int offset, int count)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
serialPort.DiscardInBuffer();
|
|
||||||
serialPort.Write(bytes, offset, count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteLine(string str)
|
|
||||||
{
|
|
||||||
serialPort.WriteLine(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] SendAndReceive(IEnumerable<byte> datas, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
byte[] mReply = null;
|
|
||||||
DataReceived += SerialPortDataReceived;
|
|
||||||
int num = Write(datas.ToArray());
|
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
|
||||||
while (mReply == null && (double)stopwatch.ElapsedMilliseconds < timeout.TotalMilliseconds)
|
|
||||||
{
|
|
||||||
Thread.Sleep(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataReceived -= SerialPortDataReceived;
|
|
||||||
return mReply;
|
|
||||||
void SerialPortDataReceived(object sender, Message msg)
|
|
||||||
{
|
|
||||||
mReply = msg.Data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
|
|
||||||
{
|
|
||||||
if (!isCloseing)
|
|
||||||
{
|
|
||||||
byte[] data = TryRead();
|
|
||||||
Message e2 = new Message(data, Encoding);
|
|
||||||
this.DataReceived?.Invoke(this, e2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 扩展方法 byte[]
|
|
||||||
/// </summary>
|
|
||||||
public static class Extension
|
|
||||||
{
|
|
||||||
public static string ToHexString(this byte[] bytes, string separator = " ")
|
|
||||||
{
|
|
||||||
if (bytes == null || bytes.Length < 1)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Join(separator, bytes.Select((byte b) => b.ToString("X2")).ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] HexToByte(this string hex)
|
|
||||||
{
|
|
||||||
hex = hex.Replace(" ", "");
|
|
||||||
byte[] array = new byte[hex.Length / 2];
|
|
||||||
for (int i = 0; i < hex.Length; i += 2)
|
|
||||||
{
|
|
||||||
array[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SerialConfigOptions
|
|
||||||
{
|
|
||||||
public string PortName { get; set; }
|
|
||||||
|
|
||||||
public int BaudRate { get; set; } = 9600;
|
|
||||||
|
|
||||||
|
|
||||||
public int DataBits { get; set; } = 8;
|
|
||||||
|
|
||||||
|
|
||||||
public StopBits StopBits { get; set; } = StopBits.One;
|
|
||||||
|
|
||||||
|
|
||||||
public Parity Parity { get; set; } = Parity.None;
|
|
||||||
|
|
||||||
|
|
||||||
public Handshake Handshake { get; set; } = Handshake.None;
|
|
||||||
|
|
||||||
|
|
||||||
public SerialConfigOptions()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialConfigOptions(string portName, int baudRate = 9600, int dataBits = 8, StopBits stopBits = StopBits.One, Parity parity = Parity.None, Handshake handshake = Handshake.None)
|
|
||||||
{
|
|
||||||
PortName = portName ?? throw new ArgumentNullException("portName");
|
|
||||||
if (dataBits < 7 || dataBits > 8)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("dataBits", "only 7,8");
|
|
||||||
}
|
|
||||||
|
|
||||||
BaudRate = baudRate;
|
|
||||||
DataBits = dataBits;
|
|
||||||
StopBits = stopBits;
|
|
||||||
Parity = parity;
|
|
||||||
Handshake = handshake;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialConfigOptions(string portName, int baudRate = 9600, int dataBits = 8, int stopBits = 1, int parity = 0, int handshake = 0)
|
|
||||||
: this(portName, baudRate, dataBits, GetStopBits(stopBits), GetParity(parity), GetHandshake(handshake))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public SerialConfigOptions(string portName, int baudRate = 9600, int dataBits = 8, string stopBits = "one", string parity = "none", string handshake = "none")
|
|
||||||
: this(portName, baudRate, dataBits, GetStopBits(stopBits), GetParity(parity), GetHandshake(handshake))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Parity GetParity(string parityVal)
|
|
||||||
{
|
|
||||||
switch (parityVal?.ToLower())
|
|
||||||
{
|
|
||||||
case "0":
|
|
||||||
case "n":
|
|
||||||
case "none":
|
|
||||||
return Parity.None;
|
|
||||||
case "1":
|
|
||||||
case "o":
|
|
||||||
case "odd":
|
|
||||||
return Parity.Odd;
|
|
||||||
case "2":
|
|
||||||
case "e":
|
|
||||||
case "even":
|
|
||||||
return Parity.Even;
|
|
||||||
case "3":
|
|
||||||
case "m":
|
|
||||||
case "mark":
|
|
||||||
return Parity.Mark;
|
|
||||||
case "4":
|
|
||||||
case "s":
|
|
||||||
case "space":
|
|
||||||
return Parity.Space;
|
|
||||||
default:
|
|
||||||
return Parity.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Parity GetParity(int parityVal)
|
|
||||||
{
|
|
||||||
return GetParity(parityVal.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StopBits GetStopBits(string stopBitsVal)
|
|
||||||
{
|
|
||||||
switch (stopBitsVal?.ToLower())
|
|
||||||
{
|
|
||||||
case "0":
|
|
||||||
case "n":
|
|
||||||
case "none":
|
|
||||||
return StopBits.None;
|
|
||||||
case "1":
|
|
||||||
case "o":
|
|
||||||
case "one":
|
|
||||||
return StopBits.One;
|
|
||||||
case "2":
|
|
||||||
case "t":
|
|
||||||
case "two":
|
|
||||||
return StopBits.Two;
|
|
||||||
case "3":
|
|
||||||
case "1.5":
|
|
||||||
case "f":
|
|
||||||
case "of":
|
|
||||||
case "opf":
|
|
||||||
case "onepointfive":
|
|
||||||
return StopBits.OnePointFive;
|
|
||||||
default:
|
|
||||||
return StopBits.One;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StopBits GetStopBits(int stopBitsVal)
|
|
||||||
{
|
|
||||||
return GetStopBits(stopBitsVal.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Handshake GetHandshake(string shake)
|
|
||||||
{
|
|
||||||
switch (shake?.ToLower())
|
|
||||||
{
|
|
||||||
case "0":
|
|
||||||
case "n":
|
|
||||||
case "none":
|
|
||||||
return Handshake.None;
|
|
||||||
case "1":
|
|
||||||
case "x":
|
|
||||||
case "xoxo":
|
|
||||||
case "xonxoff":
|
|
||||||
case "software":
|
|
||||||
return Handshake.XOnXOff;
|
|
||||||
case "2":
|
|
||||||
case "r":
|
|
||||||
case "rts":
|
|
||||||
case "requesttosend":
|
|
||||||
case "hardware":
|
|
||||||
return Handshake.RequestToSend;
|
|
||||||
case "3":
|
|
||||||
case "rx":
|
|
||||||
case "rtsxx":
|
|
||||||
case "requesttosendxonxoff":
|
|
||||||
case "both":
|
|
||||||
return Handshake.RequestToSendXOnXOff;
|
|
||||||
default:
|
|
||||||
return Handshake.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Handshake GetHandshake(int shake)
|
|
||||||
{
|
|
||||||
return GetHandshake(shake.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Message
|
|
||||||
{
|
|
||||||
private readonly Encoding _encoder = null;
|
|
||||||
|
|
||||||
public byte[] Data { get; private set; }
|
|
||||||
|
|
||||||
public string MessageString => _encoder.GetString(Data);
|
|
||||||
|
|
||||||
public Message(byte[] data, Encoding stringEncoder)
|
|
||||||
{
|
|
||||||
Data = data;
|
|
||||||
_encoder = stringEncoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ReadString(SerialPortDataFormat dataFormat= SerialPortDataFormat.Char)
|
|
||||||
{
|
|
||||||
string result = null;
|
|
||||||
byte[] data = Data;
|
|
||||||
if (Data != null && Data.Length != 0)
|
|
||||||
{
|
|
||||||
switch (dataFormat)
|
|
||||||
{
|
|
||||||
case SerialPortDataFormat.Char:
|
|
||||||
result = _encoder.GetString(data);
|
|
||||||
break;
|
|
||||||
case SerialPortDataFormat.Hex:
|
|
||||||
result = data.ToHexString();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,464 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Adapters;
|
|
||||||
using MegaRobo.Connections.Modbus;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static MegaRobo.Connections.Modbus.ModbusParams;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 高温震荡电机驱动器控制服务
|
|
||||||
/// </summary>
|
|
||||||
public class HighTemperatureMotorControlService : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 寄存器地址枚举(十六进制转十进制,Modbus 需传入十进制地址)
|
|
||||||
/// </summary>
|
|
||||||
private enum MotorRegisterAddress : ushort
|
|
||||||
{
|
|
||||||
启停控制 = 0x00, // 0x00(十进制0):启停控制
|
|
||||||
工作模式 = 0x02, // 0x02(十进制2):模式切换
|
|
||||||
速度指令 = 0x06, // 0x06(十进制6):速度指令
|
|
||||||
清除故障 = 0x4A, // 0x4A(十进制74):清除故障
|
|
||||||
驱动器状态 = 0xE3, // 0xE3(十进制227):驱动器状态
|
|
||||||
电机转速 = 0xE4 // 0xE4(十进制228):电机实际转速
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入数据枚举
|
|
||||||
/// </summary>
|
|
||||||
private enum MotorWriteData : ushort
|
|
||||||
{
|
|
||||||
停止 = 0x0000, // 启停控制:0=停止
|
|
||||||
启动 = 0x0001, // 启停控制:1=启动
|
|
||||||
速度模式 = 0x00C4, // 工作模式:0x00C4=速度模式
|
|
||||||
位置模式 = 0x00D0 // 工作模式:0x00D0=位置模式
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 驱动器状态位解析(对应 0xE3 寄存器的 bit 位)
|
|
||||||
/// </summary>
|
|
||||||
public class MotorState
|
|
||||||
{
|
|
||||||
public bool 运行状态 { get; set; } // bit0:0=停机,1=启动
|
|
||||||
public bool 过流故障 { get; set; } // bit1:1=故障
|
|
||||||
public bool 过压故障 { get; set; } // bit2:1=故障
|
|
||||||
public bool 编码器故障 { get; set; } // bit3:1=故障
|
|
||||||
public bool 位置偏差过大 { get; set; }// bit4:1=故障
|
|
||||||
public bool 欠压故障 { get; set; } // bit5:1=故障
|
|
||||||
public bool 过载故障 { get; set; } // bit6:1=故障
|
|
||||||
public bool 外部控制标志 { get; set; }// bit7:0=PC控制,1=PLC控制
|
|
||||||
public string 故障描述 { get; set; } // 汇总故障信息
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null || tcpMsg.Data == null || tcpMsg.Data.Length == 0)
|
|
||||||
return;
|
|
||||||
string hexData = BitConverter.ToString(tcpMsg.Data).Replace("-", " ");
|
|
||||||
Logger.LogInformation($"接收到电机驱动器数据(十六进制):{hexData}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
var state = ConnectionState.None;
|
|
||||||
if (ConnectorAdapter is not null)
|
|
||||||
{
|
|
||||||
state = await ConnectorAdapter.CheckConnectedAsync();
|
|
||||||
}
|
|
||||||
ConnectionState = state;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 电机启停控制
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">设备从站号</param>
|
|
||||||
/// <param name="isStart"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> ControlMotorStartStop(byte id, bool isStart)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 1. 确定写入数据:启动=0x0001,停止=0x0000
|
|
||||||
MotorWriteData writeData = isStart ? MotorWriteData.启动 : MotorWriteData.停止;
|
|
||||||
// 2. 调用 Modbus 写单个寄存器(功能码06),地址=启停控制(0x00),字节顺序AB(高字节在前)
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: id, // 从站地址(默认1)
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.启停控制,
|
|
||||||
lstData: (ushort)writeData,
|
|
||||||
byteOrder: ByteOrder.AB // 协议要求高字节在前
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"启停控制指令构建失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 发送指令并获取响应
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("启停控制未收到响应");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 验证响应(协议要求写成功后返回原报文)
|
|
||||||
bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data);
|
|
||||||
if (!isResponseMatch)
|
|
||||||
{
|
|
||||||
Logger.LogError($"启停控制响应不匹配:发送={BitConverter.ToString(writeResult.Respond)}, 接收={BitConverter.ToString(tcpMessage.Data)}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.LogInformation($"{(isStart ? "启动" : "停止")}电机成功");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "ControlMotorStartStop", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置电机速度(速度模式下)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">设备从站号</param>
|
|
||||||
/// <param name="targetSpeed">目标速度(0-3000 RPM,协议上限3000)</param>
|
|
||||||
public async Task<bool> SetMotorSpeed(byte id, int targetSpeed)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 1. 参数校验:速度范围 0-3000 RPM(协议规定)
|
|
||||||
if (targetSpeed < 0 || targetSpeed > 3000)
|
|
||||||
{
|
|
||||||
Logger.LogError($"速度值超出范围(0-3000 RPM):{targetSpeed}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 切换到速度模式(必须先设置模式,再写速度)
|
|
||||||
bool modeSuccess = await SwitchToSpeedMode(id);
|
|
||||||
if (!modeSuccess)
|
|
||||||
{
|
|
||||||
Logger.LogError("切换速度模式失败,无法设置速度");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 计算速度指令值:写入值 = (目标速度 / 3000) * 8192(协议公式)
|
|
||||||
ushort speedCommand = (ushort)Math.Round((targetSpeed / 3000.0) * 8192);
|
|
||||||
Logger.LogInformation($"目标速度={targetSpeed} RPM,计算后指令值=0x{speedCommand:X4}");
|
|
||||||
|
|
||||||
// 4. 写速度指令到寄存器 0x06(功能码06)
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: id,
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.速度指令,
|
|
||||||
lstData: speedCommand,
|
|
||||||
byteOrder: ByteOrder.AB // 高字节在前
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"速度指令构建失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 发送指令并验证响应
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("设置速度未收到响应");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. 验证响应(写成功返回原报文)
|
|
||||||
bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data);
|
|
||||||
if (!isResponseMatch)
|
|
||||||
{
|
|
||||||
Logger.LogError($"速度设置响应不匹配:发送={BitConverter.ToString(writeResult.Respond)}, 接收={BitConverter.ToString(tcpMessage.Data)}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.LogInformation($"设置电机速度成功:{targetSpeed} RPM(指令值=0x{speedCommand:X4})");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "SetMotorSpeed", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取电机驱动器状态(运行状态+故障信息)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">设备从站号</param>
|
|
||||||
public async Task<MotorState> GetMotorState(byte id)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 1. 构建读状态指令:地址0xE3(十进制227),读1个寄存器(状态是16位)
|
|
||||||
var readResult = ModbusRTU.GetReadMessage(
|
|
||||||
slaveStation: id,
|
|
||||||
readType: ModbusReadCodes.READ_HOLDING_REGISTERS, // 功能码03
|
|
||||||
startAdr: (ushort)MotorRegisterAddress.驱动器状态,
|
|
||||||
length: 1 // 状态寄存器是1个16位寄存器,长度=1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!readResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"读状态指令构建失败:{readResult.Message}");
|
|
||||||
return new MotorState { 故障描述 = "指令构建失败" };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 发送指令并获取响应
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(readResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("读状态未收到响应");
|
|
||||||
return new MotorState { 故障描述 = "未收到响应" };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 解析响应(16位状态字,字节顺序AB)
|
|
||||||
var parseResult = ModbusRTU.ReadRegisterUShort(tcpMessage.Data, ByteOrder.AB);
|
|
||||||
if (!parseResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"状态解析失败:{parseResult.Message}");
|
|
||||||
return new MotorState { 故障描述 = parseResult.Message };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 解析状态字的各个bit位(协议表5-22)
|
|
||||||
ushort statusWord = parseResult.Respond[0];
|
|
||||||
var motorState = new MotorState
|
|
||||||
{
|
|
||||||
运行状态 = (statusWord & (1 << 0)) != 0, // bit0
|
|
||||||
过流故障 = (statusWord & (1 << 1)) != 0, // bit1
|
|
||||||
过压故障 = (statusWord & (1 << 2)) != 0, // bit2
|
|
||||||
编码器故障 = (statusWord & (1 << 3)) != 0, // bit3
|
|
||||||
位置偏差过大 = (statusWord & (1 << 4)) != 0,// bit4
|
|
||||||
欠压故障 = (statusWord & (1 << 5)) != 0, // bit5
|
|
||||||
过载故障 = (statusWord & (1 << 6)) != 0, // bit6
|
|
||||||
外部控制标志 = (statusWord & (1 << 7)) != 0 // bit7
|
|
||||||
};
|
|
||||||
|
|
||||||
// 5. 汇总故障描述
|
|
||||||
var errors = new List<string>();
|
|
||||||
if (motorState.过流故障) errors.Add("过流");
|
|
||||||
if (motorState.过压故障) errors.Add("过压");
|
|
||||||
if (motorState.编码器故障) errors.Add("编码器故障");
|
|
||||||
if (motorState.位置偏差过大) errors.Add("位置偏差过大");
|
|
||||||
if (motorState.欠压故障) errors.Add("欠压");
|
|
||||||
if (motorState.过载故障) errors.Add("过载");
|
|
||||||
|
|
||||||
motorState.故障描述 = errors.Count > 0
|
|
||||||
? $"故障:{string.Join("、", errors)}"
|
|
||||||
: "无故障";
|
|
||||||
|
|
||||||
Logger.LogInformation($"电机状态:运行状态={(motorState.运行状态 ? "启动" : "停止")},{motorState.故障描述}");
|
|
||||||
return motorState;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "GetMotorState", 150, false);
|
|
||||||
return new MotorState { 故障描述 = $"异常:{ex.Message}" };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取电机实际转速
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">设备从站号</param>
|
|
||||||
public async Task<int> GetMotorActualSpeed(byte id)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 1. 构建读转速指令:地址0xE4(十进制228),读1个寄存器
|
|
||||||
var readResult = ModbusRTU.GetReadMessage(
|
|
||||||
slaveStation: id,
|
|
||||||
readType: ModbusReadCodes.READ_HOLDING_REGISTERS,
|
|
||||||
startAdr: (ushort)MotorRegisterAddress.电机转速,
|
|
||||||
length: 1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!readResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"读转速指令构建失败:{readResult.Message}");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 发送指令并获取响应
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(readResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("读转速未收到响应");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 解析转速(16位无符号数,直接表示RPM)
|
|
||||||
var parseResult = ModbusRTU.ReadRegisterUShort(tcpMessage.Data, ByteOrder.AB);
|
|
||||||
if (!parseResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"转速解析失败:{parseResult.Message}");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int actualSpeed = parseResult.Respond[0];
|
|
||||||
Logger.LogInformation($"电机实际转速:{actualSpeed} RPM");
|
|
||||||
return actualSpeed;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "GetMotorActualSpeed", 150, false);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 清除电机故障
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">设备从站号</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> ClearMotorFault(byte id)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 协议规定:写入任意值到0x4A即可清除故障,此处写0x0000
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: id,
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.清除故障,
|
|
||||||
lstData: (ushort)0x0000,
|
|
||||||
byteOrder: ByteOrder.AB
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"清除故障指令构建失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("清除故障未收到响应");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isResponseMatch = CompareBytes(writeResult.Respond, tcpMessage.Data);
|
|
||||||
if (isResponseMatch)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("清除电机故障成功");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.LogError("清除故障响应不匹配");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "HighTemperatureMotorControlService", "ClearMotorFault", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 切换到速度模式(内部调用,设置模式寄存器0x02为0x00C4)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task<bool> SwitchToSpeedMode(byte id)
|
|
||||||
{
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: id,
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.工作模式,
|
|
||||||
lstData: (ushort)MotorWriteData.速度模式,
|
|
||||||
byteOrder: ByteOrder.AB
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"切换速度模式指令构建失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(writeResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
Logger.LogError("切换速度模式未收到响应");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isMatch = CompareBytes(writeResult.Respond, tcpMessage.Data);
|
|
||||||
if (isMatch)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("切换到速度模式成功");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.LogError("切换速度模式响应不匹配");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 比较两个字节数组是否相等(验证响应报文)
|
|
||||||
/// </summary>
|
|
||||||
private bool CompareBytes(byte[] source, byte[] target)
|
|
||||||
{
|
|
||||||
if (source.Length != target.Length) return false;
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
|
||||||
{
|
|
||||||
if (source[i] != target[i]) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class HighTemperatureShakeService : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null)
|
|
||||||
return;
|
|
||||||
var msg = tcpMsg.ParseStirng();
|
|
||||||
if (string.IsNullOrEmpty(msg)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测连接状态
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
var state = ConnectionState.None;
|
|
||||||
if (ConnectorAdapter is not null)
|
|
||||||
{
|
|
||||||
state = await ConnectorAdapter.CheckConnectedAsync();
|
|
||||||
}
|
|
||||||
ConnectionState = state;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置加热温度
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="temperature"></param>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <param name="offTemp">关闭温度</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> SetTemperature(int temperature, byte deviceId, bool offTemp)
|
|
||||||
{
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(HighTemperatureUartHCM.SendSetHotTemp(temperature, deviceId, offTemp), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return false;
|
|
||||||
ParseResult result = HighTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
return result.IsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取当前温度
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<int> GetActualTemperature(byte deviceId)
|
|
||||||
{
|
|
||||||
int temperature = 0;
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(HighTemperatureUartHCM.SendReadTempRequest(deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return 0;
|
|
||||||
ParseResult result = HighTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
temperature = (int)result.Data["实际温度(℃)"];
|
|
||||||
}
|
|
||||||
return temperature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,442 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class HighTemperatureUartHCM
|
|
||||||
{
|
|
||||||
#region 协议常量定义
|
|
||||||
private const byte ST = 0x5E; // 帧头
|
|
||||||
private const byte HELLO = 0x01; // 握手指令
|
|
||||||
private const byte RDTEMP = 0x08; // 读取温度
|
|
||||||
private const byte RDADC = 0x09; // 读取传感器AD
|
|
||||||
private const byte RDEE = 0x11; // 读取EEPROM
|
|
||||||
private const byte WREE = 0x12; // 写入EEPROM
|
|
||||||
private const byte Calb = 0x15; // 校准温度
|
|
||||||
private const byte SETHOTTEMP = 0x16; // 加热温度控制
|
|
||||||
private const byte RESPONSE_FLAG = 0x80; // 上传指令标志
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 校验和计算(协议第6点:前n-1字节之和的低8位)
|
|
||||||
/// <summary>
|
|
||||||
/// 计算帧的校验和(核心:前length字节之和的低8位)
|
|
||||||
/// </summary>
|
|
||||||
private static byte CalculateChecksum(byte[] data, int length)
|
|
||||||
{
|
|
||||||
if (data == null || length <= 0 || length > data.Length)
|
|
||||||
throw new ArgumentException("校验和计算参数无效");
|
|
||||||
|
|
||||||
int sum = 0;
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
sum += data[i];
|
|
||||||
return (byte)(sum & 0xFF); // 取低8位,确保1字节
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 帧间隔控制(协议1.1g:帧与帧间隔>2ms,用Thread.Sleep确保阻塞)
|
|
||||||
/// <summary>
|
|
||||||
/// 帧间隔时间(预留3ms余量,确保符合协议要求)
|
|
||||||
/// </summary>
|
|
||||||
private static void AddFrameInterval()
|
|
||||||
{
|
|
||||||
Task.Delay(3);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 下传指令构建(PC→主控板,严格遵循协议指令格式)
|
|
||||||
/// <summary>
|
|
||||||
/// 握手指令(系统开机必发)
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendHello(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 协议固定帧长5字节
|
|
||||||
// 帧结构:ST → HELLO(0x01) → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = HELLO; // 移除序号或运算,CMD为固定指令码(协议3.1)
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4); // 前4字节求和
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取温度指令
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendReadTempRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 协议固定帧长5字节
|
|
||||||
// 帧结构:ST → RDTEMP(0x08) → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = RDTEMP;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5;
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取传感器AD指令
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendReadAdcRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 协议固定帧长5字节
|
|
||||||
// 帧结构:ST → RDADC(0x09) → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = RDADC;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5;
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取EEPROM指令
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendReadEepromRequest(byte addrHigh, byte addrMid, byte addrLow, int readLength, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
if (readLength < 1)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(readLength), "读取长度必须≥1");
|
|
||||||
|
|
||||||
int frameLength = 9 + readLength; // 帧长=9(固定段)+ 读取长度(协议3.4)
|
|
||||||
byte[] frame = new byte[frameLength];
|
|
||||||
// 帧结构:ST → RDEE(0x11) → 设备ID → LTH=N → 地址高→中→低 → 读取长度 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = RDEE;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = (byte)frameLength;
|
|
||||||
frame[4] = addrHigh;
|
|
||||||
frame[5] = addrMid;
|
|
||||||
frame[6] = addrLow;
|
|
||||||
frame[7] = (byte)readLength;
|
|
||||||
frame[frameLength - 1] = CalculateChecksum(frame, frameLength - 1);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入EEPROM指令
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendWriteEepromRequest(byte addrHigh, byte addrMid, byte addrLow, byte[] writeData, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
if (writeData == null || writeData.Length == 0)
|
|
||||||
throw new ArgumentException("写入数据不能为空", nameof(writeData));
|
|
||||||
|
|
||||||
int frameLength = 9 + writeData.Length; // 帧长=9(固定段)+ 数据长度(协议3.5)
|
|
||||||
byte[] frame = new byte[frameLength];
|
|
||||||
// 帧结构:ST → WREE(0x12) → 设备ID → LTH=N → 地址高→中→低 → 写入数据 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = WREE;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = (byte)frameLength;
|
|
||||||
frame[4] = addrHigh;
|
|
||||||
frame[5] = addrMid;
|
|
||||||
frame[6] = addrLow;
|
|
||||||
Array.Copy(writeData, 0, frame, 7, writeData.Length);
|
|
||||||
frame[frameLength - 1] = CalculateChecksum(frame, frameLength - 1);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 校准温度指令(设置B值=(实际温度-目标温度)×100)
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendCalibrateTempRequest(int calibBValue, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
if (calibBValue < short.MinValue || calibBValue > short.MaxValue)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(calibBValue), "校准B值必须在-32768~32767之间");
|
|
||||||
|
|
||||||
byte[] frame = new byte[7]; // 协议固定帧长7字节
|
|
||||||
short bParam = (short)calibBValue; // 16位有符号数(支持负值)
|
|
||||||
// 帧结构:ST → Calb(0x15) → 设备ID → LTH=7 → 参数1(高8) → 参数2(低8) → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = Calb;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 7;
|
|
||||||
frame[4] = (byte)(bParam >> 8); // 高位在前(协议3.6)
|
|
||||||
frame[5] = (byte)(bParam & 0xFF);
|
|
||||||
frame[6] = CalculateChecksum(frame, 6);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加热温度控制(设置目标温度或释放控制)
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendSetHotTemp(double targetTemp, byte deviceId = 0, bool releaseControl = false)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[7]; // 协议固定帧长7字节
|
|
||||||
ushort tempParam;
|
|
||||||
|
|
||||||
if (releaseControl)
|
|
||||||
{
|
|
||||||
tempParam = 0xFFFF; // 协议约定:释放控制=0xFFFF(关断功率)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 协议范围:室温~100℃(对应室温×100~10000),室温暂以20℃为参考
|
|
||||||
if (targetTemp < 20.0 || targetTemp > 100.0)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(targetTemp), "温度必须在[20.0, 100.0]℃之间(符合协议室温要求)");
|
|
||||||
tempParam = (ushort)(targetTemp * 100); // 放大100倍(协议3.7)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 帧结构:ST → SETHOTTEMP(0x16) → 设备ID → LTH=7 → 参数1(高8) → 参数2(低8) → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = SETHOTTEMP;
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 7;
|
|
||||||
frame[4] = (byte)(tempParam >> 8); // 高位在前(协议3.7)
|
|
||||||
frame[5] = (byte)(tempParam & 0xFF);
|
|
||||||
frame[6] = CalculateChecksum(frame, 6);
|
|
||||||
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 指令解析
|
|
||||||
/// <summary>
|
|
||||||
/// 解析主控板返回的帧数据(入口方法)
|
|
||||||
/// </summary>
|
|
||||||
public static ParseResult ParseReceivedFrame(byte[] receivedFrame)
|
|
||||||
{
|
|
||||||
// 基础校验:帧非空、最短帧≥6字节(上传指令最短为握手响应6字节)
|
|
||||||
if (receivedFrame == null || receivedFrame.Length < 6)
|
|
||||||
return new ParseResult(false, "无效帧:数据为空或长度不足", null);
|
|
||||||
|
|
||||||
// 1. 校验帧头
|
|
||||||
if (receivedFrame[0] != ST)
|
|
||||||
return new ParseResult(false, $"帧头错误:实际0x{receivedFrame[0]:X2},期望0x{ST:X2}", null);
|
|
||||||
|
|
||||||
// 2. 提取核心字段
|
|
||||||
byte cmdWithFlag = receivedFrame[1];
|
|
||||||
byte deviceId = receivedFrame[2];
|
|
||||||
byte frameLength = receivedFrame[3];
|
|
||||||
byte checksum = receivedFrame[frameLength - 1];
|
|
||||||
|
|
||||||
// 3. 校验帧长(实际长度=帧长字段)
|
|
||||||
if (receivedFrame.Length != frameLength)
|
|
||||||
return new ParseResult(false, $"帧长不匹配:实际{receivedFrame.Length}字节,期望{frameLength}字节", null);
|
|
||||||
|
|
||||||
// 4. 校验和验证
|
|
||||||
byte calculatedChecksum = CalculateChecksum(receivedFrame, frameLength - 1);
|
|
||||||
if (calculatedChecksum != checksum)
|
|
||||||
return new ParseResult(false, $"校验和错误:实际0x{checksum:X2},计算0x{calculatedChecksum:X2}", null);
|
|
||||||
|
|
||||||
// 5. 去除响应标志,获取原始指令码
|
|
||||||
byte originalCmd = (byte)(cmdWithFlag & ~RESPONSE_FLAG);
|
|
||||||
|
|
||||||
// 6. 按指令类型分发解析
|
|
||||||
switch (originalCmd)
|
|
||||||
{
|
|
||||||
case HELLO:
|
|
||||||
return ParseHelloResponse(receivedFrame, deviceId);
|
|
||||||
case RDTEMP:
|
|
||||||
return ParseReadTempResponse(receivedFrame, deviceId);
|
|
||||||
case RDADC:
|
|
||||||
return ParseReadAdcResponse(receivedFrame, deviceId);
|
|
||||||
case RDEE:
|
|
||||||
return ParseReadEepromResponse(receivedFrame, deviceId);
|
|
||||||
case WREE:
|
|
||||||
return ParseWriteEepromResponse(receivedFrame, deviceId);
|
|
||||||
case Calb:
|
|
||||||
return ParseCalibrateTempResponse(receivedFrame, deviceId);
|
|
||||||
case SETHOTTEMP:
|
|
||||||
return ParseSetHotTempResponse(receivedFrame, deviceId);
|
|
||||||
default:
|
|
||||||
return new ParseResult(false, $"未知指令:0x{originalCmd:X2}", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 各指令解析实现(严格对齐协议响应格式)
|
|
||||||
/// <summary>
|
|
||||||
/// 解析握手响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseHelloResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6) // 协议固定响应帧长6字节
|
|
||||||
return new ParseResult(false, "握手响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(协议3.1)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "握手成功" : $"握手失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "握手响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取温度响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 0x0D) // 协议固定响应帧长13字节(0x0D)
|
|
||||||
return new ParseResult(false, $"读取温度响应帧长错误:需13字节,实际{frame.Length}字节", null);
|
|
||||||
|
|
||||||
// 提取数据:参数1(设置温度)、参数2(实际温度)、参数3(预留)、标志位、状态位(协议3.2)
|
|
||||||
ushort setTempParam = (ushort)((frame[4] << 8) | frame[5]); // 高位在前
|
|
||||||
ushort actualTempParam = (ushort)((frame[6] << 8) | frame[7]); // 高位在前
|
|
||||||
byte flag = frame[10]; // 预留标志位(NC)
|
|
||||||
byte status = frame[11];
|
|
||||||
|
|
||||||
// 转换为实际温度(除以100,精度0.1℃)
|
|
||||||
double setTemp = setTempParam / 100.0;
|
|
||||||
double actualTemp = actualTempParam / 100.0;
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取温度成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "设置温度(℃)", setTemp },
|
|
||||||
{ "实际温度(℃)", actualTemp },
|
|
||||||
{ "预留标志位", flag },
|
|
||||||
{ "原始设置温度参数", $"0x{setTempParam:X4}" },
|
|
||||||
{ "原始实际温度参数", $"0x{actualTempParam:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取AD响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadAdcResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 0x0A) // 协议固定响应帧长10字节(0x0A),修正原13字节错误
|
|
||||||
return new ParseResult(false, $"读取AD响应帧长错误:需10字节,实际{frame.Length}字节", null);
|
|
||||||
|
|
||||||
// 提取数据:AD值(5-6字节)、预留(7-8字节)、状态位(9字节)(协议3.3)
|
|
||||||
ushort adcValue = (ushort)((frame[4] << 8) | frame[5]); // 高位在前
|
|
||||||
byte status = frame[8];
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取AD成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "AD值", adcValue },
|
|
||||||
{ "原始AD参数", $"0x{adcValue:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取AD响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取EEPROM响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadEepromResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length < 6) // 协议响应帧长≥6字节
|
|
||||||
return new ParseResult(false, "读取EEPROM响应帧长不足(需≥6字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:参数1~n(5到N-2字节)、状态位(N-2字节)(协议3.4)
|
|
||||||
int dataLength = frame.Length - 6; // 数据字节数=N-6
|
|
||||||
byte[] eepromData = new byte[dataLength];
|
|
||||||
Array.Copy(frame, 4, eepromData, 0, dataLength);
|
|
||||||
byte status = frame[frame.Length - 2];
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取EEPROM成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "读取数据长度(字节)", dataLength },
|
|
||||||
{ "读取数据(十六进制)", BitConverter.ToString(eepromData).Replace("-", " ") },
|
|
||||||
{ "原始数据数组", eepromData }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取EEPROM响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析写入EEPROM响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseWriteEepromResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6) // 协议固定响应帧长6字节
|
|
||||||
return new ParseResult(false, "写入EEPROM响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(协议3.5)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "写入EEPROM成功" : $"写入失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "写入EEPROM响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析校准温度响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseCalibrateTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6) // 协议固定响应帧长6字节
|
|
||||||
return new ParseResult(false, "校准温度响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(协议3.6)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "温度校准成功" : $"校准失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "校准温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析加热温度控制响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseSetHotTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6) // 协议固定响应帧长6字节
|
|
||||||
return new ParseResult(false, "加热温度响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(协议3.7)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "加热温度指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "加热温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 预留CRC16校验(协议未使用,保留以备扩展)
|
|
||||||
public static byte[] CRC16(byte[] data)
|
|
||||||
{
|
|
||||||
int len = data.Length;
|
|
||||||
if (len <= 0)
|
|
||||||
return new byte[] { 0, 0 };
|
|
||||||
|
|
||||||
ushort crc = 0xFFFF;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
crc = (ushort)(crc ^ data[i]);
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte hi = (byte)((crc & 0xFF00) >> 8);
|
|
||||||
byte lo = (byte)(crc & 0x00FF);
|
|
||||||
return BitConverter.IsLittleEndian ? new byte[] { lo, hi } : new byte[] { hi, lo };
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using Npgsql.Replication.PgOutput.Messages;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class LowTemperatureMagneticStirService : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null)
|
|
||||||
return;
|
|
||||||
var msg = tcpMsg.ParseStirng();
|
|
||||||
if (string.IsNullOrEmpty(msg)) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测连接状态
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
var state = ConnectionState.None;
|
|
||||||
if (ConnectorAdapter is not null)
|
|
||||||
{
|
|
||||||
state = await ConnectorAdapter.CheckConnectedAsync();
|
|
||||||
}
|
|
||||||
ConnectionState = state;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置电机转速
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="motorSpeed"></param>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> SetMotorSpeed(int motorSpeed, byte deviceId)
|
|
||||||
{
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendMotorControl(motorSpeed, deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return false;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
return result.IsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置温度
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="temperature"></param>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <param name="offTemp">关闭温度</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> SetTemperature(int temperature, byte deviceId, bool offTemp)
|
|
||||||
{
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendSetTemp(temperature, deviceId, offTemp), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return false;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
return result.IsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置加热温度,除霜
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hottemperature"></param>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> SetHotTemperature(int hottemperature, byte deviceId)
|
|
||||||
{
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendSetHotTemp(hottemperature, deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return false;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
return result.IsSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取电机转速
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<int> GetActualMotorSpeed(byte deviceId)
|
|
||||||
{
|
|
||||||
int motorSpeed = 0;
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendReadMotorSpeedRequest(deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return 0;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
motorSpeed = (int)result.Data["实际转速"];
|
|
||||||
}
|
|
||||||
return motorSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取当前温度
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<int> GetActualTemperature(byte deviceId)
|
|
||||||
{
|
|
||||||
int temperature = 0;
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendReadTempRequest(deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return 0;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
temperature = (int)result.Data["实际温度(℃)"];
|
|
||||||
}
|
|
||||||
return temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取开关盖状态
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<string> GetLidStatus(byte deviceId)
|
|
||||||
{
|
|
||||||
string status = string.Empty;
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(LowTemperatureUartHCM.SendReadIoStatusRequest(deviceId), TimeSpan.FromSeconds(3));
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return string.Empty;
|
|
||||||
ParseResult result = LowTemperatureUartHCM.ParseReceivedFrame(tcpMessage.Data);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
status = result.Data["开关盖状态"].ToString() ?? string.Empty;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,852 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO.Ports;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 高温温度模块 485 uart 定制HCM通信协议封装类(PC→主控板指令构建 + 主控板→PC指令解析)
|
|
||||||
/// </summary>
|
|
||||||
public static class LowTemperatureUartHCM
|
|
||||||
{
|
|
||||||
#region 协议常量定义(码表及指令规范)
|
|
||||||
private const byte ST = 0x5E; // 帧头
|
|
||||||
private const byte HELLO = 0x01; // 握手指令
|
|
||||||
private const byte STATUS = 0x05; // 读取报错状态
|
|
||||||
private const byte SETTEMP = 0x06; // 制冷温度控制
|
|
||||||
private const byte MOTOR = 0x07; // 电机控制
|
|
||||||
private const byte RDTEMP = 0x08; // 读取温度
|
|
||||||
private const byte RDADC = 0x09; // 读取传感器AD
|
|
||||||
private const byte RDEE = 0x11; // 读取EEPROM
|
|
||||||
private const byte WREE = 0x12; // 写入EEPROM
|
|
||||||
private const byte RDMotSpeed = 0x13; // 获取实际转速
|
|
||||||
private const byte RDIOStatus = 0x14; // 获取开关盖状态
|
|
||||||
private const byte Calb = 0x15; // 校准温度
|
|
||||||
private const byte SETHOTTEMP = 0x16; // 加热温度控制(补充遗漏指令)
|
|
||||||
private const byte RelayControl = 0x17; // 电磁阀控制(补充遗漏指令)
|
|
||||||
private const byte RESPONSE_FLAG = 0x80; // 上传指令标志(指令码 | 0x80)
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region
|
|
||||||
private static byte _cmdSequence = 0; // 指令序号(0-255自动溢出)
|
|
||||||
private static readonly object _lock = new object();// 线程安全锁(避免多线程序号混乱)
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 校验和计算(协议第6点:前n-1字节之和的低8位)
|
|
||||||
/// <summary>
|
|
||||||
/// 计算帧的校验和(核心:前length字节之和的低8位)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">待计算的帧数据</param>
|
|
||||||
/// <param name="length">参与计算的字节数(前n-1字节)</param>
|
|
||||||
/// <returns>校验和字节</returns>
|
|
||||||
private static byte CalculateChecksum(byte[] data, int length)
|
|
||||||
{
|
|
||||||
if (data == null || length <= 0 || length > data.Length)
|
|
||||||
throw new ArgumentException("校验和计算参数无效");
|
|
||||||
|
|
||||||
int sum = 0;
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
sum += data[i];
|
|
||||||
return (byte)(sum & 0xFF); // 取低8位,确保是1字节
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 指令序号自增(线程安全)
|
|
||||||
/// <summary>
|
|
||||||
/// 指令序号自增(0-255自动溢出,确保除溢出外无重复指令)
|
|
||||||
/// </summary>
|
|
||||||
private static void IncrementCmdSequence()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_cmdSequence++; // 字节类型自动溢出(255→0)
|
|
||||||
|
|
||||||
// 确保序号不超过0x7F(避免下发指令CMD被误认为上传指令)
|
|
||||||
if (_cmdSequence >= 0x80)
|
|
||||||
_cmdSequence = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取当前指令序号(带线程安全)
|
|
||||||
/// </summary>
|
|
||||||
private static byte GetCurrentCmdSequence()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
return _cmdSequence;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 下传指令构建(PC→主控板,返回byte[]帧)
|
|
||||||
/// <summary>
|
|
||||||
/// 握手指令(系统开机必发)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>握手指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendHello(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 按协议填充帧结构:ST → HELLO+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(HELLO | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4); // 前4字节求和取低8位
|
|
||||||
|
|
||||||
IncrementCmdSequence(); // 序号自增
|
|
||||||
AddFrameInterval(); // 帧间隔>2ms
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取报错状态指令
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>报错状态指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendStatusRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → STATUS+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(STATUS | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 温度控制指令(下发后主控板直接执行温度控制)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="targetTemp">目标温度(10.0-180.0℃,精度0.1)</param>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <param name="releaseControl">是否释放控制(true=0xFFFF,关断功率)关闭温度</param>
|
|
||||||
/// <returns>温度控制指令帧(7字节)</returns>
|
|
||||||
public static byte[] SendSetTemp(double targetTemp, byte deviceId = 0, bool releaseControl=false)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[7]; // 帧长固定7字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
int tempParam = 0; // 温度参数(16位:高8位+低8位)
|
|
||||||
|
|
||||||
// 处理参数:释放控制/正常温度
|
|
||||||
if (releaseControl)
|
|
||||||
{
|
|
||||||
tempParam = 0xFFFF; // 协议约定:释放控制=0xFFFF
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 参数校验:温度范围10.0-180.0℃(对应1000-18000)
|
|
||||||
if (targetTemp < -50.0 || targetTemp > 50.0)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(targetTemp), "温度必须在[-50 , 50]℃之间");
|
|
||||||
tempParam = (short)(targetTemp * 100); // 放大100倍(精度0.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 帧结构:ST → SETTEMP+序号 → 设备ID → LTH=7 → 参数1(高8) → 参数2(低8) → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(SETTEMP | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 7; // LTH固定为7
|
|
||||||
frame[4] = (byte)(tempParam >> 8); // 参数1(高8位)
|
|
||||||
frame[5] = (byte)(tempParam & 0xFF); // 参数2(低8位)
|
|
||||||
frame[6] = CalculateChecksum(frame, 6); // 前6字节求和
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 电机控制指令(设置电机转速)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="motorSpeed">电机转速(200-1500,16位参数)</param>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>电机控制指令帧(11字节,0x0B=11)</returns>
|
|
||||||
public static byte[] SendMotorControl(int motorSpeed, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
// 参数校验:转速范围100-1500
|
|
||||||
if (motorSpeed < 100 || motorSpeed > 1500)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(motorSpeed), "转速必须在100-1500之间");
|
|
||||||
|
|
||||||
byte[] frame = new byte[11]; // 帧长固定0x0B(11字节)
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
ushort speedParam = (ushort)motorSpeed; // 转速参数(16位)
|
|
||||||
|
|
||||||
// 帧结构:ST → MOTOR+序号 → 设备ID → LTH=0x0B → 0x10 → 预留0×3 → 参数4(高8) → 参数5(低8) → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(MOTOR | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 0x0B; // LTH固定为11
|
|
||||||
frame[4] = 0x10; // 协议固定值
|
|
||||||
frame[5] = 0; // 预留位1
|
|
||||||
frame[6] = 0; // 预留位2
|
|
||||||
frame[7] = 0; // 预留位3
|
|
||||||
frame[8] = (byte)(speedParam >> 8); // 参数4(高8位)
|
|
||||||
frame[9] = (byte)(speedParam & 0xFF); // 参数5(低8位)
|
|
||||||
frame[10] = CalculateChecksum(frame, 10); // 前10字节求和
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取温度指令(获取设置温度、实际温度、到温标志)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>读取温度指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendReadTempRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → RDTEMP+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RDTEMP | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取传感器AD指令(获取AD值)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>读取AD指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendReadAdcRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节(协议3.6)
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → RDADC+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RDADC | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取EEPROM指令(获取指定地址的硬件/调试信息)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="addrHigh">地址高位字节</param>
|
|
||||||
/// <param name="addrMid">地址中位字节</param>
|
|
||||||
/// <param name="addrLow">地址低位字节</param>
|
|
||||||
/// <param name="readLength">读取长度(字节数)</param>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>读取EEPROM指令帧(变长,9 + readLength字节)</returns>
|
|
||||||
public static byte[] SendReadEepromRequest(byte addrHigh, byte addrMid, byte addrLow, int readLength, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
// 参数校验:读取长度≥1(避免空数据)
|
|
||||||
if (readLength < 1)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(readLength), "读取长度必须≥1");
|
|
||||||
|
|
||||||
int frameLength = 9 + readLength; // 帧长N=9(固定段)+ 读取长度
|
|
||||||
byte[] frame = new byte[frameLength];
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → RDEE+序号 → 设备ID → LTH=N → 地址高→中→低 → 读取长度 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RDEE | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = (byte)frameLength; // LTH=N(实际帧长)
|
|
||||||
frame[4] = addrHigh; // 地址高位
|
|
||||||
frame[5] = addrMid; // 地址中位
|
|
||||||
frame[6] = addrLow; // 地址低位
|
|
||||||
frame[7] = (byte)readLength; // 读取长度
|
|
||||||
// 校验和:前(frameLength-1)字节求和(帧长-1 = 8 + readLength)
|
|
||||||
frame[frameLength - 1] = CalculateChecksum(frame, frameLength - 1);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 写入EEPROM指令(写入硬件/调试/标定参数)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="addrHigh">地址高位字节</param>
|
|
||||||
/// <param name="addrMid">地址中位字节</param>
|
|
||||||
/// <param name="addrLow">地址低位字节</param>
|
|
||||||
/// <param name="writeData">待写入的数据(字节数组)</param>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>写入EEPROM指令帧(变长,9 + writeData.Length字节)</returns>
|
|
||||||
public static byte[] SendWriteEepromRequest(byte addrHigh, byte addrMid, byte addrLow, byte[] writeData, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
// 参数校验:写入数据非空
|
|
||||||
if (writeData == null || writeData.Length == 0)
|
|
||||||
throw new ArgumentException("写入数据不能为空", nameof(writeData));
|
|
||||||
|
|
||||||
int frameLength = 9 + writeData.Length; // 帧长N=9(固定段)+ 数据长度
|
|
||||||
byte[] frame = new byte[frameLength];
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → WREE+序号 → 设备ID → LTH=N → 地址高→中→低 → 写入数据 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(WREE | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = (byte)frameLength; // LTH=N(实际帧长)
|
|
||||||
frame[4] = addrHigh; // 地址高位
|
|
||||||
frame[5] = addrMid; // 地址中位
|
|
||||||
frame[6] = addrLow; // 地址低位
|
|
||||||
// 填充写入数据(从第8字节开始,索引7)
|
|
||||||
Array.Copy(writeData, 0, frame, 7, writeData.Length);
|
|
||||||
// 校验和:前(frameLength-1)字节求和
|
|
||||||
frame[frameLength - 1] = CalculateChecksum(frame, frameLength - 1);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取实际转速指令
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>获取转速指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendReadMotorSpeedRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → RDMotSpeed+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RDMotSpeed | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取开关盖状态指令
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>获取开关盖状态指令帧(5字节)</returns>
|
|
||||||
public static byte[] SendReadIoStatusRequest(byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[5]; // 帧长固定5字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
|
|
||||||
// 帧结构:ST → RDIOStatus+序号 → 设备ID → LTH=5 → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RDIOStatus | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 5; // LTH固定为5
|
|
||||||
frame[4] = CalculateChecksum(frame, 4);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 校准温度指令(设置温度校准B值)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="calibBValue">校准B值(16位:B=(实际温度-目标温度)×100)</param>
|
|
||||||
/// <param name="deviceId">设备ID(0-255,默认0)</param>
|
|
||||||
/// <returns>校准温度指令帧(7字节)</returns>
|
|
||||||
public static byte[] SendCalibrateTempRequest(int calibBValue, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
// 参数校验:B值为16位有符号范围(-32768~32767)
|
|
||||||
if (calibBValue < short.MinValue || calibBValue > short.MaxValue)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(calibBValue), "校准B值必须在-32768~32767之间");
|
|
||||||
|
|
||||||
byte[] frame = new byte[7]; // 帧长固定7字节
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
ushort bParam = (ushort)calibBValue; // 转换为16位无符号(高位在前)
|
|
||||||
|
|
||||||
// 帧结构:ST → Calb+序号 → 设备ID → LTH=7 → 参数1(高8) → 参数2(低8) → 校验和
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(Calb | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 7; // LTH固定为7
|
|
||||||
frame[4] = (byte)(bParam >> 8); // 参数1(高8位)
|
|
||||||
frame[5] = (byte)(bParam & 0xFF); // 参数2(低8位)
|
|
||||||
frame[6] = CalculateChecksum(frame, 6); // 前6字节求和
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加热温度控制
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendSetHotTemp(double targetTemp, byte deviceId = 0, bool releaseControl = false)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[7];
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
ushort tempParam;
|
|
||||||
|
|
||||||
if (releaseControl)
|
|
||||||
{
|
|
||||||
tempParam = 0xFFFF; // 释放控制
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 协议范围:室温~100℃(对应室温*100~10000)
|
|
||||||
if (targetTemp < 20.0 || targetTemp > 100.0) // 室温暂以20℃为参考下限
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(targetTemp), "温度必须在[20.0 , 100]℃之间(参考室温)");
|
|
||||||
tempParam = (ushort)(targetTemp * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(SETHOTTEMP | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 7; // LTH=7
|
|
||||||
frame[4] = (byte)(tempParam >> 8);
|
|
||||||
frame[5] = (byte)(tempParam & 0xFF);
|
|
||||||
frame[6] = CalculateChecksum(frame, 6);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 电磁阀控制指令
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] SendRelayControl(bool isOpen, byte deviceId = 0)
|
|
||||||
{
|
|
||||||
byte[] frame = new byte[6];
|
|
||||||
byte seq = GetCurrentCmdSequence();
|
|
||||||
byte param = (byte)(isOpen ? 1 : 0); // 1=开启,0=关闭
|
|
||||||
|
|
||||||
frame[0] = ST;
|
|
||||||
frame[1] = (byte)(RelayControl | seq);
|
|
||||||
frame[2] = deviceId;
|
|
||||||
frame[3] = 6; // LTH=6
|
|
||||||
frame[4] = param;
|
|
||||||
frame[5] = CalculateChecksum(frame, 5);
|
|
||||||
|
|
||||||
IncrementCmdSequence();
|
|
||||||
AddFrameInterval();
|
|
||||||
return frame;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 指令解析(主控板→PC,返回结构化结果)
|
|
||||||
/// <summary>
|
|
||||||
/// 解析主控板返回的帧数据(入口方法)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="receivedFrame">主控板返回的原始字节数组</param>
|
|
||||||
/// <returns>解析结果(结构化对象,包含指令类型、状态、数据)</returns>
|
|
||||||
public static ParseResult ParseReceivedFrame(byte[] receivedFrame)
|
|
||||||
{
|
|
||||||
// 基础校验:帧非空、帧长≥5(最短帧为5字节)
|
|
||||||
if (receivedFrame == null || receivedFrame.Length < 5)
|
|
||||||
return new ParseResult(false, "无效帧:数据为空或长度不足", null);
|
|
||||||
|
|
||||||
// 1. 校验帧头(必须为ST=0x5E)
|
|
||||||
if (receivedFrame[0] != ST)
|
|
||||||
return new ParseResult(false, $"帧头错误:实际0x{receivedFrame[0]:X2},期望0x{ST:X2}", null);
|
|
||||||
|
|
||||||
// 2. 提取核心字段
|
|
||||||
byte cmdWithFlag = receivedFrame[1]; // 带0x80标志的指令码
|
|
||||||
byte deviceId = receivedFrame[2]; // 设备ID
|
|
||||||
byte frameLength = receivedFrame[3]; // 帧长LTH
|
|
||||||
byte checksum = receivedFrame[frameLength - 1]; // 帧中校验和
|
|
||||||
|
|
||||||
// 3. 校验帧长(实际长度必须等于帧长字段)
|
|
||||||
if (receivedFrame.Length != frameLength)
|
|
||||||
return new ParseResult(false, $"帧长不匹配:实际{receivedFrame.Length}字节,期望{frameLength}字节", null);
|
|
||||||
|
|
||||||
// 4. 校验和验证
|
|
||||||
byte calculatedChecksum = CalculateChecksum(receivedFrame, frameLength - 1);
|
|
||||||
if (calculatedChecksum != checksum)
|
|
||||||
return new ParseResult(false, $"校验和错误:实际0x{checksum:X2},计算0x{calculatedChecksum:X2}", null);
|
|
||||||
|
|
||||||
// 5. 去除响应标志,获取原始指令码
|
|
||||||
byte originalCmd = (byte)(cmdWithFlag & ~RESPONSE_FLAG);
|
|
||||||
|
|
||||||
// 6. 按指令类型分发解析
|
|
||||||
switch (originalCmd)
|
|
||||||
{
|
|
||||||
case HELLO:
|
|
||||||
return ParseHelloResponse(receivedFrame, deviceId);
|
|
||||||
case STATUS:
|
|
||||||
return ParseStatusResponse(receivedFrame, deviceId);
|
|
||||||
case SETTEMP:
|
|
||||||
return ParseSetTempResponse(receivedFrame, deviceId);
|
|
||||||
case MOTOR:
|
|
||||||
return ParseMotorResponse(receivedFrame, deviceId);
|
|
||||||
case RDTEMP:
|
|
||||||
return ParseReadTempResponse(receivedFrame, deviceId);
|
|
||||||
case RDADC:
|
|
||||||
return ParseReadAdcResponse(receivedFrame, deviceId);
|
|
||||||
case RDEE:
|
|
||||||
return ParseReadEepromResponse(receivedFrame, deviceId);
|
|
||||||
case WREE:
|
|
||||||
return ParseWriteEepromResponse(receivedFrame, deviceId);
|
|
||||||
case RDMotSpeed:
|
|
||||||
return ParseReadMotorSpeedResponse(receivedFrame, deviceId);
|
|
||||||
case RDIOStatus:
|
|
||||||
return ParseReadIoStatusResponse(receivedFrame, deviceId);
|
|
||||||
case Calb:
|
|
||||||
return ParseCalibrateTempResponse(receivedFrame, deviceId);
|
|
||||||
case SETHOTTEMP:
|
|
||||||
return ParseSetHotTempResponse(receivedFrame, deviceId);
|
|
||||||
case RelayControl:
|
|
||||||
return ParseRelayControlResponse(receivedFrame, deviceId);
|
|
||||||
default:
|
|
||||||
return new ParseResult(false, $"未知指令:0x{originalCmd:X2}", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 各指令解析实现
|
|
||||||
/// <summary>
|
|
||||||
/// 解析握手响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseHelloResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定6字节(协议3.1)
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "握手响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(0=成功)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "握手成功" : $"握手失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "握手响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析报错状态响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseStatusResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定8字节(协议3.2)
|
|
||||||
if (frame.Length != 8)
|
|
||||||
return new ParseResult(false, "报错状态响应帧长错误(需8字节)", null);
|
|
||||||
|
|
||||||
// 提取Error(2字节:Bit0-11)和状态位
|
|
||||||
ushort error = (ushort)((frame[4] << 8) | frame[5]);
|
|
||||||
byte status = frame[6];
|
|
||||||
|
|
||||||
// 解析Error按位含义(协议3.2)
|
|
||||||
var errorDesc = new Dictionary<string, bool>
|
|
||||||
{
|
|
||||||
{ "测温传感器故障(Bit0)", (error & (1 << 0)) != 0 },
|
|
||||||
{ "温度过高>200℃(Bit1)", (error & (1 << 1)) != 0 },
|
|
||||||
{ "温度过低≤0℃(Bit2)", (error & (1 << 2)) != 0 },
|
|
||||||
{ "电机故障(Bit3)", (error & (1 << 3)) != 0 },
|
|
||||||
{ "预留Bit4", (error & (1 << 4)) != 0 },
|
|
||||||
{ "预留Bit5", (error & (1 << 5)) != 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取报错状态成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "报错详情", errorDesc },
|
|
||||||
{ "原始Error值", $"0x{error:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "报错状态响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析温度控制响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseSetTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定6字节(协议3.3)
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "温度控制响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(0=成功)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "温度控制指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "温度控制响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析电机控制响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseMotorResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定6字节(协议3.4)
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "电机控制响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(0=成功)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "电机控制指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "电机控制响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取温度响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定0x0D(13字节,协议3.5)
|
|
||||||
if (frame.Length != 0x0D)
|
|
||||||
return new ParseResult(false, $"读取温度响应帧长错误(需13字节,实际{frame.Length}字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:设置温度(5-6字节)、实际温度(7-8字节)、预留(9-10)、标志位(11)、状态位(12)
|
|
||||||
ushort setTempParam = (ushort)((frame[4] << 8) | frame[5]);
|
|
||||||
ushort actualTempParam = (ushort)((frame[6] << 8) | frame[7]);
|
|
||||||
byte flag = frame[10]; // 0=未到温,1=到温
|
|
||||||
byte status = frame[11];
|
|
||||||
|
|
||||||
// 转换为实际温度(除以100,精度0.1)
|
|
||||||
double setTemp = setTempParam / 100.0;
|
|
||||||
double actualTemp = actualTempParam / 100.0;
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取温度成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "设置温度(℃)", setTemp },
|
|
||||||
{ "实际温度(℃)", actualTemp },
|
|
||||||
{ "到温标志", flag == 0 ? "未到温" : "已到温" },
|
|
||||||
{ "原始设置温度参数", $"0x{setTempParam:X4}" },
|
|
||||||
{ "原始实际温度参数", $"0x{actualTempParam:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取AD响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadAdcResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定0x0D(13字节,协议3.6)
|
|
||||||
if (frame.Length != 0x0D)
|
|
||||||
return new ParseResult(false, $"读取AD响应帧长错误(需13字节,实际{frame.Length}字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:AD值(5-6字节)、预留(7-8)、状态位(9)
|
|
||||||
ushort adcValue = (ushort)((frame[4] << 8) | frame[5]);
|
|
||||||
byte status = frame[8];
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取AD成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "AD值", adcValue },
|
|
||||||
{ "原始AD参数", $"0x{adcValue:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取AD响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析读取EEPROM响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadEepromResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长N≥6(协议3.7:返回长度-6为数据字节数)
|
|
||||||
if (frame.Length < 6)
|
|
||||||
return new ParseResult(false, "读取EEPROM响应帧长不足(需≥6字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:参数1~参数n(5到N-2字节)、状态位(N-2字节)
|
|
||||||
int dataLength = frame.Length - 6; // 数据字节数(N-6)
|
|
||||||
byte[] eepromData = new byte[dataLength];
|
|
||||||
Array.Copy(frame, 4, eepromData, 0, dataLength); // 从第5字节(索引4)开始复制
|
|
||||||
byte status = frame[frame.Length - 2]; // 状态位(N-2字节)
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "读取EEPROM成功" : $"读取失败(错误码:{status})" },
|
|
||||||
{ "读取数据长度(字节)", dataLength },
|
|
||||||
{ "读取数据(十六进制)", BitConverter.ToString(eepromData).Replace("-", " ") },
|
|
||||||
{ "原始数据数组", eepromData }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "读取EEPROM响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析写入EEPROM响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseWriteEepromResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定6字节(协议3.8)
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "写入EEPROM响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(0=成功)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "写入EEPROM成功" : $"写入失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "写入EEPROM响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析获取实际转速响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadMotorSpeedResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定8字节(协议3.9)
|
|
||||||
if (frame.Length != 8)
|
|
||||||
return new ParseResult(false, "获取转速响应帧长错误(需8字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:转速参数(5-6字节)、状态位(7字节)
|
|
||||||
ushort speedParam = (ushort)((frame[4] << 8) | frame[5]);
|
|
||||||
byte status = frame[6];
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "获取转速成功" : $"获取失败(错误码:{status})" },
|
|
||||||
{ "实际转速", speedParam },
|
|
||||||
{ "原始转速参数", $"0x{speedParam:X4}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "获取转速响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析获取开关盖状态响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseReadIoStatusResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定7字节(协议3.10)
|
|
||||||
if (frame.Length != 7)
|
|
||||||
return new ParseResult(false, "获取开关盖状态响应帧长错误(需7字节)", null);
|
|
||||||
|
|
||||||
// 提取数据:开关盖参数(5字节)、状态位(6字节)
|
|
||||||
byte ioParam = frame[4]; // 0=关盖,1=开盖
|
|
||||||
byte status = frame[5];
|
|
||||||
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "获取开关盖状态成功" : $"获取失败(错误码:{status})" },
|
|
||||||
{ "开关盖状态", ioParam == 0 ? "关盖" : "开盖" },
|
|
||||||
{ "原始状态参数", $"0x{ioParam:X2}" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "获取开关盖状态响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析校准温度响应
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseCalibrateTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
// 响应帧长固定6字节(协议3.11)
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "校准温度响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4]; // 状态位(0=成功)
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "温度校准指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "校准温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 加热温度控制响应解析
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseSetHotTempResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "加热温度响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4];
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "加热温度指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "加热温度响应解析成功", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 电磁阀控制响应解析
|
|
||||||
/// </summary>
|
|
||||||
private static ParseResult ParseRelayControlResponse(byte[] frame, byte deviceId)
|
|
||||||
{
|
|
||||||
if (frame.Length != 6)
|
|
||||||
return new ParseResult(false, "电磁阀控制响应帧长错误(需6字节)", null);
|
|
||||||
|
|
||||||
byte status = frame[4];
|
|
||||||
var data = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
{ "设备ID", deviceId },
|
|
||||||
{ "状态码", status },
|
|
||||||
{ "状态描述", status == 0 ? "电磁阀指令接收成功" : $"接收失败(错误码:{status})" }
|
|
||||||
};
|
|
||||||
return new ParseResult(true, "电磁阀控制响应解析成功", data);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
#endregion
|
|
||||||
/// <summary>
|
|
||||||
/// 帧间隔时间(协议要求>2ms,留3ms余量)
|
|
||||||
/// </summary>
|
|
||||||
private static void AddFrameInterval()
|
|
||||||
{
|
|
||||||
Task.Delay(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CRC16校验(用户原类中定义,协议未使用,保留以备扩展)
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] CRC16(byte[] data)
|
|
||||||
{
|
|
||||||
int len = data.Length;
|
|
||||||
if (len <= 0)
|
|
||||||
return new byte[] { 0, 0 };
|
|
||||||
|
|
||||||
ushort crc = 0xFFFF;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
crc = (ushort)(crc ^ data[i]);
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
byte hi = (byte)((crc & 0xFF00) >> 8);
|
|
||||||
byte lo = (byte)(crc & 0x00FF);
|
|
||||||
return BitConverter.IsLittleEndian ? new byte[] { lo, hi } : new byte[] { hi, lo };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 解析结果封装(包含成功状态、描述、数据)
|
|
||||||
/// </summary>
|
|
||||||
public class ParseResult
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 解析是否成功
|
|
||||||
/// </summary>
|
|
||||||
public bool IsSuccess { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析描述(成功/失败原因)
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解析后的数据(Key-Value结构,根据指令类型不同内容不同)
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, object> Data { get; }
|
|
||||||
|
|
||||||
public ParseResult(bool isSuccess, string description, Dictionary<string, object> data)
|
|
||||||
{
|
|
||||||
IsSuccess = isSuccess;
|
|
||||||
Description = description;
|
|
||||||
Data = data ?? new Dictionary<string, object>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,175 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices.USBScanner
|
|
||||||
{
|
|
||||||
public class USBScannerService : ConnectorBase
|
|
||||||
{
|
|
||||||
public SerialPortService MegaSerialPort { get; set; }
|
|
||||||
|
|
||||||
public bool IsConnected => this.MegaSerialPort?.IsOpen ?? false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 扫描仪数据接收事件(外部可订阅,实时获取串口数据)
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<Message> ScannerDataReceived;
|
|
||||||
|
|
||||||
#region Base
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
this.CoreService = coreService;
|
|
||||||
if (args != null && args.Length > 0 && args[0] is string portName)
|
|
||||||
{
|
|
||||||
this.SetConnection(portName);
|
|
||||||
}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// throw new ArgumentException("初始化失败:未传入有效的串口名称(portName)");
|
|
||||||
//}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void SetConnection(string portName)
|
|
||||||
{
|
|
||||||
// 若已有串口实例,先断开并清理
|
|
||||||
if (MegaSerialPort != null)
|
|
||||||
{
|
|
||||||
Disconnect();
|
|
||||||
}
|
|
||||||
this.MegaSerialPort = new SerialPortService(portName);
|
|
||||||
this.Connection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Connection()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (MegaSerialPort != null && !MegaSerialPort.IsOpen)
|
|
||||||
{
|
|
||||||
this.MegaSerialPort.Open();
|
|
||||||
// 2. 连接成功后订阅串口DataReceived事件(先取消再订阅,防止重复)
|
|
||||||
MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived; // 取消旧订阅
|
|
||||||
MegaSerialPort.DataReceived += MegaSerialPort_DataReceived; // 新订阅
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return ex.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.MegaSerialPort.IsOpen ? null : "连接异常";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<string> ConnectionAsync()
|
|
||||||
{
|
|
||||||
return Task.Run(this.Connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Disconnect()
|
|
||||||
{
|
|
||||||
if (MegaSerialPort != null)
|
|
||||||
{
|
|
||||||
// 3. 断开连接前取消事件订阅(避免内存泄漏)
|
|
||||||
MegaSerialPort.DataReceived -= MegaSerialPort_DataReceived;
|
|
||||||
MegaSerialPort.Dispose(); // 触发SerialPortService的Close和资源释放
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
this.Disconnect();
|
|
||||||
this.MegaSerialPort = null;
|
|
||||||
}
|
|
||||||
#endregion Base
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 串口DataReceived事件的处理方法(自动触发)
|
|
||||||
/// </summary>
|
|
||||||
private void MegaSerialPort_DataReceived(object sender, Message msg)
|
|
||||||
{
|
|
||||||
if (msg == null || msg.Data == null || msg.Data.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
string receivedData = msg.ReadString(SerialPortDataFormat.Char); // 用串口配置的格式解析
|
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
// 步骤2:对外透传数据(触发自定义事件)
|
|
||||||
// 外部订阅ScannerDataReceived即可实时获取数据
|
|
||||||
// --------------------------
|
|
||||||
OnScannerDataReceived(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 触发自定义事件(线程安全的事件触发方式)
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnScannerDataReceived(Message msg)
|
|
||||||
{
|
|
||||||
// 临时保存事件引用,避免多线程下事件被注销后为空
|
|
||||||
var handler = ScannerDataReceived;
|
|
||||||
handler?.Invoke(this, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string SendAndReceive(string cmd, TimeSpan timeout)
|
|
||||||
{
|
|
||||||
string mReply = string.Empty;
|
|
||||||
EventHandler<Message> tempHandler = (sender, msg) =>
|
|
||||||
{
|
|
||||||
mReply = msg.ReadString(SerialPortDataFormat.Char);
|
|
||||||
};
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MegaSerialPort.DataReceived += tempHandler;
|
|
||||||
MegaSerialPort.WriteLine(cmd);
|
|
||||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
|
||||||
while (string.IsNullOrEmpty(mReply) && stopwatch.Elapsed < timeout)
|
|
||||||
{
|
|
||||||
Thread.Sleep(50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
MegaSerialPort.DataReceived -= tempHandler;
|
|
||||||
}
|
|
||||||
return mReply;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
if (this.MegaSerialPort.IsOpen)
|
|
||||||
{
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ConnectionState.NotConnected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
if (string.IsNullOrEmpty(await ConnectionAsync()))
|
|
||||||
{
|
|
||||||
return ConnectionState.IsConnected;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ConnectionState.NotConnected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,163 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices.WeightDevice
|
|
||||||
{
|
|
||||||
public class WeightService_MT : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
public event EventHandler<TcpMessage> DataReceived;
|
|
||||||
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
this.CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null)
|
|
||||||
return;
|
|
||||||
var msg = tcpMsg.ParseStirng();
|
|
||||||
if (string.IsNullOrEmpty(msg)) return;
|
|
||||||
this.Logger.LogInformation($"接收到梅特勒称重仪_{this.Name}数据:{msg?.Trim()}");
|
|
||||||
this.DataReceived?.Invoke(this, tcpMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重置清零
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="immediatly">是否立即,否:使用采用当前稳定重量值作为零点</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool Reset(bool immediately = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string command = immediately ? "ZI" : "Z";
|
|
||||||
ConnectorAdapter.WriteLine(command);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
base.Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService", "Reset", 150, false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 去皮
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="immediately"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool Peel(bool immediately = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string command = immediately ? "TI" : "T";
|
|
||||||
ConnectorAdapter.WriteLine(command);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
base.Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService", "Peel", 150, false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ClearPeel()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string command = "TAC";
|
|
||||||
ConnectorAdapter.WriteLine(command);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
base.Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService", "ClearPeel", 150, false);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取称重值
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeout"></param>
|
|
||||||
/// <param name="immediately"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<string> ReadWeightAsnyc(TimeSpan timeout, bool immediately = true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string cmd = immediately ? "SI\r\n" : "S\r\n";
|
|
||||||
byte[] sendBytes = ConnectorAdapter.StringEncoder.GetBytes(cmd);
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(sendBytes, timeout);
|
|
||||||
if (tcpMessage is null)
|
|
||||||
return string.Empty;
|
|
||||||
var result = tcpMessage.ParseStirng();
|
|
||||||
//"S S 0.0000 g\r\n"
|
|
||||||
//"S D -0.0000 g\r\n"
|
|
||||||
var match = Regex.Match(result, @"-?[0-9]+(\.[0-9]{1,4})");
|
|
||||||
return match.Success ? match.Groups[0].Value : "";
|
|
||||||
|
|
||||||
//这边是不是要加个校验 S d 像你写的那样 无所谓的 因为 能读到就行 我看你的 引用地方 也没有对 非重量数值做处理
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
base.Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService", "ReadWeightAsnyc", 150, false);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测连接状态
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
var state = ConnectionState.None;
|
|
||||||
if (ConnectorAdapter is not null)
|
|
||||||
{
|
|
||||||
state = await ConnectorAdapter.CheckConnectedAsync();
|
|
||||||
}
|
|
||||||
ConnectionState = state;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,243 +0,0 @@
|
||||||
using MegaRobo.Connections;
|
|
||||||
using MegaRobo.Connections.Modbus;
|
|
||||||
using MegaRobo.Connections.Sockets.Tcp;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.ControlDevices.Abstractions;
|
|
||||||
using MegaRobo.Logger;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using static MegaRobo.C00225155.ControlDevices.HighTemperatureMotorControlService;
|
|
||||||
using static MegaRobo.Connections.Modbus.ModbusParams;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.ControlDevices
|
|
||||||
{
|
|
||||||
public class WeightService_Ts02 : ConnectorBase<MegaTcpClient>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 寄存器地址枚举
|
|
||||||
/// </summary>
|
|
||||||
private enum MotorRegisterAddress : ushort
|
|
||||||
{
|
|
||||||
WeightValueLow = 0x0000,
|
|
||||||
WeightValueHigh = 0x0002,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1:校正 2:置零
|
|
||||||
/// </summary>
|
|
||||||
Command = 0x0007,
|
|
||||||
/// <summary>
|
|
||||||
/// 1:去皮
|
|
||||||
/// </summary>
|
|
||||||
Peel = 0x000B,
|
|
||||||
/// <summary>
|
|
||||||
/// 波特率 19200
|
|
||||||
/// </summary>
|
|
||||||
BuartRate = 0x0010,
|
|
||||||
|
|
||||||
Decimalpos = 0x0014,
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<string> Initialize(ICoreService coreService, params object[] args)
|
|
||||||
{
|
|
||||||
CoreService = coreService;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
base.CoreService = coreService;
|
|
||||||
if (args is [IPEndPoint remoteHost, ..])
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter = new MegaTcpClient
|
|
||||||
{
|
|
||||||
Logger = coreService.Logger,
|
|
||||||
Name = base.Name
|
|
||||||
};
|
|
||||||
if (base.ConnectorAdapter != null)
|
|
||||||
{
|
|
||||||
base.ConnectorAdapter.DataReceived += ConnectorOnDataReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionState = await base.ConnectorAdapter.ConnectAsync(remoteHost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex);
|
|
||||||
return await Task.FromResult(ex.Message);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConnectorOnDataReceived(object sender, TcpMessage tcpMsg)
|
|
||||||
{
|
|
||||||
if (tcpMsg is null || tcpMsg.Data == null || tcpMsg.Data.Length == 0)
|
|
||||||
return;
|
|
||||||
string hexData = BitConverter.ToString(tcpMsg.Data).Replace("-", " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Task<ConnectionState> ReconnectAsync()
|
|
||||||
{
|
|
||||||
return base.ReconnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<ConnectionState> CheckConnected()
|
|
||||||
{
|
|
||||||
var state = ConnectionState.None;
|
|
||||||
if (ConnectorAdapter is not null)
|
|
||||||
{
|
|
||||||
state = await ConnectorAdapter.CheckConnectedAsync();
|
|
||||||
}
|
|
||||||
ConnectionState = state;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 去皮
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> Peel()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: 4, // 从站地址(默认1)
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.Peel,
|
|
||||||
lstData: (ushort)1,
|
|
||||||
byteOrder: ByteOrder.AB // 协议要求高字节在前
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"去皮失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ConnectorAdapter.Write(writeResult.Respond);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService_Ts02", "Peel", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 置零
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> ResetZero()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: 4, // 从站地址(默认1)
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.Command,
|
|
||||||
lstData: (ushort)2,
|
|
||||||
byteOrder: ByteOrder.AB
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"置零失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectorAdapter.Write(writeResult.Respond);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService_Ts02", "ResetZero", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取称的值
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<double> ReadWeightValue()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var readResult = ModbusRTU.GetReadMessage(
|
|
||||||
slaveStation: 4,
|
|
||||||
readType: ModbusReadCodes.READ_HOLDING_REGISTERS, // 功能码03
|
|
||||||
startAdr: (ushort)MotorRegisterAddress.WeightValueLow,
|
|
||||||
length: 2 // 状态寄存器是1个16位寄存器,长度=1
|
|
||||||
);
|
|
||||||
|
|
||||||
if (readResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
//FF 03 00 14 00 01 D1 D0 => 04 03 02 00 01 B5 84
|
|
||||||
var digitCountMessage = await ConnectorAdapter.WriteAndGetReplyAsync(new byte[] { 0xFF, 0x03, 0x00, 0x14, 0x00, 0x01, 0xD1, 0xD0 }, TimeSpan.FromSeconds(5));
|
|
||||||
if (digitCountMessage == null || digitCountMessage.Data == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var digitCount = ModbusRTU.ReadRegisterShort(digitCountMessage.Data, ByteOrder.AB).Respond[0];
|
|
||||||
var tcpMessage = await ConnectorAdapter.WriteAndGetReplyAsync(readResult.Respond, TimeSpan.FromSeconds(5));
|
|
||||||
if (tcpMessage == null || tcpMessage.Data == null)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var parseResult = ModbusRTU.ReadRegisterShort(tcpMessage.Data, ByteOrder.AB);
|
|
||||||
if (!parseResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"状态解析失败:{parseResult.Message}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var res = ((int)parseResult.Respond[0] | ((int)parseResult.Respond[1] << 16)) / (Math.Pow(10, digitCount));
|
|
||||||
return res;
|
|
||||||
//return parseResult.Respond[0] / 10.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService_Ts02", "ReadWeightValue", 150, false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置小数点位数
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">0~5</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public async Task<bool> SetDecimalPoint(ushort value)
|
|
||||||
{
|
|
||||||
if (value < 0 || value > 5)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var writeResult = ModbusRTU.WriteRegisterSingle(
|
|
||||||
deviceAdress: 4, // 从站地址(默认1)
|
|
||||||
startAdress: (ushort)MotorRegisterAddress.Decimalpos,
|
|
||||||
lstData: value,
|
|
||||||
byteOrder: ByteOrder.AB
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!writeResult.IsSuccessed)
|
|
||||||
{
|
|
||||||
Logger.LogError($"写小数点位数失败:{writeResult.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ConnectorAdapter.Write(writeResult.Respond);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogException(ex, null, LogEvent.Error, null, LogLevel.Error, "WeightService_Ts02", "SetDecimalPoint", 150, false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.DataAccess;
|
|
||||||
using System.Linq;
|
|
||||||
using MegaRobo.Entities.ViewTT;
|
|
||||||
using MegaRobo.C00225155.Entities.Entity_DB;
|
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
|
||||||
using System.Collections;
|
|
||||||
using System.DirectoryServices.Protocols;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.DataAccess;
|
|
||||||
|
|
||||||
public class DataAccessService : DataAccessBase, IDataAccessService
|
|
||||||
{
|
|
||||||
|
|
||||||
#region Labx
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public async Task<(bool, string)> CreateLiquid1mlPipetteProductModel(Liquid_lml_Dose liquidmodel)
|
|
||||||
{
|
|
||||||
(bool isOk, string msg) = (false, "");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var ctx = this.GetEntities();
|
|
||||||
var modelId = await ctx.Insertable(liquidmodel).ExecuteReturnEntityAsync();
|
|
||||||
isOk = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.OnException(ex);
|
|
||||||
msg = ex.Message;
|
|
||||||
}
|
|
||||||
return (isOk, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(bool, string)> CreateLiquid1mlPipetteProductModel_React(Liquid_lml_React liquidmodel)
|
|
||||||
{
|
|
||||||
(bool isOk, string msg) = (false, "");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using var ctx = this.GetEntities();
|
|
||||||
var modelId = await ctx.Insertable(liquidmodel).ExecuteReturnEntityAsync();
|
|
||||||
isOk = true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.OnException(ex);
|
|
||||||
msg = ex.Message;
|
|
||||||
}
|
|
||||||
return (isOk, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region 从数据库查询结果数据
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MegaRobo.Contract;
|
|
||||||
using MegaRobo.DataAccess;
|
|
||||||
using MegaRobo.Logger.Loggers.Database;
|
|
||||||
using MegaRobo.Entities.ViewTT;
|
|
||||||
using MegaRobo.C00225155.Entities.Entity_DB;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.DataAccess;
|
|
||||||
|
|
||||||
public interface IDataAccessService : IDataAccess, IEntitiesAccess, ILoggerDataService, IUserDataService
|
|
||||||
{
|
|
||||||
#region Labx
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 从数据库查询结果数据
|
|
||||||
|
|
||||||
Task<(bool, string)> CreateLiquid1mlPipetteProductModel(Liquid_lml_Dose liquidmodel);
|
|
||||||
|
|
||||||
Task<(bool, string)> CreateLiquid1mlPipetteProductModel_React(Liquid_lml_React liquidmodel);
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
|
||||||
<ImplicitUsings>disable</ImplicitUsings>
|
|
||||||
<Nullable>disable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="MegaRobo.Authentication">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Authentication.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Contract">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Contract.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.DataAccess">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.DataAccess.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Entities">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Entities.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="MegaRobo.Logger">
|
|
||||||
<HintPath>..\..\..\Common\Published\NET7.0\MegaRobo.Logger.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.110" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\MegaRobo.C00225155.Entities\MegaRobo.C00225155.Entities.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
using System.ComponentModel;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities;
|
|
||||||
|
|
||||||
public enum DeviceNames
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///投料站预称重
|
|
||||||
/// </summary>
|
|
||||||
PreWeight,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站梅特勒粉末称重模块
|
|
||||||
/// </summary>
|
|
||||||
PowderWeight,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站扫码枪
|
|
||||||
/// </summary>
|
|
||||||
Scanner,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站粉末扫码枪
|
|
||||||
/// </summary>
|
|
||||||
Scanner_Powder,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
Scanner_React,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 反应站料仓架扫码枪
|
|
||||||
/// </summary>
|
|
||||||
Scanner_ReactRack,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站移液枪
|
|
||||||
/// </summary>
|
|
||||||
Pipette_Dose_1ml,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站 id=1移液枪
|
|
||||||
/// </summary>
|
|
||||||
Pipette_Dose_1ml_1,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站id=2移液枪
|
|
||||||
/// </summary>
|
|
||||||
Pipette_Dose_1ml_2,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站id=3移液枪
|
|
||||||
/// </summary>
|
|
||||||
Pipette_Dose_1ml_3,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站id=4移液枪
|
|
||||||
/// </summary>
|
|
||||||
Pipette_Dose_1ml_4,
|
|
||||||
/// <summary>
|
|
||||||
/// 反应站1ml移液器
|
|
||||||
/// </summary>
|
|
||||||
Pipette_React_1ml,
|
|
||||||
/// <summary>
|
|
||||||
/// 投料站PLC
|
|
||||||
/// </summary>
|
|
||||||
Plc1,
|
|
||||||
/// <summary>
|
|
||||||
/// 反应站PLC
|
|
||||||
/// </summary>
|
|
||||||
Plc2,
|
|
||||||
/// <summary>
|
|
||||||
/// 高温震荡
|
|
||||||
/// </summary>
|
|
||||||
HightTemperatureShake,
|
|
||||||
/// <summary>
|
|
||||||
/// 高温震荡电机
|
|
||||||
/// </summary>
|
|
||||||
HightTemperatureMotor,
|
|
||||||
/// <summary>
|
|
||||||
/// 低温磁力搅拌
|
|
||||||
/// </summary>
|
|
||||||
LowTemperatureMagneticStir,
|
|
||||||
}
|
|
||||||
|
|
@ -1,204 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
public class DataResult_Dose:ObservableObject
|
|
||||||
{
|
|
||||||
private int boxId;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶工装号
|
|
||||||
/// </summary>
|
|
||||||
public int BoxId
|
|
||||||
{
|
|
||||||
get => boxId;
|
|
||||||
set => SetProperty(ref boxId, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int bottleId;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶号
|
|
||||||
/// </summary>
|
|
||||||
public int BottleId
|
|
||||||
{
|
|
||||||
get => bottleId;
|
|
||||||
set => SetProperty(ref bottleId, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string sampleCode;
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶SN码
|
|
||||||
/// </summary>
|
|
||||||
public string SampleCode
|
|
||||||
{
|
|
||||||
get => sampleCode;
|
|
||||||
set => SetProperty(ref sampleCode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<AddLiquidData_Dose> liquidAdditives = new ObservableCollection<AddLiquidData_Dose>();
|
|
||||||
public ObservableCollection<AddLiquidData_Dose> LiquidAdditives
|
|
||||||
{
|
|
||||||
get => liquidAdditives;
|
|
||||||
set => SetProperty(ref liquidAdditives, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ObservableCollection<AddPowderData_Dose> powderAdditives = new ObservableCollection<AddPowderData_Dose>();
|
|
||||||
public ObservableCollection<AddPowderData_Dose> PowderAdditives
|
|
||||||
{
|
|
||||||
get => powderAdditives;
|
|
||||||
set => SetProperty(ref powderAdditives, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AddLiquidData_Dose : ObservableObject
|
|
||||||
{
|
|
||||||
private string sampleCode;
|
|
||||||
/// <summary>
|
|
||||||
/// SN码
|
|
||||||
/// </summary>
|
|
||||||
public string SampleCode
|
|
||||||
{
|
|
||||||
get => sampleCode;
|
|
||||||
set => SetProperty(ref sampleCode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string liquidname;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName
|
|
||||||
{
|
|
||||||
get => liquidname;
|
|
||||||
set => SetProperty(ref liquidname, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double TargetVolume
|
|
||||||
{
|
|
||||||
get => targetVolume;
|
|
||||||
set => SetProperty(ref targetVolume, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double actualAddVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 实际加入体积
|
|
||||||
/// </summary>
|
|
||||||
public double ActualAddVolume
|
|
||||||
{
|
|
||||||
get => actualAddVolume;
|
|
||||||
set => SetProperty(ref actualAddVolume, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int addState;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:表示还未增加 1:表示正在增加 2:表示增加完成
|
|
||||||
/// </summary>
|
|
||||||
public int AddState
|
|
||||||
{
|
|
||||||
get => addState;
|
|
||||||
set => SetProperty(ref addState, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string precision;
|
|
||||||
/// <summary>
|
|
||||||
/// 精度
|
|
||||||
/// </summary>
|
|
||||||
public string Precision
|
|
||||||
{
|
|
||||||
get => precision;
|
|
||||||
set => SetProperty(ref precision, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool result;
|
|
||||||
/// <summary>
|
|
||||||
/// 检测结果,true合格,false不合格
|
|
||||||
/// </summary>
|
|
||||||
public bool bOK
|
|
||||||
{
|
|
||||||
get => result;
|
|
||||||
set => SetProperty(ref result, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AddPowderData_Dose : ObservableObject
|
|
||||||
{
|
|
||||||
private string sampleCode;
|
|
||||||
/// <summary>
|
|
||||||
/// SN码
|
|
||||||
/// </summary>
|
|
||||||
public string SampleCode
|
|
||||||
{
|
|
||||||
get => sampleCode;
|
|
||||||
set => SetProperty(ref sampleCode, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string powdername;
|
|
||||||
/// <summary>
|
|
||||||
/// 粉末名称
|
|
||||||
/// </summary>
|
|
||||||
public string PowderName
|
|
||||||
{
|
|
||||||
get => powdername;
|
|
||||||
set => SetProperty(ref powdername, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double targetWeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标加入量
|
|
||||||
/// </summary>
|
|
||||||
public double TargetWeight
|
|
||||||
{
|
|
||||||
get => targetWeight;
|
|
||||||
set => SetProperty(ref targetWeight, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double actualAddWeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 实际加入量
|
|
||||||
/// </summary>
|
|
||||||
public double ActualAddWeight
|
|
||||||
{
|
|
||||||
get => actualAddWeight;
|
|
||||||
set => SetProperty(ref actualAddWeight, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int addState;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:表示还未增加 1:表示正在增加 2:表示增加完成
|
|
||||||
/// </summary>
|
|
||||||
public int AddState
|
|
||||||
{
|
|
||||||
get => addState;
|
|
||||||
set => SetProperty(ref addState, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string precision;
|
|
||||||
/// <summary>
|
|
||||||
/// 精度
|
|
||||||
/// </summary>
|
|
||||||
public string Precision
|
|
||||||
{
|
|
||||||
get => precision;
|
|
||||||
set => SetProperty(ref precision, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool result;
|
|
||||||
/// <summary>
|
|
||||||
/// 检测结果,true合格,false不合格
|
|
||||||
/// </summary>
|
|
||||||
public bool bOK
|
|
||||||
{
|
|
||||||
get => result;
|
|
||||||
set => SetProperty(ref result, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
[Table(Comment = "反应站1ml移液枪吸液配置", Name = "Liquid_lml_React")]
|
|
||||||
public class Liquid_lml_React
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 自增ID
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = true, IsPrimaryKey = true, Comment = "自增ID")]
|
|
||||||
public int Id { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 1:50ul 2:300ul 3;1000ul
|
|
||||||
/// </summary>
|
|
||||||
public int TipType { set; get; }
|
|
||||||
/// <summary>
|
|
||||||
/// 开盖取样/稀释加样
|
|
||||||
/// </summary>
|
|
||||||
public string FuncType { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 瓶子类型 1:12ml样品瓶 2:5ml样品瓶
|
|
||||||
/// </summary>
|
|
||||||
public int BottleType { set; get; }
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 以纯水为标准的吸取比例
|
|
||||||
/// </summary>
|
|
||||||
public double Ratio { get; set; } = 1.0000;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体编号
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidParamId { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 容器编号
|
|
||||||
/// </summary>
|
|
||||||
public int ContainerPlateIndex { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 平台编号
|
|
||||||
/// </summary>
|
|
||||||
public int PlatformCode { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 是否液面探测
|
|
||||||
/// </summary>
|
|
||||||
public int LiqLedetec { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 吸液高度
|
|
||||||
/// </summary>
|
|
||||||
public int AspireHeight { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 分液高度
|
|
||||||
/// </summary>
|
|
||||||
public int DispenHeight { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 液体体积/
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidVolume { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Liquid_lml_React_Show : ObservableObject
|
|
||||||
{
|
|
||||||
private int id;
|
|
||||||
public int Id { get => id; set => SetProperty(ref id, value); }
|
|
||||||
|
|
||||||
private int tiptype;
|
|
||||||
/// <summary>
|
|
||||||
/// 1:50ul 2:300ul 3;1000ul
|
|
||||||
/// </summary>
|
|
||||||
public int TipType { get => tiptype; set => SetProperty(ref tiptype, value); }
|
|
||||||
|
|
||||||
private string functype;
|
|
||||||
/// <summary>
|
|
||||||
/// 用途,开盖取样/稀释加样
|
|
||||||
/// </summary>
|
|
||||||
public string FuncType { get => functype; set => SetProperty(ref functype, value); }
|
|
||||||
|
|
||||||
private int bottletype;
|
|
||||||
/// <summary>
|
|
||||||
/// 瓶子类型 1:12ml样品瓶 2:5ml样品瓶
|
|
||||||
/// </summary>
|
|
||||||
public int BottleType { get => bottletype; set => SetProperty(ref bottletype, value); }
|
|
||||||
|
|
||||||
private string liquidname;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName { get => liquidname; set => SetProperty(ref liquidname, value); }
|
|
||||||
|
|
||||||
private double ratio = 1.0000;
|
|
||||||
public double Ratio { get => ratio; set => SetProperty(ref ratio, value); }
|
|
||||||
|
|
||||||
private int liquidparamid;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体编号
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidParamId { get => liquidparamid; set => SetProperty(ref liquidparamid, value); }
|
|
||||||
|
|
||||||
private int containerPlateIndex;
|
|
||||||
/// <summary>
|
|
||||||
/// 容器编号
|
|
||||||
/// </summary>
|
|
||||||
public int ContainerPlateIndex { get => containerPlateIndex; set => SetProperty(ref containerPlateIndex, value); }
|
|
||||||
|
|
||||||
private int plateformcode;
|
|
||||||
/// <summary>
|
|
||||||
/// 平台编号
|
|
||||||
/// </summary>
|
|
||||||
public int PlatformCode { get => plateformcode; set => SetProperty(ref plateformcode, value); }
|
|
||||||
|
|
||||||
private int liqLedetec;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否液面探测
|
|
||||||
/// </summary>
|
|
||||||
public int LiqLedetec { get => liqLedetec; set => SetProperty(ref liqLedetec, value); }
|
|
||||||
|
|
||||||
private int aspireHeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 吸液高度
|
|
||||||
/// </summary>
|
|
||||||
public int AspireHeight { get => aspireHeight; set => SetProperty(ref aspireHeight, value); }
|
|
||||||
|
|
||||||
private int dispenHeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 分液高度
|
|
||||||
/// </summary>
|
|
||||||
public int DispenHeight { get => dispenHeight; set => SetProperty(ref dispenHeight, value); }
|
|
||||||
|
|
||||||
private int liquidVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体体积/
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidVolume { get => liquidVolume; set => SetProperty(ref liquidVolume, value); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,136 +0,0 @@
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
[Table(Comment = "投料站1ml移液枪吸液配置", Name = "Liquid_lml_Dose")]
|
|
||||||
public class Liquid_lml_Dose
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 自增ID
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsIdentity = true, IsPrimaryKey = true, Comment = "自增ID")]
|
|
||||||
public int Id { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 1:50ul 2:300ul 3;1000ul
|
|
||||||
/// </summary>
|
|
||||||
public int TipType { set; get; }
|
|
||||||
///// <summary>
|
|
||||||
///// 瓶子类型 1:12ml样品瓶 2:5ml样品瓶
|
|
||||||
///// </summary>
|
|
||||||
//public int BottleType { set; get; }
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 以纯水为标准的吸取比例
|
|
||||||
/// </summary>
|
|
||||||
public double Ratio { get; set; } = 1.0000;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体编号
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidParamId { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 吸液高度
|
|
||||||
/// </summary>
|
|
||||||
public int AspireHeight { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 分液高度
|
|
||||||
/// </summary>
|
|
||||||
public int DispenHeight { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 容器编号
|
|
||||||
/// </summary>
|
|
||||||
public int ContainerPlateIndex { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 平台编号
|
|
||||||
/// </summary>
|
|
||||||
public int PlatformCode { get; set; }
|
|
||||||
/// <summary>
|
|
||||||
/// 是否液面探测
|
|
||||||
/// </summary>
|
|
||||||
public int LiqLedetec { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 液体体积/
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidVolume { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Liquid_lml_Dose_Show : ObservableObject
|
|
||||||
{
|
|
||||||
private int id;
|
|
||||||
public int Id { get => id; set => SetProperty(ref id, value); }
|
|
||||||
|
|
||||||
private int tiptype;
|
|
||||||
/// <summary>
|
|
||||||
/// 1:50ul 2:300ul 3;1000ul
|
|
||||||
/// </summary>
|
|
||||||
public int TipType { get => tiptype; set => SetProperty(ref tiptype, value); }
|
|
||||||
|
|
||||||
//private int bottletype;
|
|
||||||
///// <summary>
|
|
||||||
///// 瓶子类型 1:12ml样品瓶 2:5ml样品瓶
|
|
||||||
///// </summary>
|
|
||||||
//public int BottleType { get => bottletype; set => SetProperty(ref bottletype, value); }
|
|
||||||
|
|
||||||
private string liquidname;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体名称
|
|
||||||
/// </summary>
|
|
||||||
public string LiquidName { get => liquidname; set => SetProperty(ref liquidname, value); }
|
|
||||||
|
|
||||||
private double ratio = 1.0000;
|
|
||||||
public double Ratio { get => ratio; set => SetProperty(ref ratio, value); }
|
|
||||||
|
|
||||||
private int liquidparamid;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体编号
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidParamId { get => liquidparamid; set => SetProperty(ref liquidparamid, value); }
|
|
||||||
|
|
||||||
private int containerPlateIndex;
|
|
||||||
/// <summary>
|
|
||||||
/// 容器编号
|
|
||||||
/// </summary>
|
|
||||||
public int ContainerPlateIndex { get => containerPlateIndex; set => SetProperty(ref containerPlateIndex, value); }
|
|
||||||
|
|
||||||
private int plateformcode;
|
|
||||||
/// <summary>
|
|
||||||
/// 平台编号
|
|
||||||
/// </summary>
|
|
||||||
public int PlatformCode { get => plateformcode; set => SetProperty(ref plateformcode, value); }
|
|
||||||
|
|
||||||
private int liqLedetec;
|
|
||||||
/// <summary>
|
|
||||||
/// 是否液面探测
|
|
||||||
/// </summary>
|
|
||||||
public int LiqLedetec { get => liqLedetec; set => SetProperty(ref liqLedetec, value); }
|
|
||||||
|
|
||||||
private int aspireHeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 吸液高度
|
|
||||||
/// </summary>
|
|
||||||
public int AspireHeight { get => aspireHeight; set => SetProperty(ref aspireHeight, value); }
|
|
||||||
|
|
||||||
private int dispenHeight;
|
|
||||||
/// <summary>
|
|
||||||
/// 分液高度
|
|
||||||
/// </summary>
|
|
||||||
public int DispenHeight { get => dispenHeight; set => SetProperty(ref dispenHeight, value); }
|
|
||||||
|
|
||||||
private int liquidVolume;
|
|
||||||
/// <summary>
|
|
||||||
/// 液体体积/
|
|
||||||
/// </summary>
|
|
||||||
public int LiquidVolume { get => liquidVolume; set => SetProperty(ref liquidVolume, value); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// PLC 错误信息点位
|
|
||||||
/// </summary>
|
|
||||||
public class PLCErrorPoint
|
|
||||||
{
|
|
||||||
public string ErrorAddress { get; set; }
|
|
||||||
public string ErrorInfo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
using MegaRobo.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
[Table(Comment = "PLC报警点位信息 ", Name = "PlcPointDict")]
|
|
||||||
public class PlcPointDict
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 唯一的Guid
|
|
||||||
/// </summary>
|
|
||||||
[Column(IsPrimaryKey = true)]
|
|
||||||
public string Guid { get; set; }
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
public short Address { get; set; }
|
|
||||||
|
|
||||||
public string ValueTypeName { get; set; }
|
|
||||||
|
|
||||||
public int FunType { get; set; }
|
|
||||||
|
|
||||||
public int Level { get; set; }
|
|
||||||
|
|
||||||
public string Antidote { get; set; }
|
|
||||||
|
|
||||||
public string Descr { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public static class PlcPoints_MaterialDose
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 1s周期 0和1切换
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCHeartPluse = 3000;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:None 1:手动 2:自动
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCMode = 3001;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:None 1:停止 2:运行中
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCRunStatus = 3002;
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化状态 0:None 1:初始化中 2:初始化失败 3:初始化完成
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCInitialStatus = 3003;
|
|
||||||
/// <summary>
|
|
||||||
/// 消息状态 0:无消息 1:有消息
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCInfoStatus = 3004;
|
|
||||||
/// <summary>
|
|
||||||
/// 处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_TransferPlate_inProcessingTaskNo = 3100;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:需初始化;
|
|
||||||
/// 1:硬件故障中;
|
|
||||||
/// 2:初始化中;
|
|
||||||
/// 3:初始化失败;
|
|
||||||
/// 4:功能完全屏蔽中;
|
|
||||||
/// 5:准备就绪,空闲中;
|
|
||||||
/// 6:与其他单元任务冲突,自主去往避让位置中;
|
|
||||||
/// 10:此任务与其他单元任务冲突,是否继续等待?
|
|
||||||
/// 11:运行上位机任务中;
|
|
||||||
/// 12:运行上位机任务中,但在等待其他单元到避让位置;
|
|
||||||
/// 15:运行上位机任务中,部分功能屏蔽;
|
|
||||||
/// 16:任务暂停中;
|
|
||||||
/// 21:失败;
|
|
||||||
/// 22:完成;
|
|
||||||
/// 99:任务撤销;
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_TransferPlate_RunResult = 3101;
|
|
||||||
|
|
||||||
public readonly static ushort R_TransferPlate_BoxPos = 3102;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 机械手处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public static ushort R_Robot_inProcessingTaskNo = 3200;
|
|
||||||
/// <summary>
|
|
||||||
/// 机械臂执行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_Robot_RunResult = 3201;
|
|
||||||
public readonly static ushort R_MetAddPowderModuleDoorState = 3220;
|
|
||||||
public readonly static ushort R_Robot_ArriveScanPos = 3221;
|
|
||||||
public readonly static ushort R_Robot_ArriveSideScanPos = 3222;
|
|
||||||
public readonly static ushort R_Robot_ArrivePreWeightPos = 3223;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液枪处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_BottleLidAndPipette_inProcessingTaskNo = 3300;
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液执行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_BottleLidAndPipette_RunResult = 3301;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪Z轴初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_1mlPipetteZInit = 3320;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_1mlPipetteInit = 3321;
|
|
||||||
|
|
||||||
|
|
||||||
public readonly static Dictionary<ushort, ushort> W_PCHeartPluse = new Dictionary<ushort, ushort> {
|
|
||||||
{ (ushort)DeviceNames.Plc1, 2000 }, { (ushort)DeviceNames.Plc2, 2000 }};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 模式切换 间隔200ms
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCMode = 2001;
|
|
||||||
/// <summary>
|
|
||||||
/// 1:停止 2:运行中
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCRunStatus = 2002;
|
|
||||||
/// <summary>
|
|
||||||
/// 整机初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Initial = 2003;
|
|
||||||
/// <summary>
|
|
||||||
/// 消息确认
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_InformationConfirm = 2004;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上位机有报警提示 0:无 1:有(用于触发蜂鸣器响)
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCErrorTip = 2008;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上位机有警告提示 0:无 1:有(用于触发蜂鸣器响)
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCAlarmTip = 2009;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 传送平台任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_TransferPlate_TaskQueue = 2100;
|
|
||||||
/// <summary>
|
|
||||||
/// 传送平台任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_TransferPlate_TaskNo = 2101;
|
|
||||||
/// <summary>
|
|
||||||
/// 传送平台任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_TransferPlate_TaskCancel = 2199;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 机械臂任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_TaskQueue = 2200;
|
|
||||||
/// <summary>
|
|
||||||
/// 机械臂任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_TaskNo = 2201;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标区域
|
|
||||||
/// 1:手套箱传送平台; 2:Tip托盘存放平台;12:托盘存放平台;
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_Param1 = 2202;
|
|
||||||
/// <summary>
|
|
||||||
/// 目标托盘位置号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_Param2 = 2203;
|
|
||||||
/// <summary>
|
|
||||||
/// 托盘类型:1:40mL瓶; 2:12mL瓶; 3:5mL瓶; 4:TIP头;
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_Param3 = 2204;
|
|
||||||
|
|
||||||
public readonly static ushort W_Robot_Param4 = 2205;
|
|
||||||
public readonly static ushort W_Robot_Param5 = 2206;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 扫码完成 1:ok 2:ng
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_ScanResult = 2221;
|
|
||||||
/// <summary>
|
|
||||||
/// 侧面扫码完成 1:ok 2:ng
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_SideScanResult = 2222;
|
|
||||||
/// <summary>
|
|
||||||
/// 预称重完成
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_PreWeightFinish = 2223;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 机械臂任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Robot_TaskCancel = 2299;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液枪 任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_TaskQueue = 2300;
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液枪任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_TaskNo = 2301;
|
|
||||||
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_Param1 = 2302;
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_Param2 = 2303;
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_Param3 = 2304;
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_Param4 = 2305;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪Z轴初始化结果 1:OK 2:NG
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_1mlPipetteZInitResult = 2320;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪初始化结果 1:OK 2:NG
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_1mlPipetteInitResult = 2321;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液枪任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_BottleLidAndPipette_TaskCancel = 2399;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Entity_DB
|
|
||||||
{
|
|
||||||
public static class PlcPoints_React
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 1s周期 0和1切换
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCHeartPluse = 3000;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:None 1:手动 2:自动
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCMode = 3001;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:None 1:停止 2:运行中
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCRunStatus = 3002;
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化状态 0:None 1:初始化中 2:初始化失败 3:初始化完成
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCInitialStatus = 3003;
|
|
||||||
/// <summary>
|
|
||||||
/// 消息状态 0:无消息 1:有消息
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_PLCInfoStatus = 3004;
|
|
||||||
/// <summary>
|
|
||||||
/// 旋转料仓处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_RotatorRack_inProcessingTaskNo = 3100;
|
|
||||||
/// <summary>
|
|
||||||
/// 0:需初始化;
|
|
||||||
/// 1:硬件故障中;
|
|
||||||
/// 2:初始化中;
|
|
||||||
/// 3:初始化失败;
|
|
||||||
/// 4:功能完全屏蔽中;
|
|
||||||
/// 5:准备就绪,空闲中;
|
|
||||||
/// 6:与其他单元任务冲突,自主去往避让位置中;
|
|
||||||
/// 10:此任务与其他单元任务冲突,是否继续等待?
|
|
||||||
/// 11:运行上位机任务中;
|
|
||||||
/// 12:运行上位机任务中,但在等待其他单元到避让位置;
|
|
||||||
/// 15:运行上位机任务中,部分功能屏蔽;
|
|
||||||
/// 16:任务暂停中;
|
|
||||||
/// 21:失败;
|
|
||||||
/// 22:完成;
|
|
||||||
/// 99:任务撤销;
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_RotatorRack_RunResult = 3101;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 进出托盘处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public static ushort R_InOutPlate_inProcessingTaskNo = 3200;
|
|
||||||
/// <summary>
|
|
||||||
/// 进出托盘执行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_InOutPlate_RunResult = 3201;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 龙门移载处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_GantryTransfer_inProcessingTaskNo = 3300;
|
|
||||||
/// <summary>
|
|
||||||
/// 开关盖&移液执行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_GantryTransfer_RunResult = 3301;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪Z轴初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_1mlPipetteZInit = 3320;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_1mlPipetteInit = 3321;
|
|
||||||
/// <summary>
|
|
||||||
/// 允许上外瓶
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_UploadOuterBottle = 3322;
|
|
||||||
/// <summary>
|
|
||||||
/// 允许上滤芯
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_UploadInnerBottle = 3323;
|
|
||||||
/// <summary>
|
|
||||||
/// 允许加样本或者稀释剂
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_AddSampleOrDiluent = 3324;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 磁力搅拌处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public static ushort R_LowTemperatureMagneticStir_inProcessingTaskNo = 3400;
|
|
||||||
/// <summary>
|
|
||||||
/// 磁力搅拌执行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_LowTemperatureMagneticStir_RunResult = 3401;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 磁力搅拌器1 盖子状态 1:打开 2:关闭
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_LowTemperatureMagneticStir_LidState1 = 3420;
|
|
||||||
/// <summary>
|
|
||||||
/// 磁力搅拌器2 盖子状态 1:打开 2:关闭
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_LowTemperatureMagneticStir_LidState2 = 3421;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹 处理中任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_NitrogenBlowing__inProcessingTaskNo = 3500;
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹运行结果
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_NitrogenBlowing_RunResult = 3501;
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹 上盖状态 1:打开 2:关闭
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort R_NitrogenBlowing_LidState = 3550;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public readonly static Dictionary<ushort, ushort> W_PCHeartPluse = new Dictionary<ushort, ushort> {
|
|
||||||
{ (ushort)DeviceNames.Plc1, 2000 }, { (ushort)DeviceNames.Plc2, 2000 }};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 模式切换 间隔200ms
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCMode = 2001;
|
|
||||||
/// <summary>
|
|
||||||
/// 1:停止 2:运行中
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCRunStatus = 2002;
|
|
||||||
/// <summary>
|
|
||||||
/// 整机初始化
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Initial = 2003;
|
|
||||||
/// <summary>
|
|
||||||
/// 消息确认
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_InformationConfirm = 2004;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上位机有报警提示 0:无 1:有(用于触发蜂鸣器响)
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCErrorTip = 2008;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 上位机有警告提示 0:无 1:有(用于触发蜂鸣器响)
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_PCAlarmTip = 2009;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 旋转料仓任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_RotatorRack_TaskQueue = 2100;
|
|
||||||
/// <summary>
|
|
||||||
/// 旋转料仓任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_RotatorRack_TaskNo = 2101;
|
|
||||||
/// <summary>
|
|
||||||
/// 旋转料仓任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_RotatorRack_TaskCancel = 2199;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 进出托盘任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_InOutPlate_TaskQueue = 2200;
|
|
||||||
/// <summary>
|
|
||||||
/// 进出托盘任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_InOutPlate_TaskNo = 2201;
|
|
||||||
/// <summary>
|
|
||||||
/// 进出托盘任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_InOutPlate_TaskCancel = 2299;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 龙门移载 任务队列序号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_GantryTransfer_TaskQueue = 2300;
|
|
||||||
/// <summary>
|
|
||||||
/// 龙门移载任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_GantryTransfer_TaskNo = 2301;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪Z轴初始化结果 1:OK 2:NG
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_1mlPipetteZInitResult = 2320;
|
|
||||||
/// <summary>
|
|
||||||
/// 1ml移液枪初始化结果 1:OK 2:NG
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_1mlPipetteInitResult = 2321;
|
|
||||||
/// <summary>
|
|
||||||
/// 请求转盘转动
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_Rotate = 2322;
|
|
||||||
/// <summary>
|
|
||||||
/// 针加液管道编号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_NeedleAddLiquidNo = 2323;
|
|
||||||
/// <summary>
|
|
||||||
/// 针加液体积
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_NeedleAddLiquidVolume = 2324;
|
|
||||||
/// <summary>
|
|
||||||
/// 龙门移载任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_GantryTransfer_TaskCancel = 2399;
|
|
||||||
/// <summary>
|
|
||||||
/// 低温磁力搅拌
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_LowTemperatureMagneticStir_TaskQueue = 2400;
|
|
||||||
/// <summary>
|
|
||||||
/// 低温磁力搅拌任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_LowTemperatureMagneticStir_TaskNo = 2401;
|
|
||||||
/// <summary>
|
|
||||||
/// 低温磁力搅拌任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_LowTemperatureMagneticStir_TaskCancel = 2499;
|
|
||||||
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// 高温震荡
|
|
||||||
///// </summary>
|
|
||||||
//public readonly static ushort W_HighTemperatureShake_TaskQueue = 2400;
|
|
||||||
///// <summary>
|
|
||||||
///// 高温震荡搅拌任务号
|
|
||||||
///// </summary>
|
|
||||||
//public readonly static ushort W_HighTemperatureShake_TaskNo = 2401;
|
|
||||||
///// <summary>
|
|
||||||
///// 高温震荡搅拌任务撤销
|
|
||||||
///// </summary>
|
|
||||||
//public readonly static ushort W_HighTemperatureShake_TaskCancel = 2499;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹 任务队列
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_NitrogenBlowing_TaskQueue = 2500;
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹任务号
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_NitrogenBlowing_TaskNo = 2401;
|
|
||||||
/// <summary>
|
|
||||||
/// 氮吹任务撤销
|
|
||||||
/// </summary>
|
|
||||||
public readonly static ushort W_NitrogenBlowing_TaskCancel = 2599;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Enums
|
|
||||||
{
|
|
||||||
public enum DeviceType
|
|
||||||
{
|
|
||||||
Type1ML = 1,
|
|
||||||
Type5ML = 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.Enums
|
|
||||||
{
|
|
||||||
public enum PlateformPos
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 过渡舱外
|
|
||||||
/// </summary>
|
|
||||||
TransferOut = 1,
|
|
||||||
/// <summary>
|
|
||||||
/// 过渡舱内
|
|
||||||
/// </summary>
|
|
||||||
TransferIn = 2,
|
|
||||||
/// <summary>
|
|
||||||
/// 取粉末治具的位置,最终停在这
|
|
||||||
/// </summary>
|
|
||||||
GloveBox1 = 3,
|
|
||||||
/// <summary>
|
|
||||||
/// 除去粉末治具之外的取放位置
|
|
||||||
/// </summary>
|
|
||||||
GloveBox2 = 4,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
namespace MegaRobo.C00225155.Entities.Enums;
|
|
||||||
|
|
||||||
public enum ViewNames
|
|
||||||
{
|
|
||||||
HomeView = 1,
|
|
||||||
SettingView, //硬件通讯配置
|
|
||||||
CommunicationDebugView, //通讯调试
|
|
||||||
FlowConfigView, //配方流程
|
|
||||||
AdditivePipetteConfigView,
|
|
||||||
UserView,
|
|
||||||
LoggerView,
|
|
||||||
Pipette1mlWindow = 10,
|
|
||||||
Pipette5mlWindow = 11,
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities
|
|
||||||
{
|
|
||||||
public enum DeviceStatus
|
|
||||||
{
|
|
||||||
Disable,
|
|
||||||
Idel,
|
|
||||||
CarryOn, //搬运中
|
|
||||||
Initing,
|
|
||||||
Runing,
|
|
||||||
Pause,
|
|
||||||
Finish,
|
|
||||||
Abort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
namespace MegaRobo.C00225155.Entities.FromWeb
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using System.Globalization;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request
|
|
||||||
/// </summary>
|
|
||||||
public partial class ConsumableBox
|
|
||||||
{
|
|
||||||
[JsonProperty("consumable")]
|
|
||||||
public List<Consumable> Consumable { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Consumable
|
|
||||||
{
|
|
||||||
[JsonProperty("detail")]
|
|
||||||
public List<Detail> Detail { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// _40mL原液工装 = 1,_12mL样品工装 = 2,_5mL样品工装 = 3,_2mL外瓶工装 = 4,_滤芯瓶工装 = 5,_16mL粉末瓶工装=6
|
|
||||||
/// ,_125mL粉末瓶工装=7 ,_50uLTip头工装= 8,_300uLTip头工装=9 ,_1000uLTip头工装=10
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public int FixtureType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("posInUpload")]
|
|
||||||
public int PosInUpload { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// tip余量
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("remainCount")]
|
|
||||||
public int RemainCount { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具二维码
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial class Detail
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 母液或粉末名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("code")]
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 盒中的位置
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("pos")]
|
|
||||||
public string Pos { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 余量(粉末单位mg 液体单位μl)
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("remainWeight")]
|
|
||||||
public double RemainWeight { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.FromWeb
|
|
||||||
{
|
|
||||||
public class ResponseBase
|
|
||||||
{
|
|
||||||
public int code { get; set; }
|
|
||||||
public string msg { get; set; }
|
|
||||||
|
|
||||||
public object data { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
// <auto-generated />
|
|
||||||
//
|
|
||||||
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
|
|
||||||
//
|
|
||||||
// using Apifox;
|
|
||||||
//
|
|
||||||
// var request = Request.FromJson(jsonString);
|
|
||||||
namespace MegaRobo.C00225155.Entities.FromWeb
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using System.Globalization;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据BS那最新的要求改的同步序列的数据结构 260116
|
|
||||||
/// </summary>
|
|
||||||
public class SampleSeqRequestEx
|
|
||||||
{
|
|
||||||
[JsonProperty("config")]
|
|
||||||
public ConfigEx Config { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样本序列,管子信息
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("sampleSeqs")]
|
|
||||||
public List<SampleSeq> SampleSeqs { get; set; }
|
|
||||||
|
|
||||||
public SampleSeqRequestEx FromJson(string json) => JsonConvert.DeserializeObject<SampleSeqRequestEx>(json);
|
|
||||||
public string ToJson() => JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConfigEx
|
|
||||||
{
|
|
||||||
[JsonProperty("boxInfo")]
|
|
||||||
public List<BoxInfoEx> BoxInfo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BoxInfoEx
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 载具类型,_40mL原液工装 = 1,_12mL样品工装 = 2,_5mL样品工装 = 3,_2mL外瓶工装 = 4,_滤芯瓶工装 = 5,_16mL粉末瓶工装=6
|
|
||||||
/// ,_125mL粉末瓶工装=7 ,_50uLTip头工装= 8,_300uLTip头工装=9 ,_1000uLTip头工装=10
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public int FixtureType { get; set; } //BoxTypeEnum
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具所在的位置,1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("posInUpload")]
|
|
||||||
public int PosInUpload { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具二维码
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("carrierQrCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Request
|
|
||||||
/// </summary>
|
|
||||||
public class SampleSeqRequest
|
|
||||||
{
|
|
||||||
[JsonProperty("config")]
|
|
||||||
public Config Config { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样本序列,管子信息
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("sampleSeqs")]
|
|
||||||
public List<SampleSeq> SampleSeqs { get; set; }
|
|
||||||
|
|
||||||
public SampleSeqRequest FromJson(string json) => JsonConvert.DeserializeObject<SampleSeqRequest>(json);
|
|
||||||
public string ToJson() => JsonConvert.SerializeObject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Config
|
|
||||||
{
|
|
||||||
[JsonProperty("boxInfo")]
|
|
||||||
public List<SampleSeqConfig> BoxInfo { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleSeqConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 载具类型,_40mL原液工装 = 1,_12mL样品工装 = 2,_5mL样品工装 = 3,_2mL外瓶工装 = 4,_滤芯瓶工装 = 5,_16mL粉末瓶工装=6
|
|
||||||
/// ,_125mL粉末瓶工装=7 ,_50uLTip头工装= 8,_300uLTip头工装=9 ,_1000uLTip头工装=10
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("fixtureType")]
|
|
||||||
public int FixtureType { get; set; } //BoxTypeEnum
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具所在的位置,1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("posInUpload")]
|
|
||||||
public int PosInUpload { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 剩余tip数目,fixtureType=8、9、10时需要传入剩余tip数目
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("remainCount")]
|
|
||||||
public int RemainCount { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具二维码
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("snCode")]
|
|
||||||
public string SnCode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleSeq
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 区域deviceKey,A1
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("area")]
|
|
||||||
public string Area { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 载具1~7
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("carrier")]
|
|
||||||
public string Carrier { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样品名称,作为5/12ml原液瓶或者粉末需要传入其名称,对于样品瓶需要传入样品名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("code")]
|
|
||||||
public string Code { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 位置 孔号
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("pos")]
|
|
||||||
public string Pos { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty("sampleConfig")]
|
|
||||||
public SampleConfig SampleConfig { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 序列id,对于样品瓶,每个都不一样,其他类型的无所谓
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("sampleSeqId")]
|
|
||||||
public long SampleSeqId { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 样本类型,_5mL = 1,_12mL = 2,其它 = 0
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("sampleType")]
|
|
||||||
public string SampleType { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleConfig
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 样品瓶工单信息,对于5/12ml样品瓶,必填,写入加粉加液信息
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("materialDoseFunctionFlow")]
|
|
||||||
public List<SampleFunction> MaterialDoseFunctionFlow { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleFunction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 添加类型,0液1固
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("functionFlowType")]
|
|
||||||
public int FunctionFlowType { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加量,液体单位是μl,固体单位是mg
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("targetVolumn")]
|
|
||||||
public double TargetVolumn { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 添加物名称,添加的液体或者固体名称
|
|
||||||
/// </summary>
|
|
||||||
[JsonProperty("userMaterialName")]
|
|
||||||
public string UserMaterialName { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.FromWeb.Test
|
|
||||||
{
|
|
||||||
public class Request
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities.FromWeb.Test
|
|
||||||
{
|
|
||||||
public class Response: ResponseBase
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MegaRobo.C00225155.Entities;
|
|
||||||
|
|
||||||
public sealed class HttpListenerEx : IDisposable
|
|
||||||
{
|
|
||||||
private Task _listener;
|
|
||||||
|
|
||||||
private readonly TcpListenerAdapter _tcpListener;
|
|
||||||
|
|
||||||
private CancellationTokenSource _cts;
|
|
||||||
|
|
||||||
private bool _disposedValue;
|
|
||||||
|
|
||||||
private bool _isListening;
|
|
||||||
|
|
||||||
public bool IsListening => _isListening;
|
|
||||||
|
|
||||||
public Socket Socket => _tcpListener.Socket;
|
|
||||||
|
|
||||||
public IPEndPoint LocalEndpoint { get; }
|
|
||||||
|
|
||||||
public event EventHandler<HttpListenerRequestEventArgs> Request;
|
|
||||||
|
|
||||||
private HttpListener()
|
|
||||||
{
|
|
||||||
_cts = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpListener(IPAddress address, int port)
|
|
||||||
: this()
|
|
||||||
{
|
|
||||||
LocalEndpoint = new IPEndPoint(address, port);
|
|
||||||
_tcpListener = new TcpListenerAdapter(LocalEndpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpListener(IPEndPoint endpoint)
|
|
||||||
: this()
|
|
||||||
{
|
|
||||||
_tcpListener = new TcpListenerAdapter(endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (_disposedValue)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException("Object has been disposed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_cts != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("HttpListener is already running.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_cts = new CancellationTokenSource();
|
|
||||||
_isListening = true;
|
|
||||||
_listener = Task.Run((Func<Task?>)StartListenerAsync, _cts.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task StartListenerAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_tcpListener.Start();
|
|
||||||
while (_isListening)
|
|
||||||
{
|
|
||||||
TcpClientAdapter client = await _tcpListener.AcceptTcpClientAsync().ConfigureAwait(continueOnCapturedContext: false);
|
|
||||||
HttpListenerRequest request = new HttpListenerRequest(client);
|
|
||||||
Task.Run(async delegate
|
|
||||||
{
|
|
||||||
HttpListenerResponse response = new HttpListenerResponse(request, client);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await request.ProcessAsync();
|
|
||||||
response.Initialize();
|
|
||||||
if (this.Request == null)
|
|
||||||
{
|
|
||||||
response.NotFound();
|
|
||||||
response.Close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.Request(this, new HttpListenerRequestEventArgs(request, response));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
response.CloseSocket();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_isListening = false;
|
|
||||||
_cts = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
if (_cts == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("HttpListener is not running.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.Request = null;
|
|
||||||
_cts.Cancel();
|
|
||||||
_cts = null;
|
|
||||||
_isListening = false;
|
|
||||||
_tcpListener.Stop();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_listener.Wait(TimeSpan.FromMilliseconds(1.0));
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<HttpListenerContext> GetContextAsync()
|
|
||||||
{
|
|
||||||
TaskCompletionSource<HttpListenerContext> tcs = new TaskCompletionSource<HttpListenerContext>();
|
|
||||||
EventHandler<HttpListenerRequestEventArgs> requestHandler = null;
|
|
||||||
requestHandler = delegate (object sender, HttpListenerRequestEventArgs evArgs)
|
|
||||||
{
|
|
||||||
HttpListenerContext result = new HttpListenerContext(evArgs.Request, evArgs.Response);
|
|
||||||
tcs.SetResult(result);
|
|
||||||
Request -= requestHandler;
|
|
||||||
};
|
|
||||||
Request += requestHandler;
|
|
||||||
return tcs.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (!_disposedValue)
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
_disposedValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(disposing: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue