]> git.basschouten.com Git - openhab-addons.git/blob
bc59ebc3f8473ff8d1a1c6a86295f16f248cef70
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.deconz.internal.handler;
14
15 import static org.openhab.binding.deconz.internal.BindingConstants.*;
16
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.stream.Collectors;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.deconz.internal.CommandDescriptionProvider;
23 import org.openhab.binding.deconz.internal.Util;
24 import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage;
25 import org.openhab.binding.deconz.internal.dto.GroupAction;
26 import org.openhab.binding.deconz.internal.dto.GroupMessage;
27 import org.openhab.binding.deconz.internal.dto.GroupState;
28 import org.openhab.binding.deconz.internal.types.ResourceType;
29 import org.openhab.core.library.types.*;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.thing.Thing;
32 import org.openhab.core.thing.ThingStatus;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.CommandDescriptionBuilder;
36 import org.openhab.core.types.CommandOption;
37 import org.openhab.core.types.RefreshType;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import com.google.gson.Gson;
42
43 /**
44  * This group thing doesn't establish any connections, that is done by the bridge Thing.
45  *
46  * It waits for the bridge to come online, grab the websocket connection and bridge configuration
47  * and registers to the websocket connection as a listener.
48  *
49  * @author Jan N. Klug - Initial contribution
50  */
51 @NonNullByDefault
52 public class GroupThingHandler extends DeconzBaseThingHandler {
53     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPE_UIDS = Set.of(THING_TYPE_LIGHTGROUP);
54     private final Logger logger = LoggerFactory.getLogger(GroupThingHandler.class);
55     private final CommandDescriptionProvider commandDescriptionProvider;
56
57     private Map<String, String> scenes = Map.of();
58     private GroupState groupStateCache = new GroupState();
59
60     public GroupThingHandler(Thing thing, Gson gson, CommandDescriptionProvider commandDescriptionProvider) {
61         super(thing, gson, ResourceType.GROUPS);
62         this.commandDescriptionProvider = commandDescriptionProvider;
63     }
64
65     @Override
66     public void handleCommand(ChannelUID channelUID, Command command) {
67         String channelId = channelUID.getId();
68
69         GroupAction newGroupAction = new GroupAction();
70         switch (channelId) {
71             case CHANNEL_ALL_ON:
72             case CHANNEL_ANY_ON:
73                 if (command instanceof RefreshType) {
74                     valueUpdated(channelUID.getId(), groupStateCache);
75                     return;
76                 }
77                 break;
78             case CHANNEL_ALERT:
79                 if (command instanceof OnOffType) {
80                     newGroupAction.alert = command == OnOffType.ON ? "alert" : "none";
81                 } else {
82                     return;
83                 }
84                 break;
85             case CHANNEL_COLOR:
86                 if (command instanceof HSBType) {
87                     HSBType hsbCommand = (HSBType) command;
88                     Integer bri = Util.fromPercentType(hsbCommand.getBrightness());
89                     newGroupAction.bri = bri;
90                     if (bri > 0) {
91                         newGroupAction.hue = (int) (hsbCommand.getHue().doubleValue() * HUE_FACTOR);
92                         newGroupAction.sat = Util.fromPercentType(hsbCommand.getSaturation());
93                     }
94                 } else if (command instanceof PercentType) {
95                     newGroupAction.bri = Util.fromPercentType((PercentType) command);
96                 } else if (command instanceof DecimalType) {
97                     newGroupAction.bri = ((DecimalType) command).intValue();
98                 } else if (command instanceof OnOffType) {
99                     newGroupAction.on = OnOffType.ON.equals(command);
100                 } else {
101                     return;
102                 }
103                 break;
104             case CHANNEL_COLOR_TEMPERATURE:
105                 if (command instanceof DecimalType) {
106                     int miredValue = Util.kelvinToMired(((DecimalType) command).intValue());
107                     newGroupAction.ct = Util.constrainToRange(miredValue, ZCL_CT_MIN, ZCL_CT_MAX);
108                 } else {
109                     return;
110                 }
111                 break;
112             case CHANNEL_SCENE:
113                 if (command instanceof StringType) {
114                     String sceneId = scenes.get(command.toString());
115                     if (sceneId != null) {
116                         sendCommand(null, command, channelUID, "scenes/" + sceneId + "/recall", null);
117                     } else {
118                         logger.debug("Ignoring command {} for {}, scene is not found in available scenes: {}", command,
119                                 channelUID, scenes);
120                     }
121                 }
122                 return;
123             default:
124                 return;
125         }
126
127         Integer bri = newGroupAction.bri;
128         if (bri != null && bri > 0) {
129             newGroupAction.on = true;
130         }
131
132         sendCommand(newGroupAction, command, channelUID, null);
133     }
134
135     @Override
136     protected void processStateResponse(DeconzBaseMessage stateResponse) {
137         if (stateResponse instanceof GroupMessage) {
138             GroupMessage groupMessage = (GroupMessage) stateResponse;
139             scenes = groupMessage.scenes.stream().collect(Collectors.toMap(scene -> scene.name, scene -> scene.id));
140             ChannelUID channelUID = new ChannelUID(thing.getUID(), CHANNEL_SCENE);
141             commandDescriptionProvider.setDescription(channelUID,
142                     CommandDescriptionBuilder.create().withCommandOptions(groupMessage.scenes.stream()
143                             .map(scene -> new CommandOption(scene.name, scene.name)).collect(Collectors.toList()))
144                             .build());
145
146         }
147         messageReceived(config.id, stateResponse);
148     }
149
150     private void valueUpdated(String channelId, GroupState newState) {
151         switch (channelId) {
152             case CHANNEL_ALL_ON:
153                 updateState(channelId, OnOffType.from(newState.all_on));
154                 break;
155             case CHANNEL_ANY_ON:
156                 updateState(channelId, OnOffType.from(newState.any_on));
157                 break;
158             default:
159         }
160     }
161
162     @Override
163     public void messageReceived(String sensorID, DeconzBaseMessage message) {
164         if (message instanceof GroupMessage) {
165             GroupMessage groupMessage = (GroupMessage) message;
166             logger.trace("{} received {}", thing.getUID(), groupMessage);
167             GroupState groupState = groupMessage.state;
168             if (groupState != null) {
169                 updateStatus(ThingStatus.ONLINE);
170                 thing.getChannels().stream().map(c -> c.getUID().getId()).forEach(c -> valueUpdated(c, groupState));
171                 groupStateCache = groupState;
172             }
173         }
174     }
175 }