Compare commits
No commits in common. "main" and "change" have entirely different histories.
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# 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
|
||||
363
.gitignore
vendored
Normal file
363
.gitignore
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
## 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
|
||||
79
BOB.sln
Normal file
79
BOB.sln
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36221.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BOB", "BOB\BOB.csproj", "{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logger", "Logger\Logger.csproj", "{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ORM", "ORM\ORM.csproj", "{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{D8209B91-D7D0-444B-B569-D3FA74D191DD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Command", "Command\Command.csproj", "{49D249DE-CB09-4390-89DC-6165965C3933}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeviceCommand", "DeviceCommand\DeviceCommand.csproj", "{94177FB3-45E4-466E-BB9F-761295736D35}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProcessManager", "ProcessManager\ProcessManager.csproj", "{269FEC4B-B5AD-4BE8-853F-56C37A3557A6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "Model\Model.csproj", "{E2897246-96B3-48BE-AA08-4E774BE2BCFB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CAN驱动", "CAN驱动\CAN驱动.csproj", "{65DCA56F-A0EB-407F-80B9-C5C5F0E69681}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FC10E4D4-0AA3-487B-B023-F8D2949E45ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9150C6A9-AE8D-42C9-8B2D-9DD04A3E7E74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4DE5DC6C-7121-4EB9-B8A8-90C694F451E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D8209B91-D7D0-444B-B569-D3FA74D191DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D8209B91-D7D0-444B-B569-D3FA74D191DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8209B91-D7D0-444B-B569-D3FA74D191DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8209B91-D7D0-444B-B569-D3FA74D191DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6C684FE1-C773-4B9D-89F1-9266C7B32DC0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{49D249DE-CB09-4390-89DC-6165965C3933}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{94177FB3-45E4-466E-BB9F-761295736D35}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{269FEC4B-B5AD-4BE8-853F-56C37A3557A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{269FEC4B-B5AD-4BE8-853F-56C37A3557A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{269FEC4B-B5AD-4BE8-853F-56C37A3557A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{269FEC4B-B5AD-4BE8-853F-56C37A3557A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E2897246-96B3-48BE-AA08-4E774BE2BCFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E2897246-96B3-48BE-AA08-4E774BE2BCFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E2897246-96B3-48BE-AA08-4E774BE2BCFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E2897246-96B3-48BE-AA08-4E774BE2BCFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65DCA56F-A0EB-407F-80B9-C5C5F0E69681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65DCA56F-A0EB-407F-80B9-C5C5F0E69681}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65DCA56F-A0EB-407F-80B9-C5C5F0E69681}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65DCA56F-A0EB-407F-80B9-C5C5F0E69681}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {22BD9235-6581-454D-97D8-F4E932F80888}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
31
BOB/App.xaml
Normal file
31
BOB/App.xaml
Normal file
@ -0,0 +1,31 @@
|
||||
<prism:PrismApplication x:Class="BOB.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:BOB"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<!--MaterialDesign: MahApps Compatibility-->
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Fonts.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.MahApps;component/Themes/MaterialDesignTheme.MahApps.Flyout.xaml" />
|
||||
|
||||
<!--MahApps-->
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
|
||||
|
||||
<!--MaterialDesign-->
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign3.Defaults.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Secondary/MaterialDesignColor.Lime.xaml" />
|
||||
|
||||
<!--自定义style-->
|
||||
<ResourceDictionary Source="Resources\Styles\WindowStyle.xaml"></ResourceDictionary>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</prism:PrismApplication>
|
||||
141
BOB/App.xaml.cs
Normal file
141
BOB/App.xaml.cs
Normal file
@ -0,0 +1,141 @@
|
||||
using BOB.Converters;
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels;
|
||||
using BOB.ViewModels.Dialogs;
|
||||
using BOB.Views;
|
||||
using BOB.Views.Dialogs;
|
||||
using Castle.DynamicProxy;
|
||||
using Model.SQLModel;
|
||||
using ORM;
|
||||
using Service.Implement;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace BOB
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : PrismApplication
|
||||
{
|
||||
protected override Window CreateShell()
|
||||
{
|
||||
return Container.Resolve<ShellView>();
|
||||
}
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
if (e.Args.Length > 0)
|
||||
{
|
||||
string deviceName = e.Args[0];
|
||||
SystemConfig.Instance.Title = deviceName;
|
||||
InitDataBase(deviceName);
|
||||
//Debugger.Launch();
|
||||
}
|
||||
else
|
||||
{
|
||||
SystemConfig.Instance.Title = "设备2";//模拟打开的设备
|
||||
InitDataBase("设备2");
|
||||
}
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
private void InitDataBase(string deviceName)
|
||||
{
|
||||
int tenantId = 0;
|
||||
string dbFileName;
|
||||
switch (deviceName)
|
||||
{
|
||||
case "设备1":
|
||||
tenantId = 10001;
|
||||
dbFileName = "设备1.db";
|
||||
break;
|
||||
case "设备2":
|
||||
tenantId = 10002;
|
||||
dbFileName = "设备2.db";
|
||||
break;
|
||||
case "设备3":
|
||||
tenantId = 10003;
|
||||
dbFileName = "设备3.db";
|
||||
break;
|
||||
case "水冷机和环境箱":
|
||||
tenantId = 10004;
|
||||
dbFileName = "水冷机和环境箱.db";
|
||||
break;
|
||||
default:
|
||||
throw new Exception("未知设备");
|
||||
}
|
||||
|
||||
// 设置租户 ID,初始化雪花 ID WorkId/DatacenterId
|
||||
DatabaseConfig.SetTenant(tenantId);
|
||||
|
||||
// 设置数据库路径
|
||||
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
|
||||
string folder = Path.Combine(baseDir, "SQLDB");
|
||||
if (!Directory.Exists(folder))
|
||||
Directory.CreateDirectory(folder);
|
||||
string dbPath = Path.Combine(folder, dbFileName);
|
||||
DatabaseConfig.SetDbConnection($"Data Source={dbPath}");
|
||||
|
||||
// 创建数据库文件并检查连接
|
||||
DatabaseConfig.CreateDatabaseAndCheckConnection(createDatabase: true, checkConnection: true);
|
||||
SqlSugarContext.DbContext.CodeFirst.InitTables(typeof(BackFeedData), typeof(EAELD9080Data), typeof(IT6724CData),typeof(PSB1100Data));
|
||||
}
|
||||
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
var regionManager = Container.Resolve<IRegionManager>();
|
||||
regionManager.RequestNavigate("ShellViewManager", "MainView");
|
||||
}
|
||||
protected override void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
//注册视图
|
||||
containerRegistry.RegisterForNavigation<MainView>("MainView");
|
||||
containerRegistry.RegisterForNavigation<MonitorView>("MonitorView");
|
||||
containerRegistry.RegisterForNavigation<Views.DataView>("DataView");
|
||||
containerRegistry.RegisterForNavigation<UpdateInfoView>("UpdateInfoView");
|
||||
//注册弹窗
|
||||
containerRegistry.RegisterDialog<MessageBoxView, MessageBoxViewModel>("MessageBox");
|
||||
containerRegistry.RegisterDialog<ParameterSetting, ParameterSettingViewModel>("ParameterSetting");
|
||||
containerRegistry.RegisterDialog<BackfeedView, BackfeedViewModel>("Backfeed");
|
||||
containerRegistry.RegisterDialog<EAEL9080View, EAEL9080ViewModel>("EAEL9080");
|
||||
containerRegistry.RegisterDialog<IOBoardView, IOBoardViewModel>("IOBoard");
|
||||
containerRegistry.RegisterDialog<IT6724CView, IT6724CViewModel>("IT6724C");
|
||||
containerRegistry.RegisterDialog<LQ7500_DView, LQ7500_DViewModel>("LQ7500_D");
|
||||
containerRegistry.RegisterDialog<PSB11000View, PSB11000ViewModel>("PSB11000");
|
||||
containerRegistry.RegisterDialog<SQ0030G1DView, SQ0030G1DViewModel>("SQ0030G1D");
|
||||
containerRegistry.RegisterDialog<WS_68030_380TView, WS_68030_380TViewModel>("WS_68030_380T");
|
||||
containerRegistry.RegisterDialog<ZXKSView, ZXKSViewModel>("ZXKS");
|
||||
containerRegistry.RegisterDialog<CANView, CANViewModel>("CAN");
|
||||
//注册全局单例变量
|
||||
containerRegistry.RegisterSingleton<GlobalVariables>();
|
||||
containerRegistry.RegisterSingleton<Devices>();
|
||||
containerRegistry.RegisterSingleton<StepRunning>();
|
||||
// 注册仓储
|
||||
containerRegistry.RegisterScoped(typeof(SqlSugarRepository<>));
|
||||
// 注册服务
|
||||
containerRegistry.RegisterScoped(typeof(BackFeedService));
|
||||
containerRegistry.RegisterScoped(typeof(EAEL9080Service));
|
||||
containerRegistry.RegisterScoped(typeof(IT6724CService));
|
||||
containerRegistry.RegisterScoped(typeof(LQ7500DService));
|
||||
containerRegistry.RegisterScoped(typeof(PSB11000Service));
|
||||
containerRegistry.RegisterScoped(typeof(SQ0030Service));
|
||||
containerRegistry.RegisterScoped(typeof(WS680Service));
|
||||
containerRegistry.RegisterScoped(typeof(ZXKXService));
|
||||
}
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
var devices = Container.Resolve<Devices>();
|
||||
devices.Dispose();
|
||||
base.OnExit(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
10
BOB/AssemblyInfo.cs
Normal file
10
BOB/AssemblyInfo.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
69
BOB/BOB.csproj
Normal file
69
BOB/BOB.csproj
Normal file
@ -0,0 +1,69 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Noto\NotoSans-Bold.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Noto\NotoSans-BoldItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Noto\NotoSans-Italic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Noto\NotoSans-Regular.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Black.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-BlackItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Bold.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-BoldItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Italic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Light.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-LightItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Medium.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-MediumItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Regular.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-Thin.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\Roboto-ThinItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-Bold.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-BoldItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-Italic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-Light.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-LightItalic.ttf" />
|
||||
<Content Remove="C:\Users\23560\.nuget\packages\materialdesignthemes\5.3.0\contentFiles\any\net8.0-windows7.0\Resources\Roboto\RobotoCondensed-Regular.ttf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="gong-wpf-dragdrop" Version="4.0.0" />
|
||||
<PackageReference Include="MaterialDesignColors" Version="5.3.0" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="5.3.0" />
|
||||
<PackageReference Include="MaterialDesignThemes.MahApps" Version="5.3.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="OxyPlot.Wpf" Version="2.2.0" />
|
||||
<PackageReference Include="Prism.Unity" Version="9.0.537" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CAN驱动\CAN驱动.csproj" />
|
||||
<ProjectReference Include="..\Command\Command.csproj" />
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
<ProjectReference Include="..\DeviceCommand\DeviceCommand.csproj" />
|
||||
<ProjectReference Include="..\Logger\Logger.csproj" />
|
||||
<ProjectReference Include="..\Model\Model.csproj" />
|
||||
<ProjectReference Include="..\ORM\ORM.csproj" />
|
||||
<ProjectReference Include="..\Service\Service.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Resources\Images\error.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\Images\info.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Resources\Images\warning.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
33
BOB/Converters/BooleanToVisibilityConverter.cs
Normal file
33
BOB/Converters/BooleanToVisibilityConverter.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class BooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is bool boolValue)
|
||||
{
|
||||
// 处理反转逻辑
|
||||
if (parameter?.ToString() == "Inverse")
|
||||
{
|
||||
boolValue = !boolValue;
|
||||
}
|
||||
return boolValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
49
BOB/Converters/DeviceNameConverter.cs
Normal file
49
BOB/Converters/DeviceNameConverter.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class DeviceNameConverter : IValueConverter
|
||||
{
|
||||
private readonly string[] specialName = { "奇偶" };
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is string name)
|
||||
{
|
||||
if (specialName.Contains(name))
|
||||
{
|
||||
if (parameter?.ToString() == "Inverse")
|
||||
{
|
||||
return Visibility.Visible;
|
||||
}
|
||||
else if (parameter?.ToString() == "Items")
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "奇偶":
|
||||
return new List<string> { "无", "奇", "偶" };
|
||||
}
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
if (parameter?.ToString() == "Inverse")
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
82
BOB/Converters/EnumValueConverter.cs
Normal file
82
BOB/Converters/EnumValueConverter.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class EnumValueConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// 验证输入参数
|
||||
if (values.Length < 2 || values[0] == null || values[1] == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 获取枚举类型
|
||||
Type enumType = values[0] as Type;
|
||||
if (enumType == null || !enumType.IsEnum)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取数值
|
||||
object value = values[1];
|
||||
|
||||
// 确保数值类型匹配枚举的底层类型
|
||||
Type underlyingType = Enum.GetUnderlyingType(enumType);
|
||||
object convertedValue;
|
||||
|
||||
try
|
||||
{
|
||||
convertedValue = System.Convert.ChangeType(value, underlyingType);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果转换失败,尝试直接使用原始值
|
||||
convertedValue = value;
|
||||
}
|
||||
|
||||
// 将数值转换为枚举值
|
||||
return Enum.ToObject(enumType, convertedValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 发生任何异常时返回null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 获取枚举值的底层数值
|
||||
Type enumType = value.GetType();
|
||||
if (!enumType.IsEnum)
|
||||
{
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
Type underlyingType = Enum.GetUnderlyingType(enumType);
|
||||
object numericValue = System.Convert.ChangeType(value, underlyingType);
|
||||
|
||||
// 返回枚举类型和对应的数值
|
||||
return [enumType, numericValue];
|
||||
}
|
||||
catch
|
||||
{
|
||||
return [null, null];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
BOB/Converters/EnumValuesConverter.cs
Normal file
23
BOB/Converters/EnumValuesConverter.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class EnumValuesConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Type type && type.IsEnum)
|
||||
{
|
||||
return Enum.GetValues(type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
BOB/Converters/FilteredParametersConverter.cs
Normal file
74
BOB/Converters/FilteredParametersConverter.cs
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
using BOB.Models;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class FilteredParametersConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length < 2 || values[0] == null || values[1] == null)
|
||||
return null;
|
||||
|
||||
Type currentParamType = values[0] as Type;
|
||||
var allParameters = values[1] as System.Collections.IEnumerable;
|
||||
|
||||
if (currentParamType == null || allParameters == null)
|
||||
return allParameters;
|
||||
|
||||
// 过滤出类型匹配的参数
|
||||
return allParameters.Cast<ParameterModel>()
|
||||
.Where(p => IsTypeMatch(currentParamType, p.Type))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private bool IsTypeMatch(Type currentType, Type candidateType)
|
||||
{
|
||||
if (candidateType == null) return false;
|
||||
|
||||
// 如果候选参数类型是 object,则匹配所有类型
|
||||
if (candidateType == typeof(object)) return true;
|
||||
|
||||
// 如果类型完全相同,则匹配
|
||||
if (candidateType == currentType) return true;
|
||||
|
||||
// 处理数值类型的兼容性
|
||||
if (IsNumericType(currentType) && IsNumericType(candidateType))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsNumericType(Type type)
|
||||
{
|
||||
if (type == null) return false;
|
||||
|
||||
switch (Type.GetTypeCode(type))
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Single:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
BOB/Converters/HexConverter.cs
Normal file
40
BOB/Converters/HexConverter.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class HexConverter : IValueConverter
|
||||
{
|
||||
// 显示时:int → hex 字符串
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is int i)
|
||||
return $"0x{i:X}"; // 例如 255 → 0xFF
|
||||
return "0x0";
|
||||
}
|
||||
|
||||
// 用户输入时:hex 字符串 → int
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var str = value?.ToString()?.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(str))
|
||||
return 0;
|
||||
|
||||
if (str.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
str = str.Substring(2);
|
||||
|
||||
if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int result))
|
||||
return result;
|
||||
|
||||
return 0; // 或 return DependencyProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
22
BOB/Converters/InverseBooleanConverter.cs
Normal file
22
BOB/Converters/InverseBooleanConverter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class InverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// null 视为 false,再取反 → true
|
||||
var b = value as bool?;
|
||||
return !(b ?? false);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var b = value as bool?;
|
||||
return !(b ?? false);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
BOB/Converters/IsEnumTypeConverter .cs
Normal file
36
BOB/Converters/IsEnumTypeConverter .cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class IsEnumTypeConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Type type)
|
||||
{
|
||||
// 检查是否为枚举类型
|
||||
bool isEnum = type.IsEnum;
|
||||
|
||||
// 根据参数决定返回值类型
|
||||
if (parameter is string strParam && strParam == "Collapse")
|
||||
{
|
||||
return isEnum ? Visibility.Collapsed : Visibility.Visible;
|
||||
}
|
||||
return isEnum ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
BOB/Converters/ParameterCategoryToStringConverter.cs
Normal file
40
BOB/Converters/ParameterCategoryToStringConverter.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using static BOB.Models.ParameterModel;
|
||||
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class ParameterCategoryToStringConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
|
||||
if (value is ParameterCategory category)
|
||||
{
|
||||
switch (category)
|
||||
{
|
||||
case ParameterCategory.Input:
|
||||
return "输入";
|
||||
case ParameterCategory.Output:
|
||||
return "输出";
|
||||
case ParameterCategory.Temp:
|
||||
return "缓存";
|
||||
default:
|
||||
return "未知";
|
||||
}
|
||||
}
|
||||
return "未知";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
BOB/Converters/ParameterCategoryToVisibilityConverter.cs
Normal file
39
BOB/Converters/ParameterCategoryToVisibilityConverter.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using static BOB.Models.ParameterModel;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class ParameterCategoryToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is ParameterCategory category)
|
||||
{
|
||||
if (parameter?.ToString() == "Item")
|
||||
{
|
||||
if (category == ParameterCategory.Temp) { return Visibility.Collapsed; }
|
||||
else { return Visibility.Visible; }
|
||||
}
|
||||
bool boolValue = category == ParameterCategory.Input;
|
||||
if (parameter?.ToString() == "Inverse")
|
||||
{
|
||||
boolValue = !boolValue;
|
||||
}
|
||||
return boolValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
BOB/Converters/ParameterTypeToBoolConverter.cs
Normal file
31
BOB/Converters/ParameterTypeToBoolConverter.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class ParameterTypeToBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if(value is Type type)
|
||||
{
|
||||
if(type == typeof(CancellationToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
38
BOB/Converters/ParameterValueToStringConverter.cs
Normal file
38
BOB/Converters/ParameterValueToStringConverter.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using ControlzEx.Standard;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class ParameterValueToStringConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is IEnumerable enumerable && !(value is string))
|
||||
{
|
||||
var elements = enumerable.Cast<object>().Select(item => item?.ToString() ?? "null");
|
||||
return $"[{string.Join(", ", elements)}]";
|
||||
}
|
||||
else if(value != null)
|
||||
{
|
||||
return value.ToString()!;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
return value.ToString()!;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
35
BOB/Converters/StringToVisibilityConverter.cs
Normal file
35
BOB/Converters/StringToVisibilityConverter.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace BOB.Converters
|
||||
{
|
||||
public class StringToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if(value is string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Visibility.Visible;
|
||||
}
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BOB/Models/DeviceConnectSettingModel.cs
Normal file
15
BOB/Models/DeviceConnectSettingModel.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class DeviceConnectSettingModel
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public string Value { get; set; } = "";
|
||||
}
|
||||
}
|
||||
49
BOB/Models/DeviceInfoModel.cs
Normal file
49
BOB/Models/DeviceInfoModel.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using Model;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class DeviceInfoModel : BindableBase
|
||||
{
|
||||
private string _deviceName;
|
||||
public string DeviceName
|
||||
{
|
||||
get => _deviceName;
|
||||
set => SetProperty(ref _deviceName, value);
|
||||
}
|
||||
|
||||
private string _deviceType;
|
||||
public string DeviceType
|
||||
{
|
||||
get => _deviceType;
|
||||
set => SetProperty(ref _deviceType, value);
|
||||
}
|
||||
|
||||
private string _remark;
|
||||
public string Remark
|
||||
{
|
||||
get => _remark;
|
||||
set => SetProperty(ref _remark, value);
|
||||
}
|
||||
|
||||
private bool _isEnabled;
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set => SetProperty(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
private bool _isConnected;
|
||||
public bool IsConnected
|
||||
{
|
||||
get => _isConnected;
|
||||
set => SetProperty(ref _isConnected, value);
|
||||
}
|
||||
|
||||
private ICommunicationConfig _communicationConfig;
|
||||
public ICommunicationConfig CommunicationConfig
|
||||
{
|
||||
get => _communicationConfig;
|
||||
set => SetProperty(ref _communicationConfig, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
BOB/Models/InstructionNode.cs
Normal file
18
BOB/Models/InstructionNode.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class InstructionNode
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ObservableCollection<InstructionNode> Children { get; set; } = new();
|
||||
public object Tag { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
40
BOB/Models/MethodModel.cs
Normal file
40
BOB/Models/MethodModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class MethodModel
|
||||
{
|
||||
|
||||
#region 构造函数
|
||||
|
||||
public MethodModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public MethodModel(MethodModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
Name = source.Name;
|
||||
FullName = source.FullName;
|
||||
|
||||
// 深拷贝参数
|
||||
Parameters = new ObservableCollection<ParameterModel>(
|
||||
source.Parameters.Select(p => new ParameterModel(p)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? FullName { get; set; }
|
||||
|
||||
public ObservableCollection<ParameterModel> Parameters { get; set; } = [];
|
||||
}
|
||||
}
|
||||
316
BOB/Models/ParameterModel.cs
Normal file
316
BOB/Models/ParameterModel.cs
Normal file
@ -0,0 +1,316 @@
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class ParameterModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public ParameterModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ParameterModel(ParameterModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
ID = source.ID;
|
||||
Name = source.Name;
|
||||
Type = source.Type;
|
||||
Category = source.Category;
|
||||
IsUseVar = source.IsUseVar;
|
||||
IsSave = source.IsSave;
|
||||
VariableName = source.VariableName;
|
||||
VariableID = source.VariableID;
|
||||
IsGlobal = source.IsGlobal;
|
||||
Value = source.Value;
|
||||
LowerLimit = source.LowerLimit;
|
||||
UpperLimit = source.UpperLimit;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Guid _id = Guid.NewGuid();
|
||||
public Guid ID
|
||||
{
|
||||
get => _id;
|
||||
set => SetProperty(ref _id, value);
|
||||
}
|
||||
|
||||
private bool _isVisible = true;
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => SetProperty(ref _isVisible, value);
|
||||
}
|
||||
|
||||
private string _name;
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
private Type _type = typeof(string);
|
||||
public Type Type
|
||||
{
|
||||
get => _type;
|
||||
set => SetProperty(ref _type, value);
|
||||
}
|
||||
|
||||
private ParameterCategory _category = ParameterCategory.Temp;
|
||||
public ParameterCategory Category
|
||||
{
|
||||
get => _category;
|
||||
set => SetProperty(ref _category, value);
|
||||
}
|
||||
|
||||
private bool _isGlobal;
|
||||
public bool IsGlobal
|
||||
{
|
||||
get => _isGlobal;
|
||||
set => SetProperty(ref _isGlobal, value);
|
||||
}
|
||||
|
||||
private object? _value;
|
||||
public object? Value
|
||||
{
|
||||
get => _value;
|
||||
set => SetProperty(ref _value, value);
|
||||
}
|
||||
|
||||
private object? _lowerLimit;
|
||||
public object? LowerLimit
|
||||
{
|
||||
get => _lowerLimit;
|
||||
set => SetProperty(ref _lowerLimit, value);
|
||||
}
|
||||
|
||||
private object? _upperLimit;
|
||||
public object? UpperLimit
|
||||
{
|
||||
get => _upperLimit;
|
||||
set => SetProperty(ref _upperLimit, value);
|
||||
}
|
||||
|
||||
private bool _result = true;
|
||||
public bool Result
|
||||
{
|
||||
get => _result;
|
||||
set => SetProperty(ref _result, value);
|
||||
}
|
||||
|
||||
private bool _isUseVar;
|
||||
public bool IsUseVar
|
||||
{
|
||||
get => _isUseVar;
|
||||
set => SetProperty(ref _isUseVar, value);
|
||||
}
|
||||
|
||||
private bool _isSave;
|
||||
public bool IsSave
|
||||
{
|
||||
get => _isSave;
|
||||
set => SetProperty(ref _isSave, value);
|
||||
}
|
||||
|
||||
private string? _variableName;
|
||||
public string? VariableName
|
||||
{
|
||||
get => _variableName;
|
||||
set => SetProperty(ref _variableName, value);
|
||||
}
|
||||
|
||||
private Guid? _variableID;
|
||||
public Guid? VariableID
|
||||
{
|
||||
get => _variableID;
|
||||
set => SetProperty(ref _variableID, value);
|
||||
}
|
||||
|
||||
public enum ParameterCategory
|
||||
{
|
||||
Input,
|
||||
Output,
|
||||
Temp
|
||||
}
|
||||
|
||||
public object? GetActualValue(Dictionary<Guid, ParameterModel> paraList)
|
||||
{
|
||||
HashSet<Guid> visitedIds = new HashSet<Guid>();
|
||||
ParameterModel current = this;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (!current.IsUseVar)
|
||||
{
|
||||
return current.Value;
|
||||
}
|
||||
|
||||
if (visitedIds.Contains(current.ID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
visitedIds.Add(current.ID);
|
||||
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
if (Type != null && Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ChangeType(Value, Type);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterModel? next = paraList[(Guid)current.VariableID!];
|
||||
if (next == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ParameterModel? GetCurrentParameter(Dictionary<Guid, ParameterModel> paraList)
|
||||
{
|
||||
HashSet<Guid> visitedIds = new HashSet<Guid>();
|
||||
ParameterModel current = this;
|
||||
|
||||
while (current != null)
|
||||
{
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
if (visitedIds.Contains(current.ID))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
visitedIds.Add(current.ID);
|
||||
|
||||
if (current.VariableID == null)
|
||||
{
|
||||
if (Type != null && Value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return current;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParameterModel? next = paraList[(Guid)current.VariableID!];
|
||||
if (next == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public (bool, string?) GetResult()
|
||||
{
|
||||
if (Type == typeof(string) && (!string.IsNullOrWhiteSpace(LowerLimit?.ToString()) || !string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 不可比较");
|
||||
}
|
||||
|
||||
if (Value == null || (LowerLimit == null && UpperLimit == null))
|
||||
{
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Value?.ToString()) || (string.IsNullOrWhiteSpace(LowerLimit?.ToString()) && string.IsNullOrWhiteSpace(UpperLimit?.ToString())))
|
||||
{
|
||||
return (true, null);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
object? comparableValue = ConvertToComparable(Value);
|
||||
object? comparableLower = LowerLimit != null ? ConvertToComparable(LowerLimit) : null;
|
||||
object? comparableUpper = UpperLimit != null ? ConvertToComparable(UpperLimit) : null;
|
||||
|
||||
if (comparableValue == null)
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 不可比较");
|
||||
}
|
||||
|
||||
bool lowerValid = true;
|
||||
bool upperValid = true;
|
||||
|
||||
if (comparableLower != null)
|
||||
{
|
||||
lowerValid = CompareValues(comparableValue, comparableLower) >= 0;
|
||||
}
|
||||
|
||||
if (comparableUpper != null)
|
||||
{
|
||||
upperValid = CompareValues(comparableValue, comparableUpper) <= 0;
|
||||
}
|
||||
|
||||
return (lowerValid && upperValid, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (true, $"参数 [ {Name}({Type}) ] 上下限比较失败:{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static object? ConvertToComparable(object value)
|
||||
{
|
||||
if (value is IConvertible convertible)
|
||||
{
|
||||
try
|
||||
{
|
||||
return convertible.ToDouble(null);
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
return convertible.ToDateTime(null);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int CompareValues(object a, object b)
|
||||
{
|
||||
if (a is double aDouble && b is double bDouble)
|
||||
{
|
||||
return aDouble.CompareTo(bDouble);
|
||||
}
|
||||
|
||||
if (a is DateTime aDate && b is DateTime bDate)
|
||||
{
|
||||
return aDate.CompareTo(bDate);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
BOB/Models/ProgramModel.cs
Normal file
44
BOB/Models/ProgramModel.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class ProgramModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public ProgramModel()
|
||||
{
|
||||
// 可以进行初始化操作
|
||||
}
|
||||
|
||||
public ProgramModel(ProgramModel source)
|
||||
{
|
||||
ID = source.ID;
|
||||
StepCollection = new ObservableCollection<StepModel>(source.StepCollection.Select(p => new StepModel(p)));
|
||||
Parameters = new ObservableCollection<ParameterModel>(source.Parameters.Select(p => new ParameterModel(p)));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Guid ID { get; set; } = Guid.NewGuid();
|
||||
|
||||
private ObservableCollection<StepModel> _stepCollection = new ObservableCollection<StepModel>();
|
||||
public ObservableCollection<StepModel> StepCollection
|
||||
{
|
||||
get => _stepCollection;
|
||||
set => SetProperty(ref _stepCollection, value); // 使用 SetProperty 来处理属性更改
|
||||
}
|
||||
|
||||
private ObservableCollection<ParameterModel> _parameters = new ObservableCollection<ParameterModel>();
|
||||
public ObservableCollection<ParameterModel> Parameters
|
||||
{
|
||||
get => _parameters;
|
||||
set => SetProperty(ref _parameters, value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
178
BOB/Models/StepModel.cs
Normal file
178
BOB/Models/StepModel.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm; // 引入 Prism 的 BindableBase
|
||||
using System;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class StepModel : BindableBase
|
||||
{
|
||||
#region 构造函数
|
||||
|
||||
public StepModel() { }
|
||||
|
||||
public StepModel(StepModel source)
|
||||
{
|
||||
if (source == null) return;
|
||||
|
||||
ID = source.ID;
|
||||
Index = source.Index;
|
||||
Name = source.Name;
|
||||
StepType = source.StepType;
|
||||
LoopCount = source.LoopCount;
|
||||
LoopStartStepId = source.LoopStartStepId;
|
||||
OKExpression = source.OKExpression;
|
||||
OKGotoStepID = source.OKGotoStepID;
|
||||
GotoSettingString = source.GotoSettingString;
|
||||
NGGotoStepID = source.NGGotoStepID;
|
||||
Description = source.Description;
|
||||
IsUsed = source.IsUsed;
|
||||
|
||||
if (source.Method != null)
|
||||
{
|
||||
Method = new MethodModel(source.Method);
|
||||
}
|
||||
if (source.SubProgram != null)
|
||||
{
|
||||
SubProgram = new ProgramModel(source.SubProgram);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Guid _id = Guid.NewGuid();
|
||||
|
||||
public Guid ID
|
||||
{
|
||||
get => _id;
|
||||
set => SetProperty(ref _id, value);
|
||||
}
|
||||
|
||||
private bool _isUsed = true;
|
||||
|
||||
public bool IsUsed
|
||||
{
|
||||
get => _isUsed;
|
||||
set => SetProperty(ref _isUsed, value);
|
||||
}
|
||||
|
||||
private int _index;
|
||||
|
||||
public int Index
|
||||
{
|
||||
get => _index;
|
||||
set => SetProperty(ref _index, value);
|
||||
}
|
||||
|
||||
private string? _name;
|
||||
|
||||
public string? Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
private string? _stepType;
|
||||
|
||||
public string? StepType
|
||||
{
|
||||
get => _stepType;
|
||||
set => SetProperty(ref _stepType, value);
|
||||
}
|
||||
|
||||
private MethodModel? _method;
|
||||
|
||||
public MethodModel? Method
|
||||
{
|
||||
get => _method;
|
||||
set => SetProperty(ref _method, value);
|
||||
}
|
||||
|
||||
private ProgramModel? _subProgram;
|
||||
|
||||
public ProgramModel? SubProgram
|
||||
{
|
||||
get => _subProgram;
|
||||
set => SetProperty(ref _subProgram, value);
|
||||
}
|
||||
|
||||
private int? _loopCount;
|
||||
|
||||
public int? LoopCount
|
||||
{
|
||||
get => _loopCount;
|
||||
set => SetProperty(ref _loopCount, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int? _currentLoopCount;
|
||||
[JsonIgnore]
|
||||
public int? CurrentLoopCount
|
||||
{
|
||||
get => _currentLoopCount;
|
||||
set => SetProperty(ref _currentLoopCount, value);
|
||||
}
|
||||
|
||||
private Guid? _loopStartStepId;
|
||||
|
||||
public Guid? LoopStartStepId
|
||||
{
|
||||
get => _loopStartStepId;
|
||||
set => SetProperty(ref _loopStartStepId, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int _result = -1;
|
||||
[JsonIgnore]
|
||||
public int Result
|
||||
{
|
||||
get => _result;
|
||||
set => SetProperty(ref _result, value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
private int? _runTime;
|
||||
[JsonIgnore]
|
||||
public int? RunTime
|
||||
{
|
||||
get => _runTime;
|
||||
set => SetProperty(ref _runTime, value);
|
||||
}
|
||||
|
||||
private string? _okExpression;
|
||||
|
||||
public string? OKExpression
|
||||
{
|
||||
get => _okExpression;
|
||||
set => SetProperty(ref _okExpression, value);
|
||||
}
|
||||
|
||||
private string _gotoSettingString = "";
|
||||
|
||||
public string GotoSettingString
|
||||
{
|
||||
get => _gotoSettingString;
|
||||
set => SetProperty(ref _gotoSettingString, value);
|
||||
}
|
||||
|
||||
private Guid? _okGotoStepID;
|
||||
|
||||
public Guid? OKGotoStepID
|
||||
{
|
||||
get => _okGotoStepID;
|
||||
set => SetProperty(ref _okGotoStepID, value);
|
||||
}
|
||||
|
||||
private Guid? _ngGotoStepID;
|
||||
|
||||
public Guid? NGGotoStepID
|
||||
{
|
||||
get => _ngGotoStepID;
|
||||
set => SetProperty(ref _ngGotoStepID, value);
|
||||
}
|
||||
|
||||
private string? _description;
|
||||
|
||||
public string? Description
|
||||
{
|
||||
get => _description;
|
||||
set => SetProperty(ref _description, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BOB/Models/SubProgramItem.cs
Normal file
15
BOB/Models/SubProgramItem.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Models
|
||||
{
|
||||
public class SubProgramItem
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public string FilePath { get; set; } = "";
|
||||
}
|
||||
}
|
||||
BIN
BOB/Resources/Images/error.png
Normal file
BIN
BOB/Resources/Images/error.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
BIN
BOB/Resources/Images/info.png
Normal file
BIN
BOB/Resources/Images/info.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.4 KiB |
BIN
BOB/Resources/Images/warning.png
Normal file
BIN
BOB/Resources/Images/warning.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
22
BOB/Resources/Styles/WindowStyle.xaml
Normal file
22
BOB/Resources/Styles/WindowStyle.xaml
Normal file
@ -0,0 +1,22 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<Style x:Key="DialogUserManageStyle"
|
||||
TargetType="Window">
|
||||
<Setter Property="WindowStyle"
|
||||
Value="None" />
|
||||
<Setter Property="Topmost"
|
||||
Value="True" />
|
||||
<Setter Property="ResizeMode"
|
||||
Value="NoResize" />
|
||||
<Setter Property="ShowInTaskbar"
|
||||
Value="False" />
|
||||
<Setter Property="AllowsTransparency"
|
||||
Value="true" />
|
||||
<Setter Property="Background"
|
||||
Value="Transparent" />
|
||||
<Setter Property="SizeToContent"
|
||||
Value="WidthAndHeight" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
65
BOB/Services/BackfeedPollingRead.cs
Normal file
65
BOB/Services/BackfeedPollingRead.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Model.SQLModel;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class BackfeedPollingRead : PollingRead
|
||||
{
|
||||
private Backfeed _Backfeed { get;set; }
|
||||
private IEventAggregator _eventAggregator { get;set; }
|
||||
private IBaseService<BackFeedData> _backFeedService { get;set; }
|
||||
public BackfeedPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_backFeedService=containerProvider.Resolve<BackFeedService>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "Backfeed";
|
||||
_Backfeed = _devices.DeviceDic["Backfeed"]as Backfeed;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 =await _Backfeed!.查询实时电流(ct);
|
||||
//实时电压 = await _Backfeed!.查询实时电压(ct);
|
||||
//实时功率 = await _Backfeed!.查询实时功率(ct);
|
||||
var reuslt= await _backFeedService.InsertAsync(new BackFeedData
|
||||
{
|
||||
RealTimeCurrent = 实时电流,
|
||||
RealTimePower= 实时电压,
|
||||
RealTimeVoltage= 实时功率,
|
||||
CollectTime=DateTime.Now
|
||||
});
|
||||
if (reuslt.IsSuccess)
|
||||
{
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("Backfeed", dataDic));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify(reuslt.Msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
BOB/Services/EAEL9080PollingRead.cs
Normal file
64
BOB/Services/EAEL9080PollingRead.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Model.SQLModel;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class EAEL9080PollingRead:PollingRead
|
||||
{
|
||||
private EAEL9080 _EAEL9080 { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private IBaseService<EAELD9080Data> _eAEL9080Service { get; set; }
|
||||
public EAEL9080PollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
_eAEL9080Service = containerProvider.Resolve<EAEL9080Service>();
|
||||
DeviceName = "EAEL9080";
|
||||
_EAEL9080 = _devices.DeviceDic["EAEL9080"] as EAEL9080;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _EAEL9080!.查询电流(ct);
|
||||
//实时电压 = await _EAEL9080!.查询电压(ct);
|
||||
//实时功率 = await _EAEL9080!.查询功率(ct);
|
||||
var reuslt = await _eAEL9080Service.InsertAsync(new EAELD9080Data
|
||||
{
|
||||
RealTimeCurrent = 实时电流,
|
||||
RealTimePower = 实时电压,
|
||||
RealTimeVoltage = 实时功率,
|
||||
CollectTime = DateTime.Now
|
||||
});
|
||||
if (reuslt.IsSuccess)
|
||||
{
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("EAEL9080", dataDic));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify(reuslt.Msg);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
63
BOB/Services/IT6724CPollingRead.cs
Normal file
63
BOB/Services/IT6724CPollingRead.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Model.SQLModel;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class IT6724CPollingRead : PollingRead
|
||||
{
|
||||
private IT6724C _IT6724C { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private IBaseService<IT6724CData> _iT6724CService { get; set; }
|
||||
public IT6724CPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
_iT6724CService = containerProvider.Resolve<IT6724CService>();
|
||||
DeviceName = "Backfeed";
|
||||
_IT6724C = _devices.DeviceDic["IT6724C"] as IT6724C;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _IT6724C!.查询实时电流(ct);
|
||||
//实时电压 = await _IT6724C!.查询实时电压(ct);
|
||||
//实时功率 = await _IT6724C!.查询实时功率(ct);
|
||||
var reuslt = await _iT6724CService.InsertAsync(new IT6724CData
|
||||
{
|
||||
RealTimeCurrent = 实时电流,
|
||||
RealTimePower = 实时电压,
|
||||
RealTimeVoltage = 实时功率,
|
||||
CollectTime = DateTime.Now
|
||||
});
|
||||
if (reuslt.IsSuccess)
|
||||
{
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("IT6724C", dataDic));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify(reuslt.Msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
BOB/Services/LQ7500-DPollingRead.cs
Normal file
41
BOB/Services/LQ7500-DPollingRead.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class LQ7500_DPollingRead : PollingRead
|
||||
{
|
||||
private LQ7500_D _LQ7500_D { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public LQ7500_DPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "LQ7500_D";
|
||||
_LQ7500_D = _devices.DeviceDic["LQ7500_D"] as LQ7500_D;
|
||||
}
|
||||
public double 内部传感器温度 { get; set; } = double.NaN;
|
||||
public double 外部传感器温度 { get; set; } = double.NaN;
|
||||
public double 水流量 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
内部传感器温度 = await _LQ7500_D.读取内部传感器温度();
|
||||
外部传感器温度 = await _LQ7500_D.读取外部传感器温度();
|
||||
水流量 = await _LQ7500_D.读取流量();
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "内部传感器温度", 内部传感器温度 },
|
||||
{ "外部传感器温度", 外部传感器温度 },
|
||||
{ "水流量", 水流量 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("LQ7500_D", dataDic));
|
||||
}
|
||||
}
|
||||
}
|
||||
65
BOB/Services/PSB11000PollingRead.cs
Normal file
65
BOB/Services/PSB11000PollingRead.cs
Normal file
@ -0,0 +1,65 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Model.SQLModel;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class PSB11000PollingRead : PollingRead
|
||||
{
|
||||
private PSB11000 _PSB11000 { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private IBaseService<PSB1100Data> _pSB1100Service { get; set; }
|
||||
public PSB11000PollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
_pSB1100Service = containerProvider.Resolve<PSB11000Service>();
|
||||
DeviceName = "PSB11000";
|
||||
_PSB11000 = _devices.DeviceDic["PSB11000"] as PSB11000;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
实时电流 = Random.Shared.NextDouble() * 10;
|
||||
实时电压 = Random.Shared.NextDouble() * 10;
|
||||
实时功率 = Random.Shared.NextDouble() * 10;
|
||||
//实时电流 = await _PSB11000!.查询电流(ct);
|
||||
//实时电压 = await _PSB11000!.查询电压(ct);
|
||||
//实时功率 = await _PSB11000!.查询功率(ct);
|
||||
var reuslt = await _pSB1100Service.InsertAsync(new PSB1100Data
|
||||
{
|
||||
RealTimeCurrent = 实时电流,
|
||||
RealTimePower = 实时电压,
|
||||
RealTimeVoltage = 实时功率,
|
||||
CollectTime = DateTime.Now
|
||||
});
|
||||
if (reuslt.IsSuccess)
|
||||
{
|
||||
var dataDic = new Dictionary<string, double>
|
||||
{
|
||||
{ "实时电流", 实时电流 },
|
||||
{ "实时电压", 实时电压 },
|
||||
{ "实时功率", 实时功率 }
|
||||
};
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Publish(("PSB11000", dataDic));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify(reuslt.Msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
BOB/Services/PollingRead.cs
Normal file
75
BOB/Services/PollingRead.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using BOB.Converters;
|
||||
using Common.PubEvent;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public abstract class PollingRead
|
||||
{
|
||||
private CancellationTokenSource _pollingCancellationTokenSource;
|
||||
private Task? _pollingTask;
|
||||
public int PollingInterval = 1000;
|
||||
public string DeviceName{get;set;}="";
|
||||
private bool IsConnect{ get; set; }=false;
|
||||
public PollingRead(IContainerProvider containerProvider)
|
||||
{
|
||||
var _eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_eventAggregator.GetEvent<ConnectionChangeEvent>().Subscribe(PollingConnection);
|
||||
}
|
||||
|
||||
private void PollingConnection((string, bool) tuple)
|
||||
{
|
||||
var (device, isConnect) = tuple;
|
||||
//System.Diagnostics.Debug.WriteLine($"PollingRead收到连接状态变化事件:设备={device},状态={isConnect}");
|
||||
if (device== DeviceName)
|
||||
{
|
||||
IsConnect = isConnect;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartPolling()
|
||||
{
|
||||
if (_pollingTask != null)
|
||||
return;
|
||||
|
||||
if (_pollingCancellationTokenSource == null || _pollingCancellationTokenSource.IsCancellationRequested)
|
||||
_pollingCancellationTokenSource = new CancellationTokenSource();
|
||||
|
||||
_pollingTask = Task.Run(() => PollingLoop(_pollingCancellationTokenSource.Token));
|
||||
}
|
||||
|
||||
public void StopPolling()
|
||||
{
|
||||
_pollingCancellationTokenSource?.Cancel();
|
||||
_pollingTask = null;
|
||||
}
|
||||
|
||||
private async Task PollingLoop(CancellationToken ct)
|
||||
{
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
if (IsConnect)
|
||||
{
|
||||
await Task.Delay(PollingInterval, ct);
|
||||
|
||||
try
|
||||
{
|
||||
await ReadDeviceDataAsync(ct);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"轮询过程中发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public abstract Task ReadDeviceDataAsync(CancellationToken ct = default);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
32
BOB/Services/SQ0030G1DPollingRead.cs
Normal file
32
BOB/Services/SQ0030G1DPollingRead.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class SQ0030G1DPollingRead : PollingRead
|
||||
{
|
||||
private SQ0030G1D _SQ0030G1D { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public SQ0030G1DPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "SQ0030G1D";
|
||||
_SQ0030G1D = _devices.DeviceDic["SQ0030G1D"] as SQ0030G1D;
|
||||
}
|
||||
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
30
BOB/Services/WS-68030-380TPollingRead.cs
Normal file
30
BOB/Services/WS-68030-380TPollingRead.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class WS_68030_380TPollingRead : PollingRead
|
||||
{
|
||||
private WS_68030_380T _WS_68030_380T { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public WS_68030_380TPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "WS_68030_380T";
|
||||
_WS_68030_380T = _devices.DeviceDic["WS_68030_380T"] as WS_68030_380T;
|
||||
}
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
32
BOB/Services/ZXKSPollingRead.cs
Normal file
32
BOB/Services/ZXKSPollingRead.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Services
|
||||
{
|
||||
public class ZXKSPollingRead : PollingRead
|
||||
{
|
||||
private ZXKS _ZXKS { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public ZXKSPollingRead(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
var _devices = containerProvider.Resolve<Devices>();
|
||||
DeviceName = "ZXKS";
|
||||
_ZXKS = _devices.DeviceDic["ZXKS"] as ZXKS;
|
||||
}
|
||||
public double 实时电流 { get; set; } = double.NaN;
|
||||
public double 实时电压 { get; set; } = double.NaN;
|
||||
public double 实时功率 { get; set; } = double.NaN;
|
||||
|
||||
public override async Task ReadDeviceDataAsync(CancellationToken ct = default)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
345
BOB/Singleton/Devices.cs
Normal file
345
BOB/Singleton/Devices.cs
Normal file
@ -0,0 +1,345 @@
|
||||
using BOB.Services;
|
||||
using CAN驱动;
|
||||
using Castle.DynamicProxy;
|
||||
using DeviceCommand.Base;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Model;
|
||||
using Npgsql.TypeHandlers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.Singleton
|
||||
{
|
||||
public class Devices
|
||||
{
|
||||
public Devices(IContainerProvider containerProvider)
|
||||
{
|
||||
_containerProvider=containerProvider;
|
||||
}
|
||||
private IContainerProvider _containerProvider;
|
||||
private CancellationTokenSource _appCancellationTokenSource = new();
|
||||
public CancellationToken AppCancellationToken => _appCancellationTokenSource.Token;
|
||||
|
||||
public Dictionary<string, object> DeviceDic { get; private set; } = new Dictionary<string, object>();
|
||||
public Dictionary<string, PollingRead> PollingReadDic { get; private set; } = new Dictionary<string, PollingRead>();
|
||||
|
||||
private readonly ProxyGenerator _proxyGen = new ProxyGenerator();
|
||||
private readonly IInterceptor _loggingInterceptor = new LoggingInterceptor();
|
||||
|
||||
private ISerialPort IT6724CDevice { get; set; }
|
||||
private ITcp EAEL9080Device { get; set; }
|
||||
private IModbusDevice IOBoardevice { get; set; }
|
||||
private IModbusDevice LQ7500_DDevice { get; set; }
|
||||
private ITcp PSB11000Device { get; set; }
|
||||
private IModbusDevice WS_68030_380TDevice { get; set; }
|
||||
private ITcp SQ0030G1DTDevice { get; set; }
|
||||
private IModbusDevice ZXKSTDevice { get; set; }
|
||||
private Backfeed BackfeedDevice { get; set; }
|
||||
|
||||
public void Init(List<DeviceConfigModel> deviceList)
|
||||
{
|
||||
foreach (var device in deviceList)
|
||||
{
|
||||
if (!device.IsEnabled) continue;
|
||||
switch (device.DeviceType)
|
||||
{
|
||||
case "DeviceCommand.Device.E36233A":
|
||||
if (device.CommunicationConfig is TcpConfig tcp1)
|
||||
{
|
||||
BackfeedDevice = _proxyGen.CreateClassProxy<Backfeed>(
|
||||
new object[] { tcp1 },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["Backfeed"] = BackfeedDevice;
|
||||
}
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.IT6724CReverse":
|
||||
if (device.CommunicationConfig is SerialPortConfig sp3)
|
||||
{
|
||||
BackfeedDevice = _proxyGen.CreateClassProxy<Backfeed>(
|
||||
new object[] { sp3 },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["Backfeed"] = BackfeedDevice;
|
||||
}
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.IT6724C":
|
||||
if (device.CommunicationConfig is SerialPortConfig sp1)
|
||||
{
|
||||
var IT6724CDevice = _proxyGen.CreateClassProxy<IT6724C>(
|
||||
new object[] { sp1.COMPort, sp1.BaudRate, sp1.DataBit, sp1.StopBit, sp1.ParityBit, sp1.ReadTimeout, sp1.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["IT6724C"] = IT6724CDevice;
|
||||
}
|
||||
else throw new InvalidOperationException("IT6724C 必须使用 SerialPortConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.LQ7500_D":
|
||||
if (device.CommunicationConfig is SerialPortConfig sp2)
|
||||
{
|
||||
var LQ7500_DDevice = _proxyGen.CreateClassProxy<LQ7500_D>(
|
||||
new object[] { sp2.COMPort, sp2.BaudRate, sp2.DataBit, sp2.StopBit, sp2.ParityBit, sp2.ReadTimeout, sp2.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["LQ7500_D"] = LQ7500_DDevice;
|
||||
}
|
||||
else throw new InvalidOperationException("LQ7500D 必须使用 SerialPortConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.EAEL9080":
|
||||
if (device.CommunicationConfig is TcpConfig tcp2)
|
||||
{
|
||||
var EAEL9080Device = _proxyGen.CreateClassProxy<EAEL9080>(
|
||||
new object[] { tcp2.IPAddress, tcp2.Port, tcp2.ReadTimeout, tcp2.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["EAEL9080"] = EAEL9080Device;
|
||||
}
|
||||
else throw new InvalidOperationException("EAEL9080 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.IOBoard":
|
||||
if (device.CommunicationConfig is TcpConfig tcp3)
|
||||
{
|
||||
var IOBoardevice = _proxyGen.CreateClassProxy<IOBoard>(
|
||||
new object[] { tcp3.IPAddress, tcp3.Port, tcp3.ReadTimeout, tcp3.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["IOBoard"] = IOBoardevice;
|
||||
}
|
||||
else throw new InvalidOperationException("IOBoard 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.PSB11000":
|
||||
if (device.CommunicationConfig is TcpConfig tcp4)
|
||||
{
|
||||
var PSB11000Device = _proxyGen.CreateClassProxy<PSB11000>(
|
||||
new object[] { tcp4.IPAddress, tcp4.Port, tcp4.ReadTimeout, tcp4.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["PSB11000"] = PSB11000Device;
|
||||
}
|
||||
else throw new InvalidOperationException("PSB11000 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.WS_68030_380T":
|
||||
if (device.CommunicationConfig is TcpConfig tcp5)
|
||||
{
|
||||
var WS_68030_380TDevice = _proxyGen.CreateClassProxy<WS_68030_380T>(
|
||||
new object[] { tcp5.IPAddress, tcp5.Port, tcp5.ReadTimeout, tcp5.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["WS_68030_380T"] = WS_68030_380TDevice;
|
||||
}
|
||||
else throw new InvalidOperationException("WS_68030_380T 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.SQ0030G1D":
|
||||
if (device.CommunicationConfig is TcpConfig tcp7)
|
||||
{
|
||||
var SQ0030G1DTDevice = _proxyGen.CreateClassProxy<SQ0030G1D>(
|
||||
new object[] { tcp7.IPAddress, tcp7.Port, tcp7.ReadTimeout, tcp7.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["SQ0030G1D"] = SQ0030G1DTDevice;
|
||||
}
|
||||
else throw new InvalidOperationException("SQ0030G1D 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
case "DeviceCommand.Device.ZXKS":
|
||||
if (device.CommunicationConfig is TcpConfig tcp6)
|
||||
{
|
||||
var ZXKSTDevice = _proxyGen.CreateClassProxy<ZXKS>(
|
||||
new object[] { tcp6.IPAddress, tcp6.Port, tcp6.ReadTimeout, tcp6.WriteTimeout },
|
||||
_loggingInterceptor
|
||||
);
|
||||
DeviceDic["ZXKS"] = ZXKSTDevice;
|
||||
}
|
||||
else throw new InvalidOperationException("ZXKS 必须使用 TcpConfig");
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"未知设备类型:{device.DeviceType}");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void InitCan()
|
||||
{
|
||||
同星驱动类.DisConnect();
|
||||
var re1 = 同星驱动类.Init("ATS测试系统");
|
||||
var re2 = 同星驱动类.Connect();
|
||||
if (re1 == 0 && re2 == 0)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public async Task ConnectAllDevicesAsync()
|
||||
{
|
||||
if (DeviceDic.Count == 0)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
foreach (var kvp in DeviceDic)
|
||||
{
|
||||
var name = kvp.Key;
|
||||
var device = kvp.Value;
|
||||
|
||||
if (device == null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"{name} 实例为空,跳过连接");
|
||||
continue;
|
||||
}
|
||||
await Task.Delay(10);
|
||||
try
|
||||
{
|
||||
// 检查并处理 ITcp 接口
|
||||
if (device is ITcp itcpDevice)
|
||||
{
|
||||
bool result = await itcpDevice.ConnectAsync(CancellationToken.None);
|
||||
LoggerHelper.SuccessWithNotify($"{name} 连接成功 (ITcp)");
|
||||
}
|
||||
// 检查并处理 IModbusDevice 接口
|
||||
else if (device is IModbusDevice imodbusDevice)
|
||||
{
|
||||
bool result = await imodbusDevice.ConnectAsync(CancellationToken.None);
|
||||
LoggerHelper.SuccessWithNotify($"{name} 连接成功 (IModbusDevice)");
|
||||
}
|
||||
// 检查并处理 ISerialPort 接口
|
||||
else if (device is ISerialPort iserialPortDevice)
|
||||
{
|
||||
bool result = await iserialPortDevice.ConnectAsync(CancellationToken.None);
|
||||
LoggerHelper.SuccessWithNotify($"{name} 连接成功 (ISerialPort)");
|
||||
}
|
||||
// 检查并处理 Backfeed 类型
|
||||
else if (device is Backfeed backfeedDevice)
|
||||
{
|
||||
if(backfeedDevice.CurrentInstance is ITcp itcpDevice1)
|
||||
{
|
||||
bool result = await itcpDevice1.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
else if (backfeedDevice.CurrentInstance is ISerialPort iserialPortDevice1)
|
||||
{
|
||||
bool result = await iserialPortDevice1.ConnectAsync(CancellationToken.None);
|
||||
}
|
||||
LoggerHelper.SuccessWithNotify($"{name} 连接成功 (Backfeed)");
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"{name} 不是有效的设备类型");
|
||||
}
|
||||
}
|
||||
catch(InvalidCastException ex)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"{name} 连接失败: {ex.Message}", ex.StackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public void StartPollingCollectionAsync()
|
||||
{
|
||||
foreach (var dc in DeviceDic)
|
||||
{
|
||||
var name = dc.Key;
|
||||
|
||||
switch (name)
|
||||
{
|
||||
case "Backfeed":
|
||||
{
|
||||
var polling = new BackfeedPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("Backfeed", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "IT6724C":
|
||||
{
|
||||
var polling = new IT6724CPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("IT6724C", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "LQ7500_D":
|
||||
{
|
||||
var polling = new LQ7500_DPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("LQ7500_D", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "EAEL9080":
|
||||
{
|
||||
var polling = new EAEL9080PollingRead(_containerProvider);
|
||||
PollingReadDic.Add("EAEL9080", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "IOBoard":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "PSB11000":
|
||||
{
|
||||
var polling = new PSB11000PollingRead(_containerProvider);
|
||||
PollingReadDic.Add("PSB11000", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
case "WS_68030_380T":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "SQ0030G1D":
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "ZXKS":
|
||||
{
|
||||
var polling = new ZXKSPollingRead(_containerProvider);
|
||||
PollingReadDic.Add("ZXKS", polling);
|
||||
polling.StartPolling();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LoggerHelper.Warn($"未定义 {name} 的轮询处理器");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_appCancellationTokenSource.Cancel();
|
||||
_appCancellationTokenSource.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
28
BOB/Singleton/GlobalVariables.cs
Normal file
28
BOB/Singleton/GlobalVariables.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using BOB.Models;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB
|
||||
{
|
||||
public class GlobalVariables
|
||||
{
|
||||
public ProgramModel Program { get; set; } = new();
|
||||
public bool IsAdmin { get; set; } = true;
|
||||
public String UserName { get; set; } = "hsc";
|
||||
public String Title { get; set; } = "主程序";
|
||||
public string CurrentFilePath { get; set; }
|
||||
public bool? IsStop { get; set; }
|
||||
public bool SingleStep { get; set; }
|
||||
public string RunState { get; set; } = "运行";
|
||||
public ObservableCollection<Assembly> Assemblies { get; set; } = new();
|
||||
public PackIconKind RunIcon { get; set; } = PackIconKind.Play;
|
||||
public StepModel SelectedStep { get; set; }
|
||||
public ParameterModel SelectedParameter { get; set; }
|
||||
}
|
||||
}
|
||||
540
BOB/Singleton/StepRunning.cs
Normal file
540
BOB/Singleton/StepRunning.cs
Normal file
@ -0,0 +1,540 @@
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using Common.Tools;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static BOB.Models.ParameterModel;
|
||||
|
||||
|
||||
namespace BOB
|
||||
{
|
||||
public class StepRunning
|
||||
{
|
||||
private GlobalVariables _globalVariables;
|
||||
private Devices _devices;
|
||||
private IContainerProvider containerProvider;
|
||||
private IEventAggregator _eventAggregator;
|
||||
|
||||
private readonly Dictionary<Guid, ParameterModel> tmpParameters = [];
|
||||
|
||||
private readonly Stopwatch stepStopwatch = new();
|
||||
|
||||
private readonly Stack<Stopwatch> loopStopwatchStack = new();
|
||||
|
||||
private readonly Stack<LoopContext> loopStack = new();
|
||||
|
||||
public CancellationTokenSource stepCTS = new();
|
||||
private bool SubSingleStep = false;
|
||||
|
||||
private Guid TestRoundID;
|
||||
public StepRunning(GlobalVariables globalVariables,IEventAggregator eventAggregator,IContainerProvider containerProvider)
|
||||
{
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = eventAggregator;
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
}
|
||||
public async Task<bool> ExecuteSteps(ProgramModel program, int depth = 0, CancellationToken cancellationToken = default)
|
||||
{
|
||||
int index = 0;
|
||||
bool stepSuccess = false;
|
||||
if (depth == 0)
|
||||
{
|
||||
loopStack.Clear();
|
||||
loopStopwatchStack.Clear();
|
||||
ResetAllStepStatus(program);
|
||||
tmpParameters.Clear();
|
||||
TestRoundID = Guid.NewGuid();
|
||||
}
|
||||
foreach (var item in program.Parameters)
|
||||
{
|
||||
tmpParameters.TryAdd(item.ID, item);
|
||||
}
|
||||
|
||||
while (index < program.StepCollection.Count)
|
||||
{
|
||||
while (_globalVariables.IsStop == true)
|
||||
{
|
||||
await Task.Delay(50);
|
||||
}
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
break;
|
||||
}
|
||||
var step = program.StepCollection[index];
|
||||
if (!step.IsUsed)
|
||||
{
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
step.Result = 0;
|
||||
if (step.StepType == "循环开始")
|
||||
{
|
||||
var endStep = program.StepCollection.FirstOrDefault(x => x.LoopStartStepId == step.ID);
|
||||
if (endStep != null)
|
||||
{
|
||||
endStep.Result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("程序循环指令未闭合,请检查后重试");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理循环开始
|
||||
if (step.StepType == "循环开始")
|
||||
{
|
||||
Stopwatch loopStopwatch = new();
|
||||
loopStopwatch.Start();
|
||||
loopStopwatchStack.Push(loopStopwatch);
|
||||
var context = new LoopContext
|
||||
{
|
||||
LoopCount = step.LoopCount ?? 1,
|
||||
CurrentLoop = 0,
|
||||
StartIndex = index,
|
||||
LoopStartStep = step
|
||||
};
|
||||
loopStack.Push(context);
|
||||
step.CurrentLoopCount = context.LoopCount;
|
||||
LoggerHelper.InfoWithNotify($"循环开始,共{context.LoopCount}次", depth);
|
||||
index++;
|
||||
}
|
||||
|
||||
// 处理循环结束
|
||||
else if (step.StepType == "循环结束")
|
||||
{
|
||||
if (loopStack.Count == 0)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("未匹配的循环结束指令", depth:depth);
|
||||
step.Result = 2;
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
var context = loopStack.Peek();
|
||||
context.CurrentLoop++;
|
||||
|
||||
// 更新循环开始步骤的显示
|
||||
context.LoopStartStep!.CurrentLoopCount = context.LoopCount - context.CurrentLoop;
|
||||
|
||||
if (context.CurrentLoop < context.LoopCount)
|
||||
{
|
||||
// 继续循环:跳转到循环开始后的第一条指令
|
||||
index = context.StartIndex + 1;
|
||||
LoggerHelper.InfoWithNotify($"循环第{context.CurrentLoop}次结束,跳回开始,剩余{context.LoopCount - context.CurrentLoop}次", depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 循环结束
|
||||
loopStack.Pop();
|
||||
var loopStopwatch = loopStopwatchStack.Peek();
|
||||
index++;
|
||||
LoggerHelper.InfoWithNotify($"循环结束,共执行{context.LoopCount}次", depth);
|
||||
if (depth == 0 && loopStopwatch.IsRunning)
|
||||
{
|
||||
loopStopwatch.Stop();
|
||||
step.RunTime = (int)loopStopwatch.ElapsedMilliseconds;
|
||||
step.Result = 1;
|
||||
program.StepCollection.First(x => x.ID == step.LoopStartStepId).Result = 1;
|
||||
loopStopwatchStack.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理普通步骤
|
||||
else
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
stepStopwatch.Restart();
|
||||
}
|
||||
|
||||
if (step.SubProgram != null)
|
||||
{
|
||||
if (_globalVariables.SingleStep)//子程序的单步执行将执行完保存下的所有Method
|
||||
{
|
||||
SubSingleStep = true;
|
||||
_globalVariables.SingleStep = false;
|
||||
}
|
||||
LoggerHelper.InfoWithNotify($"开始执行子程序 [ {step.Index} ] [ {step.Name} ] ", depth);
|
||||
stepSuccess = await ExecuteSteps(step.SubProgram, depth + 1, cancellationToken);
|
||||
UpdateCurrentStepResult(step, true, stepSuccess, depth);
|
||||
if (SubSingleStep)
|
||||
{
|
||||
SubSingleStep = false;
|
||||
_globalVariables.SingleStep = true;
|
||||
}
|
||||
}
|
||||
else if (step.Method != null)
|
||||
{
|
||||
LoggerHelper.InfoWithNotify($"开始执行指令 [ {step.Index} ] [ {step.Method!.FullName}.{step.Method.Name} ] ", depth);
|
||||
await ExecuteMethodStep(step, tmpParameters, depth, cancellationToken);
|
||||
stepSuccess = step.Result == 1;
|
||||
if (step.NGGotoStepID != null && !stepSuccess)
|
||||
{
|
||||
var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.NGGotoStepID);
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
if (step.OKGotoStepID != null && stepSuccess)
|
||||
{
|
||||
var tmp = program.StepCollection.FirstOrDefault(x => x.ID == step.OKGotoStepID);
|
||||
if (tmp != null)
|
||||
{
|
||||
index = tmp.Index - 2;
|
||||
LoggerHelper.InfoWithNotify($"指令跳转 [ {tmp.Index} ] [ {tmp.Name} ]", depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
index++;
|
||||
|
||||
if (depth == 0 && stepStopwatch.IsRunning)
|
||||
{
|
||||
stepStopwatch.Stop();
|
||||
step.RunTime = (int)stepStopwatch.ElapsedMilliseconds;
|
||||
}
|
||||
if (_globalVariables.SingleStep)
|
||||
{
|
||||
_globalVariables.IsStop = true;
|
||||
_globalVariables.RunState = "运行";
|
||||
_globalVariables.SingleStep = false;
|
||||
_eventAggregator.GetEvent<UpdateIconEvent>().Publish("Play");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loopStack.Count == 0 && stepSuccess;
|
||||
}
|
||||
|
||||
public async Task ExecuteMethodStep(StepModel step, Dictionary<Guid, ParameterModel> parameters, int depth, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(_globalVariables.Program.StepCollection.Count>1)
|
||||
_globalVariables.SelectedStep = null;
|
||||
await Task.Delay(SystemConfig.Instance.PerformanceLevel);
|
||||
|
||||
// 1. 查找类型
|
||||
Type? targetType = null;
|
||||
foreach (var assembly in _globalVariables.Assemblies)
|
||||
{
|
||||
targetType = assembly.GetType(step.Method!.FullName!);
|
||||
if (targetType != null) break;
|
||||
}
|
||||
if (targetType == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到类型 {step.Method!.FullName}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
// 2. 创建实例(仅当方法不是静态时才需要)
|
||||
object? instance = null;
|
||||
bool isMethod = false;
|
||||
|
||||
// 3. 准备参数
|
||||
var inputParams = new List<object?>();
|
||||
var paramTypes = new List<Type>();
|
||||
ParameterModel? outputParam = null;
|
||||
foreach (var param in step.Method!.Parameters)
|
||||
{
|
||||
if (param.Category == ParameterCategory.Input)
|
||||
{
|
||||
if (param.Type == typeof(CancellationToken))
|
||||
{
|
||||
inputParams.Add(stepCTS.Token);
|
||||
paramTypes.Add(param.Type!);
|
||||
continue;
|
||||
}
|
||||
var actualValue = param.GetActualValue(tmpParameters);
|
||||
// 类型转换处理
|
||||
if (actualValue != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(actualValue.ToString()))
|
||||
{
|
||||
actualValue = null;
|
||||
}
|
||||
if (actualValue != null && param.Type != null && actualValue.GetType() != param.Type)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (param.Type.IsArray)
|
||||
{
|
||||
// 获取数组元素类型
|
||||
Type elementType = param.Type.GetElementType()!;
|
||||
|
||||
// 解析字符串为字符串数组
|
||||
string[] stringArray = actualValue.ToString()!
|
||||
.Trim('[', ']')
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim())
|
||||
.ToArray();
|
||||
|
||||
// 创建目标类型数组
|
||||
Array array = Array.CreateInstance(elementType, stringArray.Length);
|
||||
|
||||
// 转换每个元素
|
||||
for (int i = 0; i < stringArray.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 特殊处理字符串类型
|
||||
if (elementType == typeof(string))
|
||||
{
|
||||
array.SetValue(stringArray[i], i);
|
||||
}
|
||||
// 特殊处理枚举类型
|
||||
else if (elementType.IsEnum)
|
||||
{
|
||||
array.SetValue(Enum.Parse(elementType, stringArray[i]), i);
|
||||
}
|
||||
// 常规类型转换
|
||||
else
|
||||
{
|
||||
array.SetValue(Convert.ChangeType(stringArray[i], elementType), i);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new InvalidCastException($"指令 [ {step.Index} ] 执行错误:元素 '{stringArray[i]}' 无法转换为 {elementType.Name}[]");
|
||||
}
|
||||
}
|
||||
actualValue = array;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (param.Type.BaseType == typeof(Enum))
|
||||
{
|
||||
actualValue = Enum.Parse(param.Type, param.Value!.ToString()!);
|
||||
}
|
||||
else
|
||||
{
|
||||
actualValue = Convert.ChangeType(actualValue, param.Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] 执行错误:参数 {param.Name} 类型转换失败: {ex.Message}", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
inputParams.Add(actualValue);
|
||||
paramTypes.Add(param.Type!);
|
||||
}
|
||||
else if (param.Category == ParameterCategory.Output)
|
||||
{
|
||||
outputParam = param;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 获取方法
|
||||
var method = targetType!.GetMethod(
|
||||
step.Method.Name!,
|
||||
BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance,
|
||||
null,
|
||||
paramTypes.ToArray(),
|
||||
null
|
||||
);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:未找到方法{step.Method.Name}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
|
||||
// 检查是否是静态方法
|
||||
bool isStaticMethod = method!.IsStatic;
|
||||
|
||||
// 如果是实例方法,需要创建实例
|
||||
if (!isStaticMethod)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance = _devices.DeviceDic[targetType.Name];
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误:创建实例失败 - {ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 执行方法
|
||||
|
||||
object? returnValue = method.Invoke(instance, inputParams.ToArray());
|
||||
try
|
||||
{
|
||||
// 处理异步方法
|
||||
if (returnValue is Task task)
|
||||
{
|
||||
await task.ConfigureAwait(false);
|
||||
// 获取结果(如果是Task<T>)
|
||||
if (task.GetType().IsGenericType)
|
||||
{
|
||||
var returnValueProperty = task.GetType().GetProperty("Result");
|
||||
returnValue = returnValueProperty?.GetValue(task);
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理VoidTaskreturnValue类型
|
||||
if (returnValue != null && returnValue.GetType().FullName == "System.Threading.Tasks.VoidTaskreturnValue")
|
||||
{
|
||||
returnValue = null;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
// 6. 处理输出
|
||||
bool paraResult = true; //记录参数上下限是否NG
|
||||
if (outputParam != null)
|
||||
{
|
||||
outputParam.Value = returnValue;
|
||||
var currentPara = outputParam.GetCurrentParameter(tmpParameters);
|
||||
if (currentPara != null)
|
||||
{
|
||||
currentPara.Value = returnValue;
|
||||
var tmp = currentPara.GetResult();
|
||||
currentPara.Result = tmp.Item1;
|
||||
paraResult = tmp.Item1;
|
||||
if (tmp.Item2 != null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify(tmp.Item2);
|
||||
}
|
||||
if (currentPara.IsSave && _globalVariables.Program.Parameters.FirstOrDefault(x => x.ID == currentPara.ID) != null)
|
||||
{
|
||||
_ = SaveDataToDatabase(_globalVariables.Program.ID, currentPara);
|
||||
}
|
||||
}
|
||||
var returnType = returnValue?.GetType();
|
||||
if (returnType != null)
|
||||
{
|
||||
if (!returnType.IsArray)
|
||||
{
|
||||
LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = {returnValue} ({returnType.Name})", depth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (returnValue is IEnumerable enumerable)
|
||||
{
|
||||
var elements = enumerable.Cast<object>().Select(item => item?.ToString() ?? "null");
|
||||
LoggerHelper.SuccessWithNotify($"输出 [ {outputParam.Name} ] = [ {string.Join(", ", elements)} ] ({returnType.Name})", depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LoggerHelper.SuccessWithNotify($"指令 [ {step.Index} ] 执行成功", depth);
|
||||
UpdateCurrentStepResult(step, paraResult: paraResult, depth: depth);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"指令 [ {step.Index} ] 执行错误: {ex.InnerException?.Message ?? ex.Message}", depth: depth);
|
||||
step.Result = 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetAllStepStatus(ProgramModel program)
|
||||
{
|
||||
foreach (var step in program.StepCollection)
|
||||
{
|
||||
step.Result = -1;
|
||||
step.RunTime = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCurrentStepResult(StepModel step, bool paraResult = true, bool stepResult = true, int depth = 0)
|
||||
{
|
||||
if (stepResult && paraResult)
|
||||
{
|
||||
if (string.IsNullOrEmpty(step.OKExpression))
|
||||
{
|
||||
step.Result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<string, object> paraDic = [];
|
||||
foreach (var item in tmpParameters)
|
||||
{
|
||||
paraDic.TryAdd(item.Value.Name, item.Value.Value!);
|
||||
}
|
||||
if (step.SubProgram != null)
|
||||
{
|
||||
foreach (var item in step.SubProgram.Parameters.Where(x => x.Category == ParameterCategory.Output))
|
||||
{
|
||||
paraDic.TryAdd(item.Name, item.Value!);
|
||||
}
|
||||
}
|
||||
else if (step.Method != null)
|
||||
{
|
||||
foreach (var item in step.Method.Parameters.Where(x => x.Category == ParameterCategory.Output))
|
||||
{
|
||||
paraDic.TryAdd(item.Name, item.Value!);
|
||||
}
|
||||
}
|
||||
bool re = ExpressionEvaluator.EvaluateExpression(step.OKExpression, paraDic);
|
||||
step.Result = re ? 1 : 2;
|
||||
if (step.Result == 2)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"指令 [ {step.Index} ] NG:条件表达式验证失败", depth: depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!paraResult)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify("参数限值校验失败", depth: depth);
|
||||
}
|
||||
step.Result = 2;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveDataToDatabase(Guid programID, ParameterModel currentPara)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region 私有类
|
||||
|
||||
private class LoopContext
|
||||
{
|
||||
public int LoopCount { get; set; }
|
||||
public int CurrentLoop { get; set; }
|
||||
public int StartIndex { get; set; }
|
||||
public StepModel? LoopStartStep { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
121
BOB/SystemConfig.cs
Normal file
121
BOB/SystemConfig.cs
Normal file
@ -0,0 +1,121 @@
|
||||
using BOB.Models;
|
||||
using Logger;
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BOB
|
||||
{
|
||||
public class SystemConfig
|
||||
{
|
||||
private static readonly object _lock = new();
|
||||
|
||||
private static SystemConfig? _instance;
|
||||
|
||||
public static SystemConfig Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new();
|
||||
_instance.LoadFromFile();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public string SystemPath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "BOB");
|
||||
public string Title { get; set; } = "";
|
||||
public int SaveDay { get; set; }
|
||||
public string DBSavePath { get; set; } = "";
|
||||
|
||||
public int PerformanceLevel { get; set; } = 50;
|
||||
|
||||
public string DLLFilePath { get; set; } = @"D:\BOB\指令\";
|
||||
|
||||
public string SubProgramFilePath { get; set; } = @"D:\BOB\子程序\";
|
||||
|
||||
public string DefaultSubProgramFilePath { get; set; } = "";
|
||||
public ObservableCollection<string> CurSingleList { get; set; }
|
||||
public List<DeviceConfigModel> DeviceList { get; set; } = new();
|
||||
|
||||
#region 配置加载方法
|
||||
public void SaveToFile()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(SystemPath))
|
||||
Directory.CreateDirectory(SystemPath);
|
||||
|
||||
string configPath = Path.Combine(SystemPath, $"{Title}.json");
|
||||
|
||||
// 支持接口多态序列化
|
||||
string json = JsonConvert.SerializeObject(this, Formatting.Indented,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.All
|
||||
});
|
||||
|
||||
File.WriteAllText(configPath, json);
|
||||
|
||||
LoggerHelper.InfoWithNotify("系统配置已保存。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"配置保存失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadFromFile()
|
||||
{
|
||||
string configPath = Path.Combine(SystemPath, $"{Title}.json");
|
||||
if(Title == "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
SaveToFile();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(configPath);
|
||||
|
||||
// 支持接口多态反序列化
|
||||
var loadedConfig = JsonConvert.DeserializeObject<SystemConfig>(json,
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
TypeNameHandling = TypeNameHandling.All
|
||||
});
|
||||
|
||||
// 复制所有可写属性(排除 JsonIgnore 属性)
|
||||
PropertyInfo[] properties = typeof(SystemConfig).GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
if (prop.CanWrite && !Attribute.IsDefined(prop, typeof(JsonIgnoreAttribute)))
|
||||
{
|
||||
prop.SetValue(this, prop.GetValue(loadedConfig));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"配置加载失败: {ex.Message}", ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
568
BOB/ViewModels/CommandTreeViewModel.cs
Normal file
568
BOB/ViewModels/CommandTreeViewModel.cs
Normal file
@ -0,0 +1,568 @@
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using Common.Attributes;
|
||||
using Logger;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
using static BOB.Models.ParameterModel;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class CommandTreeViewModel:BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private string _SearchText;
|
||||
|
||||
public string SearchText
|
||||
{
|
||||
get => _SearchText;
|
||||
set => SetProperty(ref _SearchText, value);
|
||||
}
|
||||
private ObservableCollection<InstructionNode> _instructionTree = new();
|
||||
public ObservableCollection<InstructionNode> InstructionTree
|
||||
{
|
||||
get => _instructionTree;
|
||||
set => SetProperty(ref _instructionTree, value);
|
||||
}
|
||||
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _globalVariables.Program;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.Program != value)
|
||||
{
|
||||
_globalVariables.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<Assembly> Assemblies
|
||||
{
|
||||
get => _globalVariables.Assemblies;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.Assemblies != value)
|
||||
{
|
||||
_globalVariables.Assemblies = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<SubProgramItem> _subPrograms = new();
|
||||
public ObservableCollection<SubProgramItem> SubPrograms
|
||||
{
|
||||
get => _subPrograms;
|
||||
set => SetProperty(ref _subPrograms, value);
|
||||
}
|
||||
|
||||
private Dictionary<object, InstructionNode> _treeNodeMap = new();
|
||||
public Dictionary<object, InstructionNode> TreeNodeMap
|
||||
{
|
||||
get => _treeNodeMap;
|
||||
set => SetProperty(ref _treeNodeMap, value);
|
||||
}
|
||||
|
||||
private Dictionary<string, XmlDocument> _xmlDocumentCache = new();
|
||||
public Dictionary<string, XmlDocument> XmlDocumentCache
|
||||
{
|
||||
get => _xmlDocumentCache;
|
||||
set => SetProperty(ref _xmlDocumentCache, value);
|
||||
}
|
||||
GlobalVariables _globalVariables { get; set; }
|
||||
#endregion
|
||||
public ICommand LoadedCommand { get; set; }
|
||||
public ICommand SearchEnterCommand { get; set; }
|
||||
public ICommand TreeDoubleClickCommand { get; set; }
|
||||
public ICommand ReloadCommand { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
public CommandTreeViewModel(GlobalVariables _GlobalVariables, Devices devices)
|
||||
{
|
||||
_globalVariables= _GlobalVariables;
|
||||
_devices = devices;
|
||||
LoadedCommand = new DelegateCommand(Loaded);
|
||||
SearchEnterCommand = new DelegateCommand(Search);
|
||||
TreeDoubleClickCommand = new DelegateCommand<object>(TreeDoubleClick);
|
||||
ReloadCommand = new DelegateCommand(Reload);
|
||||
}
|
||||
|
||||
|
||||
#region 委托命令
|
||||
private void Reload()
|
||||
{
|
||||
LoadAllAssemblies();
|
||||
LoadSubPrograms();
|
||||
LoadInstructionsToTreeView();
|
||||
}
|
||||
private void TreeDoubleClick(object obj)
|
||||
{
|
||||
if(obj is InstructionNode Node)
|
||||
{
|
||||
if(Node.Children.Count == 0)
|
||||
{
|
||||
int index = _globalVariables.SelectedStep?.Index >= 0 ? _globalVariables.SelectedStep.Index : -1;
|
||||
if (Node.Tag is MethodInfo method)
|
||||
{
|
||||
AddMethodToProgram(method, index);
|
||||
}
|
||||
else if(Node.Tag is string tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case "循环开始":
|
||||
AddLoopStartStep(index);
|
||||
break;
|
||||
case "循环结束":
|
||||
AddLoopEndStep(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(Node.Tag is SubProgramItem subProgram)
|
||||
{
|
||||
AddSubProgramToProgram(subProgram, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Search()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void Loaded()
|
||||
{
|
||||
//Directory.CreateDirectory(SystemConfig.Instance.DLLFilePath);
|
||||
//Directory.CreateDirectory(SystemConfig.Instance.SubProgramFilePath);
|
||||
LoadAllAssemblies();
|
||||
LoadSubPrograms();
|
||||
LoadInstructionsToTreeView();
|
||||
|
||||
}
|
||||
#endregion
|
||||
#region 加载指令
|
||||
/// <summary>
|
||||
/// 加载指定目录下的所有DLL
|
||||
/// </summary>
|
||||
private void LoadAllAssemblies()
|
||||
{
|
||||
Assemblies.Clear();
|
||||
|
||||
foreach (var dllPath in Directory.GetFiles(SystemConfig.Instance.DLLFilePath, "*.dll"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.LoadFrom(dllPath);
|
||||
Assemblies.Add(assembly);
|
||||
|
||||
// 加载对应的XML注释文件
|
||||
string xmlPath = Path.ChangeExtension(dllPath, ".xml");
|
||||
if (File.Exists(xmlPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(xmlPath);
|
||||
_xmlDocumentCache[assembly.FullName!] = xmlDoc;
|
||||
}
|
||||
catch (Exception xmlEx)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"加载XML注释失败: {Path.GetFileName(xmlPath)} - {xmlEx.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"无法加载程序集 {Path.GetFileName(dllPath)}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 子程序加载方法
|
||||
private void LoadSubPrograms()
|
||||
{
|
||||
SubPrograms.Clear();
|
||||
|
||||
if (!Directory.Exists(SystemConfig.Instance.SubProgramFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(SystemConfig.Instance.SubProgramFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var filePath in Directory.GetFiles(SystemConfig.Instance.SubProgramFilePath, "*.bob"))
|
||||
{
|
||||
try
|
||||
{
|
||||
SubPrograms.Add(new SubProgramItem
|
||||
{
|
||||
Name = Path.GetFileNameWithoutExtension(filePath),
|
||||
FilePath = filePath
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"加载子程序错误: {filePath} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 加载指令集到TreeView
|
||||
/// </summary>
|
||||
private void LoadInstructionsToTreeView()
|
||||
{
|
||||
InstructionTree.Clear();
|
||||
var controlRootNode = new InstructionNode
|
||||
{
|
||||
Name = "系统指令",
|
||||
Tag = "ControlRoot"
|
||||
};
|
||||
InstructionTree.Add(controlRootNode);
|
||||
|
||||
// 循环开始
|
||||
controlRootNode.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = "循环开始",
|
||||
Tag = "循环开始"
|
||||
});
|
||||
|
||||
// 循环结束
|
||||
controlRootNode.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = "循环结束",
|
||||
Tag = "循环结束"
|
||||
});
|
||||
|
||||
// ----------------------
|
||||
// 子程序 根节点
|
||||
// ----------------------
|
||||
var subProgramRoot = new InstructionNode
|
||||
{
|
||||
Name = "子程序",
|
||||
Tag = "SubProgramRoot"
|
||||
};
|
||||
InstructionTree.Add(subProgramRoot);
|
||||
|
||||
foreach (var subProgram in SubPrograms)
|
||||
{
|
||||
subProgramRoot.Children.Add(new InstructionNode
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
Tag = subProgram,
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------
|
||||
// 动态 DLL 指令
|
||||
// ----------------------
|
||||
foreach (var assembly in Assemblies)
|
||||
{
|
||||
List<Type> validTypes = new List<Type>();
|
||||
try
|
||||
{
|
||||
var types = assembly.GetTypes().Where(t =>
|
||||
t.IsPublic &&
|
||||
!t.IsNested &&
|
||||
|
||||
(t.IsClass || t.IsValueType) &&
|
||||
(!t.IsAbstract || t.IsSealed) &&
|
||||
t.GetCustomAttribute<BOBCommandAttribute>() != null);
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false)
|
||||
continue;
|
||||
|
||||
var allMethods = new HashSet<MethodInfo>();
|
||||
GetPublicMethods(type, allMethods);
|
||||
|
||||
if (allMethods.Count > 0)
|
||||
validTypes.Add(type);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"加载类型错误: {assembly.FullName} - {ex.Message}");
|
||||
}
|
||||
|
||||
if (validTypes.Count > 0)
|
||||
{
|
||||
var assemblyNode = new InstructionNode
|
||||
{
|
||||
Name = assembly.GetName().Name,
|
||||
Tag = assembly
|
||||
};
|
||||
InstructionTree.Add(assemblyNode);
|
||||
TreeNodeMap[assembly] = assemblyNode;
|
||||
|
||||
foreach (var type in validTypes)
|
||||
{
|
||||
if (!_devices.DeviceDic.ContainsKey(type.Name)&& assembly.GetName().Name!= "Command") continue;
|
||||
var typeNode = new InstructionNode
|
||||
{
|
||||
Name = type.Name,
|
||||
Tag = type,
|
||||
};
|
||||
assemblyNode.Children.Add(typeNode);
|
||||
TreeNodeMap[type] = typeNode;
|
||||
|
||||
var allMethods = new HashSet<MethodInfo>();
|
||||
GetPublicMethods(type, allMethods);
|
||||
|
||||
foreach (var method in allMethods)
|
||||
{
|
||||
if (method.IsSpecialName) continue;
|
||||
if (method.DeclaringType == typeof(object)) continue;
|
||||
|
||||
string[] ignoreMethods = { "GetType", "ToString", "Equals", "GetHashCode" };
|
||||
if (ignoreMethods.Contains(method.Name)) continue;
|
||||
|
||||
if (method.GetCustomAttribute<BrowsableAttribute>()?.Browsable == false) continue;
|
||||
if (type.IsAbstract && type.IsSealed && !method.IsStatic) continue;
|
||||
|
||||
var parameters = method.GetParameters();
|
||||
var paramText = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
|
||||
|
||||
var methodNode = new InstructionNode
|
||||
{
|
||||
Name = $"{method.Name}({paramText})",
|
||||
Tag = method,
|
||||
};
|
||||
|
||||
typeNode.Children.Add(methodNode);
|
||||
TreeNodeMap[method] = methodNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 辅助方法
|
||||
/// <summary>
|
||||
/// 递归获取类型的所有公共方法(包括继承的方法),但跳过被重写的方法
|
||||
/// </summary>
|
||||
/// <param name="type">要处理的目标类型</param>
|
||||
/// <param name="methods">存储方法的集合</param>
|
||||
private void GetPublicMethods(Type type, HashSet<MethodInfo> methods)
|
||||
{
|
||||
// 获取当前类型的所有公共方法(包括继承的)
|
||||
var allMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
|
||||
.Where(m => !m.IsSpecialName &&
|
||||
m.DeclaringType != typeof(object))
|
||||
.ToList();
|
||||
|
||||
// 按方法签名分组
|
||||
var groupedMethods = allMethods
|
||||
.GroupBy(m => new { m.Name, Parameters = string.Join(",", m.GetParameters().Select(p => p.ParameterType.FullName)) });
|
||||
|
||||
foreach (var group in groupedMethods)
|
||||
{
|
||||
// 从组中选择声明类型最接近当前类型(即继承层次最深)的方法
|
||||
MethodInfo? selectedMethod = null;
|
||||
int minDepth = int.MaxValue;
|
||||
|
||||
foreach (var method in group)
|
||||
{
|
||||
// 计算声明类型的深度
|
||||
int depth = 0;
|
||||
Type? current = type;
|
||||
Type declaringType = method.DeclaringType!;
|
||||
|
||||
while (current != null && current != declaringType)
|
||||
{
|
||||
depth++;
|
||||
current = current.BaseType;
|
||||
}
|
||||
|
||||
// 如果找到声明类型且在继承链上
|
||||
if (current == declaringType)
|
||||
{
|
||||
if (selectedMethod == null || depth < minDepth)
|
||||
{
|
||||
selectedMethod = method;
|
||||
minDepth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMethod != null)
|
||||
{
|
||||
methods.Add(selectedMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region 指令添加
|
||||
|
||||
private void AddMethodToProgram(MethodInfo method, int insertIndex = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = method.Name,
|
||||
StepType = "方法",
|
||||
Method = new MethodModel
|
||||
{
|
||||
FullName = method.DeclaringType?.FullName,
|
||||
Name = method.Name
|
||||
}
|
||||
};
|
||||
|
||||
// 添加输入参数
|
||||
foreach (var param in method.GetParameters())
|
||||
{
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = param.Name!,
|
||||
Type = param.ParameterType,
|
||||
Category = ParameterCategory.Input
|
||||
});
|
||||
}
|
||||
|
||||
// 添加输出参数(返回值)
|
||||
Type returnType = method.ReturnType;
|
||||
if (returnType == typeof(Task))
|
||||
{
|
||||
// 不添加输出参数(无返回值)
|
||||
}
|
||||
else if (returnType.IsGenericType &&
|
||||
returnType.GetGenericTypeDefinition() == typeof(Task<>))
|
||||
{
|
||||
// 提取实际返回类型(如 Task<bool> -> bool)
|
||||
Type actualType = returnType.GetGenericArguments()[0];
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = "Result",
|
||||
Type = actualType, // 使用实际类型
|
||||
Category = ParameterCategory.Output
|
||||
});
|
||||
}
|
||||
else if (returnType != typeof(void))
|
||||
{
|
||||
// 同步方法正常添加
|
||||
newStep.Method.Parameters.Add(new ParameterModel
|
||||
{
|
||||
Name = "Result",
|
||||
Type = returnType,
|
||||
Category = ParameterCategory.Output
|
||||
});
|
||||
}
|
||||
|
||||
// 添加到程序
|
||||
if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.StepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加方法失败: {method.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSubProgramToProgram(SubProgramItem subProgram, int insertIndex = -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = subProgram.Name,
|
||||
StepType = "子程序"
|
||||
};
|
||||
var jsonstr = File.ReadAllText($"{subProgram.FilePath}");
|
||||
var tmp = JsonConvert.DeserializeObject<ProgramModel>(jsonstr);
|
||||
if (tmp != null)
|
||||
{
|
||||
newStep.SubProgram = tmp;
|
||||
}
|
||||
if (insertIndex >= 0 && insertIndex <= Program.StepCollection.Count)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.StepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"添加子程序失败: {subProgram.Name} - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoopStartStep(int insertIndex = -1)
|
||||
{
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = "循环开始",
|
||||
StepType = "循环开始",
|
||||
LoopCount = 1,
|
||||
Method = new() { Parameters = [new() { Name = "循环次数", Type = typeof(int), Category = ParameterCategory.Input }] }
|
||||
};
|
||||
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.StepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddLoopEndStep(int insertIndex = -1)
|
||||
{
|
||||
// 查找最近的未匹配循环开始
|
||||
StepModel? lastUnmatchedLoopStart = null;
|
||||
for (int i = Program.StepCollection.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (Program.StepCollection[i].StepType == "循环开始")
|
||||
{
|
||||
bool isMatched = Program.StepCollection.Any(s => s.StepType == "循环结束" && s.LoopStartStepId == Program.StepCollection[i].ID);
|
||||
|
||||
if (!isMatched)
|
||||
{
|
||||
lastUnmatchedLoopStart = Program.StepCollection[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var newStep = new StepModel
|
||||
{
|
||||
Name = "循环结束",
|
||||
StepType = "循环结束",
|
||||
LoopStartStepId = lastUnmatchedLoopStart?.ID
|
||||
};
|
||||
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, newStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
Program.StepCollection.Add(newStep);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
360
BOB/ViewModels/DataViewModel.cs
Normal file
360
BOB/ViewModels/DataViewModel.cs
Normal file
@ -0,0 +1,360 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using Logger;
|
||||
using Model.SQLModel;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using Service.Implement;
|
||||
using Service.Interface;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class DataViewModel : BindableBase, INavigationAware
|
||||
{
|
||||
#region 属性
|
||||
|
||||
private int _currentPage = 1;
|
||||
public int CurrentPage
|
||||
{
|
||||
get => _currentPage;
|
||||
set => SetProperty(ref _currentPage, value);
|
||||
}
|
||||
|
||||
private RefAsync<int> _totalPages=new RefAsync<int>(0);
|
||||
public RefAsync<int> TotalPages
|
||||
{
|
||||
get => _totalPages;
|
||||
set => SetProperty(ref _totalPages, value);
|
||||
}
|
||||
private int _UITotalPages;
|
||||
public int UITotalPages
|
||||
{
|
||||
get => _UITotalPages;
|
||||
set => SetProperty(ref _UITotalPages, value);
|
||||
}
|
||||
|
||||
private List<string> _dataTableList;
|
||||
public List<string> DataTableList
|
||||
{
|
||||
get => _dataTableList;
|
||||
set => SetProperty(ref _dataTableList, value);
|
||||
}
|
||||
private string _SelectTable;
|
||||
public string SelectTable
|
||||
{
|
||||
get => _SelectTable;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectTable, value))
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
private List<BackFeedData> _BackFeedDataList;
|
||||
public List<BackFeedData> BackFeedDataList
|
||||
{
|
||||
get => _BackFeedDataList;
|
||||
set => SetProperty(ref _BackFeedDataList, value);
|
||||
}
|
||||
private List<EAELD9080Data> _EAELD9080DataList;
|
||||
public List<EAELD9080Data> EAELD9080DataList
|
||||
{
|
||||
get => _EAELD9080DataList;
|
||||
set => SetProperty(ref _EAELD9080DataList, value);
|
||||
}
|
||||
private List<PSB1100Data> _PSB1100DataList;
|
||||
public List<PSB1100Data> PSB1100DataList
|
||||
{
|
||||
get => _PSB1100DataList;
|
||||
set => SetProperty(ref _PSB1100DataList, value);
|
||||
}
|
||||
private List<IT6724CData> _IT6724CDataList;
|
||||
public List<IT6724CData> IT6724CDataList
|
||||
{
|
||||
get => _IT6724CDataList;
|
||||
set => SetProperty(ref _IT6724CDataList, value);
|
||||
}
|
||||
private DateTime? _startDate;
|
||||
public DateTime? StartDate
|
||||
{
|
||||
get => _startDate;
|
||||
set => SetProperty(ref _startDate, value);
|
||||
}
|
||||
|
||||
private DateTime? _endDate;
|
||||
public DateTime? EndDate
|
||||
{
|
||||
get => _endDate;
|
||||
set => SetProperty(ref _endDate, value);
|
||||
}
|
||||
private ObservableCollection<object> _currentDataSource;
|
||||
public ObservableCollection<object> CurrentDataSource
|
||||
{
|
||||
get => _currentDataSource;
|
||||
set => SetProperty(ref _currentDataSource, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand FirstPageCommand { get; private set; }
|
||||
public ICommand PreviousPageCommand { get; private set; }
|
||||
public ICommand NextPageCommand { get; private set; }
|
||||
public ICommand LastPageCommand { get; private set; }
|
||||
public ICommand LoadCommand { get; private set; }
|
||||
public ICommand QueryCommand { get; private set; }
|
||||
public ICommand RefreshCommand { get; private set; }
|
||||
public ICommand SelectTableCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
private Devices _devices { get; set; }
|
||||
private IBaseService<BackFeedData> _backFeedService { get; set; }
|
||||
private IBaseService<EAELD9080Data> _eAELD9080Service { get; set; }
|
||||
private IBaseService<PSB1100Data> _pSB1100Service { get; set; }
|
||||
private IBaseService<IT6724CData> _iT6724CService { get; set; }
|
||||
|
||||
public DataViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
_dialogService = containerProvider.Resolve<IDialogService>();
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_backFeedService= containerProvider.Resolve<BackFeedService>();
|
||||
_eAELD9080Service = containerProvider.Resolve<EAEL9080Service>();
|
||||
_pSB1100Service = containerProvider.Resolve<PSB11000Service>();
|
||||
_iT6724CService = containerProvider.Resolve<IT6724CService>();
|
||||
FirstPageCommand = new AsyncDelegateCommand(GoToFirstPage);
|
||||
PreviousPageCommand = new AsyncDelegateCommand(GoToPreviousPage);
|
||||
NextPageCommand = new AsyncDelegateCommand(GoToNextPage);
|
||||
LastPageCommand = new AsyncDelegateCommand(GoToLastPage);
|
||||
LoadCommand = new AsyncDelegateCommand(Load);
|
||||
QueryCommand = new AsyncDelegateCommand(Query);
|
||||
RefreshCommand = new AsyncDelegateCommand(Refresh);
|
||||
SelectTableCommand = new AsyncDelegateCommand(OnSelectTable);
|
||||
DataTableList = new List<string> { "BackFeedData", "EAELD9080Data", "IT6724CData", "PSB1100Data"};
|
||||
}
|
||||
|
||||
private async Task OnSelectTable()
|
||||
{
|
||||
switch (SelectTable)
|
||||
{
|
||||
case "BackFeedData":
|
||||
CurrentDataSource = new ObservableCollection<object>(BackFeedDataList);
|
||||
break;
|
||||
case "EAELD9080Data":
|
||||
CurrentDataSource = new ObservableCollection<object>(EAELD9080DataList);
|
||||
break;
|
||||
case "PSB1100Data":
|
||||
CurrentDataSource = new ObservableCollection<object>(PSB1100DataList);
|
||||
break;
|
||||
case "IT6724CData":
|
||||
CurrentDataSource = new ObservableCollection<object>(IT6724CDataList);
|
||||
break;
|
||||
default:
|
||||
CurrentDataSource = new ObservableCollection<object>();
|
||||
break;
|
||||
}
|
||||
GoToFirstPage();
|
||||
}
|
||||
private DateTime? QueryStartTime;
|
||||
private DateTime? QueryEndTime;
|
||||
private bool DataQuery=false;
|
||||
private async Task Refresh()
|
||||
{
|
||||
DataQuery = false;
|
||||
QueryStartTime = null;
|
||||
QueryEndTime = null;
|
||||
await GoToFirstPage();
|
||||
}
|
||||
|
||||
private async Task Query()
|
||||
{
|
||||
if (!StartDate.HasValue || !EndDate.HasValue)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DateTime endDateWithTime = EndDate.Value.AddDays(1);
|
||||
if (StartDate.Value < endDateWithTime)
|
||||
{
|
||||
QueryStartTime = StartDate;
|
||||
QueryEndTime = endDateWithTime;
|
||||
DataQuery = true;
|
||||
await GoToFirstPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task Load()
|
||||
{
|
||||
var backFeedResult = await _backFeedService.GetAllAsync();
|
||||
if (backFeedResult.IsSuccess)
|
||||
{
|
||||
BackFeedDataList = backFeedResult.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("加载 BackFeed 数据失败");
|
||||
}
|
||||
|
||||
var eaELD9080Result = await _eAELD9080Service.GetAllAsync();
|
||||
if (eaELD9080Result.IsSuccess)
|
||||
{
|
||||
EAELD9080DataList = eaELD9080Result.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("加载 EAELD9080 数据失败");
|
||||
}
|
||||
|
||||
var pSB1100Result = await _pSB1100Service.GetAllAsync();
|
||||
if (pSB1100Result.IsSuccess)
|
||||
{
|
||||
PSB1100DataList = pSB1100Result.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("加载 PSB1100 数据失败");
|
||||
}
|
||||
|
||||
var it6724CResult = await _iT6724CService.GetAllAsync();
|
||||
if (it6724CResult.IsSuccess)
|
||||
{
|
||||
IT6724CDataList = it6724CResult.Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("加载 IT6724C 数据失败");
|
||||
}
|
||||
}
|
||||
private async Task GoToFirstPage()
|
||||
{
|
||||
CurrentPage = 1;
|
||||
await LoadPageData(CurrentPage);
|
||||
}
|
||||
|
||||
private async Task GoToPreviousPage()
|
||||
{
|
||||
if (CurrentPage > 1)
|
||||
{
|
||||
CurrentPage--;
|
||||
await LoadPageData(CurrentPage);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GoToNextPage()
|
||||
{
|
||||
if (CurrentPage < TotalPages)
|
||||
{
|
||||
CurrentPage++;
|
||||
await LoadPageData(CurrentPage);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GoToLastPage()
|
||||
{
|
||||
CurrentPage = TotalPages;
|
||||
await LoadPageData(CurrentPage);
|
||||
}
|
||||
|
||||
private int PageSize=20;
|
||||
private async Task LoadPageData(int currentPage)
|
||||
{
|
||||
switch (SelectTable)
|
||||
{
|
||||
case "BackFeedData":
|
||||
if (DataQuery) // 如果启用日期查询
|
||||
{
|
||||
var result = await _backFeedService.GetPagedAsync(currentPage, PageSize, TotalPages, QueryStartTime, QueryEndTime);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _backFeedService.GetPagedAsync(currentPage, PageSize, TotalPages);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
break;
|
||||
|
||||
case "EAELD9080Data":
|
||||
if (DataQuery)
|
||||
{
|
||||
var result = await _eAELD9080Service.GetPagedAsync(currentPage, PageSize, TotalPages, QueryStartTime, QueryEndTime);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _eAELD9080Service.GetPagedAsync(currentPage, PageSize, TotalPages);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
break;
|
||||
|
||||
case "PSB1100Data":
|
||||
if (DataQuery)
|
||||
{
|
||||
var result = await _pSB1100Service.GetPagedAsync(currentPage, PageSize, TotalPages, QueryStartTime, QueryEndTime);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _pSB1100Service.GetPagedAsync(currentPage, PageSize, TotalPages);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
break;
|
||||
|
||||
case "IT6724CData":
|
||||
if (DataQuery)
|
||||
{
|
||||
var result = await _iT6724CService.GetPagedAsync(currentPage, PageSize, TotalPages, QueryStartTime, QueryEndTime);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _iT6724CService.GetPagedAsync(currentPage, PageSize, TotalPages);
|
||||
if (result.IsSuccess)
|
||||
CurrentDataSource = new ObservableCollection<object>(result.Data);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CurrentDataSource = new ObservableCollection<object>();
|
||||
break;
|
||||
}
|
||||
|
||||
UITotalPages = TotalPages.Value;
|
||||
}
|
||||
|
||||
#region 导航
|
||||
|
||||
public void OnNavigatedTo(NavigationContext navigationContext) { }
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext) { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
454
BOB/ViewModels/Dialogs/BackfeedViewModel.cs
Normal file
454
BOB/ViewModels/Dialogs/BackfeedViewModel.cs
Normal file
@ -0,0 +1,454 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class BackfeedViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 属性
|
||||
|
||||
private string _Title = "反灌电压";
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
private string _设备标识字符串;
|
||||
public string 设备标识字符串
|
||||
{
|
||||
get { return _设备标识字符串; }
|
||||
set { SetProperty(ref _设备标识字符串, value); }
|
||||
}
|
||||
|
||||
private string _输出电压;
|
||||
public string 输出电压
|
||||
{
|
||||
get { return _输出电压; }
|
||||
set { SetProperty(ref _输出电压, value); }
|
||||
}
|
||||
|
||||
private string _输出电流;
|
||||
public string 输出电流
|
||||
{
|
||||
get { return _输出电流; }
|
||||
set { SetProperty(ref _输出电流, value); }
|
||||
}
|
||||
|
||||
private string _OCP电流;
|
||||
public string OCP电流
|
||||
{
|
||||
get { return _OCP电流; }
|
||||
set { SetProperty(ref _OCP电流, value); }
|
||||
}
|
||||
|
||||
private string _OVP电压;
|
||||
public string OVP电压
|
||||
{
|
||||
get { return _OVP电压; }
|
||||
set { SetProperty(ref _OVP电压, value); }
|
||||
}
|
||||
|
||||
private string _OPP功率;
|
||||
public string OPP功率
|
||||
{
|
||||
get { return _OPP功率; }
|
||||
set { SetProperty(ref _OPP功率, value); }
|
||||
}
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand QueryDeviceCommand { get; private set; }
|
||||
public ICommand SetVoltageCommand { get; private set; }
|
||||
public ICommand SetCurrentCommand { get; private set; }
|
||||
public ICommand EnableOCPCommand { get; private set; }
|
||||
public ICommand DisableOCPCommand { get; private set; }
|
||||
public ICommand SetOCPCommand { get; private set; }
|
||||
public ICommand EnableOVPCommand { get; private set; }
|
||||
public ICommand DisableOVPCommand { get; private set; }
|
||||
public ICommand SetOVPCommand { get; private set; }
|
||||
public ICommand EnableOPPCommand { get; private set; }
|
||||
public ICommand DisableOPPCommand { get; private set; }
|
||||
public ICommand SetOPPCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private IEventAggregator _eventAggregator { get;set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private object device { get; set; }
|
||||
|
||||
public BackfeedViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
|
||||
// Initialize commands
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
QueryDeviceCommand = new AsyncDelegateCommand(OnQueryDevice);
|
||||
SetVoltageCommand = new AsyncDelegateCommand(OnSetVoltage);
|
||||
SetCurrentCommand = new AsyncDelegateCommand(OnSetCurrent);
|
||||
EnableOCPCommand = new AsyncDelegateCommand(OnEnableOCP);
|
||||
DisableOCPCommand = new AsyncDelegateCommand(OnDisableOCP);
|
||||
SetOCPCommand = new AsyncDelegateCommand(OnSetOCP);
|
||||
EnableOVPCommand = new AsyncDelegateCommand(OnEnableOVP);
|
||||
DisableOVPCommand = new AsyncDelegateCommand(OnDisableOVP);
|
||||
SetOVPCommand = new AsyncDelegateCommand(OnSetOVP);
|
||||
EnableOPPCommand = new AsyncDelegateCommand(OnEnableOPP);
|
||||
DisableOPPCommand = new AsyncDelegateCommand(OnDisableOPP);
|
||||
SetOPPCommand = new AsyncDelegateCommand(OnSetOPP);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data )tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
|
||||
#region Command Handlers
|
||||
|
||||
private async Task OnConnect()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.ConnectAsync();
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.ConnectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
e36233A.Close();
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
it6724CReverse.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnQueryDevice()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
设备标识字符串 = await e36233A.查询设备信息();
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
设备标识字符串 = await it6724CReverse.查询设备信息();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSetVoltage()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置电压(Convert.ToDouble(输出电压));
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置电压(Convert.ToDouble(输出电压));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSetCurrent()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置电流(Convert.ToDouble(输出电流));
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置电流(Convert.ToDouble(输出电流));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnEnableOCP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OCP开关(true);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OCP开关(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnDisableOCP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OCP开关(false);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OCP开关(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSetOCP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置电流保护OCP电流(Convert.ToDouble(OCP电流));
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置电流保护OCP电流(Convert.ToDouble(OCP电流));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnEnableOVP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OVP开关(true);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OVP开关(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnDisableOVP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OVP开关(false);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OVP开关(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSetOVP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置电压保护OVP电压(Convert.ToDouble(OVP电压));
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置电压保护OVP电压(Convert.ToDouble(OVP电压));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnEnableOPP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OVP开关(true);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OVP开关(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnDisableOPP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置OVP开关(false);
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置OVP开关(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSetOPP()
|
||||
{
|
||||
if (device is E36233A e36233A)
|
||||
{
|
||||
await e36233A.设置功率保护功率(Convert.ToDouble(OPP功率));
|
||||
}
|
||||
else if (device is IT6724CReverse it6724CReverse)
|
||||
{
|
||||
await it6724CReverse.设置功率保护功率(Convert.ToDouble(OPP功率));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dialog规范
|
||||
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
// Implement cleanup logic here if needed
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_devices.DeviceDic.ContainsKey("E36233A"))
|
||||
{
|
||||
var a = _devices.DeviceDic["E36233A"] as E36233A;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
else if (_devices.DeviceDic.ContainsKey("IT6724CReverse"))
|
||||
{
|
||||
var a = _devices.DeviceDic["IT6724CReverse"] as IT6724CReverse;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
107
BOB/ViewModels/Dialogs/CANViewModel.cs
Normal file
107
BOB/ViewModels/Dialogs/CANViewModel.cs
Normal file
@ -0,0 +1,107 @@
|
||||
using BOB.Singleton;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class CANViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
private string _Title = "同星CAN";
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
private string _BLFPath;
|
||||
|
||||
public string BLFPath
|
||||
{
|
||||
get { return _BLFPath; }
|
||||
set { SetProperty(ref _BLFPath, value); }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
public ICommand SelectBLFPathCommand { get; set; }
|
||||
public ICommand SaveBLFPathCommand { get; set; }
|
||||
public ICommand StartTranscirbeCommand { get; set; }
|
||||
public ICommand EndTranscirbeCommand { get; set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
public CANViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
|
||||
SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
|
||||
StartTranscirbeCommand = new DelegateCommand(StartTranscirbe);
|
||||
EndTranscirbeCommand = new DelegateCommand(EndTranscirbe);
|
||||
}
|
||||
|
||||
#region 命令
|
||||
private void EndTranscirbe()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void StartTranscirbe()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void SaveBLFPath()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void SelectBLFPath()
|
||||
{
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
Title = "保存 CAN报文回放 BLF 文件",
|
||||
Filter = "BLF 文件 (*.blf)|*.blf|所有文件 (*.*)|*.*",
|
||||
DefaultExt = ".blf",
|
||||
FileName = "log.blf",
|
||||
OverwritePrompt = true
|
||||
};
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
BLFPath = Path.GetFullPath(dialog.FileName);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
263
BOB/ViewModels/Dialogs/EAEL9080ViewModel.cs
Normal file
263
BOB/ViewModels/Dialogs/EAEL9080ViewModel.cs
Normal file
@ -0,0 +1,263 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Commands;
|
||||
using Prism.Events;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class EAEL9080ViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
private string _Title = "低压直流负载";
|
||||
private string _设备标识字符串;
|
||||
private string _负载模式;
|
||||
private LineSeries _电压_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "电压(V)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private LineSeries _电流_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "电流(A)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private LineSeries _功率_lineSeries = new LineSeries
|
||||
{
|
||||
Title = "功率(W)",
|
||||
StrokeThickness = 2,
|
||||
};
|
||||
private NumericalDisplayViewModel _电压MV=new();
|
||||
private NumericalDisplayViewModel _电流MV = new();
|
||||
private NumericalDisplayViewModel _功率MV=new();
|
||||
private PlotModel _曲线Model = new();
|
||||
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get { return _曲线Model; }
|
||||
set { SetProperty(ref _曲线Model, value); }
|
||||
}
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
public string 设备标识字符串
|
||||
{
|
||||
get { return _设备标识字符串; }
|
||||
set { SetProperty(ref _设备标识字符串, value); }
|
||||
}
|
||||
|
||||
public string 负载模式
|
||||
{
|
||||
get { return _负载模式; }
|
||||
set { SetProperty(ref _负载模式, value); }
|
||||
}
|
||||
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get { return _电流_lineSeries; }
|
||||
set { SetProperty(ref _电流_lineSeries, value); }
|
||||
}
|
||||
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get { return _电压_lineSeries; }
|
||||
set { SetProperty(ref _电压_lineSeries, value); }
|
||||
}
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get { return _功率_lineSeries; }
|
||||
set { SetProperty(ref _功率_lineSeries, value); }
|
||||
}
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get { return _电压MV; }
|
||||
set { SetProperty(ref _电压MV, value); }
|
||||
}
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get { return _电流MV; }
|
||||
set { SetProperty(ref _电流MV, value); }
|
||||
}
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get { return _功率MV; }
|
||||
set { SetProperty(ref _功率MV, value); }
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
public ICommand 连接命令 { get; private set; }
|
||||
public ICommand 断开命令 { get; private set; }
|
||||
public ICommand 设置为远程模式命令 { get; private set; }
|
||||
public ICommand 设置负载工作模式命令 { get; private set; }
|
||||
public ICommand 电源输出开命令 { get; private set; }
|
||||
public ICommand 电源输出关命令 { get; private set; }
|
||||
public ICommand 关闭命令 { get; private set; }
|
||||
public ICommand 查询设备信息命令 { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private EAEL9080 device { get; set; }
|
||||
|
||||
public EAEL9080ViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
连接命令 = new AsyncDelegateCommand(OnConnect);
|
||||
断开命令 = new DelegateCommand(OnDisconnect);
|
||||
设置为远程模式命令 = new AsyncDelegateCommand(OnSetRemoteMode);
|
||||
设置负载工作模式命令 = new AsyncDelegateCommand(OnSetLoadMode);
|
||||
电源输出开命令 = new AsyncDelegateCommand(OnPowerOn);
|
||||
电源输出关命令 = new AsyncDelegateCommand(OnPowerOff);
|
||||
关闭命令 = new DelegateCommand(OnOff);
|
||||
查询设备信息命令 = new AsyncDelegateCommand(OnQueryDeviceInfo);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string,double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "EAEL9080") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private async Task OnQueryDeviceInfo()
|
||||
{
|
||||
设备标识字符串 = await device.查询设备信息();
|
||||
}
|
||||
|
||||
private void OnOff()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private async void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
|
||||
|
||||
private async Task OnSetRemoteMode()
|
||||
{
|
||||
await device.设置远程控制(true);
|
||||
}
|
||||
|
||||
private async Task OnSetLoadMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnPowerOn()
|
||||
{
|
||||
await device.打开输出();
|
||||
}
|
||||
|
||||
private async Task OnPowerOff()
|
||||
{
|
||||
await device.关闭输出();
|
||||
}
|
||||
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["EAEL9080"] as EAEL9080;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
197
BOB/ViewModels/Dialogs/IOBoardViewModel.cs
Normal file
197
BOB/ViewModels/Dialogs/IOBoardViewModel.cs
Normal file
@ -0,0 +1,197 @@
|
||||
using BOB.Singleton;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class IOBoardViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
public enum Address : ushort
|
||||
{
|
||||
ushort0 = 0,
|
||||
ushort1 = 1,
|
||||
ushort2 = 2,
|
||||
ushort3 = 3,
|
||||
ushort4 = 4,
|
||||
ushort5 = 5,
|
||||
ushort6 = 6,
|
||||
ushort7 = 7,
|
||||
ushort8 = 8,
|
||||
ushort9 = 9,
|
||||
ushort10 = 10,
|
||||
ushort11 = 11,
|
||||
ushort12 = 12,
|
||||
ushort13 = 13,
|
||||
ushort14 = 14,
|
||||
ushort15 = 15
|
||||
}
|
||||
#region 属性
|
||||
private string _title = "IO板卡";
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set { SetProperty(ref _title, value); }
|
||||
}
|
||||
|
||||
private string _offset="0";
|
||||
public string Offset
|
||||
{
|
||||
get { return _offset; }
|
||||
set { SetProperty(ref _offset, value); }
|
||||
}
|
||||
|
||||
private string _batchWriteStatus;
|
||||
public string BatchWriteStatus
|
||||
{
|
||||
get { return _batchWriteStatus; }
|
||||
set { SetProperty(ref _batchWriteStatus, value); }
|
||||
}
|
||||
private Address _SelectedAddress;
|
||||
public Address SelectedAddress
|
||||
{
|
||||
get { return _SelectedAddress; }
|
||||
set { SetProperty(ref _SelectedAddress, value); }
|
||||
}
|
||||
private List<Address> _AddressList=Enum.GetValues(typeof(Address)).Cast<Address>().ToList();
|
||||
public List<Address> AddressList
|
||||
{
|
||||
get { return _AddressList; }
|
||||
set { SetProperty(ref _AddressList, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand PowerOnCommand { get; private set; }
|
||||
public ICommand PowerOffCommand { get; private set; }
|
||||
public ICommand SetCommand { get; private set; }
|
||||
public ICommand ReadCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private IOBoard device { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
public IOBoardViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
PowerOnCommand = new AsyncDelegateCommand(OnPowerOn);
|
||||
PowerOffCommand = new AsyncDelegateCommand(OnPowerOff);
|
||||
SetCommand = new AsyncDelegateCommand(OnSet);
|
||||
ReadCommand = new AsyncDelegateCommand(OnRead);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
}
|
||||
|
||||
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
|
||||
private async Task OnPowerOn()
|
||||
{
|
||||
await device.写输出开关(1, (ushort)SelectedAddress, true);
|
||||
}
|
||||
|
||||
private async Task OnPowerOff()
|
||||
{
|
||||
await device.写输出开关(1, (ushort)SelectedAddress, false);
|
||||
}
|
||||
|
||||
private async Task OnSet()
|
||||
{
|
||||
bool[] statusArray = JsonConvert.DeserializeObject<bool[]>(BatchWriteStatus);
|
||||
|
||||
if (ushort.TryParse(Offset, out ushort offset))
|
||||
{
|
||||
if (statusArray==null||statusArray.Length+offset>16||statusArray.Length<=0||offset<0)
|
||||
{
|
||||
LoggerHelper.Error("BatchWriteStatus 数组内容不符合预期");
|
||||
return;
|
||||
}
|
||||
await device.批量写输出开关(1, offset, System.Text.Json.JsonSerializer.Deserialize<bool[]>(BatchWriteStatus));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.Error("BatchWriteStatus 数组内容不符合预期");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnRead()
|
||||
{
|
||||
if (ushort.TryParse(Offset, out ushort offset))
|
||||
{
|
||||
BatchWriteStatus = System.Text.Json.JsonSerializer.Serialize( await device.批量读输出开关(1, offset, 16));
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.Error("Offset 解析失败,确保其是有效的数字!");
|
||||
}
|
||||
}
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["IOBoard"] as IOBoard;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
331
BOB/ViewModels/Dialogs/IT6724CViewModel.cs
Normal file
331
BOB/ViewModels/Dialogs/IT6724CViewModel.cs
Normal file
@ -0,0 +1,331 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Annotations;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class IT6724CViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 属性
|
||||
private string _title = "低压直流电源";
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
private string _设备标识字符串;
|
||||
public string 设备标识字符串
|
||||
{
|
||||
get => _设备标识字符串;
|
||||
set => SetProperty(ref _设备标识字符串, value);
|
||||
}
|
||||
private string _输出电压;
|
||||
public string 输出电压
|
||||
{
|
||||
get => _输出电压;
|
||||
set => SetProperty(ref _输出电压, value);
|
||||
}
|
||||
|
||||
private string _输出电流;
|
||||
public string 输出电流
|
||||
{
|
||||
get => _输出电流;
|
||||
set => SetProperty(ref _输出电流, value);
|
||||
}
|
||||
|
||||
private string _OCP电流;
|
||||
public string OCP电流
|
||||
{
|
||||
get => _OCP电流;
|
||||
set => SetProperty(ref _OCP电流, value);
|
||||
}
|
||||
|
||||
private string _OVP电压;
|
||||
public string OVP电压
|
||||
{
|
||||
get => _OVP电压;
|
||||
set => SetProperty(ref _OVP电压, value);
|
||||
}
|
||||
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand PowerOnCommand { get; private set; }
|
||||
public ICommand PowerOffCommand { get; private set; }
|
||||
public ICommand SetOutputVoltageCommand { get; private set; }
|
||||
public ICommand SetOutputCurrentCommand { get; private set; }
|
||||
public ICommand SetRemoteModeCommand { get; private set; }
|
||||
public ICommand QueryDeviceInfoCommand { get; private set; }
|
||||
public ICommand EnableOCPCommand { get; private set; }
|
||||
public ICommand DisableOCPCommand { get; private set; }
|
||||
public ICommand ClearOCPAlarmCommand { get; private set; }
|
||||
public ICommand SetOCPCommand { get; private set; }
|
||||
public ICommand EnableOVPCommand { get; private set; }
|
||||
public ICommand DisableOVPCommand { get; private set; }
|
||||
public ICommand ClearOVPAlarmCommand { get; private set; }
|
||||
public ICommand SetOVPCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private IT6724C device { get; set; }
|
||||
public IT6724CViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
PowerOnCommand = new AsyncDelegateCommand(OnPowerOn);
|
||||
PowerOffCommand = new AsyncDelegateCommand(OnPowerOff);
|
||||
SetOutputVoltageCommand = new AsyncDelegateCommand(OnSetOutputVoltage);
|
||||
SetOutputCurrentCommand = new AsyncDelegateCommand(OnSetOutputCurrent);
|
||||
SetRemoteModeCommand = new AsyncDelegateCommand(OnSetRemoteMode);
|
||||
QueryDeviceInfoCommand = new AsyncDelegateCommand(OnQueryDeviceInfo);
|
||||
EnableOCPCommand = new AsyncDelegateCommand(OnEnableOCP);
|
||||
DisableOCPCommand = new AsyncDelegateCommand(OnDisableOCP);
|
||||
ClearOCPAlarmCommand = new AsyncDelegateCommand(OnClearOCPAlarm);
|
||||
SetOCPCommand = new AsyncDelegateCommand(OnSetOCP);
|
||||
EnableOVPCommand = new AsyncDelegateCommand(OnEnableOVP);
|
||||
DisableOVPCommand = new AsyncDelegateCommand(OnDisableOVP);
|
||||
ClearOVPAlarmCommand = new AsyncDelegateCommand(OnClearOVPAlarm);
|
||||
SetOVPCommand = new AsyncDelegateCommand(OnSetOVP);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
#region 命令处理方法
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
|
||||
private async Task OnPowerOn()
|
||||
{
|
||||
await device.设置电源输出(true);
|
||||
}
|
||||
|
||||
private async Task OnPowerOff()
|
||||
{
|
||||
await device.设置电源输出(false);
|
||||
}
|
||||
|
||||
private async Task OnSetOutputVoltage()
|
||||
{
|
||||
await device.设置电压(double.Parse(输出电压));
|
||||
}
|
||||
|
||||
private async Task OnSetOutputCurrent()
|
||||
{
|
||||
await device.设置电流(double.Parse(输出电流));
|
||||
}
|
||||
|
||||
private async Task OnSetRemoteMode()
|
||||
{
|
||||
await device.设置为远程模式();
|
||||
}
|
||||
|
||||
private async Task OnQueryDeviceInfo()
|
||||
{
|
||||
设备标识字符串=await device.查询设备信息();
|
||||
}
|
||||
|
||||
private async Task OnEnableOCP()
|
||||
{
|
||||
await device.设置OCP开关(true);
|
||||
}
|
||||
|
||||
private async Task OnDisableOCP()
|
||||
{
|
||||
await device.设置OCP开关(false);
|
||||
}
|
||||
|
||||
private async Task OnClearOCPAlarm()
|
||||
{
|
||||
await device.清除电流保护();
|
||||
}
|
||||
|
||||
private async Task OnSetOCP()
|
||||
{
|
||||
await device.设置电流保护OCP电流(double.Parse(OCP电流));
|
||||
}
|
||||
|
||||
private async Task OnEnableOVP()
|
||||
{
|
||||
await device.设置OVP开关(true);
|
||||
}
|
||||
|
||||
private async Task OnDisableOVP()
|
||||
{
|
||||
await device.设置OVP开关(false);
|
||||
}
|
||||
|
||||
private async Task OnClearOVPAlarm()
|
||||
{
|
||||
await device.清除电压保护();
|
||||
}
|
||||
|
||||
private async Task OnSetOVP()
|
||||
{
|
||||
await device.设置电压保护OVP电压(double.Parse(OVP电压));
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["IT6724C"] as IT6724C;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
57
BOB/ViewModels/Dialogs/LQ7500-DViewModel.cs
Normal file
57
BOB/ViewModels/Dialogs/LQ7500-DViewModel.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using BOB.Singleton;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class LQ7500_DViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
private string _Title = "水冷机";
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
public LQ7500_DViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
}
|
||||
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
123
BOB/ViewModels/Dialogs/MessageBoxViewModel.cs
Normal file
123
BOB/ViewModels/Dialogs/MessageBoxViewModel.cs
Normal file
@ -0,0 +1,123 @@
|
||||
using Common.PubEvent;
|
||||
using ControlzEx.Standard;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class MessageBoxViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 属性
|
||||
|
||||
private string _Title;
|
||||
public string Title
|
||||
{
|
||||
get => _Title;
|
||||
set => SetProperty(ref _Title, value);
|
||||
}
|
||||
|
||||
private string _Message = "";
|
||||
public string Message
|
||||
{
|
||||
get => _Message;
|
||||
set => SetProperty(ref _Message, value);
|
||||
}
|
||||
|
||||
private string _Icon= $"pack://siteoforigin:,,,/Resources/Images/info.png";
|
||||
public string Icon
|
||||
{
|
||||
get => _Icon;
|
||||
set => SetProperty(ref _Icon, value);
|
||||
}
|
||||
|
||||
private bool _ShowYes;
|
||||
public bool ShowYes
|
||||
{
|
||||
get => _ShowYes;
|
||||
set => SetProperty(ref _ShowYes, value);
|
||||
}
|
||||
|
||||
private bool _ShowNo;
|
||||
public bool ShowNo
|
||||
{
|
||||
get => _ShowNo;
|
||||
set => SetProperty(ref _ShowNo, value);
|
||||
}
|
||||
|
||||
private bool _ShowOk;
|
||||
public bool ShowOk
|
||||
{
|
||||
get => _ShowOk;
|
||||
set => SetProperty(ref _ShowOk, value);
|
||||
}
|
||||
|
||||
private bool _ShowCancel;
|
||||
public bool ShowCancel
|
||||
{
|
||||
get => _ShowCancel;
|
||||
set => SetProperty(ref _ShowCancel, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
public ICommand YesCommand { get; set; }
|
||||
public ICommand NoCommand { get; set; }
|
||||
public ICommand OkCommand { get; set; }
|
||||
public ICommand CancelCommand { get; set; }
|
||||
#endregion
|
||||
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
private IEventAggregator _eventAggregator;
|
||||
public MessageBoxViewModel(IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator= eventAggregator;
|
||||
YesCommand = new DelegateCommand(OnYes);
|
||||
NoCommand = new DelegateCommand(OnNo);
|
||||
OkCommand = new DelegateCommand(OnOk);
|
||||
CancelCommand = new DelegateCommand(OnCancel);
|
||||
}
|
||||
|
||||
private void CloseDialog(ButtonResult result)
|
||||
{
|
||||
var parameters = new DialogParameters();
|
||||
RequestClose.Invoke(new DialogResult(result));
|
||||
}
|
||||
|
||||
private void OnYes() => CloseDialog(ButtonResult.Yes);
|
||||
private void OnNo() => CloseDialog(ButtonResult.No);
|
||||
private void OnOk() => CloseDialog(ButtonResult.OK);
|
||||
private void OnCancel() => CloseDialog(ButtonResult.Cancel);
|
||||
|
||||
#region Prism Dialog 规范
|
||||
public bool CanCloseDialog() => true;
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Title = parameters.GetValue<string>("Title");
|
||||
Message = parameters.GetValue<string>("Message");
|
||||
var iconKey = parameters.GetValue<string>("Icon"); // info / error / warn
|
||||
Icon = iconKey switch
|
||||
{
|
||||
"info" => $"pack://siteoforigin:,,,/Resources/Images/info.png",
|
||||
"error" => $"pack://siteoforigin:,,,/Resources/Images/error.png",
|
||||
"warn" => $"pack://siteoforigin:,,,/Resources/Images/warning.png",
|
||||
_ => $"pack://siteoforigin:,,,/Resources/Images/info.png" // 默认
|
||||
};
|
||||
|
||||
|
||||
ShowYes = parameters.GetValue<bool>("ShowYes");
|
||||
ShowNo = parameters.GetValue<bool>("ShowNo");
|
||||
ShowOk = parameters.GetValue<bool>("ShowOk");
|
||||
ShowCancel = parameters.GetValue<bool>("ShowCancel");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
298
BOB/ViewModels/Dialogs/PSB11000ViewModel.cs
Normal file
298
BOB/ViewModels/Dialogs/PSB11000ViewModel.cs
Normal file
@ -0,0 +1,298 @@
|
||||
using BOB.Singleton;
|
||||
using BOB.ViewModels.UserControls;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class PSB11000ViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
private string _Title = "反灌高压直流双向电源";
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
private string _设备标识字符串;
|
||||
public string 设备标识字符串
|
||||
{
|
||||
get { return _设备标识字符串; }
|
||||
set { SetProperty(ref _设备标识字符串, value); }
|
||||
}
|
||||
|
||||
private string _输出电压;
|
||||
public string 输出电压
|
||||
{
|
||||
get { return _输出电压; }
|
||||
set { SetProperty(ref _输出电压, value); }
|
||||
}
|
||||
|
||||
private string _输出电流;
|
||||
public string 输出电流
|
||||
{
|
||||
get { return _输出电流; }
|
||||
set { SetProperty(ref _输出电流, value); }
|
||||
}
|
||||
|
||||
private string _OCP电流;
|
||||
public string OCP电流
|
||||
{
|
||||
get { return _OCP电流; }
|
||||
set { SetProperty(ref _OCP电流, value); }
|
||||
}
|
||||
private LineSeries _电压_lineSeries = new LineSeries { Title = "电压(V)", StrokeThickness = 2 };
|
||||
public LineSeries 电压_lineSeries
|
||||
{
|
||||
get => _电压_lineSeries;
|
||||
set => SetProperty(ref _电压_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _电流_lineSeries = new LineSeries { Title = "电流(A)", StrokeThickness = 2 };
|
||||
public LineSeries 电流_lineSeries
|
||||
{
|
||||
get => _电流_lineSeries;
|
||||
set => SetProperty(ref _电流_lineSeries, value);
|
||||
}
|
||||
|
||||
private LineSeries _功率_lineSeries = new LineSeries { Title = "功率(W)", StrokeThickness = 2 };
|
||||
public LineSeries 功率_lineSeries
|
||||
{
|
||||
get => _功率_lineSeries;
|
||||
set => SetProperty(ref _功率_lineSeries, value);
|
||||
}
|
||||
private NumericalDisplayViewModel _电压MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电压MV
|
||||
{
|
||||
get => _电压MV;
|
||||
set => SetProperty(ref _电压MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _电流MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 电流MV
|
||||
{
|
||||
get => _电流MV;
|
||||
set => SetProperty(ref _电流MV, value);
|
||||
}
|
||||
|
||||
private NumericalDisplayViewModel _功率MV = new NumericalDisplayViewModel();
|
||||
public NumericalDisplayViewModel 功率MV
|
||||
{
|
||||
get => _功率MV;
|
||||
set => SetProperty(ref _功率MV, value);
|
||||
}
|
||||
private PlotModel _曲线Model = new PlotModel();
|
||||
public PlotModel 曲线Model
|
||||
{
|
||||
get => _曲线Model;
|
||||
set => SetProperty(ref _曲线Model, value);
|
||||
}
|
||||
public DateTimeAxis TimeAxis { get; private set; }
|
||||
public LinearAxis ValueAxis { get; private set; }
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand PowerOnCommand { get; private set; }
|
||||
public ICommand PowerOffCommand { get; private set; }
|
||||
public ICommand SetRemoteModeCommand { get; private set; }
|
||||
public ICommand QueryDeviceInfoCommand { get; private set; }
|
||||
public ICommand SwitchWorkingModeCommand { get; private set; }
|
||||
public ICommand SwitchDCSourceModeCommand { get; private set; }
|
||||
public ICommand SwitchLoadModeCommand { get; private set; }
|
||||
public ICommand SetCCVoltageCommand { get; private set; }
|
||||
public ICommand SetCCCurrentCommand { get; private set; }
|
||||
public ICommand SetOCPCurrentCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
public ICommand ResetViewCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private PSB11000 device;
|
||||
public PSB11000ViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
PowerOnCommand = new AsyncDelegateCommand(OnPowerOn);
|
||||
PowerOffCommand = new AsyncDelegateCommand(OnPowerOff);
|
||||
SetRemoteModeCommand = new AsyncDelegateCommand(OnSetRemoteMode);
|
||||
QueryDeviceInfoCommand = new AsyncDelegateCommand(OnQueryDeviceInfo);
|
||||
SwitchWorkingModeCommand = new AsyncDelegateCommand(OnSwitchWorkingMode);
|
||||
SwitchDCSourceModeCommand = new AsyncDelegateCommand(OnSwitchDCSourceMode);
|
||||
SwitchLoadModeCommand = new AsyncDelegateCommand(OnSwitchLoadMode);
|
||||
SetCCVoltageCommand = new AsyncDelegateCommand(OnSetCCVoltage);
|
||||
SetCCCurrentCommand = new AsyncDelegateCommand(OnSetCCCurrent);
|
||||
SetOCPCurrentCommand = new AsyncDelegateCommand(OnSetOCPCurrent);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(UpdateCurve);
|
||||
InitCurve();
|
||||
}
|
||||
private void ResetView()
|
||||
{
|
||||
曲线Model.ResetAllAxes();
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
private void InitCurve()
|
||||
{
|
||||
TimeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
IntervalType = DateTimeIntervalType.Seconds,
|
||||
};
|
||||
ValueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
};
|
||||
曲线Model.Axes.Add(TimeAxis);
|
||||
曲线Model.Axes.Add(ValueAxis);
|
||||
曲线Model.Series.Add(电压_lineSeries);
|
||||
曲线Model.Series.Add(电流_lineSeries);
|
||||
曲线Model.Series.Add(功率_lineSeries);
|
||||
曲线Model.Legends.Add(new Legend()
|
||||
{
|
||||
LegendPosition = LegendPosition.TopRight,
|
||||
LegendOrientation = LegendOrientation.Vertical,
|
||||
LegendPlacement = LegendPlacement.Inside
|
||||
});
|
||||
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
private void UpdateCurve((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
if (device != "IT6724C") return;
|
||||
电流MV.MonitorValue = data["实时电流"];
|
||||
电压MV.MonitorValue = data["实时电压"];
|
||||
功率MV.MonitorValue = data["实时功率"];
|
||||
|
||||
var now = DateTimeAxis.ToDouble(DateTime.Now);
|
||||
电流_lineSeries.Points.Add(new DataPoint(now, data["实时电流"]));
|
||||
电压_lineSeries.Points.Add(new DataPoint(now, data["实时电压"]));
|
||||
功率_lineSeries.Points.Add(new DataPoint(now, data["实时功率"]));
|
||||
曲线Model.InvalidatePlot(true);
|
||||
}
|
||||
#region Command Handlers
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
|
||||
private async Task OnPowerOn()
|
||||
{
|
||||
await device.打开输出();
|
||||
}
|
||||
|
||||
private async Task OnPowerOff()
|
||||
{
|
||||
await device.关闭输出();
|
||||
}
|
||||
|
||||
private async Task OnSetRemoteMode()
|
||||
{
|
||||
await device.设置远程控制(true);
|
||||
}
|
||||
|
||||
private async Task OnQueryDeviceInfo()
|
||||
{
|
||||
设备标识字符串=await device.查询设备信息();
|
||||
}
|
||||
|
||||
private async Task OnSwitchWorkingMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSwitchDCSourceMode()
|
||||
{
|
||||
// Logic for switching DC source mode
|
||||
}
|
||||
|
||||
private async Task OnSwitchLoadMode()
|
||||
{
|
||||
// Logic for switching load mode
|
||||
}
|
||||
|
||||
private async Task OnSetCCVoltage()
|
||||
{
|
||||
// Logic for setting CC voltage
|
||||
}
|
||||
|
||||
private async Task OnSetCCCurrent()
|
||||
{
|
||||
// Logic for setting CC current
|
||||
}
|
||||
|
||||
private async Task OnSetOCPCurrent()
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["PSB11000"] as PSB11000;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
137
BOB/ViewModels/Dialogs/ParameterSettingViewModel.cs
Normal file
137
BOB/ViewModels/Dialogs/ParameterSettingViewModel.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using static BOB.Models.ParameterModel;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class ParameterSettingViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 属性
|
||||
private string _title = "参数设置界面";
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => SetProperty(ref _title, value);
|
||||
}
|
||||
private Array _EnumValues;
|
||||
public Array EnumValues
|
||||
{
|
||||
get => _EnumValues;
|
||||
set => SetProperty(ref _EnumValues, value);
|
||||
}
|
||||
private ObservableCollection<Type> _types =
|
||||
[
|
||||
typeof(string), typeof(bool),
|
||||
typeof(short), typeof(int), typeof(long), typeof(float), typeof(double),
|
||||
typeof(byte[]), typeof(short[]), typeof(ushort[]), typeof(int[]), typeof(long[]), typeof(float[]), typeof(double[]),
|
||||
typeof(object)
|
||||
];
|
||||
public ObservableCollection<Type> Types
|
||||
{
|
||||
get => _types;
|
||||
set => SetProperty(ref _types, value);
|
||||
}
|
||||
|
||||
private ObservableCollection<string> _categories = new ObservableCollection<string>(
|
||||
Enum.GetNames(typeof(ParameterCategory))
|
||||
);
|
||||
public ObservableCollection<string> Categories
|
||||
{
|
||||
get => _categories;
|
||||
set => SetProperty(ref _categories, value);
|
||||
}
|
||||
private string _Mode;
|
||||
public string Mode
|
||||
{
|
||||
get => _Mode;
|
||||
set => SetProperty(ref _Mode, value);
|
||||
}
|
||||
|
||||
private ProgramModel _program;
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _program;
|
||||
set => SetProperty(ref _program, value);
|
||||
}
|
||||
private ParameterModel _Parameter;
|
||||
public ParameterModel Parameter
|
||||
{
|
||||
get => _Parameter;
|
||||
set => SetProperty(ref _Parameter, value);
|
||||
}
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose{get;set;}
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
public ICommand CancelCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ParameterSettingViewModel(GlobalVariables globalVariables, IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_globalVariables = globalVariables;
|
||||
CancelCommand = new DelegateCommand(Cancel);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
if (Mode == "ADD")
|
||||
{
|
||||
Program.Parameters.Add(Parameter);
|
||||
_globalVariables.SelectedParameter = Parameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = Program.Parameters
|
||||
.Select((x, i) => new { x, i })
|
||||
.FirstOrDefault(p => p.x.ID == _globalVariables.SelectedParameter.ID)?.i;
|
||||
|
||||
if (index.HasValue)
|
||||
{
|
||||
Program.Parameters[index.Value] = Parameter;
|
||||
}
|
||||
}
|
||||
|
||||
RequestClose.Invoke(ButtonResult.OK);
|
||||
}
|
||||
|
||||
private void Cancel()
|
||||
{
|
||||
RequestClose.Invoke(ButtonResult.No);
|
||||
}
|
||||
#region Prism Dialog 规范
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
Program =_globalVariables.Program;
|
||||
Mode = parameters.GetValue<string>("Mode");
|
||||
if (Mode == "ADD")
|
||||
{
|
||||
Parameter = new();
|
||||
}
|
||||
else
|
||||
{
|
||||
Parameter = new ParameterModel(_globalVariables.SelectedParameter);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
227
BOB/ViewModels/Dialogs/SQ0030G1DViewModel.cs
Normal file
227
BOB/ViewModels/Dialogs/SQ0030G1DViewModel.cs
Normal file
@ -0,0 +1,227 @@
|
||||
using BOB.Singleton;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class SQ0030G1DViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
|
||||
private string _Title = "交流电源";
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
private string _UPhaseVoltage;
|
||||
public string UPhaseVoltage
|
||||
{
|
||||
get { return _UPhaseVoltage; }
|
||||
set { SetProperty(ref _UPhaseVoltage, value); }
|
||||
}
|
||||
|
||||
private string _VPhaseVoltage;
|
||||
public string VPhaseVoltage
|
||||
{
|
||||
get { return _VPhaseVoltage; }
|
||||
set { SetProperty(ref _VPhaseVoltage, value); }
|
||||
}
|
||||
|
||||
private string _WPhaseVoltage;
|
||||
public string WPhaseVoltage
|
||||
{
|
||||
get { return _WPhaseVoltage; }
|
||||
set { SetProperty(ref _WPhaseVoltage, value); }
|
||||
}
|
||||
|
||||
private string _CommonOutputVoltage;
|
||||
public string CommonOutputVoltage
|
||||
{
|
||||
get { return _CommonOutputVoltage; }
|
||||
set { SetProperty(ref _CommonOutputVoltage, value); }
|
||||
}
|
||||
|
||||
private string _CommonOutputFrequency;
|
||||
public string CommonOutputFrequency
|
||||
{
|
||||
get { return _CommonOutputFrequency; }
|
||||
set { SetProperty(ref _CommonOutputFrequency, value); }
|
||||
}
|
||||
|
||||
private string _StepOutputVoltage;
|
||||
public string StepOutputVoltage
|
||||
{
|
||||
get { return _StepOutputVoltage; }
|
||||
set { SetProperty(ref _StepOutputVoltage, value); }
|
||||
}
|
||||
|
||||
private string _StepOutputFrequency;
|
||||
public string StepOutputFrequency
|
||||
{
|
||||
get { return _StepOutputFrequency; }
|
||||
set { SetProperty(ref _StepOutputFrequency, value); }
|
||||
}
|
||||
|
||||
private string _StepOutputVoltageGroup;
|
||||
public string StepOutputVoltageGroup
|
||||
{
|
||||
get { return _StepOutputVoltageGroup; }
|
||||
set { SetProperty(ref _StepOutputVoltageGroup, value); }
|
||||
}
|
||||
|
||||
private string _StepOutputFrequencyGroup;
|
||||
public string StepOutputFrequencyGroup
|
||||
{
|
||||
get { return _StepOutputFrequencyGroup; }
|
||||
set { SetProperty(ref _StepOutputFrequencyGroup, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand SetVoltageLevelLowCommand { get; private set; }
|
||||
public ICommand SetVoltageLevelHighCommand { get; private set; }
|
||||
public ICommand SetThreePhaseVoltageCommand { get; private set; }
|
||||
public ICommand SetCommonOutputVoltageCommand { get; private set; }
|
||||
public ICommand SetCommonOutputFrequencyCommand { get; private set; }
|
||||
public ICommand SetStepOutputVoltageCommand { get; private set; }
|
||||
public ICommand SetStepOutputFrequencyCommand { get; private set; }
|
||||
public ICommand OpenPowerSupplyCommand { get; private set; }
|
||||
public ICommand ClosePowerSupplyCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private SQ0030G1D device { get; set; }
|
||||
public SQ0030G1DViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
SetVoltageLevelLowCommand = new AsyncDelegateCommand(OnSetVoltageLevelLow);
|
||||
SetVoltageLevelHighCommand = new AsyncDelegateCommand(OnSetVoltageLevelHigh);
|
||||
SetThreePhaseVoltageCommand = new AsyncDelegateCommand(OnSetThreePhaseVoltage);
|
||||
SetCommonOutputVoltageCommand = new AsyncDelegateCommand(OnSetCommonOutputVoltage);
|
||||
SetCommonOutputFrequencyCommand = new AsyncDelegateCommand(OnSetCommonOutputFrequency);
|
||||
SetStepOutputVoltageCommand = new AsyncDelegateCommand(OnSetStepOutputVoltage);
|
||||
SetStepOutputFrequencyCommand = new AsyncDelegateCommand(OnSetStepOutputFrequency);
|
||||
ClosePowerSupplyCommand = new AsyncDelegateCommand(ClosePowerSupply);
|
||||
OpenPowerSupplyCommand = new AsyncDelegateCommand(OpenPowerSupply);
|
||||
}
|
||||
|
||||
#region Command Handlers
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
private async Task OpenPowerSupply()
|
||||
{
|
||||
await device.启动电源();
|
||||
}
|
||||
|
||||
private async Task ClosePowerSupply()
|
||||
{
|
||||
await device.关闭电源();
|
||||
}
|
||||
private async Task OnSetVoltageLevelLow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetVoltageLevelHigh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetThreePhaseVoltage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetCommonOutputVoltage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetCommonOutputFrequency()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetStepOutputVoltage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private async Task OnSetStepOutputFrequency()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["SQ0030G1D"] as SQ0030G1D;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
149
BOB/ViewModels/Dialogs/WS-68030-380TViewModel.cs
Normal file
149
BOB/ViewModels/Dialogs/WS-68030-380TViewModel.cs
Normal file
@ -0,0 +1,149 @@
|
||||
using BOB.Singleton;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using NetTaste;
|
||||
using Prism.Commands;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class WS_68030_380TViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
#region 属性
|
||||
|
||||
private string _title = "交流负载";
|
||||
public string Title
|
||||
{
|
||||
get { return _title; }
|
||||
set { SetProperty(ref _title, value); }
|
||||
}
|
||||
|
||||
private string _currentPowerDisplay;
|
||||
public string CurrentPowerDisplay
|
||||
{
|
||||
get { return _currentPowerDisplay; }
|
||||
set { SetProperty(ref _currentPowerDisplay, value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
|
||||
public ICommand ConnectCommand { get; private set; }
|
||||
public ICommand DisconnectCommand { get; private set; }
|
||||
public ICommand LoadCommand { get; private set; }
|
||||
public ICommand UnloadCommand { get; private set; }
|
||||
public ICommand ReadPowerCommand { get; private set; }
|
||||
public ICommand SetPowerCommand { get; private set; }
|
||||
public ICommand CloseCommand { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件聚合器和设备操作
|
||||
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private WS_68030_380T device { get; set; }
|
||||
|
||||
public WS_68030_380TViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
|
||||
// 初始化命令
|
||||
ConnectCommand = new AsyncDelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
LoadCommand = new AsyncDelegateCommand(OnLoad);
|
||||
UnloadCommand = new AsyncDelegateCommand(OnUnload);
|
||||
ReadPowerCommand = new AsyncDelegateCommand(OnReadPower);
|
||||
SetPowerCommand = new AsyncDelegateCommand(OnSetPower);
|
||||
CloseCommand = new DelegateCommand(OnClose);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令处理方法
|
||||
|
||||
private async Task OnConnect()
|
||||
{
|
||||
await device.ConnectAsync();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
device.Close();
|
||||
}
|
||||
|
||||
private async Task OnLoad()
|
||||
{
|
||||
await device.加载();
|
||||
}
|
||||
|
||||
private async Task OnUnload()
|
||||
{
|
||||
await device.卸载();
|
||||
}
|
||||
|
||||
private async Task OnReadPower()
|
||||
{
|
||||
var result = await device.读取功率_KW();
|
||||
}
|
||||
|
||||
private async Task OnSetPower()
|
||||
{
|
||||
if (float.TryParse(CurrentPowerDisplay, out float a))
|
||||
{
|
||||
await device.设置功率_KW(a);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dialog 规范
|
||||
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
var a = _devices.DeviceDic["WS_68030_380T"] as WS_68030_380T;
|
||||
if (a != null)
|
||||
{
|
||||
device = a;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("设备没有初始化无法打开测试界面");
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("找不到设备无法打开测试界面");
|
||||
}
|
||||
|
||||
}
|
||||
private void OnClose()
|
||||
{
|
||||
RequestClose.Invoke();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
57
BOB/ViewModels/Dialogs/ZXKSViewModel.cs
Normal file
57
BOB/ViewModels/Dialogs/ZXKSViewModel.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using BOB.Singleton;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BOB.ViewModels.Dialogs
|
||||
{
|
||||
public class ZXKSViewModel : BindableBase, IDialogAware
|
||||
{
|
||||
|
||||
#region 属性
|
||||
private string _Title = "环境箱";
|
||||
|
||||
public string Title
|
||||
{
|
||||
get { return _Title; }
|
||||
set { SetProperty(ref _Title, value); }
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
public ZXKSViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>();
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
|
||||
}
|
||||
|
||||
#region dialog规范
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
|
||||
public bool CanCloseDialog()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnDialogClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
58
BOB/ViewModels/LogAreaViewModel.cs
Normal file
58
BOB/ViewModels/LogAreaViewModel.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using BOB.Singleton;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using Prism.Mvvm;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class LogAreaViewModel : BindableBase
|
||||
{
|
||||
// 日志集合
|
||||
private ObservableCollection<LogItem> _logs = new();
|
||||
public ObservableCollection<LogItem> Logs
|
||||
{
|
||||
get => _logs;
|
||||
set => SetProperty(ref _logs, value);
|
||||
}
|
||||
public ICommand ClearLogCommand { get; set; }
|
||||
public Devices devices { get; set; }
|
||||
public LogAreaViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
devices=containerProvider.Resolve<Devices>();
|
||||
ClearLogCommand = new DelegateCommand(ClearLog);
|
||||
LoggerHelper.Progress = new System.Progress<(string message, string color,int depth)>(
|
||||
log =>
|
||||
{
|
||||
var brush = (Brush)new BrushConverter().ConvertFromString(log.color);
|
||||
Logs.Add(new LogItem(log.message, brush, log.depth));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void ClearLog()
|
||||
{
|
||||
Logs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 日志条目类
|
||||
public class LogItem
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Brush Color { get; set; } = Brushes.Black;
|
||||
public int Depth { get; set; }
|
||||
public LogItem(string message, Brush color, int depth = 0)
|
||||
{
|
||||
Message = new string(' ', depth * 20) + message;
|
||||
Color = color;
|
||||
Depth = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
86
BOB/ViewModels/MainViewModel.cs
Normal file
86
BOB/ViewModels/MainViewModel.cs
Normal file
@ -0,0 +1,86 @@
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using Common.PubEvents;
|
||||
using Logger;
|
||||
using NLog;
|
||||
using Prism.Dialogs;
|
||||
using Prism.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class MainViewModel : BindableBase,INavigationAware
|
||||
{
|
||||
#region 属性
|
||||
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
|
||||
|
||||
#endregion
|
||||
public DialogCloseListener RequestClose { get; set; }
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
private Devices _devices{ get; set; }
|
||||
public MainViewModel(IEventAggregator eventAggregator, IDialogService dialogService,IContainerProvider containerProvider)
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_devices=containerProvider.Resolve<Devices>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private async Task InitializeDevicesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_devices.Init(SystemConfig.Instance.DeviceList);
|
||||
await _devices.ConnectAllDevicesAsync();
|
||||
_devices.InitCan();
|
||||
_devices.StartPollingCollectionAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"设备连接异常: {ex.Message}", ex.StackTrace);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(false);
|
||||
}
|
||||
}
|
||||
#region 导航
|
||||
private bool _isInitialized = false;
|
||||
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
_eventAggregator.GetEvent<OverlayEvent>().Publish(true);
|
||||
_ = InitializeDevicesAsync();
|
||||
_isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
366
BOB/ViewModels/MonitorViewModel.cs
Normal file
366
BOB/ViewModels/MonitorViewModel.cs
Normal file
@ -0,0 +1,366 @@
|
||||
using BOB.Services;
|
||||
using BOB.Singleton;
|
||||
using Common.PubEvent;
|
||||
using Common.PubEvents;
|
||||
using Logger;
|
||||
using Microsoft.Win32;
|
||||
using OxyPlot;
|
||||
using OxyPlot.Axes;
|
||||
using OxyPlot.Legends;
|
||||
using OxyPlot.Series;
|
||||
using Prism.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class MonitorViewModel : BindableBase, INavigationAware
|
||||
{
|
||||
#region 属性
|
||||
private PlotModel _CurveModel=new();
|
||||
|
||||
public PlotModel CurveModel
|
||||
{
|
||||
get => _CurveModel;
|
||||
set => SetProperty(ref _CurveModel, value);
|
||||
}
|
||||
private Dictionary<string, LineSeries> _SeriesDic = new ();
|
||||
|
||||
public Dictionary<string,LineSeries> SeriesDic
|
||||
{
|
||||
get => _SeriesDic;
|
||||
set => SetProperty(ref _SeriesDic, value);
|
||||
}
|
||||
private string _FilePath;
|
||||
|
||||
public string FilePath
|
||||
{
|
||||
get => _FilePath;
|
||||
set => SetProperty(ref _FilePath, value);
|
||||
}
|
||||
private string _SelectCurve;
|
||||
|
||||
public string SelectCurve
|
||||
{
|
||||
get => _SelectCurve;
|
||||
set => SetProperty(ref _SelectCurve, value);
|
||||
}
|
||||
private string _SelectDeleteCurve;
|
||||
|
||||
public string SelectDeleteCurve
|
||||
{
|
||||
get => _SelectDeleteCurve;
|
||||
set => SetProperty(ref _SelectDeleteCurve, value);
|
||||
}
|
||||
private string _SelectedSaveDays;
|
||||
|
||||
public string SelectedSaveDays
|
||||
{
|
||||
get => _SelectedSaveDays;
|
||||
set => SetProperty(ref _SelectedSaveDays, value);
|
||||
}
|
||||
//private ObservableCollection<string> _CurSingleList=new();
|
||||
|
||||
public ObservableCollection<string> CurSingleList
|
||||
{
|
||||
get => SystemConfig.Instance.CurSingleList;
|
||||
set
|
||||
{
|
||||
if (SystemConfig.Instance.CurSingleList != value)
|
||||
{
|
||||
SystemConfig.Instance.CurSingleList = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
private ObservableCollection<string> _DeviceSingleList = new();
|
||||
|
||||
public ObservableCollection<string> DeviceSingleList
|
||||
{
|
||||
get => _DeviceSingleList;
|
||||
set => SetProperty(ref _DeviceSingleList, value);
|
||||
}
|
||||
#endregion
|
||||
#region 命令
|
||||
public ICommand ResetViewCommand { get; set; }
|
||||
public ICommand AddSignalCommand { get; set; }
|
||||
public ICommand RemoveSignalCommand { get; set; }
|
||||
public ICommand ChanegPathCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
|
||||
#endregion
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
private static Random _random = new Random();
|
||||
private DispatcherTimer _refreshTimer;
|
||||
private Devices _devices { get; set; }
|
||||
private readonly IProgress<(string name, double value)> _progress;
|
||||
public MonitorViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IContainerProvider containerProvider )
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_devices = containerProvider.Resolve<Devices>();
|
||||
ResetViewCommand = new DelegateCommand(ResetView);
|
||||
AddSignalCommand = new DelegateCommand<string>(AddSignal);
|
||||
RemoveSignalCommand = new DelegateCommand(RemoveSignal);
|
||||
ChanegPathCommand = new DelegateCommand(ChanegPath);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
_eventAggregator.GetEvent<CurveDataEvent>().Subscribe(OnCurveDataReceived);
|
||||
_progress = new Progress<(string name, double value)>(UpdateCurveOnUI);
|
||||
InitData();
|
||||
}
|
||||
private void UpdateCurveOnUI((string name, double value) update)
|
||||
{
|
||||
var (signalName, value) = update;
|
||||
|
||||
if (!SeriesDic.TryGetValue(signalName, out var line))
|
||||
return;
|
||||
|
||||
line.Points.Add(DateTimeAxis.CreateDataPoint(DateTime.Now, value));
|
||||
}
|
||||
|
||||
private async void OnCurveDataReceived((string device, Dictionary<string, double> data) tuple)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var (device, data) = tuple;
|
||||
foreach (var item in data)
|
||||
{
|
||||
string propname = item.Key;
|
||||
double value = item.Value;
|
||||
string signalName = device + "." + propname;
|
||||
|
||||
if (CurSingleList.Contains(signalName))
|
||||
{
|
||||
// 通过 Progress 安全更新 UI
|
||||
_progress.Report((signalName, value));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void InitData()
|
||||
{
|
||||
SelectedSaveDays=SystemConfig.Instance.SaveDay.ToString();
|
||||
FilePath= SystemConfig.Instance.DBSavePath;
|
||||
foreach (var _PollingRead in _devices.PollingReadDic)
|
||||
{
|
||||
string deviceName = _PollingRead.Key;
|
||||
PollingRead pollingRead = _PollingRead.Value;
|
||||
|
||||
var props = pollingRead.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.Where(p => p.PropertyType == typeof(double));
|
||||
|
||||
foreach (var prop in props)
|
||||
{
|
||||
DeviceSingleList.Add(deviceName + "." + prop.Name);
|
||||
}
|
||||
}
|
||||
foreach(var curve in CurSingleList)
|
||||
{
|
||||
AddSignal(curve);
|
||||
}
|
||||
InitCurveModel();
|
||||
InitTimer();
|
||||
}
|
||||
private void InitCurveModel()
|
||||
{
|
||||
CurveModel.Axes.Clear();
|
||||
|
||||
var timeAxis = new DateTimeAxis
|
||||
{
|
||||
Position = AxisPosition.Bottom,
|
||||
StringFormat = "HH:mm:ss",
|
||||
Title = "时间",
|
||||
IntervalType = DateTimeIntervalType.Seconds
|
||||
};
|
||||
CurveModel.Axes.Add(timeAxis);
|
||||
|
||||
var valueAxis = new LinearAxis
|
||||
{
|
||||
Position = AxisPosition.Left,
|
||||
Title = "数值"
|
||||
};
|
||||
CurveModel.Axes.Add(valueAxis);
|
||||
}
|
||||
|
||||
private void InitTimer()
|
||||
{
|
||||
_refreshTimer = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
_refreshTimer.Tick += (s, e) =>
|
||||
{
|
||||
CurveModel.InvalidatePlot(true);
|
||||
};
|
||||
_refreshTimer.Start();
|
||||
}
|
||||
|
||||
|
||||
private OxyColor GetRandomColor()
|
||||
{
|
||||
// 生成随机的红色、绿色、蓝色分量,范围是 0 到 255
|
||||
byte r = (byte)_random.Next(0, 256);
|
||||
byte g = (byte)_random.Next(0, 256);
|
||||
byte b = (byte)_random.Next(0, 256);
|
||||
|
||||
// 返回一个随机的颜色
|
||||
return OxyColor.FromRgb(r, g, b);
|
||||
}
|
||||
|
||||
private void AddSignal(string Curve="")
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Curve == null)
|
||||
{
|
||||
if (_SeriesDic.ContainsKey(SelectCurve))
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sineSignal = new LineSeries
|
||||
{
|
||||
Title = SelectCurve,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 2,
|
||||
Color = GetRandomColor()
|
||||
};
|
||||
CurveModel.Series.Add(sineSignal);
|
||||
CurveModel.Legends.Add(new Legend
|
||||
{
|
||||
LegendPosition = LegendPosition.TopCenter, // 图表顶部中间
|
||||
LegendOrientation = LegendOrientation.Horizontal, // 横向排列
|
||||
LegendPlacement = LegendPlacement.Inside, // 放在图上面
|
||||
LegendBorderThickness = 0, // 去掉边框,可选
|
||||
LegendBackground = OxyColors.WhiteSmoke // 背景色,可选
|
||||
});
|
||||
|
||||
SeriesDic.Add(SelectCurve, sineSignal);
|
||||
CurSingleList.Add(SelectCurve);
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var sineSignal = new LineSeries
|
||||
{
|
||||
Title = Curve,
|
||||
MarkerType = MarkerType.Circle,
|
||||
StrokeThickness = 2,
|
||||
Color = GetRandomColor()
|
||||
};
|
||||
CurveModel.Series.Add(sineSignal);
|
||||
CurveModel.Legends.Add(new Legend
|
||||
{
|
||||
LegendPosition = LegendPosition.TopCenter, // 图表顶部中间
|
||||
LegendOrientation = LegendOrientation.Horizontal, // 横向排列
|
||||
LegendPlacement = LegendPlacement.Inside, // 放在图上面
|
||||
LegendBorderThickness = 0, // 去掉边框,可选
|
||||
LegendBackground = OxyColors.WhiteSmoke // 背景色,可选
|
||||
});
|
||||
|
||||
SeriesDic.Add(Curve, sineSignal);
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("添加曲线失败", ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void RemoveSignal()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_SeriesDic.ContainsKey(SelectDeleteCurve))
|
||||
{
|
||||
var signalToRemove = _SeriesDic[SelectDeleteCurve];
|
||||
_SeriesDic.Remove(SelectDeleteCurve);
|
||||
CurveModel.Series.Remove(signalToRemove);
|
||||
CurSingleList.Remove(SelectDeleteCurve);
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("删除曲线失败",ex.StackTrace);
|
||||
}
|
||||
}
|
||||
private void Save()
|
||||
{
|
||||
SelectedSaveDays = SelectedSaveDays ?? "30";
|
||||
if (int.TryParse(SelectedSaveDays, out int saveDays))
|
||||
{
|
||||
if (saveDays > 0 && saveDays <= 30)
|
||||
{
|
||||
Console.WriteLine($"保存天数: {saveDays}");
|
||||
}
|
||||
else
|
||||
{
|
||||
//_dialogService.ShowDialog("请输入1到30之间的有效天数。", "无效输入");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//_dialogService.ShowDialog("请输入有效的数字。", "无效输入");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void ChanegPath()
|
||||
{
|
||||
var openFileDialog = new OpenFileDialog
|
||||
{
|
||||
CheckFileExists = false,
|
||||
CheckPathExists = true,
|
||||
FileName = "Folder",
|
||||
ValidateNames = false,
|
||||
Filter = "All files (*.*)|*.*"
|
||||
};
|
||||
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
{
|
||||
FilePath = System.IO.Path.GetDirectoryName(openFileDialog.FileName);
|
||||
SystemConfig.Instance.DBSavePath = FilePath;
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void ResetView()
|
||||
{
|
||||
CurveModel.ResetAllAxes();
|
||||
CurveModel.InvalidatePlot(true);
|
||||
}
|
||||
#region 导航
|
||||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool IsNavigationTarget(NavigationContext navigationContext)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnNavigatedFrom(NavigationContext navigationContext)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
365
BOB/ViewModels/ParametersManagerViewModel.cs
Normal file
365
BOB/ViewModels/ParametersManagerViewModel.cs
Normal file
@ -0,0 +1,365 @@
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using BOB.Views.Dialogs;
|
||||
using Common.PubEvent;
|
||||
using DeviceCommand.Base;
|
||||
using DeviceCommand.Device;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Model;
|
||||
using OxyPlot;
|
||||
using Prism.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class ParametersManagerViewModel:BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private ObservableCollection<DeviceConfigModel> _DeviceList;
|
||||
|
||||
public ObservableCollection<DeviceConfigModel> DeviceList
|
||||
{
|
||||
get { return _DeviceList; }
|
||||
set { SetProperty(ref _DeviceList,value); }
|
||||
}
|
||||
private ObservableCollection<DeviceInfoModel> _DeviceInfoModel;
|
||||
|
||||
public ObservableCollection<DeviceInfoModel> DeviceInfoModel
|
||||
{
|
||||
get { return _DeviceInfoModel; }
|
||||
set { SetProperty(ref _DeviceInfoModel, value); }
|
||||
}
|
||||
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _globalVariables.Program;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.Program != value)
|
||||
{
|
||||
_globalVariables.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
private ParameterModel _SelectedParameter;
|
||||
public ParameterModel SelectedParameter
|
||||
{
|
||||
get => _SelectedParameter;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectedParameter, value))
|
||||
{
|
||||
_globalVariables.SelectedParameter = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private DeviceInfoModel _SelectedDevice;
|
||||
public DeviceInfoModel SelectedDevice
|
||||
{
|
||||
get { return _SelectedDevice; }
|
||||
set { SetProperty(ref _SelectedDevice, value); }
|
||||
}
|
||||
#endregion
|
||||
private GlobalVariables _globalVariables { get; set; }
|
||||
private IDialogService _dialogService { get; set; }
|
||||
private IContainerProvider _containerProvider { get; set; }
|
||||
private Devices _devices { get; set; }
|
||||
private IEventAggregator _eventAggregator { get; set; }
|
||||
public ICommand ParameterAddCommand { get; set; }
|
||||
public ICommand ParameterEditCommand { get; set; }
|
||||
public ICommand ParameterDeleteCommand { get; set; }
|
||||
public ICommand DeviceEditCommand { get; set; }
|
||||
public ICommand ReconnnectCommand { get; set; }
|
||||
public ICommand CloseCommand { get; set; }
|
||||
|
||||
|
||||
|
||||
public ParametersManagerViewModel(GlobalVariables GlobalVariables,IDialogService dialogService,IEventAggregator eventAggregator,IContainerProvider containerProvider)
|
||||
{
|
||||
_containerProvider= containerProvider;
|
||||
_globalVariables = GlobalVariables;
|
||||
_eventAggregator= eventAggregator;
|
||||
_devices=containerProvider.Resolve<Devices>();
|
||||
_dialogService = dialogService;
|
||||
Program = _globalVariables.Program;
|
||||
ParameterAddCommand = new DelegateCommand(ParameterAdd);
|
||||
ParameterEditCommand = new DelegateCommand(ParameterEdit);
|
||||
ParameterDeleteCommand = new DelegateCommand(ParameterDelete);
|
||||
DeviceEditCommand = new DelegateCommand(DeviceEdit);
|
||||
ReconnnectCommand = new DelegateCommand(Reconnnect);
|
||||
CloseCommand = new DelegateCommand(Close);
|
||||
DeviceList = new ObservableCollection<DeviceConfigModel>(SystemConfig.Instance.DeviceList);
|
||||
InitData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void InitData()
|
||||
{
|
||||
DeviceInfoModel = new ObservableCollection<DeviceInfoModel>();
|
||||
for (int i = 0; i < DeviceList.Count; i++)
|
||||
{
|
||||
DeviceInfoModel.Add(new DeviceInfoModel
|
||||
{
|
||||
DeviceName = DeviceList[i].DeviceName,
|
||||
Remark = DeviceList[i].Remark,
|
||||
IsConnected = false,
|
||||
IsEnabled= DeviceList[i].IsEnabled,
|
||||
DeviceType= DeviceList[i].DeviceType,
|
||||
CommunicationConfig= DeviceList[i].CommunicationConfig
|
||||
});
|
||||
}
|
||||
|
||||
var progress = new Progress<(int index, bool isConnected)>();
|
||||
progress.ProgressChanged += (s, e) =>
|
||||
{
|
||||
DeviceInfoModel[e.index].IsConnected = e.isConnected;
|
||||
};
|
||||
|
||||
var token = _devices.AppCancellationToken;
|
||||
Task.Run(() => PollingConnection(progress, token));
|
||||
}
|
||||
|
||||
private async Task PollingConnection(IProgress<(int index, bool isConnected)> progress, CancellationToken token)
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
for (int i = 0; i < DeviceList.Count; i++)
|
||||
{
|
||||
bool isConnected = false;
|
||||
|
||||
if (_devices.DeviceDic.TryGetValue(DeviceList[i].Remark, out var device) && device != null)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case ITcp tcpDevice:
|
||||
isConnected = tcpDevice.TcpClient?.Connected ?? false;
|
||||
break;
|
||||
|
||||
case ISerialPort serialDevice:
|
||||
isConnected = serialDevice.SerialPort?.IsOpen ?? false;
|
||||
break;
|
||||
|
||||
case IModbusDevice modbusDevice:
|
||||
isConnected = (modbusDevice.TcpClient?.Connected ?? false) || (modbusDevice.SerialPort?.IsOpen ?? false);
|
||||
break;
|
||||
default:
|
||||
if (device is Backfeed backfeed)
|
||||
{
|
||||
if (backfeed.CurrentDevice == "E36233A")
|
||||
{
|
||||
var e36233A = backfeed.CurrentInstance as E36233A;
|
||||
if (e36233A != null)
|
||||
{
|
||||
isConnected = e36233A.TcpClient?.Connected ?? false;
|
||||
}
|
||||
}
|
||||
else if (backfeed.CurrentDevice == "IT6724CReverse")
|
||||
{
|
||||
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
|
||||
if (it6724CReverse != null)
|
||||
{
|
||||
isConnected = it6724CReverse.SerialPort?.IsOpen ?? false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
_eventAggregator.GetEvent<ConnectionChangeEvent>().Publish((DeviceList[i].Remark, isConnected));
|
||||
}
|
||||
|
||||
progress.Report((i, isConnected));
|
||||
}
|
||||
|
||||
await Task.Delay(200, token); // 支持取消
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region 委托命令
|
||||
|
||||
|
||||
|
||||
private void DeviceEdit()
|
||||
{
|
||||
if(SelectedDevice==null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var type = SelectedDevice.DeviceType.Split('.').Last();
|
||||
if(type=="E36233A"|| type == "IT6724CReverse")
|
||||
{
|
||||
_dialogService.Show("Backfeed");
|
||||
}
|
||||
else
|
||||
{
|
||||
_dialogService.Show(type);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParameterDelete()
|
||||
{
|
||||
Program.Parameters.Remove(SelectedParameter);
|
||||
}
|
||||
|
||||
private void ParameterEdit()
|
||||
{
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode",SelectedParameter==null?"ADD":"Edit" }
|
||||
};
|
||||
_dialogService.ShowDialog("ParameterSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ParameterAdd()
|
||||
{
|
||||
var param = new DialogParameters
|
||||
{
|
||||
{ "Mode", "ADD" }
|
||||
};
|
||||
_dialogService.ShowDialog("ParameterSetting", param, (r) =>
|
||||
{
|
||||
if (r.Result == ButtonResult.OK)
|
||||
{
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Publish();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
private void Close()
|
||||
{
|
||||
if (SelectedDevice != null)
|
||||
{
|
||||
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case ITcp tcpDevice:
|
||||
tcpDevice.Close();
|
||||
break;
|
||||
|
||||
case ISerialPort serialDevice:
|
||||
serialDevice.Close();
|
||||
break;
|
||||
|
||||
case IModbusDevice modbusDevice:
|
||||
modbusDevice.Close();
|
||||
break;
|
||||
default:
|
||||
if (device is Backfeed backfeed)
|
||||
{
|
||||
if (backfeed.CurrentDevice == "E36233A")
|
||||
{
|
||||
var e36233A = backfeed.CurrentInstance as E36233A;
|
||||
if (e36233A != null)
|
||||
{
|
||||
e36233A.Close();
|
||||
}
|
||||
}
|
||||
else if (backfeed.CurrentDevice == "IT6724CReverse")
|
||||
{
|
||||
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
|
||||
if (it6724CReverse != null)
|
||||
{
|
||||
it6724CReverse.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Reconnnect()
|
||||
{
|
||||
if (SelectedDevice != null)
|
||||
{
|
||||
if (_devices.DeviceDic.TryGetValue(SelectedDevice.Remark, out var device) && device != null)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case ITcp tcpDevice:
|
||||
await tcpDevice.ConnectAsync();
|
||||
|
||||
break;
|
||||
|
||||
case ISerialPort serialDevice:
|
||||
await serialDevice.ConnectAsync();
|
||||
break;
|
||||
|
||||
case IModbusDevice modbusDevice:
|
||||
await modbusDevice.ConnectAsync();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (device is Backfeed backfeed)
|
||||
{
|
||||
if (backfeed.CurrentDevice == "E36233A")
|
||||
{
|
||||
var e36233A = backfeed.CurrentInstance as E36233A;
|
||||
if (e36233A != null)
|
||||
{
|
||||
await e36233A.ConnectAsync();
|
||||
}
|
||||
}
|
||||
else if (backfeed.CurrentDevice == "IT6724CReverse")
|
||||
{
|
||||
var it6724CReverse = backfeed.CurrentInstance as IT6724CReverse;
|
||||
if (it6724CReverse != null)
|
||||
{
|
||||
await it6724CReverse.ConnectAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"设备重连时发生错误: {SelectedDevice.Remark} - {ex.Message}", ex.StackTrace);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
432
BOB/ViewModels/ShellViewModel.cs
Normal file
432
BOB/ViewModels/ShellViewModel.cs
Normal file
@ -0,0 +1,432 @@
|
||||
using BOB.Models;
|
||||
using BOB.Singleton;
|
||||
using BOB.Views;
|
||||
using CAN驱动;
|
||||
using Common.PubEvent;
|
||||
using Logger;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Microsoft.Win32;
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class ShellViewModel : BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private string _Title="";
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _Title;
|
||||
set => SetProperty(ref _Title, value);
|
||||
}
|
||||
private bool _IsLeftDrawerOpen;
|
||||
|
||||
public bool IsLeftDrawerOpen
|
||||
{
|
||||
get => _IsLeftDrawerOpen;
|
||||
set => SetProperty(ref _IsLeftDrawerOpen, value);
|
||||
}
|
||||
private bool _IsTerminate=false;
|
||||
|
||||
public bool IsTerminate
|
||||
{
|
||||
get => _IsTerminate;
|
||||
set => SetProperty(ref _IsTerminate, value);
|
||||
}
|
||||
|
||||
public String RunState
|
||||
{
|
||||
get => _globalVariables.RunState;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.RunState != value)
|
||||
{
|
||||
_globalVariables.RunState = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool SingleStep
|
||||
{
|
||||
get => _globalVariables.SingleStep;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.SingleStep != value)
|
||||
{
|
||||
_globalVariables.SingleStep = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PackIconKind RunIcon
|
||||
{
|
||||
get => _globalVariables.RunIcon;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.RunIcon != value)
|
||||
{
|
||||
_globalVariables.RunIcon = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 命令
|
||||
public ICommand LeftDrawerOpenCommand { get; set; }
|
||||
public ICommand MinimizeCommand { get; set; }
|
||||
public ICommand MaximizeCommand { get; set; }
|
||||
public ICommand CloseCommand { get; set; }
|
||||
public ICommand RunningCommand { get; set; }
|
||||
public ICommand RunSingleCommand { get; set; }
|
||||
public ICommand ResotrationCommand { get; set; }
|
||||
public ICommand StopCommand { get; set; }
|
||||
public ICommand SaveAsCommand { get; set; }
|
||||
public ICommand SaveCommand { get; set; }
|
||||
public ICommand OpenCommand { get; set; }
|
||||
public ICommand NewCommand { get; set; }
|
||||
public ICommand SetDefaultCommand { get; set; }
|
||||
public ICommand LoadCommand { get; set; }
|
||||
public ICommand NavigateCommand { get; set; }
|
||||
public ICommand SettingChannelCommand { get; set; }
|
||||
public ICommand NavigateToCanPageCommand { get; set; }
|
||||
#endregion
|
||||
|
||||
private IEventAggregator _eventAggregator;
|
||||
private GlobalVariables _globalVariables;
|
||||
private IContainerProvider _containerProvider;
|
||||
private IRegionManager _regionManager;
|
||||
private StepRunning _stepRunning;
|
||||
private IDialogService _dialogService;
|
||||
private Task? currentExecutionTask;
|
||||
public ShellViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
_eventAggregator = containerProvider.Resolve<IEventAggregator>(); ;
|
||||
_containerProvider = containerProvider;
|
||||
_globalVariables = containerProvider.Resolve<GlobalVariables>(); ;
|
||||
_regionManager = containerProvider.Resolve<IRegionManager>(); ;
|
||||
_dialogService= containerProvider.Resolve<IDialogService>();
|
||||
_stepRunning = containerProvider.Resolve<StepRunning>(); ;
|
||||
LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
|
||||
MinimizeCommand = new DelegateCommand<Window>(MinimizeWindow);
|
||||
MaximizeCommand = new DelegateCommand<Window>(MaximizeWindow);
|
||||
CloseCommand = new DelegateCommand<Window>(CloseWindow);
|
||||
RunningCommand = new DelegateCommand(Running);
|
||||
RunSingleCommand = new DelegateCommand(RunSingle);
|
||||
ResotrationCommand = new DelegateCommand(Resotration);
|
||||
StopCommand = new DelegateCommand(Stop);
|
||||
NewCommand = new DelegateCommand(New);
|
||||
OpenCommand = new DelegateCommand<string>(Open);
|
||||
SaveAsCommand = new DelegateCommand(SaveAs);
|
||||
SaveCommand = new DelegateCommand(Save);
|
||||
SetDefaultCommand = new DelegateCommand(SetDefault);
|
||||
LoadCommand = new DelegateCommand(Load);
|
||||
NavigateCommand = new DelegateCommand<string>(Navigate);
|
||||
SettingChannelCommand = new DelegateCommand(SettingChannel);
|
||||
NavigateToCanPageCommand = new DelegateCommand(NavigateToCanPage);
|
||||
_eventAggregator.GetEvent<UpdateIconEvent>().Subscribe(UpdateRunIcon);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region ToolBar命令
|
||||
private bool isConnect = false;
|
||||
|
||||
private void SettingChannel()
|
||||
{
|
||||
var re = 同星驱动类.ShowChannelMappingWindow(true);
|
||||
if (re != 0)
|
||||
{
|
||||
var msg = 同星驱动类.GetErrorDescription(re);
|
||||
LoggerHelper.ErrorWithNotify($"同星通道映射界面打开失败:{msg}");
|
||||
}
|
||||
}
|
||||
private void NavigateToCanPage()
|
||||
{
|
||||
_dialogService.Show("CAN");
|
||||
}
|
||||
private void Navigate(string content)
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case "程序界面":
|
||||
_regionManager.RequestNavigate("ShellViewManager", "MainView");
|
||||
break;
|
||||
|
||||
case "监控界面":
|
||||
_regionManager.RequestNavigate("ShellViewManager", "MonitorView");
|
||||
break;
|
||||
|
||||
case "数据管理":
|
||||
_regionManager.RequestNavigate("ShellViewManager", "DataView");
|
||||
break;
|
||||
|
||||
case "更新信息":
|
||||
_regionManager.RequestNavigate("ShellViewManager", "UpdateInfoView");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void SetDefault()
|
||||
{
|
||||
if(_globalVariables.CurrentFilePath!=null)
|
||||
{
|
||||
SystemConfig.Instance.DefaultSubProgramFilePath = _globalVariables.CurrentFilePath;
|
||||
SystemConfig.Instance.SaveToFile();
|
||||
}
|
||||
}
|
||||
private void New()
|
||||
{
|
||||
_globalVariables.CurrentFilePath = null;
|
||||
_globalVariables.Program.Parameters.Clear();
|
||||
_globalVariables.Program.StepCollection.Clear();
|
||||
}
|
||||
|
||||
private void Open(string filePath = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 如果没有传路径,弹出文件选择对话框
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
var openFileDialog = new OpenFileDialog
|
||||
{
|
||||
Filter = "BOB程序文件|*.bob|所有文件|*.*",
|
||||
Title = "打开程序",
|
||||
InitialDirectory = @"D:\BOB\子程序"
|
||||
};
|
||||
|
||||
if (openFileDialog.ShowDialog() != true)
|
||||
return; // 用户取消选择
|
||||
|
||||
filePath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
// 确认文件存在
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"文件不存在: {filePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 读取 JSON 文件
|
||||
string json = File.ReadAllText(filePath);
|
||||
|
||||
// 反序列化为 ProgramModel
|
||||
var program = JsonConvert.DeserializeObject<ProgramModel>(json);
|
||||
|
||||
if (program == null)
|
||||
{
|
||||
LoggerHelper.WarnWithNotify($"文件格式不正确或为空: {filePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
_globalVariables.Program.Parameters = program.Parameters;
|
||||
_globalVariables.Program.StepCollection = program.StepCollection;
|
||||
_globalVariables.CurrentFilePath = filePath;
|
||||
LoggerHelper.SuccessWithNotify($"成功打开文件: {filePath}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"打开文件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
private void SaveAs()
|
||||
{
|
||||
string defaultPath = @"D:\BOB\子程序";
|
||||
|
||||
// 如果目录不存在,可以自动创建
|
||||
if (!Directory.Exists(defaultPath))
|
||||
Directory.CreateDirectory(defaultPath);
|
||||
|
||||
var saveFileDialog = new SaveFileDialog
|
||||
{
|
||||
Filter = "BOB程序文件|*.bob|所有文件|*.*",
|
||||
Title = "另存为",
|
||||
FileName = "NewProgram.bob",
|
||||
InitialDirectory = defaultPath // ✅ 默认打开这个文件夹
|
||||
};
|
||||
if (saveFileDialog.ShowDialog() == true)
|
||||
{
|
||||
_globalVariables.CurrentFilePath = saveFileDialog.FileName;
|
||||
SaveProgramToFile(_globalVariables.CurrentFilePath);
|
||||
// 记录日志
|
||||
LoggerHelper.InfoWithNotify($"{_globalVariables.UserName} 另存为文件成功: {saveFileDialog.FileName}");
|
||||
}
|
||||
|
||||
}
|
||||
private void SaveProgramToFile(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tmp = ClearDeviceParameterValue(_globalVariables.Program);
|
||||
string json = JsonConvert.SerializeObject(tmp, Formatting.Indented);
|
||||
File.WriteAllText(filePath, json);
|
||||
LoggerHelper.SuccessWithNotify($"程序已保存: {filePath}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify($"保存文件失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
private ProgramModel ClearDeviceParameterValue(ProgramModel program)
|
||||
{
|
||||
var tmp = new ProgramModel(program);
|
||||
foreach (var step in tmp.StepCollection)
|
||||
{
|
||||
if (step.SubProgram != null)
|
||||
{
|
||||
step.SubProgram = ClearDeviceParameterValue(step.SubProgram);
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private void Save()
|
||||
{
|
||||
if(_globalVariables.CurrentFilePath == null)
|
||||
{
|
||||
SaveAs();
|
||||
return;
|
||||
}
|
||||
SaveProgramToFile(_globalVariables.CurrentFilePath);
|
||||
|
||||
}
|
||||
private void Stop()
|
||||
{
|
||||
if (_globalVariables.IsStop == false)
|
||||
{
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行停止命令");
|
||||
IsTerminate = true;
|
||||
_globalVariables.IsStop = null;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_stepRunning.stepCTS.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void Resotration()
|
||||
{
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行复位命令");
|
||||
IsTerminate = false;
|
||||
currentExecutionTask = null;
|
||||
_stepRunning.stepCTS = new();
|
||||
_globalVariables.IsStop = null;
|
||||
_stepRunning.ResetAllStepStatus(_globalVariables.Program);
|
||||
}
|
||||
|
||||
private async void RunSingle()
|
||||
{
|
||||
if (RunState == "运行")
|
||||
{
|
||||
SingleStep = true;
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行单步执行命令");
|
||||
RunState = "暂停";
|
||||
RunIcon = PackIconKind.Pause;
|
||||
if (_globalVariables.IsStop == null)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
if(currentExecutionTask==null)currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
await currentExecutionTask;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_globalVariables.IsStop = null;
|
||||
IsTerminate = true;
|
||||
}
|
||||
else if (_globalVariables.IsStop == true)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void Running()
|
||||
{
|
||||
|
||||
if (RunState == "运行")
|
||||
{
|
||||
SingleStep = false;
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "执行运行命令");
|
||||
RunState = "暂停";
|
||||
RunIcon = PackIconKind.Pause;
|
||||
if (_globalVariables.IsStop == null)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
if (currentExecutionTask == null) currentExecutionTask = _stepRunning.ExecuteSteps(_globalVariables.Program, cancellationToken: _stepRunning.stepCTS.Token);
|
||||
await currentExecutionTask;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
_globalVariables.IsStop = null;
|
||||
IsTerminate = true;
|
||||
}
|
||||
else if (_globalVariables.IsStop == true)
|
||||
{
|
||||
_globalVariables.IsStop = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.InfoWithNotify(_globalVariables.UserName + "点击暂停命令");
|
||||
_globalVariables.IsStop = true;
|
||||
RunState = "运行";
|
||||
RunIcon = PackIconKind.Play;
|
||||
}
|
||||
}
|
||||
|
||||
private void LeftDrawerOpen()
|
||||
{
|
||||
IsLeftDrawerOpen = true;
|
||||
}
|
||||
private void MinimizeWindow(Window window)
|
||||
{
|
||||
if (window != null)
|
||||
window.WindowState = WindowState.Minimized;
|
||||
}
|
||||
|
||||
private void MaximizeWindow(Window window)
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseWindow(Window window)
|
||||
{
|
||||
window?.Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void UpdateRunIcon(string obj)
|
||||
{
|
||||
RunIcon = obj switch
|
||||
{
|
||||
"Play" => PackIconKind.Play,
|
||||
"Pause" => PackIconKind.Pause,
|
||||
_ => RunIcon
|
||||
};
|
||||
}
|
||||
private void Load()
|
||||
{
|
||||
SystemConfig.Instance.LoadFromFile();
|
||||
if (SystemConfig.Instance.DefaultSubProgramFilePath != null)
|
||||
{
|
||||
if (File.Exists(SystemConfig.Instance.DefaultSubProgramFilePath))
|
||||
{
|
||||
Open(SystemConfig.Instance.DefaultSubProgramFilePath);
|
||||
}
|
||||
}
|
||||
Title = SystemConfig.Instance.Title;
|
||||
}
|
||||
}
|
||||
}
|
||||
195
BOB/ViewModels/SingleStepEditViewModel.cs
Normal file
195
BOB/ViewModels/SingleStepEditViewModel.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using Logger;
|
||||
using Microsoft.IdentityModel.Logging;
|
||||
using SqlSugar.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class SingleStepEditViewModel:BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private Guid _ID;
|
||||
public Guid ID
|
||||
{
|
||||
get => _ID;
|
||||
set => SetProperty(ref _ID, value);
|
||||
}
|
||||
private StepModel _SelectedStep;
|
||||
public StepModel SelectedStep
|
||||
{
|
||||
get => _SelectedStep;
|
||||
set => SetProperty(ref _SelectedStep, value);
|
||||
}
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _globalVariables.Program;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.Program != value)
|
||||
{
|
||||
_globalVariables.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
private GlobalVariables _globalVariables;
|
||||
private IEventAggregator _eventAggregator;
|
||||
private IDialogService _dialogService;
|
||||
public ICommand CancelEditCommand { get; set; }
|
||||
public ICommand SaveStepCommand { get; set; }
|
||||
public SingleStepEditViewModel(GlobalVariables globalVariables,IEventAggregator eventAggregator,IDialogService dialogService)
|
||||
{
|
||||
_globalVariables= globalVariables;
|
||||
_eventAggregator= eventAggregator;
|
||||
_dialogService = dialogService;
|
||||
_eventAggregator.GetEvent<EditSetpEvent>().Subscribe(EditSingleSetp);
|
||||
CancelEditCommand = new DelegateCommand(CancelEdit);
|
||||
SaveStepCommand = new DelegateCommand(SaveStep);
|
||||
_eventAggregator.GetEvent<DeletedStepEvent>().Subscribe(DisposeSelectedStep);
|
||||
_eventAggregator.GetEvent<ParamsChangedEvent>().Subscribe(ParamsChanged);
|
||||
}
|
||||
|
||||
private void ParamsChanged()
|
||||
{
|
||||
CancelEdit();
|
||||
}
|
||||
|
||||
private void DisposeSelectedStep(Guid id)
|
||||
{
|
||||
if (SelectedStep == null) return;
|
||||
if(id== SelectedStep.ID)
|
||||
SelectedStep = null;
|
||||
}
|
||||
|
||||
private void CancelEdit()
|
||||
{
|
||||
SelectedStep = null;
|
||||
}
|
||||
|
||||
private void SaveStep()
|
||||
{
|
||||
if (SelectedStep == null || (SelectedStep.Method == null && SelectedStep.SubProgram == null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var steps = _globalVariables.Program.StepCollection;
|
||||
int index = steps.ToList().FindIndex(x => x.ID == ID);
|
||||
if (index >= 0)
|
||||
{
|
||||
steps[index] = SelectedStep;
|
||||
if (steps[index].Method != null)
|
||||
{
|
||||
if (steps[index].StepType == "循环开始")
|
||||
{
|
||||
try
|
||||
{
|
||||
steps[index].LoopCount = Convert.ToInt32(SelectedStep.Method!.Parameters[0].Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
LoggerHelper.ErrorWithNotify("循环指令参数设置错误:类型转换失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].Method.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.Method!.Parameters[i];
|
||||
var originalParam = steps[index].Method.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _globalVariables.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
else if (steps[index].SubProgram != null)
|
||||
{
|
||||
if (SelectedStep.SubProgram.Parameters.Where(x => x.VariableName == null && x.IsUseVar == true).FirstOrDefault() != null)
|
||||
{
|
||||
var parameters1 = new DialogParameters
|
||||
{
|
||||
{ "Title", "警告" },
|
||||
{ "Message", "选中变量不得为空!" },
|
||||
{ "Icon", "warn" },
|
||||
{ "ShowOk", true },
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox",parameters1);
|
||||
return;
|
||||
}
|
||||
(steps[index].OKGotoStepID, steps[index].NGGotoStepID) = GetOKNGGotoStepID(SelectedStep.GotoSettingString);
|
||||
for (int i = 0; i < steps[index].SubProgram.Parameters.Count; i++)
|
||||
{
|
||||
var editedParam = SelectedStep.SubProgram!.Parameters[i];
|
||||
var originalParam = steps[index].SubProgram.Parameters[i];
|
||||
if (editedParam.IsUseVar)
|
||||
{
|
||||
originalParam.VariableName = editedParam.VariableName;
|
||||
originalParam.VariableID = _globalVariables.Program.Parameters.FirstOrDefault(x => x.Name == editedParam.VariableName)!.ID;
|
||||
}
|
||||
originalParam.Value = editedParam.Value;
|
||||
originalParam.IsUseVar = editedParam.IsUseVar;
|
||||
originalParam.LowerLimit = editedParam.LowerLimit;
|
||||
originalParam.UpperLimit = editedParam.UpperLimit;
|
||||
}
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
{ "Title", "提示" },
|
||||
{ "Message", "保存成功!" },
|
||||
{ "Icon", "info" },
|
||||
{ "ShowOk", true }
|
||||
};
|
||||
_dialogService.ShowDialog("MessageBox", parameters);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private (Guid,Guid) GetOKNGGotoStepID(string GotoSettingString)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(GotoSettingString))
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
|
||||
var match = Regex.Match(GotoSettingString, @"^(\d+)\s*/\s*(\d+)$");
|
||||
if (match.Success)
|
||||
{
|
||||
int ok = int.Parse(match.Groups[1].Value);
|
||||
int ng = int.Parse(match.Groups[2].Value);
|
||||
|
||||
Guid okGuid = _globalVariables.Program.StepCollection.ElementAtOrDefault(ok-1)?.ID ?? Guid.Empty;
|
||||
Guid ngGuid = _globalVariables.Program.StepCollection.ElementAtOrDefault(ng-1)?.ID ?? Guid.Empty;
|
||||
|
||||
return (okGuid, ngGuid);
|
||||
}
|
||||
return (Guid.Empty, Guid.Empty);
|
||||
}
|
||||
private void EditSingleSetp()
|
||||
{
|
||||
ID = _globalVariables.SelectedStep.ID;
|
||||
SelectedStep = new StepModel(_globalVariables.SelectedStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
143
BOB/ViewModels/StepsManagerViewModel.cs
Normal file
143
BOB/ViewModels/StepsManagerViewModel.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using BOB.Models;
|
||||
using Common.PubEvent;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Xml;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class StepsManagerViewModel:BindableBase
|
||||
{
|
||||
#region 属性
|
||||
private string _Title;
|
||||
public string Title
|
||||
{
|
||||
get => _Title;
|
||||
set => SetProperty(ref _Title, value);
|
||||
}
|
||||
private StepModel _SelectedStep;
|
||||
public StepModel SelectedStep
|
||||
{
|
||||
get => _SelectedStep;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _SelectedStep, value))
|
||||
{
|
||||
_globalVariables.SelectedStep = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public ProgramModel Program
|
||||
{
|
||||
get => _globalVariables.Program;
|
||||
set
|
||||
{
|
||||
if (_globalVariables.Program != value)
|
||||
{
|
||||
_globalVariables.Program = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
private bool _IsAdmin;
|
||||
public bool IsAdmin
|
||||
{
|
||||
get => _IsAdmin;
|
||||
set => SetProperty(ref _IsAdmin, value);
|
||||
}
|
||||
GlobalVariables _globalVariables { get; set; }
|
||||
private List<StepModel> tmpCopyList = new List<StepModel>();
|
||||
private IEventAggregator _eventAggregator;
|
||||
|
||||
#endregion
|
||||
public ICommand EditStepCommand { get;set; }
|
||||
public ICommand CopyStepCommand { get;set; }
|
||||
public ICommand PasteStepCommand { get;set; }
|
||||
public ICommand DeleteStepCommand { get;set; }
|
||||
public StepsManagerViewModel(GlobalVariables _GlobalVariables,IEventAggregator eventAggregator)
|
||||
{
|
||||
_eventAggregator = eventAggregator;
|
||||
_globalVariables = _GlobalVariables;
|
||||
IsAdmin = _globalVariables.IsAdmin;
|
||||
EditStepCommand = new DelegateCommand(EditStep);
|
||||
CopyStepCommand = new DelegateCommand(CopyStep);
|
||||
PasteStepCommand = new DelegateCommand(PasteStep);
|
||||
DeleteStepCommand = new DelegateCommand(DeleteStep);
|
||||
Program.StepCollection.CollectionChanged += StepCollection_CollectionChanged;
|
||||
|
||||
}
|
||||
#region 委托命令
|
||||
private void EditStep()
|
||||
{
|
||||
if (IsAdmin && SelectedStep != null&& _globalVariables.SelectedStep!=null)
|
||||
{
|
||||
_eventAggregator.GetEvent<EditSetpEvent>().Publish() ;
|
||||
}
|
||||
}
|
||||
private void CopyStep()
|
||||
{
|
||||
if (IsAdmin && SelectedStep != null)
|
||||
{
|
||||
tmpCopyList.Clear();
|
||||
tmpCopyList.Add(SelectedStep);
|
||||
}
|
||||
}
|
||||
private void PasteStep()
|
||||
{
|
||||
if (IsAdmin && tmpCopyList.Any())
|
||||
{
|
||||
int insertIndex = Program.StepCollection.IndexOf(SelectedStep) + 1;
|
||||
foreach (var item in tmpCopyList)
|
||||
{
|
||||
Program.StepCollection.Insert(insertIndex, new StepModel(item) { ID = Guid.NewGuid() });
|
||||
insertIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DeleteStep()
|
||||
{
|
||||
if (IsAdmin && SelectedStep != null)
|
||||
{
|
||||
var tmpList = new List<StepModel> { SelectedStep };
|
||||
_eventAggregator.GetEvent<DeletedStepEvent>().Publish(SelectedStep.ID);
|
||||
foreach (var item in tmpList)
|
||||
{
|
||||
Program.StepCollection.Remove(item);
|
||||
}
|
||||
_globalVariables.SelectedStep = null;
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
private void StepCollection_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
// Add/Move/Remove 都会触发,这里判断具体情形
|
||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
|
||||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Move||
|
||||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
// 如果需要等 UI 更新完再处理,可也用 Dispatcher 延迟一小段时间
|
||||
Application.Current?.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
// after drop: 重新编号或其他处理
|
||||
for (int i = 0; i < Program.StepCollection.Count; i++)
|
||||
Program.StepCollection[i].Index = i + 1;
|
||||
|
||||
// 发布 Prism 事件(如果需要)
|
||||
// _eventAggregator.GetEvent<StepMovedEvent>().Publish(...);
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
46
BOB/ViewModels/UpdateInfoViewModel.cs
Normal file
46
BOB/ViewModels/UpdateInfoViewModel.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Model;
|
||||
using Newtonsoft.Json;
|
||||
using Prism.Mvvm;
|
||||
using Prism.Ioc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BOB.ViewModels
|
||||
{
|
||||
public class UpdateInfoViewModel : BindableBase
|
||||
{
|
||||
private List<UpdateInfoModel> _updateList;
|
||||
public List<UpdateInfoModel> UpdateList
|
||||
{
|
||||
get => _updateList;
|
||||
set => SetProperty(ref _updateList, value);
|
||||
}
|
||||
|
||||
public UpdateInfoViewModel(IContainerProvider containerProvider)
|
||||
{
|
||||
string path = Path.Combine(SystemConfig.Instance.SystemPath, "UpdateInfo.json");
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(path, Encoding.UTF8);
|
||||
UpdateList = JsonConvert.DeserializeObject<List<UpdateInfoModel>>(json)
|
||||
?? new List<UpdateInfoModel>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
UpdateList = new List<UpdateInfoModel>();
|
||||
Console.WriteLine("读取 UpdateInfo.json 出错: " + ex.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
UpdateList = new List<UpdateInfoModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
BOB/ViewModels/UserControls/NumericalDisplayViewModel.cs
Normal file
69
BOB/ViewModels/UserControls/NumericalDisplayViewModel.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using Prism.Mvvm;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace BOB.ViewModels.UserControls
|
||||
{
|
||||
public class NumericalDisplayViewModel : BindableBase
|
||||
{
|
||||
public NumericalDisplayViewModel()
|
||||
{
|
||||
|
||||
}
|
||||
private string _channelNumber = string.Empty;
|
||||
private double _MonitorValue = double.NaN;
|
||||
private double _upperLimit = double.NaN;
|
||||
private double _lowerLimit = double.NaN;
|
||||
private SolidColorBrush _textColor = Brushes.Green;
|
||||
private SolidColorBrush _backgroundColor = Brushes.White;
|
||||
private Visibility _limitsVisibility = Visibility.Visible;
|
||||
|
||||
// 通道号
|
||||
public string ChannelNumber
|
||||
{
|
||||
get => _channelNumber;
|
||||
set => SetProperty(ref _channelNumber, value);
|
||||
}
|
||||
|
||||
public double MonitorValue
|
||||
{
|
||||
get => _MonitorValue;
|
||||
set => SetProperty(ref _MonitorValue, value);
|
||||
}
|
||||
|
||||
// 上限
|
||||
public double UpperLimit
|
||||
{
|
||||
get => _upperLimit;
|
||||
set => SetProperty(ref _upperLimit, value);
|
||||
}
|
||||
|
||||
// 下限
|
||||
public double LowerLimit
|
||||
{
|
||||
get => _lowerLimit;
|
||||
set => SetProperty(ref _lowerLimit, value);
|
||||
}
|
||||
|
||||
// 文字颜色
|
||||
public SolidColorBrush TextColor
|
||||
{
|
||||
get => _textColor;
|
||||
set => SetProperty(ref _textColor, value);
|
||||
}
|
||||
|
||||
// 背景颜色
|
||||
public SolidColorBrush BackgroundColor
|
||||
{
|
||||
get => _backgroundColor;
|
||||
set => SetProperty(ref _backgroundColor, value);
|
||||
}
|
||||
|
||||
// 上下限可见度
|
||||
public Visibility LimitsVisibility
|
||||
{
|
||||
get => _limitsVisibility;
|
||||
set => SetProperty(ref _limitsVisibility, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
BOB/Views/CommandTree.xaml
Normal file
81
BOB/Views/CommandTree.xaml
Normal file
@ -0,0 +1,81 @@
|
||||
<UserControl x:Class="BOB.Views.CommandTree"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:local="clr-namespace:BOB.Views"
|
||||
xmlns:model="clr-namespace:BOB.Models"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<prism:InvokeCommandAction Command="{Binding LoadedCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="439*" />
|
||||
<ColumnDefinition Width="361*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<GroupBox Header="指令"
|
||||
Grid.ColumnSpan="2">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<StackPanel Grid.Row="0"
|
||||
Orientation="Horizontal"
|
||||
Margin="10,0,7,12"
|
||||
VerticalAlignment="Center">
|
||||
<TextBox MinWidth="150"
|
||||
Height="25"
|
||||
Margin="0,0,5,0"
|
||||
VerticalContentAlignment="Center"
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}"
|
||||
materialDesign:HintAssist.Hint="搜索内容">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="KeyDown">
|
||||
<prism:InvokeCommandAction Command="{Binding SearchEnterCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
<!-- TreeView -->
|
||||
<TreeView Grid.Row="1"
|
||||
ItemsSource="{Binding InstructionTree}">
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type model:InstructionNode}"
|
||||
ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
<!-- 双击 -->
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseDoubleClick">
|
||||
<prism:InvokeCommandAction Command="{Binding TreeDoubleClickCommand}"
|
||||
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=TreeView}}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<TreeView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="重新加载"
|
||||
Command="{Binding ReloadCommand}" />
|
||||
</ContextMenu>
|
||||
</TreeView.ContextMenu>
|
||||
</TreeView>
|
||||
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
BOB/Views/CommandTree.xaml.cs
Normal file
28
BOB/Views/CommandTree.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// CommandTreeView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CommandTree : UserControl
|
||||
{
|
||||
public CommandTree()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
129
BOB/Views/DataView.xaml
Normal file
129
BOB/Views/DataView.xaml
Normal file
@ -0,0 +1,129 @@
|
||||
<UserControl x:Class="BOB.Views.DataView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:vs="clr-namespace:BOB.Views"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="1080"
|
||||
d:DesignWidth="1920">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Loaded">
|
||||
<i:InvokeCommandAction Command="{Binding LoadCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<DataGrid ItemsSource="{Binding CurrentDataSource}"
|
||||
AutoGenerateColumns="True"
|
||||
Margin="20,20,0,0" />
|
||||
<GroupBox Header="数据处理"
|
||||
Grid.Row="1"
|
||||
Margin="5"
|
||||
Padding="0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="5">
|
||||
<ComboBox ItemsSource="{Binding DataTableList}"
|
||||
SelectedItem="{Binding SelectTable, Mode=TwoWay}"
|
||||
MinWidth="150"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="15,0,15,0" />
|
||||
<Button Content="选择数据表"
|
||||
Command="{Binding SelectTableCommand}"
|
||||
Margin="15,0,15,0" />
|
||||
<!-- 查询输入框 -->
|
||||
<!--<TextBox x:Name="QueryTextBox"
|
||||
Width="200"
|
||||
Margin="0,0,10,0" />
|
||||
--><!-- 查询按钮 --><!--
|
||||
<Button Content="查询"
|
||||
Command="{Binding QueryCommand}"
|
||||
CommandParameter="{Binding Text, ElementName=QueryTextBox}"
|
||||
Margin="10,0,20,0" />-->
|
||||
</StackPanel>
|
||||
|
||||
<!-- 右侧内容: 日期选择器 -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Grid.Column="2"
|
||||
Margin="5">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Margin="15,0,15,0"
|
||||
Text="起始日期:" />
|
||||
<DatePicker materialDesign:HintAssist.Hint="起始日期"
|
||||
materialDesign:TextFieldAssist.HasClearButton="True"
|
||||
Style="{StaticResource MaterialDesignFloatingHintDatePicker}"
|
||||
Width="120"
|
||||
|
||||
Margin="0,0,10,0"
|
||||
SelectedDate="{Binding StartDate, Mode=TwoWay}" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="15,0,15,0"
|
||||
Text="结束日期:" />
|
||||
<DatePicker materialDesign:HintAssist.Hint="结束日期"
|
||||
materialDesign:TextFieldAssist.HasClearButton="True"
|
||||
Style="{StaticResource MaterialDesignFloatingHintDatePicker}"
|
||||
Width="120"
|
||||
Margin="0,0,10,0"
|
||||
SelectedDate="{Binding EndDate, Mode=TwoWay}" />
|
||||
<!-- 查询按钮 -->
|
||||
<Button Content="查询"
|
||||
Command="{Binding QueryCommand}"
|
||||
Margin="10,0,0,0" />
|
||||
<Button Content="刷新数据"
|
||||
Command="{Binding RefreshCommand}"
|
||||
Margin="15,0,15,0" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- 分页控件 -->
|
||||
<StackPanel Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="5">
|
||||
<Button Content="第一页"
|
||||
Command="{Binding FirstPageCommand}"
|
||||
Margin="10,0,10,0" />
|
||||
<Button Content="上一页"
|
||||
Command="{Binding PreviousPageCommand}"
|
||||
Margin="10,0,10,0" />
|
||||
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
Margin="10 10 0 10"
|
||||
Text="{Binding CurrentPage}"
|
||||
materialDesign:HintAssist.Hint="" />
|
||||
<TextBlock Text="/"
|
||||
Margin="0 10"
|
||||
materialDesign:HintAssist.Hint="" />
|
||||
<TextBlock Text="{Binding UITotalPages}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="0 10" />
|
||||
|
||||
<Button Content="下一页"
|
||||
Command="{Binding NextPageCommand}"
|
||||
Margin="10,0,10,0" />
|
||||
<Button Content="最后一页"
|
||||
Command="{Binding LastPageCommand}"
|
||||
Margin="10,0,15,0" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
BOB/Views/DataView.xaml.cs
Normal file
28
BOB/Views/DataView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// DataView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DataView : UserControl
|
||||
{
|
||||
public DataView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
228
BOB/Views/Dialogs/BackfeedView.xaml
Normal file
228
BOB/Views/Dialogs/BackfeedView.xaml
Normal file
@ -0,0 +1,228 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.BackfeedView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="220" />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 实时监控 -->
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Padding="0,0,0,0">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 实时曲线 -->
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 调试选项 -->
|
||||
<GroupBox Header="调试选项"
|
||||
Grid.Row="2">
|
||||
<TreeView Margin="10">
|
||||
<!-- 连接状态设置 -->
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 查询 -->
|
||||
<TreeViewItem Header="查询">
|
||||
<TreeViewItem Header="查询设备标识">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="查询设备标识"
|
||||
Margin="5"
|
||||
Command="{Binding QueryDeviceCommand}" />
|
||||
<Label Content="结果"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding 设备标识字符串}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 设置 -->
|
||||
<TreeViewItem Header="设置">
|
||||
<!-- 远程模式 -->
|
||||
<TreeViewItem Header="远程">
|
||||
<Button Content="设置为远程模式"
|
||||
Command="{Binding SetRemoteModeCommand}"
|
||||
Margin="5" />
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 输出设置 -->
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding OutputOnCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding OutputOffCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电压(V)"
|
||||
Command="{Binding SetVoltageCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电压}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电流(A)"
|
||||
Command="{Binding SetCurrentCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电流}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 电流保护 -->
|
||||
<TreeViewItem Header="电流保护(OCP)">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding EnableOCPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding DisableOCPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="清除报警"
|
||||
Command="{Binding ClearOCPAlarmCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电流保护(A)"
|
||||
Command="{Binding SetOCPCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OCP电流}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 电压保护 -->
|
||||
<TreeViewItem Header="电压保护(OVP)">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding EnableOVPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding DisableOVPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="清除报警"
|
||||
Command="{Binding ClearOVPAlarmCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电压保护(V)"
|
||||
Command="{Binding SetOVPCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OVP电压}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 功率保护 -->
|
||||
<TreeViewItem Header="功率保护(OPP)">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding EnableOPPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding DisableOPPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="清除报警"
|
||||
Command="{Binding ClearOPPAlarmCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置功率(W)"
|
||||
Command="{Binding SetOPPCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OPP功率}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/BackfeedView.xaml.cs
Normal file
36
BOB/Views/Dialogs/BackfeedView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// BackfeedView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class BackfeedView : UserControl
|
||||
{
|
||||
public BackfeedView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
225
BOB/Views/Dialogs/CANView.xaml
Normal file
225
BOB/Views/Dialogs/CANView.xaml
Normal file
@ -0,0 +1,225 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.CANView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:cons="clr-namespace:BOB.Converters"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<UserControl.Resources>
|
||||
<cons:HexConverter x:Key="HexConverter" />
|
||||
</UserControl.Resources>
|
||||
<GroupBox Header="CAN手动设置"
|
||||
Padding="0,0,0,0"
|
||||
MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- TreeView 用于显示不同选项 -->
|
||||
<TreeView Grid.Row="1">
|
||||
<!-- 调试选项 -->
|
||||
<TreeViewItem Header="调试选项"
|
||||
Visibility="{Binding 高级模式可见度}">
|
||||
<Button Content="初始化TSMaster"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="初始化TSMaster" />
|
||||
<Button Content="释放TSMaster"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="释放TSMaster" />
|
||||
<Button Content="注册监听事件"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="注册监听事件" />
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 监视选项 -->
|
||||
<TreeViewItem Header="监视">
|
||||
<Frame x:Name="监视Frame"
|
||||
Height="400"
|
||||
Width="700" />
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- DBC 配置 -->
|
||||
<TreeViewItem Header="DBC">
|
||||
<Label Content="请注意,要在断开CAN卡的情况下才能操作DBC!"
|
||||
Foreground="Red" />
|
||||
<Button Content="卸载所有DBC"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="卸载DBC" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Margin="0 0 10 0"
|
||||
Content="更换DBC"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="更换DBC" />
|
||||
<Button Content="加载DBC"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="加载DBC" />
|
||||
<Label Content="通道(从0开始)"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding DBC加载通道}"
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<Button Content="查看DBC"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="查看DBC" />
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- CAN卡连接选项 -->
|
||||
<TreeViewItem Header="CAN卡连接">
|
||||
<Button Content="连接"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="连接" />
|
||||
<Button Content="断开"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="断开" />
|
||||
<Button Content="清空循环发送报文"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="清空循环发送报文" />
|
||||
<Button Content="硬件配置"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="硬件配置" />
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- DBC报文发送 -->
|
||||
<TreeViewItem Header="DBC报文发送">
|
||||
<DockPanel>
|
||||
<Label Content="报文" />
|
||||
<ComboBox MinWidth="100"
|
||||
SelectedIndex="{Binding 选中报文}"
|
||||
ItemsSource="{Binding 报文}"
|
||||
/>
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="信号" />
|
||||
<ComboBox SelectedIndex="{Binding 选中信号}"
|
||||
ItemsSource="{Binding 信号}"
|
||||
MinWidth="100" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="信号值" />
|
||||
<TextBox Text="{Binding can报文}"
|
||||
MinWidth="100" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="循环发送时间间隔(ms)(0为单次发送)" />
|
||||
<TextBox Text="{Binding dbc循环发送时间间隔}"
|
||||
MinWidth="100" />
|
||||
</DockPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="通道(从0开始)"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding 报文发送通道}"
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,10,10,10" />
|
||||
<Button Content="加载报文"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="加载报文"
|
||||
Margin="10" />
|
||||
<Button Content="设置信号并发送"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="设置" />
|
||||
<CheckBox Content="直接发送"
|
||||
IsChecked="{Binding 直接发送}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 自定义报文发送 -->
|
||||
<TreeViewItem Header="自定义报文发送">
|
||||
<DockPanel>
|
||||
<Label Content="通道" />
|
||||
<ComboBox MinWidth="100"
|
||||
SelectedItem="{Binding AIdxChn}"
|
||||
ItemsSource="{Binding APP_CHANNEL名称}"
|
||||
/>
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="ID" />
|
||||
<TextBox MinWidth="100"
|
||||
Text="{Binding AID, Converter={StaticResource HexConverter}, Mode=TwoWay}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="DLC" />
|
||||
<TextBox MinWidth="200"
|
||||
Text="{Binding ADLC}" />
|
||||
<CheckBox Content="自动设定"
|
||||
IsChecked="{Binding 自动设定}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="报文" />
|
||||
<TextBox MinWidth="200"
|
||||
Text="{Binding 自定义报文}" />
|
||||
</DockPanel>
|
||||
<DockPanel>
|
||||
<Label Content="循环发送时间间隔(ms)(0为单次发送)" />
|
||||
<TextBox Text="{Binding 自定义循环发送时间间隔}"
|
||||
MinWidth="100" />
|
||||
</DockPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox Content="发送帧"
|
||||
IsChecked="{Binding AIsTx}" />
|
||||
<CheckBox Content="扩展帧"
|
||||
IsChecked="{Binding AIsExt}" />
|
||||
<CheckBox Content="远程帧"
|
||||
IsChecked="{Binding AIsRemote}" />
|
||||
<CheckBox Content="FD"
|
||||
IsChecked="{Binding AIsFD}" />
|
||||
<CheckBox Content="BRS"
|
||||
IsChecked="{Binding AIsBRS}" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="发送"
|
||||
Command="{Binding ButtonClickCommand}"
|
||||
CommandParameter="自定义报文发送" />
|
||||
<CheckBox Margin="10"
|
||||
Content="更新到数据库"
|
||||
IsChecked="{Binding 更新到数据库}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<!-- 报文录制 -->
|
||||
<TreeViewItem Header="报文录制">
|
||||
<DockPanel>
|
||||
<Label Content="路径(开始录制时使用)"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox MinWidth="100"
|
||||
Text="{Binding BLFPath}"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Button Content="选择路径" Margin="10 0"
|
||||
Command="{Binding SelectBLFPathCommand}"
|
||||
CommandParameter="选择路径" />
|
||||
<Button Content="保存路径"
|
||||
Command="{Binding SaveBLFPathCommand}"
|
||||
CommandParameter="保存路径" />
|
||||
</DockPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开始录制"
|
||||
Command="{Binding StartTranscirbeCommand}"
|
||||
CommandParameter="开始录制" />
|
||||
<Button Content="结束录制"
|
||||
Margin="10 0"
|
||||
Command="{Binding EndTranscirbeCommand}"
|
||||
CommandParameter="结束录制" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/CANView.xaml.cs
Normal file
36
BOB/Views/Dialogs/CANView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// CANView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class CANView : UserControl
|
||||
{
|
||||
public CANView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
BOB/Views/Dialogs/EAEL9080View.xaml
Normal file
132
BOB/Views/Dialogs/EAEL9080View.xaml
Normal file
@ -0,0 +1,132 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.EAEL9080View"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:oxy1="clr-namespace:OxyPlot.Wpf;assembly=OxyPlot.Wpf"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Background="White"
|
||||
Height="850"
|
||||
Width="900"
|
||||
>
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="220" />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 实时监控 -->
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Padding="0,0,0,0">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 实时曲线 -->
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 调试选项 -->
|
||||
<GroupBox Header="调试选项"
|
||||
Grid.Row="2">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding 连接命令}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding 断开命令}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="查询">
|
||||
<TreeViewItem Header="查询设备标识">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="查询设备标识"
|
||||
Margin="5"
|
||||
Command="{Binding 查询设备信息命令}" />
|
||||
<Label Content="结果"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding 设备标识字符串}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint="设备标识字符串"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="远程">
|
||||
<Button Content="设置为远程模式"
|
||||
Command="{Binding 设置为远程模式命令}" />
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="模式切换">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="负载模式切换"
|
||||
Command="{Binding 设置负载工作模式命令}"
|
||||
Margin="5" />
|
||||
<ComboBox MinWidth="200"
|
||||
ItemsSource="{Binding 负载模式枚举}"
|
||||
SelectedItem="{Binding 负载模式}"
|
||||
materialDesign:HintAssist.Hint="负载模式"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding 电源输出开命令}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding 电源输出关命令}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="2" VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding 关闭命令}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/EAEL9080View.xaml.cs
Normal file
36
BOB/Views/Dialogs/EAEL9080View.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// EAEL9080View.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class EAEL9080View : UserControl
|
||||
{
|
||||
public EAEL9080View()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
BOB/Views/Dialogs/IOBoardView.xaml
Normal file
94
BOB/Views/Dialogs/IOBoardView.xaml
Normal file
@ -0,0 +1,94 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.IOBoardView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<GroupBox Header="IO板卡手动设置"
|
||||
Padding="0,0,0,0"
|
||||
MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid >
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="输出">
|
||||
<TreeViewItem Header="单通道设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Margin="5"
|
||||
Command="{Binding PowerOnCommand}" />
|
||||
<Button Content="关"
|
||||
Margin="5"
|
||||
Command="{Binding PowerOffCommand}" />
|
||||
<Label Content="输出地址"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<ComboBox SelectedItem="{Binding SelectedAddress, Mode=TwoWay}"
|
||||
ItemsSource="{Binding AddressList}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="全通道设置">
|
||||
<StackPanel>
|
||||
<Label Content="偏移"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding Offset}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="状态"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding BatchWriteStatus}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommand}" />
|
||||
<Button Content="读取"
|
||||
Margin="5"
|
||||
Command="{Binding ReadCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/IOBoardView.xaml.cs
Normal file
36
BOB/Views/Dialogs/IOBoardView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// IOBoardView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class IOBoardView : UserControl
|
||||
{
|
||||
public IOBoardView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
188
BOB/Views/Dialogs/IT6724CView.xaml
Normal file
188
BOB/Views/Dialogs/IT6724CView.xaml
Normal file
@ -0,0 +1,188 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.IT6724CView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtoDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="220" />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Padding="0,0,0,0">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 实时曲线 -->
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="调试选项"
|
||||
Grid.Row="2">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="查询">
|
||||
<TreeViewItem Header="查询设备标识">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="查询设备标识"
|
||||
Margin="5"
|
||||
Command="{Binding QueryDeviceInfoCommand}" />
|
||||
<Label Content="结果"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding 设备标识字符串}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="远程">
|
||||
<Button Content="设置为远程模式"
|
||||
Command="{Binding SetRemoteModeCommand}"
|
||||
Margin="5" />
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding PowerOnCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding PowerOffCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电压(V)"
|
||||
Command="{Binding SetOutputVoltageCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电压}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电流(A)"
|
||||
Command="{Binding SetOutputCurrentCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电流}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="电流保护(OCP)">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding EnableOCPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding DisableOCPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="清除报警"
|
||||
Command="{Binding ClearOCPAlarmCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电流保护(A)"
|
||||
Command="{Binding SetOCPCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OCP电流}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="电压保护(OVP)">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding EnableOVPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding DisableOVPCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="清除报警"
|
||||
Command="{Binding ClearOVPAlarmCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置电压保护(V)"
|
||||
Command="{Binding SetOVPCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OVP电压}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
37
BOB/Views/Dialogs/IT6724CView.xaml.cs
Normal file
37
BOB/Views/Dialogs/IT6724CView.xaml.cs
Normal file
@ -0,0 +1,37 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// IT6724CView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class IT6724CView : UserControl
|
||||
{
|
||||
public IT6724CView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private void MouseLeftButtoDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
BOB/Views/Dialogs/LQ7500-DView.xaml
Normal file
21
BOB/Views/Dialogs/LQ7500-DView.xaml
Normal file
@ -0,0 +1,21 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.LQ7500_DView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/LQ7500-DView.xaml.cs
Normal file
36
BOB/Views/Dialogs/LQ7500-DView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// LQ7500_DView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class LQ7500_DView : UserControl
|
||||
{
|
||||
public LQ7500_DView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
BOB/Views/Dialogs/MessageBoxView.xaml
Normal file
85
BOB/Views/Dialogs/MessageBoxView.xaml
Normal file
@ -0,0 +1,85 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.MessageBoxView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="Transparent"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="250"
|
||||
Width="300">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Border CornerRadius="20" Background="white">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<!-- Title -->
|
||||
<TextBlock Grid.Row="0"
|
||||
Margin="15 5 5 5"
|
||||
FontSize="18"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Title}"
|
||||
Foreground="#333" />
|
||||
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
Grid.Row="1">
|
||||
<!-- Icon -->
|
||||
<Image
|
||||
Width="100"
|
||||
Height="100"
|
||||
VerticalAlignment="Top"
|
||||
Margin="5 15 0 0"
|
||||
Source="{Binding Icon}" />
|
||||
<!-- Message -->
|
||||
<TextBlock
|
||||
FontSize="20"
|
||||
Margin="15 0 0 0"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Message}" />
|
||||
</StackPanel>
|
||||
<!-- Buttons -->
|
||||
<StackPanel Grid.Row="2"
|
||||
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
|
||||
<Button Content="Yes"
|
||||
Width="80"
|
||||
Margin="10 10"
|
||||
Visibility="{Binding ShowYes, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Command="{Binding YesCommand}" />
|
||||
|
||||
<Button Content="No"
|
||||
Width="80"
|
||||
Margin="10 10"
|
||||
Visibility="{Binding ShowNo, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Command="{Binding NoCommand}" />
|
||||
|
||||
<Button Content="OK"
|
||||
Width="80"
|
||||
Margin="10 10"
|
||||
Visibility="{Binding ShowOk, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Command="{Binding OkCommand}" />
|
||||
|
||||
<Button Content="Cancel"
|
||||
Width="80"
|
||||
Margin="10 10"
|
||||
Visibility="{Binding ShowCancel, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Command="{Binding CancelCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
28
BOB/Views/Dialogs/MessageBoxView.xaml.cs
Normal file
28
BOB/Views/Dialogs/MessageBoxView.xaml.cs
Normal file
@ -0,0 +1,28 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// MessageBoxView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MessageBoxView : UserControl
|
||||
{
|
||||
public MessageBoxView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
189
BOB/Views/Dialogs/PSB11000View.xaml
Normal file
189
BOB/Views/Dialogs/PSB11000View.xaml
Normal file
@ -0,0 +1,189 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.PSB11000View"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:oxy="http://oxyplot.org/wpf"
|
||||
xmlns:ucs="clr-namespace:BOB.Views.UserControls"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="220" />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="350" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<GroupBox x:Name="实时监控区"
|
||||
Header="实时监控"
|
||||
Padding="0,0,0,0">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电压MV,Mode=TwoWay}"
|
||||
Grid.Column="0" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 电流MV,Mode=TwoWay}"
|
||||
Grid.Column="1" />
|
||||
<ucs:NumericalDisplay DataContext="{Binding 功率MV,Mode=TwoWay}"
|
||||
Grid.Column="2" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="实时曲线"
|
||||
Grid.Row="1"
|
||||
Padding="0,0,0,0">
|
||||
<oxy:PlotView Model="{Binding 曲线Model}">
|
||||
<oxy:PlotView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="视图复位"
|
||||
Command="{Binding ResetViewCommand}" />
|
||||
</ContextMenu>
|
||||
</oxy:PlotView.ContextMenu>
|
||||
</oxy:PlotView>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Header="调试选项"
|
||||
Grid.Row="2">
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="查询">
|
||||
<TreeViewItem Header="查询设备标识">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="查询设备标识"
|
||||
Margin="5"
|
||||
Command="{Binding QueryDeviceInfoCommand}" />
|
||||
<Label Content="结果"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding 设备标识字符串}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="远程">
|
||||
<Button Content="设置为远程模式"
|
||||
Command="{Binding SetRemoteModeCommand}" />
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="模式切换">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="工作模式切换"
|
||||
Command="{Binding SwitchWorkingModeCommand}"
|
||||
Margin="5" />
|
||||
<ComboBox MinWidth="200"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
ItemsSource="{Binding 工作模式枚举}"
|
||||
SelectedItem="{Binding 工作模式}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="直流源模式切换"
|
||||
Command="{Binding SwitchDCSourceModeCommand}"
|
||||
Margin="5" />
|
||||
<ComboBox MinWidth="200"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
ItemsSource="{Binding 直流源模式枚举}"
|
||||
SelectedItem="{Binding 直流源模式}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="负载模式切换"
|
||||
Command="{Binding SwitchLoadModeCommand}"
|
||||
Margin="5" />
|
||||
<ComboBox MinWidth="200"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
ItemsSource="{Binding 负载模式枚举}"
|
||||
SelectedItem="{Binding 负载模式}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开"
|
||||
Command="{Binding PowerOnCommand}"
|
||||
Margin="5" />
|
||||
<Button Content="关"
|
||||
Command="{Binding PowerOffCommand}"
|
||||
Margin="5" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置CC模式电压(V)"
|
||||
Command="{Binding SetCCVoltageCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电压}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置CC模式电流(A)"
|
||||
Command="{Binding SetCCCurrentCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding 输出电流}"
|
||||
MinWidth="100"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设置OCP电流(A)"
|
||||
Command="{Binding SetOCPCurrentCommand}"
|
||||
Margin="5" />
|
||||
<Label Content="值:"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Text="{Binding OCP电流}"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
MinWidth="100"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Add similar blocks for other settings (OVP, OPP, etc.) -->
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
</GroupBox>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/PSB11000View.xaml.cs
Normal file
36
BOB/Views/Dialogs/PSB11000View.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// PSB11000View.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class PSB11000View : UserControl
|
||||
{
|
||||
public PSB11000View()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
BOB/Views/Dialogs/ParameterSetting.xaml
Normal file
136
BOB/Views/Dialogs/ParameterSetting.xaml
Normal file
@ -0,0 +1,136 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.ParameterSetting"
|
||||
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:converters="clr-namespace:BOB.Converters"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
xmlns:behavior="clr-namespace:Common.Behaviors;assembly=Common"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Width="420"
|
||||
Height="284"
|
||||
mc:Ignorable="d">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<UserControl.Resources>
|
||||
<converters:IsEnumTypeConverter x:Key="IsEnumTypeConverter" />
|
||||
<converters:ParameterValueToStringConverter x:Key="ParameterValueToStringConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<GroupBox Padding="10,15,10,0"
|
||||
Header="{Binding Title}"
|
||||
behavior:WindowDragBehavior.EnableWindowDrag="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer>
|
||||
<StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数名称*" />
|
||||
<TextBox Width="120"
|
||||
Text="{Binding Parameter.Name}"
|
||||
materialDesign:HintAssist.Hint="参数名称" />
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数类型*" />
|
||||
<ComboBox Width="120"
|
||||
VerticalAlignment="Bottom"
|
||||
ItemsSource="{Binding Types}"
|
||||
materialDesign:HintAssist.Hint="参数类型"
|
||||
SelectedItem="{Binding Parameter.Type}"
|
||||
/>
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数类别*" />
|
||||
<ComboBox Width="120"
|
||||
VerticalAlignment="Bottom"
|
||||
ItemsSource="{Binding Categories}"
|
||||
materialDesign:HintAssist.Hint="参数类别"
|
||||
Text="{Binding Parameter.Category}" />
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数下限" />
|
||||
<TextBox Width="120"
|
||||
VerticalAlignment="Bottom"
|
||||
Text="{Binding Parameter.LowerLimit}"
|
||||
materialDesign:HintAssist.Hint="参数下限" />
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数上限" />
|
||||
<TextBox Width="120"
|
||||
VerticalAlignment="Bottom"
|
||||
Text="{Binding Parameter.UpperLimit}"
|
||||
materialDesign:HintAssist.Hint="参数名上限" />
|
||||
</StackPanel>
|
||||
<StackPanel Height="30"
|
||||
Margin="7"
|
||||
Orientation="Horizontal">
|
||||
<Label Width="60"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="参数值" />
|
||||
|
||||
<!-- 非枚举类型时显示文本框 -->
|
||||
<TextBox MinWidth="120"
|
||||
VerticalAlignment="Bottom"
|
||||
Text="{Binding Parameter.Value, Converter={StaticResource ParameterValueToStringConverter}}"
|
||||
materialDesign:HintAssist.Hint="参数值"
|
||||
Visibility="{Binding Parameter.Type, Converter={StaticResource IsEnumTypeConverter}, ConverterParameter=Collapse}" />
|
||||
|
||||
<!-- 枚举类型时显示下拉框 -->
|
||||
<!--<ComboBox MinWidth="120"
|
||||
VerticalAlignment="Bottom"
|
||||
ItemsSource="{Binding EnumValues}"
|
||||
SelectedItem="{Binding Parameter.Value}"
|
||||
Visibility="{Binding Parameter.Type, Converter={StaticResource IsEnumTypeConverter}}" />-->
|
||||
<CheckBox Margin="10,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="保存数据"
|
||||
IsChecked="{Binding Parameter.IsSave}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<StackPanel Grid.Row="1"
|
||||
Margin="5,10,5,15"
|
||||
FlowDirection="RightToLeft"
|
||||
Orientation="Horizontal">
|
||||
<Button Content="取消"
|
||||
Width="70"
|
||||
Command="{Binding CancelCommand}" />
|
||||
<Button Content="保存"
|
||||
Width="70"
|
||||
Margin="20,0"
|
||||
Command="{Binding SaveCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
37
BOB/Views/Dialogs/ParameterSetting.xaml.cs
Normal file
37
BOB/Views/Dialogs/ParameterSetting.xaml.cs
Normal file
@ -0,0 +1,37 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// ParameterSetting.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ParameterSetting : UserControl
|
||||
{
|
||||
public ParameterSetting()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ComboBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (sender is ComboBox comboBox && !comboBox.IsDropDownOpen)
|
||||
{
|
||||
comboBox.IsDropDownOpen = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
208
BOB/Views/Dialogs/SQ0030G1DView.xaml
Normal file
208
BOB/Views/Dialogs/SQ0030G1DView.xaml
Normal file
@ -0,0 +1,208 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.SQ0030G1DView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<GroupBox Header="AC源手动设置"
|
||||
Padding="0,0,0,0"
|
||||
MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid >
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
<TreeViewItem Header="电压开关设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="开启"
|
||||
Margin="5"
|
||||
Command="{Binding OpenPowerSupplyCommand}" />
|
||||
<Button Content="关闭"
|
||||
Margin="5"
|
||||
Command="{Binding ClosePowerSupplyCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设置">
|
||||
<TreeViewItem Header="设定三相电压输出">
|
||||
<TreeViewItem Header="设定三相电压档位">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="低档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelLowCommand}" />
|
||||
<Button Content="高档"
|
||||
Margin="5"
|
||||
Command="{Binding SetVoltageLevelHighCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Button Content="设定三相输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetThreePhaseVoltageCommand}" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="U相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding UPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="V相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding VPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Label Content="W相输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding WPhaseVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设定通用功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定通用功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputVoltageCommand}" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CommonOutputVoltage}"
|
||||
MinWidth="50"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定通用功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetCommonOutputFrequencyCommand}" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CommonOutputFrequency}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="设定步阶功能输出">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出电压"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputVoltageCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltageGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出电压"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputVoltage}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="V"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="设定步阶功能输出频率"
|
||||
Margin="5"
|
||||
Command="{Binding SetStepOutputFrequencyCommand}" />
|
||||
<Label Content="组号"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequencyGroup}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="输出频率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding StepOutputFrequency}"
|
||||
MinWidth="50"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
<Label Content="Hz"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/SQ0030G1DView.xaml.cs
Normal file
36
BOB/Views/Dialogs/SQ0030G1DView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// SQ0030G1DView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class SQ0030G1DView : UserControl
|
||||
{
|
||||
public SQ0030G1DView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
BOB/Views/Dialogs/WS-68030-380TView.xaml
Normal file
75
BOB/Views/Dialogs/WS-68030-380TView.xaml
Normal file
@ -0,0 +1,75 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.WS_68030_380TView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<GroupBox Header="AC载手动设置"
|
||||
Padding="0,0,0,0"
|
||||
MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
<Grid >
|
||||
<TreeView Margin="10">
|
||||
<TreeViewItem Header="连接状态设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="连接"
|
||||
Margin="5"
|
||||
Command="{Binding ConnectCommand}" />
|
||||
<Button Content="断开"
|
||||
Margin="5"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="上下载设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="加载"
|
||||
Margin="5"
|
||||
Command="{Binding LoadCommand}" />
|
||||
<Button Content="卸载"
|
||||
Margin="5"
|
||||
Command="{Binding UnloadCommand}" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
|
||||
<TreeViewItem Header="功率设置">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="读取功率"
|
||||
Margin="5"
|
||||
Command="{Binding ReadPowerCommand}" />
|
||||
<Button Content="设置功率"
|
||||
Margin="5"
|
||||
Command="{Binding SetPowerCommand}" />
|
||||
<Label Content="功率"
|
||||
Margin="5"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBox Text="{Binding CurrentPowerDisplay}"
|
||||
MinWidth="100"
|
||||
Margin="5"
|
||||
materialDesign:HintAssist.Hint=""
|
||||
VerticalContentAlignment="Center" />
|
||||
</StackPanel>
|
||||
</TreeViewItem>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2"
|
||||
VerticalAlignment="Bottom">
|
||||
<Button Content="关闭"
|
||||
Width="70"
|
||||
Margin="10"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{Binding CloseCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/WS-68030-380TView.xaml.cs
Normal file
36
BOB/Views/Dialogs/WS-68030-380TView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// WS_68030_380TView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class WS_68030_380TView : UserControl
|
||||
{
|
||||
public WS_68030_380TView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
BOB/Views/Dialogs/ZXKSView.xaml
Normal file
21
BOB/Views/Dialogs/ZXKSView.xaml
Normal file
@ -0,0 +1,21 @@
|
||||
<UserControl x:Class="BOB.Views.Dialogs.ZXKSView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:BOB.Views.Dialogs"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Background="White"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
Height="850"
|
||||
Width="900">
|
||||
<prism:Dialog.WindowStyle>
|
||||
<Style BasedOn="{StaticResource DialogUserManageStyle}"
|
||||
TargetType="Window" />
|
||||
</prism:Dialog.WindowStyle>
|
||||
<Grid MouseLeftButtonDown="MouseLeftButtonDown">
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
36
BOB/Views/Dialogs/ZXKSView.xaml.cs
Normal file
36
BOB/Views/Dialogs/ZXKSView.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// ZXKSView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class ZXKSView : UserControl
|
||||
{
|
||||
public ZXKSView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Window.GetWindow(this)?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
BOB/Views/LogArea.xaml
Normal file
34
BOB/Views/LogArea.xaml
Normal file
@ -0,0 +1,34 @@
|
||||
<UserControl x:Class="BOB.Views.LogArea"
|
||||
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:prism="http://prismlibrary.com/"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800">
|
||||
|
||||
<Grid>
|
||||
<GroupBox Header="系统运行日志">
|
||||
<ListView x:Name="LogListView"
|
||||
FontWeight="DemiBold"
|
||||
ItemsSource="{Binding Logs}"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<ListView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="清空日志"
|
||||
Command="{Binding ClearLogCommand}" />
|
||||
</ContextMenu>
|
||||
</ListView.ContextMenu>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Foreground="{Binding Color}"
|
||||
Text="{Binding Message}"
|
||||
TextWrapping="Wrap" />
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
34
BOB/Views/LogArea.xaml.cs
Normal file
34
BOB/Views/LogArea.xaml.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using BOB.ViewModels;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
public partial class LogArea : UserControl
|
||||
{
|
||||
public LogArea()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// 绑定 DataContext 后,订阅日志集合变化
|
||||
this.Loaded += (s, e) =>
|
||||
{
|
||||
if (DataContext is LogAreaViewModel vm)
|
||||
{
|
||||
vm.Logs.CollectionChanged += Logs_CollectionChanged;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void Logs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
// 每次新增日志,滚动到最后一条
|
||||
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
if (this.LogListView.Items.Count > 0)
|
||||
{
|
||||
this.LogListView.ScrollIntoView(this.LogListView.Items[^1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
BOB/Views/MainView.xaml
Normal file
44
BOB/Views/MainView.xaml
Normal file
@ -0,0 +1,44 @@
|
||||
<UserControl x:Class="BOB.Views.MainView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:vs="clr-namespace:BOB.Views"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="1080"
|
||||
d:DesignWidth="1920">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1.5*"/>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
|
||||
<vs:CommandTree Grid.Row="0" Margin="5"
|
||||
Grid.Column="0"
|
||||
Grid.RowSpan="2" />
|
||||
<vs:StepsManager Grid.Row="0"
|
||||
Margin="5"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"/>
|
||||
<vs:SingleStepEdit Grid.Row="0"
|
||||
Margin="5"
|
||||
Grid.Column="3" />
|
||||
<vs:LogArea Grid.Row="1"
|
||||
Margin="5"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2" />
|
||||
<vs:ParametersManager Grid.Row="1"
|
||||
Margin="5"
|
||||
Grid.Column="3" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
32
BOB/Views/MainView.xaml.cs
Normal file
32
BOB/Views/MainView.xaml.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Common.PubEvent;
|
||||
using Prism.Events;
|
||||
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.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BOB.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// MainView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class MainView : UserControl
|
||||
{
|
||||
public MainView(IEventAggregator eventAggregator)
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user