Architecture choice: Modbus TCP has no network discovery mechanism, so
discovery piggybacks on nymea's NetworkDeviceDiscovery (ARP/mDNS scan)
and then probes each host via GET /RealTimeData (V2C Trydan HTTP REST API).
The presence of a "Paused" field in the JSON response is used as a Trydan
fingerprint — it matches the charger model and is absent on generic devices.
cf. evcc charger/trydan.go realTimeData struct.
Probes run concurrently (one QNetworkReply per host) but the sequence
terminates via two independent paths that could both fire:
1. The NetworkDeviceDiscoveryReply::finished callback arms a 3-second
QTimer::singleShot to give outstanding probes time to complete.
2. Each probe completion path checks (m_scanFinished && pendingProbes==0)
and calls finishDiscovery() early if all probes are already done.
A m_finished bool guard prevents double-emission of discoveryFinished()
if both paths fire in quick succession (e.g. all probes complete exactly
as the timer fires).
Manual-entry (createMethod "user") skips discovery entirely; setupThing()
is called directly with the user-supplied IP.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>