implemented evaluation of ip addresses

This commit is contained in:
Holger Börchers 2023-11-17 21:21:54 +01:00
parent b393146e58
commit cf924f7b2a
12 changed files with 192 additions and 100 deletions

13
.idea/.idea.SddpViewer/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/projectSettingsUpdater.xml
/.idea.SddpViewer.iml
/contentModel.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AvaloniaProject">
<option name="projectPerEditor">
<map>
<entry key="MainWindow.axaml" value="SddpViewer.csproj" />
</map>
</option>
</component>
</project>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

6
.idea/.idea.SddpViewer/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -20,4 +20,4 @@ public partial class App : Application
base.OnFrameworkInitializationCompleted();
}
}
}

View File

@ -1,53 +1,53 @@
namespace SddpViewer
{
using System;
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Rssdp;
using Rssdp;
public partial class DiscoveredDeviceViewModel : ObservableObject
{
private readonly DiscoveredSsdpDevice device;
public DiscoveredDeviceViewModel(DiscoveredSsdpDevice device)
public partial class DiscoveredDeviceViewModel : ObservableObject
{
this.device = device;
private readonly DiscoveredSsdpDevice device;
public DiscoveredDeviceViewModel(DiscoveredSsdpDevice device)
{
this.device = device;
}
/// <summary>
/// Sets or returns the type of notification, being either a uuid, device type, service type or upnp:rootdevice.
/// </summary>
public string NotificationType => this.device.NotificationType;
/// <summary>
/// Sets or returns the universal service name (USN) of the device.
/// </summary>
public string Usn => this.device.Usn;
/// <summary>
/// Sets or returns a URL pointing to the device description document for this device.
/// </summary>
public Uri DescriptionLocation => this.device.DescriptionLocation;
/// <summary>
/// Sets or returns the length of time this information is valid for (from the <see cref="P:Rssdp.DiscoveredSsdpDevice.AsAt" /> time).
/// </summary>
public TimeSpan CacheLifetime => this.device.CacheLifetime;
/// <summary>
/// Sets or returns the date and time this information was received.
/// </summary>
public DateTimeOffset AsAt => this.device.AsAt;
[ObservableProperty]
private string _friendlyName = "";
public async Task GetFurtherInformationAsync()
{
var ssdpDevice = await this.device.GetDeviceInfo().ConfigureAwait(false);
FriendlyName = ssdpDevice.FriendlyName;
}
}
/// <summary>
/// Sets or returns the type of notification, being either a uuid, device type, service type or upnp:rootdevice.
/// </summary>
public string NotificationType => this.device.NotificationType;
/// <summary>
/// Sets or returns the universal service name (USN) of the device.
/// </summary>
public string Usn => this.device.Usn;
/// <summary>
/// Sets or returns a URL pointing to the device description document for this device.
/// </summary>
public Uri DescriptionLocation => this.device.DescriptionLocation;
/// <summary>
/// Sets or returns the length of time this information is valid for (from the <see cref="P:Rssdp.DiscoveredSsdpDevice.AsAt" /> time).
/// </summary>
public TimeSpan CacheLifetime => this.device.CacheLifetime;
/// <summary>
/// Sets or returns the date and time this information was received.
/// </summary>
public DateTimeOffset AsAt => this.device.AsAt;
[ObservableProperty]
private string _friendlyName = "";
public async Task GetFurtherInformationAsync()
{
var ssdpDevice = await this.device.GetDeviceInfo().ConfigureAwait(false);
FriendlyName = ssdpDevice.FriendlyName;
}
}
}
}

View File

@ -1,35 +1,34 @@
<Window
x:Class="SddpViewer.MainWindow"
xmlns="https://github.com/avaloniaui"
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:sddpViewer="clr-namespace:SddpViewer"
Title="SDDP viewer"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d"
x:Class="SddpViewer.MainWindow"
x:CompileBindings="True"
x:DataType="sddpViewer:MainWindowViewModel"
mc:Ignorable="d">
xmlns="https://github.com/avaloniaui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sddpViewer="clr-namespace:SddpViewer"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.DataContext>
<sddpViewer:MainWindowViewModel />
</Window.DataContext>
<Grid RowDefinitions="Auto, *">
<StackPanel Margin="10" Spacing="5">
<TextBlock Text="Settings" />
<TextBox
Text="{Binding DeviceIpAddress}"
UseFloatingWatermark="True"
Watermark="Device IP Address" />
<TextBox
Text="{Binding NotificationFilter}"
UseFloatingWatermark="True"
Watermark="Notification filter" />
<TextBlock Text="Device IP Address" />
<ComboBox
DisplayMemberBinding="{Binding DisplayName}"
HorizontalAlignment="Stretch"
ItemsSource="{Binding NetworkAdapters}"
SelectedItem="{Binding SelectedNetworkAdapter}" />
<TextBlock Text="Notification filter" />
<TextBox Text="{Binding NotificationFilter}" />
<Button Command="{Binding SearchDevicesNowCommand}" Content="Search now" />
</StackPanel>
<DataGrid
Grid.Row="1"
AutoGenerateColumns="True"
Grid.Row="1"
IsReadOnly="True"
ItemsSource="{Binding SddpDevices}" />
</Grid>

