Merge branch 'DataMaintenance' of http://123.132.248.154:10000/HC_YFZX/Infrastructure into DataMaintenance
commit
510890b0e1
|
|
@ -0,0 +1,668 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using Newtonsoft.Json;
|
||||
using System.Globalization;
|
||||
using InvalidOperationException = System.InvalidOperationException;
|
||||
|
||||
namespace Infrastructure.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 大华平台API访问工具类
|
||||
/// </summary>
|
||||
public class DaHuaApi
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _baseUrl = "https://icc-dev.hibetatest.com:4077";
|
||||
private readonly string _kccKey;
|
||||
private readonly string _kccSecret;
|
||||
private readonly string _kccId;
|
||||
private static OAuthTokenResponse _currentToken;
|
||||
private static DateTime _tokenExpiry;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数(KCC认证方式)
|
||||
/// </summary>
|
||||
/// <param name="baseUrl">API基础URL</param>
|
||||
/// <param name="kccId">KCC ID</param>
|
||||
/// <param name="kccKey">KCC Key</param>
|
||||
/// <param name="kccSecret">KCC Secret</param>
|
||||
public DaHuaApi(string baseUrl, string kccId, string kccKey, string kccSecret)
|
||||
{
|
||||
_baseUrl = baseUrl;
|
||||
_kccId = kccId;
|
||||
_kccKey = kccKey;
|
||||
_kccSecret = kccSecret;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数(OAuth2认证方式)
|
||||
/// </summary>
|
||||
/// <param name="baseUrl">API基础URL</param>
|
||||
public DaHuaApi(string baseUrl)
|
||||
{
|
||||
_baseUrl = baseUrl;
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用用户名密码方式进行OAuth2认证获取Token
|
||||
/// </summary>
|
||||
/// <param name="clientId">客户端ID</param>
|
||||
/// <param name="clientSecret">客户端密钥</param>
|
||||
/// <param name="username">用户名</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <returns>认证结果</returns>
|
||||
public async Task<OAuthTokenResponse> AuthenticateAsync(string clientId, string clientSecret, string username,
|
||||
string password)
|
||||
{
|
||||
// 1. 获取公钥
|
||||
var publicKeyResponse =
|
||||
await _httpClient.GetAsync($"{_baseUrl}/evo-apigw/evo-oauth/1.0.0/oauth/public-key");
|
||||
var publicKeyResult =
|
||||
JsonConvert.DeserializeObject<PublicKeyResponse>(await publicKeyResponse.Content.ReadAsStringAsync());
|
||||
|
||||
if (!publicKeyResult.Success)
|
||||
{
|
||||
throw new InvalidOperationException($"获取公钥失败: {publicKeyResult.ErrMsg}");
|
||||
}
|
||||
|
||||
var encryptedPassword = RsaHelper.Encrypt(password, publicKeyResult.Data.PublicKey);
|
||||
|
||||
// 3. 获取Token
|
||||
var tokenRequest = new
|
||||
{
|
||||
grant_type = "password",
|
||||
username = username,
|
||||
password = encryptedPassword,
|
||||
client_id = clientId,
|
||||
client_secret = clientSecret,
|
||||
public_key = publicKeyResult.Data.PublicKey
|
||||
};
|
||||
|
||||
var json = JsonConvert.SerializeObject(tokenRequest);
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
|
||||
var tokenResponse =
|
||||
await _httpClient.PostAsync($"{_baseUrl}/evo-apigw/evo-oauth/1.0.0/oauth/extend/token", content);
|
||||
var result = await tokenResponse.Content.ReadAsStringAsync();
|
||||
// {"success":true,"data":{"access_token":"2:3hRw0P7m3YD7skQwL9qNoPtcg9by378W","refresh_token":"KGnWspOzRdwFcD9D3bKztHc12H41vNjT","magicId":"TjNv14H21cHtzKb3D9DcFwdRzOpsWnGK","scope":"supplier","remainderDays":166,"token_type":"bearer","expires_in":7199,"userId":"2"},"code":"0","errMsg":""}
|
||||
var tokenResult =
|
||||
JsonConvert.DeserializeObject<OAuthTokenResponse>(result);
|
||||
|
||||
if (tokenResult.success)
|
||||
{
|
||||
_currentToken = tokenResult;
|
||||
_tokenExpiry = DateTime.UtcNow.AddSeconds(tokenResult.data.expires_in - 60); // 提前60秒过期以避免边界问题
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"获取Token失败: {tokenResult.errMsg}");
|
||||
}
|
||||
|
||||
return tokenResult;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 确保Token有效
|
||||
/// </summary>
|
||||
private async Task EnsureValidTokenAsync()
|
||||
{
|
||||
if (_currentToken == null || DateTime.UtcNow > _tokenExpiry)
|
||||
{
|
||||
await AuthenticateAsync("CompanyName", "42bec152-8f04-476a-9aec-e7d616ff3cb3",
|
||||
"TEST", "OGR28u6_cc");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成KCC签名
|
||||
/// </summary>
|
||||
/// <param name="method">HTTP方法</param>
|
||||
/// <param name="uri">请求URI</param>
|
||||
/// <param name="body">请求体</param>
|
||||
/// <param name="timestamp">时间戳</param>
|
||||
/// <returns>KCC签名字符串</returns>
|
||||
private string GenerateKccSignature(string method, string uri, string body, long timestamp)
|
||||
{
|
||||
// 构建签名原文
|
||||
var signString = $"POST\n{uri}\n{body}\n{_kccId}\n{timestamp}";
|
||||
|
||||
// 使用HMAC-SHA1算法计算签名
|
||||
using (var hmac = new HMACSHA1(Encoding.UTF8.GetBytes(_kccSecret)))
|
||||
{
|
||||
var hashBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signString));
|
||||
return Convert.ToBase64String(hashBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置请求的认证头部
|
||||
/// </summary>
|
||||
/// <param name="uri">请求URI</param>
|
||||
/// <param name="json">请求体JSON</param>
|
||||
private async Task SetAuthorizationHeaderAsync(string uri, string json)
|
||||
{
|
||||
_httpClient.DefaultRequestHeaders.Clear();
|
||||
// 如果有KCC配置,使用KCC认证
|
||||
if (!string.IsNullOrEmpty(_kccId) && !string.IsNullOrEmpty(_kccKey) && !string.IsNullOrEmpty(_kccSecret))
|
||||
{
|
||||
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var signature = GenerateKccSignature("POST", uri, json, timestamp);
|
||||
|
||||
_httpClient.DefaultRequestHeaders.Add("KCC-ID", _kccId);
|
||||
_httpClient.DefaultRequestHeaders.Add("KCC-TS", timestamp.ToString());
|
||||
_httpClient.DefaultRequestHeaders.Add("KCC-SIGN", signature);
|
||||
}
|
||||
// 如果有Token,使用OAuth2认证
|
||||
else
|
||||
{
|
||||
await EnsureValidTokenAsync();
|
||||
_httpClient.DefaultRequestHeaders.Add("Authorization",
|
||||
$"{_currentToken.data.token_type} {_currentToken.data.access_token}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取设备通道分类信息
|
||||
/// 对应接口: /evo-api/go/geo-term/i.a.o/device/channel/subsystem/page
|
||||
/// </summary>
|
||||
/// <param name="request">请求参数</param>
|
||||
/// <returns>通道分类信息响应</returns>
|
||||
public async Task<ChannelCategoryResponse> GetChannelCategoriesAsync(ChannelCategoryRequest request)
|
||||
{
|
||||
var url = $"{_baseUrl}/evo-apigw/evo-brm/1.2.0/device/channel/subsystem/page";
|
||||
var uri = "/evo-apigw/evo-brm/1.2.0/device/channel/subsystem/page";
|
||||
|
||||
var json = JsonConvert.SerializeObject(request);
|
||||
|
||||
// 设置认证头部
|
||||
await SetAuthorizationHeaderAsync(uri, json);
|
||||
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
var responseString = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
// {"success":true,
|
||||
// "data":{"pageData":
|
||||
// [{"id":110,"deviceCode":"1000102","unitType":1,
|
||||
// "unitSeq":0,"channelSeq":0,"channelCode":"1000102$1$0$0",
|
||||
// "channelName":"1.1.1.1_1","channelType":"1","cameraType":"2",
|
||||
// "ownerCode":"001001","gpsX":"","gpsY":"","isOnline":0,
|
||||
// "stat":1,"capability":"00000000000000000000000000000001","chExt":"{}",
|
||||
// "isVirtual":0,"createTime":"2025-11-11 15:43:30"},
|
||||
// {"id":108,"deviceCode":"1000099","unitType":7,"unitSeq":0,"channelSeq":0,"channelCode":"1000099$7$0$0",
|
||||
// "channelSn":"","channelName":"膨化食品测试设备-1_门禁通道_1",
|
||||
// "ownerCode":"001010","isOnline":0,"stat":1,
|
||||
// "chExt":"{\"workStatus\":5,\"psamEnable\":0,\"isUse\":\"0\",
|
||||
// \"channelBindFace\":\"\",\"channelBindOrg\":\"\",\"cpuCardEnable\":1,
|
||||
// \"physicalId\":\"\",\"channelCapacity\":5,\"channelUnii\":\"\",\"closeTimeOut\":60,\"icCardEnable\":1,\"collaborativeEnable\":0,\"snapshotUpload\":0,\"enableMode\":0,\"timeoutAlarmEnable\":0,\"manapassword\":\"12345678\",\"collectTypeFlag\":7,\"channelPersonType\":1,\"nfcAntiCopyEnable\":0,\"readerList\":[{\"name\":\"膨化食品测试设备-1_门禁通道_1读卡器1\",\"code\":1,\"openType\":26,\"businessType\":1},{\"name\":\"膨化食品测试设备-1_门禁通道_1读卡器2\",\"code\":2,\"openType\":26,\"businessType\":2}],\"icEncryptEnable\":0,\"delayTime\":3,\"status\":\"5\"}","isVirtual":0,"createTime":"2025-11-06 13:31:30"},{"id":109,"deviceCode":"1000099","unitType":1,"unitSeq":0,"channelSeq":0,"channelCode":"1000099$1$0$0","channelSn":"","channelName":"膨化食品测试设备-1_视频通道_1","channelType":"1","cameraType":"2","ownerCode":"001010","isOnline":0,"stat":1,"capability":"00000000000000000000000000000000","chExt":"{\"keyCode\":\"\"}","isVirtual":0,"createTime":"2025-11-06 13:31:30"},{"id":63,"deviceCode":"1000056","unitType":1,"unitSeq":0,"channelSeq":0,"channelCode":"1000056$1$0$0","channelName":"127.0.0.2_1","channelType":"1","cameraType":"2","ownerCode":"001006","gpsX":"","gpsY":"","isOnline":0,"stat":1,"capability":"00000000000000000000001100000001","chExt":"{\"keyCode\":\"\"}","isVirtual":0,"createTime":"2025-09-25 16:22:56"},{"id":10,"deviceCode":"1000008","unitType":1,"unitSeq":0,"channelSeq":0,"channelCode":"1000008$1$0$0","channelSn":"1007749","channelName":"IPC10001001_1","channelType":"1","cameraType":"2","ownerCode":"001002001","gpsX":"","gpsY":"","isOnline":1,"stat":1,"capability":"00000000000000000000000100000001","chExt":"{\"keyCode\":\"\"}","isVirtual":0,"createTime":"2025-09-09 16:18:44"},{"id":4,"deviceCode":"1000002","unitType":4,"unitSeq":0,"channelSeq":0,"channelCode":"1000002$4$0$0","channelName":"9G0D671YAJB4F8F_1","ownerCode":"001001","gpsX":"","gpsY":"","isOnline":1,"stat":1,"isVirtual":0,"createTime":"2025-09-08 20:36:40"},{"id":3,"deviceCode":"1000002","unitType":3,"unitSeq":0,"channelSeq":1,"channelCode":"1000002$3$0$1","channelName":"9G0D671YAJB4F8F_2","ownerCode":"001001","gpsX":"","gpsY":"","isOnline":1,"stat":1,"chExt":"{\"alarmType\":\"2\",\"alarmLevel\":\"1\"}","isVirtual":0,"createTime":"2025-09-08 20:36:40"},{"id":2,"deviceCode":"1000002","unitType":3,"unitSeq":0,"channelSeq":0,"channelCode":"1000002$3$0$0","channelName":"9G0D671YAJB4F8F_1","ownerCode":"001001","gpsX":"","gpsY":"","isOnline":1,"stat":1,"chExt":"{\"alarmType\":\"6001\",\"alarmLevel\":\"1\"}","isVirtual":0,"createTime":"2025-09-08 20:36:40"},{"id":1,"deviceCode":"1000002","unitType":1,"unitSeq":0,"channelSeq":0,"channelCode":"1000002$1$0$0","channelName":"DH-SD-6C3232-HNY-DB-EFR","channelType":"1","cameraType":"2","ownerCode":"001001","gpsX":"120.519063","gpsY":"30.381539","isOnline":1,"stat":1,"capability":"00000000000000010000000000000001","chExt":"{}","isVirtual":0,"createTime":"2025-09-08 20:36:40"}],"currentPage":1,"totalPage":1,"pageSize":10,"totalRows":9},"code":"0","errMsg":""}
|
||||
return JsonConvert.DeserializeObject<ChannelCategoryResponse>(responseString);
|
||||
}
|
||||
|
||||
throw new HttpRequestException($"请求失败: {response.StatusCode}, {responseString}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 启动RTSP实时预览
|
||||
/// 对应接口: /evo-api/go/admin/API/MTS/Video/StartVideo
|
||||
/// </summary>
|
||||
/// <param name="request">预览请求参数</param>
|
||||
/// <returns>RTSP预览响应</returns>
|
||||
public async Task<RtspPreviewResponse> StartRtspPreviewAsync(RtspPreviewRequest request)
|
||||
{
|
||||
var url = $"{_baseUrl}/evo-apigw/admin/API/MTS/Video/StartVideo";
|
||||
var uri = "/evo-apigw/admin/API/MTS/Video/StartVideo";
|
||||
|
||||
var requestData = new Dictionary<string, object>
|
||||
{
|
||||
["data"] = request.data
|
||||
};
|
||||
var json = JsonConvert.SerializeObject(requestData);
|
||||
|
||||
// 设置认证头部
|
||||
await SetAuthorizationHeaderAsync(uri, json);
|
||||
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
var responseString = await response.Content.ReadAsStringAsync();
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<RtspPreviewResponse>(responseString);
|
||||
}
|
||||
|
||||
throw new HttpRequestException($"请求失败: {response.StatusCode}, {responseString}");
|
||||
}
|
||||
}
|
||||
|
||||
#region OAuth2认证相关模型
|
||||
|
||||
/// <summary>
|
||||
/// 公钥响应
|
||||
/// </summary>
|
||||
public class PublicKeyResponse
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Code { get; set; }
|
||||
public string ErrMsg { get; set; }
|
||||
public PublicKeyData Data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 公钥数据
|
||||
/// </summary>
|
||||
public class PublicKeyData
|
||||
{
|
||||
public string PublicKey { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OAuth2 Token响应
|
||||
/// </summary>
|
||||
public class OAuthTokenResponse
|
||||
{
|
||||
public bool success { get; set; }
|
||||
public string code { get; set; }
|
||||
public string errMsg { get; set; }
|
||||
public OAuthTokenData data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OAuth2 Token数据
|
||||
/// </summary>
|
||||
public class OAuthTokenData
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public string refresh_token { get; set; }
|
||||
public string magicId { get; set; }
|
||||
public string scope { get; set; }
|
||||
public int remainderDays { get; set; }
|
||||
public string token_type { get; set; }
|
||||
public long expires_in { get; set; }
|
||||
public string userId { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ChannelCategory相关模型定义
|
||||
|
||||
/// <summary>
|
||||
/// 设备通道分类请求参数
|
||||
/// </summary>
|
||||
public class ChannelCategoryRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前页码
|
||||
/// </summary>
|
||||
public int pageNum { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 每页大小
|
||||
/// </summary>
|
||||
public int pageSize { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 排序字段
|
||||
/// </summary>
|
||||
public string sort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序方式 ASC/DESC
|
||||
/// </summary>
|
||||
public string sortType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有者编码
|
||||
/// </summary>
|
||||
public string ownerCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备编码列表
|
||||
/// </summary>
|
||||
public List<string> deviceCodeList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道编码列表
|
||||
/// </summary>
|
||||
public List<string> channelCodeList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备大类
|
||||
/// </summary>
|
||||
public int? deviceCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备小类
|
||||
/// </summary>
|
||||
public int? deviceType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单元类型列表
|
||||
/// </summary>
|
||||
public List<int> unitTypeList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道类型列表
|
||||
/// </summary>
|
||||
public List<int> channelTypeList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
public int? isOnline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已接入
|
||||
/// </summary>
|
||||
public int? access { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否虚拟
|
||||
/// </summary>
|
||||
public int? isVirtual { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备通道状态
|
||||
/// </summary>
|
||||
public int? stat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含子设备编码标签
|
||||
/// </summary>
|
||||
public bool includeSubOwnerCodeFlag { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通道分类查询响应
|
||||
/// </summary>
|
||||
public class ChannelCategoryResponse
|
||||
{
|
||||
public string errMsg { get; set; }
|
||||
|
||||
public bool success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public int code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据
|
||||
/// </summary>
|
||||
public ChannelCategoryData data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通道分类响应数据
|
||||
/// </summary>
|
||||
public class ChannelCategoryData
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public int currentPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总页数
|
||||
/// </summary>
|
||||
public int totalPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 每页大小
|
||||
/// </summary>
|
||||
public int pageSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总行数
|
||||
/// </summary>
|
||||
public int totalRows { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 页面数据
|
||||
/// </summary>
|
||||
public List<ChannelInfoVO> pageData { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 通道信息
|
||||
/// </summary>
|
||||
public class ChannelInfoVO
|
||||
{
|
||||
/// <summary>
|
||||
/// ID
|
||||
/// </summary>
|
||||
public long id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备编码
|
||||
/// </summary>
|
||||
public string deviceCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单元类型
|
||||
/// </summary>
|
||||
public int unitType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 单元序列
|
||||
/// </summary>
|
||||
public int unitSeq { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道序列
|
||||
/// </summary>
|
||||
public int channelSeq { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道编码
|
||||
/// </summary>
|
||||
public string channelCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道序号
|
||||
/// </summary>
|
||||
public string channelSn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道名称
|
||||
/// </summary>
|
||||
public string channelName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道类型
|
||||
/// </summary>
|
||||
public string channelType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 摄像头类型
|
||||
/// </summary>
|
||||
public string cameraType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有者编码
|
||||
/// </summary>
|
||||
public string ownerCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GPS X坐标
|
||||
/// </summary>
|
||||
public string gpsX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// GPS Y坐标
|
||||
/// </summary>
|
||||
public string gpsY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 光栅图ID
|
||||
/// </summary>
|
||||
public long mapId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 域ID
|
||||
/// </summary>
|
||||
public long domainId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public string memo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否在线
|
||||
/// </summary>
|
||||
public int isOnline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 状态
|
||||
/// </summary>
|
||||
public int stat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 能力集
|
||||
/// </summary>
|
||||
public string capability { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已接入
|
||||
/// </summary>
|
||||
public int access { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 通道详情扩展信息Json体
|
||||
/// </summary>
|
||||
public string chExt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否是虚拟通道
|
||||
/// </summary>
|
||||
public string isVirtual { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RTSP预览相关模型定义
|
||||
|
||||
/// <summary>
|
||||
/// RTSP预览请求参数
|
||||
/// </summary>
|
||||
public class RtspPreviewRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据部分
|
||||
/// </summary>
|
||||
public RtspPreviewData data { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RTSP预览数据部分
|
||||
/// </summary>
|
||||
public class RtspPreviewData
|
||||
{
|
||||
/// <summary>
|
||||
/// 视频通道编码
|
||||
/// </summary>
|
||||
public string channelId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据类型:1-视频
|
||||
/// </summary>
|
||||
public string dataType { get; set; } = "1";
|
||||
|
||||
/// <summary>
|
||||
/// 码流类型:1-主码流,2-辅码流,3-编码流
|
||||
/// </summary>
|
||||
public string streamType { get; set; } = "1";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RTSP预览响应
|
||||
/// </summary>
|
||||
public class RtspPreviewResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// 状态码
|
||||
/// </summary>
|
||||
public int code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 描述信息
|
||||
/// </summary>
|
||||
public string errMsg { get; set; }
|
||||
public bool success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 响应数据
|
||||
/// </summary>
|
||||
public RtspPreviewResult data { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RTSP预览结果数据
|
||||
/// </summary>
|
||||
public class RtspPreviewResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 最低帧率
|
||||
/// </summary>
|
||||
public string minRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 协议
|
||||
/// </summary>
|
||||
public string protocol { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// IP地址
|
||||
/// </summary>
|
||||
public string ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 端口号
|
||||
/// </summary>
|
||||
public string port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用STUN协议
|
||||
/// </summary>
|
||||
public string stunEnable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// STUN协议端口
|
||||
/// </summary>
|
||||
public string stunPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// RTSP地址
|
||||
/// </summary>
|
||||
public string url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连接类型
|
||||
/// </summary>
|
||||
public string connectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 会话ID
|
||||
/// </summary>
|
||||
public string session { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 令牌
|
||||
/// </summary>
|
||||
public string token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 轨迹ID
|
||||
/// </summary>
|
||||
public string trackId { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace Infrastructure.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// RSA加解密帮助类 (.NET 6 兼容版本)
|
||||
/// </summary>
|
||||
public class RsaHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成RSA密钥对
|
||||
/// </summary>
|
||||
/// <returns>包含公钥和私钥的元组</returns>
|
||||
public static (string publicKey, string privateKey) GenerateKeyPair()
|
||||
{
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
// 设置密钥大小为2048位
|
||||
rsa.KeySize = 2048;
|
||||
|
||||
// 使用PEM格式导出密钥
|
||||
var publicKey = ExportPublicKey(rsa);
|
||||
var privateKey = ExportPrivateKey(rsa);
|
||||
return (publicKey, privateKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用公钥加密数据
|
||||
/// </summary>
|
||||
/// <param name="plainText">明文</param>
|
||||
/// <param name="publicKey">公钥(PEM格式)</param>
|
||||
/// <returns>Base64编码的密文</returns>
|
||||
public static string Encrypt(string plainText, string publicKey)
|
||||
{
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
ImportPublicKey(rsa, publicKey);
|
||||
var data = Encoding.UTF8.GetBytes(plainText);
|
||||
var encryptedData = rsa.Encrypt(data, RSAEncryptionPadding.Pkcs1);
|
||||
return Convert.ToBase64String(encryptedData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用私钥解密数据
|
||||
/// </summary>
|
||||
/// <param name="cipherText">Base64编码的密文</param>
|
||||
/// <param name="privateKey">私钥(PEM格式)</param>
|
||||
/// <returns>解密后的明文</returns>
|
||||
public static string Decrypt(string cipherText, string privateKey)
|
||||
{
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
ImportPrivateKey(rsa, privateKey);
|
||||
var data = Convert.FromBase64String(cipherText);
|
||||
var decryptedData = rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
|
||||
return Encoding.UTF8.GetString(decryptedData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用私钥签名数据
|
||||
/// </summary>
|
||||
/// <param name="data">要签名的数据</param>
|
||||
/// <param name="privateKey">私钥(PEM格式)</param>
|
||||
/// <returns>Base64编码的签名</returns>
|
||||
public static string SignData(string data, string privateKey)
|
||||
{
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
ImportPrivateKey(rsa, privateKey);
|
||||
var dataBytes = Encoding.UTF8.GetBytes(data);
|
||||
var signatureBytes = rsa.SignData(dataBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
return Convert.ToBase64String(signatureBytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用公钥验证签名
|
||||
/// </summary>
|
||||
/// <param name="data">原始数据</param>
|
||||
/// <param name="signature">Base64编码的签名</param>
|
||||
/// <param name="publicKey">公钥(PEM格式)</param>
|
||||
/// <returns>验证是否成功</returns>
|
||||
public static bool VerifyData(string data, string signature, string publicKey)
|
||||
{
|
||||
using (var rsa = RSA.Create())
|
||||
{
|
||||
ImportPublicKey(rsa, publicKey);
|
||||
var dataBytes = Encoding.UTF8.GetBytes(data);
|
||||
var signatureBytes = Convert.FromBase64String(signature);
|
||||
return rsa.VerifyData(dataBytes, signatureBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出公钥为PEM格式
|
||||
/// </summary>
|
||||
/// <param name="rsa">RSA实例</param>
|
||||
/// <returns>PEM格式公钥</returns>
|
||||
private static string ExportPublicKey(RSA rsa)
|
||||
{
|
||||
// 使用SubjectPublicKeyInfo格式导出公钥
|
||||
var publicKey = rsa.ExportSubjectPublicKeyInfo();
|
||||
return ExportToPem(publicKey, "PUBLIC KEY");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导出私钥为PEM格式
|
||||
/// </summary>
|
||||
/// <param name="rsa">RSA实例</param>
|
||||
/// <returns>PEM格式私钥</returns>
|
||||
private static string ExportPrivateKey(RSA rsa)
|
||||
{
|
||||
// 使用Pkcs8格式导出私钥
|
||||
var privateKey = rsa.ExportPkcs8PrivateKey();
|
||||
return ExportToPem(privateKey, "PRIVATE KEY");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从PEM格式导入公钥
|
||||
/// </summary>
|
||||
/// <param name="rsa">RSA实例</param>
|
||||
/// <param name="publicKey">PEM格式公钥</param>
|
||||
private static void ImportPublicKey(RSA rsa, string publicKey)
|
||||
{
|
||||
var keyData = ImportFromPem(publicKey);
|
||||
// 使用ImportSubjectPublicKeyInfo导入公钥
|
||||
rsa.ImportSubjectPublicKeyInfo(keyData, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从PEM格式导入私钥
|
||||
/// </summary>
|
||||
/// <param name="rsa">RSA实例</param>
|
||||
/// <param name="privateKey">PEM格式私钥</param>
|
||||
private static void ImportPrivateKey(RSA rsa, string privateKey)
|
||||
{
|
||||
var keyData = ImportFromPem(privateKey);
|
||||
// 使用ImportPkcs8PrivateKey导入私钥
|
||||
rsa.ImportPkcs8PrivateKey(keyData, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将字节数组导出为PEM格式
|
||||
/// </summary>
|
||||
/// <param name="keyData">密钥数据</param>
|
||||
/// <param name="type">密钥类型</param>
|
||||
/// <returns>PEM格式字符串</returns>
|
||||
private static string ExportToPem(byte[] keyData, string type)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
builder.AppendLine($"-----BEGIN {type}-----");
|
||||
|
||||
var base64String = Convert.ToBase64String(keyData);
|
||||
for (int i = 0; i < base64String.Length; i += 64)
|
||||
{
|
||||
builder.AppendLine(base64String.Substring(i, Math.Min(64, base64String.Length - i)));
|
||||
}
|
||||
|
||||
builder.AppendLine($"-----END {type}-----");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从PEM格式导入数据
|
||||
/// </summary>
|
||||
/// <param name="pemData">PEM格式数据</param>
|
||||
/// <returns>密钥字节数组</returns>
|
||||
private static byte[] ImportFromPem(string pemData)
|
||||
{
|
||||
var lines = pemData.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var base64Data = new StringBuilder();
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var trimmedLine = line.Trim();
|
||||
if (!trimmedLine.StartsWith("---") && !string.IsNullOrEmpty(trimmedLine))
|
||||
{
|
||||
base64Data.Append(trimmedLine);
|
||||
}
|
||||
}
|
||||
|
||||
return Convert.FromBase64String(base64Data.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ using SqlSugar;
|
|||
using System.Net.WebSockets;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Infrastructure.Helpers;
|
||||
using Yitter.IdGenerator;
|
||||
using static Org.BouncyCastle.Math.EC.ECCurve;
|
||||
|
||||
|
|
@ -43,7 +44,9 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
private IConfiguration _configuration;
|
||||
IOptions<KikvisionConfig> _options;
|
||||
IOptions<JPushClientConfig> _jpoptions;
|
||||
public FireManagementApp(IConfiguration configuration, IOptions<KikvisionConfig> options, IOptions<JPushClientConfig> jpoptions, ISugarUnitOfWork<SugarDbContext> unitWork,
|
||||
|
||||
public FireManagementApp(IConfiguration configuration, IOptions<KikvisionConfig> options,
|
||||
IOptions<JPushClientConfig> jpoptions, ISugarUnitOfWork<SugarDbContext> unitWork,
|
||||
ISimpleClient<FmFireclueTask> repository, IAuth auth) : base(unitWork, repository, auth)
|
||||
{
|
||||
_auth = auth;
|
||||
|
|
@ -128,6 +131,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//删除任务
|
||||
public async Task<Response<bool>> DeleteTask(long id)
|
||||
{
|
||||
|
|
@ -158,6 +162,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//更新任务状态
|
||||
public async Task<Response<bool>> ReceiveFireClueTask(long taskid, int state, string recipient)
|
||||
{
|
||||
|
|
@ -178,6 +183,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//更新任务图片或者新增线索
|
||||
public async Task<Response<bool>> ReceiveTaskImage(string info)
|
||||
{
|
||||
|
|
@ -196,7 +202,6 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
else
|
||||
{
|
||||
//新增线索信息
|
||||
|
||||
}
|
||||
|
||||
if (db.Commit())
|
||||
|
|
@ -209,11 +214,13 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ReciveTaskInfo
|
||||
{
|
||||
public long taskid { get; set; }
|
||||
public string path { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询下发人员
|
||||
/// </summary>
|
||||
|
|
@ -250,6 +257,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
return new Response<List<FmFireclueTask>> { Result = tasks };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 任务详情
|
||||
/// </summary>
|
||||
|
|
@ -278,7 +286,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
Audio = a.Audio,
|
||||
Image = a.Image,
|
||||
})
|
||||
.Mapper(a => a.StateName = ((TaskState)a.State).GetDescription())
|
||||
.Mapper(a => a.StateName = ((TaskState)a.State).GetDescription())
|
||||
.FirstAsync();
|
||||
var rep = db.FmFireTaskUser.AsQueryable().Where(r => r.UserId == userid && r.TaskId == id).First();
|
||||
if (rep != null)
|
||||
|
|
@ -286,6 +294,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
info.State = rep.State;
|
||||
info.StateName = ((TaskState)rep.State).GetDescription();
|
||||
}
|
||||
|
||||
return new Response<FireClueTaskResp> { Result = info };
|
||||
}
|
||||
}
|
||||
|
|
@ -586,6 +595,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加火情日志
|
||||
/// </summary>
|
||||
|
|
@ -596,7 +606,8 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
using (var db = base.UnitWork.CreateContext())
|
||||
{
|
||||
var userId = _auth.GetCurrentUser().User.Id;
|
||||
info.CreateId = userId; info.CreateTime = DateTime.Now;
|
||||
info.CreateId = userId;
|
||||
info.CreateTime = DateTime.Now;
|
||||
await db.FmFireclueinfoLog.InsertAsync(info);
|
||||
if (db.Commit())
|
||||
{
|
||||
|
|
@ -608,6 +619,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//按月统计火情线索
|
||||
public async Task<Response<List<FireInfoForChart>>> GetFireClueStatistics(int type)
|
||||
{
|
||||
|
|
@ -753,6 +765,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
return new Response<List<FmFireclueinfoLog>> { Result = list };
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -961,33 +974,36 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询人员上报的线索
|
||||
/// </summary>
|
||||
/// <param name="userid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByUserId(int pageIndex, int state, int pageSize, string userid)
|
||||
public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByUserId(int pageIndex, int state,
|
||||
int pageSize, string userid)
|
||||
{
|
||||
using (var db = base.UnitWork.CreateContext())
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var list = await db.FmFireclueInfo.AsQueryable().Where(a => a.CreateId.ToString() == userid).Select(a => new FireClueInfoResp
|
||||
{
|
||||
Id = a.Id,
|
||||
CreateId = a.CreateId.ToString(),
|
||||
ReportPerson = a.ReportPerson,
|
||||
Lat = a.Lat,
|
||||
Lng = a.Lng,
|
||||
Address = a.Address,
|
||||
ReportTime = a.ReportTime,
|
||||
Describe = a.Describe,
|
||||
SourceType = a.SourceType,
|
||||
State = a.State,
|
||||
AreaName = a.AreaName,
|
||||
ClueNo = a.ClueNo,
|
||||
}).Mapper(a => a.SourceTypeName = ((SourceType)a.SourceType).GetDescription())
|
||||
.Mapper(a => a.StateName = ((State)a.State).GetDescription())
|
||||
.OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc).ToPageListAsync(pageIndex, pageSize, total);
|
||||
var list = await db.FmFireclueInfo.AsQueryable().Where(a => a.CreateId.ToString() == userid).Select(a =>
|
||||
new FireClueInfoResp
|
||||
{
|
||||
Id = a.Id,
|
||||
CreateId = a.CreateId.ToString(),
|
||||
ReportPerson = a.ReportPerson,
|
||||
Lat = a.Lat,
|
||||
Lng = a.Lng,
|
||||
Address = a.Address,
|
||||
ReportTime = a.ReportTime,
|
||||
Describe = a.Describe,
|
||||
SourceType = a.SourceType,
|
||||
State = a.State,
|
||||
AreaName = a.AreaName,
|
||||
ClueNo = a.ClueNo,
|
||||
}).Mapper(a => a.SourceTypeName = ((SourceType)a.SourceType).GetDescription())
|
||||
.Mapper(a => a.StateName = ((State)a.State).GetDescription())
|
||||
.OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc).ToPageListAsync(pageIndex, pageSize, total);
|
||||
return new Response<PageInfo<List<FireClueInfoResp>>>
|
||||
{
|
||||
Code = 200,
|
||||
|
|
@ -1001,9 +1017,12 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly string baseUrl = "http://10.176.126.121:8766/liveBroadCast/bd/api/v1/device/liveBroadCast";
|
||||
private static readonly string baseUrl =
|
||||
"http://10.176.126.121:8766/liveBroadCast/bd/api/v1/device/liveBroadCast";
|
||||
|
||||
private static readonly string sk = "ba98a152296f13c565d2a6dfd219994f"; // 用户的sk
|
||||
private static readonly string account = "AK202006291525121"; // 用户的ak
|
||||
|
||||
public async Task<string> GetFlvUrlAsync(string deviceCode)
|
||||
{
|
||||
// 获取当前的时间戳
|
||||
|
|
@ -1036,8 +1055,10 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
requestMessage.Headers.Add("signature", signature);
|
||||
|
||||
// 设置 Content-Type 和 Accept 请求头
|
||||
requestMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
|
||||
requestMessage.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
||||
requestMessage.Content.Headers.ContentType =
|
||||
new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
|
||||
requestMessage.Headers.Accept.Add(
|
||||
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
// 发送请求
|
||||
var response = await client.SendAsync(requestMessage);
|
||||
|
|
@ -1076,12 +1097,15 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetLive(string deviceCode)
|
||||
{
|
||||
string flvUrl = await GetFlvUrlAsync(deviceCode);
|
||||
return flvUrl;
|
||||
}
|
||||
|
||||
#region socket
|
||||
|
||||
public async Task SendSocketMessage(WebSocketModel wsModel)
|
||||
{
|
||||
try
|
||||
|
|
@ -1091,16 +1115,16 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
string ws = _configuration.GetSection("WebSocket").Value;
|
||||
await webSocket.ConnectAsync(new Uri(ws), CancellationToken.None);
|
||||
byte[] data = Encoding.UTF8.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(wsModel));
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(data), System.Net.WebSockets.WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
await webSocket.CloseAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure, "Closing connection", CancellationToken.None);
|
||||
await webSocket.SendAsync(new ArraySegment<byte>(data),
|
||||
System.Net.WebSockets.WebSocketMessageType.Text, true, CancellationToken.None);
|
||||
await webSocket.CloseAsync(System.Net.WebSockets.WebSocketCloseStatus.NormalClosure,
|
||||
"Closing connection", CancellationToken.None);
|
||||
//webSocket.Dispose();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1116,7 +1140,8 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
Audience audience = new Audience();
|
||||
if (infoid != 0)
|
||||
{
|
||||
var renwu = db.FmFireTaskUser.AsQueryable().Where(r => r.TaskId == infoid).Select(r => r.UserId).ToList();
|
||||
var renwu = db.FmFireTaskUser.AsQueryable().Where(r => r.TaskId == infoid).Select(r => r.UserId)
|
||||
.ToList();
|
||||
var users = db.User.AsQueryable().Where(r => renwu.Contains(r.Id.ToString())).ToList();
|
||||
if (users.Count > 0)
|
||||
{
|
||||
|
|
@ -1131,6 +1156,7 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
audience.Alias = users.Select(a => a.Account).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
PushPayload pushPayload = new PushPayload()
|
||||
{
|
||||
Platform = new List<string> { "android", "ios" },
|
||||
|
|
@ -1156,9 +1182,11 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
return "success";
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 海康设备
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个设备的视频流
|
||||
/// </summary>
|
||||
|
|
@ -1168,7 +1196,8 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
[AllowAnonymous]
|
||||
public string GetPreviewURLs(string cameraIndexCode, string protocol)
|
||||
{
|
||||
HttpUtillib.SetPlatformInfo(_options.Value.AppKey, _options.Value.SecretKey, _options.Value.Url, _options.Value.Port, true);
|
||||
HttpUtillib.SetPlatformInfo(_options.Value.AppKey, _options.Value.SecretKey, _options.Value.Url,
|
||||
_options.Value.Port, true);
|
||||
|
||||
var obj = new
|
||||
{
|
||||
|
|
@ -1186,11 +1215,14 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
{
|
||||
return Encoding.UTF8.GetString(result);
|
||||
}
|
||||
|
||||
return "fail";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 人员类型统计
|
||||
#region 人员类型统计
|
||||
|
||||
/// <summary>
|
||||
/// 人员类型统计
|
||||
/// </summary>
|
||||
|
|
@ -1229,16 +1261,19 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
Result = res
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 获取物资相关接口
|
||||
|
||||
/// <summary>
|
||||
/// 获取全部营房信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public dynamic GetAllYingFang()
|
||||
{
|
||||
string sql = @"SELECT ""id"",""dwmc"",""dwzd"",""lsdw"",""dwzdjd"",""dwzdwd"",""dzxm"",""lxfs"",""syrs"",""zbqk"",""tbr"", st_astext(""geom"") as geom FROM ""fm_shp_1692148217"" ";
|
||||
string sql =
|
||||
@"SELECT ""id"",""dwmc"",""dwzd"",""lsdw"",""dwzdjd"",""dwzdwd"",""dzxm"",""lxfs"",""syrs"",""zbqk"",""tbr"", st_astext(""geom"") as geom FROM ""fm_shp_1692148217"" ";
|
||||
|
||||
using (var db = Repository.AsSugarClient())
|
||||
{
|
||||
|
|
@ -1258,7 +1293,9 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
{
|
||||
string sql = string.Empty;
|
||||
if (!string.IsNullOrEmpty(wuzi))
|
||||
sql = "SELECT \"id\", \"type\",\"name\",info,st_astext(geom) as geom FROM \"fm_shp_1686205187\" WHERE info like '%" + wuzi + "%'";
|
||||
sql =
|
||||
"SELECT \"id\", \"type\",\"name\",info,st_astext(geom) as geom FROM \"fm_shp_1686205187\" WHERE info like '%" +
|
||||
wuzi + "%'";
|
||||
else
|
||||
sql = "SELECT \"id\", \"type\",\"name\",info,st_astext(geom) as geom FROM \"fm_shp_1686205187\" ";
|
||||
|
||||
|
|
@ -1266,8 +1303,10 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
data.count = dt.Rows.Count;
|
||||
data.data = dt;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 任务相关
|
||||
|
|
@ -1277,7 +1316,8 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
/// </summary>
|
||||
/// <param name="userid"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Response<PageInfo<List<FireClueTaskResp>>>> LoadFireClueTaskByUserId(string userid, int pageIndex, int pageSize)
|
||||
public async Task<Response<PageInfo<List<FireClueTaskResp>>>> LoadFireClueTaskByUserId(string userid,
|
||||
int pageIndex, int pageSize)
|
||||
{
|
||||
using (SugarDbContext db = base.UnitWork.CreateContext())
|
||||
{
|
||||
|
|
@ -1301,14 +1341,15 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
Audio = a.Audio,
|
||||
Image = a.Image,
|
||||
}).Mapper(c => c.StateName = ((TaskState)c.State).GetDescription())
|
||||
.OrderBy(a => a.TaskTime, OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
.OrderBy(a => a.TaskTime, OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
return new Response<PageInfo<List<FireClueTaskResp>>>
|
||||
{
|
||||
Result = new PageInfo<List<FireClueTaskResp>> { Items = query, Total = totalNumber }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询所有任务
|
||||
/// </summary>
|
||||
|
|
@ -1336,17 +1377,18 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
Audio = a.Audio,
|
||||
TaskTime = a.TaskTime,
|
||||
RecipientUsers = SqlFunc.Subqueryable<FmFireTaskUser>().Where(r => r.TaskId == a.Id)
|
||||
.LeftJoin<SysUser>((r, s) => r.UserId == s.Id.ToString())
|
||||
.SelectStringJoin((a, s) => s.Name, ","),
|
||||
.LeftJoin<SysUser>((r, s) => r.UserId == s.Id.ToString())
|
||||
.SelectStringJoin((a, s) => s.Name, ","),
|
||||
}).Mapper(c => c.StateName = ((TaskState)c.State).GetDescription())
|
||||
.OrderBy(a => a.TaskTime, OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
.OrderBy(a => a.TaskTime, OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
return new Response<PageInfo<List<FireClueTaskResp>>>
|
||||
{
|
||||
Result = new PageInfo<List<FireClueTaskResp>> { Items = query, Total = totalNumber }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询火情线索
|
||||
/// </summary>
|
||||
|
|
@ -1354,7 +1396,8 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByAreaName(string areaname, int pageIndex = 1, int pageSize = 10)
|
||||
public async Task<Response<PageInfo<List<FireClueInfoResp>>>> LoadFireClueInfoByAreaName(string areaname,
|
||||
int pageIndex = 1, int pageSize = 10)
|
||||
{
|
||||
using (SugarDbContext db = base.UnitWork.CreateContext())
|
||||
{
|
||||
|
|
@ -1382,15 +1425,16 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
FireType = 1
|
||||
})
|
||||
.Mapper(a => a.SourceTypeName = ((SourceType)a.SourceType).GetDescription())
|
||||
.Mapper(a => a.StateName = ((State)a.State).GetDescription())
|
||||
.OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
.Mapper(a => a.StateName = ((State)a.State).GetDescription())
|
||||
.OrderBy(a => a.ReportTime, SqlSugar.OrderByType.Desc)
|
||||
.ToPageListAsync(pageIndex, pageSize, totalNumber);
|
||||
return new Response<PageInfo<List<FireClueInfoResp>>>
|
||||
{
|
||||
Result = new PageInfo<List<FireClueInfoResp>> { Items = query, Total = totalNumber }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// App获取在线人员实时位置信息
|
||||
/// </summary>
|
||||
|
|
@ -1424,7 +1468,9 @@ namespace OpenAuth.App.ServiceApp.FireManagement
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public async Task<Response<dynamic>> ListCameraWithInRange(string lng, string lat, int radius)
|
||||
{
|
||||
// '{lng}', '{lat}'
|
||||
|
|
@ -1445,5 +1491,61 @@ ORDER BY
|
|||
Result = x
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Response<dynamic>> ListDaHuaCameraInfo(int pageNum, int pageSize, int isOnline)
|
||||
{
|
||||
var daHuaApi = new DaHuaApi("https://icc-dev.hibetatest.com:4077");
|
||||
var channelCategoryRequest = new ChannelCategoryRequest
|
||||
{
|
||||
pageNum = pageNum,
|
||||
pageSize = pageSize,
|
||||
isOnline = 1,
|
||||
unitTypeList = new List<int> { 1 },
|
||||
};
|
||||
Console.WriteLine(JsonConvert.SerializeObject(channelCategoryRequest));
|
||||
var channelCategoryResponse = await daHuaApi.GetChannelCategoriesAsync(channelCategoryRequest);
|
||||
if (channelCategoryResponse.success)
|
||||
{
|
||||
return new Response<dynamic>
|
||||
{
|
||||
Result = channelCategoryResponse.data.pageData
|
||||
};
|
||||
}
|
||||
|
||||
return new Response<dynamic>
|
||||
{
|
||||
Code = channelCategoryResponse.code,
|
||||
Message = channelCategoryResponse.errMsg
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<Response<dynamic>> GetDaHuaRtsp(string channelCode,string streamType)
|
||||
{
|
||||
var daHuaApi = new DaHuaApi("https://icc-dev.hibetatest.com:4077");
|
||||
|
||||
var request = new RtspPreviewRequest
|
||||
{
|
||||
data = new RtspPreviewData
|
||||
{
|
||||
channelId = channelCode,
|
||||
dataType = "1",
|
||||
streamType = streamType //主码流
|
||||
}
|
||||
};
|
||||
var y = await daHuaApi.StartRtspPreviewAsync(request);
|
||||
if (y.success)
|
||||
{
|
||||
return new Response<dynamic>
|
||||
{
|
||||
Result = y.data
|
||||
};
|
||||
}
|
||||
|
||||
return new Response<dynamic>
|
||||
{
|
||||
Code = y.code,
|
||||
Message = y.errMsg
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,4 +28,16 @@ public class CameraController : ControllerBase
|
|||
{
|
||||
return await _app.ListCameraWithInRange(lng, lat, radius);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<Response<dynamic>> ListDaHuaCameraInfo(int pageNum = 1, int pageSize = 10, int isOnline = 1)
|
||||
{
|
||||
return await _app.ListDaHuaCameraInfo(pageNum, pageSize, isOnline);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<Response<dynamic>> GetDaHuaRtsp(string channelCode, string streamType = "1")
|
||||
{
|
||||
return await _app.GetDaHuaRtsp(channelCode, streamType);
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
<None Remove="log\**" />
|
||||
<None Remove="wwwroot\**" />
|
||||
<EmbeddedResource Include="index.html" />
|
||||
<None Remove="temp-keys\key-4421ef20-c9a7-4085-ab32-780e0497cf9b.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -81,6 +82,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="Controllers\BaseControllers\Permission\" />
|
||||
<Folder Include="Controllers\ServiceControllers\DaHuaCamera\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Reference in New Issue