Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[hdpowerview] Add support for Generation 3 #13355

Merged
merged 77 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 76 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
42a1902
[hdpowerview] generation 3 PR2
andrewfg Sep 4, 2022
d1b773e
[hdpowerview] add missing serializer
andrewfg Sep 4, 2022
16049df
[hdpowerview] fix PUT command json
andrewfg Sep 4, 2022
81d8c94
[hdpowerview] delete unnecessary json file
andrewfg Sep 4, 2022
9581cf1
[hdpowerview] tweak serializer
andrewfg Sep 5, 2022
24adb14
[hpowerview] stronger type check on generics
andrewfg Sep 7, 2022
57fb1bc
[hdpowerview] implement battery kind on gen 3
andrewfg Sep 10, 2022
86a0f2c
[hdpowerview] implement generation configuration
andrewfg Sep 10, 2022
40a19f8
[hdpowerview] implement generation 1/2 and 3 mDNS
andrewfg Sep 10, 2022
4bac717
[hdpowerview] spotless:apply
andrewfg Sep 10, 2022
b347558
[hdpowerview] return empty repeaters object rather than throw exception
andrewfg Sep 15, 2022
a2fef4a
[hdpowerview] use osgi ClientBuilder, SseEventSourceFactory instances
andrewfg Oct 20, 2022
adb2b96
[hdpowerview] adopt reviewer request
andrewfg Oct 26, 2022
6ce09b9
[hdpowerview] cosmetics
andrewfg Oct 26, 2022
0684ff3
[hdpowerview] rename classes
andrewfg Oct 26, 2022
0f2721f
[hdpowerview] (interim) adopt reviewer suggestions
andrewfg Oct 27, 2022
7a4d352
[hdpowerview] readme, class names, minor bugs
andrewfg Oct 28, 2022
baddcac
[hdpowerview] extend console extension for gen 3
andrewfg Oct 28, 2022
d9b5424
[hdpowerview] implement class naming convention
andrewfg Oct 28, 2022
f4b9b58
[hdpowerview] console changes
andrewfg Oct 28, 2022
7581dc0
[hdpowerview] console texts
andrewfg Oct 28, 2022
e64e5dd
[hdpowerview] move modules
andrewfg Nov 1, 2022
52cbd88
[hdpowerview] generation 3 PR2
andrewfg Sep 4, 2022
f0f3e27
[hdpowerview] add missing serializer
andrewfg Sep 4, 2022
e2802a5
[hdpowerview] fix PUT command json
andrewfg Sep 4, 2022
dd13e96
[hdpowerview] delete unnecessary json file
andrewfg Sep 4, 2022
d622022
[hdpowerview] tweak serializer
andrewfg Sep 5, 2022
d9c5c79
[hpowerview] stronger type check on generics
andrewfg Sep 7, 2022
29709e9
[hdpowerview] implement battery kind on gen 3
andrewfg Sep 10, 2022
f52593b
[hdpowerview] implement generation configuration
andrewfg Sep 10, 2022
023ff89
[hdpowerview] implement generation 1/2 and 3 mDNS
andrewfg Sep 10, 2022
0a8ecce
[hdpowerview] spotless:apply
andrewfg Sep 10, 2022
9eedcb8
[hdpowerview] return empty repeaters object rather than throw exception
andrewfg Sep 15, 2022
aafa8aa
[hdpowerview] use osgi ClientBuilder, SseEventSourceFactory instances
andrewfg Oct 20, 2022
a3566b4
[hdpowerview] adopt reviewer request
andrewfg Oct 26, 2022
152330f
[hdpowerview] cosmetics
andrewfg Oct 26, 2022
7bd2c0e
[hdpowerview] rename classes
andrewfg Oct 26, 2022
55a04f6
[hdpowerview] (interim) adopt reviewer suggestions
andrewfg Oct 27, 2022
82577d0
[hdpowerview] readme, class names, minor bugs
andrewfg Oct 28, 2022
3330708
[hdpowerview] extend console extension for gen 3
andrewfg Oct 28, 2022
f08c053
[hdpowerview] implement class naming convention
andrewfg Oct 28, 2022
40011e5
[hdpowerview] console changes
andrewfg Oct 28, 2022
c107774
[hdpowerview] console texts
andrewfg Oct 28, 2022
624b6b3
[hdpowerview] move modules
andrewfg Nov 1, 2022
5b3773a
Merge branch 'hdpowerview-generation3-pr2' of https://github.com/andr…
andrewfg Nov 12, 2022
a17d79a
Merge remote-tracking branch 'upstream/main' into hdpowerview-generat…
andrewfg Nov 12, 2022
62120f8
[hdpowerview] add import
andrewfg Nov 12, 2022
13c9699
[hdpowerview] adopt SSE learnings from hue clip 2 testing
andrewfg Nov 18, 2022
dd09244
[hdpowerview] add exception handling
andrewfg Nov 22, 2022
f8bb872
Merge remote-tracking branch 'upstream/main' into hdpowerview-generat…
andrewfg Dec 10, 2022
082b604
Merge remote-tracking branch 'upstream/main' into hdpowerview-generat…
andrewfg Feb 23, 2023
c90a8c1
[hdpowerview] update copyright date
andrewfg Feb 23, 2023
7477f02
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg Mar 2, 2023
3de0fd6
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg Mar 4, 2023
dc9fe63
[hdpowerview] add yaml file
andrewfg Mar 5, 2023
5447bde
[hdpowerview] add integration registration
andrewfg Mar 5, 2023
4db576d
[hdpowerview] fix refresh
andrewfg Mar 5, 2023
f418075
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg Mar 5, 2023
ef97dc0
[hdpowerview] bug fixes based on Mockoon simulator
andrewfg Mar 8, 2023
77386bd
[hdpowerview] more bug fixes based on Mockoon simulator
andrewfg Mar 10, 2023
01f1802
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg Mar 15, 2023
25e3c5a
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg Mar 23, 2023
575f1cb
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg May 19, 2023
f803078
[hdpowerview] initial fixes from live testing
andrewfg May 20, 2023
8f26c69
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg May 20, 2023
d125de1
[hdpowerview] tweaks
andrewfg May 20, 2023
cba2fdc
Merge branch 'hdpowerview-generation3-pr2' of https://github.com/andr…
andrewfg May 20, 2023
eca336e
[hdpowerview] thing xml and i18n
andrewfg May 20, 2023
2a484ab
[hdpowerview] uom, thing xml, start up, and documentation
andrewfg May 21, 2023
f9e359b
[hdpowerview] shutdown, state, etc.
andrewfg May 21, 2023
49b9bca
[hdpowerview] fix pattern
andrewfg May 22, 2023
8f99a52
Merge branch 'openhab:main' into hdpowerview-generation3-pr2
andrewfg May 22, 2023
8d522f0
[hdpowerview] shortcut logging
andrewfg May 22, 2023
070c91d
[hdpowerview] comment for maintainers
andrewfg May 22, 2023
9e3a280
[hdpowerview] adopt reviewer requests
andrewfg May 23, 2023
d23a2e9
[hdpowerview] adopt reviewer requests
andrewfg May 23, 2023
137f987
Remove redundant logging
jlaur May 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 123 additions & 77 deletions bundles/org.openhab.binding.hdpowerview/README.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
Expand Down Expand Up @@ -74,6 +75,17 @@ public class HDPowerViewBindingConstants {

public static final List<String> NETBIOS_NAMES = Arrays.asList("PDBU-Hub3.0", "PowerView-Hub");

public static final Pattern VALID_IP_V4_ADDRESS = Pattern
.compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b");

// generation 3
public static final ThingTypeUID THING_TYPE_GATEWAY = new ThingTypeUID(BINDING_ID, "gateway");
public static final ThingTypeUID THING_TYPE_SHADE3 = new ThingTypeUID(BINDING_ID, "shade3");

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_HUB, THING_TYPE_SHADE,
THING_TYPE_REPEATER);
THING_TYPE_REPEATER, THING_TYPE_GATEWAY, THING_TYPE_SHADE3);

