Skip to content

Commit

Permalink
[hue] Improved code (notify status listener) (openhab#7511)
Browse files Browse the repository at this point in the history
* [hue] Improved code (notify status listener)

Signed-off-by: Laurent Garnier <[email protected]>
  • Loading branch information
lolodomo authored and J-N-K committed Jul 14, 2020
1 parent 47bd992 commit 3eb5d5b
Showing 1 changed file with 56 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,24 @@
@NonNullByDefault
public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueClient {

private long lightPollingInterval = TimeUnit.SECONDS.toSeconds(10);
private long sensorPollingInterval = TimeUnit.MILLISECONDS.toMillis(500);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);

private static final String DEVICE_TYPE = "EclipseSmartHome";

private static enum StatusType {
ADDED,
REMOVED,
GONE,
CHANGED
}

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

private final Map<String, FullLight> lastLightStates = new ConcurrentHashMap<>();
private final Map<String, FullSensor> lastSensorStates = new ConcurrentHashMap<>();

private final List<LightStatusListener> lightStatusListeners = new CopyOnWriteArrayList<>();
private final List<SensorStatusListener> sensorStatusListeners = new CopyOnWriteArrayList<>();

final ReentrantLock pollingLock = new ReentrantLock();

Expand Down Expand Up @@ -148,32 +164,6 @@ private boolean isReachable(String ipAddress) {
}
}

private static final String STATE_ADDED = "added";
private static final String STATE_GONE = "gone";
private static final String STATE_CHANGED = "changed";

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE);

private static final String DEVICE_TYPE = "EclipseSmartHome";

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

private final Map<String, FullLight> lastLightStates = new ConcurrentHashMap<>();
private final Map<String, FullSensor> lastSensorStates = new ConcurrentHashMap<>();

private boolean lastBridgeConnectionState = false;

private boolean propertiesInitializedSuccessfully = false;

private final List<LightStatusListener> lightStatusListeners = new CopyOnWriteArrayList<>();
private final List<SensorStatusListener> sensorStatusListeners = new CopyOnWriteArrayList<>();

private @Nullable ScheduledFuture<?> lightPollingJob;
private @Nullable ScheduledFuture<?> sensorPollingJob;

private @NonNullByDefault({}) HueBridge hueBridge = null;
private @NonNullByDefault({}) HueBridgeConfig hueBridgeConfig = null;

private final Runnable sensorPollingRunnable = new PollingRunnable() {
@Override
protected void doConnectedRun() throws IOException, ApiException {
Expand All @@ -187,27 +177,20 @@ protected void doConnectedRun() throws IOException, ApiException {
lastSensorStates.put(sensorId, sensor);
if (!lastFullSensorState.equals(sensor.getState())) {
logger.debug("Status update for Hue sensor '{}' detected: {}", sensorId, sensor.getState());
notifySensorStatusListeners(sensor, STATE_CHANGED);
notifySensorStatusListeners(sensor, StatusType.CHANGED);
}
} else {
lastSensorStates.put(sensorId, sensor);
logger.debug("Hue sensor '{}' added.", sensorId);
notifySensorStatusListeners(sensor, STATE_ADDED);

notifySensorStatusListeners(sensor, StatusType.ADDED);
}
}

// Check for removed sensors
for (Entry<String, FullSensor> fullSensorEntry : lastSensorStateCopy.entrySet()) {
lastSensorStates.remove(fullSensorEntry.getKey());
logger.debug("Hue sensor '{}' removed.", fullSensorEntry.getKey());
for (SensorStatusListener sensorStatusListener : sensorStatusListeners) {
try {
sensorStatusListener.onSensorRemoved(hueBridge, fullSensorEntry.getValue());
} catch (Exception e) {
logger.error("An exception occurred while calling the Sensor Listeners", e);
}
}
notifySensorStatusListeners(fullSensorEntry.getValue(), StatusType.REMOVED);
}
}
};
Expand All @@ -232,30 +215,37 @@ protected void doConnectedRun() throws IOException, ApiException {
lastLightStates.put(lightId, fullLight);
if (!lastFullLightState.equals(fullLight.getState())) {
logger.debug("Status update for Hue light '{}' detected.", lightId);
notifyLightStatusListeners(fullLight, STATE_CHANGED);
notifyLightStatusListeners(fullLight, StatusType.CHANGED);
}
} else {
lastLightStates.put(lightId, fullLight);
logger.debug("Hue light '{}' added.", lightId);
notifyLightStatusListeners(fullLight, STATE_ADDED);
notifyLightStatusListeners(fullLight, StatusType.ADDED);
}
}

// Check for removed lights
for (Entry<String, FullLight> fullLightEntry : lastLightStateCopy.entrySet()) {
lastLightStates.remove(fullLightEntry.getKey());
logger.debug("Hue light '{}' removed.", fullLightEntry.getKey());
for (LightStatusListener lightStatusListener : lightStatusListeners) {
try {
lightStatusListener.onLightRemoved(hueBridge, fullLightEntry.getValue());
} catch (Exception e) {
logger.error("An exception occurred while calling the BridgeHeartbeatListener", e);
}
}
notifyLightStatusListeners(fullLightEntry.getValue(), StatusType.REMOVED);
}
}
};

private long lightPollingInterval = TimeUnit.SECONDS.toSeconds(10);
private long sensorPollingInterval = TimeUnit.MILLISECONDS.toMillis(500);

private boolean lastBridgeConnectionState = false;

