Camera Information System
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
8.4 KiB

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;
/// <summary>
/// 追踪标签服务类
/// </summary>
public class MarkSearcherServer : IMarkSearcherServer, ISingleton
{
#region Attr
private readonly SqlSugarRepository<CbCamera> _cbCameraRep;
private readonly SqlSugarRepository<CbCameraParams> _cbCameraParamsRep;
private readonly SqlSugarRepository<CmMarkLabel> _cmMarkLableRep;
private readonly IDatabase _cache;
private readonly ICameraSdkServer _cameraSdkServer;
/// <summary>
/// {cbCameraId, MarkSearcherBase}
/// </summary>
private ConcurrentDictionary<long, MarkSearcherBase> MarkSearcherDict { get; set; } = new();
/// <summary>
/// MarkSearcherDict 原子操作锁
/// </summary>
private ReaderWriterLockSlim MsDictRWLock { get; } = new();
#endregion Attr
public MarkSearcherServer(
IDatabase cache,
ICameraSdkServer cameraSdkServer
)
{
_cbCameraRep = App.GetService<SqlSugarRepository<CbCamera>>();
_cbCameraParamsRep = App.GetService<SqlSugarRepository<CbCameraParams>>();
_cmMarkLableRep = App.GetService<SqlSugarRepository<CmMarkLabel>>();
_cache = cache;
_cameraSdkServer = cameraSdkServer;
}
#region Base Method
public bool ActivateSearcher(long cameraId)
{
try
{
MsDictRWLock.EnterWriteLock();
return ActivateSearcherAtom(cameraId);
}
finally
{
MsDictRWLock.ExitWriteLock();
}
}
/// <summary>
/// ActivateSearcher 原子操作
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
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<CmMarkLabel> 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();
}
}
/// <summary>
/// DeactivateSearcher 原子操作
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
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<bool> ActivateSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return ActivateSearcher(cameraId);
});
}
public async Task<bool> DeactivateSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return DeactivateSearcher(cameraId);
});
}
public async Task<bool> IsExistsSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return IsExistsSearcher(cameraId);
});
}
public async Task<MarkSearcherBase> GetSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return GetSearcher(cameraId);
});
}
public async Task<bool> ActivateMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return ActivateMarkLabel(cameraId, markLabelId);
});
}
public async Task<bool> DeactivateMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return DeactivateMarkLabel(cameraId, markLabelId);
});
}
public async Task<bool> IsExistsMarkLabelAsync(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return IsExistsMarkLabel(cameraId, markLabelId);
});
}
#endregion Base Method Async
}