Skip to content

Commit

Permalink
[hdpowerview] Optimize initialization of shades (openhab#12113)
Browse files Browse the repository at this point in the history
* Optimize initialization of shades.

Fixes openhab#12071

Signed-off-by: Jacob Laursen <[email protected]>

* Avoid hashmap reallocation during initialization.

Signed-off-by: Jacob Laursen <[email protected]>
Signed-off-by: Andras Uhrin <[email protected]>
  • Loading branch information
jlaur authored and andrasU committed Nov 12, 2022
1 parent 37d4f5a commit 5f3e7ef
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -57,6 +58,7 @@
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
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.ThingHandler;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
Expand All @@ -77,11 +79,10 @@
@NonNullByDefault
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 HttpClient httpClient;
private final HDPowerViewTranslationProvider translationProvider;
private final ConcurrentHashMap<ThingUID, ShadeData> pendingShadeInitializations = new ConcurrentHashMap<>();

private long refreshInterval;
private long hardRefreshPositionInterval;
Expand Down Expand Up @@ -135,11 +136,11 @@ public void handleCommand(ChannelUID channelUID, Command command) {
if (sceneChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) {
webTargets.activateScene(id);
// Reschedule soft poll for immediate shade position update.
scheduleSoftPoll(0);
scheduleSoftPoll();
} else if (sceneGroupChannelTypeUID.equals(channel.getChannelTypeUID()) && OnOffType.ON == command) {
webTargets.activateSceneCollection(id);
// Reschedule soft poll for immediate shade position update.
scheduleSoftPoll(0);
scheduleSoftPoll();
} else if (automationChannelTypeUID.equals(channel.getChannelTypeUID())) {
webTargets.enableScheduledEvent(id, OnOffType.ON == command);
}
Expand All @@ -162,6 +163,7 @@ public void initialize() {
return;
}

pendingShadeInitializations.clear();
webTargets = new HDPowerViewWebTargets(httpClient, host);
refreshInterval = config.refresh;
hardRefreshPositionInterval = config.hardRefresh;
Expand Down Expand Up @@ -193,21 +195,42 @@ public void handleRemoval() {
public void dispose() {
super.dispose();
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() {
scheduleSoftPoll(INITIAL_SOFT_POLL_DELAY_MS);
scheduleSoftPoll();
scheduleHardPoll();
}

private void scheduleSoftPoll(long initialDelay) {
private void scheduleSoftPoll() {
ScheduledFuture<?> future = this.pollFuture;
if (future != null) {
future.cancel(false);
}
logger.debug("Scheduling poll for {} ms out, then every {} ms", initialDelay, refreshInterval);
this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, initialDelay, refreshInterval,
TimeUnit.MILLISECONDS);
logger.debug("Scheduling poll every {} ms", refreshInterval);
this.pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshInterval, TimeUnit.MILLISECONDS);
}

private void scheduleHardPoll() {
Expand Down Expand Up @@ -336,17 +359,35 @@ private void pollShades() throws HubInvalidResponseException, HubProcessingExcep
}

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());
if (thingHandler == null) {
logger.debug("Shade '{}' handler not initialized", shadeId);
pendingShadeInitializations.put(thing.getUID(), shadeData);
return;
}
if (shadeData == null) {
logger.debug("Shade '{}' has no data in hub", shadeId);
} else {
logger.debug("Updating shade '{}'", shadeId);
ThingStatus thingStatus = thingHandler.getThing().getStatus();
switch (thingStatus) {
case UNKNOWN:
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,7 @@ public void initialize() {
"@text/offline.conf-error.invalid-bridge-handler");
return;
}
ThingStatus bridgeStatus = bridge.getStatus();
if (bridgeStatus == ThingStatus.ONLINE) {
updateStatus(ThingStatus.UNKNOWN);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
updateStatus(ThingStatus.UNKNOWN);
}

@Override
Expand Down

0 comments on commit 5f3e7ef

Please sign in to comment.