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>
160 public class BridgeParameters {
161 /** Information retrieved by {@link VeluxBridgeActuators#getProducts} */
162 public VeluxBridgeActuators actuators = new VeluxBridgeActuators();
164 /** Information retrieved by {@link org.openhab.binding.velux.internal.bridge.VeluxBridgeScenes#getScenes} */
165 VeluxBridgeScenes scenes = new VeluxBridgeScenes();
167 /** Information retrieved by {@link VeluxBridgeDeviceStatus#retrieve} */
168 VeluxBridgeDeviceStatus.Channel gateway = new VeluxBridgeDeviceStatus().getChannel();
170 /** Information retrieved by {@link VeluxBridgeGetFirmware#retrieve} */
171 VeluxBridgeGetFirmware.Channel firmware = new VeluxBridgeGetFirmware().getChannel();
173 /** Information retrieved by {@link VeluxBridgeLANConfig#retrieve} */
174 VeluxBridgeLANConfig.Channel lanConfig = new VeluxBridgeLANConfig().getChannel();
176 /** Information retrieved by {@link VeluxBridgeWLANConfig#retrieve} */
177 VeluxBridgeWLANConfig.Channel wlanConfig = new VeluxBridgeWLANConfig().getChannel();
183 * Provide the ThingType for a given Channel.
185 * Separated into this private method to deal with the deprecated method.
188 * @param channelUID for type {@link ChannelUID}.
189 * @return thingTypeUID of type {@link ThingTypeUID}.
191 ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
192 String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
193 if (segments.length > 1) {
194 return new ThingTypeUID(segments[0], segments[1]);
196 logger.warn("thingTypeUIDOf({}) failed.", channelUID);
197 return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
200 // Objects and Methods for interface VeluxBridgeInstance
203 * Information retrieved by ...
206 public VeluxBridgeConfiguration veluxBridgeConfiguration() {
207 return veluxBridgeConfiguration;
211 * Information retrieved by {@link VeluxBridgeActuators#getProducts}
214 public VeluxExistingProducts existingProducts() {
215 return bridgeParameters.actuators.getChannel().existingProducts;
219 * Information retrieved by {@link VeluxBridgeScenes#getScenes}
222 public VeluxExistingScenes existingScenes() {
223 return bridgeParameters.scenes.getChannel().existingScenes;
226 // Objects and Methods for interface VeluxBridgeProvider *****
229 public boolean bridgeCommunicate(BridgeCommunicationProtocol communication) {
230 logger.warn("bridgeCommunicate() called. Should never be called (as implemented by protocol-specific layers).");
235 public @Nullable BridgeAPI bridgeAPI() {
236 logger.warn("bridgeAPI() called. Should never be called (as implemented by protocol-specific layers).");
240 // Provisioning/Deprovisioning methods *****
243 public void initialize() {
244 logger.info("Initializing Velux Bridge '{}'.", getThing().getUID());
245 // The framework requires you to return from this method quickly.
246 // Setting the thing status to UNKNOWN temporarily and let the background task decide for the real status.
247 logger.trace("initialize() called.");
248 updateStatus(ThingStatus.UNKNOWN);
249 // Take care of unusual situations...
250 if (scheduler.isShutdown()) {
251 logger.warn("initialize(): scheduler is shutdown, aborting the initialization of this bridge.");
254 if (handleScheduler.isShutdown()) {
255 logger.trace("initialize(): handleScheduler is shutdown, aborting the initialization of this bridge.");
258 logger.trace("initialize(): preparing background initialization task.");
259 // Background initialization...
260 scheduler.execute(() -> {
261 logger.trace("initialize.scheduled(): Further work within scheduler.execute().");
262 logger.trace("initialize.scheduled(): Initializing bridge configuration parameters.");
263 this.veluxBridgeConfiguration = new VeluxBinding(getConfigAs(VeluxBridgeConfiguration.class)).checked();
264 logger.trace("initialize.scheduled(): work on updated bridge configuration parameters.");
265 bridgeParamsUpdated();
267 logger.debug("initialize.scheduled(): activated scheduler with {} milliseconds.",
268 this.veluxBridgeConfiguration.refreshMSecs);
269 refreshJob = scheduler.scheduleWithFixedDelay(() -> {
272 } catch (RuntimeException e) {
273 logger.warn("Exception occurred during activated refresh scheduler: {}.", e.getMessage());
275 }, this.veluxBridgeConfiguration.refreshMSecs, this.veluxBridgeConfiguration.refreshMSecs,
276 TimeUnit.MILLISECONDS);
277 logger.trace("initialize.scheduled(): done.");
279 logger.trace("initialize() done.");
283 * NOTE: It takes care about shutting down the connections before removal of this binding.
286 public synchronized void dispose() {
287 logger.info("Shutting down Velux Bridge '{}'.", getThing().getUID());
288 logger.trace("dispose(): shutting down continous refresh.");
289 // Just for avoidance of Potential null pointer access
290 ScheduledFuture<?> currentRefreshJob = refreshJob;
291 if (currentRefreshJob != null) {
292 logger.trace("dispose(): stopping the refresh.");
293 currentRefreshJob.cancel(true);
295 // Background execution of dispose
296 scheduler.execute(() -> {
297 logger.trace("dispose.scheduled(): (synchronous) logout initiated.");
298 thisBridge.bridgeLogout();
299 logger.trace("dispose.scheduled(): shutting down JSON bridge.");
300 myJsonBridge.shutdown();
301 logger.trace("dispose.scheduled(): shutting down SLIP bridge.");
302 mySlipBridge.shutdown();
304 logger.trace("dispose(): calling super class.");
306 logger.trace("dispose() done.");
310 * NOTE: It takes care by calling {@link #handleCommand} with the REFRESH command, that every used channel is
314 public void channelLinked(ChannelUID channelUID) {
315 if (thing.getStatus() == ThingStatus.ONLINE) {
316 channel2VeluxActuator.put(channelUID, new Thing2VeluxActuator(this, channelUID));
317 logger.trace("channelLinked({}) refreshing channel value with help of handleCommand as Thing is online.",
318 channelUID.getAsString());
319 handleCommand(channelUID, RefreshType.REFRESH);
321 logger.trace("channelLinked({}) doing nothing as Thing is not online.", channelUID.getAsString());
326 public void channelUnlinked(ChannelUID channelUID) {
327 logger.trace("channelUnlinked({}) called.", channelUID.getAsString());
330 // Reconfiguration methods
332 private void bridgeParamsUpdated() {
333 logger.debug("bridgeParamsUpdated() called.");
335 // Determine the appropriate bridge communication channel
336 boolean validBridgeFound = false;
337 if (myJsonBridge.supportedProtocols.contains(veluxBridgeConfiguration.protocol)) {
338 logger.debug("bridgeParamsUpdated(): choosing JSON as communication method.");
339 thisBridge = myJsonBridge;
340 validBridgeFound = true;
342 if (mySlipBridge.supportedProtocols.contains(veluxBridgeConfiguration.protocol)) {
343 logger.debug("bridgeParamsUpdated(): choosing SLIP as communication method.");
344 thisBridge = mySlipBridge;
345 validBridgeFound = true;
347 if (!validBridgeFound) {
348 logger.debug("No valid protocol selected, aborting this {} binding.", VeluxBindingConstants.BINDING_ID);
349 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
350 "@text/runtime.bridge-offline-no-valid-bridgeProtocol-selected");
351 logger.trace("bridgeParamsUpdated() done.");
355 logger.trace("bridgeParamsUpdated(): Trying to authenticate towards bridge.");
357 if (!thisBridge.bridgeLogin()) {
358 logger.warn("{} bridge login sequence failed; expecting bridge is OFFLINE.",
359 VeluxBindingConstants.BINDING_ID);
360 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
361 "@text/runtime.bridge-offline-login-sequence-failed");
362 logger.trace("bridgeParamsUpdated() done.");
366 logger.trace("bridgeParamsUpdated(): Querying bridge state.");
367 bridgeParameters.gateway = new VeluxBridgeDeviceStatus().retrieve(thisBridge);
369 logger.trace("bridgeParamsUpdated(): Fetching existing scenes.");
370 bridgeParameters.scenes.getScenes(thisBridge);
371 logger.info("Found {} scenes:\n\t{}", VeluxBindingConstants.BINDING_ID,
372 bridgeParameters.scenes.getChannel().existingScenes.toString(false, "\n\t"));
373 logger.trace("bridgeParamsUpdated(): Fetching existing actuators/products.");
374 bridgeParameters.actuators.getProducts(thisBridge);
375 logger.info("Found {} actuators:\n\t{}", VeluxBindingConstants.BINDING_ID,
376 bridgeParameters.actuators.getChannel().existingProducts.toString(false, "\n\t"));
378 if (thisBridge.bridgeAPI().setHouseStatusMonitor() != null) {
379 logger.trace("bridgeParamsUpdated(): Activating HouseStatusMonitor.");
380 if (new VeluxBridgeSetHouseStatusMonitor().modifyHSM(thisBridge, true)) {
381 logger.trace("bridgeParamsUpdated(): HSM activated.");
383 logger.warn("Activation of House-Status-Monitoring failed (might lead to a lack of status updates).");
387 veluxBridgeConfiguration.hasChanged = false;
388 logger.info("{} Bridge is online with {} scenes and {} actuators, now.", VeluxBindingConstants.BINDING_ID,
389 bridgeParameters.scenes.getChannel().existingScenes.getNoMembers(),
390 bridgeParameters.actuators.getChannel().existingProducts.getNoMembers());
391 logger.debug("Velux veluxBridge is online, now.");
392 updateStatus(ThingStatus.ONLINE);
393 logger.trace("bridgeParamsUpdated() successfully finished.");
396 // Continuous synchronization methods
398 private synchronized void refreshOpenHAB() {
399 logger.debug("refreshOpenHAB() initiated by {} starting cycle {}.", Thread.currentThread(), refreshCounter);
401 if (handleScheduler.isShutdown()) {
402 logger.trace("refreshOpenHAB(): handleScheduler is shutdown, recreating a scheduler pool.");
403 handleScheduler = ThreadPoolManager.getScheduledPool(VeluxBindingConstants.BINDING_ID);
406 logger.trace("refreshOpenHAB(): processing of possible HSM messages.");
407 // Background execution of bridge related I/O
408 handleScheduler.execute(() -> {
409 logger.trace("refreshOpenHAB.scheduled() initiated by {} will process HouseStatus.",
410 Thread.currentThread());
411 if (new VeluxBridgeGetHouseStatus().evaluateState(thisBridge)) {
412 logger.trace("refreshOpenHAB.scheduled(): successfully processed of GetHouseStatus()");
414 logger.trace("refreshOpenHAB.scheduled() initiated by {} has finished.", Thread.currentThread());
418 "refreshOpenHAB(): looping through all (both child things and bridge) linked channels for a need of refresh.");
419 for (ChannelUID channelUID : BridgeChannels.getAllLinkedChannelUIDs(this)) {
420 if (VeluxItemType.isToBeRefreshedNow(refreshCounter, thingTypeUIDOf(channelUID), channelUID.getId())) {
421 logger.trace("refreshOpenHAB(): refreshing channel {}.", channelUID);
422 handleCommand(channelUID, RefreshType.REFRESH);
425 logger.trace("refreshOpenHAB(): looping through properties for a need of refresh.");
426 for (VeluxItemType veluxItem : VeluxItemType.getPropertyEntriesByThing(getThing().getThingTypeUID())) {
427 if (VeluxItemType.isToBeRefreshedNow(refreshCounter, getThing().getThingTypeUID(),
428 veluxItem.getIdentifier())) {
429 logger.trace("refreshOpenHAB(): refreshing property {}.", veluxItem.getIdentifier());
430 handleCommand(new ChannelUID(getThing().getUID(), veluxItem.getIdentifier()), RefreshType.REFRESH);
433 logger.debug("refreshOpenHAB() initiated by {} finished cycle {}.", Thread.currentThread(), refreshCounter);
438 * In case of recognized changes in the real world, the method will
439 * update the corresponding states via openHAB event bus.
441 private void syncChannelsWithProducts() {
442 if (!bridgeParameters.actuators.getChannel().existingProducts.isDirty()) {
445 logger.trace("syncChannelsWithProducts(): there are some existing products with changed parameters.");
446 outer: for (VeluxProduct product : bridgeParameters.actuators.getChannel().existingProducts
447 .valuesOfModified()) {
448 logger.trace("syncChannelsWithProducts(): actuator {} has changed values.", product.getProductName());
449 ProductBridgeIndex productPbi = product.getBridgeProductIndex();
450 logger.trace("syncChannelsWithProducts(): bridge index is {}.", productPbi);
451 for (ChannelUID channelUID : BridgeChannels.getAllLinkedChannelUIDs(this)) {
452 if (!channel2VeluxActuator.containsKey(channelUID)) {
453 logger.trace("syncChannelsWithProducts(): channel {} not found.", channelUID);
456 if (!channel2VeluxActuator.get(channelUID).isKnown()) {
457 logger.trace("syncChannelsWithProducts(): channel {} not registered on bridge.", channelUID);
460 ProductBridgeIndex channelPbi = channel2VeluxActuator.get(channelUID).getProductBridgeIndex();
461 if (!channelPbi.equals(productPbi)) {
464 // Handle value inversion
465 boolean isInverted = channel2VeluxActuator.get(channelUID).isInverted();
466 logger.trace("syncChannelsWithProducts(): isInverted is {}.", isInverted);
467 VeluxProductPosition position = new VeluxProductPosition(product.getCurrentPosition());
468 if (position.isValid()) {
469 PercentType positionAsPercent = position.getPositionAsPercentType(isInverted);
470 logger.debug("syncChannelsWithProducts(): updating channel {} to position {}%.", channelUID,
472 updateState(channelUID, positionAsPercent);
474 logger.trace("syncChannelsWithProducts(): update of channel {} to position {} skipped.", channelUID,
480 logger.trace("syncChannelsWithProducts(): resetting dirty flag.");
481 bridgeParameters.actuators.getChannel().existingProducts.resetDirtyFlag();
482 logger.trace("syncChannelsWithProducts() done.");
485 // Processing of openHAB events
488 public void handleCommand(ChannelUID channelUID, Command command) {
489 logger.trace("handleCommand({}): command {} on channel {} will be scheduled.", Thread.currentThread(), command,
490 channelUID.getAsString());
491 logger.debug("handleCommand({},{}) called.", channelUID.getAsString(), command);
493 // Background execution of bridge related I/O
494 handleScheduler.execute(() -> {
495 logger.trace("handleCommand.scheduled({}) Start work with calling handleCommandScheduled().",
496 Thread.currentThread());
497 handleCommandScheduled(channelUID, command);
498 logger.trace("handleCommand.scheduled({}) done.", Thread.currentThread());
500 logger.trace("handleCommand({}) done.", Thread.currentThread());
504 * Normally called by {@link #handleCommand} to handle a command for a given channel with possibly long execution
507 * <B>NOTE:</B> This method is to be called as separated thread to ensure proper openHAB framework in parallel.
510 * @param channelUID the {@link ChannelUID} of the channel to which the command was sent,
511 * @param command the {@link Command}.
513 private synchronized void handleCommandScheduled(ChannelUID channelUID, Command command) {
514 logger.trace("handleCommandScheduled({}): command {} on channel {}.", Thread.currentThread(), command,
515 channelUID.getAsString());
516 logger.debug("handleCommandScheduled({},{}) called.", channelUID.getAsString(), command);
519 * ===========================================================
523 if (veluxBridgeConfiguration.isProtocolTraceEnabled) {
524 Threads.findDeadlocked();
527 String channelId = channelUID.getId();
528 State newState = null;
529 String itemName = channelUID.getAsString();
530 VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thingTypeUIDOf(channelUID), channelUID.getId());
532 if (itemType == VeluxItemType.UNKNOWN) {
533 logger.warn("{} Cannot determine type of Channel {}, ignoring command {}.",
534 VeluxBindingConstants.LOGGING_CONTACT, channelUID, command);
535 logger.trace("handleCommandScheduled() aborting.");
540 if (!channel2VeluxActuator.containsKey(channelUID)) {
541 channel2VeluxActuator.put(channelUID, new Thing2VeluxActuator(this, channelUID));
544 if (veluxBridgeConfiguration.hasChanged) {
545 logger.trace("handleCommandScheduled(): work on updated bridge configuration parameters.");
546 bridgeParamsUpdated();
549 syncChannelsWithProducts();
551 if (command instanceof RefreshType) {
553 * ===========================================================
556 logger.trace("handleCommandScheduled(): work on refresh.");
557 if (!itemType.isReadable()) {
558 logger.debug("handleCommandScheduled(): received a Refresh command for a non-readable item.");
560 logger.trace("handleCommandScheduled(): refreshing item {} (type {}).", itemName, itemType);
561 try { // expecting an IllegalArgumentException for unknown Velux device
565 newState = ChannelBridgeStatus.handleRefresh(channelUID, channelId, this);
567 case BRIDGE_DOWNTIME:
568 newState = new DecimalType(
569 thisBridge.lastCommunication() - thisBridge.lastSuccessfulCommunication());
571 case BRIDGE_FIRMWARE:
572 newState = ChannelBridgeFirmware.handleRefresh(channelUID, channelId, this);
574 case BRIDGE_IPADDRESS:
575 case BRIDGE_SUBNETMASK:
576 case BRIDGE_DEFAULTGW:
578 newState = ChannelBridgeLANconfig.handleRefresh(channelUID, channelId, this);
580 case BRIDGE_WLANSSID:
581 case BRIDGE_WLANPASSWORD:
582 newState = ChannelBridgeWLANconfig.handleRefresh(channelUID, channelId, this);
585 newState = ChannelBridgeScenes.handleRefresh(channelUID, channelId, this);
587 case BRIDGE_PRODUCTS:
588 newState = ChannelBridgeProducts.handleRefresh(channelUID, channelId, this);
591 newState = ChannelBridgeCheck.handleRefresh(channelUID, channelId, this);
594 case ACTUATOR_POSITION:
596 case ROLLERSHUTTER_POSITION:
597 case WINDOW_POSITION:
598 newState = ChannelActuatorPosition.handleRefresh(channelUID, channelId, this);
600 case ACTUATOR_LIMIT_MINIMUM:
601 case ROLLERSHUTTER_LIMIT_MINIMUM:
602 case WINDOW_LIMIT_MINIMUM:
603 newState = ChannelActuatorLimitation.handleRefresh(channelUID, "", this);
605 case ACTUATOR_LIMIT_MAXIMUM:
606 case ROLLERSHUTTER_LIMIT_MAXIMUM:
607 case WINDOW_LIMIT_MAXIMUM:
608 newState = ChannelActuatorLimitation.handleRefresh(channelUID, channelId, this);
611 // VirtualShutter channels
612 case VSHUTTER_POSITION:
613 newState = ChannelVShutterPosition.handleRefresh(channelUID, channelId, this);
618 "handleCommandScheduled(): cannot handle REFRESH on channel {} as it is of type {}.",
619 itemName, channelId);
621 } catch (IllegalArgumentException e) {
622 logger.warn("Cannot handle REFRESH on channel {} as it isn't (yet) known to the bridge.", itemName);
624 if (newState != null) {
625 if (itemType.isChannel()) {
626 logger.debug("handleCommandScheduled(): updating channel {} to {}.", channelUID, newState);
627 updateState(channelUID, newState);
629 if (itemType.isProperty()) {
630 logger.debug("handleCommandScheduled(): updating property {} to {}.", channelUID, newState);
631 ThingProperty.setValue(this, itemType.getIdentifier(), newState.toString());
635 logger.info("handleCommandScheduled({},{}): updating of item {} (type {}) failed.",
636 channelUID.getAsString(), command, itemName, itemType);
641 * ===========================================================
644 logger.trace("handleCommandScheduled(): working on item {} (type {}) with COMMAND {}.", itemName, itemType,
646 Command newValue = null;
647 try { // expecting an IllegalArgumentException for unknown Velux device
651 if (command == OnOffType.ON) {
652 logger.trace("handleCommandScheduled(): about to reload informations from veluxBridge.");
653 bridgeParamsUpdated();
655 logger.trace("handleCommandScheduled(): ignoring OFF command.");
658 case BRIDGE_DO_DETECTION:
659 ChannelBridgeDoDetection.handleCommand(channelUID, channelId, command, this);
664 ChannelSceneAction.handleCommand(channelUID, channelId, command, this);
666 case SCENE_SILENTMODE:
667 ChannelSceneSilentmode.handleCommand(channelUID, channelId, command, this);
671 case ACTUATOR_POSITION:
673 case ROLLERSHUTTER_POSITION:
674 case WINDOW_POSITION:
675 ChannelActuatorPosition.handleCommand(channelUID, channelId, command, this);
677 case ACTUATOR_LIMIT_MINIMUM:
678 case ROLLERSHUTTER_LIMIT_MINIMUM:
679 case WINDOW_LIMIT_MINIMUM:
680 ChannelActuatorLimitation.handleCommand(channelUID, channelId, command, this);
682 case ACTUATOR_LIMIT_MAXIMUM:
683 case ROLLERSHUTTER_LIMIT_MAXIMUM:
684 case WINDOW_LIMIT_MAXIMUM:
685 ChannelActuatorLimitation.handleCommand(channelUID, channelId, command, this);
688 // VirtualShutter channels
689 case VSHUTTER_POSITION:
690 newValue = ChannelVShutterPosition.handleCommand(channelUID, channelId, command, this);
694 logger.warn("{} Cannot handle command {} on channel {} (type {}).",
695 VeluxBindingConstants.LOGGING_CONTACT, command, itemName, itemType);
697 } catch (IllegalArgumentException e) {
698 logger.warn("Cannot handle command on channel {} as it isn't (yet) known to the bridge.", itemName);
700 if (newValue != null) {
701 postCommand(channelUID, newValue);
704 ThingProperty.setValue(this, VeluxBindingConstants.PROPERTY_BRIDGE_TIMESTAMP_ATTEMPT,
705 new java.util.Date(thisBridge.lastCommunication()).toString());
706 ThingProperty.setValue(this, VeluxBindingConstants.PROPERTY_BRIDGE_TIMESTAMP_SUCCESS,
707 new java.util.Date(thisBridge.lastSuccessfulCommunication()).toString());
708 logger.trace("handleCommandScheduled({}) done.", Thread.currentThread());