diff --git a/v2c/integrationpluginv2c.cpp b/v2c/integrationpluginv2c.cpp index 0c428e5..fba02de 100644 --- a/v2c/integrationpluginv2c.cpp +++ b/v2c/integrationpluginv2c.cpp @@ -68,13 +68,23 @@ void IntegrationPluginV2c::setupThing(ThingSetupInfo *info) const quint16 port = static_cast(thing->paramValue(trydanThingPortParamTypeId).toUInt()); const quint16 slaveId = 1; // V2C Trydan always uses unit ID 1 - TrydanModbusTcpMaster *master = new TrydanModbusTcpMaster( - monitor->networkDeviceInfo().address(), port, slaveId, thing); + // Prefer the monitor's cached address (ARP/mDNS already resolved) but fall back + // to the stored address param. The monitor has a null address at first + // registerMonitor() when the device was added by IP (createMethod "user") or when + // nymead restarts before the monitor's ARP scan completes — connecting to a null + // QHostAddress would produce "device ':502'" and fail immediately. + QHostAddress address = monitor->networkDeviceInfo().address(); + if (address.isNull()) + address = QHostAddress(thing->paramValue(trydanThingAddressParamTypeId).toString()); - // Update target IP if the device gets a new DHCP lease. + TrydanModbusTcpMaster *master = new TrydanModbusTcpMaster(address, port, slaveId, thing); + + // Update target IP when DHCP renews. Guard against transient null info that + // the monitor can emit during its own internal refresh cycles. connect(monitor, &NetworkDeviceMonitor::networkDeviceInfoChanged, master, [master](const NetworkDeviceInfo &info) { - master->setHostAddress(info.address()); + if (!info.address().isNull()) + master->setHostAddress(info.address()); }); // Abort the setup if the info object is destroyed before we finish.