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,
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)
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
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: