2 * Copyright (c) 2010-2023 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.feican.internal.handler;
15 import static org.openhab.binding.feican.internal.FeicanBindingConstants.*;
17 import java.io.IOException;
18 import java.net.SocketException;
19 import java.net.UnknownHostException;
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;
40 * The {@link FeicanHandler} is responsible for handling commands, which are sent to one of the channels.
42 * @author Hilbrand Bouwkamp - Initial contribution
45 public class FeicanHandler extends BaseThingHandler {
47 private final Logger logger = LoggerFactory.getLogger(FeicanHandler.class);
48 private final Commands commands = new Commands();
50 private @NonNullByDefault({}) Connection connection;
53 * Creates a new handler for the Feican thing.
55 * @param thing The thing to create the handler for
57 public FeicanHandler(Thing thing) {
62 public void handleCommand(ChannelUID channelUID, Command command) {
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);
73 } catch (IOException e) {
74 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage());
79 public void initialize() {
80 final FeicanConfiguration config = getConfigAs(FeicanConfiguration.class);
82 logger.debug("Initializing Feican Wifi RGWB Bulb on IP address {}", config.ipAddress);
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());
94 public void dispose() {
96 if (connection != null) {
102 * Handle for {@link OnOffType} commands.
104 * @param onOff value to set: on or off
105 * @throws IOException Connection to the bulb failed
107 private void handleOnOff(OnOffType onOff) throws IOException {
108 connection.sendCommand(commands.switchOnOff(onOff));
112 * Handle for {@link DecimalType} as an {@link OnOffType} command.
114 * @param value value to derive on or off state from
115 * @throws IOException Connection to the bulb failed
117 private void handleOnOff(DecimalType value) throws IOException {
118 handleOnOff(DecimalType.ZERO.equals(value) ? OnOffType.OFF : OnOffType.ON);
122 * Handle setting the color.
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.
133 * @param channelUID Channel the command is for
134 * @param command color to set
135 * @throws IOException Connection to the bulb failed
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);
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
151 * @param channelUID Channel the command is for
152 * @param command The percentType command
153 * @throws IOException Connection to the bulb failed
155 private void handlePercentage(ChannelUID channelUID, PercentType command) throws IOException {
156 String id = channelUID.getId();
160 handleBrightness(command);
161 handleOnOff(command);
163 case CHANNEL_COLOR_TEMPERATURE:
164 handleColorTemperature(command);
165 handleOnOff(OnOffType.ON);
167 case CHANNEL_PROGRAM_SPEED:
168 handleProgramSpeed(command);
169 handleOnOff(OnOffType.ON);
175 * Handles the brightness command.
177 * @param command percentage of brightness to set
178 * @throws IOException Connection to the bulb failed
180 private void handleBrightness(PercentType command) throws IOException {
181 connection.sendCommand(commands.brightness(command));
185 * Handles the color temperature command.
187 * @param command color temperature as set a value between 0 and 100
188 * @throws IOException Connection to the bulb failed
190 private void handleColorTemperature(PercentType command) throws IOException {
191 connection.sendCommand(commands.colorTemperature(command));
195 * Handles the speed of a preset program.
197 * @param command the speed as set as a percentage value
198 * @throws IOException Connection to the bulb failed
200 private void handleProgramSpeed(PercentType command) throws IOException {
201 connection.sendCommand(commands.programSpeed(command));
205 * Handles setting a preset program.
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
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())));