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.

312 lines
8.1 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 ReaderWriterLockSlim msDictLock { get; } = 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;
bool ret = _cbCameraId2IpDict.TryGetValue(cameraId, out string cameraIp);
if (!ret) continue;
ret = _cameraPtzInfoDict.TryGetValue(cameraIp, out PtzInfo ptzInfo);
if (!ret) 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 ActivateSearcher(long cameraId)
{
try
{
msDictLock.EnterWriteLock();
if (_markSearcherDict.ContainsKey(cameraId))
return false;
// 获取 cbCamera
CbCamera cbCamera = _cbCameraRep.GetById(cameraId);
if (cbCamera == null) return false;
// 获取 tbPtzCamera
string cameraIp = cbCamera.Ip;
bool ret = _tbPtzCameraDict.TryGetValue(cameraIp, out TbPtzCamera tbPtzCamera);
if (!ret)
{
tbPtzCamera = _tbPtzCameraRep.GetFirst(u => u.Ip == cameraIp);
if (tbPtzCamera == null) return false;
_tbPtzCameraDict[cameraIp] = tbPtzCamera;
}
// 存储 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.VideoWidth,
item.VideoHeight,
item.CanvasLeftRatio,
item.CanvasTopRatio
);
markSeacher.AddMarkLabelCalcInfo(markLabelCalcInfo);
}
// 将 markSeacher 放入字典
_markSearcherDict[cameraId] = markSeacher;
}
finally
{
msDictLock.ExitWriteLock();
}
return true;
}
/// <summary>
/// 解除 cbCamera 进入运算
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool DeActivateSearcher(long cameraId)
{
try
{
msDictLock.EnterWriteLock();
_markSearcherDict.Remove(cameraId);
_markLabelCalcResultListDict.Remove(cameraId);
}
finally
{
msDictLock.ExitWriteLock();
}
return true;
}
public bool IsExistSearcher(long cameraId)
{
return _markSearcherDict.ContainsKey(cameraId);
}
public bool ActivateMarkLabel(long cameraId, long markLabelId)
{
bool ret = _markSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher);
if (!ret)
return false;
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.VideoWidth,
label.VideoHeight,
label.CanvasLeftRatio,
label.CanvasTopRatio
);
return markSearcher.AddMarkLabelCalcInfo(markLabelCalcInfo);
}
public bool DectivateMarkLabel(long cameraId, long markLabelId)
{
bool ret = _markSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher);
return ret ? markSearcher.DeleteMarkLabelCalcInfo(markLabelId) : false;
}
public bool IsExistCameraMarkLabel(long cameraId, long markLabelId)
{
bool ret = _markSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher) &&
markSearcher.ExistsMarkLabelCalcInfo(markLabelId);
return ret;
}
public List<MarkLabelCalcResult> GetMarkLabelCalcResultList(long cameraId)
{
bool ret = _markLabelCalcResultListDict.TryGetValue(cameraId, out List<MarkLabelCalcResult> list);
return ret ? list : new();
}
public PtzInfo GetCameraPtzInfo(long cameraId)
{
PtzInfo ptzInfo = null;
bool ret = _cbCameraId2IpDict.TryGetValue(cameraId,out string cameraIp) &&
_cameraPtzInfoDict.TryGetValue(cameraIp, out ptzInfo);
return ret ? ptzInfo : null;
}
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> IsExistSearcherAsync(long cameraId)
{
return await Task.Run(() =>
{
return IsExistSearcher(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 DectivateMarkLabel(cameraId, markLabelId);
});
}
public async Task<bool> IsExistMarkLabelAysnc(long cameraId, long markLabelId)
{
return await Task.Run(() =>
{
return IsExistCameraMarkLabel(cameraId, markLabelId);
});
}
public async Task<List<MarkLabelCalcResult>> GetMarkLabelCalcResultListAsync(long cameraId)
{
return await Task.Run(() =>
{
return GetMarkLabelCalcResultList(cameraId);
});
}
#endregion external call
}