From f189e9dc4ec1c29157c5dc024226f87015957e43 Mon Sep 17 00:00:00 2001 From: Andreas Lanz Date: Fri, 24 Oct 2025 22:53:55 +0200 Subject: [PATCH 1/5] [boschindego] Add support for multiple accounts / bridges Signed-off-by: Andreas Lanz --- .../org.openhab.binding.boschindego/README.md | 2 +- .../console/BoschIndegoCommandExtension.java | 90 ++++++++++++++++--- 2 files changed, 79 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.binding.boschindego/README.md b/bundles/org.openhab.binding.boschindego/README.md index 2cfd0505a833c..a0c86a335d97f 100644 --- a/bundles/org.openhab.binding.boschindego/README.md +++ b/bundles/org.openhab.binding.boschindego/README.md @@ -25,7 +25,7 @@ To authorize, please follow these steps: - With developer tools showing on the right, go to [Bosch Indego login page](https://prodindego.b2clogin.com/prodindego.onmicrosoft.com/b2c_1a_signup_signin/oauth2/v2.0/authorize?redirect_uri=com.bosch.indegoconnect://login&client_id=65bb8c9d-1070-4fb4-aa95-853618acc876&response_type=code&scope=openid%20offline_access%20https://prodindego.onmicrosoft.com/indego-mobile-api/Indego.Mower.User) again. - "Please wait..." should now be displayed. - Find the `authresp` and copy the code: `com.bosch.indegoconnect://login/?code=` -- Use the openHAB console to authorize with this code: `openhab:boschindego authorize ` +- Use the openHAB console to authorize with this code (`` is optional if only one bridge is defined): `openhab:boschindego [] authorize ` ### `indego` Thing Configuration diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java index d21bb01ec72ec..57b22831a56fb 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java @@ -12,8 +12,9 @@ */ package org.openhab.binding.boschindego.internal.console; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -27,7 +28,7 @@ import org.openhab.core.io.console.extensions.ConsoleCommandExtension; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingRegistry; -import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.ThingUID; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -54,26 +55,53 @@ public BoschIndegoCommandExtension(final @Reference ThingRegistry thingRegistry) @Override public void execute(String[] args, Console console) { - if (args.length != 2 || !AUTHORIZE.equals(args[0])) { + String authCode; + Thing bridge; + + if (args.length == 2 && AUTHORIZE.equals(args[0])) { + try { + bridge = getSingleBridge(); + } catch (IllegalStateException e) { + console.println("Error finding indego bridge: " + e.getMessage()); + printUsage(console); + return; + } + + if (bridge == null) { + console.println("No BoschIndego Bridge defined."); + return; + } + + authCode = args[1]; + } else if (args.length == 3 && AUTHORIZE.equals(args[1])) { + bridge = getBridgeById(args[0]); + if (bridge == null) { + console.println("Unknown thing id '" + args[0] + "'"); + return; + } + + authCode = args[2]; + } else { printUsage(console); return; } - for (Thing thing : thingRegistry.getAll()) { - ThingHandler thingHandler = thing.getHandler(); - if (thingHandler instanceof BoschAccountHandler accountHandler) { - try { - accountHandler.authorize(args[1]); - } catch (IndegoAuthenticationException e) { - console.println("Authorization error: " + e.getMessage()); - } + if (bridge.getHandler() instanceof BoschAccountHandler accountHandler) { + try { + accountHandler.authorize(authCode); + } catch (IndegoAuthenticationException e) { + console.println("Authorization error: " + e.getMessage()); } + } else { + console.println("Bridge is not a valid BoschIndego bridge"); + printUsage(console); } } @Override public List getUsages() { - return Arrays.asList(buildCommandUsage(AUTHORIZE, "authorize by authorization code")); + return List + .of(buildCommandUsage("[] " + AUTHORIZE + " ", "authorize by authorization code")); } @Override @@ -84,8 +112,46 @@ public List getUsages() { @Override public boolean complete(String[] args, int cursorArgumentIndex, int cursorPosition, List candidates) { if (cursorArgumentIndex <= 0) { + return new StringsCompleter( + Stream.concat(Stream.of(AUTHORIZE), getBridgeIds().stream().map(ThingUID::getAsString)).toList(), + false).complete(args, cursorArgumentIndex, cursorPosition, candidates); + } else if (cursorArgumentIndex == 1 && !AUTHORIZE.equals(args[0])) { return SUBCMD_COMPLETER.complete(args, cursorArgumentIndex, cursorPosition, candidates); } return false; } + + private List getBridgeIds() { + List bridgeIds = new ArrayList<>(); + for (Thing thing : thingRegistry.getAll()) { + if (thing.getHandler() instanceof BoschAccountHandler) { + bridgeIds.add(thing.getUID()); + } + } + return bridgeIds; + } + + private @Nullable Thing getBridgeById(String uid) { + Thing thing; + try { + ThingUID thingUID = new ThingUID(uid); + thing = thingRegistry.get(thingUID); + } catch (IllegalArgumentException e) { + thing = null; + } + return thing; + } + + private @Nullable Thing getSingleBridge() { + Thing bridge = null; + for (Thing thing : thingRegistry.getAll()) { + if (thing.getHandler() instanceof BoschAccountHandler) { + if (bridge != null) { + throw new IllegalStateException("More than one BoschIndego Bridge found."); + } + bridge = thing; + } + } + return bridge; + } } From 91ade7fc9d47bccb349f776ef9428327a3c50d33 Mon Sep 17 00:00:00 2001 From: Andreas Lanz Date: Sun, 26 Oct 2025 00:03:28 +0200 Subject: [PATCH 2/5] [boschindego] Making bridgeId mandatory and use Id instead of Uid Signed-off-by: Andreas Lanz --- .../org.openhab.binding.boschindego/README.md | 2 +- .../console/BoschIndegoCommandExtension.java | 79 +++++-------------- 2 files changed, 22 insertions(+), 59 deletions(-) diff --git a/bundles/org.openhab.binding.boschindego/README.md b/bundles/org.openhab.binding.boschindego/README.md index a0c86a335d97f..95cd8a0805a54 100644 --- a/bundles/org.openhab.binding.boschindego/README.md +++ b/bundles/org.openhab.binding.boschindego/README.md @@ -25,7 +25,7 @@ To authorize, please follow these steps: - With developer tools showing on the right, go to [Bosch Indego login page](https://prodindego.b2clogin.com/prodindego.onmicrosoft.com/b2c_1a_signup_signin/oauth2/v2.0/authorize?redirect_uri=com.bosch.indegoconnect://login&client_id=65bb8c9d-1070-4fb4-aa95-853618acc876&response_type=code&scope=openid%20offline_access%20https://prodindego.onmicrosoft.com/indego-mobile-api/Indego.Mower.User) again. - "Please wait..." should now be displayed. - Find the `authresp` and copy the code: `com.bosch.indegoconnect://login/?code=` -- Use the openHAB console to authorize with this code (`` is optional if only one bridge is defined): `openhab:boschindego [] authorize ` +- Use the openHAB console to authorize with this code: `openhab:boschindego authorize ` ### `indego` Thing Configuration diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java index 57b22831a56fb..ba0afb82308cf 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java @@ -12,9 +12,9 @@ */ package org.openhab.binding.boschindego.internal.console; -import java.util.ArrayList; +import static org.openhab.binding.boschindego.internal.BoschIndegoBindingConstants.THING_TYPE_ACCOUNT; + import java.util.List; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -55,34 +55,18 @@ public BoschIndegoCommandExtension(final @Reference ThingRegistry thingRegistry) @Override public void execute(String[] args, Console console) { - String authCode; - Thing bridge; - if (args.length == 2 && AUTHORIZE.equals(args[0])) { - try { - bridge = getSingleBridge(); - } catch (IllegalStateException e) { - console.println("Error finding indego bridge: " + e.getMessage()); - printUsage(console); - return; - } - - if (bridge == null) { - console.println("No BoschIndego Bridge defined."); - return; - } + if (args.length != 3 || !AUTHORIZE.equals(args[1])) { + printUsage(console); + return; + } - authCode = args[1]; - } else if (args.length == 3 && AUTHORIZE.equals(args[1])) { - bridge = getBridgeById(args[0]); - if (bridge == null) { - console.println("Unknown thing id '" + args[0] + "'"); - return; - } + String bridgeId = args[0]; + String authCode = args[2]; - authCode = args[2]; - } else { - printUsage(console); + Thing bridge = getBridgeById(bridgeId); + if (bridge == null) { + console.println("Unknown bridge id '" + bridgeId + "'"); return; } @@ -101,7 +85,7 @@ public void execute(String[] args, Console console) { @Override public List getUsages() { return List - .of(buildCommandUsage("[] " + AUTHORIZE + " ", "authorize by authorization code")); + .of(buildCommandUsage(" " + AUTHORIZE + " ", "authorize by authorization code")); } @Override @@ -112,46 +96,25 @@ public List getUsages() { @Override public boolean complete(String[] args, int cursorArgumentIndex, int cursorPosition, List candidates) { if (cursorArgumentIndex <= 0) { - return new StringsCompleter( - Stream.concat(Stream.of(AUTHORIZE), getBridgeIds().stream().map(ThingUID::getAsString)).toList(), - false).complete(args, cursorArgumentIndex, cursorPosition, candidates); + return new StringsCompleter(getBridgeIds(), true).complete(args, cursorArgumentIndex, cursorPosition, + candidates); } else if (cursorArgumentIndex == 1 && !AUTHORIZE.equals(args[0])) { return SUBCMD_COMPLETER.complete(args, cursorArgumentIndex, cursorPosition, candidates); } return false; } - private List getBridgeIds() { - List bridgeIds = new ArrayList<>(); - for (Thing thing : thingRegistry.getAll()) { - if (thing.getHandler() instanceof BoschAccountHandler) { - bridgeIds.add(thing.getUID()); - } - } - return bridgeIds; + private List getBridgeIds() { + return thingRegistry.getAll().stream().filter(thing -> thing.getHandler() instanceof BoschAccountHandler) + .map(thing -> thing.getUID().getId()).toList(); } - private @Nullable Thing getBridgeById(String uid) { - Thing thing; + private @Nullable Thing getBridgeById(String bridgeId) { try { - ThingUID thingUID = new ThingUID(uid); - thing = thingRegistry.get(thingUID); + ThingUID thingUID = new ThingUID(THING_TYPE_ACCOUNT, bridgeId); + return thingRegistry.get(thingUID); } catch (IllegalArgumentException e) { - thing = null; - } - return thing; - } - - private @Nullable Thing getSingleBridge() { - Thing bridge = null; - for (Thing thing : thingRegistry.getAll()) { - if (thing.getHandler() instanceof BoschAccountHandler) { - if (bridge != null) { - throw new IllegalStateException("More than one BoschIndego Bridge found."); - } - bridge = thing; - } + return null; } - return bridge; } } From 6b92d39707fff98ccf40f2efb6f0ab8f2ddc78c2 Mon Sep 17 00:00:00 2001 From: Andreas Lanz Date: Sun, 26 Oct 2025 20:59:27 +0100 Subject: [PATCH 3/5] [boschindego] Inline unnecessary variable Signed-off-by: Andreas Lanz --- .../internal/console/BoschIndegoCommandExtension.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java index ba0afb82308cf..fd5934595dc5e 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java @@ -111,8 +111,7 @@ private List getBridgeIds() { private @Nullable Thing getBridgeById(String bridgeId) { try { - ThingUID thingUID = new ThingUID(THING_TYPE_ACCOUNT, bridgeId); - return thingRegistry.get(thingUID); + return thingRegistry.get(new ThingUID(THING_TYPE_ACCOUNT, bridgeId)); } catch (IllegalArgumentException e) { return null; } From 44e5642f502e75876504502d004a2fb1d4b090c2 Mon Sep 17 00:00:00 2001 From: Andreas Lanz Date: Sat, 8 Nov 2025 20:36:52 +0100 Subject: [PATCH 4/5] [boschindego] Switch Cmd and BridgeId Signed-off-by: Andreas Lanz --- bundles/org.openhab.binding.boschindego/README.md | 2 +- .../console/BoschIndegoCommandExtension.java | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bundles/org.openhab.binding.boschindego/README.md b/bundles/org.openhab.binding.boschindego/README.md index 95cd8a0805a54..e66d078405f62 100644 --- a/bundles/org.openhab.binding.boschindego/README.md +++ b/bundles/org.openhab.binding.boschindego/README.md @@ -25,7 +25,7 @@ To authorize, please follow these steps: - With developer tools showing on the right, go to [Bosch Indego login page](https://prodindego.b2clogin.com/prodindego.onmicrosoft.com/b2c_1a_signup_signin/oauth2/v2.0/authorize?redirect_uri=com.bosch.indegoconnect://login&client_id=65bb8c9d-1070-4fb4-aa95-853618acc876&response_type=code&scope=openid%20offline_access%20https://prodindego.onmicrosoft.com/indego-mobile-api/Indego.Mower.User) again. - "Please wait..." should now be displayed. - Find the `authresp` and copy the code: `com.bosch.indegoconnect://login/?code=` -- Use the openHAB console to authorize with this code: `openhab:boschindego authorize ` +- Use the openHAB console to authorize with this code: `openhab:boschindego authorize ` ### `indego` Thing Configuration diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java index fd5934595dc5e..9e1ae61edc0f2 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java @@ -43,7 +43,7 @@ public class BoschIndegoCommandExtension extends AbstractConsoleCommandExtension implements ConsoleCommandCompleter { private static final String AUTHORIZE = "authorize"; - private static final StringsCompleter SUBCMD_COMPLETER = new StringsCompleter(List.of(AUTHORIZE), false); + private static final StringsCompleter CMD_COMPLETER = new StringsCompleter(List.of(AUTHORIZE), false); private final ThingRegistry thingRegistry; @@ -56,12 +56,12 @@ public BoschIndegoCommandExtension(final @Reference ThingRegistry thingRegistry) @Override public void execute(String[] args, Console console) { - if (args.length != 3 || !AUTHORIZE.equals(args[1])) { + if (args.length != 3 || !AUTHORIZE.equals(args[0])) { printUsage(console); return; } - String bridgeId = args[0]; + String bridgeId = args[1]; String authCode = args[2]; Thing bridge = getBridgeById(bridgeId); @@ -84,8 +84,7 @@ public void execute(String[] args, Console console) { @Override public List getUsages() { - return List - .of(buildCommandUsage(" " + AUTHORIZE + " ", "authorize by authorization code")); + return List.of(buildCommandUsage(AUTHORIZE + " ", "authorize by authorization code")); } @Override @@ -96,10 +95,10 @@ public List getUsages() { @Override public boolean complete(String[] args, int cursorArgumentIndex, int cursorPosition, List candidates) { if (cursorArgumentIndex <= 0) { + return CMD_COMPLETER.complete(args, cursorArgumentIndex, cursorPosition, candidates); + } else if (cursorArgumentIndex == 1 && AUTHORIZE.equals(args[0])) { return new StringsCompleter(getBridgeIds(), true).complete(args, cursorArgumentIndex, cursorPosition, candidates); - } else if (cursorArgumentIndex == 1 && !AUTHORIZE.equals(args[0])) { - return SUBCMD_COMPLETER.complete(args, cursorArgumentIndex, cursorPosition, candidates); } return false; } From 2fe7548e8d4f4b2b4bea511e03b834826c539ca6 Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Sat, 8 Nov 2025 23:22:25 +0100 Subject: [PATCH 5/5] Update bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java Signed-off-by: Jacob Laursen --- .../internal/console/BoschIndegoCommandExtension.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java index 9e1ae61edc0f2..8b4f0c53427fb 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/console/BoschIndegoCommandExtension.java @@ -84,7 +84,8 @@ public void execute(String[] args, Console console) { @Override public List getUsages() { - return List.of(buildCommandUsage(AUTHORIZE + " ", "authorize by authorization code")); + return List.of( + buildCommandUsage(AUTHORIZE + " ", "authorize by authorization code")); } @Override