Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

[LIFX] Update ThingStatus at most once a second #3816

Merged
merged 2 commits into from Jul 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -10,6 +10,9 @@
import static org.eclipse.smarthome.binding.lifx.LifxBindingConstants.*;
import static org.eclipse.smarthome.binding.lifx.internal.LifxUtils.increaseDecreasePercentType;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
Expand Down Expand Up @@ -47,6 +50,7 @@
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingStatusInfo;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.RefreshType;
Expand All @@ -68,24 +72,28 @@ public class LifxLightHandler extends BaseThingHandler implements LifxProperties

private final Logger logger = LoggerFactory.getLogger(LifxLightHandler.class);

private static final long FADE_TIME_DEFAULT = 300;
private static final int MAX_STATE_CHANGE_DURATION = 4000;
private static final Duration FADE_TIME_DEFAULT = Duration.ofMillis(300);
private static final Duration MIN_STATUS_INFO_UPDATE_INTERVAL = Duration.ofSeconds(1);
private static final Duration MAX_STATE_CHANGE_DURATION = Duration.ofSeconds(4);

private final LifxChannelFactory channelFactory;
private Products product;

private long fadeTime = FADE_TIME_DEFAULT;
private Duration fadeTime = FADE_TIME_DEFAULT;
private PercentType powerOnBrightness;

private MACAddress macAddress;
private String macAsHex;

private final ReentrantLock lock = new ReentrantLock();

private Map<String, State> channelStates;
private CurrentLightState currentLightState;
private LifxLightState pendingLightState;

private Map<String, State> channelStates;
private ThingStatusInfo statusInfo;
private LocalDateTime lastStatusInfoUpdate = LocalDateTime.MIN;

private LifxLightCommunicationHandler communicationHandler;
private LifxLightCurrentStateUpdater currentStateUpdater;
private LifxLightStateChanger lightStateChanger;
Expand All @@ -103,15 +111,15 @@ public boolean isOffline() {
}

public void setOnline() {
updateStatus(ThingStatus.ONLINE);
updateStatusIfChanged(ThingStatus.ONLINE);
}

public void setOffline() {
updateStatus(ThingStatus.OFFLINE);
updateStatusIfChanged(ThingStatus.OFFLINE);
}

public void setOfflineByCommunicationError() {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}

@Override
Expand Down Expand Up @@ -280,17 +288,9 @@ public void dispose() {
}
}

