Sfoglia il codice sorgente

项目完结

master
小杨 8 mesi fa
parent
commit
ec940cba91
28 ha cambiato i file con 3223 aggiunte e 41 eliminazioni
  1. +7
    -1
      BPA.WeimoCube.sln
  2. +7
    -4
      BPA.WeimoCube/App.xaml
  3. BIN
     
  4. BIN
     
  5. BIN
     
  6. +85
    -0
      BPA.WeimoCube/Assets/Styles/ComboBoxStyles.xaml
  7. +24
    -0
      BPA.WeimoCube/BPA.WeimoCube.csproj
  8. +38
    -0
      BPA.WeimoCube/Common/Command.cs
  9. +82
    -0
      BPA.WeimoCube/Common/Config.cs
  10. +114
    -0
      BPA.WeimoCube/Common/LogProvider.cs
  11. +20
    -0
      BPA.WeimoCube/Common/MessageShow.cs
  12. +34
    -0
      BPA.WeimoCube/Common/NotifyBase.cs
  13. +60
    -0
      BPA.WeimoCube/Common/PanDuanGongJ.cs
  14. +13
    -0
      BPA.WeimoCube/CommunicationClassLibrary/CommunicationLibrary.cs
  15. +0
    -12
      BPA.WeimoCube/MainWindow.xaml
  16. +0
    -24
      BPA.WeimoCube/MainWindow.xaml.cs
  17. +16
    -0
      BPA.WeimoCube/Model/FormulaAttList.cs
  18. +33
    -0
      BPA.WeimoCube/Model/FormulaAttachment.cs
  19. +353
    -0
      BPA.WeimoCube/Model/MainWModel.cs
  20. +53
    -0
      BPA.WeimoCube/Model/RecipeNumberDataType.cs
  21. +854
    -0
      BPA.WeimoCube/ViewModels/MainWindowViewModel.cs
  22. +26
    -0
      BPA.WeimoCube/ViewModels/ViewModelLocator.cs
  23. +984
    -0
      BPA.WeimoCube/Views/MainWindow.xaml
  24. +45
    -0
      BPA.WeimoCube/Views/MainWindow.xaml.cs
  25. +17
    -0
      CommcationLibray/CommcationLibray.csproj
  26. +115
    -0
      CommcationLibray/ModbusBase.cs
  27. +215
    -0
      CommcationLibray/ModbusTCP.cs
  28. +28
    -0
      CommcationLibray/Result.cs

+ 7
- 1
BPA.WeimoCube.sln Vedi File

@@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34607.119
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BPA.WeimoCube", "BPA.WeimoCube\BPA.WeimoCube.csproj", "{2BB3F0FF-6FBD-45EC-9111-DA96D58DDC72}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BPA.WeimoCube", "BPA.WeimoCube\BPA.WeimoCube.csproj", "{2BB3F0FF-6FBD-45EC-9111-DA96D58DDC72}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommcationLibray", "CommcationLibray\CommcationLibray.csproj", "{19E2F031-486A-40C2-9EC5-9158F90F74FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -15,6 +17,10 @@ Global
{2BB3F0FF-6FBD-45EC-9111-DA96D58DDC72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BB3F0FF-6FBD-45EC-9111-DA96D58DDC72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BB3F0FF-6FBD-45EC-9111-DA96D58DDC72}.Release|Any CPU.Build.0 = Release|Any CPU
{19E2F031-486A-40C2-9EC5-9158F90F74FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19E2F031-486A-40C2-9EC5-9158F90F74FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19E2F031-486A-40C2-9EC5-9158F90F74FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19E2F031-486A-40C2-9EC5-9158F90F74FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


+ 7
- 4
BPA.WeimoCube/App.xaml Vedi File

@@ -2,8 +2,11 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BPA.WeimoCube"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
xmlns:vm="clr-namespace:BPA.WeimoCube.ViewModels"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<!--在应用层面实例化Locator对象-->
<vm:ViewModelLocator x:Key="locator"/>
<vm:MainWindowViewModel x:Key="mvm"/>
</Application.Resources>
</Application>

BIN
Vedi File


BIN
Vedi File


BIN
Vedi File


+ 85
- 0
BPA.WeimoCube/Assets/Styles/ComboBoxStyles.xaml Vedi File

@@ -0,0 +1,85 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTemplate x:Key="ComboBoxToggleButton"
TargetType="{x:Type ToggleButton}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.ColumnSpan="2" CornerRadius="3" BorderThickness="1" BorderBrush="#EEE"
Background="#FFF"/>
<Path x:Name="Arrow" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z" Fill="#888">
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="#EEE"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

<ControlTemplate x:Key="ComboBoxTextBox"
TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost"
Focusable="False"
Background="{TemplateBinding Background}" />
</ControlTemplate>

<Style TargetType="ComboBox" x:Key="PropComboBoxStyle">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton x:Name="ToggleButton" Template="{StaticResource ComboBoxToggleButton}"
Focusable="false"
ClickMode="Press"
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter x:Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="5,3"
VerticalAlignment="Center"
HorizontalAlignment="Left">
</ContentPresenter>
<Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True" Focusable="False" PopupAnimation="Slide">
<Grid x:Name="DropDown" SnapsToDevicePixels="True" MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="DropDownBorder" BorderThickness="1" BorderBrush="#FF888888" Background="White">
</Border>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
<Trigger SourceName="Popup" Property="AllowsTransparency" Value="true">
<Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4" />
<Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


</ResourceDictionary>

+ 24
- 0
BPA.WeimoCube/BPA.WeimoCube.csproj Vedi File

@@ -6,6 +6,30 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<None Remove="Assets\Fonts\digital_display.ttf" />
<None Remove="Assets\Fonts\iconfont.ttf" />
<None Remove="Assets\Images\logo.png" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="CommonServiceLocator" Version="2.0.7" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageReference Include="MvvmLight" Version="5.4.1.1" />
<PackageReference Include="MvvmLightLibs" Version="5.4.1.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CommcationLibray\CommcationLibray.csproj" />
</ItemGroup>

<ItemGroup>
<Resource Include="Assets\Fonts\digital_display.ttf" />
<Resource Include="Assets\Fonts\iconfont.ttf" />
<Resource Include="Assets\Images\logo.png" />
</ItemGroup>

</Project>

+ 38
- 0
BPA.WeimoCube/Common/Command.cs Vedi File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 绑定事件
/// </summary>
public class Command : ICommand
{
public event EventHandler? CanExecuteChanged;

public bool CanExecute(object? parameter)
{
if (DoCanExecute == null) return true;
return DoCanExecute.Invoke(parameter);
}

public void Execute(object? parameter)
{
DoExecute?.Invoke(parameter);
}

public Action<object> DoExecute { get; set; }
public Func<object, bool> DoCanExecute { get; set; }

public Command(Action<object> doExecute,Func<object,bool> doCanExecute) {
DoExecute=doExecute;
DoCanExecute=doCanExecute;
}

public Command(Action<object> doExecute) : this(doExecute, null) { }
}
}

+ 82
- 0
BPA.WeimoCube/Common/Config.cs Vedi File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Markup;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 配置ip和端口实体
/// </summary>
public class Config
{/// <summary>
/// ip地址
/// </summary>
public string ModbusTcpIP { get; set; }
/// <summary>
/// 端口号
/// </summary>
public int ModbusTcpPort { get; set; }
/// <summary>
/// 文件保存路径
/// </summary>
public string LogPath { get; set; }
/// <summary>
/// 读取数据长度
/// </summary>
public ushort ReadDataLength { get; set; }
/// <summary>
/// 写入数据长度
/// </summary>
public int WriteDataLength { get; set; }
/// <summary>
/// 配方编号地址
/// </summary>
public string RecipeNumberAddress { get; set; }

/// <summary>
/// 配方编号数据类型id
/// </summary>
public int RecipeDataID { get; set; }
/// <summary>
/// 配方编号数据格式Id
/// </summary>
public int DataFormulasID { get; set; }
/// <summary>
/// 显示订单编号地址
/// </summary>
public string DisplayOrderNumberAddress { get; set; }

/// <summary>
/// 显示订单编号数据类型ID
/// </summary>
public int OrderNumberTypeID { get; set; }
/// <summary>
/// 显示订单编号数据格式ID
/// </summary>
public int OrderNumberDataFormat { get; set; }
/// <summary>
/// 写入编号地址
/// </summary>
public string WriteNumberAddress { get; set; }
/// <summary>
/// 启动配料地址
/// </summary>
public string StartIngredientAddress { get; set; }
/// <summary>
/// 配料完成地址
/// </summary>
public string IngredientCompletionAddress { get; set; }
/// <summary>
/// 设备状态地址
/// </summary>
public string DeviceStatusAddress { get; set; }
/// <summary>
/// 信息错误地址
/// </summary>
public string InformationErrorAddress { get; set; }

}
}

+ 114
- 0
BPA.WeimoCube/Common/LogProvider.cs Vedi File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 日志操作类
/// </summary>
public class LogProvider
{
public string LogPath { get; set; }
private readonly object _lock = new object();

StringBuilder logStr = new StringBuilder();
int count = 0;

public LogProvider(string log_path)
{
LogPath = log_path;
}

public void WriteLog(
string msg,
bool isRecord,
bool isError = false,
[CallerLineNumber] int line = 0,
[CallerMemberName] string methodName = "",
[CallerFilePath] string filePath = "")
{
if (!isRecord) return;

WriteLog(new Log
{
Time = DateTime.Now,
LogType = isError ? LogType.ERROR : LogType.LOG,
Message = msg,

ErrorFile = filePath,
ErroMethod = methodName,
ErrorLineNum = line,
});
}

private void WriteLog(Log log)
{
lock (_lock)
{
count++;
logStr.Append(log.ToString());

if (count >= 100)
{
SaveLog();

count = 0;
logStr.Clear();
}
}
}

public void Dispose()
{
SaveLog();
}

private void SaveLog()
{
string fileName = DateTime.Now.ToString("yyyyMMdd") + ".log";
string filePath = Path.Combine(this.LogPath, fileName);

// 清除3天前日志
string delFile = DateTime.Now.AddDays(-3).ToString("yyyyMMdd") + ".log";
string delFilePath = Path.Combine(this.LogPath, fileName);
if (File.Exists(delFilePath))
File.Delete(delFilePath);

File.AppendAllText(filePath, logStr.ToString());
}
}