View File

@ -8,4 +8,4 @@ public partial class MainWindow : Window
{
InitializeComponent();
}
}
}

View File

@ -1,4 +1,10 @@
namespace SddpViewer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace SddpViewer;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
@ -10,35 +16,53 @@ using Rssdp;
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private string _deviceIpAddress = "192.168.42.193";
[ObservableProperty]
private string _notificationFilter = "upnp:rootdevice";
public ObservableCollection<DiscoveredDeviceViewModel> SddpDevices { get; } = new();
[RelayCommand(AllowConcurrentExecutions = false)]
private async Task SearchDevicesNowAsync()
{
SddpDevices.Clear();
var locator = new SsdpDeviceLocator(DeviceIpAddress);
if (!string.IsNullOrWhiteSpace(NotificationFilter))
public MainWindowViewModel()
{
locator.NotificationFilter = NotificationFilter;
NetworkAdapters = NetworkAdapter.GetAvailableNetworkAdapter().ToArray();
SelectedNetworkAdapter = NetworkAdapters.FirstOrDefault();
}
var availableDevices = await locator.SearchAsync().ConfigureAwait(true);
foreach (var ssdpDevice in availableDevices)
[ObservableProperty]
private IReadOnlyList<NetworkAdapter> _networkAdapters;
[ObservableProperty]
private NetworkAdapter? _selectedNetworkAdapter;
[ObservableProperty]
private string _deviceIpAddress = "192.168.42.193";
[ObservableProperty]
private string _notificationFilter = "upnp:rootdevice";
public ObservableCollection<DiscoveredDeviceViewModel> SddpDevices { get; } = new();
[RelayCommand(AllowConcurrentExecutions = false)]
private async Task SearchDevicesNowAsync()
{
var discoveredDeviceViewModel = new DiscoveredDeviceViewModel(ssdpDevice);
SddpDevices.Add(discoveredDeviceViewModel);
SddpDevices.Clear();
if (SelectedNetworkAdapter is null)
{
throw new NotSupportedException();
}
var locator = new SsdpDeviceLocator(SelectedNetworkAdapter.IpAddress.ToString());
if (!string.IsNullOrWhiteSpace(NotificationFilter))
{
locator.NotificationFilter = NotificationFilter;
}
var availableDevices = await locator.SearchAsync().ConfigureAwait(true);
foreach (var ssdpDevice in availableDevices)
{
var discoveredDeviceViewModel = new DiscoveredDeviceViewModel(ssdpDevice);
SddpDevices.Add(discoveredDeviceViewModel);
}
await Parallel
.ForEachAsync(
SddpDevices,
async (device, token) =>
{
await device.GetFurtherInformationAsync().ConfigureAwait(true);
}
)
.ConfigureAwait(true);
}
await Parallel.ForEachAsync(
SddpDevices,
async (device, token) =>
{
await device.GetFurtherInformationAsync().ConfigureAwait(true);
}
).ConfigureAwait(true);
}
}

31
NetworkAdapter.cs Normal file
View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
namespace SddpViewer;
public record NetworkAdapter(string Name, IPAddress IpAddress)
{
public string DisplayName => $"{Name} - {IpAddress}";
public static IEnumerable<NetworkAdapter> GetAvailableNetworkAdapter()
{
foreach (var nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
if (nic.NetworkInterfaceType == NetworkInterfaceType.Loopback)
continue;
var physicalAddress = nic.GetIPProperties()
.UnicastAddresses.FirstOrDefault(
x => x.Address.AddressFamily == AddressFamily.InterNetwork
);
if (physicalAddress is not null)
{
yield return new NetworkAdapter(nic.Name, physicalAddress.Address);
}
}
}
}

View File

@ -9,13 +9,10 @@ class Program
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
public static void Main(string[] args) =>
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>().UsePlatformDetect().WithInterFont().LogToTrace();
}