private long getFadeTime() {
Object fadeCfg = getConfig().get(LifxBindingConstants.CONFIG_PROPERTY_FADETIME);
if (fadeCfg == null) {
return FADE_TIME_DEFAULT;
}
try {
return Long.parseLong(fadeCfg.toString());
} catch (NumberFormatException e) {
logger.warn("Invalid value '{}' for transition time, using default instead.", fadeCfg.toString());
return FADE_TIME_DEFAULT;
}
private Duration getFadeTime() {
BigDecimal fadeCfg = (BigDecimal) getConfig().get(LifxBindingConstants.CONFIG_PROPERTY_FADETIME);
return fadeCfg == null ? FADE_TIME_DEFAULT : Duration.ofMillis(fadeCfg.longValue());
}

private PercentType getPowerOnBrightness() {
Expand Down Expand Up @@ -483,7 +483,7 @@ private LifxLightState getLightStateForCommand() {
}

private boolean isStateChangePending() {
return pendingLightState.getMillisSinceLastChange() < MAX_STATE_CHANGE_DURATION;
return pendingLightState.getDurationSinceLastChange().minus(MAX_STATE_CHANGE_DURATION).isNegative();
}

private void handleTemperatureCommand(PercentType temperature) {
Expand Down Expand Up @@ -573,4 +573,20 @@ private void updateStateIfChanged(String channel, State newState) {
}
}

private void updateStatusIfChanged(ThingStatus status) {
updateStatusIfChanged(status, ThingStatusDetail.NONE);
}

private void updateStatusIfChanged(ThingStatus status, ThingStatusDetail statusDetail) {
ThingStatusInfo newStatusInfo = new ThingStatusInfo(status, statusDetail, null);
Duration durationSinceLastUpdate = Duration.between(lastStatusInfoUpdate, LocalDateTime.now());
boolean intervalElapsed = MIN_STATUS_INFO_UPDATE_INTERVAL.minus(durationSinceLastUpdate).isNegative();

if (statusInfo == null || !statusInfo.equals(newStatusInfo) || intervalElapsed) {
statusInfo = newStatusInfo;
lastStatusInfoUpdate = LocalDateTime.now();
updateStatus(status, statusDetail);
}
}

}
Expand Up @@ -9,6 +9,8 @@

import static org.eclipse.smarthome.binding.lifx.LifxBindingConstants.DEFAULT_COLOR;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
Expand All @@ -33,7 +35,7 @@ public class LifxLightState {
private PercentType infrared;
private SignalStrength signalStrength;

private long lastChange;
private LocalDateTime lastChange = LocalDateTime.MIN;

private List<LifxLightStateListener> listeners = new CopyOnWriteArrayList<>();

Expand Down Expand Up @@ -184,11 +186,11 @@ public void setSignalStrength(SignalStrength newSignalStrength) {
}

private void updateLastChange() {
lastChange = System.currentTimeMillis();
lastChange = LocalDateTime.now();
}

public long getMillisSinceLastChange() {
return System.currentTimeMillis() - lastChange;
public Duration getDurationSinceLastChange() {
return Duration.between(lastChange, LocalDateTime.now());
}

public void addListener(LifxLightStateListener listener) {
Expand Down
Expand Up @@ -10,6 +10,7 @@
import static org.eclipse.smarthome.binding.lifx.LifxBindingConstants.PACKET_INTERVAL;
import static org.eclipse.smarthome.binding.lifx.internal.LifxUtils.*;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -68,7 +69,7 @@ public class LifxLightStateChanger implements LifxLightStateListener, LifxRespon
private final ScheduledExecutorService scheduler;
private final LifxLightState pendingLightState;
private final LifxLightCommunicationHandler communicationHandler;
private final long fadeTime;
private final Duration fadeTime;
private final Products product;

private final ReentrantLock lock = new ReentrantLock();
Expand Down Expand Up @@ -129,7 +130,7 @@ public void run() {

public LifxLightStateChanger(MACAddress macAddress, ScheduledExecutorService scheduler,
LifxLightState pendingLightState, LifxLightCommunicationHandler communicationHandler, Products product,
long fadeTime) {
Duration fadeTime) {
this.macAsHex = macAddress.getHex();
this.scheduler = scheduler;
this.pendingLightState = pendingLightState;
Expand Down Expand Up @@ -277,14 +278,15 @@ private PendingPacket removeAcknowledgedPacket(int sequenceNumber) {
@Override
public void handleColorsChange(HSBK[] oldColors, HSBK[] newColors) {
if (sameColors(newColors)) {
SetColorRequest packet = new SetColorRequest(pendingLightState.getColors()[0], fadeTime);
SetColorRequest packet = new SetColorRequest(pendingLightState.getColors()[0], fadeTime.toMillis());
removePacketsByType(SetColorZonesRequest.TYPE);
replacePacketsInMap(packet);
} else {
List<SetColorZonesRequest> packets = new ArrayList<>();
for (int i = 0; i < newColors.length; i++) {
if (newColors[i] != null && !newColors[i].equals(oldColors[i])) {
packets.add(new SetColorZonesRequest(i, newColors[i], fadeTime, ApplicationRequest.APPLY));
packets.add(
new SetColorZonesRequest(i, newColors[i], fadeTime.toMillis(), ApplicationRequest.APPLY));
}
}
if (!packets.isEmpty()) {
Expand Down