internal class Log
{
public DateTime Time { get; set; }
public string Message { get; set; }
public LogType LogType { get; set; }

public string ErrorFile { get; set; }
public string ErroMethod { get; set; }
public int ErrorLineNum { get; set; }

public override string ToString()
{
if (this.LogType == LogType.LOG)
return $"{Time.ToString("yyyy-MM-dd HH:mm:ss")} [{LogType.ToString()}] {Message}\r\n";

if (this.LogType == LogType.ERROR)
return $"{Time.ToString("yyyy-MM-dd HH:mm:ss")} [{LogType.ToString()}] {Message}\r\n" +
$"\t异常文件:{ErrorFile}\r\n" +
$"\t异常位置:{ErroMethod} [Line:{ErrorLineNum}]\r\n";

return base.ToString();
}
}

internal enum LogType
{
LOG, ERROR
}
}

+ 20
- 0
BPA.WeimoCube/Common/MessageShow.cs Vedi File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 公共消息弹窗类
/// </summary>
public class MessageShow
{
public static void GetMessage(string mes)
{
MessageBox.Show(mes);
}
}
}

+ 34
- 0
BPA.WeimoCube/Common/NotifyBase.cs Vedi File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 双向绑定
/// </summary>
public class NotifyBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

public void RaisePropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}

#region 属性设置
public void Set<T>(ref T field, T value, [CallerMemberName] string propName = "")
{
if (!field.Equals(value))
{
field = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
#endregion
}
}

+ 60
- 0
BPA.WeimoCube/Common/PanDuanGongJ.cs Vedi File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;

namespace BPA.WeimoCube.Common
{
/// <summary>
/// 判断工具类
/// </summary>
public class PanDuanGongJ
{
/// <summary>
/// 判断端口号是否正确
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
public static bool IsIPPort(string port)
{

bool isPort = false;
int portNum;
//将字符串转化为整数
isPort = Int32.TryParse(port, out portNum);

if (isPort && portNum >= 0 && portNum <= 65535)
{
isPort = true;
}
else
{
isPort = false;
}
return isPort;
}

/// <summary>
/// 判断ip是否合法
/// </summary>
/// <param name="IP"></param>
public static bool IsIPGf(string IP)
{
bool isIp = false;
string regexStrIPV4 = (@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
if (Regex.IsMatch(IP, regexStrIPV4) && IP != "0.0.0.0")
{
isIp=true;
}
else
{
isIp=false;
}
return isIp;
}
}
}

+ 13
- 0
BPA.WeimoCube/CommunicationClassLibrary/CommunicationLibrary.cs Vedi File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.CommunicationClassLibrary
{
//通讯基类
class CommunicationLibrary
{
}
}

+ 0
- 12
BPA.WeimoCube/MainWindow.xaml Vedi File

@@ -1,12 +0,0 @@
<Window x:Class="BPA.WeimoCube.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BPA.WeimoCube"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>

</Grid>
</Window>

+ 0
- 24
BPA.WeimoCube/MainWindow.xaml.cs Vedi File

@@ -1,24 +0,0 @@
using System.Text;
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 BPA.WeimoCube
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

+ 16
- 0
BPA.WeimoCube/Model/FormulaAttList.cs Vedi File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.Model
{
/// <summary>
/// 配方集合
/// </summary>
public class FormulaAttList
{
public List<FormulaAttachment> FormulaList { get; set; }=new List<FormulaAttachment>();
}
}

+ 33
- 0
BPA.WeimoCube/Model/FormulaAttachment.cs Vedi File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace BPA.WeimoCube.Model
{
/// <summary>
/// 配方附件
/// </summary>
public class FormulaAttachment
{
/// <summary>
/// 配方编号 属性
/// </summary>
public string FormulaNumber { get; set; }
/// <summary>
/// 配方名称
/// </summary>
public string FormulaName { get; set; }
/// <summary>
/// 备用
/// </summary>
public string spare { get; set; }

/// <summary>
/// 序号
/// </summary>
public int SerialNumber { get; set; }
}
}

+ 353
- 0
BPA.WeimoCube/Model/MainWModel.cs Vedi File

@@ -0,0 +1,353 @@
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.Model
{
/// <summary>
/// 主窗口实体模型
/// </summary>
public class MainWModel : ObservableObject
{
public event PropertyChangedEventHandler? PropertyChanged;
private string _ip;
/// <summary>
/// ip地址
/// </summary>
public string Ip
{
get { return _ip; }
set
{
Set<string>(ref _ip, value);
}
}
private string _port;
/// <summary>
/// 端口
/// </summary>
public string Port
{
get { return _port; }
set { Set<string>(ref _port, value); }
}

private string _RecipeNumberAddress;
/// <summary>
/// 配方编号地址
/// </summary>
public string RecipeNumberAddress { get { return _RecipeNumberAddress; } set { Set<string>(ref _RecipeNumberAddress, value); } }

private string _DisplayOrderNumberAddress;
/// <summary>
/// 显示订单编号地址
/// </summary>
public string DisplayOrderNumberAddress { get { return _DisplayOrderNumberAddress; } set { Set<string>(ref _DisplayOrderNumberAddress, value); } }

private string _WriteNumberAddress;
/// <summary>
/// 写入编号地址
/// </summary>
public string WriteNumberAddress { get { return _WriteNumberAddress; } set { Set<string>(ref _WriteNumberAddress, value); } }

private string _StartIngredientAddress;
/// <summary>
/// 启动配料地址
/// </summary>
public string StartIngredientAddress { get { return _StartIngredientAddress; } set { Set<string>(ref _StartIngredientAddress, value); } }

private string _IngredientCompletionAddress;
/// <summary>
/// 配料完成地址
/// </summary>
public string IngredientCompletionAddress { get { return _IngredientCompletionAddress; } set { Set<string>(ref _IngredientCompletionAddress, value); } }

private string _DeviceStatusAddress;
/// <summary>
/// 设备状态地址
/// </summary>
public string DeviceStatusAddress { get { return _DeviceStatusAddress; } set { Set<string>(ref _DeviceStatusAddress, value); } }

private string _InformationErrorAddress;
/// <summary>
/// 信息错误地址
/// </summary>
public string InformationErrorAddress { get { return _InformationErrorAddress; } set { Set<string>(ref _InformationErrorAddress, value); } }



private bool _TCPCRWIsEnabled = true;
/// <summary>
/// 连接ModbusTcp是否启用
/// </summary>
public bool TCPCRWIsEnabled
{
get { return _TCPCRWIsEnabled; }
set { Set<bool>(ref _TCPCRWIsEnabled, value); }
}

private bool _TCPDRWIsEnabled = false;
/// <summary>
/// 断开连接按钮是否启用
/// </summary>
public bool TCPDRWIsEnabled
{
get { return _TCPDRWIsEnabled; }
set { Set<bool>(ref _TCPDRWIsEnabled, value); }
}


private bool _isStart =true;
/// <summary>
/// 是否监控
/// </summary>
public bool IsStart
{
get { return _isStart; }
set
{
Set<bool>(ref _isStart, value);
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsStart"));
if (!value)
{
this.ShowMessage("监控未开始,请打开监控开关",false);
this.ConnectionStatus = value;
}

}
}

private bool _ConnectionStatus;
/// <summary>
/// 连接状态
/// </summary>
public bool ConnectionStatus
{
get { return _ConnectionStatus; }
set { Set<bool>(ref _ConnectionStatus, value); }
}

private int _WriteDataLength;
/// <summary>
/// 写入数据长度
/// </summary>
public int WriteDataLength
{
get { return _WriteDataLength; }
set {Set<int>(ref _WriteDataLength , value); }
}

private ushort _ReadDataLength;
/// <summary>
/// 读取数据长度
/// </summary>
public ushort ReadDataLength
{
get { return _ReadDataLength; }
set {Set<ushort>(ref _ReadDataLength , value); }
}



private object _CurrentOrderNumber;
/// <summary>
/// 当前订单编号
/// 可以用于显示当前的订单编号
/// </summary>
public object CurrentOrderNumber
{
get { return _CurrentOrderNumber; }
set { Set(ref _CurrentOrderNumber, value); }
}


private object _FormulaNumber ;
/// <summary>
/// 配方编号
/// 需要调用的配方编号(编号来源见附件)
/// </summary>
public object FormulaNumber
{
get { return _FormulaNumber; }
set { Set(ref _FormulaNumber, value); }
}

private bool _DetermineWriteNumber;
/// <summary>
/// 确定写入编号
/// 确认配方数据,并下发到配料机
/// </summary>
public bool DetermineWriteNumber
{
get { return _DetermineWriteNumber; }
set { Set(ref _DetermineWriteNumber, value); }
}

private bool _StartingIngredients;
/// <summary>
/// 启动配料
/// 根据当前选择配方启动配料(当前模式不需要使用该功能,预留)
/// </summary>
public bool StartingIngredients
{
get { return _StartingIngredients; }
set { Set(ref _StartingIngredients, value); }
}

private bool _IngredientsCompleted;
/// <summary>
/// 配料完成
/// 启动配料后,待动作完成该值为True,再次执行配料请求为False
/// </summary>
public bool IngredientsCompleted
{
get { return _IngredientsCompleted; }
set { Set(ref _IngredientsCompleted, value); }
}

private bool _DeviceStatus;
/// <summary>
/// 设备状态
/// 上电为False,推送了订单为True
/// </summary>
public bool DeviceStatus
{
get { return _DeviceStatus; }
set { Set(ref _DeviceStatus, value); }
}

private string _TopDianState;
/// <summary>
/// 设备上电状态显示
/// </summary>
public string TopDianState
{
get { return _TopDianState; }
set { Set(ref _TopDianState, value); }
}

private string _OrderPushState;
/// <summary>
/// 订单推送状态显示
/// </summary>
public string OrderPushState
{
get { return _OrderPushState; }
set { Set(ref _OrderPushState, value); }
}

private bool _InformationError;
/// <summary>
/// 信息错误
/// 点击了取消配料,该标志位为True.上位机收到信息后主动置False
/// </summary>
public bool InformationError
{
get { return _InformationError; }
set { Set(ref _InformationError, value); }
}


private bool _isLog;
/// <summary>
/// 打开日志
/// </summary>
public bool IsLog
{
get { return _isLog; }
set
{
Set<bool>(ref _isLog, value);
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsLog"));
}
}

private int _blurRadius = 0;
/// <summary>
/// 主界面的 模糊半径
/// </summary>
public int BlurRadius
{
get { return _blurRadius; }
set
{

Set<int>(ref _blurRadius, value);
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("BlurRadius"));
}
}

private DateTime _currentDate;
/// <summary>
/// 当前时间
/// </summary>
public DateTime CurrentDate
{
get { return _currentDate; }
set
{
//_currentDate = value;
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentDate"));
Set<DateTime>(ref _currentDate, value);

}
}


private string _message;
/// <summary>
/// 错误信息
/// </summary>
public string Message
{
get { return _message; }
set
{
//_message = value;
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Message"));
Set<string>(ref _message, value);

}
}
private string _msgColor = "#90EE90";
/// <summary>
/// 错误信息颜色
/// </summary>
public string MsgColor
{
get { return _msgColor; }
set
{
//_msgColor = value;
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MsgColor"));
Set<string>(ref _msgColor, value);

}
}

private string _logPath;
/// <summary>
/// 保存日志路径
/// </summary>
public string LogPath
{
get { return _logPath; }
set
{
Set<string>(ref _logPath, value);
//PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("LogPath"));
}
}

public void ShowMessage(string message, bool state = true)
{
this.Message = message;
this.MsgColor = state ? "#90EE90" : "#FF4500";
}

}
}

