diff --git a/ESH-INF/binding/binding.xml b/ESH-INF/binding/binding.xml index f94ecb6616c1403a19baa52e809ee32ae2ba465b..822a76d07919741584dd5a2863d905d38a416481 100644 --- a/ESH-INF/binding/binding.xml +++ b/ESH-INF/binding/binding.xml @@ -4,7 +4,7 @@ xsi:schemaLocation="http://eclipse.org/smarthome/schemas/binding/v1.0.0 http://eclipse.org/smarthome/schemas/binding-1.0.0.xsd"> <name>OpenLicht Binding</name> - <description>This is the binding for OpenLicht.</description> + <description>This is the binding for OpenLicht (Last Update: 2018-10-01).</description> <author>René Schöne</author> </binding:binding> diff --git a/ESH-INF/config/config.xml b/ESH-INF/config/config.xml index 9a3bff11cbc4a5bf50389ecc0e2ea184b4c5e5e7..baaa2e994044efe7611c03840bd198f9144c7f3b 100644 --- a/ESH-INF/config/config.xml +++ b/ESH-INF/config/config.xml @@ -16,6 +16,11 @@ <description>Base topic for publishing updates. Do not include a trailing slash.</description> <default>sensors</default> </parameter> + <parameter name="unsupported-category-reset" type="integer" required="false"> + <label>MQTT Unsupported Category Reset Timeout</label> + <description>Timeout in seconds to log again unsupported MQTT categories. Set to zero to disable (default).</description> + <default>0</default> + </parameter> </config-description> </config-description:config-descriptions> diff --git a/ESH-INF/thing/thing-types.xml b/ESH-INF/thing/thing-types.xml index ae709002d0da722f09c91159128688de2b96402b..7d84ec764ae49fb98ab141448188526934c84129 100644 --- a/ESH-INF/thing/thing-types.xml +++ b/ESH-INF/thing/thing-types.xml @@ -31,19 +31,28 @@ <description>Provides sensor information from a Polar M600 smart watch</description> <channels> - <channel typeId="polar-acceleration-type" id="polar-acceleration-x"> + <channel typeId="acceleration-type" id="acceleration-x"> <label>Acceleration X</label> - <description>Acceleration on the x-axis.</description> </channel> - <channel typeId="polar-acceleration-type" id="polar-acceleration-y" /> - <channel typeId="polar-acceleration-type" id="polar-acceleration-z" /> - <channel typeId="polar-rotation-type" id="polar-rotation-x" /> - <channel typeId="polar-rotation-type" id="polar-rotation-y" /> - <channel typeId="polar-rotation-type" id="polar-rotation-z" /> - <channel typeId="polar-activity-type" id="polar-activity" /> - <channel typeId="polar-heart-rate-type" id="polar-heart-rate" /> - <channel typeId="polar-steps-type" id="polar-steps" /> - <channel typeId="openlicht-brightness-type" id="polar-brightness" /> + <channel typeId="acceleration-type" id="acceleration-y"> + <label>Acceleration Y</label> + </channel> + <channel typeId="acceleration-type" id="acceleration-z"> + <label>Acceleration Z</label> + </channel> + <channel typeId="rotation-type" id="rotation-x"> + <label>Rotation X</label> + </channel> + <channel typeId="rotation-type" id="rotation-y"> + <label>Rotation Y</label> + </channel> + <channel typeId="rotation-type" id="rotation-z"> + <label>Rotation Z</label> + </channel> + <channel typeId="activity-type" id="activity" /> + <channel typeId="heart-rate-type" id="heart-rate" /> + <channel typeId="steps-type" id="steps" /> + <channel typeId="brightness-type" id="brightness" /> </channels> <config-description-ref uri="thing-type:openlicht:mqttdevice" /> @@ -55,26 +64,35 @@ <description>Provides sensor information from a Moto 360 smart watch</description> <channels> - <channel typeId="polar-acceleration-type" id="polar-acceleration-x"> + <channel typeId="acceleration-type" id="acceleration-x"> <label>Acceleration X</label> - <description>Acceleration on the x-axis.</description> </channel> - <channel typeId="polar-acceleration-type" id="polar-acceleration-y" /> - <channel typeId="polar-acceleration-type" id="polar-acceleration-z" /> - <channel typeId="polar-rotation-type" id="polar-rotation-x" /> - <channel typeId="polar-rotation-type" id="polar-rotation-y" /> - <channel typeId="polar-rotation-type" id="polar-rotation-z" /> - <channel typeId="polar-activity-type" id="polar-activity" /> - <channel typeId="polar-heart-rate-type" id="polar-heart-rate" /> - <channel typeId="polar-steps-type" id="polar-steps" /> - <channel typeId="openlicht-brightness-type" id="polar-brightness" /> + <channel typeId="acceleration-type" id="acceleration-y"> + <label>Acceleration Y</label> + </channel> + <channel typeId="acceleration-type" id="acceleration-z"> + <label>Acceleration Z</label> + </channel> + <channel typeId="rotation-type" id="rotation-x"> + <label>Rotation X</label> + </channel> + <channel typeId="rotation-type" id="rotation-y"> + <label>Rotation Y</label> + </channel> + <channel typeId="rotation-type" id="rotation-z"> + <label>Rotation Z</label> + </channel> + <channel typeId="activity-type" id="activity" /> + <channel typeId="heart-rate-type" id="heart-rate" /> + <channel typeId="steps-type" id="steps" /> + <channel typeId="brightness-type" id="brightness" /> </channels> <config-description-ref uri="thing-type:openlicht:mqttdevice" /> </thing-type> <!-- Accelerator Type --> - <channel-type id="polar-acceleration-type"> + <channel-type id="acceleration-type"> <item-type>Number</item-type> <label>Acceleration</label> <description>Acceleration in one direction in meters per second.</description> @@ -83,7 +101,7 @@ </channel-type> <!-- Rotation Type --> - <channel-type id="polar-rotation-type"> + <channel-type id="rotation-type"> <item-type>Number</item-type> <label>Rotation</label> <description>Rotation around one axis (unitless).</description> @@ -92,7 +110,7 @@ </channel-type> <!-- Activity Type --> - <channel-type id="polar-activity-type"> + <channel-type id="activity-type"> <item-type>String</item-type> <label>Activity</label> <description>Current recognized activity.</description> @@ -108,7 +126,7 @@ </channel-type> <!-- Heart Rate Type --> - <channel-type id="polar-heart-rate-type"> + <channel-type id="heart-rate-type"> <item-type>Number</item-type> <label>Heart Rate</label> <description>Heart rate in beats per minute.</description> @@ -116,7 +134,7 @@ </channel-type> <!-- Steps Type --> - <channel-type id="polar-steps-type"> + <channel-type id="steps-type"> <item-type>Number</item-type> <label>Steps</label> <description>Steps run today.</description> @@ -129,14 +147,23 @@ <description>Provides sensor information from a smart phone (a Samsung S6 in our case)</description> <channels> - <channel typeId="openlicht-brightness-type" id="samsung-brightness" /> + <channel typeId="brightness-type" id="brightness" /> + <channel typeId="rotation-type" id="rotation-x"> + <label>Rotation X</label> + </channel> + <channel typeId="rotation-type" id="rotation-y"> + <label>Rotation Y</label> + </channel> + <channel typeId="rotation-type" id="rotation-z"> + <label>Rotation Z</label> + </channel> </channels> <config-description-ref uri="thing-type:openlicht:mqttdevice" /> </thing-type> <!-- General Brightness Type --> - <channel-type id="openlicht-brightness-type"> + <channel-type id="brightness-type"> <item-type>Number</item-type> <label>Brightness</label> <description>Brightness (Lux).</description> diff --git a/pom.xml b/pom.xml index 65813eb2d4a861334681d8423f6f5d78a3e6bdd5..e590521ca4cecdbd3ff32d2a07127d1c127edd74 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>pom</artifactId> <groupId>org.openhab.binding</groupId> - <version>2.3.0-SNAPSHOT</version> + <version>2.4.0-SNAPSHOT</version> </parent> <artifactId>org.openhab.binding.openlicht</artifactId> diff --git a/src/main/java/org/openhab/binding/openlicht/BindingConstants.java b/src/main/java/org/openhab/binding/openlicht/BindingConstants.java index 0327eb53167a893766507d551a0e92327b3b1fa8..dabf7128bd67b28baacf4167e9a447a396c2e408 100644 --- a/src/main/java/org/openhab/binding/openlicht/BindingConstants.java +++ b/src/main/java/org/openhab/binding/openlicht/BindingConstants.java @@ -29,6 +29,7 @@ public class BindingConstants { // Configuration keys public static final String CONFIG_BROKER_NAME = "brokerName"; public static final String CONFIG_BASE_TOPIC = "base-topic"; + public static final String CONFIG_TIMEOUT_MQTT_UNSUPPORTED_CATEGORIES = "unsupported-category-reset"; // List of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_SKYWRITER_HAT = new ThingTypeUID(BINDING_ID, "skywriter-hat"); @@ -38,17 +39,16 @@ public class BindingConstants { // List of all Channel ids public static final String CHANNEL_FLICK = "flick"; - public static final String CHANNEL_ACCELERATION_X = "polar-acceleration-x"; - public static final String CHANNEL_ACCELERATION_Y = "polar-acceleration-y"; - public static final String CHANNEL_ACCELERATION_Z = "polar-acceleration-z"; - public static final String CHANNEL_ROTATION_X = "polar-rotation-x"; - public static final String CHANNEL_ROTATION_Y = "polar-rotation-y"; - public static final String CHANNEL_ROTATION_Z = "polar-rotation-z"; - public static final String CHANNEL_ACTIVITY = "polar-activity"; - public static final String CHANNEL_HEART_RATE = "polar-heart-rate"; - public static final String CHANNEL_STEPS = "polar-steps"; - public static final String CHANNEL_BRIGHTNESS_POLAR = "polar-brightness"; - public static final String CHANNEL_BRIGHTNESS_SAMSUNG = "samsung-brightness"; + public static final String CHANNEL_ACCELERATION_X = "acceleration-x"; + public static final String CHANNEL_ACCELERATION_Y = "acceleration-y"; + public static final String CHANNEL_ACCELERATION_Z = "acceleration-z"; + public static final String CHANNEL_ROTATION_X = "rotation-x"; + public static final String CHANNEL_ROTATION_Y = "rotation-y"; + public static final String CHANNEL_ROTATION_Z = "rotation-z"; + public static final String CHANNEL_ACTIVITY = "activity"; + public static final String CHANNEL_HEART_RATE = "heart-rate"; + public static final String CHANNEL_STEPS = "steps"; + public static final String CHANNEL_BRIGHTNESS = "brightness"; // List of MQTT categories public static final String MQTT_CATEGORY_FLICK = "flick"; diff --git a/src/main/java/org/openhab/binding/openlicht/handler/AbstractMqttHandler.java b/src/main/java/org/openhab/binding/openlicht/handler/AbstractMqttHandler.java index 2ee0ac7a4388c69fad9928ab48546792d6dbbd26..b94281b2a950b8402a38d9a500d92045381987e0 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/AbstractMqttHandler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/AbstractMqttHandler.java @@ -2,7 +2,12 @@ package org.openhab.binding.openlicht.handler; import static org.openhab.binding.openlicht.BindingConstants.*; +import java.math.BigDecimal; +import java.nio.ByteBuffer; +import java.util.concurrent.ScheduledExecutorService; + import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; @@ -12,6 +17,8 @@ import org.eclipse.smarthome.io.transport.mqtt.MqttBrokersObserver; import org.eclipse.smarthome.io.transport.mqtt.MqttException; import org.eclipse.smarthome.io.transport.mqtt.MqttMessageSubscriber; import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; +import org.osgi.framework.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +30,7 @@ public abstract class AbstractMqttHandler extends BaseThingHandler // protected OpenLichtConfiguration config; - private MqttService mqttService; + private @Nullable MqttService mqttService; private int usedTopicLength = 0; @@ -31,15 +38,21 @@ public abstract class AbstractMqttHandler extends BaseThingHandler private boolean warnNoBrokerConnection = true; - public AbstractMqttHandler(Thing thing, MqttService mqttService) { + protected @Nullable ScheduledExecutorService executor; + + private Version version; + + public AbstractMqttHandler(Thing thing, ConfigurationHolder configurationHolder) { super(thing); - this.mqttService = mqttService; + this.mqttService = configurationHolder.getMqttService(); + this.executor = configurationHolder.getExecutor(); + this.version = configurationHolder.getVersion(); } @Override public void initialize() { // config = getConfigAs(OpenLichtConfiguration.class); - String brokerName = getConfigValue(CONFIG_BROKER_NAME); + String brokerName = getConfigValueAsString(CONFIG_BROKER_NAME); // remove this handler from mqttService (in case initialize is called because of a config update) this.mqttService.removeBrokersListener(this); @@ -55,16 +68,21 @@ public abstract class AbstractMqttHandler extends BaseThingHandler brokerAdded(myBroker); } } - publish("init"); + publish("init version: " + version.toString()); } - private String getConfigValue(String key) { + protected String getConfigValueAsString(String key) { return (String) getThing().getConfiguration().get(key); } + protected Integer getConfigValueAsInteger(String key) { + BigDecimal bd = (BigDecimal) getThing().getConfiguration().get(key); + return bd == null ? null : bd.intValue(); + } + @Override public void brokerAdded(MqttBrokerConnection broker) { - String brokerName = getConfigValue(CONFIG_BROKER_NAME); + String brokerName = getConfigValueAsString(CONFIG_BROKER_NAME); if (broker.getName().equals(brokerName)) { // this is our broker! currentBrokerConnection = broker; @@ -94,7 +112,7 @@ public abstract class AbstractMqttHandler extends BaseThingHandler @Override public void brokerRemoved(MqttBrokerConnection broker) { - String brokerName = getConfigValue(CONFIG_BROKER_NAME); + String brokerName = getConfigValueAsString(CONFIG_BROKER_NAME); if (broker.getName().equals(brokerName)) { // this was our broker! updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Broker is offline"); @@ -123,7 +141,7 @@ public abstract class AbstractMqttHandler extends BaseThingHandler @Override public final String getTopic() { - return getConfigValue(CONFIG_BASE_TOPIC) + (getSubTopic() == null ? "" : "/" + getSubTopic()) + return getConfigValueAsString(CONFIG_BASE_TOPIC) + (getSubTopic() == null ? "" : "/" + getSubTopic()) + (subscribeSubTopics() ? "/#" : ""); } @@ -160,4 +178,16 @@ public abstract class AbstractMqttHandler extends BaseThingHandler return true; } + /** + * Writes a float array from the given input based on the length of the targeted output. + * + * @param input the buffer to read from + * @param output the array to write in + */ + protected void writeFloatArray(ByteBuffer input, float[] output) { + for (int i = 0; i < output.length; i++) { + output[i] = input.getFloat(); + } + } + } diff --git a/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartWatchHandler.java b/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartWatchHandler.java index 69c1724203f7851f9d6dbbb05118120cd95ee41e..b84a57b79395a84fb56bf5426d6bcf635052bb93 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartWatchHandler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartWatchHandler.java @@ -17,12 +17,14 @@ import static org.openhab.binding.openlicht.BindingConstants.*; import java.nio.ByteBuffer; import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,11 +38,30 @@ public abstract class AbstractSmartWatchHandler extends AbstractMqttHandler { private final Logger logger = LoggerFactory.getLogger(AbstractSmartWatchHandler.class); - private Set<String> seenUnsupportedCategories; + private static Set<String> seenUnsupportedCategories; - public AbstractSmartWatchHandler(Thing thing, MqttService mqttService) { - super(thing, mqttService); - seenUnsupportedCategories = new HashSet<>(); + private static ScheduledExecutorService executor; + + public AbstractSmartWatchHandler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); + maybeSetupStatics(); + Integer timeout = getConfigValueAsInteger(CONFIG_TIMEOUT_MQTT_UNSUPPORTED_CATEGORIES); + if (timeout != null && timeout > 0) { + Runnable command = new Runnable() { + + @Override + public void run() { + seenUnsupportedCategories.clear(); + } + }; + executor.scheduleAtFixedRate(command, 0, timeout, TimeUnit.SECONDS); + } + } + + private synchronized void maybeSetupStatics() { + if (seenUnsupportedCategories == null) { + seenUnsupportedCategories = new HashSet<>(); + } } @Override @@ -58,22 +79,19 @@ public abstract class AbstractSmartWatchHandler extends AbstractMqttHandler { public void processMessage(String topic, byte[] payload) { // switch category of message (last part of topic after last slash) String category = topic.substring(getTopicLength()); - // String state = new String(payload); ByteBuffer buffer = ByteBuffer.wrap(payload); float[] values; switch (category) { case MQTT_CATEGORY_BRIGHTNESS: - updateState(CHANNEL_BRIGHTNESS_POLAR, new DecimalType(buffer.getInt())); + updateState(CHANNEL_BRIGHTNESS, new DecimalType(buffer.getFloat())); break; case MQTT_CATEGORY_ACCELERATION: - // expected form: [0.12345678, 0.12345678, 0.12345678] values = new float[3]; writeFloatArray(buffer, values); updateState(CHANNEL_ACCELERATION_X, new DecimalType(values[0])); updateState(CHANNEL_ACCELERATION_Y, new DecimalType(values[1])); updateState(CHANNEL_ACCELERATION_Z, new DecimalType(values[2])); case MQTT_CATEGORY_ROTATION: - // expected form: [0.12345678, 0.12345678, 0.12345678] values = new float[3]; writeFloatArray(buffer, values); updateState(CHANNEL_ROTATION_X, new DecimalType(values[0])); @@ -84,12 +102,6 @@ public abstract class AbstractSmartWatchHandler extends AbstractMqttHandler { } } - private void writeFloatArray(ByteBuffer input, float[] output) { - for (int i = 0; i < output.length; i++) { - output[i] = input.getFloat(); - } - } - private void logUnsupportedCategory(String category) { if (seenUnsupportedCategories.add(category)) { logger.warn("Category not supported: {}", category); @@ -97,11 +109,6 @@ public abstract class AbstractSmartWatchHandler extends AbstractMqttHandler { } } - @Override - protected String getSubTopic() { - return "polar"; - } - @Override protected boolean subscribeSubTopics() { return true; diff --git a/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartphoneHandler.java b/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartphoneHandler.java index 8f928400226acd405709ff374ecb6c022a0f9151..e9f70183e0bd54f7f1090097184328f3a693d3a6 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartphoneHandler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/AbstractSmartphoneHandler.java @@ -14,6 +14,8 @@ package org.openhab.binding.openlicht.handler; import static org.openhab.binding.openlicht.BindingConstants.*; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; import java.util.HashSet; import java.util.Set; @@ -21,7 +23,7 @@ import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,8 +39,8 @@ public abstract class AbstractSmartphoneHandler extends AbstractMqttHandler { private Set<String> seenUnsupportedCategories; - public AbstractSmartphoneHandler(Thing thing, MqttService mqttService) { - super(thing, mqttService); + public AbstractSmartphoneHandler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); seenUnsupportedCategories = new HashSet<>(); } @@ -46,7 +48,7 @@ public abstract class AbstractSmartphoneHandler extends AbstractMqttHandler { public void handleCommand(ChannelUID channelUID, Command command) { String channelId = channelUID.getId(); switch (channelId) { - case CHANNEL_BRIGHTNESS_SAMSUNG: + case CHANNEL_BRIGHTNESS: break; default: logger.warn("Unknown channel id {}!", channelId); @@ -57,11 +59,17 @@ public abstract class AbstractSmartphoneHandler extends AbstractMqttHandler { public void processMessage(String topic, byte[] payload) { // switch category of message (last part of topic after last slash) String category = topic.substring(getTopicLength()); - String state = new String(payload); + ByteBuffer buffer = ByteBuffer.wrap(payload); + FloatBuffer floatBuffer; switch (category) { case MQTT_CATEGORY_BRIGHTNESS: - updateState(CHANNEL_BRIGHTNESS_SAMSUNG, DecimalType.valueOf(state)); + updateState(CHANNEL_BRIGHTNESS, new DecimalType(buffer.getFloat())); break; + case MQTT_CATEGORY_ROTATION: + floatBuffer = buffer.asFloatBuffer(); + updateState(CHANNEL_ROTATION_X, new DecimalType(floatBuffer.get(0))); + updateState(CHANNEL_ROTATION_Y, new DecimalType(floatBuffer.get(1))); + updateState(CHANNEL_ROTATION_Z, new DecimalType(floatBuffer.get(2))); default: logUnsupportedCategory(category); } diff --git a/src/main/java/org/openhab/binding/openlicht/handler/Moto360Handler.java b/src/main/java/org/openhab/binding/openlicht/handler/Moto360Handler.java index 4d5a57cbc09af2155dd51567977dfe391fa31472..bf201fa5562a9e41dec5210fd31d00c05f746dd6 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/Moto360Handler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/Moto360Handler.java @@ -1,12 +1,17 @@ package org.openhab.binding.openlicht.handler; import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; public class Moto360Handler extends AbstractSmartWatchHandler { - public Moto360Handler(Thing thing, MqttService mqttService) { - super(thing, mqttService); + public Moto360Handler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); + } + + @Override + protected String getSubTopic() { + return "moto360"; } } diff --git a/src/main/java/org/openhab/binding/openlicht/handler/PolarM600Handler.java b/src/main/java/org/openhab/binding/openlicht/handler/PolarM600Handler.java index 934d399ec6791f22a56ce17d96c120e7d91434a4..6e30e8dd3b16663862b725501b24c7c4d70ab340 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/PolarM600Handler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/PolarM600Handler.java @@ -1,12 +1,17 @@ package org.openhab.binding.openlicht.handler; import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; public class PolarM600Handler extends AbstractSmartWatchHandler { - public PolarM600Handler(Thing thing, MqttService mqttService) { - super(thing, mqttService); + public PolarM600Handler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); + } + + @Override + protected String getSubTopic() { + return "polar"; } } diff --git a/src/main/java/org/openhab/binding/openlicht/handler/SamsungS6Handler.java b/src/main/java/org/openhab/binding/openlicht/handler/SamsungS6Handler.java index 6a8eb3ac1ed0c0abc7dcb728293862034f8d8cd6..2a65819c0f2ff5fd864042b953d70d873cd9c2f7 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/SamsungS6Handler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/SamsungS6Handler.java @@ -1,12 +1,12 @@ package org.openhab.binding.openlicht.handler; import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; public class SamsungS6Handler extends AbstractSmartphoneHandler { - public SamsungS6Handler(Thing thing, MqttService mqttService) { - super(thing, mqttService); + public SamsungS6Handler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); } } diff --git a/src/main/java/org/openhab/binding/openlicht/handler/SkyWriterHATHandler.java b/src/main/java/org/openhab/binding/openlicht/handler/SkyWriterHATHandler.java index bdfae51465d11859254a267e9ec681cb2b3ef6c3..d5d97b9638ee7c26159722bc25d067b12211052b 100644 --- a/src/main/java/org/openhab/binding/openlicht/handler/SkyWriterHATHandler.java +++ b/src/main/java/org/openhab/binding/openlicht/handler/SkyWriterHATHandler.java @@ -14,7 +14,7 @@ import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.openhab.binding.openlicht.internal.ConfigurationHolder; /** * The {@link SkyWriterHATHandler} is responsible for handling commands, which are @@ -24,8 +24,8 @@ import org.eclipse.smarthome.io.transport.mqtt.MqttService; */ public class SkyWriterHATHandler extends AbstractMqttHandler { - public SkyWriterHATHandler(Thing thing, MqttService mqttService) { - super(thing, mqttService); + public SkyWriterHATHandler(Thing thing, ConfigurationHolder configurationHolder) { + super(thing, configurationHolder); } @Override diff --git a/src/main/java/org/openhab/binding/openlicht/internal/ConfigurationHolder.java b/src/main/java/org/openhab/binding/openlicht/internal/ConfigurationHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..8355ff91ebe90beedc5ef15c3573fa84dbbfaa4a --- /dev/null +++ b/src/main/java/org/openhab/binding/openlicht/internal/ConfigurationHolder.java @@ -0,0 +1,19 @@ +package org.openhab.binding.openlicht.internal; + +import java.util.concurrent.ScheduledExecutorService; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.io.transport.mqtt.MqttService; +import org.osgi.framework.Version; + +public interface ConfigurationHolder { + + @Nullable + ScheduledExecutorService getExecutor(); + + @Nullable + MqttService getMqttService(); + + Version getVersion(); + +} diff --git a/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtConfiguration.java b/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtConfiguration.java index 6cde499d91d43d81d2ef2fc700abd4e12ef9dadc..28824d9695ed41d9927f29f04222d2ca4c9f6c7d 100644 --- a/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtConfiguration.java +++ b/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtConfiguration.java @@ -25,7 +25,12 @@ public class OpenLichtConfiguration { public String brokerName; /** - * Topic for subscription. + * Base topic for publishing updates. Do not include a trailing slash. */ - public String topic; + public String baseTopic; + + /** + * Timeout in seconds to log again unsupported MQTT categories. Set to zero to disable (default). + */ + public int unsupportedCategoryResetTimeout; } diff --git a/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtHandlerFactory.java b/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtHandlerFactory.java index 5ef4ad154eff11db99cac5de51e6b236b218302e..79ec8565f3edc8a4e6fa49ffb5ed39c5557bd56a 100644 --- a/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtHandlerFactory.java +++ b/src/main/java/org/openhab/binding/openlicht/internal/OpenLichtHandlerFactory.java @@ -16,6 +16,8 @@ import static org.openhab.binding.openlicht.BindingConstants.*; import java.util.Collections; import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -31,6 +33,9 @@ import org.openhab.binding.openlicht.handler.Moto360Handler; import org.openhab.binding.openlicht.handler.PolarM600Handler; import org.openhab.binding.openlicht.handler.SamsungS6Handler; import org.openhab.binding.openlicht.handler.SkyWriterHATHandler; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.Version; +import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; @@ -45,12 +50,13 @@ import org.slf4j.LoggerFactory; */ @NonNullByDefault @Component(configurationPid = "binding.openlicht", service = ThingHandlerFactory.class) -public class OpenLichtHandlerFactory extends BaseThingHandlerFactory { +public class OpenLichtHandlerFactory extends BaseThingHandlerFactory implements ConfigurationHolder { private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( Stream.of(THING_TYPE_SKYWRITER_HAT, THING_TYPE_POLAR_M600, THING_TYPE_MOTO_360, THING_TYPE_SAMSUNG_S6) .collect(Collectors.toSet())); private @Nullable MqttService service; + private @Nullable ScheduledExecutorService executor; @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -62,21 +68,50 @@ public class OpenLichtHandlerFactory extends BaseThingHandlerFactory { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (THING_TYPE_SKYWRITER_HAT.equals(thingTypeUID)) { - return new SkyWriterHATHandler(thing, this.service); + return new SkyWriterHATHandler(thing, this); } if (THING_TYPE_POLAR_M600.equals(thingTypeUID)) { - return new PolarM600Handler(thing, this.service); + return new PolarM600Handler(thing, this); } if (THING_TYPE_MOTO_360.equals(thingTypeUID)) { - return new Moto360Handler(thing, this.service); + return new Moto360Handler(thing, this); } if (THING_TYPE_SAMSUNG_S6.equals(thingTypeUID)) { - return new SamsungS6Handler(thing, this.service); + return new SamsungS6Handler(thing, this); } return null; } + @Override + protected void activate(ComponentContext componentContext) { + super.activate(componentContext); + executor = Executors.newScheduledThreadPool(2); + } + + @Override + protected void deactivate(ComponentContext componentContext) { + super.deactivate(componentContext); + if (executor != null) { + executor.shutdown(); + } + } + + @Override + public @Nullable ScheduledExecutorService getExecutor() { + return executor; + } + + @Override + public @Nullable MqttService getMqttService() { + return service; + } + + @Override + public Version getVersion() { + return FrameworkUtil.getBundle(getClass()).getVersion(); + } + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) public void setMqttService(MqttService service) { LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Setting mqtt service to {}", service);