Broadcast Discovery can't find cameras on different subnet

I am trying to discover a camera that is on a different subnet (reason is to get macAdress of camera and then force ip inside correct subnet), but no camera is shown.
I tested using BroadcastDiscovery.cpp example from cvb 13.04 for windows
that i then compiled for linux arm.
With this I am able to discover cameras only if they are already in my subnet eg.
my network card has ip 10.0.0.1 (subnet 255.255.255.0) and camera has ip 10.0.0.x
as soon as i force camera ip to 10.0.1.x then it is no more discovered.
this is code I used:

/****************************************************************************
              STEMMER IMAGING 
 ----------------------------------------------------------------------------
  Program  :  VCGEVBroadcastDiscovery
  Date     :  01/2017
  Purpose  :  C++ Console example which shows how to list all GEV devices 
              seen by a broadcast discovery
              
  Revision :  1.0
 ****************************************************************************/

#include <iostream>
#include <iomanip>
#include <vector>

#include <iCVCDriver.h>
#include <iCVCImg.h>
#include <iCVGenApi.h>
#include <CVCError.h>
#include <iCVCUtilities.h>

using namespace std;

// function to retrieve information on a discovered node
std::wstring RetriveInfo(ATLIST discoverList, size_t index, DODiscoverInfoCommands cmd)
{
  // Inquire the size of the needed buffer to receive the information
  size_t sizeBuf = 0;
  cvbres_t res = DOEntryGetInfoW(discoverList, index, cmd, NULL, sizeBuf);
  if (res < 0)
  {
    wcout << "Error retrieving info cmd " << cmd << endl;
    return std::wstring();
  }

  // allocate the buffer
  sizeBuf+=2;
  std::vector<wchar_t> buf(sizeBuf);

  // retrieve the information
  res = DOEntryGetInfoW(discoverList, index, cmd, const_cast<wchar_t *>(&buf[0]), sizeBuf);
  if (res < 0)
  {
    wcout << "Error retrieving info cmd " << cmd << endl;
    return std::wstring();
  }

  return std::wstring(&buf[0]);
}

void DiscoverOnSingleInterface(const wchar_t *Seed)
{
  ATLIST discoverListBCD = NULL;
  cvbres_t res = DODiscoverW(Seed, 
                            DO_DISCOVER_FLAG_IGNORE_VINS | 
                            DO_DISCOVER_FLAG_LEVEL_DEVICE | 
                            DO_DISCOVER_FLAG_IGNORE_ACCESS_STATUS, 
                            0, discoverListBCD, 0);
  
  // Retrieve the number of found entries
  size_t numEntries = 0;
  res = DOGetNumEntries(discoverListBCD, numEntries);
  if (res < 0)
  {
    wcout << "Failure executing discover: " << hex << showbase << res << endl;
    return;
  }

  if (numEntries > 0)
  {
    wcout << numEntries << " Device(s) found @ Iface-ID: " << RetriveInfo(discoverListBCD, 0, DO_DISCOVER_INFO_INTERFACE_ID).c_str() << endl;
    for (size_t devIdx = 0; devIdx < numEntries; devIdx++)
      wcout << "\t" << "Device " << devIdx << " -> " << RetriveInfo(discoverListBCD, devIdx, DO_DISCOVER_INFO_DEVICE_ID).c_str() << endl;
    wcout << endl;
  }
  
  ReleaseObject(discoverListBCD);
}

// entry function
int main(int argc, char* argv[])
{  
  // Execute a simple discovery 
  ATLIST discoverList = NULL;
  std::wcout << "Execute Discovery" << std::endl;
  cvbres_t res = DODiscoverW(L"", DO_DISCOVER_FLAG_IGNORE_VINS | DO_DISCOVER_FLAG_LEVEL_INTERFACE, 0, discoverList, 0);

  // Retrieve the number of found entries
  size_t numEntries = 0;
  res = DOGetNumEntries(discoverList, numEntries);
  if (res < 0)
  {
    wcout << "Failure executing discover: " << hex << showbase << res << endl;
    exit(0);
  }

  // In case there is no device found .. return 
  if (numEntries == 0)
  {
    std::wcout << "No device found." << std::endl;
    ReleaseObject(discoverList);
    exit(0);
  }
  std::wcout << "Found " << numEntries << " interfaces." << endl;
  wcout << std::endl;

  for (size_t i = 0 ; i < numEntries; i++)
  {
    if (RetriveInfo(discoverList, i, DO_DISCOVER_INFO_INTERFACE_TLTYPE).compare(L"GEV") == 0)
    {
      DOSetFeature(discoverList, i, NMH2_ID_INTERFACE, "Cust::DisableSubnetMatch", "1");
      DOSetFeature(discoverList, i, NMH2_ID_INTERFACE, "Cust::AllowBroadcastDiscoveryResponse", "1");

      wstring jat = RetriveInfo(discoverList, i, DO_DISCOVER_INFO_ACCESS_TOKEN);

      DiscoverOnSingleInterface(jat.c_str());
    }
  }

  wcout << std::endl;

  // Free Resources
  ReleaseObject(discoverList); 
  return 0;
}

