Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions PowerControlHub/BaseConfigCommandHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include "BaseCommandHandler.h"
#include "ConfigController.h"
#include "ConfigManager.h"
#include "SystemDefinitions.h"
#include "SystemFunctions.h"
Expand Down Expand Up @@ -97,4 +98,35 @@ class BaseConfigCommandHandler
out = SystemFunctions::parseBooleanValue(v);
return true;
}

static const char* configResultToString(ConfigResult result)
{
switch (result)
{
case ConfigResult::Success:
return "Success";
case ConfigResult::InvalidConfig:
return "Invalid config";
case ConfigResult::Failed:
return "Failed";
case ConfigResult::MissingName:
return "Missing name";
case ConfigResult::TooLong:
return "Value too long";
case ConfigResult::InvalidRelay:
return "Invalid relay";
case ConfigResult::InvalidCommand:
return "Invalid command";
case ConfigResult::InvalidParameter:
return "Invalid parameter";
case ConfigResult::BluetoothInitFailed:
return "Bluetooth init failed";
case ConfigResult::WifiInitFailed
: return "WiFi init failed";
case ConfigResult::InvalidPin:
return "Invalid pin";
default:
return "Unknown error";
}
}
};
6 changes: 5 additions & 1 deletion PowerControlHub/ConfigNetworkHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
if (paramCount >= 1)
{
bool enable;

if (!getParamValueBool(params, paramCount, "v", enable))
{
result = ConfigResult::InvalidParameter;
Expand Down Expand Up @@ -922,6 +922,10 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
return CommandResult::ok();
}

snprintf(responseBuffer, bufferSize,
"\"error\":%u,\"message\":\"%s\"",
static_cast<uint8_t>(result),
configResultToString(result));
return CommandResult::error(static_cast<uint8_t>(result));
}

Expand Down
4 changes: 2 additions & 2 deletions PowerControlHub/PowerControlHub.vcxproj

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions PowerControlHubApp/AppShell.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public AppShell()
Routing.RegisterRoute(nameof(LocalSensorDetailPage), typeof(LocalSensorDetailPage));
Routing.RegisterRoute(nameof(TimeSettingsPage), typeof(TimeSettingsPage));
Routing.RegisterRoute(nameof(MqttSettingsPage), typeof(MqttSettingsPage));
Routing.RegisterRoute(nameof(SdCardSettingsPage), typeof(SdCardSettingsPage));
}
}
}
17 changes: 17 additions & 0 deletions PowerControlHubApp/Internal/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ internal static class Constants
public const string RouteSystemGetDateTime = "api/system/F7";
public const string RouteSystemSetDateTime = "api/system/F6";
public const string RouteConfigTimezoneOffset = "api/config/C20";
public const string RouteConfigSdCardSpiPins = "api/config/C4";
public const string RouteConfigSdCardInitSpeed = "api/config/C31";
public const string RouteConfigSdCardCsPin = "api/config/C32";
public const string RouteConfigMqttGet = "api/mqtt/{0}";
public const string RouteConfigMqttSet = "api/mqtt/{0}?v={1}";
public const string MqttConfigEnabled = "M0";
Expand All @@ -212,14 +215,28 @@ internal static class Constants
public const string MqttDisconnectedLabel = "Disconnected";
public const string MqttMsgSaveFailed = "Save failed — device unreachable";
public const string MqttMsgSaved = "MQTT settings saved";
public const string SdCardMsgSaveFailed = "Save failed — device unreachable";
public const string SdCardMsgSaved = "SD Card settings saved";
public const string SdCardMsgPartiallySaved = "⚠ Partially saved — SPI pins rejected (check for pin conflicts)";
public const string SdCardMsgSpiFailed = "⚠ SPI pins not saved (pin conflict or invalid pin)";
public const string SdCardMsgRefreshed = "Refreshed";
public const int SdCardDefaultSpeed = 4;
public const int SdCardPinDisabled = 255;
public const string SdCardConfigSpiPins = "C4";
public const string SdCardConfigInitSpeed = "C31";
public const string SdCardConfigCsPin = "C32";
public const string RouteWarnings = "api/warning/W5";
public const string ForwardSlash = "/";
public const string ResultSuccess = "success";
public const string JsonSpiSckKey = "sck";
public const string JsonSpiMosiKey = "mosi";
public const string JsonSpiMisoKey = "miso";
public const string RouteDashboardPage = "//DashboardPage";
public const string RouteSettingsPage = "//SettingsPage";
public const string RouteSystemPage = "//SystemPage";
public const string RouteTimeSettingsPage = "TimeSettingsPage";
public const string RouteMqttSettingsPage = "MqttSettingsPage";
public const string RouteSdCardSettingsPage = "SdCardSettingsPage";
public const string ConnectionTypeKey = "X-Connection-Type";
public const string ConnectionTypePersistent = "persistent";
public const int MaximumPermanentConnections = 2;
Expand Down
2 changes: 2 additions & 0 deletions PowerControlHubApp/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public static MauiApp CreateMauiApp()
builder.Services.AddTransient<LocalSensorDetailViewModel>();
builder.Services.AddTransient<TimeSettingsViewModel>();
builder.Services.AddTransient<MqttSettingsViewModel>();
builder.Services.AddTransient<SdCardSettingsViewModel>();

