using Cis.Application.Cb;
using Cis.Application.Cm;
using Cis.Application.Core.Component.PtzServer;
using EC.Helper.CameraSDK;
using StackExchange.Redis;
using System.Collections.Concurrent;
namespace Cis.Application.Core.Component.MarkSeacher;
///
/// 追踪标签服务类
///
public class MarkSearcherServer : IMarkSearcherServer, ISingleton
{
#region Attr
private readonly SqlSugarRepository _cbCameraRep;
private readonly SqlSugarRepository _cbCameraParamsRep;
private readonly SqlSugarRepository _cmMarkLableRep;
private readonly IDatabase _cache;
private readonly ICameraSdkServer _cameraSdkServer;
///
/// {cbCameraId, MarkSearcherBase}
///
private ConcurrentDictionary MarkSearcherDict { get; set; } = new();
///
/// MarkSearcherDict 原子操作锁
///
private ReaderWriterLockSlim MsDictRWLock { get; } = new();
#endregion Attr
public MarkSearcherServer(
IDatabase cache,
ICameraSdkServer cameraSdkServer
)
{
_cbCameraRep = App.GetService>();
_cbCameraParamsRep = App.GetService>();
_cmMarkLableRep = App.GetService>();
_cache = cache;
_cameraSdkServer = cameraSdkServer;
}
#region Base Method
public bool ActivateSearcher(long cameraId)
{
try
{
MsDictRWLock.EnterWriteLock();
return ActivateSearcherAtom(cameraId);
}
finally
{
MsDictRWLock.ExitWriteLock();
}
}
///
/// ActivateSearcher 原子操作
///
///
///
private bool ActivateSearcherAtom(long cameraId)
{
bool ret = MarkSearcherDict.ContainsKey(cameraId);
if (ret) return false;
// 获取相机
CbCamera cbCamera = _cbCameraRep.GetById(cameraId);
if (cbCamera == null) return false;
// 获取相机参数
CbCameraParams cbCameraParams = _cbCameraParamsRep.GetById(cbCamera.CbCameraParamsId);
if (cbCameraParams == null) return false;
// 注册并获取 ptz
ret = _cameraSdkServer.IsExistsCamera(cbCamera.Ip);
if (!ret)
{
CameraInfo cameraInfo = CameraInfo.New(cbCameraParams.CameraType, cbCamera.Ip, cbCamera.UserName, cbCamera.Password);
ret = _cameraSdkServer.RegisterCamera(cameraInfo);
if (!ret)
{
// double check
ret = _cameraSdkServer.IsExistsCamera(cbCamera.Ip);
if (!ret) return false;
}
}
ret = _cameraSdkServer.GetPtzInfoByIp(cbCamera.Ip, out PtzInfo ptzInfo);
if (!ret) return false;
// 创建相机计算参数
CameraCalcParams cameraCalcParams = CameraCalcParams.New(cbCamera.Id, ptzInfo, cbCameraParams.FocusX, cbCameraParams.FocusY);
// 创建 markSearcher
MarkSearcherBase markSearcher = ((CameraType)cbCameraParams.CameraType).CreateMarkSearcher(cameraCalcParams);
if (markSearcher == null) return false;
// 获取标签列表
List cmMarkLabelList = _cmMarkLableRep.GetList(u => u.CbCameraId == cameraId);
// 将标签添加到 markSearcher
foreach (CmMarkLabel item in cmMarkLabelList)
{
// 创建标签计算参数
MarkLabelCalcParams labelCalcParams = MarkLabelCalcParams.New(
item.Id,
PtzInfo.New(item.PanPosition, item.TiltPosition, item.ZoomPosition),
item.VideoWidth,
item.VideoHeight,
item.CanvasLeftRatio,
item.CanvasTopRatio
);
markSearcher.AddMarkLabelCalcParams(labelCalcParams);
}
// 存放 markSearcher
ret = MarkSearcherDict.TryAdd(cameraId, markSearcher);
if (!ret) return false;
// 记录缓存
_cache.HashSet(CacheInfo.CameraId2Ip, cbCamera.Id, cbCamera.Ip);
_cache.HashIncrement(CacheInfo.CameraIpCounts, cbCamera.Ip);
return true;
}
public bool DeactivateSearcher(long cameraId)
{
try
{
MsDictRWLock.EnterWriteLock();
return DeactivateSearcherAtom(cameraId);
}
finally
{
MsDictRWLock.ExitWriteLock();
}
}
///
/// DeactivateSearcher 原子操作
///
///
///
private bool DeactivateSearcherAtom(long cameraId)
{
bool ret = MarkSearcherDict.TryRemove(cameraId, out _);
if (!ret) return false;
RedisValue value = _cache.HashGet(CacheInfo.CameraId2Ip, cameraId);
if (!value.HasValue) return false;
string cameraIp = (string)value;
_cache.HashDelete(CacheInfo.CameraId2Ip, cameraId);
_cache.HashDecrement(CacheInfo.CameraIpCounts, cameraIp);
//int ipCount = (int)_cache.HashGet(CacheInfo.CameraIpCounts, cameraIp);
//if (ipCount <= 0)
//{
// // 直接删除 or 设置过期
// _cache.HashDelete(CacheInfo.CameraIpCounts, cameraIp);
// _cameraSdkServer.DeleteCamera(cameraIp);
//}
return true;
}
public bool IsExistsSearcher(long cameraId)
{
return MarkSearcherDict.ContainsKey(cameraId);
}
public MarkSearcherBase GetSearcher(long cameraId)
{
MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase searcher);
return searcher;
}
public bool ActivateMarkLabel(long cameraId, long markLabelId)
{
bool ret = MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher);
if (!ret) return false;
ret = markSearcher.IsExistsMarkLabelCalcParams(markLabelId);
if (ret) return false;
CmMarkLabel label = _cmMarkLableRep.GetById(markLabelId);
if (label == null) return false;
MarkLabelCalcParams labelCalcParams = MarkLabelCalcParams.New(
label.Id,
PtzInfo.New(label.PanPosition, label.TiltPosition, label.ZoomPosition),
label.VideoWidth,
label.VideoHeight,
label.CanvasLeftRatio,
label.CanvasTopRatio
);
ret = markSearcher.AddMarkLabelCalcParams(labelCalcParams);
return ret;
}
public bool DeactivateMarkLabel(long cameraId, long markLabelId)
{
bool ret = MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher);
if (!ret) return false;
ret = markSearcher.DeleteMarkLabelCalcParams(markLabelId);
return ret;
}
public bool IsExistsMarkLabel(long cameraId, long markLabelId)
{
return MarkSearcherDict.TryGetValue(cameraId, out MarkSearcherBase searcher)
&& searcher.IsExistsMarkLabelCalcParams(markLabelId);
}
#endregion Base Method
#region Base Method Async
public async Task ActivateSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return ActivateSearcher(cameraId);
});
}
public async Task DeactivateSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return DeactivateSearcher(cameraId);
});
}
public async Task IsExistsSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return IsExistsSearcher(cameraId);
});
}
public async Task GetSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return GetSearcher(cameraId);
});
}
public async Task ActivateMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return ActivateMarkLabel(cameraId, markLabelId);
});
}
public async Task DeactivateMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return DeactivateMarkLabel(cameraId, markLabelId);
});
}
public async Task IsExistsMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return IsExistsMarkLabel(cameraId, markLabelId);
});
}
#endregion Base Method Async
}