+ 53
- 0
BPA.WeimoCube/Model/RecipeNumberDataType.cs Vedi File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.Model
{
/// <summary>
/// 配方编号数据类型 下拉框实体
/// </summary>
public class RecipeNumberDataType
{
/// <summary>
/// id
/// </summary>
public int ID { get; set; }
/// <summary>
/// 数据类型名称显示
/// </summary>
public string DataName { get; set; }
}

/// <summary>
/// 数据格式 下拉框实体
/// </summary>
public class FormulaNumberDataFormat
{
/// <summary>
/// id
/// </summary>
public int FormatID { get; set; }
/// <summary>
/// 数据格式名称显示
/// </summary>
public string DataFormatName { get; set; }
}


public enum DirectionType : int
{
Byte = 0,
Int = 1,
Uint = 2,
Short = 3,
Ushort = 4,
Float = 5,
String = 6,
Bool = 7,
Double=8,
}

}

+ 854
- 0
BPA.WeimoCube/ViewModels/MainWindowViewModel.cs Vedi File

@@ -0,0 +1,854 @@
using BPA.Helper;
using BPA.WeimoCube.Common;
using BPA.WeimoCube.Model;
using CommcationLibray;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using S7.Net.Types;
using SharpCompress.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ThingsGateway.Foundation.Core;
using ThingsGateway.Foundation.Extension;

namespace BPA.WeimoCube.ViewModels
{
/// <summary>
/// 主实体视图模型
/// </summary>
public class MainWindowViewModel : ObservableObject
{
#region 属性
//配方附件
public ObservableCollection<FormulaAttachment> formulaAttachment { get; set; } = new ObservableCollection<FormulaAttachment>();
/// <summary>
/// 数据类型
/// </summary>
public ObservableCollection<RecipeNumberDataType> dataTypes { get; set; } = new ObservableCollection<RecipeNumberDataType>();
/// <summary>
/// 数据格式
/// </summary>
public ObservableCollection<FormulaNumberDataFormat> formulas { get; set; } = new ObservableCollection<FormulaNumberDataFormat>();

private List<Task> tasks = new List<Task>();
private CancellationTokenSource cts = new CancellationTokenSource();
private ModbusTCP modbus = new ModbusTCP();
/// <summary>
/// 实例主窗口实体类
/// </summary>
public MainWModel MainWModel { get; set; } = new MainWModel();
/// <summary>
/// 日志操作类
/// </summary>
private LogProvider LogProvider;

/// <summary>
/// 连接ModbusTcp 事件
/// </summary>
public RelayCommand<object> ConnectMTCPCommand { get; set; }
/// <summary>
/// 定义设置事件
/// </summary>
public RelayCommand<object> ConfigCommand { get; set; }
/// <summary>
/// 定义关闭设置配置事件
/// </summary>
public RelayCommand<object> ConfigCloseCommand { get; set; }
/// <summary>
/// 定义开打文件夹事件
/// </summary>
public RelayCommand<object> LogPathSelectCommand { get; set; }
/// <summary>
/// 打开日志事件
/// </summary>
public RelayCommand<object> OpenLogPathCommand { get; set; }
/// <summary>
/// 定义写入编号事件
/// </summary>
public RelayCommand<object> WriteNumberCommand { get; set; }
/// <summary>
/// 定义确定写入编号事件
/// </summary>
public RelayCommand<object> DetermineWriteNumberCommand { get; set; }
/// <summary>
/// 定义启动配料事件
/// </summary>
public RelayCommand<object> StartingIngredientsCommand { get; set; }
/// <summary>
/// 定义打开配料附件事件
/// </summary>
public RelayCommand<object> OpenIngredientAttachmentCommand { get; set; }
/// <summary>
/// 附件列表行点击事件
/// </summary>
public RelayCommand<object> DoubleClickCommand { get; set; }
/// <summary>
/// 定义退出事件
/// </summary>
public RelayCommand<object> CloseCommand { get; set; }

/// <summary>
/// 订单推送 标志位
/// 0表示已推送
/// 1表示已完成
/// </summary>
private int OrderPushStatus = 0;
/// <summary>
/// 确定写入编号的记录 ,如果当前订单还没操作 不能进行第二次写入
/// </summary>
private bool DetermineWriteStatus = false;
/// <summary>
/// 设备状态 为false 可以继续派发下一个订单
/// </summary>
private bool DeviceStatus;
/// <summary>
/// 是否取消订单
/// </summary>
private bool WhetherCancel;

private RecipeNumberDataType _dataType;
/// <summary>
/// 数据类型下拉值初始显示
/// </summary>
public RecipeNumberDataType DataType
{
get => _dataType;
set { Set<RecipeNumberDataType>(ref _dataType, value); }
}

private FormulaNumberDataFormat _dataFormulas;
/// <summary>
/// 数据格式下拉值初始显示
/// </summary>
public FormulaNumberDataFormat DataFormulas
{
get { return _dataFormulas; }
set { Set<FormulaNumberDataFormat>(ref _dataFormulas, value); }
}

private RecipeNumberDataType _OrderNumberType;
/// <summary>
/// 数据类型下拉值初始显示
/// </summary>
public RecipeNumberDataType OrderNumberType
{
get => _OrderNumberType;
set { Set<RecipeNumberDataType>(ref _OrderNumberType, value); }
}

private FormulaNumberDataFormat _OrderNumberData;
/// <summary>
/// 数据格式下拉值初始显示
/// </summary>
public FormulaNumberDataFormat OrderNumberData
{
get { return _OrderNumberData; }
set { Set<FormulaNumberDataFormat>(ref _OrderNumberData, value); }
}


#endregion

public MainWindowViewModel()
{
var task = Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
MainWModel.CurrentDate = System.DateTime.Now;
await Task.Delay(new TimeSpan(1, 0, 0));
}
}, cts.Token);
tasks.Add(task);
LogProvider = new LogProvider(MainWModel.LogPath);

this.RaisePropertyChanged("MainWModel");
ConnectMTCPCommand = new RelayCommand<object>(new Action<object>(DoConnectModbusTcpCommand));
ConfigCommand = new RelayCommand<object>(new Action<object>(Config));
ConfigCloseCommand = new RelayCommand<object>(new Action<object>(ConfigClose));
LogPathSelectCommand = new RelayCommand<object>(new Action<object>(LogPathSelect));
OpenLogPathCommand = new RelayCommand<object>(new Action<object>(OpenLogFolder));
WriteNumberCommand = new RelayCommand<object>(new Action<object>(WriteNumber));

DetermineWriteNumberCommand = new RelayCommand<object>(new Action<object>(DetermineWriteNumber));
StartingIngredientsCommand = new RelayCommand<object>(new Action<object>(StartingIngredients));
OpenIngredientAttachmentCommand = new RelayCommand<object>(new Action<object>(OpenIngredientAttachment));

DoubleClickCommand = new RelayCommand<object>(param => RowClick(param), param => true);

CloseCommand = new RelayCommand<object>(new Action<object>(Close));

this.SetRecipeNumberTypeData();
this.SetFormulaNumberDataFormat();
this.ChuShiHuaConfigData();
this.GetFormulaData();
this.StartMointor();
//MainWModel.IsStart = true;
}
/// <summary>
/// 附件列表行点击事件
/// </summary>
/// <param name="parameter"></param>
private void RowClick(object parameter)
{
var selectedItem = (FormulaAttachment)parameter;
try
{
MainWModel.FormulaNumber = (short)Convert.ToInt32(selectedItem.FormulaNumber);
}
catch (Exception ex)
{
MessageError($"配方编号类型转换失败!!! 失败信息:{ex.Message} + {selectedItem.ToString()}");
}

}

/// <summary>
/// 初始化配置文件数据
/// </summary>
private void ChuShiHuaConfigData()
{
// 配置数据的初始化
try
{
string json = File.ReadAllText("config.json");
Config config = System.Text.Json.JsonSerializer.Deserialize<Config>(json);
MainWModel.Ip = config.ModbusTcpIP;
MainWModel.Port = config.ModbusTcpPort.ToString();
MainWModel.LogPath = config.LogPath;

MainWModel.RecipeNumberAddress = config.RecipeNumberAddress;
MainWModel.DisplayOrderNumberAddress = config.DisplayOrderNumberAddress;
MainWModel.WriteNumberAddress = config.WriteNumberAddress;
MainWModel.StartIngredientAddress = config.StartIngredientAddress;
MainWModel.IngredientCompletionAddress = config.IngredientCompletionAddress;
MainWModel.DeviceStatusAddress = config.DeviceStatusAddress;
MainWModel.InformationErrorAddress = config.InformationErrorAddress;

MainWModel.ReadDataLength = config.ReadDataLength;
MainWModel.WriteDataLength = config.WriteDataLength;

DataType = dataTypes.First(m => m.ID == config.RecipeDataID);//绑定到下拉框显示的值
DataFormulas = formulas.First(m => m.FormatID == config.DataFormulasID);

OrderNumberType = dataTypes.First(m => m.ID == config.OrderNumberTypeID);//绑定到下拉框显示的值
OrderNumberData = formulas.First(m => m.FormatID == config.OrderNumberDataFormat);
}
catch (Exception ex)
{
MainWModel.ShowMessage("初始化参数加载失败," + ex.Message, false);
//return;
}
}