// Pages
builder.Services.AddSingleton<DashboardPage>();
Expand All @@ -109,6 +110,7 @@ public static MauiApp CreateMauiApp()
builder.Services.AddTransient<LocalSensorDetailPage>();
builder.Services.AddTransient<TimeSettingsPage>();
builder.Services.AddTransient<MqttSettingsPage>();
builder.Services.AddTransient<SdCardSettingsPage>();

#if DEBUG
builder.Logging.AddDebug();
Expand Down
3 changes: 3 additions & 0 deletions PowerControlHubApp/PowerControlHubApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@
<MauiXaml Update="Views\RelayDetailPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\SdCardSettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\SettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
Expand Down
96 changes: 96 additions & 0 deletions PowerControlHubApp/Services/ConfigConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,102 @@ public async Task<bool> SetMqttDiscoveryPrefixAsync(string prefix, CancellationT
return await SetMqttStringAsync(MqttConfigDiscoveryPrefix, prefix, ct);
}

public async Task<(int Sck, int Mosi, int Miso)?> GetSdCardSpiPinsAsync(CancellationToken ct = default)
{
try
{
string json = await _client.GetStringAsync(RouteConfigSdCardSpiPins, ct);
using JsonDocument doc = JsonDocument.Parse(json);

if (doc.RootElement.TryGetProperty(ResultSuccess, out var success) &&
success.GetBoolean() &&
doc.RootElement.TryGetProperty(JsonSpiSckKey, out var sck) &&
doc.RootElement.TryGetProperty(JsonSpiMosiKey, out var mosi) &&
doc.RootElement.TryGetProperty(JsonSpiMisoKey, out var miso))
{
return (sck.GetInt32(), mosi.GetInt32(), miso.GetInt32());
}
}
catch
{
// fall through
}
return null;
}

public async Task<bool> SetSdCardSpiPinsAsync(int sck, int mosi, int miso, CancellationToken ct = default)
{
try
{
string url = $"{RouteConfigSdCardSpiPins}?sck={sck}&mosi={mosi}&miso={miso}";
HttpResponseMessage response = await _client.PostAsync(url, null, ct);
return response.IsSuccessStatusCode;
}
catch
{
return false;
}
}

public async Task<int?> GetSdCardInitSpeedAsync(CancellationToken ct = default)
{
return await GetConfigIntAsync(RouteConfigSdCardInitSpeed, ct);
}

public async Task<bool> SetSdCardInitSpeedAsync(int speed, CancellationToken ct = default)
{
return await SetConfigValueAsync(RouteConfigSdCardInitSpeed, speed, ct);
}

public async Task<int?> GetSdCardCsPinAsync(CancellationToken ct = default)
{
return await GetConfigIntAsync(RouteConfigSdCardCsPin, ct);
}

public async Task<bool> SetSdCardCsPinAsync(int pin, CancellationToken ct = default)
{
return await SetConfigValueAsync(RouteConfigSdCardCsPin, pin, ct);
}

private async Task<int?> GetConfigIntAsync(string route, CancellationToken ct)
{
try
{
string json = await _client.GetStringAsync(route, ct);
using JsonDocument doc = JsonDocument.Parse(json);

if (doc.RootElement.TryGetProperty(ResultSuccess, out var success) &&
success.GetBoolean() &&
doc.RootElement.TryGetProperty(JsonValueKey, out var v))
{
if (v.ValueKind == JsonValueKind.Number && v.TryGetInt32(out int val))
return val;

if (v.ValueKind == JsonValueKind.String && int.TryParse(v.GetString(), out val))
return val;
}
}
catch
{
// fall through
}
return null;
}

