Skip to content

Commit

Permalink
[deconz] Add support for ZHAThermostat (openhab#7828)
Browse files Browse the repository at this point in the history
* [deconz] Add support for ZHAThermostat

Adds support for Zigbee Thermostat based on Eurotronics Spirit
Closes openhab#6251

Signed-off-by: Lukas Agethen <[email protected]>
  • Loading branch information
LukasA83 authored and andrewfg committed Aug 31, 2020
1 parent 5ad0608 commit aaa3e3d
Show file tree
Hide file tree
Showing 17 changed files with 829 additions and 243 deletions.
11 changes: 9 additions & 2 deletions bundles/org.openhab.binding.deconz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ These sensors are supported:
| deCONZ Artificial Daylight Sensor | deCONZ specific: simulated sensor | `daylightsensor` |
| Carbon-Monoxide Sensor | ZHACarbonmonoxide | `carbonmonoxide` |

Additionally lights and window coverings (blinds) are supported:

Additionally lights, window coverings (blinds) and thermostats are supported:

| Device type | Resource Type | Thing type |
|--------------------------------------|----------------------------------------|----------------------|
Expand All @@ -36,6 +37,7 @@ Additionally lights and window coverings (blinds) are supported:
| Color Light (w/o temperature) | Color dimmable light | `colorlight` |
| Extended Color Light (w/temperature) | Extended color light | `extendedcolorlight` |
| Blind / Window Covering | Window covering device | `windowcovering` |
| Thermostat | ZHAThermostat | `thermostat` |

## Discovery

Expand Down Expand Up @@ -118,7 +120,7 @@ The sensor devices support some of the following channels:
| light_level | Number | R | Current light level | lightsensor |
| dark | Switch | R | Light level is below the darkness threshold | lightsensor, sometimes for presencesensor |
| daylight | Switch | R | Light level is above the daylight threshold | lightsensor |
| temperature | Number:Temperature | R | Current temperature in ˚C | temperaturesensor, some Xiaomi sensors |
| temperature | Number:Temperature | R | Current temperature in ˚C | temperaturesensor, some Xiaomi sensors,thermostat|
| humidity | Number:Dimensionless | R | Current humidity in % | humiditysensor |
| pressure | Number:Pressure | R | Current pressure in hPa | pressuresensor |
| open | Contact | R | Status of contacts: `OPEN`; `CLOSED` | openclosesensor |
Expand All @@ -133,6 +135,7 @@ The sensor devices support some of the following channels:
| battery_low | Switch | R | Battery level low: `ON`; `OFF` | any battery-powered sensor |
| carbonmonoxide | Switch | R | `ON` = carbon monoxide detected | carbonmonoxide |


**NOTE:** Beside other non mandatory channels, the `battery_level` and `battery_low` channels will be added to the Thing during runtime if the sensor is battery-powered.
The specification of your sensor depends on the deCONZ capabilities.
Have a detailed look for [supported devices](https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Supported-Devices).
Expand All @@ -146,6 +149,10 @@ Other devices support
| color | Color | R/W | Color of an multi-color light | `colorlight`, `extendedcolorlight` |
| color_temperature | Number | R/W | `0`->`100` represents cold -> warm | `colortemperaturelight`, `extendedcolorlight` |
| position | Rollershutter | R/W | Position of the blind | `windowcovering` |
| heatsetpoint | Number:Temperature | R/W | Target Temperature in °C | `thermostat` |
| valve | Number:Dimensionless | R | Valve position in % | `thermostat` |
| mode | String | R/W | Mode: "auto", "heat" and "off" | `thermostat` |
| offset | Number | R | Temperature offset for sensor | `thermostat` |

### Trigger Channels

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ public class BindingConstants {
public static final ThingTypeUID THING_TYPE_BATTERY_SENSOR = new ThingTypeUID(BINDING_ID, "batterysensor");
public static final ThingTypeUID THING_TYPE_CARBONMONOXIDE_SENSOR = new ThingTypeUID(BINDING_ID,
"carbonmonoxidesensor");
// Special sensor - Thermostat
public static final ThingTypeUID THING_TYPE_THERMOSTAT = new ThingTypeUID(BINDING_ID, "thermostat");

// lights
public static final ThingTypeUID THING_TYPE_ONOFF_LIGHT = new ThingTypeUID(BINDING_ID, "onofflight");
Expand Down Expand Up @@ -88,6 +90,10 @@ public class BindingConstants {
public static final String CHANNEL_BATTERY_LEVEL = "battery_level";
public static final String CHANNEL_BATTERY_LOW = "battery_low";
public static final String CHANNEL_CARBONMONOXIDE = "carbonmonoxide";
public static final String CHANNEL_HEATSETPOINT = "heatsetpoint";
public static final String CHANNEL_THERMOSTAT_MODE = "mode";
public static final String CHANNEL_TEMPERATURE_OFFSET = "offset";
public static final String CHANNEL_VALVE_POSITION = "valve";

public static final String CHANNEL_SWITCH = "switch";
public static final String CHANNEL_BRIGHTNESS = "brightness";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@
import org.eclipse.smarthome.io.net.http.WebSocketFactory;
import org.openhab.binding.deconz.internal.handler.DeconzBridgeHandler;
import org.openhab.binding.deconz.internal.handler.LightThingHandler;
import org.openhab.binding.deconz.internal.handler.SensorThermostatThingHandler;
import org.openhab.binding.deconz.internal.handler.SensorThingHandler;
import org.openhab.binding.deconz.internal.netutils.AsyncHttpClient;
import org.openhab.binding.deconz.internal.types.LightType;
import org.openhab.binding.deconz.internal.types.LightTypeDeserializer;
import org.openhab.binding.deconz.internal.types.ThermostatMode;
import org.openhab.binding.deconz.internal.types.ThermostatModeGsonTypeAdapter;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
Expand All @@ -50,7 +53,7 @@
public class DeconzHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
.of(DeconzBridgeHandler.SUPPORTED_THING_TYPES, LightThingHandler.SUPPORTED_THING_TYPE_UIDS,
SensorThingHandler.SUPPORTED_THING_TYPES)
SensorThingHandler.SUPPORTED_THING_TYPES, SensorThermostatThingHandler.SUPPORTED_THING_TYPES)
.flatMap(Set::stream).collect(Collectors.toSet());

private final Gson gson;
Expand All @@ -65,6 +68,7 @@ public DeconzHandlerFactory(final @Reference WebSocketFactory webSocketFactory,

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LightType.class, new LightTypeDeserializer());
gsonBuilder.registerTypeAdapter(ThermostatMode.class, new ThermostatModeGsonTypeAdapter());
gson = gsonBuilder.create();
}

Expand All @@ -84,6 +88,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new LightThingHandler(thing, gson);
} else if (SensorThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
return new SensorThingHandler(thing, gson);
} else if (SensorThermostatThingHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
return new SensorThermostatThingHandler(thing, gson);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.openhab.binding.deconz.internal.dto.SensorMessage;
import org.openhab.binding.deconz.internal.handler.DeconzBridgeHandler;
import org.openhab.binding.deconz.internal.handler.LightThingHandler;
import org.openhab.binding.deconz.internal.handler.SensorThermostatThingHandler;
import org.openhab.binding.deconz.internal.handler.SensorThingHandler;
import org.openhab.binding.deconz.internal.types.LightType;
import org.slf4j.Logger;
Expand All @@ -49,7 +50,8 @@
@NonNullByDefault
public class ThingDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
.of(LightThingHandler.SUPPORTED_THING_TYPE_UIDS, SensorThingHandler.SUPPORTED_THING_TYPES)
.of(LightThingHandler.SUPPORTED_THING_TYPE_UIDS, SensorThingHandler.SUPPORTED_THING_TYPES,
SensorThermostatThingHandler.SUPPORTED_THING_TYPES)
.flatMap(Set::stream).collect(Collectors.toSet());
private final Logger logger = LoggerFactory.getLogger(ThingDiscoveryService.class);

Expand Down Expand Up @@ -193,6 +195,8 @@ private void addSensor(String sensorID, SensorMessage sensor) {
thingTypeUID = THING_TYPE_VIBRATION_SENSOR; // ZHAVibration
} else if (sensor.type.contains("ZHABattery")) {
thingTypeUID = THING_TYPE_BATTERY_SENSOR; // ZHABattery
} else if (sensor.type.contains("ZHAThermostat")) {
thingTypeUID = THING_TYPE_THERMOSTAT; // ZHAThermostat
} else {
logger.debug("Unknown type {}", sensor.type);
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.deconz.internal.types.ThermostatMode;

/**
* The {@link SensorConfig} is send by the the Rest API.
Expand All @@ -23,11 +24,15 @@
* https://dresden-elektronik.github.io/deconz-rest-doc/sensors/.
*
* @author David Graeff - Initial contribution
* @author Lukas Agethen - Add Thermostat parameters
*/
@NonNullByDefault
public class SensorConfig {
public boolean on = true;
public boolean reachable = true;
public @Nullable Integer battery;
public @Nullable Float temperature;
public @Nullable Integer heatsetpoint;
public @Nullable ThermostatMode mode;
public @Nullable Integer offset;
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public class SensorState {
public @Nullable Integer buttonevent;
/** Switches may provide this value. */
public @Nullable Integer gesture;
/** Thermostat may provide this value. */
public @Nullable Integer valve;
/** deCONZ sends a last update string with every event. */
public @Nullable String lastupdated;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.deconz.internal.dto;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.deconz.internal.types.ThermostatMode;

/**
* The {@link ThermostatConfig} is send to the Rest API to configure Thermostat.
*
* @author Lukas Agethen - Initial contribution
*/
@NonNullByDefault
public class ThermostatConfig {
public @Nullable Integer heatsetpoint;
public @Nullable ThermostatMode mode;
public @Nullable Integer offset;
}
Loading

0 comments on commit aaa3e3d

Please sign in to comment.