From bbe1fd2fc2323bddcaae51fe1a6332acabbd779f Mon Sep 17 00:00:00 2001 From: Dan Cunningham Date: Sun, 29 Dec 2024 11:03:09 -0800 Subject: [PATCH] Adds peridic M-Search for devices Signed-off-by: Dan Cunningham --- .../upnp/internal/UpnpIOServiceImpl.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/bundles/org.openhab.core.io.transport.upnp/src/main/java/org/openhab/core/io/transport/upnp/internal/UpnpIOServiceImpl.java b/bundles/org.openhab.core.io.transport.upnp/src/main/java/org/openhab/core/io/transport/upnp/internal/UpnpIOServiceImpl.java index b417714002e..2deb47664d3 100644 --- a/bundles/org.openhab.core.io.transport.upnp/src/main/java/org/openhab/core/io/transport/upnp/internal/UpnpIOServiceImpl.java +++ b/bundles/org.openhab.core.io.transport.upnp/src/main/java/org/openhab/core/io/transport/upnp/internal/UpnpIOServiceImpl.java @@ -34,6 +34,9 @@ import org.jupnp.model.gena.CancelReason; import org.jupnp.model.gena.GENASubscription; import org.jupnp.model.message.UpnpResponse; +import org.jupnp.model.message.discovery.OutgoingSearchRequest; +import org.jupnp.model.message.header.UDNHeader; +import org.jupnp.model.message.header.UpnpHeader; import org.jupnp.model.meta.Action; import org.jupnp.model.meta.Device; import org.jupnp.model.meta.DeviceIdentity; @@ -46,6 +49,8 @@ import org.jupnp.model.types.UDN; import org.jupnp.registry.Registry; import org.jupnp.registry.RegistryListener; +import org.jupnp.transport.Router; +import org.jupnp.transport.RouterException; import org.openhab.core.common.ThreadPoolManager; import org.openhab.core.io.transport.upnp.UpnpIOParticipant; import org.openhab.core.io.transport.upnp.UpnpIOService; @@ -361,6 +366,7 @@ public boolean isRegistered(UpnpIOParticipant participant) { public void registerParticipant(UpnpIOParticipant participant) { if (participant != null) { participants.add(participant); + sendDeviceSearchRequest(participant); } } @@ -434,6 +440,10 @@ public UPNPPollingRunnable(UpnpIOParticipant participant, String serviceID, Stri public void run() { // It is assumed that during addStatusListener() a check is made whether the participant is correctly // registered + + // before polling, send a search request to the device to keep it registered + sendDeviceSearchRequest(participant); + try { Device device = getDevice(participant); if (device != null) { @@ -471,6 +481,27 @@ public void run() { } } + /** + * Send a device search request to the UPnP remote device. + * + * Some devices, such as LinkPlay based systems (WiiM, Arylic, etc.) loose their registrations over time. Sending a + * periodic search request will help keep the device registered. + */ + protected void sendDeviceSearchRequest(UpnpIOParticipant participant) { + try { + UpnpHeader searchTarget = new UDNHeader(new UDN(participant.getUDN())); + OutgoingSearchRequest searchRequest = new OutgoingSearchRequest(searchTarget, 5); + Router router = upnpService.getRouter(); + // this would only be null if running unit tests + if (router != null) { + router.send(searchRequest); + logger.debug("M-SEARCH query sent for device UDN: {}", searchTarget.getValue()); + } + } catch (RouterException e) { + logger.debug("Failed to send M-SEARCH", e); + } + } + @Override public void addStatusListener(UpnpIOParticipant participant, String serviceID, String actionID, int interval) { if (participant != null) {