Compare commits

...
2 Commits
Author SHA1 Message Date
huangsucan c4fc2d80fd can修改 2026-09-12 20:31:45 +08:00
huangsucan 4acb4d8d13 启动加载页 2026-08-31 14:55:21 +08:00
8 changed files with 761 additions and 10 deletions
+5 -1
View File
@@ -636,11 +636,14 @@ namespace CANModule.ViewModels
{ {
// 提取实际 CAN ID(去掉扩展帧标志位) // 提取实际 CAN ID(去掉扩展帧标志位)
int actualId = (int)(canId & 0x1FFFFFFF); int actualId = (int)(canId & 0x1FFFFFFF);
// 原始字节转为 [0x00, 0x01, ...] 格式,供监视表格直接显示
string hexData = (data);
var find = CanMessageList.FirstOrDefault(s => s.ID == actualId && s. == channel); var find = CanMessageList.FirstOrDefault(s => s.ID == actualId && s. == channel);
if (find != null) if (find != null)
{ {
find. = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(); find. = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds();
find. = dlcLength; find. = dlcLength;
find. = hexData;
} }
else else
{ {
@@ -649,7 +652,8 @@ namespace CANModule.ViewModels
= (byte)channel, = (byte)channel,
ID = actualId, ID = actualId,
= (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(), = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(),
= dlcLength = dlcLength,
= hexData
}); });
} }
}); });
+5 -4
View File
@@ -79,16 +79,17 @@
<!-- 监视选项 --> <!-- 监视选项 -->
<TreeViewItem Header="监视"> <TreeViewItem Header="监视">
<DataGrid x:Name="表格" <DataGrid x:Name="表格"
Width="550" Width="Auto"
Height="350" Height="350"
VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.IsVirtualizing="True"
IsReadOnly="True" IsReadOnly="True"
AutoGenerateColumns="False" AutoGenerateColumns="False"
ItemsSource="{Binding CanMessageList, Mode=OneWay}"> ItemsSource="{Binding CanMessageList, Mode=OneWay}">
<DataGrid.Columns> <DataGrid.Columns>
<DataGridTextColumn Header="通道" Binding="{Binding 通道}" Width="90" /> <DataGridTextColumn Header="通道" Binding="{Binding 通道}" Width="60" />
<DataGridTextColumn Header="报文ID" Binding="{Binding 报文ID, Converter={StaticResource HexConverter}}" Width="150" /> <DataGridTextColumn Header="报文ID" Binding="{Binding 报文ID, Converter={StaticResource HexConverter}}" Width="110" />
<DataGridTextColumn Header="长度" Binding="{Binding 长度}" Width="90" /> <DataGridTextColumn Header="长度" Binding="{Binding 长度}" Width="50" />
<DataGridTextColumn Header="数据" Binding="{Binding 数据}" Width="Auto" />
<DataGridTextColumn Header="时间戳" Binding="{Binding 时间戳}" Width="Auto" /> <DataGridTextColumn Header="时间戳" Binding="{Binding 时间戳}" Width="Auto" />
</DataGrid.Columns> </DataGrid.Columns>
</DataGrid> </DataGrid>
@@ -234,11 +234,23 @@ namespace MainModule.ViewModels
#region #region
private async Task OnLoad() private async Task OnLoad()
{ {
if (!IsInitialized) // 设备初始化期间仅对当前台架显示灰度遮罩层,初始化完成后关闭(finally 保证异常时也能关闭)
_eventAggregator.GetEvent<ScopeOverlayEvent>().Publish(new ScopeOverlayArgs { Scope = TestStatus, Show = true });
// 让遮罩层先完成渲染,再进入同步阻塞的设备初始化(泵送 Dispatcher 至 Render 优先级)
System.Windows.Application.Current?.Dispatcher.Invoke(() => { }, System.Windows.Threading.DispatcherPriority.Render);
try
{ {
await _deviceManager.ConnectAllDevices(); if (!IsInitialized)
IsInitialized = true; {
await _deviceManager.ConnectAllDevices();
IsInitialized = true;
}
} }
finally
{
_eventAggregator.GetEvent<ScopeOverlayEvent>().Publish(new ScopeOverlayArgs { Scope = TestStatus, Show = false });
}
} }
private void OnRefresh() private void OnRefresh()
@@ -128,6 +128,26 @@
</vs:ParametersManager.Style> </vs:ParametersManager.Style>
</vs:ParametersManager> </vs:ParametersManager>
<Border x:Name="Overlay"
Background="#40000000"
Visibility="Collapsed"
Panel.ZIndex="1"
Grid.RowSpan="2"
Grid.ColumnSpan="4">
<StackPanel Width="150"
VerticalAlignment="Center"
Margin="0 0 0 100">
<ProgressBar Width="80"
Height="80"
Margin="20"
IsIndeterminate="True"
Style="{StaticResource MaterialDesignCircularProgressBar}" />
<TextBlock FontSize="30"
Text="加载中......"
HorizontalAlignment="Center" />
</StackPanel>
</Border>
</Grid> </Grid>
</Border> </Border>
</UserControl> </UserControl>
+19 -2
View File
@@ -1,4 +1,6 @@
using System; using Prism.Events;
using MainModule.ViewModels;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -12,6 +14,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Navigation; using System.Windows.Navigation;
using System.Windows.Shapes; using System.Windows.Shapes;
using UIShare.PubEvent;
namespace MainModule.Views namespace MainModule.Views
{ {
@@ -20,9 +23,23 @@ namespace MainModule.Views
/// </summary> /// </summary>
public partial class AutomatedTestingView : UserControl public partial class AutomatedTestingView : UserControl
{ {
public AutomatedTestingView() public AutomatedTestingView(IEventAggregator eventAggregator)
{ {
InitializeComponent(); InitializeComponent();
eventAggregator.GetEvent<OverlayEvent>().Subscribe(ShowOverlay);
// 台架级加载遮罩:仅台架名称匹配时响应,避免其他台架/主窗口同时变灰
eventAggregator.GetEvent<ScopeOverlayEvent>().Subscribe(ShowScopeOverlay);
}
private void ShowOverlay(bool arg)
{
Overlay.Visibility = arg ? Visibility.Visible : Visibility.Collapsed;
}
private void ShowScopeOverlay(ScopeOverlayArgs args)
{
// 只处理属于当前台架的遮罩事件(TestStatus 在 OnNavigatedTo 时赋值)
if (DataContext is not AutomatedTestingViewModel vm || vm.TestStatus != args.Scope) return;
Overlay.Visibility = args.Show ? Visibility.Visible : Visibility.Collapsed;
} }
} }
} }
+18
View File
@@ -9,4 +9,22 @@ namespace UIShare.PubEvent
public class OverlayEvent : PubSubEvent<bool> public class OverlayEvent : PubSubEvent<bool>
{ {
} }
/// <summary>
/// 作用域感知的灰度遮罩事件:仅台架名称与 Scope 匹配的台架视图显示/隐藏加载遮罩,
/// 避免全局 OverlayEvent 导致所有台架及主窗口同时变灰。
/// </summary>
public class ScopeOverlayEvent : PubSubEvent<ScopeOverlayArgs>
{
}
/// <summary>作用域遮罩事件参数。</summary>
public class ScopeOverlayArgs
{
/// <summary>台架名称(与 SystemConfig.Title / TestStatus 一致)。</summary>
public string Scope { get; set; } = string.Empty;
/// <summary>true 显示遮罩,false 隐藏遮罩。</summary>
public bool Show { get; set; }
}
} }
+8
View File
@@ -7,6 +7,7 @@
private int _报文ID; private int _报文ID;
private double _时间戳; private double _时间戳;
private byte _长度; private byte _长度;
private string _数据;
// 通道属性 // 通道属性
@@ -37,6 +38,13 @@
set { SetProperty(ref _长度, value); } set { SetProperty(ref _长度, value); }
} }
// 数据属性(原始报文字节十六进制字符串,如 [0x00, 0x01, ...]
public string
{
get { return _数据; }
set { SetProperty(ref _数据, value); }
}
} }
} }
+671
View File
@@ -0,0 +1,671 @@
$ErrorActionPreference = "Stop"
# ============================================================
# 通用模板函数
# ============================================================
function Write-ViewModel {
param(
[string]$ProjectPath, # e.g. "c:\Users\kk\Desktop\BOB"
[string]$ClassName, # e.g. "E36233A"
[string]$DeviceType, # e.g. "可编程直流电源"
[string]$DeviceNamespace, # e.g. "DeviceCommand.Device"
[string]$Properties, # C# property block
[string]$Commands, # ICommand declarations
[string]$CommandInits, # Command initialization in constructor
[string]$ExtraUsings = ""
)
$dir = Join-Path $ProjectPath "DeviceEditModule\ViewModels"
if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
$content = @"
using $DeviceNamespace;
using Prism.Commands;
using Prism.Ioc;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.ViewModelBase;
$ExtraUsings
namespace DeviceEditModule.ViewModels
{
/// <summary>
/// $ClassName $DeviceType ViewModel
/// </summary>
public class ${ClassName}ViewModel : NavigateViewModelBase, IDisposable
{
#region
private readonly DeviceManager _deviceManager;
private ${ClassName}? _device;
private CancellationTokenSource? _cts;
#endregion
#region
private string _deviceName = "$ClassName";
public string DeviceName
{
get => _deviceName;
set => SetProperty(ref _deviceName, value);
}
private bool _isConnected;
public bool IsConnected
{
get => _isConnected;
set => SetProperty(ref _isConnected, value);
}
private bool _isBusy;
/// <summary> true UI </summary>
public bool IsBusy
{
get => _isBusy;
set => SetProperty(ref _isBusy, value);
}
#endregion
$Properties
private string _responseLog = string.Empty;
/// <summary></summary>
public string ResponseLog
{
get => _responseLog;
set => SetProperty(ref _responseLog, value);
}
#endregion
#region
$Commands
#endregion
public ${ClassName}ViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_deviceManager = containerProvider.Resolve<DeviceManager>();
$CommandInits
Initialize();
}
#region / Navigation
public void Initialize(string? deviceName = null)
{
${ClassName}? found = null;
string? foundName = null;
if (deviceName != null &&
_deviceManager.DeviceMap.TryGetValue(deviceName, out var d) &&
d is ${ClassName} e)
{
found = e;
foundName = deviceName;
}
else
{
foreach (var kv in _deviceManager.DeviceMap)
{
if (kv.Value is ${ClassName} it)
{
found = it;
foundName = kv.Key;
break;
}
}
}
_device = found;
DeviceName = foundName ?? "$ClassName ()";
IsConnected = _device?.IsConnected ?? false;
AppendLog(found != null
? $" [{DeviceName}]{(IsConnected ? "" : "")}"
: " DeviceManager $ClassName ");
}
public override void OnNavigatedTo(NavigationContext context)
{
var name = context.Parameters.GetValue<string?>("DeviceName");
Initialize(name);
}
#endregion
#region
private CancellationToken Ct() => (_cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))).Token;
private async Task Exec(Func<Task> action)
{
if (_device == null)
{
AppendLog("");
return;
}
if (IsBusy) return;
IsBusy = true;
try
{
await action();
IsConnected = _device.IsConnected;
}
catch (OperationCanceledException)
{
AppendLog("");
}
catch (Exception ex)
{
AppendLog($"{ex.Message}");
}
finally
{
IsBusy = false;
}
}
private void AppendLog(string message)
{
var line = $"[{DateTime.Now:HH:mm:ss}] {message}";
ResponseLog = ResponseLog.Length > 4000
? line + "\n" + ResponseLog[..3000]
: line + "\n" + ResponseLog;
}
#endregion
public void Dispose()
{
_cts?.Cancel();
_cts?.Dispose();
}
}
}
"@
$file = Join-Path $dir "${ClassName}ViewModel.cs"
[System.IO.File]::WriteAllText($file, $content, [System.Text.Encoding]::UTF8)
Write-Host " Created: $file"
}
function Write-ViewXaml {
param(
[string]$ProjectPath,
[string]$ClassName,
[string]$DeviceTitle, # e.g. "E36233A 可编程直流电源"
[string]$Icon, # e.g. "Flash"
[string]$LeftGroups, # GroupBox XAML blocks for left column
[string]$RightGroups # GroupBox XAML blocks for right column
)
$dir = Join-Path $ProjectPath "DeviceEditModule\Views"
if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
$content = @"
<UserControl x:Class="DeviceEditModule.Views.${ClassName}View"
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:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="False"
d:DesignHeight="760" d:DesignWidth="860">
<UserControl.Resources>
<converters:BooleanToVisibilityConverter x:Key="BoolToVis"/>
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel Margin="12">
<!-- === === -->
<materialDesign:Card Margin="0,0,0,8" Padding="12,8">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<materialDesign:PackIcon Kind="$Icon" Width="22" Height="22"
Foreground="#1565C0" Margin="0,0,8,0"
VerticalAlignment="Center"/>
<TextBlock Text="$DeviceTitle"
FontSize="15" FontWeight="Bold"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding DeviceName, StringFormat=' [{0}]'}"
FontSize="13" Foreground="#757575"
VerticalAlignment="Center" Margin="4,0,0,0"/>
</StackPanel>
<!-- -->
<StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center">
<Border Width="10" Height="10" CornerRadius="5" Margin="0,0,6,0">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="#F44336"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Background" Value="#4CAF50"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<TextBlock VerticalAlignment="Center" FontSize="12">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value=""/>
<Setter Property="Foreground" Value="#F44336"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Text" Value=""/>
<Setter Property="Foreground" Value="#4CAF50"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<!-- -->
<ProgressBar IsIndeterminate="True" Width="80" Height="4"
Margin="12,0,0,0"
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVis}}"/>
</StackPanel>
</Grid>
</materialDesign:Card>
<!-- === 2 === -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- -->
<StackPanel Grid.Column="0" Margin="0,0,4,0">
$LeftGroups
</StackPanel>
<!-- -->
<StackPanel Grid.Column="1" Margin="4,0,0,0">
$RightGroups
</StackPanel>
</Grid>
</StackPanel>
</ScrollViewer>
</UserControl>
"@
$file = Join-Path $dir "${ClassName}View.xaml"
[System.IO.File]::WriteAllText($file, $content, [System.Text.Encoding]::UTF8)
Write-Host " Created: $file"
}
function Write-ViewXamlCs {
param(
[string]$ProjectPath,
[string]$ClassName
)
$dir = Join-Path $ProjectPath "DeviceEditModule\Views"
$content = @"
using System.Windows.Controls;
namespace DeviceEditModule.Views
{
/// <summary>
/// ${ClassName}View.xaml
/// </summary>
public partial class ${ClassName}View : UserControl
{
public ${ClassName}View()
{
InitializeComponent();
}
}
}
"@
$file = Join-Path $dir "${ClassName}View.xaml.cs"
[System.IO.File]::WriteAllText($file, $content, [System.Text.Encoding]::UTF8)
Write-Host " Created: $file"
}
# ============================================================
# XAML 通用片段
# ============================================================
$XamlLogGroup = @"
<!-- -->
<GroupBox Header="" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Orientation="Horizontal" Margin="4,8">
<Button Content=" IDN" Command="{Binding QueryIdentityCommand}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
</GroupBox>
<!-- -->
<GroupBox Header="" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<ScrollViewer Height="260" VerticalScrollBarVisibility="Auto">
<TextBox Text="{Binding ResponseLog, Mode=OneWay}"
materialDesign:HintAssist.Hint=""
IsReadOnly="True"
TextWrapping="Wrap"
FontSize="11"
FontFamily="Consolas"
Background="#FAFAFA"
BorderThickness="0"
VerticalAlignment="Top"/>
</ScrollViewer>
</GroupBox>
"@
function Xaml-OutputControl($onCmd, $offCmd, $onLabel="开启输出", $offLabel="关闭输出") {
return @"
<!-- -->
<GroupBox Header="" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<Button Content="$onLabel" Command="{Binding $onCmd}"
Style="{StaticResource MaterialDesignRaisedButton}"
Background="#388E3C" Foreground="White"
Height="32" Padding="12,0" FontSize="12" Margin="4,0"/>
<Button Content="$offLabel" Command="{Binding $offCmd}"
Style="{StaticResource WarnBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
"@
}
function Xaml-ParamInput($header, $label, $binding, $cmd) {
return @"
<!-- $header -->
<GroupBox Header="$header" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="$label" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding $binding, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="" Command="{Binding $cmd}"
Style="{StaticResource CmdBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
"@
}
function Xaml-Measure($label, $binding, $unit) {
return @"
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="$label" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource MeasureBox}"
materialDesign:HintAssist.Hint=""
Text="{Binding $binding, Mode=OneWay}"/>
<TextBlock Text="$unit" VerticalAlignment="Center" Margin="2,0,8,0"/>
</StackPanel>
"@
}
function Xaml-MeasureGroup($header, $measures, $refreshCmd=$null) {
$refreshBtn = ""
if ($refreshCmd) {
$refreshBtn = @"
<Button Content="" Command="{Binding $refreshCmd}"
Style="{StaticResource CmdBtn}"
HorizontalAlignment="Left" Margin="0,4,0,0"/>
"@
}
return @"
<!-- $header -->
<GroupBox Header="$header" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
$measures
$refreshBtn
</StackPanel>
</GroupBox>
"@
}
# ============================================================
# BOB 设备
# ============================================================
$BOB = "c:\Users\kk\Desktop\BOB"
Write-Host "=== Generating BOB device edit views ==="
# --- 1. E36233A ---
Write-Host "`n--- E36233A ---"
Write-ViewModel -ProjectPath $BOB -ClassName "E36233A" -DeviceType "可编程直流电源" -DeviceNamespace "DeviceCommand.Device" `
-Properties @"
#region
private double _voltage = 0.0;
public double Voltage { get => _voltage; set => SetProperty(ref _voltage, value); }
private double _current = 0.0;
public double Current { get => _current; set => SetProperty(ref _current, value); }
private double _ocpValue = 0.0;
public double OcpValue { get => _ocpValue; set => SetProperty(ref _ocpValue, value); }
private double _ovpValue = 0.0;
public double OvpValue { get => _ovpValue; set => SetProperty(ref _ovpValue, value); }
private int _channel = 1;
public int Channel { get => _channel; set => SetProperty(ref _channel, value); }
#endregion
#region
private double _measuredVoltage;
public double MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); }
private double _measuredCurrent;
public double MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); }
"@ `
-Commands @"
public ICommand QueryIdentityCommand { get; }
public ICommand OutputOnCommand { get; }
public ICommand OutputOffCommand { get; }
public ICommand SetRemoteCommand { get; }
public ICommand SetVoltageCommand { get; }
public ICommand SetCurrentCommand { get; }
public ICommand SetOcpCommand { get; }
public ICommand SetOvpCommand { get; }
public ICommand SetChannelCommand { get; }
public ICommand QueryMeasureCommand { get; }
public ICommand ClearProtectionCommand { get; }
"@ `
-CommandInits @"
QueryIdentityCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.(Ct()))));
OutputOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(true, Ct()); AppendLog(""); }));
OutputOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(false, Ct()); AppendLog(""); }));
SetRemoteCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog(""); }));
SetVoltageCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Voltage, Ct()); AppendLog($" {Voltage} V"); }));
SetCurrentCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Current, Ct()); AppendLog($" {Current} A"); }));
SetOcpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.OCP(OcpValue, Ct()); AppendLog($"OCP {OcpValue} A"); }));
SetOvpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.OVP(OvpValue, Ct()); AppendLog($"OVP {OvpValue} V"); }));
SetChannelCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Channel, Ct()); AppendLog($" {Channel}"); }));
ClearProtectionCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); await _device!.(Ct()); AppendLog(""); }));
QueryMeasureCommand = new DelegateCommand(async () => await Exec(async () =>
{
MeasuredVoltage = await _device!.(Ct());
MeasuredCurrent = await _device!.(Ct());
AppendLog($" -> :{MeasuredVoltage}V :{MeasuredCurrent}A");
}));
"@
Write-ViewXaml -ProjectPath $BOB -ClassName "E36233A" -DeviceTitle "E36233A 可编程直流电源" -Icon "Flash" `
-LeftGroups @"
$(Xaml-OutputControl "OutputOnCommand" "OutputOffCommand")
<!-- -->
<GroupBox Header="" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<TextBox Style="{StaticResource NumInput}"
materialDesign:HintAssist.Hint=""
Text="{Binding Channel, UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="" Command="{Binding SetChannelCommand}" Style="{StaticResource CmdBtn}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<Button Content="" Command="{Binding SetRemoteCommand}" Style="{StaticResource CmdBtn}"/>
<Button Content="" Command="{Binding ClearProtectionCommand}" Style="{StaticResource WarnBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
$(Xaml-ParamInput "电压设置" "电压 (V)" "Voltage" "SetVoltageCommand")
$(Xaml-ParamInput "电流设置" "电流 (A)" "Current" "SetCurrentCommand")
$(Xaml-ParamInput "OCP设置" "OCP (A)" "OcpValue" "SetOcpCommand")
$(Xaml-ParamInput "OVP设置" "OVP (V)" "OvpValue" "SetOvpCommand")
"@ `
-RightGroups @"
$(Xaml-MeasureGroup "实时测量" "$(Xaml-Measure '实际电压' 'MeasuredVoltage' 'V')
$(Xaml-Measure '实际电流' 'MeasuredCurrent' 'A')" "QueryMeasureCommand")
$XamlLogGroup
"@
Write-ViewXamlCs -ProjectPath $BOB -ClassName "E36233A"
# --- 2. EAEL9080 ---
Write-Host "`n--- EAEL9080 ---"
Write-ViewModel -ProjectPath $BOB -ClassName "EAEL9080" -DeviceType "双向可编程直流电源" -DeviceNamespace "DeviceCommand.Device" `
-Properties @"
#region
private double _voltage = 0.0;
public double Voltage { get => _voltage; set => SetProperty(ref _voltage, value); }
private double _current = 0.0;
public double Current { get => _current; set => SetProperty(ref _current, value); }
private double _power = 0.0;
public double Power { get => _power; set => SetProperty(ref _power, value); }
private double _ovpValue = 0.0;
public double OvpValue { get => _ovpValue; set => SetProperty(ref _ovpValue, value); }
private double _ocpValue = 0.0;
public double OcpValue { get => _ocpValue; set => SetProperty(ref _ocpValue, value); }
#endregion
#region
private string _measuredVoltage = "";
public string MeasuredVoltage { get => _measuredVoltage; set => SetProperty(ref _measuredVoltage, value); }
private string _measuredCurrent = "";
public string MeasuredCurrent { get => _measuredCurrent; set => SetProperty(ref _measuredCurrent, value); }
private string _measuredPower = "";
public string MeasuredPower { get => _measuredPower; set => SetProperty(ref _measuredPower, value); }
#endregion
"@ `
-Commands @"
public ICommand QueryIdentityCommand { get; }
public ICommand ResetDeviceCommand { get; }
public ICommand OutputOnCommand { get; }
public ICommand OutputOffCommand { get; }
public ICommand InputOnCommand { get; }
public ICommand InputOffCommand { get; }
public ICommand SetVoltageCommand { get; }
public ICommand SetCurrentCommand { get; }
public ICommand SetPowerCommand { get; }
public ICommand SetOvpCommand { get; }
public ICommand SetOcpCommand { get; }
public ICommand QueryMeasureCommand { get; }
public ICommand RemoteOnCommand { get; }
public ICommand RemoteOffCommand { get; }
"@ `
-CommandInits @"
QueryIdentityCommand = new DelegateCommand(async () => await Exec(async () => AppendLog("IDN: " + await _device!.(Ct()))));
ResetDeviceCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Ct()); AppendLog(""); }));
OutputOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC(true, Ct()); AppendLog("DC"); }));
OutputOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC(false, Ct()); AppendLog("DC"); }));
InputOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC(true, Ct()); AppendLog("DC"); }));
InputOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.DC(false, Ct()); AppendLog("DC"); }));
SetVoltageCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Voltage, Ct()); AppendLog($" {Voltage} V"); }));
SetCurrentCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Current, Ct()); AppendLog($" {Current} A"); }));
SetPowerCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(Power, Ct()); AppendLog($" {Power} W"); }));
SetOvpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(OvpValue, Ct()); AppendLog($"OVP {OvpValue} V"); }));
SetOcpCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(OcpValue, Ct()); AppendLog($"OCP {OcpValue} A"); }));
RemoteOnCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(true, Ct()); AppendLog(""); }));
RemoteOffCommand = new DelegateCommand(async () => await Exec(async () => { await _device!.(false, Ct()); AppendLog(""); }));
QueryMeasureCommand = new DelegateCommand(async () => await Exec(async () =>
{
MeasuredVoltage = await _device!.(Ct());
MeasuredCurrent = await _device!.(Ct());
MeasuredPower = await _device!.(Ct());
AppendLog($" -> :{MeasuredVoltage} :{MeasuredCurrent} :{MeasuredPower}");
}));
"@
Write-ViewXaml -ProjectPath $BOB -ClassName "EAEL9080" -DeviceTitle "EA EL9080 双向可编程直流电源" -Icon "Flash" `
-LeftGroups @"
<!-- / -->
<GroupBox Header="/" Margin="0,0,0,8"
materialDesign:ColorZoneAssist.Mode="PrimaryLight">
<StackPanel Margin="4,4,4,4">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<Button Content="" Command="{Binding OutputOnCommand}"
Style="{StaticResource MaterialDesignRaisedButton}"
Background="#388E3C" Foreground="White" Height="32" Padding="12,0" FontSize="12" Margin="4,0"/>
<Button Content="" Command="{Binding OutputOffCommand}" Style="{StaticResource WarnBtn}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<Button Content="" Command="{Binding InputOnCommand}"
Style="{StaticResource MaterialDesignRaisedButton}"
Background="#1565C0" Foreground="White" Height="32" Padding="12,0" FontSize="12" Margin="4,0"/>
<Button Content="" Command="{Binding InputOffCommand}" Style="{StaticResource WarnBtn}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock Text="" Style="{StaticResource ParamLabel}"/>
<Button Content="" Command="{Binding RemoteOnCommand}" Style="{StaticResource CmdBtn}"/>
<Button Content="" Command="{Binding RemoteOffCommand}" Style="{StaticResource CmdBtn}"/>
<Button Content="" Command="{Binding ResetDeviceCommand}" Style="{StaticResource WarnBtn}"/>
</StackPanel>
</StackPanel>
</GroupBox>
$(Xaml-ParamInput "电压设置" "电压 (V)" "Voltage" "SetVoltageCommand")
$(Xaml-ParamInput "电流设置" "电流 (A)" "Current" "SetCurrentCommand")
$(Xaml-ParamInput "功率设置" "功率 (W)" "Power" "SetPowerCommand")
$(Xaml-ParamInput "OVP设置" "OVP (V)" "OvpValue" "SetOvpCommand")
$(Xaml-ParamInput "OCP设置" "OCP (A)" "OcpValue" "SetOcpCommand")
"@ `
-RightGroups @"
$(Xaml-MeasureGroup "实时测量" "$(Xaml-Measure '实际电压' 'MeasuredVoltage' 'V')
$(Xaml-Measure '实际电流' 'MeasuredCurrent' 'A')
$(Xaml-Measure '实际功率' 'MeasuredPower' 'W')" "QueryMeasureCommand")
$XamlLogGroup
"@
Write-ViewXamlCs -ProjectPath $BOB -ClassName "EAEL9080"
Write-Host "BOB part 1 done (E36233A, EAEL9080)"