namespace SHH.CameraDashboard;
public partial class CameraRepository
{
#region GetListByAddressAsync 获取摄像头列表
///
/// [新增] 动态检测方法。
/// 专门用于向导界面,根据临时输入的 IP 地址和端口号来获取摄像头列表。
///
/// 目标服务器的 IP 地址。
/// 目标服务器的端口号。
/// 调用此方法的页面或步骤名称,用于日志记录。
///
/// 一个异步任务,其结果包含一个 对象的列表。
/// - 如果成功获取到列表,返回该列表(可能为空)。
/// - 如果获取过程中发生任何异常(如网络错误、服务器无响应等),返回 null。
///
public async Task?> 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>(jsonResponse);
// 4. 确保返回的列表不为 null
// 如果反序列化结果为 null(例如,API 返回 "null"),则返回一个空列表,
// 这样调用方可以安全地遍历,而无需进行 null 检查。
return cameraList ?? new List();
}
catch (Exception)
{
// 5. 捕获所有异常
// 在动态检测阶段,网络不通、服务器宕机等都是预期内的情况。
// 返回 null 作为明确的失败信号,ViewModel 可以据此向用户显示“连接失败”等提示。
return null;
}
}
#endregion
#region ControlPowerAsync 摄像头启停
///
/// 调用服务端的接口来控制指定摄像头的启停状态(开机/关机)。
///
/// 目标服务器的 IP 地址。
/// 目标服务器的端口号。
/// 要控制的摄像头的唯一ID。
/// true 表示开机,false 表示关机。
/// 调用此方法的页面或功能名称,用于日志记录。
///
/// 一个异步任务,其结果为一个布尔值:
/// - true:表示操作成功(HTTP 响应为 200 OK)。
/// - false:表示操作失败(如网络错误、服务器返回 4xx/5xx 错误等)。
///
public async Task 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
}