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
2 changes: 1 addition & 1 deletion PowerControlHub/ConfigController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ ConfigResult ConfigController::generateAuthKeys()
if (_config == nullptr)
return ConfigResult::InvalidConfig;

char deviceId[32];
char deviceId[26];
deviceId[0] = '\0';

if (SystemFunctions::GenerateDefaultPassword(deviceId, sizeof(deviceId)) != BufferSuccess)
Expand Down
35 changes: 19 additions & 16 deletions PowerControlHub/ConfigNetworkHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,14 +405,14 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
getParamValueBool(params, paramCount, ConfigAuthGenerateParam, generate);

if (generate)
{
result = _configController->generateAuthKeys();
{
result = _configController->generateAuthKeys();

if (result == ConfigResult::Success)
{
formatJsonResponse(responseBuffer, bufferSize, true, "");
}
if (result == ConfigResult::Success)
{
formatJsonResponse(responseBuffer, bufferSize, true, "");
}
}
else
{
const char* apiKeyVal = getParamValue(params, paramCount, ConfigAuthApiKeyParam);
Expand All @@ -426,7 +426,7 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
? "API key too long"
: "API key invalid";
formatJsonResponse(responseBuffer, bufferSize, false, msg);
return CommandResult(false);
return CommandResult{false, 0};
}
}

Expand All @@ -435,24 +435,26 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
if (hmacKeyVal)
{
result = _configController->setAuthHmacKey(hmacKeyVal);

if (result != ConfigResult::Success)
{
const char* msg = (result == ConfigResult::TooLong)
? "HMAC key too long"
: "HMAC key invalid";
formatJsonResponse(responseBuffer, bufferSize, false, msg);
return CommandResult(false);
return CommandResult{false, 0};
}
}

bool enabled;
if (getParamValueBool(params, paramCount, ConfigAuthEnabledParam, enabled))
{
result = _configController->setAuthEnabled(enabled);

if (result != ConfigResult::Success)
{
formatJsonResponse(responseBuffer, bufferSize, false, "Cannot enable auth: keys not set");
return CommandResult(false);
return CommandResult{false, 0};
}
}

