Balluff - BVS CA-GT Technical Documentation
Using the primary application switchover functionality

There are scenarios where a second application should take control over a device that is already under control of another (primary) application (e.g. systems which requires redundancy, fault recovery or systems with a higher level management entity).

The switchover procedure will look like this: The primary application

  1. requests (and gets granted) exclusive access,
  2. verifies that the device supports switchover consulting GVCP capability register,
  3. sets the control switchover key register,
  4. requests (and gets granted) control access with enabled switchover (this is done without closing the control channel),

Another application that knows the key, can request (and gets granted) device control.

You can enable the switchover via "Device → PrimaryApplicationSwitchoverEnable". Set this register to "On" to allow other applications to take control over the device.

Figure 1: ImpactControlCenter - Device PrimaryApplicationSwitchoverEnable

If the control access has been granted, "DesiredAccess", "PrimaryApplicationSwitchoverEnable" and "PrimaryApplicationSwitchoverKey" will become read-only.

Now, in "Setting → Base → Camera → GenICam → Transport Layer Control" the property "Gev Primary Application Switchover Key" can be used by the control application to define a value that must be specified by an application that wants to take over control over the device. E.g. "666":

Figure 2: ImpactControlCenter - Gev Primary Application Switchover Key

The other application now tries to take over control with the correct switchover key and this access is granted. As a result the first application can no longer write to the device (executing "int timestampLatch()" fails with "DEV_ACCESS_DENIED").

Figure 3: ImpactControlCenter - Application Switchover
Note
If the other application tries to take over control without specifying the correct switchover key, an "DEV_ACCESS_DENIED" error will appear.

Code samples

The following code samples show, how to create functions which

  • bind and set a property,
  • how to configure the switchover access and
  • how to take over the control.
//-----------------------------------------------------------------------------
template<typename _Ty, typename _Tx>
void bindAndSetProperty( _Ty& prop, ComponentLocatorBase& locator, const string& propName, 
const _Tx& value )
//-----------------------------------------------------------------------------
{
  locator.bindComponent( prop, propName );
  if( prop.isValid() )
  {
    try
    {
      prop.write( value );
      cout << "Property '" << propName << "' set to '" << prop.readS() << "'." << endl; 
      // read back the value from the property in order to notice any rounding(e.g. for 
      // properties defining a setp width)
    }
    catch( const ImpactAcquireException& e )
    {
      cout << "Failed to write '" << value << "' to property '" << propName << "'. Error message: " 
      << e.getErrorString() << endl;
      displayPropertyData( prop );
    }
  }
  else
  {
    cout << "Property '" << propName << "' is not supported by this device or could not be located." 
    << endl;
  }
}

//-----------------------------------------------------------------------------
void configureControlAccessWithSwitchoverEnabled( Device* pDev, int64_type key )
//-----------------------------------------------------------------------------
{
  try
  {
    ComponentLocator locator(pDev->hDev());
    PropertyIBoolean primaryApplicationSwitchoverEnable;
    bindAndSetProperty( primaryApplicationSwitchoverEnable, locator, 
     "PrimaryApplicationSwitchoverEnable", bTrue );
    pDev->interfaceLayout.write( dilGenICam );
    pDev->desiredAccess.write( damControl );
    pDev->open();
    DeviceComponentLocator devLocator(pDev, dltSetting);
    PropertyI64 gevPrimaryApplicationSwitchoverKey;
    bindAndSetProperty( gevPrimaryApplicationSwitchoverKey, locator, 
     "GevPrimaryApplicationSwitchoverKey", key );
  }
  catch( const ImpactAcquireException& e )
  {
    cout << string(__FUNCTION__) << ": " << e.getErrorString() << "(" 
    << e.getErrorCodeAsString() << ") occurred at line " << e.getErrorOrigin() << endl;
  }
}

//-----------------------------------------------------------------------------
void takeOverControlAccess( Device* pDev, int64_type key, bool boKeepSwitchoverPossible )
//-----------------------------------------------------------------------------
{
  try
  {
    ComponentLocator locator(pDev->hDev());
    PropertyIBoolean primaryApplicationSwitchoverEnable;
    bindAndSetProperty( primaryApplicationSwitchoverEnable, locator, 
    "PrimaryApplicationSwitchoverEnable", boKeepSwitchoverPossible ? bTrue : bFalse );
    PropertyI64 primaryApplicationSwitchoverKey;
    bindAndSetProperty( primaryApplicationSwitchoverKey, locator, 
    "PrimaryApplicationSwitchoverKey", key );
    pDev->interfaceLayout.write( dilGenICam );
    pDev->desiredAccess.write( damControl );
    pDev->open();
  }
  catch( const ImpactAcquireException& e )
  {
    cout << string(__FUNCTION__) << ": " << e.getErrorString() << "(" 
    << e.getErrorCodeAsString() << ") occurred at line " << e.getErrorOrigin() << endl;
  }
}