2 * Copyright (c) 2010-2020 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.avmfritz.internal.handler;
15 import static org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants.*;
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;
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.core.library.types.DateTimeType;
29 import org.openhab.core.thing.Channel;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.CommonTriggerEvents;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingUID;
34 import org.openhab.core.types.UnDefType;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Handler for a FRITZ! buttons. Handles commands, which are sent to one of the channels.
41 * @author Christoph Weitkamp - Initial contribution
44 public class AVMFritzButtonHandler extends DeviceHandler {
46 private static final String TOP_RIGHT_SUFFIX = "-1";
47 private static final String BOTTOM_RIGHT_SUFFIX = "-3";
48 private static final String BOTTOM_LEFT_SUFFIX = "-5";
49 private static final String TOP_LEFT_SUFFIX = "-7";
51 private final Logger logger = LoggerFactory.getLogger(AVMFritzButtonHandler.class);
53 * keeps track of the last timestamp for handling trigger events
55 private Instant lastTimestamp;
60 * @param thing Thing object representing a FRITZ! button
62 public AVMFritzButtonHandler(Thing thing) {
64 lastTimestamp = Instant.now();
68 public void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device) {
69 if (thing.getUID().equals(thingUID)) {
70 super.onDeviceUpdated(thingUID, device);
72 if (device instanceof DeviceModel) {
73 DeviceModel deviceModel = (DeviceModel) device;
74 if (deviceModel.isHANFUNButton()) {
75 updateHANFUNButton(deviceModel.getButtons());
77 if (deviceModel.isButton()) {
78 if (DECT400_THING_TYPE.equals(thing.getThingTypeUID())) {
79 updateShortLongPressButton(deviceModel.getButtons());
80 } else if (DECT440_THING_TYPE.equals(thing.getThingTypeUID())) {
81 updateButtons(deviceModel.getButtons());
83 updateBattery(deviceModel);
89 private void updateShortLongPressButton(List<ButtonModel> buttons) {
90 ButtonModel shortPressButton = buttons.size() > 0 ? buttons.get(0) : null;
91 ButtonModel longPressButton = buttons.size() > 1 ? buttons.get(1) : null;
92 ButtonModel lastPressedButton = shortPressButton != null && (longPressButton == null
93 || shortPressButton.getLastpressedtimestamp() > longPressButton.getLastpressedtimestamp())
96 if (lastPressedButton != null) {
97 updateButton(lastPressedButton,
98 lastPressedButton.equals(shortPressButton) ? CommonTriggerEvents.SHORT_PRESSED
99 : CommonTriggerEvents.LONG_PRESSED);
103 private void updateButtons(List<ButtonModel> buttons) {
104 Optional<ButtonModel> topLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_LEFT_SUFFIX))
106 if (topLeft.isPresent()) {
107 updateButton(topLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_LEFT);
109 Optional<ButtonModel> bottomLeft = buttons.stream().filter(b -> b.getIdentifier().endsWith(BOTTOM_LEFT_SUFFIX))
111 if (bottomLeft.isPresent()) {
112 updateButton(bottomLeft.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_LEFT);
114 Optional<ButtonModel> topRight = buttons.stream().filter(b -> b.getIdentifier().endsWith(TOP_RIGHT_SUFFIX))
116 if (topRight.isPresent()) {
117 updateButton(topRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_TOP_RIGHT);
119 Optional<ButtonModel> bottomRight = buttons.stream()
120 .filter(b -> b.getIdentifier().endsWith(BOTTOM_RIGHT_SUFFIX)).findFirst();
121 if (bottomRight.isPresent()) {
122 updateButton(bottomRight.get(), CommonTriggerEvents.PRESSED, CHANNEL_GROUP_BOTTOM_RIGHT);
126 private void updateHANFUNButton(List<ButtonModel> buttons) {
127 if (!buttons.isEmpty()) {
128 updateButton(buttons.get(0), CommonTriggerEvents.PRESSED);
132 private void updateButton(ButtonModel buttonModel, String event) {
133 updateButton(buttonModel, event, null);
136 private void updateButton(ButtonModel buttonModel, String event, @Nullable String channelGroupId) {
137 int lastPressedTimestamp = buttonModel.getLastpressedtimestamp();
138 if (lastPressedTimestamp == 0) {
139 updateThingChannelState(
140 channelGroupId == null ? CHANNEL_LAST_CHANGE
141 : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE,
144 ZonedDateTime timestamp = ZonedDateTime.ofInstant(Instant.ofEpochSecond(lastPressedTimestamp),
145 ZoneId.systemDefault());
146 Instant then = timestamp.toInstant();
147 // Avoid dispatching events if "lastpressedtimestamp" is older than now "lastTimestamp" (e.g. during
149 if (then.isAfter(lastTimestamp)) {
150 lastTimestamp = then;
151 triggerThingChannel(channelGroupId == null ? CHANNEL_PRESS
152 : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_PRESS, event);
154 updateThingChannelState(
155 channelGroupId == null ? CHANNEL_LAST_CHANGE
156 : channelGroupId + ChannelUID.CHANNEL_GROUP_SEPARATOR + CHANNEL_LAST_CHANGE,
157 new DateTimeType(timestamp));
162 * Triggers thing channels.
164 * @param channelId ID of the channel to be triggered.
165 * @param event Event to emit
167 private void triggerThingChannel(String channelId, String event) {
168 Channel channel = thing.getChannel(channelId);
169 if (channel != null) {
170 triggerChannel(channel.getUID(), event);
172 logger.debug("Channel '{}' in thing '{}' does not exist.", channelId, thing.getUID());