/// <summary>
/// 初始数据类型
/// </summary>
private void SetRecipeNumberTypeData()
{
dataTypes.Clear();
int i = 0;
foreach (DirectionType type in Enum.GetValues(typeof(DirectionType)))
{
dataTypes.Add(new RecipeNumberDataType
{
ID = i,
DataName = type.ToString()
});
i++;
}
}

/// <summary>
/// 初始数据格式
/// </summary>
private void SetFormulaNumberDataFormat()
{
formulas.Clear();
int i = 0;
foreach (BPADataFormat item in Enum.GetValues(typeof(BPADataFormat)))
{
formulas.Add(new FormulaNumberDataFormat
{
FormatID = i,
DataFormatName = item.ToString()
});
i++;
}
}

/// <summary>
/// 初始化配方数据
/// </summary>
private void GetFormulaData()
{
try
{
formulaAttachment.Clear();//先清除集合
string jsons = File.ReadAllText("Formula.json");
FormulaAttList configs = System.Text.Json.JsonSerializer.Deserialize<FormulaAttList>(jsons);
configs.FormulaList.ForEach(s =>
{
formulaAttachment.Add(new FormulaAttachment
{
FormulaName = s.FormulaName,
FormulaNumber = s.FormulaNumber,
SerialNumber = s.SerialNumber,
spare = s.spare,
});
});
}
catch (Exception ex)
{

MainWModel.ShowMessage("初始化配方数据加载失败," + ex.Message, false);
}

}

/// <summary>
/// 打开配料附件配置文件
/// </summary>
/// <param name="text"></param>
private void OpenIngredientAttachment(object text)
{
//D:\黑波罗科技\BPA.WeimoCube\BPA.WeimoCube\bin\Debug\net6.0-windows
string PeiLaoPath = System.IO.Directory.GetCurrentDirectory();
if (Directory.Exists(PeiLaoPath))
{
Process.Start("explorer.exe", PeiLaoPath);
}
}

/// <summary>
/// 打开日志文件
/// </summary>
private void OpenLogFolder(object text)
{
if (Directory.Exists(MainWModel.LogPath))
{
Process.Start("explorer.exe", MainWModel.LogPath);
}
}

/// <summary>
/// 打开文件夹
/// </summary>
/// <param name="text"></param>
private void LogPathSelect(object text)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
//过滤文件类型
//openFileDialog.Filter = "文档(*.txt)|*.txt|所有文件(*.*)|*.*";
//允许多选
openFileDialog.Multiselect = true;
if (openFileDialog.ShowDialog() == true)
{
string paths = Path.GetDirectoryName(openFileDialog.FileName);
//FileName 完整路径:相对路径+文件名+后缀
//文件内容读取
MainWModel.LogPath = paths;
LogProvider.LogPath = MainWModel.LogPath;
//string[] names = openFileDialog.FileNames;
}

}

/// <summary>
/// 点击设置
/// </summary>
/// <param name="text"></param>
private void Config(object text)
{
//MainWModel.IsStart = false;
MainWModel.BlurRadius = 10;
}
/// <summary>
/// 隐藏设置界面
/// </summary>
private void ConfigClose(object text)
{
MainWModel.BlurRadius = 0;

// 数据保存的动作
try
{
Config config = new Config();
config.ModbusTcpIP = MainWModel.Ip;
config.ModbusTcpPort = Convert.ToInt32(MainWModel.Port);
config.LogPath = MainWModel.LogPath;
config.RecipeNumberAddress = MainWModel.RecipeNumberAddress;
config.DisplayOrderNumberAddress = MainWModel.DisplayOrderNumberAddress;
config.WriteNumberAddress = MainWModel.WriteNumberAddress;
config.StartIngredientAddress = MainWModel.StartIngredientAddress;
config.IngredientCompletionAddress = MainWModel.IngredientCompletionAddress;
config.DeviceStatusAddress = MainWModel.DeviceStatusAddress;
config.InformationErrorAddress = MainWModel.InformationErrorAddress;
config.RecipeDataID = DataType.ID;
config.DataFormulasID = DataFormulas.FormatID;
config.OrderNumberTypeID = OrderNumberType.ID;
config.OrderNumberDataFormat = OrderNumberData.FormatID;

config.ReadDataLength = MainWModel.ReadDataLength;
config.WriteDataLength= MainWModel.WriteDataLength;
// Framework Nuget:安装 Newtonsoft.Json 库,参照472版本的程序
var json = System.Text.Json.JsonSerializer.Serialize(config);
File.WriteAllText("config.json", json);

LogProvider.WriteLog("配置文件修改完成", MainWModel.IsLog);
}
catch (Exception ex)
{
LogProvider.WriteLog("写配置文件失败!" + ex.Message, MainWModel.IsLog, isError: true);
MainWModel.ShowMessage("写配置文件失败!" + ex.Message, false);
}

}

/// <summary>
/// 实现 连接modbusTcp 按钮事件
/// </summary>
/// <param name="text"></param>
private void DoConnectModbusTcpCommand(object text)
{

//if (TiJiaoPanDuan())
//{
// modbus.ConnectModbusTcp(MainWModel.Ip, Convert.ToInt32(MainWModel.Port));
// MainWModel.TCPDRWIsEnabled = true;
//}
}

/// <summary>
/// 开启监听
/// </summary>
private void StartMointor()
{

bool connctionSoss = false;
var task = Task.Factory.StartNew(async () =>
{
while (!cts.IsCancellationRequested)
{
//Debug.WriteLine("开启监听");
var state = new CommcationLibray.Result();
await Task.Delay(400);
if (!MainWModel.IsStart) continue;
if (MainWModel.ConnectionStatus) continue;
if (TiJiaoPanDuan())
{
try
{
if (!connctionSoss)
MainWModel.ShowMessage("连接中.......");

Application.Current.Dispatcher.Invoke(new Action(async () =>
{
state = await modbus.ConnectModbusTcp(MainWModel.Ip, Convert.ToInt32(MainWModel.Port));
}), System.Windows.Threading.DispatcherPriority.SystemIdle, null);


await Task.Delay(500);

if (!state.State)
{
MainWModel.ShowMessage("连接失败", false);
MainWModel.ConnectionStatus = state.State;
connctionSoss = false;
}
else
{
connctionSoss = true;
MainWModel.ConnectionStatus = state.State;
MainWModel.ShowMessage("连接成功");
this.GetInformationError();
this.GetDeviceStatus();
}

}
catch (Exception ex)
{
MessageError($"连接失败!!! 失败信息:{ex.Message}");
}
}
}
}, cts.Token);
tasks.Add(task);
}


/// <summary>
/// 点击了取消配料,该标志位为True.上位机收到信息后主动置False
/// </summary>
private void GetInformationError()
{
var task = Task.Factory.StartNew(async () =>
{
while (!cts.IsCancellationRequested)
{
await Task.Delay(400);
try
{
if (!IsState()) return;
var Result = new CommcationLibray.Result();
Result = modbus.ReadCancelIngredients(MainWModel.InformationErrorAddress);
if (!Result.State)
{
MessageError($"获取取消配料数据失败!!! 失败信息:{Result.Exception}");
}
else
{
//为1说明点击了取消配料
if ((bool)Result.Datas)
{
this.WhetherCancel = true;
this.WriteInformationError();
MainWModel.OrderPushState = $"订单->{MainWModel.CurrentOrderNumber}已取消!";
MessageBox.Show($"当前订单-> {MainWModel.CurrentOrderNumber} 已取消!");
}
}
}
catch (Exception ex)
{
MessageError($"获取取消配料数据失败!!! 失败信息:{ex.Message}");
}
}
}, cts.Token);
tasks.Add(task);
}

/// <summary>
/// 循环获取设备状态
/// </summary>
private void GetDeviceStatus()
{
var task = Task.Factory.StartNew(async () =>
{
while (!cts.IsCancellationRequested)
{
await Task.Delay(400);
try
{
if (!IsState()) return;
var Result = new CommcationLibray.Result();
Result = modbus.ReadDeviceStatus(MainWModel.DeviceStatusAddress);
if (!Result.State)
{
MessageError($"获取设备状态数据失败!!! 失败信息:{Result.Exception}");
}
else
{
this.DeviceStatus = (bool)Result.Datas;
this.StateFanKui((bool)Result.Datas);
}
}
catch (Exception ex)
{
MessageError($"获取设备状态数据失败!!! 失败信息:{ex.Message}");
}
}
}, cts.Token);
tasks.Add(task);
}


/// <summary>
/// 点击取消配料时 上位机自动触发 设置值为false
/// </summary>
private void WriteInformationError()
{
if (!IsState()) return;
var Result = new CommcationLibray.Result();
Result = modbus.WriteCancelIngredients(MainWModel.InformationErrorAddress, false);
if (!Result.State)
{
MessageError($"写入读取配料状态失败!!! 失败信息:{Result.Exception}");
}
}


/// <summary>
/// 封装读取操作
/// </summary>
/// <param></param>
private void ReadCaoZuo()
{
try
{
switch (OrderNumberType.ID)
{
case 0:
ReadOrders<byte>();
break;
case 1:
ReadOrders<int>();
break;
case 2:
ReadOrders<uint>();
break;
case 3:
ReadOrders<short>();
break;
case 4:
ReadOrders<ushort>();
break;
case 5:
ReadOrders<float>();
break;
case 6:
ReadOrders<string>();
break;
case 7:
ReadOrders<bool>();
break;
case 8:
ReadOrders<double>();
break;
}
}
catch (Exception ex)
{
MessageError($"数据转换失败!!! 失败信息:{ex.Message}");
}
}

/// <summary>
/// 读取订单
/// </summary>
private void ReadOrders<T>()
{
var Result = new CommcationLibray.Result();
Result = modbus.GetOrders<T>(MainWModel.DisplayOrderNumberAddress,MainWModel.ReadDataLength, (BPADataFormat)OrderNumberData.FormatID );//BPADataFormat.CDAB
if (!Result.State)
{
MessageError($"读取订单失败!!! 失败信息:{Result.Exception}");
}
else
{
MainWModel.ShowMessage("读取订单成功");
MainWModel.CurrentOrderNumber = Result.Datas ;
}

}

