[hdpowerview] Optimize initialization of shades (#12113)

* Optimize initialization of shades.

Fixes #12071

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>

* Avoid hashmap reallocation during initialization.

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen 2022-01-28 07:47:32 +01:00 committed by GitHub
parent 608d0ae23a
commit dab48ddd95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 20 deletions

View File

@ -17,6 +17,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -57,6 +58,7 @@ import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseBridgeHandler; import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.builder.ChannelBuilder; import org.openhab.core.thing.binding.builder.ChannelBuilder;
@ -77,11 +79,10 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public class HDPowerViewHubHandler extends BaseBridgeHandler { public class HDPowerViewHubHandler extends BaseBridgeHandler {
private static final long INITIAL_SOFT_POLL_DELAY_MS = 5_000;
private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubHandler.class); private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubHandler.class);
private final HttpClient httpClient; private final HttpClient httpClient;
private final HDPowerViewTranslationProvider translationProvider; private final HDPowerViewTranslationProvider translationProvider;
private final ConcurrentHashMap<ThingUID, ShadeData> pendingShadeInitializations = new ConcurrentHashMap<>();
private long refreshInterval; private long refreshInterval;
private long hardRefreshPositionInterval; private long hardRefreshPositionInterval;
@ -135,11 +136,11 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
if (sceneChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) { if (sceneChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) {
webTargets.activateScene(id); webTargets.activateScene(id);
// Reschedule soft poll for immediate shade position update. // Reschedule soft poll for immediate shade position update.
scheduleSoftPoll(0); scheduleSoftPoll();
} else if (sceneGroupChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) { } else if (sceneGroupChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) {
webTargets.activateSceneCollection(id); webTargets.activateSceneCollection(id);
// Reschedule soft poll for immediate shade position update. // Reschedule soft poll for immediate shade position update.
scheduleSoftPoll(0); scheduleSoftPoll();
} else if (automationChannelTypeUID.equals(channel.getChannelTypeUID())) { } else if (automationChannelTypeUID.equals(channel.getChannelTypeUID())) {
webTargets.enableScheduledEvent(id, OnOffType.ON == command); webTargets.enableScheduledEvent(id, OnOffType.ON == command);
} }
@ -162,6 +163,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
return; return;
} }
pendingShadeInitializations.clear();
webTargets = new HDPowerViewWebTargets(httpClient, host); webTargets = new HDPowerViewWebTargets(httpClient, host);
refreshInterval = config.refresh; refreshInterval = config.refresh;
hardRefreshPositionInterval = config.hardRefresh; hardRefreshPositionInterval = config.hardRefresh;
@ -193,21 +195,42 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
public void dispose() { public void dispose() {
super.dispose(); super.dispose();
stopPoll(); stopPoll();
pendingShadeInitializations.clear();
}
@Override
public void childHandlerInitialized(final ThingHandler childHandler, final Thing childThing) {
logger.debug("Child handler initialized: {}", childThing.getUID());
if (childHandler instanceof HDPowerViewShadeHandler) {
ShadeData shadeData = pendingShadeInitializations.remove(childThing.getUID());
if (shadeData != null) {
updateShadeThing(shadeData.id, childThing, shadeData);
}
}
super.childHandlerInitialized(childHandler, childThing);
}
@Override
public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) {
logger.debug("Child handler disposed: {}", childThing.getUID());
if (childHandler instanceof HDPowerViewShadeHandler) {
pendingShadeInitializations.remove(childThing.getUID());
}
super.childHandlerDisposed(childHandler, childThing);
} }
private void schedulePoll() { private void schedulePoll() {
scheduleSoftPoll(INITIAL_SOFT_POLL_DELAY_MS); scheduleSoftPoll();
scheduleHardPoll(); scheduleHardPoll();
} }
private void scheduleSoftPoll(long initialDelay) { private void scheduleSoftPoll() {
ScheduledFuture<?> future = this.pollFuture; ScheduledFuture<?> future = this.pollFuture;
if (future != null) { if (future != null) {
future.cancel(false); future.cancel(false);
} }
logger.debug("Scheduling poll for {} ms out, then every {} ms", initialDelay, refreshInterval); logger.debug("Scheduling poll every {} ms", refreshInterval);
this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, initialDelay, refreshInterval, this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshInterval, TimeUnit.MILLISECONDS);
TimeUnit.MILLISECONDS);
} }
private void scheduleHardPoll() { private void scheduleHardPoll() {
@ -336,17 +359,35 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
} }
private void updateShadeThing(int shadeId, Thing thing, @Nullable ShadeData shadeData) { private void updateShadeThing(int shadeId, Thing thing, @Nullable ShadeData shadeData) {
if (shadeData == null) {
logger.debug("Shade '{}' has no data in hub", shadeId);
return;
}
HDPowerViewShadeHandler thingHandler = ((HDPowerViewShadeHandler) thing.getHandler()); HDPowerViewShadeHandler thingHandler = ((HDPowerViewShadeHandler) thing.getHandler());
if (thingHandler == null) { if (thingHandler == null) {
logger.debug("Shade '{}' handler not initialized", shadeId); logger.debug("Shade '{}' handler not initialized", shadeId);
pendingShadeInitializations.put(thing.getUID(), shadeData);
return; return;
} }
if (shadeData == null) { ThingStatus thingStatus = thingHandler.getThing().getStatus();
logger.debug("Shade '{}' has no data in hub", shadeId); switch (thingStatus) {
} else { case UNKNOWN:
logger.debug("Updating shade '{}'", shadeId); case ONLINE:
case OFFLINE:
logger.debug("Updating shade '{}'", shadeId);
thingHandler.onReceiveUpdate(shadeData);
break;
case UNINITIALIZED:
case INITIALIZING:
logger.debug("Shade '{}' handler not yet ready; status: {}", shadeId, thingStatus);
pendingShadeInitializations.put(thing.getUID(), shadeData);
break;
case REMOVING:
case REMOVED:
default:
logger.debug("Ignoring shade update for shade '{}' in status {}", shadeId, thingStatus);
break;
} }
thingHandler.onReceiveUpdate(shadeData);
} }
private List<Scene> fetchScenes() private List<Scene> fetchScenes()

View File

@ -107,12 +107,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
"@text/offline.conf-error.invalid-bridge-handler"); "@text/offline.conf-error.invalid-bridge-handler");
return; return;
} }
ThingStatus bridgeStatus = bridge.getStatus(); updateStatus(ThingStatus.UNKNOWN);
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.UNKNOWN);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} }
@Override @Override