2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.velux.internal.handler;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ScheduledExecutorService;
18 import java.util.concurrent.ScheduledFuture;
19 import java.util.concurrent.TimeUnit;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.openhab.binding.velux.internal.VeluxBinding;
24 import org.openhab.binding.velux.internal.VeluxBindingConstants;
25 import org.openhab.binding.velux.internal.VeluxItemType;
26 import org.openhab.binding.velux.internal.bridge.VeluxBridge;
27 import org.openhab.binding.velux.internal.bridge.VeluxBridgeActuators;
28 import org.openhab.binding.velux.internal.bridge.VeluxBridgeDeviceStatus;
29 import org.openhab.binding.velux.internal.bridge.VeluxBridgeGetFirmware;
30 import org.openhab.binding.velux.internal.bridge.VeluxBridgeGetHouseStatus;
31 import org.openhab.binding.velux.internal.bridge.VeluxBridgeInstance;
32 import org.openhab.binding.velux.internal.bridge.VeluxBridgeLANConfig;
33 import org.openhab.binding.velux.internal.bridge.VeluxBridgeProvider;
34 import org.openhab.binding.velux.internal.bridge.VeluxBridgeScenes;
35 import org.openhab.binding.velux.internal.bridge.VeluxBridgeSetHouseStatusMonitor;
36 import org.openhab.binding.velux.internal.bridge.VeluxBridgeWLANConfig;
37 import org.openhab.binding.velux.internal.bridge.common.BridgeAPI;
38 import org.openhab.binding.velux.internal.bridge.common.BridgeCommunicationProtocol;
39 import org.openhab.binding.velux.internal.bridge.json.JsonVeluxBridge;
40 import org.openhab.binding.velux.internal.bridge.slip.SlipVeluxBridge;
41 import org.openhab.binding.velux.internal.config.VeluxBridgeConfiguration;
42 import org.openhab.binding.velux.internal.development.Threads;
43 import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseBridgeHandler;
44 import org.openhab.binding.velux.internal.handler.utils.Thing2VeluxActuator;
45 import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
46 import org.openhab.binding.velux.internal.things.VeluxExistingProducts;
47 import org.openhab.binding.velux.internal.things.VeluxExistingScenes;
48 import org.openhab.binding.velux.internal.things.VeluxProduct;
49 import org.openhab.binding.velux.internal.things.VeluxProduct.ProductBridgeIndex;
50 import org.openhab.binding.velux.internal.things.VeluxProductPosition;
51 import org.openhab.binding.velux.internal.utils.Localization;
52 import org.openhab.core.common.AbstractUID;
53 import org.openhab.core.common.ThreadPoolManager;
54 import org.openhab.core.library.types.DecimalType;
55 import org.openhab.core.library.types.OnOffType;
56 import org.openhab.core.library.types.PercentType;
57 import org.openhab.core.thing.Bridge;
58 import org.openhab.core.thing.ChannelUID;
59 import org.openhab.core.thing.ThingStatus;
60 import org.openhab.core.thing.ThingStatusDetail;
61 import org.openhab.core.thing.ThingTypeUID;
62 import org.openhab.core.types.Command;
63 import org.openhab.core.types.RefreshType;
64 import org.openhab.core.types.State;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
69 * <B>Common interaction with the </B><I>Velux</I><B> bridge.</B>
71 * It implements the communication between <B>OpenHAB</B> and the <I>Velux</I> Bridge:
73 * <LI><B>OpenHAB</B> Event Bus → <I>Velux</I> <B>bridge</B>
75 * Sending commands and value updates.</LI>
78 * <LI><I>Velux</I> <B>bridge</B> → <B>OpenHAB</B>:
80 * Retrieving information by sending a Refresh command.</LI>
83 * Entry point for this class is the method
84 * {@link VeluxBridgeHandler#handleCommand handleCommand}.
86 * @author Guenther Schreiner - Initial contribution.
89 public class VeluxBridgeHandler extends ExtendedBaseBridgeHandler implements VeluxBridgeInstance, VeluxBridgeProvider {
90 private final Logger logger = LoggerFactory.getLogger(VeluxBridgeHandler.class);
95 * Scheduler for continuous refresh by scheduleWithFixedDelay.
97 private @Nullable ScheduledFuture<?> refreshJob = null;
100 * Counter of refresh invocations by {@link refreshJob}.
102 private int refreshCounter = 0;
105 * Dedicated thread pool for the long-running bridge communication threads.
107 private ScheduledExecutorService handleScheduler = ThreadPoolManager
108 .getScheduledPool(VeluxBindingConstants.BINDING_ID);
110 private VeluxBridge myJsonBridge = new JsonVeluxBridge(this);
111 private VeluxBridge mySlipBridge = new SlipVeluxBridge(this);
114 * **************************************
115 * ***** Default visibility Objects *****
118 VeluxBridge thisBridge = myJsonBridge;
119 public BridgeParameters bridgeParameters = new BridgeParameters();
120 Localization localization;
123 * Mapping from ChannelUID to class Thing2VeluxActuator, which return Velux device information, probably cached.
125 Map<ChannelUID, Thing2VeluxActuator> channel2VeluxActuator = new ConcurrentHashMap<>();
128 * Information retrieved by {@link VeluxBinding#VeluxBinding}.
130 private VeluxBridgeConfiguration veluxBridgeConfiguration = new VeluxBridgeConfiguration();
133 * ************************
134 * ***** Constructors *****
137 public VeluxBridgeHandler(final Bridge bridge, Localization localization) {
139 logger.trace("VeluxBridgeHandler(constructor with bridge={}, localization={}) called.", bridge, localization);
140 this.localization = localization;
141 logger.debug("Creating a VeluxBridgeHandler for thing '{}'.", getThing().getUID());
148 * Set of information retrieved from the bridge/gateway:
151 * <LI>{@link #actuators} - Already known actuators,</LI>
152 * <LI>{@link #scenes} - Already on the gateway defined scenes,</LI>
153 * <LI>{@link #gateway} - Current status of the gateway status,</LI>
154 * <LI>{@link #firmware} - Information about the gateway firmware revision,</LI>
155 * <LI>{@link #lanConfig} - Information about the gateway configuration,</LI>
156 * <LI>{@link #wlanConfig} - Information about the gateway configuration.</LI>
159 public class BridgeParameters {
160 /** Information retrieved by {@link VeluxBridgeActuators#getProducts} */
161 public VeluxBridgeActuators actuators = new VeluxBridgeActuators();
163 /** Information retrieved by {@link org.openhab.binding.velux.internal.bridge.VeluxBridgeScenes#getScenes} */
164 VeluxBridgeScenes scenes = new VeluxBridgeScenes();
166 /** Information retrieved by {@link VeluxBridgeDeviceStatus#retrieve} */
167 VeluxBridgeDeviceStatus.Channel gateway = new VeluxBridgeDeviceStatus().getChannel();
169 /** Information retrieved by {@link VeluxBridgeGetFirmware#retrieve} */
170 VeluxBridgeGetFirmware.Channel firmware = new VeluxBridgeGetFirmware().getChannel();
172 /** Information retrieved by {@link VeluxBridgeLANConfig#retrieve} */
173 VeluxBridgeLANConfig.Channel lanConfig = new VeluxBridgeLANConfig().getChannel();
175 /** Information retrieved by {@link VeluxBridgeWLANConfig#retrieve} */
176 VeluxBridgeWLANConfig.Channel wlanConfig = new VeluxBridgeWLANConfig().getChannel();
182 * Provide the ThingType for a given Channel.
184 * Separated into this private method to deal with the deprecated method.
187 * @param channelUID for type {@link ChannelUID}.
188 * @return thingTypeUID of type {@link ThingTypeUID}.
190 ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
191 String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
192 if (segments.length > 1) {
193 return new ThingTypeUID(segments[0], segments[1]);
195 logger.warn("thingTypeUIDOf({}) failed.", channelUID);
196 return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
199 // Objects and Methods for interface VeluxBridgeInstance
202 * Information retrieved by ...
205 public VeluxBridgeConfiguration veluxBridgeConfiguration() {
206 return veluxBridgeConfiguration;
210 * Information retrieved by {@link VeluxBridgeActuators#getProducts}
213 public VeluxExistingProducts existingProducts() {
214 return bridgeParameters.actuators.getChannel().existingProducts;
218 * Information retrieved by {@link VeluxBridgeScenes#getScenes}
221 public VeluxExistingScenes existingScenes() {
222 return bridgeParameters.scenes.getChannel().existingScenes;
225 // Objects and Methods for interface VeluxBridgeProvider *****
228 public boolean bridgeCommunicate(BridgeCommunicationProtocol communication) {
229 logger.warn("bridgeCommunicate() called. Should never be called (as implemented by protocol-specific layers).");
234 public @Nullable BridgeAPI bridgeAPI() {
235 logger.warn("bridgeAPI() called. Should never be called (as implemented by protocol-specific layers).");
239 // Provisioning/Deprovisioning methods *****
242 public void initialize() {
243 logger.info("Initializing Velux Bridge '{}'.", getThing().getUID());
244 // The framework requires you to return from this method quickly.
245 // Setting the thing status to UNKNOWN temporarily and let the background task decide for the real status.
246 logger.trace("initialize() called.");
247 updateStatus(ThingStatus.UNKNOWN);
248 // Take care of unusual situations...
249 if (scheduler.isShutdown()) {
250 logger.warn("initialize(): scheduler is shutdown, aborting the initialization of this bridge.");
253 if (handleScheduler.isShutdown()) {
254 logger.trace("initialize(): handleScheduler is shutdown, aborting the initialization of this bridge.");
257 logger.trace("initialize(): preparing background initialization task.");
258 // Background initialization...
259 scheduler.execute(() -> {
260 logger.trace("initialize.scheduled(): Further work within scheduler.execute().");
261 logger.trace("initialize.scheduled(): Initializing bridge configuration parameters.");
262 this.veluxBridgeConfiguration = new VeluxBinding(getConfigAs(VeluxBridgeConfiguration.class)).checked();
263 logger.trace("initialize.scheduled(): work on updated bridge configuration parameters.");
264 bridgeParamsUpdated();
266 logger.debug("initialize.scheduled(): activated scheduler with {} milliseconds.",
267 this.veluxBridgeConfiguration.refreshMSecs);
268 refreshJob = scheduler.scheduleWithFixedDelay(() -> {
271 } catch (RuntimeException e) {
272 logger.warn("Exception occurred during activated refresh scheduler: {}.", e.getMessage());
274 }, this.veluxBridgeConfiguration.refreshMSecs, this.veluxBridgeConfiguration.refreshMSecs,
275 TimeUnit.MILLISECONDS);
276 logger.trace("initialize.scheduled(): done.");
278 logger.trace("initialize() done.");
282 * NOTE: It takes care about shutting down the connections before removal of this binding.
285 public synchronized void dispose() {
286 logger.info("Shutting down Velux Bridge '{}'.", getThing().getUID());
287 logger.trace("dispose(): shutting down continous refresh.");
288 // Just for avoidance of Potential null pointer access
289 ScheduledFuture<?> currentRefreshJob = refreshJob;
290 if (currentRefreshJob != null) {
291 logger.trace("dispose(): stopping the refresh.");
292 currentRefreshJob.cancel(true);
294 // Background execution of dispose
295 scheduler.execute(() -> {
296 logger.trace("dispose.scheduled(): (synchronous) logout initiated.");
297 thisBridge.bridgeLogout();
298 logger.trace("dispose.scheduled(): shutting down JSON bridge.");
299 myJsonBridge.shutdown();
300 logger.trace("dispose.scheduled(): shutting down SLIP bridge.");
301 mySlipBridge.shutdown();
303 logger.trace("dispose(): calling super class.");
305 logger.trace("dispose() done.");
309 * NOTE: It takes care by calling {@link #handleCommand} with the REFRESH command, that every used channel is
313 public void channelLinked(ChannelUID channelUID) {
314 if (thing.getStatus() == ThingStatus.ONLINE) {
315 channel2VeluxActuator.put(channelUID, new Thing2VeluxActuator(this, channelUID));
316 logger.trace("channelLinked({}) refreshing channel value with help of handleCommand as Thing is online.",
317 channelUID.getAsString());
318 handleCommand(channelUID, RefreshType.REFRESH);
320 logger.trace("channelLinked({}) doing nothing as Thing is not online.", channelUID.getAsString());
325 public void channelUnlinked(ChannelUID channelUID) {
326 logger.trace("channelUnlinked({}) called.", channelUID.getAsString());
329 // Reconfiguration methods
331 private void bridgeParamsUpdated() {
332 logger.debug("bridgeParamsUpdated() called.");
334 // Determine the appropriate bridge communication channel
335 boolean validBridgeFound = false;
336 if (myJsonBridge.supportedProtocols.contains(veluxBridgeConfiguration.protocol)) {
337 logger.debug("bridgeParamsUpdated(): choosing JSON as communication method.");
338 thisBridge = myJsonBridge;
339 validBridgeFound = true;
341 if (mySlipBridge.supportedProtocols.contains(veluxBridgeConfiguration.protocol)) {
342 logger.debug("bridgeParamsUpdated(): choosing SLIP as communication method.");
343 thisBridge = mySlipBridge;
344 validBridgeFound = true;
346 if (!validBridgeFound) {
347 logger.debug("No valid protocol selected, aborting this {} binding.", VeluxBindingConstants.BINDING_ID);
348 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
349 "@text/runtime.bridge-offline-no-valid-bridgeProtocol-selected");
350 logger.trace("bridgeParamsUpdated() done.");
354 logger.trace("bridgeParamsUpdated(): Trying to authenticate towards bridge.");
356 if (!thisBridge.bridgeLogin()) {
357 logger.warn("{} bridge login sequence failed; expecting bridge is OFFLINE.",
358 VeluxBindingConstants.BINDING_ID);
359 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
360 "@text/runtime.bridge-offline-login-sequence-failed");
361 logger.trace("bridgeParamsUpdated() done.");
365 logger.trace("bridgeParamsUpdated(): Querying bridge state.");
366 bridgeParameters.gateway = new VeluxBridgeDeviceStatus().retrieve(thisBridge);
368 logger.trace("bridgeParamsUpdated(): Fetching existing scenes.");
369 bridgeParameters.scenes.getScenes(thisBridge);
370 logger.info("Found {} scenes:\n\t{}", VeluxBindingConstants.BINDING_ID,
371 bridgeParameters.scenes.getChannel().existingScenes.toString(false, "\n\t"));
372 logger.trace("bridgeParamsUpdated(): Fetching existing actuators/products.");
373 bridgeParameters.actuators.getProducts(thisBridge);
374 logger.info("Found {} actuators:\n\t{}", VeluxBindingConstants.BINDING_ID,
375 bridgeParameters.actuators.getChannel().existingProducts.toString(false, "\n\t"));
377 if (thisBridge.bridgeAPI().setHouseStatusMonitor() != null) {
378 logger.trace("bridgeParamsUpdated(): Activating HouseStatusMonitor.");
379 if (new VeluxBridgeSetHouseStatusMonitor().modifyHSM(thisBridge, true)) {
380 logger.trace("bridgeParamsUpdated(): HSM activated.");
382 logger.warn("Activation of House-Status-Monitoring failed (might lead to a lack of status updates).");
386 veluxBridgeConfiguration.hasChanged = false;
387 logger.info("{} Bridge is online with {} scenes and {} actuators, now.", VeluxBindingConstants.BINDING_ID,
388 bridgeParameters.scenes.getChannel().existingScenes.getNoMembers(),
389 bridgeParameters.actuators.getChannel().existingProducts.getNoMembers());
390 logger.debug("Velux veluxBridge is online, now.");
391 updateStatus(ThingStatus.ONLINE);
392 logger.trace("bridgeParamsUpdated() successfully finished.");
395 // Continuous synchronization methods
397 private synchronized void refreshOpenHAB() {
398 logger.debug("refreshOpenHAB() initiated by {} starting cycle {}.", Thread.currentThread(), refreshCounter);
400 if (handleScheduler.isShutdown()) {
401 logger.trace("refreshOpenHAB(): handleScheduler is shutdown, recreating a scheduler pool.");
402 handleScheduler = ThreadPoolManager.getScheduledPool(VeluxBindingConstants.BINDING_ID);
405 logger.trace("refreshOpenHAB(): processing of possible HSM messages.");
406 // Background execution of bridge related I/O
407 handleScheduler.execute(() -> {
408 logger.trace("refreshOpenHAB.scheduled() initiated by {} will process HouseStatus.",
409 Thread.currentThread());
410 if (new VeluxBridgeGetHouseStatus().evaluateState(thisBridge)) {
411 logger.trace("refreshOpenHAB.scheduled(): successfully processed of GetHouseStatus()");
413 logger.trace("refreshOpenHAB.scheduled() initiated by {} has finished.", Thread.currentThread());
417 "refreshOpenHAB(): looping through all (both child things and bridge) linked channels for a need of refresh.");
418 for (ChannelUID channelUID : BridgeChannels.getAllLinkedChannelUIDs(this)) {
419 if (VeluxItemType.isToBeRefreshedNow(refreshCounter, thingTypeUIDOf(channelUID), channelUID.getId())) {
420 logger.trace("refreshOpenHAB(): refreshing channel {}.", channelUID);
421 handleCommand(channelUID, RefreshType.REFRESH);
424 logger.trace("refreshOpenHAB(): looping through properties for a need of refresh.");
425 for (VeluxItemType veluxItem : VeluxItemType.getPropertyEntriesByThing(getThing().getThingTypeUID())) {
426 if (VeluxItemType.isToBeRefreshedNow(refreshCounter, getThing().getThingTypeUID(),
427 veluxItem.getIdentifier())) {
428 logger.trace("refreshOpenHAB(): refreshing property {}.", veluxItem.getIdentifier());
429 handleCommand(new ChannelUID(getThing().getUID(), veluxItem.getIdentifier()), RefreshType.REFRESH);
432 logger.debug("refreshOpenHAB() initiated by {} finished cycle {}.", Thread.currentThread(), refreshCounter);
437 * In case of recognized changes in the real world, the method will
438 * update the corresponding states via openHAB event bus.
440 private void syncChannelsWithProducts() {
441 if (!bridgeParameters.actuators.getChannel().existingProducts.isDirty()) {
444 logger.trace("syncChannelsWithProducts(): there are some existing products with changed parameters.");
445 outer: for (VeluxProduct product : bridgeParameters.actuators.getChannel().existingProducts
446 .valuesOfModified()) {
447 logger.trace("syncChannelsWithProducts(): actuator {} has changed values.", product.getProductName());
448 ProductBridgeIndex productPbi = product.getBridgeProductIndex();
449 logger.trace("syncChannelsWithProducts(): bridge index is {}.", productPbi);
450 for (ChannelUID channelUID : BridgeChannels.getAllLinkedChannelUIDs(this)) {
451 if (!channel2VeluxActuator.containsKey(channelUID)) {
452 logger.trace("syncChannelsWithProducts(): channel {} not found.", channelUID);
455 if (!channel2VeluxActuator.get(channelUID).isKnown()) {
456 logger.trace("syncChannelsWithProducts(): channel {} not registered on bridge.", channelUID);
459 ProductBridgeIndex channelPbi = channel2VeluxActuator.get(channelUID).getProductBridgeIndex();
460 if (!channelPbi.equals(productPbi)) {
463 // Handle value inversion
464 boolean isInverted = channel2VeluxActuator.get(channelUID).isInverted();
465 logger.trace("syncChannelsWithProducts(): isInverted is {}.", isInverted);
466 VeluxProductPosition position = new VeluxProductPosition(product.getCurrentPosition());
467 if (position.isValid()) {
468 PercentType positionAsPercent = position.getPositionAsPercentType(isInverted);
469 logger.debug("syncChannelsWithProducts(): updating channel {} to position {}%.", channelUID,
471 updateState(channelUID, positionAsPercent);
473 logger.trace("syncChannelsWithProducts(): update of channel {} to position {} skipped.", channelUID,
479 logger.trace("syncChannelsWithProducts(): resetting dirty flag.");
480 bridgeParameters.actuators.getChannel().existingProducts.resetDirtyFlag();
481 logger.trace("syncChannelsWithProducts() done.");
484 // Processing of openHAB events
487 public void handleCommand(ChannelUID channelUID, Command command) {
488 logger.trace("handleCommand({}): command {} on channel {} will be scheduled.", Thread.currentThread(), command,
489 channelUID.getAsString());
490 logger.debug("handleCommand({},{}) called.", channelUID.getAsString(), command);
492 // Background execution of bridge related I/O
493 handleScheduler.execute(() -> {
494 logger.trace("handleCommand.scheduled({}) Start work with calling handleCommandScheduled().",
495 Thread.currentThread());
496 handleCommandScheduled(channelUID, command);
497 logger.trace("handleCommand.scheduled({}) done.", Thread.currentThread());
499 logger.trace("handleCommand({}) done.", Thread.currentThread());
503 * Normally called by {@link #handleCommand} to handle a command for a given channel with possibly long execution
506 * <B>NOTE:</B> This method is to be called as separated thread to ensure proper openHAB framework in parallel.
509 * @param channelUID the {@link ChannelUID} of the channel to which the command was sent,
510 * @param command the {@link Command}.
512 private synchronized void handleCommandScheduled(ChannelUID channelUID, Command command) {
513 logger.trace("handleCommandScheduled({}): command {} on channel {}.", Thread.currentThread(), command,
514 channelUID.getAsString());
515 logger.debug("handleCommandScheduled({},{}) called.", channelUID.getAsString(), command);
518 * ===========================================================
522 if (veluxBridgeConfiguration.isProtocolTraceEnabled) {
523 Threads.findDeadlocked();
526 String channelId = channelUID.getId();
527 State newState = null;
528 String itemName = channelUID.getAsString();
529 VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thingTypeUIDOf(channelUID), channelUID.getId());
531 if (itemType == VeluxItemType.UNKNOWN) {
532 logger.warn("{} Cannot determine type of Channel {}, ignoring command {}.",
533 VeluxBindingConstants.LOGGING_CONTACT, channelUID, command);
534 logger.trace("handleCommandScheduled() aborting.");
539 if (!channel2VeluxActuator.containsKey(channelUID)) {
540 channel2VeluxActuator.put(channelUID, new Thing2VeluxActuator(this, channelUID));
543 if (veluxBridgeConfiguration.hasChanged) {
544 logger.trace("handleCommandScheduled(): work on updated bridge configuration parameters.");
545 bridgeParamsUpdated();
548 syncChannelsWithProducts();
550 if (command instanceof RefreshType) {
552 * ===========================================================
555 logger.trace("handleCommandScheduled(): work on refresh.");
556 if (!itemType.isReadable()) {
557 logger.debug("handleCommandScheduled(): received a Refresh command for a non-readable item.");
559 logger.trace("handleCommandScheduled(): refreshing item {} (type {}).", itemName, itemType);
560 try { // expecting an IllegalArgumentException for unknown Velux device
564 newState = ChannelBridgeStatus.handleRefresh(channelUID, channelId, this);
566 case BRIDGE_DOWNTIME:
567 newState = new DecimalType(
568 thisBridge.lastCommunication() - thisBridge.lastSuccessfulCommunication());
570 case BRIDGE_FIRMWARE:
571 newState = ChannelBridgeFirmware.handleRefresh(channelUID, channelId, this);
573 case BRIDGE_IPADDRESS:
574 case BRIDGE_SUBNETMASK:
575 case BRIDGE_DEFAULTGW:
577 newState = ChannelBridgeLANconfig.handleRefresh(channelUID, channelId, this);
579 case BRIDGE_WLANSSID:
580 case BRIDGE_WLANPASSWORD:
581 newState = ChannelBridgeWLANconfig.handleRefresh(channelUID, channelId, this);
584 newState = ChannelBridgeScenes.handleRefresh(channelUID, channelId, this);
586 case BRIDGE_PRODUCTS:
587 newState = ChannelBridgeProducts.handleRefresh(channelUID, channelId, this);
590 newState = ChannelBridgeCheck.handleRefresh(channelUID, channelId, this);
593 case ACTUATOR_POSITION:
595 case ROLLERSHUTTER_POSITION:
596 case WINDOW_POSITION:
597 newState = ChannelActuatorPosition.handleRefresh(channelUID, channelId, this);
599 case ACTUATOR_LIMIT_MINIMUM:
600 case ROLLERSHUTTER_LIMIT_MINIMUM:
601 case WINDOW_LIMIT_MINIMUM:
602 newState = ChannelActuatorLimitation.handleRefresh(channelUID, "", this);
604 case ACTUATOR_LIMIT_MAXIMUM:
605 case ROLLERSHUTTER_LIMIT_MAXIMUM:
606 case WINDOW_LIMIT_MAXIMUM:
607 newState = ChannelActuatorLimitation.handleRefresh(channelUID, channelId, this);
610 // VirtualShutter channels
611 case VSHUTTER_POSITION:
612 newState = ChannelVShutterPosition.handleRefresh(channelUID, channelId, this);
617 "handleCommandScheduled(): cannot handle REFRESH on channel {} as it is of type {}.",
618 itemName, channelId);
620 } catch (IllegalArgumentException e) {
621 logger.warn("Cannot handle REFRESH on channel {} as it isn't (yet) known to the bridge.", itemName);
623 if (newState != null) {
624 if (itemType.isChannel()) {
625 logger.debug("handleCommandScheduled(): updating channel {} to {}.", channelUID, newState);
626 updateState(channelUID, newState);
628 if (itemType.isProperty()) {
629 logger.debug("handleCommandScheduled(): updating property {} to {}.", channelUID, newState);
630 ThingProperty.setValue(this, itemType.getIdentifier(), newState.toString());
634 logger.info("handleCommandScheduled({},{}): updating of item {} (type {}) failed.",
635 channelUID.getAsString(), command, itemName, itemType);
640 * ===========================================================
643 logger.trace("handleCommandScheduled(): working on item {} (type {}) with COMMAND {}.", itemName, itemType,
645 Command newValue = null;
646 try { // expecting an IllegalArgumentException for unknown Velux device
650 if (command == OnOffType.ON) {
651 logger.trace("handleCommandScheduled(): about to reload informations from veluxBridge.");
652 bridgeParamsUpdated();
654 logger.trace("handleCommandScheduled(): ignoring OFF command.");
657 case BRIDGE_DO_DETECTION:
658 ChannelBridgeDoDetection.handleCommand(channelUID, channelId, command, this);
663 ChannelSceneAction.handleCommand(channelUID, channelId, command, this);
665 case SCENE_SILENTMODE:
666 ChannelSceneSilentmode.handleCommand(channelUID, channelId, command, this);
670 case ACTUATOR_POSITION:
672 case ROLLERSHUTTER_POSITION:
673 case WINDOW_POSITION:
674 ChannelActuatorPosition.handleCommand(channelUID, channelId, command, this);
676 case ACTUATOR_LIMIT_MINIMUM:
677 case ROLLERSHUTTER_LIMIT_MINIMUM:
678 case WINDOW_LIMIT_MINIMUM:
679 ChannelActuatorLimitation.handleCommand(channelUID, channelId, command, this);
681 case ACTUATOR_LIMIT_MAXIMUM:
682 case ROLLERSHUTTER_LIMIT_MAXIMUM:
683 case WINDOW_LIMIT_MAXIMUM:
684 ChannelActuatorLimitation.handleCommand(channelUID, channelId, command, this);
687 // VirtualShutter channels
688 case VSHUTTER_POSITION:
689 newValue = ChannelVShutterPosition.handleCommand(channelUID, channelId, command, this);
693 logger.warn("{} Cannot handle command {} on channel {} (type {}).",
694 VeluxBindingConstants.LOGGING_CONTACT, command, itemName, itemType);
696 } catch (IllegalArgumentException e) {
697 logger.warn("Cannot handle command on channel {} as it isn't (yet) known to the bridge.", itemName);
699 if (newValue != null) {
700 postCommand(channelUID, newValue);
703 ThingProperty.setValue(this, VeluxBindingConstants.PROPERTY_BRIDGE_TIMESTAMP_ATTEMPT,
704 new java.util.Date(thisBridge.lastCommunication()).toString());
705 ThingProperty.setValue(this, VeluxBindingConstants.PROPERTY_BRIDGE_TIMESTAMP_SUCCESS,
706 new java.util.Date(thisBridge.lastSuccessfulCommunication()).toString());
707 logger.trace("handleCommandScheduled({}) done.", Thread.currentThread());