/// <summary>
/// 写入编号
/// </summary>
/// <param name="test"></param>
private void WriteNumber(object test)
{
WriteCaoZuo(0);

}
/// <summary>
/// 确定写入编号
/// </summary>
/// <param name="test"></param>
private void DetermineWriteNumber(object test)
{
WriteCaoZuo(1);
}

/// <summary>
/// 封装写入操作
/// </summary>
/// <param name="type"> 0 表示写入 ,1表示确定写入</param>
private void WriteCaoZuo(int type)
{
try
{
if (MainWModel.FormulaNumber == null)
{
MessageError($"请输入配方编号!!!");
return;
}
switch (DataType.ID)
{
case 0:
WriteCaoZuoDataType(type, Convert.ToByte(MainWModel.FormulaNumber));
break;
case 1:
WriteCaoZuoDataType(type, Convert.ToInt32(MainWModel.FormulaNumber));
break;
case 2:
WriteCaoZuoDataType(type, Convert.ToUInt32(MainWModel.FormulaNumber));
break;
case 3:
WriteCaoZuoDataType(type, (short)Convert.ToInt32(MainWModel.FormulaNumber));
break;
case 4:
WriteCaoZuoDataType(type, (ushort)Convert.ToInt32(MainWModel.FormulaNumber));
break;
case 5:
WriteCaoZuoDataType(type, (float)Convert.ToDouble(MainWModel.FormulaNumber));
break;
case 6:
WriteCaoZuoDataType(type, Convert.ToString(MainWModel.FormulaNumber));
break;
case 7:
WriteCaoZuoDataType(type, Convert.ToBoolean(Convert.ToInt32(MainWModel.FormulaNumber)));
break;
case 8:
WriteCaoZuoDataType(type, Convert.ToDouble(MainWModel.FormulaNumber));
break;
}
}
catch (Exception ex)
{
MessageError($"数据转换失败!!! 失败信息:{ex.Message}");
}
}


private void WriteCaoZuoDataType<T>(int type, T values)
{
if (!IsState()) return;
if (!this.DetermineWriteStatus && !this.DeviceStatus)
{
BPADataFormat bPAData = (BPADataFormat)DataFormulas.FormatID;
var Result = new CommcationLibray.Result();
string error = type == 0 ? "写入" : "确定写入";
Result = type == 0 ? modbus.WriteRecipeNumber<T>(MainWModel.RecipeNumberAddress, values, MainWModel.WriteDataLength, (BPADataFormat)DataFormulas.FormatID)
: modbus.DetermineWriteNumberCommand(MainWModel.WriteNumberAddress, true);
if (!Result.State)
{
MessageError($"{error}编号失败!!! 失败信息:{Result.Exception}");
}
else
{
MainWModel.ShowMessage($"{error}编号成功");
if (type == 0)
this.ReadCaoZuo();
else
{
this.DetermineWriteStatus = true;
}
}
}
else
{
MessageBox.Show("请等待上次订单完成后再操作!!!");
}
}

/// <summary>
/// 启动配料
/// </summary>
/// <param name="test"></param>
private void StartingIngredients(object test)
{

}

private void StateFanKui(bool state)
{
switch (state)
{
case false:
MainWModel.TopDianState = "空闲中......";
if (this.DetermineWriteStatus && !this.WhetherCancel)
{
MainWModel.OrderPushState = "已完成";
}
this.DetermineWriteStatus = false;
this.WhetherCancel = false;
break;
case true:
MainWModel.OrderPushState = "已推送";
if (this.DetermineWriteStatus)
{
MainWModel.TopDianState = "待操作";
}
break;
default:
break;
}
}

/// <summary>
/// 错误信息
/// </summary>
/// <param name="error"></param>
private void MessageError(string error)
{
MainWModel.ShowMessage(error, false);
LogProvider.WriteLog(error, MainWModel.IsLog, isError: true);
}

private bool TiJiaoPanDuan()
{
if (string.IsNullOrEmpty(MainWModel.Ip))
{
MainWModel.ShowMessage("请输入IP地址!!!", false);
return false;
}
if (string.IsNullOrEmpty(MainWModel.Port))
{
MainWModel.ShowMessage("请输入端口号!!!", false);

return false;
}
if (!PanDuanGongJ.IsIPGf(MainWModel.Ip))
{
MainWModel.ShowMessage("请输入合法的IP地址!!!", false);

return false;
}
if (!PanDuanGongJ.IsIPPort(MainWModel.Port))
{
MainWModel.ShowMessage("请输入正确的端口号!!!", false);

return false;
}
return true;
}

/// <summary>
/// 判断是否打开监听
/// </summary>
/// <returns></returns>
private bool IsState()
{
if (!MainWModel.IsStart || !MainWModel.ConnectionStatus)
{
MainWModel.ShowMessage("未连接状态!!!", false);
return false;
}
else
{
return true;
}
}
/// <summary>
/// 退出
/// </summary>
/// <param name="text"></param>
private void Close(object text)
{
CancelAllTasksAsync();
}

public void CancelAllTasksAsync()
{
cts?.Cancel();
}
}
}




+ 26
- 0
BPA.WeimoCube/ViewModels/ViewModelLocator.cs Vedi File

@@ -0,0 +1,26 @@
using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BPA.WeimoCube.ViewModels
{
public class ViewModelLocator
{
public ViewModelLocator()
{
// 容器的初始化
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

// 注册主窗体视图模型
SimpleIoc.Default.Register<MainWindowViewModel>();

}

public MainWindowViewModel MainViewModel { get => ServiceLocator.Current.GetInstance<MainWindowViewModel>(); }

}
}

+ 984
- 0
BPA.WeimoCube/Views/MainWindow.xaml Vedi File

@@ -0,0 +1,984 @@
<Window x:Class="BPA.WeimoCube.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BPA.WeimoCube"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d" FontFamily="Microsoft YaHei" FontSize="12" FontWeight="ExtraLight"
Title="MainWindow" Height="650" Width="1200" WindowStyle="None" AllowsTransparency="True" >
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="1" CaptionHeight="50"/>
</WindowChrome.WindowChrome>
<Window.Background>
<RadialGradientBrush Center="0.5,0" GradientOrigin="0.5,-0.5" RadiusX="0.7" RadiusY="1.2">
<GradientStop Color="#FF61BAFF" Offset="0"/>
<GradientStop Color="#FF29384E" Offset="1"/>
</RadialGradientBrush>
</Window.Background>
<Window.Resources>
<FontFamily x:Key="FF">../Assets/Fonts/#iconfont</FontFamily>

<Style TargetType="ToggleButton" x:Key="SwitchButtonStyle">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="#9FFF"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="Margin" Value="5,0"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Background="#1000" CornerRadius="5" Name="root">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="18"/>
</Grid.RowDefinitions>
<Border Height="17" Width="33" CornerRadius="8.5" Background="#FFF" Name="back">
<Grid>
<TextBlock Text="开" FontFamily="9" Foreground="White"
VerticalAlignment="Center" HorizontalAlignment="Left"
Margin="5,0"/>
<TextBlock Text="关" FontFamily="9" Foreground="Gray"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="5,0"/>
<Ellipse Width="15" Height="15" Fill="#DDD"
Margin="1,0" HorizontalAlignment="Left" Name="ellipse"/>
</Grid>
</Border>

<ContentPresenter Grid.Row="1"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</Border>

<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="root" Property="Background" Value="#2000"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="back" Property="Background" Value="Orange"/>
<Setter TargetName="ellipse" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="ellipse" Property="Fill" Value="white"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style TargetType="Button" x:Key="ControlButtonStyle">
<Setter Property="Width" Value="50"/>
<Setter Property="Margin" Value="5,0"/>
<Setter Property="Background" Value="#1000"/>
<Setter Property="Foreground" Value="#9FFF"/>
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" CornerRadius="5">
<Border Background="Transparent" Name="bor" CornerRadius="5">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bor" Property="Background" Value="#2000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btnConfig">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation To="0,0,0,0" Duration="0:0:0.3"
Storyboard.TargetName="bor_config"
Storyboard.TargetProperty="Margin"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="btnConfigClose">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation To="0,0,-250,0" Duration="0:0:0.3"
Storyboard.TargetName="bor_config"
Storyboard.TargetProperty="Margin"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>

<Grid DataContext="{Binding Source={StaticResource mvm}}">

<Ellipse Width="120" Height="120" VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="-20" Fill="#06000000"/>
<Ellipse Width="180" Height="150" VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="30,-100,0,0" Fill="#08000000"/>
<Ellipse Width="50" Height="50" VerticalAlignment="Top" HorizontalAlignment="Left"
Margin="20,90,0,0" Fill="#06FFFFFF"/>


<Grid Margin="20,0">
<Grid.Effect>
<BlurEffect Radius="{Binding MainWModel.BlurRadius}"/>
</Grid.Effect>
<Grid.RowDefinitions>
<RowDefinition Height="65"/>
<RowDefinition Height="40"/>
<RowDefinition/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>

<!--第一行信息-->
<Border Height="1" VerticalAlignment="Bottom" >
<Border.Background>
<RadialGradientBrush RadiusX="0.7">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#0FFFFFFF" Offset="0.3"/>
<GradientStop Color="#0FFF" Offset="1"/>
</RadialGradientBrush>
</Border.Background>
</Border>

<StackPanel Orientation="Horizontal">
<StackPanel.Effect>
<DropShadowEffect BlurRadius="5" Color="Black" ShadowDepth="0" Opacity="0.5"/>
</StackPanel.Effect>
<Image Source="../Assets/Images/Logo.png" Width="125" Height="65"/>
<TextBlock Text="黑菠萝" Foreground="#DD87E8EC" FontSize="20"
FontWeight="Black" VerticalAlignment="Center" Margin="15,0"/>
</StackPanel>

<TextBlock Text="配料监控系统(MODBUS-TCP)" VerticalAlignment="Center"
FontWeight="Black" HorizontalAlignment="Center" FontSize="30" >
<TextBlock.Effect>
<DropShadowEffect BlurRadius="5" Color="Black" ShadowDepth="0" Opacity="0.5"/>
</TextBlock.Effect>
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="Gold" Offset="0"/>
<GradientStop Color="Orange" Offset="1"/>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>

