From 3a17c3c1972da3beab3da50427b6bd17f8314875 Mon Sep 17 00:00:00 2001 From: lolodomo Date: Sat, 2 May 2020 17:06:49 +0200 Subject: [PATCH] [hue] Improved code (notify status listener) (#7511) * [hue] Improved code (notify status listener) Signed-off-by: Laurent Garnier --- .../internal/handler/HueBridgeHandler.java | 122 ++++++++---------- 1 file changed, 56 insertions(+), 66 deletions(-) diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java index fb91d47756176..0102bae0ba8a9 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java @@ -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 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 lastLightStates = new ConcurrentHashMap<>(); + private final Map lastSensorStates = new ConcurrentHashMap<>(); + + private final List lightStatusListeners = new CopyOnWriteArrayList<>(); + private final List sensorStatusListeners = new CopyOnWriteArrayList<>(); final ReentrantLock pollingLock = new ReentrantLock(); @@ -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 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 lastLightStates = new ConcurrentHashMap<>(); - private final Map lastSensorStates = new ConcurrentHashMap<>(); - - private boolean lastBridgeConnectionState = false; - - private boolean propertiesInitializedSuccessfully = false; - - private final List lightStatusListeners = new CopyOnWriteArrayList<>(); - private final List 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 { @@ -187,13 +177,12 @@ 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); } } @@ -201,13 +190,7 @@ protected void doConnectedRun() throws IOException, ApiException { for (Entry 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); } } }; @@ -232,12 +215,12 @@ 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); } } @@ -245,17 +228,24 @@ protected void doConnectedRun() throws IOException, ApiException { for (Entry 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); } @@ -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); @@ -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); @@ -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); @@ -700,12 +690,12 @@ private T withReAuthentication(String taskDescription, Callable 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; @@ -714,20 +704,20 @@ 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); @@ -735,7 +725,7 @@ private void notifyLightStatusListeners(final FullLight fullLight, final String } } - 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; @@ -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);