Functional1

This commit is contained in:
audioprog 2025-08-16 06:01:36 +02:00
parent fb4730effe
commit fcacfe127a
4 changed files with 98 additions and 31 deletions

View file

@ -11,7 +11,8 @@
ExtendClientAreaToDecorationsHint="True" ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaTitleBarHeightHint="0"> ExtendClientAreaTitleBarHeightHint="0">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="0">
<Button x:Name="StatusText" Content="Stream" Width="100" Height="50" Click="Button_Click"/> <Button x:Name="StatusText" Content="Stream" Width="70" Height="50" Click="Button_Click"/>
<Button x:Name="SettingsButton" Content="..." Width="30" Height="50" Click="SettingsButton_Click"/>
</StackPanel> </StackPanel>
</Window> </Window>

View file

@ -1,6 +1,8 @@
using System; using System;
using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
@ -9,15 +11,42 @@ namespace HAcontrol;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private Settings? settings = null;
private System.Threading.CancellationTokenSource? _cts; private System.Threading.CancellationTokenSource? _cts;
private static MainWindow self;
public static MainWindow Self => self;
public MainWindow() public MainWindow()
{ {
self = this;
InitializeComponent(); InitializeComponent();
LoadSettings();
_cts = new System.Threading.CancellationTokenSource(); _cts = new System.Threading.CancellationTokenSource();
StartStatePolling(_cts.Token); StartStatePolling(_cts.Token);
} }
public void LoadSettings()
{
if (!File.Exists(SettingsWindow.SettingsFile))
{
// Create default settings file if it does not exist
var defaultSettings = new Settings();
var json = JsonSerializer.Serialize(defaultSettings, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(SettingsWindow.SettingsFile, json);
}
{
var json = File.ReadAllText(SettingsWindow.SettingsFile);
settings = JsonSerializer.Deserialize<Settings>(json);
}
}
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
base.OnClosed(e); base.OnClosed(e);
@ -43,7 +72,14 @@ public partial class MainWindow : Window
private async void Button_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) private async void Button_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
string webhookUrl = "/api/webhook/"; if (settings == null)
{
StatusText.Content = "Einstellungen fehlen!";
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
return;
}
string webhookUrl = $"{settings.HomeAssistantUrl}/api/webhook/{settings.WebhookId}";
string payload = "{\"event\": \"\"}"; string payload = "{\"event\": \"\"}";
// HttpClientHandler to ignore SSL certificate errors (for development only!) // HttpClientHandler to ignore SSL certificate errors (for development only!)
@ -62,37 +98,59 @@ public partial class MainWindow : Window
private async Task GetState() private async Task GetState()
{ {
// HttpClientHandler to ignore SSL certificate errors (for development only!) if (settings == null)
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
using (var client = new HttpClient(handler))
{ {
string statusUrl = "/api/states/"; StatusText.Content = "Einstellungen fehlen!";
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", ""); StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
return;
}
using var response = await client.GetAsync(statusUrl); try
string statusJson = await response.Content.ReadAsStringAsync(); {
// HttpClientHandler to ignore SSL certificate errors (for development only!)
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
// Parse the JSON and extract the state using (var client = new HttpClient(handler))
try
{ {
var jsonDoc = System.Text.Json.JsonDocument.Parse(statusJson); string statusUrl = $"{settings.HomeAssistantUrl}/api/states/{settings.Entity}";
string? state = jsonDoc.RootElement.GetProperty("state").GetString(); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", settings.AccessToken);
string? entity = jsonDoc.RootElement.GetProperty("entity_id").GetString();
StatusText.Content = $"{state}"; using var response = await client.GetAsync(statusUrl);
if (state == "on") string statusJson = await response.Content.ReadAsStringAsync();
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Green);
else if (state == "off") // Parse the JSON and extract the state
try
{
var jsonDoc = System.Text.Json.JsonDocument.Parse(statusJson);
string? state = jsonDoc.RootElement.GetProperty("state").GetString();
string? entity = jsonDoc.RootElement.GetProperty("entity_id").GetString();
StatusText.Content = $"{state}";
if (state == "on")
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Green);
else if (state == "off")
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
else
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Orange);
}
catch
{
StatusText.Content = "Fehler!";
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red); StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
else }
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Orange);
}
catch
{
StatusText.Content = "Fehler!";
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
} }
} }
catch (Exception ex)
{
StatusText.Content = "Fehler!";
StatusText.Foreground = new Avalonia.Media.SolidColorBrush(Avalonia.Media.Colors.Red);
Console.WriteLine($"Error fetching state: {ex.Message}");
}
}
private void SettingsButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
var settingsWindow = new SettingsWindow();
settingsWindow.ShowDialog(this);
} }
} }

View file

@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="HAcontrol.SettingsWindow" x:Class="HAcontrol.SettingsWindow"
Title="Einstellungen" Width="400" Height="250"> Title="Einstellungen" Width="400" Height="340">
<StackPanel Margin="20" Spacing="10"> <StackPanel Margin="20" Spacing="10">
<TextBlock Text="Home Assistant URL:"/> <TextBlock Text="Home Assistant URL:"/>
<TextBox x:Name="UrlBox"/> <TextBox x:Name="UrlBox"/>
@ -11,6 +11,8 @@
<TextBox x:Name="TokenBox"/> <TextBox x:Name="TokenBox"/>
<TextBlock Text="Webhook ID:"/> <TextBlock Text="Webhook ID:"/>
<TextBox x:Name="WebhookBox"/> <TextBox x:Name="WebhookBox"/>
<TextBlock Text="HA Entity:"/>
<TextBox x:Name="EntityBox"/>
<Button Content="Speichern" HorizontalAlignment="Right" Click="Save_Click"/> <Button Content="Speichern" HorizontalAlignment="Right" Click="Save_Click"/>
</StackPanel> </StackPanel>
</Window> </Window>

View file

@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using System;
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
@ -7,7 +8,8 @@ namespace HAcontrol;
public partial class SettingsWindow : Window public partial class SettingsWindow : Window
{ {
private const string SettingsFile = "settings.json"; public static readonly string SettingsFile =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "ha_control_settings.json");
public SettingsWindow() public SettingsWindow()
{ {
@ -26,6 +28,7 @@ public partial class SettingsWindow : Window
UrlBox.Text = settings.HomeAssistantUrl; UrlBox.Text = settings.HomeAssistantUrl;
TokenBox.Text = settings.AccessToken; TokenBox.Text = settings.AccessToken;
WebhookBox.Text = settings.WebhookId; WebhookBox.Text = settings.WebhookId;
EntityBox.Text = settings.Entity;
} }
} }
} }
@ -36,11 +39,14 @@ public partial class SettingsWindow : Window
{ {
HomeAssistantUrl = UrlBox.Text ?? string.Empty, HomeAssistantUrl = UrlBox.Text ?? string.Empty,
AccessToken = TokenBox.Text ?? string.Empty, AccessToken = TokenBox.Text ?? string.Empty,
WebhookId = WebhookBox.Text ?? string.Empty WebhookId = WebhookBox.Text ?? string.Empty,
Entity = EntityBox.Text ?? string.Empty
}; };
var json = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true }); var json = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(SettingsFile, json); File.WriteAllText(SettingsFile, json);
this.Close(); this.Close();
MainWindow.Self.LoadSettings();
} }
} }