]> git.basschouten.com Git - openhab-addons.git/blob
66a64a839299bd15bf0c4c8b5ecd8e98dd226bd9
[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.feican.internal.handler;
14
15 import static org.openhab.binding.feican.internal.FeicanBindingConstants.*;
16
17 import java.io.IOException;
18 import java.net.SocketException;
19 import java.net.UnknownHostException;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.feican.internal.Commands;
23 import org.openhab.binding.feican.internal.Connection;
24 import org.openhab.binding.feican.internal.FeicanConfiguration;
25 import org.openhab.core.library.types.DecimalType;
26 import org.openhab.core.library.types.HSBType;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.library.types.PercentType;
29 import org.openhab.core.library.types.StringType;
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.ThingStatusDetail;
34 import org.openhab.core.thing.binding.BaseThingHandler;
35 import org.openhab.core.types.Command;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * The {@link FeicanHandler} is responsible for handling commands, which are sent to one of the channels.
41  *
42  * @author Hilbrand Bouwkamp - Initial contribution
43  */
44 @NonNullByDefault
45 public class FeicanHandler extends BaseThingHandler {
46
47     private final Logger logger = LoggerFactory.getLogger(FeicanHandler.class);
48     private final Commands commands = new Commands();
49
50     private @NonNullByDefault({}) Connection connection;
51
52     /**
53      * Creates a new handler for the Feican thing.
54      *
55      * @param thing The thing to create the handler for
56      */
57     public FeicanHandler(Thing thing) {
58         super(thing);
59     }
60
61     @Override
62     public void handleCommand(ChannelUID channelUID, Command command) {
63         try {
64             if (command instanceof OnOffType onOffCommand) {
65                 handleOnOff(onOffCommand);
66             } else if (command instanceof HSBType hsbCommand) {
67                 handleColor(channelUID, hsbCommand);
68             } else if (command instanceof PercentType percentCommand) {
69                 handlePercentage(channelUID, percentCommand);
70             } else if (command instanceof StringType stringCommand) {
71                 handleString(channelUID, stringCommand);
72             }
73         } catch (IOException e) {
74             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
75         }
76     }
77
78     @Override
79     public void initialize() {
80         final FeicanConfiguration config = getConfigAs(FeicanConfiguration.class);
81
82         logger.debug("Initializing Feican Wifi RGWB Bulb on IP address {}", config.ipAddress);
83         try {
84             connection = new Connection(config.ipAddress);
85             updateStatus(ThingStatus.ONLINE);
86         } catch (UnknownHostException e) {
87             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
88         } catch (SocketException e) {
89             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
90         }
91     }
92
93     @Override
94     public void dispose() {
95         super.dispose();
96         if (connection != null) {
97             connection.close();
98         }
99     }
100
101     /**
102      * Handle for {@link OnOffType} commands.
103      *
104      * @param onOff value to set: on or off
105      * @throws IOException Connection to the bulb failed
106      */
107     private void handleOnOff(OnOffType onOff) throws IOException {
108         connection.sendCommand(commands.switchOnOff(onOff));
109     }
110
111     /**
112      * Handle for {@link DecimalType} as an {@link OnOffType} command.
113      *
114      * @param value value to derive on or off state from
115      * @throws IOException Connection to the bulb failed
116      */
117     private void handleOnOff(DecimalType value) throws IOException {
118         handleOnOff(DecimalType.ZERO.equals(value) ? OnOffType.OFF : OnOffType.ON);
119     }
120
121     /**
122      * Handle setting the color.
123      *
124      * The Feican bulb has a separate command for the brightness. This brightness value is applied to any color value
125      * send. Because in the color command the brightness is also calculated this would mean the brightness will be
126      * applied twice; first when getting the RGB values and second in the bulb itself when passing a color value a
127      * earlier set brightness value is applied. To work around this, the brightness value is first send to the bulb and
128      * the color is send with a 100% brightness. So the brightness is controlled by the bulb. This is also needed for 2
129      * reasons. First color temperature also works with brightness and thus to set it with color temperature the
130      * brightness must be set on the bulb. Secondly when setting brightness in the color widget only the brightness
131      * value is passed and no color value is available, therefore this binding then sets the brightness on the bulb.
132      *
133      * @param channelUID Channel the command is for
134      * @param command color to set
135      * @throws IOException Connection to the bulb failed
136      */
137     private void handleColor(ChannelUID channelUID, HSBType command) throws IOException {
138         if (CHANNEL_COLOR.equals(channelUID.getId())) {
139             handleBrightness(command.getBrightness());
140             connection.sendCommand(
141                     commands.color(new HSBType(command.getHue(), command.getSaturation(), PercentType.HUNDRED)));
142             handleOnOff(command);
143         }
144     }
145
146     /**
147      * Handle percentType commands. Action depends on what channel send the command. For brightness related channels
148      * after the brightness command an extra onOff command is send to update the onOff state conform the brightness
149      * state.
150      *
151      * @param channelUID Channel the command is for
152      * @param command The percentType command
153      * @throws IOException Connection to the bulb failed
154      */
155     private void handlePercentage(ChannelUID channelUID, PercentType command) throws IOException {
156         String id = channelUID.getId();
157
158         switch (id) {
159             case CHANNEL_COLOR:
160                 handleBrightness(command);
161                 handleOnOff(command);
162                 break;
163             case CHANNEL_COLOR_TEMPERATURE:
164                 handleColorTemperature(command);
165                 handleOnOff(OnOffType.ON);
166                 break;
167             case CHANNEL_PROGRAM_SPEED:
168                 handleProgramSpeed(command);
169                 handleOnOff(OnOffType.ON);
170                 break;
171         }
172     }
173
174     /**
175      * Handles the brightness command.
176      *
177      * @param command percentage of brightness to set
178      * @throws IOException Connection to the bulb failed
179      */
180     private void handleBrightness(PercentType command) throws IOException {
181         connection.sendCommand(commands.brightness(command));
182     }
183
184     /**
185      * Handles the color temperature command.
186      *
187      * @param command color temperature as set a value between 0 and 100
188      * @throws IOException Connection to the bulb failed
189      */
190     private void handleColorTemperature(PercentType command) throws IOException {
191         connection.sendCommand(commands.colorTemperature(command));
192     }
193
194     /**
195      * Handles the speed of a preset program.
196      *
197      * @param command the speed as set as a percentage value
198      * @throws IOException Connection to the bulb failed
199      */
200     private void handleProgramSpeed(PercentType command) throws IOException {
201         connection.sendCommand(commands.programSpeed(command));
202     }
203
204     /**
205      * Handles setting a preset program.
206      *
207      * @param channelUID works for the program channel
208      * @param command String value as id of the program to set
209      * @throws IOException Connection to the bulb failed
210      */
211     private void handleString(ChannelUID channelUID, StringType command) throws NumberFormatException, IOException {
212         if (CHANNEL_PROGRAM.equals(channelUID.getId())) {
213             connection.sendCommand(commands.program(Integer.valueOf(command.toFullString())));
214         }
215     }
216 }