1 Like

Hi @enrico ,

your code looks good to me so far.

Maybe you want to give this example a try:

auto allInterfaceFlags = Cvb::Driver::DiscoverFlags::UpToLevelInterface | Cvb::Driver::DiscoverFlags::IgnoreGevFD; 
auto allInterfaces = Cvb::DeviceFactory::Discover(allInterfaceFlags);  

// Let's say your camera is connected to the 4th interface found: 
Cvb::Driver::DiscoveryInformation& iface = allInterfaces.at(4); 
auto allDevFlags = Cvb::Driver::DiscoverFlags::IgnoreVins | Cvb::Driver::DiscoverFlags::IncludeInaccessible | Cvb::Driver::DiscoverFlags::IgnoreGevFD; 

iface.SetGenApiFeature("TLInterface", "DisableSubnetMatch", "1"); 
iface.SetGenApiFeature("TLInterface", "AllowBroadcastDiscoveryResponse", "1"); 

// Find all devices connected to that device 
auto devsFound = Cvb::DeviceFactory::Discover(iface, allDevFlags); 

if (devsFound.size() > 0) 
{ 
  auto interfaceDevice = Cvb::DeviceFactory::Open(iface.AccessToken()); 
  auto interfaceNM = interfaceDevice->NodeMap(CVB_LIT("TLInterface")); 
  auto deviceUpdateListNode = interfaceNM->Node<Cvb::CommandNode>(CVB_LIT("DeviceUpdateList")); 
  auto cfgIPNode = interfaceNM->Node<Cvb::IntegerNode>(CVB_LIT("IPCfg_IP")); 
  auto cfgSubnetNode = interfaceNM->Node<Cvb::IntegerNode>(CVB_LIT("IPCfg_Subnet")); 
  auto cfgMacNode = interfaceNM->Node<Cvb::IntegerNode>(CVB_LIT("IPCfg_MAC")); 
  auto cfgForceNode = interfaceNM->Node<Cvb::CommandNode>(CVB_LIT("IPCfg_SetForceIP")); 
  auto cfgStaticNode = interfaceNM->Node<Cvb::CommandNode>(CVB_LIT("IPCfg_SetStatIP"));  

  // make node map aware of the device 
  deviceUpdateListNode->Execute(); 

  // we want to configure the found device with MAC 
  // 00-01-0D-C2-43-66 

  // reverse: 66-43-C2-0D-01-00 
  int64_t macReverse = 0x6643c20d0100; 
  cfgMacNode->SetValue(macReverse); 

  // New IP 169.254.0.1 -> hex: 0xa9fe0001 
  cfgIPNode->SetValue(0xa9fe0001); 

  // Subnet 255.255.0.0 -> hex: 0xFFFF0000 
  cfgSubnetNode->SetValue(0xFFFF0000); 

  // Force the new IP 
  cfgForceNode->Execute(); 

  // make node map aware of new IP 
  deviceUpdateListNode->Execute(); 

  //// permanently write the IP to the camera 
  cfgStaticNode->Execute(); 
}

This is using the latest CVB++ wrappers which are closer to modern C#.
You could also check if you can find the camera in the GenICam Browser after you have set the camera to the IP of another subnet (10.0.1.x → please check what value x has, 0 or 1 might be a problem).

Also if you have two network adapters with the subnetmask 255.255.255.0.
It is very likely, that if you are on a docker container or similar, that you have an adapter that answers to the broadcast of the camera instead of the camera.

You could send us over your IPConfig if you cant find the problem.

Cheers
Chris

1 Like

Hi,

i remember a “problem” with Linux network stack, that subnet broadcasting is not implemented there.
Maybe @c.hartmann can tell us more?

1 Like

Hi @enrico ,

there are 2 things going on.

First:
Ignore Subnet Discovery. See: https://forum.commonvisionblox.com/t/ignore-subnet-discovery-on-linux/1677

Second:
You are misusing the “Force IP”. The “Force IP” actions should be used to force cameras into your subnet, not out. You will experience further issues if you intend to use a camera outside of your subnet(s).
(If you use just to configure the cameras to another network adapter then it’s fine, i.e. disregard my second comment).

Have fun,
Christopher

3 Likes

i was already writing xD

1 Like