diff --git a/.gitignore b/.gitignore
index 679d59b..edff431 100644
--- a/.gitignore
+++ b/.gitignore
@@ -475,3 +475,5 @@ FodyWeavers.xsd
# Local History for Visual Studio Code
.history/
+# Custom
+!/EC.Helper/libs/**
diff --git a/Cis.Application/AppConfig.json b/Cis.Application/AppConfig.json
index 5c17e0c..f66edbd 100644
--- a/Cis.Application/AppConfig.json
+++ b/Cis.Application/AppConfig.json
@@ -1,12 +1,13 @@
{
"$schema": "https://gitee.com/dotnetchina/Furion/raw/v4/schemas/v4/furion-schema.json",
- "CameraDataOptions": {
- "LazyInit": false,
- "LoopInterval": "1000"
- },
- "PTZServer": {
- "Type": "",
- "Ip": "127.0.0.1",
- "Port": "7022"
+ "CameraData": {
+ "CameraPtz": {
+ "LoopInterval": "1000",
+ "Timeout": "2000"
+ },
+ "MarkSearcher": {
+ "LoopInterval": "1000",
+ "Timeout": "2000"
+ }
}
}
\ No newline at end of file
diff --git a/Cis.Application/Cb/Common/CbInfo.cs b/Cis.Application/Cb/Common/CbInfo.cs
index b612a81..6f658e5 100644
--- a/Cis.Application/Cb/Common/CbInfo.cs
+++ b/Cis.Application/Cb/Common/CbInfo.cs
@@ -5,40 +5,50 @@
///
public class CbInfo
{
- #region Api Info
+ #region Api Info
- ///
- /// Api 分组名
- ///
- public const string GroupName = "CameraBase";
+ ///
+ /// Api 分组名
+ ///
+ public const string GroupName = "CameraBase";
- ///
- /// Api 分组排序
- ///
- public const int GroupOrder = 100;
+ ///
+ /// Api 分组排序
+ ///
+ public const int GroupOrder = 100;
- #endregion Api Info
+ #endregion Api Info
- #region Database Info
+ #region Database Info
- ///
- /// 数据库标识
- ///
- public const string DbName = SqlSugarConst.DefaultConfigId;
+ ///
+ /// 数据库标识
+ ///
+ public const string DbName = SqlSugarConst.DefaultConfigId;
- #endregion Database Info
+ #endregion Database Info
- #region Table Info
+ #region Table Info
- ///
- /// CbCamera 表名
- ///
- public const string CbCameraTbName = "cb_camera";
+ ///
+ /// CbCamera 表名
+ ///
+ public const string CbCameraTbName = "cb_camera";
- ///
- /// CbCamera 表描述
- ///
- public const string CbCameraTbDesc = "相机表";
+ ///
+ /// CbCamera 表描述
+ ///
+ public const string CbCameraTbDesc = "相机表";
- #endregion Table Info
+ ///
+ /// CbCameraParams 表名
+ ///
+ public const string CbCameraParamsTbName = "cb_camera_params";
+
+ ///
+ /// CbCameraParams 表描述
+ ///
+ public const string CbCameraParamsTbDesc = "相机参数表";
+
+ #endregion Table Info
}
\ No newline at end of file
diff --git a/Cis.Application/Cb/Entity/CbCamera.cs b/Cis.Application/Cb/Entity/CbCamera.cs
index d4a1947..9776a10 100644
--- a/Cis.Application/Cb/Entity/CbCamera.cs
+++ b/Cis.Application/Cb/Entity/CbCamera.cs
@@ -1,44 +1,44 @@
namespace Cis.Application.Cb;
///
-/// 系统字典类型表
+/// 相机表
///
[SugarTable(CbInfo.CbCameraTbName, CbInfo.CbCameraTbDesc)]
[Tenant(CbInfo.DbName)]
public class CbCamera : EntityBase
{
- ///
- /// 名称
- ///
- [SugarColumn(ColumnDescription = "名称", Length = 64)]
- [Required, MaxLength(64)]
- public string Name { get; set; }
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public string Name { get; set; }
- ///
- /// ip 地址
- ///
- [SugarColumn(ColumnDescription = "ip地址", Length = 16)]
- [Required, MaxLength(16)]
- public string Ip { get; set; }
+ ///
+ /// ip 地址
+ ///
+ [SugarColumn(ColumnDescription = "ip地址", Length = 16)]
+ [Required, MaxLength(16)]
+ public string Ip { get; set; }
- ///
- /// 端口
- ///
- [SugarColumn(ColumnDescription = "端口", Length = 5, DefaultValue = "80")]
- [Required, MaxLength(5)]
- public string Port { get; set; }
+ ///
+ /// 账号
+ ///
+ [SugarColumn(ColumnDescription = "账号", Length = 32)]
+ [Required, MaxLength(32)]
+ public string UserName { get; set; }
- ///
- /// 账号
- ///
- [SugarColumn(ColumnDescription = "账号", Length = 32)]
- [Required, MaxLength(32)]
- public string UserName { get; set; }
+ ///
+ /// 密码
+ ///
+ [SugarColumn(ColumnDescription = "密码", Length = 32)]
+ [Required, MaxLength(32)]
+ public string Password { get; set; }
- ///
- /// 密码
- ///
- [SugarColumn(ColumnDescription = "密码", Length = 32)]
- [Required, MaxLength(32)]
- public string Password { get; set; }
+ ///
+ /// 相机参数 Id
+ ///
+ [SugarColumn(ColumnDescription = "相机参数Id")]
+ [Required]
+ public long CbCameraParamsId { get; set; }
}
\ No newline at end of file
diff --git a/Cis.Application/Cb/Entity/CbCameraParams.cs b/Cis.Application/Cb/Entity/CbCameraParams.cs
new file mode 100644
index 0000000..ed5187a
--- /dev/null
+++ b/Cis.Application/Cb/Entity/CbCameraParams.cs
@@ -0,0 +1,44 @@
+namespace Cis.Application.Cb;
+
+///
+/// 相机参数表
+///
+[SugarTable(CbInfo.CbCameraParamsTbName, CbInfo.CbCameraParamsTbDesc)]
+[Tenant(CbInfo.DbName)]
+public class CbCameraParams : EntityBase
+{
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public string Name { get; set; }
+
+ ///
+ /// 相机类型
+ ///
+ [SugarColumn(ColumnDescription = "相机类型")]
+ [Required]
+ public int CameraType { get; set; }
+
+ ///
+ /// sdk 端口
+ ///
+ [SugarColumn(ColumnDescription = "sdk端口")]
+ [Required]
+ public int SdkPort { get; set; }
+
+ ///
+ /// FocusX
+ ///
+ [SugarColumn(ColumnDescription = "FocusX")]
+ [Required]
+ public double FocusX { get; set; }
+
+ ///
+ /// FocusY
+ ///
+ [SugarColumn(ColumnDescription = "FocusY")]
+ [Required]
+ public double FocusY { get; set; }
+}
\ No newline at end of file
diff --git a/Cis.Application/Cb/Service/CbCameraParamsService.cs b/Cis.Application/Cb/Service/CbCameraParamsService.cs
new file mode 100644
index 0000000..fb30cf0
--- /dev/null
+++ b/Cis.Application/Cb/Service/CbCameraParamsService.cs
@@ -0,0 +1,61 @@
+using Newtonsoft.Json.Linq;
+
+namespace Cis.Application.Cb;
+
+///
+/// 相机参数服务
+///
+[ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.GroupOrder)]
+public class CbCameraParamsService : IDynamicApiController, ITransient
+{
+ private readonly SqlSugarRepository _baseRep;
+
+ public CbCameraParamsService(SqlSugarRepository baseRep)
+ {
+ _baseRep = baseRep;
+ }
+
+ [HttpPost]
+ public async Task Add([FromForm] CbCameraParams entity)
+ {
+ return await _baseRep.InsertAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Update([FromForm] CbCameraParams entity)
+ {
+ return await _baseRep.UpdateAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Delete([FromForm] CbCameraParams entity)
+ {
+ return await _baseRep.DeleteAsync(entity);
+ }
+
+ [HttpGet]
+ public async Task Get(long id)
+ {
+ CbCameraParams entity = await _baseRep.GetByIdAsync(id);
+ return entity;
+ }
+
+ [HttpGet]
+ public async Task> GetList(string queryJson = "")
+ {
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToListAsync();
+ return list;
+ }
+
+ [HttpGet]
+ public async Task> GetPageList(string queryJson, string pagination)
+ {
+ Pagination pageObj = pagination.ToObject();
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToPageListAsync(pageObj.Index, pageObj.Size);
+ return list;
+ }
+}
\ No newline at end of file
diff --git a/Cis.Application/Cb/Service/CbCameraService.cs b/Cis.Application/Cb/Service/CbCameraService.cs
index febfc89..2606197 100644
--- a/Cis.Application/Cb/Service/CbCameraService.cs
+++ b/Cis.Application/Cb/Service/CbCameraService.cs
@@ -8,55 +8,54 @@ namespace Cis.Application.Cb;
[ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.GroupOrder)]
public class CbCameraService : IDynamicApiController, ITransient
{
- private readonly SqlSugarRepository _cbCameraRep;
-
- public CbCameraService(SqlSugarRepository cbCameraRep)
- {
- _cbCameraRep = cbCameraRep;
- }
-
- [HttpPost]
- public async Task Add([FromForm] CbCamera entity)
- {
- return await _cbCameraRep.InsertAsync(entity);
- }
-
- [HttpPost]
- public async Task Update([FromForm] CbCamera entity)
- {
- return await _cbCameraRep.UpdateAsync(entity);
- }
-
- [HttpPost]
- public async Task Delete([FromForm] CbCamera entity)
- {
- return await _cbCameraRep.DeleteAsync(entity);
- }
-
- [HttpGet]
- public async Task Get(long id)
- {
- CbCamera entity = await _cbCameraRep.GetByIdAsync(id);
- return entity;
- }
-
- [HttpGet]
- public async Task> GetList(string queryJson = "")
- {
- JObject queryObj = queryJson.ToJObject();
- List list = await _cbCameraRep.AsQueryable()
- .ToListAsync();
- return list;
- }
-
- [HttpGet]
- public async Task> GetPageList(string queryJson, string pagination)
- {
- Pagination pageObj = pagination.ToObject();
- JObject queryObj = queryJson.ToJObject();
- List list = await _cbCameraRep.AsQueryable()
- .ToPageListAsync(pageObj.Index, pageObj.Size);
- return list;
- }
-
+ private readonly SqlSugarRepository _baseRep;
+
+ public CbCameraService(SqlSugarRepository baseRep)
+ {
+ _baseRep = baseRep;
+ }
+
+ [HttpPost]
+ public async Task Add([FromForm] CbCamera entity)
+ {
+ return await _baseRep.InsertAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Update([FromForm] CbCamera entity)
+ {
+ return await _baseRep.UpdateAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Delete([FromForm] CbCamera entity)
+ {
+ return await _baseRep.DeleteAsync(entity);
+ }
+
+ [HttpGet]
+ public async Task Get(long id)
+ {
+ CbCamera entity = await _baseRep.GetByIdAsync(id);
+ return entity;
+ }
+
+ [HttpGet]
+ public async Task> GetList(string queryJson = "")
+ {
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToListAsync();
+ return list;
+ }
+
+ [HttpGet]
+ public async Task> GetPageList(string queryJson, string pagination)
+ {
+ Pagination pageObj = pagination.ToObject();
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToPageListAsync(pageObj.Index, pageObj.Size);
+ return list;
+ }
}
\ No newline at end of file
diff --git a/Cis.Application/Cis.Application.csproj b/Cis.Application/Cis.Application.csproj
index f99bc03..5d90d17 100644
--- a/Cis.Application/Cis.Application.csproj
+++ b/Cis.Application/Cis.Application.csproj
@@ -24,6 +24,7 @@
+
diff --git a/Cis.Application/Cis.Application.xml b/Cis.Application/Cis.Application.xml
index 4df3d6c..288411d 100644
--- a/Cis.Application/Cis.Application.xml
+++ b/Cis.Application/Cis.Application.xml
@@ -34,9 +34,19 @@
CbCamera 表描述
+
+
+ CbCameraParams 表名
+
+
+
+
+ CbCameraParams 表描述
+
+
- 系统字典类型表
+ 相机表
@@ -49,11 +59,6 @@
ip 地址
-
-
- 端口
-
-
账号
@@ -64,6 +69,46 @@
密码
+
+
+ 相机参数 Id
+
+
+
+
+ 相机参数表
+
+
+
+
+ 名称
+
+
+
+
+ 相机类型
+
+
+
+
+ sdk 端口
+
+
+
+
+ FocusX
+
+
+
+
+ FocusY
+
+
+
+
+ 相机参数服务
+
+
相机服务
@@ -131,7 +176,7 @@
- 标记标签表
+ 标签表
@@ -176,281 +221,460 @@
- 标记标签服务
+ 标签服务
-
+
- 当前相机参数信息
+ {cameraId, List(MarkLabelCalcResult)}
-
+
- _markLabelInfoList 锁对象,写锁
+ 初始化线程
-
+
- 需要计算的 markLabelInfo 列表
+ 刷新所有相机 ptz
+ 有待改善,应设置超时计数机制
+ https://blog.csdn.net/qq_28368039/article/details/118597396
-
+
- 世界坐标转化为相机坐标矩阵
+ 刷新相机 ptz
+
+
-
+
- 计算标签位置过程
+ 刷新所有 markSearcher
-
-
+
- 判断相机是否进行了转动,转动了则需要重新计算世界坐标到相机坐标的转换矩阵
+ 刷新 markSearcher
-
+
-
+
- 获取将世界坐标系中的点转化为相机坐标系中的点的转换矩阵
+ CameraId2Ip 字典
-
-
-
+
- 获取将相机坐标系中的点转化为世界坐标系中的点的转换矩阵
+ CameraIpCounts 字典
-
+
+
+
+ CameraPtzInfos 字典
+
+
+
+
+ Api 分组名
+
+
+
+
+ Api 分组排序
+
+
+
+
+ 循环间隔,单位毫秒
+
+
+
+
+ 超时时间,单位毫秒
+
+
+
+
+ 相机 sdk 服务类
+
+
+
+
+ {ip, ICameraSDK}
+
+
+
+
+ 相机 sdk 服务接口
+
+
+
+
+ 注册相机
+
+
-
+
- 此方法计算在球机zoom值最小的情况下成像矩阵中的 f 本质为获取像元大小
- 尝试方案1:通过计算的方式来获取
- 尝试方案2:通过张友定相机标定的方法来生成成像矩阵中的 f
+ 注销相机
+
+
-
+
- 将Pan值转化为角度
+ 是否存在相机
+
-
+
- 将Tilt转化为角度
+ 获取 ptz
+
+
-
+
- 根据当前zoom值获取相机矩阵参数
+ 获取 ptz
-
+
+
-
+
+
+ 相机计算参数
+
+
+
+
+ Camera Id
+
+
+
+
+ Ptz 信息
+
+
+
+
+ FocusX
+
+
+
+
+ FocusY
+
+
+
+
+ 视频宽度
+
+
+
+
+ 视频高度
+
+
+
+
+ 标签计算参数
+
+
+
- Ptz Api 接口
+ MarkLabel Id
-
+
- Ptz Api
+ Ptz 信息
-
+
- (cbCameraId, cbCameraIp)
+ 视频宽度
-
+
- (cameraIp, TbPtzCamera)
+ 视频高度
-
+
- (cameraIp, PtzInfo)
+ 画布 left 距离比例
-
+
- _markSearcherDict 锁对象,写锁
+ 画布 top 距离比例
-
+
- (cbCameraId, MarkSearcherBase)
+ 标签计算结果
-
+
- (cameraId, List(MarkLabelCalcResult))
+ MarkLabel Id
-
+
- 循环运行
+ true 显示(在当前视频画面里面)
+ false 不显示(不在当前视频画面里面)
-
+
- 激活 cbCamera 进入运算
+ 画布 left 距离比例
+
+
+
+
+ 画布 top 距离比例
+
+
+
+
+ 追踪标签服务接口
+
+
+
+
+ 激活相机进入运算
-
+
- 解除 cbCamera 进入运算
+ 解除相机进入运算
-
+
- 是否懒加载
+ 是否存在相机进入运算
+
+
-
+
- 循环间隔,单位毫秒
+ 获取 Searcher
+
+
-
+
- PtzServer选项
+ 激活标签进入运算
+
+
+
-
+
- 服务类别
+ 解除标签进入运算
+
+
+
-
+
- 服务IP
+ 是否存在标签进入运算
+
+
+
-
+
- 服务端口
+ 激活相机进入运算
+
+
-
+
- 相机计算信息
+ 解除相机进入运算
+
+
-
+
- Camera Id
+ 是否存在相机进入运算
+
+
-
+
- Ptz 信息
+ 获取 Searcher
+
+
-
+
- 视频的宽度
+ 激活标签进入运算
+
+
+
-
+
- 视频的高度
+ 解除标签进入运算
+
+
+
-
+
- 最小焦距
+ 是否存在标签进入运算
+
+
+
-
+
- Ptz 信息
+ 追踪标签服务类
-
+
- Pan 坐标
+ {cbCameraId, MarkSearcherBase}
-
+
- Tilt 坐标
+ MarkSearcherDict 原子操作锁
-
+
- Zoom 坐标
+ ActivateSearcher 原子操作
+
+
-
+
- 标记标签计算信息
+ DeactivateSearcher 原子操作
+
+
-
+
- MarkLabel Id
+ 当前相机计算参数
-
+
- Ptz 信息
+ 相机当前位置的世界坐标转化为相机坐标矩阵
-
+
- 视频宽度
+ {cameraId, MarkLabelCalcParams}
-
+
- 视频高度
+ 判断相机是否进行了转动,转动了则需要重新计算世界坐标到相机坐标的转换矩阵
+
+
-
+
- 画布 left 距离比例
+ 此方法计算在球机zoom值最小的情况下成像矩阵中的 f 本质为获取像元大小
+ 尝试方案1:通过计算的方式来获取
+ 尝试方案2:通过张正友相机标定的方法来生成成像矩阵中的 f
-
+
- 画布 top 距离比例
+ 获取将世界坐标系中的点转化为相机坐标系中的点的转换矩阵
+
+
-
+
- 标记标签计算结果
+ 获取将相机坐标系中的点转化为世界坐标系中的点的转换矩阵
+
+
-
+
- MarkLabel Id
+ 计算标签位置过程
+
-
+
- true 显示(在当前视频画面里面)
- false 不显示(不在当前视频画面里面)
+ 将Pan值转化为角度
+
-
+
- 画布 left 距离比例
+ 将Tilt转化为角度
+
-
+
- 画布 top 距离比例
+ 根据当前zoom值获取相机矩阵参数
+
+
+
+
+
+
+ 更新相机计算参数
+
+
+
+
+
+ 添加标签计算参数
+
+
+
+
+
+
+ 删除标签计算参数
+
+
+
+
+
+ 是否存在标签计算参数
+
+
+
@@ -585,15 +809,5 @@
系统字典类型服务
-
-
- 数据库标识
-
-
-
-
- TbPtzCamera 表名
-
-
diff --git a/Cis.Application/Cm/Common/CmInfo.cs b/Cis.Application/Cm/Common/CmInfo.cs
index abfda16..eddfd1f 100644
--- a/Cis.Application/Cm/Common/CmInfo.cs
+++ b/Cis.Application/Cm/Common/CmInfo.cs
@@ -5,50 +5,50 @@
///
public class CmInfo
{
- #region Api Info
+ #region Api Info
- ///
- /// Api 分组名
- ///
- public const string GroupName = "CameraMark";
+ ///
+ /// Api 分组名
+ ///
+ public const string GroupName = "CameraMark";
- ///
- /// Api 分组排序
- ///
- public const int GroupOrder = 100;
+ ///
+ /// Api 分组排序
+ ///
+ public const int GroupOrder = 100;
- #endregion Api Info
+ #endregion Api Info
- #region Database Info
+ #region Database Info
- ///
- /// 数据库标识
- ///
- public const string DbName = SqlSugarConst.DefaultConfigId;
+ ///
+ /// 数据库标识
+ ///
+ public const string DbName = SqlSugarConst.DefaultConfigId;
- #endregion Database Info
+ #endregion Database Info
- #region Table Info
+ #region Table Info
- ///
- /// CmMarkGroup 表名
- ///
- public const string CmMarkGroupTbName = "cm_mark_group";
+ ///
+ /// CmMarkGroup 表名
+ ///
+ public const string CmMarkGroupTbName = "cm_mark_group";
- ///
- /// CmMarkGroup 表描述
- ///
- public const string CmMarkGroupTbDesc = "标记分组表";
+ ///
+ /// CmMarkGroup 表描述
+ ///
+ public const string CmMarkGroupTbDesc = "标记分组表";
- ///
- /// CmMarkLabel 表名
- ///
- public const string CmMarkLabelTbName = "cm_mark_label";
+ ///
+ /// CmMarkLabel 表名
+ ///
+ public const string CmMarkLabelTbName = "cm_mark_label";
- ///
- /// CmMarkLabel 表描述
- ///
- public const string CmMarkLabelTbDesc = "标记标签表";
+ ///
+ /// CmMarkLabel 表描述
+ ///
+ public const string CmMarkLabelTbDesc = "标签表";
- #endregion Table Info
+ #endregion Table Info
}
\ No newline at end of file
diff --git a/Cis.Application/Cm/Entity/CmMarkGroup.cs b/Cis.Application/Cm/Entity/CmMarkGroup.cs
index b19e0ed..843f56d 100644
--- a/Cis.Application/Cm/Entity/CmMarkGroup.cs
+++ b/Cis.Application/Cm/Entity/CmMarkGroup.cs
@@ -7,22 +7,22 @@
[Tenant(CmInfo.DbName)]
public class CmMarkGroup : EntityBase
{
- ///
- /// 名称
- ///
- [SugarColumn(ColumnDescription = "名称", Length = 64)]
- public string Name { get; set; }
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ public string Name { get; set; }
- ///
- /// 排序
- ///
- [SugarColumn(ColumnDescription = "排序")]
- public int Order { get; set; }
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int Order { get; set; }
- ///
- /// 备注
- ///
- [SugarColumn(ColumnDescription = "备注", Length = 256)]
- [MaxLength(256)]
- public string Remark { get; set; }
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string Remark { get; set; }
}
\ No newline at end of file
diff --git a/Cis.Application/Cm/Entity/CmMarkLabel.cs b/Cis.Application/Cm/Entity/CmMarkLabel.cs
index 09e3617..3f4a646 100644
--- a/Cis.Application/Cm/Entity/CmMarkLabel.cs
+++ b/Cis.Application/Cm/Entity/CmMarkLabel.cs
@@ -1,64 +1,64 @@
namespace Cis.Application.Cm;
///
-/// 标记标签表
+/// 标签表
///
[SugarTable(CmInfo.CmMarkLabelTbName, CmInfo.CmMarkLabelTbDesc)]
[Tenant(CmInfo.DbName)]
public class CmMarkLabel : EntityBase
{
- ///
- /// 相机 Id
- ///
- [SugarColumn(ColumnDescription = "相机Id")]
- public long CbCameraId { get; set; }
+ ///
+ /// 相机 Id
+ ///
+ [SugarColumn(ColumnDescription = "相机Id")]
+ public long CbCameraId { get; set; }
- ///
- /// 标记组 Id
- ///
- [SugarColumn(ColumnDescription = "标记组Id")]
- public long CmMarkGroupId { get; set; }
+ ///
+ /// 标记组 Id
+ ///
+ [SugarColumn(ColumnDescription = "标记组Id")]
+ public long CmMarkGroupId { get; set; }
- ///
- /// 名称
- ///
- [SugarColumn(ColumnDescription = "名称", Length = 64)]
- public string Name { get; set; }
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ public string Name { get; set; }
- ///
- /// Pan 坐标
- ///
- [SugarColumn(ColumnDescription = "Pan坐标")]
- public double PanPosition { get; set; }
+ ///
+ /// Pan 坐标
+ ///
+ [SugarColumn(ColumnDescription = "Pan坐标")]
+ public double PanPosition { get; set; }
- ///
- /// Tilt 坐标
- ///
- [SugarColumn(ColumnDescription = "Tilt坐标")]
- public double TiltPosition { get; set; }
+ ///
+ /// Tilt 坐标
+ ///
+ [SugarColumn(ColumnDescription = "Tilt坐标")]
+ public double TiltPosition { get; set; }
- ///
- /// Zoom 坐标
- ///
- [SugarColumn(ColumnDescription = "Zoom坐标")]
- public double ZoomPosition { get; set; }
+ ///
+ /// Zoom 坐标
+ ///
+ [SugarColumn(ColumnDescription = "Zoom坐标")]
+ public double ZoomPosition { get; set; }
- [SugarColumn(ColumnDescription = "视频宽度")]
- public double VideoWidth { get; set; }
+ [SugarColumn(ColumnDescription = "视频宽度")]
+ public double VideoWidth { get; set; }
- [SugarColumn(ColumnDescription = "视频高度")]
- public double VideoHeight { get; set; }
+ [SugarColumn(ColumnDescription = "视频高度")]
+ public double VideoHeight { get; set; }
- [SugarColumn(ColumnDescription = "画布 left 距离比例")]
- public double CanvasLeftRatio { get; set; }
+ [SugarColumn(ColumnDescription = "画布 left 距离比例")]
+ public double CanvasLeftRatio { get; set; }
- [SugarColumn(ColumnDescription = "画布 top 距离比例")]
- public double CanvasTopRatio { get; set; }
+ [SugarColumn(ColumnDescription = "画布 top 距离比例")]
+ public double CanvasTopRatio { get; set; }
- ///
- /// 备注
- ///
- [SugarColumn(ColumnDescription = "备注", Length = 256)]
- [MaxLength(256)]
- public string Remark { get; set; }
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string Remark { get; set; }
}
\ No newline at end of file
diff --git a/Cis.Application/Cm/Service/CmMarkGroupService.cs b/Cis.Application/Cm/Service/CmMarkGroupService.cs
index 0b9d9df..341bd51 100644
--- a/Cis.Application/Cm/Service/CmMarkGroupService.cs
+++ b/Cis.Application/Cm/Service/CmMarkGroupService.cs
@@ -8,54 +8,54 @@ namespace Cis.Application.Cm;
[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)]
public class CmMarkGroupService : IDynamicApiController, ITransient
{
- private readonly SqlSugarRepository _cmMarkGroupRep;
-
- public CmMarkGroupService(SqlSugarRepository cmMarkGroupRep)
- {
- _cmMarkGroupRep = cmMarkGroupRep;
- }
-
- [HttpPost]
- public async Task Add([FromForm] CmMarkGroup entity)
- {
- return await _cmMarkGroupRep.InsertAsync(entity);
- }
-
- [HttpPost]
- public async Task Update([FromForm] CmMarkGroup entity)
- {
- return await _cmMarkGroupRep.UpdateAsync(entity);
- }
-
- [HttpPost]
- public async Task Delete([FromForm] CmMarkGroup entity)
- {
- return await _cmMarkGroupRep.DeleteAsync(entity);
- }
-
- [HttpGet]
- public async Task Get(long id)
- {
- CmMarkGroup entity = await _cmMarkGroupRep.GetByIdAsync(id);
- return entity;
- }
-
- [HttpGet]
- public async Task> GetList(string queryJson)
- {
- JObject queryObj = queryJson.ToJObject();
- List list = await _cmMarkGroupRep.AsQueryable()
- .ToListAsync();
- return list;
- }
-
- [HttpGet]
- public async Task> GetPageList(string queryJson, string pagination)
- {
- Pagination pageObj = pagination.ToObject();
- JObject queryObj = queryJson.ToJObject();
- List list = await _cmMarkGroupRep.AsQueryable()
- .ToPageListAsync(pageObj.Index, pageObj.Size);
- return list;
- }
+ private readonly SqlSugarRepository _baseRep;
+
+ public CmMarkGroupService(SqlSugarRepository baseRep)
+ {
+ _baseRep = baseRep;
+ }
+
+ [HttpPost]
+ public async Task Add([FromForm] CmMarkGroup entity)
+ {
+ return await _baseRep.InsertAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Update([FromForm] CmMarkGroup entity)
+ {
+ return await _baseRep.UpdateAsync(entity);
+ }
+
+ [HttpPost]
+ public async Task Delete([FromForm] CmMarkGroup entity)
+ {
+ return await _baseRep.DeleteAsync(entity);
+ }
+
+ [HttpGet]
+ public async Task Get(long id)
+ {
+ CmMarkGroup entity = await _baseRep.GetByIdAsync(id);
+ return entity;
+ }
+
+ [HttpGet]
+ public async Task> GetList(string queryJson)
+ {
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToListAsync();
+ return list;
+ }
+
+ [HttpGet]
+ public async Task> GetPageList(string queryJson, string pagination)
+ {
+ Pagination pageObj = pagination.ToObject();
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToPageListAsync(pageObj.Index, pageObj.Size);
+ return list;
+ }
}
\ No newline at end of file
diff --git a/Cis.Application/Cm/Service/CmMarkLabelService.cs b/Cis.Application/Cm/Service/CmMarkLabelService.cs
index 853af86..7a1bed5 100644
--- a/Cis.Application/Cm/Service/CmMarkLabelService.cs
+++ b/Cis.Application/Cm/Service/CmMarkLabelService.cs
@@ -1,85 +1,87 @@
using Cis.Application.Core;
+using Cis.Application.Core.Component.CameraSDK;
+using EC.Helper.CameraSDK;
using Newtonsoft.Json.Linq;
namespace Cis.Application.Cm;
///
-/// 标记标签服务
+/// 标签服务
///
[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)]
public class CmMarkLabelService : IDynamicApiController, ITransient
{
- private readonly SqlSugarRepository _cmMarkLabelRep;
+ private readonly SqlSugarRepository _baseRep;
- private CameraDataCenter _cameraDataCenter { get; set; }
+ private CameraSdkServer _cameraSdk { get; set; }
- public CmMarkLabelService(CameraDataCenter cameraDataCenter,
- SqlSugarRepository cmMarkLabelRep)
- {
- _cameraDataCenter = cameraDataCenter;
- _cmMarkLabelRep = cmMarkLabelRep;
- }
+ public CmMarkLabelService(
+ SqlSugarRepository baseRep,
+ CameraSdkServer cameraSdk
+ )
+ {
+ _baseRep = baseRep;
+ _cameraSdk = cameraSdk;
+ }
- [HttpPost]
- public async Task Add([FromForm] CmMarkLabel entity)
- {
- PtzInfo ptzInfo = _cameraDataCenter.GetCameraPtzInfo(entity.CbCameraId);
- if (ptzInfo == null)
- return false;
- entity.PanPosition = ptzInfo.Pan;
- entity.TiltPosition = ptzInfo.Tilt;
- entity.ZoomPosition = ptzInfo.Zoom;
- return await _cmMarkLabelRep.InsertAsync(entity);
- }
+ [HttpPost]
+ public async Task Add([FromForm] CmMarkLabel entity)
+ {
+ bool ret = _cameraSdk.GetPtzInfoById(entity.CbCameraId.ToString(), out PtzInfo ptzInfo);
+ if (!ret) return false;
+ entity.PanPosition = ptzInfo.Pan;
+ entity.TiltPosition = ptzInfo.Tilt;
+ entity.ZoomPosition = ptzInfo.Zoom;
+ return await _baseRep.InsertAsync(entity);
+ }
- [HttpPost]
- public async Task AddReturnId([FromForm] CmMarkLabel entity)
- {
- PtzInfo ptzInfo = _cameraDataCenter.GetCameraPtzInfo(entity.CbCameraId);
- if (ptzInfo == null)
- return 0;
- entity.PanPosition = ptzInfo.Pan;
- entity.TiltPosition = ptzInfo.Tilt;
- entity.ZoomPosition = ptzInfo.Zoom;
- await _cmMarkLabelRep.InsertAsync(entity);
- return entity.Id;
- }
+ [HttpPost]
+ public async Task AddReturnId([FromForm] CmMarkLabel entity)
+ {
+ bool ret = _cameraSdk.GetPtzInfoById(entity.CbCameraId.ToString(), out PtzInfo ptzInfo);
+ if (!ret) return 0;
+ entity.PanPosition = ptzInfo.Pan;
+ entity.TiltPosition = ptzInfo.Tilt;
+ entity.ZoomPosition = ptzInfo.Zoom;
+ await _baseRep.InsertAsync(entity);
+ return entity.Id;
+ }
- [HttpPost]
- public async Task Update([FromForm] CmMarkLabel entity)
- {
- return await _cmMarkLabelRep.UpdateAsync(entity);
- }
+ [HttpPost]
+ public async Task Update([FromForm] CmMarkLabel entity)
+ {
+ return await _baseRep.UpdateAsync(entity);
+ }
- [HttpPost]
- public async Task Delete([FromForm] CmMarkLabel entity)
- {
- return await _cmMarkLabelRep.DeleteAsync(entity);
- }
+ [HttpPost]
+ public async Task Delete([FromForm] CmMarkLabel entity)
+ {
+ return await _baseRep.DeleteAsync(entity);
+ }
- [HttpGet]
- public async Task Get(long id)
- {
- CmMarkLabel entity = await _cmMarkLabelRep.GetByIdAsync(id);
- return entity;
- }
+ [HttpGet]
+ public async Task Get(long id)
+ {
+ CmMarkLabel entity = await _baseRep.GetByIdAsync(id);
+ return entity;
+ }
- [HttpGet]
- public async Task> GetList(string queryJson = "")
- {
- JObject queryObj = queryJson.ToJObject();
- List list = await _cmMarkLabelRep.AsQueryable()
- .ToListAsync();
- return list;
- }
+ [HttpGet]
+ public async Task> GetList(string queryJson = "")
+ {
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToListAsync();
+ return list;
+ }
- [HttpGet]
- public async Task> GetPageList(string queryJson, string pagination)
- {
- Pagination pageObj = pagination.ToObject();
- JObject queryObj = queryJson.ToJObject();
- List list = await _cmMarkLabelRep.AsQueryable()
- .ToPageListAsync(pageObj.Index, pageObj.Size);
- return list;
- }
+ [HttpGet]
+ public async Task> GetPageList(string queryJson, string pagination)
+ {
+ Pagination pageObj = pagination.ToObject();
+ JObject queryObj = queryJson.ToJObject();
+ List list = await _baseRep.AsQueryable()
+ .ToPageListAsync(pageObj.Index, pageObj.Size);
+ return list;
+ }
}
\ No newline at end of file
diff --git a/Cis.Application/Core/Algo/HikMarkSeacher.cs b/Cis.Application/Core/Algo/HikMarkSeacher.cs
deleted file mode 100644
index b169e94..0000000
--- a/Cis.Application/Core/Algo/HikMarkSeacher.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System.Drawing;
-
-namespace Cis.Application.Core;
-
-public class HikMarkSeacher : MarkSearcherBase
-{
- public HikMarkSeacher(CameraCalcInfo cameraCalcInfo) : base(cameraCalcInfo)
- {
- }
-
- #region Implement
-
- protected override double ConvertPanPosToAngle(double panPos)
- {
- double ret = 0.1 * HexToDecMa(panPos) / 180 * Math.PI;
- ret = (ret >= 0) ? ret : (2 * Math.PI + ret);
- return ret;
- }
-
- protected override double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0)
- {
- double ndiff;
- if (tiltPos > tiltMinPos)
- ndiff = HexToDecMa(tiltPos) - HexToDecMa(tiltMinPos);
- else
- ndiff = HexToDecMa(tiltPos) + HexToDecMa(13824) - HexToDecMa(tiltMinPos);
- double ret = 0.1 * ndiff / 180 * Math.PI;
- return ret;
- }
-
- protected override PointF GetFOfMatrixByZoomPos(double zoomPos)
- {
- PointF pointF = new()
- {
- X = (float)GetFx(zoomPos),
- Y = (float)GetFy(zoomPos)
- };
- return pointF;
- }
-
- protected override void CalcSensor()
- {
- _cameraCalcInfo.MinFocusX = 1783.6 / _cameraCalcInfo.VideoWidth;
- _cameraCalcInfo.MinFocusY = 1781.4 / _cameraCalcInfo.VideoHeight;
- }
-
- #endregion Implement
-
- #region Util
-
- protected virtual double GetFx(double zoomPos)
- {
- CameraCalcInfo calcInfo = _cameraCalcInfo;
- return calcInfo.MinFocusX * GetZoomTag(zoomPos);
- }
-
- protected virtual double GetFy(double zoomPos)
- {
- CameraCalcInfo calcInfo = _cameraCalcInfo;
- return calcInfo.MinFocusY * GetZoomTag(zoomPos);
- }
-
- protected virtual double GetZoomTag(double zoomPos)
- {
- double ret = HexToDecMa(zoomPos) * 0.1;
- ret = (ret - 1) * 0.65 + 1;
- return ret;
- }
-
- protected int HexToDecMa(double wHex)
- {
- int wHexInt = wHex.ToInt();
- int ret = (wHexInt / 4096) * 1000 + ((wHexInt % 4096) / 256) * 100 + ((wHexInt % 256) / 16) * 10 + (wHexInt % 16);
- return ret;
- }
-
-
-
- #endregion Util
-}
diff --git a/Cis.Application/Core/Algo/MarkSearcherBase.cs b/Cis.Application/Core/Algo/MarkSearcherBase.cs
deleted file mode 100644
index b840e9c..0000000
--- a/Cis.Application/Core/Algo/MarkSearcherBase.cs
+++ /dev/null
@@ -1,260 +0,0 @@
-using MathNet.Numerics.LinearAlgebra;
-using MathNet.Numerics.LinearAlgebra.Double;
-using System.Collections.Concurrent;
-using System.Drawing;
-
-namespace Cis.Application.Core;
-
-public abstract class MarkSearcherBase
-{
- #region Attr
-
- ///
- /// 当前相机参数信息
- ///
- protected CameraCalcInfo _cameraCalcInfo { get; set; }
-
- ///
- /// _markLabelInfoList 锁对象,写锁
- ///
- private static object mliListLock { get; } = new();
-
- ///
- /// 需要计算的 markLabelInfo 列表
- ///
- protected ConcurrentDictionary _markLabelInfoDict { get; set; } = new();
-
- //protected MatrixBuilder MBuilder { get; set; } = Matrix.Build;
-
- ///
- /// 世界坐标转化为相机坐标矩阵
- ///
- protected Matrix World2CameraMatrix { get; set; }
-
- #endregion Attr
-
- public MarkSearcherBase(CameraCalcInfo cameraCalcInfo)
- {
- UpdateCameraCalcInfoRelated(cameraCalcInfo);
- }
-
- #region Calc
-
- ///
- /// 计算标签位置过程
- ///
- ///
- public List Calc()
- {
- List resultList = new();
-
- if (World2CameraMatrix == null || _markLabelInfoDict.IsEmpty)
- return resultList;
-
- foreach (MarkLabelCalcInfo item in _markLabelInfoDict.Values)
- {
- Matrix labelC2WMatrix = ConvertCameraToWorld(item);
- Matrix labelPointMatrix = new DenseMatrix(3, 1, new double[]
- {
- (item.CanvasLeftRatio * item.VideoWidth) / _cameraCalcInfo.VideoWidth - 0.5 ,
- (item.CanvasTopRatio * item.VideoHeight) / _cameraCalcInfo.VideoHeight - 0.5 ,
- 1
- });
- Matrix lResult = labelC2WMatrix.Multiply(labelPointMatrix);
- Matrix pResult = World2CameraMatrix.Multiply(lResult);
-
- double x = pResult[0, 0] / pResult[2, 0] + 0.5;
- double y = pResult[1, 0] / pResult[2, 0] + 0.5;
- MarkLabelCalcResult labelCalcResult;
- if (x > 0.99 || x < 0.01 || y > 0.99 || y < 0.01 || pResult[2, 0] < 0)
- labelCalcResult = MarkLabelCalcResult.New(item.Id, false);
- else
- labelCalcResult = MarkLabelCalcResult.New(item.Id, true, x, y);
- resultList.Add(labelCalcResult);
- }
- return resultList;
- }
-
- public async Task> CalcAsync()
- {
- return await Task.Run(Calc);
- }
-
- ///
- /// 判断相机是否进行了转动,转动了则需要重新计算世界坐标到相机坐标的转换矩阵
- ///
- ///
- ///
- protected bool IsCameraRotate(PtzInfo newInfo)
- {
- bool ret = _cameraCalcInfo.PtzInfo.Pan != newInfo.Pan ||
- _cameraCalcInfo.PtzInfo.Tilt != newInfo.Tilt ||
- _cameraCalcInfo.PtzInfo.Zoom != newInfo.Zoom;
- return ret;
- }
-
- ///
- /// 获取将世界坐标系中的点转化为相机坐标系中的点的转换矩阵
- ///
- ///
- ///
- protected Matrix ConvertWorldToCamera(CameraCalcInfo cameraCalcInfo)
- {
- double panAngle = ConvertPanPosToAngle(cameraCalcInfo.PtzInfo.Pan);
- double tiltAngle = ConvertTiltPosToAngle(cameraCalcInfo.PtzInfo.Tilt);
- PointF pointF = GetFOfMatrixByZoomPos(cameraCalcInfo.PtzInfo.Zoom);
- double sinPan = Math.Sin(panAngle);
- double cosPan = Math.Cos(panAngle);
- double sinTilt = Math.Sin(tiltAngle);
- double cosTilt = Math.Cos(tiltAngle);
-
- Matrix fMatrix = new DenseMatrix(3, 3, new double[]
- {
- pointF.X, 0, 0 ,
- 0, pointF.Y, 0 ,
- 0, 0, 1 ,
- });
-
- Matrix rotateTiltMatrix = new DenseMatrix(3, 3, new double[]
- {
- 1, 0, 0 ,
- 0, cosTilt, sinTilt ,
- 0, -sinTilt, cosTilt ,
- });
-
- Matrix midResult = fMatrix.Multiply(rotateTiltMatrix);
-
- Matrix rotatePanMatrix = new DenseMatrix(3, 3, new double[]
- {
- cosPan, 0, sinPan ,
- 0, 1, 0 ,
- -sinPan, 0, cosPan ,
- });
-
- var last = midResult.Multiply(rotatePanMatrix);
- return last;
- }
-
- ///
- /// 获取将相机坐标系中的点转化为世界坐标系中的点的转换矩阵
- ///
- ///
- ///
- protected Matrix ConvertCameraToWorld(MarkLabelCalcInfo labelCalcInfo)
- {
- double panAngle = ConvertPanPosToAngle(labelCalcInfo.PtzInfo.Pan);
- double tiltAngle = ConvertTiltPosToAngle(labelCalcInfo.PtzInfo.Tilt);
- PointF pointF = GetFOfMatrixByZoomPos(labelCalcInfo.PtzInfo.Zoom);
- double sinPan = Math.Sin(panAngle);
- double cosPan = Math.Cos(panAngle);
- double sinTilt = Math.Sin(tiltAngle);
- double cosTilt = Math.Cos(tiltAngle);
-
- Matrix rotatePanMatrix = new DenseMatrix(3, 3, new double[]
- {
- cosPan, 0, -sinPan ,
- 0, 1, 0 ,
- sinPan, 0, cosPan
- });
-
- Matrix rotateTiltMatrix = new DenseMatrix(3, 3, new double[]
- {
- 1, 0, 0 ,
- 0, cosTilt, -sinTilt ,
- 0, sinTilt, cosTilt
- });
-
- Matrix midResult = rotatePanMatrix.Multiply(rotateTiltMatrix);
-
- Matrix fMatrix = new DenseMatrix(3, 3, new double[]
- {
- (1 / pointF.X), 0, 0 ,
- 0, (1 / pointF.Y), 0 ,
- 0, 0, 1
- });
-
- var last = midResult.Multiply(fMatrix);
- return last;
- }
-
- ///
- /// 此方法计算在球机zoom值最小的情况下成像矩阵中的 f 本质为获取像元大小
- /// 尝试方案1:通过计算的方式来获取
- /// 尝试方案2:通过张友定相机标定的方法来生成成像矩阵中的 f
- ///
- protected virtual void CalcSensor()
- {
- }
-
- #endregion Calc
-
- #region Util
-
- ///
- /// 将Pan值转化为角度
- ///
- ///
- protected abstract double ConvertPanPosToAngle(double panPos);
-
- ///
- /// 将Tilt转化为角度
- ///
- ///
- protected abstract double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0);
-
- ///
- /// 根据当前zoom值获取相机矩阵参数
- ///
- ///
- ///
- protected abstract PointF GetFOfMatrixByZoomPos(double zoomPos);
-
- #endregion Util
-
- #region Operate Attr
-
- protected void UpdateCameraCalcInfoRelated(CameraCalcInfo cameraCalcInfo)
- {
- _cameraCalcInfo = cameraCalcInfo;
- CalcSensor();
- World2CameraMatrix = ConvertWorldToCamera(cameraCalcInfo);
- }
-
- public void UpdateCameraCalcInfo(PtzInfo ptzInfo)
- {
- if (IsCameraRotate(ptzInfo))
- {
- _cameraCalcInfo.PtzInfo = ptzInfo;
- World2CameraMatrix = ConvertWorldToCamera(_cameraCalcInfo);
- }
- }
-
- public bool AddMarkLabelCalcInfo(MarkLabelCalcInfo info)
- {
- lock (mliListLock)
- {
- if (_markLabelInfoDict.ContainsKey(info.Id))
- return false;
- return _markLabelInfoDict.TryAdd(info.Id, info);
- }
- }
-
- public bool DeleteMarkLabelCalcInfo(long id)
- {
- lock (mliListLock)
- {
- if (!_markLabelInfoDict.ContainsKey(id))
- return true;
- return _markLabelInfoDict.Remove(id);
- }
- }
-
- public bool ExistsMarkLabelCalcInfo(long id)
- {
- if (_markLabelInfoDict.ContainsKey(id))
- return true;
- return false;
- }
-
- #endregion Operate Attr
-}
\ No newline at end of file
diff --git a/Cis.Application/Core/Api/IPtzApi.cs b/Cis.Application/Core/Api/IPtzApi.cs
deleted file mode 100644
index e3461e5..0000000
--- a/Cis.Application/Core/Api/IPtzApi.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Cis.Application.Core;
-
-///
-/// Ptz Api 接口
-///
-public interface IPtzApi
-{
-
-}
\ No newline at end of file
diff --git a/Cis.Application/Core/Api/PtzServerApi.cs b/Cis.Application/Core/Api/PtzServerApi.cs
deleted file mode 100644
index f85b487..0000000
--- a/Cis.Application/Core/Api/PtzServerApi.cs
+++ /dev/null
@@ -1,205 +0,0 @@
-using System.Net.Sockets;
-using System.Runtime.InteropServices;
-
-namespace Cis.Application.Core;
-
-///
-/// Ptz Api
-///
-public class PtzServerApi : IPtzApi, ISingleton
-{
- #region Attr
-
- private TcpClient _tcpClient { get; set; }
-
- private NetworkStream _stream { get; set; }
-
- #endregion Attr
-
- public PtzServerApi()
- {
- PtzServerOptions options = App.GetOptions();
- _tcpClient = new TcpClient(options.Ip, options.Port);
- //创建一个 networkstream 用来写入和读取数据
- _stream = _tcpClient.GetStream();
- }
-
- public RequestRealControl GetPtzRrc(int cameraId)
- {
- RequestRealControl realControl = new();
- try
- {
- string recieve_string = string.Empty;
- realControl.token = 666;
-
- realControl.CameraInfo.cameraid = cameraId;
- realControl.Status = true;
- realControl.realControlType = RealControlType.PTZINFO_GET_;
- byte[] data = StructToByte(realControl);
- _stream.Write(data, 0, data.Length);
-
- byte[] recieve_byte = new byte[_tcpClient.ReceiveBufferSize];
- _stream.Read(recieve_byte, 0, (int)_tcpClient.ReceiveBufferSize);
- //stream.BeginRead(recieve_byte, 0, (int)tcp_client.ReceiveBufferSize,EndRead, stream);
- realControl = (RequestRealControl)BytetoStruct(recieve_byte, typeof(RequestRealControl));
- if (realControl.PTZPositionInfo.FT < 0)
- {
- realControl.PTZPositionInfo.FT = 3600 + realControl.PTZPositionInfo.FT;
- }
- }
- catch (Exception)
- {
- realControl = default;
- }
- return realControl;
- }
-
- public PtzInfo GetPtzInfo(int cameraId)
- {
- RequestRealControl rrc = GetPtzRrc(cameraId);
- PtzInfo ptzInfo = PtzInfo.New(rrc.PTZPositionInfo.FP, rrc.PTZPositionInfo.FT, rrc.PTZPositionInfo.FZ);
- return ptzInfo;
- }
-
- public static byte[] StructToByte(object structObj)
- {
- //获取结构体大小
- int size = Marshal.SizeOf(structObj);
-
- byte[] data = new byte[size];
-
- //分配内存空间
- IntPtr structPtr = Marshal.AllocHGlobal(size);
- // 将结构体数据复制到内存空间
- Marshal.StructureToPtr(structObj, structPtr, false);
- // 将内存空间的数据拷贝到byte数组
- Marshal.Copy(structPtr, data, 0, size);
- //释放内存
- Marshal.FreeHGlobal(structPtr);
- return data;
- }
-
- public static object BytetoStruct(byte[] bytes, Type type)
- {
- object obj = new object();
- try
- {
- byte[] temp = bytes;
- // 获取结构体大小
- int size = Marshal.SizeOf(type);
- if (size > bytes.Length)
- return null;
- // 分配结构体内存空间
- IntPtr structPtr = Marshal.AllocHGlobal(size);
- // 将byte数组内容拷贝到内存中
- Marshal.Copy(temp, 0, structPtr, size);
-
- // 将内存空间转化为目标结构体
- obj = Marshal.PtrToStructure(structPtr, type);
- //释放内存
- Marshal.FreeHGlobal(structPtr);
- }
- catch (Exception)
- {
- }
- return obj;
- }
-
-}
-
-#region 与ptz服务交互使用结构体
-
-//----------------------------------------------------------------------------------------
-// 与ptz服务交互使用结构体
-//----------------------------------------------------------------------------------------
-//注意这个属性不能少
-[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
-public struct RequestRealControl
-{
- public int token;
-
- public CameraInfo CameraInfo;
-
- public RealControlType realControlType;
-
- //请求时 状态 true:开始;false:结束 答复时:true:成功;其他:失败
- public bool Status;
-
- public PresentInfo PresentInfo;
-
- public PTZPosInfo PTZPositionInfo;
- //int数组,SizeConst表示数组的个数,在转换成
- //byte数组前必须先初始化数组,再使用,初始化
- //的数组长度必须和SizeConst一致,例test = new int[6];
- //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
- //public int[] test;
-}
-
-[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
-public struct CameraInfo
-{
- public int cameraid;
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
- public char[] ip;
-
- public ushort port;
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
- private char[] user;
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
- private char[] password;
-}
-
-[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
-public struct PresentInfo
-{
- public int presentNo;//预置位编号
-
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
- private char[] PresentName; // 预置位名称
-}
-
-[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)]
-public struct PTZPosInfo
-{
- public int FP;//p信息
- public int FT;//T信息
- public int FZ;//Z信息
- public int TitlePosMin;//描述点垂直参数min
- public int ZoomPosMin;//描述点变倍参数min
-
- public float FHorWidth;//水平宽度 精确到小数点后两位 *10000
- public float FVerWidth;//垂直宽度 精确到小数点后两位 *10000
- public float FFold;//zoom=1没变时的焦距 精确到小数点后两位 *100
-
- public int CameraType;
-}
-
-public enum RealControlType
-{
- MOVE_UP_ = 1,
- MOVE_DOWN_,
- MOVE_LEFT_,
- MOVE_RIGHT_,
- MOVE_LEFTUP_,
- MOVE_LEFTDOWN_,
- MOVE_RIGHTUP_,
- MOVE_RIGHTDOWN_,
-
- ZOOM_IN_,
- ZOOM_OUT_,
- FOCUS_NEAR_,
- FOCUS_FAR_,
- IRIS_OPEN_,
- IRIS_CLOSE_,
-
- PRESET_SET_,
- PRESET_CALL_,
-
- PTZINFO_GET_,
- PTZINFO_SET_
-}
-
-#endregion 与ptz服务交互使用结构体
\ No newline at end of file
diff --git a/Cis.Application/Core/Center/CameraDataCenter.cs b/Cis.Application/Core/Center/CameraDataCenter.cs
index 6dfef8b..0dbbeeb 100644
--- a/Cis.Application/Core/Center/CameraDataCenter.cs
+++ b/Cis.Application/Core/Center/CameraDataCenter.cs
@@ -1,309 +1,166 @@
using Cis.Application.Cb;
using Cis.Application.Cm;
-using Cis.Application.Tb;
-using Microsoft.Extensions.Logging;
+using Cis.Application.Core.Component.MarkSeacher;
+using Cis.Application.Core.Component.PtzServer;
+using EC.Helper.CameraSDK;
+using StackExchange.Profiling.Internal;
+using StackExchange.Redis;
using System.Collections.Concurrent;
namespace Cis.Application.Core;
-public class CameraDataCenter
+public class CameraDataCenter : ISingleton
{
#region Attr
private readonly SqlSugarRepository _cbCameraRep;
private readonly SqlSugarRepository _cmMarkLableRep;
- private readonly SqlSugarRepository _tbPtzCameraRep;
- private readonly PtzServerApi _ptzServerApi;
- private readonly CameraDataOptions options;
+ private readonly IDatabase _cache;
- private Thread _thread { get; set; }
+ private readonly CameraDataOptions _options;
+ private readonly ICameraSdkServer _cameraSdkServer;
+ private readonly IMarkSearcherServer _markSearcherServer;
///
- /// (cbCameraId, cbCameraIp)
+ /// {cameraId, List(MarkLabelCalcResult)}
///
- private Dictionary _cbCameraId2IpDict { get; set; } = new();
- ///
- /// (cameraIp, TbPtzCamera)
- ///
- private ConcurrentDictionary _tbPtzCameraDict { get; set; } = new();
-
- ///
- /// (cameraIp, PtzInfo)
- ///
- private ConcurrentDictionary _cameraPtzInfoDict { get; set; } = new();
-
- ///
- /// _markSearcherDict 锁对象,写锁
- ///
- private static ReaderWriterLockSlim msDictLock { get; } = new();
-
- ///
- /// (cbCameraId, MarkSearcherBase)
- ///
- private ConcurrentDictionary _markSearcherDict { get; set; } = new();
-
- ///
- /// (cameraId, List(MarkLabelCalcResult))
- ///
-
- private ConcurrentDictionary> _markLabelCalcResultListDict { get; set; } = new();
+ private ConcurrentDictionary> SearchResultListDict { get; set; } = new();
#endregion Attr
- private readonly ILogger _logger;
-
- public CameraDataCenter()
+ public CameraDataCenter(
+ IDatabase cache,
+ ICameraSdkServer cameraSdkServer,
+ IMarkSearcherServer markSearcherServer
+ )
{
_cbCameraRep = App.GetService>();
_cmMarkLableRep = App.GetService>();
- _tbPtzCameraRep = App.GetService>();
- _ptzServerApi = App.GetService();
- options = App.GetOptions();
- _logger = App.GetService>();
- Init();
+ _cache = cache;
+ _options = App.GetOptions();
+ _cameraSdkServer = cameraSdkServer;
+ _markSearcherServer = markSearcherServer;
+ InitThread();
}
- private void Init()
+ #region Loop
+
+ private Thread RefreshCameraPtzThread { get; set; }
+
+ private Thread RefreshMarkSearcherThread { get; set; }
+
+ ///
+ /// 初始化线程
+ ///
+ private void InitThread()
{
- if (!options.LazyInit)
+ // 初始化 CameraPtzThread
+ RefreshCameraPtzThread = new Thread(() =>
{
- List list = _tbPtzCameraRep.GetList();
- // 根据 Ip 去重
- foreach (TbPtzCamera item in list)
+ while (true)
{
- if (!_tbPtzCameraDict.ContainsKey(item.Ip))
- _tbPtzCameraDict[item.Ip] = item;
+ RefreshCameraPtzInfos();
+ Thread.Sleep(_options.CameraPtz.LoopInterval);
}
- }
+ })
+ {
+ IsBackground = true// 设置后台线程
+ };
+ // 启动 CameraPtzThread
+ RefreshCameraPtzThread.Start();
- // 初始化 thread
- _thread = new Thread(WorkLoop)
+ // 初始化 MarkSearcherThread
+ RefreshMarkSearcherThread = new Thread(() =>
+ {
+ while (true)
+ {
+ RefreshMarkSearchers();
+ Thread.Sleep(_options.MarkSearcher.LoopInterval);
+ }
+ })
{
IsBackground = true// 设置后台线程
};
- _thread.Start();
+ // 启动 MarkSearcherThread
+ RefreshMarkSearcherThread.Start();
}
- #region Loop
-
///
- /// 循环运行
+ /// 刷新所有相机 ptz
+ /// 有待改善,应设置超时计数机制
+ /// https://blog.csdn.net/qq_28368039/article/details/118597396
///
- private void WorkLoop()
+ private async void RefreshCameraPtzInfos()
{
- while (true)
+ HashEntry[] entries = _cache.HashGetAll(CacheInfo.CameraIpCounts);
+ List tasks = new();
+ foreach (HashEntry entry in entries)
{
- RefreshPtzInfoByApi();
- RefreshMarkSearcher();
- Thread.Sleep(options.LoopInterval);
+ string cameraIp = entry.Name;
+ tasks.Add(RefreshCameraPtzInfo(cameraIp));
}
+ await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(_options.CameraPtz.Timeout));
}
- private void RefreshPtzInfoByApi()
- {
- foreach (TbPtzCamera item in _tbPtzCameraDict.Values)
- {
- PtzInfo ptzInfo = _ptzServerApi.GetPtzInfo(item.CameraId);
- _cameraPtzInfoDict[item.Ip] = ptzInfo;
- }
- }
-
- private async void RefreshMarkSearcher()
+ ///
+ /// 刷新相机 ptz
+ ///
+ ///
+ ///
+ private async Task RefreshCameraPtzInfo(string cameraIp)
{
- foreach (KeyValuePair 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 resultList = await markSearcher.CalcAsync();
- _markLabelCalcResultListDict[cameraId] = resultList;
- }
+ bool ret = _cameraSdkServer.GetPtzInfoByIp(cameraIp, out PtzInfo ptzInfo);
+ if (!ret) return;
+ await _cache.HashSetAsync(CacheInfo.CameraPtzInfos, cameraIp, ptzInfo.ToJson());
}
- #endregion Loop
-
- #region external call
-
///
- /// 激活 cbCamera 进入运算
+ /// 刷新所有 markSearcher
///
- ///
- ///
- public bool ActivateSearcher(long cameraId)
+ private async void RefreshMarkSearchers()
{
- 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 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
+ HashEntry[] entries = _cache.HashGetAll(CacheInfo.CameraId2Ip);
+ List tasks = new();
+ foreach (HashEntry entry in entries)
{
- msDictLock.ExitWriteLock();
+ string cameraId = entry.Name;
+ tasks.Add(RefreshMarkSearcher(cameraId.ToLong()));
}
- return true;
+ await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(_options.CameraPtz.Timeout));
}
///
- /// 解除 cbCamera 进入运算
+ /// 刷新 markSearcher
///
///
///
- public bool DeActivateSearcher(long cameraId)
+ private async Task RefreshMarkSearcher(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);
+ MarkSearcherBase markSearcher = _markSearcherServer.GetSearcher(cameraId);
+ if (markSearcher == null) return;
+ string cameraIp = _cache.HashGet(CacheInfo.CameraId2Ip, cameraId);
+ RedisValue value = _cache.HashGet(CacheInfo.CameraPtzInfos, cameraIp);
+ if (value.IsNull) return;
+ PtzInfo ptzInfo = value.ToString().FromJson();
+ markSearcher.UpdateCameraCalcParams(ptzInfo);
+ List resultList = await markSearcher.SearchAsync();
+ SearchResultListDict[cameraId] = resultList;
}
- 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;
- }
+ #endregion Loop
- public bool IsExistCameraMarkLabel(long cameraId, long markLabelId)
- {
- bool ret = _markSearcherDict.TryGetValue(cameraId, out MarkSearcherBase markSearcher) &&
- markSearcher.ExistsMarkLabelCalcInfo(markLabelId);
- return ret;
- }
+ #region Base Method
public List GetMarkLabelCalcResultList(long cameraId)
{
- bool ret = _markLabelCalcResultListDict.TryGetValue(cameraId, out List 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 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 IsExistSearcherAsync(long cameraId)
- {
- return await Task.Run(() =>
- {
- return IsExistSearcher(cameraId);
- });
- }
-
- public async Task ActivateMarkLabelAsync(long cameraId, long markLabelId)
- {
- return await Task.Run(() =>
- {
- return ActivateMarkLabel(cameraId, markLabelId);
- });
+ bool ret = SearchResultListDict.TryGetValue(cameraId, out List resultList);
+ return ret ? resultList : new List();
}
- public async Task DeactivateMarkLabelAsync(long cameraId, long markLabelId)
- {
- return await Task.Run(() =>
- {
- return DectivateMarkLabel(cameraId, markLabelId);
- });
- }
+ #endregion Base Method
- public async Task IsExistMarkLabelAysnc(long cameraId, long markLabelId)
- {
- return await Task.Run(() =>
- {
- return IsExistCameraMarkLabel(cameraId, markLabelId);
- });
- }
+ #region Base Method Async
public async Task> GetMarkLabelCalcResultListAsync(long cameraId)
{
@@ -313,5 +170,5 @@ public class CameraDataCenter
});
}
- #endregion external call
+ #endregion Base Method Async
}
\ No newline at end of file
diff --git a/Cis.Application/Core/Common/CacheInfo.cs b/Cis.Application/Core/Common/CacheInfo.cs
new file mode 100644
index 0000000..b5ec0f3
--- /dev/null
+++ b/Cis.Application/Core/Common/CacheInfo.cs
@@ -0,0 +1,23 @@
+namespace Cis.Application.Core;
+
+public class CacheInfo
+{
+ #region Cache Name
+
+ ///
+ /// CameraId2Ip 字典
+ ///
+ public static string CameraId2Ip { get; set; } = "CameraId2Ip";
+
+ ///
+ /// CameraIpCounts 字典
+ ///
+ public static string CameraIpCounts { get; set; } = "CameraIpCounts";
+
+ ///
+ /// CameraPtzInfos 字典
+ ///
+ public static string CameraPtzInfos { get; set; } = "CameraPtzInfos";
+
+ #endregion Cache Name
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Common/CoreInfo.cs b/Cis.Application/Core/Common/CoreInfo.cs
new file mode 100644
index 0000000..5130a4c
--- /dev/null
+++ b/Cis.Application/Core/Common/CoreInfo.cs
@@ -0,0 +1,18 @@
+namespace Cis.Application.Core;
+
+public class CoreInfo
+{
+ #region Api Info
+
+ ///
+ /// Api 分组名
+ ///
+ public const string GroupName = "Core";
+
+ ///
+ /// Api 分组排序
+ ///
+ public const int GroupOrder = 100;
+
+ #endregion Api Info
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Common/Extension.cs b/Cis.Application/Core/Common/Extension.cs
new file mode 100644
index 0000000..e2746c8
--- /dev/null
+++ b/Cis.Application/Core/Common/Extension.cs
@@ -0,0 +1,30 @@
+using Cis.Application.Core.Component.MarkSeacher;
+using EC.Helper.CameraSDK;
+
+namespace Cis.Application.Core;
+
+[SuppressSniffer]
+public static class Extension
+{
+ public static ICameraSDK CreateCameraSDK(this CameraType cameraType, CameraInfo cameraInfo)
+ {
+ return cameraType switch
+ {
+ CameraType.HiK => new HiKSDK(cameraInfo),
+ CameraType.DaHua => new DaHuaSDK(cameraInfo),
+ CameraType.YuShi => new YuShiSDK(cameraInfo),
+ _ => null,
+ };
+ }
+
+ public static MarkSearcherBase CreateMarkSearcher(this CameraType cameraType, CameraCalcParams cameraCalcParams)
+ {
+ return cameraType switch
+ {
+ CameraType.HiK => new HiKMarkSearcher(cameraCalcParams),
+ CameraType.DaHua => new DaHuaMarkSearcher(cameraCalcParams),
+ CameraType.YuShi => new YuShiMarkSearcher(cameraCalcParams),
+ _ => null
+ };
+ }
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Common/Options.cs b/Cis.Application/Core/Common/Options.cs
index 6eb32fa..8218838 100644
--- a/Cis.Application/Core/Common/Options.cs
+++ b/Cis.Application/Core/Common/Options.cs
@@ -2,34 +2,30 @@
public class CameraDataOptions : IConfigurableOptions
{
- ///
- /// 是否懒加载
- ///
- public bool LazyInit { get; set; }
+ public string Test { get; set; }
- ///
- /// 循环间隔,单位毫秒
- ///
- public int LoopInterval { get; set; }
+ public CameraPtz CameraPtz { get; set; }
+
+ public MarkSearcher MarkSearcher { get; set; }
}
-///
-/// PtzServer选项
-///
-public class PtzServerOptions : IConfigurableOptions
+public class CameraDataBase
{
- ///
- /// 服务类别
- ///
- public string Type { get; set; }
+ ///
+ /// 循环间隔,单位毫秒
+ ///
+ public int LoopInterval { get; set; }
+
+ ///
+ /// 超时时间,单位毫秒
+ ///
+ public int Timeout { get; set; }
+}
- ///
- /// 服务IP
- ///
- public string Ip { get; set; }
+public class CameraPtz : CameraDataBase
+{
+}
- ///
- /// 服务端口
- ///
- public int Port { get; set; }
+public class MarkSearcher : CameraDataBase
+{
}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/CameraSDK/CameraSdkServer.cs b/Cis.Application/Core/Component/CameraSDK/CameraSdkServer.cs
new file mode 100644
index 0000000..05586c0
--- /dev/null
+++ b/Cis.Application/Core/Component/CameraSDK/CameraSdkServer.cs
@@ -0,0 +1,73 @@
+using Cis.Application.Core.Component.PtzServer;
+using EC.Helper.CameraSDK;
+using StackExchange.Redis;
+using System.Collections.Concurrent;
+
+namespace Cis.Application.Core.Component.CameraSDK;
+
+///
+/// 相机 sdk 服务类
+///
+public class CameraSdkServer : ICameraSdkServer, ISingleton
+{
+ #region Attr
+
+ private readonly IDatabase _cache;
+
+ ///
+ /// {ip, ICameraSDK}
+ ///
+ private ConcurrentDictionary CameraSdkDict { get; set; } = new();
+
+ #endregion Attr
+
+ public CameraSdkServer(IDatabase cache)
+ {
+ _cache = cache;
+ }
+
+ #region Base Method
+
+ public bool RegisterCamera(CameraInfo cameraInfo)
+ {
+ bool ret = CameraSdkDict.ContainsKey(cameraInfo.Ip);
+ if (ret) return false;
+ ICameraSDK cameraSDK = ((CameraType)cameraInfo.Type).CreateCameraSDK(cameraInfo);
+ if (cameraSDK == null) return false;
+ ret = cameraSDK.Init();
+ if (!ret) return false;
+ ret = CameraSdkDict.TryAdd(cameraInfo.Ip, cameraSDK);
+ return ret;
+ }
+
+ public bool DeleteCamera(string ip)
+ {
+ return CameraSdkDict.TryRemove(ip, out _);
+ }
+
+ public bool IsExistsCamera(string ip)
+ {
+ return CameraSdkDict.ContainsKey(ip);
+ }
+
+ #endregion Base Method
+
+ #region Main Method
+
+ public bool GetPtzInfoById(string cameraId, out PtzInfo ptzInfo)
+ {
+ RedisValue value = _cache.HashGet(CacheInfo.CameraId2Ip, cameraId);
+ if (value.IsNull) { ptzInfo = PtzInfo.Default; return false; }
+ string ip = value.ToString();
+ return GetPtzInfoByIp(ip, out ptzInfo);
+ }
+
+ public bool GetPtzInfoByIp(string ip, out PtzInfo ptzInfo)
+ {
+ bool ret = CameraSdkDict.TryGetValue(ip, out ICameraSDK cameraSDK);
+ if (!ret) { ptzInfo = PtzInfo.Default; return false; }
+ return cameraSDK.GetPtzInfo(out ptzInfo);
+ }
+
+ #endregion Main Method
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/CameraSDK/ICameraSdkServer.cs b/Cis.Application/Core/Component/CameraSDK/ICameraSdkServer.cs
new file mode 100644
index 0000000..30adb5c
--- /dev/null
+++ b/Cis.Application/Core/Component/CameraSDK/ICameraSdkServer.cs
@@ -0,0 +1,54 @@
+using EC.Helper.CameraSDK;
+
+namespace Cis.Application.Core.Component.PtzServer;
+
+///
+/// 相机 sdk 服务接口
+///
+public interface ICameraSdkServer
+{
+ #region Base Method
+
+ ///
+ /// 注册相机
+ ///
+ ///
+ ///
+ public bool RegisterCamera(CameraInfo cameraInfo);
+
+ ///
+ /// 注销相机
+ ///
+ ///
+ ///
+ public bool DeleteCamera(string ip);
+
+ ///
+ /// 是否存在相机
+ ///
+ ///
+ ///
+ public bool IsExistsCamera(string ip);
+
+ #endregion Base Method
+
+ #region Main Method
+
+ ///
+ /// 获取 ptz
+ ///
+ ///
+ ///
+ ///
+ public bool GetPtzInfoById(string cameraId, out PtzInfo ptzInfo);
+
+ ///
+ /// 获取 ptz
+ ///
+ ///
+ ///
+ ///
+ public bool GetPtzInfoByIp(string ip, out PtzInfo ptzInfo);
+
+ #endregion Main Method
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Entity/CameraCalcParams.cs b/Cis.Application/Core/Component/MarkSeacher/Entity/CameraCalcParams.cs
new file mode 100644
index 0000000..0f2515c
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Entity/CameraCalcParams.cs
@@ -0,0 +1,52 @@
+using EC.Helper.CameraSDK;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+///
+/// 相机计算参数
+///
+public class CameraCalcParams
+{
+ ///
+ /// Camera Id
+ ///
+ public long Id { get; set; }
+
+ ///
+ /// Ptz 信息
+ ///
+ public PtzInfo PtzInfo { get; set; }
+
+ ///
+ /// FocusX
+ ///
+ public double FocusX { get; set; }
+
+ ///
+ /// FocusY
+ ///
+ public double FocusY { get; set; }
+
+ ///
+ /// 视频宽度
+ ///
+ public int VideoWidth { get; set; }
+
+ ///
+ /// 视频高度
+ ///
+ public int VideoHeight { get; set; }
+
+ public static CameraCalcParams New(long id, PtzInfo ptzInfo, double focusX, double focusY, int videoWidth = 1920, int videoHeight = 1080)
+ {
+ return new()
+ {
+ Id = id,
+ PtzInfo = ptzInfo,
+ FocusX = focusX,
+ FocusY = focusY,
+ VideoWidth = videoWidth,
+ VideoHeight = videoHeight,
+ };
+ }
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcParams.cs b/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcParams.cs
new file mode 100644
index 0000000..7fd8dc2
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcParams.cs
@@ -0,0 +1,52 @@
+using EC.Helper.CameraSDK;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+///
+/// 标签计算参数
+///
+public class MarkLabelCalcParams
+{
+ ///
+ /// MarkLabel Id
+ ///
+ public long Id { get; set; }
+
+ ///
+ /// Ptz 信息
+ ///
+ public PtzInfo PtzInfo { get; set; }
+
+ ///
+ /// 视频宽度
+ ///
+ public double VideoWidth { get; set; }
+
+ ///
+ /// 视频高度
+ ///
+ public double VideoHeight { get; set; }
+
+ ///
+ /// 画布 left 距离比例
+ ///
+ public double CanvasLeftRatio { get; set; }
+
+ ///
+ /// 画布 top 距离比例
+ ///
+ public double CanvasTopRatio { get; set; }
+
+ public static MarkLabelCalcParams New(long id, PtzInfo ptzInfo, double videoWidth, double videoHeight, double canvasLeftRatio, double canvasTopRatio)
+ {
+ return new()
+ {
+ Id = id,
+ PtzInfo = ptzInfo,
+ VideoWidth = videoWidth,
+ VideoHeight = videoHeight,
+ CanvasLeftRatio = canvasLeftRatio,
+ CanvasTopRatio = canvasTopRatio
+ };
+ }
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcResult.cs b/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcResult.cs
new file mode 100644
index 0000000..473db6b
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Entity/MarkLabelCalcResult.cs
@@ -0,0 +1,48 @@
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+///
+/// 标签计算结果
+///
+public class MarkLabelCalcResult
+{
+ ///
+ /// MarkLabel Id
+ ///
+ public long Id { get; set; }
+
+ ///
+ /// true 显示(在当前视频画面里面)
+ /// false 不显示(不在当前视频画面里面)
+ ///
+ public bool InFlag { get; set; }
+
+ ///
+ /// 画布 left 距离比例
+ ///
+ public double CanvasLeftRatio { get; set; }
+
+ ///
+ /// 画布 top 距离比例
+ ///
+ public double CanvasTopRatio { get; set; }
+
+ public static MarkLabelCalcResult New(long id, bool inFlag)
+ {
+ return new()
+ {
+ Id = id,
+ InFlag = inFlag
+ };
+ }
+
+ public static MarkLabelCalcResult New(long id, bool inFlag, double canvasLeftRatio, double canvasTopRatio)
+ {
+ return new()
+ {
+ Id = id,
+ InFlag = inFlag,
+ CanvasLeftRatio = canvasLeftRatio,
+ CanvasTopRatio = canvasTopRatio
+ };
+ }
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs b/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs
new file mode 100644
index 0000000..9c63f74
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/IMarkSearcherServer.cs
@@ -0,0 +1,119 @@
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+///
+/// 追踪标签服务接口
+///
+public interface IMarkSearcherServer
+{
+ #region Base Method
+
+ ///
+ /// 激活相机进入运算
+ ///
+ ///
+ ///
+ public bool ActivateSearcher(long cameraId);
+
+ ///
+ /// 解除相机进入运算
+ ///
+ ///
+ ///
+ public bool DeactivateSearcher(long cameraId);
+
+ ///
+ /// 是否存在相机进入运算
+ ///
+ ///
+ ///
+ public bool IsExistsSearcher(long cameraId);
+
+ ///
+ /// 获取 Searcher
+ ///
+ ///
+ ///
+ public MarkSearcherBase GetSearcher(long cameraId);
+
+ ///
+ /// 激活标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public bool ActivateMarkLabel(long cameraId, long markLabelId);
+
+ ///
+ /// 解除标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public bool DeactivateMarkLabel(long cameraId, long markLabelId);
+
+ ///
+ /// 是否存在标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public bool IsExistsMarkLabel(long cameraId, long markLabelId);
+
+ #endregion Base Method
+
+ #region Base Method
+
+ ///
+ /// 激活相机进入运算
+ ///
+ ///
+ ///
+ public Task ActivateSearcherAsync(long cameraId);
+
+ ///
+ /// 解除相机进入运算
+ ///
+ ///
+ ///
+ public Task DeactivateSearcherAsync(long cameraId);
+
+ ///
+ /// 是否存在相机进入运算
+ ///
+ ///
+ ///
+ public Task IsExistsSearcherAsync(long cameraId);
+
+ ///
+ /// 获取 Searcher
+ ///
+ ///
+ ///
+ public Task GetSearcherAsync(long cameraId);
+
+ ///
+ /// 激活标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public Task ActivateMarkLabelAsync(long cameraId, long markLabelId);
+
+ ///
+ /// 解除标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public Task DeactivateMarkLabelAsync(long cameraId, long markLabelId);
+
+ ///
+ /// 是否存在标签进入运算
+ ///
+ ///
+ ///
+ ///
+ public Task IsExistsMarkLabelAsync(long cameraId, long markLabelId);
+
+ #endregion Base Method
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs b/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs
new file mode 100644
index 0000000..1b0fa7a
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs
@@ -0,0 +1,268 @@
+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.IsNull) 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
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Seacher/DaHuaMarkSearcher.cs b/Cis.Application/Core/Component/MarkSeacher/Seacher/DaHuaMarkSearcher.cs
new file mode 100644
index 0000000..478cfd2
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Seacher/DaHuaMarkSearcher.cs
@@ -0,0 +1,31 @@
+using System.Drawing;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+public class DaHuaMarkSearcher : MarkSearcherBase
+{
+ public DaHuaMarkSearcher(CameraCalcParams cameraCalcParams) : base(cameraCalcParams)
+ {
+ }
+
+ #region Implement
+
+ protected override double ConvertPanPosToAngle(double panPos)
+ {
+ double ret = (-0.1 * panPos) / 180 * Math.PI;
+ return ret;
+ }
+
+ protected override double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0)
+ {
+ double ret = (0.1 * tiltPos) / 180 * Math.PI;
+ return ret;
+ }
+
+ protected override PointF GetFOfMatrixByZoomPos(double zoomPos)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion Implement
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Seacher/HiKMarkSeacher.cs b/Cis.Application/Core/Component/MarkSeacher/Seacher/HiKMarkSeacher.cs
new file mode 100644
index 0000000..b841719
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Seacher/HiKMarkSeacher.cs
@@ -0,0 +1,73 @@
+using System.Drawing;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+public class HiKMarkSearcher : MarkSearcherBase
+{
+ public HiKMarkSearcher(CameraCalcParams cameraCalcParams) : base(cameraCalcParams)
+ {
+ }
+
+ #region Implement
+
+ protected override double ConvertPanPosToAngle(double panPos)
+ {
+ double ret = 0.1 * HexToDecMa(panPos) / 180 * Math.PI;
+ ret = (ret >= 0) ? ret : (2 * Math.PI + ret);
+ return ret;
+ }
+
+ protected override double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0)
+ {
+ double ndiff;
+ if (tiltPos > tiltMinPos)
+
+ ndiff = HexToDecMa(tiltPos) - HexToDecMa(tiltMinPos);
+ else
+ ndiff = HexToDecMa(tiltPos) + HexToDecMa(13824) - HexToDecMa(tiltMinPos);
+ double ret = 0.1 * ndiff / 180 * Math.PI;
+ return ret;
+ }
+
+ protected override PointF GetFOfMatrixByZoomPos(double zoomPos)
+ {
+ PointF pointF = new()
+ {
+ X = (float)GetFx(zoomPos),
+ Y = (float)GetFy(zoomPos)
+ };
+ return pointF;
+ }
+
+ #endregion Implement
+
+ #region Util
+
+ protected virtual double GetFx(double zoomPos)
+ {
+ CameraCalcParams calcParams = CameraCalcParams;
+ return calcParams.FocusX * GetZoomTag(zoomPos);
+ }
+
+ protected virtual double GetFy(double zoomPos)
+ {
+ CameraCalcParams calcParams = CameraCalcParams;
+ return calcParams.FocusY * GetZoomTag(zoomPos);
+ }
+
+ protected virtual double GetZoomTag(double zoomPos)
+ {
+ double ret = HexToDecMa(zoomPos) * 0.1;
+ ret = (ret - 1) * 0.65 + 1;
+ return ret;
+ }
+
+ protected int HexToDecMa(double wHex)
+ {
+ int wHexInt = wHex.ToInt();
+ int ret = (wHexInt / 4096) * 1000 + ((wHexInt % 4096) / 256) * 100 + ((wHexInt % 256) / 16) * 10 + (wHexInt % 16);
+ return ret;
+ }
+
+ #endregion Util
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs b/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs
new file mode 100644
index 0000000..bd6d8d2
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Seacher/MarkSearcherBase.cs
@@ -0,0 +1,254 @@
+using EC.Helper.CameraSDK;
+using MathNet.Numerics.LinearAlgebra;
+using MathNet.Numerics.LinearAlgebra.Double;
+using System.Collections.Concurrent;
+using System.Drawing;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+public abstract class MarkSearcherBase
+{
+ #region Attr
+
+ ///
+ /// 当前相机计算参数
+ ///
+ protected CameraCalcParams CameraCalcParams { get; set; }
+
+ ///
+ /// 相机当前位置的世界坐标转化为相机坐标矩阵
+ ///
+ protected Matrix World2CameraMatrix { get; set; }
+
+ ///
+ /// {cameraId, MarkLabelCalcParams}
+ ///
+ private ConcurrentDictionary MarkLabelCalcParamsDict { get; set; } = new();
+
+ #endregion Attr
+
+ public MarkSearcherBase(CameraCalcParams cameraCalcParams)
+ {
+ CameraCalcParams = cameraCalcParams;
+ CalcSensor();
+ World2CameraMatrix = ConvertWorldToCamera(cameraCalcParams);
+ }
+
+ #region Calc
+
+ ///
+ /// 判断相机是否进行了转动,转动了则需要重新计算世界坐标到相机坐标的转换矩阵
+ ///
+ ///
+ ///
+ protected bool IsCameraRotate(PtzInfo newInfo)
+ {
+ bool ret = CameraCalcParams.PtzInfo.Pan != newInfo.Pan ||
+ CameraCalcParams.PtzInfo.Tilt != newInfo.Tilt ||
+ CameraCalcParams.PtzInfo.Zoom != newInfo.Zoom;
+ return ret;
+ }
+
+ ///
+ /// 此方法计算在球机zoom值最小的情况下成像矩阵中的 f 本质为获取像元大小
+ /// 尝试方案1:通过计算的方式来获取
+ /// 尝试方案2:通过张正友相机标定的方法来生成成像矩阵中的 f
+ ///
+ protected void CalcSensor()
+ {
+ CameraCalcParams.FocusX /= CameraCalcParams.VideoWidth;
+ CameraCalcParams.FocusY /= CameraCalcParams.VideoHeight;
+ }
+
+ ///
+ /// 获取将世界坐标系中的点转化为相机坐标系中的点的转换矩阵
+ ///
+ ///
+ ///
+ protected Matrix ConvertWorldToCamera(CameraCalcParams cameraCalcParams)
+ {
+ double panAngle = ConvertPanPosToAngle(cameraCalcParams.PtzInfo.Pan);
+ double tiltAngle = ConvertTiltPosToAngle(cameraCalcParams.PtzInfo.Tilt);
+ PointF pointF = GetFOfMatrixByZoomPos(cameraCalcParams.PtzInfo.Zoom);
+ double sinPan = Math.Sin(panAngle);
+ double cosPan = Math.Cos(panAngle);
+ double sinTilt = Math.Sin(tiltAngle);
+ double cosTilt = Math.Cos(tiltAngle);
+
+ Matrix fMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ pointF.X, 0, 0,
+ 0, pointF.Y, 0,
+ 0, 0, 1,
+ });
+
+ Matrix rotateTiltMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ 1, 0, 0,
+ 0, cosTilt, sinTilt,
+ 0, -sinTilt, cosTilt,
+ });
+
+ Matrix rotatePanMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ cosPan, 0, sinPan,
+ 0, 1, 0,
+ -sinPan, 0, cosPan,
+ });
+
+ Matrix resultMatrix = fMatrix.Multiply(rotateTiltMatrix).Multiply(rotatePanMatrix);
+ return resultMatrix;
+ }
+
+ ///
+ /// 获取将相机坐标系中的点转化为世界坐标系中的点的转换矩阵
+ ///
+ ///
+ ///
+ protected Matrix ConvertCameraToWorld(MarkLabelCalcParams labelCalcParams)
+ {
+ double panAngle = ConvertPanPosToAngle(labelCalcParams.PtzInfo.Pan);
+ double tiltAngle = ConvertTiltPosToAngle(labelCalcParams.PtzInfo.Tilt);
+ PointF pointF = GetFOfMatrixByZoomPos(labelCalcParams.PtzInfo.Zoom);
+ double sinPan = Math.Sin(panAngle);
+ double cosPan = Math.Cos(panAngle);
+ double sinTilt = Math.Sin(tiltAngle);
+ double cosTilt = Math.Cos(tiltAngle);
+
+ Matrix rotatePanMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ cosPan, 0, -sinPan,
+ 0, 1, 0,
+ sinPan, 0, cosPan,
+ });
+
+ Matrix rotateTiltMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ 1, 0, 0,
+ 0, cosTilt, -sinTilt,
+ 0, sinTilt, cosTilt,
+ });
+
+ Matrix fMatrix = new DenseMatrix(3, 3, new double[]
+ {
+ (1 / pointF.X), 0, 0,
+ 0, (1 / pointF.Y), 0,
+ 0, 0, 1,
+ });
+
+ Matrix resultMatrix = rotatePanMatrix.Multiply(rotateTiltMatrix).Multiply(fMatrix);
+ return resultMatrix;
+ }
+
+ ///
+ /// 计算标签位置过程
+ ///
+ ///
+ public List Search()
+ {
+ List resultList = new();
+
+ if (World2CameraMatrix == null || MarkLabelCalcParamsDict.IsEmpty)
+ return resultList;
+
+ foreach (MarkLabelCalcParams item in MarkLabelCalcParamsDict.Values)
+ {
+ Matrix labelC2WMatrix = ConvertCameraToWorld(item);
+ Matrix labelPointMatrix = new DenseMatrix(3, 1, new double[]
+ {
+ (item.CanvasLeftRatio-0.5)*item.VideoWidth / CameraCalcParams.VideoWidth,
+ (item.CanvasTopRatio-0.5)*item.VideoHeight / CameraCalcParams.VideoHeight,
+ 1
+ });
+ Matrix lResult = labelC2WMatrix.Multiply(labelPointMatrix);
+ Matrix pResult = World2CameraMatrix.Multiply(lResult);
+
+ double x = pResult[0, 0] / pResult[2, 0] + 0.5;
+ double y = pResult[1, 0] / pResult[2, 0] + 0.5;
+ MarkLabelCalcResult labelCalcResult;
+ if (x > 0.99 || x < 0.01 || y > 0.99 || y < 0.01 || pResult[2, 0] < 0)
+ labelCalcResult = MarkLabelCalcResult.New(item.Id, false);
+ else
+ labelCalcResult = MarkLabelCalcResult.New(item.Id, true, x, y);
+ resultList.Add(labelCalcResult);
+ }
+ return resultList;
+ }
+
+ public async Task> SearchAsync()
+ {
+ return await Task.Run(Search);
+ }
+
+ #endregion Calc
+
+ #region Util
+
+ ///
+ /// 将Pan值转化为角度
+ ///
+ ///
+ protected abstract double ConvertPanPosToAngle(double panPos);
+
+ ///
+ /// 将Tilt转化为角度
+ ///
+ ///
+ protected abstract double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0);
+
+ ///
+ /// 根据当前zoom值获取相机矩阵参数
+ ///
+ ///
+ ///
+ protected abstract PointF GetFOfMatrixByZoomPos(double zoomPos);
+
+ #endregion Util
+
+ #region Base Method
+
+ ///
+ /// 更新相机计算参数
+ ///
+ ///
+ public void UpdateCameraCalcParams(PtzInfo ptzInfo)
+ {
+ if (IsCameraRotate(ptzInfo))
+ {
+ CameraCalcParams.PtzInfo = ptzInfo;
+ World2CameraMatrix = ConvertWorldToCamera(CameraCalcParams);
+ }
+ }
+
+ ///
+ /// 添加标签计算参数
+ ///
+ ///
+ ///
+ public bool AddMarkLabelCalcParams(MarkLabelCalcParams labelCalcParams)
+ {
+ return MarkLabelCalcParamsDict.TryAdd(labelCalcParams.Id, labelCalcParams);
+ }
+
+ ///
+ /// 删除标签计算参数
+ ///
+ ///
+ ///
+ public bool DeleteMarkLabelCalcParams(long markLabelId)
+ {
+ return MarkLabelCalcParamsDict.TryRemove(markLabelId, out _);
+ }
+
+ ///
+ /// 是否存在标签计算参数
+ ///
+ ///
+ ///
+ public bool IsExistsMarkLabelCalcParams(long markLabelId)
+ {
+ return MarkLabelCalcParamsDict.ContainsKey(markLabelId);
+ }
+
+ #endregion Base Method
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Component/MarkSeacher/Seacher/YuShiMarkSeacher.cs b/Cis.Application/Core/Component/MarkSeacher/Seacher/YuShiMarkSeacher.cs
new file mode 100644
index 0000000..2bd253f
--- /dev/null
+++ b/Cis.Application/Core/Component/MarkSeacher/Seacher/YuShiMarkSeacher.cs
@@ -0,0 +1,29 @@
+using System.Drawing;
+
+namespace Cis.Application.Core.Component.MarkSeacher;
+
+public class YuShiMarkSearcher : MarkSearcherBase
+{
+ public YuShiMarkSearcher(CameraCalcParams cameraCalcParams) : base(cameraCalcParams)
+ {
+ }
+
+ #region Implement
+
+ protected override double ConvertPanPosToAngle(double panPos)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override double ConvertTiltPosToAngle(double tiltPos, double tiltMinPos = 0)
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override PointF GetFOfMatrixByZoomPos(double zoomPos)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion Implement
+}
\ No newline at end of file
diff --git a/Cis.Application/Core/Entity/CameraCalcInfo.cs b/Cis.Application/Core/Entity/CameraCalcInfo.cs
deleted file mode 100644
index 11b9191..0000000
--- a/Cis.Application/Core/Entity/CameraCalcInfo.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-namespace Cis.Application.Core;
-
-///
-/// 相机计算信息
-///
-public class CameraCalcInfo
-{
- ///
- /// Camera Id
- ///
- public long Id { get; set; }
-
- ///
- /// Ptz 信息
- ///
- public PtzInfo PtzInfo { get; set; }
-
- ///
- /// 视频的宽度
- ///
- public int VideoWidth { get; set; } = 1920;
-
- ///
- /// 视频的高度
- ///
- public int VideoHeight { get; set; } = 1080;
-
- ///
- /// 最小焦距
- ///
- public double MinFocusX { get; set; } = 0f;
-
- public double MinFocusY { get; set; } = 0f;
-
- public static CameraCalcInfo New(long id, PtzInfo ptzInfo)
- {
- return new()
- {
- Id = id,
- PtzInfo = ptzInfo
- };
- }
-
- public static CameraCalcInfo New(long id, PtzInfo ptzInfo, int videoWidth, int videoHeight)
- {
- return new()
- {
- Id = id,
- PtzInfo = ptzInfo,
- VideoWidth = videoWidth,
- VideoHeight = videoHeight
- };
- }
-}
-
-///
-/// Ptz 信息
-///
-public class PtzInfo
-{
- ///
- /// Pan 坐标
- ///
- public double Pan { get; set; }
-
- ///
- /// Tilt 坐标
- ///
- public double Tilt { get; set; }
-
- ///
- /// Zoom 坐标
- ///
- public double Zoom { get; set; }
-
- public static PtzInfo New(double pan, double tilt, double zoom)
- {
- return new()
- {
- Pan = pan,
- Tilt = tilt,
- Zoom = zoom
- };
- }
-}
-
-///
-/// 标记标签计算信息
-///
-public class MarkLabelCalcInfo
-{
- ///
- /// MarkLabel Id
- ///
- public long Id { get; set; }
-
- ///
- /// Ptz 信息
- ///
- public PtzInfo PtzInfo { get; set; }
-
- ///
- /// 视频宽度
- ///
- public double VideoWidth { get; set; }
-
- ///
- /// 视频高度
- ///
- public double VideoHeight { get; set; }
-
- ///
- /// 画布 left 距离比例
- ///
- public double CanvasLeftRatio { get; set; }
-
- ///
- /// 画布 top 距离比例
- ///
- public double CanvasTopRatio { get; set; }
-
- public static MarkLabelCalcInfo New(long id, PtzInfo ptzInfo, double videoWidth, double videoHeight, double canvasLeftRatio, double canvasTopRatio)
- {
- return new()
- {
- Id = id,
- PtzInfo = ptzInfo,
- VideoWidth = videoWidth,
- VideoHeight = videoHeight,
- CanvasLeftRatio = canvasLeftRatio,
- CanvasTopRatio = canvasTopRatio
- };
- }
-}
-
-///
-/// 标记标签计算结果
-///
-public class MarkLabelCalcResult
-{
- ///
- /// MarkLabel Id
- ///
- public long Id { get; set; }
-
- ///
- /// true 显示(在当前视频画面里面)
- /// false 不显示(不在当前视频画面里面)
- ///
- public bool InFlag { get; set; }
-
- ///
- /// 画布 left 距离比例
- ///
- public double CanvasLeftRatio { get; set; }
-
- ///
- /// 画布 top 距离比例
- ///
- public double CanvasTopRatio { get; set; }
-
- public static MarkLabelCalcResult New(long id, bool inFlag)
- {
- return new()
- {
- Id = id,
- InFlag = inFlag
- };
- }
-
- public static MarkLabelCalcResult New(long id, bool inFlag, double canvasLeftRatio, double canvasTopRatio)
- {
- return new()
- {
- Id = id,
- InFlag = inFlag,
- CanvasLeftRatio = canvasLeftRatio,
- CanvasTopRatio = canvasTopRatio
- };
- }
-}
\ No newline at end of file
diff --git a/Cis.Application/Core/Service/MarkSearchService.cs b/Cis.Application/Core/Service/MarkSearchService.cs
index 47654d9..59cdc34 100644
--- a/Cis.Application/Core/Service/MarkSearchService.cs
+++ b/Cis.Application/Core/Service/MarkSearchService.cs
@@ -1,60 +1,62 @@
-using Cis.Application.Cm;
+using Cis.Application.Core.Component.MarkSeacher;
namespace Cis.Application.Core;
-[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)]
+[ApiDescriptionSettings(CoreInfo.GroupName, Order = CoreInfo.GroupOrder)]
public class MarkSearchService : IDynamicApiController, ITransient
{
- #region Attr
-
- private CameraDataCenter _cameraDataCenter { get; set; }
-
- #endregion Attr
-
- public MarkSearchService(CameraDataCenter cameraDataCenter)
- {
- _cameraDataCenter = cameraDataCenter;
- }
-
- [HttpPost]
- public async Task ActivateSearcher([FromForm] long cameraId)
- {
- return await _cameraDataCenter.ActivateSearcherAsync(cameraId);
- }
-
- [HttpPost]
- public async Task DeActivateSearcher([FromForm] long cameraId)
- {
- return await _cameraDataCenter.DeActivateSearcherAsync(cameraId);
- }
-
- [HttpGet]
- public async Task IsExistSearcher(long cameraId)
- {
- return await _cameraDataCenter.IsExistSearcherAsync(cameraId);
- }
-
- [HttpPost]
- public async Task ActivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId)
- {
- return await _cameraDataCenter.ActivateMarkLabelAsync(cameraId, markLabelId);
- }
-
- [HttpPost]
- public async Task DeactivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId)
- {
- return await _cameraDataCenter.DeactivateMarkLabelAsync(cameraId, markLabelId);
- }
-
- [HttpGet]
- public async Task IsExistMarkLabel(long cameraId,long markLabelId)
- {
- return await _cameraDataCenter.IsExistMarkLabelAysnc(cameraId, markLabelId);
- }
-
- [HttpGet]
- public async Task> GetMarkLabelCalcResultList(long cameraId)
- {
- return await _cameraDataCenter.GetMarkLabelCalcResultListAsync(cameraId);
- }
+ #region Attr
+
+ private readonly CameraDataCenter _cameraDataCenter;
+ private readonly IMarkSearcherServer _markSearcherServer;
+
+ #endregion Attr
+
+ public MarkSearchService(CameraDataCenter cameraDataCenter, IMarkSearcherServer markSearcherServer)
+ {
+ _cameraDataCenter = cameraDataCenter;
+ _markSearcherServer = markSearcherServer;
+ }
+
+ [HttpPost]
+ public async Task ActivateSearcher([FromForm] long cameraId)
+ {
+ return await _markSearcherServer.ActivateSearcherAsync(cameraId);
+ }
+
+ [HttpPost]
+ public async Task DeactivateSearcher([FromForm] long cameraId)
+ {
+ return await _markSearcherServer.DeactivateSearcherAsync(cameraId);
+ }
+
+ [HttpGet]
+ public async Task IsExistsSearcher(long cameraId)
+ {
+ return await _markSearcherServer.IsExistsSearcherAsync(cameraId);
+ }
+
+ [HttpPost]
+ public async Task ActivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId)
+ {
+ return await _markSearcherServer.ActivateMarkLabelAsync(cameraId, markLabelId);
+ }
+
+ [HttpPost]
+ public async Task DeactivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId)
+ {
+ return await _markSearcherServer.DeactivateMarkLabelAsync(cameraId, markLabelId);
+ }
+
+ [HttpGet]
+ public async Task IsExistsMarkLabel(long cameraId, long markLabelId)
+ {
+ return await _markSearcherServer.IsExistsMarkLabelAsync(cameraId, markLabelId);
+ }
+
+ [HttpGet]
+ public async Task> GetMarkLabelCalcResultList(long cameraId)
+ {
+ return await _cameraDataCenter.GetMarkLabelCalcResultListAsync(cameraId);
+ }
}
\ No newline at end of file
diff --git a/Cis.Application/GlobalUsings.cs b/Cis.Application/GlobalUsings.cs
index 9320314..76b15eb 100644
--- a/Cis.Application/GlobalUsings.cs
+++ b/Cis.Application/GlobalUsings.cs
@@ -3,7 +3,6 @@ global using Furion;
global using Furion.ConfigurableOptions;
global using Furion.DependencyInjection;
global using Furion.DynamicApiController;
-global using Furion.FriendlyException;
global using Microsoft.AspNetCore.Mvc;
global using SqlSugar;
global using System.ComponentModel.DataAnnotations;
\ No newline at end of file
diff --git a/Cis.Application/Startup.cs b/Cis.Application/Startup.cs
index bc134be..f9a3256 100644
--- a/Cis.Application/Startup.cs
+++ b/Cis.Application/Startup.cs
@@ -1,4 +1,7 @@
using Cis.Application.Core;
+using Cis.Application.Core.Component.CameraSDK;
+using Cis.Application.Core.Component.MarkSeacher;
+using Cis.Application.Core.Component.PtzServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
@@ -8,24 +11,25 @@ namespace Cis.Application;
[AppStartup(100)]
public class Startup : AppStartup
{
- ///
- /// 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
- ///
- ///
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddConfigurableOptions();
- services.AddConfigurableOptions();
+ ///
+ /// 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
+ ///
+ ///
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddConfigurableOptions();
- services.AddSingleton(new CameraDataCenter());
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton(typeof(CameraDataCenter));
}
- ///
- /// 配置应用请求处理管道
- ///
- ///
- ///
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- }
+ ///
+ /// 配置应用请求处理管道
+ ///
+ ///
+ ///
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ }
}
\ No newline at end of file
diff --git a/Cis.Application/Sys/Common/SysInfo.cs b/Cis.Application/Sys/Common/SysInfo.cs
index f68a522..326f615 100644
--- a/Cis.Application/Sys/Common/SysInfo.cs
+++ b/Cis.Application/Sys/Common/SysInfo.cs
@@ -5,50 +5,50 @@
///
public class SysInfo
{
- #region Api Info
+ #region Api Info
- ///
- /// Api 分组名
- ///
- public const string GroupName = "System";
+ ///
+ /// Api 分组名
+ ///
+ public const string GroupName = "System";
- ///
- /// Api 分组排序
- ///
- public const int GroupOrder = 100;
+ ///
+ /// Api 分组排序
+ ///
+ public const int GroupOrder = 100;
- #endregion Api Info
+ #endregion Api Info
- #region Database Info
+ #region Database Info
- ///
- /// 数据库标识
- ///
- public const string DbName = SqlSugarConst.DefaultConfigId;
+ ///
+ /// 数据库标识
+ ///
+ public const string DbName = SqlSugarConst.DefaultConfigId;
- #endregion Database Info
+ #endregion Database Info
- #region Table Info
+ #region Table Info
- ///
- /// SysDictType 表名
- ///
- public const string SysDictTypeTbName = "sys_dict_type";
+ ///
+ /// SysDictType 表名
+ ///
+ public const string SysDictTypeTbName = "sys_dict_type";
- ///
- /// SysDictType 表描述
- ///
- public const string SysDictTypeTbDesc = "系统字典类型表";
+ ///
+ /// SysDictType 表描述
+ ///
+ public const string SysDictTypeTbDesc = "系统字典类型表";
- ///
- /// SysDataType 表名
- ///
- public const string SysDictDataTbName = "sys_data_data";
+ ///
+ /// SysDataType 表名
+ ///
+ public const string SysDictDataTbName = "sys_data_data";
- ///
- /// SysDataType 表描述
- ///
- public const string SysDictDataTbDesc = "系统字典值表";
+ ///
+ /// SysDataType 表描述
+ ///
+ public const string SysDictDataTbDesc = "系统字典值表";
- #endregion Table Info
+ #endregion Table Info
}
\ No newline at end of file
diff --git a/Cis.Application/Sys/Entity/SysDictType.cs b/Cis.Application/Sys/Entity/SysDictType.cs
index 5c325fc..00e5173 100644
--- a/Cis.Application/Sys/Entity/SysDictType.cs
+++ b/Cis.Application/Sys/Entity/SysDictType.cs
@@ -6,36 +6,36 @@
[SugarTable(SysInfo.SysDictTypeTbName, SysInfo.SysDictTypeTbDesc)]
public class SysDictType : EntityBase
{
- ///
- /// 名称
- ///
- [SugarColumn(ColumnDescription = "名称", Length = 64)]
- [Required, MaxLength(64)]
- public string Name { get; set; }
+ ///
+ /// 名称
+ ///
+ [SugarColumn(ColumnDescription = "名称", Length = 64)]
+ [Required, MaxLength(64)]
+ public string Name { get; set; }
- ///
- /// 编码
- ///
- [SugarColumn(ColumnDescription = "编码", Length = 64)]
- [Required, MaxLength(64)]
- public string Code { get; set; }
+ ///
+ /// 编码
+ ///
+ [SugarColumn(ColumnDescription = "编码", Length = 64)]
+ [Required, MaxLength(64)]
+ public string Code { get; set; }
- ///
- /// 排序
- ///
- [SugarColumn(ColumnDescription = "排序")]
- public int Order { get; set; }
+ ///
+ /// 排序
+ ///
+ [SugarColumn(ColumnDescription = "排序")]
+ public int Order { get; set; }
- ///
- /// 备注
- ///
- [SugarColumn(ColumnDescription = "备注", Length = 256)]
- [MaxLength(256)]
- public string Remark { get; set; }
+ ///
+ /// 备注
+ ///
+ [SugarColumn(ColumnDescription = "备注", Length = 256)]
+ [MaxLength(256)]
+ public string Remark { get; set; }
- ///
- /// 状态
- ///
- [SugarColumn(ColumnDescription = "状态")]
- public StatusEnum Status { get; set; } = StatusEnum.Enable;
+ ///
+ /// 状态
+ ///
+ [SugarColumn(ColumnDescription = "状态")]
+ public StatusEnum Status { get; set; } = StatusEnum.Enable;
}
\ No newline at end of file
diff --git a/Cis.Application/Sys/Service/SysDictDataService.cs b/Cis.Application/Sys/Service/SysDictDataService.cs
index ccf6223..59b9890 100644
--- a/Cis.Application/Sys/Service/SysDictDataService.cs
+++ b/Cis.Application/Sys/Service/SysDictDataService.cs
@@ -8,54 +8,54 @@ namespace Cis.Application.Sys;
[ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.GroupOrder)]
public class SysDictDataService : IDynamicApiController, ITransient
{
- private readonly SqlSugarRepository _sysDictDataRep;
-
- public SysDictDataService(SqlSugarRepository sysDictDataRep)
- {
- _sysDictDataRep = sysDictDataRep;
- }
-
- [HttpPost]
- public async Task Add([FromForm] SysDictData entity)
- {
- return await _sysDictDataRep.InsertAsync(entity);
- }
-
- [HttpPost]
- public async Task Update([FromForm] SysDictData entity)
- {
- return await _sysDictDataRep.UpdateAsync(entity);
- }
-
- [HttpPost]
- public async Task Delete([FromForm] SysDictData entity)
- {
- return await _sysDictDataRep.DeleteAsync(entity);
- }
-
- [HttpGet]
- public async Task