From 8285cfeb00de333a7215ad6b8983c3fcf02925a3 Mon Sep 17 00:00:00 2001 From: keyldev Date: Mon, 12 Oct 2026 11:47:46 +0300 Subject: [PATCH] fix(majestic): don't let a missing info.json hide the config (#88) - Treat 404 on api/v1/info.json as "no info", like the HTML fallback - Desktop camera page loads config even when info.json fails - Matches what the web API and connect service already did --- .../ViewModels/SingleCameraPageViewModel.cs | 17 +++++++++++++++-- .../Majestic/MajesticHttpClient.cs | 7 +++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/OpenIPC.Viewer.App/ViewModels/SingleCameraPageViewModel.cs b/src/OpenIPC.Viewer.App/ViewModels/SingleCameraPageViewModel.cs index 0bc72cf..8e9c65b 100644 --- a/src/OpenIPC.Viewer.App/ViewModels/SingleCameraPageViewModel.cs +++ b/src/OpenIPC.Viewer.App/ViewModels/SingleCameraPageViewModel.cs @@ -1248,8 +1248,21 @@ private async Task EditMajesticOverSshAsync() { var cfgTask = _majestic.GetConfigAsync(ep, ct); var infoTask = _majestic.GetInfoAsync(ep, ct); - await Task.WhenAll(cfgTask, infoTask).ConfigureAwait(false); - return (await cfgTask.ConfigureAwait(false), await infoTask.ConfigureAwait(false)); + var config = await cfgTask.ConfigureAwait(false); + + // info.json is optional metadata (model/firmware) — a firmware that + // doesn't serve it must not hide an otherwise editable config. + MajesticInfo info; + try + { + info = await infoTask.ConfigureAwait(false); + } + catch (Exception ex) when (!ct.IsCancellationRequested) + { + _logger.LogInformation(ex, "Majestic info unavailable for {CameraId}", _camera.Id); + info = new MajesticInfo(null, null, null, null); + } + return (config, info); } [RelayCommand] diff --git a/src/OpenIPC.Viewer.Devices/Majestic/MajesticHttpClient.cs b/src/OpenIPC.Viewer.Devices/Majestic/MajesticHttpClient.cs index be6ced0..98e15fa 100644 --- a/src/OpenIPC.Viewer.Devices/Majestic/MajesticHttpClient.cs +++ b/src/OpenIPC.Viewer.Devices/Majestic/MajesticHttpClient.cs @@ -105,6 +105,13 @@ public async Task GetConfigAsync(MajesticEndpoint endpoint, Canc public async Task GetInfoAsync(MajesticEndpoint endpoint, CancellationToken ct) { using var resp = await SendAsync(endpoint, HttpMethod.Get, "api/v1/info.json", ct).ConfigureAwait(false); + // Newer lite builds (e.g. gk7205v200 2.6.09.24-lite) dropped info.json + // entirely and answer 404 — same meaning as the HTML fallback below. + if (resp.StatusCode == System.Net.HttpStatusCode.NotFound) + { + _logger.LogDebug("Majestic info.json not served by {Host}; skipping", endpoint.Host); + return new MajesticInfo(null, null, null, null); + } await EnsureSuccessAsync(resp, ct).ConfigureAwait(false); var rawJson = await resp.Content.ReadAsStringAsync(ct).ConfigureAwait(false); // Some firmwares don't serve info.json and return the web UI's HTML