I'm new to programming and this is my first app with ONVIF. I have a basic Windows forms app to control a fixed camera, that will stream over LAN to a Win10 PC that cannot be upgraded from .NET Framework 4.52. I'm currently receiving/recording RTSP video stream with VLC.
How do I implement zoom and focus functions to consume these PTZ services?
I need to have some basic zoom in/out buttons and probably couple the logic for the focal length/focus to adjust accordingly.
I have tried:
Following the implementation algorithm described in this answer: ONVIF: what is the command to focus in /out?
Added this Controller class to my project https://www.codeproject.com/Tips/1192709/ONVIF-PTZ-Control-in-Csharp
Using the specification, doesn't give me but some generic description I can't fully understand onvif.org/specs/srv/ptz/ONVIF-PTZ-Service-Spec-v221.pdf
Using the WSDL filed I used VS2019 to add the service reference for: device, media1, media2, ptz services. I also find it more useful for a quick reference than the specification PDF. http://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl
My approach:
- (Not my code, my comments) from the Controller.cs referenced, here is how services are accessed:
var messageElement = new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.CreateVersion(
EnvelopeVersion.Soap12, AddressingVersion.None)
};
HttpTransportBindingElement httpBinding = new HttpTransportBindingElement()
{
AuthenticationScheme = AuthenticationSchemes.Digest
};
CustomBinding bind = new CustomBinding(messageElement, httpBinding);
mediaClient = new MediaClient(bind,
new EndpointAddress($"http://{cameraAddress}/onvif/Media"));
mediaClient.ClientCredentials.HttpDigest.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
mediaClient.ClientCredentials.HttpDigest.ClientCredential.UserName = userName;
mediaClient.ClientCredentials.HttpDigest.ClientCredential.Password = password;
ptzClient = new PTZClient(bind,
new EndpointAddress($"http://{cameraAddress}/onvif/PTZ"));
ptzClient.ClientCredentials.HttpDigest.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Impersonation;
ptzClient.ClientCredentials.HttpDigest.ClientCredential.UserName = userName;
ptzClient.ClientCredentials.HttpDigest.ClientCredential.Password = password;
var profs = mediaClient.GetProfiles();//TODO: Inspect profiles returned
profile = mediaClient.GetProfile(profs[0].token);
options = ptzClient.GetConfigurationOptions(configs[0].token);
velocity = new MRML_PELCO_EXF1230_7N_Camera_Control_v1.OnvifPTZService.PTZSpeed()
{
PanTilt = new MRML_PELCO_EXF1230_7N_Camera_Control_v1.OnvifPTZService.Vector2D()
{
x = 0,
y = 0,
space = options.Spaces.ContinuousPanTiltVelocitySpace[0].URI,
},
Zoom = new MRML_PELCO_EXF1230_7N_Camera_Control_v1.OnvifPTZService.Vector1D()
{
x = 0,
//Inspect this space var:
//space = options.Spaces.ContinuousZoomVelocitySpace[0].URI, // mm/s
//specifies the change per second of the focal length
space = options.Spaces.RelativeZoomTranslationSpace[0].URI
//See page 40 of ONVIF-PTZ-Service-Spec
}
};
if (relative)
{
timer = new Timer(TimerInterval);
timer.Elapsed += Timer_Elapsed;
velocity.PanTilt.space = options.Spaces.RelativePanTiltTranslationSpace[0].URI;
panDistance = (options.Spaces.RelativePanTiltTranslationSpace[0].XRange.Max -
options.Spaces.RelativePanTiltTranslationSpace[0].XRange.Min) / PanIncrements;
tiltDistance = (options.Spaces.RelativePanTiltTranslationSpace[0].YRange.Max -
options.Spaces.RelativePanTiltTranslationSpace[0].YRange.Min) / TiltIncrements;
}
vector = new PTZVector()
{
PanTilt = new OnvifPTZService.Vector2D()
{
x = 0,
y = 0,
space = options.Spaces.RelativePanTiltTranslationSpace[0].URI
}
};
result = initialised = true;
- In the Controller class linked above, I have added the following:
//I realize this should be cleaned up but as a novice, I'm more worried about it working soon
public void zoomIn()
{
if(initialised)
{
//It is unclear if these variables were initialized correctly
translation = new PTZVector()
{ //THIS IS INCORRECT:
//Zoom = options.Spaces.RelativeZoomTranslationSpace[0].XRange.Min
};
// Actions to be performed
//Input: ReferenceToken ProfileToken, PTZVector Translation, PTZSpeed Speed
ptzClient.RelativeMove(profile.token, translation, speed);
//Other variables passed here are declared & initialized in the Controller.cs file
}
}
The issues: I'm running out of time and need to have zoom/focus working like yesterday. I will comment at some point on the specific errors outputted. For now I put this in front of expert eyes that could potentially point out my silly rookie mistakes.
p.s. I should say the camera is in a remote location so I need to gather knowledge, write anything I can, upload to a memory card and then go try in this location with slow internet on my phone as a backup i.e. the PC running the app has no internet. So yeah, not ideal.