Browse Source

feat: 集成 onvif 模块

master
fajiao 2 years ago
parent
commit
69cf27806e
  1. 9
      Cis.Application/Cb/Common/CbInfo.cs
  2. 12
      Cis.Application/Cb/Service/CbCameraParamsService.cs
  3. 12
      Cis.Application/Cb/Service/CbCameraService.cs
  4. 4
      Cis.Application/Cis.Application.csproj
  5. 464
      Cis.Application/Cis.Application.xml
  6. 9
      Cis.Application/Cm/Common/CmInfo.cs
  7. 14
      Cis.Application/Cm/Service/CmMarkGroupService.cs
  8. 41
      Cis.Application/Cm/Service/CmMarkLabelService.cs
  9. 9
      Cis.Application/Core/Common/CoreInfo.cs
  10. 6
      Cis.Application/Core/Component/CameraSDK/CameraSdkServer.cs
  11. 6
      Cis.Application/Core/Component/CameraSDK/ICameraSdkServer.cs
  12. 6
      Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs
  13. 54
      Cis.Application/Core/Component/Onvif/IOnvifServer.cs
  14. 68
      Cis.Application/Core/Component/Onvif/OnvifServer.cs
  15. 54
      Cis.Application/Core/Service/MarkSearchService.cs
  16. 245
      Cis.Application/Core/Service/OnvifService.cs
  17. 2
      Cis.Application/Startup.cs
  18. 9
      Cis.Application/Sys/Common/SysInfo.cs
  19. 14
      Cis.Application/Sys/Service/SysDictDataService.cs
  20. 14
      Cis.Application/Sys/Service/SysDictTypeService.cs
  21. 1
      Cis.Core/Cache/CacheSetup.cs
  22. 121
      Cis.Core/Cis.Core.xml
  23. 63
      Cis.Core/Common/Entity/ServiceBase.cs
  24. 5
      Cis.sln
  25. 6
      EC.Helper/EC.Helper.csproj
  26. 22861
      EC.Helper/Onvif/Common/DataTypes.cs
  27. 1735
      EC.Helper/Onvif/Device/DataTypes.cs
  28. 2935
      EC.Helper/Onvif/Device/DeviceClient.cs
  29. 723
      EC.Helper/Onvif/Discovery/DiscoveryClient.cs
  30. 143
      EC.Helper/Onvif/Imaging/DataTypes.cs
  31. 185
      EC.Helper/Onvif/Imaging/ImagingClient.cs
  32. 662
      EC.Helper/Onvif/Media/DataTypes.cs
  33. 2125
      EC.Helper/Onvif/Media/MediaClient.cs
  34. 286
      EC.Helper/Onvif/OnvifClient.cs
  35. 114
      EC.Helper/Onvif/OnvifClientFactory.cs
  36. 184
      EC.Helper/Onvif/PTZ/DataTypes.cs
  37. 661
      EC.Helper/Onvif/PTZ/PTZClient.cs
  38. 26
      EC.Helper/Onvif/RemoteDiscovery/Constants.cs
  39. 180
      EC.Helper/Onvif/RemoteDiscovery/Discovery.cs
  40. 30
      EC.Helper/Onvif/RemoteDiscovery/DiscoveryDevice.cs
  41. 20
      EC.Helper/Onvif/RemoteDiscovery/ExtensionMethods.cs
  42. 136
      EC.Helper/Onvif/RemoteDiscovery/OnvifUdpClient.cs
  43. 112
      EC.Helper/Onvif/RemoteDiscovery/XmlProbeReponse.cs
  44. 80
      EC.Helper/Onvif/Security/SoapSecurityHeader.cs
  45. 40
      EC.Helper/Onvif/Security/SoapSecurityHeaderBehavior.cs
  46. 30
      EC.Helper/Onvif/Security/SoapSecurityHeaderInspector.cs

9
Cis.Application/Cb/Common/CbInfo.cs

@ -13,9 +13,14 @@ public class CbInfo
public const string GroupName = "CameraBase"; public const string GroupName = "CameraBase";
/// <summary> /// <summary>
/// Api 分组排序 /// CbCamera Api 分组排序
/// </summary> /// </summary>
public const int GroupOrder = 100; public const int CbCameraGroupOrder = 100;
/// <summary>
/// CbCameraParams Api 分组排序
/// </summary>
public const int CbCameraParamsGroupOrder = 100;
#endregion Api Info #endregion Api Info

12
Cis.Application/Cb/Service/CbCameraParamsService.cs

