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

Hello Silas.

Sorry for the long wait, been on and off multiple projects!
I have tried your resolution and followed your advice.
I have also adapted your example to my code to match it and make it work the way intended.
Unfortunately, none of the node maps really changed, the IP/Subnet/gateway stay 0.0.0.0 on:
IPCfg_IP / IPCfg_Subnet and IPCfg_Gateway even by doing it manually via GenICam browser.

By using the access token “access = found_devices[i].access_token” the code you provided me runs just fine, but yet no change on IP address of the actual camera.

While by using this one:

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

unfortunately it throws me an error:

    access = cvb.DeviceFactory.open(os.path.join(cvb.install_path(), "drivers", "GenICam.vin"), port=0)
RuntimeError: C-API call failed; try getting a log by using CVB LogGUI/silogutil: {"Name": "LoadImageFileW", "CVC_ERROR_CODE": 1}

While on LogGUI I don’t see any logs.

Now I am wondering if there is a way to change the IP address without accessing the camera nodemaps, the same way I do manually by right-clicking the camera in GenICam Browser and selecting Assign IP, as the nodemaps related to them are all read-only if the camera is accessed via token.

image
image

Basically, instead of editing the nodemaps, I will edit what’s in the NIC.

Many thanks,

Axel Princeton

@axelprinceton
Hey!

Sorry for the delayed response. I was out of the office :slight_smile:

I think you identified the problem in the last line. As of my knowledge, if your NIC is set to DHCP, you can’t set a persistent static IP that is outside of your network range. If you set the desired range in your NIC, the code should work.

Thanks and regards
Silas