From e294915aab587f08dd69cf6c34375c857596753a Mon Sep 17 00:00:00 2001 From: "Jan N. Klug" Date: Sun, 7 May 2023 18:21:35 +0200 Subject: [PATCH] Profile, ThingHandler, CommunicationManager Signed-off-by: Jan N. Klug --- .../core/thing/binding/BaseThingHandler.java | 31 ++++++++++++++++++ .../thing/binding/ThingHandlerCallback.java | 9 ++++++ .../thing/internal/CommunicationManager.java | 14 ++++++++ .../internal/ThingHandlerCallbackImpl.java | 6 ++++ .../profiles/ProfileCallbackImpl.java | 14 ++++++++ .../profiles/SystemDefaultProfile.java | 10 ++++-- .../core/thing/profiles/ProfileCallback.java | 3 ++ .../thing/profiles/TimeSeriesProfile.java | 32 +++++++++++++++++++ 8 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TimeSeriesProfile.java diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/BaseThingHandler.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/BaseThingHandler.java index 91efce1e6f4..d3a53ba92fb 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/BaseThingHandler.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/BaseThingHandler.java @@ -41,6 +41,7 @@ import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -287,6 +288,36 @@ protected void updateState(String channelID, State state) { updateState(channelUID, state); } + /** + * Send a time series to the channel. This can be used to transfer historic data or forecasts. + * + * @param channelUID unique id of the channel + * @param timeSeries the {@link TimeSeries} that is sent + */ + protected void sendTimeSeries(ChannelUID channelUID, TimeSeries timeSeries) { + synchronized (this) { + ThingHandlerCallback callback1 = this.callback; + if (callback1 != null) { + callback1.sendTimeSeries(channelUID, timeSeries); + } else { + logger.warn( + "Handler {} of thing {} tried sending to channel {} although the handler was already disposed.", + this.getClass().getSimpleName(), channelUID.getThingUID(), channelUID.getId()); + } + } + } + + /** + * Send a time series to the channel. This can be used to transfer historic data or forecasts. + * + * @param channelID id of the channel + * @param timeSeries the {@link TimeSeries} that is sent + */ + protected void sendTimeSeries(String channelID, TimeSeries timeSeries) { + ChannelUID channelUID = new ChannelUID(this.getThing().getUID(), channelID); + sendTimeSeries(channelUID, timeSeries); + } + /** * Emits an event for the given channel. * diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/ThingHandlerCallback.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/ThingHandlerCallback.java index 0f99a65435e..33763184d25 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/ThingHandlerCallback.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/binding/ThingHandlerCallback.java @@ -35,6 +35,7 @@ import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; /** * {@link ThingHandlerCallback} is callback interface for {@link ThingHandler}s. The implementation of a @@ -65,6 +66,14 @@ public interface ThingHandlerCallback { */ void postCommand(ChannelUID channelUID, Command command); + /** + * Informs about a time series, whcihs is send from the channel. + * + * @param channelUID channel UID + * @param timeSeries time series + */ + void sendTimeSeries(ChannelUID channelUID, TimeSeries timeSeries); + /** * Informs about an updated status of a thing. * diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/CommunicationManager.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/CommunicationManager.java index 85e05e0f257..e8b1584da5f 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/CommunicationManager.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/CommunicationManager.java @@ -69,12 +69,14 @@ import org.openhab.core.thing.profiles.ProfileFactory; import org.openhab.core.thing.profiles.ProfileTypeUID; import org.openhab.core.thing.profiles.StateProfile; +import org.openhab.core.thing.profiles.TimeSeriesProfile; import org.openhab.core.thing.profiles.TriggerProfile; import org.openhab.core.thing.type.ChannelType; import org.openhab.core.thing.type.ChannelTypeRegistry; import org.openhab.core.thing.type.ChannelTypeUID; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; import org.openhab.core.types.Type; import org.openhab.core.types.util.UnitUtils; import org.osgi.service.component.annotations.Activate; @@ -585,6 +587,18 @@ public void postCommand(ChannelUID channelUID, Command command) { }); } + public void sendTimeSeries(ChannelUID channelUID, TimeSeries timeSeries) { + final Thing thing = getThing(channelUID.getThingUID()); + handleCallFromHandler(channelUID, thing, profile -> { + if (profile instanceof TimeSeriesProfile timeSeriesProfile) { + timeSeriesProfile.onTimeSeriesFromHandler(timeSeries); + } else { + logger.warn("Profile '{}' on channel {} does not support time series.", profile.getProfileTypeUID(), + channelUID); + } + }); + } + void handleCallFromHandler(ChannelUID channelUID, @Nullable Thing thing, Consumer action) { itemChannelLinkRegistry.getLinks(channelUID).forEach(link -> { final Item item = getItem(link.getItemName()); diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ThingHandlerCallbackImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ThingHandlerCallbackImpl.java index 1ffab2b1a34..184b652dc01 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ThingHandlerCallbackImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/ThingHandlerCallbackImpl.java @@ -42,6 +42,7 @@ import org.openhab.core.thing.util.ThingHandlerHelper; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,6 +71,11 @@ public void postCommand(ChannelUID channelUID, Command command) { thingManager.communicationManager.postCommand(channelUID, command); } + @Override + public void sendTimeSeries(ChannelUID channelUID, TimeSeries timeSeries) { + thingManager.communicationManager.sendTimeSeries(channelUID, timeSeries); + } + @Override public void channelTriggered(Thing thing, ChannelUID channelUID, String event) { thingManager.communicationManager.channelTriggered(thing, channelUID, event); diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/ProfileCallbackImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/ProfileCallbackImpl.java index 463a4c653af..0dc911240d5 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/ProfileCallbackImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/ProfileCallbackImpl.java @@ -32,6 +32,7 @@ import org.openhab.core.thing.util.ThingHandlerHelper; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; import org.openhab.core.types.TypeParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -129,4 +130,17 @@ public void sendUpdate(State state) { eventPublisher.post( ItemEventFactory.createStateEvent(link.getItemName(), acceptedState, link.getLinkedUID().toString())); } + + @Override + public void sendTimeSeries(TimeSeries timeSeries) { + Item item = itemProvider.apply(link.getItemName()); + if (item == null) { + logger.warn("Cannot send time series event '{}' for item '{}', because no item could be found.", timeSeries, + link.getItemName()); + return; + } + + eventPublisher.post( + ItemEventFactory.createTimeSeriesEvent(link.getItemName(), timeSeries, link.getLinkedUID().toString())); + } } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemDefaultProfile.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemDefaultProfile.java index 1b5b7881aee..d54f02bc3ec 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemDefaultProfile.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/internal/profiles/SystemDefaultProfile.java @@ -16,10 +16,11 @@ import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.profiles.ProfileCallback; import org.openhab.core.thing.profiles.ProfileTypeUID; -import org.openhab.core.thing.profiles.StateProfile; import org.openhab.core.thing.profiles.SystemProfiles; +import org.openhab.core.thing.profiles.TimeSeriesProfile; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; /** * This is the default profile for stateful channels. @@ -30,7 +31,7 @@ * @author Simon Kaufmann - Initial contribution */ @NonNullByDefault -public class SystemDefaultProfile implements StateProfile { +public class SystemDefaultProfile implements TimeSeriesProfile { private final ProfileCallback callback; @@ -58,6 +59,11 @@ public void onCommandFromHandler(Command command) { callback.sendCommand(command); } + @Override + public void onTimeSeriesFromHandler(TimeSeries timeSeries) { + callback.sendTimeSeries(timeSeries); + } + @Override public void onStateUpdateFromItem(State state) { } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileCallback.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileCallback.java index 7c2483c8cb3..bb8a78a60a6 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileCallback.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/ProfileCallback.java @@ -16,6 +16,7 @@ import org.openhab.core.thing.link.ItemChannelLink; import org.openhab.core.types.Command; import org.openhab.core.types.State; +import org.openhab.core.types.TimeSeries; /** * Gives access to the framework features for continuing the communication flow. @@ -52,4 +53,6 @@ public interface ProfileCallback { * @param state */ void sendUpdate(State state); + + void sendTimeSeries(TimeSeries timeSeries); } diff --git a/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TimeSeriesProfile.java b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TimeSeriesProfile.java new file mode 100644 index 00000000000..9625069bcce --- /dev/null +++ b/bundles/org.openhab.core.thing/src/main/java/org/openhab/core/thing/profiles/TimeSeriesProfile.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * 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.openhab.core.thing.profiles; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.types.TimeSeries; + +/** + * The {@link TimeSeriesProfile} extends the {@link StateProfile} to support {@link TimeSeries} updates + * + * @author Jan N. Klug - Initial contribution + */ +@NonNullByDefault +public interface TimeSeriesProfile extends StateProfile { + + /** + * If a binding sends a time-series to a channel, this method will be called for each linked item. + * + * @param timeSeries the time-series + */ + void onTimeSeriesFromHandler(TimeSeries timeSeries); +}