@ -6,7 +6,7 @@ namespace Cis.Application.Cb;
/// <summary> /// <summary>
/// 相机参数服务 /// 相机参数服务
/// </summary> /// </summary>
[ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.GroupOrder)] [ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.CbCameraParamsGroupOrder)]
public class CbCameraParamsService : ServiceBase<CbCameraParams>, ITransient public class CbCameraParamsService : ServiceBase<CbCameraParams>, ITransient
{ {
public CbCameraParamsService(SqlSugarRepository<CbCameraParams> baseRep) : base(baseRep) public CbCameraParamsService(SqlSugarRepository<CbCameraParams> baseRep) : base(baseRep)
@ -14,12 +14,12 @@ public class CbCameraParamsService : ServiceBase<CbCameraParams>, ITransient
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cameraType,id,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cameraType,id,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<CbCameraParams> GetQ(string queryJson) public override async Task<CbCameraParams> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -43,7 +43,7 @@ public class CbCameraParamsService : ServiceBase<CbCameraParams>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
@ -70,13 +70,13 @@ public class CbCameraParamsService : ServiceBase<CbCameraParams>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<CbCameraParams>> GetPageList(string pagination, string queryJson="") public override async Task<List<CbCameraParams>> GetPageList([Required] string pagination, string queryJson="")
{ {
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();

12
Cis.Application/Cb/Service/CbCameraService.cs

@ -6,7 +6,7 @@ namespace Cis.Application.Cb;
/// <summary> /// <summary>
/// 相机服务 /// 相机服务
/// </summary> /// </summary>
[ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.GroupOrder)] [ApiDescriptionSettings(CbInfo.GroupName, Order = CbInfo.CbCameraGroupOrder)]
public class CbCameraService : ServiceBase<CbCamera>, ITransient public class CbCameraService : ServiceBase<CbCamera>, ITransient
{ {
public CbCameraService(SqlSugarRepository<CbCamera> baseRep) : base(baseRep) public CbCameraService(SqlSugarRepository<CbCamera> baseRep) : base(baseRep)
@ -14,12 +14,12 @@ public class CbCameraService : ServiceBase<CbCamera>, ITransient
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraParamsId,id,isDelete; like:ip,name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraParamsId,id,isDelete; like:ip,name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<CbCamera> GetQ(string queryJson) public override async Task<CbCamera> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -45,7 +45,7 @@ public class CbCameraService : ServiceBase<CbCamera>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
@ -74,13 +74,13 @@ public class CbCameraService : ServiceBase<CbCamera>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<CbCamera>> GetPageList(string pagination, string queryJson = "") public override async Task<List<CbCamera>> GetPageList([Required] string pagination, string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();

4
Cis.Application/Cis.Application.csproj

@ -18,6 +18,10 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MathNet.Numerics" Version="5.0.0" /> <PackageReference Include="MathNet.Numerics" Version="5.0.0" />
</ItemGroup> </ItemGroup>

464
Cis.Application/Cis.Application.xml

@ -14,9 +14,14 @@
Api 分组名 Api 分组名
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Cb.CbInfo.GroupOrder"> <member name="F:Cis.Application.Cb.CbInfo.CbCameraGroupOrder">
<summary> <summary>
Api 分组排序 CbCamera Api 分组排序
</summary>
</member>
<member name="F:Cis.Application.Cb.CbInfo.CbCameraParamsGroupOrder">
<summary>
CbCameraParams Api 分组排序
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Cb.CbInfo.DbName"> <member name="F:Cis.Application.Cb.CbInfo.DbName">
@ -115,26 +120,26 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraParamsService.GetQ(System.String)"> <member name="M:Cis.Application.Cb.CbCameraParamsService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:cameraType,id,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cameraType,id,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraParamsService.GetList(System.String)"> <member name="M:Cis.Application.Cb.CbCameraParamsService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraParamsService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Cb.CbCameraParamsService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cameraType,isDelete; like:name; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Cis.Application.Cb.CbCameraService"> <member name="T:Cis.Application.Cb.CbCameraService">
<summary> <summary>
@ -142,26 +147,26 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraService.GetQ(System.String)"> <member name="M:Cis.Application.Cb.CbCameraService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraParamsId,id,isDelete; like:ip,name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraParamsId,id,isDelete; like:ip,name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraService.GetList(System.String)"> <member name="M:Cis.Application.Cb.CbCameraService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cb.CbCameraService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Cb.CbCameraService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraParamsId,isDelete; like:ip,name; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Cis.Application.Cm.CmInfo"> <member name="T:Cis.Application.Cm.CmInfo">
<summary> <summary>
@ -173,9 +178,14 @@
Api 分组名 Api 分组名
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Cm.CmInfo.GroupOrder"> <member name="F:Cis.Application.Cm.CmInfo.CmMarkGroupGroupOrder">
<summary>
CmMarkGroup Api 分组排序
</summary>
</member>
<member name="F:Cis.Application.Cm.CmInfo.CmMarkLabelGroupOrder">
<summary> <summary>
Api 分组排序 CmMarkLabel Api 分组排序
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Cm.CmInfo.DbName"> <member name="F:Cis.Application.Cm.CmInfo.DbName">
@ -289,53 +299,74 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkGroupService.GetQ(System.String)"> <member name="M:Cis.Application.Cm.CmMarkGroupService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:id,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:id,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkGroupService.GetList(System.String)"> <member name="M:Cis.Application.Cm.CmMarkGroupService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkGroupService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Cm.CmMarkGroupService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Cis.Application.Cm.CmMarkLabelService"> <member name="T:Cis.Application.Cm.CmMarkLabelService">
<summary> <summary>
标签服务 标签服务
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.Add(Cis.Application.Cm.CmMarkLabel)">
<summary>
添加实体类
</summary>
<param name="entity">实体类</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.AddReturnId(Cis.Application.Cm.CmMarkLabel)">
<summary>
添加实体类并返回 id
</summary>
<param name="entity">实体类</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.AddArray(Cis.Application.Cm.CmMarkLabel[])">
<summary>
批量添加实体类
</summary>
<param name="array">实体类数组</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.GetQ(System.String)"> <member name="M:Cis.Application.Cm.CmMarkLabelService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraId,cmMarkGroupId,id,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraId,cmMarkGroupId,id,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.GetList(System.String)"> <member name="M:Cis.Application.Cm.CmMarkLabelService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Cm.CmMarkLabelService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Cm.CmMarkLabelService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="P:Cis.Application.Core.CameraDataCenter.SearchResultListDict"> <member name="P:Cis.Application.Core.CameraDataCenter.SearchResultListDict">
<summary> <summary>
@ -393,9 +424,14 @@
Api 分组名 Api 分组名
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Core.CoreInfo.GroupOrder"> <member name="F:Cis.Application.Core.CoreInfo.MarkSearchGroupOrder">
<summary> <summary>
Api 分组排序 MarkSearch Api 分组排序
</summary>
</member>
<member name="F:Cis.Application.Core.CoreInfo.OnvifGroupOrder">
<summary>
Onvif Api 分组排序
</summary> </summary>
</member> </member>
<member name="P:Cis.Application.Core.CameraDataBase.LoopInterval"> <member name="P:Cis.Application.Core.CameraDataBase.LoopInterval">
@ -423,21 +459,21 @@
相机 sdk 服务接口 相机 sdk 服务接口
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.RegisterCamera(EC.Helper.CameraSDK.CameraInfo)"> <member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.Register(EC.Helper.CameraSDK.CameraInfo)">
<summary> <summary>
注册相机 注册相机
</summary> </summary>
<param name="cameraInfo"></param> <param name="cameraInfo"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.DeleteCamera(System.String)"> <member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.Delete(System.String)">
<summary> <summary>
注销相机 注销相机
</summary> </summary>
<param name="ip"></param> <param name="ip"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.IsExistsCamera(System.String)"> <member name="M:Cis.Application.Core.Component.PtzServer.ICameraSdkServer.IsExists(System.String)">
<summary> <summary>
是否存在相机 是否存在相机
</summary> </summary>
@ -871,6 +907,215 @@
</summary> </summary>
<param name="ptzInfo"></param> <param name="ptzInfo"></param>
</member> </member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.Register(Cis.Application.Cb.CbCamera)">
<summary>
注册 onvifClient
</summary>
<param name="camera"></param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.RegisterAsync(Cis.Application.Cb.CbCamera)">
<summary>
注册 onvifClient(异步)
</summary>
<param name="camera"></param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.Delete(System.Int64)">
<summary>
注销 onvifClient
</summary>
<param name="cameraId"></param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.IsExists(System.Int64)">
<summary>
是否存在 onvifClient
</summary>
<param name="cameraId"></param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.Get(System.Int64)">
<summary>
获取 onvifClient
</summary>
<param name="cameraId"></param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.Component.Onvif.IOnvifServer.TryGet(System.Int64,EC.Helper.Onvif.OnvifClient@)">
<summary>
获取 onvifClient
</summary>
<param name="cameraId"></param>
<param name="client"></param>
<returns></returns>
</member>
<member name="P:Cis.Application.Core.Component.Onvif.OnvifServer.OnvifClientDict">
<summary>
{cameraId, OnvifClient}
</summary>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.ActivateSearcher(System.Int64)">
<summary>
激活 Searcher
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.DeactivateSearcher(System.Int64)">
<summary>
解除 Searcher
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.IsExistsSearcher(System.Int64)">
<summary>
是否存在 Searcher
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.ActivateMarkLabel(System.Int64,System.Int64)">
<summary>
激活标签
</summary>
<param name="cameraId">cbCameraId</param>
<param name="markLabelId">cmMarkLabelId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.DeactivateMarkLabel(System.Int64,System.Int64)">
<summary>
解除标签
</summary>
<param name="cameraId">cbCameraId</param>
<param name="markLabelId">cmMarkLabelId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.IsExistsMarkLabel(System.Int64,System.Int64)">
<summary>
是否存在标签
</summary>
<param name="cameraId">cbCameraId</param>
<param name="markLabelId">cmMarkLabelId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.MarkSearchService.GetMarkLabelCalcResultList(System.Int64)">
<summary>
获取标签计算结果列表
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.Register(System.Int64)">
<summary>
注册 onvifClient
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.Delete(System.Int64)">
<summary>
注销 onvifClient
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.IsExists(System.Int64)">
<summary>
是否存在 onvifClient
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.FocusAbsoluteMove(System.Int64,System.Single)">
<summary>
变焦绝对移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="position">变焦移动绝对点:[-1,1]</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.FocusRelativeMove(System.Int64,System.Single)">
<summary>
变焦相对移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="distance">变焦移动相对点:[-1,1]</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.FocusContinuousMove(System.Int64,System.Single)">
<summary>
变焦持续移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="speed">持续移动方向:[-1,1]</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.FocusStopMove(System.Int64)">
<summary>
停止变焦
</summary>
<param name="cameraId">cbCameraId</param>
</member>
<member name="M:Cis.Application.Core.OnvifService.GetStreamUrl(System.Int64)">
<summary>
获取播放视频 URL
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.GetSnapshotUrl(System.Int64)">
<summary>
获取抓图 URL
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.GetSnapshot(System.Int64)">
<summary>
获取抓图 Base64
</summary>
<param name="cameraId">cbCameraId</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.AbsoluteMove(System.Int64,System.Single,System.Single,System.Single,System.Single)">
<summary>
绝对移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="pan">水平方向移动绝对点:[-1,1]</param>
<param name="tilt">垂直方向移动绝对点:[-1,1]</param>
<param name="zoom">变倍绝对点:[-1,1]</param>
<param name="atomDist">可以理解为移动速度:[0,1],默认 0.1</param>
<returns></returns>
</member>
<member name="M:Cis.Application.Core.OnvifService.RelativeMove(System.Int64,System.Single,System.Single,System.Single,System.Single)">
<summary>
相对移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="pan">水平方向移动相对点:[-1,1]</param>
<param name="tilt">垂直方向移动相对点:[-1,1]</param>
<param name="zoom">变倍相对点:[-1,1]</param>
<param name="atomSpeed">移动速度:[0,1],默认 0.1</param>
</member>
<member name="M:Cis.Application.Core.OnvifService.ContinuousMove(System.Int64,System.Single,System.Single,System.Single,System.String)">
<summary>
持续移动
</summary>
<param name="cameraId">cbCameraId</param>
<param name="pan">水平方向移动方向:[-1,1]</param>
<param name="tilt">垂直方向移动方向:[-1,1]</param>
<param name="zoom">变倍移动方向:[-1,1]</param>
<param name="timeout">超时时间,ms</param>
</member>
<member name="M:Cis.Application.Core.OnvifService.StopMove(System.Int64)">
<summary>
停止移动
</summary>
<param name="cameraId">cbCameraId</param>
</member>
<member name="M:Cis.Application.Startup.ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection)"> <member name="M:Cis.Application.Startup.ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
<summary> <summary>
配置应用所需服务,在该方法中可以添加应用所需要的功能或服务 配置应用所需服务,在该方法中可以添加应用所需要的功能或服务
@ -894,9 +1139,14 @@
Api 分组名 Api 分组名
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Sys.SysInfo.GroupOrder"> <member name="F:Cis.Application.Sys.SysInfo.SysDictTypeGroupOrder">
<summary>
SysDictType Api 分组排序
</summary>
</member>
<member name="F:Cis.Application.Sys.SysInfo.SysDictDataGroupOrder">
<summary> <summary>
Api 分组排序 SysDictData Api 分组排序
</summary> </summary>
</member> </member>
<member name="F:Cis.Application.Sys.SysInfo.DbName"> <member name="F:Cis.Application.Sys.SysInfo.DbName">
@ -995,26 +1245,26 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictDataService.GetQ(System.String)"> <member name="M:Cis.Application.Sys.SysDictDataService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:sysDictTypeId,code,id,isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:sysDictTypeId,code,id,isDelete; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictDataService.GetList(System.String)"> <member name="M:Cis.Application.Sys.SysDictDataService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictDataService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Sys.SysDictDataService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Cis.Application.Sys.SysDictTypeService"> <member name="T:Cis.Application.Sys.SysDictTypeService">
<summary> <summary>
@ -1022,26 +1272,26 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictTypeService.GetQ(System.String)"> <member name="M:Cis.Application.Sys.SysDictTypeService.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:code,id,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:code,id,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictTypeService.GetList(System.String)"> <member name="M:Cis.Application.Sys.SysDictTypeService.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Application.Sys.SysDictTypeService.GetPageList(System.String,System.String)"> <member name="M:Cis.Application.Sys.SysDictTypeService.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param> <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
</members> </members>
</doc> </doc>

9
Cis.Application/Cm/Common/CmInfo.cs

@ -13,9 +13,14 @@ public class CmInfo
public const string GroupName = "CameraMark"; public const string GroupName = "CameraMark";
/// <summary> /// <summary>
/// Api 分组排序 /// CmMarkGroup Api 分组排序
/// </summary> /// </summary>
public const int GroupOrder = 100; public const int CmMarkGroupGroupOrder = 100;
/// <summary>
/// CmMarkLabel Api 分组排序
/// </summary>
public const int CmMarkLabelGroupOrder = 100;
#endregion Api Info #endregion Api Info

14
Cis.Application/Cm/Service/CmMarkGroupService.cs

@ -6,7 +6,7 @@ namespace Cis.Application.Cm;
/// <summary> /// <summary>
/// 标记分组服务 /// 标记分组服务
/// </summary> /// </summary>
[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)] [ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.CmMarkGroupGroupOrder)]
public class CmMarkGroupService : ServiceBase<CmMarkGroup>, ITransient public class CmMarkGroupService : ServiceBase<CmMarkGroup>, ITransient
{ {
public CmMarkGroupService(SqlSugarRepository<CmMarkGroup> baseRep) : base(baseRep) public CmMarkGroupService(SqlSugarRepository<CmMarkGroup> baseRep) : base(baseRep)
@ -14,12 +14,12 @@ public class CmMarkGroupService : ServiceBase<CmMarkGroup>, ITransient
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:id,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:id,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<CmMarkGroup> GetQ(string queryJson) public override async Task<CmMarkGroup> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -39,12 +39,12 @@ public class CmMarkGroupService : ServiceBase<CmMarkGroup>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<CmMarkGroup>> GetList(string queryJson) public override async Task<List<CmMarkGroup>> GetList(string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -66,13 +66,13 @@ public class CmMarkGroupService : ServiceBase<CmMarkGroup>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:isDelete; like:name; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<CmMarkGroup>> GetPageList(string pagination, string queryJson="") public override async Task<List<CmMarkGroup>> GetPageList([Required] string pagination, string queryJson="")
{ {
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();

41
Cis.Application/Cm/Service/CmMarkLabelService.cs

@ -8,7 +8,7 @@ namespace Cis.Application.Cm;
/// <summary> /// <summary>
/// 标签服务 /// 标签服务
/// </summary> /// </summary>
[ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.GroupOrder)] [ApiDescriptionSettings(CmInfo.GroupName, Order = CmInfo.CmMarkLabelGroupOrder)]
public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
{ {
private ICameraSdkServer _cameraSdk { get; set; } private ICameraSdkServer _cameraSdk { get; set; }
@ -18,6 +18,11 @@ public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
_cameraSdk = cameraSdk; _cameraSdk = cameraSdk;
} }
/// <summary>
/// 添加实体类
/// </summary>
/// <param name="entity">实体类</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public override async Task<bool> Add([FromForm] CmMarkLabel entity) public override async Task<bool> Add([FromForm] CmMarkLabel entity)
{ {
@ -29,6 +34,11 @@ public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
return await _baseRep.InsertAsync(entity); return await _baseRep.InsertAsync(entity);
} }
/// <summary>
/// 添加实体类并返回 id
/// </summary>
/// <param name="entity">实体类</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public override async Task<long> AddReturnId([FromForm] CmMarkLabel entity) public override async Task<long> AddReturnId([FromForm] CmMarkLabel entity)
{ {
@ -42,12 +52,31 @@ public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量添加实体类
/// </summary>
/// <param name="array">实体类数组</param>
/// <returns></returns>
[HttpPost]
public override async Task<bool> AddArray([Required][FromForm] CmMarkLabel[] array)
{
foreach (CmMarkLabel item in array)
{
bool ret = _cameraSdk.TryGetPtzInfoById(item.CbCameraId.ToString(), out PtzInfo ptzInfo);
if (!ret) return false;
item.PanPosition = ptzInfo.Pan;
item.TiltPosition = ptzInfo.Tilt;
item.ZoomPosition = ptzInfo.Zoom;
}
return await _baseRep.InsertRangeAsync(array);
}
/// <summary>
/// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,id,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,id,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<CmMarkLabel> GetQ(string queryJson) public override async Task<CmMarkLabel> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -71,7 +100,7 @@ public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
@ -102,13 +131,13 @@ public class CmMarkLabelService : ServiceBase<CmMarkLabel>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:cbCameraId,cmMarkGroupId,isDelete; like:name; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<CmMarkLabel>> GetPageList(string pagination, string queryJson="") public override async Task<List<CmMarkLabel>> GetPageList([Required] string pagination, string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();

9
Cis.Application/Core/Common/CoreInfo.cs

@ -10,9 +10,14 @@ public class CoreInfo
public const string GroupName = "Core"; public const string GroupName = "Core";
/// <summary> /// <summary>
/// Api 分组排序 /// MarkSearch Api 分组排序
/// </summary> /// </summary>
public const int GroupOrder = 100; public const int MarkSearchGroupOrder = 100;
/// <summary>
/// Onvif Api 分组排序
/// </summary>
public const int OnvifGroupOrder = 100;
#endregion Api Info #endregion Api Info
} }

6
Cis.Application/Core/Component/CameraSDK/CameraSdkServer.cs

@ -28,7 +28,7 @@ public class CameraSdkServer : ICameraSdkServer, ISingleton
#region Base Method #region Base Method
public bool RegisterCamera(CameraInfo cameraInfo) public bool Register(CameraInfo cameraInfo)
{ {
bool ret = CameraSdkDict.ContainsKey(cameraInfo.Ip); bool ret = CameraSdkDict.ContainsKey(cameraInfo.Ip);
if (ret) return false; if (ret) return false;
@ -40,12 +40,12 @@ public class CameraSdkServer : ICameraSdkServer, ISingleton
return ret; return ret;
} }
public bool DeleteCamera(string ip) public bool Delete(string ip)
{ {
return CameraSdkDict.TryRemove(ip, out _); return CameraSdkDict.TryRemove(ip, out _);
} }
public bool IsExistsCamera(string ip) public bool IsExists(string ip)
{ {
return CameraSdkDict.ContainsKey(ip); return CameraSdkDict.ContainsKey(ip);
} }

6
Cis.Application/Core/Component/CameraSDK/ICameraSdkServer.cs

@ -14,21 +14,21 @@ public interface ICameraSdkServer
/// </summary> /// </summary>
/// <param name="cameraInfo"></param> /// <param name="cameraInfo"></param>
/// <returns></returns> /// <returns></returns>
public bool RegisterCamera(CameraInfo cameraInfo); public bool Register(CameraInfo cameraInfo);
/// <summary> /// <summary>
/// 注销相机 /// 注销相机
/// </summary> /// </summary>
/// <param name="ip"></param> /// <param name="ip"></param>
/// <returns></returns> /// <returns></returns>
public bool DeleteCamera(string ip); public bool Delete(string ip);
/// <summary> /// <summary>
/// 是否存在相机 /// 是否存在相机
/// </summary> /// </summary>
/// <param name="ip"></param> /// <param name="ip"></param>
/// <returns></returns> /// <returns></returns>
public bool IsExistsCamera(string ip); public bool IsExists(string ip);
#endregion Base Method #endregion Base Method

6
Cis.Application/Core/Component/MarkSeacher/MarkSearcherServer.cs

@ -84,15 +84,15 @@ public class MarkSearcherServer : IMarkSearcherServer, ISingleton
if (cbCameraParams == null) return false; if (cbCameraParams == null) return false;
// 注册并获取 ptz // 注册并获取 ptz
ret = _cameraSdkServer.IsExistsCamera(cbCamera.Ip); ret = _cameraSdkServer.IsExists(cbCamera.Ip);
if (!ret) if (!ret)
{ {
CameraInfo cameraInfo = CameraInfo.New(cbCameraParams.CameraType, cbCamera.Ip, cbCamera.UserName, cbCamera.Password); CameraInfo cameraInfo = CameraInfo.New(cbCameraParams.CameraType, cbCamera.Ip, cbCamera.UserName, cbCamera.Password);
ret = _cameraSdkServer.RegisterCamera(cameraInfo); ret = _cameraSdkServer.Register(cameraInfo);
if (!ret) if (!ret)
{ {
// double check // double check
ret = _cameraSdkServer.IsExistsCamera(cbCamera.Ip); ret = _cameraSdkServer.IsExists(cbCamera.Ip);
if (!ret) return false; if (!ret) return false;
} }
} }

54
Cis.Application/Core/Component/Onvif/IOnvifServer.cs

@ -0,0 +1,54 @@
using Cis.Application.Cb;
using EC.Helper.Onvif;
namespace Cis.Application.Core.Component.Onvif;
public interface IOnvifServer
{
#region Base Method
/// <summary>
/// 注册 onvifClient
/// </summary>
/// <param name="camera"></param>
/// <returns></returns>
public bool Register(CbCamera camera);
/// <summary>
/// 注册 onvifClient(异步)
/// </summary>
/// <param name="camera"></param>
/// <returns></returns>
public Task<bool> RegisterAsync(CbCamera camera);
/// <summary>
/// 注销 onvifClient
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool Delete(long cameraId);
/// <summary>
/// 是否存在 onvifClient
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public bool IsExists(long cameraId);
/// <summary>
/// 获取 onvifClient
/// </summary>
/// <param name="cameraId"></param>
/// <returns></returns>
public OnvifClient Get(long cameraId);
/// <summary>
/// 获取 onvifClient
/// </summary>
/// <param name="cameraId"></param>
/// <param name="client"></param>
/// <returns></returns>
public bool TryGet(long cameraId, out OnvifClient client);
#endregion Base Method
}

68
Cis.Application/Core/Component/Onvif/OnvifServer.cs

@ -0,0 +1,68 @@
using Cis.Application.Cb;
using EC.Helper.Onvif;
using System.Collections.Concurrent;
namespace Cis.Application.Core.Component.Onvif;
public class OnvifServer : IOnvifServer, ISingleton
{
#region Attr
/// <summary>
/// {cameraId, OnvifClient}
/// </summary>
private ConcurrentDictionary<long, OnvifClient> OnvifClientDict { get; set; } = new();
#endregion Attr
public OnvifServer()
{
}
#region Base Method
public bool Register(CbCamera camera)
{
bool ret = OnvifClientDict.ContainsKey(camera.Id);
if (ret) return false;
OnvifClient client = new(camera.Ip, camera.UserName, camera.Password);
ret = client.Init().Result;
if (!ret) return false;
ret = OnvifClientDict.TryAdd(camera.Id, client);
return ret;
}
public async Task<bool> RegisterAsync(CbCamera camera)
{
bool ret = OnvifClientDict.ContainsKey(camera.Id);
if (ret) return false;
OnvifClient client = new(camera.Ip, camera.UserName, camera.Password);
ret = await client.Init();
if(!ret) return false;
ret = OnvifClientDict.TryAdd(camera.Id, client);
return ret;
}
public bool Delete(long cameraId)
{
return OnvifClientDict.TryRemove(cameraId, out _);
}
public bool IsExists(long cameraId)
{
return OnvifClientDict.ContainsKey(cameraId);
}
public OnvifClient Get(long cameraId)
{
OnvifClientDict.TryGetValue(cameraId, out OnvifClient client);
return client;
}
public bool TryGet(long cameraId, out OnvifClient client)
{
return OnvifClientDict.TryGetValue(cameraId, out client);
}
#endregion Base Method
}

54
Cis.Application/Core/Service/MarkSearchService.cs

@ -2,7 +2,7 @@
namespace Cis.Application.Core; namespace Cis.Application.Core;
[ApiDescriptionSettings(CoreInfo.GroupName, Order = CoreInfo.GroupOrder)] [ApiDescriptionSettings(CoreInfo.GroupName, Order = CoreInfo.MarkSearchGroupOrder)]
public class MarkSearchService : IDynamicApiController, ITransient public class MarkSearchService : IDynamicApiController, ITransient
{ {
#region Attr #region Attr
@ -16,44 +16,82 @@ public class MarkSearchService : IDynamicApiController, ITransient
_markSearcherServer = markSearcherServer; _markSearcherServer = markSearcherServer;
} }
/// <summary>
/// 激活 Searcher
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public async Task<bool> ActivateSearcher([FromForm] long cameraId) public async Task<bool> ActivateSearcher([Required][FromForm] long cameraId)
{ {
return await _markSearcherServer.ActivateSearcherAsync(cameraId); return await _markSearcherServer.ActivateSearcherAsync(cameraId);
} }
/// <summary>
/// 解除 Searcher
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public async Task<bool> DeactivateSearcher([FromForm] long cameraId) public async Task<bool> DeactivateSearcher([Required][FromForm] long cameraId)
{ {
return await _markSearcherServer.DeactivateSearcherAsync(cameraId); return await _markSearcherServer.DeactivateSearcherAsync(cameraId);
} }
/// <summary>
/// 是否存在 Searcher
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet] [HttpGet]
public async Task<bool> IsExistsSearcher(long cameraId) public async Task<bool> IsExistsSearcher([Required] long cameraId)
{ {
return await _markSearcherServer.IsExistsSearcherAsync(cameraId); return await _markSearcherServer.IsExistsSearcherAsync(cameraId);
} }
/// <summary>
/// 激活标签
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="markLabelId">cmMarkLabelId</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public async Task<bool> ActivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId) public async Task<bool> ActivateMarkLabel([Required][FromForm] long cameraId, [Required][FromForm] long markLabelId)
{ {
return await _markSearcherServer.ActivateMarkLabelAsync(cameraId, markLabelId); return await _markSearcherServer.ActivateMarkLabelAsync(cameraId, markLabelId);
} }
/// <summary>
/// 解除标签
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="markLabelId">cmMarkLabelId</param>
/// <returns></returns>
[HttpPost] [HttpPost]
public async Task<bool> DeactivateMarkLabel([FromForm] long cameraId, [FromForm] long markLabelId) public async Task<bool> DeactivateMarkLabel([Required][FromForm] long cameraId, [Required][FromForm] long markLabelId)
{ {
return await _markSearcherServer.DeactivateMarkLabelAsync(cameraId, markLabelId); return await _markSearcherServer.DeactivateMarkLabelAsync(cameraId, markLabelId);
} }
/// <summary>
/// 是否存在标签
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="markLabelId">cmMarkLabelId</param>
/// <returns></returns>
[HttpGet] [HttpGet]
public async Task<bool> IsExistsMarkLabel(long cameraId, long markLabelId) public async Task<bool> IsExistsMarkLabel([Required] long cameraId, [Required] long markLabelId)
{ {
return await _markSearcherServer.IsExistsMarkLabelAsync(cameraId, markLabelId); return await _markSearcherServer.IsExistsMarkLabelAsync(cameraId, markLabelId);
} }
/// <summary>
/// 获取标签计算结果列表
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet] [HttpGet]
public async Task<List<MarkLabelCalcResult>> GetMarkLabelCalcResultList(long cameraId) public async Task<List<MarkLabelCalcResult>> GetMarkLabelCalcResultList([Required] long cameraId)
{ {
return await _markSearcherServer.GetMarkLabelCalcResultListAsync(cameraId); return await _markSearcherServer.GetMarkLabelCalcResultListAsync(cameraId);
} }

245
Cis.Application/Core/Service/OnvifService.cs

@ -0,0 +1,245 @@
using Cis.Application.Cb;
using Cis.Application.Core.Component.Onvif;
using EC.Helper.Onvif;
namespace Cis.Application.Core;
[ApiDescriptionSettings(CoreInfo.GroupName, Order = CoreInfo.OnvifGroupOrder)]
public class OnvifService : IDynamicApiController, ITransient
{
#region
private readonly SqlSugarRepository<CbCamera> _cbCameraRep;
private readonly OnvifServer _onvifServer;
#endregion
public OnvifService(SqlSugarRepository<CbCamera> cbCameraRep, OnvifServer onvifServer)
{
_cbCameraRep = cbCameraRep;
_onvifServer = onvifServer;
}
#region Base Method
/// <summary>
/// 注册 onvifClient
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpPost]
public async Task<bool> Register([Required][FromForm] long cameraId)
{
CbCamera camera = await _cbCameraRep.GetByIdAsync(cameraId);
if (camera == null) return false;
bool ret = _onvifServer.IsExists(camera.Id);
if (ret) return false;
ret = await _onvifServer.RegisterAsync(camera);
return ret;
}
/// <summary>
/// 注销 onvifClient
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpPost]
public bool Delete([Required][FromForm] long cameraId)
{
return _onvifServer.Delete(cameraId);
}
/// <summary>
/// 是否存在 onvifClient
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet]
public bool IsExists([Required] long cameraId)
{
return _onvifServer.IsExists(cameraId);
}
#endregion Base Method
#region Imaging Method
/// <summary>
/// 变焦绝对移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="position">变焦移动绝对点:[-1,1]</param>
/// <returns></returns>
[HttpPost]
public async Task<bool> FocusAbsoluteMove([Required][FromForm] long cameraId, [Required][FromForm] float position)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.FocusAbsoluteMove(position);
return true;
}
/// <summary>
/// 变焦相对移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="distance">变焦移动相对点:[-1,1]</param>
/// <returns></returns>
[HttpPost]
public async Task<bool> FocusRelativeMove([Required][FromForm] long cameraId, [Required][FromForm] float distance)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.FocusRelativeMove(distance);
return true;
}
/// <summary>
/// 变焦持续移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="speed">持续移动方向:[-1,1]</param>
/// <returns></returns>
[HttpPost]
public async Task<bool> FocusContinuousMove([Required][FromForm] long cameraId, [Required][FromForm] float speed)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.FocusContinuousMove(speed);
return true;
}
/// <summary>
/// 停止变焦
/// </summary>
/// <param name="cameraId">cbCameraId</param>
[HttpPost]
public async Task<bool> FocusStopMove([Required][FromForm] long cameraId)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.FocusStopMove();
return true;
}
#endregion Imaging Method
#region Media Method
/// <summary>
/// 获取播放视频 URL
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet]
public async Task<string> GetStreamUrl([Required] long cameraId)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return string.Empty;
string url = await client.GetStreamUrl();
return url;
}
/// <summary>
/// 获取抓图 URL
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet]
public async Task<string> GetSnapshotUrl([Required] long cameraId)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return string.Empty;
string url = await client.GetSnapshotUrl();
return url;
}
/// <summary>
/// 获取抓图 Base64
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <returns></returns>
[HttpGet]
public async Task<string> GetSnapshot([Required] long cameraId)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return string.Empty;
string snapshotBase64 = await client.GetSnapshot();
return snapshotBase64;
}
#endregion Media Method
#region Ptz Method
/// <summary>
/// 绝对移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="pan">水平方向移动绝对点:[-1,1]</param>
/// <param name="tilt">垂直方向移动绝对点:[-1,1]</param>
/// <param name="zoom">变倍绝对点:[-1,1]</param>
/// <param name="atomDist">可以理解为移动速度:[0,1],默认 0.1</param>
/// <returns></returns>
[HttpPost]
public async Task<bool> AbsoluteMove([Required][FromForm] long cameraId,
[Required][FromForm] float pan, [Required][FromForm] float tilt, [Required][FromForm] float zoom, [FromForm] float atomDist = 0.1f)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.AbsoluteMove(pan, tilt, zoom, atomDist);
return true;
}
/// <summary>
/// 相对移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="pan">水平方向移动相对点:[-1,1]</param>
/// <param name="tilt">垂直方向移动相对点:[-1,1]</param>
/// <param name="zoom">变倍相对点:[-1,1]</param>
/// <param name="atomSpeed">移动速度:[0,1],默认 0.1</param>
[HttpPost]
public async Task<bool> RelativeMove([Required][FromForm] long cameraId,
[Required][FromForm] float pan, [Required][FromForm] float tilt, [Required][FromForm] float zoom, [FromForm] float atomSpeed = 0.1f)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.RelativeMove(pan, tilt, zoom, atomSpeed);
return true;
}
/// <summary>
/// 持续移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
/// <param name="pan">水平方向移动方向:[-1,1]</param>
/// <param name="tilt">垂直方向移动方向:[-1,1]</param>
/// <param name="zoom">变倍移动方向:[-1,1]</param>
/// <param name="timeout">超时时间,ms</param>
[HttpPost]
public async Task<bool> ContinuousMove([Required][FromForm] long cameraId,
[Required][FromForm] float pan, [Required][FromForm] float tilt, [Required][FromForm] float zoom, [FromForm] string timeout = "")
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.ContinuousMove(pan, tilt, zoom, timeout);
return true;
}
/// <summary>
/// 停止移动
/// </summary>
/// <param name="cameraId">cbCameraId</param>
[HttpPost]
public async Task<bool> StopMove([Required][FromForm] long cameraId)
{
bool ret = _onvifServer.TryGet(cameraId, out OnvifClient client);
if (!ret) return false;
await client.StopMove();
return true;
}
#endregion Ptz Method
}

