]> git.basschouten.com Git - openhab-addons.git/commitdiff
[electroluxair] Update to changed API (#15187)
authorJan Gustafsson <jannegpriv@gmail.com>
Sat, 8 Jul 2023 10:45:57 +0000 (12:45 +0200)
committerGitHub <noreply@github.com>
Sat, 8 Jul 2023 10:45:57 +0000 (12:45 +0200)
* Updated to changed API (#15136)

Fixes #15136

Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com>
bundles/org.openhab.binding.electroluxair/README.md
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/ElectroluxAirBindingConstants.java
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/api/ElectroluxDeltaAPI.java
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/dto/ElectroluxPureA9DTO.java
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/handler/ElectroluxAirBridgeHandler.java
bundles/org.openhab.binding.electroluxair/src/main/java/org/openhab/binding/electroluxair/internal/handler/ElectroluxAirHandler.java
bundles/org.openhab.binding.electroluxair/src/main/resources/OH-INF/i18n/electroluxair.properties
bundles/org.openhab.binding.electroluxair/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.electroluxair/src/main/resources/OH-INF/update/instructions.xml [new file with mode: 0644]

index 3492197056c9116721953e7ad02db94f4dd4e3d6..b533410b58bc54140d61c4696509b51eaf703ebe 100644 (file)
@@ -2,8 +2,6 @@
 
 This is an openHAB binding for the Pure A9 Air Purifier, by Electrolux.
 
-This binding uses the Electrolux Delta REST API.
-
 ![Electrolux Pure A9](doc/electrolux_pure_a9.png)
 
 ## Supported Things
@@ -26,15 +24,15 @@ Only the bridge require manual configuration. The Electrolux Pure A9 thing can b
 
 | Parameter | Description                                                  | Type   | Default  | Required |
 |-----------|--------------------------------------------------------------|--------|----------|----------|
-| username  | The username used to connect to the Electrolux Wellbeing app | String | NA       | yes      |
-| password  | The password used to connect to the Electrolux Wellbeing app | String | NA       | yes      |
+| 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 Wellbeing app | Number | NA       | yes      |
+| deviceId  | Product ID of your Electrolux Pure A9 found in Electrolux app           | Number | NA       | yes      |
 
 ## Channels
 
@@ -42,20 +40,22 @@ Only the bridge require manual configuration. The Electrolux Pure A9 thing can b
 
 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.)|
+| 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
 
@@ -83,4 +83,10 @@ Contact ElectroluxAirDoor "Electrolux Air Door Status" {channel="electroluxair:e
 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"}
 ```
index b6792a7926b100bf06ba04d2536478e44acf8b30..905861aa2b2578b58e72d9a8cfb8e4ae871e931c 100644 (file)
@@ -46,6 +46,8 @@ public class ElectroluxAirBindingConstants {
     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";
index b4411672d80a1692ebbf403610c216af600b79ea..88249a8edf7465ba005258645a5f34f1f1d2e6d7 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.electroluxair.internal.api;
 
+import java.time.Instant;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -27,17 +28,13 @@ 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.openhab.binding.electroluxair.internal.dto.ElectroluxPureA9DTO.AppliancesInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import com.google.gson.JsonSyntaxException;
-import com.google.gson.annotations.SerializedName;
 
 /**
  * The {@link ElectroluxDeltaAPI} class defines the Elextrolux Delta API
@@ -46,10 +43,17 @@ import com.google.gson.annotations.SerializedName;
  */
 @NonNullByDefault
 public class ElectroluxDeltaAPI {
-    private static final String CLIENT_URL = "https://electrolux-wellbeing-client.vercel.app/api/mu52m5PR9X";
-    private static final String SERVICE_URL = "https://api.delta.electrolux.com/api/";
+    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 String LOGIN = "Users/Login";
     private static final int MAX_RETRIES = 3;
 
     private final Logger logger = LoggerFactory.getLogger(ElectroluxDeltaAPI.class);
@@ -57,6 +61,7 @@ public class ElectroluxDeltaAPI {
     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;
@@ -66,70 +71,73 @@ public class ElectroluxDeltaAPI {
 
     public boolean refresh(Map<String, ElectroluxPureA9DTO> electroluxAirThings) {
         try {
-            // Login
-            login();
+            if (Instant.now().isAfter(this.tokenExpiry)) {
+                // Login again since token is expired
+                login();
+            }
             // Get all appliances
             String json = getAppliances();
-            JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray();
-
-            for (JsonElement jsonElement : jsonArray) {
-                String pncId = jsonElement.getAsJsonObject().get("pncId").getAsString();
-
-                // Get appliance info
-                String jsonApplianceInfo = getAppliancesInfo(pncId);
-                AppliancesInfo appliancesInfo = gson.fromJson(jsonApplianceInfo, AppliancesInfo.class);
-
-                // Get applicance data
-                ElectroluxPureA9DTO dto = getAppliancesData(pncId, ElectroluxPureA9DTO.class);
-                if (appliancesInfo != null) {
-                    dto.setApplicancesInfo(appliancesInfo);
+            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);
+                        }
+                    }
                 }
-                electroluxAirThings.put(dto.getTwin().getProperties().getReported().deviceId, dto);
+                return true;
             }
-            return true;
-        } catch (ElectroluxAirException e) {
+        } catch (JsonSyntaxException | ElectroluxAirException e) {
             logger.warn("Failed to refresh! {}", e.getMessage());
+
         }
         return false;
     }
 
-    public boolean workModePowerOff(String pncId) {
+    public boolean workModePowerOff(String applianceId) {
         String commandJSON = "{ \"WorkMode\": \"PowerOff\" }";
         try {
-            return sendCommand(commandJSON, pncId);
+            return sendCommand(commandJSON, applianceId);
         } catch (ElectroluxAirException e) {
             logger.warn("Work mode powerOff failed {}", e.getMessage());
         }
         return false;
     }
 
-    public boolean workModeAuto(String pncId) {
+    public boolean workModeAuto(String applianceId) {
         String commandJSON = "{ \"WorkMode\": \"Auto\" }";
         try {
-            return sendCommand(commandJSON, pncId);
+            return sendCommand(commandJSON, applianceId);
         } catch (ElectroluxAirException e) {
             logger.warn("Work mode auto failed {}", e.getMessage());
         }
         return false;
     }
 
-    public boolean workModeManual(String pncId) {
+    public boolean workModeManual(String applianceId) {
         String commandJSON = "{ \"WorkMode\": \"Manual\" }";
         try {
-            return sendCommand(commandJSON, pncId);
+            return sendCommand(commandJSON, applianceId);
         } catch (ElectroluxAirException e) {
             logger.warn("Work mode manual failed {}", e.getMessage());
         }
         return false;
     }
 
-    public boolean setFanSpeedLevel(String pncId, int fanSpeedLevel) {
+    public boolean setFanSpeedLevel(String applianceId, int fanSpeedLevel) {
         if (fanSpeedLevel < 1 && fanSpeedLevel > 10) {
             return false;
         } else {
             String commandJSON = "{ \"Fanspeed\": " + fanSpeedLevel + "}";
             try {
-                return sendCommand(commandJSON, pncId);
+                return sendCommand(commandJSON, applianceId);
             } catch (ElectroluxAirException e) {
                 logger.warn("Work mode manual failed {}", e.getMessage());
             }
@@ -137,40 +145,74 @@ public class ElectroluxDeltaAPI {
         return false;
     }
 
-    public boolean setIonizer(String pncId, String ionizerStatus) {
+    public boolean setIonizer(String applianceId, String ionizerStatus) {
         String commandJSON = "{ \"Ionizer\": " + ionizerStatus + "}";
         try {
-            return sendCommand(commandJSON, pncId);
+            return sendCommand(commandJSON, applianceId);
         } catch (ElectroluxAirException e) {
             logger.warn("Work mode manual failed {}", e.getMessage());
         }
         return false;
     }
 
-    private void login() throws ElectroluxAirException {
-        // Fetch ClientToken
-        Request request = httpClient.newRequest(CLIENT_URL).method(HttpMethod.GET);
+    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.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
         request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
 
-        logger.debug("HTTP GET Request {}.", request.toString());
+        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 login " + httpResponse.getContentAsString());
+                throw new ElectroluxAirException("Failed to get token 1" + httpResponse.getContentAsString());
             }
-            String json = httpResponse.getContentAsString();
+            json = httpResponse.getContentAsString();
+            logger.trace("Token 1: {}", json);
             JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
             String clientToken = jsonObject.get("accessToken").getAsString();
 
-            // Login using ClientToken
-            json = "{ \"Username\": \"" + configuration.username + "\",  \"Password\": \"" + configuration.password
+            // Login using access token 1
+            json = "{ \"username\": \"" + configuration.username + "\",  \"password\": \"" + configuration.password
                     + "\" }";
-            request = httpClient.newRequest(SERVICE_URL + LOGIN).method(HttpMethod.POST);
-            request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
-            request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
+            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());
@@ -179,10 +221,33 @@ public class ElectroluxDeltaAPI {
             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);
         }
@@ -192,10 +257,9 @@ public class ElectroluxDeltaAPI {
         try {
             for (int i = 0; i < MAX_RETRIES; i++) {
                 try {
-                    Request request = httpClient.newRequest(SERVICE_URL + uri).method(HttpMethod.GET);
+                    Request request = createRequest(uri, HttpMethod.GET);
                     request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
-                    request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
-                    request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
+                    request.header("x-api-key", X_API_KEY);
 
                     ContentResponse response = request.send();
                     String content = response.getContentAsString();
@@ -218,44 +282,28 @@ public class ElectroluxDeltaAPI {
     }
 
     private String getAppliances() throws ElectroluxAirException {
-        String uri = "Domains/Appliances";
-        try {
-            return getFromApi(uri);
-        } catch (ElectroluxAirException | InterruptedException e) {
-            throw new ElectroluxAirException(e);
-        }
-    }
-
-    private String getAppliancesInfo(String pncId) throws ElectroluxAirException {
-        String uri = "AppliancesInfo/" + pncId;
         try {
-            return getFromApi(uri);
+            return getFromApi(APPLIANCES_URL);
         } catch (ElectroluxAirException | InterruptedException e) {
             throw new ElectroluxAirException(e);
         }
     }
 
-    private <T> T getAppliancesData(String pncId, Class<T> dto) throws ElectroluxAirException {
-        String uri = "Appliances/" + pncId;
-        String json;
-
+    private String getAppliancesInfo(String applianceId) throws ElectroluxAirException {
         try {
-            json = getFromApi(uri);
+            return getFromApi(APPLIANCES_URL + "/" + applianceId + "/info");
         } catch (ElectroluxAirException | InterruptedException e) {
             throw new ElectroluxAirException(e);
         }
-        return gson.fromJson(json, dto);
     }
 
-    private boolean sendCommand(String commandJSON, String pncId) throws ElectroluxAirException {
-        String uri = "Appliances/" + pncId + "/Commands";
+    private boolean sendCommand(String commandJSON, String applianceId) throws ElectroluxAirException {
         try {
             for (int i = 0; i < MAX_RETRIES; i++) {
                 try {
-                    Request request = httpClient.newRequest(SERVICE_URL + uri).method(HttpMethod.PUT);
+                    Request request = createRequest(APPLIANCES_URL + "/" + applianceId + "/command", HttpMethod.PUT);
                     request.header(HttpHeader.AUTHORIZATION, "Bearer " + authToken);
-                    request.header(HttpHeader.ACCEPT, JSON_CONTENT_TYPE);
-                    request.header(HttpHeader.CONTENT_TYPE, JSON_CONTENT_TYPE);
+                    request.header("x-api-key", X_API_KEY);
                     request.content(new StringContentProvider(commandJSON), JSON_CONTENT_TYPE);
 
                     ContentResponse response = request.send();
@@ -266,19 +314,7 @@ public class ElectroluxDeltaAPI {
                         logger.debug("sendCommand failed, HTTP status: {}", response.getStatus());
                         login();
                     } else {
-                        CommandResponseDTO commandResponse = gson.fromJson(content, CommandResponseDTO.class);
-                        if (commandResponse != null) {
-                            if (commandResponse.code == 200000) {
-                                return true;
-                            } else {
-                                logger.warn("Failed to send command, error code: {}, description: {}",
-                                        commandResponse.code, commandResponse.codeDescription);
-                                return false;
-                            }
-                        } else {
-                            logger.warn("Failed to send command, commandResponse is null!");
-                            return false;
-                        }
+                        return true;
                     }
                 } catch (TimeoutException | InterruptedException e) {
                     logger.warn("TimeoutException error in get");
@@ -289,26 +325,4 @@ public class ElectroluxDeltaAPI {
         }
         return false;
     }
-
-    @SuppressWarnings("unused")
-    private static class CommandResponseDTO {
-        public int code;
-        public String codeDescription = "";
-        public String information = "";
-        public String message = "";
-        public PayloadDTO payload = new PayloadDTO();
-        public int status;
-    }
-
-    private static class PayloadDTO {
-        @SerializedName("Ok")
-        public boolean ok;
-        @SerializedName("Response")
-        public ResponseDTO response = new ResponseDTO();
-    }
-
-    private static class ResponseDTO {
-        @SerializedName("Workmode")
-        public String workmode = "";
-    }
 }
index 8b26c0a165b12dccb7467a1408509b1ec58336da..97f6bc8f86dea7737b945f80a9ab6663cfd61612 100644 (file)
@@ -12,6 +12,9 @@
  */
 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;
@@ -23,354 +26,232 @@ import com.google.gson.annotations.SerializedName;
  */
 @NonNullByDefault
 public class ElectroluxPureA9DTO {
-    public String pncId = "";
-    public ApplianceData applianceData = new ApplianceData();
-    public AppliancesInfo applicancesInfo = new AppliancesInfo();
-
-    public Twin twin = new Twin();
-    public String telemetry = "";
-
-    public String getPncId() {
-        return pncId;
-    }
-
-    public ApplianceData getApplianceData() {
-        return applianceData;
-    }
-
-    public AppliancesInfo getApplicancesInfo() {
-        return applicancesInfo;
-    }
+    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 void setApplicancesInfo(AppliancesInfo applicancesInfo) {
-        this.applicancesInfo = applicancesInfo;
+    public String getApplianceId() {
+        return applianceId;
     }
 
-    public Twin getTwin() {
-        return twin;
+    public ApplianceInfo getApplianceInfo() {
+        return applianceInfo;
     }
 
-    public String getTelemetry() {
-        return telemetry;
-    }
-
-    public class MetaData1 {
-
-        @SerializedName("$lastUpdated")
-        public String lastUpdated1 = "";
-        @SerializedName("$lastUpdatedVersion")
-        public int lastUpdatedVersion1;
-        @SerializedName("TimeZoneStandardName")
-        public TimeZoneStandardName timeZoneStandardName = new TimeZoneStandardName();
-        @SerializedName("FrmVer_NIU")
-        public FrmVerNIU frmVerNIU = new FrmVerNIU();
-    }
-
-    public class Metadata2 {
-
-        @SerializedName("$lastUpdated")
-        public String lastUpdated2 = "";
-        @SerializedName("FrmVer_NIU")
-        public FrmVerNIU frmVerNIU = new FrmVerNIU();
-        @SerializedName("Workmode")
-        public Workmode workmode = new Workmode();
-        @SerializedName("FilterRFID")
-        public FilterRFID filterRFID = new FilterRFID();
-        @SerializedName("FilterLife")
-        public FilterLife filterLife = new FilterLife();
-        @SerializedName("Fanspeed")
-        public Fanspeed fanspeed = new Fanspeed();
-        @SerializedName("UILight")
-        public UILight uILight = new UILight();
-        @SerializedName("SafetyLock")
-        public SafetyLock safetyLock = new SafetyLock();
-        @SerializedName("Ionizer")
-        public Ionizer ionizer = new Ionizer();
-        @SerializedName("Sleep")
-        public Sleep sleep = new Sleep();
-        @SerializedName("Scheduler")
-        public Scheduler scheduler = new Scheduler();
-        @SerializedName("FilterType")
-        public FilterType filterType = new FilterType();
-        @SerializedName("DspIcoPM2_5")
-        public DspIcoPM25 dspIcoPM25 = new DspIcoPM25();
-        @SerializedName("DspIcoPM1")
-        public DspIcoPM1 dspIcoPM1 = new DspIcoPM1();
-        @SerializedName("DspIcoPM10")
-        public DspIcoPM10 dspIcoPM10 = new DspIcoPM10();
-        @SerializedName("DspIcoTVOC")
-        public DspIcoTVOC dspIcoTVOC = new DspIcoTVOC();
-        @SerializedName("ErrPM2_5")
-        public ErrPM25 errPM25 = new ErrPM25();
-        @SerializedName("ErrTVOC")
-        public ErrTVOC errTVOC = new ErrTVOC();
-        @SerializedName("ErrTempHumidity")
-        public ErrTempHumidity errTempHumidity = new ErrTempHumidity();
-        @SerializedName("ErrFanMtr")
-        public ErrFanMtr errFanMtr = new ErrFanMtr();
-        @SerializedName("ErrCommSensorDisplayBrd")
-        public ErrCommSensorDisplayBrd errCommSensorDisplayBrd = new ErrCommSensorDisplayBrd();
-        @SerializedName("DoorOpen")
-        public DoorOpen doorOpen = new DoorOpen();
-        @SerializedName("ErrRFID")
-        public ErrRFID errRFID = new ErrRFID();
-        @SerializedName("SignalStrength")
-        public SignalStrength signalStrength = new SignalStrength();
-        @SerializedName("PM1")
-        public PM1 pM1 = new PM1();
-        @SerializedName("PM2_5")
-        public PM25 pM25 = new PM25();
-        @SerializedName("PM10")
-        public PM10 pM10 = new PM10();
-        @SerializedName("TVOC")
-        public TVOC tVOC = new TVOC();
-        @SerializedName("CO2")
-        public CO2 cO2 = new CO2();
-        @SerializedName("Temp")
-        public Temp temp = new Temp();
-        @SerializedName("Humidity")
-        public Humidity humidity = new Humidity();
-        @SerializedName("EnvLightLvl")
-        public EnvLightLvl envLightLvl = new EnvLightLvl();
-        @SerializedName("RSSI")
-        public RSSI rSSI = new RSSI();
+    public void setApplianceInfo(ApplianceInfo applianceInfo) {
+        this.applianceInfo = applianceInfo;
     }
 
-    public class ApplianceData {
-
-        public String applianceName = "";
-        public String created = "";
-        public String modelName = "";
-        public String pncId = "";
+    public ApplianceData getApplianceData() {
+        return applianceData;
     }
 
-    public class AppliancesInfo {
-        public String brand = "";
-        public String colour = "";
-        public String device = "";
-        public String model = "";
-        public String serialNumber = "";
+    public Properties getProperties() {
+        return properties;
     }
 
-    public class CO2 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated3 = "";
+    public String getStatus() {
+        return status;
     }
 
-    public class Desired {
-
-        @SerializedName("TimeZoneStandardName")
-        public String timeZoneStandardName = "";
-        @SerializedName("FrmVer_NIU")
-        public String frmVerNIU = "";
-        @SerializedName("$metadata")
-        public MetaData1 metadata3 = new MetaData1();
-        @SerializedName("$version")
-        public int version;
+    public String getConnectionState() {
+        return connectionState;
     }
 
-    public class DoorOpen {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+    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 class DspIcoPM1 {
-        @SerializedName("lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getManufacturingDateCode() {
+            return manufacturingDateCode;
+        }
 
-    public class DspIcoPM10 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getSerialNumber() {
+            return serialNumber;
+        }
 
-    public class DspIcoPM25 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getPnc() {
+            return pnc;
+        }
 
-    public class DspIcoTVOC {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getBrand() {
+            return brand;
+        }
 
-    public class EnvLightLvl {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getMarket() {
+            return market;
+        }
 
-    public class ErrCommSensorDisplayBrd {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getProductArea() {
+            return productArea;
+        }
 
-    public class ErrFanMtr {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getDeviceType() {
+            return deviceType;
+        }
 
-    public class ErrPM25 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getProject() {
+            return project;
+        }
 
-    public class ErrRFID {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getModel() {
+            return model;
+        }
 
-    public class ErrTVOC {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getVariant() {
+            return variant;
+        }
 
-    public class ErrTempHumidity {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
+        public String getColour() {
+            return colour;
+        }
     }
 
-    public class Fanspeed {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+    class ApplianceData {
+        private String applianceName = "";
+        private String created = "";
+        private String modelName = "";
 
-    public class FilterLife {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getApplianceName() {
+            return applianceName;
+        }
 
-    public class FilterRFID {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getCreated() {
+            return created;
+        }
 
-    public class FilterType {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
+        public String getModelName() {
+            return modelName;
+        }
     }
 
-    public class FrmVerNIU {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-        @SerializedName("$lastUpdatedVersion")
-        public int lastUpdatedVersion;
-    }
+    public class Properties {
+        private Desired desired = new Desired();
+        private Reported reported = new Reported();
+        private Object metadata = new Object();
 
-    // public class FrmVerNIU_ {
-    // @SerializedName("$lastUpdated")
-    // public String lastUpdated = "";
-    // }
+        public Desired getDesired() {
+            return desired;
+        }
 
-    public class Humidity {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public Reported getReported() {
+            return reported;
+        }
 
-    public class Ionizer {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
+        public Object getMetadata() {
+            return metadata;
+        }
     }
 
-    public class PM1 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+    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 class PM10 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getTimeZoneStandardName() {
+            return timeZoneStandardName;
+        }
 
-    public class PM25 {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
+        public String getFrmVerNIU() {
+            return frmVerNIU;
+        }
 
-    public class Properties {
-        public Desired desired = new Desired();
-        public Reported reported = new Reported();
+        public boolean isLocationReq() {
+            return locationReq;
+        }
 
-        public Reported getReported() {
-            return reported;
+        public Map<String, Object> getMetadata() {
+            return metadata;
         }
-    }
 
-    public class RSSI {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
+        public int getVersion() {
+            return version;
+        }
     }
 
     public class Reported {
-
         @SerializedName("FrmVer_NIU")
-        public String frmVerNIU = "";
+        private String frmVerNIU = "";
         @SerializedName("Workmode")
-        public String workmode = "";
+        private String workmode = "";
         @SerializedName("FilterRFID")
-        public String filterRFID = "";
+        private String filterRFID = "";
         @SerializedName("FilterLife")
-        public int filterLife;
+        private int filterLife = 0;
         @SerializedName("Fanspeed")
-        public int fanspeed;
+        private int fanSpeed = 0;
         @SerializedName("UILight")
-        public boolean uILight;
+        private boolean uiLight = false;
         @SerializedName("SafetyLock")
-        public boolean safetyLock;
+        private boolean safetyLock = false;
         @SerializedName("Ionizer")
-        public boolean ionizer;
+        private boolean ionizer = false;
         @SerializedName("Sleep")
-        public boolean sleep;
+        private boolean sleep = false;
         @SerializedName("Scheduler")
-        public boolean scheduler;
+        private boolean scheduler = false;
         @SerializedName("FilterType")
-        public int filterType;
+        private int filterType = 0;
         @SerializedName("DspIcoPM2_5")
-        public boolean dspIcoPM25;
+        private boolean dspIcoPM25 = false;
         @SerializedName("DspIcoPM1")
-        public boolean dspIcoPM1;
+        private boolean dspIcoPM1 = false;
         @SerializedName("DspIcoPM10")
-        public boolean dspIcoPM10;
+        private boolean dspIcoPM10 = false;
         @SerializedName("DspIcoTVOC")
-        public boolean dspIcoTVOC;
+        private boolean dspIcoTVOC = false;
         @SerializedName("ErrPM2_5")
-        public boolean errPM25;
+        private boolean errPM25 = false;
         @SerializedName("ErrTVOC")
-        public boolean errTVOC;
+        private boolean errTVOC = false;
         @SerializedName("ErrTempHumidity")
-        public boolean errTempHumidity;
+        private boolean errTempHumidity = false;
         @SerializedName("ErrFanMtr")
-        public boolean errFanMtr;
+        private boolean errFanMtr = false;
         @SerializedName("ErrCommSensorDisplayBrd")
-        public boolean errCommSensorDisplayBrd;
+        private boolean errCommSensorDisplayBrd = false;
         @SerializedName("DoorOpen")
-        public boolean doorOpen;
+        private boolean doorOpen = false;
         @SerializedName("ErrRFID")
-        public boolean errRFID;
+        private boolean errRFID = false;
         @SerializedName("SignalStrength")
-        public String signalStrength = "";
-        @SerializedName("$metadata")
-        public Metadata2 metadata2 = new Metadata2();
-        @SerializedName("$version")
-        public int version;
-        public String deviceId = "";
-        @SerializedName("PM1")
-        public int pM1;
-        @SerializedName("PM2_5")
-        public int pM25;
-        @SerializedName("PM10")
-        public int pM10;
-        @SerializedName("TVOC")
-        public int tVOC;
+        private String signalStrength = "";
+        private Map<String, Object> metadata = new HashMap<>();
+        private int version = 0;
+        private String deviceId = "";
         @SerializedName("CO2")
-        public int cO2;
+        private int co2 = 0;
+        @SerializedName("TVOC")
+        private int tvoc = 0;
         @SerializedName("Temp")
-        public int temp;
+        private int temp = 0;
         @SerializedName("Humidity")
-        public int humidity;
-        @SerializedName("EnvLightLvl")
-        public int envLightLvl;
+        private int humidity = 0;
         @SerializedName("RSSI")
-        public int 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;
@@ -389,11 +270,11 @@ public class ElectroluxPureA9DTO {
         }
 
         public int getFanspeed() {
-            return fanspeed;
+            return fanSpeed;
         }
 
-        public boolean isuILight() {
-            return uILight;
+        public boolean isUILight() {
+            return uiLight;
         }
 
         public boolean isSafetyLock() {
@@ -464,6 +345,10 @@ public class ElectroluxPureA9DTO {
             return signalStrength;
         }
 
+        public Map<String, Object> getMetadata() {
+            return metadata;
+        }
+
         public int getVersion() {
             return version;
         }
@@ -472,24 +357,12 @@ public class ElectroluxPureA9DTO {
             return deviceId;
         }
 
-        public int getpM1() {
-            return pM1;
+        public int getCO2() {
+            return co2;
         }
 
-        public int getpM25() {
-            return pM25;
-        }
-
-        public int getpM10() {
-            return pM10;
-        }
-
-        public int gettVOC() {
-            return tVOC;
-        }
-
-        public int getcO2() {
-            return cO2;
+        public int getTVOC() {
+            return tvoc;
         }
 
         public int getTemp() {
@@ -500,82 +373,20 @@ public class ElectroluxPureA9DTO {
             return humidity;
         }
 
-        public int getEnvLightLvl() {
-            return envLightLvl;
+        public int getRSSI() {
+            return rssi;
         }
 
-        public int getrSSI() {
-            return rSSI;
+        public int getPM1() {
+            return pm1;
         }
-    }
 
-    public class SafetyLock {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class Scheduler {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class SignalStrength {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class Sleep {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class TVOC {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class Temp {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class TimeZoneStandardName {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-        @SerializedName("$lastUpdatedVersion")
-        public int lastUpdatedVersion;
-    }
-
-    public class Twin {
-        public String deviceId = "";
-        public Properties properties = new Properties();
-        public String status = "";
-        public String connectionState = "";
-
-        public String getDeviceId() {
-            return deviceId;
-        }
-
-        public Properties getProperties() {
-            return properties;
-        }
-
-        public String getStatus() {
-            return status;
+        public int getPM25() {
+            return pm25;
         }
 
-        public String getConnectionState() {
-            return connectionState;
+        public int getPM10() {
+            return pm10;
         }
     }
-
-    public class UILight {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
-
-    public class Workmode {
-        @SerializedName("$lastUpdated")
-        public String lastUpdated = "";
-    }
 }
index df9805986f86d5918d64332415da50c0737e99d5..b510aadcb5aa5fb46b728d1ce2cee606f0222fd5 100644 (file)
@@ -12,7 +12,7 @@
  */
 package org.openhab.binding.electroluxair.internal.handler;
 
-import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.THING_TYPE_BRIDGE;
+import static org.openhab.binding.electroluxair.internal.ElectroluxAirBindingConstants.*;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -37,6 +37,7 @@ 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;
 
@@ -147,6 +148,8 @@ public class ElectroluxAirBridgeHandler extends BaseBridgeHandler {
 
     @Override
     public void handleCommand(ChannelUID channelUID, Command command) {
-        return;
+        if (CHANNEL_STATUS.equals(channelUID.getId()) && command instanceof RefreshType) {
+            scheduler.schedule(this::refreshAndUpdateStatus, 1, TimeUnit.SECONDS);
+        }
     }
 }
index a1e24492ea570433e7e47c233aa6c13c6baa9da8..1fcb8e2b6cfa44851ffe5afb0e48495c7baf09d5 100644 (file)
@@ -22,6 +22,7 @@ import javax.measure.quantity.Temperature;
 
 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;
@@ -38,6 +39,7 @@ 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;
@@ -66,30 +68,62 @@ public class ElectroluxAirHandler extends BaseThingHandler {
     public void handleCommand(ChannelUID channelUID, Command command) {
         logger.debug("Command received: {}", command);
         if (CHANNEL_STATUS.equals(channelUID.getId()) || command instanceof RefreshType) {
-            update();
+            Bridge bridge = getBridge();
+            if (bridge != null) {
+                BridgeHandler bridgeHandler = bridge.getHandler();
+                if (bridgeHandler != null) {
+                    bridgeHandler.handleCommand(channelUID, command);
+                }
+            }
         } else {
             ElectroluxPureA9DTO dto = getElectroluxPureA9DTO();
-            ElectroluxDeltaAPI api = getElectroluxDeltaAPO();
+            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.getPncId());
+                        api.workModePowerOff(dto.getApplianceId());
                     } else if (command.toString().equals(COMMAND_WORKMODE_AUTO)) {
-                        api.workModeAuto(dto.getPncId());
+                        api.workModeAuto(dto.getApplianceId());
                     } else if (command.toString().equals(COMMAND_WORKMODE_MANUAL)) {
-                        api.workModeManual(dto.getPncId());
+                        api.workModeManual(dto.getApplianceId());
                     }
                 } else if (CHANNEL_FAN_SPEED.equals(channelUID.getId())) {
-                    api.setFanSpeedLevel(dto.getPncId(), Integer.parseInt(command.toString()));
+                    api.setFanSpeedLevel(dto.getApplianceId(), Integer.parseInt(command.toString()));
                 } else if (CHANNEL_IONIZER.equals(channelUID.getId())) {
                     if (command == OnOffType.OFF) {
-                        api.setIonizer(dto.getPncId(), "false");
+                        api.setIonizer(dto.getApplianceId(), "false");
                     } else if (command == OnOffType.ON) {
-                        api.setIonizer(dto.getPncId(), "true");
+                        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);
+                    }
+                }
             }
         }
     }
@@ -115,7 +149,7 @@ public class ElectroluxAirHandler extends BaseThingHandler {
         }
     }
 
-    private @Nullable ElectroluxDeltaAPI getElectroluxDeltaAPO() {
+    private @Nullable ElectroluxDeltaAPI getElectroluxDeltaAPI() {
         Bridge bridge = getBridge();
         if (bridge != null) {
             ElectroluxAirBridgeHandler handler = (ElectroluxAirBridgeHandler) bridge.getHandler();
@@ -143,6 +177,7 @@ public class ElectroluxAirHandler extends BaseThingHandler {
             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);
@@ -152,38 +187,39 @@ public class ElectroluxAirHandler extends BaseThingHandler {
     private State getValue(String channelId, ElectroluxPureA9DTO dto) {
         switch (channelId) {
             case CHANNEL_TEMPERATURE:
-                return new QuantityType<Temperature>(dto.getTwin().getProperties().getReported().getTemp(),
-                        SIUnits.CELSIUS);
+                return new QuantityType<Temperature>(dto.getProperties().getReported().getTemp(), SIUnits.CELSIUS);
             case CHANNEL_HUMIDITY:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getHumidity(),
-                        Units.PERCENT);
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getHumidity(), Units.PERCENT);
             case CHANNEL_TVOC:
-                return new QuantityType<Density>(dto.getTwin().getProperties().getReported().gettVOC(),
+                return new QuantityType<Density>(dto.getProperties().getReported().getTVOC(),
                         Units.MICROGRAM_PER_CUBICMETRE);
             case CHANNEL_PM1:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getpM1(),
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getPM1(),
                         Units.PARTS_PER_BILLION);
             case CHANNEL_PM25:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getpM25(),
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getPM25(),
                         Units.PARTS_PER_BILLION);
             case CHANNEL_PM10:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getpM10(),
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getPM10(),
                         Units.PARTS_PER_BILLION);
             case CHANNEL_CO2:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getcO2(),
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getCO2(),
                         Units.PARTS_PER_MILLION);
             case CHANNEL_FAN_SPEED:
-                return new StringType(Integer.toString(dto.getTwin().getProperties().getReported().getFanspeed()));
+                return new StringType(Integer.toString(dto.getProperties().getReported().getFanspeed()));
             case CHANNEL_FILTER_LIFE:
-                return new QuantityType<Dimensionless>(dto.getTwin().getProperties().getReported().getFilterLife(),
+                return new QuantityType<Dimensionless>(dto.getProperties().getReported().getFilterLife(),
                         Units.PERCENT);
             case CHANNEL_IONIZER:
-                return OnOffType.from(dto.getTwin().getProperties().getReported().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.getTwin().getProperties().getReported().workmode);
+                return new StringType(dto.getProperties().getReported().getWorkmode());
             case CHANNEL_DOOR_OPEN:
-                return dto.getTwin().getProperties().getReported().doorOpen ? OpenClosedType.OPEN
-                        : OpenClosedType.CLOSED;
+                return dto.getProperties().getReported().isDoorOpen() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
         }
         return UnDefType.UNDEF;
     }
@@ -196,13 +232,12 @@ public class ElectroluxAirHandler extends BaseThingHandler {
             if (bridgeHandler != null) {
                 ElectroluxPureA9DTO dto = bridgeHandler.getElectroluxAirThings().get(config.getDeviceId());
                 if (dto != null) {
-                    properties.put(Thing.PROPERTY_VENDOR, dto.getApplicancesInfo().brand);
-                    properties.put(PROPERTY_COLOUR, dto.getApplicancesInfo().colour);
-                    properties.put(PROPERTY_DEVICE, dto.getApplicancesInfo().device);
-                    properties.put(Thing.PROPERTY_MODEL_ID, dto.getApplicancesInfo().model);
-                    properties.put(Thing.PROPERTY_SERIAL_NUMBER, dto.getApplicancesInfo().serialNumber);
-                    properties.put(Thing.PROPERTY_FIRMWARE_VERSION,
-                            dto.getTwin().getProperties().getReported().frmVerNIU);
+                    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());
                 }
             }
         }
index 0286bee26f5dbeedaa8df063ba29ca63efa7cc99..8f481de8cbcbcb3c45e6a0799356d03bc558b68f 100644 (file)
@@ -50,12 +50,16 @@ 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
index a69ca57505fb059f7e11847ff24454387c4c7af7..4f72d7387bcbe30cfe1b197508eb7395073a7437 100644 (file)
                        <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>
                <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>
diff --git a/bundles/org.openhab.binding.electroluxair/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.electroluxair/src/main/resources/OH-INF/update/instructions.xml
new file mode 100644 (file)
index 0000000..43ed585
--- /dev/null
@@ -0,0 +1,17 @@
+<?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>