]> git.basschouten.com Git - openhab-addons.git/blob
34b0e992a44ff0c87d5d5f2428d0904aa9817b82
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.avmfritz.internal.handler;
14
15 import static org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants.*;
16
17 import java.time.Instant;
18 import java.time.ZoneId;
19 import java.time.ZonedDateTime;
20 import java.util.List;
21 import java.util.Optional;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel;
26 import org.openhab.binding.avmfritz.internal.dto.ButtonModel;
27 import org.openhab.binding.avmfritz.internal.dto.DeviceModel;
28 import org.openhab.binding.avmfritz.internal.dto.HumidityModel;
29 import org.openhab.core.library.types.DateTimeType;
30 import org.openhab.core.library.types.QuantityType;
31 import org.openhab.core.library.unit.Units;
32 import org.openhab.core.thing.Channel;
33 import org.openhab.core.thing.ChannelUID;
34 import org.openhab.core.thing.CommonTriggerEvents;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingUID;
37 import org.openhab.core.types.UnDefType;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Handler for a FRITZ! buttons. Handles commands, which are sent to one of the channels.
43  *
44  * @author Christoph Weitkamp - Initial contribution
45  */
46 @NonNullByDefault
47 public class AVMFritzButtonHandler extends DeviceHandler {
48
49     private static final String TOP_RIGHT_SUFFIX = "-1";
50     private static final String BOTTOM_RIGHT_SUFFIX = "-3";
51     private static final String BOTTOM_LEFT_SUFFIX = "-5";
52     private static final String TOP_LEFT_SUFFIX = "-7";
53
54     private final Logger logger = LoggerFactory.getLogger(AVMFritzButtonHandler.class);
55     /**
56      * keeps track of the last timestamp for handling trigger events
57      */
58     private Instant lastTimestamp;
59
60     /**
61      * Constructor
62      *
63      * @param thing Thing object representing a FRITZ! button
64      */
65     public AVMFritzButtonHandler(Thing thing) {
66         super(thing);
67         lastTimestamp = Instant.now();
68     }
69
70     @Override
71     public void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device) {
72         if (thing.getUID().equals(thingUID)) {
73             super.onDeviceUpdated(thingUID, device);
74
75             if (device instanceof DeviceModel) {
76                 DeviceModel deviceModel = (DeviceModel) device;
77                 if (deviceModel.isHANFUNButton()) {
78                     updateHANFUNButton(deviceModel.getButtons());
79                 }
80                 if (deviceModel.isButton()) {
81                     if (DECT400_THING_TYPE.equals(thing.getThingTypeUID())) {
82                         updateShortLongPressButton(deviceModel.getButtons());
83                     } else if (DECT440_THING_TYPE.equals(thing.getThingTypeUID())) {
84                         updateButtons(deviceModel.getButtons());
85                     }
86                     updateBattery(deviceModel);
87                 }
88             }
89         }
90     }
91
92     @Override
93     protected void updateHumiditySensor(@Nullable HumidityModel humidityModel) {
94         if (humidityModel != null) {
95             updateThingChannelState(CHANNEL_GROUP_SENSORS + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_HUMIDITY,
96                     new QuantityType<>(humidityModel.getRelativeHumidity(), Units.PERCENT));
97         }
98     }
99
100     private void updateShortLongPressButton(List<ButtonModel> buttons) {
101         ButtonModel shortPressButton = buttons.size() > 0 ? buttons.get(0) : null;
102         ButtonModel longPressButton = buttons.size() > 1 ? buttons.get(1) : null;
103         ButtonModel lastPressedButton = shortPressButton != null && (longPressButton == null
104                 || shortPressButton.getLastpressedtimestamp() > longPressButton.getLastpressedtimestamp())
105                         ? shortPressButton
106                         : longPressButton;
107         if (lastPressedButton != null) {
108             updateButton(lastPressedButton,
109                     lastPressedButton.equals(shortPressButton) ? CommonTriggerEvents.SHORT_PRESSED
110                             : CommonTriggerEvents.LONG_PRESSED);
111         }
112     }
113
114     private void updateButtons(List<ButtonModel> buttons) {
115         Optional<ButtonModel> topLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_LEFT_SUFFIX))
116                 .findFirst();
117         if (topLeft.isPresent()) {
118             updateButton(topLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_LEFT);
119         }
120         Optional<ButtonModel> bottomLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(BOTTOM_LEFT_SUFFIX))
121                 .findFirst();
122         if (bottomLeft.isPresent()) {
123             updateButton(bottomLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_LEFT);
124         }
125         Optional<ButtonModel> topRight = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_RIGHT_SUFFIX))
126                 .findFirst();
127         if (topRight.isPresent()) {
128             updateButton(topRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_RIGHT);
129         }
130         Optional<ButtonModel> bottomRight = buttons.stream()
131                 .filter(b -> b.getIdentifier().endsWith(BOTTOM_RIGHT_SUFFIX)).findFirst();
132         if (bottomRight.isPresent()) {
133             updateButton(bottomRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_RIGHT);
134         }
135     }
136
137     private void updateHANFUNButton(List<ButtonModel> buttons) {
138         if (!buttons.isEmpty()) {
139             updateButton(buttons.get(0), CommonTriggerEvents.PRESSED);
140         }
141     }
142
143     private void updateButton(ButtonModel buttonModel, String event) {
144         updateButton(buttonModel, event, null);
145     }
146
147     private void updateButton(ButtonModel buttonModel, String event, @Nullable String channelGroupId) {
148         int lastPressedTimestamp = buttonModel.getLastpressedtimestamp();
149         if (lastPressedTimestamp == 0) {
150             updateThingChannelState(
151                     channelGroupId == null ? CHANNEL_LAST_CHANGE
152                             : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE,
153                     UnDefType.UNDEF);
154         } else {
155             ZonedDateTime timestamp = ZonedDateTime.ofInstant(Instant.ofEpochSecond(lastPressedTimestamp),
156                     ZoneId.systemDefault());
157             Instant then = timestamp.toInstant();
158             // Avoid dispatching events if "lastpressedtimestamp" is older than now "lastTimestamp" (e.g. during
159             // restart)
160             if (then.isAfter(lastTimestamp)) {
161                 lastTimestamp = then;
162                 triggerThingChannel(channelGroupId == null ? CHANNEL_PRESS
163                         : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_PRESS, event);
164             }
165             updateThingChannelState(
166                     channelGroupId == null ? CHANNEL_LAST_CHANGE
167                             : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE,
168                     new DateTimeType(timestamp));
169         }
170     }
171
172     /**
173      * Triggers thing channels.
174      *
175      * @param channelId ID of the channel to be triggered.
176      * @param event Event to emit
177      */
178     private void triggerThingChannel(String channelId, String event) {
179         Channel channel = thing.getChannel(channelId);
180         if (channel != null) {
181             triggerChannel(channel.getUID(), event);
182         } else {
183             logger.debug("Channel '{}' in thing '{}' does not exist.", channelId, thing.getUID());
184         }
185     }
186 }