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;
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;
@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;
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);
}
return;
}
+ pendingShadeInitializations.clear();
webTargets = new HDPowerViewWebTargets(httpClient, host);
refreshInterval = config.refresh;
hardRefreshPositionInterval = config.hardRefresh;
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() {
}
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()