I'm currently trying to switch the state of a relay-output on several test cameras (all Onvif compliant). The confusion starts when trying to retrieve the list of relay-outputs for an Hikvision PTZ camera. I can successfully get the relay-output(it only has 1) and ask for its 'RelayLogicalState' which can be either open or closed.
For switching the relay-output I use the 'SetRelayOutputState', its parameters are the token of the relay-output to switch and a 'RelayLogicalState'. Since there is only 1 relay-output I can only send that token, the 'RelayLogicalState' is an enum of 2 items (active or inactive) not much to do wrong here. I can switch the state of the relay-output but when calling 'GetrelayOutputs' again to check its state this function will always set the input to 'inactive'.
For BOSCH I can retrieve the relay-output again only 1 is present but calling 'SetRelayOutputState' does nothing with either of the 2 'RelayLogicalState' when called.
For reference: http://www.onvif.org/ver10/deviceio.wsdl
Both cameras have the latest firmware installed and according to the Onvif Device Manager both use Onvif version 2.0.
private void OutputLowButton_Click(object sender, EventArgs e)
{
if (relayOutputs != null)
{
//only 1 present so we take the first for this example
var output = relayOutputs.First();
execute(() => IOClient.SetRelayOutputState(output.token, RelayLogicalState.inactive));
}
}
private void OutputHighButton_Click(object sender, EventArgs e)
{
if (relayOutputs != null)
{
//only 1 present so we take the first for this example
var output = relayOutputs.First();
execute(() => IOClient.SetRelayOutputState(output.token, RelayLogicalState.active));
}
}
private void OutputStateButton_Click(object sender, EventArgs e)
{
//only 1 present so we take the first for this example
var relayOutputs = execute(() => IOClient.GetRelayOutputs());
if(relayOutputs != null)
MessageBox.Show(relayOutputs.First().Properties.IdleState.ToString());
}
EDIT
Eventually I got it working in the following manner:
relayOutput.Properties.Mode = Onv_Device_Management.RelayMode.Bistable;
relayOutput.Properties.IdleState = Onv_Device_Management.RelayIdleState.open;
TryCatch(() => deviceClient.SetRelayOutputSettingsAsync(relayOutput.token, relayOutput.Properties));
TryCatch(() => deviceClient.SetRelayOutputState(relayOutput.token, Onv_Device_Management.RelayLogicalState.active));
I had some problem with that too. There is another onvif function called SetRelayOutputSettings
. You have couple of settings there:
idleState
open/close
delayTime
time when if mode is "monostable" it will come back to idleState
Mode
bistable - you have to handle changing state by yourself
monostable - after you set state, it will come back to idleState after "delayTime"
Of course you have to deliver Token there also. Still to solve problem I had to call functions in this sequence(pseudocode I am not c#):
void SetState(string token, bool bOpen) // true if high, false if low
{
SetRelayOutputSettings(token, bOpen, "bistable", 20);
SetRelayOutputState(token, "active");
SetRelayOutputState(token, "inactive");
}
Hope that help you.