2 * Copyright (c) 2010-2023 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.miio.internal.handler;
15 import java.time.Instant;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.miio.internal.MiIoBindingConfiguration;
20 import org.openhab.binding.miio.internal.MiIoSendCommand;
21 import org.openhab.binding.miio.internal.basic.BasicChannelTypeProvider;
22 import org.openhab.binding.miio.internal.basic.MiIoBasicDevice;
23 import org.openhab.binding.miio.internal.basic.MiIoDatabaseWatchService;
24 import org.openhab.binding.miio.internal.cloud.CloudConnector;
25 import org.openhab.core.i18n.LocaleProvider;
26 import org.openhab.core.i18n.TranslationProvider;
27 import org.openhab.core.thing.Bridge;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.thing.type.ChannelTypeRegistry;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * The {@link MiIoLumiHandler} is responsible for handling commands, which are
37 * sent to one of the channels.
39 * @author Marcel Verpaalen - Initial contribution
42 public class MiIoLumiHandler extends MiIoBasicHandler {
44 private final Logger logger = LoggerFactory.getLogger(MiIoLumiHandler.class);
45 private @Nullable MiIoGatewayHandler bridgeHandler;
47 public MiIoLumiHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatchService,
48 CloudConnector cloudConnector, ChannelTypeRegistry channelTypeRegistry,
49 BasicChannelTypeProvider basicChannelTypeProvider, TranslationProvider i18nProvider,
50 LocaleProvider localeProvider) {
51 super(thing, miIoDatabaseWatchService, cloudConnector, channelTypeRegistry, basicChannelTypeProvider,
52 i18nProvider, localeProvider);
56 public void initialize() {
59 updateStatus(ThingStatus.UNKNOWN);
61 final MiIoBindingConfiguration config = this.configuration;
62 if (config != null && config.deviceId.isBlank()) {
63 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Missing required deviceId");
66 Bridge bridge = getBridge();
68 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
69 "No device bridge has been configured");
72 logger.debug("Bridge for {} {} = {} {} ({})", getThing().getUID(), getThing().getLabel(),
73 bridge.getBridgeUID(), bridge.getLabel(), bridge.getHandler());
79 MiIoGatewayHandler getBridgeHandler() {
80 if (bridgeHandler == null) {
81 Bridge bridge = getBridge();
83 final MiIoGatewayHandler bridgeHandler = (MiIoGatewayHandler) bridge.getHandler();
84 if (bridgeHandler != null) {
85 if (!bridgeHandler.childDevices.containsKey(getThing())) {
86 logger.warn(("Child device {} missing at bridge {}. We should not see this"),
87 getThing().getUID(), bridgeHandler.getThing().getUID());
88 bridgeHandler.childDevices.forEach((k, v) -> logger.debug("Devices in bridge: {} : {}", k, v));
90 this.bridgeHandler = bridgeHandler;
93 logger.debug("Bridge is defined, but bridge handler not found for {} {}.", getThing().getUID(),
94 getThing().getLabel());
97 logger.debug("Bridge is missing for {} {}", getThing().getUID(), getThing().getLabel());
99 return this.bridgeHandler;
103 public String getCloudServer() {
104 final MiIoGatewayHandler bh = this.bridgeHandler;
106 return bh.getCloudServer();
108 final MiIoBindingConfiguration config = this.configuration;
109 return config != null ? config.cloudServer : "";
113 // Override to inject the sender
115 protected int sendCommand(String command, String params, String cloudServer, String sender) {
116 final MiIoGatewayHandler bridge = getBridgeHandler();
117 if (bridge != null) {
118 logger.debug("Send via bridge {} {} (Cloudserver {})", command, params, cloudServer);
119 return bridge.sendCommand(command, params, cloudServer, getThing().getUID().getAsString());
121 logger.debug("Bridge handler is null. This is unexpected and prevents sending the update");
127 protected synchronized void updateData() {
128 logger.debug("Periodic update for '{}' ({})", getThing().getUID(), getThing().getThingTypeUID());
130 checkChannelStructure();
131 final MiIoBindingConfiguration config = this.configuration;
132 final MiIoBasicDevice midevice = miioDevice;
133 if (midevice != null && configuration != null && config != null) {
134 Bridge bridge = getBridge();
135 if (bridge == null || !bridge.getStatus().equals(ThingStatus.ONLINE)) {
136 logger.debug("Bridge {} offline, skipping regular refresh for {}", getThing().getBridgeUID(),
137 getThing().getUID());
138 refreshCustomProperties(midevice, true);
141 deviceVariables.put(TIMESTAMP, Instant.now().getEpochSecond());
142 logger.debug("Refresh properties for child device {}", getThing().getLabel());
143 refreshProperties(midevice, config.deviceId);
144 logger.debug("Refresh custom commands for child device {}", getThing().getLabel());
145 refreshCustomProperties(midevice, false);
147 logger.debug("Null value occured for device {}: {}", midevice, config);
149 } catch (Exception e) {
150 logger.debug("Error while performing periodic refresh for '{}': {}", getThing().getUID(), e.getMessage());
155 public void onMessageReceived(MiIoSendCommand response) {
156 super.onMessageReceived(response);
157 if (!response.isError() && (!response.getSender().isBlank()
158 && response.getSender().contentEquals(getThing().getUID().getAsString()))) {
159 updateStatus(ThingStatus.ONLINE);