SampleSmart 1.0.0.0
SampleSmart 사용 방법을 보여 주는 예제 프로젝트입니다.
로딩중...
검색중...
일치하는것 없음
IoSampleRuntime.cs
이 파일의 문서화 페이지로 가기
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3using System.Runtime.CompilerServices;
4using System.Text;
5using Dreamine.IO.Abstractions.Models;
6using Dreamine.IO.Fastech.Ethernet.Controllers;
7using Dreamine.IO.Fastech.Ethernet.Options;
8using Dreamine.IO.Fastech.Ethernet.Protocol;
9using Dreamine.IO.Fastech.Ethernet.Transport;
10
12
21public sealed class IoSampleRuntime : INotifyPropertyChanged, IAsyncDisposable
22{
31 private readonly SampleFastech16PointTransport _transport = new();
40 private FastechEthernetIoController? _controller;
49 private UdpFastechEthernetIoTransport? _realTransport;
58 private FastechPlusE16PointProtocol? _realProtocol;
67 private string _statusMessage = "Ready. Use Real UDP Controller for hardware, or Sample Controller for UI-only testing.";
76 private bool _isConnected;
85 private bool _isSampleMode;
86
96 {
97 Inputs = new ObservableCollection<IoPointState>(
98 Enumerable.Range(0, 16).Select(i => new IoPointState(0, i, $"DI{i:00}")));
99
100 Outputs = new ObservableCollection<IoPointState>(
101 Enumerable.Range(0, 16).Select(i => new IoPointState(0, i, $"DO{i:00}")));
102 }
103
112 public event PropertyChangedEventHandler? PropertyChanged;
113
122 public ObservableCollection<IoPointState> Inputs { get; }
123
132 public ObservableCollection<IoPointState> Outputs { get; }
133
142 public string Host { get; set; } = "192.168.0.10";
143
152 public string PortText { get; set; } = "3001";
153
162 public string StatusMessage
163 {
164 get => _statusMessage;
165 private set
166 {
167 if (_statusMessage == value)
168 {
169 return;
170 }
171
172 _statusMessage = value;
174 }
175 }
176
185 public bool IsConnected
186 {
187 get => _isConnected;
188 private set
189 {
190 if (_isConnected == value)
191 {
192 return;
193 }
194
195 _isConnected = value;
197 }
198 }
199
209 {
210 _controller = new FastechEthernetIoController(
214
215 _realTransport = null;
216 _realProtocol = null;
217 _isSampleMode = true;
218 IsConnected = false;
219 StatusMessage = "Sample Fastech Ethernet 16/16 controller selected.";
220 }
221
230 public void UseRealController()
231 {
232 var options = CreateOptions();
233 _realTransport = new UdpFastechEthernetIoTransport(options);
234 _realProtocol = new FastechPlusE16PointProtocol();
235 _controller = new FastechEthernetIoController(options, _realTransport, _realProtocol);
236
237 _isSampleMode = false;
238 IsConnected = false;
239 StatusMessage = $"Real Fastech Ezi-IO Plus-E UDP controller selected. Target={Host}:{PortText}.";
240 }
241
258 public async Task ConnectAsync()
259 {
261
262 if (_controller is null)
263 {
264 return;
265 }
266
267 var result = await _controller.ConnectAsync();
268 IsConnected = result.IsSuccess;
269 StatusMessage = result.IsSuccess
270 ? $"Fastech {GetModeText()} controller connected. Use Probe or Read DI to confirm device response."
271 : result.Message ?? $"Failed to connect the Fastech {GetModeText()} controller.";
272 }
273
290 public async Task DisconnectAsync()
291 {
292 if (_controller is null)
293 {
294 return;
295 }
296
297 var result = await _controller.DisconnectAsync();
298 IsConnected = false;
299 StatusMessage = result.IsSuccess
300 ? $"Fastech {GetModeText()} controller disconnected."
301 : result.Message ?? $"Failed to disconnect the Fastech {GetModeText()} controller.";
302 }
303
320 public async Task ProbeHardwareAsync()
321 {
322 if (_isSampleMode || _realTransport is null || _realProtocol is null)
323 {
325 }
326
327 if (!IsConnected)
328 {
329 await ConnectAsync();
330 }
331
332 if (_realTransport is null || _realProtocol is null)
333 {
334 StatusMessage = "Real Fastech UDP controller is not ready.";
335 return;
336 }
337
338 var request = _realProtocol.BuildGetSlaveInfo();
339 var response = await _realTransport.SendAndReceiveAsync(request, 1000, 0);
340 if (!response.IsSuccess || response.Value is null)
341 {
342 StatusMessage = $"Probe failed: {response.Message}. TX={ToHex(_realTransport.LastRequestFrame)}";
343 return;
344 }
345
346 var info = _realProtocol.ParseSlaveInfo(response.Value);
347 StatusMessage = info.IsSuccess
348 ? $"Probe OK: {info.Value}. TX={ToHex(_realTransport.LastRequestFrame)} RX={ToHex(_realTransport.LastResponseFrame)}"
349 : $"Probe parse failed: {info.Message}. TX={ToHex(_realTransport.LastRequestFrame)} RX={ToHex(_realTransport.LastResponseFrame)}";
350 }
351
368 public async Task RefreshInputsAsync()
369 {
370 if (!EnsureConnected())
371 {
372 return;
373 }
374
375 var points = Inputs
376 .Select(x => new IoPoint(x.Module, x.Channel, x.Name))
377 .ToArray();
378
379 var result = await _controller!.DigitalInputs.ReadAsync(points);
380 if (!result.IsSuccess || result.Value is null)
381 {
382 StatusMessage = result.Message ?? "Failed to refresh digital inputs.";
384 return;
385 }
386
387 ApplyValues(Inputs, result.Value);
388 StatusMessage = $"Digital inputs refreshed from the Fastech {GetModeText()} controller. {GetRawFrameDiagnostics()}";
389 }
390
407 public async Task WriteOutputsAsync()
408 {
409 if (!EnsureConnected())
410 {
411 return;
412 }
413
414 var values = Outputs.ToDictionary(
415 x => new IoPoint(x.Module, x.Channel, x.Name),
416 x => x.Value);
417
418 var result = await _controller!.DigitalOutputs.WriteAsync(values);
419 StatusMessage = result.IsSuccess
420 ? $"Digital outputs written to the Fastech {GetModeText()} controller. {GetRawFrameDiagnostics()}"
421 : result.Message ?? "Failed to write digital outputs.";
422 if (!result.IsSuccess)
423 {
425 }
426 }
427
444 public async Task ReadOutputsAsync()
445 {
446 if (!EnsureConnected())
447 {
448 return;
449 }
450
451 var points = Outputs
452 .Select(x => new IoPoint(x.Module, x.Channel, x.Name))
453 .ToArray();
454
455 var result = await _controller!.DigitalOutputs.ReadAsync(points);
456 if (!result.IsSuccess || result.Value is null)
457 {
458 StatusMessage = result.Message ?? "Failed to read digital outputs.";
460 return;
461 }
462
463 ApplyValues(Outputs, result.Value);
464 StatusMessage = $"Digital outputs read back from the Fastech {GetModeText()} controller. {GetRawFrameDiagnostics()}";
465 }
466
483 public async Task ToggleSampleInputsAsync()
484 {
485 _transport.ToggleInputPattern();
486 await RefreshInputsAsync();
487 }
488
505 public async ValueTask DisposeAsync()
506 {
507 if (_controller is not null)
508 {
509 await _controller.DisposeAsync();
510 }
511
512 await _transport.DisposeAsync();
513 }
514
531 private FastechEthernetIoOptions CreateOptions()
532 {
533 var port = int.TryParse(PortText, out var parsedPort)
534 ? parsedPort
535 : 3001;
536
537 return new FastechEthernetIoOptions
538 {
539 Host = string.IsNullOrWhiteSpace(Host) ? "127.0.0.1" : Host,
540 Port = port,
541 TransportType = Dreamine.IO.Fastech.Ethernet.Options.FastechEthernetIoTransportType.Udp,
542 ExpectedResponseLength = 0
543 };
544 }
545
554 private void EnsureController()
555 {
556 if (_controller is not null)
557 {
558 return;
559 }
560
562 }
563
580 private bool EnsureConnected()
581 {
583
584 if (_controller is null || !IsConnected)
585 {
586 StatusMessage = $"Connect the Fastech {GetModeText()} controller first.";
587 return false;
588 }
589
590 return true;
591 }
592
617 private static void ApplyValues(IReadOnlyList<IoPointState> points, IReadOnlyList<bool> values)
618 {
619 for (var i = 0; i < points.Count && i < values.Count; i++)
620 {
621 points[i].Value = values[i];
622 }
623 }
624
641 private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
642 {
643 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
644 }
645
662 private string GetModeText()
663 {
664 return _isSampleMode ? "sample" : "real UDP";
665 }
666
676 {
677 var diagnostics = GetRawFrameDiagnostics();
678 if (!string.IsNullOrWhiteSpace(diagnostics))
679 {
680 StatusMessage = $"{StatusMessage} {diagnostics}";
681 }
682 }
683
700 private string GetRawFrameDiagnostics()
701 {
702 return _realTransport is null || _isSampleMode
703 ? string.Empty
704 : $"TX={ToHex(_realTransport.LastRequestFrame)} RX={ToHex(_realTransport.LastResponseFrame)}";
705 }
706
731 private static string ToHex(IReadOnlyList<byte> bytes)
732 {
733 if (bytes.Count == 0)
734 {
735 return "<none>";
736 }
737
738 var builder = new StringBuilder(bytes.Count * 3);
739 for (var i = 0; i < bytes.Count; i++)
740 {
741 if (i > 0)
742 {
743 builder.Append(' ');
744 }
745
746 builder.Append(bytes[i].ToString("X2"));
747 }
748
749 return builder.ToString();
750 }
751}
ObservableCollection< IoPointState > Outputs
readonly SampleFastech16PointTransport _transport
void OnPropertyChanged([CallerMemberName] string? propertyName=null)
static string ToHex(IReadOnlyList< byte > bytes)
UdpFastechEthernetIoTransport? _realTransport
static void ApplyValues(IReadOnlyList< IoPointState > points, IReadOnlyList< bool > values)
ObservableCollection< IoPointState > Inputs