2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.meater.internal.handler;
15 import static org.openhab.binding.meater.internal.MeaterBindingConstants.*;
17 import java.time.Instant;
18 import java.time.ZonedDateTime;
20 import javax.measure.quantity.Temperature;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.binding.meater.internal.MeaterConfiguration;
25 import org.openhab.binding.meater.internal.dto.MeaterProbeDTO.Cook;
26 import org.openhab.binding.meater.internal.dto.MeaterProbeDTO.Device;
27 import org.openhab.core.i18n.TimeZoneProvider;
28 import org.openhab.core.library.types.DateTimeType;
29 import org.openhab.core.library.types.QuantityType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.library.unit.SIUnits;
32 import org.openhab.core.library.unit.Units;
33 import org.openhab.core.thing.Bridge;
34 import org.openhab.core.thing.Channel;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingStatusDetail;
39 import org.openhab.core.thing.binding.BaseThingHandler;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.State;
42 import org.openhab.core.types.UnDefType;
45 * The {@link MeaterHandler} is responsible for handling commands, which are
46 * sent to one of the channels.
48 * @author Jan Gustafsson - Initial contribution
51 public class MeaterHandler extends BaseThingHandler {
53 private String deviceId = "";
54 private TimeZoneProvider timeZoneProvider;
56 public MeaterHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
58 this.timeZoneProvider = timeZoneProvider;
62 public void handleCommand(ChannelUID channelUID, Command command) {
66 public void initialize() {
67 deviceId = getConfigAs(MeaterConfiguration.class).getDeviceId();
68 updateStatus(ThingStatus.UNKNOWN);
70 scheduler.execute(() -> {
75 public void update() {
76 Device meaterProbe = getMeaterProbe();
77 if (meaterProbe != null) {
80 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
81 "@text/offline.communication-error.description");
85 private @Nullable Device getMeaterProbe() {
86 Bridge bridge = getBridge();
87 if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
88 MeaterBridgeHandler bridgeHandler = (MeaterBridgeHandler) bridge.getHandler();
89 if (bridgeHandler != null) {
90 return bridgeHandler.getMeaterThings().get(deviceId);
96 private void update(Device meaterProbe) {
97 // Update all channels from the updated data
98 getThing().getChannels().stream().map(Channel::getUID).filter(channelUID -> isLinked(channelUID))
99 .forEach(channelUID -> {
100 State state = getValue(channelUID.getId(), meaterProbe);
101 updateState(channelUID, state);
103 updateStatus(ThingStatus.ONLINE);
106 private State getValue(String channelId, Device meaterProbe) {
107 Cook cook = meaterProbe.cook;
109 case CHANNEL_INTERNAL_TEMPERATURE:
110 return new QuantityType<Temperature>(meaterProbe.temperature.internal, SIUnits.CELSIUS);
111 case CHANNEL_AMBIENT_TEMPERATURE:
112 return new QuantityType<Temperature>(meaterProbe.temperature.ambient, SIUnits.CELSIUS);
113 case CHANNEL_COOK_TARGET_TEMPERATURE:
115 return new QuantityType<Temperature>(cook.temperature.target, SIUnits.CELSIUS);
118 case CHANNEL_COOK_PEAK_TEMPERATURE:
120 return new QuantityType<Temperature>(cook.temperature.peak, SIUnits.CELSIUS);
123 case CHANNEL_COOK_ELAPSED_TIME:
125 return new QuantityType<>(cook.time.elapsed, Units.SECOND);
128 case CHANNEL_COOK_REMAINING_TIME:
130 return cook.time.remaining == -1 ? UnDefType.UNDEF
131 : new QuantityType<>(cook.time.remaining, Units.SECOND);
134 case CHANNEL_COOK_ID:
136 return new StringType(cook.id);
139 case CHANNEL_COOK_NAME:
141 return new StringType(cook.name);
144 case CHANNEL_COOK_STATE:
146 return new StringType(cook.state);
149 case CHANNEL_LAST_CONNECTION:
150 Instant instant = meaterProbe.getLastConnection();
151 if (instant != null) {
152 return new DateTimeType(ZonedDateTime.ofInstant(instant, timeZoneProvider.getTimeZone()));
155 case CHANNEL_COOK_ESTIMATED_END_TIME:
157 if (cook.time.remaining > -1) {
158 return new DateTimeType(
159 ZonedDateTime.now(timeZoneProvider.getTimeZone()).plusSeconds(cook.time.remaining));
163 return UnDefType.UNDEF;