You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
5.4 KiB
270 lines
5.4 KiB
using EC.Onvif.Common;
|
|
using EC.Onvif.Device;
|
|
using EC.Onvif.Imaging;
|
|
using EC.Onvif.Media;
|
|
using EC.Onvif.PTZ;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using Capabilities = EC.Onvif.Common.Capabilities;
|
|
|
|
namespace EC.Onvif
|
|
{
|
|
public class OnvifClient
|
|
{
|
|
#region Attr
|
|
|
|
public string Hostname { get; private set; }
|
|
|
|
public string Username { get; private set; }
|
|
|
|
public string Password { get; private set; }
|
|
|
|
public static float atomDist { get; private set; } = 0.01f;
|
|
|
|
public static float atomSpeed { get; private set; } = 0.1f;
|
|
|
|
#endregion Attr
|
|
|
|
#region Client Attr
|
|
|
|
private DeviceClient Device { get; set; }
|
|
|
|
private MediaClient Media { get; set; }
|
|
|
|
private PTZClient PTZ { get; set; }
|
|
|
|
private ImagingClient Imaging { get; set; }
|
|
|
|
private Capabilities Caps { get; set; }
|
|
|
|
#endregion Client Attr
|
|
|
|
#region Settings Attr
|
|
|
|
private string profileToken { get; set; }
|
|
|
|
private string videoSourceToken { get; set; }
|
|
|
|
#endregion Settings Attr
|
|
|
|
public OnvifClient(string hostname, string username, string password)
|
|
{
|
|
Hostname = hostname;
|
|
Username = username;
|
|
Password = password;
|
|
}
|
|
|
|
public async Task 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)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#region DeviceClient
|
|
|
|
public bool IsDeviceContected()
|
|
{
|
|
return Device != null;
|
|
}
|
|
|
|
#endregion DeviceClient
|
|
|
|
#region MediaClient
|
|
|
|
public bool IsMediaContected()
|
|
{
|
|
bool ret = IsDeviceContected();
|
|
return ret;
|
|
}
|
|
|
|
private StreamSetup RtspStreamSetup { get; } = new()
|
|
{
|
|
Stream = StreamType.RTPUnicast,
|
|
Transport = new() { Protocol = TransportProtocol.RTSP }
|
|
};
|
|
|
|
public async Task<string> GetStreamUri()
|
|
{
|
|
MediaUri mediaUri = await Media.GetStreamUriAsync(RtspStreamSetup, profileToken);
|
|
return mediaUri.Uri;
|
|
}
|
|
|
|
public async Task<string> GetSnapshotUri()
|
|
{
|
|
MediaUri mediaUri = await Media.GetSnapshotUriAsync(profileToken);
|
|
return mediaUri.Uri;
|
|
}
|
|
|
|
#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>
|
|
/// <returns></returns>
|
|
public async Task AbsoluteMove(float pan, float tilt, float zoom)
|
|
{
|
|
await PTZ.AbsoluteMoveAsync(profileToken, new PTZVector
|
|
{
|
|
PanTilt = new Vector2D
|
|
{
|
|
x = pan,
|
|
y = tilt
|
|
},
|
|
Zoom = new Vector1D
|
|
{
|
|
x = zoom
|
|
}
|
|
}, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 相对移动
|
|
/// </summary>
|
|
/// <param name="pan"></param>
|
|
/// <param name="tilt"></param>
|
|
/// <param name="zoom"></param>
|
|
public async Task RelativeMove(float pan, float tilt, float zoom)
|
|
{
|
|
await PTZ.RelativeMoveAsync(profileToken, new PTZVector
|
|
{
|
|
PanTilt = new Vector2D
|
|
{
|
|
x = pan,
|
|
y = tilt
|
|
},
|
|
Zoom = new Vector1D
|
|
{
|
|
x = zoom
|
|
}
|
|
}, null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 持续移动
|
|
/// </summary>
|
|
/// <param name="pan">0~100</param>
|
|
/// <param name="tilt">0~100</param>
|
|
/// <param name="zoom">0~100</param>
|
|
public async Task ContinuousMove(float pan, float tilt, float zoom)
|
|
{
|
|
await PTZ.ContinuousMoveAsync(profileToken, new PTZSpeed
|
|
{
|
|
PanTilt = new Vector2D
|
|
{
|
|
x = pan,
|
|
y = tilt
|
|
},
|
|
Zoom = new Vector1D
|
|
{
|
|
x = zoom
|
|
}
|
|
}, null);
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|