2
Cis.Application/Startup.cs

@ -1,6 +1,7 @@
using Cis.Application.Core; using Cis.Application.Core;
using Cis.Application.Core.Component.CameraSDK; using Cis.Application.Core.Component.CameraSDK;
using Cis.Application.Core.Component.MarkSeacher; using Cis.Application.Core.Component.MarkSeacher;
using Cis.Application.Core.Component.Onvif;
using Cis.Application.Core.Component.PtzServer; using Cis.Application.Core.Component.PtzServer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
@ -20,6 +21,7 @@ public class Startup : AppStartup
services.AddConfigurableOptions<CameraDataOptions>(); services.AddConfigurableOptions<CameraDataOptions>();
services.AddSingleton<ICameraSdkServer, CameraSdkServer>(); services.AddSingleton<ICameraSdkServer, CameraSdkServer>();
services.AddSingleton<IOnvifServer, OnvifServer>();
services.AddSingleton<IMarkSearcherServer, MarkSearcherServer>(); services.AddSingleton<IMarkSearcherServer, MarkSearcherServer>();
services.AddSingleton(typeof(CameraDataCenter)); services.AddSingleton(typeof(CameraDataCenter));
} }

9
Cis.Application/Sys/Common/SysInfo.cs

@ -13,9 +13,14 @@ public class SysInfo
public const string GroupName = "System"; public const string GroupName = "System";
/// <summary> /// <summary>
/// Api 分组排序 /// SysDictType Api 分组排序
/// </summary> /// </summary>
public const int GroupOrder = 100; public const int SysDictTypeGroupOrder = 100;
/// <summary>
/// SysDictData Api 分组排序
/// </summary>
public const int SysDictDataGroupOrder = 100;
#endregion Api Info #endregion Api Info

14
Cis.Application/Sys/Service/SysDictDataService.cs

