From af3623e77d7bed209867e8a87bb1bea9b5813fef Mon Sep 17 00:00:00 2001 From: copystring <1298861+copystring@users.noreply.github.com> Date: Wed, 20 May 2026 17:16:34 +0200 Subject: [PATCH 1/3] fix endpoint refresh retry after MQTT outage --- src/lib/localApi.test.ts | 31 +++++++++++++++++++++++++++++++ src/lib/localApi.ts | 1 + 2 files changed, 32 insertions(+) diff --git a/src/lib/localApi.test.ts b/src/lib/localApi.test.ts index ec15f926bf..5d17531212 100644 --- a/src/lib/localApi.test.ts +++ b/src/lib/localApi.test.ts @@ -422,4 +422,35 @@ describe("local_api transport sequence", () => { expect(requests).to.deep.equal([{ method: "service.get_net_info", params: {} }]); expect(api.localDevices[duid].ip).to.equal("10.1.1.90"); }); + + it("does not throttle the next endpoint refresh after MQTT was temporarily unavailable", async () => { + const duid = "duid"; + const adapter = new MockAdapter() as any; + const api = new local_api(adapter); + const requests: string[] = []; + let mqttConnected = false; + + adapter.mqtt_api = { isConnected: () => mqttConnected }; + adapter.requestsHandler = { + sendRequest: async (_duid: string, method: string) => { + requests.push(method); + return [{ ip: "10.1.1.91" }]; + }, + rejectPendingTcpRequests: () => 0, + }; + adapter.getDeviceProtocolVersion = async () => "1.0"; + api.initiateClient = async () => {}; + api.localDevices[duid] = { + ip: "10.1.1.81", + version: "1.0", + staleSince: 100, + }; + + await expect(api.refreshEndpoint(duid, "mqtt down", false)).resolves.to.equal(false); + mqttConnected = true; + await expect(api.refreshEndpoint(duid, "mqtt back", false)).resolves.to.equal(true); + + expect(requests).to.deep.equal(["get_network_info"]); + expect(api.localDevices[duid].ip).to.equal("10.1.1.91"); + }); }); diff --git a/src/lib/localApi.ts b/src/lib/localApi.ts index c2cf877697..0c63b285e8 100644 --- a/src/lib/localApi.ts +++ b/src/lib/localApi.ts @@ -730,6 +730,7 @@ export class local_api { private async refreshEndpointInternal(duid: string, reason: string): Promise { if (!this.adapter.requestsHandler?.sendRequest || !this.adapter.mqtt_api?.isConnected?.()) { + this.endpointRefreshLastStartedAt.delete(duid); this.adapter.rLog("TCP", duid, "Debug", undefined, undefined, `Skipping endpoint refresh after ${reason}: MQTT unavailable.`, "debug"); return false; } From 224853e8905d2e719ed861b6c9d8b4a55c3cbb89 Mon Sep 17 00:00:00 2001 From: copystring <1298861+copystring@users.noreply.github.com> Date: Wed, 20 May 2026 17:34:38 +0200 Subject: [PATCH 2/3] fix endpoint refresh throttle cleanup timing --- src/lib/localApi.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/localApi.ts b/src/lib/localApi.ts index 0c63b285e8..8650f9152a 100644 --- a/src/lib/localApi.ts +++ b/src/lib/localApi.ts @@ -719,6 +719,12 @@ export class local_api { } const promise = this.refreshEndpointInternal(duid, reason) + .then((refreshed) => { + if (!refreshed && (!this.adapter.requestsHandler?.sendRequest || !this.adapter.mqtt_api?.isConnected?.())) { + this.endpointRefreshLastStartedAt.delete(duid); + } + return refreshed; + }) .finally(() => { this.endpointRefreshPromises.delete(duid); }); @@ -730,7 +736,6 @@ export class local_api { private async refreshEndpointInternal(duid: string, reason: string): Promise { if (!this.adapter.requestsHandler?.sendRequest || !this.adapter.mqtt_api?.isConnected?.()) { - this.endpointRefreshLastStartedAt.delete(duid); this.adapter.rLog("TCP", duid, "Debug", undefined, undefined, `Skipping endpoint refresh after ${reason}: MQTT unavailable.`, "debug"); return false; } From 81b0eb24054aa2ea5fc2151da2e4360203090664 Mon Sep 17 00:00:00 2001 From: copystring <1298861+copystring@users.noreply.github.com> Date: Wed, 20 May 2026 17:39:34 +0200 Subject: [PATCH 3/3] update changelog entry for ioBroker format --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2327da6c54..7ef1085014 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ This feature only works when map creation is enabled in the adapter options. Ope ### **WORK IN PROGRESS** * (copystring) Fixed missing auto-empty command for Roborock Qrevo MaxV (#1272). +* (copystring) Fixed local endpoint refresh after temporary MQTT outages so stale local IP recovery retries immediately again. * (copystring) Require bug reports to upload a `.txt` debug log file. ### 0.7.1 (2026-05-19)