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.mihome.internal;
15 import static org.openhab.binding.mihome.internal.XiaomiGatewayBindingConstants.*;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Hashtable;
22 import java.util.stream.Collectors;
23 import java.util.stream.Stream;
25 import org.openhab.binding.mihome.internal.discovery.XiaomiItemDiscoveryService;
26 import org.openhab.binding.mihome.internal.handler.XiaomiActorCurtainHandler;
27 import org.openhab.binding.mihome.internal.handler.XiaomiActorGatewayHandler;
28 import org.openhab.binding.mihome.internal.handler.XiaomiActorPlugHandler;
29 import org.openhab.binding.mihome.internal.handler.XiaomiAqaraActorSwitch1Handler;
30 import org.openhab.binding.mihome.internal.handler.XiaomiAqaraActorSwitch2Handler;
31 import org.openhab.binding.mihome.internal.handler.XiaomiAqaraSensorSwitch1Handler;
32 import org.openhab.binding.mihome.internal.handler.XiaomiAqaraSensorSwitch2Handler;
33 import org.openhab.binding.mihome.internal.handler.XiaomiBridgeHandler;
34 import org.openhab.binding.mihome.internal.handler.XiaomiDeviceBaseHandler;
35 import org.openhab.binding.mihome.internal.handler.XiaomiSensorCubeHandler;
36 import org.openhab.binding.mihome.internal.handler.XiaomiSensorGasHandler;
37 import org.openhab.binding.mihome.internal.handler.XiaomiSensorHtHandler;
38 import org.openhab.binding.mihome.internal.handler.XiaomiSensorLockHandler;
39 import org.openhab.binding.mihome.internal.handler.XiaomiSensorMagnetHandler;
40 import org.openhab.binding.mihome.internal.handler.XiaomiSensorMotionHandler;
41 import org.openhab.binding.mihome.internal.handler.XiaomiSensorSmokeHandler;
42 import org.openhab.binding.mihome.internal.handler.XiaomiSensorSwitchHandler;
43 import org.openhab.binding.mihome.internal.handler.XiaomiSensorVibrationHandler;
44 import org.openhab.binding.mihome.internal.handler.XiaomiSensorWaterHandler;
45 import org.openhab.core.config.core.Configuration;
46 import org.openhab.core.config.discovery.DiscoveryService;
47 import org.openhab.core.thing.Bridge;
48 import org.openhab.core.thing.Thing;
49 import org.openhab.core.thing.ThingTypeUID;
50 import org.openhab.core.thing.ThingUID;
51 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
52 import org.openhab.core.thing.binding.ThingHandler;
53 import org.openhab.core.thing.binding.ThingHandlerFactory;
54 import org.osgi.framework.ServiceRegistration;
55 import org.osgi.service.component.annotations.Component;
58 * The {@link XiaomiHandlerFactory} is responsible for creating things and thing
61 * @author Patrick Boos - Initial contribution
62 * @author Dieter Schmidt - Refactor, add devices
63 * @author Daniel Walters - Added Aqara Door/Window sensor and Aqara temperature, humidity and pressure sensor
64 * @author Kuba Wolanin - Added Water Leak sensor and Aqara motion sensor
66 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.mihome")
67 public class XiaomiHandlerFactory extends BaseThingHandlerFactory {
69 private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
70 .unmodifiableSet(Stream.concat(XiaomiBridgeHandler.SUPPORTED_THING_TYPES.stream(),
71 XiaomiDeviceBaseHandler.SUPPORTED_THING_TYPES.stream()).collect(Collectors.toSet()));
73 private Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
76 public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID,
78 if (XiaomiBridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
79 ThingUID newBridgeUID = getBridgeThingUID(thingTypeUID, thingUID, configuration);
80 return super.createThing(thingTypeUID, configuration, newBridgeUID, null);
81 } else if (XiaomiDeviceBaseHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
82 ThingUID newThingUID = getThingUID(thingTypeUID, thingUID, configuration, bridgeUID);
83 return super.createThing(thingTypeUID, configuration, newThingUID, bridgeUID);
85 throw new IllegalArgumentException(
86 "The thing type " + thingTypeUID + " is not supported by the mihome binding.");
90 public boolean supportsThingType(ThingTypeUID thingTypeUID) {
91 return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
94 private ThingUID getBridgeThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration) {
95 if (thingUID == null) {
96 String serialNumber = (String) configuration.get(SERIAL_NUMBER);
97 return new ThingUID(thingTypeUID, serialNumber);
102 private ThingUID getThingUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Configuration configuration,
103 ThingUID bridgeUID) {
104 if (thingUID == null) {
105 String itemId = (String) configuration.get(ITEM_ID);
106 return new ThingUID(thingTypeUID, itemId, bridgeUID.getId());
112 protected ThingHandler createHandler(Thing thing) {
113 ThingTypeUID thingTypeUID = thing.getThingTypeUID();
115 if (THING_TYPE_BRIDGE.equals(thingTypeUID)) {
116 XiaomiBridgeHandler handler = new XiaomiBridgeHandler((Bridge) thing);
117 registerItemDiscoveryService(handler);
119 } else if (THING_TYPE_GATEWAY.equals(thingTypeUID)) {
120 return new XiaomiActorGatewayHandler(thing);
121 } else if (THING_TYPE_SENSOR_HT.equals(thingTypeUID)) {
122 return new XiaomiSensorHtHandler(thing);
123 } else if (THING_TYPE_SENSOR_MOTION.equals(thingTypeUID)) {
124 return new XiaomiSensorMotionHandler(thing);
125 } else if (THING_TYPE_SENSOR_SWITCH.equals(thingTypeUID)) {
126 return new XiaomiSensorSwitchHandler(thing);
127 } else if (THING_TYPE_SENSOR_AQARA_SWITCH.equals(thingTypeUID)) {
128 return new XiaomiSensorSwitchHandler(thing);
129 } else if (THING_TYPE_SENSOR_MAGNET.equals(thingTypeUID)) {
130 return new XiaomiSensorMagnetHandler(thing);
131 } else if (THING_TYPE_SENSOR_CUBE.equals(thingTypeUID)) {
132 return new XiaomiSensorCubeHandler(thing);
133 } else if (THING_TYPE_SENSOR_SMOKE.equals(thingTypeUID)) {
134 return new XiaomiSensorSmokeHandler(thing);
135 } else if (THING_TYPE_SENSOR_GAS.equals(thingTypeUID)) {
136 return new XiaomiSensorGasHandler(thing);
137 } else if (THING_TYPE_SENSOR_WATER.equals(thingTypeUID)) {
138 return new XiaomiSensorWaterHandler(thing);
139 } else if (THING_TYPE_SENSOR_AQARA1.equals(thingTypeUID)) {
140 return new XiaomiAqaraSensorSwitch1Handler(thing);
141 } else if (THING_TYPE_SENSOR_AQARA2.equals(thingTypeUID)) {
142 return new XiaomiAqaraSensorSwitch2Handler(thing);
143 } else if (THING_TYPE_ACTOR_AQARA1.equals(thingTypeUID)) {
144 return new XiaomiAqaraActorSwitch1Handler(thing);
145 } else if (THING_TYPE_ACTOR_AQARA2.equals(thingTypeUID)) {
146 return new XiaomiAqaraActorSwitch2Handler(thing);
147 } else if (THING_TYPE_ACTOR_PLUG.equals(thingTypeUID)) {
148 return new XiaomiActorPlugHandler(thing);
149 } else if (THING_TYPE_ACTOR_AQARA_ZERO1.equals(thingTypeUID)) {
150 return new XiaomiAqaraActorSwitch1Handler(thing);
151 } else if (THING_TYPE_ACTOR_AQARA_ZERO2.equals(thingTypeUID)) {
152 return new XiaomiAqaraActorSwitch2Handler(thing);
153 } else if (THING_TYPE_ACTOR_CURTAIN.equals(thingTypeUID)) {
154 return new XiaomiActorCurtainHandler(thing);
155 } else if (THING_TYPE_SENSOR_AQARA_WEATHER_V1.equals(thingTypeUID)) {
156 return new XiaomiSensorHtHandler(thing);
157 } else if (THING_TYPE_SENSOR_AQARA_MAGNET.equals(thingTypeUID)) {
158 return new XiaomiSensorMagnetHandler(thing);
159 } else if (THING_TYPE_SENSOR_AQARA_MOTION.equals(thingTypeUID)) {
160 return new XiaomiSensorMotionHandler(thing);
161 } else if (THING_TYPE_SENSOR_AQARA_VIBRATION.equals(thingTypeUID)) {
162 return new XiaomiSensorVibrationHandler(thing);
163 } else if (THING_TYPE_SENSOR_AQARA_LOCK.equals(thingTypeUID)) {
164 return new XiaomiSensorLockHandler(thing);
165 } else if (THING_TYPE_BASIC.equals(thingTypeUID)) {
166 return new XiaomiDeviceBaseHandler(thing);
173 protected synchronized void removeHandler(ThingHandler thingHandler) {
174 if (thingHandler instanceof XiaomiBridgeHandler) {
175 ServiceRegistration<?> serviceReg = this.discoveryServiceRegs.remove(thingHandler.getThing().getUID());
176 if (serviceReg != null) {
177 // remove discovery service, if bridge handler is removed
178 XiaomiItemDiscoveryService service = (XiaomiItemDiscoveryService) bundleContext
179 .getService(serviceReg.getReference());
180 serviceReg.unregister();
181 if (service != null) {
182 service.onHandlerRemoved();
183 service.deactivate();
189 private synchronized void registerItemDiscoveryService(XiaomiBridgeHandler bridgeHandler) {
190 XiaomiItemDiscoveryService discoveryService = new XiaomiItemDiscoveryService(bridgeHandler);
191 this.discoveryServiceRegs.put(bridgeHandler.getThing().getUID(),
192 bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));