]> git.basschouten.com Git - openhab-addons.git/blob
c39631046b133a539b38ea6a27b3a9d977265f88
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.dali.internal.handler;
14
15 import static org.openhab.binding.dali.internal.DaliBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.util.List;
19 import java.util.concurrent.CompletableFuture;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.dali.internal.protocol.DaliAddress;
24 import org.openhab.binding.dali.internal.protocol.DaliDAPCCommand;
25 import org.openhab.binding.dali.internal.protocol.DaliResponse;
26 import org.openhab.binding.dali.internal.protocol.DaliResponse.NumericMask;
27 import org.openhab.binding.dali.internal.protocol.DaliStandardCommand;
28 import org.openhab.core.library.types.HSBType;
29 import org.openhab.core.library.types.IncreaseDecreaseType;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.PercentType;
32 import org.openhab.core.thing.Bridge;
33 import org.openhab.core.thing.ChannelUID;
34 import org.openhab.core.thing.Thing;
35 import org.openhab.core.thing.ThingStatus;
36 import org.openhab.core.thing.ThingStatusDetail;
37 import org.openhab.core.thing.binding.BaseThingHandler;
38 import org.openhab.core.thing.binding.BridgeHandler;
39 import org.openhab.core.types.Command;
40 import org.openhab.core.types.RefreshType;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * The {@link DaliRgbHandler} handles commands for things of type RGB.
46  *
47  * @author Robert Schmid - Initial contribution
48  */
49 @NonNullByDefault
50 public class DaliRgbHandler extends BaseThingHandler {
51     private final Logger logger = LoggerFactory.getLogger(DaliRgbHandler.class);
52     private @Nullable List<Integer> outputs;
53
54     public DaliRgbHandler(Thing thing) {
55         super(thing);
56     }
57
58     @Override
59     public void initialize() {
60         Bridge bridge = getBridge();
61
62         if (bridge == null) {
63             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured");
64         } else {
65             updateStatus(ThingStatus.ONLINE);
66         }
67
68         outputs = List.of(((BigDecimal) this.thing.getConfiguration().get(TARGET_ID_R)).intValueExact(),
69                 ((BigDecimal) this.thing.getConfiguration().get(TARGET_ID_G)).intValueExact(),
70                 ((BigDecimal) this.thing.getConfiguration().get(TARGET_ID_B)).intValueExact());
71     }
72
73     @Override
74     public void handleCommand(ChannelUID channelUID, Command command) {
75         try {
76             if (CHANNEL_COLOR.equals(channelUID.getId())) {
77                 boolean queryDeviceState = false;
78
79                 if (command instanceof HSBType hsbCommand) {
80                     PercentType[] rgb = hsbCommand.toRGB();
81
82                     for (int i = 0; i < 3; i++) {
83                         byte dimmValue = (byte) ((rgb[i].floatValue() * DALI_SWITCH_100_PERCENT) / 100);
84                         getBridgeHandler().sendCommand(
85                                 new DaliDAPCCommand(DaliAddress.createShortAddress(outputs.get(i)), dimmValue));
86                     }
87                 } else if (command instanceof OnOffType onOffCommand) {
88                     if (onOffCommand == OnOffType.ON) {
89                         for (Integer output : outputs) {
90                             getBridgeHandler().sendCommand(new DaliDAPCCommand(DaliAddress.createShortAddress(output),
91                                     (byte) DALI_SWITCH_100_PERCENT));
92                         }
93                     } else {
94                         for (Integer output : outputs) {
95                             getBridgeHandler().sendCommand(
96                                     DaliStandardCommand.createOffCommand(DaliAddress.createShortAddress(output)));
97                         }
98                     }
99                 } else if (command instanceof IncreaseDecreaseType increaseDecreaseCommand) {
100                     if (increaseDecreaseCommand == IncreaseDecreaseType.INCREASE) {
101                         for (Integer output : outputs) {
102                             getBridgeHandler().sendCommand(
103                                     DaliStandardCommand.createUpCommand(DaliAddress.createShortAddress(output)));
104                         }
105                     } else {
106                         for (Integer output : outputs) {
107                             getBridgeHandler().sendCommand(
108                                     DaliStandardCommand.createDownCommand(DaliAddress.createShortAddress(output)));
109                         }
110                     }
111
112                     queryDeviceState = true;
113                 } else if (command instanceof RefreshType) {
114                     queryDeviceState = true;
115                 }
116
117                 if (queryDeviceState) {
118                     CompletableFuture<@Nullable NumericMask> responseR = getBridgeHandler()
119                             .sendCommandWithResponse(
120                                     DaliStandardCommand.createQueryActualLevelCommand(
121                                             DaliAddress.createShortAddress(outputs.get(0))),
122                                     DaliResponse.NumericMask.class);
123                     CompletableFuture<@Nullable NumericMask> responseG = getBridgeHandler()
124                             .sendCommandWithResponse(
125                                     DaliStandardCommand.createQueryActualLevelCommand(
126                                             DaliAddress.createShortAddress(outputs.get(1))),
127                                     DaliResponse.NumericMask.class);
128                     CompletableFuture<@Nullable NumericMask> responseB = getBridgeHandler()
129                             .sendCommandWithResponse(
130                                     DaliStandardCommand.createQueryActualLevelCommand(
131                                             DaliAddress.createShortAddress(outputs.get(2))),
132                                     DaliResponse.NumericMask.class);
133
134                     CompletableFuture.allOf(responseR, responseG, responseB).thenAccept(x -> {
135                         @Nullable
136                         NumericMask r = responseR.join(), g = responseG.join(), b = responseB.join();
137                         if (r != null && !r.mask && g != null && !g.mask && b != null && !b.mask) {
138                             Integer rValue = r.value != null ? r.value : 0;
139                             Integer gValue = g.value != null ? g.value : 0;
140                             Integer bValue = b.value != null ? b.value : 0;
141                             updateState(channelUID,
142                                     HSBType.fromRGB((int) (rValue.floatValue() * 255 / DALI_SWITCH_100_PERCENT),
143                                             (int) (gValue.floatValue() * 255 / DALI_SWITCH_100_PERCENT),
144                                             (int) (bValue.floatValue() * 255 / DALI_SWITCH_100_PERCENT)));
145                         }
146                     }).exceptionally(e -> {
147                         logger.warn("Error querying device status: {}", e.getMessage());
148                         return null;
149                     });
150                 }
151             }
152         } catch (DaliException e) {
153             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
154         }
155     }
156
157     protected DaliserverBridgeHandler getBridgeHandler() throws DaliException {
158         Bridge bridge = this.getBridge();
159         if (bridge == null) {
160             throw new DaliException("No bridge was found");
161         }
162
163         BridgeHandler handler = bridge.getHandler();
164         if (handler == null) {
165             throw new DaliException("No handler was found");
166         }
167
168         return (DaliserverBridgeHandler) handler;
169     }
170 }