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.milight.internal.handler;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.milight.internal.MilightBindingConstants;
17 import org.openhab.binding.milight.internal.MilightThingState;
18 import org.openhab.binding.milight.internal.protocol.MilightV6SessionManager;
19 import org.openhab.binding.milight.internal.protocol.ProtocolConstants;
20 import org.openhab.binding.milight.internal.protocol.QueueItem;
21 import org.openhab.binding.milight.internal.protocol.QueuedSend;
22 import org.openhab.core.thing.ChannelUID;
23 import org.openhab.core.thing.Thing;
24 import org.openhab.core.types.Command;
25 import org.openhab.core.types.RefreshType;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Implements basic V6 bulb functionally. But commands are different for different v6 bulbs, so almost all the work is
33 * @author David Graeff - Initial contribution
36 public abstract class AbstractLedV6Handler extends AbstractLedHandler {
37 protected final Logger logger = LoggerFactory.getLogger(AbstractLedV6Handler.class);
39 protected static final int MAX_BR = 100; // Maximum brightness (0x64)
40 protected static final int MAX_SAT = 100; // Maximum saturation (0x64)
41 protected static final int MAX_TEMP = 100; // Maximum colour temperature (0x64)
43 protected @NonNullByDefault({}) MilightV6SessionManager session;
45 public AbstractLedV6Handler(Thing thing, QueuedSend sendQueue, int typeOffset) {
46 super(thing, sendQueue, typeOffset);
50 protected void start(AbstractBridgeHandler handler) {
51 BridgeV6Handler h = (BridgeV6Handler) handler;
52 session = h.getSessionManager();
55 protected abstract byte getAddr();
57 protected abstract byte getBrCmd();
60 public void setHSB(int hue, int saturation, int brightness, MilightThingState state) {
61 if (hue > 360 || hue < 0) {
62 logger.error("Hue argument out of range");
66 // 0xFF = Red, D9 = Lavender, BA = Blue, 85 = Aqua, 7A = Green, 54 = Lime, 3B = Yellow, 1E = Orange
67 // we have to map [0,360] to [0,0xFF], where red equals hue=0 and the milight color 0xFF (=255)
68 // Integer milightColorNo = (256 + 0xFF - (int) (hue / 360.0 * 255.0)) % 256;
70 // Compute destination hue and current hue value, each mapped to 256 values.
71 // int cHue = state.hue360 * 255 / 360; // map to 256 values
72 int dHue = hue * 255 / 360; // map to 256 values
73 sendRepeatableCat(ProtocolConstants.CAT_COLOR_SET, 1, dHue, dHue, dHue, dHue);
77 if (brightness != -1) {
78 setBrightness(brightness, state);
81 if (saturation != -1) {
82 setSaturation(saturation, state);
87 public void setBrightness(int newvalue, MilightThingState state) {
88 int value = Math.min(Math.max(newvalue, 0), 100);
91 setPower(false, state);
92 } else if (state.brightness == 0) {
93 // If if was dimmed to minimum (off), turn it on again
94 setPower(true, state);
97 int br = (value * MAX_BR) / 100;
98 br = Math.min(br, MAX_BR);
100 sendRepeatableCat(ProtocolConstants.CAT_BRIGHTNESS_SET, getBrCmd(), br);
102 state.brightness = value;
106 public void changeColorTemperature(int colorTempRelative, MilightThingState state) {
107 if (!session.isValid()) {
108 logger.error("Bridge communication session not valid yet!");
112 if (colorTempRelative == 0) {
116 int ct = (state.colorTemperature * MAX_TEMP) / 100 + colorTempRelative;
117 ct = Math.min(ct, MAX_TEMP);
118 ct = Math.max(ct, 0);
119 setColorTemperature(ct * 100 / MAX_TEMP, state);
123 public void changeBrightness(int relativeBrightness, MilightThingState state) {
124 if (!session.isValid()) {
125 logger.error("Bridge communication session not valid yet!");
129 if (relativeBrightness == 0) {
133 int br = (state.brightness * MAX_BR) / 100 + relativeBrightness;
134 br = Math.min(br, MAX_BR);
135 br = Math.max(br, 0);
137 setBrightness(br * 100 / MAX_BR, state);
141 public void changeSaturation(int relativeSaturation, MilightThingState state) {
142 if (!session.isValid()) {
143 logger.error("Bridge communication session not valid yet!");
147 if (relativeSaturation == 0) {
151 int br = (state.brightness * MAX_BR) / 100 + relativeSaturation;
152 br = Math.min(br, MAX_BR);
153 br = Math.max(br, 0);
155 setSaturation(br * 100 / MAX_BR, state);
159 public void previousAnimationMode(MilightThingState state) {
160 if (!session.isValid()) {
161 logger.error("Bridge communication session not valid yet!");
165 int mode = state.animationMode - 1;
166 mode = Math.min(mode, 9);
167 mode = Math.max(mode, 1);
169 setLedMode(mode, state);
173 public void nextAnimationMode(MilightThingState state) {
174 if (!session.isValid()) {
175 logger.error("Bridge communication session not valid yet!");
179 int mode = state.animationMode + 1;
180 mode = Math.min(mode, 9);
181 mode = Math.max(mode, 1);
183 setLedMode(mode, state);
187 public void handleCommand(ChannelUID channelUID, Command command) {
188 if (command instanceof RefreshType) {
189 super.handleCommand(channelUID, command);
193 switch (channelUID.getId()) {
194 case MilightBindingConstants.CHANNEL_LINKLED: {
195 sendQueue.queue(new QueueItem(socket, uidc(ProtocolConstants.CAT_LINK),
196 session.makeLink(getAddr(), config.zone, true), true, delayTimeMS, repeatTimes, address, port));
199 case MilightBindingConstants.CHANNEL_UNLINKLED: {
200 sendQueue.queue(new QueueItem(socket, uidc(ProtocolConstants.CAT_LINK),
201 session.makeLink(getAddr(), config.zone, false), true, delayTimeMS, repeatTimes, address,
206 super.handleCommand(channelUID, command);
210 protected void sendNonRepeatable(int... data) {
211 sendQueue.queue(QueueItem.createNonRepeatable(socket, delayTimeMS, address, port,
212 session.makeCommand(getAddr(), config.zone, data)));
215 protected void sendRepeatableCat(int cat, int... data) {
216 sendQueue.queue(new QueueItem(socket, uidc(cat), session.makeCommand(getAddr(), config.zone, data), true,
217 delayTimeMS, repeatTimes, address, port));
220 protected void sendRepeatable(int... data) {
221 sendQueue.queue(QueueItem.createRepeatable(socket, delayTimeMS, repeatTimes, address, port,
222 session.makeCommand(getAddr(), config.zone, data)));