[hue] Added support for publishing ChannelDescriptionChangedEvents (#10718)

* Added service references to DynamicStateDescriptionProvider to support publishing ChannelDescriptionChangedEvent

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2021-06-24 12:15:49 +02:00 committed by GitHub
parent 225e2ae15a
commit c5c2cab0a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 34 deletions

View File

@ -24,7 +24,7 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.hue.internal.handler.HueBridgeHandler;
import org.openhab.binding.hue.internal.handler.HueGroupHandler;
import org.openhab.binding.hue.internal.handler.HueLightHandler;
import org.openhab.binding.hue.internal.handler.HueStateDescriptionOptionProvider;
import org.openhab.binding.hue.internal.handler.HueStateDescriptionProvider;
import org.openhab.binding.hue.internal.handler.sensors.ClipHandler;
import org.openhab.binding.hue.internal.handler.sensors.DimmerSwitchHandler;
import org.openhab.binding.hue.internal.handler.sensors.GeofencePresenceHandler;
@ -67,11 +67,11 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory {
ClipHandler.SUPPORTED_THING_TYPES.stream(), HueGroupHandler.SUPPORTED_THING_TYPES.stream())
.flatMap(i -> i).collect(Collectors.toSet()));
private final HueStateDescriptionOptionProvider stateOptionProvider;
private final HueStateDescriptionProvider stateDescriptionProvider;
@Activate
public HueThingHandlerFactory(final @Reference HueStateDescriptionOptionProvider stateOptionProvider) {
this.stateOptionProvider = stateOptionProvider;
public HueThingHandlerFactory(final @Reference HueStateDescriptionProvider stateDescriptionProvider) {
this.stateDescriptionProvider = stateDescriptionProvider;
}
@Override
@ -142,9 +142,9 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory {
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
if (HueBridgeHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new HueBridgeHandler((Bridge) thing, stateOptionProvider);
return new HueBridgeHandler((Bridge) thing, stateDescriptionProvider);
} else if (HueLightHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new HueLightHandler(thing, stateOptionProvider);
return new HueLightHandler(thing, stateDescriptionProvider);
} else if (DimmerSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new DimmerSwitchHandler(thing);
} else if (TapSwitchHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
@ -160,7 +160,7 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory {
} else if (ClipHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new ClipHandler(thing);
} else if (HueGroupHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) {
return new HueGroupHandler(thing, stateOptionProvider);
return new HueGroupHandler(thing, stateDescriptionProvider);
} else {
return null;
}

View File

@ -97,7 +97,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl
private static final long SCENE_POLLING_INTERVAL = TimeUnit.SECONDS.convert(10, TimeUnit.MINUTES);
private final Logger logger = LoggerFactory.getLogger(HueBridgeHandler.class);
private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
private final HueStateDescriptionProvider stateDescriptionOptionProvider;
private final Map<String, FullLight> lastLightStates = new ConcurrentHashMap<>();
private final Map<String, FullSensor> lastSensorStates = new ConcurrentHashMap<>();
@ -403,7 +403,7 @@ public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueCl
private List<String> consoleScenesList = new ArrayList<>();
public HueBridgeHandler(Bridge bridge, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
public HueBridgeHandler(Bridge bridge, HueStateDescriptionProvider stateDescriptionOptionProvider) {
super(bridge);
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
}

View File

@ -62,7 +62,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
public static final String PROPERTY_MEMBERS = "members";
private final Logger logger = LoggerFactory.getLogger(HueGroupHandler.class);
private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
private final HueStateDescriptionProvider stateDescriptionOptionProvider;
private @NonNullByDefault({}) String groupId;
@ -79,7 +79,7 @@ public class HueGroupHandler extends BaseThingHandler implements GroupStatusList
private List<String> consoleScenesList = List.of();
public HueGroupHandler(Thing thing, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
public HueGroupHandler(Thing thing, HueStateDescriptionProvider stateDescriptionOptionProvider) {
super(thing);
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
}

View File

@ -49,7 +49,7 @@ import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.openhab.core.types.StateDescription;
import org.openhab.core.types.StateDescriptionFragment;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -83,7 +83,7 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class);
private final HueStateDescriptionOptionProvider stateDescriptionOptionProvider;
private final HueStateDescriptionProvider stateDescriptionProvider;
private @NonNullByDefault({}) String lightId;
@ -105,9 +105,9 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
private @Nullable ScheduledFuture<?> scheduledFuture;
public HueLightHandler(Thing hueLight, HueStateDescriptionOptionProvider stateDescriptionOptionProvider) {
public HueLightHandler(Thing hueLight, HueStateDescriptionProvider stateDescriptionProvider) {
super(hueLight);
this.stateDescriptionOptionProvider = stateDescriptionOptionProvider;
this.stateDescriptionProvider = stateDescriptionProvider;
}
@Override
@ -185,18 +185,14 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList
colorTemperatureCapabilties = ct;
// minimum and maximum are inverted due to mired/Kelvin conversion!
StateDescription stateDescription = StateDescriptionFragmentBuilder.create()
StateDescriptionFragment stateDescriptionFragment = StateDescriptionFragmentBuilder.create()
.withMinimum(new BigDecimal(LightStateConverter.miredToKelvin(ct.max))) //
.withMaximum(new BigDecimal(LightStateConverter.miredToKelvin(ct.min))) //
.withStep(new BigDecimal(100)) //
.withPattern("%.0f K") //
.build().toStateDescription();
if (stateDescription != null) {
stateDescriptionOptionProvider.setDescription(
new ChannelUID(thing.getUID(), CHANNEL_COLORTEMPERATURE_ABS), stateDescription);
} else {
logger.warn("Failed to create state description in thing {}", thing.getUID());
}
.build();
stateDescriptionProvider.setStateDescriptionFragment(
new ChannelUID(thing.getUID(), CHANNEL_COLORTEMPERATURE_ABS), stateDescriptionFragment);
}
}
capabilitiesInitializedSuccessfully = true;

View File

@ -14,16 +14,21 @@ package org.openhab.binding.hue.internal.handler;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
import org.openhab.core.thing.events.ThingEventFactory;
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
import org.openhab.core.types.StateDescription;
import org.openhab.core.types.StateDescriptionFragment;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@ -34,27 +39,36 @@ import org.osgi.service.component.annotations.Reference;
*
* @author Hengrui Jiang - Initial contribution
*/
@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionOptionProvider.class })
@Component(service = { DynamicStateDescriptionProvider.class, HueStateDescriptionProvider.class })
@NonNullByDefault
public class HueStateDescriptionOptionProvider extends BaseDynamicStateDescriptionProvider {
public class HueStateDescriptionProvider extends BaseDynamicStateDescriptionProvider {
private final Map<ChannelUID, StateDescription> descriptions = new ConcurrentHashMap<>();
private final Map<ChannelUID, StateDescriptionFragment> stateDescriptionFragments = new ConcurrentHashMap<>();
@Activate
public HueStateDescriptionOptionProvider(
public HueStateDescriptionProvider(final @Reference EventPublisher eventPublisher, //
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
this.eventPublisher = eventPublisher;
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
}
public void setDescription(ChannelUID channelUID, StateDescription description) {
descriptions.put(channelUID, description);
public void setStateDescriptionFragment(ChannelUID channelUID, StateDescriptionFragment stateDescriptionFragment) {
StateDescriptionFragment oldStateDescriptionFragment = stateDescriptionFragments.get(channelUID);
if (!stateDescriptionFragment.equals(oldStateDescriptionFragment)) {
stateDescriptionFragments.put(channelUID, stateDescriptionFragment);
postEvent(ThingEventFactory.createChannelDescriptionChangedEvent(channelUID,
itemChannelLinkRegistry != null ? itemChannelLinkRegistry.getLinkedItemNames(channelUID) : Set.of(),
stateDescriptionFragment, oldStateDescriptionFragment));
}
}
@Override
public @Nullable StateDescription getStateDescription(Channel channel,
@Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
StateDescription stateDescription = descriptions.get(channel.getUID());
return stateDescription != null ? stateDescription
StateDescriptionFragment stateDescriptionFragment = stateDescriptionFragments.get(channel.getUID());
return stateDescriptionFragment != null ? stateDescriptionFragment.toStateDescription()
: super.getStateDescription(channel, originalStateDescription, locale);
}
}

View File

@ -39,7 +39,6 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandlerCallback;
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
import org.openhab.core.types.Command;
import com.google.gson.Gson;
@ -385,6 +384,7 @@ public class HueLightHandlerTest {
assertSendCommand(channel, command, currentState, expectedReply, "LCT001", "Philips");
}
@SuppressWarnings("null")
private void assertSendCommand(String channel, Command command, HueLightState currentState, String expectedReply,
String expectedModel, String expectedVendor) {
FullLight light = gson.fromJson(currentState.toString(), FullConfig.class).getLights().get(0);
@ -400,8 +400,7 @@ public class HueLightHandlerTest {
long fadeTime = 400;
HueLightHandler hueLightHandler = new HueLightHandler(mockThing,
new HueStateDescriptionOptionProvider(mock(ChannelTypeI18nLocalizationService.class))) {
HueLightHandler hueLightHandler = new HueLightHandler(mockThing, mock(HueStateDescriptionProvider.class)) {
@Override
protected synchronized HueClient getHueClient() {
return mockClient;