From 55e38ab147572545be799f73f9ca96c7d0ecf829 Mon Sep 17 00:00:00 2001 From: LiuXin Date: Thu, 14 Aug 2025 20:42:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=8B=E8=BD=BD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RequestDto/SubscribeEventReqDto.cs | 65 ++---- .../DahAlarm/DahuaGeneralCtlService.cs | 217 ++++-------------- .../DahAlarm/IDahuaGeneralCtlService.cs | 15 +- .../Controllers/AlarmController.cs | 18 +- .../Properties/launchSettings.json | 8 +- .../AlarmService.API/appsettings.json | 5 +- .../Manage.AppHost.AppHost/AppHost.cs | 4 +- .../DaHua/VideoManageController.cs | 11 + .../RequestDto/DahuaVideoQueryDto.cs | 47 ++++ .../Dahvision/DahuaGeneralCtlService.cs | 13 ++ .../Dahvision/IDahuaGeneralCtlService.cs | 7 + .../Dahvision/IRootVideoPlaybackService.cs | 7 + .../Dahvision/RootVideoPlaybackService.cs | 10 + 13 files changed, 171 insertions(+), 256 deletions(-) diff --git a/WeiCloud.Fusion/AlarmService/Alarm.Application/RequestDto/SubscribeEventReqDto.cs b/WeiCloud.Fusion/AlarmService/Alarm.Application/RequestDto/SubscribeEventReqDto.cs index 21a454e..05aeaa7 100644 --- a/WeiCloud.Fusion/AlarmService/Alarm.Application/RequestDto/SubscribeEventReqDto.cs +++ b/WeiCloud.Fusion/AlarmService/Alarm.Application/RequestDto/SubscribeEventReqDto.cs @@ -5,85 +5,66 @@ namespace Alarm.Application.RequestDto public sealed class SubscribeReqDto { [JsonPropertyName("param")] - public required SubscribeParam Param { get; init; } + public SubscribeParam Param { get; set; } = new(); } + public sealed class SubscribeParam { [JsonPropertyName("monitors")] - public required List Monitors { get; init; } + public List Monitors { get; set; } = new(); [JsonPropertyName("subsystem")] - public required SubsystemInfo Subsystem { get; init; } + public SubsystemConfig Subsystem { get; set; } = new(); } - public sealed class MonitorEntry + public sealed class MonitorConfig { - /// 回调地址(ICC 能访问到) + // 为避免歧义,内部命名用 MonitorUrl,映射到 JSON 的 "monitor" [JsonPropertyName("monitor")] - public required string Monitor { get; init; } + public string? MonitorUrl { get; set; } - /// 固定 url [JsonPropertyName("monitorType")] - public string MonitorType { get; init; } = "url"; + public string? MonitorType { get; set; } - /// 事件大类订阅配置 [JsonPropertyName("events")] - public required List Events { get; init; } + public List Events { get; set; } = new(); } - /// 事件大类订阅(alarm / business / state / perception ...) - public sealed class EventSubscribe + public sealed class EventConfig { [JsonPropertyName("category")] - public required string Category { get; init; } // 用 string 保持向后兼容 + public string? Category { get; set; } - /// 1=订阅该大类全部(仍受 authorities 过滤),0=按维度筛选 + // 你的示例是 0/1 数字,这里保持 int;若你更想用 bool,可改成 bool 并写自定义转换 [JsonPropertyName("subscribeAll")] - public int SubscribeAll { get; init; } = 1; + public int? SubscribeAll { get; set; } - /// 级联:0=本级,1=下级,2=本级+下级 [JsonPropertyName("domainSubscribe")] - public int DomainSubscribe { get; init; } = 0; + public int? DomainSubscribe { get; set; } - /// 权限过滤(可多组) [JsonPropertyName("authorities")] - public List? Authorities { get; init; } - - /// 仅 alarm 使用:0=事件,1=报警。未提供时默认 0 - [JsonPropertyName("eventType")] - public int? EventType { get; init; } - - /// 报警级别过滤(仅 alarm 有意义),如 1/2/3 ... - [JsonPropertyName("grades")] - public List? Grades { get; init; } + public List Authorities { get; set; } = new(); } - /// 权限过滤:缺省=订阅全部;空数组=不订阅。 - public sealed class AuthorityFilter + public sealed class Authority { - /// 事件/业务/感知子类型(如 "57", "car.capture") + // 二选一的字段:有的事件给 types,有的给 nodeCodes [JsonPropertyName("types")] - public List? Types { get; init; } + public List? Types { get; set; } - /// 设备/通道编码 [JsonPropertyName("nodeCodes")] - public List? NodeCodes { get; init; } - - /// 组织编码 - [JsonPropertyName("orgs")] - public List? Orgs { get; init; } + public List? NodeCodes { get; set; } } - public sealed class SubsystemInfo + public sealed class SubsystemConfig { - /// 固定 0 [JsonPropertyName("subsystemType")] - public int SubsystemType { get; init; } = 0; + public int SubsystemType { get; set; } [JsonPropertyName("name")] - public required string Name { get; init; } + public string? Name { get; set; } [JsonPropertyName("magic")] - public required string Magic { get; init; } + public string? Magic { get; set; } } } \ No newline at end of file diff --git a/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/DahuaGeneralCtlService.cs b/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/DahuaGeneralCtlService.cs index 3f893c4..f920b42 100644 --- a/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/DahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/DahuaGeneralCtlService.cs @@ -4,6 +4,7 @@ using Common.Shared.Application.DaHua; using Common.Shared.DomainService; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using MongoDB.Bson; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System; @@ -18,9 +19,10 @@ namespace Alarm.DomainService.DahAlarm { private readonly ILogger _logger; private readonly IConfiguration _configuration; - private readonly HttpClient _http; + private readonly MQTTClient _mqttClient; private readonly IMqttClientService _mqttClientService; + private readonly ITokenProviderService _tokenProviderService; private string mqttHostIp; private int mqttHostPort; private int mqttTimeout; @@ -36,11 +38,11 @@ namespace Alarm.DomainService.DahAlarm /// /// /// - public DahuaGeneralCtlService(ILogger logger, IConfiguration configuration, HttpClient http, MQTTClient mQTTClient, IMqttClientService mqttClientService) + public DahuaGeneralCtlService(ILogger logger, IConfiguration configuration, MQTTClient mQTTClient, IMqttClientService mqttClientService, ITokenProviderService tokenProviderService) { _logger = logger; _configuration = configuration; - _http = http; + _mqttClient = mQTTClient; mqttHostIp = _configuration["SubscribeMQTT:HostIP"]!;//IP地址 mqttHostPort = _configuration["SubscribeMQTT:HostPort"].ToInt();//端口号 @@ -50,112 +52,16 @@ namespace Alarm.DomainService.DahAlarm mqttClientId = _configuration["SubscribeMQTT:ClientId"]!; topicName = _configuration["SubscribeMQTT:TopicName"]!; _mqttClientService = mqttClientService; + _tokenProviderService = tokenProviderService; } /// - /// 获取公钥 - /// - /// - /// - public async Task> GetPublicKey() - { - DaHApiResult result = new() { Success = true, Code = "0", Data = new PublicKeyDto() { PublicKey = "" } }; - try - { - var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/evo-oauth/1.0.0/oauth/public-key"; - - using var resp = await _http.GetAsync(url); - resp.EnsureSuccessStatusCode(); - var json = await resp.Content.ReadAsStringAsync(); - var envelope = JsonSerializer.Deserialize>(json, new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }); - - if (envelope?.Data?.PublicKey is null or { Length: 0 }) - { - _logger.LogWarning("获取大华公钥失败,返回结果:{Result}", json); - result.Success = false; - result.Code = "1001"; - result.Msg = "获取大华公钥失败"; - - return result; - } - - result.Data.PublicKey = envelope.Data.PublicKey; - } - catch (Exception ex) - { - _logger.LogWarning(ex, "大华平台获取公钥出错"); - } - return result; - } - - /// - /// 获取token + /// 开发测试的时候,忽略证书 /// - /// - /// - public async Task> GetToken(LoginRequestDto dto) + private static readonly HttpClient _http = new HttpClient(new HttpClientHandler { - DaHApiResult result = new DaHApiResult() { Success = true, Code = "0" }; - if (dto is null) - { - result.Success = false; - - result.Code = "1002"; - result.Msg = "请求参数不能为空"; - _logger.LogWarning("获取大华登录令牌失败,参数不能为空"); - return result; - } - if (string.IsNullOrWhiteSpace(dto.Password)) - { - result.Success = false; - result.Code = "1003"; - result.Msg = "密码不能为空"; - _logger.LogWarning("获取大华登录令牌失败,密码不能为空"); - return result; - } - try - { - //1. 获取公钥 - DaHApiResult publicKeyResult = await GetPublicKey(); - if (!publicKeyResult.Success) - { - result.Code = "500"; - result.Msg = publicKeyResult.Msg; - _logger.LogWarning("获取大华公钥失败:{Msg}", publicKeyResult.Msg); - } - //2. 鉴权 - dto.PublicKey = publicKeyResult.Data.PublicKey; - - var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/evo-oauth/1.0.0/oauth/extend/token"; - //必须加密 - dto.Password = EncryptByPublicKey(dto.Password, dto.PublicKey!); - using var resp = await _http.PostAsJsonAsync(url, dto); - resp.EnsureSuccessStatusCode(); - - var tokenInfo = await resp.Content.ReadFromJsonAsync>(); - - if (tokenInfo == null || !result.Success || result.Code != "0") - { - result.Success = false; - result.Code = "1004"; - result.Msg = "获取大华登录令牌失败"; - _logger.LogWarning("获取大华登录令牌失败,返回结果:{Result}", result); - } - //固定的拼接方式 - result.Data.AccessToken = string.Concat(tokenInfo!.Data.TokenType, " ", tokenInfo.Data.AccessToken); - } - catch (Exception ex) - { - _logger.LogError(ex, "获取大华登录令牌出错"); - result.Success = false; - result.Code = "1004"; - result.Msg = "获取大华登录令牌失败"; - } - return result; - } + ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator + }); /// /// 新增报警事件订阅 @@ -163,13 +69,13 @@ namespace Alarm.DomainService.DahAlarm /// /// /// - public async Task> AddSubscribeEvent(string accessToken) + public async Task> AddSubscribeEvent() { var result = new DaHApiResult { Success = true, Code = "0", Data = new object() }; try { - var baseHost = _configuration["DahuaEvent:Host"]; + var baseHost = _configuration["DahuaAuth:Host"]; if (string.IsNullOrWhiteSpace(baseHost)) { return new DaHApiResult @@ -186,28 +92,41 @@ namespace Alarm.DomainService.DahAlarm { Param = new SubscribeParam { - Monitors = new List + Monitors = new List + { + new MonitorConfig + { + MonitorUrl = _configuration["DahuaAuth:Callback"], + MonitorType = "url", + Events = new List { - new() + new EventConfig { - Monitor = _configuration["DahuaEvent:Callback"]!, - Events = - [ - new() + Category = "alarm", + SubscribeAll = 1, + DomainSubscribe = 2, + Authorities = new List + { + new Authority { - Category = "alarm", - SubscribeAll = 1, - DomainSubscribe = 2, - - EventType = 1 + Types = new List { "4321" } } - ] + } } - }, - Subsystem = new SubsystemInfo { SubsystemType = 0, Name = _configuration["DahuaEvent:SubsystemName"]!, Magic = _configuration["DahuaEvent:SubsystemMagic"]! } + } + } + }, + Subsystem = new SubsystemConfig + { + SubsystemType = 0, + Name = "192.168.21.43_alarm", + Magic = "192.168.21.43" + } } }; + var clientId = _configuration["DahuaAuth:ClientId"]; + var token = await _tokenProviderService.GetTokenAsync(clientId!); // —— 发起请求 —— using var request = new HttpRequestMessage(HttpMethod.Post, url) { @@ -219,7 +138,7 @@ namespace Alarm.DomainService.DahAlarm }; // 大华网关要求:Authorization 放完整值(Bearer xxx) - request.Headers.TryAddWithoutValidation("Authorization", accessToken); + request.Headers.TryAddWithoutValidation("Authorization", token); request.Headers.Accept.ParseAdd("application/json"); using var resp = await _http.SendAsync(request); @@ -303,61 +222,5 @@ namespace Alarm.DomainService.DahAlarm } return result; } - - #region RES加密 - - private static String EncryptByPublicKey(String context, String publicKey) - { - RSACryptoServiceProvider rsa = new(); - - rsa.ImportParameters(FromXmlStringExtensions(ConvertToXmlPublicJavaKey(publicKey))); - byte[] byteText = System.Text.Encoding.UTF8.GetBytes(context); - byte[] byteEntry = rsa.Encrypt(byteText, false); - return Convert.ToBase64String(byteEntry); - } - - public static RSAParameters FromXmlStringExtensions(string xmlString) - { - RSAParameters parameters = new RSAParameters(); - - System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument(); - xmlDoc.LoadXml(xmlString); - - if (xmlDoc.DocumentElement!.Name.Equals("RSAKeyValue")) - { - foreach (System.Xml.XmlNode node in xmlDoc.DocumentElement.ChildNodes) - { - switch (node.Name) - { - case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break; - } - } - } - else - { - throw new Exception("Invalid XML RSA key."); - } - - return parameters; - } - - public static string ConvertToXmlPublicJavaKey(string publicJavaKey) - { - RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicJavaKey)); - string xmlpublicKey = string.Format("{0}{1}", - Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), - Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); - Console.WriteLine(xmlpublicKey); - return xmlpublicKey; - } - - #endregion RES加密 } } \ No newline at end of file diff --git a/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/IDahuaGeneralCtlService.cs b/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/IDahuaGeneralCtlService.cs index 147adbe..f348cd3 100644 --- a/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/IDahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/AlarmService/Alarm.DomainService/DahAlarm/IDahuaGeneralCtlService.cs @@ -9,25 +9,12 @@ namespace Alarm.DomainService.DahAlarm /// public interface IDahuaGeneralCtlService { - /// - /// 获取公钥 - /// - /// - Task> GetPublicKey(); - - /// - /// 鉴权 - /// - /// PublicKey - /// - Task> GetToken(LoginRequestDto dto); - /// /// 新增订阅报警事件 /// /// /// - Task> AddSubscribeEvent(string accessToken); + Task> AddSubscribeEvent(); /// /// AddSubscribeEvent回调函数处理 diff --git a/WeiCloud.Fusion/AlarmService/AlarmService.API/Controllers/AlarmController.cs b/WeiCloud.Fusion/AlarmService/AlarmService.API/Controllers/AlarmController.cs index b76761c..25a97de 100644 --- a/WeiCloud.Fusion/AlarmService/AlarmService.API/Controllers/AlarmController.cs +++ b/WeiCloud.Fusion/AlarmService/AlarmService.API/Controllers/AlarmController.cs @@ -20,26 +20,14 @@ namespace AlarmService.API.Controllers _generalCtlService = generalCtlService; } - /// - /// 大华视频的登录获取Token - /// - /// - /// - [HttpPost("token/dh")] - public async Task> GetDaHToken(LoginRequestDto dto) - { - return await _generalCtlService.GetToken(dto); - } - /// /// 订阅报警事件 /// - /// /// [HttpPost] - public async Task> AddSubscribeEvent(string accessToken) + public async Task> AddSubscribeEvent() { - return await _generalCtlService.AddSubscribeEvent(accessToken); + return await _generalCtlService.AddSubscribeEvent(); } /// @@ -48,7 +36,7 @@ namespace AlarmService.API.Controllers /// /// [HttpPost] - public async Task> HandleAsync(EventEnvelopeDto env) + public async Task> DahuaAuthCallback(EventEnvelopeDto env) { return await _generalCtlService.HandleAsync(env); } diff --git a/WeiCloud.Fusion/AlarmService/AlarmService.API/Properties/launchSettings.json b/WeiCloud.Fusion/AlarmService/AlarmService.API/Properties/launchSettings.json index 22a2459..b4be839 100644 --- a/WeiCloud.Fusion/AlarmService/AlarmService.API/Properties/launchSettings.json +++ b/WeiCloud.Fusion/AlarmService/AlarmService.API/Properties/launchSettings.json @@ -13,7 +13,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "launchUrl": "weatherforecast", + "launchUrl": "swagger", "applicationUrl": "http://localhost:5283", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -23,7 +23,7 @@ "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "launchUrl": "weatherforecast", + "launchUrl": "swagger", "applicationUrl": "https://localhost:7230;http://localhost:5283", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" @@ -32,10 +32,10 @@ "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, - "launchUrl": "weatherforecast", + "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } -} +} \ No newline at end of file diff --git a/WeiCloud.Fusion/AlarmService/AlarmService.API/appsettings.json b/WeiCloud.Fusion/AlarmService/AlarmService.API/appsettings.json index 355c787..79c0bdd 100644 --- a/WeiCloud.Fusion/AlarmService/AlarmService.API/appsettings.json +++ b/WeiCloud.Fusion/AlarmService/AlarmService.API/appsettings.json @@ -24,6 +24,9 @@ "ClientSecret": "6d6c78f8-3d4c-4e76-ab6b-827942a7b725", "Username": "system", - "Password": "Admin123" + "Password": "Admin123", + "Callback": "http://demo.weienergy.cn:5000/api/Alarm/DahuaAuthCallback", + "SubsystemName": "192.168.21.43_alarm", + "SubsystemMagic": "192.168.21.43" } } \ No newline at end of file diff --git a/WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/AppHost.cs b/WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/AppHost.cs index d3e2148..6e0bce7 100644 --- a/WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/AppHost.cs +++ b/WeiCloud.Fusion/AspireApp/Manage.AppHost.AppHost/AppHost.cs @@ -6,12 +6,10 @@ var apiService = builder.AddProject("apiserv var videoapi = builder.AddProject("videoapi"); var alarmapi = builder.AddProject("alarmapi"); -var sharedapi = builder.AddProject("sharedapi"); - builder.AddProject("webfrontend") .WithReference(videoapi) .WithReference(alarmapi) - .WithReference(sharedapi) + .WithExternalHttpEndpoints() .WithHttpHealthCheck("/health") .WithReference(apiService) diff --git a/WeiCloud.Fusion/VideoService/Video.API/Controllers/DaHua/VideoManageController.cs b/WeiCloud.Fusion/VideoService/Video.API/Controllers/DaHua/VideoManageController.cs index a830ca0..281f875 100644 --- a/WeiCloud.Fusion/VideoService/Video.API/Controllers/DaHua/VideoManageController.cs +++ b/WeiCloud.Fusion/VideoService/Video.API/Controllers/DaHua/VideoManageController.cs @@ -141,6 +141,17 @@ namespace Video.API.Controllers.DaHua return await _rootVideoPlaybackService.Logout(authorization, openId, userClient); } + /// + /// 返回下载地址 + /// + /// + /// + [HttpGet("download")] + public async Task Download(DownloadReqDto dto) + { + return await _rootVideoPlaybackService.Download(dto); + } + #endregion 大华视频处理 } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.Application/RequestDto/DahuaVideoQueryDto.cs b/WeiCloud.Fusion/VideoService/Video.Application/RequestDto/DahuaVideoQueryDto.cs index f597276..097cd35 100644 --- a/WeiCloud.Fusion/VideoService/Video.Application/RequestDto/DahuaVideoQueryDto.cs +++ b/WeiCloud.Fusion/VideoService/Video.Application/RequestDto/DahuaVideoQueryDto.cs @@ -336,4 +336,51 @@ namespace Video.Application [JsonPropertyName("recordType")] public string RecordType { get; set; } } + + public class DownloadReqDto + { + /// + /// 1. 通道编号(必选) + /// 组成=设备编码%24通道号; + /// 例如:通道编码是1000006$1$0$25,则通道编号为1000006%2425 + /// + [JsonPropertyName("vcuid")] + public required string Vcuid { get; set; } + + /// + /// 2. 码流类型(必选) + /// 1-主码流 2-辅码流 + /// + [JsonPropertyName("subtype")] + public required string Subtype { get; set; } = "1"; + + /// + /// 3. 开始时间(必选) + /// 格式:2023_3_23_14_48_36 + /// + [JsonPropertyName("starttime")] + public required string StartTime { get; set; } + + /// + /// 4. 结束时间(必选) + /// 格式:2023_3_23_18_48_36 + /// + [JsonPropertyName("endtime")] + public required string EndTime { get; set; } + + /// + /// 5. 录像回放类型(必选) + /// 2-设备录像 3-中心录像 + /// + [JsonPropertyName("videoType")] + public required string VideoType { get; set; } + + /// + /// 7. 录像类型(必选) + /// 录像存储为设备录像时,即videoType=2时,recordType固定送0; + /// 录像存储是中心存储时,即videoType=3时,参考枚举:1:普通录像 2:报警录像 81:补录录像 82:预录录像 + /// + [JsonPropertyName("recordType")] + public required string RecordType { get; set; } + } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs index 81d127f..df50009 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs @@ -404,5 +404,18 @@ namespace Video.DomainService return new DaHApiResult { Success = false, Code = "1010", Msg = "实时流请求失败" }; } } + + /// + /// 下载 + /// + /// + /// + /// + public async Task Download(DownloadReqDto dto) + { + var clientId = _configuration["DahuaAuth:ClientId"]; + var token = await _tokenProviderService.GetTokenAsync(clientId!); + return _configuration["DahuaAuth:Host"] + $"/evo-apigw/evo-httpnode/vod/cam/download.mp4?vcuid={dto.Vcuid}&subtype={dto.Subtype}&starttime={dto.StartTime}endtime={dto.EndTime}&videoType={dto.VideoType}&token={token}&recordType={dto.RecordType}"; + } } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IDahuaGeneralCtlService.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IDahuaGeneralCtlService.cs index 257ae7a..c3a19eb 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IDahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IDahuaGeneralCtlService.cs @@ -56,5 +56,12 @@ namespace Video.DomainService /// 没有返回值 /// Task> Logout(string authorization, string? openId, int? userClient); + + /// + /// 返回下载地址 + /// + /// + /// + Task Download(DownloadReqDto dto); } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IRootVideoPlaybackService.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IRootVideoPlaybackService.cs index bf18574..1ff573c 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IRootVideoPlaybackService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/IRootVideoPlaybackService.cs @@ -49,5 +49,12 @@ namespace Video.DomainService /// /// Task> Logout(string authorization, string? openId, int? userClient); + + /// + /// 返回下载地址 + /// + /// + /// + Task Download(DownloadReqDto dto); } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/RootVideoPlaybackService.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/RootVideoPlaybackService.cs index fe78aaa..3138167 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/RootVideoPlaybackService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/RootVideoPlaybackService.cs @@ -157,6 +157,16 @@ namespace Video.DomainService return result; } + /// + /// 返回下载地址 + /// + /// + /// + public async Task Download(DownloadReqDto dto) + { + return await _dahuaGeneralCtlService.Download(dto); + } + #endregion 大华视频处理 } } \ No newline at end of file