Avalonia+ASP.NET Core Web API实现设备集中控制平台简单方案
综合设计方案
下面的设计方案结合了设备通信协议的扩展、ASP.NET Core Web API、以及使用 Avalonia 实现跨平台桌面前端。
1. 协议层
定义 ICommunicationProtocol 接口,并为不同的协议创建具体实现。
1 public interface ICommunicationProtocol 2 { 3 void Connect(); 4 void Disconnect(); 5 byte[] ReadData(ushort startAddress, int quantity); 6 void WriteData(ushort startAddress, byte[] data); 7 bool IsConnected { get; } 8 } 9 10 public class ModbusRtuProtocol : ICommunicationProtocol 11 { 12 // 实现接口中的方法 13 public void Connect() { /* ... */ } 14 public void Disconnect() { /* ... */ } 15 public byte[] ReadData(ushort startAddress, int quantity) { /* ... */ return new byte[0]; } 16 public void WriteData(ushort startAddress, byte[] data) { /* ... */ } 17 public bool IsConnected { get; private set; } 18 }
2. 服务层
管理设备和协议实例的服务层。
1 public class DeviceService 2 { 3 private Dictionary<string, ICommunicationProtocol> deviceProtocols = new Dictionary<string, ICommunicationProtocol>(); 4 5 public void AddDevice(string name, ICommunicationProtocol protocol) 6 { 7 deviceProtocols[name] = protocol; 8 } 9 10 public void RemoveDevice(string name) 11 { 12 deviceProtocols.Remove(name); 13 } 14 15 public byte[] ReadData(string deviceName, ushort startAddress, int quantity) 16 { 17 if (deviceProtocols.TryGetValue(deviceName, out var protocol)) 18 { 19 return protocol.ReadData(startAddress, quantity); 20 } 21 throw new Exception("Device not found"); 22 } 23 24 public void WriteData(string deviceName, ushort startAddress, byte[] data) 25 { 26 if (deviceProtocols.TryGetValue(deviceName, out var protocol)) 27 { 28 protocol.WriteData(startAddress, data); 29 } 30 else 31 { 32 throw new Exception("Device not found"); 33 } 34 } 35 36 public void ConnectDevice(string deviceName) 37 { 38 if (deviceProtocols.TryGetValue(deviceName, out var protocol)) 39 { 40 protocol.Connect(); 41 } 42 } 43 44 public void DisconnectDevice(string deviceName) 45 { 46 if (deviceProtocols.TryGetValue(deviceName, out var protocol)) 47 { 48 protocol.Disconnect(); 49 } 50 } 51 }
3. ASP.NET Core Web API
暴露服务层功能的 Web API。
1 [ApiController] 2 [Route("api/[controller]")] 3 public class DeviceController : ControllerBase 4 { 5 private readonly DeviceService _deviceService; 6 7 public DeviceController(DeviceService deviceService) 8 { 9 _deviceService = deviceService; 10 } 11 12 [HttpPost("add-device")] 13 public IActionResult AddDevice(string name, string protocolType) 14 { 15 ICommunicationProtocol protocol = ProtocolFactory.Create(protocolType); // 假设有个工厂类创建协议实例 16 _deviceService.AddDevice(name, protocol); 17 return Ok(); 18 } 19 20 [HttpPost("remove-device")] 21 public IActionResult RemoveDevice(string name) 22 { 23 _deviceService.RemoveDevice(name); 24 return Ok(); 25 } 26 27 [HttpGet("read-data")] 28 public IActionResult ReadData(string deviceName, ushort startAddress, int quantity) 29 { 30 var data = _deviceService.ReadData(deviceName, startAddress, quantity); 31 return Ok(data); 32 } 33 34 [HttpPost("write-data")] 35 public IActionResult WriteData(string deviceName, ushort startAddress, byte[] data) 36 { 37 _deviceService.WriteData(deviceName, startAddress, data); 38 return Ok(); 39 } 40 41 [HttpPost("connect-device")] 42 public IActionResult ConnectDevice(string deviceName) 43 { 44 _deviceService.ConnectDevice(deviceName); 45 return Ok(); 46 } 47 48 [HttpPost("disconnect-device")] 49 public IActionResult DisconnectDevice(string deviceName) 50 { 51 _deviceService.DisconnectDevice(deviceName); 52 return Ok(); 53 } 54 }
4. 前端层(使用 Avalonia)
使用 Avalonia 创建跨平台桌面应用,提供用户界面以与设备交互。
首先,创建一个 Avalonia 项目,然后定义主窗口和视图模型:
MainWindow.axaml:
1 <Window xmlns="https://github.com/avaloniaui" 2 xmlns:d="https://github.com/avaloniaui/designtime" 3 xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 mc:Ignorable="d" 6 x:Class="YourNamespace.MainWindow" 7 Title="Device Control"> 8 <StackPanel> 9 <TextBox Name="DeviceNameTextBox" PlaceholderText="Device Name" /> 10 <ComboBox Name="ProtocolTypeComboBox"> 11 <ComboBoxItem Content="Modbus RTU" /> 12 <ComboBoxItem Content="Another Protocol" /> 13 </ComboBox> 14 <Button Name="AddDeviceButton" Content="Add Device" Click="OnAddDeviceButtonClick" /> 15 <!-- 其他UI元素和绑定 --> 16 </StackPanel> 17 </Window>
MainWindow.axaml.cs:
1 public partial class MainWindow : Window 2 { 3 public MainWindow() 4 { 5 InitializeComponent(); 6 } 7 8 private async void OnAddDeviceButtonClick(object sender, Avalonia.Interactivity.RoutedEventArgs e) 9 { 10 var deviceName = DeviceNameTextBox.Text; 11 var protocolType = (ProtocolTypeComboBox.SelectedItem as ComboBoxItem)?.Content.ToString(); 12 13 using (var client = new HttpClient()) 14 { 15 var response = await client.PostAsync($"http://localhost:5000/api/device/add-device?name={deviceName}&protocolType={protocolType}", null); 16 if (response.IsSuccessStatusCode) 17 { 18 MessageBox.Avalonia.MessageBoxManager.GetMessageBoxStandardWindow("Success", "Device added successfully.").Show(); 19 } 20 } 21 } 22 }
5. 数据展示和图表绘制
在前端,通过HTTP请求获取设备数据,并使用图表库进行绘制(例如使用LiveCharts库)。
DeviceDataChart.axaml:
1 <UserControl xmlns="https://github.com/avaloniaui" 2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 3 xmlns:lvc="clr-namespace:LiveChartsCore.SkiaSharpView.Avalonia;assembly=LiveChartsCore.SkiaSharpView.Avalonia" 4 x:Class="YourNamespace.DeviceDataChart"> 5 <lvc:CartesianChart Series="{Binding Series}" /> 6 </UserControl>
DeviceDataChartViewModel.cs:
1 public class DeviceDataChartViewModel : ReactiveObject 2 { 3 public ObservableCollection<ISeries> Series { get; set; } 4 5 public DeviceDataChartViewModel() 6 { 7 Series = new ObservableCollection<ISeries> 8 { 9 new LineSeries<double> 10 { 11 Values = new ObservableCollection<double> { 3, 5, 7, 4, 2, 6, 3 } 12 } 13 }; 14 } 15 16 public async Task LoadData(string deviceName) 17 { 18 using (var client = new HttpClient()) 19 { 20 var response = await client.GetAsync($"http://localhost:5000/api/device/read-data?deviceName={deviceName}&startAddress=0&quantity=10"); 21 if (response.IsSuccessStatusCode) 22 { 23 var data = await response.Content.ReadAsAsync<byte[]>(); 24 Series[0].Values = data.Select(b => (double)b).ToArray(); 25 } 26 } 27 } 28 }
总结
协议层:使用接口和具体实现,支持多种设备协议。
服务层:管理设备和协议实例。
Web API:提供统一的接口供前端调用。
前端层:使用 Avalonia 创建跨平台桌面应用,展示设备数据并提供用户交互功能。
这种设计模式结合了可扩展性、跨平台支持和易用性,满足了集中控制和大规模设备管理的需求。