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.lifx.internal;
15 import static org.openhab.binding.lifx.internal.LifxBindingConstants.DEFAULT_COLOR;
17 import java.time.Duration;
18 import java.time.LocalDateTime;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.concurrent.CopyOnWriteArrayList;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.lifx.internal.dto.Effect;
26 import org.openhab.binding.lifx.internal.dto.HevCycleState;
27 import org.openhab.binding.lifx.internal.dto.PowerState;
28 import org.openhab.binding.lifx.internal.dto.SignalStrength;
29 import org.openhab.binding.lifx.internal.fields.HSBK;
30 import org.openhab.binding.lifx.internal.listener.LifxLightStateListener;
31 import org.openhab.core.library.types.HSBType;
32 import org.openhab.core.library.types.OnOffType;
33 import org.openhab.core.library.types.PercentType;
36 * The {@link LifxLightState} stores the properties that represent the state of a light.
38 * @author Wouter Born - Initial contribution
41 public class LifxLightState {
43 private HSBK[] colors = new HSBK[] { new HSBK(DEFAULT_COLOR) };
44 private @Nullable HevCycleState hevCycleState;
45 private @Nullable PercentType infrared;
46 private @Nullable PowerState powerState;
47 private @Nullable SignalStrength signalStrength;
48 private @Nullable Effect tileEffect;
50 private LocalDateTime lastChange = LocalDateTime.MIN;
51 private List<LifxLightStateListener> listeners = new CopyOnWriteArrayList<>();
53 public void copy(LifxLightState other) {
54 this.powerState = other.getPowerState();
55 this.colors = other.getColors();
56 this.hevCycleState = other.getHevCycleState();
57 this.infrared = other.getInfrared();
58 this.signalStrength = other.getSignalStrength();
59 this.tileEffect = other.getTileEffect();
62 public @Nullable PowerState getPowerState() {
66 public HSBK getColor() {
67 return colors.length > 0 ? new HSBK(colors[0]) : new HSBK(DEFAULT_COLOR);
70 public HSBK getColor(int zoneIndex) {
71 return zoneIndex < colors.length ? new HSBK(colors[zoneIndex]) : new HSBK(DEFAULT_COLOR);
74 public HSBK[] getColors() {
75 HSBK[] colorsCopy = new HSBK[colors.length];
76 for (int i = 0; i < colors.length; i++) {
77 colorsCopy[i] = colors[i] != null ? new HSBK(colors[i]) : null;
82 public @Nullable HevCycleState getHevCycleState() {
86 public @Nullable PercentType getInfrared() {
90 public @Nullable SignalStrength getSignalStrength() {
91 return signalStrength;
94 public @Nullable Effect getTileEffect() {
98 public void setColor(HSBType newHSB) {
99 HSBK newColor = getColor();
100 newColor.setHSB(newHSB);
104 public void setColor(HSBType newHSB, int zoneIndex) {
105 HSBK newColor = getColor(zoneIndex);
106 newColor.setHSB(newHSB);
107 setColor(newColor, zoneIndex);
110 public void setBrightness(PercentType brightness) {
111 HSBK[] newColors = getColors();
112 for (HSBK newColor : newColors) {
113 newColor.setBrightness(brightness);
115 setColors(newColors);
118 public void setBrightness(PercentType brightness, int zoneIndex) {
119 HSBK newColor = getColor(zoneIndex);
120 newColor.setBrightness(brightness);
121 setColor(newColor, zoneIndex);
124 public void setColor(HSBK newColor) {
125 HSBK[] newColors = getColors();
126 Arrays.fill(newColors, newColor);
127 setColors(newColors);
130 public void setColor(HSBK newColor, int zoneIndex) {
131 HSBK[] newColors = getColors();
132 newColors[zoneIndex] = newColor;
133 setColors(newColors);
136 public void setColors(HSBK[] newColors) {
137 HSBK[] oldColors = this.colors;
138 this.colors = newColors;
140 listeners.forEach(listener -> listener.handleColorsChange(oldColors, newColors));
143 public void setPowerState(OnOffType newOnOff) {
144 setPowerState(PowerState.fromOnOffType(newOnOff));
147 public void setPowerState(PowerState newPowerState) {
148 PowerState oldPowerState = this.powerState;
149 this.powerState = newPowerState;
151 listeners.forEach(listener -> listener.handlePowerStateChange(oldPowerState, newPowerState));
154 public void setTemperature(int kelvin) {
155 HSBK[] newColors = getColors();
156 for (HSBK newColor : newColors) {
157 newColor.setKelvin(kelvin);
159 setColors(newColors);
162 public void setTemperature(int kelvin, int zoneIndex) {
163 HSBK newColor = getColor(zoneIndex);
164 newColor.setKelvin(kelvin);
165 setColor(newColor, zoneIndex);
168 public void setHevCycleState(HevCycleState newHevCycleState) {
169 HevCycleState oldHevCycleState = this.hevCycleState;
170 this.hevCycleState = newHevCycleState;
172 listeners.forEach(listener -> listener.handleHevCycleStateChange(oldHevCycleState, newHevCycleState));
175 public void setInfrared(PercentType newInfrared) {
176 PercentType oldInfrared = this.infrared;
177 this.infrared = newInfrared;
179 listeners.forEach(listener -> listener.handleInfraredChange(oldInfrared, newInfrared));
182 public void setSignalStrength(SignalStrength newSignalStrength) {
183 SignalStrength oldSignalStrength = this.signalStrength;
184 this.signalStrength = newSignalStrength;
186 listeners.forEach(listener -> listener.handleSignalStrengthChange(oldSignalStrength, newSignalStrength));
189 public void setTileEffect(Effect newEffect) {
190 // Caller has to take care that newEffect is another object
191 Effect oldEffect = tileEffect;
192 tileEffect = newEffect;
194 listeners.forEach(listener -> listener.handleTileEffectChange(oldEffect, newEffect));
197 private void updateLastChange() {
198 lastChange = LocalDateTime.now();
201 public Duration getDurationSinceLastChange() {
202 return Duration.between(lastChange, LocalDateTime.now());
205 public void addListener(LifxLightStateListener listener) {
206 listeners.add(listener);
209 public void removeListener(LifxLightStateListener listener) {
210 listeners.remove(listener);