mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 07:02:02 +01:00
[electroluxair] Remove binding (#17336)
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
parent
1d490981ea
commit
67170f6f61
@ -95,7 +95,6 @@
|
||||
/bundles/org.openhab.binding.ecovacs/ @maniac103
|
||||
/bundles/org.openhab.binding.ecowatt/ @lolodomo
|
||||
/bundles/org.openhab.binding.ekey/ @hmerk
|
||||
/bundles/org.openhab.binding.electroluxair/ @jannegpriv
|
||||
/bundles/org.openhab.binding.elerotransmitterstick/ @vbier
|
||||
/bundles/org.openhab.binding.elroconnects/ @mherwege
|
||||
/bundles/org.openhab.binding.emotiva/ @espenaf
|
||||
|
@ -464,11 +464,6 @@
|
||||
<artifactId>org.openhab.binding.ekey</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.electroluxair</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.binding.elerotransmitterstick</artifactId>
|
||||
|
@ -1,13 +0,0 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
@ -1,92 +0,0 @@
|
||||
# ElectroluxAir Binding
|
||||
|
||||
This is an openHAB binding for the Pure A9 Air Purifier, by Electrolux.
|
||||
|
||||
![Electrolux Pure A9](doc/electrolux_pure_a9.png)
|
||||
|
||||
## Supported Things
|
||||
|
||||
This binding supports the following thing types:
|
||||
|
||||
- api: Bridge - Implements the API that is used to communicate with the Air Purifier
|
||||
|
||||
- electroluxpurea9: The Pure A9 Air Purifier
|
||||
|
||||
## Discovery
|
||||
|
||||
After the configuration of the Bridge, your Electrolux Pure A9 device will be automatically discovered and placed as a thing in the inbox.
|
||||
|
||||
### Configuration Options
|
||||
|
||||
Only the bridge require manual configuration. The Electrolux Pure A9 thing can be added by hand, or you can let the discovery mechanism automatically find it.
|
||||
|
||||
#### Bridge
|
||||
|
||||
| Parameter | Description | Type | Default | Required |
|
||||
|-----------|--------------------------------------------------------------|--------|----------|----------|
|
||||
| username | The username used to connect to the Electrolux app | String | NA | yes |
|
||||
| password | The password used to connect to the Electrolux app | String | NA | yes |
|
||||
| refresh | Specifies the refresh interval in second | Number | 600 | yes |
|
||||
|
||||
#### Electrolux Pure A9
|
||||
|
||||
| Parameter | Description | Type | Default | Required |
|
||||
|-----------|-------------------------------------------------------------------------|--------|----------|----------|
|
||||
| deviceId | Product ID of your Electrolux Pure A9 found in Electrolux app | Number | NA | yes |
|
||||
|
||||
## Channels
|
||||
|
||||
### Electrolux Pure A9
|
||||
|
||||
The following channels are supported:
|
||||
|
||||
| Channel Type ID | Item Type | Description |
|
||||
|-----------------------------|-----------------------|--------------------------------------------------------------------------------|
|
||||
| temperature | Number:Temperature | This channel reports the current temperature. |
|
||||
| humidity | Number:Dimensionless | This channel reports the current humidity in percentage. |
|
||||
| tvoc | Number:Density | This channel reports the total Volatile Organic Compounds in microgram/m3. |
|
||||
| pm1 | Number:Dimensionless | This channel reports the Particulate Matter 1 in ppb. |
|
||||
| pm2_5 | Number:Dimensionless | This channel reports the Particulate Matter 2.5 in ppb. |
|
||||
| pm10 | Number:Dimensionless | This channel reports the Particulate Matter 10 in ppb. |
|
||||
| co2 | Number:Dimensionless | This channel reports the CO2 level in ppm. |
|
||||
| fanSpeed | Number | This channel sets and reports the current fan speed (1-9). |
|
||||
| filterLife | Number:Dimensionless | This channel reports the remaining filter life in %. |
|
||||
| ionizer | Switch | This channel sets and reports the status of the Ionizer function (On/Off). |
|
||||
| doorOpen | Contact | This channel reports the status of door (Opened/Closed). |
|
||||
| workMode | String | This channel sets and reports the current work mode (Auto, Manual, PowerOff.) |
|
||||
| uiLIght | Switch | This channel sets and reports the status of the UI Light function (On/Off). |
|
||||
| safetyLock | Switch | This channel sets and reports the status of the Safety Lock function (On/Off).|
|
||||
|
||||
## Full Example
|
||||
|
||||
### Things-file
|
||||
|
||||
```java
|
||||
// Bridge configuration
|
||||
Bridge electroluxair:api:myAPI "Electrolux Delta API" [username="user@password.com", password="12345", refresh="300"] {
|
||||
|
||||
Thing electroluxpurea9 myElectroluxPureA9 "Electrolux Pure A9" [ deviceId="123456789" ]
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Items-file
|
||||
|
||||
```java
|
||||
// CO2
|
||||
Number ElectroluxAirCO2 "Electrolux Air CO2 [%d ppm]" {channel="electroluxair:electroluxpurea9:myAPI:MyElectroluxPureA9:co2"}
|
||||
// Temperature
|
||||
Number:Temperature ElectroluxAirTemperature "Electrolux Air Temperature" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:temperature"}
|
||||
// Door status
|
||||
Contact ElectroluxAirDoor "Electrolux Air Door Status" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:doorOpen"}
|
||||
// Work mode
|
||||
String ElectroluxAirWorkModeSetting "ElectroluxAir Work Mode Setting" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:workMode"}
|
||||
// Fan speed
|
||||
Number ElectroluxAirFanSpeed "Electrolux Air Fan Speed Setting" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:fanSpeed"}
|
||||
// UI Light
|
||||
Switch ElectroluxAirUILight "Electrolux Air UI Light Setting" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:uiLight"}
|
||||
// Ionizer
|
||||
Switch ElectroluxAirIonizer "Electrolux Air Ionizer Setting" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:ionizer"}
|
||||
// Safety Lock
|
||||
Switch ElectroluxAirSafetyLock "Electrolux Air Safety Lock Setting" {channel="electroluxair:electroluxpurea9:myAPI:myElectroluxPureA9:safetyLock"}
|
||||
```
|
Binary file not shown.
Before Width: | Height: | Size: 213 KiB |
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>4.2.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.electroluxair</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: ElectroluxAir Binding</name>
|
||||
|
||||
</project>
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.electroluxair-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-electroluxair" description="ElectroluxAir Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.electroluxair/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "electroluxair";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_ELECTROLUX_PURE_A9 = new ThingTypeUID(BINDING_ID, "electroluxpurea9");
|
||||
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "api");
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_STATUS = "status";
|
||||
public static final String CHANNEL_TEMPERATURE = "temperature";
|
||||
public static final String CHANNEL_HUMIDITY = "humidity";
|
||||
public static final String CHANNEL_TVOC = "tvoc";
|
||||
public static final String CHANNEL_PM1 = "pm1";
|
||||
public static final String CHANNEL_PM25 = "pm2_5";
|
||||
public static final String CHANNEL_PM10 = "pm10";
|
||||
public static final String CHANNEL_CO2 = "co2";
|
||||
public static final String CHANNEL_FILTER_LIFE = "filterLife";
|
||||
public static final String CHANNEL_DOOR_OPEN = "doorOpen";
|
||||
public static final String CHANNEL_FAN_SPEED = "fanSpeed";
|
||||
public static final String CHANNEL_WORK_MODE = "workMode";
|
||||
public static final String CHANNEL_IONIZER = "ionizer";
|
||||
public static final String CHANNEL_UI_LIGHT = "uiLight";
|
||||
public static final String CHANNEL_SAFETY_LOCK = "safetyLock";
|
||||
|
||||
// List of all Properties ids
|
||||
public static final String PROPERTY_BRAND = "brand";
|
||||
public static final String PROPERTY_COLOUR = "colour";
|
||||
public static final String PROPERTY_MODEL = "model";
|
||||
public static final String PROPERTY_DEVICE = "device";
|
||||
public static final String PROPERTY_FW_VERSION = "fwVersion";
|
||||
public static final String PROPERTY_SERIAL_NUMBER = "serialNumber";
|
||||
public static final String PROPERTY_WORKMODE = "workmode";
|
||||
|
||||
// List of all Commands
|
||||
public static final String COMMAND_WORKMODE_POWEROFF = "PowerOff";
|
||||
public static final String COMMAND_WORKMODE_AUTO = "Auto";
|
||||
public static final String COMMAND_WORKMODE_MANUAL = "Manual";
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_BRIDGE,
|
||||
THING_TYPE_ELECTROLUX_PURE_A9);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirBridgeConfiguration} class contains fields mapping bridge configuration parameters.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirBridgeConfiguration {
|
||||
public @Nullable String username;
|
||||
public @Nullable String password;
|
||||
public int refresh;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirConfiguration {
|
||||
public static final String DEVICE_ID_LABEL = "deviceId";
|
||||
|
||||
private String deviceId = "";
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* {@link ElectroluxAirException} is used when there is exception communicating with Electrolux Delta API.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 2543564118231301159L;
|
||||
|
||||
public ElectroluxAirException(Exception source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
public ElectroluxAirException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getMessage() {
|
||||
Throwable throwable = getCause();
|
||||
if (throwable != null) {
|
||||
String localMessage = throwable.getMessage();
|
||||
if (localMessage != null) {
|
||||
return localMessage;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
@ -1,329 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.api;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirBridgeConfiguration;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirException;
|
||||
import org.openhab.binding.electroluxair.internal.dto.ElectroluxPureA9DTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxDeltaAPI} class defines the Elextrolux Delta API
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxDeltaAPI {
|
||||
private static final String CLIENT_ID = "ElxOneApp";
|
||||
private static final String CLIENT_SECRET = "8UKrsKD7jH9zvTV7rz5HeCLkit67Mmj68FvRVTlYygwJYy4dW6KF2cVLPKeWzUQUd6KJMtTifFf4NkDnjI7ZLdfnwcPtTSNtYvbP7OzEkmQD9IjhMOf5e1zeAQYtt2yN";
|
||||
private static final String X_API_KEY = "2AMqwEV5MqVhTKrRCyYfVF8gmKrd2rAmp7cUsfky";
|
||||
|
||||
private static final String BASE_URL = "https://api.ocp.electrolux.one";
|
||||
private static final String TOKEN_URL = BASE_URL + "/one-account-authorization/api/v1/token";
|
||||
private static final String AUTHENTICATION_URL = BASE_URL + "/one-account-authentication/api/v1/authenticate";
|
||||
private static final String API_URL = BASE_URL + "/appliance/api/v2";
|
||||
private static final String APPLIANCES_URL = API_URL + "/appliances";
|
||||
|
||||
private static final String JSON_CONTENT_TYPE = "application/json";
|
||||
private static final int MAX_RETRIES = 3;
|
||||
private static final int REQUEST_TIMEOUT_MS = 10_000;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ElectroluxDeltaAPI.class);
|
||||
private final Gson gson;
|
||||
private final HttpClient httpClient;
|
||||
private final ElectroluxAirBridgeConfiguration configuration;
|
||||
private String authToken = "";
|
||||
private Instant tokenExpiry = Instant.MIN;
|
||||
|
||||
public ElectroluxDeltaAPI(ElectroluxAirBridgeConfiguration configuration, Gson gson, HttpClient httpClient) {
|
||||
this.gson = gson;
|
||||
this.configuration = configuration;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
public boolean refresh(Map<String, ElectroluxPureA9DTO> electroluxAirThings) {
|
||||
try {
|
||||
if (Instant.now().isAfter(this.tokenExpiry)) {
|
||||
// Login again since token is expired
|
||||
login();
|
||||
}
|
||||
// Get all appliances
|
||||
String json = getAppliances();
|
||||
ElectroluxPureA9DTO[] dtos = gson.fromJson(json, ElectroluxPureA9DTO[].class);
|
||||
if (dtos != null) {
|
||||
for (ElectroluxPureA9DTO dto : dtos) {
|
||||
String applianceId = dto.getApplianceId();
|
||||
// Get appliance info
|
||||
String jsonApplianceInfo = getAppliancesInfo(applianceId);
|
||||
ElectroluxPureA9DTO.ApplianceInfo applianceInfo = gson.fromJson(jsonApplianceInfo,
|
||||
ElectroluxPureA9DTO.ApplianceInfo.class);
|
||||
if (applianceInfo != null) {
|
||||
if ("AIR_PURIFIER".equals(applianceInfo.getDeviceType())) {
|
||||
dto.setApplianceInfo(applianceInfo);
|
||||
electroluxAirThings.put(dto.getProperties().getReported().getDeviceId(), dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} catch (JsonSyntaxException | ElectroluxAirException e) {
|
||||
logger.warn("Failed to refresh! {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean workModePowerOff(String applianceId) {
|
||||
String commandJSON = "{ \"WorkMode\": \"PowerOff\" }";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode powerOff failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean workModeAuto(String applianceId) {
|
||||
String commandJSON = "{ \"WorkMode\": \"Auto\" }";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode auto failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean workModeManual(String applianceId) {
|
||||
String commandJSON = "{ \"WorkMode\": \"Manual\" }";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode manual failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setFanSpeedLevel(String applianceId, int fanSpeedLevel) {
|
||||
if (fanSpeedLevel < 1 && fanSpeedLevel > 10) {
|
||||
return false;
|
||||
} else {
|
||||
String commandJSON = "{ \"Fanspeed\": " + fanSpeedLevel + "}";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode manual failed {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setIonizer(String applianceId, String ionizerStatus) {
|
||||
String commandJSON = "{ \"Ionizer\": " + ionizerStatus + "}";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode manual failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setUILight(String applianceId, String uiLightStatus) {
|
||||
String commandJSON = "{ \"UILight\": " + uiLightStatus + "}";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode manual failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setSafetyLock(String applianceId, String safetyLockStatus) {
|
||||
String commandJSON = "{ \"SafetyLock\": " + safetyLockStatus + "}";
|
||||
try {
|
||||
return sendCommand(commandJSON, applianceId);
|
||||
} catch (ElectroluxAirException e) {
|
||||
logger.warn("Work mode manual failed {}", e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Request createRequest(String uri, HttpMethod httpMethod) {
|
||||
Request request = httpClient.newRequest(uri).method(httpMethod);
|
||||
request.timeout(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
|
||||
request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
|
||||
|
||||
logger.debug("HTTP POST Request {}.", request.toString());
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
private void login() throws ElectroluxAirException {
|
||||
try {
|
||||
String json = "{\"clientId\": \"" + CLIENT_ID + "\", \"clientSecret\": \"" + CLIENT_SECRET
|
||||
+ "\", \"grantType\": \"client_credentials\"}";
|
||||
|
||||
// Fetch ClientToken
|
||||
Request request = createRequest(TOKEN_URL, HttpMethod.POST);
|
||||
request.content(new StringContentProvider(json), JSON_CONTENT_TYPE);
|
||||
|
||||
logger.debug("HTTP POST Request {}.", request.toString());
|
||||
|
||||
ContentResponse httpResponse = request.send();
|
||||
if (httpResponse.getStatus() != HttpStatus.OK_200) {
|
||||
throw new ElectroluxAirException("Failed to get token 1" + httpResponse.getContentAsString());
|
||||
}
|
||||
json = httpResponse.getContentAsString();
|
||||
logger.trace("Token 1: {}", json);
|
||||
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
|
||||
String clientToken = jsonObject.get("accessToken").getAsString();
|
||||
|
||||
// Login using access token 1
|
||||
json = "{ \"username\": \"" + configuration.username + "\", \"password\": \"" + configuration.password
|
||||
+ "\" }";
|
||||
request = createRequest(AUTHENTICATION_URL, HttpMethod.POST);
|
||||
request.header(HttpHeader.AUTHORIZATION, "Bearer " + clientToken);
|
||||
request.header("x-api-key", X_API_KEY);
|
||||
|
||||
request.content(new StringContentProvider(json), JSON_CONTENT_TYPE);
|
||||
|
||||
logger.debug("HTTP POST Request {}.", request.toString());
|
||||
|
||||
httpResponse = request.send();
|
||||
if (httpResponse.getStatus() != HttpStatus.OK_200) {
|
||||
throw new ElectroluxAirException("Failed to login " + httpResponse.getContentAsString());
|
||||
}
|
||||
json = httpResponse.getContentAsString();
|
||||
logger.trace("Token 2: {}", json);
|
||||
jsonObject = JsonParser.parseString(json).getAsJsonObject();
|
||||
String idToken = jsonObject.get("idToken").getAsString();
|
||||
String countryCode = jsonObject.get("countryCode").getAsString();
|
||||
String credentials = "{\"clientId\": \"" + CLIENT_ID + "\", \"idToken\": \"" + idToken
|
||||
+ "\", \"grantType\": \"urn:ietf:params:oauth:grant-type:token-exchange\"}";
|
||||
|
||||
// Fetch access token 2
|
||||
request = createRequest(TOKEN_URL, HttpMethod.POST);
|
||||
request.header("Origin-Country-Code", countryCode);
|
||||
request.content(new StringContentProvider(credentials), JSON_CONTENT_TYPE);
|
||||
|
||||
logger.debug("HTTP POST Request {}.", request.toString());
|
||||
|
||||
httpResponse = request.send();
|
||||
if (httpResponse.getStatus() != HttpStatus.OK_200) {
|
||||
throw new ElectroluxAirException("Failed to get token 1" + httpResponse.getContentAsString());
|
||||
}
|
||||
|
||||
// Fetch AccessToken
|
||||
json = httpResponse.getContentAsString();
|
||||
logger.trace("AccessToken: {}", json);
|
||||
jsonObject = JsonParser.parseString(json).getAsJsonObject();
|
||||
this.authToken = jsonObject.get("accessToken").getAsString();
|
||||
int expiresIn = jsonObject.get("expiresIn").getAsInt();
|
||||
this.tokenExpiry = Instant.now().plusSeconds(expiresIn);
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
throw new ElectroluxAirException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getFromApi(String uri) throws ElectroluxAirException, InterruptedException {
|
||||
try {
|
||||
for (int i = 0; i < MAX_RETRIES; i++) {
|
||||
try {
|
||||
Request request = createRequest(uri, HttpMethod.GET);
|
||||
request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
|
||||
request.header("x-api-key", X_API_KEY);
|
||||
|
||||
ContentResponse response = request.send();
|
||||
String content = response.getContentAsString();
|
||||
logger.trace("API response: {}", content);
|
||||
|
||||
if (response.getStatus() != HttpStatus.OK_200) {
|
||||
logger.debug("getFromApi failed, HTTP status: {}", response.getStatus());
|
||||
login();
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
} catch (TimeoutException e) {
|
||||
logger.debug("TimeoutException error in get: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
throw new ElectroluxAirException("Failed to fetch from API!");
|
||||
} catch (JsonSyntaxException | ElectroluxAirException | ExecutionException e) {
|
||||
throw new ElectroluxAirException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAppliances() throws ElectroluxAirException {
|
||||
try {
|
||||
return getFromApi(APPLIANCES_URL);
|
||||
} catch (ElectroluxAirException | InterruptedException e) {
|
||||
throw new ElectroluxAirException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAppliancesInfo(String applianceId) throws ElectroluxAirException {
|
||||
try {
|
||||
return getFromApi(APPLIANCES_URL + "/" + applianceId + "/info");
|
||||
} catch (ElectroluxAirException | InterruptedException e) {
|
||||
throw new ElectroluxAirException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendCommand(String commandJSON, String applianceId) throws ElectroluxAirException {
|
||||
try {
|
||||
for (int i = 0; i < MAX_RETRIES; i++) {
|
||||
try {
|
||||
Request request = createRequest(APPLIANCES_URL + "/" + applianceId + "/command", HttpMethod.PUT);
|
||||
request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
|
||||
request.header("x-api-key", X_API_KEY);
|
||||
request.content(new StringContentProvider(commandJSON), JSON_CONTENT_TYPE);
|
||||
|
||||
ContentResponse response = request.send();
|
||||
String content = response.getContentAsString();
|
||||
logger.trace("API response: {}", content);
|
||||
|
||||
if (response.getStatus() != HttpStatus.OK_200) {
|
||||
logger.debug("sendCommand failed, HTTP status: {}", response.getStatus());
|
||||
login();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (TimeoutException | InterruptedException e) {
|
||||
logger.warn("TimeoutException error in get");
|
||||
}
|
||||
}
|
||||
} catch (JsonSyntaxException | ElectroluxAirException | ExecutionException e) {
|
||||
throw new ElectroluxAirException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirConfiguration;
|
||||
import org.openhab.binding.electroluxair.internal.handler.ElectroluxAirBridgeHandler;
|
||||
import org.openhab.core.config.discovery.AbstractThingHandlerDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.ServiceScope;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirDiscoveryService} searches for available
|
||||
* Electrolux Pure A9 discoverable through Electrolux Delta API.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@Component(scope = ServiceScope.PROTOTYPE, service = ElectroluxAirDiscoveryService.class)
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirDiscoveryService extends AbstractThingHandlerDiscoveryService<ElectroluxAirBridgeHandler> {
|
||||
private static final int SEARCH_TIME = 2;
|
||||
|
||||
public ElectroluxAirDiscoveryService() {
|
||||
super(ElectroluxAirBridgeHandler.class, SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
ThingUID bridgeUID = thingHandler.getThing().getUID();
|
||||
thingHandler.getElectroluxAirThings().entrySet().stream().forEach(thing -> {
|
||||
thingDiscovered(DiscoveryResultBuilder
|
||||
.create(new ThingUID(THING_TYPE_ELECTROLUX_PURE_A9, bridgeUID, thing.getKey()))
|
||||
.withLabel("Electrolux Pure A9").withBridge(bridgeUID)
|
||||
.withProperty(ElectroluxAirConfiguration.DEVICE_ID_LABEL, thing.getKey())
|
||||
.withRepresentationProperty(ElectroluxAirConfiguration.DEVICE_ID_LABEL).build());
|
||||
});
|
||||
|
||||
stopScan();
|
||||
}
|
||||
}
|
@ -1,392 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.dto;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxPureA9DTO} class defines the DTO for the Electrolux Pure A9.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxPureA9DTO {
|
||||
private String applianceId = "";
|
||||
private ApplianceInfo applianceInfo = new ApplianceInfo();
|
||||
private ApplianceData applianceData = new ApplianceData();
|
||||
private Properties properties = new Properties();
|
||||
private String status = "";
|
||||
private String connectionState = "";
|
||||
|
||||
public String getApplianceId() {
|
||||
return applianceId;
|
||||
}
|
||||
|
||||
public ApplianceInfo getApplianceInfo() {
|
||||
return applianceInfo;
|
||||
}
|
||||
|
||||
public void setApplianceInfo(ApplianceInfo applianceInfo) {
|
||||
this.applianceInfo = applianceInfo;
|
||||
}
|
||||
|
||||
public ApplianceData getApplianceData() {
|
||||
return applianceData;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getConnectionState() {
|
||||
return connectionState;
|
||||
}
|
||||
|
||||
public class ApplianceInfo {
|
||||
private String manufacturingDateCode = "";
|
||||
private String serialNumber = "";
|
||||
private String pnc = "";
|
||||
private String brand = "";
|
||||
private String market = "";
|
||||
private String productArea = "";
|
||||
private String deviceType = "";
|
||||
private String project = "";
|
||||
private String model = "";
|
||||
private String variant = "";
|
||||
private String colour = "";
|
||||
|
||||
public String getManufacturingDateCode() {
|
||||
return manufacturingDateCode;
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public String getPnc() {
|
||||
return pnc;
|
||||
}
|
||||
|
||||
public String getBrand() {
|
||||
return brand;
|
||||
}
|
||||
|
||||
public String getMarket() {
|
||||
return market;
|
||||
}
|
||||
|
||||
public String getProductArea() {
|
||||
return productArea;
|
||||
}
|
||||
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public String getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getVariant() {
|
||||
return variant;
|
||||
}
|
||||
|
||||
public String getColour() {
|
||||
return colour;
|
||||
}
|
||||
}
|
||||
|
||||
class ApplianceData {
|
||||
private String applianceName = "";
|
||||
private String created = "";
|
||||
private String modelName = "";
|
||||
|
||||
public String getApplianceName() {
|
||||
return applianceName;
|
||||
}
|
||||
|
||||
public String getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public String getModelName() {
|
||||
return modelName;
|
||||
}
|
||||
}
|
||||
|
||||
public class Properties {
|
||||
private Desired desired = new Desired();
|
||||
private Reported reported = new Reported();
|
||||
private Object metadata = new Object();
|
||||
|
||||
public Desired getDesired() {
|
||||
return desired;
|
||||
}
|
||||
|
||||
public Reported getReported() {
|
||||
return reported;
|
||||
}
|
||||
|
||||
public Object getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
}
|
||||
|
||||
class Desired {
|
||||
@SerializedName("TimeZoneStandardName")
|
||||
private String timeZoneStandardName = "";
|
||||
@SerializedName("FrmVer_NIU")
|
||||
private String frmVerNIU = "";
|
||||
@SerializedName("LocationReq")
|
||||
private boolean locationReq;
|
||||
private Map<String, Object> metadata = new HashMap<>();
|
||||
private int version;
|
||||
|
||||
public String getTimeZoneStandardName() {
|
||||
return timeZoneStandardName;
|
||||
}
|
||||
|
||||
public String getFrmVerNIU() {
|
||||
return frmVerNIU;
|
||||
}
|
||||
|
||||
public boolean isLocationReq() {
|
||||
return locationReq;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
public class Reported {
|
||||
@SerializedName("FrmVer_NIU")
|
||||
private String frmVerNIU = "";
|
||||
@SerializedName("Workmode")
|
||||
private String workmode = "";
|
||||
@SerializedName("FilterRFID")
|
||||
private String filterRFID = "";
|
||||
@SerializedName("FilterLife")
|
||||
private int filterLife = 0;
|
||||
@SerializedName("Fanspeed")
|
||||
private int fanSpeed = 0;
|
||||
@SerializedName("UILight")
|
||||
private boolean uiLight = false;
|
||||
@SerializedName("SafetyLock")
|
||||
private boolean safetyLock = false;
|
||||
@SerializedName("Ionizer")
|
||||
private boolean ionizer = false;
|
||||
@SerializedName("Sleep")
|
||||
private boolean sleep = false;
|
||||
@SerializedName("Scheduler")
|
||||
private boolean scheduler = false;
|
||||
@SerializedName("FilterType")
|
||||
private int filterType = 0;
|
||||
@SerializedName("DspIcoPM2_5")
|
||||
private boolean dspIcoPM25 = false;
|
||||
@SerializedName("DspIcoPM1")
|
||||
private boolean dspIcoPM1 = false;
|
||||
@SerializedName("DspIcoPM10")
|
||||
private boolean dspIcoPM10 = false;
|
||||
@SerializedName("DspIcoTVOC")
|
||||
private boolean dspIcoTVOC = false;
|
||||
@SerializedName("ErrPM2_5")
|
||||
private boolean errPM25 = false;
|
||||
@SerializedName("ErrTVOC")
|
||||
private boolean errTVOC = false;
|
||||
@SerializedName("ErrTempHumidity")
|
||||
private boolean errTempHumidity = false;
|
||||
@SerializedName("ErrFanMtr")
|
||||
private boolean errFanMtr = false;
|
||||
@SerializedName("ErrCommSensorDisplayBrd")
|
||||
private boolean errCommSensorDisplayBrd = false;
|
||||
@SerializedName("DoorOpen")
|
||||
private boolean doorOpen = false;
|
||||
@SerializedName("ErrRFID")
|
||||
private boolean errRFID = false;
|
||||
@SerializedName("SignalStrength")
|
||||
private String signalStrength = "";
|
||||
private Map<String, Object> metadata = new HashMap<>();
|
||||
private int version = 0;
|
||||
private String deviceId = "";
|
||||
@SerializedName("CO2")
|
||||
private int co2 = 0;
|
||||
@SerializedName("TVOC")
|
||||
private int tvoc = 0;
|
||||
@SerializedName("Temp")
|
||||
private int temp = 0;
|
||||
@SerializedName("Humidity")
|
||||
private int humidity = 0;
|
||||
@SerializedName("RSSI")
|
||||
private int rssi = 0;
|
||||
@SerializedName("PM1")
|
||||
private int pm1 = 0;
|
||||
@SerializedName("PM2_5")
|
||||
private int pm25 = 0;
|
||||
@SerializedName("PM10")
|
||||
private int pm10 = 0;
|
||||
|
||||
public String getFrmVerNIU() {
|
||||
return frmVerNIU;
|
||||
}
|
||||
|
||||
public String getWorkmode() {
|
||||
return workmode;
|
||||
}
|
||||
|
||||
public String getFilterRFID() {
|
||||
return filterRFID;
|
||||
}
|
||||
|
||||
public int getFilterLife() {
|
||||
return filterLife;
|
||||
}
|
||||
|
||||
public int getFanspeed() {
|
||||
return fanSpeed;
|
||||
}
|
||||
|
||||
public boolean isUILight() {
|
||||
return uiLight;
|
||||
}
|
||||
|
||||
public boolean isSafetyLock() {
|
||||
return safetyLock;
|
||||
}
|
||||
|
||||
public boolean isIonizer() {
|
||||
return ionizer;
|
||||
}
|
||||
|
||||
public boolean isSleep() {
|
||||
return sleep;
|
||||
}
|
||||
|
||||
public boolean isScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
public int getFilterType() {
|
||||
return filterType;
|
||||
}
|
||||
|
||||
public boolean isDspIcoPM25() {
|
||||
return dspIcoPM25;
|
||||
}
|
||||
|
||||
public boolean isDspIcoPM1() {
|
||||
return dspIcoPM1;
|
||||
}
|
||||
|
||||
public boolean isDspIcoPM10() {
|
||||
return dspIcoPM10;
|
||||
}
|
||||
|
||||
public boolean isDspIcoTVOC() {
|
||||
return dspIcoTVOC;
|
||||
}
|
||||
|
||||
public boolean isErrPM25() {
|
||||
return errPM25;
|
||||
}
|
||||
|
||||
public boolean isErrTVOC() {
|
||||
return errTVOC;
|
||||
}
|
||||
|
||||
public boolean isErrTempHumidity() {
|
||||
return errTempHumidity;
|
||||
}
|
||||
|
||||
public boolean isErrFanMtr() {
|
||||
return errFanMtr;
|
||||
}
|
||||
|
||||
public boolean isErrCommSensorDisplayBrd() {
|
||||
return errCommSensorDisplayBrd;
|
||||
}
|
||||
|
||||
public boolean isDoorOpen() {
|
||||
return doorOpen;
|
||||
}
|
||||
|
||||
public boolean isErrRFID() {
|
||||
return errRFID;
|
||||
}
|
||||
|
||||
public String getSignalStrength() {
|
||||
return signalStrength;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public int getCO2() {
|
||||
return co2;
|
||||
}
|
||||
|
||||
public int getTVOC() {
|
||||
return tvoc;
|
||||
}
|
||||
|
||||
public int getTemp() {
|
||||
return temp;
|
||||
}
|
||||
|
||||
public int getHumidity() {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
public int getRSSI() {
|
||||
return rssi;
|
||||
}
|
||||
|
||||
public int getPM1() {
|
||||
return pm1;
|
||||
}
|
||||
|
||||
public int getPM25() {
|
||||
return pm25;
|
||||
}
|
||||
|
||||
public int getPM10() {
|
||||
return pm10;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.handler;
|
||||
|
||||
import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirBridgeConfiguration;
|
||||
import org.openhab.binding.electroluxair.internal.api.ElectroluxDeltaAPI;
|
||||
import org.openhab.binding.electroluxair.internal.discovery.ElectroluxAirDiscoveryService;
|
||||
import org.openhab.binding.electroluxair.internal.dto.ElectroluxPureA9DTO;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirBridgeHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirBridgeHandler extends BaseBridgeHandler {
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BRIDGE);
|
||||
|
||||
private int refreshTimeInSeconds = 300;
|
||||
|
||||
private final Gson gson;
|
||||
private final HttpClient httpClient;
|
||||
private final Map<String, ElectroluxPureA9DTO> electroluxAirThings = new ConcurrentHashMap<>();
|
||||
|
||||
private @Nullable ElectroluxDeltaAPI api;
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
public ElectroluxAirBridgeHandler(Bridge bridge, HttpClient httpClient, Gson gson) {
|
||||
super(bridge);
|
||||
this.httpClient = httpClient;
|
||||
this.gson = gson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
ElectroluxAirBridgeConfiguration config = getConfigAs(ElectroluxAirBridgeConfiguration.class);
|
||||
|
||||
ElectroluxDeltaAPI electroluxDeltaAPI = new ElectroluxDeltaAPI(config, gson, httpClient);
|
||||
refreshTimeInSeconds = config.refresh;
|
||||
|
||||
if (config.username == null || config.password == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Configuration of username, password is mandatory");
|
||||
} else if (refreshTimeInSeconds < 0) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Refresh time cannot be negative!");
|
||||
} else {
|
||||
try {
|
||||
this.api = electroluxDeltaAPI;
|
||||
scheduler.execute(() -> {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
startAutomaticRefresh();
|
||||
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, ElectroluxPureA9DTO> getElectroluxAirThings() {
|
||||
return electroluxAirThings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Set.of(ElectroluxAirDiscoveryService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stopAutomaticRefresh();
|
||||
}
|
||||
|
||||
public @Nullable ElectroluxDeltaAPI getElectroluxDeltaAPI() {
|
||||
return api;
|
||||
}
|
||||
|
||||
private boolean refreshAndUpdateStatus() {
|
||||
if (api != null) {
|
||||
if (api.refresh(electroluxAirThings)) {
|
||||
getThing().getThings().stream().forEach(thing -> {
|
||||
ElectroluxAirHandler handler = (ElectroluxAirHandler) thing.getHandler();
|
||||
if (handler != null) {
|
||||
handler.update();
|
||||
}
|
||||
});
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
return true;
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void startAutomaticRefresh() {
|
||||
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||
this.refreshJob = scheduler.scheduleWithFixedDelay(this::refreshAndUpdateStatus, 0, refreshTimeInSeconds,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAutomaticRefresh() {
|
||||
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
this.refreshJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (CHANNEL_STATUS.equals(channelUID.getId()) && command instanceof RefreshType) {
|
||||
scheduler.schedule(this::refreshAndUpdateStatus, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.handler;
|
||||
|
||||
import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants;
|
||||
import org.openhab.binding.electroluxair.internal.ElectroluxAirConfiguration;
|
||||
import org.openhab.binding.electroluxair.internal.api.ElectroluxDeltaAPI;
|
||||
import org.openhab.binding.electroluxair.internal.dto.ElectroluxPureA9DTO;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.BridgeHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ElectroluxAirHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ElectroluxAirHandler.class);
|
||||
|
||||
private ElectroluxAirConfiguration config = new ElectroluxAirConfiguration();
|
||||
|
||||
public ElectroluxAirHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
logger.debug("Command received: {}", command);
|
||||
if (CHANNEL_STATUS.equals(channelUID.getId()) || command instanceof RefreshType) {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
BridgeHandler bridgeHandler = bridge.getHandler();
|
||||
if (bridgeHandler != null) {
|
||||
bridgeHandler.handleCommand(channelUID, command);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ElectroluxPureA9DTO dto = getElectroluxPureA9DTO();
|
||||
ElectroluxDeltaAPI api = getElectroluxDeltaAPI();
|
||||
if (api != null && dto != null) {
|
||||
if (CHANNEL_WORK_MODE.equals(channelUID.getId())) {
|
||||
if (command.toString().equals(COMMAND_WORKMODE_POWEROFF)) {
|
||||
api.workModePowerOff(dto.getApplianceId());
|
||||
} else if (command.toString().equals(COMMAND_WORKMODE_AUTO)) {
|
||||
api.workModeAuto(dto.getApplianceId());
|
||||
} else if (command.toString().equals(COMMAND_WORKMODE_MANUAL)) {
|
||||
api.workModeManual(dto.getApplianceId());
|
||||
}
|
||||
} else if (CHANNEL_FAN_SPEED.equals(channelUID.getId())) {
|
||||
api.setFanSpeedLevel(dto.getApplianceId(), Integer.parseInt(command.toString()));
|
||||
} else if (CHANNEL_IONIZER.equals(channelUID.getId())) {
|
||||
if (command == OnOffType.OFF) {
|
||||
api.setIonizer(dto.getApplianceId(), "false");
|
||||
} else if (command == OnOffType.ON) {
|
||||
api.setIonizer(dto.getApplianceId(), "true");
|
||||
} else {
|
||||
logger.debug("Unknown command! {}", command);
|
||||
}
|
||||
} else if (CHANNEL_UI_LIGHT.equals(channelUID.getId())) {
|
||||
if (command == OnOffType.OFF) {
|
||||
api.setUILight(dto.getApplianceId(), "false");
|
||||
} else if (command == OnOffType.ON) {
|
||||
api.setUILight(dto.getApplianceId(), "true");
|
||||
} else {
|
||||
logger.debug("Unknown command! {}", command);
|
||||
}
|
||||
} else if (CHANNEL_SAFETY_LOCK.equals(channelUID.getId())) {
|
||||
if (command == OnOffType.OFF) {
|
||||
api.setSafetyLock(dto.getApplianceId(), "false");
|
||||
} else if (command == OnOffType.ON) {
|
||||
api.setSafetyLock(dto.getApplianceId(), "true");
|
||||
} else {
|
||||
logger.debug("Unknown command! {}", command);
|
||||
}
|
||||
}
|
||||
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
BridgeHandler bridgeHandler = bridge.getHandler();
|
||||
if (bridgeHandler != null) {
|
||||
bridgeHandler.handleCommand(
|
||||
new ChannelUID(this.thing.getUID(), ElectroluxAirBindingConstants.CHANNEL_STATUS),
|
||||
RefreshType.REFRESH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(ElectroluxAirConfiguration.class);
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
scheduler.execute(() -> {
|
||||
update();
|
||||
Map<String, String> properties = refreshProperties();
|
||||
updateProperties(properties);
|
||||
});
|
||||
}
|
||||
|
||||
public void update() {
|
||||
ElectroluxPureA9DTO dto = getElectroluxPureA9DTO();
|
||||
if (dto != null) {
|
||||
update(dto);
|
||||
} else {
|
||||
logger.warn("ElectroluxPureA9DTO is null!");
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable ElectroluxDeltaAPI getElectroluxDeltaAPI() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ElectroluxAirBridgeHandler handler = (ElectroluxAirBridgeHandler) bridge.getHandler();
|
||||
if (handler != null) {
|
||||
return handler.getElectroluxDeltaAPI();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable ElectroluxPureA9DTO getElectroluxPureA9DTO() {
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ElectroluxAirBridgeHandler bridgeHandler = (ElectroluxAirBridgeHandler) bridge.getHandler();
|
||||
if (bridgeHandler != null) {
|
||||
return bridgeHandler.getElectroluxAirThings().get(config.getDeviceId());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void update(@Nullable ElectroluxPureA9DTO dto) {
|
||||
if (dto != null) {
|
||||
// Update all channels from the updated data
|
||||
getThing().getChannels().stream().map(Channel::getUID).filter(channelUID -> isLinked(channelUID))
|
||||
.forEach(channelUID -> {
|
||||
State state = getValue(channelUID.getId(), dto);
|
||||
logger.trace("Channel: {}, State: {}", channelUID, state);
|
||||
updateState(channelUID, state);
|
||||
});
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
private State getValue(String channelId, ElectroluxPureA9DTO dto) {
|
||||
switch (channelId) {
|
||||
case CHANNEL_TEMPERATURE:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getTemp(), SIUnits.CELSIUS);
|
||||
case CHANNEL_HUMIDITY:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getHumidity(), Units.PERCENT);
|
||||
case CHANNEL_TVOC:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getTVOC(), Units.MICROGRAM_PER_CUBICMETRE);
|
||||
case CHANNEL_PM1:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getPM1(), Units.PARTS_PER_BILLION);
|
||||
case CHANNEL_PM25:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getPM25(), Units.PARTS_PER_BILLION);
|
||||
case CHANNEL_PM10:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getPM10(), Units.PARTS_PER_BILLION);
|
||||
case CHANNEL_CO2:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getCO2(), Units.PARTS_PER_MILLION);
|
||||
case CHANNEL_FAN_SPEED:
|
||||
return new StringType(Integer.toString(dto.getProperties().getReported().getFanspeed()));
|
||||
case CHANNEL_FILTER_LIFE:
|
||||
return new QuantityType<>(dto.getProperties().getReported().getFilterLife(), Units.PERCENT);
|
||||
case CHANNEL_IONIZER:
|
||||
return OnOffType.from(dto.getProperties().getReported().isIonizer());
|
||||
case CHANNEL_UI_LIGHT:
|
||||
return OnOffType.from(dto.getProperties().getReported().isUILight());
|
||||
case CHANNEL_SAFETY_LOCK:
|
||||
return OnOffType.from(dto.getProperties().getReported().isSafetyLock());
|
||||
case CHANNEL_WORK_MODE:
|
||||
return new StringType(dto.getProperties().getReported().getWorkmode());
|
||||
case CHANNEL_DOOR_OPEN:
|
||||
return dto.getProperties().getReported().isDoorOpen() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
private Map<String, String> refreshProperties() {
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge != null) {
|
||||
ElectroluxAirBridgeHandler bridgeHandler = (ElectroluxAirBridgeHandler) bridge.getHandler();
|
||||
if (bridgeHandler != null) {
|
||||
ElectroluxPureA9DTO dto = bridgeHandler.getElectroluxAirThings().get(config.getDeviceId());
|
||||
if (dto != null) {
|
||||
properties.put(Thing.PROPERTY_VENDOR, dto.getApplianceInfo().getBrand());
|
||||
properties.put(PROPERTY_COLOUR, dto.getApplianceInfo().getColour());
|
||||
properties.put(PROPERTY_DEVICE, dto.getApplianceInfo().getDeviceType());
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, dto.getApplianceInfo().getModel());
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, dto.getApplianceInfo().getSerialNumber());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, dto.getProperties().getReported().getFrmVerNIU());
|
||||
}
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.electroluxair.internal.handler;
|
||||
|
||||
import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The {@link ElectroluxAirHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Jan Gustafsson - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.electroluxair", service = ThingHandlerFactory.class)
|
||||
public class ElectroluxAirHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ELECTROLUX_PURE_A9,
|
||||
THING_TYPE_BRIDGE);
|
||||
private final Gson gson;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public ElectroluxAirHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
this.gson = new Gson();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_ELECTROLUX_PURE_A9.equals(thingTypeUID)) {
|
||||
return new ElectroluxAirHandler(thing);
|
||||
} else if (THING_TYPE_BRIDGE.equals(thingTypeUID)) {
|
||||
return new ElectroluxAirBridgeHandler((Bridge) thing, httpClient, gson);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<addon:addon id="electroluxair" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:addon="https://openhab.org/schemas/addon/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd">
|
||||
|
||||
<type>binding</type>
|
||||
<name>ElectroluxAir Binding</name>
|
||||
<description>This is the binding for Electrolux Pure A9 Air Purifier.</description>
|
||||
<connection>cloud</connection>
|
||||
|
||||
</addon:addon>
|
@ -1,67 +0,0 @@
|
||||
# add-on
|
||||
|
||||
addon.electroluxair.name = ElectroluxAir Binding
|
||||
addon.electroluxair.description = This is the binding for Electrolux Pure A9 Air Purifier.
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.electroluxair.api.label = Electrolux Delta API
|
||||
thing-type.electroluxair.api.description = This bridge represents the web API connector.
|
||||
thing-type.electroluxair.electroluxpurea9.label = ElectroluxAir Pure A9
|
||||
thing-type.electroluxair.electroluxpurea9.description = This thing represents the ElectroluxAir Pure A9.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.electroluxair.api.password.label = Password
|
||||
thing-type.config.electroluxair.api.password.description = The password used to login to Electrolux Wellbeing app.
|
||||
thing-type.config.electroluxair.api.refresh.label = Refresh Interval
|
||||
thing-type.config.electroluxair.api.refresh.description = Specifies the refresh interval in seconds.
|
||||
thing-type.config.electroluxair.api.username.label = Username
|
||||
thing-type.config.electroluxair.api.username.description = The username used to login to Electrolux Wellbeing app.
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.label = Device Id
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.description = Unique Id.
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.electroluxair.co2.label = CO2
|
||||
channel-type.electroluxair.co2.description = CarbonDioxide
|
||||
channel-type.electroluxair.doorOpen.label = Door Status
|
||||
channel-type.electroluxair.doorOpen.description = Door Status Open/Closed
|
||||
channel-type.electroluxair.fanSpeed.label = Fan Speed Setting
|
||||
channel-type.electroluxair.fanSpeed.description = Fan Speed Setting
|
||||
channel-type.electroluxair.fanSpeed.state.option.1 = Level 1
|
||||
channel-type.electroluxair.fanSpeed.state.option.2 = Level 2
|
||||
channel-type.electroluxair.fanSpeed.state.option.3 = Level 3
|
||||
channel-type.electroluxair.fanSpeed.state.option.4 = Level 4
|
||||
channel-type.electroluxair.fanSpeed.state.option.5 = Level 5
|
||||
channel-type.electroluxair.fanSpeed.state.option.6 = Level 6
|
||||
channel-type.electroluxair.fanSpeed.state.option.7 = Level 7
|
||||
channel-type.electroluxair.fanSpeed.state.option.8 = Level 8
|
||||
channel-type.electroluxair.fanSpeed.state.option.9 = Level 9
|
||||
channel-type.electroluxair.filterLife.label = Filter Life
|
||||
channel-type.electroluxair.filterLife.description = Filter Life
|
||||
channel-type.electroluxair.humidity.label = Humidity
|
||||
channel-type.electroluxair.humidity.description = Humidity
|
||||
channel-type.electroluxair.ionizer.label = Ionizer Status
|
||||
channel-type.electroluxair.ionizer.description = Ionizer Status
|
||||
channel-type.electroluxair.pm1.label = PM1
|
||||
channel-type.electroluxair.pm1.description = Particulate Matter 1 (0.001mm)
|
||||
channel-type.electroluxair.pm10.label = PM10
|
||||
channel-type.electroluxair.pm10.description = Particulate Matter 10 (0.01mm)
|
||||
channel-type.electroluxair.pm2_5.label = PM2.5
|
||||
channel-type.electroluxair.pm2_5.description = Particulate Matter 2.5 (0.0025mm)
|
||||
channel-type.electroluxair.safetyLock.label = Safety Lock
|
||||
channel-type.electroluxair.safetyLock.description = Safety Lock Status
|
||||
channel-type.electroluxair.status.label = Current Status
|
||||
channel-type.electroluxair.status.description = Information on current status.
|
||||
channel-type.electroluxair.temperature.label = Temperature
|
||||
channel-type.electroluxair.temperature.description = Temperature
|
||||
channel-type.electroluxair.tvoc.label = TVOC
|
||||
channel-type.electroluxair.tvoc.description = Total Volatile Organic Compounds
|
||||
channel-type.electroluxair.uiLight.label = UI Light
|
||||
channel-type.electroluxair.uiLight.description = Air Quality Light Status
|
||||
channel-type.electroluxair.workMode.label = Work Mode Setting
|
||||
channel-type.electroluxair.workMode.description = Work Mode Setting
|
||||
channel-type.electroluxair.workMode.state.option.PowerOff = Power Off
|
||||
channel-type.electroluxair.workMode.state.option.Auto = Automatic
|
||||
channel-type.electroluxair.workMode.state.option.Manual = Manual
|
@ -1,67 +0,0 @@
|
||||
# add-on
|
||||
|
||||
addon.electroluxair.name = Extension ElectroluxAir
|
||||
addon.electroluxair.description = Il s'agit de l'extension pour le purificateur d'air Electrolux Pure A9.
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.electroluxair.api.label = API Delta Electrolux
|
||||
thing-type.electroluxair.api.description = Cette passerelle représente le connecteur de l'API web.
|
||||
thing-type.electroluxair.electroluxpurea9.label = ElectroluxAir Pure A9
|
||||
thing-type.electroluxair.electroluxpurea9.description = Cet objet représente l'ElectroluxAir Pure A9.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.electroluxair.api.password.label = Mot de passe
|
||||
thing-type.config.electroluxair.api.password.description = Le mot de passe utilisé pour se connecter à l'application Wellbeing Electrolux.
|
||||
thing-type.config.electroluxair.api.refresh.label = Intervalle d’actualisation
|
||||
thing-type.config.electroluxair.api.refresh.description = Définit l'intervalle d'actualisation en secondes.
|
||||
thing-type.config.electroluxair.api.username.label = Nom d'utilisateur
|
||||
thing-type.config.electroluxair.api.username.description = Le nom d'utilisateur utilisé pour se connecter à l'application Wellbeing Electrolux.
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.label = Identifiant de l'appareil
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.description = Identifiant unique
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.electroluxair.co2.label = CO2
|
||||
channel-type.electroluxair.co2.description = Dioxyde de carbone
|
||||
channel-type.electroluxair.doorOpen.label = État Porte
|
||||
channel-type.electroluxair.doorOpen.description = Statut de la porte ouverte/fermée
|
||||
channel-type.electroluxair.fanSpeed.label = Réglage Vitesse Ventilateur
|
||||
channel-type.electroluxair.fanSpeed.description = Réglage de la vitesse du ventilateur
|
||||
channel-type.electroluxair.fanSpeed.state.option.1 = Vitesse 1
|
||||
channel-type.electroluxair.fanSpeed.state.option.2 = Vitesse 2
|
||||
channel-type.electroluxair.fanSpeed.state.option.3 = Vitesse 3
|
||||
channel-type.electroluxair.fanSpeed.state.option.4 = Vitesse 4
|
||||
channel-type.electroluxair.fanSpeed.state.option.5 = Vitesse 5
|
||||
channel-type.electroluxair.fanSpeed.state.option.6 = Vitesse 6
|
||||
channel-type.electroluxair.fanSpeed.state.option.7 = Vitesse 7
|
||||
channel-type.electroluxair.fanSpeed.state.option.8 = Vitesse 8
|
||||
channel-type.electroluxair.fanSpeed.state.option.9 = Vitesse 9
|
||||
channel-type.electroluxair.filterLife.label = Durée Vie Filtre
|
||||
channel-type.electroluxair.filterLife.description = Durée de vie du filtre
|
||||
channel-type.electroluxair.humidity.label = Humidité
|
||||
channel-type.electroluxair.humidity.description = Humidité
|
||||
channel-type.electroluxair.ionizer.label = Statut Ioniseur
|
||||
channel-type.electroluxair.ionizer.description = Statut de l'ioniseur
|
||||
channel-type.electroluxair.pm1.label = PM1
|
||||
channel-type.electroluxair.pm1.description = Densité de particules 1 (0.001mm)
|
||||
channel-type.electroluxair.pm10.label = PM10
|
||||
channel-type.electroluxair.pm10.description = Densité de particules 10 (0.01mm)
|
||||
channel-type.electroluxair.pm2_5.label = PM2.5
|
||||
channel-type.electroluxair.pm2_5.description = Densité de particules 2.5 (0.0025mm)
|
||||
channel-type.electroluxair.safetyLock.label = Verrou Sécurité
|
||||
channel-type.electroluxair.safetyLock.description = Statut du verrouillage de sécurité
|
||||
channel-type.electroluxair.status.label = État Actuel
|
||||
channel-type.electroluxair.status.description = Informations sur l'état actuel.
|
||||
channel-type.electroluxair.temperature.label = Température
|
||||
channel-type.electroluxair.temperature.description = Température
|
||||
channel-type.electroluxair.tvoc.label = TVOC
|
||||
channel-type.electroluxair.tvoc.description = Total de composés organiques volatils
|
||||
channel-type.electroluxair.uiLight.label = Lumière Interface
|
||||
channel-type.electroluxair.uiLight.description = Statut de la lumière indiquant la qualité de l'air
|
||||
channel-type.electroluxair.workMode.label = Réglage Mode Fonctionnement
|
||||
channel-type.electroluxair.workMode.description = Réglage du mode de fonctionnement
|
||||
channel-type.electroluxair.workMode.state.option.PowerOff = Extinction
|
||||
channel-type.electroluxair.workMode.state.option.Auto = Automatique
|
||||
channel-type.electroluxair.workMode.state.option.Manual = Manuel
|
@ -1,67 +0,0 @@
|
||||
# add-on
|
||||
|
||||
addon.electroluxair.name = Binding ElectroluxAir
|
||||
addon.electroluxair.description = Questo è il binding per il Purificatore Electrolux Pure A9 Air.
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.electroluxair.api.label = API Electrolux Delta
|
||||
thing-type.electroluxair.api.description = Questo bridge rappresenta il connettore web API.
|
||||
thing-type.electroluxair.electroluxpurea9.label = ElectroluxAir Pure A9
|
||||
thing-type.electroluxair.electroluxpurea9.description = Questo Thing rappresenta l'ElectroluxAir Pure A9.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.electroluxair.api.password.label = Password
|
||||
thing-type.config.electroluxair.api.password.description = La password utilizzata per accedere all'app Electrolux Wellbeing.
|
||||
thing-type.config.electroluxair.api.refresh.label = Intervallo di aggiornamento
|
||||
thing-type.config.electroluxair.api.refresh.description = Specifica l'intervallo di aggiornamento in secondi.
|
||||
thing-type.config.electroluxair.api.username.label = Nome utente
|
||||
thing-type.config.electroluxair.api.username.description = Il nome utente usato per accedere all'app Electrolux Wellbeing.
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.label = Id Dispositivo
|
||||
thing-type.config.electroluxair.electroluxpurea9.deviceId.description = Id univoco.
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.electroluxair.co2.label = CO2
|
||||
channel-type.electroluxair.co2.description = Diossido di Carbonio
|
||||
channel-type.electroluxair.doorOpen.label = Stato Porta
|
||||
channel-type.electroluxair.doorOpen.description = Stato Della Porta Aperto/Chiuso
|
||||
channel-type.electroluxair.fanSpeed.label = Impostazioni Velocità Ventilatore
|
||||
channel-type.electroluxair.fanSpeed.description = Impostazioni della Velocità del Ventilatore
|
||||
channel-type.electroluxair.fanSpeed.state.option.1 = Livello 1
|
||||
channel-type.electroluxair.fanSpeed.state.option.2 = Livello 2
|
||||
channel-type.electroluxair.fanSpeed.state.option.3 = Livello 3
|
||||
channel-type.electroluxair.fanSpeed.state.option.4 = Livello 4
|
||||
channel-type.electroluxair.fanSpeed.state.option.5 = Livello 5
|
||||
channel-type.electroluxair.fanSpeed.state.option.6 = Livello 6
|
||||
channel-type.electroluxair.fanSpeed.state.option.7 = Livello 7
|
||||
channel-type.electroluxair.fanSpeed.state.option.8 = Livello 8
|
||||
channel-type.electroluxair.fanSpeed.state.option.9 = Livello 9
|
||||
channel-type.electroluxair.filterLife.label = Vita Filtro
|
||||
channel-type.electroluxair.filterLife.description = Vita del Filtro
|
||||
channel-type.electroluxair.humidity.label = Umidità
|
||||
channel-type.electroluxair.humidity.description = Umidità
|
||||
channel-type.electroluxair.ionizer.label = Stato Ionizzatore
|
||||
channel-type.electroluxair.ionizer.description = Stato Ionizzatore
|
||||
channel-type.electroluxair.pm1.label = PM1
|
||||
channel-type.electroluxair.pm1.description = Particolato 1 (0.001mm)
|
||||
channel-type.electroluxair.pm10.label = PM10
|
||||
channel-type.electroluxair.pm10.description = Particolato 10 (0.01mm)
|
||||
channel-type.electroluxair.pm2_5.label = PM 2.5
|
||||
channel-type.electroluxair.pm2_5.description = Particolato 2.5 (0.0025mm)
|
||||
channel-type.electroluxair.safetyLock.label = Blocco Di Sicurezza
|
||||
channel-type.electroluxair.safetyLock.description = Stato Blocco Di Sicurezza
|
||||
channel-type.electroluxair.status.label = Stato Attuale
|
||||
channel-type.electroluxair.status.description = Informazioni sullo stato attuale.
|
||||
channel-type.electroluxair.temperature.label = Temperatura
|
||||
channel-type.electroluxair.temperature.description = Temperatura
|
||||
channel-type.electroluxair.tvoc.label = TVOC
|
||||
channel-type.electroluxair.tvoc.description = Composti Organici Volatili Totali
|
||||
channel-type.electroluxair.uiLight.label = Luminosità UI
|
||||
channel-type.electroluxair.uiLight.description = Luce Stato Qualità Dell'Aria
|
||||
channel-type.electroluxair.workMode.label = Impostazioni Modalità Lavoro
|
||||
channel-type.electroluxair.workMode.description = Impostazioni Modalità Lavoro
|
||||
channel-type.electroluxair.workMode.state.option.PowerOff = Spegnimento
|
||||
channel-type.electroluxair.workMode.state.option.Auto = Automatico
|
||||
channel-type.electroluxair.workMode.state.option.Manual = Manuale
|
@ -1,200 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="electroluxair"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="api">
|
||||
<label>Electrolux Delta API</label>
|
||||
<description>This bridge represents the web API connector.</description>
|
||||
|
||||
<properties>
|
||||
<property name="vendor">Electrolux</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="username" type="text" required="true">
|
||||
<label>Username</label>
|
||||
<description>The username used to login to Electrolux Wellbeing app.</description>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<label>Password</label>
|
||||
<context>password</context>
|
||||
<description>The password used to login to Electrolux Wellbeing app.</description>
|
||||
</parameter>
|
||||
<parameter name="refresh" type="integer" min="10" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>Specifies the refresh interval in seconds.</description>
|
||||
<default>300</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
<thing-type id="electroluxpurea9">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>ElectroluxAir Pure A9</label>
|
||||
<description>This thing represents the ElectroluxAir Pure A9.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="temperature" typeId="temperature"/>
|
||||
<channel id="humidity" typeId="humidity"/>
|
||||
<channel id="tvoc" typeId="tvoc"/>
|
||||
<channel id="pm1" typeId="pm1"/>
|
||||
<channel id="pm2_5" typeId="pm2_5"/>
|
||||
<channel id="pm10" typeId="pm10"/>
|
||||
<channel id="co2" typeId="co2"/>
|
||||
<channel id="filterLife" typeId="filterLife"/>
|
||||
<channel id="doorOpen" typeId="doorOpen"/>
|
||||
<channel id="fanSpeed" typeId="fanSpeed"/>
|
||||
<channel id="workMode" typeId="workMode"/>
|
||||
<channel id="ionizer" typeId="ionizer"/>
|
||||
<channel id="uiLight" typeId="uiLight"/>
|
||||
<channel id="safetyLock" typeId="safetyLock"/>
|
||||
<channel id="status" typeId="status"/>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="vendor">Electrolux</property>
|
||||
<property name="thingTypeVersion">1</property>
|
||||
</properties>
|
||||
|
||||
<representation-property>deviceId</representation-property>
|
||||
|
||||
<config-description>
|
||||
<parameter name="deviceId" type="text" required="true">
|
||||
<label>Device Id</label>
|
||||
<description>Unique Id.</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="status">
|
||||
<item-type>String</item-type>
|
||||
<label>Current Status</label>
|
||||
<description>Information on current status.</description>
|
||||
<state readOnly="true" pattern="%s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<description>Temperature</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%.1f %unit%">
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="humidity">
|
||||
<item-type unitHint="%">Number:Dimensionless</item-type>
|
||||
<label>Humidity</label>
|
||||
<description>Humidity</description>
|
||||
<category>Humidity</category>
|
||||
<state readOnly="true" min="0" max="100" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="tvoc">
|
||||
<item-type>Number:Density</item-type>
|
||||
<label>TVOC</label>
|
||||
<description>Total Volatile Organic Compounds</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
|
||||
<channel-type id="pm1">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>PM1</label>
|
||||
<description>Particulate Matter 1 (0.001mm)</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pm2_5">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>PM2.5</label>
|
||||
<description>Particulate Matter 2.5 (0.0025mm)</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pm10">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>PM10</label>
|
||||
<description>Particulate Matter 10 (0.01mm)</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="co2">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>CO2</label>
|
||||
<description>CarbonDioxide</description>
|
||||
<state readOnly="true" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="filterLife">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Filter Life</label>
|
||||
<description>Filter Life</description>
|
||||
<state readOnly="true" min="0" max="100" pattern="%d %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="doorOpen">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Door Status</label>
|
||||
<description>Door Status Open/Closed</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="fanSpeed">
|
||||
<item-type>Number</item-type>
|
||||
<label>Fan Speed Setting</label>
|
||||
<description>Fan Speed Setting</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="1">Level 1</option>
|
||||
<option value="2">Level 2</option>
|
||||
<option value="3">Level 3</option>
|
||||
<option value="4">Level 4</option>
|
||||
<option value="5">Level 5</option>
|
||||
<option value="6">Level 6</option>
|
||||
<option value="7">Level 7</option>
|
||||
<option value="8">Level 8</option>
|
||||
<option value="9">Level 9</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="workMode">
|
||||
<item-type>String</item-type>
|
||||
<label>Work Mode Setting</label>
|
||||
<description>Work Mode Setting</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="PowerOff">Power Off</option>
|
||||
<option value="Auto">Automatic</option>
|
||||
<option value="Manual">Manual</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ionizer">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Ionizer Status</label>
|
||||
<description>Ionizer Status</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="uiLight">
|
||||
<item-type>Switch</item-type>
|
||||
<label>UI Light</label>
|
||||
<description>Air Quality Light Status</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="safetyLock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Safety Lock</label>
|
||||
<description>Safety Lock Status</description>
|
||||
</channel-type>
|
||||
|
||||
|
||||
</thing:thing-descriptions>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
|
||||
|
||||
<thing-type uid="electroluxair:electroluxpurea9">
|
||||
<instruction-set targetVersion="1">
|
||||
<add-channel id="uiLight">
|
||||
<type>electroluxair:uiLight</type>
|
||||
</add-channel>
|
||||
<add-channel id="safetyLock">
|
||||
<type>electroluxair:safetyLock</type>
|
||||
</add-channel>
|
||||
</instruction-set>
|
||||
</thing-type>
|
||||
|
||||
</update:update-descriptions>
|
@ -126,7 +126,6 @@
|
||||
<module>org.openhab.binding.ecovacs</module>
|
||||
<module>org.openhab.binding.ecowatt</module>
|
||||
<module>org.openhab.binding.ekey</module>
|
||||
<module>org.openhab.binding.electroluxair</module>
|
||||
<module>org.openhab.binding.elerotransmitterstick</module>
|
||||
<module>org.openhab.binding.elroconnects</module>
|
||||
<module>org.openhab.binding.emotiva</module>
|
||||
|
Loading…
Reference in New Issue
Block a user