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.MilightThingState;
17 import org.openhab.binding.milight.internal.protocol.ProtocolConstants;
18 import org.openhab.binding.milight.internal.protocol.QueueItem;
19 import org.openhab.binding.milight.internal.protocol.QueuedSend;
20 import org.openhab.core.thing.Thing;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Implements functionality for the very first RGB bulbs for protocol version 2.
26 * A lot of stuff is not supported by this type of bulbs and they are not auto discovered
27 * and can only be add manually in the things file.
29 * @author David Graeff - Initial contribution
32 public class MilightV2RGBHandler extends AbstractLedHandler {
33 protected final Logger logger = LoggerFactory.getLogger(MilightV2RGBHandler.class);
34 protected static final int BR_LEVELS = 9;
36 public MilightV2RGBHandler(Thing thing, QueuedSend sendQueue) {
37 super(thing, sendQueue, 5);
40 protected QueueItem createRepeatable(byte[] data) {
41 return QueueItem.createRepeatable(socket, delayTimeMS, repeatTimes, address, port, data);
44 protected QueueItem createRepeatable(int uidc, byte[] data) {
45 return new QueueItem(socket, uidc, data, true, delayTimeMS, repeatTimes, address, port);
48 protected QueueItem createNonRepeatable(byte[] data) {
49 return QueueItem.createNonRepeatable(socket, delayTimeMS, address, port, data);
52 // We have no real saturation control for RGB bulbs. If the saturation is under a 50% threshold
53 // we just change to white mode instead.
55 public void setHSB(int hue, int saturation, int brightness, MilightThingState state) {
56 if (saturation < 50) {
59 setPower(true, state);
61 sendQueue.queue(createRepeatable(uidc(ProtocolConstants.CAT_COLOR_SET),
62 new byte[] { 0x20, AbstractLedV3Handler.makeColor(hue), 0x55 }));
64 if (brightness != -1) {
65 setBrightness(brightness, state);
71 public void setPower(boolean on, MilightThingState state) {
73 logger.debug("milight: sendOn");
74 byte[] messageBytes = null;
75 // message rgb bulbs ON
76 messageBytes = new byte[] { 0x22, 0x00, 0x55 };
77 sendQueue.queue(createRepeatable(uidc(ProtocolConstants.CAT_POWER_MODE), messageBytes));
79 logger.debug("milight: sendOff");
80 byte[] messageBytes = null;
82 // message rgb bulbs OFF
83 messageBytes = new byte[] { 0x21, 0x00, 0x55 };
85 sendQueue.queue(createRepeatable(uidc(ProtocolConstants.CAT_POWER_MODE), messageBytes));
90 public void whiteMode(MilightThingState state) {
94 public void nightMode(MilightThingState state) {
98 public void changeColorTemperature(int colorTempRelative, MilightThingState state) {
102 public void setLedMode(int mode, MilightThingState state) {
106 public void setSaturation(int value, MilightThingState state) {
110 public void changeSaturation(int relativeSaturation, MilightThingState state) {
114 public void setColorTemperature(int colorTemp, MilightThingState state) {
118 public void setBrightness(int value, MilightThingState state) {
120 setPower(false, state);
124 if (value > state.brightness) {
125 int repeatCount = (value - state.brightness) / 10;
126 for (int i = 0; i < repeatCount; i++) {
128 changeBrightness(+1, state);
131 } else if (value < state.brightness) {
132 int repeatCount = (state.brightness - value) / 10;
133 for (int i = 0; i < repeatCount; i++) {
135 changeBrightness(-1, state);
139 state.brightness = value;
143 public void changeBrightness(int relativeBrightness, MilightThingState state) {
144 int newPercent = state.brightness + relativeBrightness;
145 if (newPercent < 0) {
148 if (newPercent > 100) {
151 if (state.brightness != -1 && newPercent == 0) {
152 setPower(false, state);
154 setPower(true, state);
155 int steps = (int) Math.abs(Math.floor(relativeBrightness * BR_LEVELS / 100.0));
156 for (int s = 0; s < steps; ++s) {
157 byte[] t = { (byte) (relativeBrightness < 0 ? 0x24 : 0x23), 0x00, 0x55 };
158 sendQueue.queue(createNonRepeatable(t));
161 state.brightness = newPercent;
165 public void changeSpeed(int relativeSpeed, MilightThingState state) {
169 public void previousAnimationMode(MilightThingState state) {
170 setPower(true, state);
171 sendQueue.queue(createNonRepeatable(new byte[] { 0x28, 0x00, 0x55 }));
172 state.animationMode = Math.min(state.animationMode - 1, 0);
176 public void nextAnimationMode(MilightThingState state) {
177 setPower(true, state);
178 sendQueue.queue(createNonRepeatable(new byte[] { 0x27, 0x00, 0x55 }));
179 state.animationMode = Math.max(state.animationMode + 1, 100);