From 819cc3906b17737718f4b436e15fce5676b432e1 Mon Sep 17 00:00:00 2001 From: k3ldar Date: Sat, 9 May 2026 15:23:56 +0200 Subject: [PATCH 1/4] Json Safe float values --- PowerControlHub.sln | 14 ++++++++++++++ PowerControlHub/Dht11SensorHandler.h | 22 +++++++++++----------- PowerControlHub/GpsSensorHandler.h | 23 ++++++++++++----------- PowerControlHub/SystemFunctions.cpp | 15 +++++++++++++++ PowerControlHub/SystemFunctions.h | 14 ++++++++++++++ 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/PowerControlHub.sln b/PowerControlHub.sln index 290cc91..0b77191 100644 --- a/PowerControlHub.sln +++ b/PowerControlHub.sln @@ -45,6 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerControlHubApp", "PowerControlHubApp\PowerControlHubApp.csproj", "{9A5A950B-B42B-40DE-BDA7-299184BB23BA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,18 @@ Global {31F2CD6A-B9E7-9FD4-3808-399C52A59619}.Release|ARM.Build.0 = Release|Any CPU {31F2CD6A-B9E7-9FD4-3808-399C52A59619}.Release|ARM64.ActiveCfg = Release|Any CPU {31F2CD6A-B9E7-9FD4-3808-399C52A59619}.Release|ARM64.Build.0 = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|ARM.Build.0 = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Debug|ARM64.Build.0 = Debug|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|Any CPU.Build.0 = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|ARM.ActiveCfg = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|ARM.Build.0 = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|ARM64.ActiveCfg = Release|Any CPU + {9A5A950B-B42B-40DE-BDA7-299184BB23BA}.Release|ARM64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PowerControlHub/Dht11SensorHandler.h b/PowerControlHub/Dht11SensorHandler.h index c1bd0c8..781655a 100644 --- a/PowerControlHub/Dht11SensorHandler.h +++ b/PowerControlHub/Dht11SensorHandler.h @@ -250,24 +250,24 @@ class Dht11SensorHandler : public BaseSensor, public BroadcastLoggerSupport void formatStatusJson(char* buffer, size_t size) override { - // Validate output buffer + // Validate output buffer if (!buffer || size == 0) { return; } - char celsius[8]; - char humidity[8]; - char celsiusOffset[8]; - char humidityOffset[8]; - dtostrf(_celsius, 1, 1, celsius); - dtostrf(_humidity, 1, 1, humidity); - dtostrf(_temperatureOffset, 1, 1, celsiusOffset); - dtostrf(_humidityOffset, 1, 1, humidityOffset); + char celsius[16]; + char humidity[16]; + char celsiusOffset[16]; + char humidityOffset[16]; + SystemFunctions::safeJsonFloat(_celsius, celsius, sizeof(celsius), 1); + SystemFunctions::safeJsonFloat(_humidity, humidity, sizeof(humidity), 1); + SystemFunctions::safeJsonFloat(_temperatureOffset, celsiusOffset, sizeof(celsiusOffset), 1); + SystemFunctions::safeJsonFloat(_humidityOffset, humidityOffset,sizeof(humidityOffset), 1); double dewPt = Environment::dewPoint(_celsius, _humidity); - char dewPointStr[8]; - dtostrf(dewPt, 1, 1, dewPointStr); + char dewPointStr[16]; + SystemFunctions::safeJsonFloat(static_cast(dewPt), dewPointStr, sizeof(dewPointStr), 1); char comfortBuf[24]; strncpy_P(comfortBuf, Environment::getComfortDescription(_celsius, _humidity, dewPt), sizeof(comfortBuf)); diff --git a/PowerControlHub/GpsSensorHandler.h b/PowerControlHub/GpsSensorHandler.h index bd09967..b782d4f 100644 --- a/PowerControlHub/GpsSensorHandler.h +++ b/PowerControlHub/GpsSensorHandler.h @@ -28,6 +28,7 @@ #include "BaseSensor.h" #include "DateTimeManager.h" #include "SensorCommandHandler.h" +#include "SystemFunctions.h" constexpr unsigned long GpsCheckMs = 10; constexpr unsigned long StatusUpdateMs = 1000UL; @@ -422,17 +423,17 @@ class GpsSensorHandler : public BaseSensor, public BroadcastLoggerSupport { char lat[16]; char lon[16]; - char alt[12]; - char speed[12]; - char course[12]; - - dtostrf(_latitude, 1, 6, lat); - dtostrf(_longitude, 1, 6, lon); - dtostrf(_altitude, 1, 2, alt); - dtostrf(_speedKmh, 1, 2, speed); - dtostrf(_courseDeg, 1, 2, course); - - snprintf_P(buffer, size, + char alt[16]; + char speed[16]; + char course[16]; + + SystemFunctions::safeJsonFloat(static_cast(_latitude), lat, sizeof(lat), 6); + SystemFunctions::safeJsonFloat(static_cast(_longitude), lon, sizeof(lon), 6); + SystemFunctions::safeJsonFloat(static_cast(_altitude), alt, sizeof(alt), 2); + SystemFunctions::safeJsonFloat(static_cast(_speedKmh), speed, sizeof(speed), 2); + SystemFunctions::safeJsonFloat(static_cast(_courseDeg), course, sizeof(course), 2); + + snprintf_P(buffer, size, PSTR("\"gps\":{\"lat\":%s,\"lon\":%s,\"alt\":%s,\"speed\":%s,\"course\":%s,\"sats\":%lu,\"valid\":%s}"), lat, lon, alt, speed, course, _satellites, _hasValidFix ? "true" : "false"); } diff --git a/PowerControlHub/SystemFunctions.cpp b/PowerControlHub/SystemFunctions.cpp index 4b59f2e..c8fb417 100644 --- a/PowerControlHub/SystemFunctions.cpp +++ b/PowerControlHub/SystemFunctions.cpp @@ -607,4 +607,19 @@ void SystemFunctions::formatTimeParts(char* buffer, size_t bufferSize, const Tim (unsigned)timeparts.hours, (unsigned)timeparts.minutes, (unsigned)timeparts.seconds); +} + +void SystemFunctions::safeJsonFloat(float value, char* output, size_t outputSize, uint8_t decimals) +{ + if (!output || outputSize == 0) + return; + + if (isnan(value) || isinf(value)) + { + strncpy(output, "null", outputSize); + output[outputSize - 1] = '\0'; + return; + } + + dtostrf(value, 1, decimals, output); } \ No newline at end of file diff --git a/PowerControlHub/SystemFunctions.h b/PowerControlHub/SystemFunctions.h index 0da3865..7bfa50e 100644 --- a/PowerControlHub/SystemFunctions.h +++ b/PowerControlHub/SystemFunctions.h @@ -353,6 +353,20 @@ class SystemFunctions */ static void sanitizeJsonString(const char* input, char* output, size_t outputSize); + /** + * @brief Format a float as a JSON number, emitting null for non-finite values. + * + * IEEE 754 special values (NaN, +Inf, -Inf) are not valid JSON numbers. + * This helper emits the literal `null` for any non-finite value so that + * the output is always valid JSON. + * + * @param value The float value to format. + * @param output Destination buffer. + * @param outputSize Size of destination buffer including null terminator. + * @param decimals Number of decimal places (passed to dtostrf). + */ + static void safeJsonFloat(float value, char* output, size_t outputSize, uint8_t decimals = 2); + /** * @brief Escape a string for safe embedding in HTML content. * From 3d6b02a052faa8d1046a2cd9cbb1c65f3a57f6d5 Mon Sep 17 00:00:00 2001 From: k3ldar Date: Sat, 9 May 2026 15:28:46 +0200 Subject: [PATCH 2/4] Start of PowerControlHubApp early work in progress --- PowerControlHubApp/App.xaml | 15 + PowerControlHubApp/App.xaml.cs | 66 +++ PowerControlHubApp/AppShell.xaml | 22 + PowerControlHubApp/AppShell.xaml.cs | 10 + .../Converters/ValueConverters.cs | 43 ++ PowerControlHubApp/MainPage.xaml | 36 ++ PowerControlHubApp/MainPage.xaml.cs | 24 + PowerControlHubApp/MauiProgram.cs | 49 ++ PowerControlHubApp/Models/LogEntry.cs | 24 + PowerControlHubApp/Models/OtaStatusModel.cs | 52 +++ PowerControlHubApp/Models/RelayModel.cs | 66 +++ PowerControlHubApp/Models/SensorModel.cs | 281 ++++++++++++ PowerControlHubApp/Models/SensorType.cs | 17 + .../Platforms/Android/AndroidManifest.xml | 6 + .../Platforms/Android/MainActivity.cs | 11 + .../Platforms/Android/MainApplication.cs | 16 + .../Android/Resources/values/colors.xml | 6 + .../Platforms/MacCatalyst/AppDelegate.cs | 10 + .../Platforms/MacCatalyst/Entitlements.plist | 14 + .../Platforms/MacCatalyst/Info.plist | 40 ++ .../Platforms/MacCatalyst/Program.cs | 17 + PowerControlHubApp/Platforms/Windows/App.xaml | 8 + .../Platforms/Windows/App.xaml.cs | 25 + .../Platforms/Windows/Package.appxmanifest | 46 ++ .../Platforms/Windows/app.manifest | 17 + .../Platforms/iOS/AppDelegate.cs | 10 + PowerControlHubApp/Platforms/iOS/Info.plist | 32 ++ PowerControlHubApp/Platforms/iOS/Program.cs | 17 + .../iOS/Resources/PrivacyInfo.xcprivacy | 51 ++ PowerControlHubApp/PowerControlHubApp.csproj | 112 +++++ .../Resources/AppIcon/appicon.svg | 4 + .../Resources/AppIcon/appiconfg.svg | 8 + .../Resources/Fonts/OpenSans-Regular.ttf | Bin 0 -> 107280 bytes .../Resources/Fonts/OpenSans-Semibold.ttf | Bin 0 -> 111204 bytes .../Resources/Images/dotnet_bot.png | Bin 0 -> 92532 bytes .../Resources/Raw/AboutAssets.txt | 15 + .../Resources/Splash/splash.svg | 8 + .../Resources/Styles/AppColorsDark.xaml | 29 ++ .../Resources/Styles/AppColorsDark.xaml.cs | 6 + .../Resources/Styles/AppColorsLight.xaml | 29 ++ .../Resources/Styles/AppColorsLight.xaml.cs | 6 + .../Resources/Styles/Colors.xaml | 44 ++ .../Resources/Styles/Styles.xaml | 434 ++++++++++++++++++ PowerControlHubApp/Services/LogService.cs | 55 +++ .../Services/PowerHubService.cs | 218 +++++++++ PowerControlHubApp/Services/ThemeService.cs | 101 ++++ .../ViewModels/DashboardViewModel.cs | 331 +++++++++++++ .../ViewModels/SettingsViewModel.cs | 92 ++++ PowerControlHubApp/Views/DashboardPage.xaml | 344 ++++++++++++++ .../Views/DashboardPage.xaml.cs | 51 ++ PowerControlHubApp/Views/SettingsPage.xaml | 120 +++++ PowerControlHubApp/Views/SettingsPage.xaml.cs | 17 + .../BinaryPresenceSensorTemplate.xaml | 26 ++ .../BinaryPresenceSensorTemplate.xaml.cs | 6 + .../Views/Templates/Dht11SensorTemplate.xaml | 53 +++ .../Templates/Dht11SensorTemplate.xaml.cs | 6 + .../Templates/GenericSensorTemplate.xaml | 19 + .../Templates/GenericSensorTemplate.xaml.cs | 6 + .../Views/Templates/GpsSensorTemplate.xaml | 60 +++ .../Views/Templates/GpsSensorTemplate.xaml.cs | 6 + .../Views/Templates/LightSensorTemplate.xaml | 44 ++ .../Templates/LightSensorTemplate.xaml.cs | 6 + .../Views/Templates/SensorTemplateSelector.cs | 37 ++ .../Views/Templates/SystemSensorTemplate.xaml | 33 ++ .../Templates/SystemSensorTemplate.xaml.cs | 6 + .../Templates/VoltageSensorTemplate.xaml | 34 ++ .../Templates/VoltageSensorTemplate.xaml.cs | 6 + .../Views/Templates/WaterSensorTemplate.xaml | 34 ++ .../Templates/WaterSensorTemplate.xaml.cs | 6 + 69 files changed, 3443 insertions(+) create mode 100644 PowerControlHubApp/App.xaml create mode 100644 PowerControlHubApp/App.xaml.cs create mode 100644 PowerControlHubApp/AppShell.xaml create mode 100644 PowerControlHubApp/AppShell.xaml.cs create mode 100644 PowerControlHubApp/Converters/ValueConverters.cs create mode 100644 PowerControlHubApp/MainPage.xaml create mode 100644 PowerControlHubApp/MainPage.xaml.cs create mode 100644 PowerControlHubApp/MauiProgram.cs create mode 100644 PowerControlHubApp/Models/LogEntry.cs create mode 100644 PowerControlHubApp/Models/OtaStatusModel.cs create mode 100644 PowerControlHubApp/Models/RelayModel.cs create mode 100644 PowerControlHubApp/Models/SensorModel.cs create mode 100644 PowerControlHubApp/Models/SensorType.cs create mode 100644 PowerControlHubApp/Platforms/Android/AndroidManifest.xml create mode 100644 PowerControlHubApp/Platforms/Android/MainActivity.cs create mode 100644 PowerControlHubApp/Platforms/Android/MainApplication.cs create mode 100644 PowerControlHubApp/Platforms/Android/Resources/values/colors.xml create mode 100644 PowerControlHubApp/Platforms/MacCatalyst/AppDelegate.cs create mode 100644 PowerControlHubApp/Platforms/MacCatalyst/Entitlements.plist create mode 100644 PowerControlHubApp/Platforms/MacCatalyst/Info.plist create mode 100644 PowerControlHubApp/Platforms/MacCatalyst/Program.cs create mode 100644 PowerControlHubApp/Platforms/Windows/App.xaml create mode 100644 PowerControlHubApp/Platforms/Windows/App.xaml.cs create mode 100644 PowerControlHubApp/Platforms/Windows/Package.appxmanifest create mode 100644 PowerControlHubApp/Platforms/Windows/app.manifest create mode 100644 PowerControlHubApp/Platforms/iOS/AppDelegate.cs create mode 100644 PowerControlHubApp/Platforms/iOS/Info.plist create mode 100644 PowerControlHubApp/Platforms/iOS/Program.cs create mode 100644 PowerControlHubApp/Platforms/iOS/Resources/PrivacyInfo.xcprivacy create mode 100644 PowerControlHubApp/PowerControlHubApp.csproj create mode 100644 PowerControlHubApp/Resources/AppIcon/appicon.svg create mode 100644 PowerControlHubApp/Resources/AppIcon/appiconfg.svg create mode 100644 PowerControlHubApp/Resources/Fonts/OpenSans-Regular.ttf create mode 100644 PowerControlHubApp/Resources/Fonts/OpenSans-Semibold.ttf create mode 100644 PowerControlHubApp/Resources/Images/dotnet_bot.png create mode 100644 PowerControlHubApp/Resources/Raw/AboutAssets.txt create mode 100644 PowerControlHubApp/Resources/Splash/splash.svg create mode 100644 PowerControlHubApp/Resources/Styles/AppColorsDark.xaml create mode 100644 PowerControlHubApp/Resources/Styles/AppColorsDark.xaml.cs create mode 100644 PowerControlHubApp/Resources/Styles/AppColorsLight.xaml create mode 100644 PowerControlHubApp/Resources/Styles/AppColorsLight.xaml.cs create mode 100644 PowerControlHubApp/Resources/Styles/Colors.xaml create mode 100644 PowerControlHubApp/Resources/Styles/Styles.xaml create mode 100644 PowerControlHubApp/Services/LogService.cs create mode 100644 PowerControlHubApp/Services/PowerHubService.cs create mode 100644 PowerControlHubApp/Services/ThemeService.cs create mode 100644 PowerControlHubApp/ViewModels/DashboardViewModel.cs create mode 100644 PowerControlHubApp/ViewModels/SettingsViewModel.cs create mode 100644 PowerControlHubApp/Views/DashboardPage.xaml create mode 100644 PowerControlHubApp/Views/DashboardPage.xaml.cs create mode 100644 PowerControlHubApp/Views/SettingsPage.xaml create mode 100644 PowerControlHubApp/Views/SettingsPage.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/BinaryPresenceSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/BinaryPresenceSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/Dht11SensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/Dht11SensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/GenericSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/GenericSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/GpsSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/GpsSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/LightSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/LightSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/SensorTemplateSelector.cs create mode 100644 PowerControlHubApp/Views/Templates/SystemSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/SystemSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/VoltageSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/VoltageSensorTemplate.xaml.cs create mode 100644 PowerControlHubApp/Views/Templates/WaterSensorTemplate.xaml create mode 100644 PowerControlHubApp/Views/Templates/WaterSensorTemplate.xaml.cs diff --git a/PowerControlHubApp/App.xaml b/PowerControlHubApp/App.xaml new file mode 100644 index 0000000..a96558e --- /dev/null +++ b/PowerControlHubApp/App.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/PowerControlHubApp/App.xaml.cs b/PowerControlHubApp/App.xaml.cs new file mode 100644 index 0000000..aab35de --- /dev/null +++ b/PowerControlHubApp/App.xaml.cs @@ -0,0 +1,66 @@ +using Microsoft.Extensions.DependencyInjection; +using PowerControlHubApp.Services; + +namespace PowerControlHubApp +{ + public partial class App : Application + { + public App(ThemeService themeService) + { + InitializeComponent(); + // Apply after InitializeComponent so Application.Resources is populated. + themeService.ApplySaved(); + } + + protected override Window CreateWindow(IActivationState? activationState) + { + var window = new Window(new AppShell()); + +#if WINDOWS + window.HandlerChanged += OnWindowHandlerChanged; +#endif + + return window; + } + +#if WINDOWS + private static void OnWindowHandlerChanged(object? sender, EventArgs e) + { + if (sender is not Window mauiWindow) + return; + + // Detach — only needs to run once + mauiWindow.HandlerChanged -= OnWindowHandlerChanged; + + if (mauiWindow.Handler?.PlatformView is not Microsoft.UI.Xaml.Window nativeWindow) + return; + + var appWindow = nativeWindow.AppWindow; + + // Restore saved position and size (stored in physical pixels) + int savedW = Preferences.Get("win_w", 0); + int savedH = Preferences.Get("win_h", 0); + int savedX = Preferences.Get("win_x", int.MinValue); + int savedY = Preferences.Get("win_y", int.MinValue); + + if (savedW > 0 && savedH > 0) + appWindow.Resize(new Windows.Graphics.SizeInt32(savedW, savedH)); + + if (savedX != int.MinValue && savedY != int.MinValue) + appWindow.Move(new Windows.Graphics.PointInt32(savedX, savedY)); + + // Persist position/size whenever the window moves or is resized + appWindow.Changed += (aw, args) => + { + if (!args.DidPositionChange && !args.DidSizeChange) + return; + + Preferences.Set("win_x", aw.Position.X); + Preferences.Set("win_y", aw.Position.Y); + Preferences.Set("win_w", aw.Size.Width); + Preferences.Set("win_h", aw.Size.Height); + }; + } +#endif + } +} diff --git a/PowerControlHubApp/AppShell.xaml b/PowerControlHubApp/AppShell.xaml new file mode 100644 index 0000000..2ecf608 --- /dev/null +++ b/PowerControlHubApp/AppShell.xaml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/PowerControlHubApp/AppShell.xaml.cs b/PowerControlHubApp/AppShell.xaml.cs new file mode 100644 index 0000000..c54287f --- /dev/null +++ b/PowerControlHubApp/AppShell.xaml.cs @@ -0,0 +1,10 @@ +namespace PowerControlHubApp +{ + public partial class AppShell : Shell + { + public AppShell() + { + InitializeComponent(); + } + } +} diff --git a/PowerControlHubApp/Converters/ValueConverters.cs b/PowerControlHubApp/Converters/ValueConverters.cs new file mode 100644 index 0000000..082a30e --- /dev/null +++ b/PowerControlHubApp/Converters/ValueConverters.cs @@ -0,0 +1,43 @@ +using System.Globalization; + +namespace PowerControlHubApp.Converters; + +/// Returns true when the integer value is greater than zero. +public class IntToBoolConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value is int i && i > 0; + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => throw new NotImplementedException(); +} + +/// Returns true when the integer value equals zero (inverse of IntToBoolConverter). +public class IntToInverseBoolConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value is not int i || i == 0; + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => throw new NotImplementedException(); +} + +/// Returns true when the string is non-empty. +public class StringToBoolConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value is string s && !string.IsNullOrEmpty(s); + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => throw new NotImplementedException(); +} + +/// Returns a green colour for true (connected) and a red colour for false (disconnected). +public class BoolToStatusColorConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + => value is true ? Color.FromArgb("#44cc44") : Color.FromArgb("#cc4444"); + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => throw new NotImplementedException(); +} diff --git a/PowerControlHubApp/MainPage.xaml b/PowerControlHubApp/MainPage.xaml new file mode 100644 index 0000000..0fd8e0e --- /dev/null +++ b/PowerControlHubApp/MainPage.xaml @@ -0,0 +1,36 @@ + + + + + + + +