Skip to content
Snippets Groups Projects
Commit 08227a2f authored by René Schöne's avatar René Schöne
Browse files

Refactoring to (hopefully now) correct version of mqtt and some cleanup.

- Added HandlerPhase for better thing status updates
- Do not use MqttService anymore, instead register for thing changes and react, if broker is found
- Working on EraserHandler, not fully working yet
- Remove date on binding xml, as updating the bundle works reliably now
parent 194d753c
Branches
No related tags found
No related merge requests found
Showing
with 447 additions and 154 deletions
......@@ -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 (Last Update: 2019-04-09 15:21).</description>
<description>This is the binding for OpenLicht.</description>
<author>René Schöne</author>
</binding:binding>
......@@ -8,6 +8,7 @@
<thing-type id="eraser">
<label>Eraser</label>
<description>Establish communication with a running eraser via MQTT</description>
<config-description>
<parameter name="brokerName" type="text" required="true">
<label>Broker Name</label>
......@@ -30,6 +31,11 @@
<description>MQTT topic prefix for messages leaving openHAB to eraser.</description>
<default>oh/out/</default>
</parameter>
<parameter name="publish-group" type="text" required="true">
<label>Publish group</label>
<description>Group whose member will trigger an update</description>
<context>item</context>
</parameter>
</config-description>
</thing-type>
......
......@@ -9,9 +9,11 @@ Bundle-Vendor: openHAB
Bundle-Version: 2.3.0.qualifier
Import-Package:
org.eclipse.jdt.annotation;resolution:=optional,
org.eclipse.smarthome.binding.mqtt.handler,
org.eclipse.smarthome.config.core,
org.eclipse.smarthome.core.common.registry,
org.eclipse.smarthome.core.events,
org.eclipse.smarthome.core.items,
org.eclipse.smarthome.core.items.events,
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.thing,
......@@ -22,7 +24,9 @@ Import-Package:
org.eclipse.smarthome.io.transport.mqtt,
org.osgi.framework,
org.osgi.service.component,
org.osgi.service.component.annotations;version="[1.3.0,2.0.0)";resolution:=optional,
org.slf4j
Service-Component: OSGI-INF/*.xml
Export-Package: org.openhab.binding.openlicht,
org.openhab.binding.openlicht.handler
Automatic-Module-Name: org.openhab.binding.openlicht
......@@ -32,6 +32,7 @@ public class BindingConstants {
public static final String CONFIG_BYTE_BASED_MESSAGES = "byte-based-messages";
public static final String CONFIG_TIMEOUT_MQTT_UNSUPPORTED_CATEGORIES = "unsupported-category-reset";
public static final String CONFIG_ERASER_OUT_TOPIC = "outTopic";
public static final String CONFIG_ERASER_PUBLISH_GROUP = "publish-group";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_SKYWRITER_HAT = new ThingTypeUID(BINDING_ID, "skywriter-hat");
......
package org.openhab.binding.openlicht.handler;
import static org.openhab.binding.openlicht.BindingConstants.*;
import static org.openhab.binding.openlicht.handler.HandlerPhase.*;
import java.math.BigDecimal;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.binding.mqtt.handler.AbstractBrokerHandler;
import org.eclipse.smarthome.core.common.registry.RegistryChangeListener;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingRegistry;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
//import org.openhab.binding.mqtt.handler.AbstractBrokerHandler;
//import org.openhab.binding.openlicht.internal.ConfigurationHolder;
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
import org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection;
import org.eclipse.smarthome.io.transport.mqtt.MqttMessageSubscriber;
import org.eclipse.smarthome.io.transport.mqtt.MqttService;
import org.eclipse.smarthome.io.transport.mqtt.MqttServiceObserver;
import org.openhab.binding.openlicht.internal.ConfigurationHolder;
import org.osgi.framework.Version;
......@@ -28,11 +27,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractMqttHandler extends BaseThingHandler
implements MqttMessageSubscriber, MqttServiceObserver/* , RegistryChangeListener<Thing> */ {
implements MqttMessageSubscriber, MqttServiceObserver, RegistryChangeListener<Thing> {
protected final @NonNull Logger logger = LoggerFactory.getLogger(AbstractMqttHandler.class);
// private @Nullable ThingRegistry thingRegistry;
private @Nullable MqttService mqttService;
private final @NonNull Logger logger = LoggerFactory.getLogger(AbstractMqttHandler.class);
private @Nullable ThingRegistry thingRegistry;
// private @Nullable MqttService mqttService;
private int usedTopicLength = 0;
private MqttBrokerConnection currentBrokerConnection = null;
private boolean warnNoBrokerConnection = true;
......@@ -44,44 +43,49 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
public AbstractMqttHandler(Thing thing, ConfigurationHolder configurationHolder) {
super(thing);
// this.thingRegistry = configurationHolder.getThingRegistry();
// this.thingRegistry.addRegistryChangeListener(this);
this.mqttService = configurationHolder.getMqttService();
if (this.mqttService != null) {
this.mqttService.addBrokersListener(this);
this.thingRegistry = configurationHolder.getThingRegistry();
if (this.thingRegistry != null) {
this.thingRegistry.addRegistryChangeListener(this);
} else {
logger.warn("No mqtt service, so no broker listener added");
logger.warn("No Thing registry, so no updated broker");
}
// this.mqttService = configurationHolder.getMqttService();
// if (this.mqttService != null) {
// this.mqttService.addBrokersListener(this);
// } else {
// logger.warn("No mqtt service, so no broker listener added");
// }
this.executor = configurationHolder.getExecutor();
this.version = configurationHolder.getVersion();
this.configUpdateLock = new ReentrantLock();
logger.info("Started handler " + this.getClass().getSimpleName() + " in version " + version);
}
// @Override
// public void added(Thing element) {
// if (thingIsMyMqttBroker(element)) {
// addConnectionOf(element);
// }
// }
//
// @Override
// public void removed(Thing element) {
// if (thingIsMyMqttBroker(element)) {
// removeMyBroker();
// }
// }
//
// @Override
// public void updated(Thing oldElement, Thing element) {
// if (thingIsMyMqttBroker(element)) {
// removeMyBroker();
// addConnectionOf(element);
// }
// }
@Override
public void added(Thing element) {
if (thingIsMyMqttBroker(element)) {
addConnectionOf(element);
}
}
@Override
public void removed(Thing element) {
if (thingIsMyMqttBroker(element)) {
removeMyBroker();
}
}
@Override
public void updated(Thing oldElement, Thing element) {
if (thingIsMyMqttBroker(element)) {
removeMyBroker();
addConnectionOf(element);
}
}
@Override
public void brokerAdded(String brokerID, MqttBrokerConnection broker) {
logger.debug("{} checking new broker '{}'", me(), brokerID);
if (brokerID.equals(myBrokerName)) {
myBrokerAdded(broker);
}
......@@ -94,60 +98,68 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
}
}
// private boolean thingIsMyMqttBroker(Thing thing) {
// if (!"mqtt:systemBroker".equals(thing.getThingTypeUID().getAsString())
// && !"mqtt:broker".equals(thing.getThingTypeUID().getAsString())) {
// return false;
// }
// return myBrokerName.equals(thing.getUID().getAsString());
// }
private boolean thingIsMyMqttBroker(Thing thing) {
if (myBrokerName == null) {
logger.warn("Broker name of {} not set", me());
return false;
}
if (!"mqtt:systemBroker".equals(thing.getThingTypeUID().getAsString())
&& !"mqtt:broker".equals(thing.getThingTypeUID().getAsString())) {
return false;
}
return myBrokerName.equals(thing.getLabel());
}
// private void addConnectionOf(Thing mqttBroker) {
// ThingHandler handler = mqttBroker.getHandler();
// this.mqttService.addBrokerConnection(myBrokerName, currentBrokerConnection)
// if (handler instanceof AbstractBrokerHandler) {
// AbstractBrokerHandler abh = (AbstractBrokerHandler) handler;
// myBrokerAdded(abh.getConnection());
// }
// }
private void addConnectionOf(Thing mqttBroker) {
ThingHandler handler = mqttBroker.getHandler();
// this.mqttService.addBrokerConnection(myBrokerName, currentBrokerConnection);
if (handler instanceof AbstractBrokerHandler) {
AbstractBrokerHandler abh = (AbstractBrokerHandler) handler;
myBrokerAdded(abh.getConnection());
}
}
@Override
public void initialize() {
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_PENDING, "Searching broker");
statusUpdate(INIT, true, "Searching broker");
new Thread(() -> {
try {
this.logger.debug("Initializing {}", me());
this.configUpdateLock.lock();
this.logger.debug("Initializing");
moreInitializeBefore();
this.byteBaseMessages = getConfigValueAsBoolean(CONFIG_BYTE_BASED_MESSAGES);
String brokerName = getConfigValueAsString(CONFIG_BROKER_NAME);
if (brokerName == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "BrokerName not set");
statusUpdate(CONFIGURATION, false, "BrokerName not set");
return;
}
this.myBrokerName = brokerName;
logger.debug("Setting myBrokerName to '{}'", myBrokerName);
logger.debug("Setting myBrokerName to '{}' for {}", myBrokerName, me());
// for (Thing thing : this.thingRegistry.getAll()) {
// if (thingIsMyMqttBroker(thing)) {
// addConnectionOf(thing);
// }
// }
MqttService service = this.mqttService;
if (service == null) {
logger.debug("No mqtt service yet");
} else {
for (Entry<@NonNull String, @NonNull MqttBrokerConnection> entry : service.getAllBrokerConnections()
.entrySet()) {
brokerAdded(entry.getKey(), entry.getValue());
if (this.thingRegistry != null) {
for (Thing thing : this.thingRegistry.getAll()) {
if (thingIsMyMqttBroker(thing)) {
addConnectionOf(thing);
}
}
} else {
logger.warn("No thing registry, thus no broker connection");
}
// MqttService service = this.mqttService;
// if (service == null) {
// logger.warn("No mqtt service yet for {}", me());
// } else {
// for (Entry<@NonNull String, @NonNull MqttBrokerConnection> entry : service.getAllBrokerConnections()
// .entrySet()) {
// brokerAdded(entry.getKey(), entry.getValue());
// }
// }
if (this.currentBrokerConnection == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
"Broker with name '" + this.myBrokerName + "' not found.");
} else {
updateStatus(ThingStatus.ONLINE);
statusUpdate(COMMUNICATION, false,
"Broker with name '" + this.myBrokerName + "' not found for " + me());
}
moreInitialize();
moreInitializeAfter();
logger.debug("Finished initialization of {}", me());
} finally {
this.configUpdateLock.unlock();
}
......@@ -168,27 +180,23 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
}
public void myBrokerAdded(MqttBrokerConnection broker) {
this.logger.info("Got correct broker, subscribing to topic {}", getTopic());
this.logger.info("Got correct broker {}, subscribing to topic {} for {}", broker, getTopic(), me());
currentBrokerConnection = broker;
warnNoBrokerConnection = true;
updateTopicLength();
CompletableFuture<@NonNull Boolean> future = null;
try {
currentBrokerConnection.start();
if (subscribeTopic()) {
future = broker.subscribe(getTopic(), this);
}
if (future != null && future.get()) {
updateStatus(ThingStatus.ONLINE);
this.logger.info("Broker found, thing is online");
}
} catch (InterruptedException e) {
this.logger.debug("Interrupted while waiting for connection");
} catch (ExecutionException e) {
String message = "Could not add subscriber to broker";
this.logger.error(message);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
this.logger.warn("exception", e);
String description = "Subscribing to topic " + getTopic() + " at " + broker;
statusUpdate(CONFIGURATION, true, description);
currentBrokerConnection.start();
if (subscribeTopic()) {
broker.subscribe(getTopic(), this).whenComplete((result, exception) -> {
if (exception != null) {
this.logger.warn("exception", exception);
statusUpdate(COMMUNICATION, false, exception.getMessage());
return;
}
this.logger.info("Broker found for {}, thing is online", me());
statusUpdate(FINISH, true, "Finished");
});
}
}
......@@ -199,10 +207,21 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
}
public void removeMyBroker() {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Broker is offline");
if (this.mqttService != null) {
this.mqttService.removeBrokerConnection(myBrokerName);
statusUpdate(COMMUNICATION, false, "Broker is offline");
try {
if (currentBrokerConnection != null) {
currentBrokerConnection.unsubscribe(getTopic(), this);
}
} finally {
currentBrokerConnection = null;
logger.debug("Removing broker of {}", me());
}
}
@Override
public void dispose() {
super.dispose();
logger.debug("Disposing " + this);
currentBrokerConnection = null;
}
......@@ -210,7 +229,7 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
if (currentBrokerConnection == null) {
if (warnNoBrokerConnection) {
// just report once
logger.warn("Can't publish message, no connection");
logger.warn("Can't publish message in {}, no connection", me());
warnNoBrokerConnection = false;
}
return;
......@@ -230,10 +249,53 @@ public abstract class AbstractMqttHandler extends BaseThingHandler
return this.usedTopicLength;
}
protected String me() {
return this.getClass().getSimpleName() + ":" + getThing().getUID().getAsString();
}
/**
* Updates the state of the managed thing. Subclasses may override this to add special handling.
*
* @param phase Phase of the thing configuration
* @param success Whether the phase was successful
* @param description Detailed description of the status
*/
protected void statusUpdate(HandlerPhase phase, boolean success, String description) {
switch (phase) {
case INIT:
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_PENDING, description);
break;
case CONFIGURATION:
if (success) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, description);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description);
}
break;
case COMMUNICATION:
if (success) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, description);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, description);
}
break;
case FINISH:
updateStatus(ThingStatus.ONLINE);
break;
}
}
/**
* Subclasses may override this to do more asynchronous initialization before normal initialization.
*/
protected void moreInitializeBefore() {
// empty by default
}
/**
* Subclasses may override this to do more asynchronous initialization.
* Subclasses may override this to do more asynchronous initialization after normal initialization.
*/
protected void moreInitialize() {
protected void moreInitializeAfter() {
// empty by default
}
......
......@@ -23,6 +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.core.types.RefreshType;
import org.openhab.binding.openlicht.internal.ConfigurationHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -46,6 +47,9 @@ public abstract class AbstractSmartphoneHandler extends AbstractMqttHandler {
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
return;
}
logger.info("Got command for read-only thing: {} {}", channelUID.getAsString(), command.toFullString());
}
......
package org.openhab.binding.openlicht.handler;
import java.util.Collections;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.events.Event;
import org.eclipse.smarthome.core.events.EventFilter;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.events.EventSubscriber;
import org.eclipse.smarthome.core.items.events.ItemEventFactory;
import org.eclipse.smarthome.core.items.events.ItemStateEvent;
import org.eclipse.smarthome.core.items.GenericItem;
import org.eclipse.smarthome.core.items.GroupItem;
import org.eclipse.smarthome.core.items.Item;
import org.eclipse.smarthome.core.items.ItemNotFoundException;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.items.StateChangeListener;
import org.eclipse.smarthome.core.library.types.DateTimeType;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.library.types.HSBType;
import org.eclipse.smarthome.core.library.types.OnOffType;
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.core.types.State;
import org.openhab.binding.openlicht.BindingConstants;
import org.openhab.binding.openlicht.internal.ConfigurationHolder;
import org.openhab.binding.openlicht.internal.DelegateEraserRegistryChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EraserHandler extends AbstractMqttHandler implements EventSubscriber {
public class EraserHandler extends AbstractMqttHandler implements StateChangeListener {
private @Nullable EventPublisher eventPublisher;
private final @NonNull Logger logger = LoggerFactory.getLogger(EraserHandler.class);
private @Nullable ItemRegistry itemRegistry;
private String outTopic;
private String publishGroupName;
private boolean publishGroupFound = false;
private Set<GenericItem> observedItems = new HashSet<>();
private WeakReference<DelegateEraserRegistryChangeListener> delegateListener;
private HandlerPhase lastStatusUpdatePhase;
private boolean lastStatusUpdateSuccess;
private String lastStatusUpdateDescription;
public EraserHandler(Thing thing, ConfigurationHolder configurationHolder) {
super(thing, configurationHolder);
this.eventPublisher = configurationHolder.getEventPublisher();
this.itemRegistry = configurationHolder.getItemRegistry();
ItemRegistry registry = this.itemRegistry;
if (registry != null) {
delegateListener = new WeakReference<DelegateEraserRegistryChangeListener>(
new DelegateEraserRegistryChangeListener(this));
registry.addRegistryChangeListener(delegateListener.get());
}
}
@Override
protected void moreInitialize() {
protected void moreInitializeBefore() {
this.outTopic = getConfigValueAsString(BindingConstants.CONFIG_ERASER_OUT_TOPIC);
this.publishGroupName = getConfigValueAsString(BindingConstants.CONFIG_ERASER_PUBLISH_GROUP);
if (this.outTopic.charAt(this.outTopic.length() - 1) != '/') {
this.outTopic += "/";
}
if (this.itemRegistry != null) {
try {
Item publishGroupItem = this.itemRegistry.getItem(this.publishGroupName);
myGroupFound(publishGroupItem);
} catch (ItemNotFoundException e) {
this.publishGroupFound = false;
logger.warn("Could not find group with name '" + this.publishGroupName + "'");
}
} else {
logger.warn("No item registry set, so no updates for item changes");
}
}
private void myGroupFound(Item publishGroupItem) {
if (publishGroupItem instanceof GroupItem) {
this.publishGroupFound = true;
GroupItem groupItem = (GroupItem) publishGroupItem;
for (Item member : groupItem.getAllMembers()) {
added(member);
}
} else {
logger.warn("Found an item with name {}, but was not a generic item", this.publishGroupName);
}
}
@Override
protected void statusUpdate(HandlerPhase phase, boolean success, String description) {
this.lastStatusUpdatePhase = phase;
this.lastStatusUpdateSuccess = success;
this.lastStatusUpdateDescription = description;
String newDescription = description;
if (!this.publishGroupFound) {
// append information to description
newDescription = description + (success ? ", but" : " and") + " group to publish with name '"
+ this.publishGroupName + "' not found.";
}
switch (phase) {
case INIT:
super.statusUpdate(phase, success, description);
break;
case CONFIGURATION:
case COMMUNICATION:
super.statusUpdate(phase, success, newDescription);
break;
case FINISH:
if (this.publishGroupFound) {
super.statusUpdate(phase, success, description);
} else {
super.statusUpdate(HandlerPhase.CONFIGURATION, false, newDescription);
}
break;
}
}
@Override
public void dispose() {
super.dispose();
if (this.itemRegistry != null) {
this.itemRegistry.removeRegistryChangeListener(delegateListener.get());
delegateListener.clear();
}
for (GenericItem observedItem : observedItems) {
observedItem.removeStateChangeListener(this);
}
}
@Override
public void processMessage(String topic, byte[] payload) {
// check topic, and forward payload to respective item
logger.debug("Got message, in topc: '" + topic + "'");
int indexOfLastSlash = topic.lastIndexOf('/');
String itemName = topic.substring(indexOfLastSlash);
ItemStateEvent eshEvent = ItemEventFactory.createStateEvent(itemName, new StringType(new String(payload)));
EventPublisher publisher = this.eventPublisher;
if (publisher == null) {
logger.debug("No event publisher to process message");
String itemName = topic.substring(indexOfLastSlash + 1);
logger.debug("Using item name: '" + itemName + "'");
ItemRegistry registry = this.itemRegistry;
if (registry != null) {
Item item;
try {
item = registry.getItem(itemName);
} catch (ItemNotFoundException e) {
logger.debug("Item with name '" + itemName + "' not found.");
return;
}
// assume this is a GenericItem
GenericItem genericItem = (GenericItem) item;
State newState = setState(genericItem, new String(payload));
if (newState != null) {
genericItem.setState(newState);
} else {
logger.warn("Could not set state for {} using '{}'", genericItem, new String(payload));
}
genericItem.setState(new StringType(new String(payload)));
} else {
publisher.post(eshEvent);
logger.debug("No item registry to process message");
}
}
private State setState(GenericItem genericItem, String state) {
for (Class<? extends @NonNull State> type : genericItem.getAcceptedDataTypes()) {
if (type.equals(StringType.class)) {
return new StringType(state);
} else if (type.equals(DecimalType.class)) {
return new DecimalType(state);
} else if (type.equals(OnOffType.class)) {
return OnOffType.from(state);
} else if (type.equals(DateTimeType.class)) {
return new DateTimeType(state);
} else if (type.equals(HSBType.class)) {
return new HSBType(state);
}
}
return null;
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("got a command " + command);
}
//
// @Override
// public Set<@NonNull String> getSubscribedEventTypes() {
// return Collections.singleton(ItemStateEvent.TYPE);
// }
//
// @Override
// public @Nullable EventFilter getEventFilter() {
// return null;
// }
//
// @Override
// public void receive(Event event) {
// // publish MQTT message
// logger.debug("Received an event: " + event);
// ItemStateEvent itemStateEvent = (ItemStateEvent) event;
// String topic = outTopic + itemStateEvent.getItemName();
// String payload = itemStateEvent.getPayload();
// publish(topic, payload);
// }
@Override
public Set<@NonNull String> getSubscribedEventTypes() {
return Collections.singleton(ItemStateEvent.TYPE);
public void added(Item element) {
GenericItem genericItem = (GenericItem) element;
if (!this.publishGroupFound && genericItem.getName().equals(this.publishGroupName)) {
myGroupFound(genericItem);
// update status with last known value (to remove the clause about missing group item)
statusUpdate(lastStatusUpdatePhase, lastStatusUpdateSuccess, lastStatusUpdateDescription);
}
List<@NonNull String> groupNames = genericItem.getGroupNames();
if (groupNames.contains(this.publishGroupName)) {
if (observedItems.add(genericItem)) {
genericItem.addStateChangeListener(this);
}
}
}
@Override
public @Nullable EventFilter getEventFilter() {
return null;
public void removed(Item element) {
GenericItem genericItem = (GenericItem) element;
genericItem.removeStateChangeListener(this);
if (this.publishGroupFound && genericItem.getName().equals(this.publishGroupName)) {
// someone evil deleted the publish group
this.publishGroupFound = false;
GroupItem groupItem = (GroupItem) genericItem;
for (Item member : groupItem.getAllMembers()) {
removed(member);
}
}
}
public void updated(Item oldElement, Item element) {
removed(oldElement);
added(element);
}
@Override
public void receive(Event event) {
// publish MQTT message
logger.debug("Recevied an event: " + event);
ItemStateEvent itemStateEvent = (ItemStateEvent) event;
String topic = outTopic + itemStateEvent.getItemName();
String payload = itemStateEvent.getPayload();
public void stateChanged(Item item, State oldState, State newState) {
logger.debug("Recevied an event for item: '" + item.getName() + "'");
String topic = outTopic + item.getName();
String payload = newState.toFullString();
publish(topic, payload);
}
@Override
public void stateUpdated(Item item, State state) {
// ignored, as no change
}
}
package org.openhab.binding.openlicht.handler;
public enum HandlerPhase {
INIT,
CONFIGURATION,
COMMUNICATION,
FINISH
}
......@@ -5,18 +5,11 @@ import static org.openhab.binding.openlicht.BindingConstants.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.BiConsumer;
import org.eclipse.smarthome.core.library.types.DecimalType;
import org.eclipse.smarthome.core.types.State;
public class MqttUtils {
@FunctionalInterface
public interface UpdateState extends BiConsumer<String, State> {
}
public static Map<String, DecimalType> handleSimpleJsonMessage(final String message) {
Map<String, DecimalType> result = new HashMap<>();
String content = message.substring(1, message.length() - 1);
......
......@@ -10,11 +10,14 @@ package org.openhab.binding.openlicht.handler;
import static org.openhab.binding.openlicht.BindingConstants.CHANNEL_FLICK;
import org.eclipse.jdt.annotation.NonNull;
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.openhab.binding.openlicht.internal.ConfigurationHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link SkyWriterHATHandler} is responsible for handling commands, which are
......@@ -24,6 +27,8 @@ import org.openhab.binding.openlicht.internal.ConfigurationHolder;
*/
public class SkyWriterHATHandler extends AbstractMqttHandler {
private final @NonNull Logger logger = LoggerFactory.getLogger(SkyWriterHATHandler.class);
public SkyWriterHATHandler(Thing thing, ConfigurationHolder configurationHolder) {
super(thing, configurationHolder);
}
......
package org.openhab.binding.openlicht.handler;
import java.util.function.BiConsumer;
import org.eclipse.smarthome.core.types.State;
@FunctionalInterface
public interface UpdateState extends BiConsumer<String, State> {
}
......@@ -3,7 +3,7 @@ package org.openhab.binding.openlicht.internal;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.thing.ThingRegistry;
import org.eclipse.smarthome.io.transport.mqtt.MqttService;
import org.osgi.framework.Version;
......@@ -20,7 +20,7 @@ public interface ConfigurationHolder {
ThingRegistry getThingRegistry();
@Nullable
EventPublisher getEventPublisher();
ItemRegistry getItemRegistry();
Version getVersion();
......
package org.openhab.binding.openlicht.internal;
import org.eclipse.smarthome.core.common.registry.RegistryChangeListener;
import org.eclipse.smarthome.core.items.Item;
import org.openhab.binding.openlicht.handler.EraserHandler;
public class DelegateEraserRegistryChangeListener implements RegistryChangeListener<Item> {
private EraserHandler handler;
public DelegateEraserRegistryChangeListener(EraserHandler handler) {
this.handler = handler;
}
@Override
public void added(Item element) {
handler.added(element);
}
@Override
public void removed(Item element) {
handler.removed(element);
}
@Override
public void updated(Item oldElement, Item element) {
handler.updated(oldElement, element);
}
}
......@@ -23,7 +23,7 @@ import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingRegistry;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
......@@ -43,6 +43,7 @@ import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
......@@ -55,13 +56,14 @@ import org.slf4j.LoggerFactory;
@Component(configurationPid = "binding.openlicht", service = ThingHandlerFactory.class)
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 static final Logger logger = LoggerFactory.getLogger(OpenLichtHandlerFactory.class);
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, THING_TYPE_ERASER).collect(Collectors.toSet()));
private @Nullable MqttService service;
private @Nullable ThingRegistry thingRegistry;
private @Nullable ItemRegistry itemRegistry;
private @Nullable ScheduledExecutorService executor;
private @Nullable EventPublisher eventPublisher;
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
......@@ -121,8 +123,8 @@ public class OpenLichtHandlerFactory extends BaseThingHandlerFactory implements
}
@Override
public @Nullable EventPublisher getEventPublisher() {
return eventPublisher;
public @Nullable ItemRegistry getItemRegistry() {
return itemRegistry;
}
@Override
......@@ -132,34 +134,34 @@ public class OpenLichtHandlerFactory extends BaseThingHandlerFactory implements
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC)
public void setMqttService(MqttService service) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Setting mqtt service to {}", service);
logger.info("Setting mqtt service to {}", service);
this.service = service;
}
public void unsetMqttService(MqttService service) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Deleting mqtt service {}", service);
logger.info("Deleting mqtt service {}", service);
this.service = null;
}
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC)
public void setThingRegistry(ThingRegistry thingRegistry) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Setting thing registry to {}", thingRegistry);
logger.info("Setting thing registry to {}", thingRegistry);
this.thingRegistry = thingRegistry;
}
public void unsetThingRegistry(ThingRegistry service) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Deleting thing registry {}", service);
public void unsetThingRegistry(ThingRegistry thingRegistry) {
logger.info("Deleting thing registry {}", thingRegistry);
this.thingRegistry = null;
}
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC)
public void setEventPublisher(EventPublisher eventPublisher) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Setting event publisher to {}", thingRegistry);
this.eventPublisher = eventPublisher;
public void setItemRegistry(ItemRegistry itemRegistry) {
logger.info("Setting item registry to {}", itemRegistry);
this.itemRegistry = itemRegistry;
}
public void unsetEventPublisher(EventPublisher eventPublisher) {
LoggerFactory.getLogger(OpenLichtHandlerFactory.class).info("Deleting event publisher {}", service);
this.eventPublisher = null;
public void unsetItemRegistry(ItemRegistry itemRegistry) {
logger.info("Deleting item registry {}", itemRegistry);
this.itemRegistry = null;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment