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.
 
 
 
 

242 lines
6.3 KiB

using Cis.Application.Cb;
using Cis.Application.Cm;
using Cis.Application.Tb;
using System.Collections.Concurrent;
namespace Cis.Application.Core;
public class CameraDataCenter
{
#region Attr
private readonly SqlSugarRepository<CbCamera> _cbCameraRep;
private readonly SqlSugarRepository<CmMarkLabel> _cmMarkLableRep;
private readonly SqlSugarRepository<TbPtzCamera> _tbPtzCameraRep;
private readonly PtzServerApi _ptzServerApi;
private readonly CameraDataOptions options = App.GetOptions<CameraDataOptions>();
private Thread _thread { get; set; }
/// <summary>
/// (cbCameraId, cbCameraIp)
/// </summary>
private Dictionary<long, string> _cbCameraId2IpDict { get; set; } = new();
/// <summary>
/// (cameraIp, TbPtzCamera)
/// </summary>
private ConcurrentDictionary<string, TbPtzCamera> _tbPtzCameraDict { get; set; } = new();
/// <summary>
/// (cameraIp, PtzInfo)
/// </summary>
private ConcurrentDictionary<string, PtzInfo> _cameraPtzInfoDict { get; set; } = new();
/// <summary>
/// _markSearcherDict 锁对象,写锁
/// </summary>
private static readonly ReaderWriterLockSlim msDictLock = new();
/// <summary>
/// (cbCameraId, MarkSearcherBase)
/// </summary>
private ConcurrentDictionary<long, MarkSearcherBase> _markSearcherDict { get; set; } = new();
/// <summary>
/// (cameraId, List(MarkLabelCalcResult))
/// </summary>
private ConcurrentDictionary<long, List<MarkLabelCalcResult>> _markLabelCalcResultListDict { get; set; } = new();
#endregion Attr
public CameraDataCenter()
{
_cbCameraRep = App.GetService<SqlSugarRepository<CbCamera>>();
_cmMarkLableRep = App.GetService<SqlSugarRepository<CmMarkLabel>>();
_tbPtzCameraRep = App.GetService<SqlSugarRepository<TbPtzCamera>>();
_ptzServerApi = App.GetService<PtzServerApi>();
Init();
}
private void Init()
{
if (!options.LazyInit)
{
List<TbPtzCamera> list = _tbPtzCameraRep.GetList();
// 根据 Ip 去重
foreach (TbPtzCamera item in list)
{
if (!_tbPtzCameraDict.ContainsKey(item.Ip))
_tbPtzCameraDict[item.Ip] = item;
}
}
// 初始化 thread
_thread = new Thread(WorkLoop)
{
IsBackground = true// 设置后台线程
};
_thread.Start();
}
#region Loop
/// <summary>
/// 循环运行
/// </summary>
private void WorkLoop()
{
while (true)
{
RefreshPtzInfoByApi();
RefreshMarkSearcher();
Thread.Sleep(options.LoopInterval);
}
}
private void RefreshPtzInfoByApi()
{
foreach (TbPtzCamera item in _tbPtzCameraDict.Values)
{
PtzInfo ptzInfo = _ptzServerApi.GetPtzInfo(item.CameraId);
_cameraPtzInfoDict[item.Ip] = ptzInfo;
}
}
private void RefreshMarkSearcher()
{
foreach (KeyValuePair<long, MarkSearcherBase> pair in _markSearcherDict)
{
long cameraId = pair.Key;
MarkSearcherBase markSearcher = pair.Value;
string cameraIp = _cbCameraId2IpDict[cameraId];
if (cameraIp == null) continue;
PtzInfo ptzInfo = _cameraPtzInfoDict[cameraIp];
if (ptzInfo == null) continue;
markSearcher.UpdateCameraCalcInfo(ptzInfo);
List<MarkLabelCalcResult> resultList = markSearcher.Calc();
_markLabelCalcResultListDict[cameraId] = resultList;
}
}
#endregion Loop
#region external call
/// <summary>
/// 激活 cbCamera 进入运算
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool ActiveCamera(long cameraId)
{
try
{
msDictLock.EnterWriteLock();
if (_markSearcherDict.ExistsKey(cameraId))
return false;
// 获取 cbCamera
CbCamera cbCamera = _cbCameraRep.GetById(cameraId);
if (cbCamera == null) return false;
// 获取 tbPtzCamera
TbPtzCamera tbPtzCamera;
string cameraIp = cbCamera.Ip;
if (!_tbPtzCameraDict.ExistsKey(cameraIp))
{
tbPtzCamera = _tbPtzCameraRep.GetFirst(u => u.Ip == cameraIp);
if (tbPtzCamera == null) return false;
_tbPtzCameraDict[cameraIp] = tbPtzCamera;
}
else
{
tbPtzCamera = _tbPtzCameraDict[cameraIp];
}
// 存储 cbCamera id 对应 ip 关系
_cbCameraId2IpDict[cbCamera.Id] = cameraIp;
// 创建 cameraCalcInfo
CameraCalcInfo cameraCalcInfo = CameraCalcInfo.New(cameraId, _ptzServerApi.GetPtzInfo(tbPtzCamera.Id));
// 创建 markSeacher
HikMarkSeacher markSeacher = new(cameraCalcInfo);
// 获取 cmMarkLabel 列表
List<CmMarkLabel> cmMarkLabelList = _cmMarkLableRep.GetList(u => u.CbCameraId == cameraId);
// 将 cmMarkLabel 一一添加到 markSeacher
foreach (CmMarkLabel item in cmMarkLabelList)
{
MarkLabelCalcInfo markLabelCalcInfo = MarkLabelCalcInfo.New(
item.Id,
PtzInfo.New(item.PanPosition, item.TiltPosition, item.ZoomPosition),
item.CanvasWidth,
item.CanvasHeight,
item.CanvasLeft,
item.CanvasTop
);
markSeacher.AddMarkLabelCalcInfo(markLabelCalcInfo);
}
// 将 markSeacher 放入字典
_markSearcherDict[cameraId] = markSeacher;
}
finally
{
msDictLock.ExitWriteLock();
}
return true;
}
/// <summary>
/// 解除 cbCamera 进入运算
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool DeActiveCamera(long cameraId)
{
try
{
msDictLock.EnterWriteLock();
_markSearcherDict.Remove(cameraId);
_markLabelCalcResultListDict.Remove(cameraId);
}
finally
{
msDictLock.ExitWriteLock();
}
return true;
}
public bool AddCameraMarkLabel(long cameraId, long markLabelId)
{
if (!_markSearcherDict.ExistsKey(cameraId))
return false;
MarkSearcherBase markSearcher = _markSearcherDict[cameraId];
if (markSearcher.ExistsMarkLabelCalcInfo(markLabelId))
return false;
CmMarkLabel label = _cmMarkLableRep.GetById(markLabelId);
if (label == null)
return false;
MarkLabelCalcInfo markLabelCalcInfo = MarkLabelCalcInfo.New(
label.Id,
PtzInfo.New(label.PanPosition, label.TiltPosition, label.ZoomPosition),
label.CanvasWidth,
label.CanvasHeight,
label.CanvasLeft,
label.CanvasTop
);
return markSearcher.AddMarkLabelCalcInfo(markLabelCalcInfo);
}
public bool DeleteCameraMarkLabel(long cameraId, long marklabelId)
{
if (!_markSearcherDict.ExistsKey(cameraId))
return false;
MarkSearcherBase markSearcher = _markSearcherDict[cameraId];
return markSearcher.DeleteMarkLabelCalcInfo(marklabelId);
}
public List<MarkLabelCalcResult> GetMarkLabelCalcResults(long cameraId)
{
return null;
}
#endregion external call
}