diff --git a/WeiCloud.Fusion/Common.SharedService/Common.Shared.Application/DaHua/RequestDto/DahuaVideoQueryDto.cs b/WeiCloud.Fusion/Common.SharedService/Common.Shared.Application/DaHua/RequestDto/DahuaVideoQueryDto.cs index d042e23..cbf4a22 100644 --- a/WeiCloud.Fusion/Common.SharedService/Common.Shared.Application/DaHua/RequestDto/DahuaVideoQueryDto.cs +++ b/WeiCloud.Fusion/Common.SharedService/Common.Shared.Application/DaHua/RequestDto/DahuaVideoQueryDto.cs @@ -59,6 +59,11 @@ namespace Common.Shared.Application.DaHua public class PlaybackReqDto { public PlaybackItem Data { get; set; } + + /// + /// 如果多个icc平台的话,决定是哪个平台的回放 + /// + public string? IpAddress { get; set; } } /// @@ -109,6 +114,11 @@ namespace Common.Shared.Application.DaHua public class RtspPlayBackReqDto { public RtspPlaybackItem Data { get; set; } + + /// + /// 如果多个icc平台的话,决定是哪个平台的回放 + /// + public string? IpAddress { get; set; } } /// @@ -258,6 +268,11 @@ namespace Common.Shared.Application.DaHua /// [JsonPropertyName("data")] public StreamRequestData Data { get; set; } + + /// + /// 如果多个icc平台的话,决定是哪个平台的回放 + /// + public string? IpAddress { get; set; } } /// @@ -270,6 +285,11 @@ namespace Common.Shared.Application.DaHua /// [JsonPropertyName("data")] public StreamRtspRequestData Data { get; set; } + + /// + /// 如果多个icc平台的话,决定是哪个平台的回放 + /// + public string? IpAddress { get; set; } } /// @@ -398,5 +418,10 @@ namespace Common.Shared.Application.DaHua /// [JsonPropertyName("recordType")] public required string RecordType { get; set; } + + /// + /// 如果多个icc平台的话,决定是哪个平台的回放 + /// + public string? IpAddress { get; set; } } } \ No newline at end of file diff --git a/WeiCloud.Fusion/VideoService/Video.API/Program.cs b/WeiCloud.Fusion/VideoService/Video.API/Program.cs index e58b492..f91072e 100644 --- a/WeiCloud.Fusion/VideoService/Video.API/Program.cs +++ b/WeiCloud.Fusion/VideoService/Video.API/Program.cs @@ -1,5 +1,6 @@ using Autofac; using Autofac.Extensions.DependencyInjection; +using Common.Shared.Application.DaHua; using Common.Shared.DomainService; using Microsoft.OpenApi.Models; using NLog; diff --git a/WeiCloud.Fusion/VideoService/Video.API/appsettings.json b/WeiCloud.Fusion/VideoService/Video.API/appsettings.json index 2485a3e..5c7aa11 100644 --- a/WeiCloud.Fusion/VideoService/Video.API/appsettings.json +++ b/WeiCloud.Fusion/VideoService/Video.API/appsettings.json @@ -22,19 +22,29 @@ "RedisConnection": "v4.weienergy.cn:6380,allowadmin=true,password=Zrhredis#2019,defaultDatabase=10", "DBConnection": "server=v4.weienergy.cn;uid=root;pwd=Zrhdb#2019;port=3307;database=WeiCloudDB.Cap;default command timeout=100;CharSet=utf8;SslMode=None;allowPublicKeyRetrieval=true" }, + "VideoOpen": "1", //0表示部署视频对接,1表示不对接 //大华摄像头的配置 "DahuaAuth": { "Host": "demo.weienergy.cn:15214", "ClientId": "taiyanggong", - "RealRootHost": "192.168.21.18:9100", //RTSP实时播放的icc地址 - "RealReplaceHost": "demo.weienergy.cn:15210", //rtps试试播放的替换地址 - "TimeRootHost": "192.168.21.18:9320", //RTSP历史回放的icc地址 - "TimeReplaceHost": "demo.weienergy.cn:15211", //rtps历史回放的替换地址 - "ClientSecret": "6d6c78f8-3d4c-4e76-ab6b-827942a7b725", - "Username": "system", - "Password": "Admin123" + "Password": "Admin123", + "Real": { + "DefaultRoot": "192.168.21.18:9100", + "DefaultReplace": "demo.weienergy.cn:15210", + "Overrides": { + "192.168.21.20:9100": "demo.weienergy.cn:15210", + "10.20.30.40:9100": "demo.weienergy.cn:15210" + } + }, + "Time": { + "DefaultRoot": "192.168.21.18:9320", + "DefaultReplace": "demo.weienergy.cn:15211", + "Overrides": { + "192.168.21.20:9320": "demo.weienergy.cn:15211" + } + } } } \ 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 482f21a..e234798 100644 --- a/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/DahuaGeneralCtlService.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System.Net.Http.Json; using System.Text.Json; +using Video.DomainService.Dahvision; namespace Video.DomainService { @@ -48,15 +49,18 @@ namespace Video.DomainService try { - // 2) Token:优先入参,其次缓存/获取(建议返回完整的 "Bearer xxx") var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("hls等录像回放:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; } var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/admin/API/video/stream/record"; + if (dto.IpAddress != null) + { + url = $"https://{dto.IpAddress}/evo-apigw/admin/API/video/stream/record"; + } // 3) 构造请求(把 dto 放进 Body),并用 SendAsync 发送,才能带上头 using var req = new HttpRequestMessage(HttpMethod.Post, url) @@ -80,7 +84,12 @@ namespace Video.DomainService _logger.LogWarning("录像请求业务失败: {Body}", body); return new DaHApiResult { Success = false, Code = "1008", Msg = "录像请求失败" }; } - result.Data!.Url = result.Data.Url + "?token=" + token; + result.Data!.Url = UrlHostReplacer.ReplaceHost( + result.Data.Url, + dto.IpAddress, + _configuration, + "Time" + ) + "?token=" + result.Data.Token; return result; } catch (Exception ex) @@ -107,13 +116,16 @@ namespace Video.DomainService var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("查询普通录像信息列表:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; } var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/admin/API/SS/Record/QueryRecords"; - + if (dto.IpAddress != null) + { + url = $"https://{dto.IpAddress}/evo-apigw/admin/API/SS/Record/QueryRecords"; + } using var req = new HttpRequestMessage(HttpMethod.Post, url) { Content = JsonContent.Create(dto) // 关键:把 dto 放进请求体 @@ -164,7 +176,7 @@ namespace Video.DomainService var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("通道分页查询失败:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; @@ -225,7 +237,7 @@ namespace Video.DomainService // 2) Token:优先用入参;否则走缓存/获取(建议返回已带前缀的 "Bearer xxx") var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning(" HLS实时流请求失败:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; @@ -233,6 +245,11 @@ namespace Video.DomainService var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/admin/API/video/stream/realtime"; + if (dto.IpAddress != null) + { + url = $"https://{dto.IpAddress}/evo-apigw/admin/API/video/stream/realtime"; + } + // 3) 用 HttpRequestMessage 发送,才能带上自定义头 using var req = new HttpRequestMessage(HttpMethod.Post, url) { @@ -255,7 +272,12 @@ namespace Video.DomainService _logger.LogWarning("实时流请求业务失败: {Body}", body); return new DaHApiResult { Success = false, Code = "1010", Msg = "实时流请求失败" }; } - result.Data!.Url = result.Data.Url + "?token=" + token; + result.Data!.Url = UrlHostReplacer.ReplaceHost( + result.Data.Url, + dto.IpAddress, + _configuration, + "Real" + ) + "?token=" + result.Data.Token; return result; } catch (Exception ex) @@ -335,13 +357,17 @@ namespace Video.DomainService // 先用缓存里的 token,不足5分钟过期再刷新(按你之前的口径来) var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("rtsp录像回放:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; } var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/admin/API/SS/Playback/StartPlaybackByTime"; + if (dto.IpAddress != null) + { + url = $"https://{dto.IpAddress}/evo-apigw/admin/API/SS/Playback/StartPlaybackByTime"; + } using var req = new HttpRequestMessage(HttpMethod.Post, url) { @@ -366,7 +392,12 @@ namespace Video.DomainService _logger.LogWarning("录像请求业务失败: {Body}", body); return new DaHApiResult { Success = false, Code = "1008", Msg = "录像请求失败" }; } - result.Data!.Url = result.Data.Url.Replace(_configuration["DahuaAuth:TimeRootHost"], _configuration["DahuaAuth:TimeReplaceHost"]) + "?token=" + result.Data.Token; + result.Data!.Url = UrlHostReplacer.ReplaceHost( + result.Data.Url, + dto.IpAddress, + _configuration, + "Time" + ) + "?token=" + result.Data.Token; return result; } catch (Exception ex) @@ -393,13 +424,17 @@ namespace Video.DomainService var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("rtsp实时预览接口方式:token无效"); return new DaHApiResult { Success = false, Code = "1009", Msg = "token无效" }; } var url = $"https://{_configuration["DahuaAuth:Host"]}/evo-apigw/admin/API/MTS/Video/StartVideo"; + if (dto.IpAddress != null) + { + url = $"https://{dto.IpAddress}/evo-apigw/admin/API/MTS/Video/StartVideo"; + } using var req = new HttpRequestMessage(HttpMethod.Post, url) { @@ -424,7 +459,12 @@ namespace Video.DomainService _logger.LogWarning("实时流请求业务失败: {Body}", body); return new DaHApiResult { Success = false, Code = "1010", Msg = "实时流请求失败" }; } - result.Data!.Url = result.Data.Url.Replace(_configuration["DahuaAuth:RealRootHost"], _configuration["DahuaAuth:RealReplaceHost"]) + "?token=" + result.Data!.Token; + result.Data!.Url = UrlHostReplacer.ReplaceHost( + result.Data.Url, + dto.IpAddress, + _configuration, + "Real" + ) + "?token=" + result.Data.Token; return result; } catch (Exception ex) @@ -444,13 +484,18 @@ namespace Video.DomainService { var clientId = _configuration["DahuaAuth:ClientId"]; var token = await _tokenProviderService.GetTokenAsync(clientId!); - if (_tokenProviderService.IsTokenValid(token)) + if (!_tokenProviderService.IsTokenValid(token)) { _logger.LogWarning("下载:token无效"); return "下载地址无效"; } - 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}"; + var url = _configuration["DahuaAuth:Host"]; + if (dto.IpAddress != null) + { + url = dto.IpAddress; + } + return url + $"/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/UrlHostReplacer.cs b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs new file mode 100644 index 0000000..1d4e020 --- /dev/null +++ b/WeiCloud.Fusion/VideoService/Video.DomainService/Dahvision/UrlHostReplacer.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Configuration; + +namespace Video.DomainService.Dahvision +{ + public static class UrlHostReplacer + { + public static string ReplaceHost(string url, string? ipAddress, IConfiguration config, string sectionName) + { + var section = config.GetSection($"DahuaAuth:{sectionName}"); + var defaultRoot = section["DefaultRoot"]!; + var defaultReplace = section["DefaultReplace"]!; + + // 1) 确定 fromHost + var fromHost = string.IsNullOrWhiteSpace(ipAddress) ? defaultRoot : ipAddress; + + // 2) 尝试在 Overrides 找对应的 value + var overrides = section.GetSection("Overrides").Get>() ?? new(); + var toHost = overrides.TryGetValue(fromHost, out var mapped) + ? mapped + : defaultReplace; + + // 3) 字符串替换 + return url.Replace(fromHost, toHost, StringComparison.OrdinalIgnoreCase); + } + } +} \ No newline at end of file