Expand All @@ -467,20 +469,21 @@ CommandResult ConfigNetworkHandler::handleRequest(const char* method,
{
// N0 - returns all nextion settings as a JSON-style response in responseBuffer
Config* config = ConfigManager::getConfigPtr();

if (config == nullptr)
{
result = ConfigResult::InvalidConfig;
}
else
{
int len = snprintf(responseBuffer, bufferSize,
"en=%u;hw=%u;rx=%u;tx=%u;baud=%lu;uart=%u",
config->nextion.enabled ? 1u : 0u,
config->nextion.isHardwareSerial ? 1u : 0u,
config->nextion.rxPin,
config->nextion.txPin,
config->nextion.baudRate,
config->nextion.uartNum);
"\"en\":%u,\"hw\":%u,\"rx\":%u,\"tx\":%u,\"baud\":%lu,\"uart\":%u",
config->nextion.enabled ? 1u : 0u,
config->nextion.isHardwareSerial ? 1u : 0u,
config->nextion.rxPin,
config->nextion.txPin,
config->nextion.baudRate,
config->nextion.uartNum);
result = (len > 0 && len < static_cast<int>(bufferSize))
? ConfigResult::Success : ConfigResult::InvalidParameter;
}
Expand Down
2 changes: 1 addition & 1 deletion PowerControlHub/SystemFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ uint8_t SystemFunctions::GenerateDefaultPassword(char* buffer, size_t bufferSize
WiFi.macAddress(mac);
#endif

snprintf_P(buffer, bufferSize, PSTR("sfb-%02X%02X%02X"), mac[3], mac[4], mac[5]);
snprintf_P(buffer, bufferSize, PSTR("pch-%02X%02X%02X"), mac[3], mac[4], mac[5]);
#else
randomSeed(analogRead(A0) + analogRead(A1) + millis());
uint32_t storedID = static_cast<uint32_t>(random(PasswordRandomMin, LONG_MAX));
Expand Down
1 change: 1 addition & 0 deletions PowerControlHubApp/AppShell.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public AppShell()
Routing.RegisterRoute(nameof(MqttSettingsPage), typeof(MqttSettingsPage));
Routing.RegisterRoute(nameof(SdCardSettingsPage), typeof(SdCardSettingsPage));
Routing.RegisterRoute(nameof(NetworkSecurityPage), typeof(NetworkSecurityPage));
Routing.RegisterRoute(nameof(NextionSettingsPage), typeof(NextionSettingsPage));
}
}
}
40 changes: 40 additions & 0 deletions PowerControlHubApp/Internal/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,46 @@ internal static class Constants
public const string RouteConfigSdCardSpiPins = "api/config/C4";
public const string RouteConfigSdCardInitSpeed = "api/config/C31";
public const string RouteConfigSdCardCsPin = "api/config/C32";
// Nextion display config
public const string RouteConfigNextionGet = "api/config/N0";
public const string RouteConfigNextionSetFormat = "api/config/N{0}?v={1}";
public const string RouteNextionSettingsPage = "NextionSettingsPage";
public const string NextionMsgSaveFailed = "Save failed — device unreachable";
public const string NextionMsgSaved = "Nextion settings saved";
public const string NextionMsgRefreshed = "Refreshed";
public const string NextionUart1 = "UART1";
public const string NextionUart2 = "UART2";
public const string NextionRebootTitle = "Reboot Required";
public const string NextionRebootMessage = "Changes require a device reboot to take effect. Reboot device now? (If the device has no reboot endpoint you will need to power-cycle it manually)";
public const string NextionRebootButton = "Reboot";
public const string NextionRebootOk = "OK";
public const string NextionRebootSaved = "Settings saved. Please power-cycle the device to apply Nextion configuration.";
public const string NextionRebootFailed = "Failed to save settings before reboot.";
public const string NextionRouteN1 = "api/config/N1";
public const string NextionRouteN2 = "api/config/N2";
public const string NextionRouteN3 = "api/config/N3";
public const string NextionRouteN4 = "api/config/N4";
public const string NextionRouteN5 = "api/config/N5";
public const string NextionRouteN6 = "api/config/N6";
// Nextion JSON property names (N0 response)
public const string NextionJsonN1 = "n1";
public const string NextionJsonN2 = "n2";
public const string NextionJsonN3 = "n3";
public const string NextionJsonN4 = "n4";
public const string NextionJsonN5 = "n5";
public const string NextionJsonN6 = "n6";
public const string NextionJsonEnabled = "enabled";
public const string NextionJsonHardwareSerial = "hardwareserial";
public const string NextionJsonRxPin = "rxpin";
public const string NextionJsonTxPin = "txpin";
public const string NextionJsonBaudRate = "baudrate";
public const string NextionJsonUartNumber = "uartnumber";
public const string NextionJsonEn = "en";
public const string NextionJsonHw = "hw";
public const string NextionJsonRx = "rx";
public const string NextionJsonTx = "tx";
public const string NextionJsonBaud = "baud";
public const string NextionJsonUart = "uart";
public const string RouteConfigAuth = "api/config/C19";
public const string ConfigAuthEnabledParam = "e";
public const string ConfigAuthApiKeyParam = "k";
Expand Down
2 changes: 2 additions & 0 deletions PowerControlHubApp/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public static MauiApp CreateMauiApp()
builder.Services.AddTransient<MqttSettingsViewModel>();
builder.Services.AddTransient<SdCardSettingsViewModel>();
builder.Services.AddTransient<NetworkSecurityViewModel>();
builder.Services.AddTransient<NextionSettingsViewModel>();

// Pages
builder.Services.AddSingleton<DashboardPage>();
Expand All @@ -124,6 +125,7 @@ public static MauiApp CreateMauiApp()
builder.Services.AddTransient<MqttSettingsPage>();
builder.Services.AddTransient<SdCardSettingsPage>();
builder.Services.AddTransient<NetworkSecurityPage>();
builder.Services.AddTransient<NextionSettingsPage>();

