Skip to content

Commit

Permalink
[tradfri] Add support for Air Purifier (#14836)
Browse files Browse the repository at this point in the history
* [tradfri] Added Support for Air Purifier (#7)

Added Support for Tradfri Air Purifier:
* Added documentation disambiguation Tradfri vs Dirigera
* Added Tradfri Air Purifier - fanMode and fanSpeed
* Workable Tradfri Air Purifier basic implementation
* Tradfri: modified fanMode type and definition
* Tradfri Air Purifier: Added disableLed
* Tradfri Air Purifier: Added lockPhysicalButton
* Tradfri Air Purifier: Added airQuality data
* Tradfri Air Purifier: Added filterCheck data
* Tradfri Air Purifier: Added translations
* Tradfri Air Purifier: Added filter_uptime
* Tradfri Air Purifier: code optimization
* Documentation for supported Air Purifier channels
Fixes #14816

Signed-off-by: Vivien Boistuaud <github@boistuaud.net>
  • Loading branch information
vivienbo authored Jun 17, 2023
1 parent b505f7b commit 801b860
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 26 deletions.
96 changes: 72 additions & 24 deletions bundles/org.openhab.binding.tradfri/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# TRÅDFRI Binding

This binding integrates the IKEA TRÅDFRI gateway and devices connected to it (such as dimmable LED bulbs).
This binding only supports IKEA TRÅDFRI gateway v1.x, it is **not** compatible with DIRIGERA.

## Supported Things

Expand All @@ -22,22 +23,34 @@ These are:
| Non-Colour Controller | 0x0820 | 0820 |
| Non-Colour Scene Controller | 0x0830 | 0830 |
| Control Outlet | 0x0010 | 0010 |
| Window Covering Device | 0x0202 | 0202 |
| Window Covering Controller | 0x0202 | 0203 |

The following matrix lists the capabilities (channels) for each of the supported lighting device types:

| Thing type | Brightness | Color | Color Temperature | Battery Level | Battery Low | Power | Position |
|-------------|:----------:|:-----:|:-----------------:|:-------------:|:-----------:|:-----:|:---------|
| 0010 | | | | | | X | |
| 0100 | X | | | | | | |
| 0220 | X | | X | | | | |
| 0210 | | X | X | | | | |
| 0107 | | | | X | X | | |
| 0820 | | | | X | X | | |
| 0830 | | | | X | X | | |
| 0202 | | | | X | X | | X |
| 0203 | | | | X | X | | |
| Thing type | Brightness | Color | Color Temperature | Battery Level | Battery Low | Power |
|-------------|:----------:|:-----:|:-----------------:|:-------------:|:-----------:|:-----:|
| 0010 | | | | | | X |
| 0100 | X | | | | | |
| 0220 | X | | X | | | |
| 0210 | | X | X | | | |
| 0107 | | | | X | X | |
| 0820 | | | | X | X | |
| 0830 | | | | X | X | |

The following things are also supported even thought they are not standardized in Zigbee Light Link:

| Device type | Zigbee Device ID | Thing type |
|---------------------------------|------------------|------------|
| Window Covering Device | 0x0202 | 0202 |
| Window Covering Controller | 0x0203 | 0203 |
| Air Purifier | 0x0007 | 0007 |

The following matrix lists the capabilities (channels) for each of the supported non-lighting device types:

| Thing type | Battery Level | Battery Low | Position | Fan Mode | Lock Button | Disabled LED | Air Quality | Fan Speed | Filter Check | Filter Uptime |
|-------------|:-------------:|:-----------:|:--------:|:--------:|:-----------:|:------------:|:-----------:|:---------:|:------------:|:-------------:|
| 0202 | X | X | X | | | | | | | |
| 0203 | X | X | | | | | | | | |
| 0007 | | | | X | X | X | X | X | X | X |

## Thing Configuration

Expand Down Expand Up @@ -65,17 +78,33 @@ The control outlet supports the `power` channel.

A blind or curtain supports, beside `battery_level` and `battery_low` channels, a `positon` channel.

Refer to the matrix above.

| Channel Type ID | Item Type | Description |
|-------------------|---------------|--------------------------------------------------------|
| brightness | Dimmer | The brightness of the bulb in percent |
| color_temperature | Dimmer | color temperature from 0% = cold to 100% = warm |
| color | Color | full color |
| battery_level | Number | battery level (in %) |
| battery_low | Switch | battery low warning (<=10% = ON, >10% = OFF) |
| power | Switch | power switch |
| position | Rollershutter | position of the blinds from 0% = open to 100% = closed |
An air purifier supports:
* `fan_mode` and `fan_speed` channels, which allows for control of the fan and reading of the current speed.
* `disable_led` and `lock_button` channels, to respectively disable the LED's and lock the button on the physical device.
* `air_quality_pm25` and `air_quality_rating` channels, which reads the particulate matter 2.5μm and corresponding indication of air quality (similar to Tradfri app rating).
* `filter_check_next` and `filter_check_alarm` channels, which represents the remaining number of minutes until the next filter check and whether it is time to do the filter check now. Filter check must be completed through the TRÅDFRI app (or on the hardware buttons in case of replacement).
* a `filter_uptime` channel, which represents the current time since last filter change.

Refer to the matrixes above.

| Channel Type ID | Item Type | Description |
|---------------------|----------------------|----------------------------------------------------------------------------------------------|
| brightness | Dimmer | The brightness of the bulb in percent |
| color_temperature | Dimmer | Color temperature from 0% = cold to 100% = warm |
| color | Color | Full color |
| battery_level | Number | Battery level (in %) |
| battery_low | Switch | Battery low warning (<=10% = ON, >10% = OFF) |
| power | Switch | Power switch |
| position | Rollershutter | Position of the blinds from 0% = open to 100% = closed |
| fan_mode | Number | Fan mode, target speed of the fan (0 = off, 1 = auto, 10..50 = Level 1 to 5) |
| fan_speed | Number | Current Fan Speed between 0 (off) and 50 (maximum speed) |
| disable_led | Switch | Disables the LED's on the device |
| lock_button | Switch | Disables the physical button on the device (applications can still make changes) |
| air_quality_pm25 | Number:Dimensionless | Density of Particulate Matter of 2.5μm, measured in ppm |
| air_quality_rating | Number | Gives a rating about air quality (1 = Good, 2 = OK, 3 = Bad) similar to Tradfri app |
| filter_check_next | Number:Time | Time in minutes before the next filter check if > 0, if < 0 you are late checking the filter |
| filter_check_alarm | Switch | When ON, you must perform a filter check (i.e. `filter_check_next` is < 0) |
| filter_uptime | Number:Time | Time elapsed since the last filter change, in minutes |

## Full Example

Expand All @@ -89,6 +118,7 @@ Bridge tradfri:gateway:mygateway [ host="192.168.0.177", code="EHPW5rIJKyXFgjH3"
0830 myRemoteControl "My Remote Control" [ id=65545 ]
0010 myControlOutlet "My Control Outlet" [ id=65542 ]
0202 myBlinds "My Blinds" [ id=65547 ]
0007 myAirPurifier "My Air Purifier" [ id=65548 ]
}
```

Expand All @@ -103,6 +133,15 @@ Number RemoteControlBatteryLevel { channel="tradfri:0830:mygateway:myRemoteContr
Switch RemoteControlBatteryLow { channel="tradfri:0830:mygateway:myRemoteControl:battery_low" }
Switch ControlOutlet { channel="tradfri:0010:mygateway:myControlOutlet:power" }
Rollershutter BlindPosition { channel="tradfri:0202:mygateway:myBlinds:position" }
Number AirPurifierFanMode { channel="tradfri:0007:mygateway:myAirPurifier:fan_mode" }
Number AirPurifierFanSpeed { channel="tradfri:0007:mygateway:myAirPurifier:fan_speed" }
Switch AirPurifierDisableLED { channel="tradfri:0007:mygateway:myAirPurifier:disable_led" }
Switch AirPurifierLockPhysicalButton { channel="tradfri:0007:mygateway:myAirPurifier:lock_button" }
Number AirPurifierQualityPM25 { channel="tradfri:0007:mygateway:myAirPurifier:air_quality_pm25" }
Number AirPurifierQualityRating { channel="tradfri:0007:mygateway:myAirPurifier:air_quality_rating" }
Number AirPurifierFilterCheckTTL { channel="tradfri:0007:mygateway:myAirPurifier:filter_check_next" }
Switch AirPurifierFilterCheckAlarm { channel="tradfri:0007:mygateway:myAirPurifier:filter_check_alarm" }
Number AirPurifierFilterUptime { channel="tradfri:0007:mygateway:myAirPurifier:filter_uptime" }
```

demo.sitemap:
Expand All @@ -119,6 +158,15 @@ sitemap demo label="Main Menu"
Switch item=RemoteControlBatteryLow label="Battery Low Warning"
Switch item=ControlOutlet label="Power Switch"
Switch item=BlindPosition label="Blind Position [%d]"
Selection item=AirPurifierFanMode label="Fan Mode"
Text item=AirPurifierFanSpeed label="Current Fan Speed [%d]"
Switch item=AirPurifierDisableLED label="Disable LEDs"
Switch item=AirPurifierLockPhysicalButton label="Disable Physical Buttons"
Text item=AirPurifierQualityPM25 label="PM2.5"
Text item=AirPurifierQualityRating label="Air Quality"
Text item=AirPurifierFilterCheckTTL label="TTL before next filter check [%d min]"
Text item=AirPurifierFilterCheckAlarm label="Need to Check Filter [%s]"
Text item=AirPurifierFilterUptime label="Current filter uptime [%d min]"
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* @author Kai Kreuzer - Initial contribution
* @author Christoph Weitkamp - Added support for remote controller and motion sensor devices (read-only battery level)
* @author Manuel Raffel - Added support for blinds
* @author Vivien Boistuaud - Added support for air purifier
*/
@NonNullByDefault
public class TradfriBindingConstants {
Expand All @@ -45,6 +46,7 @@ public class TradfriBindingConstants {
public static final ThingTypeUID THING_TYPE_MOTION_SENSOR = new ThingTypeUID(BINDING_ID, "0107");
public static final ThingTypeUID THING_TYPE_BLINDS = new ThingTypeUID(BINDING_ID, "0202");
public static final ThingTypeUID THING_TYPE_OPEN_CLOSE_REMOTE_CONTROL = new ThingTypeUID(BINDING_ID, "0203");
public static final ThingTypeUID THING_TYPE_AIR_PURIFIER = new ThingTypeUID(BINDING_ID, "0007");

public static final Set<ThingTypeUID> SUPPORTED_LIGHT_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_DIMMABLE_LIGHT, THING_TYPE_COLOR_TEMP_LIGHT, THING_TYPE_COLOR_LIGHT)
Expand All @@ -54,6 +56,8 @@ public class TradfriBindingConstants {

public static final Set<ThingTypeUID> SUPPORTED_BLINDS_TYPES_UIDS = Collections.singleton(THING_TYPE_BLINDS);

public static final Set<ThingTypeUID> SUPPORTED_AIR_PURIFIER_TYPES_UIDS = Set.of(THING_TYPE_AIR_PURIFIER);

// List of all Gateway Configuration Properties
public static final String GATEWAY_CONFIG_HOST = "host";
public static final String GATEWAY_CONFIG_PORT = "port";
Expand All @@ -70,7 +74,8 @@ public class TradfriBindingConstants {

public static final Set<ThingTypeUID> SUPPORTED_DEVICE_TYPES_UIDS = Collections.unmodifiableSet(Stream
.of(SUPPORTED_LIGHT_TYPES_UIDS.stream(), SUPPORTED_CONTROLLER_TYPES_UIDS.stream(),
SUPPORTED_PLUG_TYPES_UIDS.stream(), SUPPORTED_BLINDS_TYPES_UIDS.stream())
SUPPORTED_PLUG_TYPES_UIDS.stream(), SUPPORTED_BLINDS_TYPES_UIDS.stream(),
SUPPORTED_AIR_PURIFIER_TYPES_UIDS.stream())
.reduce(Stream::concat).orElseGet(Stream::empty).collect(Collectors.toSet()));

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
Expand All @@ -85,9 +90,20 @@ public class TradfriBindingConstants {
public static final String CHANNEL_POSITION = "position";
public static final String CHANNEL_BATTERY_LEVEL = "battery_level";
public static final String CHANNEL_BATTERY_LOW = "battery_low";
public static final String CHANNEL_FAN_MODE = "fan_mode";
public static final String CHANNEL_FAN_SPEED = "fan_speed";
public static final String CHANNEL_DISABLE_LED = "disable_led";
public static final String CHANNEL_LOCK_BUTTON = "lock_button";
public static final String CHANNEL_AIR_QUALITY_PM25 = "air_quality_pm25";
public static final String CHANNEL_AIR_QUALITY_RATING = "air_quality_rating";
public static final String CHANNEL_FILTER_CHECK_NEXT = "filter_check_next";
public static final String CHANNEL_FILTER_CHECK_ALARM = "filter_check_alarm";
public static final String CHANNEL_FILTER_UPTIME = "filter_uptime";

// IPSO Objects
public static final String DEVICES = "15001";
public static final String AIR_PURIFIER = "15025";
public static final String AIR_QUALITY = "5907";
public static final String AUTH_PATH = "9063";
public static final String BLINDS = "15015";
public static final String CLIENT_IDENTITY_PROPOSED = "9090";
Expand All @@ -107,6 +123,9 @@ public class TradfriBindingConstants {
public static final String END_TIME_HR = "9048";
public static final String END_TIME_MN = "9049";
public static final String ERROR_TAG = "errorcode";
public static final String FAN_MODE = "5900";
public static final String FAN_SPEED = "5908";
public static final String FILTER_UPTIME = "5902";
public static final String FORCE_CHECK_OTA_UPDATE = "9032";
public static final String GATEWAY = "15011";
public static final String GATEWAY_DETAILS = "15012";
Expand All @@ -125,9 +144,11 @@ public class TradfriBindingConstants {
public static final String IKEA_MOODS = "9068";
public static final String INSTANCE_ID = "9003";
public static final String LAST_SEEN = "9020";
public static final String LED_DISABLE = "5906";
public static final String LIGHT = "3311";
public static final int LIGHTS_OFF_SMART_TASK = 2;
public static final String LIGHT_SETTING = "15013";
public static final String LOCK_PHYSICAL_BUTTON = "5905";
public static final int LOSS_OF_INTERNET_CONNECTIVITY = 5001;
public static final String MASTER_TOKEN_TAG = "9036";
public static final String MAX_MSR_VALUE = "5602";
Expand All @@ -137,6 +158,7 @@ public class TradfriBindingConstants {
public static final String NAME = "9001";
public static final int NEW_FIRMWARE_AVAILABLE = 1001;
public static final String NEW_PSK_BY_GW = "9091";
public static final String NEXT_FILTER_CHECK = "5910";
public static final String NOTIFICATION_EVENT = "9015";
public static final String NOTIFICATION_NVPAIR = "9017";
public static final String NOTIFICATION_STATE = "9014";
Expand Down Expand Up @@ -201,8 +223,27 @@ public class TradfriBindingConstants {
public static final String TYPE_SENSOR = "4";
public static final String TYPE_REPEATER = "6";
public static final String TYPE_BLINDS = "7";
public static final String TYPE_AIR_PURIFIER = "10";

public static final String DEVICE_VENDOR = "0";
public static final String DEVICE_MODEL = "1";
public static final String DEVICE_FIRMWARE = "3";
public static final String DEVICE_BATTERY_LEVEL = "9";

// List of Air Purifier Constants
public static final int FAN_MODE_OFF = 0;
public static final int FAN_MODE_AUTO = 1;
public static final int FAN_MODE_SPEED1 = 10;
public static final int FAN_MODE_SPEED2 = 20;
public static final int FAN_MODE_SPEED3 = 30;
public static final int FAN_MODE_SPEED4 = 40;
public static final int FAN_MODE_SPEED5 = 50;

public static final Set<Integer> AIR_PURIFIER_FANMODE = Set.of(FAN_MODE_OFF, FAN_MODE_AUTO, FAN_MODE_SPEED1,
FAN_MODE_SPEED2, FAN_MODE_SPEED3, FAN_MODE_SPEED4, FAN_MODE_SPEED5);

public static final int AIR_PURIFIER_AIR_QUALITY_OK = 36;
public static final int AIR_PURIFIER_AIR_QUALITY_BAD = 86;

public static final int AIR_PURIFIER_AIR_QUALITY_UNDEFINED = 65535;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.tradfri.internal.handler.TradfriAirPurifierHandler;
import org.openhab.binding.tradfri.internal.handler.TradfriBlindHandler;
import org.openhab.binding.tradfri.internal.handler.TradfriControllerHandler;
import org.openhab.binding.tradfri.internal.handler.TradfriGatewayHandler;
Expand Down Expand Up @@ -63,6 +64,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new TradfriLightHandler(thing);
} else if (SUPPORTED_PLUG_TYPES_UIDS.contains(thingTypeUID)) {
return new TradfriPlugHandler(thing);
} else if (THING_TYPE_AIR_PURIFIER.equals(thingTypeUID)) {
return new TradfriAirPurifierHandler(thing);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* @author Christoph Weitkamp - Added support for remote controller and motion sensor devices (read-only battery level)
* @author Andre Fuechsel - fixed the results removal
* @author Manuel Raffel - Added support for blinds
* @author Vivien Boistuaud - Added support for Air Purifiers
*/
@NonNullByDefault
public class TradfriDiscoveryService extends AbstractDiscoveryService
Expand Down Expand Up @@ -158,6 +159,8 @@ public void onUpdate(@Nullable String instanceId, @Nullable JsonObject data) {
} else if (TYPE_SENSOR.equals(type) && data.has(SENSOR)) {
// Motion sensor
thingId = new ThingUID(THING_TYPE_MOTION_SENSOR, bridge, Integer.toString(id));
} else if (TYPE_AIR_PURIFIER.equals(type) && data.has(AIR_PURIFIER)) {
thingId = new ThingUID(THING_TYPE_AIR_PURIFIER, bridge, Integer.toString(id));
}

if (thingId == null) {
Expand Down
Loading

0 comments on commit 801b860

Please sign in to comment.