<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right">
<ToggleButton Content="监控" Style="{StaticResource SwitchButtonStyle}"
IsChecked="{Binding MainWModel.IsStart}"/>
<ToggleButton Content="日志" Style="{StaticResource SwitchButtonStyle}"
IsChecked="{Binding MainWModel.IsLog}"/>

<Button Style="{StaticResource ControlButtonStyle}"
Name="btnConfig" Command="{Binding ConfigCommand}">
<StackPanel>
<TextBlock Text="&#xe70f;" FontFamily="{StaticResource FF}"
FontSize="20" Margin="0,5,0,3"/>
<TextBlock Text="设置" FontSize="9" HorizontalAlignment="Center" Margin="0,0,0,5"/>
</StackPanel>
</Button>
<Button Style="{StaticResource ControlButtonStyle}" CommandParameter="{x:Null}" Command="{Binding CloseCommand}" x:Name="close" Click="Button_Click">
<StackPanel>
<TextBlock Text="&#xe67d;" FontFamily="{StaticResource FF}"
FontSize="20" Margin="0,5,0,3"/>
<TextBlock Text="退出" FontSize="9" HorizontalAlignment="Center" Margin="0,0,0,5"/>
</StackPanel>
</Button>
</StackPanel>

<!--第二行信息-->
<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Left" Orientation="Horizontal">
<TextBlock Text="&#xe695;" FontFamily="{StaticResource FF}"
FontSize="22" Foreground="Gold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{Binding MainWModel.CurrentDate,StringFormat={}{0:yyyy年MM月dd日 dddd},ConverterCulture=zh-CN}" VerticalAlignment="Center" Margin="10,0" FontWeight="Black" FontSize="24" Foreground="#8FFF"/>
</StackPanel>

<StackPanel Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right" Orientation="Horizontal"
TextBlock.Foreground="{Binding MainWModel.MsgColor}">
<StackPanel.Effect>
<DropShadowEffect BlurRadius="5" Color="Gray" ShadowDepth="0" Opacity="0.3"/>
</StackPanel.Effect>
<TextBlock Text="&#xe600;" FontFamily="{StaticResource FF}" FontSize="22" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{Binding MainWModel.Message}" FontWeight="Black" VerticalAlignment="Center" FontSize="24" Margin="10,0"/>
</StackPanel>

<!--第三行-->

<UniformGrid Columns="2" Rows="1" Grid.Row="2">

<Border CornerRadius="5" Background="#1000" BorderThickness="0.5" Margin="10">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#87E8EC" Offset="0"/>
<GradientStop Color="Transparent" Offset="0.3"/>
<GradientStop Color="Transparent" Offset="0.8"/>
<GradientStop Color="#87E8EC" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>

<Grid Margin="10,0">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!--从站编号-->
<TextBlock Text="{Binding SlaveId,StringFormat={}{0:00} - 号从站}"
VerticalAlignment="Center" Foreground="#9987E8EC"
FontWeight="Normal"/>
<!--配料基础信息-->
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center" HorizontalAlignment="Right"
Grid.Column="1">
<Border Width="10" Height="10" Background="Orange" Margin="5,0"/>
<TextBlock Text="配料基础信息" FontWeight="Black" Foreground="#9FFF" FontSize="20"/>
</StackPanel>

<!--附件显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="1" Margin="0,0,0,5">
<Grid ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="&#xe618;" FontFamily="{StaticResource FF}"
Grid.RowSpan="2" FontSize="120"
Margin="-40,10,0,0"
Foreground="#09FFFFFF"/>
<Border HorizontalAlignment="Center" VerticalAlignment="Top"
Background="#BF90"
CornerRadius="0,0,5,5">
<TextBlock Text="附件" Margin="15,3"
FontWeight="Black" FontSize="18" Foreground="White"/>
</Border>

<TextBlock Grid.Row="3" Margin="5,170" TextWrapping="Wrap" VerticalAlignment="Bottom" Foreground="#5bae23" Text="1.点击打开配料附件按钮,即可自动打开配料配置文件所在的目录。" />
<TextBlock Grid.Row="3" Margin="5,120" TextWrapping="Wrap" VerticalAlignment="Bottom" Foreground="#5bae23" Text="2.在当前目录中找到文件名为 Formula.json 是配置文件。" />
<TextBlock Grid.Row="3" Margin="5,85" TextWrapping="Wrap" VerticalAlignment="Bottom" Foreground="#5bae23" Text="3.打开文件可以修改里面内容数据。" />
<TextBlock Grid.Row="3" Margin="5,65" TextWrapping="Wrap" VerticalAlignment="Bottom" Foreground="#5bae23" Text="4.修改完成后保存即可。" />

<Grid Grid.Row="3" Margin="0,10" VerticalAlignment="Bottom">

<Button Content="打开配料附件" Grid.Column="0" Grid.Row="0" Background="#38ada9"
Style="{StaticResource ControlButtonStyle}"
FontSize="18" FontWeight="Black" Margin="2" Width="130" Height="40" Foreground="Wheat"
Command="{Binding OpenIngredientAttachmentCommand}"/>

</Grid>


</Grid>
</Border>
<TextBlock Grid.Row="1" VerticalAlignment="Center"
HorizontalAlignment="Center" FontSize="30"
Margin="0,20,0,0"
FontFamily="../Assets/Fonts/#Digital Display"
Text="{Binding Temperature,StringFormat={}{0:0.0}}"
Foreground="White"/>

<!--附件显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="2" Margin="0,0,0,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xe642;" FontFamily="{StaticResource FF}"
VerticalAlignment="Center" HorizontalAlignment="Left"
Foreground="Orange" FontSize="14" Margin="10,0"/>
<TextBlock Grid.Column="1">
<Run Text="{Binding Humidity,StringFormat={}{0:0.0}}" FontSize="18" Foreground="#AFFF"
FontWeight="Normal"/>
<Run Text="%" FontSize="11" Foreground="#7FFF"/>
</TextBlock>

<TextBlock Text="附件" Grid.Column="2"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="10,0" Foreground="#2FFF"/>
</Grid>
</Border>

<Border CornerRadius="5" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2" Background="#1000" Margin="5,0,0,5">
<!--<GroupBox Header="附件:" Background="#1000" FontSize="20" FontWeight="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0">-->

<ListView x:Name="listviews" Background="#2001" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding formulaAttachment}" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Margin="5,5,5,5">
<!--行双击事件-->
<b:Interaction.Triggers>
<b:EventTrigger EventName="MouseDoubleClick">
<b:InvokeCommandAction Command="{Binding DoubleClickCommand}" CommandParameter="{Binding ElementName=listviews, Path=SelectedItem}"/>
</b:EventTrigger>
</b:Interaction.Triggers>

<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding ="{Binding SerialNumber}" Width="0"/>
<GridViewColumn Width="130">
<GridViewColumn.Header>
<TextBlock Width="130" TextAlignment="Center" FontSize="20" Foreground="#e58e26" FontWeight="Black">配方编号</TextBlock>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate >
<TextBlock TextWrapping="Wrap" Margin="30,0,0,0" FontSize="18" Foreground="#f8df72" TextAlignment="Center" Text="{Binding FormulaNumber}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="150">
<GridViewColumn.Header>
<TextBlock Width="auto" FontSize="20" FontWeight="Black" Foreground="#e58e26" TextAlignment="Center">配方名称</TextBlock>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Margin="20,0,0,0" FontSize="18" Foreground="#f8df72" TextAlignment="Center" Text="{Binding FormulaName}" ></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

<GridViewColumn >
<GridViewColumn.Header>
<TextBlock Width="auto" FontSize="18" FontWeight="Black" Foreground="#e58e26" TextAlignment="Center">备用</TextBlock>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Foreground="#f8df72" Text="{Binding spare}" ></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<!--隐藏列头-->
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="Visible"/>
</Style>
<Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseDown">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="LightBlue" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseUp">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.Color" To="Transparent" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
</ListView>


<!--</GroupBox>-->
</Border>


</Grid>
</Border>

<UniformGrid Rows="2" Grid.Row="2">
<Border CornerRadius="5" Background="#1000" BorderThickness="0.5" Margin="10">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#87E8EC" Offset="0"/>
<GradientStop Color="Transparent" Offset="0.3"/>
<GradientStop Color="Transparent" Offset="0.8"/>
<GradientStop Color="#87E8EC" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>

<Grid Margin="10,0">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!--从站编号-->
<TextBlock Text="{Binding SlaveId,StringFormat={}{0:00} - 号从站}"
VerticalAlignment="Center" Foreground="#9987E8EC"
FontWeight="Normal"/>
<!--设备状态反馈-->
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center" HorizontalAlignment="Right"
Grid.Column="1">
<Border Width="10" Height="10" Background="Orange" Margin="5,0"/>
<TextBlock Text="订单及设备状态" Foreground="#9FFF" FontWeight="Black" FontSize="20" Margin="0,0,5,0"/>
</StackPanel>

<!--订单显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="1" Margin="0,0,0,5">
<Grid ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="&#xe618;" FontFamily="{StaticResource FF}"
Grid.RowSpan="2" FontSize="120"
Margin="-40,10,0,0"
Foreground="#09FFFFFF"/>
<Border HorizontalAlignment="Center" VerticalAlignment="Top"
Background="#BF90"
CornerRadius="0,0,5,5">
<TextBlock Text="订单" Margin="15,3"
FontWeight="Black" FontSize="18" Foreground="White"/>
</Border>

</Grid>
</Border>
<TextBlock Text="当前订单编号" Margin="1,50" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Center"
FontSize="22" FontWeight="Black" Foreground="#fad390"/>
<TextBlock Text="{Binding MainWModel.CurrentOrderNumber}" Grid.RowSpan="2" Margin="1,90" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Center"
FontSize="20" FontWeight="Black" Foreground="#e55039"/>

<TextBlock Grid.Row="1" VerticalAlignment="Center"
HorizontalAlignment="Center" FontSize="30"
Margin="0,20,0,0"
FontFamily="../Assets/Fonts/#Digital Display"
Text="{Binding Temperature,StringFormat={}{0:0.0}}"
Foreground="White"/>

<!--湿度显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="2" Margin="0,0,0,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xe642;" FontFamily="{StaticResource FF}"
VerticalAlignment="Center" HorizontalAlignment="Left"
Foreground="Orange" FontSize="14" Margin="10,0"/>
<TextBlock Grid.Column="1">
<Run Text="{Binding Humidity,StringFormat={}{0:0.0}}" FontSize="18" Foreground="#AFFF"
FontWeight="Normal"/>
<Run Text="$" FontSize="11" Foreground="#7FFF"/>
</TextBlock>

