From 804aaee370eb89d21895418c5b33742748877073 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Gr=C3=A4ff?=
Date: Wed, 12 Dec 2018 11:08:36 +0100
Subject: [PATCH] MQTT: Add MQTT receive tests for all channel types (#6664)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The TypeParser commit a few days ago allowed to send command strings
like INCREASE/DECREASE. Unfortunately it broke a few channels.
* This commit adds tests for all channel types.
* The RGB color channel was broken (even before the TypeParser commit): Fixed.
Added features:
* Add location, datetime and image channel types including
tests and readme sections.
Refactor:
* The internal.values.* classes are a lot slimmer. Value itself
is not an interface but an abstract class now.
* Move the xml thing/channel configurations to ESH-INF/config.
* Rename two methods for clarity, so that value.getValue().getValue()
is not a think anymore.
Signed-off-by: David Gräff
---
.../HomeAssistantMQTTImplementationTests.java | 18 +-
.../generic/HomieImplementationTests.java | 12 +-
.../internal/generic/ChannelStateTests.java | 182 +++++++++--
.../ChannelStateTransformationTests.java | 2 +-
.../handler/GenericThingHandlerTests.java | 10 +-
.../handler/HomieThingHandlerTests.java | 10 +-
.../generic/internal/values/ValueTests.java | 90 +++---
.../ESH-INF/config/number-channel-config.xml | 21 +-
.../ESH-INF/config/string-channel-config.xml | 46 +++
.../ESH-INF/config/switch-channel-config.xml | 53 +++
.../ESH-INF/thing/channels.xml | 305 ++----------------
.../README.md | 40 ++-
.../internal/MqttBindingConstants.java | 4 +-
.../homeassistant/AbstractComponent.java | 2 +-
.../convention/homie300/Property.java | 11 +-
.../internal/generic/ChannelConfig.java | 1 -
.../generic/ChannelConfigBuilder.java | 5 +
.../internal/generic/ChannelState.java | 87 +++--
.../generic/ChannelStateTransformation.java | 2 +-
.../handler/AbstractMQTTThingHandler.java | 4 +-
.../internal/handler/GenericThingHandler.java | 2 +-
.../generic/internal/values/ColorValue.java | 115 +++----
.../internal/values/DateTimeValue.java | 54 ++++
.../generic/internal/values/ImageValue.java | 41 +++
.../internal/values/LocationValue.java | 43 +++
.../generic/internal/values/NumberValue.java | 136 ++------
.../generic/internal/values/OnOffValue.java | 64 +---
.../internal/values/OpenCloseValue.java | 65 +---
.../internal/values/PercentageValue.java | 96 ++++++
.../generic/internal/values/TextValue.java | 42 +--
.../mqtt/generic/internal/values/Value.java | 122 +++++--
.../generic/internal/values/ValueFactory.java | 13 +-
32 files changed, 933 insertions(+), 765 deletions(-)
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/string-channel-config.xml
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/switch-channel-config.xml
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/DateTimeValue.java
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ImageValue.java
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/LocationValue.java
create mode 100644 extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/PercentageValue.java
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomeAssistantMQTTImplementationTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomeAssistantMQTTImplementationTests.java
index f43c2b23d90..852ef562d62 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomeAssistantMQTTImplementationTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomeAssistantMQTTImplementationTests.java
@@ -36,12 +36,12 @@
import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.ComponentSwitch;
import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents;
import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents.ComponentDiscovered;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID;
import org.eclipse.smarthome.binding.mqtt.generic.internal.generic.ChannelStateUpdateListener;
import org.eclipse.smarthome.binding.mqtt.generic.internal.generic.MqttChannelTypeProvider;
-import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.HaID;
import org.eclipse.smarthome.binding.mqtt.generic.internal.handler.ThingChannelConstants;
-import org.eclipse.smarthome.binding.mqtt.generic.internal.values.OnOffValue;
import org.eclipse.smarthome.core.library.types.OnOffType;
+import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.UnDefType;
import org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection;
import org.eclipse.smarthome.io.transport.mqtt.MqttConnectionObserver;
@@ -126,7 +126,7 @@ public void setUp() throws InterruptedException, ExecutionException, TimeoutExce
public void tearDown() throws InterruptedException, ExecutionException, TimeoutException {
if (connection != null) {
connection.removeConnectionObserver(failIfChange);
- connection.stop().get(500, TimeUnit.MILLISECONDS);
+ connection.stop().get(1000, TimeUnit.MILLISECONDS);
}
}
@@ -190,9 +190,9 @@ public void parseHATree() throws InterruptedException, ExecutionException, Timeo
verify(channelTypeProvider, times(1)).setChannelType(any(), any());
// We expect a switch component with an OnOff channel with the initial value UNDEF:
- OnOffValue value = (OnOffValue) haComponents.get(haID.getChannelGroupID()).channelTypes()
- .get(ComponentSwitch.switchChannelID).channelState.getValue();
- assertThat(value.getValue(), is(UnDefType.UNDEF));
+ State value = haComponents.get(haID.getChannelGroupID()).channelTypes()
+ .get(ComponentSwitch.switchChannelID).channelState.getCache().getChannelState();
+ assertThat(value, is(UnDefType.UNDEF));
haComponents.values().stream().map(e -> e.start(connection, scheduler, 100))
.reduce(CompletableFuture.completedFuture(null), (a, v) -> a.thenCompose(b -> v)).exceptionally(e -> {
@@ -204,9 +204,9 @@ public void parseHATree() throws InterruptedException, ExecutionException, Timeo
verify(channelStateUpdateListener, times(1)).updateChannelState(any(), any());
// Value should be ON now.
- value = (OnOffValue) haComponents.get(haID.getChannelGroupID()).channelTypes()
- .get(ComponentSwitch.switchChannelID).channelState.getValue();
- assertThat(value.getValue(), is(OnOffType.ON));
+ value = haComponents.get(haID.getChannelGroupID()).channelTypes()
+ .get(ComponentSwitch.switchChannelID).channelState.getCache().getChannelState();
+ assertThat(value, is(OnOffType.ON));
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomieImplementationTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomieImplementationTests.java
index 88c176c031c..b9ee5d88a87 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomieImplementationTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/HomieImplementationTests.java
@@ -176,7 +176,7 @@ public void retrieveAllTopics() throws InterruptedException, ExecutionException,
CountDownLatch c = new CountDownLatch(registeredTopics);
connection.subscribe(deviceTopic + "/#", (topic, payload) -> c.countDown()).get(200, TimeUnit.MILLISECONDS);
assertTrue("Connection " + connection.getClientId() + " not retrieving all topics",
- c.await(200, TimeUnit.MILLISECONDS));
+ c.await(1000, TimeUnit.MILLISECONDS));
}
@Test
@@ -217,7 +217,7 @@ public void retrieveAttributes() throws InterruptedException, ExecutionException
verify(channelState).processMessage(any(), any());
verify(callback).updateChannelState(any(), any());
- assertThat(property.getChannelState().getValue().getValue(), is(new DecimalType(10)));
+ assertThat(property.getChannelState().getCache().getChannelState(), is(new DecimalType(10)));
property.stop().get();
assertThat(connection.hasSubscribers(), is(false));
@@ -307,17 +307,17 @@ public void parseHomieTree() throws InterruptedException, ExecutionException, Ti
// The device->node->property tree is ready. Now subscribe to property values.
device.startChannels(connection, scheduler, 50, handler).get();
assertThat(propertyBell.getChannelState().isStateful(), is(false));
- assertThat(propertyBell.getChannelState().getValue().getValue(), is(UnDefType.UNDEF));
- assertThat(property.getChannelState().getValue().getValue(), is(new DecimalType(10)));
+ assertThat(propertyBell.getChannelState().getCache().getChannelState(), is(UnDefType.UNDEF));
+ assertThat(property.getChannelState().getCache().getChannelState(), is(new DecimalType(10)));
property = node.properties.get("testRetain");
WaitForTopicValue watcher = new WaitForTopicValue(embeddedConnection, propertyTestTopic + "/set");
// Watch the topic. Publish a retain=false value to MQTT
- property.getChannelState().setValue(OnOffType.OFF).get();
+ property.getChannelState().publishValue(OnOffType.OFF).get();
assertThat(watcher.waitForTopicValue(50), is("false"));
// Publish a retain=false value to MQTT.
- property.getChannelState().setValue(OnOffType.ON).get();
+ property.getChannelState().publishValue(OnOffType.ON).get();
// This test is flaky if the MQTT broker does not get a time to "forget" this non-retained value
Thread.sleep(50);
// No value is expected to be retained on this MQTT topic
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTests.java
index 684535c999f..fcd0ad0236b 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTests.java
@@ -12,12 +12,16 @@
*/
package org.eclipse.smarthome.binding.mqtt.generic.internal.generic;
-import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
+import java.math.BigDecimal;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@@ -28,11 +32,18 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.binding.mqtt.generic.internal.convention.homeassistant.DiscoverComponents.ComponentDiscovered;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.ColorValue;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.DateTimeValue;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.ImageValue;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.LocationValue;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.NumberValue;
+import org.eclipse.smarthome.binding.mqtt.generic.internal.values.PercentageValue;
import org.eclipse.smarthome.binding.mqtt.generic.internal.values.TextValue;
+import org.eclipse.smarthome.core.library.types.HSBType;
+import org.eclipse.smarthome.core.library.types.RawType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection;
-import org.eclipse.smarthome.test.java.JavaOSGiTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +55,7 @@
*
* @author David Graeff - Initial contribution
*/
-public class ChannelStateTests extends JavaOSGiTest {
+public class ChannelStateTests {
@Mock
MqttBrokerConnection connection;
@@ -62,6 +73,8 @@ public class ChannelStateTests extends JavaOSGiTest {
ScheduledExecutorService scheduler;
+ ChannelConfig config = ChannelConfigBuilder.create("state", "command").build();
+
@Before
public void setUp() {
initMocks(this);
@@ -84,9 +97,7 @@ public void tearDown() {
@Test
public void noInteractionTimeoutTest() throws InterruptedException, ExecutionException, TimeoutException {
-
- ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state", "command").build(), channelUID,
- textValue, channelStateUpdateListener));
+ ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener));
c.start(connection, scheduler, 50).get(100, TimeUnit.MILLISECONDS);
verify(connection).subscribe(eq("state"), eq(c));
c.stop().get();
@@ -94,30 +105,29 @@ public void noInteractionTimeoutTest() throws InterruptedException, ExecutionExc
}
@Test
- public void publishTest() throws InterruptedException, ExecutionException, TimeoutException {
- ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state", "command").build(), channelUID,
- textValue, channelStateUpdateListener));
+ public void publishFormatTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener));
c.start(connection, scheduler, 0).get(50, TimeUnit.MILLISECONDS);
verify(connection).subscribe(eq("state"), eq(c));
- c.setValue(new StringType("UPDATE")).get();
+ c.publishValue(new StringType("UPDATE")).get();
verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE".getBytes())), anyInt(),
eq(false));
c.config.formatBeforePublish = "prefix%s";
- c.setValue(new StringType("UPDATE")).get();
+ c.publishValue(new StringType("UPDATE")).get();
verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "prefixUPDATE".getBytes())), anyInt(),
eq(false));
c.config.formatBeforePublish = "%1$s-%1$s";
- c.setValue(new StringType("UPDATE")).get();
+ c.publishValue(new StringType("UPDATE")).get();
verify(connection).publish(eq("command"), argThat(p -> Arrays.equals(p, "UPDATE-UPDATE".getBytes())), anyInt(),
eq(false));
c.config.formatBeforePublish = "%s";
c.config.retained = true;
- c.setValue(new StringType("UPDATE")).get();
+ c.publishValue(new StringType("UPDATE")).get();
verify(connection).publish(eq("command"), any(), anyInt(), eq(true));
c.stop().get();
@@ -125,28 +135,154 @@ public void publishTest() throws InterruptedException, ExecutionException, Timeo
}
@Test
- public void receiveTest() throws InterruptedException, ExecutionException, TimeoutException {
- ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state", "command").build(), channelUID,
- textValue, channelStateUpdateListener));
+ public void receiveWildcardTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(),
+ channelUID, textValue, channelStateUpdateListener));
CompletableFuture<@Nullable Void> future = c.start(connection, scheduler, 100);
- c.processMessage("state", "A TEST".getBytes());
+ c.processMessage("state/bla/topic", "A TEST".getBytes());
future.get(300, TimeUnit.MILLISECONDS);
- assertThat(textValue.getValue().toString(), is("A TEST"));
+ assertThat(textValue.getChannelState().toString(), is("A TEST"));
verify(channelStateUpdateListener).updateChannelState(eq(channelUID), any());
}
@Test
- public void receiveWildcardTest() throws InterruptedException, ExecutionException, TimeoutException {
- ChannelState c = spy(new ChannelState(ChannelConfigBuilder.create("state/+/topic", "command").build(),
- channelUID, textValue, channelStateUpdateListener));
+ public void receiveStringTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ChannelState c = spy(new ChannelState(config, channelUID, textValue, channelStateUpdateListener));
CompletableFuture<@Nullable Void> future = c.start(connection, scheduler, 100);
- c.processMessage("state/bla/topic", "A TEST".getBytes());
+ c.processMessage("state", "A TEST".getBytes());
future.get(300, TimeUnit.MILLISECONDS);
- assertThat(textValue.getValue().toString(), is("A TEST"));
+ assertThat(textValue.getChannelState().toString(), is("A TEST"));
verify(channelStateUpdateListener).updateChannelState(eq(channelUID), any());
}
+
+ @Test
+ public void receiveDecimalTest() throws InterruptedException, ExecutionException, TimeoutException {
+ NumberValue value = new NumberValue(null, null, new BigDecimal(10));
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "15".getBytes());
+ assertThat(value.getChannelState().toString(), is("15"));
+
+ c.processMessage("state", "INCREASE".getBytes());
+ assertThat(value.getChannelState().toString(), is("25"));
+
+ c.processMessage("state", "DECREASE".getBytes());
+ assertThat(value.getChannelState().toString(), is("15"));
+
+ verify(channelStateUpdateListener, times(3)).updateChannelState(eq(channelUID), any());
+ }
+
+ @Test
+ public void receiveDecimalFractionalTest() throws InterruptedException, ExecutionException, TimeoutException {
+ NumberValue value = new NumberValue(null, null, new BigDecimal(10.5));
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "5.5".getBytes());
+ assertThat(value.getChannelState().toString(), is("5.5"));
+
+ c.processMessage("state", "INCREASE".getBytes());
+ assertThat(value.getChannelState().toString(), is("16.0"));
+ }
+
+ @Test
+ public void receivePercentageTest() throws InterruptedException, ExecutionException, TimeoutException {
+ PercentageValue value = new PercentageValue(new BigDecimal(-100), new BigDecimal(100), new BigDecimal(10));
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "-100".getBytes()); // 0%
+ assertThat(value.getChannelState().toString(), is("0"));
+
+ c.processMessage("state", "100".getBytes()); // 100%
+ assertThat(value.getChannelState().toString(), is("100"));
+
+ c.processMessage("state", "0".getBytes()); // 50%
+ assertThat(value.getChannelState().toString(), is("50"));
+
+ c.processMessage("state", "INCREASE".getBytes());
+ assertThat(value.getChannelState().toString(), is("60"));
+ }
+
+ @Test
+ public void receiveRGBColorTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ColorValue value = new ColorValue(true, "FON", "FOFF");
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "ON".getBytes());
+ assertThat(value.getChannelState().toString(), is("0,0,10"));
+ assertThat(value.getMQTTpublishValue().toString(), is("25,25,25"));
+
+ c.processMessage("state", "FOFF".getBytes());
+ assertThat(value.getChannelState().toString(), is("0,0,0"));
+ assertThat(value.getMQTTpublishValue().toString(), is("0,0,0"));
+
+ HSBType t = HSBType.fromRGB(12, 18, 231);
+
+ c.processMessage("state", "12,18,231".getBytes());
+ assertThat(value.getChannelState(), is(t)); // HSB
+ // rgb -> hsv -> rgb is quite lossy
+ assertThat(value.getMQTTpublishValue().toString(), is("13,20,225"));
+ }
+
+ @Test
+ public void receiveHSBColorTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ColorValue value = new ColorValue(false, "FON", "FOFF");
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "ON".getBytes()); // Minimum brightness is 10
+ assertThat(value.getChannelState().toString(), is("0,0,10"));
+ assertThat(value.getMQTTpublishValue().toString(), is("0,0,10"));
+
+ c.processMessage("state", "FOFF".getBytes());
+ assertThat(value.getChannelState().toString(), is("0,0,0"));
+ assertThat(value.getMQTTpublishValue().toString(), is("0,0,0"));
+
+ c.processMessage("state", "12,18,100".getBytes());
+ assertThat(value.getChannelState().toString(), is("12,18,100"));
+ assertThat(value.getMQTTpublishValue().toString(), is("12,18,100"));
+ }
+
+ @Test
+ public void receiveLocationTest() throws InterruptedException, ExecutionException, TimeoutException {
+ LocationValue value = new LocationValue();
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ c.processMessage("state", "46.833974, 7.108433".getBytes());
+ assertThat(value.getChannelState().toString(), is("46.833974,7.108433"));
+ assertThat(value.getMQTTpublishValue().toString(), is("46.833974,7.108433"));
+ }
+
+ @Test
+ public void receiveDateTimeTest() throws InterruptedException, ExecutionException, TimeoutException {
+ DateTimeValue value = new DateTimeValue();
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ ZonedDateTime zd = ZonedDateTime.now();
+ String datetime = zd.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+ c.processMessage("state", datetime.getBytes());
+ assertThat(value.getChannelState().toString(), is(datetime + "+0100"));
+ assertThat(value.getMQTTpublishValue().toString(), is(datetime));
+ }
+
+ @Test
+ public void receiveImageTest() throws InterruptedException, ExecutionException, TimeoutException {
+ ImageValue value = new ImageValue();
+ ChannelState c = spy(new ChannelState(config, channelUID, value, channelStateUpdateListener));
+ c.start(connection, mock(ScheduledExecutorService.class), 100);
+
+ byte payload[] = new byte[] { (byte) 0xFF, (byte) 0xD8, 0x01, 0x02, (byte) 0xFF, (byte) 0xD9 };
+ c.processMessage("state", payload);
+ assertThat(value.getChannelState(), is(instanceOf(RawType.class)));
+ assertThat(((RawType) value.getChannelState()).getMimeType(), is("image/jpeg"));
+ }
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformationTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformationTests.java
index 5d13f7d101f..a5fd8ce6775 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformationTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformationTests.java
@@ -126,6 +126,6 @@ public void processMessageWithJSONPath() throws Exception {
channelConfig.processMessage(channelConfig.getStateTopic(), payload);
verify(callback).stateUpdated(eq(textChannelUID), argThat(arg -> "23.2".equals(arg.toString())));
- assertThat(channelConfig.getValue().getValue().toString(), is("23.2"));
+ assertThat(channelConfig.getCache().getChannelState().toString(), is("23.2"));
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java
index 80e4f9b6b52..40a4d88ac7c 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandlerTests.java
@@ -132,11 +132,11 @@ public void handleCommandRefresh() {
thingHandler.initialize();
TextValue value = spy(new TextValue());
- doReturn(value).when(channelConfig).getValue();
+ doReturn(value).when(channelConfig).getCache();
thingHandler.connection = connection;
thingHandler.handleCommand(textChannelUID, RefreshType.REFRESH);
- verify(value).getValue();
+ verify(value).getChannelState();
}
@Test
@@ -152,7 +152,7 @@ public void handleCommandUpdateString() {
StringType updateValue = new StringType("UPDATE");
thingHandler.handleCommand(textChannelUID, updateValue);
verify(value).update(eq(updateValue));
- assertThat(channelConfig.getValue().getValue().toString(), is("UPDATE"));
+ assertThat(channelConfig.getCache().getChannelState().toString(), is("UPDATE"));
}
@Test
@@ -169,7 +169,7 @@ public void handleCommandUpdateBoolean() {
thingHandler.handleCommand(textChannelUID, updateValue);
verify(value).update(eq(updateValue));
- assertThat(channelConfig.getValue().getValue(), is(OnOffType.ON));
+ assertThat(channelConfig.getCache().getChannelState(), is(OnOffType.ON));
}
@Test
@@ -187,6 +187,6 @@ public void processMessage() {
verify(callback).statusUpdated(eq(thing), argThat(arg -> arg.getStatus().equals(ThingStatus.ONLINE)));
verify(callback).stateUpdated(eq(textChannelUID), argThat(arg -> "UPDATE".equals(arg.toString())));
- assertThat(textValue.getValue().toString(), is("UPDATE"));
+ assertThat(textValue.getChannelState().toString(), is("UPDATE"));
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/HomieThingHandlerTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/HomieThingHandlerTests.java
index 3265e147c7d..f252a5402e1 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/HomieThingHandlerTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/HomieThingHandlerTests.java
@@ -230,7 +230,7 @@ public void handleCommandRefresh() {
thingHandler.handleCommand(property.channelUID, RefreshType.REFRESH);
verify(callback).stateUpdated(argThat(arg -> property.channelUID.equals(arg)),
- argThat(arg -> property.getChannelState().getValue().getValue().equals(arg)));
+ argThat(arg -> property.getChannelState().getCache().getChannelState().equals(arg)));
}
@SuppressWarnings("null")
@@ -260,21 +260,21 @@ public void handleCommandUpdate() {
StringType updateValue = new StringType("UPDATE");
thingHandler.handleCommand(property.channelUID, updateValue);
- assertThat(property.getChannelState().getValue().getValue().toString(), is("UPDATE"));
+ assertThat(property.getChannelState().getCache().getChannelState().toString(), is("UPDATE"));
verify(connection, times(1)).publish(any(), any(), anyInt(), anyBoolean());
// Check non writable property
property.attributes.settable = false;
property.attributesReceived();
// Assign old value
- Value value = property.getChannelState().getValue();
+ Value value = property.getChannelState().getCache();
Command command = TypeParser.parseCommand(value.getSupportedCommandTypes(), "OLDVALUE");
- property.getChannelState().getValue().update(command);
+ property.getChannelState().getCache().update(command);
// Try to update with new value
updateValue = new StringType("SOMETHINGNEW");
thingHandler.handleCommand(property.channelUID, updateValue);
// Expect old value and no MQTT publish
- assertThat(property.getChannelState().getValue().getValue().toString(), is("OLDVALUE"));
+ assertThat(property.getChannelState().getCache().getChannelState().toString(), is("OLDVALUE"));
verify(connection, times(1)).publish(any(), any(), anyInt(), anyBoolean());
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueTests.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueTests.java
index e9f0599e449..c0b9cbda02a 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueTests.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic.test/src/test/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueTests.java
@@ -58,16 +58,16 @@ public void colorUpdate() {
v.update(p(v, "255, 255, 255"));
v.update(p(v, "OFF"));
- assertThat(((HSBType) v.getValue()).getBrightness().intValue(), is(0));
+ assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(0));
// Minimum brightness setting after brightness 0 is 10 for ON command
v.update(p(v, "ON"));
- assertThat(((HSBType) v.getValue()).getBrightness().intValue(), is(10));
+ assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(10));
v.update(p(v, "0"));
- assertThat(((HSBType) v.getValue()).getBrightness().intValue(), is(0));
+ assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(0));
// Minimum brightness setting after brightness 0 is 10 for ON command
v.update(p(v, "1"));
- assertThat(((HSBType) v.getValue()).getBrightness().intValue(), is(10));
+ assertThat(((HSBType) v.getChannelState()).getBrightness().intValue(), is(10));
}
@Test(expected = IllegalArgumentException.class)
@@ -78,13 +78,13 @@ public void illegalColorUpdate() {
@Test(expected = IllegalArgumentException.class)
public void illegalNumberCommand() {
- NumberValue v = new NumberValue(null, null, null, null, false);
+ NumberValue v = new NumberValue(null, null, null);
v.update(OnOffType.OFF);
}
@Test(expected = IllegalArgumentException.class)
public void illegalPercentCommand() {
- NumberValue v = new NumberValue(null, null, null, null, false);
+ PercentageValue v = new PercentageValue(null, null, null);
v.update(OnOffType.OFF);
}
@@ -96,7 +96,7 @@ public void illegalOnOffCommand() {
@Test(expected = IllegalArgumentException.class)
public void illegalPercentUpdate() {
- NumberValue v = new NumberValue(null, null, null, null, true);
+ PercentageValue v = new PercentageValue(null, null, null);
v.update(new DecimalType(101.0));
}
@@ -104,69 +104,81 @@ public void illegalPercentUpdate() {
public void onoffUpdate() {
OnOffValue v = new OnOffValue("fancyON", "fancyOff");
// Test with command
- assertThat(v.update(OnOffType.OFF), is("fancyOff"));
- assertThat(v.getValue(), is(OnOffType.OFF));
- assertThat(v.update(OnOffType.ON), is("fancyON"));
- assertThat(v.getValue(), is(OnOffType.ON));
+ v.update(OnOffType.OFF);
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OnOffType.OFF));
+ v.update(OnOffType.ON);
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OnOffType.ON));
// Test with string, representing the command
- assertThat(v.update(new StringType("OFF")), is("fancyOff"));
- assertThat(v.getValue(), is(OnOffType.OFF));
- assertThat(v.update(new StringType("ON")), is("fancyON"));
- assertThat(v.getValue(), is(OnOffType.ON));
+ v.update(new StringType("OFF"));
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OnOffType.OFF));
+ v.update(new StringType("ON"));
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OnOffType.ON));
// Test with custom string, setup in the constructor
- assertThat(v.update(new StringType("fancyOff")), is("fancyOff"));
- assertThat(v.getValue(), is(OnOffType.OFF));
- assertThat(v.update(new StringType("fancyON")), is("fancyON"));
- assertThat(v.getValue(), is(OnOffType.ON));
+ v.update(new StringType("fancyOff"));
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OnOffType.OFF));
+ v.update(new StringType("fancyON"));
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OnOffType.ON));
}
@Test
public void openCloseUpdate() {
OpenCloseValue v = new OpenCloseValue("fancyON", "fancyOff");
// Test with command
- assertThat(v.update(OpenClosedType.CLOSED), is("fancyOff"));
- assertThat(v.getValue(), is(OpenClosedType.CLOSED));
- assertThat(v.update(OpenClosedType.OPEN), is("fancyON"));
- assertThat(v.getValue(), is(OpenClosedType.OPEN));
+ v.update(OpenClosedType.CLOSED);
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
+ v.update(OpenClosedType.OPEN);
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
// Test with string, representing the command
- assertThat(v.update(new StringType("CLOSED")), is("fancyOff"));
- assertThat(v.getValue(), is(OpenClosedType.CLOSED));
- assertThat(v.update(new StringType("OPEN")), is("fancyON"));
- assertThat(v.getValue(), is(OpenClosedType.OPEN));
+ v.update(new StringType("CLOSED"));
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
+ v.update(new StringType("OPEN"));
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
// Test with custom string, setup in the constructor
- assertThat(v.update(new StringType("fancyOff")), is("fancyOff"));
- assertThat(v.getValue(), is(OpenClosedType.CLOSED));
- assertThat(v.update(new StringType("fancyON")), is("fancyON"));
- assertThat(v.getValue(), is(OpenClosedType.OPEN));
+ v.update(new StringType("fancyOff"));
+ assertThat(v.getMQTTpublishValue(), is("fancyOff"));
+ assertThat(v.getChannelState(), is(OpenClosedType.CLOSED));
+ v.update(new StringType("fancyON"));
+ assertThat(v.getMQTTpublishValue(), is("fancyON"));
+ assertThat(v.getChannelState(), is(OpenClosedType.OPEN));
}
@Test
public void percentCalc() {
- NumberValue v = new NumberValue(true, new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), true);
+ PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0));
v.update(new DecimalType(110.0));
- assertThat((PercentType) v.getValue(), is(new PercentType(100)));
+ assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
v.update(new DecimalType(10.0));
- assertThat((PercentType) v.getValue(), is(new PercentType(0)));
+ assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
}
@Test
public void decimalCalc() {
- NumberValue v = new NumberValue(true, new BigDecimal(0.1), new BigDecimal(1.0), new BigDecimal(0.1), true);
+ PercentageValue v = new PercentageValue(new BigDecimal(0.1), new BigDecimal(1.0), new BigDecimal(0.1));
v.update(new DecimalType(1.0));
- assertThat((PercentType) v.getValue(), is(new PercentType(100)));
+ assertThat((PercentType) v.getChannelState(), is(new PercentType(100)));
v.update(new DecimalType(0.1));
- assertThat((PercentType) v.getValue(), is(new PercentType(0)));
+ assertThat((PercentType) v.getChannelState(), is(new PercentType(0)));
v.update(new DecimalType(0.2));
- assertEquals(((PercentType) v.getValue()).floatValue(), 11.11f, 0.01f);
+ assertEquals(((PercentType) v.getChannelState()).floatValue(), 11.11f, 0.01f);
}
@Test(expected = IllegalArgumentException.class)
public void percentCalcInvalid() {
- NumberValue v = new NumberValue(true, new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0), true);
+ PercentageValue v = new PercentageValue(new BigDecimal(10.0), new BigDecimal(110.0), new BigDecimal(1.0));
v.update(new DecimalType(9.0));
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/number-channel-config.xml b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/number-channel-config.xml
index 08105edaf92..591122c0ee0 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/number-channel-config.xml
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/number-channel-config.xml
@@ -4,7 +4,7 @@
xmlns:config-description="http://eclipse.org/smarthome/schemas/config-description/v1.0.0"
xsi:schemaLocation="http://eclipse.org/smarthome/schemas/config-description/v1.0.0 http://eclipse.org/smarthome/schemas/config-description-1.0.0.xsd">
-
+ An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less then and will publish values non-retained.
@@ -30,16 +30,19 @@
falsetrue
+
+
+
+ This configuration represents the minimum of the allowed range. For a percentage channel that equals zero percent.
+
+
+
+ This configuration represents the maximum of the allowed range. For a percentage channel that equals one-hundred percent.
+
- A number channel can receive Increase/Decrease commands and computes the target number by adding or subtracting this delta value.
- 10.0
- true
-
-
-
- If enabled, the value will be published to the MQTT broker including the fractional part of the number and a dot as the decimal marker.
- false
+ A number/dimmer channel can receive Increase/Decrease commands and computes the target number by adding or subtracting this delta value.
+ 1.0true
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/string-channel-config.xml b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/string-channel-config.xml
new file mode 100644
index 00000000000..05b942f88f2
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/string-channel-config.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+ An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
+
+
+
+ An MQTT topic that this thing will send a command to. If not set, this will be a read-only channel.
+
+
+
+ Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
+ true
+
+
+
+ Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
+ true
+ %s
+
+
+
+ The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
+ false
+ true
+
+
+
+ If the received MQTT value should not only update the state of linked items, but command them, enable this option.
+ false
+ true
+
+
+
+
+ If your MQTT topic is limited to a set of one or more specific commands or specific states, define those states here. Separate multiple states with commas. An example for a light bulb state set: ON,DIMMED,OFF
+ true
+
+
+
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/switch-channel-config.xml b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/switch-channel-config.xml
new file mode 100644
index 00000000000..778f32f07fc
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/config/switch-channel-config.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+ An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
+
+
+
+ An MQTT topic that this thing will send a command to. If not set, this will be a read-only switch.
+
+
+
+ Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
+ true
+
+
+
+ Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
+ true
+ %s
+
+
+
+ The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
+ false
+ true
+
+
+
+ If the received MQTT value should not only update the state of linked items, but command them, enable this option.
+ false
+ true
+
+
+
+
+ A number (like 1, 10) or a string (like "enabled") that is recognised as on/open state. You can use this parameter for a second keyword, next to ON (OPEN respectively on a Contact).
+ 1
+ true
+
+
+
+ A number (like 0, -10) or a string (like "disabled") that is recognised as off/closed state. You can use this parameter for a second keyword, next to OFF (CLOSED respectively on a Contact).
+ 0
+ true
+
+
+
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/thing/channels.xml b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/thing/channels.xml
index 16d067ed63a..75aa2706e8a 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/thing/channels.xml
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/ESH-INF/thing/channels.xml
@@ -7,314 +7,67 @@
String
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
-
-
-
- An MQTT topic that this thing will send a command to. If not set, this will be a read-only channel.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- If your MQTT topic is limited to a set of one or more specific commands or specific states, define those states here. Separate multiple states with commas. An example for a light bulb state set: ON,DIMMED,OFF
- true
-
-
+
+
+ DateTime
+
+ Current date and/or time
+
+
+
+
+ Image
+
+ An image to display. Send a binary bmp, jpg, png or any other supported format to this channel.
+
+
+
+
+
+ Location
+
+ GPS coordinates as Latitude,Longitude,Altitude
+
+
+
Number
-
+ Dimmer
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
-
-
-
- An MQTT topic that this thing will send a command to. If not set, this will be a read-only channel.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- The received number needs to be converted to a percentage. This configuration represents the minimum of the allowed range that equals zero percent.
- 0.0
-
-
-
- The received number needs to be converted to a percentage. This configuration represents the maximum of the allowed range that equals one-hundred percent.
- 100.0
-
-
-
- A dimmer channel can receive Increase/Decrease commands and computes the target percentage by adding or subtracting this delta percentage.
- 10.0
- true
-
-
-
- If enabled, the value will be published to the MQTT broker including the fractional part of the number and a dot as the decimal marker.
- false
- true
-
-
+ Switch
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.
-
-
-
- An MQTT topic that this thing will send a command to. If not set, this will be a read-only switch.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- A number (like 1, 10) or a string (like enabled) that is recognised as on state. "ON" (case insensitive) will always be recognised. You can use this parameter for a second keyword.
- 1
- true
-
-
-
- A number (like 0, -10) or a string (like disabled) that is recognised as off state. "OFF" (case insensitive) will always be recognised. You can use this parameter for a second keyword.
- 0
- true
-
-
+ Contact
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.status.temperature" for a json {device: {status: { temperature: 23.2 }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- A number (like 1, 10) or a string (like "positionUp") that is recognised as open state. "OPEN" (case insensitive) will always be recognised. You can use this parameter for a second keyword.
- 1
- true
-
-
-
- A number (like 0, -10) or a string (like "positionDown") that is recognised as close state. "CLOSED" (case insensitive) will always be recognised. You can use this parameter for a second keyword.
- 0
- true
-
-
+ Color
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state.
-
-
-
- An MQTT topic that this thing will send a command to. If not set, this will be a read-only channel.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.color.rgb" for a json {device: {color: { rgb: "12,43,112" }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- A number (like 1, 10) or a string (like ON) that is recognised as on state.
- ON
- true
-
-
-
- A number (like 0, -10) or a string (like OFF) that is recognised as off state.
- OFF
- true
-
-
+ Color
-
-
-
- An MQTT topic that this thing will subscribe to, to receive the state.
-
-
-
- An MQTT topic that this thing will send a command to. If not set, this will be a read-only channel.
-
-
-
- Applies a transformation to an incoming MQTT topic value. A transformation example for a received JSON would be "JSONPATH:$.device.color.hsb" for a json {device: {color: { hsb: "12,43,112" }}}. Any supported transformation service can be used.
- true
-
-
-
- Format a value before it is published to the MQTT broker. The default is to just pass the channel/item state. If you want to apply a prefix, say "MYCOLOR,", you would use "MYCOLOR,%s". If you want to adjust the precision of a number to for example 4 digits, you would use "%.4f".
- true
- %s
-
-
-
- The value will be published to the command topic as retained message. A retained value stays on the broker and can even be seen by MQTT clients that are subscribing at a later point in time.
- false
- true
-
-
-
- If the received MQTT value should not only update the state of linked items, but command them, enable this option.
- false
- true
-
-
-
-
- A number (like 1, 10) or a string (like ON) that is recognised as on state.
- ON
- true
-
-
-
- A number (like 0, -10) or a string (like OFF) that is recognised as off state.
- OFF
- true
-
-
+
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/README.md b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/README.md
index 63bc7ebfeaa..524ed73fc0f 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/README.md
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/README.md
@@ -49,6 +49,9 @@ You can manually add the following channels:
* **switch**: This channel represents a on/off state of a given topic and can send an on/off value to a given topic.
* **colorRGB**: This channel handles color values in RGB format.
* **colorHSB**: This channel handles color values in HSB format.
+* **location**: This channel handles a location.
+* **image**: This channel handles binary images in common java supported formats (bmp,jpg,png).
+* **datetime**: This channel handles date/time values.
## Thing and Channel configuration
@@ -68,13 +71,13 @@ All things require a configured broker.
You can connect this channel to a String item.
### Channel Type "number"
-
-* __min__: An optional minimum value
-* __max__: An optional maximum value
+
+* __min__: An optional minimum value.
+* __max__: An optional maximum value.
* __step__: For decrease, increase commands the step needs to be known
-* __isDecimal__: If set to true the value is send as a decimal value, otherwise it is send as integer.
-If any of the parameters is a float/double (has a decimal point value), then a float value is send to the MQTT topic otherwise an int value is send.
+A decimal value (like 0.2) is send to the MQTT topic if the number has a fractional part.
+If you always require an integer, please use the formatter.
You can connect this channel to a Number item.
@@ -86,6 +89,8 @@ You can connect this channel to a Number item.
The value is internally stored as a percentage for a value between **min** and **max**.
+The channel will publish a value between 0 and 100.
+
You can connect this channel to a Rollershutter or Dimmer item.
### Channel Type "contact", "switch"
@@ -109,6 +114,31 @@ e.g. "112,54,123" for an RGB channel (0-255 per component) and "360,100,100" for
The channel expects values on the corresponding MQTT topic to be in this format as well.
+### Channel Type "location"
+
+You can connect this channel to a Location item.
+
+The channel will publish the location as comma separated list to the MQTT broker,
+e.g. "112,54,123" for latitude, longitude, altitude. The altitude is optional.
+
+The channel expects values on the corresponding MQTT topic to be in this format as well.
+
+### Channel Type "image"
+
+You can connect this channel to an Image item. This is a read-only channel.
+
+The channel expects values on the corresponding MQTT topic to contain the binary
+data of a bmp, jpg, png or any other format that the installed java runtime supports.
+
+### Channel Type "datetime"
+
+You can connect this channel to a DateTime item.
+
+The channel will publish the date/time in the format "yyyy-MM-dd'T'HH:mm"
+for example 2018-01-01T12:14:00. If you require another format, please use the formatter.
+
+The channel expects values on the corresponding MQTT topic to be in this format as well.
+
## Limitations
* This binding does not support Homie Node Instances.
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/MqttBindingConstants.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/MqttBindingConstants.java
index fa4f2438a79..ac2045c0701 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/MqttBindingConstants.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/MqttBindingConstants.java
@@ -35,11 +35,13 @@ public class MqttBindingConstants {
public static final String COLOR_RGB = "colorRGB";
public static final String COLOR_HSB = "colorHSB";
public static final String CONTACT = "contact";
- public static final String DATETIME = "dateTime";
public static final String DIMMER = "dimmer";
public static final String NUMBER = "number";
public static final String STRING = "string";
public static final String SWITCH = "switch";
+ public static final String IMAGE = "image";
+ public static final String LOCATION = "location";
+ public static final String DATETIME = "datetime";
public static final String CONFIG_HA_CHANNEL = "mqtt:ha_channel";
public static final String CONFIG_HOMIE_CHANNEL = "mqtt:homie_channel";
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homeassistant/AbstractComponent.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homeassistant/AbstractComponent.java
index 3ee94740970..dc684f7fc8d 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homeassistant/AbstractComponent.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homeassistant/AbstractComponent.java
@@ -174,7 +174,7 @@ public ChannelGroupType type() {
* to the MQTT broker got lost.
*/
public void resetState() {
- channels.values().forEach(c -> c.channelState.getValue().resetState());
+ channels.values().forEach(c -> c.channelState.getCache().resetState());
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homie300/Property.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homie300/Property.java
index 4626b4b8f77..cae7c0a2205 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homie300/Property.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/convention/homie300/Property.java
@@ -135,7 +135,7 @@ private ChannelType createChannelType(PropertyAttributes attributes, ChannelStat
return ChannelTypeBuilder.state(channelTypeUID, attributes.name, channelState.getItemType())
.withConfigDescriptionURI(URI.create(MqttBindingConstants.CONFIG_HOMIE_CHANNEL))
.withStateDescription(
- channelState.getValue().createStateDescription(attributes.unit, !attributes.settable))
+ channelState.getCache().createStateDescription(attributes.unit, !attributes.settable))
.build();
} else {
if (attributes.datatype.equals(DataTypeEnum.enum_)) {
@@ -159,6 +159,7 @@ public void createChannelFromAttribute() {
final String stateTopic = topic;
Value value;
+ Boolean isDecimal = null;
switch (attributes.datatype) {
case boolean_:
value = new OnOffValue("true", "false");
@@ -172,7 +173,7 @@ public void createChannelFromAttribute() {
break;
case float_:
case integer_:
- boolean isDecimal = attributes.datatype == DataTypeEnum.float_;
+ isDecimal = attributes.datatype == DataTypeEnum.float_;
String s[] = attributes.format.split("\\:");
BigDecimal min = s.length == 2 ? convertFromString(s[0]) : null;
BigDecimal max = s.length == 2 ? convertFromString(s[1]) : null;
@@ -183,7 +184,7 @@ public void createChannelFromAttribute() {
step = new BigDecimal(1);
}
- value = new NumberValue(isDecimal, min, max, step, false);
+ value = new NumberValue(min, max, step);
break;
case string_:
case unknown:
@@ -195,6 +196,10 @@ public void createChannelFromAttribute() {
ChannelConfigBuilder b = ChannelConfigBuilder.create().makeTrigger(!attributes.retained)
.withStateTopic(stateTopic);
+ if (isDecimal != null && !isDecimal) {
+ b = b.withFormatter("%d"); // Apply formatter to only publish integers
+ }
+
if (attributes.settable) {
b = b.withCommandTopic(commandTopic);
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfig.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfig.java
index 76655d2d2b3..2f36b488b52 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfig.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfig.java
@@ -47,7 +47,6 @@ public class ChannelConfig {
public @Nullable BigDecimal min;
public @Nullable BigDecimal max;
public @Nullable BigDecimal step;
- public boolean isDecimal = false;
public @Nullable String on;
public @Nullable String off;
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfigBuilder.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfigBuilder.java
index 0053ef1ebad..a1ed58ba30e 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfigBuilder.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelConfigBuilder.java
@@ -40,6 +40,11 @@ public ChannelConfig build() {
return config;
}
+ public ChannelConfigBuilder withFormatter(String formatter) {
+ config.formatBeforePublish = formatter;
+ return this;
+ }
+
public ChannelConfigBuilder withStateTopic(@Nullable String topic) {
if (topic != null) {
config.stateTopic = topic;
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelState.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelState.java
index 793e6cda061..b691c109678 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelState.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelState.java
@@ -28,7 +28,6 @@
import org.eclipse.smarthome.binding.mqtt.generic.internal.values.Value;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.TypeParser;
import org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection;
import org.eclipse.smarthome.io.transport.mqtt.MqttMessageSubscriber;
@@ -51,7 +50,7 @@ public class ChannelState implements MqttMessageSubscriber {
protected final ChannelConfig config;
/** Channel value **/
- protected final Value value;
+ protected final Value cachedValue;
// Runtime variables
@@ -67,15 +66,16 @@ public class ChannelState implements MqttMessageSubscriber {
*
* @param config The channel configuration
* @param channelUID The channelUID is used for the {@link ChannelStateUpdateListener} to notify about value changes
- * @param value The channel state value.
+ * @param cachedValue MQTT only notifies us once about a value, during the subscribe. The channel state therefore
+ * needs a cache for the current value.
* @param channelStateUpdateListener A channel state update listener
*/
- public ChannelState(ChannelConfig config, ChannelUID channelUID, Value value,
+ public ChannelState(ChannelConfig config, ChannelUID channelUID, Value cachedValue,
@Nullable ChannelStateUpdateListener channelStateUpdateListener) {
this.config = config;
this.channelStateUpdateListener = channelStateUpdateListener;
this.channelUID = channelUID;
- this.value = value;
+ this.cachedValue = cachedValue;
this.readOnly = StringUtils.isBlank(config.commandTopic);
}
@@ -101,10 +101,15 @@ public void clearTransformations() {
}
/**
- * Returns the value state object of this message subscriber.
+ * Returns the cached value state object of this message subscriber.
+ *
+ * MQTT only notifies us once about a value, during the subscribe.
+ * The channel state therefore needs a cache for the current value.
+ * If MQTT has not yet published a value, the cache might still be in UNDEF state.
+ *
*/
- public Value getValue() {
- return value;
+ public Value getCache() {
+ return cachedValue;
}
/**
@@ -118,9 +123,7 @@ public ChannelUID channelUID() {
* Incoming message from the MqttBrokerConnection
*
* @param topic The topic. Is the same as the field stateTopic.
- * @param payload The byte payload. Must be UTF8 encoded text.
- * Some clients may decide to encode their own binary number or struct types.
- * We do not and cannot support those here though.
+ * @param payload The byte payload. Must be UTF8 encoded text or binary data.
*/
@Override
public void processMessage(String topic, byte[] payload) {
@@ -130,33 +133,49 @@ public void processMessage(String topic, byte[] payload) {
return;
}
- // Apply transformations
+ if (cachedValue.isBinary()) {
+ cachedValue.update(payload);
+ channelStateUpdateListener.updateChannelState(channelUID, cachedValue.getChannelState());
+ receivedOrTimeout();
+ return;
+ }
+
+ // String value: Apply transformations
String strvalue = new String(payload, StandardCharsets.UTF_8);
for (ChannelStateTransformation t : transformations) {
strvalue = t.processValue(strvalue);
}
+ // Is trigger?: Special handling
if (config.trigger) {
channelStateUpdateListener.triggerChannel(channelUID, strvalue);
- } else {
- try {
- Command command = TypeParser.parseCommand(value.getSupportedCommandTypes(), strvalue);
- if (command == null) {
- throw new IllegalArgumentException("TypeParser failed");
- }
- value.update(command);
- final State updatedState = value.getValue();
- if (config.postCommand) {
- channelStateUpdateListener.postChannelState(channelUID, (Command) updatedState);
- } else {
- channelStateUpdateListener.updateChannelState(channelUID, updatedState);
- }
- } catch (IllegalArgumentException e) {
- logger.warn("Incoming payload '{}' not supported by type '{}': {}", strvalue,
- value.getClass().getSimpleName(), e.getMessage());
- }
+ receivedOrTimeout();
+ return;
}
+ Command command = TypeParser.parseCommand(cachedValue.getSupportedCommandTypes(), strvalue);
+ if (command == null) {
+ logger.warn("Incoming payload '{}' not supported by type '{}'", strvalue,
+ cachedValue.getClass().getSimpleName());
+ receivedOrTimeout();
+ return;
+ }
+
+ // Map the string to an ESH command, update the cached value and post the command to the framework
+ try {
+ cachedValue.update(command);
+ } catch (IllegalArgumentException | IllegalStateException e) {
+ logger.warn("Command '{}' not supported by type '{}': {}", strvalue, cachedValue.getClass().getSimpleName(),
+ e.getMessage());
+ receivedOrTimeout();
+ return;
+ }
+
+ if (config.postCommand) {
+ channelStateUpdateListener.postChannelState(channelUID, (Command) cachedValue.getChannelState());
+ } else {
+ channelStateUpdateListener.updateChannelState(channelUID, cachedValue.getChannelState());
+ }
receivedOrTimeout();
}
@@ -178,7 +197,7 @@ public String getCommandTopic() {
* Returns the channelType ID which also happens to be an item-type
*/
public String getItemType() {
- return value.getItemType();
+ return cachedValue.getItemType();
}
/**
@@ -208,7 +227,7 @@ private void internalStop() {
this.connection = null;
this.channelStateUpdateListener = null;
hasSubscribed = false;
- value.resetState();
+ cachedValue.resetState();
}
private void receivedOrTimeout() {
@@ -279,8 +298,10 @@ public boolean hasSubscribed() {
* @param command The command to send
* @return A future that completes with true if the publishing worked and false and/or exceptionally otherwise.
*/
- public CompletableFuture<@Nullable Void> setValue(Command command) {
- String mqttCommandValue = getValue().update(command);
+ public CompletableFuture<@Nullable Void> publishValue(Command command) {
+ cachedValue.update(command);
+
+ String mqttCommandValue = cachedValue.getMQTTpublishValue();
final MqttBrokerConnection connection = this.connection;
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformation.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformation.java
index 74fb66e8223..2c61c3c92f5 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformation.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/generic/ChannelStateTransformation.java
@@ -45,7 +45,7 @@ public class ChannelStateTransformation {
* temperature: 23.2 }}}.
* @param channelUID The channel UID, used in processMessage() to inform the respective channel
* of an update.
- * @param value A value object
+ * @param cachedValue A value object
* @param provider The transformation service provider
*/
public ChannelStateTransformation(String pattern, TransformationServiceProvider provider) {
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/AbstractMQTTThingHandler.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/AbstractMQTTThingHandler.java
index c2b9208b6d0..49156f51310 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/AbstractMQTTThingHandler.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/AbstractMQTTThingHandler.java
@@ -112,11 +112,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
}
if (command instanceof RefreshType || data.isReadOnly()) {
- updateState(channelUID.getId(), data.getValue().getValue());
+ updateState(channelUID.getId(), data.getCache().getChannelState());
return;
}
- final CompletableFuture<@Nullable Void> future = data.setValue(command);
+ final CompletableFuture<@Nullable Void> future = data.publishValue(command);
future.exceptionally(e -> {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
return null;
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandler.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandler.java
index ed79ecfa529..eda7371282e 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandler.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/handler/GenericThingHandler.java
@@ -94,7 +94,7 @@ public GenericThingHandler(Thing thing, MqttChannelStateDescriptionProvider stat
@Override
protected void stop() {
- channelStateByChannelUID.values().forEach(c -> c.getValue().resetState());
+ channelStateByChannelUID.values().forEach(c -> c.getCache().resetState());
}
@Override
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ColorValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ColorValue.java
index 9e94628eaaa..24c706ad0f7 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ColorValue.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ColorValue.java
@@ -12,8 +12,7 @@
*/
package org.eclipse.smarthome.binding.mqtt.generic.internal.values;
-import java.util.Collections;
-import java.util.List;
+import java.math.BigDecimal;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -22,32 +21,28 @@
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.HSBType;
import org.eclipse.smarthome.core.library.types.OnOffType;
-import org.eclipse.smarthome.core.library.types.OpenClosedType;
import org.eclipse.smarthome.core.library.types.PercentType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
-import org.eclipse.smarthome.core.types.StateDescription;
import org.eclipse.smarthome.core.types.UnDefType;
/**
* Implements a color value.
*
- * Accepts user updates from a HSBType, OnOffType or OpenClosedType.
- * Accepts MQTT state updates as comma separated HSB ("h,s,b"), RGB ("r,g,b") and on, off strings.
- * On, Off strings can be customized but "1","ON","0","OFF" are always recognized.
+ *
+ * Accepts user updates from a HSBType, OnOffType and StringType.
+ *
+ * Accepts MQTT state updates as OnOffType and a
+ * StringType with comma separated HSB ("h,s,b"), RGB ("r,g,b") and on, off strings.
+ * On, Off strings can be customized.
*
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public class ColorValue implements Value {
- private State state = UnDefType.UNDEF;
- private HSBType colorValue;
+public class ColorValue extends Value {
private final boolean isRGB;
private final String onValue;
private final String offValue;
- private List> commandTypes = Stream.of(OnOffType.class, HSBType.class, StringType.class)
- .collect(Collectors.toList());
/**
* Creates a non initialized color value.
@@ -56,32 +51,12 @@ public class ColorValue implements Value {
* @param offValue The OFF value string. This will be compared to MQTT messages.
*/
public ColorValue(boolean isRGB, @Nullable String onValue, @Nullable String offValue) {
+ super(CoreItemFactory.COLOR, Stream.of(OnOffType.class, StringType.class).collect(Collectors.toList()));
this.isRGB = isRGB;
- colorValue = new HSBType();
this.onValue = onValue == null ? "ON" : onValue;
this.offValue = offValue == null ? "OFF" : offValue;
}
- /**
- * Create color type from string.
- *
- * @param colorTextValue Expects hue,saturation,brightness as comma separated string. hue is in the range [0,360],
- * saturation and brightness are in [0,100].
- * @param onValue The ON value string. This will be compared to MQTT messages.
- * @param offValue The OFF value string. This will be compared to MQTT messages.
- */
- public ColorValue(boolean isRGB, String colorTextValue, @Nullable String onValue, @Nullable String offValue) {
- this.isRGB = isRGB;
- colorValue = new HSBType(colorTextValue);
- this.onValue = onValue == null ? "ON" : onValue;
- this.offValue = offValue == null ? "OFF" : offValue;
- }
-
- @Override
- public State getValue() {
- return state;
- }
-
/**
* Updates the color value.
*
@@ -90,66 +65,54 @@ public State getValue() {
* [0,255].
*/
@Override
- public String update(Command command) throws IllegalArgumentException {
- if (command instanceof OnOffType) {
+ public void update(Command command) throws IllegalArgumentException {
+ HSBType oldvalue = (state == UnDefType.UNDEF) ? new HSBType() : (HSBType) state;
+ if (command instanceof HSBType) {
+ state = (HSBType) command;
+ } else if (command instanceof OnOffType) {
OnOffType boolValue = ((OnOffType) command);
- PercentType minOn = new PercentType(Math.max(colorValue.getBrightness().intValue(), 10));
- colorValue = new HSBType(colorValue.getHue(), colorValue.getSaturation(),
- boolValue == OnOffType.ON ? minOn : new PercentType(0));
- } else if (command instanceof OpenClosedType) {
- OnOffType boolValue = ((OpenClosedType) command) == OpenClosedType.OPEN ? OnOffType.ON : OnOffType.OFF;
- PercentType minOn = new PercentType(Math.max(colorValue.getBrightness().intValue(), 10));
- colorValue = new HSBType(colorValue.getHue(), colorValue.getSaturation(),
+ PercentType minOn = new PercentType(Math.max(oldvalue.getBrightness().intValue(), 10));
+ state = new HSBType(oldvalue.getHue(), oldvalue.getSaturation(),
boolValue == OnOffType.ON ? minOn : new PercentType(0));
- } else if (command instanceof HSBType) {
- colorValue = (HSBType) command;
- } else if (command instanceof StringType) {
+ } else {
final String updatedValue = command.toString();
if (onValue.equals(updatedValue)) {
- PercentType minOn = new PercentType(Math.max(colorValue.getBrightness().intValue(), 10));
- colorValue = new HSBType(colorValue.getHue(), colorValue.getSaturation(), minOn);
+ PercentType minOn = new PercentType(Math.max(oldvalue.getBrightness().intValue(), 10));
+ state = new HSBType(oldvalue.getHue(), oldvalue.getSaturation(), minOn);
} else if (offValue.equals(updatedValue)) {
- colorValue = new HSBType(colorValue.getHue(), colorValue.getSaturation(), new PercentType(0));
+ state = new HSBType(oldvalue.getHue(), oldvalue.getSaturation(), new PercentType(0));
} else if (isRGB) {
String[] split = updatedValue.split(",");
if (split.length != 3) {
throw new IllegalArgumentException(updatedValue + " is not a valid RGB syntax");
}
- colorValue = HSBType.fromRGB(Integer.parseInt(split[0]), Integer.parseInt(split[1]),
+ state = HSBType.fromRGB(Integer.parseInt(split[0]), Integer.parseInt(split[1]),
Integer.parseInt(split[2]));
} else {
- colorValue = new HSBType(updatedValue);
-
+ state = new HSBType(updatedValue);
}
- } else {
- throw new IllegalArgumentException("Didn't recognise the color value " + command.toString());
- }
- state = colorValue;
- if (isRGB) {
- return colorValue.getRed() + "," + colorValue.getGreen() + "," + colorValue.getBlue();
- } else {
- return colorValue.toString();
}
}
- @Override
- public String getItemType() {
- return CoreItemFactory.COLOR;
- }
+ private static BigDecimal factor = new BigDecimal(2.5);
@Override
- public StateDescription createStateDescription(String unit, boolean readOnly) {
- return new StateDescription(null, null, null, "%s " + unit.replace("%", "%%"), readOnly,
- Collections.emptyList());
- }
-
- @Override
- public List> getSupportedCommandTypes() {
- return commandTypes;
- }
+ public String getMQTTpublishValue() {
+ if (state == UnDefType.UNDEF) {
+ return "";
+ }
- @Override
- public void resetState() {
- state = UnDefType.UNDEF;
+ if (isRGB) {
+ PercentType[] rgb = ((HSBType) state).toRGB();
+ StringBuilder b = new StringBuilder();
+ b.append(rgb[0].toBigDecimal().multiply(factor).intValue());
+ b.append(',');
+ b.append(rgb[1].toBigDecimal().multiply(factor).intValue());
+ b.append(',');
+ b.append(rgb[2].toBigDecimal().multiply(factor).intValue());
+ return b.toString();
+ } else {
+ return state.toString();
+ }
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/DateTimeValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/DateTimeValue.java
new file mode 100644
index 00000000000..a68d2a5763a
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/DateTimeValue.java
@@ -0,0 +1,54 @@
+/**
+ * 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.binding.mqtt.generic.internal.values;
+
+import java.time.format.DateTimeFormatter;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.library.CoreItemFactory;
+import org.eclipse.smarthome.core.library.types.DateTimeType;
+import org.eclipse.smarthome.core.library.types.StringType;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.core.types.UnDefType;
+
+/**
+ * Implements a datetime value.
+ *
+ * @author David Graeff - Initial contribution
+ */
+@NonNullByDefault
+public class DateTimeValue extends Value {
+ public DateTimeValue() {
+ super(CoreItemFactory.DATETIME, Stream.of(DateTimeType.class, StringType.class).collect(Collectors.toList()));
+ }
+
+ @Override
+ public void update(Command command) throws IllegalArgumentException {
+ if (command instanceof DateTimeType) {
+ state = ((DateTimeType) command);
+ } else {
+ state = DateTimeType.valueOf(command.toString());
+ }
+ }
+
+ @Override
+ public String getMQTTpublishValue() {
+ if (state == UnDefType.UNDEF) {
+ return "";
+ }
+
+ return ((DateTimeType) state).getZonedDateTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
+ }
+}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ImageValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ImageValue.java
new file mode 100644
index 00000000000..b7409fa3094
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ImageValue.java
@@ -0,0 +1,41 @@
+/**
+ * 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.binding.mqtt.generic.internal.values;
+
+import java.util.Collections;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.library.CoreItemFactory;
+import org.eclipse.smarthome.core.types.Command;
+
+/**
+ * Implements an image value.
+ *
+ * @author David Graeff - Initial contribution
+ */
+@NonNullByDefault
+public class ImageValue extends Value {
+ public ImageValue() {
+ super(CoreItemFactory.IMAGE, Collections.emptyList());
+ }
+
+ @Override
+ public void update(Command command) throws IllegalArgumentException {
+ throw new IllegalArgumentException("Binary type. Command not allowed");
+ }
+
+ @Override
+ public boolean isBinary() {
+ return true;
+ }
+}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/LocationValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/LocationValue.java
new file mode 100644
index 00000000000..20050186346
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/LocationValue.java
@@ -0,0 +1,43 @@
+/**
+ * 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.binding.mqtt.generic.internal.values;
+
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.library.CoreItemFactory;
+import org.eclipse.smarthome.core.library.types.PointType;
+import org.eclipse.smarthome.core.library.types.StringType;
+import org.eclipse.smarthome.core.types.Command;
+
+/**
+ * Implements a location value.
+ *
+ * @author David Graeff - Initial contribution
+ */
+@NonNullByDefault
+public class LocationValue extends Value {
+ public LocationValue() {
+ super(CoreItemFactory.LOCATION, Stream.of(PointType.class, StringType.class).collect(Collectors.toList()));
+ }
+
+ @Override
+ public void update(Command command) throws IllegalArgumentException {
+ if (command instanceof PointType) {
+ state = ((PointType) command);
+ } else {
+ state = PointType.valueOf(command.toString());
+ }
+ }
+}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/NumberValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/NumberValue.java
index a9aab6fb1a1..a5314b5f843 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/NumberValue.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/NumberValue.java
@@ -14,7 +14,6 @@
import java.math.BigDecimal;
import java.util.Collections;
-import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -23,137 +22,52 @@
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
-import org.eclipse.smarthome.core.library.types.PercentType;
-import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.library.types.UpDownType;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateDescription;
import org.eclipse.smarthome.core.types.UnDefType;
/**
- * Implements a percentage value. Minimum and maximum are definable.
+ * Implements a number value.
+ *
+ *
+ * Accepts user updates and MQTT state updates from a DecimalType, IncreaseDecreaseType and UpDownType.
+ *
*
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public class NumberValue implements Value {
- private State state = UnDefType.UNDEF;
- private final double min;
- private final double max;
- private final double step;
- private final Boolean isDecimal;
- private final boolean isPercent;
- private List> commandTypes = Stream
- .of(DecimalType.class, IncreaseDecreaseType.class, UpDownType.class).collect(Collectors.toList());
-
- private DecimalType numberValue;
-
- public NumberValue(@Nullable Boolean isDecimal, @Nullable BigDecimal min, @Nullable BigDecimal max,
- @Nullable BigDecimal step, boolean isPercent) {
- this.isDecimal = isDecimal == null ? false : isDecimal;
- this.min = min == null ? 0.0 : min.doubleValue();
- this.max = max == null ? 100.0 : max.doubleValue();
- if (isPercent && this.min >= this.max) {
- throw new IllegalArgumentException("Min need to be smaller than max!");
- }
- this.step = step == null ? 1.0 : step.doubleValue();
- this.isPercent = isPercent;
- numberValue = new DecimalType();
- }
+public class NumberValue extends Value {
+ private final @Nullable BigDecimal min;
+ private final @Nullable BigDecimal max;
+ private final BigDecimal step;
- @Override
- public State getValue() {
- return state;
+ public NumberValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step) {
+ super(CoreItemFactory.NUMBER, Stream.of(DecimalType.class, IncreaseDecreaseType.class, UpDownType.class)
+ .collect(Collectors.toList()));
+ this.min = min;
+ this.max = max;
+ this.step = step == null ? new BigDecimal(1.0) : step;
}
@Override
- public String update(Command command) throws IllegalArgumentException {
- if (isPercent) {
- if (command instanceof DecimalType) {
- double v = ((DecimalType) command).doubleValue();
- v = (v - min) * 100.0 / (max - min);
- numberValue = new PercentType(new BigDecimal(v));
- } else if (command instanceof IncreaseDecreaseType) {
- if (((IncreaseDecreaseType) command) == IncreaseDecreaseType.INCREASE) {
- final double v = numberValue.doubleValue() + step;
- numberValue = new PercentType(new BigDecimal(v <= max ? v : max));
- } else {
- double v = numberValue.doubleValue() - step;
- numberValue = new PercentType(new BigDecimal(v >= min ? v : min));
- }
- } else if (command instanceof UpDownType) {
- if (((UpDownType) command) == UpDownType.UP) {
- final double v = numberValue.doubleValue() + step;
- numberValue = new PercentType(new BigDecimal(v <= max ? v : max));
- } else {
- final double v = numberValue.doubleValue() - step;
- numberValue = new PercentType(new BigDecimal(v >= min ? v : min));
- }
+ public void update(Command command) throws IllegalArgumentException {
+ DecimalType oldvalue = (state == UnDefType.UNDEF) ? new DecimalType() : (DecimalType) state;
+ if (command instanceof DecimalType) {
+ state = (DecimalType) command;
+ } else if (command instanceof IncreaseDecreaseType || command instanceof UpDownType) {
+ if (command == IncreaseDecreaseType.INCREASE || command == UpDownType.UP) {
+ state = new DecimalType(oldvalue.toBigDecimal().add(step));
} else {
- throw new IllegalArgumentException(
- "Type " + command.getClass().getName() + " not supported for PercentValue");
- }
-
- if (isDecimal) {
- state = numberValue;
- return numberValue.toString();
- } else {
- state = numberValue;
- return String.valueOf(numberValue.intValue());
+ state = new DecimalType(oldvalue.toBigDecimal().subtract(step));
}
} else {
- if (command instanceof DecimalType) {
- numberValue = (DecimalType) command;
- } else if (command instanceof IncreaseDecreaseType) {
- double v;
- if (((IncreaseDecreaseType) command) == IncreaseDecreaseType.INCREASE) {
- v = numberValue.doubleValue() + step;
- } else {
- v = numberValue.doubleValue() - step;
- }
- numberValue = new DecimalType(v);
- } else if (command instanceof UpDownType) {
- double v;
- if (((UpDownType) command) == UpDownType.UP) {
- v = numberValue.doubleValue() + step;
- } else {
- v = numberValue.doubleValue() - step;
- }
- numberValue = new DecimalType(v);
- } else {
- throw new IllegalArgumentException(
- "Type " + command.getClass().getName() + " not supported for NumberValue");
- }
-
- if (isDecimal) {
- state = numberValue;
- return numberValue.toString();
- } else {
- state = numberValue;
- return String.valueOf(numberValue.intValue());
- }
+ state = DecimalType.valueOf(command.toString());
}
}
- @Override
- public String getItemType() {
- return isPercent ? CoreItemFactory.DIMMER : CoreItemFactory.NUMBER;
- }
-
@Override
public StateDescription createStateDescription(String unit, boolean readOnly) {
- return new StateDescription(new BigDecimal(min), new BigDecimal(max), new BigDecimal(step),
- "%s " + unit.replace("%", "%%"), readOnly, Collections.emptyList());
- }
-
- @Override
- public List> getSupportedCommandTypes() {
- return commandTypes;
- }
-
- @Override
- public void resetState() {
- state = UnDefType.UNDEF;
+ return new StateDescription(min, max, step, "%s " + unit.replace("%", "%%"), readOnly, Collections.emptyList());
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OnOffValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OnOffValue.java
index 72c8293d5a5..c5cee9b5a7f 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OnOffValue.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OnOffValue.java
@@ -12,8 +12,6 @@
*/
package org.eclipse.smarthome.binding.mqtt.generic.internal.values;
-import java.util.Collections;
-import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -23,9 +21,6 @@
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
-import org.eclipse.smarthome.core.types.StateDescription;
-import org.eclipse.smarthome.core.types.UnDefType;
/**
* Implements an on/off boolean value.
@@ -33,21 +28,17 @@
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public class OnOffValue implements Value {
- private State state = UnDefType.UNDEF;
- private OnOffType onOffValue;
+public class OnOffValue extends Value {
private final String onString;
private final String offString;
- private List> commandTypes = Stream.of(OnOffType.class, StringType.class)
- .collect(Collectors.toList());
/**
* Creates a switch On/Off type, that accepts "ON", "1" for on and "OFF","0" for off.
*/
public OnOffValue() {
+ super(CoreItemFactory.SWITCH, Stream.of(OnOffType.class, StringType.class).collect(Collectors.toList()));
this.onString = OnOffType.ON.name();
this.offString = OnOffType.OFF.name();
- this.onOffValue = OnOffType.OFF;
}
/**
@@ -57,58 +48,29 @@ public OnOffValue() {
* @param offValue The OFF value string. This will be compared to MQTT messages.
*/
public OnOffValue(@Nullable String onValue, @Nullable String offValue) {
+ super(CoreItemFactory.SWITCH, Stream.of(OnOffType.class, StringType.class).collect(Collectors.toList()));
this.onString = onValue == null ? OnOffType.ON.name() : onValue;
this.offString = offValue == null ? OnOffType.OFF.name() : offValue;
- this.onOffValue = OnOffType.OFF;
}
@Override
- public State getValue() {
- return state;
- }
-
- @Override
- public String update(Command command) throws IllegalArgumentException {
+ public void update(Command command) throws IllegalArgumentException {
if (command instanceof OnOffType) {
- onOffValue = ((OnOffType) command);
- } else if (command instanceof StringType) {
+ state = (OnOffType) command;
+ } else {
final String updatedValue = command.toString();
- final String upperCase = updatedValue.toUpperCase();
- if (onString.equals(updatedValue) || OnOffType.ON.name().equals(upperCase)) {
- onOffValue = OnOffType.ON;
- } else if (offString.equals(updatedValue) || OnOffType.OFF.name().equals(upperCase)) {
- onOffValue = OnOffType.OFF;
+ if (onString.equals(updatedValue)) {
+ state = OnOffType.ON;
+ } else if (offString.equals(updatedValue)) {
+ state = OnOffType.OFF;
} else {
- throw new IllegalArgumentException("Didn't recognise the on/off value " + updatedValue);
+ state = OnOffType.valueOf(updatedValue);
}
-
- } else {
- throw new IllegalArgumentException(
- "Type " + command.getClass().getName() + " not supported for OnOffValue");
}
-
- state = onOffValue;
- return (onOffValue == OnOffType.ON) ? onString : offString;
- }
-
- @Override
- public String getItemType() {
- return CoreItemFactory.SWITCH;
- }
-
- @Override
- public StateDescription createStateDescription(String unit, boolean readOnly) {
- return new StateDescription(null, null, null, "%s " + unit.replace("%", "%%"), readOnly,
- Collections.emptyList());
- }
-
- @Override
- public List> getSupportedCommandTypes() {
- return commandTypes;
}
@Override
- public void resetState() {
- state = UnDefType.UNDEF;
+ public String getMQTTpublishValue() {
+ return (state == OnOffType.ON) ? onString : offString;
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OpenCloseValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OpenCloseValue.java
index 13a1404d309..38ad67e3f12 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OpenCloseValue.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/OpenCloseValue.java
@@ -12,8 +12,6 @@
*/
package org.eclipse.smarthome.binding.mqtt.generic.internal.values;
-import java.util.Collections;
-import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -23,9 +21,6 @@
import org.eclipse.smarthome.core.library.types.OpenClosedType;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
-import org.eclipse.smarthome.core.types.StateDescription;
-import org.eclipse.smarthome.core.types.UnDefType;
/**
* Implements an open/close boolean value.
@@ -33,21 +28,17 @@
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public class OpenCloseValue implements Value {
- private State state = UnDefType.UNDEF;
- private OpenClosedType boolValue;
+public class OpenCloseValue extends Value {
private final String openString;
private final String closeString;
- private List> commandTypes = Stream.of(OpenClosedType.class, StringType.class)
- .collect(Collectors.toList());
/**
* Creates a contact Open/Close type.
*/
public OpenCloseValue() {
+ super(CoreItemFactory.CONTACT, Stream.of(OpenClosedType.class, StringType.class).collect(Collectors.toList()));
this.openString = OpenClosedType.OPEN.name();
this.closeString = OpenClosedType.CLOSED.name();
- this.boolValue = OpenClosedType.CLOSED;
}
/**
@@ -57,57 +48,29 @@ public OpenCloseValue() {
* @param closeValue The OFF value string. This will be compared to MQTT messages.
*/
public OpenCloseValue(@Nullable String openValue, @Nullable String closeValue) {
+ super(CoreItemFactory.CONTACT, Stream.of(OpenClosedType.class, StringType.class).collect(Collectors.toList()));
this.openString = openValue == null ? OpenClosedType.OPEN.name() : openValue;
this.closeString = closeValue == null ? OpenClosedType.CLOSED.name() : closeValue;
- this.boolValue = OpenClosedType.CLOSED;
}
@Override
- public State getValue() {
- return state;
- }
-
- @Override
- public String update(Command command) throws IllegalArgumentException {
+ public void update(Command command) throws IllegalArgumentException {
if (command instanceof OpenClosedType) {
- boolValue = ((OpenClosedType) command);
- } else if (command instanceof StringType) {
- final String updatedValue = ((StringType) command).toString();
- final String upperCase = updatedValue.toUpperCase();
- if (openString.equals(updatedValue) || OpenClosedType.OPEN.name().equals(upperCase)) {
- boolValue = OpenClosedType.OPEN;
- } else if (closeString.equals(updatedValue) || OpenClosedType.CLOSED.name().equals(upperCase)) {
- boolValue = OpenClosedType.CLOSED;
+ state = (OpenClosedType) command;
+ } else {
+ final String updatedValue = command.toString();
+ if (openString.equals(updatedValue)) {
+ state = OpenClosedType.OPEN;
+ } else if (closeString.equals(updatedValue)) {
+ state = OpenClosedType.CLOSED;
} else {
- throw new IllegalArgumentException("Didn't recognise the open/closed value " + updatedValue);
+ state = OpenClosedType.valueOf(updatedValue);
}
- } else {
- throw new IllegalArgumentException(
- "Type " + command.getClass().getName() + " not supported for OpenCloseValue");
}
-
- state = boolValue;
- return (boolValue == OpenClosedType.OPEN) ? openString : closeString;
- }
-
- @Override
- public String getItemType() {
- return CoreItemFactory.CONTACT;
- }
-
- @Override
- public StateDescription createStateDescription(String unit, boolean readOnly) {
- return new StateDescription(null, null, null, "%s " + unit.replace("%", "%%"), readOnly,
- Collections.emptyList());
- }
-
- @Override
- public List> getSupportedCommandTypes() {
- return commandTypes;
}
@Override
- public void resetState() {
- state = UnDefType.UNDEF;
+ public String getMQTTpublishValue() {
+ return (state == OpenClosedType.OPEN) ? openString : closeString;
}
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/PercentageValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/PercentageValue.java
new file mode 100644
index 00000000000..eefcc7296fa
--- /dev/null
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/PercentageValue.java
@@ -0,0 +1,96 @@
+/**
+ * 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.binding.mqtt.generic.internal.values;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.library.CoreItemFactory;
+import org.eclipse.smarthome.core.library.types.DecimalType;
+import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType;
+import org.eclipse.smarthome.core.library.types.PercentType;
+import org.eclipse.smarthome.core.library.types.UpDownType;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.core.types.StateDescription;
+import org.eclipse.smarthome.core.types.UnDefType;
+
+/**
+ * Implements a percentage value. Minimum and maximum are definable.
+ *
+ *
+ * Accepts user updates from a DecimalType, IncreaseDecreaseType and UpDownType.
+ * If this is a percent value, PercentType
+ *
+ * Accepts MQTT state updates as DecimalType, IncreaseDecreaseType and UpDownType
+ * StringType with comma separated HSB ("h,s,b"), RGB ("r,g,b") and on, off strings.
+ * On, Off strings can be customized.
+ *
+ * @author David Graeff - Initial contribution
+ */
+@NonNullByDefault
+public class PercentageValue extends Value {
+ private final double min;
+ private final double max;
+ private final double step;
+
+ public PercentageValue(@Nullable BigDecimal min, @Nullable BigDecimal max, @Nullable BigDecimal step) {
+ super(CoreItemFactory.DIMMER, Stream.of(DecimalType.class, IncreaseDecreaseType.class, UpDownType.class)
+ .collect(Collectors.toList()));
+ this.min = min == null ? 0.0 : min.doubleValue();
+ this.max = max == null ? 100.0 : max.doubleValue();
+ if (this.min >= this.max) {
+ throw new IllegalArgumentException("Min need to be smaller than max!");
+ }
+ this.step = step == null ? 1.0 : step.doubleValue();
+ }
+
+ @Override
+ public void update(Command command) throws IllegalArgumentException {
+ PercentType oldvalue = (state == UnDefType.UNDEF) ? new PercentType() : (PercentType) state;
+ if (command instanceof PercentType) {
+ state = (PercentType) command;
+ } else if (command instanceof DecimalType) {
+ double v = ((DecimalType) command).doubleValue();
+ v = (v - min) * 100.0 / (max - min);
+ state = new PercentType(new BigDecimal(v));
+ } else if (command instanceof IncreaseDecreaseType) {
+ if (((IncreaseDecreaseType) command) == IncreaseDecreaseType.INCREASE) {
+ final double v = oldvalue.doubleValue() + step;
+ state = new PercentType(new BigDecimal(v <= max ? v : max));
+ } else {
+ double v = oldvalue.doubleValue() - step;
+ state = new PercentType(new BigDecimal(v >= min ? v : min));
+ }
+ } else if (command instanceof UpDownType) {
+ if (((UpDownType) command) == UpDownType.UP) {
+ final double v = oldvalue.doubleValue() + step;
+ state = new PercentType(new BigDecimal(v <= max ? v : max));
+ } else {
+ final double v = oldvalue.doubleValue() - step;
+ state = new PercentType(new BigDecimal(v >= min ? v : min));
+ }
+ } else {
+ state = PercentType.valueOf(command.toString());
+ }
+ }
+
+ @Override
+ public StateDescription createStateDescription(String unit, boolean readOnly) {
+ return new StateDescription(new BigDecimal(min), new BigDecimal(max), new BigDecimal(step),
+ "%s " + unit.replace("%", "%%"), readOnly, Collections.emptyList());
+ }
+}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/TextValue.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/TextValue.java
index 83a46e5f639..49b144739d2 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/TextValue.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/TextValue.java
@@ -25,10 +25,8 @@
import org.eclipse.smarthome.core.library.CoreItemFactory;
import org.eclipse.smarthome.core.library.types.StringType;
import org.eclipse.smarthome.core.types.Command;
-import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateDescription;
import org.eclipse.smarthome.core.types.StateOption;
-import org.eclipse.smarthome.core.types.UnDefType;
/**
* Implements a text/string value. Allows to restrict the incoming value to a set of states.
@@ -36,9 +34,7 @@
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public class TextValue implements Value {
- private State state = UnDefType.UNDEF;
- private StringType strValue;
+public class TextValue extends Value {
private final @Nullable Set states;
/**
@@ -48,7 +44,7 @@ public class TextValue implements Value {
* will be allowed.
*/
public TextValue(String[] states) {
- strValue = new StringType();
+ super(CoreItemFactory.STRING, Collections.singletonList(StringType.class));
Set s = Stream.of(states).filter(e -> StringUtils.isNotBlank(e)).collect(Collectors.toSet());
if (s.size() > 0) {
this.states = s;
@@ -58,30 +54,18 @@ public TextValue(String[] states) {
}
public TextValue() {
- strValue = new StringType();
+ super(CoreItemFactory.STRING, Collections.singletonList(StringType.class));
this.states = null;
}
@Override
- public State getValue() {
- return state;
- }
-
- @Override
- public String update(Command command) throws IllegalArgumentException {
+ public void update(Command command) throws IllegalArgumentException {
final Set states = this.states;
- String value = command.toString();
- if (states != null && !states.contains(value)) {
- throw new IllegalArgumentException("Value " + value + " not within range");
+ String valueStr = command.toString();
+ if (states != null && !states.contains(valueStr)) {
+ throw new IllegalArgumentException("Value " + valueStr + " not within range");
}
- strValue = new StringType(value);
- state = strValue;
- return value;
- }
-
- @Override
- public String getItemType() {
- return CoreItemFactory.STRING;
+ state = new StringType(valueStr);
}
/**
@@ -102,14 +86,4 @@ public StateDescription createStateDescription(String unit, boolean readOnly) {
}
return new StateDescription(null, null, null, "%s " + unit.replace("%", "%%"), readOnly, stateOptions);
}
-
- @Override
- public void resetState() {
- state = UnDefType.UNDEF;
- }
-
- @Override
- public List> getSupportedCommandTypes() {
- return Collections.singletonList(StringType.class);
- }
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/Value.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/Value.java
index 86e0d2f9172..f80c264e216 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/Value.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/Value.java
@@ -12,32 +12,49 @@
*/
package org.eclipse.smarthome.binding.mqtt.generic.internal.values;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URLConnection;
+import java.util.Collections;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.binding.mqtt.generic.internal.handler.GenericThingHandler;
import org.eclipse.smarthome.core.library.CoreItemFactory;
+import org.eclipse.smarthome.core.library.types.DecimalType;
+import org.eclipse.smarthome.core.library.types.PercentType;
+import org.eclipse.smarthome.core.library.types.RawType;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.StateDescription;
import org.eclipse.smarthome.core.types.UnDefType;
/**
- * MQTT topics are not inherently typed. Users are able to map topic values to framework types, for example
- * for numbers {@link NumberValue}, boolean values {@link OnOffValue}, number values
- * with limits {@link NumberValue} and string values {@link TextValue}.
+ * MQTT topics are not inherently typed.
*
- * This interface allows the handler class {@link GenericThingHandler} to treat all MQTT topics the same.
- * {@link #getValue()} is used to retrieve the topic state and a call to {@link #update(Command)} sets the value.
+ *
+ * With this class users are able to map MQTT topic values to framework types,
+ * for example for numbers {@link NumberValue}, boolean values {@link OnOffValue}, percentage values
+ * {@link PercentageValue}, string values {@link TextValue} and more.
+ *
+ *
+ *
+ * This abstract class allows the handler class {@link GenericThingHandler} to treat all MQTT topics the same.
+ * {@link #getCache()} is used to retrieve the topic state and a call to {@link #update(Command)} sets the value.
+ *
*
* @author David Graeff - Initial contribution
*/
@NonNullByDefault
-public interface Value {
- /**
- * Returns the item-type (one of {@link CoreItemFactory}).
- */
- String getItemType();
+public abstract class Value {
+ protected State state = UnDefType.UNDEF;
+ protected final List> commandTypes;
+ private final String itemType;
+
+ protected Value(String itemType, List> commandTypes) {
+ this.itemType = itemType;
+ this.commandTypes = commandTypes;
+ }
/**
* Return a list of supported command types. The order of the list is important.
@@ -45,29 +62,96 @@ public interface Value {
* The framework will try to parse an incoming string into one of those command types,
* starting with the first and continue until it succeeds.
*
+ *
+ * Your {@link #update(Command)} method must accept all command types of this list.
+ * You may accept more command types. This allows you to restrict the parsing of incoming
+ * MQTT values to the listed types, but handle more user commands.
+ *
+ * A prominent example is the {@link NumberValue}, which does not return {@link PercentType},
+ * because that would interfere with {@link DecimalType} while parsing the MQTT value.
+ * It does however accept a {@link PercentType} for {@link #update(Command)}, because a
+ * linked Item could send that type of command.
*/
- List> getSupportedCommandTypes();
+ public final List> getSupportedCommandTypes() {
+ return commandTypes;
+ }
+
+ /**
+ * Returns the item-type (one of {@link CoreItemFactory}).
+ */
+ public final String getItemType() {
+ return itemType;
+ }
/**
* Returns the current value state.
*/
- State getValue();
+ public final State getChannelState() {
+ return state;
+ }
+
+ public String getMQTTpublishValue() {
+ return state.toString();
+ }
+
+ /**
+ * Returns true if this is a binary type.
+ */
+ public boolean isBinary() {
+ return false;
+ }
+
+ /**
+ * If the MQTT connection is not yet initialised or no values have
+ * been received yet, the default value is {@link UnDefType#UNDEF}. To restore to the
+ * default value after a connection got lost etc, this method will be called.
+ */
+ public final void resetState() {
+ state = UnDefType.UNDEF;
+ }
/**
* Updates the internal value state with the given command.
*
* @param command The command to update the internal value.
- * @return An updated value state. The same as if {@link #getValue()} is called.
* @exception IllegalArgumentException Thrown if for example a text is assigned to a number type.
*/
- String update(Command command) throws IllegalArgumentException;
+ public abstract void update(Command command) throws IllegalArgumentException;
/**
- * If the MQTT connection is not yet initialised or no values have
- * been received yet, the default value is {@link UnDefType#UNDEF}. To restore to the
- * default value after a connection got lost etc, this method will be called.
+ * Updates the internal value state with the given binary payload.
+ *
+ * @param data The binary payload to update the internal value.
+ * @exception IllegalArgumentException Thrown if for example a text is assigned to a number type.
*/
- void resetState();
+ public void update(byte data[]) throws IllegalArgumentException {
+ String mimeType = null;
+
+ // URLConnection.guessContentTypeFromStream(input) is not sufficient to detect all JPEG files
+ if (data.length >= 2 && data[0] == (byte) 0xFF && data[1] == (byte) 0xD8 && data[data.length - 2] == (byte) 0xFF
+ && data[data.length - 1] == (byte) 0xD9) {
+ mimeType = "image/jpeg";
+ } else {
+ try (final ByteArrayInputStream input = new ByteArrayInputStream(data)) {
+ try {
+ mimeType = URLConnection.guessContentTypeFromStream(input);
+ } catch (final IOException ignored) {
+ }
+ } catch (final IOException ignored) {
+ }
+ }
+ state = new RawType(data, mimeType == null ? RawType.DEFAULT_MIME_TYPE : mimeType);
+ }
- StateDescription createStateDescription(String unit, boolean readOnly);
+ /**
+ * Return the state description for this value state.
+ *
+ * @param unit An optional unit string. Might be an empty string.
+ * @param readOnly True if this is a read-only value.
+ * @return A state description
+ */
+ public StateDescription createStateDescription(String unit, boolean readOnly) {
+ return new StateDescription(null, null, null, "%s " + unit.replace("%", "%%"), readOnly,
+ Collections.emptyList());
+ }
}
diff --git a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueFactory.java b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueFactory.java
index fc269575a7d..6211b700f3d 100644
--- a/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueFactory.java
+++ b/extensions/binding/org.eclipse.smarthome.binding.mqtt.generic/src/main/java/org/eclipse/smarthome/binding/mqtt/generic/internal/values/ValueFactory.java
@@ -37,11 +37,20 @@ public static Value createValueState(ChannelConfig config, String channelTypeID)
value = StringUtils.isBlank(config.allowedStates) ? new TextValue()
: new TextValue(config.allowedStates.split(","));
break;
+ case MqttBindingConstants.DATETIME:
+ value = new DateTimeValue();
+ break;
+ case MqttBindingConstants.IMAGE:
+ value = new ImageValue();
+ break;
+ case MqttBindingConstants.LOCATION:
+ value = new LocationValue();
+ break;
case MqttBindingConstants.NUMBER:
- value = new NumberValue(config.isDecimal, config.min, config.max, config.step, false);
+ value = new NumberValue(config.min, config.max, config.step);
break;
case MqttBindingConstants.DIMMER:
- value = new NumberValue(config.isDecimal, config.min, config.max, config.step, true);
+ value = new PercentageValue(config.min, config.max, config.step);
break;
case MqttBindingConstants.COLOR_RGB:
value = new ColorValue(true, config.on, config.off);