65个文件已修改
41个文件已添加
3 文件已重命名
102个文件已删除
4 文件已复制
| File was renamed from VisionBuilder.Engine/VisionBuilder.Engine.csproj |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
| | | <PropertyGroup> |
| | | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
| | | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
| | | <ProjectGuid>{8E5E8A68-0B9D-4A6A-B325-730C64603FDF}</ProjectGuid> |
| | | <ProjectGuid>{D0806FA6-3F6D-4304-81B8-EAD9DA7CB5B2}</ProjectGuid> |
| | | <OutputType>Library</OutputType> |
| | | <AppDesignerFolder>Properties</AppDesignerFolder> |
| | | <RootNamespace>VisionBuilder.Engine</RootNamespace> |
| | | <AssemblyName>VisionBuilder.Engine</AssemblyName> |
| | | <RootNamespace>ConnectionUtil</RootNamespace> |
| | | <AssemblyName>ConnectionUtil</AssemblyName> |
| | | <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
| | | <FileAlignment>512</FileAlignment> |
| | | <Deterministic>true</Deterministic> |
| | |
| | | <Reference Include="System.Xml" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="Runner.cs" /> |
| | | <Compile Include="PipeClient.cs" /> |
| | | <Compile Include="PipeClient2.cs" /> |
| | | <Compile Include="PipeServer.cs" /> |
| | | <Compile Include="PipeServer2.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj"> |
| | | <Project>{3e3bf44a-0b69-45c5-9512-528cb48a7106}</Project> |
| | | <Name>HMI.Core</Name> |
| | | </ProjectReference> |
| | | <Compile Include="SCADAApi.cs" /> |
| | | <Compile Include="TcpClient.cs" /> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | </Project> |
| New file |
| | |
| | | using System; |
| | | using System.IO; |
| | | using System.IO.Pipes; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | public class PipeClient : IDisposable |
| | | { |
| | | private readonly string _pipeName; |
| | | private readonly string _serverName; |
| | | private readonly CancellationTokenSource _cancellationTokenSource; |
| | | private NamedPipeClientStream _pipeClient; |
| | | private bool _isDisposed; |
| | | private bool _isConnected; |
| | | private readonly object _sendLock = new object(); |
| | | |
| | | // 事件定义 |
| | | public event EventHandler<PipeDataEventArgs> OnData; |
| | | public event EventHandler OnConnected; |
| | | public event EventHandler OnDisconnected; |
| | | |
| | | public PipeClient(string pipeName, string serverName = ".") |
| | | { |
| | | _pipeName = pipeName; |
| | | _serverName = serverName; |
| | | _cancellationTokenSource = new CancellationTokenSource(); |
| | | } |
| | | |
| | | public void Connect(int timeoutMs = 5000) |
| | | { |
| | | if (_isConnected) |
| | | return; |
| | | _pipeClient = new NamedPipeClientStream(_pipeName); |
| | | |
| | | _pipeClient.Connect(timeoutMs); |
| | | _pipeClient.ReadMode = PipeTransmissionMode.Message; |
| | | _isConnected = true; |
| | | Console.WriteLine("连接成功!"); |
| | | |
| | | // 触发连接成功事件 |
| | | OnConnected?.Invoke(this, EventArgs.Empty); |
| | | } |
| | | |
| | | public bool SendMessage(string message, out string response, int timeoutMs = 5000) |
| | | { |
| | | if (!_isConnected) |
| | | { |
| | | response = "客户端未连接到服务器"; |
| | | return false; |
| | | } |
| | | response = null; |
| | | lock (_sendLock) |
| | | { |
| | | try |
| | | { |
| | | // 发送消息 |
| | | _pipeClient.WriteMessage(message); |
| | | return true; |
| | | while (_isConnected && !_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | response = _pipeClient.ReadMessage(); |
| | | break; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"接收数据时发生错误: {ex.Message}"); |
| | | break; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void Disconnect() |
| | | { |
| | | _isConnected = false; |
| | | _cancellationTokenSource.Cancel(); |
| | | } |
| | | |
| | | public void Dispose() |
| | | { |
| | | if (!_isDisposed) |
| | | { |
| | | Disconnect(); |
| | | _pipeClient?.Dispose(); |
| | | _cancellationTokenSource.Dispose(); |
| | | _isDisposed = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.IO; |
| | | using System.IO.Pipes; |
| | | using System.Threading; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | public class PipeClient2 : IDisposable |
| | | { |
| | | private readonly string _pipeName; |
| | | private readonly string _serverName; |
| | | private readonly CancellationTokenSource _cancellationTokenSource; |
| | | private readonly ReaderWriterLockSlim _lock; |
| | | private NamedPipeClientStream _pipeClient; |
| | | private bool _isDisposed; |
| | | private bool _isConnected; |
| | | private Thread _receiveThread; |
| | | |
| | | // 事件定义 |
| | | public event EventHandler<PipeDataEventArgs> OnData; |
| | | public event EventHandler OnConnected; |
| | | public event EventHandler OnDisconnected; |
| | | |
| | | public PipeClient2(string pipeName, string serverName = ".") |
| | | { |
| | | _pipeName = pipeName; |
| | | _serverName = serverName; |
| | | _cancellationTokenSource = new CancellationTokenSource(); |
| | | _lock = new ReaderWriterLockSlim(); |
| | | } |
| | | |
| | | public void Connect(int timeoutMs = 5000) |
| | | { |
| | | if (_isConnected) |
| | | return; |
| | | |
| | | try |
| | | { |
| | | // 加上 PipeOptions.Asynchronous 可以异步接受服务器发送的数据,但是很影响性能 |
| | | _pipeClient = new NamedPipeClientStream(_serverName, _pipeName, PipeDirection.InOut); |
| | | |
| | | // 创建超时取消令牌 |
| | | using (var timeoutCts = new CancellationTokenSource(timeoutMs)) |
| | | { |
| | | _pipeClient.Connect(timeoutMs); |
| | | _pipeClient.ReadMode = PipeTransmissionMode.Message; |
| | | _isConnected = true; |
| | | |
| | | // 触发连接成功事件 |
| | | OnConnected?.Invoke(this, EventArgs.Empty); |
| | | |
| | | // 开始接收数据 |
| | | //_receiveThread = new Thread(ReceiveData); |
| | | //_receiveThread.Start(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | throw; |
| | | } |
| | | } |
| | | |
| | | private void ReceiveData() |
| | | { |
| | | try |
| | | { |
| | | while (_isConnected && !_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | string message = _pipeClient.ReadMessage(); |
| | | if (string.IsNullOrEmpty(message)) |
| | | break; |
| | | // 触发数据接收事件 |
| | | OnData?.Invoke(this, new PipeDataEventArgs("", message)); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | _isConnected = false; |
| | | // 触发断开连接事件 |
| | | OnDisconnected?.Invoke(this, EventArgs.Empty); |
| | | } |
| | | } |
| | | |
| | | public bool SendMessage(string message, out string response, int timeoutMs = 5000) |
| | | { |
| | | response = null; |
| | | if (!_isConnected) |
| | | return false; |
| | | try |
| | | { |
| | | |
| | | _lock.EnterWriteLock(); |
| | | try |
| | | { |
| | | _pipeClient.WriteMessage(message); |
| | | } |
| | | finally |
| | | { |
| | | _lock.ExitWriteLock(); |
| | | } |
| | | response = _pipeClient.ReadMessage(); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | response = ex.Message; |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public void Disconnect() |
| | | { |
| | | _isConnected = false; |
| | | _cancellationTokenSource.Cancel(); |
| | | _receiveThread?.Join(1000); // 等待接收线程结束 |
| | | } |
| | | |
| | | public void Dispose() |
| | | { |
| | | if (!_isDisposed) |
| | | { |
| | | Disconnect(); |
| | | _pipeClient?.Dispose(); |
| | | _cancellationTokenSource.Dispose(); |
| | | _lock.Dispose(); |
| | | _isDisposed = true; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.IO; |
| | | using System.IO.Pipes; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | public class PipeServer : IDisposable |
| | | { |
| | | private readonly string _pipeName; |
| | | private readonly int _maxNumberOfServerInstances; |
| | | private readonly CancellationTokenSource _cancellationTokenSource; |
| | | private readonly ConcurrentDictionary<string, NamedPipeServerStream> _activeConnections; |
| | | private bool _isDisposed; |
| | | |
| | | // 事件定义 |
| | | public event EventHandler<PipeDataEventArgs> OnData; |
| | | public event EventHandler<PipeConnectionEventArgs> OnNewConnection; |
| | | public event EventHandler<PipeConnectionEventArgs> OnClientDisconnected; |
| | | public event EventHandler<PipeErrorEventArgs> OnError; |
| | | |
| | | public PipeServer(string pipeName, int maxNumberOfServerInstances = NamedPipeServerStream.MaxAllowedServerInstances) |
| | | { |
| | | _pipeName = pipeName; |
| | | _maxNumberOfServerInstances = maxNumberOfServerInstances; |
| | | _cancellationTokenSource = new CancellationTokenSource(); |
| | | _activeConnections = new ConcurrentDictionary<string, NamedPipeServerStream>(); |
| | | } |
| | | |
| | | public void Start() |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | try |
| | | { |
| | | while (!_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | var pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, |
| | | _maxNumberOfServerInstances, PipeTransmissionMode.Message); |
| | | try |
| | | { |
| | | pipeServer.WaitForConnection(); |
| | | |
| | | // 生成唯一的连接ID |
| | | string connectionId = Guid.NewGuid().ToString(); |
| | | _activeConnections.TryAdd(connectionId, pipeServer); |
| | | |
| | | // 触发新连接事件 |
| | | OnNewConnection?.Invoke(this, new PipeConnectionEventArgs(connectionId)); |
| | | |
| | | // 开始处理该连接的数据 |
| | | HandleClient(connectionId, pipeServer); |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | pipeServer.Dispose(); |
| | | break; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | pipeServer.Dispose(); |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("等待连接时发生错误", ex)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("服务器运行时发生错误", ex)); |
| | | } |
| | | |
| | | }); |
| | | } |
| | | |
| | | static string ReadMessage(PipeStream s) |
| | | { |
| | | MemoryStream ms = new MemoryStream(); |
| | | byte[] buffer = new byte[0x1000]; // Read in 4 KB blocks |
| | | do |
| | | { |
| | | ms.Write(buffer, 0, s.Read(buffer, 0, buffer.Length)); |
| | | } |
| | | while (!s.IsMessageComplete); |
| | | return Encoding.UTF8.GetString(ms.ToArray()); |
| | | } |
| | | |
| | | private void HandleClient(string connectionId, NamedPipeServerStream pipeServer) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | try |
| | | { |
| | | while (pipeServer.IsConnected && !_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | string message = ReadMessage(pipeServer); |
| | | if (string.IsNullOrEmpty(message)) |
| | | continue; |
| | | Console.WriteLine(message); |
| | | if (message == "ping") |
| | | { |
| | | message = "pong"; |
| | | } |
| | | else |
| | | { |
| | | message += "Response"; |
| | | } |
| | | SendMessage(connectionId, message); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs($"处理客户端 {connectionId} 数据时发生错误", ex)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | // 清理连接 |
| | | _activeConnections.TryRemove(connectionId, out _); |
| | | pipeServer.Dispose(); |
| | | |
| | | // 触发断开连接事件 |
| | | OnClientDisconnected?.Invoke(this, new PipeConnectionEventArgs(connectionId)); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | public void SendMessage(string connectionId, string message) |
| | | { |
| | | if (_activeConnections.TryGetValue(connectionId, out var pipeServer)) |
| | | { |
| | | try |
| | | { |
| | | var msg = Encoding.UTF8.GetBytes(message); |
| | | pipeServer.Write(msg, 0, msg.Length); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs($"向客户端 {connectionId} 发送消息时发生错误", ex)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | public async Task StartAsync() |
| | | { |
| | | try |
| | | { |
| | | while (!_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | var pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, |
| | | _maxNumberOfServerInstances, PipeTransmissionMode.Message); |
| | | |
| | | try |
| | | { |
| | | await pipeServer.WaitForConnectionAsync(_cancellationTokenSource.Token); |
| | | |
| | | // 生成唯一的连接ID |
| | | string connectionId = Guid.NewGuid().ToString(); |
| | | _activeConnections.TryAdd(connectionId, pipeServer); |
| | | |
| | | // 触发新连接事件 |
| | | OnNewConnection?.Invoke(this, new PipeConnectionEventArgs(connectionId)); |
| | | |
| | | // 开始处理该连接的数据 |
| | | _ = HandleClientAsync(connectionId, pipeServer); |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | pipeServer.Dispose(); |
| | | break; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | pipeServer.Dispose(); |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("等待连接时发生错误", ex)); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("服务器运行时发生错误", ex)); |
| | | } |
| | | } |
| | | |
| | | private async Task HandleClientAsync(string connectionId, NamedPipeServerStream pipeServer) |
| | | { |
| | | try |
| | | { |
| | | using (var reader = new StreamReader(pipeServer)) |
| | | using (var writer = new StreamWriter(pipeServer)) |
| | | { |
| | | writer.AutoFlush = true; |
| | | |
| | | while (pipeServer.IsConnected && !_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | string message = await reader.ReadLineAsync(); |
| | | if (string.IsNullOrEmpty(message)) |
| | | continue; |
| | | |
| | | // 触发数据接收事件 |
| | | OnData?.Invoke(this, new PipeDataEventArgs(connectionId, message)); |
| | | |
| | | // 发送响应 |
| | | await writer.WriteLineAsync($"服务器已收到消息: {message}"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs($"处理客户端 {connectionId} 数据时发生错误", ex)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | // 清理连接 |
| | | _activeConnections.TryRemove(connectionId, out _); |
| | | pipeServer.Dispose(); |
| | | |
| | | // 触发断开连接事件 |
| | | OnClientDisconnected?.Invoke(this, new PipeConnectionEventArgs(connectionId)); |
| | | } |
| | | } |
| | | |
| | | public async Task SendMessageAsync(string connectionId, string message) |
| | | { |
| | | if (_activeConnections.TryGetValue(connectionId, out var pipeServer)) |
| | | { |
| | | try |
| | | { |
| | | using (var writer = new StreamWriter(pipeServer)) |
| | | { |
| | | writer.AutoFlush = true; |
| | | await writer.WriteLineAsync(message); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs($"向客户端 {connectionId} 发送消息时发生错误", ex)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void Stop() |
| | | { |
| | | _cancellationTokenSource.Cancel(); |
| | | } |
| | | |
| | | public void Dispose() |
| | | { |
| | | if (!_isDisposed) |
| | | { |
| | | Stop(); |
| | | foreach (var connection in _activeConnections.Values) |
| | | { |
| | | connection.Dispose(); |
| | | } |
| | | _activeConnections.Clear(); |
| | | _cancellationTokenSource.Dispose(); |
| | | _isDisposed = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public class PipeDataEventArgs : EventArgs |
| | | { |
| | | public string ConnectionId { get; } |
| | | public string Data { get; } |
| | | |
| | | public PipeDataEventArgs(string connectionId, string data) |
| | | { |
| | | ConnectionId = connectionId; |
| | | Data = data; |
| | | } |
| | | } |
| | | |
| | | public class PipeConnectionEventArgs : EventArgs |
| | | { |
| | | public string ConnectionId { get; } |
| | | |
| | | public PipeConnectionEventArgs(string connectionId) |
| | | { |
| | | ConnectionId = connectionId; |
| | | } |
| | | } |
| | | |
| | | public class PipeErrorEventArgs : EventArgs |
| | | { |
| | | public string Message { get; } |
| | | public Exception Exception { get; } |
| | | |
| | | public PipeErrorEventArgs(string message, Exception exception) |
| | | { |
| | | Message = message; |
| | | Exception = exception; |
| | | } |
| | | } |
| | | |
| | | public class StreamString |
| | | { |
| | | private Stream ioStream; |
| | | private UnicodeEncoding streamEncoding; |
| | | |
| | | public StreamString(Stream ioStream) |
| | | { |
| | | this.ioStream = ioStream; |
| | | streamEncoding = new UnicodeEncoding(); |
| | | } |
| | | |
| | | public string ReadString() |
| | | { |
| | | int len = 0; |
| | | |
| | | |
| | | len = ioStream.ReadByte() * 256; |
| | | len += ioStream.ReadByte(); |
| | | byte[] inBuffer = new byte[len]; |
| | | ioStream.Read(inBuffer, 0, len); |
| | | |
| | | return streamEncoding.GetString(inBuffer); |
| | | } |
| | | |
| | | public int WriteString(string outString) |
| | | { |
| | | byte[] outBuffer = streamEncoding.GetBytes(outString); |
| | | int len = outBuffer.Length; |
| | | if (len > UInt16.MaxValue) |
| | | { |
| | | len = (int)UInt16.MaxValue; |
| | | } |
| | | ioStream.WriteByte((byte)(len / 256)); |
| | | ioStream.WriteByte((byte)(len & 255)); |
| | | ioStream.Write(outBuffer, 0, len); |
| | | ioStream.Flush(); |
| | | |
| | | return outBuffer.Length + 2; |
| | | } |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Collections.Concurrent; |
| | | using System.IO; |
| | | using System.IO.Pipes; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | public static class PipeStreamUtil |
| | | { |
| | | public static string ReadMessage(this PipeStream ps) |
| | | { |
| | | |
| | | MemoryStream ms = new MemoryStream(); |
| | | byte[] buffer = new byte[0x1000]; |
| | | do |
| | | { |
| | | ms.Write(buffer, 0, ps.Read(buffer, 0, buffer.Length)); |
| | | } |
| | | while (!ps.IsMessageComplete); |
| | | return Encoding.UTF8.GetString(ms.ToArray()); |
| | | } |
| | | |
| | | public static void WriteMessage(this PipeStream ps, string message) |
| | | { |
| | | var msg = Encoding.UTF8.GetBytes(message); |
| | | ps.Write(msg, 0, msg.Length); |
| | | ps.Flush(); |
| | | } |
| | | } |
| | | |
| | | public class PipeServer2 : IDisposable |
| | | { |
| | | private readonly string _pipeName; |
| | | private readonly int _maxNumberOfServerInstances; |
| | | private readonly CancellationTokenSource _cancellationTokenSource; |
| | | private readonly ConcurrentDictionary<string, NamedPipeServerStream> _activeConnections; |
| | | private readonly ReaderWriterLockSlim _lock; |
| | | private bool _isDisposed; |
| | | private bool _isRunning; |
| | | |
| | | // 事件定义 |
| | | public event EventHandler<PipeDataEventArgs> OnData; |
| | | public event EventHandler<PipeConnectionEventArgs> OnClientConnected; |
| | | public event EventHandler<PipeConnectionEventArgs> OnClientDisconnected; |
| | | public event EventHandler<PipeErrorEventArgs> OnError; |
| | | |
| | | public PipeServer2(string pipeName, int maxNumberOfServerInstances = 254) |
| | | { |
| | | _pipeName = pipeName; |
| | | _maxNumberOfServerInstances = maxNumberOfServerInstances; |
| | | _cancellationTokenSource = new CancellationTokenSource(); |
| | | _activeConnections = new ConcurrentDictionary<string, NamedPipeServerStream>(); |
| | | _lock = new ReaderWriterLockSlim(); |
| | | } |
| | | |
| | | public void Start() |
| | | { |
| | | if (_isRunning) |
| | | return; |
| | | |
| | | _isRunning = true; |
| | | |
| | | Task.Run(() => |
| | | { |
| | | while (_isRunning && !_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | var pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.InOut, _maxNumberOfServerInstances |
| | | , PipeTransmissionMode.Message); |
| | | pipeServer.WaitForConnection(); |
| | | |
| | | string clientId = Guid.NewGuid().ToString(); |
| | | if (_activeConnections.TryAdd(clientId, pipeServer)) |
| | | { |
| | | // 启动处理客户端消息的线程 |
| | | Thread clientThread = new Thread(() => HandleClient(clientId, pipeServer)); |
| | | clientThread.Start(); |
| | | |
| | | OnClientConnected?.Invoke(this, new PipeConnectionEventArgs(clientId)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("Connect", ex)); |
| | | Thread.Sleep(1000); // 发生错误时等待一秒再重试 |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | |
| | | |
| | | private void HandleClient(string clientId, NamedPipeServerStream pipeServer) |
| | | { |
| | | try |
| | | { |
| | | while (!_cancellationTokenSource.Token.IsCancellationRequested) |
| | | { |
| | | try |
| | | { |
| | | // 等待客户端发送消息 |
| | | string message = pipeServer.ReadMessage(); |
| | | if (string.IsNullOrEmpty(message)) |
| | | break; |
| | | |
| | | OnData?.Invoke(this, new PipeDataEventArgs(clientId, message)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs("HandleClientMessageError", ex)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | if (_activeConnections.TryRemove(clientId, out var pipe)) |
| | | { |
| | | pipe.Dispose(); |
| | | } |
| | | OnClientDisconnected?.Invoke(this, new PipeConnectionEventArgs(clientId)); |
| | | } |
| | | } |
| | | |
| | | public void SendMessage(string clientId, string message) |
| | | { |
| | | if (!_activeConnections.TryGetValue(clientId, out var pipeServer)) |
| | | { |
| | | throw new InvalidOperationException($"找不到客户端 {clientId}"); |
| | | } |
| | | |
| | | _lock.EnterWriteLock(); |
| | | try |
| | | { |
| | | try |
| | | { |
| | | pipeServer.WriteMessage(message); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | OnError?.Invoke(this, new PipeErrorEventArgs($"向客户端 {clientId} 发送消息时发生错误", ex)); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | _lock.ExitWriteLock(); |
| | | } |
| | | } |
| | | |
| | | public void BroadcastMessage(string message) |
| | | { |
| | | _lock.EnterWriteLock(); |
| | | try |
| | | { |
| | | foreach (var pipeServer in _activeConnections.Values) |
| | | { |
| | | pipeServer.WriteMessage(message); |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | _lock.ExitWriteLock(); |
| | | } |
| | | } |
| | | |
| | | public void Stop() |
| | | { |
| | | _isRunning = false; |
| | | _cancellationTokenSource.Cancel(); |
| | | } |
| | | |
| | | public void Dispose() |
| | | { |
| | | if (!_isDisposed) |
| | | { |
| | | Stop(); |
| | | foreach (var pipeServer in _activeConnections.Values) |
| | | { |
| | | pipeServer.Dispose(); |
| | | } |
| | | _activeConnections.Clear(); |
| | | _cancellationTokenSource.Dispose(); |
| | | _lock.Dispose(); |
| | | _isDisposed = true; |
| | | } |
| | | } |
| | | } |
| | | } |
copy from VisionBuilder.Engine/Properties/AssemblyInfo.cs
copy to ConnectionUtil/Properties/AssemblyInfo.cs
| File was copied from VisionBuilder.Engine/Properties/AssemblyInfo.cs |
| | |
| | | // 有关程序集的一般信息由以下 |
| | | // 控制。更改这些特性值可修改 |
| | | // 与程序集关联的信息。 |
| | | [assembly: AssemblyTitle("VisionBuilder.Engine")] |
| | | [assembly: AssemblyTitle("ConnectionUtil")] |
| | | [assembly: AssemblyDescription("")] |
| | | [assembly: AssemblyConfiguration("")] |
| | | [assembly: AssemblyCompany("HP Inc.")] |
| | | [assembly: AssemblyProduct("VisionBuilder.Engine")] |
| | | [assembly: AssemblyCopyright("Copyright © HP Inc. 2024")] |
| | | [assembly: AssemblyCompany("")] |
| | | [assembly: AssemblyProduct("ConnectionUtil")] |
| | | [assembly: AssemblyCopyright("Copyright © 2025")] |
| | | [assembly: AssemblyTrademark("")] |
| | | [assembly: AssemblyCulture("")] |
| | | |
| | |
| | | [assembly: ComVisible(false)] |
| | | |
| | | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID |
| | | [assembly: Guid("8e5e8a68-0b9d-4a6a-b325-730c64603fdf")] |
| | | [assembly: Guid("d0806fa6-3f6d-4304-81b8-ead9da7cb5b2")] |
| | | |
| | | // 程序集的版本信息由下列四个值组成: |
| | | // |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 |
| | | //通过使用 "*",如下所示: |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Net.Sockets; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | public interface SCADAApi : IDisposable |
| | | { |
| | | /// <summary> |
| | | /// 连接方法 |
| | | /// </summary> |
| | | /// <param name="config"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool Connect(object config, out string errMsg); |
| | | /// <summary> |
| | | /// IP连接Scada服务器 |
| | | /// </summary> |
| | | /// <param name="IP">MES服务器IP</param> |
| | | /// <param name="Port"> MES服务器Port口</param> |
| | | /// <param name="LocalIP">本地连接IP</param> |
| | | /// <param name="LocalPort">本地连接端口</param> |
| | | /// <returns></returns> |
| | | bool Connect(string IP, int Port, string LocalIP, int LocalPort); |
| | | |
| | | /// <summary> |
| | | /// 连接Scada管理服务器 |
| | | /// </summary> |
| | | /// <param name="IP"> Scada服务器IP</param> |
| | | /// <param name="Port">ScadPort口</param> |
| | | /// <param name="LocalPort">本地连接端口</param> |
| | | /// <param name="errMsg"></param> |
| | | /// <param name="socket"></param> |
| | | /// <returns></returns> |
| | | bool Connect2(string IP, int Port, int LocalPort, out string errMsg, Socket socket = null); |
| | | |
| | | /// <summary> |
| | | /// 连接Scada管理服务器 |
| | | /// </summary> |
| | | /// <param name="IP">ScadaManagerIP</param> |
| | | /// <param name="Port">ScadaManagerPort口</param> |
| | | /// <param name="LocalPort">本地连接端口</param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool ConnectManager(string IP, int Port, int LocalPort, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 断开服务器连接 |
| | | /// </summary> |
| | | void DisConnect(); |
| | | |
| | | /// <summary> |
| | | /// 批量写增加参数 |
| | | /// </summary> |
| | | /// <param name="id"></param> |
| | | /// <param name="par"></param> |
| | | /// <returns></returns> |
| | | bool DoAddParWriteMultiple(int id, string par); |
| | | |
| | | /// <summary> |
| | | /// 换型 |
| | | /// </summary> |
| | | /// <param name="_ProductLineName"></param> |
| | | /// <param name="_ProductName"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <param name="_WorkStationName"></param> |
| | | /// <returns></returns> |
| | | bool DoDoChangeModel(string _ProductLineName, string _ProductName, out string errMsg, string _WorkStationName = null); |
| | | |
| | | /// <summary> |
| | | /// 批量读值 |
| | | /// </summary> |
| | | /// <param name="_Id"></param> |
| | | /// <returns></returns> |
| | | string[,] DoFctReadMultiple(int[] _Id); |
| | | |
| | | /// <summary> |
| | | /// 单一读值 |
| | | /// </summary> |
| | | /// <param name="_name"></param> |
| | | /// <param name="result"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool DoFctReadSingle(string _name, out string result, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 单一写值 |
| | | /// </summary> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool DoFctWriteMultiple(out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 写单一值 |
| | | /// </summary> |
| | | /// <param name="_name"></param> |
| | | /// <param name="_value"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool DoFctWriteSingle(string _name, string _value, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// mqtt发布消息 |
| | | /// </summary> |
| | | /// <param name="topic">主题</param> |
| | | /// <param name="_value">值</param> |
| | | /// <param name="errMsg">错误信息></param> |
| | | /// <returns></returns> |
| | | bool DoMqttPublish(string topic, string _value, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="_user"></param> |
| | | /// <param name="_password"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool DoLogin(string _user, string _password, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 重启DataServer服务器 |
| | | /// </summary> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool DoReSETDataServer(out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 获取动态IP |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | string getLocalIP(); |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="_paraMPairs"></param> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | short[,] GetLowerComputerStatus(short[] _paraMPairs, out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 初始化批量写参数 |
| | | /// </summary> |
| | | void InitParWriteMultiple(); |
| | | |
| | | /// <summary> |
| | | /// 检查与LTSCADA是否断开连接了 |
| | | /// </summary> |
| | | /// <param name="errMsg"></param> |
| | | /// <returns></returns> |
| | | bool IsConnected(out string errMsg); |
| | | |
| | | /// <summary> |
| | | /// 批量写 |
| | | /// </summary> |
| | | /// <param name="_paraMPairs">参数列表</param> |
| | | /// <param name="errMsg">错误信息</param> |
| | | /// <returns>处理结果</returns> |
| | | bool ToFctWriteMultiple(Dictionary<int, string> _paraMPairs, out string errMsg); |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace ConnectionUtil |
| | | { |
| | | /// <summary> |
| | | /// TCP客户端包装类 |
| | | /// </summary> |
| | | /// <summary> |
| | | /// TCP客户端包装类 |
| | | /// </summary> |
| | | public class TcpClientWrapper : IDisposable |
| | | { |
| | | private System.Net.Sockets.TcpClient _client; |
| | | private NetworkStream _stream; |
| | | private readonly string _host; |
| | | private readonly int _port; |
| | | private bool _isConnected; |
| | | private readonly CancellationTokenSource _cts; |
| | | private Task _heartbeatTask; |
| | | private readonly SemaphoreSlim _sendReceiveLock; |
| | | |
| | | /// <summary> |
| | | /// 初始化TCP客户端 |
| | | /// </summary> |
| | | /// <param name="host">服务器地址</param> |
| | | /// <param name="port">服务器端口</param> |
| | | public TcpClientWrapper(string host = "127.0.0.1", int port = 6543) |
| | | { |
| | | _host = host; |
| | | _port = port; |
| | | _cts = new CancellationTokenSource(); |
| | | _sendReceiveLock = new SemaphoreSlim(1, 1); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 异步连接到服务器 |
| | | /// </summary> |
| | | /// <returns>连接是否成功</returns> |
| | | public async Task<bool> ConnectAsync() |
| | | { |
| | | try |
| | | { |
| | | _client = new System.Net.Sockets.TcpClient(); |
| | | await _client.ConnectAsync(_host, _port); |
| | | _stream = _client.GetStream(); |
| | | _isConnected = true; |
| | | |
| | | // 启动心跳任务 |
| | | _heartbeatTask = StartHeartbeatAsync(_cts.Token); |
| | | |
| | | Console.WriteLine($"成功连接到服务器 {_host}:{_port}"); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"连接服务器失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 同步连接到服务器 |
| | | /// </summary> |
| | | /// <returns>连接是否成功</returns> |
| | | public bool Connect() |
| | | { |
| | | try |
| | | { |
| | | _client = new System.Net.Sockets.TcpClient(); |
| | | _client.Connect(_host, _port); |
| | | _stream = _client.GetStream(); |
| | | _isConnected = true; |
| | | |
| | | // 启动心跳任务 |
| | | _heartbeatTask = StartHeartbeatAsync(_cts.Token); |
| | | return true; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"连接服务器失败:{ex.Message}"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 启动心跳检测 |
| | | /// </summary> |
| | | private async Task StartHeartbeatAsync(CancellationToken token) |
| | | { |
| | | while (!token.IsCancellationRequested && _isConnected) |
| | | { |
| | | try |
| | | { |
| | | await Task.Delay(20000, token); // 20秒发送一次心跳 |
| | | if (_isConnected) |
| | | { |
| | | await SendMessageAsync("ping"); |
| | | } |
| | | } |
| | | catch (OperationCanceledException) |
| | | { |
| | | break; |
| | | } |
| | | catch (Exception) |
| | | { |
| | | _isConnected = false; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 发送消息并接收响应 |
| | | /// </summary> |
| | | /// <typeparam name="T">响应数据类型</typeparam> |
| | | /// <param name="data">要发送的数据对象</param> |
| | | /// <param name="timeout">超时时间</param> |
| | | /// <returns>服务器响应数据</returns> |
| | | public async Task<string> SendMessageAsync(string message, TimeSpan? timeout = null) |
| | | { |
| | | if (!_isConnected) |
| | | { |
| | | throw new InvalidOperationException("未连接到服务器"); |
| | | } |
| | | |
| | | TimeSpan actualTimeout = timeout ?? TimeSpan.FromSeconds(30); |
| | | |
| | | if (!await _sendReceiveLock.WaitAsync(actualTimeout)) |
| | | { |
| | | throw new TimeoutException("等待发送超时"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | byte[] messageBytes = Encoding.UTF8.GetBytes(message + "\r\n"); |
| | | |
| | | // 发送消息 |
| | | await _stream.WriteAsync(messageBytes, 0, messageBytes.Length); |
| | | |
| | | // 接收响应 |
| | | byte[] buffer = new byte[1024]; |
| | | StringBuilder response = new StringBuilder(); |
| | | int bytesRead; |
| | | |
| | | CancellationTokenSource cts = new CancellationTokenSource(actualTimeout); |
| | | |
| | | try |
| | | { |
| | | // 读取直到遇到换行符 |
| | | while ((bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length)) > 0) |
| | | { |
| | | string received = Encoding.UTF8.GetString(buffer, 0, bytesRead); |
| | | response.Append(received); |
| | | |
| | | if (received.EndsWith("\r\n")) |
| | | { |
| | | break; |
| | | } |
| | | |
| | | if (cts.Token.IsCancellationRequested) |
| | | { |
| | | throw new TimeoutException("接收响应超时"); |
| | | } |
| | | } |
| | | } |
| | | finally |
| | | { |
| | | cts.Dispose(); |
| | | } |
| | | |
| | | string jsonResponse = response.ToString().TrimEnd('\r', '\n'); |
| | | Console.WriteLine($"收到服务器响应:{jsonResponse}"); |
| | | |
| | | // 反序列化响应 |
| | | return jsonResponse; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine($"发送消息失败:{ex.Message}"); |
| | | _isConnected = false; |
| | | throw; |
| | | } |
| | | finally |
| | | { |
| | | _sendReceiveLock.Release(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 同步发送消息并接收响应 |
| | | /// </summary> |
| | | /// <typeparam name="T">响应数据类型</typeparam> |
| | | /// <param name="data">要发送的数据对象</param> |
| | | /// <param name="timeout">超时时间</param> |
| | | /// <returns>服务器响应数据</returns> |
| | | public string SendMessage(string message, TimeSpan? timeout = null) |
| | | { |
| | | timeout = timeout ?? TimeSpan.FromSeconds(30); |
| | | |
| | | try |
| | | { |
| | | // 使用 Task.Run 来执行异步操作,并等待结果 |
| | | return Task.Run(() => SendMessageAsync(message, timeout)).Result; |
| | | } |
| | | catch (AggregateException ae) |
| | | { |
| | | // 解包异常 |
| | | throw ae.InnerException; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查是否已连接 |
| | | /// </summary> |
| | | public bool IsConnected |
| | | { |
| | | get { return _isConnected; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 释放资源 |
| | | /// </summary> |
| | | public void Dispose() |
| | | { |
| | | _cts.Cancel(); |
| | | _isConnected = false; |
| | | if (_stream != null) |
| | | { |
| | | _stream.Dispose(); |
| | | } |
| | | if (_client != null) |
| | | { |
| | | _client.Dispose(); |
| | | } |
| | | _cts.Dispose(); |
| | | if (_sendReceiveLock != null) |
| | | { |
| | | _sendReceiveLock.Dispose(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 关闭连接 |
| | | /// </summary> |
| | | public void Close() |
| | | { |
| | | Dispose(); |
| | | } |
| | | } |
| | | } |
| | |
| | | <ErrorReport>prompt</ErrorReport> |
| | | <WarningLevel>4</WarningLevel> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> |
| | | <DebugSymbols>true</DebugSymbols> |
| | | <OutputPath>bin\x64\Debug\</OutputPath> |
| | | <DefineConstants>DEBUG;TRACE</DefineConstants> |
| | | <DebugType>full</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | <Prefer32Bit>true</Prefer32Bit> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> |
| | | <OutputPath>bin\x64\Release\</OutputPath> |
| | | <DefineConstants>TRACE</DefineConstants> |
| | | <Optimize>true</Optimize> |
| | | <DebugType>pdbonly</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | <Prefer32Bit>true</Prefer32Bit> |
| | | </PropertyGroup> |
| | | <ItemGroup> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Core" /> |
| | |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <None Include="App.config" /> |
| | | <None Include="Properties\app.manifest" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\ModBusTcpController\ModBusTcpController\ModBusTcpController.csproj"> |
| | | <Project>{49db0c9b-b239-4608-a91e-f5ed43afaf96}</Project> |
| | | <Name>ModBusTcpController</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\SimpleUtil\DIOController\DIOController.csproj"> |
| | | <Project>{34ffbafe-478f-4b6e-95e7-92a949011a9b}</Project> |
| | | <Name>DIOController</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\SimpleUtil\HMI.Util.Base\HMI.Util.Base.csproj"> |
| | | <Project>{d59e25d1-9b27-46a1-8438-92661dd23fae}</Project> |
| | | <Name>HMI.Util.Base</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | </Project> |
| | |
| | | using DIOController; |
| | | using HMI.Util.Base; |
| | | using ModBusTcp; |
| | | using System; |
| | | using System.Text; |
| | | |
| | |
| | | { |
| | | static void Main(string[] args) |
| | | { |
| | | string msg; |
| | | ModBusTcpController controller = new ModBusTcpController("127.0.0.1", 502); |
| | | if (controller.Start(out msg)) |
| | | { |
| | | bool res; |
| | | int? target; |
| | | |
| | | controller.WriteBool("1", true, out msg); |
| | | controller.ReadDOBool("1", out res, out msg); |
| | | Console.WriteLine(res); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | controller.WriteInt("1", 1, out msg); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | } |
| | | controller.Close(); |
| | | |
| | | //AlarmUtil.GetProcessIdByName("TestPlatform"); |
| | | |
| | | /// ModbusTcp |
| | | //IDIOController controller = DIOControllerCreator |
| | | // .CreateController("C:\\Workspace\\VisualStudio\\WPFProject\\SimpleUtil\\DIOController\\bin\\Release\\modbus.ini"); |
| | |
| | | //controller.ReadDOBool("0", out res, out msg); |
| | | //controller.WriteBool("0", true, out msg); |
| | | //controller.Dispose(); |
| | | string recvstr = "62 FD 82 39 39 39 37 32 32 36 36 30 38 34 33 39 35 33 38 53 38 44 41 30 30 32 32"; |
| | | string recvData; |
| | | if (recvstr.Contains("FF")) |
| | | { |
| | | recvData = recvstr.Replace(" ", "").Substring(6); |
| | | } |
| | | else |
| | | { |
| | | byte[] bus = HexToByteArray(recvstr.Replace(" ", "").Substring(6)); |
| | | recvData = Encoding.Default.GetString(bus); |
| | | } |
| | | //string recvstr = "62 FD 82 39 39 39 37 32 32 36 36 30 38 34 33 39 35 33 38 53 38 44 41 30 30 32 32"; |
| | | //string recvData; |
| | | //if (recvstr.Contains("FF")) |
| | | //{ |
| | | // recvData = recvstr.Replace(" ", "").Substring(6); |
| | | //} |
| | | //else |
| | | //{ |
| | | // byte[] bus = HexToByteArray(recvstr.Replace(" ", "").Substring(6)); |
| | | // recvData = Encoding.Default.GetString(bus); |
| | | //} |
| | | } |
| | | |
| | | public static byte[] HexToByteArray(string hexString) |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <assemblyIdentity version="1.0.0.0" name="MyApplication.app" /> |
| | | <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> |
| | | <security> |
| | | <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> |
| | | <!-- UAC 清单选项 |
| | | 如果想要更改 Windows 用户帐户控制级别,请使用 |
| | | 以下节点之一替换 requestedExecutionLevel 节点。 |
| | | |
| | | <requestedExecutionLevel level="asInvoker" uiAccess="false" /> |
| | | <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> |
| | | <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> |
| | | |
| | | 指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。 |
| | | 如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此 |
| | | 元素。 |
| | | --> |
| | | <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> |
| | | </requestedPrivileges> |
| | | <applicationRequestMinimum> |
| | | <defaultAssemblyRequest permissionSetReference="Custom" /> |
| | | <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" Unrestricted="true" /> |
| | | </applicationRequestMinimum> |
| | | </security> |
| | | </trustInfo> |
| | | <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
| | | <application> |
| | | <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的 |
| | | Windows 版本的列表。取消评论适当的元素, |
| | | Windows 将自动选择最兼容的环境。 --> |
| | | <!-- Windows Vista --> |
| | | <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> |
| | | <!-- Windows 7 --> |
| | | <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> |
| | | <!-- Windows 8 --> |
| | | <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> |
| | | <!-- Windows 8.1 --> |
| | | <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> |
| | | <!-- Windows 10 --> |
| | | <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> |
| | | </application> |
| | | </compatibility> |
| | | <!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行 |
| | | 自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需 |
| | | 选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应 |
| | | 在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。 |
| | | |
| | | 将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation --> |
| | | <!-- |
| | | <application xmlns="urn:schemas-microsoft-com:asm.v3"> |
| | | <windowsSettings> |
| | | <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> |
| | | <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> |
| | | </windowsSettings> |
| | | </application> |
| | | --> |
| | | <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) --> |
| | | <!-- |
| | | <dependency> |
| | | <dependentAssembly> |
| | | <assemblyIdentity |
| | | type="win32" |
| | | name="Microsoft.Windows.Common-Controls" |
| | | version="6.0.0.0" |
| | | processorArchitecture="*" |
| | | publicKeyToken="6595b64144ccf1df" |
| | | language="*" |
| | | /> |
| | | </dependentAssembly> |
| | | </dependency> |
| | | --> |
| | | </assembly> |
| | |
| | | /// <summary> |
| | | /// 代码管理 |
| | | /// </summary> |
| | | private ObservableCollection<AlarmSetting> alarmSettings = new ObservableCollection<AlarmSetting>(); |
| | | private ObservableCollection<AlarmSetting> blockAlarmSettings = new ObservableCollection<AlarmSetting>(); |
| | | |
| | | public ObservableCollection<AlarmSetting> BlockAlarmSettings |
| | | { |
| | | get => blockAlarmSettings; |
| | | set |
| | | { |
| | | blockAlarmSettings = value; |
| | | RefreshBlockCache(); |
| | | } |
| | | } |
| | | private Dictionary<string, Dictionary<string, string>> BlockMap = new Dictionary<string, Dictionary<string, string>>(); |
| | | private Dictionary<string, string> BlockReadCache = new Dictionary<string, string>(); |
| | | |
| | | private void RefreshBlockCache() |
| | | { |
| | | BlockMap.Clear(); |
| | | BlockReadCache.Clear(); |
| | | if (BlockAlarmSettings == null || BlockAlarmSettings.Count <= 0) |
| | | { |
| | | return; |
| | | } |
| | | foreach (var setting in BlockAlarmSettings) |
| | | { |
| | | string key = $"{setting.DBAddress}.{setting.StartAddress}"; |
| | | if (!BlockMap.ContainsKey(key)) |
| | | { |
| | | BlockMap[key] = new Dictionary<string, string>(); |
| | | } |
| | | var codes = BlockMap[key]; |
| | | codes[setting.AlarmCode] = setting.Description; |
| | | } |
| | | } |
| | | |
| | | // <summary> |
| | | /// 标志位报警管理 |
| | | /// </summary> |
| | |
| | | /// </summary> |
| | | private List<AlarmText> currentAlarmCachePlcToMain = new List<AlarmText>(); |
| | | |
| | | private AlarmText alarm; |
| | | //private AlarmText alarm; |
| | | private SystemSetting systemSetting; |
| | | |
| | | private ObservableCollection<AlarmText> datasource = new ObservableCollection<AlarmText>(); |
| | |
| | | |
| | | MonitorTimer = new Timer |
| | | { |
| | | Interval = 100, |
| | | Interval = 1000, |
| | | }; |
| | | MonitorTimer.Elapsed += MonitorTimer_Elapsed; |
| | | if (!lTSCADAApi.Connect2(opcIP, opcPort, localPort, out string errMsg)) |
| | |
| | | |
| | | PcTimer = new Timer |
| | | { |
| | | Interval = 100, |
| | | Interval = 1000, |
| | | AutoReset = false |
| | | }; |
| | | PcTimer.Elapsed += PcTimer_Elapsed; |
| | |
| | | |
| | | private void OpenSettingWindow() |
| | | { |
| | | AlarmSettingList listModal = new AlarmSettingList(blockPath, markPath,alarmSettings,markAlarmSetting, log) |
| | | AlarmSettingList listModal = new AlarmSettingList(blockPath, markPath, BlockAlarmSettings, markAlarmSetting, log) |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | listModal.ShowDialog(); |
| | | alarmSettings = listModal.Datasource; |
| | | BlockAlarmSettings = listModal.Datasource; |
| | | markAlarmSetting = listModal.MarkDatasource; |
| | | } |
| | | |
| | |
| | | { |
| | | try |
| | | { |
| | | alarmSettings = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(blockPath); |
| | | BlockAlarmSettings = XmlHelper.DeserializeFromXml<ObservableCollection<AlarmSetting>>(blockPath); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("LoadAlarmSetting Error.", ex); |
| | | alarmSettings = new ObservableCollection<AlarmSetting>(); |
| | | BlockAlarmSettings = new ObservableCollection<AlarmSetting>(); |
| | | } |
| | | |
| | | try |
| | |
| | | case "AlarmCode": |
| | | AlarmText aalarm = AlarmTexts.FirstOrDefault(alarm => alarm.AlarmCode == MsgStr); |
| | | if (aalarm == null) break; |
| | | var data = new AlarmText { |
| | | var data = new AlarmText |
| | | { |
| | | Source = "PC", |
| | | AlarmCode = aalarm.AlarmCode, |
| | | AlarmInfo = aalarm.MAlarmText_CN, |
| | |
| | | // } |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// PLC报警读取 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void MonitorTimer_Elapsed(object sender, ElapsedEventArgs e) |
| | | { |
| | | try |
| | |
| | | |
| | | isHaveAlarm = false; |
| | | List<AlarmText> cache = new List<AlarmText>(); |
| | | foreach (var item in alarmSettings) |
| | | //foreach (var item in BlockAlarmSettings) |
| | | //{ |
| | | // var name = $"{item.DBAddress}.{item.StartAddress}"; |
| | | // if (lTSCADAApi.DoFctReadSingle(name, out string alarmCode, out errMsg) && alarmCode != "0") |
| | | // { |
| | | // isHaveAlarm = true; |
| | | // if (!textMap.TryGetValue(alarmCode, out alarm)) { |
| | | // continue; |
| | | // } |
| | | // var newAlarm = new AlarmText |
| | | // { |
| | | // Source = "PLC", |
| | | // AlarmCode = alarm.AlarmCode, |
| | | // ModuleName_CN = alarm.ModuleName_CN, |
| | | // MAlarmText_CN = alarm.MAlarmText_CN, |
| | | // Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | // AlarmInfo = $"{alarm.ModuleName_CN} {alarm.MAlarmText_CN}" |
| | | // }; |
| | | // if (this.currentAlarmCachePlc |
| | | // .Find(alarm => alarm.AlarmCode == newAlarm.AlarmCode) == null) |
| | | // { |
| | | // this.currentAlarmCachePlc.Add(newAlarm); |
| | | // } |
| | | // } |
| | | //} |
| | | |
| | | foreach (var key in BlockMap.Keys) |
| | | { |
| | | var name = $"{item.DBAddress}.{item.StartAddress}"; |
| | | if (lTSCADAApi.DoFctReadSingle(name, out string alarmCode, out errMsg) && alarmCode != "0") |
| | | if (lTSCADAApi.DoFctReadSingle(key, out string alarmCode, out errMsg) && BlockMap[key].ContainsKey(alarmCode)) |
| | | { |
| | | //if(BlockReadCache.ContainsKey(key) && alarmCode) |
| | | isHaveAlarm = true; |
| | | if (!textMap.TryGetValue(alarmCode, out alarm)) { |
| | | continue; |
| | | } |
| | | var text = BlockMap[key][alarmCode]; |
| | | var newAlarm = new AlarmText |
| | | { |
| | | PLC_DB_BLOCK = key, |
| | | Source = "PLC", |
| | | AlarmCode = alarm.AlarmCode, |
| | | ModuleName_CN = alarm.ModuleName_CN, |
| | | MAlarmText_CN = alarm.MAlarmText_CN, |
| | | AlarmCode = alarmCode, |
| | | ModuleName_CN = text, |
| | | MAlarmText_CN = text, |
| | | Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), |
| | | AlarmInfo = $"{alarm.ModuleName_CN} {alarm.MAlarmText_CN}" |
| | | AlarmInfo = $"{alarmCode} {text}" |
| | | }; |
| | | if (this.currentAlarmCachePlc |
| | | .Find(alarm => alarm.AlarmCode == newAlarm.AlarmCode) == null) |
| | | .Find(alarm => alarm.AlarmCode == newAlarm.AlarmCode && alarm.PLC_DB_BLOCK == newAlarm.PLC_DB_BLOCK) == null) |
| | | { |
| | | this.currentAlarmCachePlc.Add(newAlarm); |
| | | } |
| | |
| | | private void RefreshDBSetting() |
| | | { |
| | | List<byte> bytes = new List<byte>(); |
| | | foreach (var item in alarmSettings) |
| | | foreach (var item in BlockAlarmSettings) |
| | | { |
| | | //byte[] itemalarmCodeBytes = this.plc.Simens_S7_ReadBytes_DB("DB", item.DBAddress, item.StartAddress, item.Length); |
| | | //bytes.AddRange(itemalarmCodeBytes.ToList()); |
| | |
| | | } |
| | | } |
| | | this.currentAlarmCachePc.Clear(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 发送日志消息 |
| | | /// </summary> |
| | | /// <param name="Msg">日志消息</param> |
| | | private void SendLogMsg(string Msg) |
| | | { |
| | | string LogMsg = "{\"Type\":\"Alarm\",\"Source\":\"" + alarm.Source + "\",\"Msg\":\"" + Msg + "\",\"Time\":\"" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\"}"; |
| | | this.loggeralarm.Send("Log", LogMsg); |
| | | } |
| | | } |
| | | } |
| | |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="300"> |
| | | <GridViewColumn Width="100"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource Alm.DbAddress}"/> |
| | | </GridViewColumn.Header> |
| | |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="200"> |
| | | <GridViewColumn Width="150"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource Alm.StartAddress}"/> |
| | | </GridViewColumn.Header> |
| | |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="200"> |
| | | <GridViewColumn Width="100"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource Alm.DbLength}"/> |
| | | </GridViewColumn.Header> |
| | |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="150"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="报警代码"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding AlarmCode}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="250"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="报警文本"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Description}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource App.Opt}"/> |
| | |
| | | [ExcelColumn("长度")] |
| | | public int Length { get; set; } |
| | | |
| | | [ExcelColumn("报警代码")] |
| | | public string AlarmCode { get; set; } |
| | | |
| | | [ExcelColumn("报警描述")] |
| | | public string Description { get; set; } |
| | | } |
| | |
| | | /// </summary> |
| | | [XmlIgnore] |
| | | public string Source { get; set; } |
| | | |
| | | [XmlIgnore] |
| | | public string PLC_DB_BLOCK { get; set; } |
| | | } |
| | | } |
| | |
| | | <Generator>ResXFileCodeGenerator</Generator> |
| | | <LastGenOutput>Resources.Designer.cs</LastGenOutput> |
| | | </EmbeddedResource> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | <None Include="Properties\Settings.settings"> |
| | | <Generator>SettingsSingleFileGenerator</Generator> |
| | |
| | | </None> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\ConnectionUtil\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{D0806FA6-3F6D-4304-81B8-EAD9DA7CB5B2}</Project> |
| | | <ProjectReference Include="..\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{d0806fa6-3f6d-4304-81b8-ead9da7cb5b2}</Project> |
| | | <Name>ConnectionUtil</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj"> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <configuration> |
| | | <runtime> |
| | | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <dependentAssembly> |
| | | <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> |
| | | <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> |
| | | </dependentAssembly> |
| | | </assemblyBinding> |
| | | </runtime> |
| | | </configuration> |
| | |
| | | |
| | | public string LogoPath { get; private set; } = ".\\JingCeLogo.png"; |
| | | public string WindowTitle { get; private set; } = "产品测试平台"; |
| | | public string PlcIp { get; private set; } |
| | | public string PlcIp { get; private set; } = "127.0.0.1"; |
| | | public int PlcPort { get; private set; } = 102; |
| | | public bool PlcEnabled { get; private set; } |
| | | public string CurrentLanguage { get; private set; } = "zh-CN"; |
| | | public int LogExpiredDays { get; private set; } = 7; |
| | |
| | | set { Set(ref plcIp, value); } |
| | | } |
| | | |
| | | private int plcPort; |
| | | public int PlcPort |
| | | { |
| | | get => plcPort; |
| | | set { Set(ref plcPort, value); } |
| | | } |
| | | |
| | | private bool plcEnabled; |
| | | public bool PlcEnabled |
| | | { |
| | |
| | | Map.Clear(); |
| | | foreach (var data in settings) |
| | | { |
| | | Map.Add(data.Program, data); |
| | | Map[data.Program] = data; |
| | | names.Add(data.Program); |
| | | } |
| | | programInput.ItemsSource = names; |
| | |
| | | { |
| | | ObservableCollection<MenuData> data = new ObservableCollection<MenuData>(); |
| | | ObservableCollection<MenuData> treeData = new ObservableCollection<MenuData>(); |
| | | DataTable dt = sqliteHelper.GetDataTable("SELECT m1.*,m2.name AS parentName FROM menu AS m1 LEFT JOIN menu AS m2 ON m1.parentCode = m2.code Order By m1.sort,m1.id;"); |
| | | DataTable dt = sqliteHelper.GetDataTable("SELECT m1.*,m2.name AS parentName FROM menu AS m1 LEFT JOIN menu AS m2 ON m1.parentCode = m2.code Order By IIF(m1.level=1,m1.sort,m2.sort),IIF(m1.level=1,0,m1.sort),m1.id;"); |
| | | Dictionary<string, MenuData> cache = new Dictionary<string, MenuData>(); |
| | | if (dt != null) |
| | | { |
| | |
| | | |
| | | private bool ValidateForm() |
| | | { |
| | | bool flag = FormGroupHelper.ValidateForm(formPanel, new Dictionary<string, object> { |
| | | var cache = new Dictionary<string, object> { |
| | | { "FgValue",GetTargetValue()} |
| | | }); |
| | | }; |
| | | bool flag = FormGroupHelper.ValidateForm(formPanel, cache); |
| | | if (flag) |
| | | { |
| | | Data.Name = TbName.Text; |
| | |
| | | |
| | | private string GetTargetValue() |
| | | { |
| | | if (CbType.Text == "Int" || Data.Type == "Double") |
| | | var type = CbType.Text; |
| | | if (type == "Int" || type == "Double") |
| | | { |
| | | return NiNumberValue.Text; |
| | | } |
| | | else if (CbType.Text == "Bool") |
| | | else if (type == "Bool") |
| | | { |
| | | return CbBoolValue.Text; |
| | | } |
| | |
| | | |
| | | private string GetTargetValue() |
| | | { |
| | | if (CbType.Text == "Int" || Data.Type == "Double") |
| | | var type = CbType.Text; |
| | | if (type == "Int" || type == "Double") |
| | | { |
| | | return NiNumberValue.Text; |
| | | } |
| | | else if (CbType.Text == "Bool") |
| | | else if (type == "Bool") |
| | | { |
| | | return CbBoolValue.Text; |
| | | } |
| | |
| | | <GroupBox Grid.Row="1" Header="{DynamicResource Setting.PlcSetting}" Padding="10"> |
| | | <StackPanel> |
| | | <pu:FormGroup Header="{DynamicResource Setting.PlcIp}" HeaderWidth="Auto" GroupName="MyFormGroup"> |
| | | <TextBox Text="{Binding PlcIp}"/> |
| | | <TextBox Text="{Binding PlcIp,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup Header="PLC Port" HeaderWidth="Auto" GroupName="MyFormGroup"> |
| | | <pu:NumberInput Value="{Binding PlcPort,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="{DynamicResource Setting.PlcEnabled}" HeaderWidth="Auto" GroupName="MyFormGroup"> |
| | | <CheckBox IsChecked="{Binding PlcEnabled,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> |
| | | </pu:FormGroup> |
copy from VisionBuilder.Engine/VisionBuilder.Engine.csproj
copy to HMI.StdControl/HMI.StdControl.csproj
| File was copied from VisionBuilder.Engine/VisionBuilder.Engine.csproj |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
| | | <PropertyGroup> |
| | | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
| | | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
| | | <ProjectGuid>{8E5E8A68-0B9D-4A6A-B325-730C64603FDF}</ProjectGuid> |
| | | <ProjectGuid>{7A066856-182F-4435-B648-E9FB91AFF657}</ProjectGuid> |
| | | <OutputType>Library</OutputType> |
| | | <AppDesignerFolder>Properties</AppDesignerFolder> |
| | | <RootNamespace>VisionBuilder.Engine</RootNamespace> |
| | | <AssemblyName>VisionBuilder.Engine</AssemblyName> |
| | | <RootNamespace>HMI.StdControl</RootNamespace> |
| | | <AssemblyName>HMI.StdControl</AssemblyName> |
| | | <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
| | | <FileAlignment>512</FileAlignment> |
| | | <Deterministic>true</Deterministic> |
| | |
| | | <ErrorReport>prompt</ErrorReport> |
| | | <WarningLevel>4</WarningLevel> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> |
| | | <DebugSymbols>true</DebugSymbols> |
| | | <OutputPath>bin\x64\Debug\</OutputPath> |
| | | <DefineConstants>DEBUG;TRACE</DefineConstants> |
| | | <DebugType>full</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> |
| | | <OutputPath>bin\x64\Release\</OutputPath> |
| | | <DefineConstants>TRACE</DefineConstants> |
| | | <Optimize>true</Optimize> |
| | | <DebugType>pdbonly</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | </PropertyGroup> |
| | | <ItemGroup> |
| | | <Reference Include="PresentationCore" /> |
| | | <Reference Include="PresentationFramework" /> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Core" /> |
| | | <Reference Include="System.Xaml" /> |
| | | <Reference Include="System.Xml.Linq" /> |
| | | <Reference Include="System.Data.DataSetExtensions" /> |
| | | <Reference Include="Microsoft.CSharp" /> |
| | | <Reference Include="System.Data" /> |
| | | <Reference Include="System.Net.Http" /> |
| | | <Reference Include="System.Xml" /> |
| | | <Reference Include="WindowsBase" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="Runner.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | <Compile Include="StdEnableMes.xaml.cs"> |
| | | <DependentUpon>StdEnableMes.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="StdUIEventArg.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Page Include="StdEnableMes.xaml"> |
| | | <SubType>Designer</SubType> |
| | | <Generator>MSBuild:Compile</Generator> |
| | | </Page> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj"> |
| | | <Project>{3e3bf44a-0b69-45c5-9512-528cb48a7106}</Project> |
| | | <Project>{3E3BF44A-0B69-45C5-9512-528CB48A7106}</Project> |
| | | <Name>HMI.Core</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
copy from VisionBuilder.Engine/Properties/AssemblyInfo.cs
copy to HMI.StdControl/Properties/AssemblyInfo.cs
| File was copied from VisionBuilder.Engine/Properties/AssemblyInfo.cs |
| | |
| | | // 有关程序集的一般信息由以下 |
| | | // 控制。更改这些特性值可修改 |
| | | // 与程序集关联的信息。 |
| | | [assembly: AssemblyTitle("VisionBuilder.Engine")] |
| | | [assembly: AssemblyTitle("HMI.StdControl")] |
| | | [assembly: AssemblyDescription("")] |
| | | [assembly: AssemblyConfiguration("")] |
| | | [assembly: AssemblyCompany("HP Inc.")] |
| | | [assembly: AssemblyProduct("VisionBuilder.Engine")] |
| | | [assembly: AssemblyCopyright("Copyright © HP Inc. 2024")] |
| | | [assembly: AssemblyCompany("")] |
| | | [assembly: AssemblyProduct("HMI.StdControl")] |
| | | [assembly: AssemblyCopyright("Copyright © 2025")] |
| | | [assembly: AssemblyTrademark("")] |
| | | [assembly: AssemblyCulture("")] |
| | | |
| | |
| | | [assembly: ComVisible(false)] |
| | | |
| | | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID |
| | | [assembly: Guid("8e5e8a68-0b9d-4a6a-b325-730c64603fdf")] |
| | | [assembly: Guid("7a066856-182f-4435-b648-e9fb91aff657")] |
| | | |
| | | // 程序集的版本信息由下列四个值组成: |
| | | // |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 |
| | | //通过使用 "*",如下所示: |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| New file |
| | |
| | | <UserControl x:Class="HMI.StdControl.StdEnableMes" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:HMI.StdControl" |
| | | mc:Ignorable="d" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <CheckBox x:Name="CbEnableMes" IsChecked="{Binding EnableMes,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | VerticalContentAlignment="Center" |
| | | Content="{DynamicResource Ts.EnableMes}" /> |
| | | </UserControl> |
| New file |
| | |
| | | using HMI.Core.Manager; |
| | | using System; |
| | | using System.ComponentModel; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace HMI.StdControl |
| | | { |
| | | /// <summary> |
| | | /// StdEnableMes.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class StdEnableMes : UserControl, INotifyPropertyChanged |
| | | { |
| | | |
| | | #region ... |
| | | public virtual event PropertyChangedEventHandler PropertyChanged; |
| | | |
| | | protected virtual void Set([CallerMemberName] string name = null) |
| | | { |
| | | |
| | | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); |
| | | } |
| | | |
| | | protected void Set<T>(ref T old, T @new, [CallerMemberName] string propertyName = null) |
| | | { |
| | | old = @new; |
| | | if (propertyName != null) |
| | | { |
| | | Set(propertyName); |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | private event EventHandler<StdUIEventArg> valueChanged; |
| | | public event EventHandler<StdUIEventArg> ValueChanged |
| | | { |
| | | add |
| | | { |
| | | valueChanged += value; |
| | | } |
| | | remove |
| | | { |
| | | valueChanged -= value; |
| | | } |
| | | } |
| | | |
| | | private bool enableMes; |
| | | public bool EnableMes |
| | | { |
| | | get => enableMes; |
| | | set |
| | | { |
| | | if (WriteConfig("EnableMes", value)) |
| | | { |
| | | Set(ref enableMes, value); |
| | | } |
| | | Set(ref enableMes, value); |
| | | } |
| | | } |
| | | |
| | | public StdEnableMes() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName("EnableMes"); |
| | | if (value == null) |
| | | { |
| | | this.Visibility = System.Windows.Visibility.Collapsed; |
| | | } |
| | | else |
| | | { |
| | | enableMes = bool.Parse(value.Value); |
| | | Set("EnableMes"); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | enableMes = false; |
| | | Set("EnableMes"); |
| | | } |
| | | } |
| | | |
| | | private bool WriteConfig(string name, bool value) |
| | | { |
| | | try |
| | | { |
| | | valueChanged?.Invoke(this, new StdUIEventArg() |
| | | { |
| | | StringValue = name, |
| | | BoolValue = value |
| | | }); |
| | | return ParameterManager.UpdateCommonParameter(name, value, out string errMsg); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace HMI.StdControl |
| | | { |
| | | public class StdUIEventArg |
| | | { |
| | | public string StringValue { get; set; } |
| | | public bool BoolValue { get; set; } |
| | | } |
| | | } |
| | |
| | | |
| | | public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( |
| | | "Value", |
| | | typeof(bool), |
| | | typeof(bool?), |
| | | typeof(LightBall), |
| | | new FrameworkPropertyMetadata(false)); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | public bool Value |
| | | public bool? Value |
| | | { |
| | | get => (bool)GetValue(ValueProperty); |
| | | get => (bool?)GetValue(ValueProperty); |
| | | set |
| | | { |
| | | SetValue(ValueProperty, value); |
| | |
| | | <Compile Include="ScannerSetting.xaml.cs"> |
| | | <DependentUpon>ScannerSetting.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="ScrollLabel.cs" /> |
| | | <Compile Include="Style\BaseWindow.xaml.cs"> |
| | | <DependentUpon>BaseWindow.xaml</DependentUpon> |
| | | </Compile> |
| New file |
| | |
| | | using System; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media.Animation; |
| | | |
| | | namespace HMI.UI |
| | | { |
| | | public class ScrollLabel : Control |
| | | { |
| | | static ScrollLabel() |
| | | { |
| | | DefaultStyleKeyProperty.OverrideMetadata(typeof(ScrollLabel), new FrameworkPropertyMetadata(typeof(ScrollLabel))); |
| | | } |
| | | |
| | | private DoubleAnimation animation; |
| | | |
| | | public override void OnApplyTemplate() |
| | | { |
| | | base.OnApplyTemplate(); |
| | | |
| | | // 在模板应用后启动初始动画 |
| | | var scrollViewer = GetTemplateChild("slv") as ScrollViewer; |
| | | var label = GetTemplateChild("label") as Label; |
| | | if (scrollViewer != null) |
| | | { |
| | | // 等待布局完成后再启动动画 |
| | | scrollViewer.Loaded += (s, e) => |
| | | { |
| | | var storyboard = new Storyboard(); |
| | | animation = new DoubleAnimation |
| | | { |
| | | From = 0, |
| | | To = scrollViewer.ScrollableWidth, |
| | | Duration = new Duration(TimeSpan.FromSeconds(3)), |
| | | AutoReverse = true, |
| | | RepeatBehavior = RepeatBehavior.Forever, |
| | | BeginTime = TimeSpan.FromSeconds(0.2) |
| | | }; |
| | | |
| | | Storyboard.SetTarget(animation, scrollViewer); |
| | | Storyboard.SetTargetProperty(animation, new PropertyPath(ScrollViewerBehavior.HorizontalOffsetProperty)); |
| | | |
| | | storyboard.Children.Add(animation); |
| | | scrollViewer.Resources["ScrollAnimation"] = storyboard; |
| | | storyboard.Begin(); |
| | | }; |
| | | } |
| | | } |
| | | |
| | | private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) |
| | | { |
| | | //RefreshAnimation(); |
| | | } |
| | | |
| | | private void RefreshAnimation() |
| | | { |
| | | // 查找ScrollViewer并重新启动动画 |
| | | var scrollViewer = GetTemplateChild("slv") as ScrollViewer; |
| | | |
| | | if (scrollViewer != null) |
| | | { |
| | | scrollViewer.Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | // 停止当前动画 |
| | | var storyboard = scrollViewer.Resources["ScrollAnimation"] as Storyboard; |
| | | if (storyboard != null) |
| | | { |
| | | storyboard.Stop(); |
| | | if (animation != null) |
| | | { |
| | | animation.To = scrollViewer.ScrollableWidth; |
| | | } |
| | | storyboard.Begin(); |
| | | } |
| | | |
| | | }), System.Windows.Threading.DispatcherPriority.Background); |
| | | } |
| | | } |
| | | |
| | | public static readonly DependencyProperty ValueProperty = |
| | | DependencyProperty.RegisterAttached("Value", typeof(string), typeof(ScrollLabel), |
| | | new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnValueChanged))); |
| | | |
| | | private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) |
| | | { |
| | | var scrollLabel = obj as ScrollLabel; |
| | | scrollLabel?.RefreshAnimation(); |
| | | } |
| | | |
| | | public event EventHandler<string> ValueChanged; |
| | | |
| | | public string Value |
| | | { |
| | | get { return (string)GetValue(ValueProperty); } |
| | | set |
| | | { |
| | | SetValue(ValueProperty, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static class ScrollViewerBehavior |
| | | { |
| | | public static readonly DependencyProperty HorizontalOffsetProperty = |
| | | DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ScrollViewerBehavior), |
| | | new UIPropertyMetadata(0.0, OnHorizontalOffsetChanged)); |
| | | public static void SetHorizontalOffset(FrameworkElement target, double value) |
| | | { |
| | | target.SetValue(HorizontalOffsetProperty, value); |
| | | } |
| | | public static double GetHorizontalOffset(FrameworkElement target) |
| | | { |
| | | return (double)target.GetValue(HorizontalOffsetProperty); |
| | | } |
| | | private static void OnHorizontalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) |
| | | { |
| | | var view = target as ScrollViewer; |
| | | if (view != null) |
| | | { |
| | | view.ScrollToHorizontalOffset((double)e.NewValue); |
| | | } |
| | | } |
| | | |
| | | public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ScrollViewerBehavior), new UIPropertyMetadata(0.0, OnVerticalOffsetChanged)); |
| | | public static void SetVerticalOffset(FrameworkElement target, double value) |
| | | { |
| | | target.SetValue(VerticalOffsetProperty, value); |
| | | } |
| | | public static double GetVerticalOffset(FrameworkElement target) |
| | | { |
| | | return (double)target.GetValue(VerticalOffsetProperty); |
| | | } |
| | | private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) |
| | | { |
| | | var view = target as ScrollViewer; |
| | | if (view != null) |
| | | { |
| | | view.ScrollToVerticalOffset((double)e.NewValue); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | <Brush x:Key="CellValue">#f6f7d7</Brush> |
| | | |
| | | <LinearGradientBrush x:Key="PrimaryColor1" StartPoint="0.5,0" EndPoint="0.5,1"> |
| | | <!--<GradientStop Color="#369bdb" Offset="0.027"/> |
| | | <GradientStop Color="#2b577f" Offset="0.994"/>--> |
| | | <!--<LinearGradientBrush x:Key="PrimaryColor1" StartPoint="0.5,0" EndPoint="0.5,1"> |
| | | <GradientStop Color="#557ec8" Offset="0.027"/> |
| | | <GradientStop Color="#375aa3" Offset="0.994"/> |
| | | </LinearGradientBrush> |
| | | </LinearGradientBrush>--> |
| | | |
| | | <LinearGradientBrush x:Key="HoriBar" StartPoint="0,0.5" EndPoint="1,0.5"> |
| | | <Brush x:Key="PrimaryColor1">#22448b</Brush> |
| | | <Brush x:Key="HoriBar">#22448b</Brush> |
| | | <Brush x:Key="ReHoriBar">#22448b</Brush> |
| | | <Brush x:Key="TableHeader">#22448b</Brush> |
| | | <Brush x:Key="VerBar">#22448b</Brush> |
| | | <Brush x:Key="ReVerBar">#22448b</Brush> |
| | | |
| | | <!--<LinearGradientBrush x:Key="HoriBar" StartPoint="0,0.5" EndPoint="1,0.5"> |
| | | <GradientStop Color="#5d87d2" Offset="0"/> |
| | | <GradientStop Color="#22448b" Offset="1"/> |
| | | </LinearGradientBrush> |
| | |
| | | <GradientStop Color="#23458c" Offset="0"/> |
| | | <GradientStop Color="#4268b1" Offset="0.5"/> |
| | | <GradientStop Color="#5d87d2" Offset="1"/> |
| | | </LinearGradientBrush> |
| | | </LinearGradientBrush>--> |
| | | |
| | | <LinearGradientBrush x:Key="GreenVerBar" StartPoint="0.5,0" EndPoint="0.5,1"> |
| | | <Brush x:Key="GreenVerBar">#21c418</Brush> |
| | | <Brush x:Key="DangerVerBar">#d64343</Brush> |
| | | |
| | | |
| | | <!--<LinearGradientBrush x:Key="GreenVerBar" StartPoint="0.5,0" EndPoint="0.5,1"> |
| | | <GradientStop Color="#28ea1d" Offset="0"/> |
| | | <GradientStop Color="#21c418" Offset="0.5"/> |
| | | <GradientStop Color="#1b9e14" Offset="1"/> |
| | |
| | | <GradientStop Color="#fd583e" Offset="0"/> |
| | | <GradientStop Color="#d5341f" Offset="0.5"/> |
| | | <GradientStop Color="#aa0e00" Offset="1"/> |
| | | </LinearGradientBrush> |
| | | </LinearGradientBrush>--> |
| | | |
| | | <RadialGradientBrush x:Key="Normal" GradientOrigin="0.5,0.5" |
| | | RadiusX="0.75" |
| | |
| | | xmlns:puconfig="clr-namespace:Panuon.WPF.UI.Configurations;assembly=Panuon.WPF.UI"> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxWarn" |
| | | InteropOwnersMask="True" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | |
| | | </pu:MessageBoxXSettings> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxError" |
| | | InteropOwnersMask="True" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | |
| | | </pu:MessageBoxXSettings> |
| | | |
| | | <pu:MessageBoxXSettings x:Key="MsgBoxInfo" |
| | | InteropOwnersMask="True" |
| | | InteropOwnersMask="False" |
| | | InverseButtonsSequence="False"> |
| | | <pu:MessageBoxXSettings.WindowXStyle> |
| | | <Style TargetType="pu:WindowX" BasedOn="{StaticResource {x:Static pu:MessageBoxX.WindowXStyleKey}}"> |
| | |
| | | <Ellipse Height="{TemplateBinding Size}" Width="{TemplateBinding Size}" VerticalAlignment="Center"> |
| | | <Ellipse.Style> |
| | | <Style TargetType="Ellipse"> |
| | | <Setter Property="Fill" Value="{StaticResource RedLight}"/> |
| | | <Setter Property="Fill" Value="Gray"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Value,RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True"> |
| | | <Setter Property="Fill" Value="{StaticResource GreenLight}"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Value,RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="False"> |
| | | <Setter Property="Fill" Value="{StaticResource RedLight}"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | |
| | | <Style TargetType="{x:Type local:ScrollLabel}"> |
| | | <Setter Property="Template"> |
| | | <Setter.Value> |
| | | <ControlTemplate TargetType="{x:Type local:ScrollLabel}"> |
| | | <ScrollViewer Name="slv" IsHitTestVisible="False" Width="{TemplateBinding Width}" |
| | | VerticalScrollBarVisibility="Hidden" |
| | | BorderThickness="0" |
| | | HorizontalScrollBarVisibility="Hidden"> |
| | | <Label x:Name="label" Content="{Binding Path=Value, RelativeSource={RelativeSource TemplatedParent}}" |
| | | VerticalContentAlignment="Center" |
| | | BorderThickness="0" |
| | | Foreground="{TemplateBinding Foreground}" |
| | | Padding="{TemplateBinding Padding}" |
| | | Margin="{TemplateBinding Margin}" |
| | | HorizontalContentAlignment="Left" FontSize="{TemplateBinding FontSize}"> |
| | | <!--<Label.Triggers> |
| | | <EventTrigger RoutedEvent="Label.Loaded"> |
| | | <BeginStoryboard HandoffBehavior="Compose"> |
| | | <Storyboard> |
| | | <DoubleAnimation From="0" |
| | | To="{Binding ElementName=slv,Path=ScrollableWidth}" |
| | | Duration="0:0:3" |
| | | Storyboard.TargetName="slv" |
| | | AutoReverse="True" |
| | | RepeatBehavior="Forever" |
| | | BeginTime="0:0:0.2" |
| | | Storyboard.TargetProperty="(local:ScrollViewerBehavior.HorizontalOffset)"> |
| | | </DoubleAnimation> |
| | | </Storyboard> |
| | | </BeginStoryboard> |
| | | </EventTrigger> |
| | | </Label.Triggers>--> |
| | | </Label> |
| | | </ScrollViewer> |
| | | </ControlTemplate> |
| | | </Setter.Value> |
| | | </Setter> |
| | | </Style> |
| | | </ResourceDictionary> |
| | |
| | | <Project>{d0806fa6-3f6d-4304-81b8-ead9da7cb5b2}</Project> |
| | | <Name>ConnectionUtil</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\..\ModBusTcpController\ModBusTcpController\ModBusTcpController.csproj"> |
| | | <Project>{49db0c9b-b239-4608-a91e-f5ed43afaf96}</Project> |
| | | <Name>ModBusTcpController</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj"> |
| | | <Project>{2A6F9720-A890-4036-9D73-41A0DAE28341}</Project> |
| | | <Name>HMI.Base</Name> |
| | |
| | | using HMI.Core.Util; |
| | | using HMI.Simple.Util; |
| | | using log4net; |
| | | using ModBusTcp; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.DataBoard; |
| | | using Plugin.TestResult_WPF; |
| | |
| | | ProductModelHelper.GetModelBySNR("cc123", out string model, out string msg); |
| | | LangUtil.Load(); |
| | | InitializeComponent(); |
| | | RebuildDb(); |
| | | //RebuildDb(); |
| | | |
| | | ModBusTcpController controller = new ModBusTcpController("127.0.0.1", 502); |
| | | if (controller.Start(out msg)) { |
| | | bool res; |
| | | int? target; |
| | | |
| | | controller.WriteBool("1", true, out msg); |
| | | controller.ReadDOBool("1", out res, out msg); |
| | | Console.WriteLine(res); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | controller.WriteInt("1", 1, out msg); |
| | | controller.ReadDOInt("1", out target, out msg); |
| | | Console.WriteLine(target); |
| | | Console.WriteLine(target); |
| | | } |
| | | |
| | | |
| | | //page.Children.Add(new UserControl1()); |
| | | } |
| | | |
| | |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | Task.Run(() => |
| | | { |
| | | for (int j = 0; j < 1000; j++) |
| | | { |
| | | string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | tsExecution.AddTestData(0, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | Thread.Sleep(5); |
| | | } |
| | | }); |
| | | //Task.Run(() => |
| | | //{ |
| | | // for (int j = 0; j < 1000; j++) |
| | | // { |
| | | // string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | // string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | // tsExecution.AddTestData(0, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | // Thread.Sleep(5); |
| | | // } |
| | | //}); |
| | | |
| | | Task.Run(() => |
| | | { |
| | | for (int j = 0; j < 1000; j++) |
| | | { |
| | | string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | tsExecution.AddTestData(1, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | Thread.Sleep(5); |
| | | } |
| | | }); |
| | | //Task.Run(() => |
| | | //{ |
| | | // for (int j = 0; j < 1000; j++) |
| | | // { |
| | | // string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | // string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | // tsExecution.AddTestData(1, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | // Thread.Sleep(5); |
| | | // } |
| | | //}); |
| | | |
| | | Task.Run(() => |
| | | { |
| | | for (int j = 0; j < 1000; j++) |
| | | { |
| | | string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | tsExecution.AddTestData(2, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | Thread.Sleep(5); |
| | | } |
| | | }); |
| | | //Task.Run(() => |
| | | //{ |
| | | // for (int j = 0; j < 1000; j++) |
| | | // { |
| | | // string status = (j % 2 == 0) ? "Passed" : "Failed"; |
| | | // string d = (j % 2 == 0) ? "9" : "9999999999999999999999999999999999999999999999999999999999999999995"; |
| | | // tsExecution.AddTestData(2, $"ConnectivityCANRec,2,3,4,{d},6,{status}"); |
| | | // Thread.Sleep(5); |
| | | // } |
| | | //}); |
| | | |
| | | //Task.Run(() => |
| | | //{ |
| New file |
| | |
| | | using HslCommunication.ModBus; |
| | | |
| | | namespace ModBusTcp |
| | | { |
| | | public class ModBusTcpController |
| | | { |
| | | public string Ip { get; set; } |
| | | public int Port { get; set; } |
| | | |
| | | private ModbusTcpNet client; |
| | | |
| | | public ModBusTcpController(string ip, int port) |
| | | { |
| | | Ip = ip; |
| | | Port = port; |
| | | } |
| | | |
| | | public bool Start(out string errMsg) |
| | | { |
| | | errMsg = string.Empty; |
| | | client = new ModbusTcpNet(Ip, Port); |
| | | var res = client.ConnectServer(); |
| | | errMsg = res.Message; |
| | | return res.IsSuccess; |
| | | } |
| | | |
| | | public bool ReadDIBool(string address, out bool res, out string msg) |
| | | { |
| | | var result = client?.ReadBool($"x=2;{address}"); |
| | | msg = result?.Message; |
| | | res = result?.Content == true; |
| | | return result?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool ReadDOBool(string address, out bool res, out string msg) |
| | | { |
| | | var result = client?.ReadBool(address); |
| | | msg = result?.Message; |
| | | res = result?.Content == true; |
| | | return result?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool WriteBool(string address, bool value, out string msg) |
| | | { |
| | | msg = string.Empty; |
| | | var res = client?.Write(address, value); |
| | | msg = res.Message; |
| | | return res?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool ReadDIInt(string address, out int? res, out string msg) |
| | | { |
| | | var result = client?.ReadInt32($"x=2;{address}"); |
| | | msg = result?.Message; |
| | | res = result?.Content; |
| | | return result?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool ReadDOInt(string address, out int? res, out string msg) |
| | | { |
| | | var result = client?.ReadInt32(address); |
| | | msg = result?.Message; |
| | | res = result?.Content; |
| | | return result?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool WriteInt(string address, int value, out string msg) |
| | | { |
| | | msg = string.Empty; |
| | | var res = client?.Write(address, value); |
| | | msg = res.Message; |
| | | return res?.IsSuccess == true; |
| | | } |
| | | |
| | | public bool Close() |
| | | { |
| | | return client?.ConnectClose()?.IsSuccess == true; |
| | | |
| | | } |
| | | public void Dispose() |
| | | { |
| | | client?.Dispose(); |
| | | } |
| | | } |
| | | } |
copy from VisionBuilder.Engine/VisionBuilder.Engine.csproj
copy to ModBusTcpController/ModBusTcpController.csproj
| File was copied from VisionBuilder.Engine/VisionBuilder.Engine.csproj |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
| | | <PropertyGroup> |
| | | <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
| | | <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
| | | <ProjectGuid>{8E5E8A68-0B9D-4A6A-B325-730C64603FDF}</ProjectGuid> |
| | | <ProjectGuid>{49DB0C9B-B239-4608-A91E-F5ED43AFAF96}</ProjectGuid> |
| | | <OutputType>Library</OutputType> |
| | | <AppDesignerFolder>Properties</AppDesignerFolder> |
| | | <RootNamespace>VisionBuilder.Engine</RootNamespace> |
| | | <AssemblyName>VisionBuilder.Engine</AssemblyName> |
| | | <RootNamespace>ModBusTcpController</RootNamespace> |
| | | <AssemblyName>ModBusTcpController</AssemblyName> |
| | | <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
| | | <FileAlignment>512</FileAlignment> |
| | | <Deterministic>true</Deterministic> |
| | |
| | | <ErrorReport>prompt</ErrorReport> |
| | | <WarningLevel>4</WarningLevel> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> |
| | | <DebugSymbols>true</DebugSymbols> |
| | | <OutputPath>bin\x64\Debug\</OutputPath> |
| | | <DefineConstants>DEBUG;TRACE</DefineConstants> |
| | | <DebugType>full</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> |
| | | <OutputPath>bin\x64\Release\</OutputPath> |
| | | <DefineConstants>TRACE</DefineConstants> |
| | | <Optimize>true</Optimize> |
| | | <DebugType>pdbonly</DebugType> |
| | | <PlatformTarget>x64</PlatformTarget> |
| | | <LangVersion>7.3</LangVersion> |
| | | <ErrorReport>prompt</ErrorReport> |
| | | </PropertyGroup> |
| | | <ItemGroup> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Core" /> |
| | |
| | | <Reference Include="System.Xml" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="Runner.cs" /> |
| | | <Compile Include="ModBusTcpController.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj"> |
| | | <Project>{3e3bf44a-0b69-45c5-9512-528cb48a7106}</Project> |
| | | <Name>HMI.Core</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | </Project> |
| File was renamed from VisionBuilder.Engine/Properties/AssemblyInfo.cs |
| | |
| | | // 有关程序集的一般信息由以下 |
| | | // 控制。更改这些特性值可修改 |
| | | // 与程序集关联的信息。 |
| | | [assembly: AssemblyTitle("VisionBuilder.Engine")] |
| | | [assembly: AssemblyTitle("ModBusTcpController")] |
| | | [assembly: AssemblyDescription("")] |
| | | [assembly: AssemblyConfiguration("")] |
| | | [assembly: AssemblyCompany("HP Inc.")] |
| | | [assembly: AssemblyProduct("VisionBuilder.Engine")] |
| | | [assembly: AssemblyCopyright("Copyright © HP Inc. 2024")] |
| | | [assembly: AssemblyCompany("")] |
| | | [assembly: AssemblyProduct("ModBusTcpController")] |
| | | [assembly: AssemblyCopyright("Copyright © 2025")] |
| | | [assembly: AssemblyTrademark("")] |
| | | [assembly: AssemblyCulture("")] |
| | | |
| | |
| | | [assembly: ComVisible(false)] |
| | | |
| | | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID |
| | | [assembly: Guid("8e5e8a68-0b9d-4a6a-b325-730c64603fdf")] |
| | | [assembly: Guid("49db0c9b-b239-4608-a91e-f5ed43afaf96")] |
| | | |
| | | // 程序集的版本信息由下列四个值组成: |
| | | // |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 |
| | | //通过使用 "*",如下所示: |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| | |
| | | <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> |
| | | <FileAlignment>512</FileAlignment> |
| | | <Deterministic>true</Deterministic> |
| | | <NuGetPackageImportStamp> |
| | | </NuGetPackageImportStamp> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
| | | <DebugSymbols>true</DebugSymbols> |
| | |
| | | </PropertyGroup> |
| | | <ItemGroup> |
| | | <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> |
| | | <HintPath>..\WPFProject\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> |
| | | <HintPath>..\WPFProject\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="SupersocketCommon"> |
| | | <HintPath>..\Libs\SupersocketCommon.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Core" /> |
| | | <Reference Include="System.Numerics" /> |
| | | <Reference Include="System.Xml.Linq" /> |
| | | <Reference Include="System.Data.DataSetExtensions" /> |
| | | <Reference Include="Microsoft.CSharp" /> |
| | |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\ConnectionUtil\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{d0806fa6-3f6d-4304-81b8-ead9da7cb5b2}</Project> |
| | | <Name>ConnectionUtil</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <None Include="packages.config" /> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | </Project> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <configuration> |
| | | <runtime> |
| | | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <dependentAssembly> |
| | | <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> |
| | | <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> |
| | | </dependentAssembly> |
| | | </assemblyBinding> |
| | | </runtime> |
| | | </configuration> |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <packages> |
| | | <package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" /> |
| | | <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" /> |
| | | </packages> |
| File was renamed from Plugin.ChangeModel/AssemblyInfo.cs |
| | |
| | | using HMI.Core.Annotation; |
| | | using System.Windows; |
| | | |
| | | [assembly:ThemeInfo( |
| | |
| | | //(used if a resource is not found in the page, |
| | | // app, or any theme specific resource dictionaries) |
| | | )] |
| | | [assembly: PluginClassName("Plugin.CurrentSensorControl.ControlPage")] |
| New file |
| | |
| | | <UserControl x:Class="Plugin.CurrentSensorControl.BurnInCell" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.CurrentSensorControl" |
| | | mc:Ignorable="d" |
| | | |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:mdi="clr-namespace:HMI.UI.MDI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <Style TargetType="pu:Switch"> |
| | | <Setter Property="ContentPlacement" Value="Left" /> |
| | | <Setter Property="BoxHeight" Value="16" /> |
| | | <Setter Property="CheckedBackground" Value="{StaticResource GreenVerBar}" /> |
| | | <Setter Property="Background" Value="{StaticResource DangerColor}" /> |
| | | <Setter Property="ToggleSize" Value="10" /> |
| | | <Setter Property="ToggleShadowColor" Value="{x:Null}" /> |
| | | </Style> |
| | | </UserControl.Resources> |
| | | |
| | | <GroupBox Header="{Binding Header}"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition /> |
| | | <RowDefinition /> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | <pu:Switch Grid.Row="0" Grid.Column="0" CheckedContent="电源开" x:Name="powerSw" |
| | | IsChecked="{Binding PowerStatus,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | Content="电源关"/> |
| | | |
| | | <pu:Switch Grid.Row="0" Grid.Column="1" CheckedContent="激活" x:Name="activationSw" |
| | | IsChecked="{Binding ActivationStatus,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | Content="未激活"/> |
| | | |
| | | <pu:Switch Grid.Row="1" Grid.Column="0" CheckedContent="OK亮" x:Name="okLightSw" |
| | | IsChecked="{Binding OkLightOn,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | Content="OK灭"/> |
| | | |
| | | |
| | | <pu:Switch Grid.Row="1" Grid.Column="1" CheckedContent="NG亮" x:Name="ngLightSw" |
| | | IsChecked="{Binding NgLightOn,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | Content="NG灭"/> |
| | | |
| | | <!--<ui:LightBall Grid.Row="1" Grid.Column="0" Value="{Binding CellStatus}" Content="OK/NG状态"/>--> |
| | | |
| | | <!--<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding PowerStatus}"/> |
| | | |
| | | <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding ActivationStatus}"/>--> |
| | | |
| | | |
| | | </Grid> |
| | | </GroupBox> |
| | | </UserControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using HslCommunication.Profinet.Siemens; |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// BurnInOven.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class BurnInCell : UserControl |
| | | { |
| | | private BaseConfig config; |
| | | |
| | | [ObservableProperty] |
| | | private string header; |
| | | |
| | | [ObservableProperty] |
| | | private string req; |
| | | |
| | | [ObservableProperty] |
| | | private bool lightOK; |
| | | |
| | | [ObservableProperty] |
| | | private bool lightNG; |
| | | |
| | | private bool powerStatus; |
| | | |
| | | public bool PowerStatus |
| | | { |
| | | get => powerStatus; |
| | | set |
| | | { |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Power"; |
| | | if (S7Context.WriteData(api, name, value)) |
| | | { |
| | | powerStatus = value; |
| | | OnPropertyChanged(nameof(PowerStatus)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool activationStatus; |
| | | public bool ActivationStatus |
| | | { |
| | | get => activationStatus; |
| | | set |
| | | { |
| | | |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Activation"; |
| | | if (S7Context.WriteData(api, name, value)) |
| | | { |
| | | activationStatus = value; |
| | | OnPropertyChanged(nameof(ActivationStatus)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool okLightOn; |
| | | public bool OkLightOn |
| | | { |
| | | get => okLightOn; |
| | | set |
| | | { |
| | | |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Light_OK"; |
| | | if (S7Context.WriteData(api, name, value)) |
| | | { |
| | | okLightOn = value; |
| | | OnPropertyChanged(nameof(OkLightOn)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | private bool ngLightOn; |
| | | public bool NgLightOn |
| | | { |
| | | get => ngLightOn; |
| | | set |
| | | { |
| | | |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Light_NG"; |
| | | if (S7Context.WriteData(api, name, value)) |
| | | { |
| | | ngLightOn = value; |
| | | OnPropertyChanged(nameof(NgLightOn)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | [ObservableProperty] |
| | | private bool? cellStatus; |
| | | |
| | | private int ovenIndex; |
| | | private int cellIndex; |
| | | private SiemensS7Net api; |
| | | |
| | | public BurnInCell(int ovenIndex, int cellIndex) |
| | | { |
| | | this.ovenIndex = ovenIndex; |
| | | this.cellIndex = cellIndex; |
| | | this.Header = $"Cell {cellIndex + 1}"; |
| | | DataContext = this; |
| | | api = S7Context.Get($"1"); |
| | | config = BaseConfig.Instance; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public void Refresh() |
| | | { |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Power"; |
| | | object val; string errMsg; |
| | | if (S7Context.GetData(api, name, out val)) |
| | | { |
| | | powerStatus = (bool)val; |
| | | OnPropertyChanged("PowerStatus"); |
| | | } |
| | | |
| | | name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Activation"; |
| | | if (S7Context.GetData(api, name, out val)) |
| | | { |
| | | activationStatus = (bool)val; |
| | | OnPropertyChanged("ActivationStatus"); |
| | | } |
| | | |
| | | name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Light_OK"; |
| | | if (S7Context.GetData(api, name, out val)) |
| | | { |
| | | okLightOn = (bool)val; |
| | | OnPropertyChanged("OkLightOn"); |
| | | } |
| | | |
| | | name = $"Oven{ovenIndex + 1}_Cell{cellIndex + 1}_Light_NG"; |
| | | if (S7Context.GetData(api, name, out val)) |
| | | { |
| | | ngLightOn = (bool)val; |
| | | OnPropertyChanged("NgLightOn"); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <UserControl x:Class="Plugin.CurrentSensorControl.BurnInOven" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.CurrentSensorControl" |
| | | mc:Ignorable="d" |
| | | |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:mdi="clr-namespace:HMI.UI.MDI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <Style x:Key="ovenTb" TargetType="TextBox" BasedOn="{StaticResource EditorTextBoxStyle}"> |
| | | <Setter Property="Height" Value="20"/> |
| | | <Setter Property="MinWidth" Value="60"/> |
| | | <Setter Property="FontSize" Value="14"/> |
| | | </Style> |
| | | </UserControl.Resources> |
| | | |
| | | <GroupBox Header="{Binding Header}"> |
| | | <Grid dp:GridHelper.Space="5" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition /> |
| | | </Grid.RowDefinitions> |
| | | <StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="5"> |
| | | <pu:FormGroup Header="状态"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding ReqStatus}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:Switch CheckedContent="照明开" x:Name="lightSw" |
| | | CheckedBackground="Green" |
| | | Background="{StaticResource DangerColor}" |
| | | IsChecked="{Binding LightStatus,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" |
| | | Content="照明关"/> |
| | | |
| | | <Button Background="{StaticResource PrimaryColor}" Foreground="{StaticResource PrimaryColorContract}" |
| | | Click="Button_Click" |
| | | Tag="0" |
| | | Content="停止等待"/> |
| | | <Button Background="{StaticResource DangerColor}" Foreground="{StaticResource DangerColorContrast}" |
| | | Click="Button_Click" |
| | | Tag="1" |
| | | Content="加热启动"/> |
| | | <Button Background="{StaticResource SuccessColor}" Foreground="{StaticResource SuccessColorContrast}" |
| | | Click="Button_Click" |
| | | Tag="2" |
| | | Content="冷却启动"/> |
| | | </StackPanel> |
| | | |
| | | <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="5"> |
| | | <pu:FormGroup Header="设定温度"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding SetTemp}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="安全温度"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding SaveTemp}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="温度下限"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding TempDown}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="温度上限"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding TempUp}"/> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="平均温度"> |
| | | <TextBox Style="{StaticResource ovenTb}" IsReadOnly="True" Text="{Binding AvgTemp}"/> |
| | | </pu:FormGroup> |
| | | </StackPanel> |
| | | |
| | | <UniformGrid Grid.Row="2" Grid.Column="0" x:Name="mainGrid"></UniformGrid> |
| | | </Grid> |
| | | </GroupBox> |
| | | </UserControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using ConnectionUtil; |
| | | using HslCommunication.Profinet.Siemens; |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Drawing; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Markup; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// BurnInOven.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class BurnInOven : UserControl |
| | | { |
| | | private BaseConfig config; |
| | | |
| | | private static readonly string[] datas = new string[] { "_LEDLight", "_Req", "_SetTemp", "_SaveTemp", "_TempDown", "_TempUp", "_AvgTemp" }; |
| | | |
| | | [ObservableProperty] |
| | | private string header; |
| | | |
| | | [ObservableProperty] |
| | | private string req; |
| | | [ObservableProperty] |
| | | private string reqStatus; |
| | | |
| | | [ObservableProperty] |
| | | private string setTemp; |
| | | [ObservableProperty] |
| | | private string saveTemp; |
| | | [ObservableProperty] |
| | | private string tempDown; |
| | | [ObservableProperty] |
| | | private string tempUp; |
| | | [ObservableProperty] |
| | | private string avgTemp; |
| | | |
| | | private bool lightStatus; |
| | | |
| | | public bool LightStatus |
| | | { |
| | | get => lightStatus; |
| | | set |
| | | { |
| | | try |
| | | { |
| | | string name = $"Oven{ovenIndex + 1}_LEDLight"; |
| | | if (S7Context.WriteData(api, name, value)) |
| | | { |
| | | lightStatus = value; |
| | | OnPropertyChanged(nameof(lightStatus)); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | private int ovenIndex; |
| | | |
| | | private SiemensS7Net api; |
| | | |
| | | private int cellCount; |
| | | |
| | | private BurnInCell[] cells; |
| | | |
| | | public BurnInOven(int ovenIndex) |
| | | { |
| | | this.ovenIndex = ovenIndex; |
| | | config = BaseConfig.Instance; |
| | | this.cellCount = config.PositionCount; |
| | | this.cells = new BurnInCell[cellCount]; |
| | | DataContext = this; |
| | | api = S7Context.Get($"1"); |
| | | InitializeComponent(); |
| | | InitGrid(); |
| | | } |
| | | |
| | | private void InitGrid() |
| | | { |
| | | mainGrid.Columns = config.PositionColumn; |
| | | for (int i = 0; i < cellCount; i++) |
| | | { |
| | | var cell = new BurnInCell(ovenIndex, i); |
| | | cells[i] = cell; |
| | | mainGrid.Children.Add(cell); |
| | | } |
| | | } |
| | | |
| | | public void Refresh() |
| | | { |
| | | try |
| | | { |
| | | //Task[] allTask = new Task[cells.Length]; |
| | | //for (int i = 0; i < cells.Length; i++) |
| | | //{ |
| | | // var cell = cells[i]; |
| | | // var task = Task.Factory.StartNew(() => |
| | | // { |
| | | // cell.Refresh(); |
| | | // }); |
| | | // allTask[i] = task; |
| | | //} |
| | | //Task.WaitAll(allTask); |
| | | |
| | | foreach (var cell in cells) |
| | | { |
| | | cell.Refresh(); |
| | | } |
| | | |
| | | string name; |
| | | object v; |
| | | foreach (var data in datas) |
| | | { |
| | | name = $"Oven{ovenIndex + 1}{data}"; |
| | | if (S7Context.GetData(api, name, out v)) |
| | | { |
| | | var val = v?.ToString(); |
| | | if (data == "_LEDLight") |
| | | { |
| | | lightStatus = bool.Parse(val); |
| | | OnPropertyChanged("LightStatus"); |
| | | } |
| | | else if (data == "_Req") |
| | | { |
| | | Req = val; |
| | | if (val == "0") |
| | | { |
| | | ReqStatus = "停止等待"; |
| | | } |
| | | else if (val == "1") |
| | | { |
| | | ReqStatus = "加热启动"; |
| | | } |
| | | else if (val == "2") |
| | | { |
| | | ReqStatus = "冷却启动"; |
| | | } |
| | | } |
| | | else if (data == "_SetTemp") |
| | | { |
| | | SetTemp = val; |
| | | } |
| | | else if (data == "_SaveTemp") |
| | | { |
| | | SaveTemp = val; |
| | | } |
| | | else if (data == "_TempDown") |
| | | { |
| | | TempDown = val; |
| | | } |
| | | else if (data == "_TempUp") |
| | | { |
| | | TempUp = val; |
| | | } |
| | | else if (data == "_AvgTemp") |
| | | { |
| | | AvgTemp = val; |
| | | } |
| | | } |
| | | |
| | | |
| | | //; |
| | | //if (api.DoFctReadSingle(name, out string val, out _)) |
| | | //{ |
| | | // if (data == "_Req") |
| | | // { |
| | | // Req = val; |
| | | // if (val == "0") |
| | | // { |
| | | // ReqStatus = "停止等待"; |
| | | // } |
| | | // else if (val == "1") |
| | | // { |
| | | // ReqStatus = "加热启动"; |
| | | // } |
| | | // else if (val == "2") |
| | | // { |
| | | // ReqStatus = "冷却启动"; |
| | | // } |
| | | // } |
| | | // else if (data == "_SetTemp") |
| | | // { |
| | | // SetTemp = val; |
| | | // } |
| | | // else if (data == "_SaveTemp") |
| | | // { |
| | | // SaveTemp = val; |
| | | // } |
| | | // else if (data == "_TempDown") |
| | | // { |
| | | // TempDown = val; |
| | | // } |
| | | // else if (data == "_TempUp") |
| | | // { |
| | | // TempUp = val; |
| | | // } |
| | | // else if (data == "_AvgTemp") |
| | | // { |
| | | // AvgTemp = val; |
| | | // } |
| | | //} |
| | | } |
| | | |
| | | //if (api.Connec (out string errMsg)) |
| | | //{ |
| | | |
| | | //} |
| | | //else |
| | | //{ |
| | | // OPCContext.Connect($"Oven{ovenIndex}"); |
| | | // Thread.Sleep(1000); |
| | | //} |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | var btn = sender as Button; |
| | | string name = $"Oven{ovenIndex + 1}_Cmd"; |
| | | S7Context.WriteData(api, name, short.Parse(btn.Tag.ToString())); |
| | | //api.DoFctWriteSingle(name, btn.Tag.ToString(), out string errMsg); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <UserControl x:Class="Plugin.CurrentSensorControl.BurnInOvenCollection" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.CurrentSensorControl" |
| | | mc:Ignorable="d" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:mdi="clr-namespace:HMI.UI.MDI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <Grid x:Name="mainGrid" dp:GridHelper.Space="6"> |
| | | |
| | | </Grid> |
| | | </UserControl> |
| New file |
| | |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Drawing; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// BurnInOvenCollection.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class BurnInOvenCollection : UserControl |
| | | { |
| | | private int rowCount; |
| | | private int colCount; |
| | | private int cellCount; |
| | | private BurnInOven[] ovens; |
| | | private BaseConfig config; |
| | | |
| | | public BurnInOvenCollection() |
| | | { |
| | | config = BaseConfig.Instance; |
| | | InitializeComponent(); |
| | | InitMainGrid(); |
| | | } |
| | | |
| | | public void InitMainGrid() |
| | | { |
| | | this.rowCount = config.Row; |
| | | this.colCount = config.Column; |
| | | ovens = new BurnInOven[this.rowCount * this.colCount]; |
| | | if (config.CellCount < 0) |
| | | { |
| | | this.cellCount = rowCount * colCount; |
| | | } |
| | | else |
| | | { |
| | | this.cellCount = config.CellCount; |
| | | } |
| | | for (int r = 0; r < rowCount; r++) |
| | | { |
| | | RowDefinition row = new RowDefinition(); |
| | | mainGrid.RowDefinitions.Add(row); |
| | | } |
| | | |
| | | for (int c = 0; c < colCount; c++) |
| | | { |
| | | ColumnDefinition col = new ColumnDefinition(); |
| | | mainGrid.ColumnDefinitions.Add(col); |
| | | } |
| | | string[] names = config.NameStr.Split(','); |
| | | for (int n = 0; n < cellCount; n++) |
| | | { |
| | | string name = n < names.Length ? names[n] : ""; |
| | | BurnInOven child = new BurnInOven(n); |
| | | child.Header = name; |
| | | mainGrid.Children.Add(child); |
| | | ovens[n] = child; |
| | | int row = n / colCount; |
| | | int col = n % colCount; |
| | | Grid.SetRow(child, row); |
| | | Grid.SetColumn(child, col); |
| | | } |
| | | } |
| | | |
| | | public void Refresh() |
| | | { |
| | | try |
| | | { |
| | | for (int i = 0; i < ovens.Length; i++) |
| | | { |
| | | var oven = ovens[i]; |
| | | oven.Refresh(); |
| | | } |
| | | //Task[] allTask = new Task[ovens.Length]; |
| | | //for (int i = 0; i < ovens.Length; i++) |
| | | //{ |
| | | // var oven = ovens[i]; |
| | | // var task = Task.Factory.StartNew(() => |
| | | // { |
| | | // oven.Refresh(); |
| | | // }); |
| | | // allTask[i] = task; |
| | | //} |
| | | //Task.WaitAll(allTask); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <pu:WindowX x:Class="Plugin.CurrentSensorControl.BurnInSettingModal" |
| | | 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:Plugin.CurrentSensorControl" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:sys="clr-namespace:System;assembly=mscorlib" |
| | | mc:Ignorable="d" |
| | | Title="Form" |
| | | Width="1200" |
| | | Height="900" |
| | | WindowStartupLocation="CenterOwner" |
| | | Style="{StaticResource ModalWindow}"> |
| | | <Window.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Includes="TabControl" /> |
| | | <ResourceDictionary Source="/HMI.UI;component/Style/PanuonListView.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | </ResourceDictionary> |
| | | </Window.Resources> |
| | | <Grid Margin="5" dp:GridHelper.Space="5" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | <Button Style="{StaticResource ExportBtn}" x:Name="exportBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource ImportBtn}" x:Name="importBtn" Click="Button_Click"/> |
| | | </StackPanel> |
| | | <ListView Grid.Row="1" Style="{StaticResource DefaultListTable}" x:Name="table" |
| | | ItemsSource="{Binding Datasource}" |
| | | VirtualizingPanel.IsContainerVirtualizable="True" |
| | | VirtualizingPanel.IsVirtualizing="True" |
| | | VirtualizingPanel.VirtualizationMode="Standard"> |
| | | <ListView.Resources> |
| | | <Style x:Key="RowLink" TargetType="Button" BasedOn="{StaticResource LinkButton}"> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Path=IsMouseOver, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}" |
| | | Value="True"> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Path=IsSelected, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}" |
| | | Value="True"> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <Style x:Key="DeleteLink" TargetType="Button" BasedOn="{StaticResource DangerLinkButton}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Delete}"/> |
| | | </Style> |
| | | |
| | | <Style x:Key="EditLink" TargetType="Button" BasedOn="{StaticResource RowLink}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Edit}"/> |
| | | </Style> |
| | | </ListView.Resources> |
| | | <ListView.View> |
| | | <GridView AllowsColumnReorder="False"> |
| | | <GridViewColumn Width="60" Header="#"> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding Converter={StaticResource lvRowNumber}, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}"/> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="200"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="Name"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Name}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="100"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="Address"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Address}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="Type"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Type}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="Length"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Length}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="Desc"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Description}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource App.Opt}"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | <Button x:Name="editBtn" Style="{StaticResource EditLink}" |
| | | Click="Button_Click" Tag="{Binding }"/> |
| | | |
| | | <Button x:Name="delBtn" Style="{StaticResource DeleteLink}" |
| | | Click="Button_Click" Tag="{Binding }"/> |
| | | </StackPanel> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | </GridView> |
| | | </ListView.View> |
| | | </ListView> |
| | | </Grid> |
| | | </pu:WindowX> |
| New file |
| | |
| | | using HMI.UI.DpUtil; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Microsoft.Win32; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// ModalWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class BurnInSettingModal : WindowX |
| | | { |
| | | public BurnInSettingModal() |
| | | { |
| | | this.DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | private ObservableCollection<PLCTagData> datasource; |
| | | |
| | | public ObservableCollection<PLCTagData> Datasource |
| | | { |
| | | get => datasource; |
| | | set |
| | | { |
| | | Set(ref datasource, value); |
| | | } |
| | | } |
| | | |
| | | private bool _isProcessing; |
| | | |
| | | protected override void OnClosing(CancelEventArgs e) |
| | | { |
| | | //Press Continue Button |
| | | if (DialogResult == true) |
| | | { |
| | | if (_isProcessing) |
| | | { |
| | | e.Cancel = true; |
| | | return; |
| | | } |
| | | var okButton = WindowXModalDialog.GetOKButton(this); |
| | | try |
| | | { |
| | | _isProcessing = true; |
| | | ButtonHelper.SetIsPending(okButton, true); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ToastHelper.Error(this, $"Error!{ex.Message}"); |
| | | e.Cancel = true; |
| | | return; |
| | | } |
| | | finally |
| | | { |
| | | _isProcessing = false; |
| | | ButtonHelper.SetIsPending(okButton, false); |
| | | } |
| | | } |
| | | base.OnClosing(e); |
| | | } |
| | | |
| | | private bool ValidateName(object value, out string err) |
| | | { |
| | | err = null; |
| | | //string group = TbGroup.Text; |
| | | //var temp = Datasource.FirstOrDefault(d => d.Group == group && d.Name == value.ToString()); |
| | | //if (temp != null && temp != Data) |
| | | //{ |
| | | // err = this.lang("App.MustBeUnique", $"{this.lang("doc.group")},{this.lang("doc.name")}"); |
| | | // return false; |
| | | //} |
| | | return true; |
| | | } |
| | | |
| | | private bool ValidateAddress(object value, out string err) |
| | | { |
| | | err = null; |
| | | //string group = TbGroup.Text; |
| | | //var temp = Datasource.FirstOrDefault(d => d.Address == value.ToString()); |
| | | //if (temp != null && temp != Data) |
| | | //{ |
| | | // err = this.lang("App.MustBeUnique", this.lang("doc.Address")); |
| | | // return false; |
| | | //} |
| | | return true; |
| | | } |
| | | |
| | | public bool? Open( ObservableCollection<PLCTagData> datasource) |
| | | { |
| | | this.Datasource = datasource; |
| | | return this.ShowDialog(); |
| | | } |
| | | |
| | | private void DoExport() |
| | | { |
| | | SaveFileDialog sfd = new SaveFileDialog(); |
| | | if (sfd.ShowDialog() == true) |
| | | { |
| | | ExcelHelper.ExportExcel(sfd.FileName, Datasource); |
| | | } |
| | | } |
| | | |
| | | private void DoImport() |
| | | { |
| | | OpenFileDialog ofd = new OpenFileDialog(); |
| | | if (ofd.ShowDialog() == true) |
| | | { |
| | | try |
| | | { |
| | | Datasource = new ObservableCollection<PLCTagData>(ExcelHelper.ReadFromExcel<PLCTagData>(ofd.FileName)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ControlPage.Logger.Error("Import Error.", ex); |
| | | ToastHelper.Error(ex.Message); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | var btn = sender as Button; |
| | | switch (btn.Name) { |
| | | case "exportBtn": |
| | | DoExport(); |
| | | break; |
| | | case "importBtn": |
| | | DoImport(); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <hb:SimpleMaskControl x:Class="Plugin.CurrentSensorControl.ControlPage" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.CurrentSensorControl" |
| | | mc:Ignorable="d" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:mdi="clr-namespace:HMI.UI.MDI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | Loaded="SimpleMaskControl_Loaded" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Includes="TabControl" /> |
| | | <ResourceDictionary Source="/HMI.UI;component/Style/PanuonListView.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | </ResourceDictionary> |
| | | </UserControl.Resources> |
| | | |
| | | <Border Style="{StaticResource CardBoarder}" Padding="0" Background="#FFF"> |
| | | <TabControl |
| | | pu:TabControlHelper.HeaderPanelAlignment="Stretch" |
| | | pu:TabControlHelper.ItemsBackground="{DynamicResource VerBar}" |
| | | pu:TabControlHelper.ItemsForeground="#FFFFFF" |
| | | pu:TabControlHelper.ItemsFontSize="14" |
| | | pu:TabControlHelper.ItemsHeight="30" |
| | | pu:TabControlHelper.ItemsHorizontalHeaderAlignment="Left" |
| | | pu:TabControlHelper.ItemsHoverBackground="{DynamicResource SecondPrimaryColor}" |
| | | pu:TabControlHelper.ItemsHoverForeground="#FFFFFF" |
| | | pu:TabControlHelper.ItemsPadding="20,0,20,0" |
| | | pu:TabControlHelper.ItemsRibbonLineCornerRadius="4" |
| | | pu:TabControlHelper.ItemsRibbonLineMargin="0,5,0,5" |
| | | pu:TabControlHelper.ItemsRibbonLineThickness="4" |
| | | pu:TabControlHelper.ItemsRibbonLineVisibility="Visible" |
| | | pu:TabControlHelper.ItemsSelectedBackground="#FFF" |
| | | pu:TabControlHelper.ItemsSelectedRibbonLineBrush="#FFFFFF" |
| | | pu:TabControlHelper.ItemsSelectedRibbonLineThickness="2"> |
| | | <TabControl.Template> |
| | | <ControlTemplate TargetType="{x:Type TabControl}"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="*"/> |
| | | </Grid.RowDefinitions> |
| | | <Border BorderThickness="1,1,1,0" BorderBrush="#acacac" Background="{DynamicResource VerBar}" Padding="2,2,10,0"> |
| | | <TabPanel x:Name="HeaderPanel" Grid.Row="0" Panel.ZIndex="1" IsItemsHost="True"/> |
| | | </Border> |
| | | |
| | | <Border Grid.Row="1" BorderBrush="{TemplateBinding BorderBrush}" |
| | | BorderThickness="1,0,1,1" Background="{TemplateBinding Background}"> |
| | | <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/> |
| | | </Border> |
| | | </Grid> |
| | | </ControlTemplate> |
| | | </TabControl.Template> |
| | | <TabItem Header="老化调试"> |
| | | <Grid dp:GridHelper.Space="5" dp:GridHelper.SpaceIgnore="ALL"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <StackPanel Orientation="Horizontal"> |
| | | <Button Style="{StaticResource SettingBtn}" x:Name="burnInSettingBtn" Click="Button_Click"/> |
| | | </StackPanel> |
| | | |
| | | <local:BurnInOvenCollection Grid.Row="1" Grid.Column="0" x:Name="ovenCollection"/> |
| | | </Grid> |
| | | </TabItem> |
| | | <TabItem Header="电流监控"> |
| | | |
| | | <Grid dp:GridHelper.Space="8"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | |
| | | <DockPanel> |
| | | <StackPanel dp:StackPanelHelper.ChildSpace="10" DockPanel.Dock="Right" Orientation="Horizontal"> |
| | | <Button Style="{StaticResource AddBtn}" x:Name="addBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource RfhBtn}" x:Name="rfhBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource ExportBtn}" x:Name="exportBtn" Click="Button_Click"/> |
| | | <Button Style="{StaticResource ImportBtn}" x:Name="importBtn" Click="Button_Click"/> |
| | | <!--<Button Style="{StaticResource DelBtn}"/>--> |
| | | </StackPanel> |
| | | |
| | | <StackPanel Orientation="Horizontal" VerticalAlignment="Center" dp:StackPanelHelper.ChildSpace="10"> |
| | | <pu:FormGroup FontSize="18" Header="电流传感器" Orientation="Horizontal"> |
| | | |
| | | </pu:FormGroup> |
| | | <Button Style="{StaticResource ResetBtn}" |
| | | x:Name="connectAllBtn" Click="Button_Click" Content="全部连接" /> |
| | | <Button Style="{StaticResource SettingBtn}" Content="全部断开" x:Name="disConnectAllBtn" Click="Button_Click"/> |
| | | <!--<Button Style="{StaticResource SettingBtn}" Content="设置" x:Name="settingBtn" Click="Button_Click"/>--> |
| | | </StackPanel> |
| | | </DockPanel> |
| | | <TabControl Grid.Row="1" |
| | | pu:TabControlHelper.HeaderPanelAlignment="Stretch" |
| | | pu:TabControlHelper.ItemsBackground="{DynamicResource VerBar}" |
| | | pu:TabControlHelper.ItemsForeground="#FFFFFF" |
| | | pu:TabControlHelper.ItemsFontSize="14" |
| | | pu:TabControlHelper.ItemsHeight="30" |
| | | pu:TabControlHelper.ItemsHorizontalHeaderAlignment="Left" |
| | | pu:TabControlHelper.ItemsHoverBackground="{DynamicResource SecondPrimaryColor}" |
| | | pu:TabControlHelper.ItemsHoverForeground="#FFFFFF" |
| | | pu:TabControlHelper.ItemsPadding="20,0,0,0" |
| | | pu:TabControlHelper.ItemsRibbonLineCornerRadius="4" |
| | | pu:TabControlHelper.ItemsRibbonLineMargin="0,5,0,5" |
| | | pu:TabControlHelper.ItemsRibbonLineThickness="4" |
| | | pu:TabControlHelper.ItemsRibbonLineVisibility="Visible" |
| | | pu:TabControlHelper.ItemsSelectedBackground="#FFF" |
| | | pu:TabControlHelper.ItemsSelectedRibbonLineBrush="#FFFFFF" |
| | | pu:TabControlHelper.ItemsSelectedRibbonLineThickness="2" |
| | | pu:TabControlHelper.ItemsWidth="100" > |
| | | <TabControl.Template> |
| | | <ControlTemplate TargetType="{x:Type TabControl}"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="*"/> |
| | | </Grid.RowDefinitions> |
| | | <Border BorderThickness="1,1,1,0" BorderBrush="#acacac" Background="{DynamicResource VerBar}" Padding="2,2,10,0"> |
| | | <TabPanel x:Name="HeaderPanel" Grid.Row="0" Panel.ZIndex="1" IsItemsHost="True"/> |
| | | </Border> |
| | | |
| | | <Border Grid.Row="1" BorderBrush="{TemplateBinding BorderBrush}" |
| | | BorderThickness="1,0,1,1" Background="{TemplateBinding Background}"> |
| | | <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent"/> |
| | | </Border> |
| | | </Grid> |
| | | </ControlTemplate> |
| | | </TabControl.Template> |
| | | |
| | | <TabItem Header="控件"> |
| | | <ScrollViewer Grid.Row="1" Grid.Column="0" |
| | | Style="{StaticResource DefaultScrollViewer}" |
| | | VerticalScrollBarVisibility="Auto"> |
| | | <WrapPanel Background="#FFF" x:Name="diWrap"/> |
| | | </ScrollViewer> |
| | | </TabItem> |
| | | <TabItem Header="列表"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <ListView Grid.Row="1" Style="{StaticResource DefaultListTable}" x:Name="table" |
| | | ItemsSource="{Binding Datasource}" |
| | | VirtualizingPanel.IsContainerVirtualizable="True" |
| | | VirtualizingPanel.IsVirtualizing="True" |
| | | VirtualizingPanel.VirtualizationMode="Standard"> |
| | | <ListView.Resources> |
| | | <Style x:Key="RowLink" TargetType="Button" BasedOn="{StaticResource LinkButton}"> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding Path=IsMouseOver, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}" |
| | | Value="True"> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding Path=IsSelected, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}" |
| | | Value="True"> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | |
| | | <Style x:Key="DeleteLink" TargetType="Button" BasedOn="{StaticResource DangerLinkButton}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Delete}"/> |
| | | </Style> |
| | | |
| | | <Style x:Key="EditLink" TargetType="Button" BasedOn="{StaticResource RowLink}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Edit}"/> |
| | | </Style> |
| | | </ListView.Resources> |
| | | <ListView.View> |
| | | <GridView AllowsColumnReorder="False"> |
| | | <GridViewColumn Width="60" Header="#"> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <TextBlock Text="{Binding Converter={StaticResource lvRowNumber}, |
| | | RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListViewItem,AncestorLevel=1}}"/> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | |
| | | <GridViewColumn Width="700"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource doc.name}"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Name}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="100"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="IP"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Ip}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="端口"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Port}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="地址"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Address}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="通道"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <Border Style="{StaticResource CellBorder}"> |
| | | <TextBlock Style="{StaticResource ListTableTextBlock}" |
| | | Text="{Binding Channel}"/> |
| | | </Border> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | <GridViewColumn Width="120"> |
| | | <GridViewColumn.Header> |
| | | <TextBlock Text="{DynamicResource App.Opt}"/> |
| | | </GridViewColumn.Header> |
| | | <GridViewColumn.CellTemplate> |
| | | <DataTemplate> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | <Button x:Name="editBtn" Style="{StaticResource EditLink}" |
| | | Click="Button_Click" Tag="{Binding }"/> |
| | | |
| | | <Button x:Name="delBtn" Style="{StaticResource DeleteLink}" |
| | | Click="Button_Click" Tag="{Binding }"/> |
| | | </StackPanel> |
| | | </DataTemplate> |
| | | </GridViewColumn.CellTemplate> |
| | | </GridViewColumn> |
| | | </GridView> |
| | | </ListView.View> |
| | | </ListView> |
| | | </Grid> |
| | | </TabItem> |
| | | </TabControl> |
| | | </Grid> |
| | | </TabItem> |
| | | </TabControl> |
| | | </Border> |
| | | </hb:SimpleMaskControl> |
| | | |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using ConnectionUtil; |
| | | using HMI.Base; |
| | | using HMI.Core.Setting; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using log4net; |
| | | using Microsoft.Win32; |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Collections.ObjectModel; |
| | | using System.IO; |
| | | using System.Timers; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// ControlPage.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class ControlPage : SimpleMaskControl |
| | | { |
| | | [ObservableProperty] |
| | | private ObservableCollection<SensorData> datasource = new ObservableCollection<SensorData>(); |
| | | private List<SingleSensor> controls = new List<SingleSensor>(); |
| | | |
| | | private System.Timers.Timer timer; |
| | | private System.Timers.Timer opcTimer; |
| | | private SCADAApi api; |
| | | public static ILog Logger { get; private set; } |
| | | |
| | | private volatile bool needRead = false; |
| | | |
| | | public ControlPage() |
| | | { |
| | | timer = new System.Timers.Timer(); |
| | | timer.Elapsed += Timer_Elapsed; |
| | | timer.AutoReset = false; |
| | | timer.Interval = 1000; |
| | | |
| | | opcTimer = new System.Timers.Timer(); |
| | | opcTimer.Elapsed += OpcTimer_Elapsed; ; |
| | | opcTimer.AutoReset = false; |
| | | opcTimer.Interval = 1000; |
| | | |
| | | S7Context.Init(SystemSetting.Instance.PlcIp, SystemSetting.Instance.PlcPort); |
| | | |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | private void OpcTimer_Elapsed(object sender, ElapsedEventArgs e) |
| | | { |
| | | opcTimer.Enabled = false; |
| | | try |
| | | { |
| | | var time = DateTime.Now; |
| | | ovenCollection.Refresh(); |
| | | log.Debug($"Time Cast: {(DateTime.Now - time).TotalMilliseconds}ms"); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | } |
| | | finally |
| | | { |
| | | if (needRead) opcTimer.Enabled = true; |
| | | } |
| | | } |
| | | |
| | | private void Timer_Elapsed(object sender, ElapsedEventArgs e) |
| | | { |
| | | timer.Enabled = false; |
| | | try |
| | | { |
| | | foreach (var ctl in controls) |
| | | { |
| | | if (!needRead) return; |
| | | if (ctl is SingleSensor ss) |
| | | { |
| | | ss.ReadCurrent(); |
| | | Thread.Sleep(50); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | finally |
| | | { |
| | | if (needRead) timer.Enabled = true; |
| | | } |
| | | } |
| | | |
| | | public override void InitFinish() |
| | | { |
| | | Logger = log; |
| | | } |
| | | |
| | | public override void Active() |
| | | { |
| | | StartReadCurrent(); |
| | | } |
| | | |
| | | public override void DeActive() |
| | | { |
| | | StopReadCurrent(); |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | | { |
| | | StopReadCurrent(); |
| | | base.DoClose(sender, e); |
| | | } |
| | | |
| | | public void StartReadCurrent() |
| | | { |
| | | needRead = true; |
| | | timer.Enabled = true; |
| | | opcTimer.Enabled = true; |
| | | } |
| | | |
| | | public void StopReadCurrent() |
| | | { |
| | | needRead = false; |
| | | timer.Enabled = false; |
| | | opcTimer.Enabled = false; |
| | | } |
| | | |
| | | private void LoadSensorData() |
| | | { |
| | | string path = Path.Combine(BaseFolder, "sensor.data"); |
| | | var list = new ObservableCollection<SensorData>(); |
| | | try |
| | | { |
| | | if (File.Exists(path)) |
| | | { |
| | | list = XmlHelper.DeserializeFromXml<ObservableCollection<SensorData>>(path); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Load Sensor Data Failed.", ex); |
| | | } |
| | | Datasource = list; |
| | | } |
| | | |
| | | private void ClearSensorControl() |
| | | { |
| | | foreach (var ctl in diWrap.Children) |
| | | { |
| | | if (ctl is SingleSensor ss) |
| | | { |
| | | ss.Close(); |
| | | } |
| | | } |
| | | diWrap.Children.Clear(); |
| | | controls.Clear(); |
| | | } |
| | | |
| | | private void RefreshSensorControl(bool start) |
| | | { |
| | | StopReadCurrent(); |
| | | ClearSensorControl(); |
| | | foreach (var data in Datasource) |
| | | { |
| | | SingleSensor ss = new SingleSensor(data.Name, data.Ip, data.Port, data.Address, data.Channel) |
| | | { |
| | | Width = 240 |
| | | }; |
| | | diWrap.Children.Add(ss); |
| | | controls.Add(ss); |
| | | Task.Factory.StartNew(() => |
| | | { |
| | | ss.Connect(); |
| | | }); |
| | | } |
| | | if (start) StartReadCurrent(); |
| | | } |
| | | |
| | | private void ConnectAllSensor() |
| | | { |
| | | foreach (var ctl in diWrap.Children) |
| | | { |
| | | if (ctl is SingleSensor ss) |
| | | { |
| | | ss.Connect(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void DisconnectAllSensor() |
| | | { |
| | | foreach (var ctl in diWrap.Children) |
| | | { |
| | | if (ctl is SingleSensor ss) |
| | | { |
| | | ss.Close(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void SimpleMaskControl_Loaded(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | LoadSensorData(); |
| | | RefreshSensorControl(needRead); |
| | | LoadBurnInSetting(); |
| | | Loaded -= SimpleMaskControl_Loaded; |
| | | } |
| | | |
| | | private void OpenDataModal(SensorData data) |
| | | { |
| | | DataModal modal = new DataModal() |
| | | { |
| | | Title = "新增", |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (modal.Open(data, Datasource) == true) |
| | | { |
| | | string path = Path.Combine(BaseFolder, "sensor.data"); |
| | | try |
| | | { |
| | | XmlHelper.SerializeToXml(path, Datasource); |
| | | LoadSensorData(); |
| | | RefreshSensorControl(needRead); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ToastHelper.Error("保存失败"); |
| | | log.Error("Save Sensor Data Failed.", ex); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void DoExport() |
| | | { |
| | | try |
| | | { |
| | | SaveFileDialog sfd = new SaveFileDialog(); |
| | | sfd.Filter = "Excel 文件 (*.xls)|*.xls"; |
| | | if (sfd.ShowDialog() == true) |
| | | { |
| | | ExcelHelper.ExportExcel(sfd.FileName, Datasource); |
| | | } |
| | | ToastHelper.Success(this.lang("App.ExportSuccess")); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Export Failed.", ex); |
| | | ToastHelper.Error(this.lang("App.ExportFailed")); |
| | | } |
| | | } |
| | | |
| | | private void DoImport() |
| | | { |
| | | try |
| | | { |
| | | OpenFileDialog ofd = new OpenFileDialog(); |
| | | ofd.Filter = "Excel 文件 (*.xls)|*.xls"; |
| | | if (ofd.ShowDialog() == true) |
| | | { |
| | | var datas = ExcelHelper.ReadFromExcel<SensorData>(ofd.FileName); |
| | | string path = Path.Combine(BaseFolder, "sensor.data"); |
| | | XmlHelper.SerializeToXml(path, datas); |
| | | DoRefresh(); |
| | | ToastHelper.Success(this.lang("App.ExportSuccess")); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Error("Export Failed.", ex); |
| | | ToastHelper.Error(this.lang("App.ExportFailed")); |
| | | } |
| | | } |
| | | |
| | | private void SaveDatasouce(object datasource) |
| | | { |
| | | string path = Path.Combine(BaseFolder, "sensor.data"); |
| | | XmlHelper.SerializeToXml(path, datasource); |
| | | } |
| | | |
| | | private void DoRefresh() |
| | | { |
| | | ShowMask(() => |
| | | { |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | LoadSensorData(); |
| | | RefreshSensorControl(needRead); |
| | | })); |
| | | }, (ex) => |
| | | { |
| | | log.Error("Refresh Sensor Data Failed.", ex); |
| | | }, "请稍后", "正在加载..."); |
| | | } |
| | | |
| | | private void DoDelete(SensorData data) |
| | | { |
| | | if (MsgBoxHelper2.WarnChoose("删除?") == MessageBoxResult.OK) |
| | | { |
| | | var index = Datasource.IndexOf(data); |
| | | if (index >= 0) |
| | | { |
| | | Datasource.RemoveAt(index); |
| | | SaveDatasouce(Datasource); |
| | | DoRefresh(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void Button_Click(object sender, System.Windows.RoutedEventArgs e) |
| | | { |
| | | var btn = sender as Button; |
| | | var tag = btn?.Tag; |
| | | switch (btn?.Name) |
| | | { |
| | | case "addBtn": |
| | | OpenDataModal(new SensorData()); |
| | | break; |
| | | case "rfhBtn": |
| | | DoRefresh(); |
| | | break; |
| | | case "editBtn": |
| | | OpenDataModal((SensorData)tag); |
| | | break; |
| | | case "delBtn": |
| | | DoDelete((SensorData)tag); |
| | | break; |
| | | case "connectAllBtn": |
| | | ConnectAllSensor(); |
| | | break; |
| | | case "disConnectAllBtn": |
| | | DisconnectAllSensor(); |
| | | break; |
| | | case "exportBtn": |
| | | DoExport(); |
| | | break; |
| | | case "importBtn": |
| | | DoImport(); |
| | | break; |
| | | case "burnInSettingBtn": |
| | | OpenBurnSettingModal(); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | |
| | | [ObservableProperty] |
| | | private ObservableCollection<PLCTagData> burnInSettingData; |
| | | |
| | | private void LoadBurnInSetting() |
| | | { |
| | | S7Context.dataCache.Clear(); |
| | | ObservableCollection<PLCTagData> datas; |
| | | try |
| | | { |
| | | string path = Path.Combine(BaseFolder, "BurnInSettingData.data"); |
| | | if (File.Exists(path)) |
| | | { |
| | | datas = XmlHelper.DeserializeFromXml<ObservableCollection<PLCTagData>>(path); |
| | | } |
| | | else |
| | | { |
| | | datas = new ObservableCollection<PLCTagData>(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | datas = new ObservableCollection<PLCTagData>(); |
| | | } |
| | | BurnInSettingData = datas; |
| | | LoadBurnInSettingCache(); |
| | | } |
| | | |
| | | private void LoadBurnInSettingCache() |
| | | { |
| | | foreach (var data in BurnInSettingData) |
| | | { |
| | | S7Context.dataCache[data.Name] = data; |
| | | } |
| | | } |
| | | |
| | | private void OpenBurnSettingModal() |
| | | { |
| | | BurnInSettingModal modal = new BurnInSettingModal |
| | | { |
| | | Owner = Window.GetWindow(this) |
| | | }; |
| | | if (modal.Open(BurnInSettingData) == true) |
| | | { |
| | | var datas = modal.Datasource; |
| | | try |
| | | { |
| | | string path = Path.Combine(BaseFolder, "BurnInSettingData.data"); |
| | | XmlHelper.SerializeToXml(path, datas); |
| | | BurnInSettingData = datas; |
| | | LoadBurnInSettingCache(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | <pu:WindowX x:Class="Plugin.CurrentSensorControl.DataModal" |
| | | 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:Plugin.CurrentSensorControl" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:sys="clr-namespace:System;assembly=mscorlib" |
| | | mc:Ignorable="d" |
| | | Title="Form" |
| | | SizeToContent="Height" |
| | | Width="600" |
| | | WindowStartupLocation="CenterOwner" |
| | | Style="{StaticResource ModalWindow}"> |
| | | <Window.Resources> |
| | | |
| | | </Window.Resources> |
| | | |
| | | <Grid Margin="10"> |
| | | <StackPanel x:Name="formPanel"> |
| | | <pu:FormGroup x:Name="FgName" Header="名称" |
| | | Style="{StaticResource InputFormGroupStyle}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <TextBox x:Name="TbName" Style="{StaticResource EditorTextBoxStyle}" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgIP" Header="IP" |
| | | Style="{StaticResource InputFormGroupStyle}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <TextBox x:Name="TbIP" Style="{StaticResource EditorTextBoxStyle}" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgPort" Header="Port" |
| | | Style="{StaticResource InputFormGroupStyle}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <pu:NumberInput x:Name="NiPort" Style="{StaticResource FormNumberInput}" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgAddress" Header="Address" |
| | | Style="{StaticResource InputFormGroupStyle}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <pu:NumberInput x:Name="NiAddress" Style="{StaticResource FormNumberInput}" /> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup x:Name="FgChannel" Header="Channel" |
| | | Style="{StaticResource InputFormGroupStyle}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | GroupName="MyFormGroup"> |
| | | <pu:NumberInput x:Name="NiChannel" Style="{StaticResource FormNumberInput}" /> |
| | | </pu:FormGroup> |
| | | </StackPanel> |
| | | </Grid> |
| | | </pu:WindowX> |
| New file |
| | |
| | | using HMI.UI.DpUtil; |
| | | using HMI.UI.Util; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.CurrentSensorControl.Entity; |
| | | using System.Collections.ObjectModel; |
| | | using System.ComponentModel; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// ModalWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class DataModal : WindowX |
| | | { |
| | | public DataModal() |
| | | { |
| | | this.DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public SensorData data { get; private set; } |
| | | public ObservableCollection<SensorData> datasource { get; private set; } |
| | | |
| | | private bool _isProcessing; |
| | | |
| | | protected override void OnClosing(CancelEventArgs e) |
| | | { |
| | | //Press Continue Button |
| | | if (DialogResult == true) |
| | | { |
| | | if (_isProcessing) |
| | | { |
| | | e.Cancel = true; |
| | | return; |
| | | } |
| | | var okButton = WindowXModalDialog.GetOKButton(this); |
| | | try |
| | | { |
| | | _isProcessing = true; |
| | | ButtonHelper.SetIsPending(okButton, true); |
| | | if (!ValidateForm()) |
| | | { |
| | | e.Cancel = true; |
| | | return; |
| | | } |
| | | SaveOrUpdateData(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ToastHelper.Error(this, $"Error!{ex.Message}"); |
| | | e.Cancel = true; |
| | | return; |
| | | } |
| | | finally |
| | | { |
| | | _isProcessing = false; |
| | | ButtonHelper.SetIsPending(okButton, false); |
| | | } |
| | | } |
| | | base.OnClosing(e); |
| | | } |
| | | |
| | | private bool ValidateName(object value, out string err) |
| | | { |
| | | err = null; |
| | | //string group = TbGroup.Text; |
| | | //var temp = Datasource.FirstOrDefault(d => d.Group == group && d.Name == value.ToString()); |
| | | //if (temp != null && temp != Data) |
| | | //{ |
| | | // err = this.lang("App.MustBeUnique", $"{this.lang("doc.group")},{this.lang("doc.name")}"); |
| | | // return false; |
| | | //} |
| | | return true; |
| | | } |
| | | |
| | | private bool ValidateAddress(object value, out string err) |
| | | { |
| | | err = null; |
| | | //string group = TbGroup.Text; |
| | | //var temp = Datasource.FirstOrDefault(d => d.Address == value.ToString()); |
| | | //if (temp != null && temp != Data) |
| | | //{ |
| | | // err = this.lang("App.MustBeUnique", this.lang("doc.Address")); |
| | | // return false; |
| | | //} |
| | | return true; |
| | | } |
| | | |
| | | private bool ValidateForm() |
| | | { |
| | | bool flag = FormGroupHelper.ValidateForm(formPanel); |
| | | if (flag) |
| | | { |
| | | data.Name = TbName.Text; |
| | | data.Ip = TbIP.Text; |
| | | data.Port = ((int?)NiPort.Value) ?? 0; |
| | | data.Address = ((int?)NiAddress.Value) ?? 0; |
| | | data.Channel = ((int?)NiChannel.Value) ?? 0; |
| | | } |
| | | return flag; |
| | | } |
| | | |
| | | private void SaveOrUpdateData() |
| | | { |
| | | var index = datasource.IndexOf(data); |
| | | if (index > -1) |
| | | { |
| | | datasource[index] = data; |
| | | } |
| | | else |
| | | { |
| | | datasource.Add(data); |
| | | } |
| | | } |
| | | |
| | | public bool? Open(SensorData data, ObservableCollection<SensorData> datasource) |
| | | { |
| | | this.data = data; |
| | | this.datasource = datasource; |
| | | TbName.Text = data.Name; |
| | | TbIP.Text = data.Ip; |
| | | NiPort.Value = data.Port; |
| | | NiAddress.Value = data.Address; |
| | | NiChannel.Value = data.Channel; |
| | | return this.ShowDialog(); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using System.Collections; |
| | | using System.Configuration; |
| | | using System.Runtime.CompilerServices; |
| | | |
| | | namespace Plugin.CurrentSensorControl.Entity |
| | | { |
| | | public class BaseConfig |
| | | { |
| | | private static Hashtable customConfig = (Hashtable)ConfigurationManager.GetSection("TestResultConfig"); |
| | | |
| | | public static readonly BaseConfig Instance = new BaseConfig(); |
| | | |
| | | private BaseConfig() { |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 首页布局行数 |
| | | /// </summary> |
| | | private int row = 1; |
| | | public int Row |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? row : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | private string GetValue([CallerMemberName] string propertyName = null) |
| | | { |
| | | return (customConfig != null && customConfig.ContainsKey(propertyName)) ? customConfig[propertyName].ToString() : null; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 首页布局列数 |
| | | /// </summary> |
| | | private int column = 2; |
| | | public int Column |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? column : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 炉数 -1 就是row*column |
| | | /// </summary> |
| | | private int cellCount = -1; |
| | | public int CellCount |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? cellCount : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 点位列数 |
| | | /// </summary> |
| | | private int positionColumn = 6; |
| | | public int PositionColumn |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? positionColumn : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 每个炉子的点位数 |
| | | /// </summary> |
| | | private int positionCount = 54; |
| | | public int PositionCount |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? positionCount : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 曲线最多保存多少数据 |
| | | /// </summary> |
| | | private int maxSize = 10000; |
| | | public int MaxSize |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? maxSize : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 图表刷新频率 ms |
| | | /// </summary> |
| | | private int refreshInterval = 500; |
| | | public int RefreshInterval |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? refreshInterval : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 炉子名称 |
| | | /// </summary> |
| | | private string nameStr = "A,B,C,D,E,F,G"; |
| | | public string NameStr |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? nameStr : data; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 默认展示的图表标题 |
| | | /// </summary> |
| | | private string mainChartTitle = "平均温度"; |
| | | public string MainChartTitle |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? mainChartTitle : data; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 双击打开的详细图表标题 |
| | | /// </summary> |
| | | private string detailChartTitle = "详细温度"; |
| | | public string DetailChartTitle |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? detailChartTitle : data; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 穴位Step列表最大容量 |
| | | /// </summary> |
| | | private int cellListMaxSize = 10000; |
| | | public int CellListMaxSize |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? cellListMaxSize : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | private int portStart = 6660; |
| | | public int PortStart |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? portStart : int.Parse(data); |
| | | } |
| | | } |
| | | |
| | | private string codeParserType; |
| | | public string CodeParserType |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? codeParserType : data.ToString(); |
| | | } |
| | | } |
| | | |
| | | public bool testing = false; |
| | | } |
| | | } |
| New file |
| | |
| | | using ConnectionUtil; |
| | | using OPCConnection; |
| | | |
| | | namespace Plugin.CurrentSensorControl.Entity |
| | | { |
| | | public class OPCContext |
| | | { |
| | | private static Dictionary<string, SCADAApi> cache = new Dictionary<string, SCADAApi>(); |
| | | private static string opcIP = "127.0.0.1"; |
| | | private static int opcPort = 6543; |
| | | private static int localPort = 18888; |
| | | |
| | | public static SCADAApi Get(string name) |
| | | { |
| | | if (!cache.ContainsKey(name)) |
| | | { |
| | | var client = new OPCClient(); |
| | | if (!client.Connect2(opcIP, opcPort, localPort, out string errMsg)) |
| | | { |
| | | |
| | | } |
| | | else |
| | | { |
| | | |
| | | } |
| | | cache[name] = client; |
| | | } |
| | | return cache[name]; |
| | | } |
| | | |
| | | public static bool Connect(string name) |
| | | { |
| | | if (cache.ContainsKey(name)) |
| | | { |
| | | return cache[name].Connect2(opcIP, opcPort, localPort, out string errMsg) == true; |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using HMI.Core; |
| | | |
| | | namespace Plugin.CurrentSensorControl.Entity |
| | | { |
| | | public enum PLCTagType { |
| | | BOOL, |
| | | SHORT, |
| | | INT, |
| | | FLOAT |
| | | } |
| | | |
| | | public class PLCTagData |
| | | { |
| | | [ExcelColumn("名称")] |
| | | public string Name { get; set; } |
| | | [ExcelColumn("地址")] |
| | | public string Address { get; set; } |
| | | [ExcelColumn("类型")] |
| | | public PLCTagType Type { get; set; } |
| | | [ExcelColumn("长度")] |
| | | public int Length { get; set; } |
| | | [ExcelColumn("描述")] |
| | | public string Description { get; set; } |
| | | } |
| | | } |
| New file |
| | |
| | | using HslCommunication; |
| | | using HslCommunication.Core.Pipe; |
| | | using HslCommunication.Profinet.Siemens; |
| | | |
| | | namespace Plugin.CurrentSensorControl.Entity |
| | | { |
| | | public class S7Context |
| | | { |
| | | private static Dictionary<string, SiemensS7Net> cache = new Dictionary<string, SiemensS7Net>(); |
| | | public static Dictionary<string, PLCTagData> dataCache = new Dictionary<string, PLCTagData>(); |
| | | |
| | | private static string Ip; |
| | | private static int Port; |
| | | |
| | | public static void Init(string ip, int port) |
| | | { |
| | | Ip = ip; |
| | | Port = port; |
| | | } |
| | | |
| | | |
| | | public static SiemensS7Net Get(string name) |
| | | { |
| | | if (!cache.ContainsKey(name)) |
| | | { |
| | | var client = new SiemensS7Net(SiemensPLCS.S1500); |
| | | cache[name] = client; |
| | | PipeTcpNet pipeTcpNet = new PipeTcpNet(Ip, Port); |
| | | pipeTcpNet.ConnectTimeOut = 5000; |
| | | pipeTcpNet.ReceiveTimeOut = 10000; |
| | | client.CommunicationPipe = pipeTcpNet; |
| | | client.ConnectServer(); |
| | | } |
| | | return cache[name]; |
| | | } |
| | | |
| | | public static bool Connect(string name) |
| | | { |
| | | |
| | | return false; |
| | | } |
| | | |
| | | public static bool GetData(SiemensS7Net api, string name, out object val) |
| | | { |
| | | val = null; |
| | | if (dataCache.ContainsKey(name)) |
| | | { |
| | | var data = dataCache[name]; |
| | | string address = data.Address; |
| | | if (data.Type == PLCTagType.BOOL) |
| | | { |
| | | var res = api.ReadBool(address); |
| | | val = res.Content; |
| | | return res.IsSuccess; |
| | | } |
| | | else if (data.Type == PLCTagType.SHORT) |
| | | { |
| | | var res = api.ReadInt16(address); |
| | | val = res.Content; |
| | | return res.IsSuccess; |
| | | } |
| | | else if (data.Type == PLCTagType.INT) |
| | | { |
| | | var res = api.ReadInt32(address); |
| | | val = res.Content; |
| | | return res.IsSuccess; |
| | | } |
| | | else if (data.Type == PLCTagType.FLOAT) |
| | | { |
| | | var res = api.ReadFloat(address); |
| | | val = res.Content; |
| | | return res.IsSuccess; |
| | | } |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public static bool WriteData(SiemensS7Net api, string name, object val) |
| | | { |
| | | if (dataCache.ContainsKey(name)) |
| | | { |
| | | var data = dataCache[name]; |
| | | string address = data.Address; |
| | | OperateResult res; |
| | | switch (data.Type) |
| | | { |
| | | case PLCTagType.BOOL: |
| | | res = api.Write(address, (bool)val); |
| | | break; |
| | | case PLCTagType.SHORT: |
| | | res = api.Write(address, (short)val); |
| | | break; |
| | | case PLCTagType.INT: |
| | | res = api.Write(address, (int)val); |
| | | break; |
| | | case PLCTagType.FLOAT: |
| | | res = api.Write(address, (float)val); |
| | | break; |
| | | default: |
| | | return true; |
| | | } |
| | | return res.IsSuccess; |
| | | } |
| | | else |
| | | { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | using HMI.Core; |
| | | |
| | | namespace Plugin.CurrentSensorControl.Entity |
| | | { |
| | | public class SensorData |
| | | { |
| | | [ExcelColumn("名称")] |
| | | public string Name { get; set; } |
| | | [ExcelColumn("IP")] |
| | | public string Ip { get; set; } |
| | | [ExcelColumn("端口")] |
| | | public int Port { get; set; } |
| | | |
| | | [ExcelColumn("地址")] |
| | | public int Address { get; set; } |
| | | |
| | | [ExcelColumn("通道")] |
| | | public int Channel { get; set; } |
| | | } |
| | | } |
| New file |
| | |
| | | <Project Sdk="Microsoft.NET.Sdk"> |
| | | |
| | | <PropertyGroup> |
| | | <OutputType>Library</OutputType> |
| | | <TargetFramework>net472</TargetFramework> |
| | | <Nullable>enable</Nullable> |
| | | <LangVersion>10.0</LangVersion> |
| | | <ImplicitUsings>enable</ImplicitUsings> |
| | | <UseWPF>true</UseWPF> |
| | | </PropertyGroup> |
| | | |
| | | <ItemGroup> |
| | | <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> |
| | | <PackageReference Include="log4net" Version="3.0.4" /> |
| | | <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" /> |
| | | <PackageReference Include="Panuon.WPF.UI" Version="1.3.0.2" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj" /> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj" /> |
| | | <ProjectReference Include="..\HMI.UI\HMI.UI.csproj" /> |
| | | <ProjectReference Include="..\OPCClient\OPCClient.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Reference Include="CurrentReadHelper"> |
| | | <HintPath>..\..\..\..\Users\chrry\Desktop\CurrentReadHelper\builds\CurrentReadHelper.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="HslCommunication"> |
| | | <HintPath>..\Libs\HslCommunication.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="SimensDriver"> |
| | | <HintPath>..\Libs\SimensDriver.dll</HintPath> |
| | | </Reference> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Compile Update="BurnInCell.xaml.cs"> |
| | | <SubType>Code</SubType> |
| | | </Compile> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| New file |
| | |
| | | <UserControl x:Class="Plugin.CurrentSensorControl.SingleSensor" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.CurrentSensorControl" |
| | | mc:Ignorable="d" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:mdi="clr-namespace:HMI.UI.MDI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | Background="#FFF" |
| | | Padding="5" |
| | | Width="Auto" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <ResourceDictionary> |
| | | <ResourceDictionary.MergedDictionaries> |
| | | <pu:StyleDictionary Includes="TabControl" /> |
| | | <ResourceDictionary Source="/HMI.UI;component/Style/PanuonListView.xaml"/> |
| | | </ResourceDictionary.MergedDictionaries> |
| | | |
| | | <Style TargetType="TextBox" x:Key="labelText"> |
| | | <Setter Property="Height" Value="35"/> |
| | | <Setter Property="FontSize" Value="20"/> |
| | | <Setter Property="VerticalContentAlignment" Value="Center"/> |
| | | <Setter Property="BorderThickness" Value="0"/> |
| | | <Setter Property="Background" Value="Transparent"/> |
| | | <Setter Property="Width" Value="120"/> |
| | | </Style> |
| | | </ResourceDictionary> |
| | | </UserControl.Resources> |
| | | |
| | | <GroupBox Header="{x:Null}" Padding="5"> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="12"/> |
| | | </Grid.RowDefinitions> |
| | | <StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Center" dp:StackPanelHelper.ChildSpace="5"> |
| | | <!--<TextBox IsReadOnly="True" Text="{Binding SensorName}" Style="{StaticResource labelText}"> |
| | | <TextBox.ToolTip> |
| | | <ToolTip Padding="5" BorderThickness="1" BorderBrush="Black" Background="Yellow" Content="1231231"/> |
| | | </TextBox.ToolTip> |
| | | </TextBox>--> |
| | | |
| | | <ui:ScrollLabel Width="80" Value="{Binding SensorName}"/> |
| | | <ui:LightBall Size="30" Value="{Binding IsConnected}"/> |
| | | <Button x:Name="controlBtn" Click="controlBtn_Click"> |
| | | <Button.Style> |
| | | <Style TargetType="Button" BasedOn="{StaticResource ResetBtn}"> |
| | | <Setter Property="Content" Value="连接"/> |
| | | <Setter Property="Background" Value="{DynamicResource GreenVerBar}"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding IsConnected}" Value="True"> |
| | | <Setter Property="Background" Value="{DynamicResource DangerVerBar}"/> |
| | | <Setter Property="Content" Value="断开"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Button.Style> |
| | | </Button> |
| | | </StackPanel> |
| | | <pu:FormGroup Grid.Row="1" Header="电流(A)" Style="{StaticResource InputFormGroupStyle}"> |
| | | <TextBox IsReadOnly="True" Text="{Binding Current}" Style="{StaticResource EditorTextBoxStyle}"/> |
| | | </pu:FormGroup> |
| | | <Label Grid.Row="2" Foreground="Red" Padding="0" FontSize="10" Content="{Binding ErrMsg}"/> |
| | | </Grid> |
| | | </GroupBox> |
| | | </UserControl> |
| New file |
| | |
| | | using CommunityToolkit.Mvvm.ComponentModel; |
| | | using HslCommunication; |
| | | using HslCommunication.ModBus; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | | namespace Plugin.CurrentSensorControl |
| | | { |
| | | /// <summary> |
| | | /// SingleSensor.xaml 的交互逻辑 |
| | | /// </summary> |
| | | [ObservableObject] |
| | | public partial class SingleSensor : UserControl |
| | | { |
| | | private static Dictionary<string, ModbusRtuOverTcp> clients = new Dictionary<string, ModbusRtuOverTcp>(); |
| | | private static Dictionary<ModbusRtuOverTcp, bool> status = new Dictionary<ModbusRtuOverTcp, bool>(); |
| | | |
| | | [ObservableProperty] |
| | | private string sensorName; |
| | | |
| | | [ObservableProperty] |
| | | private bool isConnected; |
| | | |
| | | [ObservableProperty] |
| | | private string current; |
| | | |
| | | [ObservableProperty] |
| | | private string ip; |
| | | |
| | | [ObservableProperty] |
| | | private int port; |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 地址(站号) |
| | | /// </summary> |
| | | [ObservableProperty] |
| | | private int address; |
| | | |
| | | [ObservableProperty] |
| | | private string errMsg; |
| | | |
| | | /// <summary> |
| | | /// 通道 |
| | | /// </summary> |
| | | [ObservableProperty] |
| | | private int channel; |
| | | |
| | | private ModbusRtuOverTcp client; |
| | | |
| | | |
| | | public SingleSensor() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public SingleSensor(string name, string ip, int port, int address, int channel) : this() |
| | | { |
| | | SensorName = name; |
| | | Ip = ip; |
| | | Port = port; |
| | | Address = address; |
| | | Channel = channel; |
| | | string key = $"{Ip}:{Port}:{Address}"; |
| | | if (!clients.ContainsKey(key)) |
| | | { |
| | | client = new ModbusRtuOverTcp(Ip, Port, (byte)Address); |
| | | clients[key] = client; |
| | | } |
| | | else |
| | | { |
| | | client = clients[key]; |
| | | } |
| | | } |
| | | |
| | | private void controlBtn_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | if (IsConnected) |
| | | { |
| | | this.Close(); |
| | | } |
| | | else |
| | | { |
| | | Task.Factory.StartNew(() => { this.Connect(); }); |
| | | } |
| | | } |
| | | |
| | | public void Connect() |
| | | { |
| | | lock (client) |
| | | { |
| | | if (!status.ContainsKey(client) || !status[client]) |
| | | { |
| | | var res = client.ConnectServer(); |
| | | IsConnected = res.IsSuccess; |
| | | status[client] = IsConnected; |
| | | } |
| | | else |
| | | { |
| | | IsConnected = status[client]; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public void ReadCurrent() |
| | | { |
| | | //if (status.ContainsKey(client) && status[client]) |
| | | //{ |
| | | // OperateResult<double[]> res; |
| | | // lock (client) |
| | | // { |
| | | // res = client.ReadDouble(channel.ToString(), 1); |
| | | // } |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | // if (res.IsSuccess) |
| | | // { |
| | | // Current = res.Content[0].ToString(); |
| | | // ErrMsg = string.Empty; |
| | | // } |
| | | // else |
| | | // { |
| | | // ErrMsg = res.Message; |
| | | // //Close(); |
| | | // } |
| | | // }); |
| | | //} |
| | | //else |
| | | //{ |
| | | // IsConnected = false; |
| | | //} |
| | | var sb = status[client]; |
| | | if (IsConnected) |
| | | { |
| | | OperateResult<double[]> res; |
| | | lock (client) |
| | | { |
| | | res = client.ReadDouble(channel.ToString(), 1); |
| | | } |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | if (res.IsSuccess) |
| | | { |
| | | Current = res.Content[0].ToString(); |
| | | ErrMsg = string.Empty; |
| | | } |
| | | else |
| | | { |
| | | ErrMsg = res.Message; |
| | | //Close(); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | public void Close() |
| | | { |
| | | lock (client) |
| | | { |
| | | var connected = status[client]; |
| | | if (connected) |
| | | { |
| | | var res = client.ConnectClose(); |
| | | if (res.IsSuccess) |
| | | { |
| | | client.Dispose(); |
| | | } |
| | | IsConnected = !res.IsSuccess; |
| | | status[client] = IsConnected; |
| | | } |
| | | else |
| | | { |
| | | IsConnected = connected; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | <Generator>ResXFileCodeGenerator</Generator> |
| | | <LastGenOutput>Resources.Designer.cs</LastGenOutput> |
| | | </EmbeddedResource> |
| | | <None Include="app.config" /> |
| | | <None Include="packages.config" /> |
| | | <None Include="Properties\Settings.settings"> |
| | | <Generator>SettingsSingleFileGenerator</Generator> |
| | |
| | | </None> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\ConnectionUtil\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{D0806FA6-3F6D-4304-81B8-EAD9DA7CB5B2}</Project> |
| | | <ProjectReference Include="..\ConnectionUtil\ConnectionUtil.csproj"> |
| | | <Project>{d0806fa6-3f6d-4304-81b8-ead9da7cb5b2}</Project> |
| | | <Name>ConnectionUtil</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj"> |
| New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <configuration> |
| | | <runtime> |
| | | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <dependentAssembly> |
| | | <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> |
| | | <bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" /> |
| | | </dependentAssembly> |
| | | </assemblyBinding> |
| | | </runtime> |
| | | </configuration> |
| | |
| | | bool Start(out string msg); |
| | | |
| | | bool ReadDIBool(string address, out bool res, out string msg); |
| | | bool ReadDIDouble(string address, out double? res, out string msg); |
| | | |
| | | bool ReadDOBool(string address, out bool res, out string msg); |
| | | |
| | |
| | | { |
| | | client?.Dispose(); |
| | | } |
| | | |
| | | public bool ReadDIDouble(string address, out double? res, out string msg) |
| | | { |
| | | var result = client?.ReadDouble($"x=2;{address}"); |
| | | msg = result?.Message; |
| | | res = result?.Content; |
| | | return result?.IsSuccess == true; |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | this.Close(); |
| | | } |
| | | |
| | | public bool ReadDIDouble(string address, out double? res, out string msg) |
| | | { |
| | | throw new NotImplementedException(); |
| | | } |
| | | } |
| | | } |
| | |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\hslCommunicationV12.0.3带源码demo\HslCommunication\HslCommunication.csproj" /> |
| | | <ProjectReference Include="..\HMI.Base\HMI.Base.csproj" /> |
| | | <ProjectReference Include="..\HMI.Core\HMI.Core.csproj" /> |
| | | <ProjectReference Include="..\HMI.UI\HMI.UI.csproj" /> |
| | | <ProjectReference Include="..\HMI.Util\HMI.Util.csproj" /> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Reference Include="HslCommunication"> |
| | | <HintPath>..\Libs\HslCommunication.dll</HintPath> |
| | | </Reference> |
| | | </ItemGroup> |
| | | |
| | | </Project> |
| | |
| | | { |
| | | if (data.Dio == DIOType.DI) |
| | | { |
| | | if (data.ControlType == ControlType.BOOL) |
| | | { |
| | | return new LightBall |
| | | { |
| | | Size = 40, |
| | | DataContext = data |
| | | }; |
| | | } |
| | | else |
| | | { |
| | | return new TextBox |
| | | { |
| | | IsReadOnly = true |
| | | }; |
| | | } |
| | | } |
| | | Style btnStyle = this.FindResource("PrimaryButton") as Style; |
| | | var btn = new Button |
| | |
| | | case ControlType.LREAL: |
| | | case ControlType.STRING: |
| | | case ControlType.WSTRING: |
| | | ((Button)ui).Content = value; |
| | | ((TextBox)ui).Text = value; |
| | | break; |
| | | default: |
| | | ((TextBox)ui).Text = value; |
| | | break; |
| | | } |
| | | }); |
| | |
| | | value = null; |
| | | return false; |
| | | } |
| | | string msg; |
| | | switch (data.ControlType) |
| | | { |
| | | case ControlType.BOOL: |
| | |
| | | bool res = false; |
| | | if (data.Dio == DIOType.DI) |
| | | { |
| | | res = controller.ReadDIBool(data.Address, out val, out string msg); |
| | | res = controller.ReadDIBool(data.Address, out val, out msg); |
| | | } |
| | | else |
| | | { |
| | | res = controller.ReadDOBool(data.Address, out val, out string msg); |
| | | res = controller.ReadDOBool(data.Address, out val, out msg); |
| | | } |
| | | if (res == true) |
| | | { |
| | |
| | | value = null; |
| | | return false; |
| | | default: |
| | | if (controller.ReadDIDouble(data.Address, out double? dVal, out msg)) |
| | | { |
| | | value = dVal.ToString(); |
| | | } |
| | | value = null; |
| | | return true; |
| | | } |
| | |
| | | Loaded="PluginControl_Loaded" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | | <Style TargetType="ComboBox" BasedOn="{StaticResource FormComboxStyle}"> |
| | | <Style x:Key="cbDate" TargetType="ComboBox" BasedOn="{StaticResource FormComboxStyle}"> |
| | | <EventSetter Event="SelectionChanged" Handler="ComboBox_SelectionChanged"/> |
| | | <Setter Property="pu:ComboBoxHelper.ClearButtonVisibility" Value="Collapsed"/> |
| | | <Setter Property="SelectedValuePath" Value="Value"/> |
| | | <Setter Property="DisplayMemberPath" Value="Name"/> |
| | | </Style> |
| | | <Style TargetType="pu:DateTimePicker" BasedOn="{StaticResource TimePicker}"> |
| | | <Setter Property="MinWidth" Value="0"/> |
| | |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | |
| | | <ColumnDefinition/> |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | <ComboBox x:Name="cb0" ItemsSource="{Binding Options}" SelectedValuePath="Value" DisplayMemberPath="Name"/> |
| | | <pu:FormGroup Header="型号"> |
| | | <Grid> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <ComboBox x:Name="modelSelect" Style="{StaticResource FormComboxStyle}" |
| | | pu:ComboBoxHelper.ClearButtonVisibility="Visible" SelectionChanged="modelSelect_SelectionChanged"/> |
| | | <Button x:Name="btnAll" Grid.Column="1" Click="Button_Click" |
| | | Style="{StaticResource RfhBtn}" Content="全部刷新"/> |
| | | </Grid> |
| | | </pu:FormGroup> |
| | | |
| | | <ComboBox x:Name="cb1" Grid.Column="1" ItemsSource="{Binding Options}" |
| | | SelectedValuePath="Value" DisplayMemberPath="Name"/> |
| | | <ComboBox x:Name="cb2" Grid.Column="2" ItemsSource="{Binding Options}" |
| | | SelectedValuePath="Value" DisplayMemberPath="Name"/> |
| | | <ComboBox Grid.Row="1" Grid.Column="0" x:Name="cb0" ItemsSource="{Binding Options}" |
| | | Style="{StaticResource cbDate}"/> |
| | | |
| | | <ComboBox x:Name="cb3" Grid.Column="3" ItemsSource="{Binding Options}" |
| | | SelectedValuePath="Value" DisplayMemberPath="Name"/> |
| | | <ComboBox Grid.Row="1" Grid.Column="1" x:Name="cb1" ItemsSource="{Binding Options}" |
| | | Style="{StaticResource cbDate}"/> |
| | | |
| | | <Grid Grid.Row="1" Grid.Column="0"> |
| | | <ComboBox Grid.Row="1" Grid.Column="2" x:Name="cb2" ItemsSource="{Binding Options}" |
| | | Style="{StaticResource cbDate}"/> |
| | | |
| | | <ComboBox Grid.Row="1" Grid.Column="3" x:Name="cb3" ItemsSource="{Binding Options}" |
| | | Style="{StaticResource cbDate}"/> |
| | | |
| | | <Grid Grid.Row="2" Grid.Column="0"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | |
| | | Content="{DynamicResource bd.btn}"/> |
| | | </Grid> |
| | | |
| | | <Grid Grid.Row="1" Grid.Column="1"> |
| | | <Grid Grid.Row="2" Grid.Column="1"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | |
| | | Content="{DynamicResource bd.btn}"/> |
| | | </Grid> |
| | | |
| | | <Grid Grid.Row="1" Grid.Column="2"> |
| | | <Grid Grid.Row="2" Grid.Column="2"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | |
| | | Content="{DynamicResource bd.btn}"/> |
| | | </Grid> |
| | | |
| | | <Grid Grid.Row="1" Grid.Column="3"> |
| | | <Grid Grid.Row="2" Grid.Column="3"> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | |
| | | Content="{DynamicResource bd.btn}"/> |
| | | </Grid> |
| | | |
| | | <wv2:WebView2 Grid.Row="2" Grid.ColumnSpan="4" Name = "webview2" |
| | | <wv2:WebView2 Grid.Row="3" Grid.ColumnSpan="4" Name = "webview2" |
| | | SizeChanged="webview2_SizeChanged" |
| | | NavigationCompleted="Webview2_NavigationCompleted" |
| | | Loaded="webview2_Loaded"/> |
| | |
| | | using HMI.Base; |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | |
| | | set { Set(ref _options, value); } |
| | | } |
| | | |
| | | private string iniFile; |
| | | public override void InitFinish() |
| | | { |
| | | iniFile = Path.Combine(BaseFolder, "Config.ini"); |
| | | if (!File.Exists(iniFile)) |
| | | { |
| | | File.Create(iniFile); |
| | | } |
| | | LoadProduct(); |
| | | } |
| | | |
| | | private void PluginControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void LoadProduct() |
| | | { |
| | | List<ProductData> products = ProductManager.GetProducts<List<ProductData>>() |
| | | ?? new List<ProductData>(); |
| | | this.modelSelect.Items.Clear(); |
| | | List<string> productSource = new List<string>(); |
| | | foreach (var prd in products) |
| | | { |
| | | this.modelSelect.Items.Add(prd.Name); |
| | | productSource.Add(prd.Name); |
| | | } |
| | | |
| | | string model = IniFileHelper.ReadIniData("Config", "Model", "", iniFile); |
| | | if (!string.IsNullOrEmpty(model)) |
| | | { |
| | | this.modelSelect.SelectedItem = model; |
| | | } |
| | | else if (products.Count > 0) |
| | | { |
| | | this.modelSelect.SelectedIndex = 0; |
| | | } |
| | | } |
| | | |
| | | private void RefreshAll() |
| | | { |
| | | try |
| | | { |
| | | var start0 = dtp00.SelectedDateTime ?? DateTime.Now; |
| | | var end0 = dtp01.SelectedDateTime ?? DateTime.Now; |
| | | RefreshChart0(start0, end0); |
| | | } |
| | | catch { } |
| | | |
| | | try |
| | | { |
| | | var start1 = dtp10.SelectedDateTime ?? DateTime.Now; |
| | | var end1 = dtp11.SelectedDateTime ?? DateTime.Now; |
| | | RefreshChart1(start1, end1); |
| | | } |
| | | catch { } |
| | | |
| | | try |
| | | { |
| | | var start2 = dtp20.SelectedDateTime ?? DateTime.Now; |
| | | var end2 = dtp21.SelectedDateTime ?? DateTime.Now; |
| | | RefreshChart2(start2, end2); |
| | | } |
| | | catch { } |
| | | |
| | | try |
| | | { |
| | | var start3 = dtp30.SelectedDateTime ?? DateTime.Now; |
| | | var end3 = dtp31.SelectedDateTime ?? DateTime.Now; |
| | | RefreshChart3(start3, end3); |
| | | } |
| | | catch { } |
| | | } |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | |
| | | DateTime start, end; |
| | | switch (btn.Name) |
| | | { |
| | | case "btnAll": |
| | | RefreshAll(); |
| | | break; |
| | | case "btn0": |
| | | start = dtp00.SelectedDateTime ?? DateTime.Now; |
| | | end = dtp01.SelectedDateTime ?? DateTime.Now; |
| | |
| | | } |
| | | |
| | | |
| | | private List<SerialData> SelectSerialDataByTime(DateTime start, DateTime end) |
| | | private List<SerialData> SelectSerialDataByTime(string model, DateTime start, DateTime end) |
| | | { |
| | | var s1 = DateTime.Now; |
| | | string[] files = GetDbFiles(BaseFolder, start, end); |
| | |
| | | { |
| | | return new List<SerialData>(); |
| | | } |
| | | string sql = $"SELECT * FROM serialData WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' ORDER BY time DESC;"; |
| | | string segment = string.Empty; |
| | | if (!string.IsNullOrEmpty(model)) |
| | | { |
| | | segment = $"AND model = '{model}'"; |
| | | } |
| | | |
| | | string sql = $@"SELECT * FROM serialData WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' |
| | | {segment} ORDER BY time DESC;"; |
| | | |
| | | DataTable dt = new DataTable(); |
| | | foreach (string file in files) |
| | |
| | | return data; |
| | | } |
| | | |
| | | private List<SerialData> SelectResultDataByTime(DateTime start, DateTime end) |
| | | private List<SerialData> SelectResultDataByTime(string model, DateTime start, DateTime end) |
| | | { |
| | | string[] files = GetDbFiles(BaseFolder, start, end); |
| | | if (files == null || files.Length <= 0) |
| | | { |
| | | return new List<SerialData>(); |
| | | } |
| | | string sql = $"SELECT * FROM testResult WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}';"; |
| | | |
| | | string segment = string.Empty; |
| | | if (!string.IsNullOrEmpty(model)) |
| | | { |
| | | segment = $"AND model = '{model}'"; |
| | | } |
| | | |
| | | string sql = $@"SELECT * FROM testResult WHERE time BETWEEN '{start:yyyy-MM-dd HH:mm:ss}' AND '{end:yyyy-MM-dd HH:mm:ss}' {segment};"; |
| | | |
| | | DataTable dt = new DataTable(); |
| | | foreach (string file in files) |
| | |
| | | { |
| | | dtp00.SelectedDateTime = start; |
| | | dtp01.SelectedDateTime = end; |
| | | string model = modelSelect.SelectedItem?.ToString(); |
| | | Task.Run(() => |
| | | { |
| | | try |
| | |
| | | { |
| | | webview2.CoreWebView2?.ExecuteScriptAsync($"loading0('加载中,请稍后...')"); |
| | | })); |
| | | List<SerialData> datas = SelectResultDataByTime(start, end); |
| | | List<SerialData> datas = SelectResultDataByTime(model, start, end); |
| | | datas.OrderByDescending(e => e.time); |
| | | int all = 0, output = 0; |
| | | HashSet<string> snCache = new HashSet<string>(); |
| | |
| | | { |
| | | dtp10.SelectedDateTime = start; |
| | | dtp11.SelectedDateTime = end; |
| | | string model = modelSelect.SelectedItem?.ToString(); |
| | | Task.Run(() => |
| | | { |
| | | try |
| | |
| | | { |
| | | webview2.CoreWebView2?.ExecuteScriptAsync($"loading1('加载中,请稍后...')"); |
| | | })); |
| | | List<SerialData> datas = SelectResultDataByTime(start, end); |
| | | List<SerialData> datas = SelectResultDataByTime(model, start, end); |
| | | |
| | | datas = datas.OrderByDescending(e => e.time).ToList(); |
| | | Dictionary<string, int?> pieData = new Dictionary<string, int?> { |
| | |
| | | { |
| | | dtp20.SelectedDateTime = start; |
| | | dtp21.SelectedDateTime = end; |
| | | string model = modelSelect.SelectedItem?.ToString(); |
| | | Task.Run(() => |
| | | { |
| | | try |
| | |
| | | { |
| | | webview2.CoreWebView2?.ExecuteScriptAsync($"loading2('加载中,请稍后...')"); |
| | | })); |
| | | List<SerialData> datas = SelectResultDataByTime(start, end); |
| | | List<SerialData> datas = SelectResultDataByTime(model, start, end); |
| | | |
| | | var groups = |
| | | datas.GroupBy(d => d.time.ToString("yyyy-MM-dd")); |
| | |
| | | { |
| | | dtp30.SelectedDateTime = start; |
| | | dtp31.SelectedDateTime = end; |
| | | string model = modelSelect.SelectedItem?.ToString(); |
| | | Task.Run(() => |
| | | { |
| | | try |
| | |
| | | webview2.CoreWebView2?.ExecuteScriptAsync($"loading3('加载中,请稍后...')"); |
| | | })); |
| | | var st = DateTime.Now; |
| | | List<SerialData> datas = SelectSerialDataByTime(start, end); |
| | | List<SerialData> datas = SelectSerialDataByTime(model, start, end); |
| | | var s2 = DateTime.Now; |
| | | log.Info($"RefreshChart3 Data Cast {(s2 - st).TotalMilliseconds}"); |
| | | |
| | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void modelSelect_SelectionChanged(object sender, SelectionChangedEventArgs e) |
| | | { |
| | | if (e.AddedItems.Count > 0) |
| | | { |
| | | IniFileHelper.WriteIniData("Config", "Model", e.AddedItems[0].ToString(), iniFile); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | using HMI.Core.Annotation; |
| | | using System.Reflection; |
| | | using System.Resources; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Runtime.InteropServices; |
| | | using System.Windows; |
| | | |
| | |
| | | try |
| | | { |
| | | SequenceContext?.StationGlobals.SetValBoolean("StationState.StopTest", 1, true); |
| | | log.Info($"Stop Result: {SequenceContext?.StationGlobals.GetValBoolean("StationState.StopTest", 1)}"); |
| | | if (this.execution == null) return true; |
| | | return this.execution.WaitForEndEx(2000, true, null, null); |
| | | } |
| | |
| | | |
| | | try |
| | | { |
| | | //log.Info($"Event: {EventCase}, NumericData: {MethodCode}, StringData: {strData}"); |
| | | log.Info($"Event: {EventCase}, NumericData: {MethodCode}, StringData: {strData}"); |
| | | } |
| | | catch |
| | | { |
| | |
| | | int index2 = int.Parse(arr2[0]); |
| | | this.tsSockets[index2].SetInfo(arr2[1]); |
| | | break; |
| | | case 8: |
| | | IsRunning = false; |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | |
| | | { "testing","测试中"}, |
| | | { "alert","报警"}, |
| | | { "ready","准备就绪"}, |
| | | { "abort","手动停止"}, |
| | | }; |
| | | |
| | | public static readonly Dictionary<string, SolidBrush> COLOR_MAP = new Dictionary<string, SolidBrush>() { |
| | |
| | | { "testing",new SolidBrush(Color.FromArgb(0,0,0,0))}, |
| | | { "checkInFailed",new SolidBrush(Color.FromArgb(0,0,0,0))}, |
| | | { "checkIn",new SolidBrush(Color.FromArgb(0,0,0,0))}, |
| | | { "abort",new SolidBrush(Color.FromArgb(0,0,0,0))}, |
| | | }; |
| | | |
| | | public static string GetRandomStatus() |
| | |
| | | </Grid.ColumnDefinitions> |
| | | |
| | | <TextBlock FontSize="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='30,940'}" |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='20,940'}" |
| | | FontWeight="Bold" |
| | | Margin="0" |
| | | HorizontalAlignment="Center" |
| | |
| | | Style="{StaticResource FormComboxStyle}" |
| | | pu:ComboBoxHelper.ClearButtonVisibility="Collapsed" |
| | | BorderBrush="Black" |
| | | Height="26" |
| | | BorderThickness="0,1,0,0" |
| | | pu:ComboBoxHelper.Watermark="{DynamicResource Tr.ProductInfo}" |
| | | Width="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | |
| | | <local:InfoTable x:Name="infoTable" Grid.Row="0" Grid.Column="1" |
| | | Grid.RowSpan="2" |
| | | FontSize="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='15,940'}"></local:InfoTable> |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='12,940'}"></local:InfoTable> |
| | | </Grid> |
| | | |
| | | <UniformGrid x:Name="mainGrid" Grid.Row="1" dp:UniformGridHelper.InnerBorder="1" |
| | |
| | | <!--<local:Chart Grid.Row="2" x:Name="chart" BorderThickness="0,1,0,1" BorderBrush="Black" |
| | | MouseDoubleClick="chart_MouseDoubleClick"/>--> |
| | | |
| | | <StatusBar Grid.Row="3"> |
| | | <StatusBar FontSize="18" Grid.Row="3"> |
| | | <StatusBar.ItemsPanel> |
| | | <ItemsPanelTemplate> |
| | | <DockPanel/> |
| | |
| | | |
| | | <StatusBarItem DockPanel.Dock="Right"> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="8"> |
| | | <Button Style="{StaticResource DeleteLink}" Click="Button_Click_2" Content="停止测试"/> |
| | | <!--<Button Style="{StaticResource DeleteLink}" Click="Button_Click_2" Content="停止测试"/>--> |
| | | |
| | | <StackPanel Orientation="Horizontal"> |
| | | <Ellipse Width="10" Height="10"> |
| | |
| | | Content="{DynamicResource Tr.Scan}"/> |
| | | <Button Grid.Column="1" Click="ClearAllSnr_Click" Style="{StaticResource DangerButton}" |
| | | Content="{DynamicResource Tr.ClearAllSNR}"/> |
| | | <Button Grid.Column="2" Click="SetStationGlobal_Click" Style="{StaticResource SuccessButton}" |
| | | Content="{DynamicResource App.Start}"/> |
| | | <!--<Button Grid.Column="2" Click="SetStationGlobal_Click" Style="{StaticResource SuccessButton}" |
| | | Content="{DynamicResource App.Start}"/>--> |
| | | <Button Grid.Column="2" Click="StartSingleClick"> |
| | | <Button.Style> |
| | | <Style TargetType="Button" BasedOn="{StaticResource SuccessButton}"> |
| | | <Setter Property="Content" Value="{DynamicResource App.Start}"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding IsTesting}" Value="True"> |
| | | <Setter Property="Background" Value="{DynamicResource DangerVerBar}"/> |
| | | <Setter Property="Content" Value="停止测试"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Button.Style> |
| | | </Button> |
| | | </Grid> |
| | | |
| | | </Grid> |
| | |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Plugin.TestResult; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using Plugin.TestResult_WPF.Util; |
| | | using SuperSocket.SocketBase.Config; |
| | | using SuperSocket.SocketBase.Protocol; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.IO; |
| | | using System.Net.WebSockets; |
| | | using System.Runtime.CompilerServices; |
| | | using System.Threading.Tasks; |
| | | using System.Timers; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | |
| | | set => RaiseAndSetIfchanged(ref _statusText, value); |
| | | } |
| | | |
| | | private bool _isTesting; |
| | | |
| | | public bool IsTesting |
| | | { |
| | | get { return _isTesting; } |
| | | set => RaiseAndSetIfchanged(ref _isTesting, value); |
| | | } |
| | | |
| | | private string tcpServerStatus; |
| | | |
| | | public string TcpServerStatus |
| | |
| | | set { RaiseAndSetIfchanged(ref tcpServerInfo, value); } |
| | | } |
| | | |
| | | private static CommonCodeParser codeParser = new CommonCodeParser(); |
| | | private static ICodeParser codeParser; |
| | | private readonly int index; |
| | | private readonly int cellCount; |
| | | private readonly string chartTitle; |
| | |
| | | |
| | | private TcpServer tcpServer; |
| | | private string CountIniPath; |
| | | |
| | | private DateTime? testStartTime; |
| | | |
| | | private Timer testTimeTimer; |
| | | |
| | | // 平均温度 |
| | | public List<double> tempratures = new List<double>(); |
| | |
| | | |
| | | for (int i = 0; i < this.cellCount; i++) |
| | | { |
| | | var cell = new SingleCell(title, i, config.CellListMaxSize, countIniPath); |
| | | var cellRow = (i / config.PositionColumn) + 1; |
| | | var cellCol = (i % config.PositionColumn) + 1; |
| | | var cellTitle = $"{title}-{cellRow}-{cellCol}"; |
| | | |
| | | var cell = new SingleCell(this, cellTitle, i, config.CellListMaxSize, countIniPath); |
| | | mainGrid.Children.Add(cell); |
| | | cells[i] = cell; |
| | | } |
| | | |
| | | if (config.CodeParserType == "JK01") |
| | | { |
| | | codeParser = new JKCodeParser(); |
| | | } |
| | | else |
| | | { |
| | | codeParser = new CommonCodeParser(); |
| | | } |
| | | ReadCount(); |
| | | testTimeTimer = new Timer(); |
| | | testTimeTimer.Interval = 10000; |
| | | testTimeTimer.AutoReset = true; |
| | | testTimeTimer.Elapsed += TestTimeTimer_Elapsed; |
| | | } |
| | | |
| | | private void TestTimeTimer_Elapsed(object sender, ElapsedEventArgs e) |
| | | { |
| | | if (testStartTime == null) return; |
| | | var now = DateTime.Now; |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | SetConsumeTime((now - testStartTime).Value.TotalSeconds); |
| | | })); |
| | | } |
| | | |
| | | public int GetSize() |
| | |
| | | |
| | | public void SetStatus(string status) |
| | | { |
| | | ViewControl.Logger.Debug($"In Status: {status}"); |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | var lastStatus = infoTable.status; |
| | | if (status == "preCheck") |
| | | { |
| | | ViewControl.Logger.Debug($"In preCheck"); |
| | | IsTesting = true; |
| | | return; |
| | | } |
| | | if (status == "stop") |
| | | { |
| | | IsTesting = false; |
| | | return; |
| | | } |
| | | if (status == "abort") |
| | | { |
| | | IsTesting = false; |
| | | } |
| | | infoTable.status = status; |
| | | |
| | | if (lastStatus != "testing" && status == "testing") |
| | | { |
| | | testStartTime = DateTime.Now; |
| | | SetStartTime(testStartTime?.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | testTimeTimer.Start(); |
| | | } |
| | | if (lastStatus == "testing" && status != "testing") |
| | | { |
| | | testTimeTimer.Stop(); |
| | | var now = DateTime.Now; |
| | | SetConsumeTime((now - testStartTime).Value.TotalSeconds); |
| | | SetEndTime(now.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | testStartTime = null; |
| | | } |
| | | })); |
| | | } |
| | | |
| | | public void SetOkCount(int count) |
| | |
| | | |
| | | private void SetStationGlobal_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | |
| | | } |
| | | |
| | | private void StartSingleClick(object sender, RoutedEventArgs e) |
| | | { |
| | | if (IsTesting) |
| | | { |
| | | if (MsgBoxHelper2.WarnChoose($"确实停止老化炉[{title}]的测试吗") == MessageBoxResult.OK) |
| | | { |
| | | parent.SetStartFlag(this.index, false); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ClearChartData(); |
| | | parent.SetStartFlag(this.index, true); |
| | | } |
| | | } |
| | | |
| | | private void ScanWindow_Click(object sender, RoutedEventArgs e) |
| | |
| | | |
| | | if (scanner != null) |
| | | { |
| | | scanner.Activate(); |
| | | scanner.ShowDialog(); |
| | | } |
| | | else |
| | | { |
| | | scanner = new Scanner(this.lang("Tr.ScanTitle", title)) |
| | | { |
| | | Owner = Window.GetWindow(this), |
| | | Tag = title |
| | | }; |
| | | scanner.FinishBarcode += Scanner_FinishBarcode; |
| | | scanner.ComplateClick += Scanner_ComplateClick; ; |
| | | scanner.Closed += Scanner_Closed; |
| | | scanner.Show(); |
| | | scanner.ShowDialog(); |
| | | } |
| | | } |
| | | |
| | | private void Scanner_ComplateClick(object sender, RoutedEventArgs e) |
| | | { |
| | | string paramName = $"StationState.Scanner[{index}]"; |
| | | parent.engine.Globals.SetValBoolean(paramName, 1, true); |
| | | //parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | |
| | | private void Scanner_Closed(object sender, EventArgs e) |
| | |
| | | private void Scanner_FinishBarcode(object sender, BarcodeEventArg e) |
| | | { |
| | | if (parent.SequenceContext == null) return; |
| | | CellInfo cellInfo = codeParser.GetCellInfoByCode(e.positionCode); |
| | | |
| | | string paramName = $"StationState.StartScanner_{title}"; |
| | | parent.engine.Globals.SetValBoolean(paramName, 0, true); |
| | | CellInfo cellInfo = codeParser.GetCellInfoByCode(e.positionCode); |
| | | string positionCode = e.positionCode, snrCode = e.snrCode; |
| | | //TODO 需要增加条码校验功能 |
| | | |
| | | //将读到的条码写入到SN中 |
| | | int dutNo = Convert.ToInt16(positionCode.Split('-')[2]) - 1; |
| | | dutNo = this.index * this.cellCount + dutNo; |
| | | int dutNo = this.index * this.cellCount + cellInfo.Index; |
| | | |
| | | string LookupStr = $"StationState.SN[{dutNo}]"; |
| | | ViewControl.Logger.Info($"PositionCode: [{e.positionCode}], SNR: [{e.snrCode}], LookUpStr: [{LookupStr}]"); |
| | | |
| | | parent.engine.Globals.SetValString(LookupStr, 0, snrCode); |
| | | ViewControl.Logger.Debug($"PositionCode: [{e.positionCode}], SNR: [{e.snrCode}], LookUpStr: [{LookupStr}]"); |
| | | ViewControl.Logger.Debug($"OvenName: [{cellInfo.OvenName}], CellIndex: [{cellInfo.Index}]"); |
| | | var cell = parent.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index); |
| | | if (snrCode == null) |
| | | { |
| | | string oldLookUp = $"StationState.SN[{e.oldIndex}]"; |
| | | var oldCellInfo = codeParser.GetCellInfoByCode(e.oldPosition); |
| | | var oldCell = parent.nameTables[oldCellInfo.OvenName].GetSingleCell(oldCellInfo.Index); |
| | | if (oldCell.status != "hadCode") |
| | | { |
| | | throw new Exception($"穴位[{e.oldPosition}]当前不允许清除条码!"); |
| | | } |
| | | // 移除条码 |
| | | parent.engine.Globals.SetValString(oldLookUp, 1, ""); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | string code = parent.engine.Globals.GetValString(LookupStr, 0); |
| | | |
| | | oldCell.SetStatus("waiting"); |
| | | oldCell.sn = ""; |
| | | return; |
| | | } |
| | | |
| | | /// 清掉上个条码的记录 |
| | | var lastSn = cell.sn; |
| | | if (!string.IsNullOrEmpty(lastSn)) |
| | | { |
| | | Scanner.RemoveSNR(lastSn); |
| | | } |
| | | |
| | | // 写入条码 |
| | | parent.engine.Globals.SetValString(LookupStr, 1, snrCode); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | |
| | | parent.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).SetStatus("hadCode"); |
| | | parent.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).sn = snrCode; |
| | | Scanner.InsertNewCode(snrCode, positionCode, dutNo); |
| | | } |
| | | |
| | | |
| | |
| | | /// </summary> |
| | | private void StartTcpServer() |
| | | { |
| | | var serverConfig = new ServerConfig() |
| | | { |
| | | MaxRequestLength = 1024 * 1024, |
| | | Port = config.PortStart + index |
| | | }; |
| | | try |
| | | { |
| | | if (tcpServer == null) |
| | | { |
| | | tcpServer = new TcpServer(); |
| | | tcpServer.NewRequestReceived += TcpServer_NewRequestReceived; |
| | | if (!tcpServer.Setup(config.PortStart + index)) |
| | | if (!tcpServer.Setup(serverConfig)) |
| | | { |
| | | ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.SettingFailed")); |
| | | return; |
| | |
| | | } |
| | | else if (tcpServer.State != SuperSocket.SocketBase.ServerState.Running) |
| | | { |
| | | if (!tcpServer.Setup(config.PortStart + index)) |
| | | if (!tcpServer.Setup(serverConfig)) |
| | | { |
| | | ChangeTcpServerStatus("ERROR", this.lang("Tr.TcpServer.SettingFailed")); |
| | | return; |
| | |
| | | /// </summary> |
| | | public void RelaseResource() |
| | | { |
| | | testTimeTimer?.Stop(); |
| | | StopTcpServer(); |
| | | } |
| | | |
| | |
| | | private void TcpServer_NewRequestReceived(TcpSession session, StringRequestInfo requestInfo) |
| | | { |
| | | string msg = requestInfo.Body; |
| | | //ViewControl.Logger.Info($"TCP Data From {session.RemoteEndPoint}: {msg}."); |
| | | ViewControl.Logger.Debug($"TCP Data From {session.RemoteEndPoint}: {msg}."); |
| | | string[] datas_10015 = msg.Split(';'); |
| | | int cellIndex = int.Parse(datas_10015[1]); |
| | | |
| | |
| | | { |
| | | step = values[0], |
| | | value = values[1], |
| | | result = values[2], |
| | | range = values[3], |
| | | condition = values[4], |
| | | updateTime = values[5] |
| | | limitUp = values[2], |
| | | limitDown = values[3], |
| | | unit = values[4], |
| | | result = values[5], |
| | | updateTime = values[6] |
| | | }); |
| | | //session.Send("1"); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | public void ClearVData() |
| | | { |
| | | foreach (var cell in cells) |
| | | { |
| | | cell.ClearVData(); |
| | | } |
| | | } |
| | | |
| | | private void Button_Click_1(object sender, RoutedEventArgs e) |
| | | { |
| | | ScannerSetting setting = new ScannerSetting() |
| | |
| | | |
| | | private void ClearAllSnr_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | var str = $"StationState.Start_{title}"; |
| | | var str = $"StationState.DoorClose[{index}]"; |
| | | if (parent.engine.Globals.GetValBoolean(str, 0) == true) |
| | | { |
| | | MsgBoxHelper.Error(Window.GetWindow(this), "程序运行中,不能清空条码"); |
| | |
| | | { |
| | | try |
| | | { |
| | | for (int i = 0; i < this.cellCount; i++) |
| | | { |
| | | int dutNo = this.index * this.cellCount + i; |
| | | string LookupStr = $"StationState.SN[{dutNo}]"; |
| | | parent.engine.Globals.SetValString(LookupStr, 0, ""); |
| | | GetSingleCell(i).SetStatus("waiting"); |
| | | } |
| | | ClearAllSN(); |
| | | ToastHelper.Success(LangUtil.Get("App.DeleteSuccess")); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | } |
| | | } |
| | | |
| | | public void ClearAllSN() |
| | | { |
| | | for (int i = 0; i < this.cellCount; i++) |
| | | { |
| | | ClearCellSN(i); |
| | | } |
| | | } |
| | | |
| | | public void TryClearCellSN(int cellIndex) |
| | | { |
| | | var str = $"StationState.DoorClose[{this.index}]"; |
| | | if (parent.engine.Globals.GetValBoolean(str, 0) == true) |
| | | { |
| | | MsgBoxHelper.Error(Window.GetWindow(this), "程序运行中,不能清空条码"); |
| | | return; |
| | | } |
| | | ClearCellSN(cellIndex); |
| | | } |
| | | |
| | | private void ClearCellSN(int index) |
| | | { |
| | | var cell = GetSingleCell(index); |
| | | int dutNo = this.index * this.cellCount + index; |
| | | string LookupStr = $"StationState.SN[{dutNo}]"; |
| | | var lastSN = cell.sn; |
| | | cell.sn = ""; |
| | | cell.SetStatus("waiting"); |
| | | parent.engine.Globals.SetValString(LookupStr, 1, ""); |
| | | parent.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | if (!string.IsNullOrEmpty(lastSN)) Scanner.RemoveSNR(lastSN); |
| | | } |
| | | |
| | | private void Button_Click_2(object sender, RoutedEventArgs e) |
| | | { |
| | | if (MsgBoxHelper.WarnMessage(Window.GetWindow(this), "确定要停止该炉位的老化测试吗?") == MessageBoxResult.OK) |
| | |
| | | <DataTrigger Binding="{Binding status}" Value="ready"> |
| | | <Setter Property="Background" Value="#FF08FF00"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding status}" Value="abort"> |
| | | <Setter Property="Background" Value="Black"/> |
| | | <Setter Property="Foreground" Value="White"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Label.Style> |
| | |
| | | InteropOwnersMask="False" |
| | | Topmost="False" |
| | | Loaded="Window_Loaded" |
| | | SizeToContent="Height" |
| | | Unloaded="Window_Unloaded" |
| | | SizeChanged="Window_SizeChanged" |
| | | pu:WindowXModalDialog.Buttons="{x:Null}" |
| | | Title="{Binding title}" Height="500" Width="800"> |
| | | Title="{Binding title}" Width="800" Height="825"> |
| | | <Grid x:Name="mainGrid"> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="500"/> |
| | | <RowDefinition Height="150"/> |
| | | <RowDefinition Height="150"/> |
| | | <RowDefinition Height="25"/> |
| | | </Grid.RowDefinitions> |
| | | <DataGrid ItemsSource="{Binding dataSource}" AutoGenerateColumns="False" |
| | | CanUserAddRows="False" |
| | |
| | | </DataTemplate> |
| | | </DataGridTemplateColumn.CellTemplate> |
| | | </DataGridTemplateColumn>--> |
| | | <DataGridTextColumn Header="测试项名称" Binding="{Binding step}"/> |
| | | <DataGridTextColumn Header="测试项" Binding="{Binding step}"/> |
| | | <DataGridTextColumn Header="测试值" Binding="{Binding value}"/> |
| | | <DataGridTextColumn Header="上限" Binding="{Binding limitUp}"/> |
| | | <DataGridTextColumn Header="下限" Binding="{Binding limitDown}"/> |
| | | <DataGridTextColumn Header="单位" Binding="{Binding unit}"/> |
| | | <DataGridTextColumn Header="测试结果" Binding="{Binding result}"/> |
| | | <DataGridTextColumn Header="测试范围" Binding="{Binding range}"/> |
| | | <DataGridTextColumn Header="测试条件" Binding="{Binding condition}"/> |
| | | <DataGridTextColumn Header="更新时间" Binding="{Binding updateTime}"/> |
| | | </DataGrid.Columns> |
| | | </DataGrid> |
| | | |
| | | <Grid Background="#f1eded" Grid.Row="2" Height="25"> |
| | | <Grid Background="#f1eded" Grid.Row="3"> |
| | | <DockPanel> |
| | | <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" Margin="0,0,30,0"> |
| | | <Label Padding="0" FontSize="12" |
| | |
| | | set => Set(ref _dataSource, value); |
| | | } |
| | | private Chart electricChart; |
| | | public InfoWindow(string title, ObservableCollection<Info> infos, Chart electricChart, int probeCount) |
| | | private Chart vChart; |
| | | public InfoWindow(string title, ObservableCollection<Info> infos, Chart electricChart, Chart vChart, int probeCount) |
| | | { |
| | | this.title = title; |
| | | this.dataSource = infos; |
| | |
| | | this.electricChart = electricChart; |
| | | mainGrid.Children.Add(electricChart); |
| | | Grid.SetRow(electricChart, 1); |
| | | |
| | | this.vChart = vChart; |
| | | mainGrid.Children.Add(vChart); |
| | | Grid.SetRow(vChart, 2); |
| | | } |
| | | |
| | | private static int AlarmProbeCount; |
| | |
| | | protected override void OnClosed(EventArgs e) |
| | | { |
| | | electricChart = null; |
| | | vChart = null; |
| | | mainGrid.Children.Clear(); |
| | | base.OnClosed(e); |
| | | } |
| | | |
| | | private void Window_SizeChanged(object sender, SizeChangedEventArgs e) |
| | | { |
| | | if (electricChart != null) |
| | | { |
| | | electricChart.Height = this.ActualHeight * 0.3; |
| | | } |
| | | //if (electricChart != null) |
| | | //{ |
| | | // electricChart.Height = this.ActualHeight * 0.3; |
| | | //} |
| | | } |
| | | |
| | | private void Button_Click(object sender, RoutedEventArgs e) |
| | |
| | | } |
| | | } |
| | | |
| | | private string codeParserType; |
| | | public string CodeParserType |
| | | { |
| | | get |
| | | { |
| | | var data = GetValue(); |
| | | return data == null ? codeParserType : data.ToString(); |
| | | } |
| | | } |
| | | |
| | | public bool testing = false; |
| | | } |
| | | } |
| | |
| | | set => RaiseAndSetIfchanged(ref _value, value); |
| | | } |
| | | |
| | | private string _unit; |
| | | |
| | | public string unit |
| | | { |
| | | get => _unit; |
| | | |
| | | set => RaiseAndSetIfchanged(ref _unit, value); |
| | | } |
| | | |
| | | private string _result; |
| | | |
| | | public string result |
| | |
| | | set => RaiseAndSetIfchanged(ref _result, value); |
| | | } |
| | | |
| | | private string _range; |
| | | private string _limitDown; |
| | | |
| | | public string range |
| | | public string limitDown |
| | | { |
| | | get => _range; |
| | | get => _limitDown; |
| | | |
| | | set => RaiseAndSetIfchanged(ref _range, value); |
| | | set => RaiseAndSetIfchanged(ref _limitDown, value); |
| | | } |
| | | |
| | | private string _condition; |
| | | private string _limitUp; |
| | | |
| | | public string condition |
| | | public string limitUp |
| | | { |
| | | get => _condition; |
| | | get => _limitUp; |
| | | |
| | | set => RaiseAndSetIfchanged(ref _condition, value); |
| | | set => RaiseAndSetIfchanged(ref _limitUp, value); |
| | | } |
| | | |
| | | private string _updateTime; |
| | |
| | | <Compile Include="ScannerSetting.xaml.cs"> |
| | | <DependentUpon>ScannerSetting.xaml</DependentUpon> |
| | | </Compile> |
| | | <Compile Include="Util\ICodeParser.cs" /> |
| | | <Compile Include="Util\JKCodeParser.cs" /> |
| | | <Compile Include="Util\CommonCodeParser.cs" /> |
| | | <Compile Include="Util\FontSizeConverter.cs" /> |
| | | <Compile Include="ViewControl.xaml.cs"> |
| | |
| | | <Project>{736cd77d-b81e-4866-bb00-84b0b57110f0}</Project> |
| | | <Name>HMI.ParameterManage</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.StdControl\HMI.StdControl.csproj"> |
| | | <Project>{7a066856-182f-4435-b648-e9fb91aff657}</Project> |
| | | <Name>HMI.StdControl</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.UI\HMI.UI.csproj"> |
| | | <Project>{f17de6b5-af1d-48c6-94a0-6b763a6546a6}</Project> |
| | | <Name>HMI.UI</Name> |
| | |
| | | <Name>Plugin.TsSupport</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Resource Include="Resource\abort.png" /> |
| | | </ItemGroup> |
| | | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
| | | <Import Project="..\WPFProject\packages\HarfBuzzSharp.NativeAssets.macOS.7.3.0.3\build\net462\HarfBuzzSharp.NativeAssets.macOS.targets" Condition="Exists('..\WPFProject\packages\HarfBuzzSharp.NativeAssets.macOS.7.3.0.3\build\net462\HarfBuzzSharp.NativeAssets.macOS.targets')" /> |
| | | <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> |
| | |
| | | // [assembly: AssemblyVersion("1.0.*")] |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.0")] |
| | | [assembly: PluginClassName("Plugin.TestResult_WPF.ViewControl")] |
| | |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:cc="clr-namespace:HMI.Core;assembly=HMI.Core" |
| | | InteropOwnersMask="False" |
| | | InteropOwnersMask="True" |
| | | SizeToContent="Height" |
| | | pu:WindowXModalDialog.Buttons="{x:Null}" |
| | | Title="{Binding title}" Width="600"> |
| | |
| | | Header="{DynamicResource Tr.PositionSnr}" |
| | | dp:FormGroupHelper.IsRequired="True" |
| | | Style="{StaticResource InputFormGroupStyle}"> |
| | | <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="positionText" TextWrapping="NoWrap"/> |
| | | <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="positionText" TextWrapping="NoWrap" KeyDown="TextBox_KeyDown"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup |
| | | Header="{DynamicResource Tr.ProductSnr}" |
| | | dp:FormGroupHelper.IsRequired="True" Style="{StaticResource InputFormGroupStyle}"> |
| | | <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="snrText" TextWrapping="NoWrap"/> |
| | | <TextBox Style="{StaticResource EditorTextBoxStyle}" x:Name="snrText" TextWrapping="NoWrap" KeyDown="TextBox_KeyDown"/> |
| | | </pu:FormGroup> |
| | | </StackPanel> |
| | | |
| | | </GroupBox> |
| | | |
| | | <Button Grid.Row="2" Click="Con_Click" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.ContinueScan}"/> |
| | | <Button Grid.Row="2" Grid.Column="1" Click="Ok_Click" Style="{StaticResource SuccessButton}" |
| | | <!--<Button Grid.Row="2" Click="Con_Click" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.ContinueScan}"/>--> |
| | | <Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Click="Ok_Click" Style="{StaticResource SuccessButton}" |
| | | Content="{DynamicResource Tr.FinishScan}"/> |
| | | </Grid> |
| | | </pu:WindowX> |
| | |
| | | using HMI.Core.Util; |
| | | using HMI.UI.MDI; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Panuon.WPF.UI; |
| | | using Plugin.TestResult.Model; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.ComponentModel; |
| | | using System.IO.Ports; |
| | | using System.Windows; |
| | | using System.Windows.Input; |
| | | |
| | | namespace Plugin.TestResult_WPF |
| | | { |
| | |
| | | public string name { get; private set; } |
| | | public string positionCode { get; private set; } |
| | | public string snrCode { get; private set; } |
| | | public string oldPosition { get; private set; } |
| | | public int oldIndex { get; private set; } |
| | | |
| | | public BarcodeEventArg(string name, string positionCode, string snrCode) |
| | | public BarcodeEventArg(string name, string positionCode, string snrCode, string oldPosition, int oldIndex) |
| | | { |
| | | this.name = name; |
| | | this.positionCode = positionCode; |
| | | this.snrCode = snrCode; |
| | | this.oldPosition = oldPosition; |
| | | this.oldIndex = oldIndex; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | public event EventHandler<BarcodeEventArg> FinishBarcode; |
| | | public event EventHandler<RoutedEventArgs> ComplateClick; |
| | | |
| | | private static Dictionary<string, string> snrCache = new Dictionary<string, string>(); |
| | | private static Dictionary<string, int> snrIndex = new Dictionary<string, int>(); |
| | | |
| | | private DataTable dataTable; |
| | | SerialPort serialPort; |
| | |
| | | } |
| | | } |
| | | |
| | | public static void InsertNewCode(string snr, string position, int index) |
| | | { |
| | | snrCache[snr] = position; |
| | | snrIndex[snr] = index; |
| | | } |
| | | |
| | | public static void RemoveSNR(string snr) |
| | | { |
| | | snrCache.Remove(snr); |
| | | snrIndex.Remove(snr); |
| | | } |
| | | |
| | | private void SendCode(string tag, string position, string snr) |
| | | { |
| | | if (snrCache.ContainsKey(snr)) |
| | | { |
| | | var oldPosition = snrCache[snr]; |
| | | if (MsgBoxHelper2.WarnChoose($"条码[{snr}]已放置于[{oldPosition}]中,是否清除?") == MessageBoxResult.OK) |
| | | { |
| | | try |
| | | { |
| | | FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, null, oldPosition, snrIndex[snr])); |
| | | snrCache.Remove(snr); |
| | | snrIndex.Remove(snr); |
| | | FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, snr, null, -1)); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ToastHelper.Error(ex.Message); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | FinishBarcode.Invoke(this, new BarcodeEventArg(tag, position, snr, null, -1)); |
| | | } |
| | | } |
| | | |
| | | private void Con_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | Dispatcher.Invoke(() => |
| | |
| | | } |
| | | try |
| | | { |
| | | FinishBarcode.Invoke(this, new BarcodeEventArg(Tag.ToString(), position, snr)); |
| | | //positionText.Text = ""; |
| | | //snrText.Text = ""; |
| | | SendCode(Tag.ToString(), position, snr); |
| | | positionText.Text = ""; |
| | | snrText.Text = ""; |
| | | positionText.Focus(); |
| | | } |
| | | catch (Exception ex) |
| | |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 原来的完成扫描逻辑 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | //private void Ok_Click(object sender, RoutedEventArgs e) |
| | | //{ |
| | | // string position = positionText.Text, snr = snrText.Text; |
| | | // if (string.IsNullOrEmpty(position) || string.IsNullOrEmpty(snr)) |
| | | // { |
| | | // ToastHelper.Warning(this, this.lang("Tr.PleaseInputSnrs")); |
| | | // return; |
| | | // } |
| | | // try |
| | | // { |
| | | // SendCode(Tag.ToString(), position, snr); |
| | | // this.Close(); |
| | | // } |
| | | // catch (Exception ex) |
| | | // { |
| | | // ViewControl.Logger.Error("Con_Click Failed.", ex); |
| | | // ToastHelper.Warning(this, ex.Message); |
| | | // } |
| | | //} |
| | | |
| | | private void Ok_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | string position = positionText.Text, snr = snrText.Text; |
| | | if (string.IsNullOrEmpty(position) || string.IsNullOrEmpty(snr)) |
| | | { |
| | | ToastHelper.Warning(this, this.lang("Tr.PleaseInputSnrs")); |
| | | return; |
| | | } |
| | | try |
| | | { |
| | | FinishBarcode.Invoke(this, new BarcodeEventArg(Tag.ToString(), position, snr)); |
| | | ComplateClick?.Invoke(this, e); |
| | | this.Close(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ViewControl.Logger.Error("Con_Click Failed.", ex); |
| | | ToastHelper.Warning(this, ex.Message); |
| | | } |
| | | } |
| | | |
| | | private string ReadDataFrom(SerialPort sp) |
| | |
| | | { |
| | | byte[] buffer = new byte[sp.BytesToRead]; |
| | | sp.Read(buffer, 0, buffer.Length); |
| | | barcode += System.Text.Encoding.UTF8.GetString(buffer); |
| | | barcode += System.Text.Encoding.ASCII.GetString(buffer); |
| | | System.Threading.Thread.Sleep(50); |
| | | } |
| | | return barcode; |
| | |
| | | { |
| | | } |
| | | } |
| | | |
| | | private void TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) |
| | | { |
| | | if (e.Key == Key.Enter) |
| | | { |
| | | //string barcode = |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | if (snrText.IsFocused) |
| | | { |
| | | Con_Click(null, null); |
| | | } |
| | | else |
| | | { |
| | | snrText.Focus(); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | mc:Ignorable="d" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | x:Name="uc" |
| | | Padding="5" |
| | | MouseDoubleClick="UserControl_MouseDoubleClick" |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <UserControl.Resources> |
| | |
| | | |
| | | <UserControl.ContextMenu> |
| | | <ContextMenu> |
| | | <MenuItem IsCheckable="True" IsChecked="{Binding CellIsDisabled,Mode=TwoWay}" Header="禁用"/> |
| | | <!--<MenuItem IsCheckable="True" IsChecked="{Binding CellIsDisabled,Mode=TwoWay}" Header="禁用"/>--> |
| | | <MenuItem IsCheckable="False" x:Name="clearSNRItem" Click="MenuItem_Click" Header="清除条码"/> |
| | | </ContextMenu> |
| | | </UserControl.ContextMenu> |
| | | |
| | |
| | | <DataTrigger Binding="{Binding status}" Value="hadCode"> |
| | | <Setter Property="Background" Value="#FFF"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding status}" Value="abort"> |
| | | <Setter Property="Background" Value="Black"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </UserControl.Style> |
| | | <Grid> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition Height="18"/> |
| | | </Grid.RowDefinitions> |
| | | <Grid.ColumnDefinitions> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition/> |
| | | <ColumnDefinition Width="Auto"/> |
| | | </Grid.ColumnDefinitions> |
| | | <!--<TextBox Grid.Row="0" IsReadOnly="True" TextAlignment="Center" Margin="0,0,0,3" FontSize="15" |
| | | Background="Transparent" BorderThickness="0" Text="{Binding title}"/>--> |
| | | <Label Grid.Column="0" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Padding="0" Margin="0" |
| | | <StackPanel Orientation="Horizontal" Background="LightGray" Grid.Row="1" Grid.Column="1" VerticalAlignment="Top" HorizontalAlignment="Right"> |
| | | <TextBlock Foreground="Red" Text="探针预警"> |
| | | <TextBlock.Style> |
| | | <Style TargetType="TextBlock"> |
| | | <Setter Property="Visibility" Value="Collapsed"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding probeAlarm}" Value="True"> |
| | | <Setter Property="Visibility" Value="Visible"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </TextBlock.Style> |
| | | </TextBlock> |
| | | <TextBlock Margin="0"> |
| | | <Run Text="{Binding ProbeCount}"/> |
| | | <Run Text="/"/> |
| | | <Run Text="{Binding probeWarn}"/> |
| | | </TextBlock> |
| | | </StackPanel> |
| | | <Label Grid.Row="0" Grid.Column="0" HorizontalContentAlignment="Left" VerticalContentAlignment="Top" Padding="0" Margin="5,5,0,0" |
| | | FontSize="{Binding ActualWidth,RelativeSource={RelativeSource AncestorType=UserControl}, |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='15,103'}" |
| | | Converter={StaticResource FontSizeConverter}, ConverterParameter='8,103'}" |
| | | FontWeight="Bold" |
| | | Background="Transparent" BorderThickness="0" Content="{Binding title}"/> |
| | | <Image Grid.Column="1"> |
| | | Background="Transparent" BorderThickness="0" Content="{Binding title}"> |
| | | <Label.Style> |
| | | <Style TargetType="Label"> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding status}" Value="abort"> |
| | | <Setter Property="Foreground" Value="#FFF"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Label.Style> |
| | | </Label> |
| | | <ui:ScrollLabel Grid.Row="1" Grid.Column="0" Margin="3,0,0,5" Padding="0" Value="{Binding sn}"/> |
| | | |
| | | <Image Grid.Row="0" Grid.Column="1" Width="30" HorizontalAlignment="Right" Height="30" Margin="0,5,5,0"> |
| | | <Image.Style> |
| | | <Style TargetType="Image"> |
| | | <Setter Property="HorizontalAlignment" Value="Center"/> |
| | | <Setter Property="VerticalAlignment" Value="Bottom"/> |
| | | <Setter Property="VerticalAlignment" Value="Top"/> |
| | | <Style.Triggers> |
| | | <DataTrigger Binding="{Binding status}" Value="ok"> |
| | | <Setter Property="Source" Value="Resource/ok2.png"/> |
| | |
| | | <DataTrigger Binding="{Binding status}" Value="hadCode"> |
| | | <Setter Property="Source" Value="Resource/barcode.png"/> |
| | | </DataTrigger> |
| | | <DataTrigger Binding="{Binding status}" Value="abort"> |
| | | <Setter Property="Source" Value="Resource/abort.png"/> |
| | | </DataTrigger> |
| | | </Style.Triggers> |
| | | </Style> |
| | | </Image.Style> |
| | |
| | | using HMI.Util; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Util; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using Plugin.TestResult_WPF.Constant; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using System; |
| | |
| | | private InfoWindow window; |
| | | private int maxSize; |
| | | |
| | | private static string dataLogPath; |
| | | private static int ProbeWarn; |
| | | |
| | | static SingleCell() |
| | | { |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName("TS_DataLogPath"); |
| | | dataLogPath = value?.Value ?? Path.Combine(PathHelper.ConfigFolder, "DataBoard"); |
| | | } |
| | | catch |
| | | { |
| | | dataLogPath = Path.Combine(PathHelper.ConfigFolder, "DataBoard"); |
| | | } |
| | | |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName("ProbeWarn"); |
| | | ProbeWarn = value != null ? int.Parse(value.Value) : 1000; |
| | | } |
| | | catch |
| | | { |
| | | ProbeWarn = 1000; |
| | | } |
| | | } |
| | | |
| | | public SingleCell() |
| | | { |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | } |
| | | |
| | | public SingleCell(string parentName, int index, int maxSize, string iniFile) |
| | | private DataTable table; |
| | | |
| | | public SingleCell(DataTable table, string title, int index, int maxSize, string iniFile) |
| | | { |
| | | this.parentName = parentName; |
| | | this.table = table; |
| | | this.title = title; |
| | | this.index = index; |
| | | this.maxSize = maxSize; |
| | | this.countIniPath = iniFile; |
| | | this.probeWarn = ProbeWarn; |
| | | DataContext = this; |
| | | InitializeComponent(); |
| | | LoadProbeCount(); |
| | | } |
| | | |
| | | private string _parentName; |
| | | public string parentName |
| | | private string _sn; |
| | | public string sn |
| | | { |
| | | get { return _parentName; } |
| | | get { return _sn; } |
| | | set |
| | | { |
| | | RaiseAndSetIfchanged(ref _parentName, value); |
| | | RaisePropertyChanged("title"); |
| | | RaiseAndSetIfchanged(ref _sn, value); |
| | | RaisePropertyChanged("sn"); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private string _title; |
| | | public string title |
| | | { |
| | | get => _title; |
| | | set |
| | | { |
| | | RaiseAndSetIfchanged(ref _title, value); |
| | | } |
| | | } |
| | | |
| | | public string title => $"{parentName}-{index + 1}"; |
| | | private int _probeWarn; |
| | | public int probeWarn |
| | | { |
| | | get => _probeWarn; |
| | | set |
| | | { |
| | | RaiseAndSetIfchanged(ref _probeWarn, value); |
| | | } |
| | | } |
| | | |
| | | private string _status = CommonStatus.WAITING; |
| | | |
| | |
| | | |
| | | private ConcurrentQueue<Info> queue = new ConcurrentQueue<Info>(); |
| | | |
| | | private List<Info> allInfos = new List<Info>(); |
| | | |
| | | private ObservableCollection<Info> _infos = new ObservableCollection<Info>(); |
| | | |
| | | public ObservableCollection<Info> infos |
| | |
| | | set |
| | | { |
| | | RaiseAndSetIfchanged(ref probeCount, value); |
| | | probeAlarm = value >= probeWarn; |
| | | } |
| | | } |
| | | |
| | | private bool _probeAlarm; |
| | | public bool probeAlarm |
| | | { |
| | | get => _probeAlarm; |
| | | set |
| | | { |
| | | RaiseAndSetIfchanged(ref _probeAlarm, value); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | if (window == null) |
| | | { |
| | | window = new InfoWindow(title, infos, electricChart, ProbeCount); |
| | | window = new InfoWindow(title, infos, electricChart, vChart, ProbeCount); |
| | | window.Closed += Window_Closed; |
| | | window.ClearProbeCountEvent += Window_ClearProbeCountEvent; |
| | | window.Owner = Window.GetWindow(this); |
| | |
| | | |
| | | public void SetStatus(string status) |
| | | { |
| | | var oldStatus = this.status; |
| | | this.status = status; |
| | | if (status == "testing") |
| | | if (oldStatus != "testing" && status == "testing") |
| | | { |
| | | UpdateProbeCount(ProbeCount + 1); |
| | | } |
| | |
| | | |
| | | public void SetInfos(Info info) |
| | | { |
| | | allInfos.Add(info); |
| | | if (queue.Count >= maxSize) |
| | | { |
| | | queue.TryDequeue(out var first); |
| | |
| | | |
| | | public void ClearInfo() |
| | | { |
| | | allInfos.Clear(); |
| | | queue = new ConcurrentQueue<Info>(); |
| | | var list = new ObservableCollection<Info>(queue); |
| | | this.infos = list; |
| | | if (window != null) window.UpdateSource(this.infos); |
| | | } |
| | | |
| | | private Chart electricChart = new Chart("电流曲线(A)", false, 20); |
| | | private Chart electricChart = new Chart("电流曲线(A)", false, 20) |
| | | { |
| | | Height = 150 |
| | | }; |
| | | |
| | | public void AddElectricData(double data) |
| | | { |
| | | electricChart.AddData(data); |
| | |
| | | public void ClearElectricData() |
| | | { |
| | | electricChart.Clear(); |
| | | } |
| | | |
| | | private Chart vChart = new Chart("电压曲线(V)", false, 20) |
| | | { |
| | | Height = 150 |
| | | }; |
| | | |
| | | public void AddVData(double data) |
| | | { |
| | | vChart.AddData(data); |
| | | } |
| | | |
| | | public void ClearVData() |
| | | { |
| | | vChart.Clear(); |
| | | } |
| | | |
| | | public void SaveElectricDataToCSV(string filePath) |
| | |
| | | Console.WriteLine(ex.ToString()); |
| | | } |
| | | } |
| | | |
| | | public void SaveVDataToCSV(string filePath) |
| | | { |
| | | try |
| | | { |
| | | List<double> datas = vChart?.GetSingleData(); |
| | | |
| | | FileInfo fi = new FileInfo(filePath); |
| | | if (!fi.Directory.Exists) |
| | | { |
| | | fi.Directory.Create(); //文件不存在,创建文件 |
| | | } |
| | | |
| | | using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) |
| | | using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8)) |
| | | { |
| | | string title = "电压数据(V)"; |
| | | sw.WriteLine(title); |
| | | if (datas != null) |
| | | { |
| | | for (int i = 0; i < datas.Count; i++) |
| | | { |
| | | sw.WriteLine(datas[i].ToString()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Console.WriteLine(ex.ToString()); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 保存测试数据到CSV |
| | | /// </summary> |
| | | /// <param name="filePath"></param> |
| | | public void SaveInfoToCSV(string filePath) |
| | | { |
| | | try |
| | | { |
| | | FileInfo fi = new FileInfo(filePath); |
| | | if (!fi.Directory.Exists) |
| | | { |
| | | fi.Directory.Create(); //文件不存在,创建文件 |
| | | } |
| | | |
| | | using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) |
| | | using (StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.UTF8)) |
| | | { |
| | | string title = "测试项,测试值,下限,上限,单位,结果,测试时间"; |
| | | sw.WriteLine(title); |
| | | foreach (var info in allInfos) |
| | | { |
| | | string row = $"{info.step},{info.value},{info.limitDown},{info.limitUp},{info.unit},{info.result},{info.updateTime}"; |
| | | sw.WriteLine(row); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ViewControl.Logger.Error($"Cell[{title}] SaveInfoToCSV Error.", ex); |
| | | } |
| | | } |
| | | |
| | | private SqliteHelper CheckSqlHelper() |
| | | { |
| | | string today = DateTime.Now.ToString("yyyyMMdd"); |
| | | string dbPath = Path.Combine(dataLogPath, $"Data_{today}.db"); |
| | | if (!File.Exists(dbPath)) |
| | | { |
| | | SqliteHelper.CreateDatabase(dbPath); |
| | | } |
| | | var sqliteHelper = new SqliteHelper(dbPath); |
| | | sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS serialData ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | sn TEXT NOT NULL, |
| | | model TEXT, |
| | | station TEXT NOT NULL, |
| | | step TEXT NOT NULL, |
| | | position TEXT, |
| | | limitDown TEXT, |
| | | limitUp TEXT, |
| | | unit TEXT, |
| | | offset TEXT, |
| | | value TEXT, |
| | | status TEXT, |
| | | finalStatus TEXT, |
| | | consumeTime TEXT, |
| | | totalConsumeTime TEXT, |
| | | time DATETIME NOT NULL);"); |
| | | sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS testResult ( |
| | | id INTEGER PRIMARY KEY AUTOINCREMENT, |
| | | sn TEXT NOT NULL, |
| | | model TEXT, |
| | | station TEXT NOT NULL, |
| | | position TEXT, |
| | | status TEXT, |
| | | result TEXT NOT NULL, |
| | | time DATETIME NOT NULL);"); |
| | | return sqliteHelper; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 保存测试数据到Sqlite |
| | | /// </summary> |
| | | /// <param name="filePath"></param> |
| | | public void SaveInfoToDB() |
| | | { |
| | | try |
| | | { |
| | | using (var helper = CheckSqlHelper()) |
| | | { |
| | | List<string> sqls = new List<string>(); |
| | | var timestr = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | foreach (var info in allInfos) |
| | | { |
| | | string sql = $@"INSERT INTO serialData (sn,station,step,limitDown,limitUp,unit,value,status,finalStatus,time) |
| | | VALUES ('{sn}','','{info.step}','{info.limitDown}','{info.limitUp}','{info.unit}','{info.value}','{info.result}','{this.status}','{timestr}');"; |
| | | sqls.Add(sql); |
| | | } |
| | | sqls.Add($"INSERT INTO testResult (sn,station,position,result,time) VALUES ('{sn}','','{title}','{this.status}','{timestr}');"); |
| | | helper.ExecuteBatchSql(sqls); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | ViewControl.Logger.Error($"Cell[{title}] SaveToDB Error.", ex); |
| | | } |
| | | } |
| | | |
| | | private void MenuItem_Click(object sender, RoutedEventArgs e) |
| | | { |
| | | var item = sender as MenuItem; |
| | | switch (item?.Name) |
| | | { |
| | | case "clearSNRItem": |
| | | table.TryClearCellSN(this.index); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | d:DesignHeight="450" d:DesignWidth="800"> |
| | | <Grid x:Name="panel"> |
| | | <WindowsFormsHost x:Name="host" Visibility="Collapsed"></WindowsFormsHost> |
| | | <Grid x:Name="mainGrid" dp:GridHelper.Space="10"> |
| | | <Grid x:Name="mainGrid" dp:GridHelper.Space="6"> |
| | | |
| | | </Grid> |
| | | </Grid> |
| | |
| | | using NationalInstruments.TestStand.Interop.API; |
| | | using NationalInstruments.TestStand.Interop.UI.Ax; |
| | | using NationalInstruments.TestStand.Utility; |
| | | using Plugin.TestResult_WPF.Constant; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using Plugin.TsSupport; |
| | | using System; |
| | |
| | | |
| | | private void Refresh() |
| | | { |
| | | for (int i = 0; i < tables.Length; i++) |
| | | { |
| | | var sb = new System.Timers.Timer() |
| | | { |
| | | Interval = 1000, |
| | | AutoReset = true, |
| | | }; |
| | | var table = tables[i]; |
| | | Random random = new Random(i * 13); |
| | | sb.Elapsed += (s, e) => |
| | | { |
| | | table.RefreshCount(1, 0); |
| | | table.SetTemperature(random.Next(100)); |
| | | for (int j = 0; j < 3; j++) |
| | | { |
| | | table.SetTemperature(j + "89", random.Next(100)); |
| | | } |
| | | //table.SetOkCount(random.Next(100)); |
| | | //table.SetNgCount(random.Next(100)); |
| | | table.SetStatus(CommonStatus.GetRandomStatus()); |
| | | table.SetStartTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | table.SetEndTime(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); |
| | | table.SetConsumeTime(random.Next(10000)); |
| | | tables[0].GetSingleCell(0).AddElectricData(random.Next(100)); |
| | | |
| | | var cell = tables[0].GetSingleCell(0);//table.GetSingleCell(random.Next(table.GetSize())); |
| | | cell.SetStatus(CommonStatus.GetRandomStatus()); |
| | | cell.SetInfos(new Info |
| | | { |
| | | step = random.Next(1000) + "", |
| | | value = random.Next(1000) + "" |
| | | }); |
| | | table.SetStatusText(DateTime.Now + ""); |
| | | }; |
| | | sb.Start(); |
| | | } |
| | | } |
| | | |
| | | private string CountIniPath; |
| | |
| | | { |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(testSeqFile)) return; |
| | | this.modeSeq = this.engine.GetSequenceFileEx(@"C:\Program Files\National Instruments\TestStand 2020\Components\Models\TestStandModels\ParallelModel.seq"); |
| | | this.testSeq = this.engine.GetSequenceFileEx(this.testSeqFile, 0, TypeConflictHandlerTypes.ConflictHandler_UseGlobalType); |
| | | this.execution = this.engine.NewExecution(this.testSeq, "Test UUTs", this.modeSeq, false, 0, null, null, null); |
| | |
| | | { |
| | | step = values[0], |
| | | value = values[1], |
| | | result = values[2], |
| | | range = values[3], |
| | | condition = values[4], |
| | | updateTime = values[5] |
| | | limitUp = values[2], |
| | | limitDown = values[3], |
| | | unit = values[4], |
| | | result = values[5], |
| | | updateTime = values[6] |
| | | }); |
| | | return; |
| | | } |
| | |
| | | } |
| | | if (MethodCode == 12) |
| | | { |
| | | /// 保存温度文件 |
| | | /// 保存炉体温度文件 |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | |
| | | } |
| | | if (MethodCode == 14) |
| | | { |
| | | /// 清空电流数据 |
| | | /// 清空电流和电压数据 |
| | | strData = e.uiMsg.StringData; |
| | | int ovenIndex = int.Parse(strData); |
| | | tables[ovenIndex].ClearElectricData(); |
| | | tables[ovenIndex].ClearVData(); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 15) |
| | | { |
| | | /// 清空电流数据 |
| | | /// 保存电流数据 |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | | int cellIndex = int.Parse(datas[1]); |
| | | string filePath = datas[2]; |
| | | tables[ovenIndex].GetSingleCell(cellIndex).SaveElectricDataToCSV(filePath); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 16) |
| | | { |
| | | /// 添加电压数据 |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | | int cellIndex = int.Parse(datas[1]); |
| | | double eData = double.Parse(datas[2]); |
| | | tables[ovenIndex].GetSingleCell(cellIndex).AddVData(eData); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 17) |
| | | { |
| | | /// 保存电压数据 |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | | int cellIndex = int.Parse(datas[1]); |
| | | string filePath = datas[2]; |
| | | tables[ovenIndex].GetSingleCell(cellIndex).SaveVDataToCSV(filePath); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 18) |
| | | { |
| | | /// 保存穴位测试数据到CSV |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | | int cellIndex = int.Parse(datas[1]); |
| | | string filePath = datas[2]; |
| | | tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToCSV(filePath); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 19) |
| | | { |
| | | /// 保存穴位测试数据到Sqlite |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int ovenIndex = int.Parse(datas[0]); |
| | | int cellIndex = int.Parse(datas[1]); |
| | | tables[ovenIndex].GetSingleCell(cellIndex).SaveInfoToDB(); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 20) |
| | | { |
| | | /// 清空条码 |
| | | strData = e.uiMsg.StringData; |
| | | int ovenIndex = int.Parse(strData); |
| | | tables[ovenIndex].ClearAllSN(); |
| | | return; |
| | | } |
| | | |
| | | if (MethodCode == 99) |
| | | { |
| | | strData = e.uiMsg.StringData; |
| | | string[] datas = strData.Split(';'); |
| | | int index = int.Parse(datas[0]); |
| | | if (MsgBoxHelper2.WarnChoose(datas[1], "提示") == MessageBoxResult.OK) |
| | | { |
| | | SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 1); |
| | | } |
| | | else |
| | | { |
| | | SequenceContext.StationGlobals.SetValNumber($"StationState.Pipe[{index}]", 1, 0); |
| | | } |
| | | return; |
| | | } |
| | | } |
| | |
| | | { |
| | | if (this.SequenceContext == null) return; |
| | | string name = tables[index].title; |
| | | string key = $"StationState.Start_{name}"; |
| | | string key = $"StationState.Start[{index}]"; |
| | | this.engine.Globals.SetValBoolean(key, 1, data); |
| | | //bool val = this.engine.Globals.GetValBoolean(key, 0); |
| | | //this.SequenceContext.StationGlobals.SetValBoolean(key, 0, data); |
| | |
| | | |
| | | public void SetCurrentProduct(string currentProduct) |
| | | { |
| | | foreach (var table in tables) |
| | | for (int i = 0; i < tables.Length; i++) |
| | | { |
| | | table.SetCurrentProduct(currentProduct); |
| | | var table = tables[i]; |
| | | // table.SetCurrentProduct(currentProduct); |
| | | string LookupStr = $"StationState.Model[{i}]"; |
| | | string tableModel = engine?.Globals?.GetValString(LookupStr, 1); |
| | | table.SetCurrentProduct(tableModel); |
| | | } |
| | | } |
| | | |
| | | public void SetOvenProduct(int index, string product) |
| | | { |
| | | string LookupStr = $"StationState.ProductModel_{tables[index].title}"; |
| | | string LookupStr = $"StationState.Model[{index}]"; |
| | | engine?.Globals?.SetValString(LookupStr, 1, product); |
| | | engine?.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | | } |
| | | } |
| | | } |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using System; |
| | | |
| | | namespace Plugin.TestResult_WPF.Util |
| | | { |
| | | public class CommonCodeParser |
| | | public class CommonCodeParser: ICodeParser |
| | | { |
| | | public CellInfo GetCellInfoByCode(string code) |
| | | { |
| New file |
| | |
| | | using Plugin.TestResult_WPF.Model; |
| | | |
| | | namespace Plugin.TestResult.Util |
| | | { |
| | | public interface ICodeParser |
| | | { |
| | | CellInfo GetCellInfoByCode(string code); |
| | | } |
| | | } |
| New file |
| | |
| | | using Plugin.TestResult.Util; |
| | | using Plugin.TestResult_WPF.Model; |
| | | using System; |
| | | |
| | | namespace Plugin.TestResult_WPF.Util |
| | | { |
| | | public class JKCodeParser : ICodeParser |
| | | { |
| | | public CellInfo GetCellInfoByCode(string code) |
| | | { |
| | | string[] arr = code.Split('-'); |
| | | if (arr == null || arr.Length != 3) |
| | | { |
| | | throw new Exception("扫码格式异常"); |
| | | } |
| | | int row = int.Parse(arr[1]); |
| | | int index = int.Parse(arr[2]); |
| | | |
| | | return new CellInfo() |
| | | { |
| | | OvenName = arr[0], |
| | | Index = (row - 1) * 4 + (index - 1), |
| | | }; |
| | | } |
| | | } |
| | | } |
| | |
| | | <hb:PluginMaskControl x:Class="Plugin.TestResult_WPF.ViewControl" |
| | | xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
| | | xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
| | | xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
| | | xmlns:local="clr-namespace:Plugin.TestResult_WPF" |
| | | xmlns:hb="clr-namespace:HMI.Base;assembly=HMI.Base" |
| | | xmlns:uic="clr-namespace:HMI.UI.Converter;assembly=HMI.UI" |
| | | xmlns:ui="clr-namespace:HMI.UI;assembly=HMI.UI" |
| | | xmlns:pw="https://opensource.panuon.com/wpf" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | xmlns:std="clr-namespace:HMI.StdControl;assembly=HMI.StdControl" |
| | | xmlns:dp="clr-namespace:HMI.UI.DpUtil;assembly=HMI.UI" |
| | | xmlns:local="clr-namespace:Plugin.TestResult_WPF" |
| | | xmlns:pu="https://opensource.panuon.com/wpf-ui" |
| | | mc:Ignorable="d" |
| | | Style="{StaticResource pluginMaskControl}" |
| | | Loaded="UserControl_Loaded" |
| | |
| | | </Style> |
| | | </UserControl.Resources> |
| | | <Grid> |
| | | <Grid.ColumnDefinitions> |
| | | <Grid.RowDefinitions> |
| | | <RowDefinition Height="Auto"/> |
| | | <RowDefinition/> |
| | | </Grid.RowDefinitions> |
| | | <!--<Grid.ColumnDefinitions> |
| | | <ColumnDefinition Width="7.5*"/> |
| | | <ColumnDefinition Width="*"/> |
| | | </Grid.ColumnDefinitions> |
| | | <local:TestResultView x:Name="testResultView" Grid.Column="0" Loaded="testResultView_Loaded" /> |
| | | <StackPanel Grid.Column="1" Background="#FFF"> |
| | | <GroupBox Header="{DynamicResource Tr.ProductInfo}"> |
| | | <ComboBox x:Name="modelSelect" Style="{StaticResource FormComboxStyle}" |
| | | </Grid.ColumnDefinitions>--> |
| | | <local:TestResultView x:Name="testResultView" Grid.Row="1" Grid.Column="0" Loaded="testResultView_Loaded" /> |
| | | <DockPanel Margin="10,0" Grid.Row="0" Grid.Column="1" Background="#FFF" VerticalAlignment="Center"> |
| | | <pu:FormGroup DockPanel.Dock="Right"> |
| | | <StackPanel Orientation="Horizontal" VerticalAlignment="Center" dp:StackPanelHelper.ChildSpace="20"> |
| | | <Button x:Name="btnStart" Click="Start_Click" Style="{StaticResource SuccessButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" Content="{DynamicResource App.Start}"/> |
| | | |
| | | <Button x:Name="btnStop" Click="Stop_Click" Style="{StaticResource DangerButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" |
| | | Content="{DynamicResource App.Stop}"/> |
| | | |
| | | <Button x:Name="btnClear" Click="BtnClear_Click" Style="{StaticResource PrimaryButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" |
| | | Content="{DynamicResource Ts.BtnClearNum}"/> |
| | | |
| | | <Button x:Name="scannerSetting" Click="ScannerSetting_Click" Style="{StaticResource PrimaryButton}" |
| | | Width="100" FontSize="14" Padding="0" Height="30" Content="扫码枪设置" Cursor="Hand"/> |
| | | |
| | | <!--<Button x:Name="btnScan1" Click="Scan_Click_1" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.Zone1Scan}"/> |
| | | |
| | | <Button x:Name="btnScan2" Click="Scan_Click_2" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.Zone2Scan}"/>--> |
| | | </StackPanel> |
| | | </pu:FormGroup> |
| | | <pu:FormGroup Header="{DynamicResource Tr.ProductInfo}" FontSize="16" Visibility="Collapsed"> |
| | | <ComboBox x:Name="modelSelect" Style="{StaticResource FormComboxStyle}" Width="200" |
| | | Height="28" |
| | | pu:ComboBoxHelper.ClearButtonVisibility="Collapsed" |
| | | SelectionChanged="modelSelect_SelectionChanged"/> |
| | | </GroupBox> |
| | | <GroupBox Header="{DynamicResource Tr.Status}"> |
| | | <StackPanel> |
| | | <Label HorizontalContentAlignment="Center" HorizontalAlignment="Stretch"> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup Header="测试程序" FontSize="16"> |
| | | <TextBox IsReadOnly="True" x:Name="tbFileName" Style="{StaticResource EditorTextBoxStyle}" Width="200" |
| | | Height="28" Text="{Binding FileName}"/> |
| | | </pu:FormGroup> |
| | | |
| | | <pu:FormGroup> |
| | | <std:StdEnableMes DockPanel.Dock="Left" FontSize="20" ValueChanged="StdEnableMes_ValueChanged"/> |
| | | </pu:FormGroup> |
| | | |
| | | |
| | | <!--<pu:FormGroup Header="{DynamicResource Tr.Status}" FontSize="16"> |
| | | <StackPanel Orientation="Horizontal" dp:StackPanelHelper.ChildSpace="10"> |
| | | <Label HorizontalContentAlignment="Center" VerticalAlignment="Center"> |
| | | <Label.Style> |
| | | <Style TargetType="Label"> |
| | | <Setter Property="HorizontalContentAlignment" Value="Center"/> |
| | |
| | | <Style TargetType="Label"> |
| | | <Setter Property="HorizontalContentAlignment" Value="Center"/> |
| | | <Setter Property="HorizontalAlignment" Value="Stretch"/> |
| | | <Setter Property="VerticalAlignment" Value="Center"/> |
| | | <Setter Property="Content" Value="{Binding produceStatus}"/> |
| | | <Setter Property="Margin" Value="0,10"/> |
| | | <Style.Triggers> |
| | |
| | | </Label.Style> |
| | | </Label> |
| | | </StackPanel> |
| | | </GroupBox> |
| | | <GroupBox Header="操作"> |
| | | <StackPanel dp:StackPanelHelper.ChildSpace="20"> |
| | | <Button x:Name="btnStart" Click="Start_Click" Style="{StaticResource SuccessButton}" |
| | | Content="{DynamicResource App.Start}"/> |
| | | |
| | | <Button x:Name="btnStop" Click="Stop_Click" Style="{StaticResource DangerButton}" |
| | | Content="{DynamicResource App.Stop}"/> |
| | | |
| | | <Button x:Name="btnClear" Click="BtnClear_Click" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Ts.BtnClearNum}"/> |
| | | |
| | | <Button x:Name="scannerSetting" Click="ScannerSetting_Click" Style="{StaticResource PrimaryButton}" |
| | | Content="扫码枪设置"/> |
| | | |
| | | <!--<Button x:Name="btnScan1" Click="Scan_Click_1" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.Zone1Scan}"/> |
| | | |
| | | <Button x:Name="btnScan2" Click="Scan_Click_2" Style="{StaticResource PrimaryButton}" |
| | | Content="{DynamicResource Tr.Zone2Scan}"/>--> |
| | | </StackPanel> |
| | | </GroupBox> |
| | | </StackPanel> |
| | | </pu:FormGroup>--> |
| | | </DockPanel> |
| | | </Grid> |
| | | </hb:PluginMaskControl> |
| | |
| | | using HMI.Core.Entity; |
| | | using HMI.Core.Manager; |
| | | using HMI.Core.Util; |
| | | using HMI.StdControl; |
| | | using HMI.UI; |
| | | using HMI.UI.Util; |
| | | using log4net; |
| | |
| | | using System.Collections.Generic; |
| | | using System.IO; |
| | | using System.Linq; |
| | | using System.Threading; |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | |
| | |
| | | private double TestVoltage = 12; |
| | | private double Time_Heating_Low = 300; |
| | | private double Time_Heating_High = 2400; |
| | | private string testSeqFile; |
| | | private Scanner scannerWindow1; |
| | | private Scanner scannerWindow2; |
| | | /// <summary> |
| | |
| | | set => Set(ref _produceStatus, value); |
| | | } |
| | | |
| | | private string _fileName; |
| | | |
| | | public string FileName |
| | | { |
| | | get => _fileName; |
| | | set => Set(ref _fileName, value); |
| | | } |
| | | |
| | | public override void SetLogger(ILog logger) |
| | | { |
| | | base.SetLogger(logger); |
| | |
| | | this.btnStop.IsEnabled = value; |
| | | } |
| | | } |
| | | |
| | | private bool AutoExecuteSeq = true; |
| | | |
| | | public ViewControl() |
| | | { |
| | |
| | | } |
| | | SannerIniFile = path; |
| | | LoadProduct(); |
| | | |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName("AutoExecuteSeq"); |
| | | AutoExecuteSeq = bool.Parse(value.Value); |
| | | } |
| | | catch |
| | | { |
| | | AutoExecuteSeq = true; |
| | | } |
| | | |
| | | try |
| | | { |
| | | var value = ParameterManager.GetCommonParameterByName("BurnInMainSeq"); |
| | | testResultView.testSeqFile = value.Value; |
| | | FileName = Path.GetFileName(value.Value); |
| | | } |
| | | catch |
| | | { |
| | | testResultView.testSeqFile = string.Empty; |
| | | FileName = string.Empty; |
| | | } |
| | | } |
| | | |
| | | public override void DoClose(object sender, EventArgs e) |
| | |
| | | int MethodCode = Convert.ToInt16(e.uiMsg.NumericData); |
| | | string strData; |
| | | |
| | | if (EventCase != 10014) return; |
| | | |
| | | try |
| | | { |
| | | log.Info($"EventCase: {EventCase}, MethodCode: {MethodCode}, StrData: {e.uiMsg.StringData}"); |
| | | log.Debug($"EventCase: {EventCase}, MethodCode: {MethodCode}, StrData: {e.uiMsg.StringData}"); |
| | | } |
| | | catch |
| | | { |
| | | |
| | | } |
| | | |
| | | if (EventCase == 8) |
| | | { |
| | | IsRunning = false; |
| | | return; |
| | | } |
| | | |
| | | if (EventCase != 10014) return; |
| | | |
| | | if (MethodCode == 0) |
| | | { |
| | |
| | | private bool isLoaded; |
| | | private void UserControl_Loaded(object sender, RoutedEventArgs e) |
| | | { |
| | | new MaskWindow(Window.GetWindow(this), (win) => |
| | | if (AutoExecuteSeq) |
| | | { |
| | | try |
| | | ShowMask(() => |
| | | { |
| | | Dispatcher.BeginInvoke(new Action(() => |
| | | { |
| | | Start_Click(null, null); |
| | | }), System.Windows.Threading.DispatcherPriority.Background); |
| | | }, (ex) => |
| | | { |
| | | ToastHelper.Error("Loaded Failed."); |
| | | log.Error("Loaded Failed.", ex); |
| | | }, "请稍后", LangUtil.Get("Ts.SequenceIsStarting")); |
| | | } |
| | | else |
| | | { |
| | | IsRunning = false; |
| | | } |
| | | Loaded -= UserControl_Loaded; |
| | | })); |
| | | } |
| | | finally |
| | | { |
| | | Dispatcher.Invoke(() => |
| | | { |
| | | win.Close(); |
| | | }); |
| | | } |
| | | }).Info(LangUtil.Get("Ts.SequenceIsStarting"), 100); |
| | | |
| | | |
| | | //new MaskWindow(Window.GetWindow(this), (win) => |
| | | //{ |
| | | // try |
| | | // { |
| | | // Dispatcher.BeginInvoke(new Action(() => |
| | | // { |
| | | // Start_Click(null, null); |
| | | // Loaded -= UserControl_Loaded; |
| | | // })); |
| | | // } |
| | | // finally |
| | | // { |
| | | // Dispatcher.Invoke(() => |
| | | // { |
| | | // win.Close(); |
| | | // }); |
| | | // } |
| | | //}).Info(LangUtil.Get("Ts.SequenceIsStarting"), 100); |
| | | |
| | | //ShowMask(() => |
| | | //{ |
| | |
| | | //this.SaftyTemperature = Convert.ToDouble(this.parameterManager.Find("SaftyTemperature").ParmValue); |
| | | //this.Time_Heating_Low = Convert.ToDouble(this.parameterManager.Find("Time_Heat_Low").ParmValue); |
| | | //this.Time_Heating_High = Convert.ToDouble(this.parameterManager.Find("Time_Heat_High").ParmValue); |
| | | testResultView.testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value; |
| | | //testResultView.testSeqFile = parameters.FirstOrDefault(p => p.Name == "TestSequence")?.Value; |
| | | |
| | | testResultView.engine.Globals.SetValString("ProductModel", 0, currentModel); |
| | | testResultView.engine.CommitGlobalsToDisk(promptOnSaveConflicts: false); |
| | |
| | | { |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(testResultView.testSeqFile)) |
| | | { |
| | | MsgBoxHelper2.Warn("请先设置BurnInMainSeq属性!"); |
| | | IsRunning = false; |
| | | return; |
| | | } |
| | | testResultView.StartTestSequence(); |
| | | IsRunning = true; |
| | | } |
| | |
| | | MsgBoxHelper.Error(Window.GetWindow(this), |
| | | $"{this.lang("Ts.StopTestSequenceFailed")}: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | private void Scan_Click_1(object sender, RoutedEventArgs e) |
| | | { |
| | | if (scannerWindow1 == null) |
| | | { |
| | | scannerWindow1 = new Scanner(this.lang("Tr.Zone1Scan")) |
| | | { |
| | | Tag = "Zone1" |
| | | }; |
| | | scannerWindow1.FinishBarcode += ScannerWindow_FinishBarcode; |
| | | //scannerWindow1.Owner = Window.GetWindow(this); |
| | | scannerWindow1.Closed += ScannerWindow1_Closed; |
| | | scannerWindow1.Show(); |
| | | } |
| | | else |
| | | { |
| | | scannerWindow1.Activate(); |
| | | } |
| | | } |
| | | |
| | | private void Scan_Click_2(object sender, RoutedEventArgs e) |
| | | { |
| | | if (scannerWindow2 == null) |
| | | { |
| | | scannerWindow2 = new Scanner(this.lang("Tr.Zone2Scan")) |
| | | { |
| | | Tag = "Zone2" |
| | | }; |
| | | scannerWindow2.FinishBarcode += ScannerWindow_FinishBarcode; |
| | | scannerWindow2.Owner = Window.GetWindow(this); |
| | | scannerWindow2.Closed += ScannerWindow2_Closed; |
| | | scannerWindow2.Show(); |
| | | } |
| | | else |
| | | { |
| | | scannerWindow2.Activate(); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 扫码完成逻辑 |
| | | /// </summary> |
| | | /// <param name="sender"></param> |
| | | /// <param name="e"></param> |
| | | private void ScannerWindow_FinishBarcode(object sender, BarcodeEventArg e) |
| | | { |
| | | if (this.SequenceContext == null) return; |
| | | CellInfo cellInfo = codeParser.GetCellInfoByCode(e.positionCode); |
| | | |
| | | string paramName = e.name == "Zone1" ? "StationState.StartScanner_A" : "StationState.StartScanner_B"; |
| | | testResultView.engine.Globals.SetValBoolean(paramName, 0, true); |
| | | string positionCode = e.positionCode, snrCode = e.snrCode; |
| | | //需要增加条码校验功能 |
| | | |
| | | //将读到的条码写入到SN中 |
| | | int dutNo = Convert.ToInt16(positionCode.Split('-')[2]) - 1; |
| | | string LookupStr = e.name == "Zone1" ? $"StationState.SN[{dutNo}]" : $"StationState.SN[{(dutNo + 54)}]"; |
| | | //this.SequenceContext.StationGlobals.SetValString(LookupStr, 0, snrCode); |
| | | //string code = this.SequenceContext.StationGlobals.GetValString(LookupStr, 0); |
| | | |
| | | testResultView.engine.Globals.SetValString(LookupStr, 0, snrCode); |
| | | string code = testResultView.engine.Globals.GetValString(LookupStr, 0); |
| | | testResultView.nameTables[cellInfo.OvenName].GetSingleCell(cellInfo.Index).SetStatus("hadCode"); |
| | | } |
| | | |
| | | private void ScannerWindow1_Closed(object sender, EventArgs e) |
| | |
| | | }; |
| | | setting.Open(false, "Config"); |
| | | } |
| | | |
| | | private void StdEnableMes_ValueChanged(object sender, StdUIEventArg e) |
| | | { |
| | | testResultView.SequenceContext?.StationGlobals.SetValBoolean($"SystemSetting.{e.StringValue}", 1, e.BoolValue); |
| | | } |
| | | } |
| | | } |
| | |
| | | // 生成号 |
| | | // 修订号 |
| | | // |
| | | [assembly: AssemblyVersion("1.0.0.0")] |
| | | [assembly: AssemblyFileVersion("1.0.0.1")] |
| | | [assembly: AssemblyVersion("1.0.0.2")] |
| | | [assembly: AssemblyFileVersion("1.0.0.2")] |
| | | [assembly: PluginClassName("Plugin.TsExecution.TsExecution")] |
| | |
| | | RowHeight="{StaticResource nanD}" |
| | | ColumnHeaderHeight="{Binding ActualWidth,ElementName=control, |
| | | Converter={StaticResource fc}, ConverterParameter='32,1093,30,45'}" |
| | | ItemsSource="{Binding Datasource}" |
| | | x:Name="table"> |
| | | ItemsSource="{Binding Datasource}" x:Name="table"> |
| | | <DataGrid.Resources> |
| | | <Style TargetType="DataGridCell" |
| | | BasedOn="{StaticResource {x:Static pu:StyleKeys.DataGridCellStyle}}"> |
| | |
| | | |
| | | protected void Set([CallerMemberName] string name = null) |
| | | { |
| | | |
| | | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); |
| | | } |
| | | |
| | |
| | | |
| | | public SingleControl(int Index, string CountIniPath, int probeWarn) |
| | | { |
| | | this.CountIniPath = CountIniPath; |
| | | DataContext = this; |
| | | this.CountIniPath = CountIniPath; |
| | | this.index = Index; |
| | | ProbeWarn = probeWarn; |
| | | |
| | |
| | | //var modal = scannerVisualModal; |
| | | //Canvas.SetLeft(modal, (scannerPanel.ActualWidth - scannerVisualModal.ActualWidth) / 2); |
| | | //Canvas.SetTop(modal, (scannerPanel.ActualHeight - scannerVisualModal.ActualHeight) / 2); |
| | | } |
| | | } |
| | | |
| | | private void TextBlock_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) |
| | | { |
| | | DependencyObject parent = VisualTreeHelper.GetParent((DependencyObject)sender); |
| | | while (parent != null) { |
| | | parent = VisualTreeHelper.GetParent(parent); |
| | | } |
| | | } |
| | | } |
| | |
| | | using HMI.Core.Util; |
| | | using HMI.MQUtil; |
| | | using HMI.UI; |
| | | using HMI.UI.Controls; |
| | | using HMI.UI.Util; |
| | | using HMI.Util; |
| | | using log4net; |
| | |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Forms.DataVisualization.Charting; |
| | | using System.Windows.Media; |
| | | |
| | | namespace Plugin.TsExecution |
| | | { |
| | |
| | | private SqliteHelper sqliteHelper; |
| | | |
| | | private MQConnector mqConnector; |
| | | private int probeWarn; |
| | | |
| | | public TsExecution() |
| | | { |
| | |
| | | //初始化TestStand引擎 |
| | | this.InitTestStandEngine(); |
| | | } |
| | | |
| | | public override void SetBaseFolder(string folder) |
| | | { |
| | | CountIniPath = Path.Combine(folder, "Count.ini"); |
| | |
| | | { |
| | | this.ReadCount(out int pass, out int fail); |
| | | this.DisplayCount(pass, fail); |
| | | InitProducts(); |
| | | ReadConfig(); |
| | | InitProducts(); |
| | | CheckSqlHelper(); |
| | | base.InitFinish(); |
| | | } |
| | |
| | | { |
| | | HandleUIMessage(eventCode, index, strData); |
| | | })); |
| | | } |
| | | |
| | | void createChildInNewThread(int index, string configFile, int probeWarn) |
| | | { |
| | | HostVisual hostVisual = new HostVisual(); |
| | | |
| | | UIElement content = new VisualHost(hostVisual); |
| | | |
| | | System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ThreadStart(() => |
| | | { |
| | | VisualTarget visualTarget = new VisualTarget(hostVisual); |
| | | |
| | | var control = new SingleControl(index, configFile, probeWarn); |
| | | control.Arrange(new Rect(new Point(), content.RenderSize)); |
| | | |
| | | visualTarget.RootVisual = control; |
| | | tsSockets.Add(control); |
| | | System.Windows.Threading.Dispatcher.Run(); |
| | | })); |
| | | //panel.Children.Add(content); |
| | | |
| | | thread.SetApartmentState(System.Threading.ApartmentState.STA); |
| | | thread.IsBackground = true; |
| | | thread.Start(); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | Products = ProductManager.GetProducts<ObservableCollection<ProductData>>(); |
| | | if (Products != null && Products.Count > 0) |
| | | { |
| | | List<ParameterData> parameters = |
| | | ParameterManager.GetCommonParameter<List<ParameterData>>(); |
| | | string tmpNum = parameters?.FirstOrDefault(p => p.Name == "SocketNum")?.Value?.ToString(); |
| | | if (!string.IsNullOrEmpty(tmpNum)) |
| | | { |
| | | this.socketNum = Convert.ToInt32(tmpNum); |
| | | } |
| | | string lastModel = engine?.Globals.GetValString("StationState.ProductModel", 1); |
| | | |
| | | var tempProduct = Products[0]; |
| | | if (!string.IsNullOrEmpty(lastModel)) |
| | | { |
| | | var product = Products.FirstOrDefault(p => p.Name == lastModel); |
| | | if (product != null) |
| | | { |
| | | SelectedProduct = product; |
| | | tempProduct = product; |
| | | } |
| | | } |
| | | SelectedProduct = tempProduct; |
| | | } |
| | | RefershUI(); |
| | | return; |
| | | } |
| | | } |
| | | SelectedProduct = Products[0]; |
| | | RefershUI(); |
| | | } |
| | | SampleStatus = false; |
| | | } |
| | | |
| | |
| | | |
| | | private void RefershUI() |
| | | { |
| | | ParameterData p = ParameterManager.GetCommonParameterByName("ProbeWarn"); |
| | | int ProbeWarn = 0; |
| | | if (p != null) |
| | | { |
| | | try |
| | | { |
| | | ProbeWarn = Convert.ToInt32(p.Value); |
| | | } |
| | | catch |
| | | { |
| | | ProbeWarn = 0; |
| | | } |
| | | } |
| | | |
| | | panel.Children.Clear(); |
| | | //重新生成子面板 |
| | | for (int i = 0; i < this.socketNum; i++) |
| | | { |
| | | SingleControl control = new SingleControl(i, CountIniPath, ProbeWarn); |
| | | SingleControl control = new SingleControl(i, CountIniPath, this.probeWarn); |
| | | panel.Children.Add(control); |
| | | tsSockets.Add(control); |
| | | |
| | |
| | | catch |
| | | { |
| | | flag = false; |
| | | } |
| | | |
| | | try |
| | | { |
| | | value = ParameterManager.GetCommonParameterByName("SocketNum"); |
| | | if (value != null) |
| | | { |
| | | this.socketNum = int.Parse(value.Value); |
| | | } |
| | | } |
| | | catch |
| | | { |
| | | this.socketNum = 2; |
| | | } |
| | | |
| | | if (flag) |
| | |
| | | tsModelPath = @"C:\Users\Public\Documents\National Instruments\TestStand 2020 (64-bit)\Components\Models\ParallelModel.seq"; |
| | | } |
| | | |
| | | try |
| | | { |
| | | |
| | | value = ParameterManager.GetCommonParameterByName("ProbeWarn"); |
| | | probeWarn = int.Parse(value?.Value); |
| | | } |
| | | catch |
| | | { |
| | | probeWarn = 0; |
| | | } |
| | | //Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableMes", "true", CountIniPath)); |
| | | //EnableCanLog = Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableCanLog", "true", CountIniPath)); |
| | | //EnableDebugMode = Convert.ToBoolean(IniFileHelper.ReadIniData("Config", "EnableDebugMode", "true", CountIniPath)); |
| | | } |
| | | |
| | | //private void WriteToTsWhenInit() |
| | | //{ |
| | | // foreach (var ts in tsSockets) |
| | | // { |
| | | // ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.EnableMes", 1, EnableMes); |
| | | // ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.EnableNGPause", 1, EnableNGPause); |
| | | // ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.EnableCanLog", 1, EnableCanLog); |
| | | // ts?.SequenceFileContext?.StationGlobals.SetValBoolean($"SystemSetting.EnableDebugMode", 1, EnableDebugMode); |
| | | // } |
| | | //} |
| | | |
| | | private bool WriteConfig(string name, bool value) |
| | | { |
| | | //IniFileHelper.WriteIniData("Config", name, value.ToString(), CountIniPath); |
| | | try |
| | | { |
| | | if (ParameterManager.UpdateCommonParameter(name, value, out string errMsg)) |
| | |
| | | this.tsSockets[index].WriteToCSV(csvPath); |
| | | } |
| | | |
| | | public void SaveTemplateCSV(int index) |
| | | { |
| | | var time = DateTime.Now; |
| | | string status = this.tsSockets[index].Status == "Passed" ? "PASS" : "FAIL"; |
| | | string csvPath = Path.Combine(csvDir, SelectedProduct?.Name ?? "未知产品", time.ToString("yyyyMMdd"), status, $"{this.tsSockets[index].Barcode}-{time.ToString("HHmmss")}.csv"); |
| | | this.tsSockets[index].WriteToCSV(csvPath); |
| | | } |
| | | |
| | | public void SavePositionDB(int index, string status) |
| | | { |
| | | CheckSqlHelper(); |
| | | var socket = this.tsSockets[index]; |
| | | var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); |
| | | string snr = socket.Barcode; |
| | | string model = SelectedProduct?.Name; |
| | | |
| | | List<string> sqls = new List<string>(); |
| | | foreach (var data in socket.Datasource) |
| | | { |
| | | sqls.Add($@"INSERT INTO serialData (sn,model,station,step,limitDown,limitUp,unit,value,status,finalStatus,consumeTime,totalConsumeTime,time) VALUES |
| | | ('{snr}','{socket.Model}','','{data.Name}','{data.LimitDown}','{data.LimitUp}','{data.Unit}','{data.Value}','{data.Result}','{socket.Status}','{data.ConsumeTime}','{socket.ElapseTime}','{time}')"); |
| | | sqls.Add($@"INSERT INTO serialData (sn,model,station,step,position,limitDown,limitUp,unit,value,status,finalStatus,consumeTime,totalConsumeTime,time) VALUES |
| | | ('{snr}','{model}','','{data.Name}','{index}','{data.LimitDown}','{data.LimitUp}','{data.Unit}','{data.Value}','{data.Result}','{socket.Status}','{data.ConsumeTime}','{socket.ElapseTime}','{time}')"); |
| | | } |
| | | sqls.Add($@"INSERT INTO testResult (sn,model,station,result,time,position,status) VALUES |
| | | ('{snr}','{socket.Model}','','{socket.Status}','{time}','{index}','{status}')"); |
| | | ('{snr}','{model}','','{socket.Status}','{time}','{index}','{status}')"); |
| | | sqliteHelper.ExecuteBatchSql(sqls); |
| | | } |
| | | |
| | |
| | | this.tsSockets[index].SetTestProcess(ProcessVal); |
| | | break; |
| | | case 10031://导出CSV |
| | | if (string.IsNullOrEmpty(strData)) |
| | | { |
| | | SaveTemplateCSV(index); |
| | | return; |
| | | } |
| | | try |
| | | { |
| | | string[] datas = strData.Split(';'); |
| | | SavePositionCSV(index, datas[0]); |
| | | if (datas.Length >= 2) |
| | | { |
| | | SavePositionDB(index, datas[1]); |
| | | } |
| | | else |
| | | { |
| | | var sss = this.tsSockets[index].Status; |
| | | SavePositionDB(index, sss); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.Warn("10031 Error.", ex); |
| | | SaveTemplateCSV(index); |
| | | } |
| | | break; |
| | | case 10032://按下标暂停测试 |
| | | this.tsSockets[index].ShowPausePanel(); |
| | |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ProjectReference Include="..\..\..\hslCommunicationV12.0.3带源码demo\HslCommunication\HslCommunication.csproj"> |
| | | <Project>{aa30059e-7269-415c-9df2-55c310dd5548}</Project> |
| | | <Name>HslCommunication</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Content Include="PCI-Dask64.dll"> |
| | | <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| | | </Content> |
| | |
| | | } |
| | | else if (data.Type == "Int") |
| | | { |
| | | context.FileGlobals.SetValInteger64($"DUTSetting.{data.Name}", 1, int.Parse(data.Value)); |
| | | context.FileGlobals.SetValNumber($"DUTSetting.{data.Name}", 1, int.Parse(data.Value)); |
| | | } |
| | | else if (data.Type == "Double") |
| | | { |
| New file |
| | |
| | | using System; |
| | | using System.Diagnostics; |
| | | using System.Linq; |
| | | using System.Runtime.InteropServices; |
| | | using System.Windows; |
| | | using System.Windows.Interop; |
| | | |
| | | namespace HMI.Util.Base |
| | | { |
| | | public interface AlarmBase |
| | | { |
| | | |
| | | bool? Alarm(string message); |
| | | } |
| | | |
| | | public class AlarmUtil |
| | | { |
| | | [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] |
| | | public static extern IntPtr GetModuleHandle(string lpModuleName); |
| | | |
| | | [DllImport("user32.dll")] |
| | | private static extern bool IsWindow(IntPtr hWnd); |
| | | |
| | | [DllImport("user32.dll")] |
| | | private static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount); |
| | | |
| | | [DllImport("user32.dll")] |
| | | private static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); |
| | | |
| | | |
| | | /// <summary> |
| | | /// 根据窗口标题获取WPF窗口对象 |
| | | /// </summary> |
| | | /// <param name="windowTitle">窗口标题</param> |
| | | /// <returns>WPF窗口对象,如果未找到则返回null</returns> |
| | | public static IntPtr GetProcessIdByName(string windowTitle) |
| | | { |
| | | Process[] processes = Process.GetProcesses(); |
| | | foreach (Process process in processes) |
| | | { |
| | | if (process.ProcessName == windowTitle) |
| | | { |
| | | var handle = process.MainWindowHandle; |
| | | Console.WriteLine(process.MainWindowHandle.ToString()); |
| | | Console.WriteLine(IsWindow(process.MainWindowHandle)); |
| | | var className = new System.Text.StringBuilder(256); |
| | | GetClassName(handle, className, className.Capacity); |
| | | Console.WriteLine(className.ToString()); |
| | | |
| | | Console.WriteLine(SendMessage(handle, 0x12, IntPtr.Zero, IntPtr.Zero)); |
| | | |
| | | |
| | | var source = HwndSource.FromHwnd(process.MainWindowHandle); |
| | | var v = source?.RootVisual; |
| | | if (v is AlarmBase ab) Console.WriteLine(ab.Alarm("123").ToString()); |
| | | return process.MainWindowHandle; |
| | | } |
| | | } |
| | | |
| | | |
| | | return IntPtr.Zero; |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | <ErrorReport>prompt</ErrorReport> |
| | | </PropertyGroup> |
| | | <ItemGroup> |
| | | <Reference Include="PresentationCore" /> |
| | | <Reference Include="PresentationFramework" /> |
| | | <Reference Include="System" /> |
| | | <Reference Include="System.Core" /> |
| | | <Reference Include="System.Xml.Linq" /> |
| | |
| | | <Reference Include="System.Data" /> |
| | | <Reference Include="System.Net.Http" /> |
| | | <Reference Include="System.Xml" /> |
| | | <Reference Include="WindowsBase" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <Compile Include="AlarmUtil.cs" /> |
| | | <Compile Include="Properties\AssemblyInfo.cs" /> |
| | | <Compile Include="RegUtil.cs" /> |
| | | </ItemGroup> |
| | |
| | | <configSections> |
| | | <section name="TestResultConfig" type="System.Configuration.SingleTagSectionHandler" /> |
| | | </configSections> |
| | | <TestResultConfig Row="2" Column="3" PortStart="6660" PositionColumn="3" PositionCount="18" NameStr="A1,A2,A3,B1,B2,B3" /> |
| | | <TestResultConfig Row="2" Column="2" PortStart="6660" PositionColumn="4" PositionCount="20" NameStr="A,B,C,D,E,F,G" CodeParserType="JK01" /> |
| | | <startup> |
| | | <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> |
| | | </startup> |
| | | <runtime> |
| | | <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| | | <probing privatePath="Libs;ThirdParty;Plugin;3rds;" /> |
| | | <probing privatePath="Libs;ThirdParty;Plugin;3rds;Api;" /> |
| | | <dependentAssembly> |
| | | <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> |
| | | <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> |
| | |
| | | </appender> |
| | | |
| | | <root> |
| | | <level value="INFO" /> |
| | | <level value="DEBUG" /> |
| | | <appender-ref ref="Console" /> |
| | | <appender-ref ref="RollingFile" /> |
| | | </root> |
| | |
| | | <Image Height="25" |
| | | Stretch="Uniform" |
| | | HorizontalAlignment="Left" |
| | | Source="/Resources/JingCeLogo.png" |
| | | Source="/Icon/JingCeLogo.png" |
| | | Margin="0,0,0,10" |
| | | RenderOptions.BitmapScalingMode="HighQuality" /> |
| | | |
| | |
| | | <Image Height="25" |
| | | Stretch="Uniform" |
| | | HorizontalAlignment="Left" |
| | | Source="/Resources/JingCeLogo.png" |
| | | Source="/Icon/JingCeLogo.png" |
| | | RenderOptions.BitmapScalingMode="HighQuality" /> |
| | | <StackPanel Margin="0,50,0,0" Grid.Row="1" x:Name="formPanel" dp:StackPanelHelper.ChildSpace="20" > |
| | | <pu:FormGroup x:Name="FrmAccount" |
| | |
| | | using System.Windows; |
| | | using System.Windows.Controls; |
| | | using System.Windows.Media.Imaging; |
| | | using HMI.Util.Base; |
| | | using System.Windows.Interop; |
| | | |
| | | namespace WPFProject |
| | | { |
| | |
| | | /// <summary> |
| | | /// PanuonWindow.xaml 的交互逻辑 |
| | | /// </summary> |
| | | public partial class PanuonWindow : WindowX, IPluginContainer,IAlarmShow |
| | | public partial class PanuonWindow : WindowX, IPluginContainer,IAlarmShow, AlarmBase |
| | | { |
| | | public PanuonWindow() |
| | | { |
| | |
| | | sb.Loaded -= list_Loaded; |
| | | } |
| | | |
| | | public bool? Alarm(string message) |
| | | { |
| | | return true; |
| | | } |
| | | |
| | | //private void BaseWindow_Loaded(object sender, RoutedEventArgs e) |
| | | //{ |
| | | // var s = (Style)this.Resources["WindowButton"]; |
| | |
| | | <Project>{a580de4a-34e7-4efe-ad2c-0871396000e9}</Project> |
| | | <Name>HMI.DataViewer</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.IOMonitor\HMI.IOMonitor.csproj"> |
| | | <Project>{f7663c79-7047-42f3-b129-73a2575ee7c6}</Project> |
| | | <Name>HMI.IOMonitor</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\HMI.LogViewer\HMI.LogViewer.csproj"> |
| | | <Project>{20c23602-b029-4e21-8c11-b9e5f2223237}</Project> |
| | | <Name>HMI.LogViewer</Name> |
| | |
| | | <Project>{de4205c6-5923-46fd-a4b9-65169bf61c75}</Project> |
| | | <Name>HMI.MenuManage</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.ChangeModel\Plugin.ChangeModel.csproj"> |
| | | <Project>{ef5972b1-dd20-404d-b2b3-37e70e2a478a}</Project> |
| | | <Name>Plugin.ChangeModel</Name> |
| | | <ProjectReference Include="..\Plugin.CurrentSensorControl\Plugin.CurrentSensorControl.csproj"> |
| | | <Project>{e4505d51-248b-4c21-b0e3-a4b2a7551d6a}</Project> |
| | | <Name>Plugin.CurrentSensorControl</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.DataBoard\Plugin.DataBoard.csproj"> |
| | | <Project>{be42ab26-3270-43e1-84b8-6929d862ff8d}</Project> |
| | |
| | | <Project>{968fe602-22d6-42bd-981c-601ad518a896}</Project> |
| | | <Name>Plugin.JarUI</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.MaterialOpt\Plugin.MaterialOpt.csproj"> |
| | | <Project>{e1f90cbd-a0d4-48da-ab25-7f490935aa4a}</Project> |
| | | <Name>Plugin.MaterialOpt</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.ModelManage\Plugin.ModelManage.csproj"> |
| | | <Project>{76ce4d21-702c-416f-95b4-f4f4c5b2d162}</Project> |
| | | <Name>Plugin.ModelManage</Name> |
| | |
| | | <ProjectReference Include="..\Plugin.SeqEditor\Plugin.SeqEditor.csproj"> |
| | | <Project>{717fd815-ff95-4f30-b4d9-9cea978ca40e}</Project> |
| | | <Name>Plugin.SeqEditor</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.ServoManage\Plugin.ServoManage.csproj"> |
| | | <Project>{1853e00f-6865-4bc6-974b-6a5e1c00bafe}</Project> |
| | | <Name>Plugin.ServoManage</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\Plugin.TestResult\Plugin.TestResult.csproj"> |
| | | <Project>{7375b74c-b6bf-4814-9838-e1caacad1897}</Project> |
| | |
| | | <ProjectReference Include="..\SimpleUtil\HMI.Simple.Util\HMI.Simple.Util.csproj"> |
| | | <Project>{cf5bebe9-2803-49c3-b773-73d082e0984a}</Project> |
| | | <Name>HMI.Simple.Util</Name> |
| | | </ProjectReference> |
| | | <ProjectReference Include="..\SimpleUtil\HMI.Util.Base\HMI.Util.Base.csproj"> |
| | | <Project>{d59e25d1-9b27-46a1-8438-92661dd23fae}</Project> |
| | | <Name>HMI.Util.Base</Name> |
| | | </ProjectReference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | |
| | | move /y "$(TargeDir)HMI.UI.dll" $(TargeDir)Libs\HMI.UI.dll" |
| | | move /y "$(TargeDir)HMI.Util.dll" $(TargeDir)Libs\HMI.Util.dll" |
| | | move /y "$(TargeDir)ConnectionUtil.dll" $(TargeDir)Libs\ConnectionUtil.dll" |
| | | move /y "$(TargeDir)HMI.StdControl.dll" $(TargeDir)Libs\HMI.StdControl.dll" |
| | | |
| | | move /y "$(TargeDir)HMI.LogUtil.dll" $(TargeDir)Api\HMI.LogUtil.dll" |
| | | move /y "$(TargeDir)HMI.SerialData.Util.dll" $(TargeDir)Api\HMI.SerialData.Util.dll" |
| | |
| | | move /y "$(TargeDir)Plugin.MaterialOpt.dll" $(TargeDir)Plugin\Plugin.MaterialOpt.dll" |
| | | move /y "$(TargeDir)Plugin.DODriverControl.dll" $(TargeDir)Plugin\Plugin.DODriverControl.dll" |
| | | move /y "$(TargeDir)Plugin.ModelManage.dll" $(TargeDir)Plugin\Plugin.ModelManage.dll" |
| | | move /y "$(TargeDir)Plugin.CurrentSensorControl.dll" $(TargeDir)Plugin\Plugin.CurrentSensorControl.dll" |
| | | |
| | | setlocal enabledelayedexpansion |
| | | |
| | |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.Core", "..\HMI.Core\HMI.Core.csproj", "{3E3BF44A-0B69-45C5-9512-528CB48A7106}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisionBuilder.Test", "..\VisionBuilder.Test\VisionBuilder.Test.csproj", "{6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisionBuilder.Engine", "..\VisionBuilder.Engine\VisionBuilder.Engine.csproj", "{8E5E8A68-0B9D-4A6A-B325-730C64603FDF}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.UI", "..\HMI.UI\HMI.UI.csproj", "{F17DE6B5-AF1D-48C6-94A0-6B763A6546A6}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.MenuManage", "..\HMI.MenuManage\HMI.MenuManage.csproj", "{DE4205C6-5923-46FD-A4B9-65169BF61C75}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisionBuilder.Run", "..\VisionBuilder.Run\VisionBuilder.Run.csproj", "{7C299AED-88CC-437E-A68B-1550AA72E6B0}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.UnitTest", "..\HMI.UnitTest\HMI.UnitTest.csproj", "{325A7F52-FE51-44F0-B3AC-5F42F5356605}" |
| | | EndProject |
| | |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.DataViewer", "..\HMI.DataViewer\HMI.DataViewer.csproj", "{A580DE4A-34E7-4EFE-AD2C-0871396000E9}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.IOMonitor", "..\HMI.IOMonitor\HMI.IOMonitor.csproj", "{F7663C79-7047-42F3-B129-73A2575EE7C6}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.ParameterManage", "..\HMI.ParameterManage\HMI.ParameterManage.csproj", "{736CD77D-B81E-4866-BB00-84B0B57110F0}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.LogViewer", "..\HMI.LogViewer\HMI.LogViewer.csproj", "{20C23602-B029-4E21-8C11-B9E5F2223237}" |
| | |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.Util", "..\HMI.Util\HMI.Util.csproj", "{AFEA100A-9223-448D-AB10-3015D93DD98C}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.ServoManage", "..\Plugin.ServoManage\Plugin.ServoManage.csproj", "{1853E00F-6865-4BC6-974B-6A5E1C00BAFE}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.DOControl", "..\Plugin.DOControl\Plugin.DOControl.csproj", "{306A83DC-A7DB-4057-BAA7-477D8756F5D9}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectionUtil", "..\..\ConnectionUtil\ConnectionUtil\ConnectionUtil.csproj", "{D0806FA6-3F6D-4304-81B8-EAD9DA7CB5B2}" |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectionUtil", "..\ConnectionUtil\ConnectionUtil.csproj", "{D0806FA6-3F6D-4304-81B8-EAD9DA7CB5B2}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OPCClient", "..\OPCClient\OPCClient.csproj", "{E5740BB5-9FC6-4A20-B7C2-CC90C281ED05}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.TestBuilder", "..\Plugin.TestBuilder\Plugin.TestBuilder.csproj", "{30201EC1-9A82-48DB-94B9-BD5C1190228B}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.DataBoard", "..\Plugin.DataBoard\Plugin.DataBoard.csproj", "{BE42AB26-3270-43E1-84B8-6929D862FF8D}" |
| | | EndProject |
| | |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.SeqEditor", "..\Plugin.SeqEditor\Plugin.SeqEditor.csproj", "{717FD815-FF95-4F30-B4D9-9CEA978CA40E}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.ChangeModel", "..\Plugin.ChangeModel\Plugin.ChangeModel.csproj", "{EF5972B1-DD20-404D-B2B3-37E70E2A478A}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lmes", "..\..\MesApi\lmes.csproj", "{376CA791-49D8-B4D7-6F98-6E86BD46CAEF}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.MaterialOpt", "..\Plugin.MaterialOpt\Plugin.MaterialOpt.csproj", "{E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.MQUtil", "..\SimpleUtil\HMI.MQUtil\HMI.MQUtil.csproj", "{F8B8B6B6-821B-4FF6-B556-9CAB840EA57A}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.DODriverControl", "..\Plugin.DODriverControl\Plugin.DODriverControl.csproj", "{61DF853D-829A-4426-BEF8-0135586005B6}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HslCommunication", "..\..\hslCommunicationV12.0.3带源码demo\HslCommunication\HslCommunication.csproj", "{AA30059E-7269-415C-9DF2-55C310DD5548}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.TsSupport", "..\Plugin.TsSupport\Plugin.TsSupport.csproj", "{3068124E-F12B-473E-99A0-2DA5A0385D05}" |
| | | EndProject |
| | |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DIOController", "..\SimpleUtil\DIOController\DIOController.csproj", "{34FFBAFE-478F-4B6E-95E7-92A949011A9B}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "..\ConsoleTest\ConsoleTest.csproj", "{2BDDB984-199B-4913-96BB-39C252E101F2}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Plugin.CurrentSensorControl", "..\Plugin.CurrentSensorControl\Plugin.CurrentSensorControl.csproj", "{E4505D51-248B-4C21-B0E3-A4B2A7551D6A}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModBusTcpController", "..\ModBusTcpController\ModBusTcpController.csproj", "{49DB0C9B-B239-4608-A91E-F5ED43AFAF96}" |
| | | EndProject |
| | | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HMI.StdControl", "..\HMI.StdControl\HMI.StdControl.csproj", "{7A066856-182F-4435-B648-E9FB91AFF657}" |
| | | EndProject |
| | | Global |
| | | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| | |
| | | {3E3BF44A-0B69-45C5-9512-528CB48A7106}.Release|x64.Build.0 = Release|x64 |
| | | {3E3BF44A-0B69-45C5-9512-528CB48A7106}.Release|x86.ActiveCfg = Release|x86 |
| | | {3E3BF44A-0B69-45C5-9512-528CB48A7106}.Release|x86.Build.0 = Release|x86 |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|x64.Build.0 = Debug|x64 |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|x64.ActiveCfg = Release|x64 |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|x64.Build.0 = Release|x64 |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {6E1CC97A-B3CB-4E9F-94E0-F264DE0D8298}.Release|x86.Build.0 = Release|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|x64.Build.0 = Debug|x64 |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|x64.ActiveCfg = Release|x64 |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|x64.Build.0 = Release|x64 |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {8E5E8A68-0B9D-4A6A-B325-730C64603FDF}.Release|x86.Build.0 = Release|Any CPU |
| | | {F17DE6B5-AF1D-48C6-94A0-6B763A6546A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {F17DE6B5-AF1D-48C6-94A0-6B763A6546A6}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {F17DE6B5-AF1D-48C6-94A0-6B763A6546A6}.Debug|x64.ActiveCfg = Debug|x64 |
| | |
| | | {DE4205C6-5923-46FD-A4B9-65169BF61C75}.Release|x64.Build.0 = Release|Any CPU |
| | | {DE4205C6-5923-46FD-A4B9-65169BF61C75}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {DE4205C6-5923-46FD-A4B9-65169BF61C75}.Release|x86.Build.0 = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|x64.Build.0 = Debug|x64 |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|x64.Build.0 = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {7C299AED-88CC-437E-A68B-1550AA72E6B0}.Release|x86.Build.0 = Release|Any CPU |
| | | {325A7F52-FE51-44F0-B3AC-5F42F5356605}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {325A7F52-FE51-44F0-B3AC-5F42F5356605}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {325A7F52-FE51-44F0-B3AC-5F42F5356605}.Debug|x64.ActiveCfg = Debug|x64 |
| | |
| | | {A580DE4A-34E7-4EFE-AD2C-0871396000E9}.Release|x64.Build.0 = Release|Any CPU |
| | | {A580DE4A-34E7-4EFE-AD2C-0871396000E9}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {A580DE4A-34E7-4EFE-AD2C-0871396000E9}.Release|x86.Build.0 = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|x64.Build.0 = Debug|x64 |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|x64.Build.0 = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {F7663C79-7047-42F3-B129-73A2575EE7C6}.Release|x86.Build.0 = Release|Any CPU |
| | | {736CD77D-B81E-4866-BB00-84B0B57110F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {736CD77D-B81E-4866-BB00-84B0B57110F0}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {736CD77D-B81E-4866-BB00-84B0B57110F0}.Debug|x64.ActiveCfg = Debug|x64 |
| | |
| | | {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|x64.Build.0 = Release|Any CPU |
| | | {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {AFEA100A-9223-448D-AB10-3015D93DD98C}.Release|x86.Build.0 = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x64.Build.0 = Debug|x64 |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x64.Build.0 = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {1853E00F-6865-4BC6-974B-6A5E1C00BAFE}.Release|x86.Build.0 = Release|Any CPU |
| | | {306A83DC-A7DB-4057-BAA7-477D8756F5D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {306A83DC-A7DB-4057-BAA7-477D8756F5D9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {306A83DC-A7DB-4057-BAA7-477D8756F5D9}.Debug|x64.ActiveCfg = Debug|x64 |
| | |
| | | {E5740BB5-9FC6-4A20-B7C2-CC90C281ED05}.Release|x64.Build.0 = Release|Any CPU |
| | | {E5740BB5-9FC6-4A20-B7C2-CC90C281ED05}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {E5740BB5-9FC6-4A20-B7C2-CC90C281ED05}.Release|x86.Build.0 = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|x64.Build.0 = Debug|x64 |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|x64.Build.0 = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {30201EC1-9A82-48DB-94B9-BD5C1190228B}.Release|x86.Build.0 = Release|Any CPU |
| | | {BE42AB26-3270-43E1-84B8-6929D862FF8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {BE42AB26-3270-43E1-84B8-6929D862FF8D}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {BE42AB26-3270-43E1-84B8-6929D862FF8D}.Debug|x64.ActiveCfg = Debug|x64 |
| | |
| | | {717FD815-FF95-4F30-B4D9-9CEA978CA40E}.Release|x64.Build.0 = Release|x64 |
| | | {717FD815-FF95-4F30-B4D9-9CEA978CA40E}.Release|x86.ActiveCfg = Release|x86 |
| | | {717FD815-FF95-4F30-B4D9-9CEA978CA40E}.Release|x86.Build.0 = Release|x86 |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|x64.Build.0 = Debug|x64 |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|x64.Build.0 = Release|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {EF5972B1-DD20-404D-B2B3-37E70E2A478A}.Release|x86.Build.0 = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|x64.Build.0 = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {376CA791-49D8-B4D7-6F98-6E86BD46CAEF}.Release|x86.Build.0 = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|x64.Build.0 = Debug|x64 |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|x64.Build.0 = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {E1F90CBD-A0D4-48DA-AB25-7F490935AA4A}.Release|x86.Build.0 = Release|Any CPU |
| | | {F8B8B6B6-821B-4FF6-B556-9CAB840EA57A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {F8B8B6B6-821B-4FF6-B556-9CAB840EA57A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {F8B8B6B6-821B-4FF6-B556-9CAB840EA57A}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | |
| | | {61DF853D-829A-4426-BEF8-0135586005B6}.Release|x64.Build.0 = Release|Any CPU |
| | | {61DF853D-829A-4426-BEF8-0135586005B6}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {61DF853D-829A-4426-BEF8-0135586005B6}.Release|x86.Build.0 = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|x64.Build.0 = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {AA30059E-7269-415C-9DF2-55C310DD5548}.Release|x86.Build.0 = Release|Any CPU |
| | | {3068124E-F12B-473E-99A0-2DA5A0385D05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {3068124E-F12B-473E-99A0-2DA5A0385D05}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {3068124E-F12B-473E-99A0-2DA5A0385D05}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | |
| | | {34FFBAFE-478F-4B6E-95E7-92A949011A9B}.Release|x86.Build.0 = Release|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x64.Build.0 = Debug|x64 |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Release|x64.Build.0 = Release|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {2BDDB984-199B-4913-96BB-39C252E101F2}.Release|x86.Build.0 = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|x64.Build.0 = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {E4505D51-248B-4C21-B0E3-A4B2A7551D6A}.Release|x86.Build.0 = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|x64.Build.0 = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {49DB0C9B-B239-4608-A91E-F5ED43AFAF96}.Release|x86.Build.0 = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|x64.ActiveCfg = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|x64.Build.0 = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|x86.ActiveCfg = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Debug|x86.Build.0 = Debug|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|Any CPU.Build.0 = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|x64.ActiveCfg = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|x64.Build.0 = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|x86.ActiveCfg = Release|Any CPU |
| | | {7A066856-182F-4435-B648-E9FB91AFF657}.Release|x86.Build.0 = Release|Any CPU |
| | | EndGlobalSection |
| | | GlobalSection(SolutionProperties) = preSolution |
| | | HideSolutionNode = FALSE |