private boolean propertiesInitializedSuccessfully = false;

private @Nullable ScheduledFuture<?> lightPollingJob;
private @Nullable ScheduledFuture<?> sensorPollingJob;

private @NonNullByDefault({}) HueBridge hueBridge = null;
private @NonNullByDefault({}) HueBridgeConfig hueBridgeConfig = null;

public HueBridgeHandler(Bridge bridge) {
super(bridge);
}
Expand Down Expand Up @@ -333,7 +323,7 @@ private void handleStateUpdateException(FullLight light, StateUpdate stateUpdate
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
} else if (e instanceof EntityNotAvailableException) {
logger.debug("Error while accessing light: {}", e.getMessage(), e);
notifyLightStatusListeners(light, STATE_GONE);
notifyLightStatusListeners(light, StatusType.GONE);
} else if (e instanceof ApiException) {
// This should not happen - if it does, it is most likely some bug that should be reported.
logger.warn("Error while accessing light: {}", e.getMessage(), e);
Expand All @@ -347,7 +337,7 @@ private void handleStateUpdateException(FullSensor sensor, StateUpdate stateUpda
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
} else if (e instanceof EntityNotAvailableException) {
logger.debug("Error while accessing sensor: {}", e.getMessage(), e);
notifySensorStatusListeners(sensor, STATE_GONE);
notifySensorStatusListeners(sensor, StatusType.GONE);
} else if (e instanceof ApiException) {
// This should not happen - if it does, it is most likely some bug that should be reported.
logger.warn("Error while accessing sensor: {}", e.getMessage(), e);
Expand All @@ -361,7 +351,7 @@ private void handleConfigUpdateException(FullSensor sensor, ConfigUpdate configU
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
} else if (e instanceof EntityNotAvailableException) {
logger.debug("Error while accessing sensor: {}", e.getMessage(), e);
notifySensorStatusListeners(sensor, STATE_GONE);
notifySensorStatusListeners(sensor, StatusType.GONE);
} else if (e instanceof ApiException) {
// This should not happen - if it does, it is most likely some bug that should be reported.
logger.warn("Error while accessing sensor: {}", e.getMessage(), e);
Expand Down Expand Up @@ -700,12 +690,12 @@ private <T> T withReAuthentication(String taskDescription, Callable<T> runnable)
}

/**
* Iterate through lightStatusListeners and notify them about a changed or added light state.
* Iterate through lightStatusListeners and notify them about a status change.
*
* @param fullLight
* @param type Can be "changed" if just a state has changed or "added" if this is a new light on the bridge.
* @param type the type of change
*/
private void notifyLightStatusListeners(final FullLight fullLight, final String type) {
private void notifyLightStatusListeners(final FullLight fullLight, StatusType type) {
if (lightStatusListeners.isEmpty()) {
logger.debug("No light status listeners to notify of light change for light '{}'", fullLight.getId());
return;
Expand All @@ -714,28 +704,28 @@ private void notifyLightStatusListeners(final FullLight fullLight, final String
for (LightStatusListener lightStatusListener : lightStatusListeners) {
try {
switch (type) {
case STATE_ADDED:
case ADDED:
logger.debug("Sending lightAdded for light '{}'", fullLight.getId());
lightStatusListener.onLightAdded(hueBridge, fullLight);
break;
case STATE_GONE:
case REMOVED:
lightStatusListener.onLightRemoved(hueBridge, fullLight);
break;
case GONE:
lightStatusListener.onLightGone(hueBridge, fullLight);
break;
case STATE_CHANGED:
case CHANGED:
logger.debug("Sending lightStateChanged for light '{}'", fullLight.getId());
lightStatusListener.onLightStateChanged(hueBridge, fullLight);
break;
default:
throw new IllegalArgumentException(
"Could not notify lightStatusListeners for unknown event type " + type);
}
} catch (Exception e) {
logger.error("An exception occurred while calling the BridgeHeartbeatListener", e);
}
}
}

private void notifySensorStatusListeners(final FullSensor fullSensor, final String type) {
private void notifySensorStatusListeners(final FullSensor fullSensor, StatusType type) {
if (sensorStatusListeners.isEmpty()) {
logger.debug("No sensor status listeners to notify of sensor change for sensor '{}'", fullSensor.getId());
return;
Expand All @@ -744,20 +734,20 @@ private void notifySensorStatusListeners(final FullSensor fullSensor, final Stri
for (SensorStatusListener sensorStatusListener : sensorStatusListeners) {
try {
switch (type) {
case STATE_ADDED:
case ADDED:
logger.debug("Sending sensorAdded for sensor '{}'", fullSensor.getId());
sensorStatusListener.onSensorAdded(hueBridge, fullSensor);
break;
case STATE_GONE:
case REMOVED:
sensorStatusListener.onSensorRemoved(hueBridge, fullSensor);
break;
case GONE:
sensorStatusListener.onSensorGone(hueBridge, fullSensor);
break;
case STATE_CHANGED:
case CHANGED:
logger.debug("Sending sensorStateChanged for sensor '{}'", fullSensor.getId());
sensorStatusListener.onSensorStateChanged(hueBridge, fullSensor);
break;
default:
throw new IllegalArgumentException(
"Could not notify sensorStatusListeners for unknown event type " + type);
}
} catch (Exception e) {
logger.error("An exception occurred while calling the Sensor Listeners", e);
Expand Down

0 comments on commit 3eb5d5b

Please sign in to comment.