#if DEBUG
builder.Logging.AddDebug();
Expand Down
11 changes: 11 additions & 0 deletions PowerControlHubApp/Models/Json/NextionConfigModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace PowerControlHubApp.Models.Json;

public sealed class NextionConfigModel
{
public bool? Enabled { get; set; }
public bool? HardwareSerial { get; set; }
public int? RxPin { get; set; }
public int? TxPin { get; set; }
public int? BaudRate { get; set; }
public int? UartNumber { get; set; }
}
3 changes: 3 additions & 0 deletions PowerControlHubApp/PowerControlHubApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
<MauiXaml Update="Views\NetworkSecurityPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\NextionSettingsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\NotConnectedBanner.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
Expand Down
91 changes: 91 additions & 0 deletions PowerControlHubApp/Services/ConfigConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,97 @@ public async Task<bool> GenerateAuthKeysAsync(CancellationToken ct = default)
}
}

public async Task<NextionConfigModel> GetNextionConfigAsync(CancellationToken ct = default)
{
try
{
string json = await _client.GetStringAsync(RouteConfigNextionGet, ct);
using JsonDocument doc = JsonDocument.Parse(json);

var model = new NextionConfigModel();

if (doc.RootElement.ValueKind == JsonValueKind.Object)
{
foreach (var prop in doc.RootElement.EnumerateObject())
{
string name = prop.Name.ToLowerInvariant();

if (name == NextionJsonN1 || name == NextionJsonEnabled || name == NextionJsonEn)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.Enabled = v != 0;
}
else if (name == NextionJsonN2 || name == NextionJsonHardwareSerial || name == NextionJsonHw)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.HardwareSerial = v != 0;
}
else if (name == NextionJsonN3 || name == NextionJsonRxPin || name == NextionJsonRx)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.RxPin = v;
}
else if (name == NextionJsonN4 || name == NextionJsonTxPin || name == NextionJsonTx)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.TxPin = v;
}
else if (name == NextionJsonN5 || name == NextionJsonBaudRate || name == NextionJsonBaud)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.BaudRate = v;
}
else if (name == NextionJsonN6 || name == NextionJsonUartNumber || name == NextionJsonUart)
{
if (prop.Value.ValueKind == JsonValueKind.Number && prop.Value.TryGetInt32(out int v))
model.UartNumber = v;
}
}
}

if (model.Enabled == null || model.HardwareSerial == null || model.RxPin == null || model.TxPin == null || model.BaudRate == null || model.UartNumber == null)
{
int? n1 = await GetConfigIntAsync(NextionRouteN1, ct);
int? n2 = await GetConfigIntAsync(NextionRouteN2, ct);
int? n3 = await GetConfigIntAsync(NextionRouteN3, ct);
int? n4 = await GetConfigIntAsync(NextionRouteN4, ct);
int? n5 = await GetConfigIntAsync(NextionRouteN5, ct);
int? n6 = await GetConfigIntAsync(NextionRouteN6, ct);

model.Enabled ??= (n1.HasValue ? n1.Value != 0 : (bool?)null);
model.HardwareSerial ??= (n2.HasValue ? n2.Value != 0 : (bool?)null);
model.RxPin ??= n3;
model.TxPin ??= n4;
model.BaudRate ??= n5;
model.UartNumber ??= n6;
}

return model;
}
catch
{
return new NextionConfigModel();
}
}

public async Task<bool> SetNextionEnabledAsync(bool enabled, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN1, enabled ? 1 : 0, ct);

public async Task<bool> SetNextionHardwareSerialAsync(bool hardwareSerial, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN2, hardwareSerial ? 1 : 0, ct);

public async Task<bool> SetNextionRxPinAsync(int pin, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN3, pin, ct);

public async Task<bool> SetNextionTxPinAsync(int pin, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN4, pin, ct);

public async Task<bool> SetNextionBaudRateAsync(int baudRate, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN5, baudRate, ct);

public async Task<bool> SetNextionUartNumberAsync(int uartNumber, CancellationToken ct = default)
=> await SetConfigValueAsync(NextionRouteN6, uartNumber, ct);