<TextBlock Text="订单" Grid.Column="2"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="10,0" Foreground="#2FFF"/>
</Grid>
</Border>


<Border CornerRadius="5" Background="#1000" Grid.Row="1" Grid.RowSpan="2" Grid.Column="1" Margin="5,0,0,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="设备状态:" Margin="1,0" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="22" FontWeight="Black" Foreground="#fad390"/>

<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding MainWModel.TopDianState}" VerticalAlignment="Center" Margin="10,0" FontWeight="Black" FontSize="24" Foreground="#90EE90"/>

<TextBlock Text="订单状态:" Margin="1,0" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="22" FontWeight="Black" Foreground="#fad390"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding MainWModel.OrderPushState}" VerticalAlignment="Center" Margin="10,0" FontWeight="Black" FontSize="24" Foreground="#90EE90"/>

</Grid>
</Border>



</Grid>
</Border>


<Border CornerRadius="5" Background="#1000" BorderThickness="0.5" Margin="10">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="#87E8EC" Offset="0"/>
<GradientStop Color="Transparent" Offset="0.3"/>
<GradientStop Color="Transparent" Offset="0.8"/>
<GradientStop Color="#87E8EC" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>

<Grid Margin="10,0">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!--从站编号-->
<TextBlock Text="{Binding SlaveId,StringFormat={}{0:00} - 号从站}"
VerticalAlignment="Center" Foreground="#9987E8EC"
FontWeight="Normal"/>
<!--写入操作-->
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center" HorizontalAlignment="Right"
Grid.Column="1">
<Border Width="10" Height="10" Background="Orange" Margin="5,0"/>
<TextBlock Text="写入操作" Foreground="#9FFF" FontWeight="Black" FontSize="20" Margin="0,0,5,0"/>
</StackPanel>

<!--写入显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="1" Margin="0,0,0,5">
<Grid ClipToBounds="True">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="&#xe618;" FontFamily="{StaticResource FF}"
Grid.RowSpan="2" FontSize="120"
Margin="-40,10,0,0"
Foreground="#09FFFFFF"/>
<Border HorizontalAlignment="Center" VerticalAlignment="Top"
Background="#BF90"
CornerRadius="0,0,5,5">
<TextBlock Text="写入" Margin="15,3"
FontWeight="Black" FontSize="18" Foreground="White"/>
</Border>
<StackPanel Orientation="Horizontal" >
<TextBlock Text="配方编号:" Margin="1,60" Grid.Row="1" VerticalAlignment="Top" HorizontalAlignment="Center"
FontSize="16" FontWeight="Black" Foreground="#fad390"/>

<Border Grid.Row="1" Margin="10,0,0,0" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="34">
<TextBox Height="34" Margin="0,0,0,0" VerticalContentAlignment="Center" Text="{Binding MainWModel.FormulaNumber,UpdateSourceTrigger=PropertyChanged}" BorderThickness="0" Background="#2FFF" FontSize="16" Foreground="#555" x:Name ="FormulaNumber" Width="70">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=FormulaNumber}"/>
</TextBox.InputBindings>
</TextBox>
</Border>

</StackPanel>


</Grid>
</Border>
<TextBlock Grid.Row="1" VerticalAlignment="Center"
HorizontalAlignment="Center" FontSize="30"
Margin="0,20,0,0"
FontFamily="../Assets/Fonts/#Digital Display"
Text="{Binding Temperature,StringFormat={}{0:0.0}}"
Foreground="White"/>

<!--写入显示区域-->
<Border CornerRadius="5" Background="#1000" Grid.Row="2" Margin="0,0,0,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="&#xe642;" FontFamily="{StaticResource FF}"
VerticalAlignment="Center" HorizontalAlignment="Left"
Foreground="Orange" FontSize="14" Margin="10,0"/>
<TextBlock Grid.Column="1">
<Run Text="{Binding Humidity,StringFormat={}{0:0.0}}" FontSize="18" Foreground="#AFFF"
FontWeight="Normal"/>
<Run Text="%" FontSize="11" Foreground="#7FFF"/>
</TextBlock>

<TextBlock Text="写入" Grid.Column="2"
VerticalAlignment="Center" HorizontalAlignment="Right"
Margin="10,0" Foreground="#2FFF"/>
</Grid>
</Border>

<Border CornerRadius="5" Background="#1000" Grid.Row="1" Grid.RowSpan="2" Grid.Column="1" Margin="5,0,0,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>

</Grid.ColumnDefinitions>

<Button Content="写入编号" Grid.Column="0" Grid.Row="1" Background="#38ada9"
Style="{StaticResource ControlButtonStyle}"
FontSize="18" FontWeight="Black" Margin="2" Width="135" Foreground="Wheat"
Command="{Binding WriteNumberCommand}"/>

<Button Content="确定写入编号" Grid.Column="0" Grid.Row="2" Background="#e55039"
Style="{StaticResource ControlButtonStyle}"
FontSize="20" FontWeight="Black" Margin="2" Width="135" Foreground="Wheat"
Command="{Binding DetermineWriteNumberCommand}"/>

<Button Content="启动配料" Grid.Column="1" Grid.Row="2" Background="#f33b1f"
Style="{StaticResource ControlButtonStyle}"
FontSize="20" FontWeight="Black" Margin="2" Width="135" Foreground="Wheat"
Command="{Binding StartingIngredientsCommand}"/>

</Grid>
</Border>


</Grid>
</Border>
</UniformGrid>

</UniformGrid>
<!--第四行-->
<TextBlock Grid.Row="3" VerticalAlignment="Center"
HorizontalAlignment="Center" Foreground="#3FFF" FontSize="11">
<Run Text="©HEIBOLUO Co,Ltd "/>
<Run Text=" "/>
<Run Text="{Binding CurrentDate,StringFormat={}{0:yyyy}}"/>
</TextBlock>
</Grid>


<!--配置信息界面-->
<Border HorizontalAlignment="Right" Width="240"
Background="#DDF7F9FA" BorderBrush="#DDD"
BorderThickness="1,0,0,0" Margin="0,0,-250,0"
Name="bor_config">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="15"/>
<RowDefinition Height="395"/>
<RowDefinition Height="55"/>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="通信参数设置" VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="18">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="10" Color="Gray" ShadowDepth="0" Opacity="0.4"/>
</TextBlock.Effect>
</TextBlock>
<Button Style="{StaticResource ControlButtonStyle}"
Width="33" Height="28"
VerticalAlignment="Center" HorizontalAlignment="Left"
Background="Transparent"
Name="btnConfigClose"
Command="{Binding ConfigCloseCommand}">
<Path Data="M0 5,10 5M4 0 ,10 5,4 10" Stroke="Gray" StrokeThickness="1"/>
</Button>

<!--ip地址-->
<Grid Grid.Row="1" Margin="10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="IP地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.Ip,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="IPName" Width="155">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=IPName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>

</Grid>
<!--端口号-->
<Grid Grid.Row="2" Margin="10,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="端口号" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.Port,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="PortName" Width="155">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>
<ScrollViewer Grid.Row="4" VerticalScrollBarVisibility="Hidden" >
<StackPanel >

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="读取数据长度" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.ReadDataLength,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="ReadDataLength" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=ReadDataLength}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="写入数据长度" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.WriteDataLength,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="WriteDataLength" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=WriteDataLength}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>


<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="配方编号地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.RecipeNumberAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="RecipeNumberAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="配方编号类型" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<ComboBox Height="34" Width="135" BorderThickness="0" Background="Transparent" ItemsSource="{Binding dataTypes}" VerticalContentAlignment="Center" DisplayMemberPath="{Binding DataName}" SelectedValuePath="{Binding ID}" Foreground="#555" SelectedItem="{Binding DataType}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataName}" VerticalAlignment="Center"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Border>
</Grid>
<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="配方编号格式" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<ComboBox Height="34" Width="135" BorderThickness="0" Background="Transparent" ItemsSource="{Binding formulas}" VerticalContentAlignment="Center" DisplayMemberPath="{Binding DataFormatName}" SelectedValuePath="{Binding FormatID}" Foreground="#555" SelectedItem="{Binding DataFormulas}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataFormatName}" VerticalAlignment="Center"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>


</Border>
</Grid>


<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="订单编号地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.DisplayOrderNumberAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="DisplayOrderNumberAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="订单编号类型" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<ComboBox Height="34" Width="135" BorderThickness="0" Background="Transparent" ItemsSource="{Binding dataTypes}" VerticalContentAlignment="Center" DisplayMemberPath="{Binding DataName}" SelectedValuePath="{Binding ID}" Foreground="#555" SelectedItem="{Binding OrderNumberType}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataName}" VerticalAlignment="Center"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="订单编号格式" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<ComboBox Height="34" Width="135" BorderThickness="0" Background="Transparent" ItemsSource="{Binding formulas}" VerticalContentAlignment="Center" DisplayMemberPath="{Binding DataFormatName}" SelectedValuePath="{Binding FormatID}" Foreground="#555" SelectedItem="{Binding DataFormulas}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DataFormatName}" VerticalAlignment="Center"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="写入编号地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.WriteNumberAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="WriteNumberAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="启动配料地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.StartIngredientAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="StartIngredientAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="配料完成地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.IngredientCompletionAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="IngredientCompletionAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="设备状态地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.DeviceStatusAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="DeviceStatusAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>

<Grid Margin="10,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="信息错误地址" VerticalAlignment="Center"/>
<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="35">
<TextBox Grid.Column="1" Height="34" Margin="0,0,0,0" BorderThickness="0" Background="Transparent" VerticalContentAlignment="Center" Text="{Binding MainWModel.InformationErrorAddress,UpdateSourceTrigger=PropertyChanged}" FontSize="16" Foreground="#555" x:Name ="InformationErrorAddress" Width="139">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding QueryCommand}" CommandParameter="{Binding ElementName=PortName}"/>
</TextBox.InputBindings>
</TextBox>
</Border>
</Grid>
</StackPanel>
</ScrollViewer>
<!--日志路径 -->
<Grid Grid.Row="5" Margin="10,0" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="日志路径" VerticalAlignment="Center"/>