public static final String PROPERTY_NAME = "name";
public static final String PROPERTY_POWER_TYPE = "powerType";
public static final String PROPERTY_BLE_NAME = "bleName";
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@

import java.util.Hashtable;

import javax.ws.rs.client.ClientBuilder;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.hdpowerview.internal.discovery.HDPowerViewDeviceDiscoveryService;
import org.openhab.binding.hdpowerview.internal.discovery.ShadeDiscoveryService;
import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler;
import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewHubHandler;
import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewRepeaterHandler;
import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewShadeHandler;
import org.openhab.binding.hdpowerview.internal.handler.ShadeThingHandler;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.i18n.LocaleProvider;
import org.openhab.core.i18n.TranslationProvider;
Expand All @@ -35,6 +40,7 @@
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.jaxrs.client.SseEventSourceFactory;

/**
* The {@link HDPowerViewHandlerFactory} is responsible for creating things and thing
Expand All @@ -48,15 +54,20 @@ public class HDPowerViewHandlerFactory extends BaseThingHandlerFactory {

private final HttpClient httpClient;
private final HDPowerViewTranslationProvider translationProvider;
private final ClientBuilder clientBuilder;
private final SseEventSourceFactory eventSourceFactory;

@Activate
public HDPowerViewHandlerFactory(@Reference HttpClientFactory httpClientFactory,
final @Reference TranslationProvider i18nProvider, final @Reference LocaleProvider localeProvider,
final @Reference ClientBuilder clientBuilder, final @Reference SseEventSourceFactory eventSourceFactory,
ComponentContext componentContext) {
super.activate(componentContext);
this.httpClient = httpClientFactory.getCommonHttpClient();
this.translationProvider = new HDPowerViewTranslationProvider(getBundleContext().getBundle(), i18nProvider,
localeProvider);
this.clientBuilder = clientBuilder;
this.eventSourceFactory = eventSourceFactory;
}

@Override
Expand All @@ -67,8 +78,14 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (HDPowerViewBindingConstants.THING_TYPE_HUB.equals(thingTypeUID)) {
if (HDPowerViewBindingConstants.THING_TYPE_GATEWAY.equals(thingTypeUID)) {
GatewayBridgeHandler handler = new GatewayBridgeHandler((Bridge) thing, httpClient, translationProvider,
clientBuilder, eventSourceFactory);
registerService(new ShadeDiscoveryService(handler));
return handler;
} else if (HDPowerViewBindingConstants.THING_TYPE_SHADE3.equals(thingTypeUID)) {
return new ShadeThingHandler(thing);
} else if (HDPowerViewBindingConstants.THING_TYPE_HUB.equals(thingTypeUID)) {
HDPowerViewHubHandler handler = new HDPowerViewHubHandler((Bridge) thing, httpClient, translationProvider);
registerService(new HDPowerViewDeviceDiscoveryService(handler));
return handler;
Expand All @@ -77,7 +94,6 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
} else if (HDPowerViewBindingConstants.THING_TYPE_REPEATER.equals(thingTypeUID)) {
return new HDPowerViewRepeaterHandler(thing);
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ public class HDPowerViewWebTargets {
private final HttpClient httpClient;

/**
* private helper class for passing http url query parameters
* helper class for passing http url query parameters
*/
private static class Query {
public static class Query {
private final String key;
private final String value;

Expand Down Expand Up @@ -425,7 +425,7 @@ public ScheduledEvents getScheduledEvents()

/**
* Enables or disables a scheduled event in the hub.
*
*
* @param scheduledEventId id of the scheduled event to be enabled or disabled
* @param enable true to enable scheduled event, false to disable
* @throws HubInvalidResponseException if response is invalid
Expand Down Expand Up @@ -527,7 +527,7 @@ public RepeaterData identifyRepeater(int repeaterId)

/**
* Enables or disables blinking for a repeater
*
*
* @param repeaterId id of the repeater for which to be enable or disable blinking
* @param enable true to enable blinking, false to disable
* @return RepeaterData class instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.hdpowerview.internal.GatewayWebTargets;
import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets;
import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade;
import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData;
import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler;
import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewHubHandler;
import org.openhab.core.io.console.Console;
import org.openhab.core.io.console.ConsoleCommandCompleter;
Expand Down Expand Up @@ -65,7 +68,7 @@ public void execute(String[] args, Console console) {
for (Thing thing : thingRegistry.getAll()) {
ThingHandler thingHandler = thing.getHandler();
if (thingHandler instanceof HDPowerViewHubHandler) {
console.println("API bridge: " + thing.getLabel());
console.println("Generation 1/2 API hub: " + thing.getLabel());
HDPowerViewWebTargets webTargets = ((HDPowerViewHubHandler) thingHandler).getWebTargets();

try {
Expand All @@ -87,6 +90,21 @@ public void execute(String[] args, Console console) {
} catch (HubException e) {
console.println("Error retrieving ID's: " + e.getMessage());
}
} else if (thingHandler instanceof GatewayBridgeHandler) {
console.println("Generation 3 API gateway: " + thing.getLabel());
GatewayWebTargets webTargets = ((GatewayBridgeHandler) thingHandler).getWebTargets();

try {
List<Shade> shades = webTargets.getShades();
if (!shades.isEmpty()) {
console.println(" - Shades:");
for (Shade shade : shades) {
console.println(" - ID: " + shade.getId() + " (" + shade.getName() + ")");
}
}
} catch (HubException e) {
console.println("Error retrieving ID's: " + e.getMessage());
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static class Type extends Base {
protected Type() {
}

protected Type(int type) {
public Type(int type) {
intValue = type;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hdpowerview.internal.discovery;

import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*;

import java.util.Set;

import javax.jmdns.ServiceInfo;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.hdpowerview.internal.config.HDPowerViewHubConfiguration;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Discovers HD PowerView Generation 3 Gateways by means of mDNS.
*
* @author Andrew Fiddian-Green - Initial contribution.
*/
@NonNullByDefault
@Component
public class GatewayDiscoveryParticipant implements MDNSDiscoveryParticipant {

private static final String LABEL_KEY = "discovery.gateway.label";

private final Logger logger = LoggerFactory.getLogger(GatewayDiscoveryParticipant.class);

@Override
public @Nullable DiscoveryResult createResult(ServiceInfo service) {
for (String host : service.getHostAddresses()) {
if (VALID_IP_V4_ADDRESS.matcher(host).matches()) {
ThingUID thingUID = new ThingUID(THING_TYPE_GATEWAY, host.replace('.', '_'));
DiscoveryResult hub = DiscoveryResultBuilder.create(thingUID)
.withProperty(HDPowerViewHubConfiguration.HOST, host)
.withRepresentationProperty(HDPowerViewHubConfiguration.HOST)
.withLabel(String.format("@text/%s [\"%s\"]", LABEL_KEY, host)).build();
logger.debug("mDNS discovered Gen 3 gateway on host '{}'", host);
return hub;
}
}
return null;
}

@Override
public String getServiceType() {
return "_powerview-g3._tcp.local.";
}

@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
return Set.of(THING_TYPE_GATEWAY);
}

@Override
public @Nullable ThingUID getThingUID(ServiceInfo service) {
for (String host : service.getHostAddresses()) {
if (VALID_IP_V4_ADDRESS.matcher(host).matches()) {
return new ThingUID(THING_TYPE_GATEWAY, host.replace('.', '_'));
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class HDPowerViewDeviceDiscoveryService extends AbstractDiscoveryService
private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();

public HDPowerViewDeviceDiscoveryService(HDPowerViewHubHandler hub) {
super(Collections.singleton(HDPowerViewBindingConstants.THING_TYPE_SHADE), 600, true);
super(Collections.singleton(HDPowerViewBindingConstants.THING_TYPE_SHADE), 60, true);
this.hub = hub;
this.scanner = createScanner();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;

import javax.jmdns.ServiceInfo;

Expand All @@ -41,10 +40,9 @@
@Component
public class HDPowerViewHubDiscoveryParticipant implements MDNSDiscoveryParticipant {

private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubDiscoveryParticipant.class);
private static final String LABEL_KEY = "discovery.hub.label";

private static final Pattern VALID_IP_V4_ADDRESS = Pattern
.compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b");
private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubDiscoveryParticipant.class);

@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
Expand All @@ -64,8 +62,8 @@ public String getServiceType() {
DiscoveryResult hub = DiscoveryResultBuilder.create(thingUID)
.withProperty(HDPowerViewHubConfiguration.HOST, host)
.withRepresentationProperty(HDPowerViewHubConfiguration.HOST)
.withLabel("PowerView Hub (" + host + ")").build();
logger.debug("mDNS discovered hub on host '{}'", host);
.withLabel(String.format("@text/%s [\"%s\"]", LABEL_KEY, host)).build();
logger.debug("mDNS discovered Gen 1/2 hub on host '{}'", host);
return hub;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class HDPowerViewHubDiscoveryService extends AbstractDiscoveryService {
private @Nullable ScheduledFuture<?> backgroundFuture;

public HDPowerViewHubDiscoveryService() {
super(Collections.singleton(THING_TYPE_HUB), 600, true);
super(Collections.singleton(THING_TYPE_HUB), 60, true);
scanner = createScanner();
}

Expand Down
Loading