private async Task SyncAuthHandlerFromDeviceAsync(CancellationToken ct)
{
try
Expand Down
8 changes: 8 additions & 0 deletions PowerControlHubApp/Services/ConfigPoller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,14 @@ private async Task RunLoopAsync(CancellationToken stoppingToken)

public Task<bool> GenerateAuthKeysAsync(CancellationToken ct = default) => _connection.GenerateAuthKeysAsync(ct);

public Task<NextionConfigModel> GetNextionConfigAsync(CancellationToken ct = default) => _connection.GetNextionConfigAsync(ct);
public Task<bool> SetNextionEnabledAsync(bool enabled, CancellationToken ct = default) => _connection.SetNextionEnabledAsync(enabled, ct);
public Task<bool> SetNextionHardwareSerialAsync(bool hardwareSerial, CancellationToken ct = default) => _connection.SetNextionHardwareSerialAsync(hardwareSerial, ct);
public Task<bool> SetNextionRxPinAsync(int pin, CancellationToken ct = default) => _connection.SetNextionRxPinAsync(pin, ct);
public Task<bool> SetNextionTxPinAsync(int pin, CancellationToken ct = default) => _connection.SetNextionTxPinAsync(pin, ct);
public Task<bool> SetNextionBaudRateAsync(int baudRate, CancellationToken ct = default) => _connection.SetNextionBaudRateAsync(baudRate, ct);
public Task<bool> SetNextionUartNumberAsync(int uartNumber, CancellationToken ct = default) => _connection.SetNextionUartNumberAsync(uartNumber, ct);

public void Dispose()
{
if (_cts != null)
Expand Down
7 changes: 7 additions & 0 deletions PowerControlHubApp/Services/IConfigConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,12 @@ public interface IConfigConnection
Task<bool> SetAuthApiKeyAsync(string apiKey, CancellationToken ct = default);
Task<bool> SetAuthHmacKeyAsync(string hmacKey, CancellationToken ct = default);
Task<bool> GenerateAuthKeysAsync(CancellationToken ct = default);
Task<NextionConfigModel> GetNextionConfigAsync(CancellationToken ct = default);
Task<bool> SetNextionEnabledAsync(bool enabled, CancellationToken ct = default);
Task<bool> SetNextionHardwareSerialAsync(bool hardwareSerial, CancellationToken ct = default);
Task<bool> SetNextionRxPinAsync(int pin, CancellationToken ct = default);
Task<bool> SetNextionTxPinAsync(int pin, CancellationToken ct = default);
Task<bool> SetNextionBaudRateAsync(int baudRate, CancellationToken ct = default);
Task<bool> SetNextionUartNumberAsync(int uartNumber, CancellationToken ct = default);
}
}
35 changes: 35 additions & 0 deletions PowerControlHubApp/Services/PowerHubService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,41 @@ public Task<bool> GenerateAuthKeysAsync(CancellationToken ct = default)
return _configConnection.GenerateAuthKeysAsync(ct);
}

public Task<NextionConfigModel> GetNextionConfigAsync(CancellationToken ct = default)
{
return _configConnection.GetNextionConfigAsync(ct);
}

public Task<bool> SetNextionEnabledAsync(bool enabled, CancellationToken ct = default)
{
return _configConnection.SetNextionEnabledAsync(enabled, ct);
}

public Task<bool> SetNextionHardwareSerialAsync(bool hardwareSerial, CancellationToken ct = default)
{
return _configConnection.SetNextionHardwareSerialAsync(hardwareSerial, ct);
}

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

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

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

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

private void OnAuthConfigChanged(AuthConfigChanged msg)
{
if (_dashboardConnection is DashboardConnection dc)
Expand Down
2 changes: 1 addition & 1 deletion PowerControlHubApp/ViewModels/BaseViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ private async Task AutoRefreshLoopAsync(CancellationToken ct)
/// updates system status, then calls <see cref="OnDataFetched"/> for
/// view-model-specific processing. Handles error cases consistently.
/// </summary>
protected async Task ExecuteRefreshAsync(CancellationToken ct)
protected virtual async Task ExecuteRefreshAsync(CancellationToken ct)
{
if (!_service.IsConfigured)
{
Expand Down
Loading
Loading