Initial commit

This commit is contained in:
Holger Börchers 2023-11-17 15:06:37 +01:00
parent 72bc3dc6c6
commit b393146e58
10 changed files with 262 additions and 0 deletions

12
App.axaml Normal file
View File

@ -0,0 +1,12 @@
<Application
x:Class="SddpViewer.App"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
</Application.Styles>
</Application>

23
App.axaml.cs Normal file
View File

@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace SddpViewer;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
}
base.OnFrameworkInitializationCompleted();
}
}

View File

@ -0,0 +1,53 @@
namespace SddpViewer
{
using System;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Rssdp;
public partial class DiscoveredDeviceViewModel : ObservableObject
{
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;
}
}
}

36
MainWindow.axaml Normal file
View File

@ -0,0 +1,36 @@
<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"
x:CompileBindings="True"
x:DataType="sddpViewer:MainWindowViewModel"
mc:Ignorable="d">
<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" />
<Button Command="{Binding SearchDevicesNowCommand}" Content="Search now" />
</StackPanel>
<DataGrid
Grid.Row="1"
AutoGenerateColumns="True"
IsReadOnly="True"
ItemsSource="{Binding SddpDevices}" />
</Grid>
</Window>

11
MainWindow.axaml.cs Normal file
View File

@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace SddpViewer;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}

44
MainWindowViewModel.cs Normal file
View File

@ -0,0 +1,44 @@
namespace SddpViewer;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
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))
{
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);
}
}

21
Program.cs Normal file
View File

@ -0,0 +1,21 @@
using Avalonia;
using System;
namespace SddpViewer;
class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// 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);
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}

22
SddpViewer.csproj Normal file
View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.5" />
<PackageReference Include="Avalonia.Desktop" Version="11.0.5" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.5" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.5" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="rssdp" Version="4.0.4" />
</ItemGroup>
</Project>

22
SddpViewer.sln Normal file
View File

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SddpViewer", "SddpViewer.csproj", "{8383E1D9-75BD-46D0-B0D5-686AA49EFFF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8383E1D9-75BD-46D0-B0D5-686AA49EFFF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8383E1D9-75BD-46D0-B0D5-686AA49EFFF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8383E1D9-75BD-46D0-B0D5-686AA49EFFF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8383E1D9-75BD-46D0-B0D5-686AA49EFFF1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

18
app.manifest Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="SddpViewer.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>