具备界面基础功能
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
namespace SHH.CameraDashboard;
|
||||
|
||||
public partial class CameraRepository
|
||||
{
|
||||
#region GetListByAddressAsync 获取摄像头列表
|
||||
|
||||
/// <summary>
|
||||
/// [新增] 动态检测方法。
|
||||
/// 专门用于向导界面,根据临时输入的 IP 地址和端口号来获取摄像头列表。
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">目标服务器的 IP 地址。</param>
|
||||
/// <param name="port">目标服务器的端口号。</param>
|
||||
/// <param name="pageName">调用此方法的页面或步骤名称,用于日志记录。</param>
|
||||
/// <returns>
|
||||
/// 一个异步任务,其结果包含一个 <see cref="WebApiCameraModel"/> 对象的列表。
|
||||
/// - 如果成功获取到列表,返回该列表(可能为空)。
|
||||
/// - 如果获取过程中发生任何异常(如网络错误、服务器无响应等),返回 <c>null</c>。
|
||||
/// </returns>
|
||||
public async Task<List<WebApiCameraModel>?> GetListByAddressAsync(string ipAddress, string port, string pageName)
|
||||
{
|
||||
// 1. 统一管理并拼接请求 URL
|
||||
// 在这里将基础地址与 API 路径组合,ViewModel 无需关心具体的路由细节。
|
||||
// WebApiRoutes.Cameras.Root 是一个假设的常量,例如 "/api/Cameras"。
|
||||
string requestUrl = $"http://{ipAddress}:{port}{WebApiRoutes.Cameras.Root}";
|
||||
|
||||
try
|
||||
{
|
||||
// 2. 调用底层的 WebApiService 发送 GET 请求
|
||||
// 传入 "Wizard" 相关的模块名,便于在日志中区分请求来源。
|
||||
string jsonResponse = await WebApiService.Instance.GetAsync(requestUrl, moduleName: $"摄像头列表-{pageName}", default, true);
|
||||
|
||||
// 3. 使用 JsonHelper 进行反序列化
|
||||
// 利用 JsonHelper 的防御性实现,即使 JSON 格式错误或内容为 "null",也不会抛出异常。
|
||||
var cameraList = JsonHelper.Deserialize<List<WebApiCameraModel>>(jsonResponse);
|
||||
|
||||
// 4. 确保返回的列表不为 null
|
||||
// 如果反序列化结果为 null(例如,API 返回 "null"),则返回一个空列表,
|
||||
// 这样调用方可以安全地遍历,而无需进行 null 检查。
|
||||
return cameraList ?? new List<WebApiCameraModel>();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// 5. 捕获所有异常
|
||||
// 在动态检测阶段,网络不通、服务器宕机等都是预期内的情况。
|
||||
// 返回 null 作为明确的失败信号,ViewModel 可以据此向用户显示“连接失败”等提示。
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ControlPowerAsync 摄像头启停
|
||||
|
||||
/// <summary>
|
||||
/// 调用服务端的接口来控制指定摄像头的启停状态(开机/关机)。
|
||||
/// </summary>
|
||||
/// <param name="ipAddress">目标服务器的 IP 地址。</param>
|
||||
/// <param name="port">目标服务器的端口号。</param>
|
||||
/// <param name="cameraId">要控制的摄像头的唯一ID。</param>
|
||||
/// <param name="enable">true 表示开机,false 表示关机。</param>
|
||||
/// <param name="pageName">调用此方法的页面或功能名称,用于日志记录。</param>
|
||||
/// <returns>
|
||||
/// 一个异步任务,其结果为一个布尔值:
|
||||
/// - <c>true</c>:表示操作成功(HTTP 响应为 200 OK)。
|
||||
/// - <c>false</c>:表示操作失败(如网络错误、服务器返回 4xx/5xx 错误等)。
|
||||
/// </returns>
|
||||
public async Task<bool> ControlPowerAsync(long cameraId, bool enable, string pageName)
|
||||
{
|
||||
var useServiceNode = AppGlobal.UseServiceNode;
|
||||
if (useServiceNode == null)
|
||||
return false;
|
||||
|
||||
var ipAddress = useServiceNode.ServiceNodeIp;
|
||||
var port = useServiceNode.ServiceNodePort;
|
||||
|
||||
// 1. 拼接请求 URL
|
||||
// 将控制参数(cameraId 和 enable)作为 URL 的一部分发送。
|
||||
string requestUrl = $"http://{ipAddress}:{port}/api/Cameras/{cameraId}/power?enabled={enable}";
|
||||
|
||||
try
|
||||
{
|
||||
// 2. 调用底层服务发送 POST 请求
|
||||
// 关键点:
|
||||
// a. 即使服务端不关心请求体(Body),`PostAsync` 方法也要求一个非 null 的 JSON 字符串。
|
||||
// 因此,我们传入一个空的 JSON 对象 "{}" 作为占位符。
|
||||
// b. 我们不检查响应内容,因为如果请求失败(例如,服务器返回 404 Not Found 或 500 Internal Server Error),
|
||||
// `WebApiService` 会抛出异常。
|
||||
await WebApiService.Instance.PostAsync(requestUrl, "{}", moduleName: $"设备启停-{pageName}");
|
||||
|
||||
// 3. 如果代码执行到这里,说明请求成功且没有抛出异常。
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 4. 捕获所有可能发生的异常
|
||||
// 这包括网络连接问题、DNS解析失败、服务器无响应或返回错误状态码等。
|
||||
// 记录异常信息到调试输出,以便于排查问题。
|
||||
System.Diagnostics.Debug.WriteLine($"控制摄像头电源失败 [IP: {ipAddress}, CameraId: {cameraId}]: {ex.Message}");
|
||||
|
||||
// 返回 false 通知调用方操作已失败。
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user