private async Task<bool> SetConfigValueAsync(string route, int value, CancellationToken ct)
{
try
{
string url = $"{route}?{JsonValueKey}={value}";
HttpResponseMessage response = await _client.PostAsync(url, null, ct);
return response.IsSuccessStatusCode;
}
catch
{
return false;
}
}

private async Task<string> GetMqttStringAsync(string command, CancellationToken ct)
{
try
Expand Down
12 changes: 12 additions & 0 deletions PowerControlHubApp/Services/ConfigPoller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,18 @@ private async Task RunLoopAsync(CancellationToken stoppingToken)

public Task<bool> SetMqttDiscoveryPrefixAsync(string prefix, CancellationToken ct = default) => _connection.SetMqttDiscoveryPrefixAsync(prefix, ct);

public Task<(int Sck, int Mosi, int Miso)?> GetSdCardSpiPinsAsync(CancellationToken ct = default) => _connection.GetSdCardSpiPinsAsync(ct);

public Task<bool> SetSdCardSpiPinsAsync(int sck, int mosi, int miso, CancellationToken ct = default) => _connection.SetSdCardSpiPinsAsync(sck, mosi, miso, ct);

public Task<int?> GetSdCardInitSpeedAsync(CancellationToken ct = default) => _connection.GetSdCardInitSpeedAsync(ct);

public Task<bool> SetSdCardInitSpeedAsync(int speed, CancellationToken ct = default) => _connection.SetSdCardInitSpeedAsync(speed, ct);

public Task<int?> GetSdCardCsPinAsync(CancellationToken ct = default) => _connection.GetSdCardCsPinAsync(ct);

public Task<bool> SetSdCardCsPinAsync(int pin, CancellationToken ct = default) => _connection.SetSdCardCsPinAsync(pin, ct);

public void Dispose()
{
if (_cts != null)
Expand Down
6 changes: 6 additions & 0 deletions PowerControlHubApp/Services/IConfigConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,11 @@ public interface IConfigConnection
Task<bool?> GetMqttConnectionStateAsync(CancellationToken ct = default);
Task<string> GetMqttDiscoveryPrefixAsync(CancellationToken ct = default);
Task<bool> SetMqttDiscoveryPrefixAsync(string prefix, CancellationToken ct = default);
Task<(int Sck, int Mosi, int Miso)?> GetSdCardSpiPinsAsync(CancellationToken ct = default);
Task<bool> SetSdCardSpiPinsAsync(int sck, int mosi, int miso, CancellationToken ct = default);
Task<int?> GetSdCardInitSpeedAsync(CancellationToken ct = default);
Task<bool> SetSdCardInitSpeedAsync(int speed, CancellationToken ct = default);
Task<int?> GetSdCardCsPinAsync(CancellationToken ct = default);
Task<bool> SetSdCardCsPinAsync(int pin, CancellationToken ct = default);
}
}
30 changes: 30 additions & 0 deletions PowerControlHubApp/Services/PowerHubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,34 @@ public Task<bool> SetMqttDiscoveryPrefixAsync(string prefix, CancellationToken c
{
return _configConnection.SetMqttDiscoveryPrefixAsync(prefix, ct);
}

public Task<(int Sck, int Mosi, int Miso)?> GetSdCardSpiPinsAsync(CancellationToken ct = default)
{
return _configConnection.GetSdCardSpiPinsAsync(ct);
}

public Task<bool> SetSdCardSpiPinsAsync(int sck, int mosi, int miso, CancellationToken ct = default)
{
return _configConnection.SetSdCardSpiPinsAsync(sck, mosi, miso, ct);
}

public Task<int?> GetSdCardInitSpeedAsync(CancellationToken ct = default)
{
return _configConnection.GetSdCardInitSpeedAsync(ct);
}

public Task<bool> SetSdCardInitSpeedAsync(int speed, CancellationToken ct = default)
{
return _configConnection.SetSdCardInitSpeedAsync(speed, ct);
}

public Task<int?> GetSdCardCsPinAsync(CancellationToken ct = default)
{
return _configConnection.GetSdCardCsPinAsync(ct);
}

public Task<bool> SetSdCardCsPinAsync(int pin, CancellationToken ct = default)
{
return _configConnection.SetSdCardCsPinAsync(pin, ct);
}
}
Loading
Loading