@ -6,7 +6,7 @@ namespace Cis.Application.Sys;
/// <summary> /// <summary>
/// 系统字典值服务 /// 系统字典值服务
/// </summary> /// </summary>
[ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.GroupOrder)] [ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.SysDictDataGroupOrder)]
public class SysDictDataService : ServiceBase<SysDictData>, ITransient public class SysDictDataService : ServiceBase<SysDictData>, ITransient
{ {
public SysDictDataService(SqlSugarRepository<SysDictData> baseRep) : base(baseRep) public SysDictDataService(SqlSugarRepository<SysDictData> baseRep) : base(baseRep)
@ -14,12 +14,12 @@ public class SysDictDataService : ServiceBase<SysDictData>, ITransient
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:sysDictTypeId,code,id,isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:sysDictTypeId,code,id,isDelete; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<SysDictData> GetQ(string queryJson) public override async Task<SysDictData> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -43,12 +43,12 @@ public class SysDictDataService : ServiceBase<SysDictData>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<SysDictData>> GetList(string queryJson) public override async Task<List<SysDictData>> GetList(string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -70,13 +70,13 @@ public class SysDictDataService : ServiceBase<SysDictData>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:sysDictTypeId,code,isDelete; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<SysDictData>> GetPageList(string pagination, string queryJson = "") public override async Task<List<SysDictData>> GetPageList([Required] string pagination, string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();

14
Cis.Application/Sys/Service/SysDictTypeService.cs

@ -6,7 +6,7 @@ namespace Cis.Application.Sys;
/// <summary> /// <summary>
/// 系统字典类型服务 /// 系统字典类型服务
/// </summary> /// </summary>
[ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.GroupOrder)] [ApiDescriptionSettings(SysInfo.GroupName, Order = SysInfo.SysDictTypeGroupOrder)]
public class SysDictTypeService : ServiceBase<SysDictType>, ITransient public class SysDictTypeService : ServiceBase<SysDictType>, ITransient
{ {
public SysDictTypeService(SqlSugarRepository<SysDictType> baseRep) : base(baseRep) public SysDictTypeService(SqlSugarRepository<SysDictType> baseRep) : base(baseRep)
@ -14,12 +14,12 @@ public class SysDictTypeService : ServiceBase<SysDictType>, ITransient
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:code,id,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:code,id,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<SysDictType> GetQ(string queryJson) public override async Task<SysDictType> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -43,12 +43,12 @@ public class SysDictTypeService : ServiceBase<SysDictType>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<SysDictType>> GetList(string queryJson) public override async Task<List<SysDictType>> GetList(string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -70,13 +70,13 @@ public class SysDictTypeService : ServiceBase<SysDictType>, ITransient
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param> /// <param name="queryJson">equal:code,isDelete; like:name; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public override async Task<List<SysDictType>> GetPageList(string pagination, string queryJson="") public override async Task<List<SysDictType>> GetPageList([Required] string pagination, string queryJson="")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();

1
Cis.Core/Cache/CacheSetup.cs

@ -14,6 +14,7 @@ public static class CacheSetup
{ {
var redisOptions = App.GetOptions<RedisOptions>(); var redisOptions = App.GetOptions<RedisOptions>();
RedisClient cache = new(redisOptions.ConnectionString); RedisClient cache = new(redisOptions.ConnectionString);
cache.FlushDb();
return cache; return cache;
}); });
} }

121
Cis.Core/Cis.Core.xml

@ -195,89 +195,76 @@
</summary> </summary>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.Add(`0)"> <member name="M:Cis.Core.Common.ServiceBase`1.Add(`0)">
<summary> <summary>
添加实体类
</summary> </summary>
<param name="entity"></param> <param name="entity">实体类</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.AddReturnId(`0)"> <member name="M:Cis.Core.Common.ServiceBase`1.AddReturnId(`0)">
<summary> <summary>
添加实体类并返回 id
</summary> </summary>
<param name="entity"></param> <param name="entity">实体类</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.AddArray(`0[])"> <member name="M:Cis.Core.Common.ServiceBase`1.AddArray(`0[])">
<summary> <summary>
批量添加实体类
</summary> </summary>
<param name="array"></param> <param name="array">实体类数组</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.Update(`0)"> <member name="M:Cis.Core.Common.ServiceBase`1.Update(`0)">
<summary> <summary>
更新实体类
</summary> </summary>
<param name="entity"></param> <param name="entity">实体类</param>
<returns></returns> <returns></returns>
</member>
<member name="M:Cis.Core.Common.ServiceBase`1.UpdateArray(`0[])">
<summary>
</summary>
<param name="array"></param>
<returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.Delete(System.Int64)"> <member name="M:Cis.Core.Common.ServiceBase`1.Delete(System.Int64)">
<summary> <summary>
删除实体类
</summary> </summary>
<param name="id"></param> <param name="id">实体类 id</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.DeleteArray(`0[])"> <member name="M:Cis.Core.Common.ServiceBase`1.FakeDelete(System.Int64,System.Boolean)">
<summary> <summary>
假删除实体类
</summary> </summary>
<param name="array"></param> <param name="id">实体类 id</param>
<returns></returns> <param name="isDelete">是否假删除</param>
</member> <returns></returns>
<member name="M:Cis.Core.Common.ServiceBase`1.FakeDelete(System.Int64)">
<summary>
</summary>
<param name="id"></param>
<returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.Get(System.Int64)"> <member name="M:Cis.Core.Common.ServiceBase`1.Get(System.Int64)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="id"></param> <param name="id">实体类 id</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.GetQ(System.String)"> <member name="M:Cis.Core.Common.ServiceBase`1.GetQ(System.String)">
<summary> <summary>
获取实体类
</summary> </summary>
<param name="queryJson">equal:id,isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:id,isDelete; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.GetList(System.String)"> <member name="M:Cis.Core.Common.ServiceBase`1.GetList(System.String)">
<summary> <summary>
批量获取实体类
</summary> </summary>
<param name="queryJson">equal:isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Cis.Core.Common.ServiceBase`1.GetPageList(System.String,System.String)"> <member name="M:Cis.Core.Common.ServiceBase`1.GetPageList(System.String,System.String)">
<summary> <summary>
批量获取分页实体类
</summary> </summary>
<param name="queryJson">equal:isDelete; between:[startTime,endTime];</param> <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param>
<param name="pagination">index,size</param> <param name="pagination">index,size</param>
<returns></returns> <returns></returns>
</member> </member>
<member name="T:Cis.Core.StatusEnum"> <member name="T:Cis.Core.StatusEnum">
<summary> <summary>

63
Cis.Core/Common/Entity/ServiceBase.cs

@ -14,9 +14,9 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
} }
/// <summary> /// <summary>
/// /// 添加实体类
/// </summary> /// </summary>
/// <param name="entity"></param> /// <param name="entity">实体类</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> Add([FromForm] T entity) public virtual async Task<bool> Add([FromForm] T entity)
@ -25,9 +25,9 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
} }
/// <summary> /// <summary>
/// /// 添加实体类并返回 id
/// </summary> /// </summary>
/// <param name="entity"></param> /// <param name="entity">实体类</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<long> AddReturnId([FromForm] T entity) public virtual async Task<long> AddReturnId([FromForm] T entity)
@ -38,20 +38,20 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
} }
/// <summary> /// <summary>
/// /// 批量添加实体类
/// </summary> /// </summary>
/// <param name="array"></param> /// <param name="array">实体类数组</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> AddArray([FromForm] T[] array) public virtual async Task<bool> AddArray([Required][FromForm] T[] array)
{ {
return await _baseRep.InsertRangeAsync(array); return await _baseRep.InsertRangeAsync(array);
} }
/// <summary> /// <summary>
/// /// 更新实体类
/// </summary> /// </summary>
/// <param name="entity"></param> /// <param name="entity">实体类</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> Update([FromForm] T entity) public virtual async Task<bool> Update([FromForm] T entity)
@ -59,71 +59,62 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
return await _baseRep.UpdateAsync(entity); return await _baseRep.UpdateAsync(entity);
} }
/// <summary>
///
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> UpdateArray([FromForm] T[] array) public virtual async Task<bool> UpdateArray([Required][FromForm] T[] array)
{ {
return await _baseRep.UpdateRangeAsync(array); return await _baseRep.UpdateRangeAsync(array);
} }
/// <summary> /// <summary>
/// /// 删除实体类
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">实体类 id</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> Delete(long id) public virtual async Task<bool> Delete([Required][FromForm] long id)
{ {
return await _baseRep.DeleteByIdAsync(id); return await _baseRep.DeleteByIdAsync(id);
} }
/// <summary>
///
/// </summary>
/// <param name="array"></param>
/// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> DeleteArray(T[] array) public virtual async Task<bool> DeleteArray([Required][FromForm] T[] array)
{ {
return await _baseRep.DeleteByIdsAsync(array); return await _baseRep.DeleteByIdsAsync(array);
} }
/// <summary> /// <summary>
/// /// 假删除实体类
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">实体类 id</param>
/// <param name="isDelete">是否假删除</param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public virtual async Task<bool> FakeDelete(long id) public virtual async Task<bool> FakeDelete([Required][FromForm] long id, [FromForm] bool isDelete = true)
{ {
return await _baseRep.AsUpdateable(new T { Id = id, IsDelete = true }) return await _baseRep.AsUpdateable(new T { Id = id, IsDelete = isDelete })
.UpdateColumns(it => it.IsDelete) .UpdateColumns(it => it.IsDelete)
.ExecuteCommandAsync() > 0; .ExecuteCommandAsync() > 0;
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id">实体类 id</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public virtual async Task<T> Get(long id) public virtual async Task<T> Get([Required] long id)
{ {
T entity = await _baseRep.GetByIdAsync(id); T entity = await _baseRep.GetByIdAsync(id);
return entity; return entity;
} }
/// <summary> /// <summary>
/// /// 获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:id,isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:id,isDelete; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public virtual async Task<T> GetQ(string queryJson) public virtual async Task<T> GetQ([Required] string queryJson)
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
@ -143,7 +134,7 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
} }
/// <summary> /// <summary>
/// /// 批量获取实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param>
/// <returns></returns> /// <returns></returns>
@ -166,13 +157,13 @@ public class ServiceBase<T> : IDynamicApiController where T : EntityBase, new()
} }
/// <summary> /// <summary>
/// /// 批量获取分页实体类
/// </summary> /// </summary>
/// <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param> /// <param name="queryJson">equal:isDelete; between:[startTime,endTime];</param>
/// <param name="pagination">index,size</param> /// <param name="pagination">index,size</param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public virtual async Task<List<T>> GetPageList(string pagination, string queryJson = "") public virtual async Task<List<T>> GetPageList([Required] string pagination, string queryJson = "")
{ {
JObject queryObj = queryJson.ToJObject(); JObject queryObj = queryJson.ToJObject();
Pagination pageObj = pagination.ToObject<Pagination>(); Pagination pageObj = pagination.ToObject<Pagination>();

5
Cis.sln

@ -13,6 +13,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cis.Web.Entry", "Cis.Web.En
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EC.Helper", "EC.Helper\EC.Helper.csproj", "{C2A5AEC8-F4FB-4D57-AE32-80502979FB9E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EC.Helper", "EC.Helper\EC.Helper.csproj", "{C2A5AEC8-F4FB-4D57-AE32-80502979FB9E}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5D70EBD8-D86C-4F6B-9231-3ED720842298}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

6
EC.Helper/EC.Helper.csproj

@ -147,6 +147,12 @@
<ItemGroup> <ItemGroup>
<Folder Include="libs\yushi\linux32\" /> <Folder Include="libs\yushi\linux32\" />
<Folder Include="RabbitFunc\" /> <Folder Include="RabbitFunc\" />
<Folder Include="Onvif\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.ServiceModel.Http" Version="4.10.0" />
<PackageReference Include="System.ServiceModel.Security" Version="4.10.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

22861
EC.Helper/Onvif/Common/DataTypes.cs

File diff suppressed because it is too large

1735
EC.Helper/Onvif/Device/DataTypes.cs

File diff suppressed because it is too large

2935
EC.Helper/Onvif/Device/DeviceClient.cs

File diff suppressed because it is too large

723
EC.Helper/Onvif/Discovery/DiscoveryClient.cs

@ -0,0 +1,723 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
//
// 对此文件的更改可能导致不正确的行为,并在以下条件下丢失:
// 代码重新生成。
// </auto-generated>
//------------------------------------------------------------------------------
namespace EC.Helper.Onvif.Discovery;
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.onvif.org/ver10/network/wsdl", ConfigurationName= "EC.Onvif.Discovery.RemoteDiscoveryPort")]
public interface RemoteDiscoveryPort
{
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Hello", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
HelloResponse Hello(HelloRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Hello", ReplyAction="*")]
System.Threading.Tasks.Task<HelloResponse> HelloAsync(HelloRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Bye", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
ByeResponse Bye(ByeRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Bye", ReplyAction="*")]
System.Threading.Tasks.Task<ByeResponse> ByeAsync(ByeRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class EndpointReferenceType
{
private AttributedURI addressField;
private ReferencePropertiesType referencePropertiesField;
private ReferenceParametersType referenceParametersField;
private AttributedQName portTypeField;
private ServiceNameType serviceNameField;
private System.Xml.XmlElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public AttributedURI Address
{
get
{
return this.addressField;
}
set
{
this.addressField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public ReferencePropertiesType ReferenceProperties
{
get
{
return this.referencePropertiesField;
}
set
{
this.referencePropertiesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=2)]
public ReferenceParametersType ReferenceParameters
{
get
{
return this.referenceParametersField;
}
set
{
this.referenceParametersField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public AttributedQName PortType
{
get
{
return this.portTypeField;
}
set
{
this.portTypeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public ServiceNameType ServiceName
{
get
{
return this.serviceNameField;
}
set
{
this.serviceNameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
public System.Xml.XmlElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class AttributedURI
{
private string valueField;
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute(DataType="anyURI")]
public string Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public partial class ProbeMatchType
{
private EndpointReferenceType endpointReferenceField;
private string typesField;
private ScopesType scopesField;
private string xAddrsField;
private uint metadataVersionField;
private System.Xml.XmlElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing", Order=0)]
public EndpointReferenceType EndpointReference
{
get
{
return this.endpointReferenceField;
}
set
{
this.endpointReferenceField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string Types
{
get
{
return this.typesField;
}
set
{
this.typesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=2)]
public ScopesType Scopes
{
get
{
return this.scopesField;
}
set
{
this.scopesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string XAddrs
{
get
{
return this.xAddrsField;
}
set
{
this.xAddrsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public uint MetadataVersion
{
get
{
return this.metadataVersionField;
}
set
{
this.metadataVersionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
public System.Xml.XmlElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public partial class ScopesType
{
private string matchByField;
private string[] textField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="anyURI")]
public string MatchBy
{
get
{
return this.matchByField;
}
set
{
this.matchByField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute(DataType="anyURI")]
public string[] Text
{
get
{
return this.textField;
}
set
{
this.textField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class ServiceNameType
{
private string portNameField;
private System.Xml.XmlQualifiedName valueField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(DataType="NCName")]
public string PortName
{
get
{
return this.portNameField;
}
set
{
this.portNameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public System.Xml.XmlQualifiedName Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class AttributedQName
{
private System.Xml.XmlQualifiedName valueField;
/// <remarks/>
[System.Xml.Serialization.XmlTextAttribute()]
public System.Xml.XmlQualifiedName Value
{
get
{
return this.valueField;
}
set
{
this.valueField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class ReferenceParametersType
{
private System.Xml.XmlElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
public System.Xml.XmlElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public partial class ReferencePropertiesType
{
private System.Xml.XmlElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order=0)]
public System.Xml.XmlElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Hello", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class HelloRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public EndpointReferenceType EndpointReference;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=1)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string Types;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=2)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public ScopesType Scopes;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=3)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string XAddrs;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=4)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public uint MetadataVersion;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=5)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public HelloRequest()
{
}
public HelloRequest(EndpointReferenceType EndpointReference, string Types, ScopesType Scopes, string XAddrs, uint MetadataVersion, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.EndpointReference = EndpointReference;
this.Types = Types;
this.Scopes = Scopes;
this.XAddrs = XAddrs;
this.MetadataVersion = MetadataVersion;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="HelloResponse", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class HelloResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public EndpointReferenceType EndpointReference;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=1)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public HelloResponse()
{
}
public HelloResponse(EndpointReferenceType EndpointReference, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.EndpointReference = EndpointReference;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Bye", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class ByeRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public EndpointReferenceType EndpointReference;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=1)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string Types;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=2)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public ScopesType Scopes;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=3)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string XAddrs;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=4)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public uint MetadataVersion;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=5)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public ByeRequest()
{
}
public ByeRequest(EndpointReferenceType EndpointReference, string Types, ScopesType Scopes, string XAddrs, uint MetadataVersion, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.EndpointReference = EndpointReference;
this.Types = Types;
this.Scopes = Scopes;
this.XAddrs = XAddrs;
this.MetadataVersion = MetadataVersion;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="ByeResponse", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class ByeResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public EndpointReferenceType EndpointReference;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=1)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public ByeResponse()
{
}
public ByeResponse(EndpointReferenceType EndpointReference, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.EndpointReference = EndpointReference;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
public interface RemoteDiscoveryPortChannel : RemoteDiscoveryPort, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
public partial class RemoteDiscoveryPortClient : System.ServiceModel.ClientBase<RemoteDiscoveryPort>, RemoteDiscoveryPort
{
public RemoteDiscoveryPortClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public HelloResponse Hello(HelloRequest request)
{
return base.Channel.Hello(request);
}
public System.Threading.Tasks.Task<HelloResponse> HelloAsync(HelloRequest request)
{
return base.Channel.HelloAsync(request);
}
public ByeResponse Bye(ByeRequest request)
{
return base.Channel.Bye(request);
}
public System.Threading.Tasks.Task<ByeResponse> ByeAsync(ByeRequest request)
{
return base.Channel.ByeAsync(request);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.onvif.org/ver10/network/wsdl", ConfigurationName= "EC.Onvif.Discovery.DiscoveryLookupPort")]
public interface DiscoveryLookupPort
{
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Probe", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
ProbeResponse Probe(ProbeRequest request);
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/network/wsdl/Probe", ReplyAction="*")]
System.Threading.Tasks.Task<ProbeResponse> ProbeAsync(ProbeRequest request);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Probe", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class ProbeRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string Types;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=1)]
[System.Xml.Serialization.XmlElementAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public ScopesType Scopes;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=2)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public ProbeRequest()
{
}
public ProbeRequest(string Types, ScopesType Scopes, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.Types = Types;
this.Scopes = Scopes;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
[System.ServiceModel.MessageContractAttribute(WrapperName="ProbeResponse", WrapperNamespace="http://www.onvif.org/ver10/network/wsdl", IsWrapped=true)]
public partial class ProbeResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery", Order=0)]
[System.Xml.Serialization.XmlElementAttribute("ProbeMatch", Namespace="http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public ProbeMatchType[] ProbeMatch;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=1)]
[System.Xml.Serialization.XmlAnyElementAttribute()]
public System.Xml.XmlElement[] Any;
public System.Xml.XmlAttribute[] AnyAttr;
public ProbeResponse()
{
}
public ProbeResponse(ProbeMatchType[] ProbeMatch, System.Xml.XmlElement[] Any, System.Xml.XmlAttribute[] AnyAttr)
{
this.ProbeMatch = ProbeMatch;
this.Any = Any;
this.AnyAttr = AnyAttr;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
public interface DiscoveryLookupPortChannel : DiscoveryLookupPort, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3-preview3.21351.2")]
public partial class DiscoveryLookupPortClient : System.ServiceModel.ClientBase<DiscoveryLookupPort>, DiscoveryLookupPort
{
public DiscoveryLookupPortClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public ProbeResponse Probe(ProbeRequest request)
{
return base.Channel.Probe(request);
}
public System.Threading.Tasks.Task<ProbeResponse> ProbeAsync(ProbeRequest request)
{
return base.Channel.ProbeAsync(request);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
}

143
EC.Helper/Onvif/Imaging/DataTypes.cs

@ -0,0 +1,143 @@
namespace EC.Helper.Onvif.Imaging;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver20/imaging/wsdl")]
public partial class Capabilities
{
private System.Xml.Linq.XElement[] anyField;
private bool imageStabilizationField;
private bool imageStabilizationFieldSpecified;
private bool presetsField;
private bool presetsFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 0)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool ImageStabilization
{
get
{
return this.imageStabilizationField;
}
set
{
this.imageStabilizationField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ImageStabilizationSpecified
{
get
{
return this.imageStabilizationFieldSpecified;
}
set
{
this.imageStabilizationFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool Presets
{
get
{
return this.presetsField;
}
set
{
this.presetsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool PresetsSpecified
{
get
{
return this.presetsFieldSpecified;
}
set
{
this.presetsFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver20/imaging/wsdl")]
public partial class ImagingPreset
{
private string nameField;
private string tokenField;
private string typeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public string Name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string token
{
get
{
return this.tokenField;
}
set
{
this.tokenField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string type
{
get
{
return this.typeField;
}
set
{
this.typeField = value;
}
}
}

185
EC.Helper/Onvif/Imaging/ImagingClient.cs

@ -0,0 +1,185 @@
using EC.Helper.Onvif.Common;
namespace EC.Helper.Onvif.Imaging;
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.onvif.org/ver20/imaging/wsdl", ConfigurationName = "EC.Onvif.Imaging.Imaging")]
public interface Imaging
{
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetServiceCapabilities", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Capabilities")]
System.Threading.Tasks.Task<Common.Capabilities> GetServiceCapabilitiesAsync();
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetImagingSettings", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "ImagingSettings")]
System.Threading.Tasks.Task<ImagingSettings20> GetImagingSettingsAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
System.Threading.Tasks.Task SetImagingSettingsAsync(string VideoSourceToken, ImagingSettings20 ImagingSettings, bool ForcePersistence);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetOptions", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "ImagingOptions")]
System.Threading.Tasks.Task<ImagingOptions20> GetOptionsAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/Move", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
System.Threading.Tasks.Task MoveAsync(string VideoSourceToken, FocusMove Focus);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetMoveOptions", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "MoveOptions")]
System.Threading.Tasks.Task<MoveOptions20> GetMoveOptionsAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/FocusStop", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
System.Threading.Tasks.Task StopAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetStatus", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Status")]
System.Threading.Tasks.Task<ImagingStatus20> GetStatusAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetPresets", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
System.Threading.Tasks.Task<GetPresetsResponse> GetPresetsAsync(GetPresetsRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/GetCurrentPreset", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Preset")]
System.Threading.Tasks.Task<ImagingPreset> GetCurrentPresetAsync(string VideoSourceToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/imaging/wsdl/SetCurrentPreset", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
System.Threading.Tasks.Task SetCurrentPresetAsync(string VideoSourceToken, string PresetToken);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresets", WrapperNamespace = "http://www.onvif.org/ver20/imaging/wsdl", IsWrapped = true)]
public partial class GetPresetsRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/imaging/wsdl", Order = 0)]
public string VideoSourceToken;
public GetPresetsRequest()
{
}
public GetPresetsRequest(string VideoSourceToken)
{
this.VideoSourceToken = VideoSourceToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresetsResponse", WrapperNamespace = "http://www.onvif.org/ver20/imaging/wsdl", IsWrapped = true)]
public partial class GetPresetsResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/imaging/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("Preset")]
public ImagingPreset[] Preset;
public GetPresetsResponse()
{
}
public GetPresetsResponse(ImagingPreset[] Preset)
{
this.Preset = Preset;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
public interface ImagingChannel : Imaging, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
public partial class ImagingClient : System.ServiceModel.ClientBase<Imaging>, Imaging
{
internal ImagingClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public System.Threading.Tasks.Task<Common.Capabilities> GetServiceCapabilitiesAsync()
{
return base.Channel.GetServiceCapabilitiesAsync();
}
public System.Threading.Tasks.Task<ImagingSettings20> GetImagingSettingsAsync(string VideoSourceToken)
{
return base.Channel.GetImagingSettingsAsync(VideoSourceToken);
}
public System.Threading.Tasks.Task SetImagingSettingsAsync(string VideoSourceToken, ImagingSettings20 ImagingSettings, bool ForcePersistence)
{
return base.Channel.SetImagingSettingsAsync(VideoSourceToken, ImagingSettings, ForcePersistence);
}
public System.Threading.Tasks.Task<ImagingOptions20> GetOptionsAsync(string VideoSourceToken)
{
return base.Channel.GetOptionsAsync(VideoSourceToken);
}
public System.Threading.Tasks.Task MoveAsync(string VideoSourceToken, FocusMove Focus)
{
return base.Channel.MoveAsync(VideoSourceToken, Focus);
}
public System.Threading.Tasks.Task<MoveOptions20> GetMoveOptionsAsync(string VideoSourceToken)
{
return base.Channel.GetMoveOptionsAsync(VideoSourceToken);
}
public System.Threading.Tasks.Task StopAsync(string VideoSourceToken)
{
return base.Channel.StopAsync(VideoSourceToken);
}
public System.Threading.Tasks.Task<ImagingStatus20> GetStatusAsync(string VideoSourceToken)
{
return base.Channel.GetStatusAsync(VideoSourceToken);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetPresetsResponse> Imaging.GetPresetsAsync(GetPresetsRequest request)
{
return base.Channel.GetPresetsAsync(request);
}
public System.Threading.Tasks.Task<GetPresetsResponse> GetPresetsAsync(string VideoSourceToken)
{
GetPresetsRequest inValue = new GetPresetsRequest();
inValue.VideoSourceToken = VideoSourceToken;
return ((Imaging)(this)).GetPresetsAsync(inValue);
}
public System.Threading.Tasks.Task<ImagingPreset> GetCurrentPresetAsync(string VideoSourceToken)
{
return base.Channel.GetCurrentPresetAsync(VideoSourceToken);
}
public System.Threading.Tasks.Task SetCurrentPresetAsync(string VideoSourceToken, string PresetToken)
{
return base.Channel.SetCurrentPresetAsync(VideoSourceToken, PresetToken);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
}

662
EC.Helper/Onvif/Media/DataTypes.cs

@ -0,0 +1,662 @@
using EC.Helper.Onvif.Common;
namespace EC.Helper.Onvif.Media;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver10/media/wsdl")]
public partial class Capabilities
{
private ProfileCapabilities profileCapabilitiesField;
private StreamingCapabilities streamingCapabilitiesField;
private System.Xml.Linq.XElement[] anyField;
private bool snapshotUriField;
private bool snapshotUriFieldSpecified;
private bool rotationField;
private bool rotationFieldSpecified;
private bool videoSourceModeField;
private bool videoSourceModeFieldSpecified;
private bool oSDField;
private bool oSDFieldSpecified;
private bool temporaryOSDTextField;
private bool temporaryOSDTextFieldSpecified;
private bool eXICompressionField;
private bool eXICompressionFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public ProfileCapabilities ProfileCapabilities
{
get
{
return this.profileCapabilitiesField;
}
set
{
this.profileCapabilitiesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public StreamingCapabilities StreamingCapabilities
{
get
{
return this.streamingCapabilitiesField;
}
set
{
this.streamingCapabilitiesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 2)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool SnapshotUri
{
get
{
return this.snapshotUriField;
}
set
{
this.snapshotUriField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool SnapshotUriSpecified
{
get
{
return this.snapshotUriFieldSpecified;
}
set
{
this.snapshotUriFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool Rotation
{
get
{
return this.rotationField;
}
set
{
this.rotationField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool RotationSpecified
{
get
{
return this.rotationFieldSpecified;
}
set
{
this.rotationFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool VideoSourceMode
{
get
{
return this.videoSourceModeField;
}
set
{
this.videoSourceModeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool VideoSourceModeSpecified
{
get
{
return this.videoSourceModeFieldSpecified;
}
set
{
this.videoSourceModeFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool OSD
{
get
{
return this.oSDField;
}
set
{
this.oSDField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool OSDSpecified
{
get
{
return this.oSDFieldSpecified;
}
set
{
this.oSDFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool TemporaryOSDText
{
get
{
return this.temporaryOSDTextField;
}
set
{
this.temporaryOSDTextField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool TemporaryOSDTextSpecified
{
get
{
return this.temporaryOSDTextFieldSpecified;
}
set
{
this.temporaryOSDTextFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool EXICompression
{
get
{
return this.eXICompressionField;
}
set
{
this.eXICompressionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool EXICompressionSpecified
{
get
{
return this.eXICompressionFieldSpecified;
}
set
{
this.eXICompressionFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver10/media/wsdl")]
public partial class ProfileCapabilities
{
private System.Xml.Linq.XElement[] anyField;
private int maximumNumberOfProfilesField;
private bool maximumNumberOfProfilesFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 0)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public int MaximumNumberOfProfiles
{
get
{
return this.maximumNumberOfProfilesField;
}
set
{
this.maximumNumberOfProfilesField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool MaximumNumberOfProfilesSpecified
{
get
{
return this.maximumNumberOfProfilesFieldSpecified;
}
set
{
this.maximumNumberOfProfilesFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver10/media/wsdl")]
public partial class VideoSourceModeExtension
{
private System.Xml.Linq.XElement[] anyField;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 0)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver10/media/wsdl")]
public partial class VideoSourceMode
{
private float maxFramerateField;
private VideoResolution maxResolutionField;
private string encodingsField;
private bool rebootField;
private string descriptionField;
private VideoSourceModeExtension extensionField;
private string tokenField;
private bool enabledField;
private bool enabledFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public float MaxFramerate
{
get
{
return this.maxFramerateField;
}
set
{
this.maxFramerateField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public VideoResolution MaxResolution
{
get
{
return this.maxResolutionField;
}
set
{
this.maxResolutionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 2)]
public string Encodings
{
get
{
return this.encodingsField;
}
set
{
this.encodingsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 3)]
public bool Reboot
{
get
{
return this.rebootField;
}
set
{
this.rebootField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 4)]
public string Description
{
get
{
return this.descriptionField;
}
set
{
this.descriptionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 5)]
public VideoSourceModeExtension Extension
{
get
{
return this.extensionField;
}
set
{
this.extensionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string token
{
get
{
return this.tokenField;
}
set
{
this.tokenField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool Enabled
{
get
{
return this.enabledField;
}
set
{
this.enabledField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool EnabledSpecified
{
get
{
return this.enabledFieldSpecified;
}
set
{
this.enabledFieldSpecified = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver10/media/wsdl")]
public partial class StreamingCapabilities
{
private System.Xml.Linq.XElement[] anyField;
private bool rTPMulticastField;
private bool rTPMulticastFieldSpecified;
private bool rTP_TCPField;
private bool rTP_TCPFieldSpecified;
private bool rTP_RTSP_TCPField;
private bool rTP_RTSP_TCPFieldSpecified;
private bool nonAggregateControlField;
private bool nonAggregateControlFieldSpecified;
private bool noRTSPStreamingField;
private bool noRTSPStreamingFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 0)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool RTPMulticast
{
get
{
return this.rTPMulticastField;
}
set
{
this.rTPMulticastField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool RTPMulticastSpecified
{
get
{
return this.rTPMulticastFieldSpecified;
}
set
{
this.rTPMulticastFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool RTP_TCP
{
get
{
return this.rTP_TCPField;
}
set
{
this.rTP_TCPField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool RTP_TCPSpecified
{
get
{
return this.rTP_TCPFieldSpecified;
}
set
{
this.rTP_TCPFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool RTP_RTSP_TCP
{
get
{
return this.rTP_RTSP_TCPField;
}
set
{
this.rTP_RTSP_TCPField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool RTP_RTSP_TCPSpecified
{
get
{
return this.rTP_RTSP_TCPFieldSpecified;
}
set
{
this.rTP_RTSP_TCPFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool NonAggregateControl
{
get
{
return this.nonAggregateControlField;
}
set
{
this.nonAggregateControlField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool NonAggregateControlSpecified
{
get
{
return this.nonAggregateControlFieldSpecified;
}
set
{
this.nonAggregateControlFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool NoRTSPStreaming
{
get
{
return this.noRTSPStreamingField;
}
set
{
this.noRTSPStreamingField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool NoRTSPStreamingSpecified
{
get
{
return this.noRTSPStreamingFieldSpecified;
}
set
{
this.noRTSPStreamingFieldSpecified = value;
}
}
}

2125
EC.Helper/Onvif/Media/MediaClient.cs

File diff suppressed because it is too large

286
EC.Helper/Onvif/OnvifClient.cs

@ -0,0 +1,286 @@
using EC.Helper.Onvif.Common;
using EC.Helper.Onvif.Device;
using EC.Helper.Onvif.Imaging;
using EC.Helper.Onvif.Media;
using EC.Helper.Onvif.PTZ;
using System.Net;
using Capabilities = EC.Helper.Onvif.Common.Capabilities;
namespace EC.Helper.Onvif;
public class OnvifClient
{
#region Attr
public string Hostname { get; private set; }
public string Username { get; private set; }
public string Password { get; private set; }
#endregion Attr
#region Client Attr
protected DeviceClient Device { get; set; }
protected MediaClient Media { get; set; }
protected PTZClient PTZ { get; set; }
protected ImagingClient Imaging { get; set; }
protected Capabilities Caps { get; set; }
#endregion Client Attr
#region Cache Attr
protected string ProfileToken { get; set; }
protected string VideoSourceToken { get; set; }
protected string SteamUrl { get; set; }
protected string SnapshotUrl { get; set; }
#endregion Cache Attr
public OnvifClient(string hostname, string username, string password)
{
Hostname = hostname;
Username = username;
Password = password;
}
public async Task<bool> Init()
{
try
{
Device = await OnvifClientFactory.CreateDeviceClientAsync(Hostname, Username, Password);
Media = await OnvifClientFactory.CreateMediaClientAsync(Hostname, Username, Password);
PTZ = await OnvifClientFactory.CreatePTZClientAsync(Hostname, Username, Password);
Imaging = await OnvifClientFactory.CreateImagingClientAsync(Hostname, Username, Password);
var profiles = await Media.GetProfilesAsync();
var videoSources = await Media.GetVideoSourcesAsync();
foreach (var profile in profiles.Profiles)
{
if (string.IsNullOrEmpty(ProfileToken))
{
ProfileToken = profile.token;
break;
}
}
foreach (var source in videoSources.VideoSources)
{
if (string.IsNullOrEmpty(VideoSourceToken))
{
VideoSourceToken = source.token;
break;
}
}
Caps = (await Device.GetCapabilitiesAsync(new CapabilityCategory[] { CapabilityCategory.All })).Capabilities;
}
catch (Exception)
{
return false;
throw;
}
return true;
}
#region DeviceClient
public bool IsDeviceContected()
{
return Device != null;
}
#endregion DeviceClient
#region MediaClient
public bool IsMediaContected()
{
bool ret = IsDeviceContected();
return ret;
}
protected StreamSetup RtspStreamSetup { get; } = new()
{
Stream = StreamType.RTPUnicast,
Transport = new() { Protocol = TransportProtocol.RTSP }
};
public async Task<string> GetStreamUrl()
{
if (string.IsNullOrEmpty(SteamUrl))
{
MediaUri mediaUri = await Media.GetStreamUriAsync(RtspStreamSetup, ProfileToken);
SteamUrl = mediaUri.Uri;
}
return SteamUrl;
}
public async Task<string> GetSnapshotUrl()
{
if (string.IsNullOrEmpty(SnapshotUrl))
{
MediaUri mediaUri = await Media.GetSnapshotUriAsync(ProfileToken);
SnapshotUrl = mediaUri.Uri;
}
return SnapshotUrl;
}
public async Task<string> GetSnapshot()
{
string url = await GetSnapshotUrl();
WebRequest request = WebRequest.Create(url);
request.Method = "GET";
request.PreAuthenticate = true;
request.Credentials = new NetworkCredential(Username, Password);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using Stream stream = response.GetResponseStream();
using MemoryStream mStream = new();
byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = stream.Read(buffer, 0, buffer.Length);
mStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
mStream.Position = 0;
return Convert.ToBase64String(mStream.ToArray());
}
#endregion MediaClient
#region PTZClient
public bool IsPTZContected()
{
bool ret = IsDeviceContected() && (PTZ != null) && !string.IsNullOrEmpty(ProfileToken);
return ret;
}
/// <summary>
/// 绝对移动
/// </summary>
/// <param name="pan"></param>
/// <param name="tilt"></param>
/// <param name="zoom"></param>
/// <param name="atomDist"></param>
/// <returns></returns>
public async Task AbsoluteMove(float pan, float tilt, float zoom, float atomDist = 0.1f)
{
await PTZ.AbsoluteMoveAsync(ProfileToken, new PTZVector
{
PanTilt = new Vector2D { x = pan, y = tilt },
Zoom = new Vector1D { x = zoom }
}, new PTZSpeed
{
PanTilt = new Vector2D { x = atomDist, y = atomDist },
Zoom = new Vector1D { x = atomDist }
});
}
/// <summary>
/// 相对移动
/// </summary>
/// <param name="pan">[-1,1]</param>
/// <param name="tilt">[-1,1]</param>
/// <param name="zoom">[-1,1]</param>
/// <param name="atomSpeed">[0,1]</param>
public async Task RelativeMove(float pan, float tilt, float zoom, float atomSpeed = 0.1f)
{
await PTZ.RelativeMoveAsync(ProfileToken, new PTZVector
{
PanTilt = new Vector2D { x = pan, y = tilt },
Zoom = new Vector1D { x = zoom }
}, new PTZSpeed
{
PanTilt = new Vector2D { x = atomSpeed, y = atomSpeed },
Zoom = new Vector1D { x = atomSpeed }
});
}
/// <summary>
/// 持续移动
/// </summary>
/// <param name="pan">[-1,1]</param>
/// <param name="tilt">[-1,1]</param>
/// <param name="zoom">[-1,1]</param>
/// <param name="timeout">ms</param>
public async Task ContinuousMove(float pan, float tilt, float zoom, string timeout = "")
{
await PTZ.ContinuousMoveAsync(ProfileToken, new PTZSpeed
{
PanTilt = new Vector2D { x = pan, y = tilt },
Zoom = new Vector1D { x = zoom }
}, timeout);
}
public async Task StopMove()
{
await PTZ.StopAsync(ProfileToken, true, true);
}
public async Task<PTZStatus> GetStatus()
{
return await PTZ.GetStatusAsync(ProfileToken);
}
#endregion PTZClient
#region ImagingClient
public bool IsImagingContected()
{
bool ret = IsDeviceContected();
return ret;
}
public async Task FocusAbsoluteMove(float position)
{
await Imaging.MoveAsync(VideoSourceToken, new FocusMove
{
Absolute = new AbsoluteFocus
{
Position = position,
//Speed = 1f,
//SpeedSpecified = true
}
});
}
public async Task FocusRelativeMove(float distance)
{
await Imaging.MoveAsync(VideoSourceToken, new FocusMove
{
Relative = new RelativeFocus
{
Distance = distance,
//Speed = 1f,
//SpeedSpecified = true
}
});
}
public async Task FocusContinuousMove(float speed)
{
await Imaging.MoveAsync(VideoSourceToken, new FocusMove
{
Continuous = new ContinuousFocus { Speed = speed }
});
}
public async Task FocusStopMove()
{
await Imaging.StopAsync(VideoSourceToken);
}
#endregion ImagingClient
}

114
EC.Helper/Onvif/OnvifClientFactory.cs

@ -0,0 +1,114 @@
using EC.Helper.Onvif.Common;
using EC.Helper.Onvif.Device;
using EC.Helper.Onvif.Imaging;
using EC.Helper.Onvif.Media;
using EC.Helper.Onvif.PTZ;
using EC.Helper.Onvif.Security;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace EC.Helper.Onvif;
public static class OnvifClientFactory
{
private static Binding CreateBinding()
{
var binding = new CustomBinding();
var textBindingElement = new TextMessageEncodingBindingElement
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
};
var httpBindingElement = new HttpTransportBindingElement
{
AllowCookies = true,
MaxBufferSize = int.MaxValue,
MaxReceivedMessageSize = int.MaxValue
};
binding.Elements.Add(textBindingElement);
binding.Elements.Add(httpBindingElement);
return binding;
}
public static async Task<DeviceClient> CreateDeviceClientAsync(string host, string username, string password)
{
return await CreateDeviceClientAsync(new Uri($"http://{host}/onvif/device_service"), username, password);
}
public static async Task<DeviceClient> CreateDeviceClientAsync(Uri uri, string username, string password)
{
var binding = CreateBinding();
var endpoint = new EndpointAddress(uri);
var device = new DeviceClient(binding, endpoint);
var time_shift = await GetDeviceTimeShift(device);
device = new DeviceClient(binding, endpoint);
device.ChannelFactory.Endpoint.EndpointBehaviors.Clear();
device.ChannelFactory.Endpoint.EndpointBehaviors.Add(new SoapSecurityHeaderBehavior(username, password, time_shift));
// Connectivity Test
await device.OpenAsync();
return device;
}
public static async Task<MediaClient> CreateMediaClientAsync(string host, string username, string password)
{
var binding = CreateBinding();
var device = await CreateDeviceClientAsync(host, username, password);
var caps = await device.GetCapabilitiesAsync(new CapabilityCategory[] { CapabilityCategory.Media });
var media = new MediaClient(binding, new EndpointAddress(new Uri(caps.Capabilities.Media.XAddr)));
var time_shift = await GetDeviceTimeShift(device);
media.ChannelFactory.Endpoint.EndpointBehaviors.Clear();
media.ChannelFactory.Endpoint.EndpointBehaviors.Add(new SoapSecurityHeaderBehavior(username, password, time_shift));
// Connectivity Test
await media.OpenAsync();
return media;
}
public static async Task<PTZClient> CreatePTZClientAsync(string host, string username, string password)
{
var binding = CreateBinding();
var device = await CreateDeviceClientAsync(host, username, password);
var caps = await device.GetCapabilitiesAsync(new CapabilityCategory[] { CapabilityCategory.PTZ });
var ptz = new PTZClient(binding, new EndpointAddress(new Uri(caps.Capabilities.PTZ.XAddr)));
var time_shift = await GetDeviceTimeShift(device);
ptz.ChannelFactory.Endpoint.EndpointBehaviors.Clear();
ptz.ChannelFactory.Endpoint.EndpointBehaviors.Add(new SoapSecurityHeaderBehavior(username, password, time_shift));
// Connectivity Test
await ptz.OpenAsync();
return ptz;
}
public static async Task<ImagingClient> CreateImagingClientAsync(string host, string username, string password)
{
var binding = CreateBinding();
var device = await CreateDeviceClientAsync(host, username, password);
var caps = await device.GetCapabilitiesAsync(new CapabilityCategory[] { CapabilityCategory.Imaging });
var imaging = new ImagingClient(binding, new EndpointAddress(new Uri(caps.Capabilities.Imaging.XAddr)));
var time_shift = await GetDeviceTimeShift(device);
imaging.ChannelFactory.Endpoint.EndpointBehaviors.Clear();
imaging.ChannelFactory.Endpoint.EndpointBehaviors.Add(new SoapSecurityHeaderBehavior(username, password, time_shift));
// Connectivity Test
await imaging.OpenAsync();
return imaging;
}
private static async Task<TimeSpan> GetDeviceTimeShift(DeviceClient device)
{
var utc = (await device.GetSystemDateAndTimeAsync()).UTCDateTime;
var dt = new System.DateTime(utc.Date.Year, utc.Date.Month, utc.Date.Day,
utc.Time.Hour, utc.Time.Minute, utc.Time.Second);
return dt - System.DateTime.UtcNow;
}
}

184
EC.Helper/Onvif/PTZ/DataTypes.cs

@ -0,0 +1,184 @@
namespace EC.Helper.Onvif.PTZ;
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl")]
public partial class Capabilities
{
private System.Xml.Linq.XElement[] anyField;
private bool eFlipField;
private bool eFlipFieldSpecified;
private bool reverseField;
private bool reverseFieldSpecified;
private bool getCompatibleConfigurationsField;
private bool getCompatibleConfigurationsFieldSpecified;
private bool moveStatusField;
private bool moveStatusFieldSpecified;
private bool statusPositionField;
private bool statusPositionFieldSpecified;
/// <remarks/>
[System.Xml.Serialization.XmlAnyElementAttribute(Order = 0)]
public System.Xml.Linq.XElement[] Any
{
get
{
return this.anyField;
}
set
{
this.anyField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool EFlip
{
get
{
return this.eFlipField;
}
set
{
this.eFlipField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool EFlipSpecified
{
get
{
return this.eFlipFieldSpecified;
}
set
{
this.eFlipFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool Reverse
{
get
{
return this.reverseField;
}
set
{
this.reverseField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ReverseSpecified
{
get
{
return this.reverseFieldSpecified;
}
set
{
this.reverseFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool GetCompatibleConfigurations
{
get
{
return this.getCompatibleConfigurationsField;
}
set
{
this.getCompatibleConfigurationsField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool GetCompatibleConfigurationsSpecified
{
get
{
return this.getCompatibleConfigurationsFieldSpecified;
}
set
{
this.getCompatibleConfigurationsFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool MoveStatus
{
get
{
return this.moveStatusField;
}
set
{
this.moveStatusField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool MoveStatusSpecified
{
get
{
return this.moveStatusFieldSpecified;
}
set
{
this.moveStatusFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public bool StatusPosition
{
get
{
return this.statusPositionField;
}
set
{
this.statusPositionField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool StatusPositionSpecified
{
get
{
return this.statusPositionFieldSpecified;
}
set
{
this.statusPositionFieldSpecified = value;
}
}
}

661
EC.Helper/Onvif/PTZ/PTZClient.cs

@ -0,0 +1,661 @@
using EC.Helper.Onvif.Common;
namespace EC.Helper.Onvif.PTZ;
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", ConfigurationName = "EC.Onvif.PTZ.PTZ")]
public interface PTZ
{
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetServiceCapabilities", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Capabilities")]
System.Threading.Tasks.Task<Capabilities> GetServiceCapabilitiesAsync();
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetNodes", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<GetNodesResponse> GetNodesAsync(GetNodesRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetNode", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PTZNode")]
System.Threading.Tasks.Task<PTZNode> GetNodeAsync(string NodeToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetConfiguration", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PTZConfiguration")]
System.Threading.Tasks.Task<PTZConfiguration> GetConfigurationAsync(string PTZConfigurationToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetConfigurations", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<GetConfigurationsResponse> GetConfigurationsAsync(GetConfigurationsRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/SetConfiguration", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task SetConfigurationAsync(PTZConfiguration PTZConfiguration, bool ForcePersistence);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetConfigurationOptions", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PTZConfigurationOptions")]
System.Threading.Tasks.Task<PTZConfigurationOptions> GetConfigurationOptionsAsync(string ConfigurationToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/SendAuxiliaryCommand", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "AuxiliaryResponse")]
System.Threading.Tasks.Task<string> SendAuxiliaryCommandAsync(string ProfileToken, string AuxiliaryData);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetPresets", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<GetPresetsResponse> GetPresetsAsync(GetPresetsRequest request);
// CODEGEN: Generating message contract since the operation has multiple return values.
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/SetPreset", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<SetPresetResponse> SetPresetAsync(SetPresetRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/RemovePreset", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task RemovePresetAsync(string ProfileToken, string PresetToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GotoPreset", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task GotoPresetAsync(string ProfileToken, string PresetToken, PTZSpeed Speed);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GotoHomePosition", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task GotoHomePositionAsync(string ProfileToken, PTZSpeed Speed);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/SetHomePosition", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task SetHomePositionAsync(string ProfileToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<ContinuousMoveResponse> ContinuousMoveAsync(ContinuousMoveRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/RelativeMove", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task RelativeMoveAsync(string ProfileToken, PTZVector Translation, PTZSpeed Speed);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetStatus", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PTZStatus")]
System.Threading.Tasks.Task<PTZStatus> GetStatusAsync(string ProfileToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/AbsoluteMove", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task AbsoluteMoveAsync(string ProfileToken, PTZVector Position, PTZSpeed Speed);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GeoMove", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task GeoMoveAsync(string ProfileToken, GeoLocation Target, PTZSpeed Speed, float AreaHeight, float AreaWidth);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/Stop", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task StopAsync(string ProfileToken, bool PanTilt, bool Zoom);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetPresetTours", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<GetPresetToursResponse> GetPresetToursAsync(GetPresetToursRequest request);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetPresetTour", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PresetTour")]
System.Threading.Tasks.Task<PresetTour> GetPresetTourAsync(string ProfileToken, string PresetTourToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetPresetTourOptions", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "Options")]
System.Threading.Tasks.Task<PTZPresetTourOptions> GetPresetTourOptionsAsync(string ProfileToken, string PresetTourToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/CreatePresetTour", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "PresetTourToken")]
System.Threading.Tasks.Task<string> CreatePresetTourAsync(string ProfileToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/ModifyPresetTour", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task ModifyPresetTourAsync(string ProfileToken, PresetTour PresetTour);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/OperatePresetTour", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task OperatePresetTourAsync(string ProfileToken, string PresetTourToken, PTZPresetTourOperation Operation);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/RemovePresetTour", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task RemovePresetTourAsync(string ProfileToken, string PresetTourToken);
[System.ServiceModel.OperationContractAttribute(Action = "http://www.onvif.org/ver20/ptz/wsdl/GetCompatibleConfigurations", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
System.Threading.Tasks.Task<GetCompatibleConfigurationsResponse> GetCompatibleConfigurationsAsync(GetCompatibleConfigurationsRequest request);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetNodes", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetNodesRequest
{
public GetNodesRequest()
{
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetNodesResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetNodesResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("PTZNode")]
public PTZNode[] PTZNode;
public GetNodesResponse()
{
}
public GetNodesResponse(PTZNode[] PTZNode)
{
this.PTZNode = PTZNode;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetConfigurations", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetConfigurationsRequest
{
public GetConfigurationsRequest()
{
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetConfigurationsResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetConfigurationsResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("PTZConfiguration")]
public PTZConfiguration[] PTZConfiguration;
public GetConfigurationsResponse()
{
}
public GetConfigurationsResponse(PTZConfiguration[] PTZConfiguration)
{
this.PTZConfiguration = PTZConfiguration;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresets", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetPresetsRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string ProfileToken;
public GetPresetsRequest()
{
}
public GetPresetsRequest(string ProfileToken)
{
this.ProfileToken = ProfileToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresetsResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetPresetsResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("Preset")]
public PTZPreset[] Preset;
public GetPresetsResponse()
{
}
public GetPresetsResponse(PTZPreset[] Preset)
{
this.Preset = Preset;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ServiceModel.MessageContractAttribute(WrapperName = "SetPreset", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class SetPresetRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string ProfileToken;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 1)]
public string PresetName;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 2)]
public string PresetToken;
public SetPresetRequest()
{
}
public SetPresetRequest(string ProfileToken, string PresetName, string PresetToken)
{
this.ProfileToken = ProfileToken;
this.PresetName = PresetName;
this.PresetToken = PresetToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ServiceModel.MessageContractAttribute(WrapperName = "SetPresetResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class SetPresetResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string PresetToken;
public SetPresetResponse()
{
}
public SetPresetResponse(string PresetToken)
{
this.PresetToken = PresetToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "ContinuousMove", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class ContinuousMoveRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string ProfileToken;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 1)]
public PTZSpeed Velocity;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 2)]
[System.Xml.Serialization.XmlElementAttribute(DataType = "duration")]
public string Timeout;
public ContinuousMoveRequest()
{
}
public ContinuousMoveRequest(string ProfileToken, PTZSpeed Velocity, string Timeout)
{
this.ProfileToken = ProfileToken;
this.Velocity = Velocity;
this.Timeout = Timeout;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "ContinuousMoveResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class ContinuousMoveResponse
{
public ContinuousMoveResponse()
{
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresetTours", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetPresetToursRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string ProfileToken;
public GetPresetToursRequest()
{
}
public GetPresetToursRequest(string ProfileToken)
{
this.ProfileToken = ProfileToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetPresetToursResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetPresetToursResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("PresetTour")]
public PresetTour[] PresetTour;
public GetPresetToursResponse()
{
}
public GetPresetToursResponse(PresetTour[] PresetTour)
{
this.PresetTour = PresetTour;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetCompatibleConfigurations", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetCompatibleConfigurationsRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
public string ProfileToken;
public GetCompatibleConfigurationsRequest()
{
}
public GetCompatibleConfigurationsRequest(string ProfileToken)
{
this.ProfileToken = ProfileToken;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName = "GetCompatibleConfigurationsResponse", WrapperNamespace = "http://www.onvif.org/ver20/ptz/wsdl", IsWrapped = true)]
public partial class GetCompatibleConfigurationsResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace = "http://www.onvif.org/ver20/ptz/wsdl", Order = 0)]
[System.Xml.Serialization.XmlElementAttribute("PTZConfiguration")]
public PTZConfiguration[] PTZConfiguration;
public GetCompatibleConfigurationsResponse()
{
}
public GetCompatibleConfigurationsResponse(PTZConfiguration[] PTZConfiguration)
{
this.PTZConfiguration = PTZConfiguration;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
public interface PTZChannel : PTZ, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.3")]
public partial class PTZClient : System.ServiceModel.ClientBase<PTZ>, PTZ
{
internal PTZClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public System.Threading.Tasks.Task<Capabilities> GetServiceCapabilitiesAsync()
{
return base.Channel.GetServiceCapabilitiesAsync();
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetNodesResponse> PTZ.GetNodesAsync(GetNodesRequest request)
{
return base.Channel.GetNodesAsync(request);
}
public System.Threading.Tasks.Task<GetNodesResponse> GetNodesAsync()
{
GetNodesRequest inValue = new GetNodesRequest();
return ((PTZ)(this)).GetNodesAsync(inValue);
}
public System.Threading.Tasks.Task<PTZNode> GetNodeAsync(string NodeToken)
{
return base.Channel.GetNodeAsync(NodeToken);
}
public System.Threading.Tasks.Task<PTZConfiguration> GetConfigurationAsync(string PTZConfigurationToken)
{
return base.Channel.GetConfigurationAsync(PTZConfigurationToken);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetConfigurationsResponse> PTZ.GetConfigurationsAsync(GetConfigurationsRequest request)
{
return base.Channel.GetConfigurationsAsync(request);
}
public System.Threading.Tasks.Task<GetConfigurationsResponse> GetConfigurationsAsync()
{
GetConfigurationsRequest inValue = new GetConfigurationsRequest();
return ((PTZ)(this)).GetConfigurationsAsync(inValue);
}
public System.Threading.Tasks.Task SetConfigurationAsync(PTZConfiguration PTZConfiguration, bool ForcePersistence)
{
return base.Channel.SetConfigurationAsync(PTZConfiguration, ForcePersistence);
}
public System.Threading.Tasks.Task<PTZConfigurationOptions> GetConfigurationOptionsAsync(string ConfigurationToken)
{
return base.Channel.GetConfigurationOptionsAsync(ConfigurationToken);
}
public System.Threading.Tasks.Task<string> SendAuxiliaryCommandAsync(string ProfileToken, string AuxiliaryData)
{
return base.Channel.SendAuxiliaryCommandAsync(ProfileToken, AuxiliaryData);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetPresetsResponse> PTZ.GetPresetsAsync(GetPresetsRequest request)
{
return base.Channel.GetPresetsAsync(request);
}
public System.Threading.Tasks.Task<GetPresetsResponse> GetPresetsAsync(string ProfileToken)
{
GetPresetsRequest inValue = new GetPresetsRequest();
inValue.ProfileToken = ProfileToken;
return ((PTZ)(this)).GetPresetsAsync(inValue);
}
public System.Threading.Tasks.Task<SetPresetResponse> SetPresetAsync(SetPresetRequest request)
{
return base.Channel.SetPresetAsync(request);
}
public System.Threading.Tasks.Task RemovePresetAsync(string ProfileToken, string PresetToken)
{
return base.Channel.RemovePresetAsync(ProfileToken, PresetToken);
}
public System.Threading.Tasks.Task GotoPresetAsync(string ProfileToken, string PresetToken, PTZSpeed Speed)
{
return base.Channel.GotoPresetAsync(ProfileToken, PresetToken, Speed);
}
public System.Threading.Tasks.Task GotoHomePositionAsync(string ProfileToken, PTZSpeed Speed)
{
return base.Channel.GotoHomePositionAsync(ProfileToken, Speed);
}
public System.Threading.Tasks.Task SetHomePositionAsync(string ProfileToken)
{
return base.Channel.SetHomePositionAsync(ProfileToken);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<ContinuousMoveResponse> PTZ.ContinuousMoveAsync(ContinuousMoveRequest request)
{
return base.Channel.ContinuousMoveAsync(request);
}
public System.Threading.Tasks.Task<ContinuousMoveResponse> ContinuousMoveAsync(string ProfileToken, PTZSpeed Velocity, string Timeout)
{
ContinuousMoveRequest inValue = new ContinuousMoveRequest();
inValue.ProfileToken = ProfileToken;
inValue.Velocity = Velocity;
inValue.Timeout = Timeout;
return ((PTZ)(this)).ContinuousMoveAsync(inValue);
}
public System.Threading.Tasks.Task RelativeMoveAsync(string ProfileToken, PTZVector Translation, PTZSpeed Speed)
{
return base.Channel.RelativeMoveAsync(ProfileToken, Translation, Speed);
}
public System.Threading.Tasks.Task<PTZStatus> GetStatusAsync(string ProfileToken)
{
return base.Channel.GetStatusAsync(ProfileToken);
}
public System.Threading.Tasks.Task AbsoluteMoveAsync(string ProfileToken, PTZVector Position, PTZSpeed Speed)
{
return base.Channel.AbsoluteMoveAsync(ProfileToken, Position, Speed);
}
public System.Threading.Tasks.Task GeoMoveAsync(string ProfileToken, GeoLocation Target, PTZSpeed Speed, float AreaHeight, float AreaWidth)
{
return base.Channel.GeoMoveAsync(ProfileToken, Target, Speed, AreaHeight, AreaWidth);
}
public System.Threading.Tasks.Task StopAsync(string ProfileToken, bool PanTilt, bool Zoom)
{
return base.Channel.StopAsync(ProfileToken, PanTilt, Zoom);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetPresetToursResponse> PTZ.GetPresetToursAsync(GetPresetToursRequest request)
{
return base.Channel.GetPresetToursAsync(request);
}
public System.Threading.Tasks.Task<GetPresetToursResponse> GetPresetToursAsync(string ProfileToken)
{
GetPresetToursRequest inValue = new GetPresetToursRequest();
inValue.ProfileToken = ProfileToken;
return ((PTZ)(this)).GetPresetToursAsync(inValue);
}
public System.Threading.Tasks.Task<PresetTour> GetPresetTourAsync(string ProfileToken, string PresetTourToken)
{
return base.Channel.GetPresetTourAsync(ProfileToken, PresetTourToken);
}
public System.Threading.Tasks.Task<PTZPresetTourOptions> GetPresetTourOptionsAsync(string ProfileToken, string PresetTourToken)
{
return base.Channel.GetPresetTourOptionsAsync(ProfileToken, PresetTourToken);
}
public System.Threading.Tasks.Task<string> CreatePresetTourAsync(string ProfileToken)
{
return base.Channel.CreatePresetTourAsync(ProfileToken);
}
public System.Threading.Tasks.Task ModifyPresetTourAsync(string ProfileToken, PresetTour PresetTour)
{
return base.Channel.ModifyPresetTourAsync(ProfileToken, PresetTour);
}
public System.Threading.Tasks.Task OperatePresetTourAsync(string ProfileToken, string PresetTourToken, PTZPresetTourOperation Operation)
{
return base.Channel.OperatePresetTourAsync(ProfileToken, PresetTourToken, Operation);
}
public System.Threading.Tasks.Task RemovePresetTourAsync(string ProfileToken, string PresetTourToken)
{
return base.Channel.RemovePresetTourAsync(ProfileToken, PresetTourToken);
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
System.Threading.Tasks.Task<GetCompatibleConfigurationsResponse> PTZ.GetCompatibleConfigurationsAsync(GetCompatibleConfigurationsRequest request)
{
return base.Channel.GetCompatibleConfigurationsAsync(request);
}
public System.Threading.Tasks.Task<GetCompatibleConfigurationsResponse> GetCompatibleConfigurationsAsync(string ProfileToken)
{
GetCompatibleConfigurationsRequest inValue = new GetCompatibleConfigurationsRequest();
inValue.ProfileToken = ProfileToken;
return ((PTZ)(this)).GetCompatibleConfigurationsAsync(inValue);
}
public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}
public virtual System.Threading.Tasks.Task CloseAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
}
}

26
EC.Helper/Onvif/RemoteDiscovery/Constants.cs

@ -0,0 +1,26 @@
namespace EC.Helper.Onvif.RemoteDiscovery;
public static class Constants
{
public static string WS_MULTICAST_ADDRESS { get; } = "239.255.255.250";
public static int WS_MULTICAST_PORT { get; } = 3702;
public static string WS_PROBE_MESSAGE { get; } =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<e:Envelope xmlns:e=\"http://www.w3.org/2003/05/soap-envelope\""
+ "xmlns:w=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\""
+ "xmlns:d=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\""
+ "xmlns:tds=\"https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl\""
+ "xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\">"
+ "<e:Header>"
+ "<w:MessageID>uuid:{0}</w:MessageID>"
+ "<w:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</w:To> "
+ "<w:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</w:Action>"
+ "</e:Header>"
+ "<e:Body>"
+ "<d:Probe><d:Types>dn:NetworkVideoTransmitter</d:Types></d:Probe>"
+ "</e:Body>"
+ "</e:Envelope>";
public static string PATTERN { get; } = @"^((onvif[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$";
}

180
EC.Helper/Onvif/RemoteDiscovery/Discovery.cs

@ -0,0 +1,180 @@
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
namespace EC.Helper.Onvif.RemoteDiscovery;
public class Discovery
{
#region Discover
/// <summary>
/// Discover new onvif devices on the network
/// </summary>
/// <param name="timeout">A timeout in seconds to wait for onvif devices</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns>a list of <see cref="DiscoveryDevice"/></returns>
/// <remarks>Use the <see cref="Discover(int, Action{DiscoveryDevice}, CancellationToken)"/>
/// overload (with an action as a parameter) if you want to retrieve devices as they reply.</remarks>
public async Task<IEnumerable<DiscoveryDevice>> DiscoverByAdapter(IEnumerable<NetworkInterface> adapterList,
int timeout, CancellationToken cancellationToken = default)
{
List<DiscoveryDevice> deviceList = new();
await Discover(adapterList, d => deviceList.Add(d), timeout, cancellationToken);
deviceList.Sort((a, b) => CastIp(a.Address).CompareTo(CastIp(b.Address)));
return deviceList;
}
/// <summary>
/// Discover new onvif devices on the network
/// </summary>
/// <param name="timeout">A timeout in seconds to wait for onvif devices</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns>a list of <see cref="DiscoveryDevice"/></returns>
/// <remarks>Use the <see cref="Discover(int, Action{DiscoveryDevice}, CancellationToken)"/>
/// overload (with an action as a parameter) if you want to retrieve devices as they reply.</remarks>
public async Task<IEnumerable<DiscoveryDevice>> DiscoverAll(int timeout, CancellationToken cancellationToken = default)
{
IEnumerable<NetworkInterface> adapterList = OnvifUdpClient.GetVaildNetworkAdapters();
IEnumerable<DiscoveryDevice> deviceList = await DiscoverByAdapter(adapterList, timeout, cancellationToken);
return deviceList;
}
/// <summary>
/// Discover new onvif devices on the network passing a callback
/// to retrieve devices as they reply
/// </summary>
/// <param name="onDeviceDiscovered">A method that is called each time a new device replies.</param>
/// <param name="timeout">A timeout in seconds to wait for onvif devices</param>
/// <param name="cancellationToken">A cancellation token</param>
/// <returns>The Task to be awaited</returns>
private async Task Discover(IEnumerable<NetworkInterface> adapterList, Action<DiscoveryDevice> onDeviceDiscovered,
int timeout, CancellationToken cancellationToken = default)
{
IEnumerable<OnvifUdpClient> clientList = OnvifUdpClient.CreateClientList(adapterList);
if (!clientList.Any())
{
throw new Exception("Missing valid NetworkInterfaces, UdpClients could not be created");
}
Task[] discoveries = clientList.Select(client => Discover(client, onDeviceDiscovered, timeout, cancellationToken)).ToArray();
await Task.WhenAll(discoveries);
}
private async Task Discover(OnvifUdpClient client, Action<DiscoveryDevice> onDeviceDiscovered, int timeout, CancellationToken cancellationToken = default)
{
Guid messageId = Guid.NewGuid();
List<UdpReceiveResult> responseList = new();
CancellationTokenSource cts = new(TimeSpan.FromSeconds(timeout));
try
{
await OnvifUdpClient.SendProbe(client, messageId);
while (true)
{
if (client.IsClosed) { return; }
if (cts.IsCancellationRequested || cancellationToken.IsCancellationRequested) { break; }
try
{
UdpReceiveResult response = await client.ReceiveAsync().WithCancellation(cancellationToken).WithCancellation(cts.Token);
if (responseList.Exists(resp => resp.RemoteEndPoint.Address.Equals(response.RemoteEndPoint.Address))) { continue; }
responseList.Add(response);
DiscoveryDevice discoveredDevice = ProcessResponse(response, messageId);
if (discoveredDevice != null)
{
await Task.Run(() => onDeviceDiscovered(discoveredDevice), cancellationToken);
}
}
catch (OperationCanceledException)
{
// Either the user canceled the action or the timeout has fired
}
catch (Exception)
{
// we catch all exceptions !
// Something might be bad in the response of a camera when call ReceiveAsync (BeginReceive in socket) fail
}
}
}
finally
{
client.Close();
}
}
#endregion Discover
#region Discover Helper
private DiscoveryDevice ProcessResponse(UdpReceiveResult response, Guid messageId)
{
if (response.Buffer == null) { return null; }
string strResponse = Encoding.UTF8.GetString(response.Buffer);
XmlProbeReponse xmlResponse = DeserializeResponse(strResponse);
if (xmlResponse.Header.RelatesTo.Contains(messageId.ToString())
&& xmlResponse.Body.ProbeMatches.Any()
&& !string.IsNullOrEmpty(xmlResponse.Body.ProbeMatches[0].Scopes))
{
return CreateDevice(xmlResponse.Body.ProbeMatches[0], response.RemoteEndPoint);
}
return null;
}
private XmlProbeReponse DeserializeResponse(string xml)
{
XmlSerializer serializer = new(typeof(XmlProbeReponse));
XmlReaderSettings settings = new();
using StringReader textReader = new(xml);
using XmlReader xmlReader = XmlReader.Create(textReader, settings);
return (XmlProbeReponse)serializer.Deserialize(xmlReader);
}
private DiscoveryDevice CreateDevice(ProbeMatch probeMatch, IPEndPoint remoteEndpoint)
{
string scopes = probeMatch.Scopes;
DiscoveryDevice discoveryDevice = new();
discoveryDevice.Address = remoteEndpoint.Address.ToString();
discoveryDevice.Model = Regex.Match(scopes, "(?<=hardware/).*?(?= )")?.Value;
discoveryDevice.Mfr = ParseMfrFromScopes(scopes);
discoveryDevice.XAdresses = ConvertToList(probeMatch.XAddrs);
discoveryDevice.Types = ConvertToList(probeMatch.Types);
return discoveryDevice;
}
private string ParseMfrFromScopes(string scopes)
{
string name = Regex.Match(scopes, "(?<=name/).*?(?= )")?.Value;
if (!string.IsNullOrEmpty(name)) { return name; }
string mfr = Regex.Match(scopes, "(?<=mfr/).*?(?= )")?.Value;
if (!string.IsNullOrEmpty(mfr)) { return mfr; }
return string.Empty;
}
private List<string> ConvertToList(string spacedListString)
{
string[] strings = spacedListString.Split(null);
List<string> list = new();
strings.ToList().ForEach(str => list.Add(str.Trim()));
return list;
}
private long CastIp(string ip)
{
byte[] addressBytes = IPAddress.Parse(ip).GetAddressBytes();
if (addressBytes.Length != 4)
{
return 0;
throw new ArgumentException("Must be an IPv4 address");
}
uint networkOrder = BitConverter.ToUInt32(addressBytes, 0);
return networkOrder;
//byte[] addressBytes = address.GetAddressBytes();
//int networkOrder = BitConverter.ToInt32(addressBytes, 0);
//return (uint)IPAddress.NetworkToHostOrder(networkOrder);
}
#endregion Discover Helper
}

30
EC.Helper/Onvif/RemoteDiscovery/DiscoveryDevice.cs

@ -0,0 +1,30 @@
namespace EC.Helper.Onvif.RemoteDiscovery;
public class DiscoveryDevice
{
/// <summary>
/// The types of this onvif device. ex: NetworkVideoTransmitter
/// </summary>
public List<string> Types { get; internal set; }
/// <summary>
/// The XAddresses of this device, the url on which the device has the webservices.
/// Normally in the form of: http://{IP}:{Port}/onvif/device_service
/// </summary>
public List<string> XAdresses { get; internal set; }
/// <summary>
/// The onvif device model
/// </summary>
public string Model { get; internal set; }
/// <summary>
/// The device manufacturer
/// </summary>
public string Mfr { get; internal set; }
/// <summary>
/// The device IP address
/// </summary>
public string Address { get; internal set; }
}

20
EC.Helper/Onvif/RemoteDiscovery/ExtensionMethods.cs

@ -0,0 +1,20 @@
namespace EC.Helper.Onvif.RemoteDiscovery;
internal static class ExtensionMethods
{
/// <summary>
/// Used to provide cancellation possibility to any Async Methods returning a Task
/// </summary>
internal static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
{
if (task != await Task.WhenAny(task, tcs.Task))
{
throw new OperationCanceledException(cancellationToken);
}
}
return await task;
}
}

136
EC.Helper/Onvif/RemoteDiscovery/OnvifUdpClient.cs

@ -0,0 +1,136 @@
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
namespace EC.Helper.Onvif.RemoteDiscovery;
public class OnvifUdpClient
{
private UdpClient client { get; set; }
public bool IsClosed { get; set; }
public OnvifUdpClient(IPEndPoint localpoint)
{
client = new UdpClient(localpoint)
{
EnableBroadcast = true
};
}
public async Task<int> SendProbeAsync(Guid messageId, IPEndPoint endPoint)
{
byte[] datagram = NewProbeMessage(messageId);
return await client?.SendAsync(datagram, datagram.Length, endPoint);
}
public async Task<UdpReceiveResult> ReceiveAsync()
{
return await client.ReceiveAsync();
}
public void Close()
{
client?.Close();
IsClosed = true;
}
public static byte[] NewProbeMessage(Guid messageId)
{
if (messageId == Guid.Empty)
{
throw new ArgumentException("messageId could not be Empty");
}
var probeMessagewithguid = string.Format(Constants.WS_PROBE_MESSAGE, messageId.ToString());
return Encoding.ASCII.GetBytes(probeMessagewithguid);
}
#region CreateClient
public static OnvifUdpClient CreateClient(NetworkInterface adapter)
{
if (!IsValidAdapter(adapter)) { return null; }
OnvifUdpClient client = null;
IPInterfaceProperties adapterProperties = adapter.GetIPProperties();
foreach (UnicastIPAddressInformation ua in adapterProperties.UnicastAddresses)
{
if (ua.Address.AddressFamily != AddressFamily.InterNetwork) { continue; }
IPEndPoint myLocalEndPoint = new(ua.Address, 0); // port does not matter
try
{
client = new(myLocalEndPoint);
}
catch (SocketException)
{
throw;
}
break;
}
return client;
}
public static IEnumerable<OnvifUdpClient> CreateClientList(IEnumerable<NetworkInterface> adapterList)
{
List<OnvifUdpClient> clientList = new();
foreach (NetworkInterface adapter in adapterList)
{
OnvifUdpClient client = CreateClient(adapter);
if (client != null) { clientList.Add(client); }
}
return clientList;
}
public static IEnumerable<OnvifUdpClient> CreateClientList()
{
IEnumerable<NetworkInterface> adapterList = GetVaildNetworkAdapters();
return CreateClientList(adapterList);
}
#endregion CreateClient
#region ClientHelper
public static List<NetworkInterface> GetNetworkAdapters()
{
NetworkInterface[] nifs = NetworkInterface.GetAllNetworkInterfaces();
return new(nifs);
}
public static List<NetworkInterface> GetVaildNetworkAdapters()
{
NetworkInterface[] nifs = NetworkInterface.GetAllNetworkInterfaces();
List<NetworkInterface> list = new();
foreach (NetworkInterface nif in nifs)
{
if (IsValidAdapter(nif)) { list.Add(nif); }
}
return list;
}
public static bool IsValidAdapter(NetworkInterface adapter)
{
// Only select interfaces that are Ethernet type and support IPv4 (important to minimize waiting time)
if (adapter.NetworkInterfaceType != NetworkInterfaceType.Ethernet &&
!adapter.NetworkInterfaceType.ToString().ToLower().StartsWith("wireless")) return false;
if (adapter.OperationalStatus == OperationalStatus.Down) { return false; }
if (!adapter.Supports(NetworkInterfaceComponent.IPv4)) { return false; }
return true;
}
/// <summary>
/// 广播
/// </summary>
/// <param name="client"></param>
/// <param name="messageId"></param>
/// <returns></returns>
public static async Task SendProbe(OnvifUdpClient client, Guid messageId)
{
IPEndPoint multicastEndpoint = new(IPAddress.Parse(Constants.WS_MULTICAST_ADDRESS), Constants.WS_MULTICAST_PORT);
await client.SendProbeAsync(messageId, multicastEndpoint);
}
#endregion ClientHelper
}

112
EC.Helper/Onvif/RemoteDiscovery/XmlProbeReponse.cs

@ -0,0 +1,112 @@
using System.Xml.Serialization;
namespace EC.Helper.Onvif.RemoteDiscovery;
/// <summary>
/// The probe response
/// </summary>
[XmlRoot("Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public class XmlProbeReponse
{
/// <summary>
/// The Header of the probe response
/// </summary>
[XmlElement(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Header Header { get; set; }
/// <summary>
/// The Body of the probe response
/// </summary>
[XmlElement(Namespace = "http://www.w3.org/2003/05/soap-envelope")]
public Body Body { get; set; }
}
/// <summary>
/// The Header of the probe response
/// </summary>
public class Header
{
/// <summary>
/// The message id
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public string MessageID { get; set; }
/// <summary>
/// The message id that relates to
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public string RelatesTo { get; set; }
/// <summary>
/// To
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public string To { get; set; }
/// <summary>
/// App sequence
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string AppSequence { get; set; }
}
/// <summary>
/// The Body of the probe response
/// </summary>
public class Body
{
/// <summary>
/// An array of probe matches
/// </summary>
[XmlArray(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public ProbeMatch[] ProbeMatches { get; set; }
}
/// <summary>
/// A probe match
/// </summary>
public class ProbeMatch
{
/// <summary>
/// The endpoint reference
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public EndpointReference EndpointReference { get; set; }
/// <summary>
/// The types
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string Types { get; set; }
/// <summary>
/// The scopes
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string Scopes { get; set; }
/// <summary>
/// The XAddrs
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string XAddrs { get; set; }
/// <summary>
/// The metadata version
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2005/04/discovery")]
public string MetadataVersion { get; set; }
}
/// <summary>
/// The endpoint reference
/// </summary>
public class EndpointReference
{
/// <summary>
/// The address
/// </summary>
[XmlElement(Namespace = "http://schemas.xmlsoap.org/ws/2004/08/addressing")]
public string Address { get; set; }
}

80
EC.Helper/Onvif/Security/SoapSecurityHeader.cs

@ -0,0 +1,80 @@
using System.Security.Cryptography;
using System.ServiceModel.Channels;
using System.Text;
using System.Xml;
namespace EC.Helper.Onvif.Security;
public class SoapSecurityHeader : MessageHeader
{
private const string ns_wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
private readonly string username;
private readonly string password;
private readonly TimeSpan time_shift;
public override string Name { get; } = "Security";
public override string Namespace { get; } = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
public SoapSecurityHeader(string username, string password, TimeSpan timeShift)
{
this.username = username;
this.password = password;
time_shift = timeShift;
}
protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
var nonce = GetNonce();
var created = DateTime.UtcNow.Add(time_shift).ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
var nonce_str = Convert.ToBase64String(nonce);
string password_hash = PasswordDigest(nonce, created, password);
writer.WriteStartElement("UsernameToken");
writer.WriteStartElement("Username");
writer.WriteValue(username);
writer.WriteEndElement();
writer.WriteStartElement("Password");
writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
writer.WriteValue(password_hash);
writer.WriteEndElement();
writer.WriteStartElement("Nonce");
writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
writer.WriteValue(nonce_str);
writer.WriteEndElement();
writer.WriteStartElement("Created");
writer.WriteXmlnsAttribute("", ns_wsu);
writer.WriteValue(created);
writer.WriteEndElement();
writer.WriteEndElement();
}
protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
{
writer.WriteStartElement("", Name, Namespace);
writer.WriteAttributeString("s", "mustUnderstand", "http://www.w3.org/2003/05/soap-envelope", "1");
writer.WriteXmlnsAttribute("", Namespace);
}
private string PasswordDigest(byte[] nonce, string created, string secret)
{
byte[] buffer = new byte[nonce.Length + Encoding.ASCII.GetByteCount(created + secret)];
nonce.CopyTo(buffer, 0);
Encoding.ASCII.GetBytes(created + password).CopyTo(buffer, nonce.Length);
return Convert.ToBase64String(SHA1.Create().ComputeHash(buffer));
}
private byte[] GetNonce()
{
byte[] nonce = new byte[0x10];
var generator = new RNGCryptoServiceProvider();
generator.GetBytes(nonce);
return nonce;
}
}

40
EC.Helper/Onvif/Security/SoapSecurityHeaderBehavior.cs

@ -0,0 +1,40 @@
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace EC.Helper.Onvif.Security;
public class SoapSecurityHeaderBehavior : IEndpointBehavior
{
private readonly string username;
private readonly string password;
private readonly TimeSpan time_shift;
public SoapSecurityHeaderBehavior(string username, string password) : this(username, password, TimeSpan.FromMilliseconds(0))
{
}
public SoapSecurityHeaderBehavior(string username, string password, TimeSpan timeShift)
{
this.username = username;
this.password = password;
time_shift = timeShift;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.ClientMessageInspectors.Add(new SoapSecurityHeaderInspector(username, password, time_shift));
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}

30
EC.Helper/Onvif/Security/SoapSecurityHeaderInspector.cs

@ -0,0 +1,30 @@
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
namespace EC.Helper.Onvif.Security;
public class SoapSecurityHeaderInspector : IClientMessageInspector
{
private readonly string username;
private readonly string password;
private readonly TimeSpan time_shift;
public SoapSecurityHeaderInspector(string username, string password, TimeSpan timeShift)
{
this.username = username;
this.password = password;
time_shift = timeShift;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Add(new SoapSecurityHeader(username, password, time_shift));
return null;
}
}
Loading…
Cancel
Save