Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Converting state into accepted types #2334

Merged
merged 1 commit into from
Oct 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
*/
package org.eclipse.smarthome.core.library.types;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;

import java.text.DecimalFormatSymbols;

import org.eclipse.smarthome.core.types.UnDefType;
import org.junit.Test;

/**
Expand Down Expand Up @@ -83,4 +83,26 @@ public void testFloatFormat() {
dt = new DecimalType("11.0");
assertEquals("11" + sep + "0", dt.format("%.1f")); // "11.0"
}

@Test
public void testConversionToOnOffType() {
assertEquals(OnOffType.ON, new DecimalType("100.0").as(OnOffType.class));
assertEquals(OnOffType.ON, new DecimalType("1.0").as(OnOffType.class));
assertEquals(OnOffType.OFF, new DecimalType("0.0").as(OnOffType.class));
}

@Test
public void testConversionToOpenCloseType() {
assertEquals(OpenClosedType.OPEN, new DecimalType("1.0").as(OpenClosedType.class));
assertEquals(OpenClosedType.CLOSED, new DecimalType("0.0").as(OpenClosedType.class));
assertEquals(UnDefType.UNDEF, new DecimalType("0.5").as(OpenClosedType.class));
}

@Test
public void testConversionToUpDownType() {
assertEquals(UpDownType.UP, new DecimalType("0.0").as(UpDownType.class));
assertEquals(UpDownType.DOWN, new DecimalType("1.0").as(UpDownType.class));
assertEquals(UnDefType.UNDEF, new DecimalType("0.5").as(OpenClosedType.class));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,26 @@ private void compareRgbToHsbValues(String hsbValues, int red, int green, int blu
assertEquals(hsb.getSaturation(), hsbRgb.getSaturation());
assertEquals(hsb.getBrightness(), hsbRgb.getBrightness());
}

@Test
public void testConversionToOnOffType() {
assertEquals(OnOffType.ON, new HSBType("100,100,100").as(OnOffType.class));
assertEquals(OnOffType.ON, new HSBType("100,100,1").as(OnOffType.class));
assertEquals(OnOffType.OFF, new HSBType("100,100,0").as(OnOffType.class));
}

@Test
public void testConversionToDecimalType() {
assertEquals(new DecimalType("1.0"), new HSBType("100,100,100").as(DecimalType.class));
assertEquals(new DecimalType("0.01"), new HSBType("100,100,1").as(DecimalType.class));
assertEquals(DecimalType.ZERO, new HSBType("100,100,0").as(DecimalType.class));
}

@Test
public void testConversionToPercentType() {
assertEquals(PercentType.HUNDRED, new HSBType("100,100,100").as(PercentType.class));
assertEquals(new PercentType("1"), new HSBType("100,100,1").as(PercentType.class));
assertEquals(PercentType.ZERO, new HSBType("100,100,0").as(PercentType.class));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (c) 2014-2016 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.library.types;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

/**
* @author Simon Kaufmann - Initial contribution and API
*/
public class OnOffTypeTest {

@Test
public void testConversionToPercentType() {
assertEquals(PercentType.HUNDRED, OnOffType.ON.as(PercentType.class));
assertEquals(PercentType.ZERO, OnOffType.OFF.as(PercentType.class));
}

@Test
public void testConversionToDecimalType() {
assertEquals(new DecimalType("1.0"), OnOffType.ON.as(DecimalType.class));
assertEquals(DecimalType.ZERO, OnOffType.OFF.as(DecimalType.class));
}

@Test
public void testConversionToHSBType() {
assertEquals(HSBType.WHITE, OnOffType.ON.as(HSBType.class));
assertEquals(HSBType.BLACK, OnOffType.OFF.as(HSBType.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) 2014-2016 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.library.types;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

/**
* @author Simon Kaufmann - Initial contribution and API
*/
public class OpenClosedTypeTest {

@Test
public void testConversionToPercentType() {
assertEquals(PercentType.ZERO, OpenClosedType.CLOSED.as(PercentType.class));
assertEquals(PercentType.HUNDRED, OpenClosedType.OPEN.as(PercentType.class));
}

@Test
public void testConversionToDecimalType() {
assertEquals(DecimalType.ZERO, OpenClosedType.CLOSED.as(DecimalType.class));
assertEquals(new DecimalType(1), OpenClosedType.OPEN.as(DecimalType.class));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import static org.junit.Assert.assertEquals;

import org.eclipse.smarthome.core.types.UnDefType;
import org.junit.Test;

/**
Expand Down Expand Up @@ -49,4 +50,33 @@ public void testEquals() {
assertEquals(true, pt3.equals(pt4));
assertEquals(false, pt3.equals(pt1));
}

@Test
public void testConversionToOnOffType() {
assertEquals(OnOffType.ON, new PercentType("100.0").as(OnOffType.class));
assertEquals(OnOffType.ON, new PercentType("1.0").as(OnOffType.class));
assertEquals(OnOffType.OFF, new PercentType("0.0").as(OnOffType.class));
}

@Test
public void testConversionToDecimalType() {
assertEquals(new DecimalType("1.0"), new PercentType("100.0").as(DecimalType.class));
assertEquals(new DecimalType("0.01"), new PercentType("1.0").as(DecimalType.class));
assertEquals(DecimalType.ZERO, new PercentType("0.0").as(DecimalType.class));
}

@Test
public void testConversionToOpenCloseType() {
assertEquals(OpenClosedType.OPEN, new PercentType("100.0").as(OpenClosedType.class));
assertEquals(OpenClosedType.CLOSED, new PercentType("0.0").as(OpenClosedType.class));
assertEquals(UnDefType.UNDEF, new PercentType("50.0").as(OpenClosedType.class));
}

@Test
public void testConversionToUpDownType() {
assertEquals(UpDownType.UP, new PercentType("0.0").as(UpDownType.class));
assertEquals(UpDownType.DOWN, new PercentType("100.0").as(UpDownType.class));
assertEquals(UnDefType.UNDEF, new PercentType("50.0").as(OpenClosedType.class));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2014-2016 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.core.library.types;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

/**
* @author Simon Kaufmann - Initial contribution and API
*/
public class UpDownTypeTest {

@Test
public void testConversionToPercentType() {
assertEquals(PercentType.ZERO, UpDownType.UP.as(PercentType.class));
assertEquals(PercentType.HUNDRED, UpDownType.DOWN.as(PercentType.class));
}

@Test
public void testConversionToDecimalType() {
assertEquals(DecimalType.ZERO, UpDownType.UP.as(DecimalType.class));
assertEquals(new DecimalType(1), UpDownType.DOWN.as(DecimalType.class));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.smarthome.config.core.BundleProcessor;
import org.eclipse.smarthome.config.core.BundleProcessor.BundleProcessorListener;
import org.eclipse.smarthome.config.core.ConfigDescription;
Expand All @@ -32,6 +33,8 @@
import org.eclipse.smarthome.core.common.SafeMethodCaller;
import org.eclipse.smarthome.core.common.ThreadPoolManager;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.items.ItemUtil;
import org.eclipse.smarthome.core.items.events.AbstractItemEventSubscriber;
import org.eclipse.smarthome.core.items.events.ItemCommandEvent;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
Expand Down Expand Up @@ -67,6 +70,7 @@
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
Expand All @@ -84,7 +88,7 @@
* @author Michael Grammling - Added dynamic configuration update
* @author Stefan Bußweiler - Added new thing status handling, migration to new event mechanism,
* refactorings thing life cycle
* @author Simon Kaufmann - Added remove handling
* @author Simon Kaufmann - Added remove handling, type conversion
* @author Kai Kreuzer - Removed usage of itemRegistry and thingLinkRegistry, fixed vetoing mechanism
* @author Andre Fuechsel - Added the {@link ThingTypeMigrationService} 
*/
Expand Down Expand Up @@ -164,15 +168,17 @@ private ThingUID getThingUID(ServiceReference<ThingHandler> reference) {

@Override
public void stateUpdated(ChannelUID channelUID, State state) {
Set<String> items = itemChannelLinkRegistry.getLinkedItems(channelUID);
for (String item : items) {
eventPublisher.post(ItemEventFactory.createStateEvent(item, state, channelUID.toString()));
Set<Item> items = itemChannelLinkRegistry.getLinkedItems(channelUID);
for (Item item : items) {
State acceptedState = ItemUtil.convertToAcceptedState(state, item);
eventPublisher
.post(ItemEventFactory.createStateEvent(item.getName(), acceptedState, channelUID.toString()));
}
}

@Override
public void postCommand(ChannelUID channelUID, Command command) {
Set<String> items = itemChannelLinkRegistry.getLinkedItems(channelUID);
Set<String> items = itemChannelLinkRegistry.getLinkedItemNames(channelUID);
for (String item : items) {
eventPublisher.post(ItemEventFactory.createCommandEvent(item, command, channelUID.toString()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public boolean isLinked(String itemName, UID uid) {
* @param uid UID
* @return a non-null collection of item names that are linked to the given UID.
*/
public Set<String> getLinkedItems(UID uid) {
public Set<String> getLinkedItemNames(UID uid) {
Set<String> linkedItems = new LinkedHashSet<>();
for (AbstractLink link : getAll()) {
if (link.getUID().equals(uid)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
Expand Down Expand Up @@ -66,7 +67,7 @@ public ItemChannelLink update(ItemChannelLink element) {
}

@Override
public Set<String> getLinkedItems(UID uid) {
public Set<String> getLinkedItemNames(UID uid) {
final Set<String> linkedItems = new LinkedHashSet<>();
for (final AbstractLink link : getAll()) {
final String itemName = link.getItemName();
Expand All @@ -77,6 +78,18 @@ public Set<String> getLinkedItems(UID uid) {
return linkedItems;
}

public Set<Item> getLinkedItems(UID uid) {
final Set<Item> linkedItems = new LinkedHashSet<>();
for (final AbstractLink link : getAll()) {
final String itemName = link.getItemName();
Item item = itemRegistry.get(itemName);
if (link.getUID().equals(uid) && item != null) {
linkedItems.add(item);
}
}
return linkedItems;
}

/**
* Returns a set of bound things for the given item name.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ protected void receiveTypedEvent(ThingStatusInfoChangedEvent event) {
Thing thing = thingRegistry.get(event.getThingUID());
if (thing != null) {
for (Channel channel : thing.getChannels()) {
if (itemChannelLinkRegistry.getLinkedItems(channel.getUID()).size() > 0) {
if (itemChannelLinkRegistry.getLinkedItemNames(channel.getUID()).size() > 0) {
informHandlerAboutLinkedChannel(thing, channel);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.Convertible;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateDescription;
Expand Down Expand Up @@ -90,8 +91,8 @@ public State getState() {
*/
@Override
public State getStateAs(Class<? extends State> typeClass) {
if (typeClass != null && typeClass.isInstance(state)) {
return state;
if (state instanceof Convertible) {
return ((Convertible) state).as(typeClass);
} else {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public interface Item {
* the accepted data types would be in this case {@link PercentType}, {@link OnOffType} and {@link UnDefType}
* </p>
*
* <p>
* The order of data types denotes the order of preference. So in case a state needs to be converted
* in order to be accepted, it will be attempted to convert it to a type from top to bottom. Therefore
* the type with the least information loss should be on top of the list - in the example above the
* {@link PercentType} carries more information than the {@link OnOffType}, hence it is listed first.
* </p>
* @return a list of data types that can be used to update the item state
*/
public List<Class<? extends State>> getAcceptedDataTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
*/
package org.eclipse.smarthome.core.items;

import org.eclipse.smarthome.core.types.Convertible;
import org.eclipse.smarthome.core.types.State;
import org.slf4j.LoggerFactory;

/**
* The {@link ItemUtil} class contains utility methods for {@link Item} objects.
* <p>
* This class cannot be instantiated, it only contains static methods.
*
* @author Michael Grammling - Initial contribution and API
* @author Simon Kaufmann - added type conversion
*/
public class ItemUtil {

Expand Down Expand Up @@ -71,4 +76,23 @@ public static void assertValidItemName(String itemName) throws IllegalArgumentEx
}
}

public static State convertToAcceptedState(final State state, final Item item) {
if (item != null && !isAccepted(item, state) && state instanceof Convertible) {
for (Class<? extends State> acceptedType : item.getAcceptedDataTypes()) {
State convertedState = ((Convertible) state).as(acceptedType);
if (convertedState != null) {
LoggerFactory.getLogger(ItemUtil.class).debug("Converting {} '{}' to {} '{}' for item '{}'",
state.getClass().getSimpleName(), state.toString(),
convertedState.getClass().getSimpleName(), convertedState.toString(), item.getName());
return convertedState;
}
}
}
return state;
}

private static boolean isAccepted(Item item, State state) {
return item.getAcceptedDataTypes().contains(state.getClass());
}

}
Loading