diff --git a/bundles/core/org.eclipse.smarthome.core.thing.test/src/test/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManagerTest.java b/bundles/core/org.eclipse.smarthome.core.thing.test/src/test/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManagerTest.java index 045caaa9a30..6b53e3bc847 100644 --- a/bundles/core/org.eclipse.smarthome.core.thing.test/src/test/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManagerTest.java +++ b/bundles/core/org.eclipse.smarthome.core.thing.test/src/test/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManagerTest.java @@ -12,7 +12,7 @@ */ package org.eclipse.smarthome.core.thing.internal; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.initMocks; @@ -26,6 +26,7 @@ import org.eclipse.smarthome.core.events.Event; import org.eclipse.smarthome.core.events.EventPublisher; import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.items.MetadataRegistry; import org.eclipse.smarthome.core.items.events.ItemCommandEvent; import org.eclipse.smarthome.core.items.events.ItemEventFactory; import org.eclipse.smarthome.core.items.events.ItemStateEvent; @@ -68,6 +69,7 @@ public class AutoUpdateManagerTest { private @Mock Thing mockThingOnline; private @Mock Thing mockThingHandlerMissing; private @Mock ThingHandler mockHandler; + private @Mock MetadataRegistry mockMetadataRegistry; private final List links = new LinkedList<>(); private AutoUpdateManager aum; @@ -95,13 +97,13 @@ public void setup() { aum.setItemChannelLinkRegistry(mockLinkRegistry); aum.setEventPublisher(mockEventPublisher); aum.setThingRegistry(mockThingRegistry); + aum.setMetadataRegistry(mockMetadataRegistry); } - private void assertEvent(String expectedContent, String extectedSource) { + private void assertStateEvent(String expectedContent, String extectedSource) { ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - verify(mockEventPublisher).post(eventCaptor.capture()); - Event event = eventCaptor.getValue(); - assertTrue(event instanceof ItemStateEvent); + verify(mockEventPublisher, atLeastOnce()).post(eventCaptor.capture()); + Event event = eventCaptor.getAllValues().stream().filter(e -> e instanceof ItemStateEvent).findFirst().get(); assertEquals(expectedContent, ((ItemStateEvent) event).getItemState().toFullString()); assertEquals(extectedSource, event.getSource()); assertNothingHappened(); @@ -109,9 +111,9 @@ private void assertEvent(String expectedContent, String extectedSource) { private void assertPredictionEvent(String expectedContent, String extectedSource) { ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(Event.class); - verify(mockEventPublisher).post(eventCaptor.capture()); - Event event = eventCaptor.getValue(); - assertTrue(event instanceof ItemStatePredictedEvent); + verify(mockEventPublisher, atLeastOnce()).post(eventCaptor.capture()); + Event event = eventCaptor.getAllValues().stream().filter(e -> e instanceof ItemStatePredictedEvent).findFirst() + .get(); assertEquals(expectedContent, ((ItemStatePredictedEvent) event).getPredictedState().toFullString()); assertEquals(extectedSource, event.getSource()); assertNothingHappened(); @@ -139,7 +141,7 @@ private void setAutoUpdatePolicy(ChannelUID channelUID, AutoUpdatePolicy policy) public void testAutoUpdate_noLink() { aum.receiveCommand(event, item); - assertEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); + assertStateEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); } @Test @@ -208,7 +210,7 @@ public void testAutoUpdate_policyRECOMMEND() { aum.receiveCommand(event, item); - assertEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); + assertStateEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); } @Test @@ -260,7 +262,7 @@ public void testAutoUpdate_errorInvalidatesVETO() { aum.receiveCommand(event, item); - assertEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); + assertStateEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); } @Test @@ -286,7 +288,7 @@ public void testAutoUpdate_errorInvalidatesDEFAULT() { aum.receiveCommand(event, item); - assertEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); + assertStateEvent("AFTER", AutoUpdateManager.EVENT_SOURCE); } @Test @@ -318,8 +320,8 @@ public void testAutoUpdate_sendOptimisticUpdates() { aum.receiveCommand(event, item); - assertPredictionEvent("AFTER", AutoUpdateManager.EVENT_SOURCE_OPTIMISTIC); - assertEvent("AFTER", AutoUpdateManager.EVENT_SOURCE_OPTIMISTIC); // no? + assertPredictionEvent("AFTER", null); + assertStateEvent("AFTER", AutoUpdateManager.EVENT_SOURCE_OPTIMISTIC); // no? } } diff --git a/bundles/core/org.eclipse.smarthome.core.thing/META-INF/MANIFEST.MF b/bundles/core/org.eclipse.smarthome.core.thing/META-INF/MANIFEST.MF index 21045bbbb1a..9f9ad1e5754 100644 --- a/bundles/core/org.eclipse.smarthome.core.thing/META-INF/MANIFEST.MF +++ b/bundles/core/org.eclipse.smarthome.core.thing/META-INF/MANIFEST.MF @@ -32,6 +32,7 @@ Import-Package: org.eclipse.jdt.annotation;resolution:=optional, org.eclipse.smarthome.config.core, org.eclipse.smarthome.config.core.dto, + org.eclipse.smarthome.config.core.metadata, org.eclipse.smarthome.config.core.status, org.eclipse.smarthome.config.core.validation, org.eclipse.smarthome.core.common, diff --git a/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateConfigDescriptionProvider.java b/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateConfigDescriptionProvider.java new file mode 100644 index 00000000000..bb75b8b5771 --- /dev/null +++ b/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateConfigDescriptionProvider.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2014,2018 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * 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.eclipse.smarthome.core.thing.internal; + +import static java.util.stream.Collectors.toList; + +import java.util.List; +import java.util.Locale; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; +import org.eclipse.smarthome.config.core.ParameterOption; +import org.eclipse.smarthome.config.core.metadata.MetadataConfigDescriptionProvider; +import org.osgi.service.component.annotations.Component; + +/** + * Provider of the config description for the auto update policy metadata. + * + * @author Simon Kaufmann - initial contribution and API + * + */ +@NonNullByDefault +@Component +public class AutoUpdateConfigDescriptionProvider implements MetadataConfigDescriptionProvider { + + @Override + public String getNamespace() { + return "autoupdate"; + } + + @Override + public @Nullable String getDescription(@Nullable Locale locale) { + return "Auto Update"; + } + + @Override + public @Nullable List getParameterOptions(@Nullable Locale locale) { + return Stream.of( // + new ParameterOption("true", "Enforce an auto update"), // + new ParameterOption("false", "Veto an auto update") // + ).collect(toList()); + } + + @Override + public @Nullable List getParameters(String value, @Nullable Locale locale) { + return null; + } + +} diff --git a/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManager.java b/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManager.java index 6171658d607..d38ed0efbeb 100644 --- a/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManager.java +++ b/bundles/core/org.eclipse.smarthome.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/AutoUpdateManager.java @@ -21,6 +21,9 @@ import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.events.EventPublisher; import org.eclipse.smarthome.core.items.Item; +import org.eclipse.smarthome.core.items.Metadata; +import org.eclipse.smarthome.core.items.MetadataKey; +import org.eclipse.smarthome.core.items.MetadataRegistry; import org.eclipse.smarthome.core.items.events.ItemCommandEvent; import org.eclipse.smarthome.core.items.events.ItemEventFactory; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -61,6 +64,7 @@ public class AutoUpdateManager { private @NonNullByDefault({}) ItemChannelLinkRegistry itemChannelLinkRegistry; private @NonNullByDefault({}) ThingRegistry thingRegistry; private @NonNullByDefault({}) EventPublisher eventPublisher; + private @NonNullByDefault({}) MetadataRegistry metadataRegistry; private boolean enabled = true; private boolean sendOptimisticUpdates = false; @@ -123,10 +127,22 @@ public void receiveCommand(ItemCommandEvent commandEvent, Item item) { if (command instanceof State) { final State state = (State) command; - // TODO: consider user-override via item meta-data - // (see https://github.com/eclipse/smarthome/pull/4390) Recommendation autoUpdate = shouldAutoUpdate(itemName); + // consider user-override via item meta-data + MetadataKey key = new MetadataKey("autoupdate", itemName); + Metadata metadata = metadataRegistry.get(key); + if (metadata != null && !metadata.getValue().trim().isEmpty()) { + boolean override = Boolean.getBoolean(metadata.getValue()); + if (override) { + logger.trace("Auto update strategy {} overriden by item metadata to REQUIRED", autoUpdate); + autoUpdate = Recommendation.REQUIRED; + } else { + logger.trace("Auto update strategy {} overriden by item metadata to DONT", autoUpdate); + autoUpdate = Recommendation.DONT; + } + } + switch (autoUpdate) { case REQUIRED: logger.trace("Automatically updating item '{}' because no channel is linked", itemName); @@ -179,6 +195,7 @@ private Recommendation shouldAutoUpdate(String itemName) { if (policy == null) { policy = AutoUpdatePolicy.DEFAULT; } + switch (policy) { case VETO: ret = Recommendation.DONT; @@ -195,6 +212,7 @@ private Recommendation shouldAutoUpdate(String itemName) { break; } } + return ret; } @@ -268,4 +286,13 @@ protected void unsetEventPublisher(EventPublisher eventPublisher) { this.eventPublisher = null; } + @Reference + protected void setMetadataRegistry(MetadataRegistry metadataRegistry) { + this.metadataRegistry = metadataRegistry; + } + + protected void unsetMetadataRegistry(MetadataRegistry metadataRegistry) { + this.metadataRegistry = null; + } + }