How to set the IP Address of a Camera in CVB

Hello everyone!
I have read through the following Thread:
How to set a the IP-Address of GEV-Camera programmatically in CVB - Programming Questions / C++ API - Common Vision Blox User Forum

What Andreas coded it’s an example of what I’d like to re-create in Python, basically setting a static IP Address on a Camera that is or is not in my subnet.
Changing one by one with the GenICam software it is easy, but I would like to automate the process thanks to a Network Switch and Python, in order to get the job done quicker and spend energies and resources on something else in the meantime.
I have tried to code something similar, but without success.
I have not found much on the documentation unfortunately (or maybe it’s just me being blind).

Does anybody know how to solve this one?
Many thanks,

Axel

@axelprinceton
Hey!

I haven’t actually done that, but from looking at the C++ code (or C# https://forum.commonvisionblox.com/t/exception-during-discovery/318/8 ), this should be possible. All the functions should also be available in Python.

Do you have any idea why your version fails? Maybe we can solve it together :slight_smile:

Best Regards,
Silas

Hello @silas, thanks for your answer.

Forgot to mention that I am working with cvbpy 1.5, on python 3.10.9 (conda) and CVB 14.00.002 on Windows.

I believe part of my code may be incorrect, also I do believe it is incorrect to open the device with the access token, but as the first link and your link suggest, the interface needs to be accessed instead.

import os
import time
import ipaddress
import socket
import cvb


cameras = {}

        print("Looking for Cameras...")

        iflags = cvb.DiscoverFlags.UpToLevelInterface | cvb.DiscoverFlags.IgnoreGevSD
        all_interfaces = cvb.DeviceFactory.discover_from_root(iflags)

        bflags = (cvb.DiscoverFlags.IgnoreVins | cvb.DiscoverFlags.IncludeInaccessible | cvb.DiscoverFlags.IgnoreGevSD)

        for interface in all_interfaces:
            cvb.DiscoveryInformation.set_genapi_feature(interface, "TLInterface", "DisableSubnetMatch", "1")
            cvb.DiscoveryInformation.set_genapi_feature(interface, "TLInterface", "AllowBroadcastDiscoveryResponse", "1")
            found_devices = cvb.DeviceFactory.discover_from_level(interface.access_token, bflags)

            if len(found_devices) > 0:
                print(f"{len(found_devices)} devices discovered.")

                for i in range(len(found_devices)):
                    access = found_devices[i].access_token
                    devsn = found_devices[i].read_property(cvb.DiscoveryProperties.DeviceSerialNumber)
                    devip = found_devices[i].read_property(cvb.DiscoveryProperties.DeviceIP)
                    devmac = found_devices[i].read_property(cvb.DiscoveryProperties.DeviceMac)
                    accstat = found_devices[i].read_property(cvb.DiscoveryProperties.DeviceAccessStatus)

                    if devip not in [camera_info["IP"] for camera_info in cameras.values()]:
                        camera_name = f"cam{len(cameras)}"
                        cameras[camera_name] = {"SN": devsn, "IP": devip, "MAC": devmac, "Access Status":accstat}

                for i, camera in enumerate(cameras, start=1):
                    print(f"{i}. Camera {camera}: {cameras[camera]}")
                    print("")
                
                choice = input("Choose a camera (1-{}), or press 'Enter' to rescan: ".format(len(cameras)))
                if choice.isdigit() and 1 <= int(choice) <= len(cameras):
                    camera_name = "cam{}".format(int(choice)-1)
                    print("You selected {}.".format(cameras[camera_name]["SN"]))
                    print("")
                    time.sleep(1)
                    os.system("cls")


#rest of my code....



#snippet

elif mchoice == "15":
                        ipconst = "10.2"

                        room_n = int(input("Enter the Room number: "))
                        if room_n < 10:
                            room = f".10{room_n}"
                        elif room_n >= 40:
                            print("Number is too great")
                        else:
                            room = f".1{room_n}"

                        camera_number = int(input("Enter the camera number (0-5): "))
                        if camera_number == 0:
                            cam = ".11"
                        elif camera_number == 1:
                            cam = ".12"
                        elif camera_number == 2:
                            cam = ".13"
                        elif camera_number == 3:
                            cam = ".14"
                        elif camera_number == 4:
                            cam = ".15"
                        elif camera_number == 5:
                            cam = ".16"
                        else:
                            print("Invalid camera number")

                        time.sleep(1)

                        ip = ipconst + room + cam
                        subnet = "255.255.255.0"

                        ip_address = ipaddress.ip_address(ip)
                        sub_address = ipaddress.ip_address(subnet)

                        hex_ip = socket.inet_aton(str(ip_address)).hex()
                        hex_sub = socket.inet_aton(str(sub_address)).hex()

                        print(ip)
                        print(hex_ip)
                        print(hex_sub)

                        with cvb.DeviceFactory.open(access) as device:
                            deviceUpdateListNode = cvb.CommandNode("DeviceUpdateList")
                            cfgIPNode = cvb.IntegerNode("IPCfg_IP")
                            cfgSubnetNode = cvb.IntegerNode("IPCfg_Subnet")
                            cfgForceNode = cvb.CommandNode("IPCfg_SetForceIP")
                            cfgStaticNode = cvb.CommandNode("IPCfg_SetStatIP")

                            deviceUpdateListNode.execute()
                            cfgIPNode.value(hex_ip)
                            cfgSubnetNode.value(hex_sub)
                            cfgForceNode.execute()
                            deviceUpdateListNode.execute()
                            cfgStaticNode.execute()

                            print("IP address Flashed: " + ip) 
                            time.sleep(2)
                            os.system("cls")
                            time.sleep(1)


Thanks again for your help!

Axel

@axelprinceton
Hey there!

I think the issue is caused by the following lines of your code:

with cvb.DeviceFactory.open(access) as device:
    deviceUpdateListNode = cvb.CommandNode("DeviceUpdateList")
    cfgIPNode = cvb.IntegerNode("IPCfg_IP")
    cfgSubnetNode = cvb.IntegerNode("IPCfg_Subnet")
    cfgForceNode = cvb.CommandNode("IPCfg_SetForceIP")
    cfgStaticNode = cvb.CommandNode("IPCfg_SetStatIP")

Here, you create new Command/Integer Nodes, but they aren’t referenced to any device.

If you have a look at the C# example I sent you, there is a method called ‘ForceIP’ that does the same thing, but it gets the nodes from the passed-in ‘iface’ NodeMap. This way it should be referenced :slight_smile:

var ifaceToOpen = allInterfaces
  .First(iface => iface[DiscoveryProperties.InterfaceId] == cam[DiscoveryProperties.InterfaceId]);
		
using (var ifaceDevice = DeviceFactory.Open(ifaceToOpen))
{
  ForceIP(ifaceDevice.NodeMaps[NodeMapNames.Interface], cam, newIP);
}

static void ForceIP(NodeMap iface, DiscoveryInformation camera, IPAddress newIP)
{
  var macAddress = PhysicalAddress.Parse(camera[DiscoveryProperties.DeviceMac]);
  var subnet = GetInterfaceSubnetMask(camera);
	
  var updateDeviceList = iface["DeviceUpdateList"] as CommandNode;
  updateDeviceList.Execute();
		
  var cfgMac = iface["IPCfg_MAC"] as IntegerNode;
  cfgMac.Value = MacToInt(macAddress);
  var cfgIP = iface["IPCfg_IP"] as IntegerNode;
  cfgIP.Value = IPToInt(newIP);
  var cfgSubnet = iface["IPCfg_Subnet"] as IntegerNode;
  cfgSubnet.Value = IPToInt(subnet);
  var cfgForceIP = iface["IPCfg_SetForceIP"] as CommandNode;
  cfgForceIP.Execute();
}

In Python, you’ll access the needed Nodemap with the following code:

import os 
import cvb  
import ipaddress

# Load driver  
device = cvb.DeviceFactory.open(os.path.join(cvb.install_path(), "drivers", "GenICam.vin"), port=0) 

#Load Interface NodeMap for the device  
dev_node_map = device.node_maps["TLInterface"]   
IPcfg = dev_node_map["IPCfg_IP"]  
print("IPcfg: " + str(ipaddress.IPv4Address(IPcfg.value))) 
IPcfg.value = int(ipaddress.IPv4Address("192.168.1.48"))
print("IPcfg: " + str(ipaddress.IPv4Address(IPcfg.value))) 

Here are all the nodes that the ‘Interface’ Nodemap holds. You can look at them yourself in the GenICam Browser :slight_smile:

I hope that helped you. If you need further assistance, feel free to come back to me :slight_smile:

Regards
Silas