<Border Grid.Column="1" Background="White" BorderBrush="#EEE" BorderThickness="1"
CornerRadius="5" Height="33">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<TextBox BorderThickness="0" Background="Transparent"
VerticalContentAlignment="Center"
Text="{Binding MainWModel.LogPath}"/>
<Border Width="1" HorizontalAlignment="Right" Background="#EEE"
Margin="0,4"/>
<Button Content="···" Grid.Column="1" Background="Transparent"
Style="{StaticResource ControlButtonStyle}"
FontSize="18" Margin="2" Width="26" Foreground="Gray"
Command="{Binding LogPathSelectCommand}"/>
</Grid>
</Border>
</Grid>

<!--打开日志目录-->
<TextBlock Grid.Row="6" VerticalAlignment="Top" HorizontalAlignment="Center"
Margin="0,5">
<Hyperlink Command="{Binding OpenLogPathCommand}">打开日志目录</Hyperlink>
</TextBlock>
</Grid>
</Border>

</Grid>
</Window>

+ 45
- 0
BPA.WeimoCube/Views/MainWindow.xaml.cs Vedi File

@@ -0,0 +1,45 @@
using System.Text;
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 BPA.WeimoCube
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//最大化时 页面高度为屏幕高度
this.MaxHeight = SystemParameters.PrimaryScreenHeight;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (System.Windows.MessageBox.Show("是否确定退出系统?", "提示", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question) == System.Windows.MessageBoxResult.Yes)
{
Button button = sender as Button;
if (button != null && button.Command != null && button.Command.CanExecute(null))
{
// 首先执行绑定的Command
button.Command.Execute(null);


}
Application.Current.Shutdown();// 关闭应用程序并终止所有实例
Environment.Exit(0);
//var w = Window.GetWindow(close); // 获取当前窗体
//w.Close();

}
}
}
}

+ 17
- 0
CommcationLibray/CommcationLibray.csproj Vedi File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Title>http://111.9.47.105:10243/repository/bpa/index.json</Title>
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BPA.Communication" Version="1.0.169" />
</ItemGroup>

</Project>

+ 115
- 0
CommcationLibray/ModbusBase.cs Vedi File

@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace CommcationLibray
{
/// <summary>
/// ModbusRTU / ModbusAscll / ModbusTCP
/// 通用公共抽象类
/// </summary>
public abstract class ModbusBase
{
/// <summary>
/// 封装公共报文区域
/// </summary>
/// <param name="unit_id"></param>
/// <param name="func_code"></param>
/// <param name="start_addr"></param>
/// <param name="count"></param>
/// <returns></returns>
public byte[] ReadCommandBytes(byte unit_id, byte func_code, ushort start_addr, ushort count)
{
byte[] req_bytes = new byte[] {
unit_id,
func_code,
(byte)(start_addr/256),
(byte)(start_addr%256),
(byte)(count/256),
(byte)(count%256)
};

return req_bytes;
}
/// <summary>
/// 获取对应的数据类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data_bytes"></param>
/// <returns></returns>
public T[] GetValues<T>(byte[] data_bytes)
{
//GetValues<ushort> data_bytes 每两个字节转换成一个数字 float 4Bytes double 8
//2 ushort short int16 uint16
//4 int uint int32 uint32 float
//8 double
//16 decimal
List<T> list = new List<T>();
try
{
//检查类型的长度
var type_len = Marshal.SizeOf(typeof(T));
for (int i = 0; i < data_bytes.Length; i+= type_len)
{
//取出对应类型字节
var temp_bytes = data_bytes.ToList().GetRange(i, type_len);
if (BitConverter.IsLittleEndian)
{
temp_bytes.Reverse();
}

Type bitConverter_type = typeof(BitConverter);
var mis = bitConverter_type.GetMethods().ToList();
var mi = mis.FirstOrDefault(mi => mi.ReturnType == typeof(T) && mi.GetParameters().Length == 2);
if (mi == null)
{
throw new Exception("数据转换类型出错!");
}

object value = mi.Invoke(bitConverter_type, new object[] { temp_bytes.ToArray(), 0 });

list.Add((T)value);

}
}
catch (Exception ex)
{

throw ex;
}
return list.ToArray();
}

public object[] GetValues(byte[] data_bytes, Type[] types)
{
object[] values = new object[types.Length];
int index = 0;
int i =0;
foreach (var type in types)
{
var type_len = Marshal.SizeOf(type);
var temp_bytes = data_bytes.ToList().GetRange(index, type_len);
temp_bytes.Reverse();

index += type_len;

Type bitConverter_type = typeof(BitConverter);
var mis = bitConverter_type.GetMethods().ToList();
var mi = mis.FirstOrDefault(mi => mi.ReturnType == type && mi.GetParameters().Length == 2);
if (mi == null)
{
throw new Exception("数据转换类型出错!");
}

object value = mi.Invoke(bitConverter_type, new object[] { temp_bytes.ToArray(), 0 });

values[i++] = value;
}
return values;
}

}
}

+ 215
- 0
CommcationLibray/ModbusTCP.cs Vedi File

@@ -0,0 +1,215 @@
using BPA.Communication;
using BPA.Helper;
using Microsoft.AspNetCore.Http;

namespace CommcationLibray
{
/// <summary>
/// modbusTcp连接基类
/// </summary>
public class ModbusTCP
{

ICommModbus commHelper;
/// <summary>
/// 连接modbusTcp
/// </summary>
/// <param name="ip">IP</param>
/// <param name="Port">端口</param>
/// <returns></returns>
public async Task<Result> ConnectModbusTcp(string ip, int Port)
{
Result results = new Result();
await Task.Run( new Action(() =>
{
CommHelper.CreateModbusTcp(ip, Port).OnSuccess(s =>
{
results.State = s.IsSuccess;
results.Exception = s.Message;
commHelper = s.Content;
}).OnFailure(s =>
{
results.State = s.IsSuccess;
results.Exception = s.Message;
});
}));
return results;
}
/// <summary>
/// 获取订单号
/// </summary>
/// <param name="address">读取保持寄存器 的地址</param>
/// <typeparam name="T">需要返回的数据类型</typeparam>
/// <param name="length">数据长度</param>
/// <param name="format">数据格式</param>
/// <returns></returns>
public Result GetOrders<T>(string address, ushort length = 1, BPADataFormat format = BPADataFormat.ABCD)
{
Result results = new Result();
try
{
if (commHelper != null)
{
var GetOrdersData = commHelper.ReadHoldRegister<T>(address, length,format);
results.State = GetOrdersData.IsSuccess;
results.Exception = GetOrdersData.Message;
results.Datas = GetOrdersData.Content;
}
else
{
results.State = false;
results.Exception = "ICommModbus 对象为空!!!";
}

}
catch (Exception ex)
{
results.State = false;
results.Exception = ex.Message;
}
return results;
}

/// <summary>
/// 写入配方编号
/// </summary>
/// <typeparam name="T">写入的数据类型</typeparam>
/// <param name="address">寄存器地址</param>
/// <param name="value">写入的值</param>
/// <param name="len">地址长度</param>
/// <param name="format">数据格式</param>
/// <returns></returns>
public Result WriteRecipeNumber<T>(string address, T value, int len = 0, BPADataFormat format = BPADataFormat.ABCD)
{
Result results = new Result();
try
{
if (commHelper != null)
{
var WriteState = commHelper.WriteHoldRegister<T>(address, value, len, format);
results.State = WriteState.IsSuccess;
results.Exception = WriteState.Message;
}
else
{
results.State = false;
results.Exception = "ICommModbus 对象为空!!!";
}
}
catch (Exception ex)
{
results.State = false;
results.Exception = ex.Message;
}
return results;
}

/// <summary>
/// 确定写入编号
/// </summary>
/// <param name="address">线圈地址</param>
/// <param name="value">写入的值</param>
/// <returns></returns>
public Result DetermineWriteNumberCommand(string address, bool value)
{
return WriteCoilData(address, value);
}

/// <summary>
/// 写入取消配料的点位
/// </summary>
/// <param name="address">线圈地址</param>
/// <param name="value">写入线圈的值</param>
/// <returns></returns>
public Result WriteCancelIngredients(string address, bool value)
{
return WriteCoilData(address,value);
}

/// <summary>
/// 读取取消配料的点位
/// </summary>
/// <param name="address">读取线圈的地址</param>
/// <returns></returns>
public Result ReadCancelIngredients(string address)
{
return ReadCoilData(address);
}

/// <summary>
/// 获取设备状态
/// </summary>
/// <param name="address">读取线圈的地址</param>
/// <returns></returns>
public Result ReadDeviceStatus(string address)
{
return ReadCoilData(address);
}

/// <summary>
/// 读取线圈数据
/// </summary>
/// <param name="address">读取线圈的地址</param>
/// <returns></returns>
private Result ReadCoilData(string address)
{
Result results = new Result();
try
{
if (commHelper != null)
{
var readState = commHelper.ReadCoil(address);
results.State = readState.IsSuccess;
results.Datas = readState.Content;
results.Exception = readState.Message;
}
else
{
results.State = false;
results.Exception = "ICommModbus 对象为空!!!";
}
}
catch (Exception ex)
{
results.State = false;
results.Exception = ex.Message;
}

return results;

}

/// <summary>
/// 写入线圈数据
/// </summary>
/// <param name="address"></param>
/// <param name="value">写入线圈的值</param>
/// <returns></returns>
private Result WriteCoilData(string address,bool value)
{
Result results = new Result();
try
{
if (commHelper != null)
{
var WriteState = commHelper.WriteCoil(address, value);
results.State = WriteState.IsSuccess;
results.Exception = WriteState.Message;
}
else
{
results.State = false;
results.Exception = "ICommModbus 对象为空!!!";
}

}
catch (Exception ex)
{
results.State = false;
results.Exception = ex.Message;
}
return results;
}

}
}

+ 28
- 0
CommcationLibray/Result.cs Vedi File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommcationLibray
{
/// <summary>
/// 包装返回结果
/// </summary>
public class Result
{
/// <summary>
/// 状态
/// </summary>
public bool State { set; get; }
/// <summary>
/// 错误信息
/// </summary>
public string Exception { get; set; }

/// <summary>
/// 转成对应的数据 ushort int float
/// </summary>
public object Datas { get; set; }
}
}

Caricamento…
Annulla
Salva