From 0e75065ff73a5261d3502ab19ee228ee57efd93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20B=C3=B6rchers?= Date: Wed, 2 Apr 2025 15:09:40 +0200 Subject: [PATCH] Many cool stuff --- .editorconfig | 6 +- src/App.axaml.cs | 22 ++-- src/DiscoveredDeviceViewModel.cs | 137 +++++++++++++++---------- src/MainWindow.axaml | 33 ++++-- src/MainWindow.axaml.cs | 8 +- src/MainWindowViewModel.cs | 168 +++++++++++++++++++------------ src/NetworkAdapter.cs | 32 +++--- src/Program.cs | 16 ++- src/SddpViewer.csproj | 18 ++-- 9 files changed, 264 insertions(+), 176 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3eb2a12..5d745b0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,9 +14,9 @@ indent_size = 2 #### Core EditorConfig Options #### # Indentation and spacing -indent_size = 4 -tab_width = 4 - +indent_size = 2 +tab_width = 2 +max_line_length = 140 # New line preferences end_of_line = crlf insert_final_newline = false diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 707af5c..9d3f700 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -5,18 +5,18 @@ namespace SddpViewer; public partial class App : Application { - public override void Initialize() + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - AvaloniaXamlLoader.Load(this); + desktop.MainWindow = new MainWindow(); } - public override void OnFrameworkInitializationCompleted() - { - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - desktop.MainWindow = new MainWindow(); - } - - base.OnFrameworkInitializationCompleted(); - } + base.OnFrameworkInitializationCompleted(); + } } diff --git a/src/DiscoveredDeviceViewModel.cs b/src/DiscoveredDeviceViewModel.cs index 2d694fe..616d53f 100644 --- a/src/DiscoveredDeviceViewModel.cs +++ b/src/DiscoveredDeviceViewModel.cs @@ -1,75 +1,106 @@ -namespace SddpViewer; +using System.Net; + +namespace SddpViewer; using System; using System.Threading.Tasks; - using CommunityToolkit.Mvvm.ComponentModel; - using Rssdp; public partial class DiscoveredDeviceViewModel : ObservableObject { - private readonly DiscoveredSsdpDevice _device; + private readonly DiscoveredSsdpDevice _device; + private SsdpDevice? _ssdpDevice; - public DiscoveredDeviceViewModel(DiscoveredSsdpDevice device) - { - _device = device; - ResponseHeader = GetResponseHeader(); - } + public DiscoveredDeviceViewModel(DiscoveredSsdpDevice device) + { + _device = device; + ResponseHeader = GetResponseHeader(); + DiscoveredAt = DateTime.Now; + IpAddress = EvaluateIpAddress(device); + MacAddress = EvaluateMacAddress(); + HostName = EvaluateHostName(); + } - private string GetResponseHeader() - { - return string.Join( - "," + Environment.NewLine, - _device.ResponseHeaders.Select(x => $"{{{x.Key} : {string.Join(";", x.Value)}}}") - ); - } + public string HostName { get; set; } - public string ResponseHeader { get; } + public string MacAddress { get; set; } - /// - /// Sets or returns the type of notification, being either a uuid, device type, service type or upnp:rootdevice. - /// - public string NotificationType => _device.NotificationType; + public string IpAddress { get; set; } - /// - /// Sets or returns the universal service name (USN) of the device. - /// - public string Usn => _device.Usn; + public DateTime DiscoveredAt { get; } - /// - /// Sets or returns a URL pointing to the device description document for this device. - /// - public Uri DescriptionLocation => _device.DescriptionLocation; + [ObservableProperty] + public partial string ResponseHeader { get; set; } - /// - /// Sets or returns the length of time this information is valid for (from the time). - /// - public TimeSpan CacheLifetime => _device.CacheLifetime; + /// + /// Sets or returns the type of notification, being either a uuid, device type, service type or upnp:rootdevice. + /// + public string NotificationType => _device.NotificationType; - /// - /// Sets or returns the date and time this information was received. - /// - public DateTimeOffset AsAt => _device.AsAt; + /// + /// Sets or returns the universal service name (USN) of the device. + /// + public string Usn => _device.Usn; - [ObservableProperty] - private string _friendlyName = ""; + /// + /// Sets or returns a URL pointing to the device description document for this device. + /// + public Uri DescriptionLocation => _device.DescriptionLocation; - [ObservableProperty] - private SsdpDeviceIcon? _icon; + /// + /// Sets or returns the length of time this information is valid for (from the time). + /// + public TimeSpan CacheLifetime => _device.CacheLifetime; - [ObservableProperty] - private Uri? _presentationUrl; + /// + /// Sets or returns the date and time this information was received. + /// + public DateTimeOffset AsAt => _device.AsAt; - [ObservableProperty] - private string _modelNumber = ""; + [ObservableProperty] + public partial string FriendlyName { get; set; } = ""; - public async Task GetFurtherInformationAsync() - { - var ssdpDevice = await _device.GetDeviceInfo().ConfigureAwait(false); - FriendlyName = ssdpDevice.FriendlyName; - Icon = ssdpDevice.Icons.MinBy(x => x.Height); - PresentationUrl = ssdpDevice.PresentationUrl; - ModelNumber = ssdpDevice.ModelNumber; - } + [ObservableProperty] + public partial SsdpDeviceIcon? Icon { get; set; } + + [ObservableProperty] + public partial Uri? PresentationUrl { get; set; } + + [ObservableProperty] + public partial string ModelNumber { get; set; } = ""; + + [ObservableProperty] + public partial string Version { get; set; } = ""; + + public async Task GetFurtherInformationAsync() + { + _ssdpDevice = await _device.GetDeviceInfo().ConfigureAwait(false); + FriendlyName = _ssdpDevice.ModelDescription; + Icon = _ssdpDevice.Icons.MinBy(x => x.Height); + PresentationUrl = _ssdpDevice.PresentationUrl; + ModelNumber = _ssdpDevice.ModelNumber; + Version = _ssdpDevice.SerialNumber?.Split(',').Last() ?? new Version().ToString(); + HttpClient client = new HttpClient(); + var response = await client.GetAsync(_ssdpDevice.ModelUrl).ConfigureAwait(false); + ResponseHeader = await response.Content.ReadAsStringAsync(); + } + + private string EvaluateHostName() => Dns.GetHostEntry(IpAddress).HostName; + + private string GetResponseHeader() => + string.Join("," + Environment.NewLine, _device.ResponseHeaders.Select(x => $"{{{x.Key} : {string.Join(";", x.Value)}}}")); + + private string EvaluateIpAddress(DiscoveredSsdpDevice device) => device.DescriptionLocation.Host; + + private string EvaluateMacAddress() + { + var lookupResult = ArpLookup.Arp.Lookup(IPAddress.Parse(IpAddress)); + return lookupResult is null ? "Unknown" : string.Join(":", lookupResult.GetAddressBytes().Select(b => $"{b:x2}")); + } + + public override bool Equals(object? obj) + { + return obj is DiscoveredDeviceViewModel viewModel && Equals(viewModel.Usn, Usn); + } } diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index c9ad6bf..e2b8b73 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -14,7 +14,7 @@ - + -