]> git.basschouten.com Git - openhab-addons.git/commitdiff
[tapocontrol] Moved error messages to i18n (#14790)
authorChristian Wild <40909464+wildcs@users.noreply.github.com>
Fri, 5 May 2023 07:12:03 +0000 (09:12 +0200)
committerGitHub <noreply@github.com>
Fri, 5 May 2023 07:12:03 +0000 (09:12 +0200)
* [tapocontrol] Moved error messages to i18n

---------

Signed-off-by: Christian Wild <christian@wildclan.de>
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoCloudConnector.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceConnector.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/api/TapoDeviceHttpApi.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorCode.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorConstants.java [deleted file]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorType.java [new file with mode: 0644]
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/device/TapoDevice.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/helpers/TapoErrorHandler.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoEnergyData.java
bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/structures/TapoLightEffect.java
bundles/org.openhab.binding.tapocontrol/src/main/resources/OH-INF/i18n/tapocontrol.properties

index c442964c9c16462dd4ef28ab14976aa705fadd77..81cf005e91128df8d4a4c5f47933578fa6f56dfe 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.tapocontrol.internal.api;
 
 import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
-import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants.*;
+import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 
 import java.util.UUID;
 import java.util.concurrent.TimeoutException;
@@ -139,11 +139,11 @@ public class TapoCloudConnector {
                     logger.trace("cloud returns error: '{}'", rBody);
                 }
             } else {
-                handleError(new TapoErrorHandler(ERR_JSON_DECODE_FAIL));
+                handleError(new TapoErrorHandler(ERR_API_JSON_DECODE_FAIL));
                 logger.trace("unexpected json-response '{}'", rBody);
             }
         } else {
-            handleError(new TapoErrorHandler(ERR_HTTP_RESPONSE, ERR_HTTP_RESPONSE_MSG));
+            handleError(new TapoErrorHandler(ERR_BINDING_HTTP_RESPONSE));
             logger.warn("invalid response while login");
             token = "";
         }
@@ -229,7 +229,7 @@ public class TapoCloudConnector {
             handleError(new TapoErrorHandler(e));
         } catch (TimeoutException e) {
             logger.debug("({}) sending request timeout: {}", uid, e.toString());
-            handleError(new TapoErrorHandler(ERR_CONNECT_TIMEOUT, e.toString()));
+            handleError(new TapoErrorHandler(ERR_BINDING_CONNECT_TIMEOUT, e.toString()));
         } catch (Exception e) {
             logger.debug("({}) sending request failed: {}", uid, e.toString());
             handleError(new TapoErrorHandler(e));
index 33594f4d6fd0b8804e1f8baba1fe2508ab68acdd..0913654bc7dd559fc274ed1c835f4dfdaa8c3d55 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.tapocontrol.internal.api;
 
 import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
-import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants.*;
+import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
 import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.jsonObjectToInt;
 
@@ -97,7 +97,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
             return this.loggedIn();
         } else {
             logger.debug("({}) no ping while login '{}'", uid, this.ipAddress);
-            handleError(new TapoErrorHandler(ERR_DEVICE_OFFLINE, "no ping while login"));
+            handleError(new TapoErrorHandler(ERR_BINDING_DEVICE_OFFLINE, "no ping while login"));
             return false;
         }
     }
@@ -296,7 +296,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
     @Override
     protected void handleSuccessResponse(String responseBody) {
         JsonObject jsnResult = getJsonFromResponse(responseBody);
-        Integer errorCode = jsonObjectToInt(jsnResult, "error_code", ERR_JSON_DECODE_FAIL);
+        Integer errorCode = jsonObjectToInt(jsnResult, "error_code", ERR_API_JSON_DECODE_FAIL.getCode());
         if (errorCode != 0) {
             logger.debug("({}) set deviceInfo not successful: {}", uid, jsnResult);
             this.device.handleConnectionState();
@@ -409,7 +409,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
             }
         }
         logger.debug("({}) sendPayload exception {}", uid, responseBody);
-        handleError(new TapoErrorHandler(ERR_HTTP_RESPONSE));
+        handleError(new TapoErrorHandler(ERR_BINDING_HTTP_RESPONSE));
         return new JsonObject();
     }
 
@@ -440,7 +440,7 @@ public class TapoDeviceConnector extends TapoDeviceHttpApi {
         } else {
             logger.trace("({})  device is offline (no ping)", uid);
             if (raiseError) {
-                handleError(new TapoErrorHandler(ERR_DEVICE_OFFLINE));
+                handleError(new TapoErrorHandler(ERR_BINDING_DEVICE_OFFLINE));
             }
             logout();
             return false;
index 3e58ead0d8b1b4ffe9527c1197c6c2a3fa698137..26ed25aebaee15cd6d074810940ba48a8b7cbc38 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.tapocontrol.internal.api;
 
 import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
-import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants.*;
+import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
 
 import java.util.concurrent.TimeUnit;
@@ -167,7 +167,7 @@ public class TapoDeviceHttpApi {
             }
         } catch (Exception e) {
             logger.debug("({}) could not createHandshake: {}", uid, e.toString());
-            handleError(new TapoErrorHandler(ERR_HAND_SHAKE_FAILED, "could not createHandshake"));
+            handleError(new TapoErrorHandler(ERR_API_HAND_SHAKE_FAILED, "could not createHandshake"));
         }
         return cookie;
     }
@@ -186,7 +186,7 @@ public class TapoDeviceHttpApi {
             return jsonObjectToString(jsonObj.getAsJsonObject("result"), "key");
         } else {
             logger.warn("({}) could not getKeyFromResponse '{}'", uid, rBody);
-            handleError(new TapoErrorHandler(ERR_HAND_SHAKE_FAILED, "could not getKeyFromResponse"));
+            handleError(new TapoErrorHandler(ERR_API_HAND_SHAKE_FAILED, "could not getKeyFromResponse"));
         }
         return "";
     }
@@ -204,7 +204,7 @@ public class TapoDeviceHttpApi {
             logger.trace("({}) got cookie: '{}'", uid, cookie);
         } catch (Exception e) {
             logger.warn("({}) could not getCookieFromResponse", uid);
-            handleError(new TapoErrorHandler(ERR_HAND_SHAKE_FAILED, "could not getCookieFromResponse"));
+            handleError(new TapoErrorHandler(ERR_API_HAND_SHAKE_FAILED, "could not getCookieFromResponse"));
         }
         return cookie;
     }
@@ -258,7 +258,7 @@ public class TapoDeviceHttpApi {
             /* get errocode (0=success) */
             JsonObject jsonObject = GSON.fromJson(decryptedResponse, JsonObject.class);
             if (jsonObject != null) {
-                Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
+                Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_API_JSON_DECODE_FAIL.getCode());
                 if (errorCode == 0) {
                     /* return result if set / else request was successful */
                     result = jsonObjectToString(jsonObject.getAsJsonObject("result"), "token");
@@ -269,11 +269,11 @@ public class TapoDeviceHttpApi {
                 }
             } else {
                 logger.debug("({}) unexpected json-response '{}'", uid, decryptedResponse);
-                tapoError.raiseError(ERR_JSON_ENCODE_FAIL, "could not get token");
+                tapoError.raiseError(ERR_API_JSON_ENCODE_FAIL, "could not get token");
             }
         } else {
             logger.debug("({}) invalid response while login", uid);
-            tapoError.raiseError(ERR_HTTP_RESPONSE, "invalid response while login");
+            tapoError.raiseError(ERR_BINDING_HTTP_RESPONSE, "invalid response while login");
         }
         /* handle error */
         if (tapoError.hasError()) {
@@ -315,7 +315,7 @@ public class TapoDeviceHttpApi {
             handleError(new TapoErrorHandler(e));
         } catch (TimeoutException e) {
             logger.debug("({}) sending request timeout: {}", uid, e.toString());
-            handleError(new TapoErrorHandler(ERR_CONNECT_TIMEOUT, e.toString()));
+            handleError(new TapoErrorHandler(ERR_BINDING_CONNECT_TIMEOUT, e.toString()));
         } catch (Exception e) {
             logger.debug("({}) sending request failed: {}", uid, e.toString());
             handleError(new TapoErrorHandler(e));
@@ -355,14 +355,14 @@ public class TapoDeviceHttpApi {
                         String errorMessage = getValueOrDefault(e.getMessage(), "");
                         if (e instanceof TimeoutException) {
                             logger.debug("({}) sendAsyncRequest timeout'{}'", uid, errorMessage);
-                            handleError(new TapoErrorHandler(ERR_CONNECT_TIMEOUT, errorMessage));
+                            handleError(new TapoErrorHandler(ERR_BINDING_CONNECT_TIMEOUT, errorMessage));
                         } else {
                             logger.debug("({}) sendAsyncRequest failed'{}'", uid, errorMessage);
                             handleError(new TapoErrorHandler(new Exception(e), errorMessage));
                         }
                     } else if (response.getStatus() != 200) {
                         logger.debug("({}) sendAsyncRequest response error'{}'", uid, response.getStatus());
-                        handleError(new TapoErrorHandler(ERR_HTTP_RESPONSE, getContentAsString()));
+                        handleError(new TapoErrorHandler(ERR_BINDING_HTTP_RESPONSE, getContentAsString()));
                     } else {
                         /* request successful */
                         String rBody = getContentAsString();
@@ -411,10 +411,10 @@ public class TapoDeviceHttpApi {
                 String responseBody = response.getContentAsString();
                 return getErrorCode(responseBody);
             } else {
-                return ERR_HTTP_RESPONSE;
+                return ERR_BINDING_HTTP_RESPONSE.getCode();
             }
         } catch (Exception e) {
-            return ERR_HTTP_RESPONSE;
+            return ERR_BINDING_HTTP_RESPONSE.getCode();
         }
     }
 
@@ -428,7 +428,7 @@ public class TapoDeviceHttpApi {
         try {
             JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
             /* get errocode (0=success) */
-            Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
+            Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_API_JSON_DECODE_FAIL.getCode());
             if (errorCode == 0) {
                 return 0;
             } else {
@@ -437,7 +437,7 @@ public class TapoDeviceHttpApi {
                 return errorCode;
             }
         } catch (Exception e) {
-            return ERR_HTTP_RESPONSE;
+            return ERR_BINDING_HTTP_RESPONSE.getCode();
         }
     }
 
@@ -451,7 +451,7 @@ public class TapoDeviceHttpApi {
         if (isValidJson(responseBody)) {
             JsonObject jsonObject = GSON.fromJson(responseBody, JsonObject.class);
             /* get errocode (0=success) */
-            Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_JSON_DECODE_FAIL);
+            Integer errorCode = jsonObjectToInt(jsonObject, "error_code", ERR_API_JSON_DECODE_FAIL.getCode());
             if (errorCode > 0) {
                 return true;
             }
@@ -491,7 +491,7 @@ public class TapoDeviceHttpApi {
                 String encryptedResponse = jsonObjectToString(jsonObject.getAsJsonObject("result"), "response");
                 return tapoCipher.decode(encryptedResponse);
             } else {
-                handleError(new TapoErrorHandler(ERR_JSON_DECODE_FAIL));
+                handleError(new TapoErrorHandler(ERR_API_JSON_DECODE_FAIL));
             }
         } catch (Exception ex) {
             logger.debug("({}) exception '{}' decryptingResponse: '{}'", uid, ex.toString(), responseBody);
@@ -549,7 +549,7 @@ public class TapoDeviceHttpApi {
         } else {
             logger.trace("({}) not logged in", uid);
             if (raiseError) {
-                handleError(new TapoErrorHandler(ERR_LOGIN));
+                handleError(new TapoErrorHandler(ERR_API_LOGIN));
             }
             return false;
         }
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorCode.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorCode.java
new file mode 100644 (file)
index 0000000..a96b8f2
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2010-2023 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.tapocontrol.internal.constants;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link TapoErrorCode} enum lists known errorcodes can be received or thrown by binding
+ *
+ * @author Christian Wild - Initial contribution
+ */
+@NonNullByDefault
+public enum TapoErrorCode {
+    NO_ERROR(0),
+    ERR_UNKNOWN(-1, TapoErrorType.UNKNOWN),
+    ERR_API_SESSION_TIMEOUT(9999, TapoErrorType.COMMUNICATION_RETRY),
+    ERR_API_NULL_TRANSPORT(1000),
+    ERR_API_REQUEST(1002),
+    ERR_API_HAND_SHAKE_FAILED(1100, TapoErrorType.COMMUNICATION_RETRY),
+    ERR_API_LOGIN_FAILED(1111),
+    ERR_API_HTTP_TRANSPORT_FAILED(1112),
+    ERR_API_MULTI_REQUEST_FAILED(1200),
+    ERR_API_JSON_DECODE_FAIL(-1003),
+    ERR_API_JSON_ENCODE_FAIL(-1004),
+    ERR_API_AES_DECODE_FAIL(-1005),
+    ERR_API_REQUEST_LEN_ERROR(-1006),
+    ERR_API_CLOUD_FAILED(-1007),
+    ERR_API_PARAMS(-1008),
+    ERR_API_RSA_KEY_LENGTH(-1010),
+    ERR_API_SESSION_PARAM(-1101),
+    ERR_API_QUICK_SETUP(-1201),
+    ERR_API_DEVICE(-1301),
+    ERR_API_DEVICE_NEXT_EVENT(-1302),
+    ERR_API_FIRMWARE(-1401),
+    ERR_API_FIRMWARE_VER_ERROR(-1402),
+    ERR_API_LOGIN(-1501),
+    ERR_API_TIME(-1601),
+    ERR_API_TIME_SYS(-1602),
+    ERR_API_TIME_SAVE(-1603),
+    ERR_API_WIRELESS(-1701),
+    ERR_API_WIRELESS_UNSUPPORTED(-1702),
+    ERR_API_SCHEDULE(-1801),
+    ERR_API_SCHEDULE_FULL(-1802),
+    ERR_API_SCHEDULE_CONFLICT(-1803),
+    ERR_API_SCHEDULE_SAVE(-1804),
+    ERR_API_SCHEDULE_INDEX(-1805),
+    ERR_API_COUNTDOWN(-1901),
+    ERR_API_COUNTDOWN_CONFLICT(-1902),
+    ERR_API_COUNTDOWN_SAVE(-1903),
+    ERR_API_ANTITHEFT(-2001),
+    ERR_API_ANTITHEFT_CONFLICT(-2002),
+    ERR_API_ANTITHEFT_SAVE(-2003),
+    ERR_API_ACCOUNT(-2101),
+    ERR_API_STAT(-2201),
+    ERR_API_STAT_SAVE(-2202),
+    ERR_API_DST(-2301),
+    ERR_API_DST_SAVE(-2302),
+
+    // List of Cloud-ErrorCodes
+    ERR_CLOUD_API_RATE(-20004),
+    ERR_CLOUD_CREDENTIALS(-20601),
+    ERR_CLOUD_JSON_FORMAT(-10100),
+    ERR_CLOUD_METHOD_MISSING(-20103),
+    ERR_CLOUD_PARAMETER_MISSING(-20104),
+    ERR_CLOUD_TOKEN_EXPIRED(-20651),
+
+    // List of Binding-ErrorCodes
+    ERR_BINDING_HTTP_RESPONSE(9001, TapoErrorType.COMMUNICATION_ERROR),
+    ERR_BINDING_COOKIE(9002, TapoErrorType.COMMUNICATION_ERROR),
+    ERR_BINDING_CREDENTIALS(9003, TapoErrorType.CONFIGURATION_ERROR),
+    ERR_BINDING_DEVICE_OFFLINE(9009, TapoErrorType.COMMUNICATION_ERROR),
+    ERR_BINDING_CONNECT_TIMEOUT(9010, TapoErrorType.COMMUNICATION_ERROR),
+
+    // List of Binding-Config-ErrorCodes
+    ERR_CONFIG_IP(10001, TapoErrorType.CONFIGURATION_ERROR), // ip not set
+    ERR_CONFIG_CREDENTIALS(10002, TapoErrorType.CONFIGURATION_ERROR), // credentials not set
+    ERR_CONFIG_NO_BRIDGE(10003, TapoErrorType.CONFIGURATION_ERROR); // no bridge configured
+
+    private Integer code;
+    private TapoErrorType errorType;
+
+    /* set code */
+    private TapoErrorCode(Integer code) {
+        this.code = code;
+        this.errorType = TapoErrorType.GENERAL;
+    }
+
+    private TapoErrorCode(Integer code, TapoErrorType errorType) {
+        this.code = code;
+        this.errorType = errorType;
+    }
+
+    /* get vlaues */
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public TapoErrorType getType() {
+        return this.errorType;
+    }
+
+    public static TapoErrorCode fromCode(int errorCode) {
+        for (TapoErrorCode e : TapoErrorCode.values()) {
+            if (e.code.equals(errorCode))
+                return e;
+        }
+        return ERR_UNKNOWN;
+    }
+}
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorConstants.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorConstants.java
deleted file mode 100644 (file)
index db9c376..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Copyright (c) 2010-2023 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.tapocontrol.internal.constants;
-
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * The {@link TapoErrorConstants} class defines error-message constants
- *
- * @author Christian Wild - Initial contribution
- */
-@NonNullByDefault
-public class TapoErrorConstants {
-    /****************************************
-     * LIST OF ERROR CODES
-     ****************************************/
-    // List of API-ErrorCodes
-    public static final Integer ERR_COMMON_FAILED = -1;
-    public static final Integer ERR_SESSION_TIMEOUT = 9999;
-    public static final Integer ERR_NULL_TRANSPORT = 1000;
-    public static final Integer ERR_REQUEST = 1002;
-    public static final Integer ERR_HAND_SHAKE_FAILED = 1100;
-    public static final Integer ERR_LOGIN_FAILED = 1111;
-    public static final Integer ERR_HTTP_TRANSPORT_FAILED = 1112;
-    public static final Integer ERR_MULTI_REQUEST_FAILED = 1200;
-    public static final Integer ERR_JSON_DECODE_FAIL = -1003;
-    public static final Integer ERR_JSON_ENCODE_FAIL = -1004;
-    public static final Integer ERR_AES_DECODE_FAIL = -1005;
-    public static final Integer ERR_REQUEST_LEN_ERROR = -1006;
-    public static final Integer ERR_CLOUD_FAILED = -1007;
-    public static final Integer ERR_PARAMS = -1008;
-    public static final Integer ERR_RSA_KEY_LENGTH = -1010;
-    public static final Integer ERR_SESSION_PARAM = -1101;
-    public static final Integer ERR_QUICK_SETUP = -1201;
-    public static final Integer ERR_DEVICE = -1301;
-    public static final Integer ERR_DEVICE_NEXT_EVENT = -1302;
-    public static final Integer ERR_FIRMWARE = -1401;
-    public static final Integer ERR_FIRMWARE_VER_ERROR = -1402;
-    public static final Integer ERR_LOGIN = -1501;
-    public static final Integer ERR_TIME = -1601;
-    public static final Integer ERR_TIME_SYS = -1602;
-    public static final Integer ERR_TIME_SAVE = -1603;
-    public static final Integer ERR_WIRELESS = -1701;
-    public static final Integer ERR_WIRELESS_UNSUPPORTED = -1702;
-    public static final Integer ERR_SCHEDULE = -1801;
-    public static final Integer ERR_SCHEDULE_FULL = -1802;
-    public static final Integer ERR_SCHEDULE_CONFLICT = -1803;
-    public static final Integer ERR_SCHEDULE_SAVE = -1804;
-    public static final Integer ERR_SCHEDULE_INDEX = -1805;
-    public static final Integer ERR_COUNTDOWN = -1901;
-    public static final Integer ERR_COUNTDOWN_CONFLICT = -1902;
-    public static final Integer ERR_COUNTDOWN_SAVE = -1903;
-    public static final Integer ERR_ANTITHEFT = -2001;
-    public static final Integer ERR_ANTITHEFT_CONFLICT = -2002;
-    public static final Integer ERR_ANTITHEFT_SAVE = -2003;
-    public static final Integer ERR_ACCOUNT = -2101;
-    public static final Integer ERR_STAT = -2201;
-    public static final Integer ERR_STAT_SAVE = -2202;
-    public static final Integer ERR_DST = -2301;
-    public static final Integer ERR_DST_SAVE = -2302;
-    // -20661
-
-    // List of Binding-ErrorCodes
-    public static final Integer ERR_HTTP_RESPONSE = 9001;
-    public static final Integer ERR_COOKIE = 9002;
-    public static final Integer ERR_CREDENTIALS = 9003;
-    public static final Integer ERR_DEVICE_OFFLINE = 9009;
-    public static final Integer ERR_CONNECT_TIMEOUT = 9010;
-
-    // List of Config-ErrorCodes
-    public static final Integer ERR_CONF_IP = 10001; // ip not set
-    public static final Integer ERR_CONF_CREDENTIALS = 10002; // credentials not set
-    public static final Integer ERR_NO_BRIDGE = 10003; // no bridge configured
-
-    /****************************************
-     * LIST OF ERROR MESSAGES
-     ****************************************/
-    // List of CLOUD-Error-Messages
-    public static final String ERR_COMMON_FAILED_MSG = ""; // -1;
-    public static final String ERR_SESSION_TIMEOUT_MSG = "Session Timeout"; // 9999;
-    public static final String ERR_NULL_TRANSPORT_MSG = ""; // 1000;
-    public static final String ERR_REQUEST_MSG = "Invalid request or command"; // 1002;
-    public static final String ERR_HAND_SHAKE_FAILED_MSG = "Can't create handshake"; // 1100;
-    public static final String ERR_LOGIN_FAILED_MSG = ""; // 1111;
-    public static final String ERR_HTTP_TRANSPORT_FAILED_MSG = ""; // 1112;
-    public static final String ERR_MULTI_REQUEST_FAILED_MSG = ""; // 1200;
-    public static final String ERR_JSON_DECODE_FAIL_MSG = "json decode failed"; // -1003;
-    public static final String ERR_JSON_ENCODE_FAIL_MSG = "json encode failed"; // -1004;
-    public static final String ERR_AES_DECODE_FAIL_MSG = ""; // -1005;
-    public static final String ERR_REQUEST_LEN_ERROR_MSG = ""; // -1006;
-    public static final String ERR_CLOUD_FAILED_MSG = ""; // -1007;
-    public static final String ERR_PARAMS_MSG = "received invalid parameter"; // -1008;
-    public static final String ERR_RSA_KEY_LENGTH_MSG = "Invalid Public Key Length"; // -1010;
-    public static final String ERR_SESSION_PARAM_MSG = ""; // -1101;
-    public static final String ERR_QUICK_SETUP_MSG = ""; // -1201;
-    public static final String ERR_DEVICE_MSG = ""; // -1301;
-    public static final String ERR_DEVICE_NEXT_EVENT_MSG = ""; // -1302;
-    public static final String ERR_FIRMWARE_MSG = ""; // -1401;
-    public static final String ERR_FIRMWARE_VER_ERROR_MSG = ""; // -1402;
-    public static final String ERR_LOGIN_MSG = "Login Error"; // -1501;
-    public static final String ERR_TIME_MSG = ""; // -1601;
-    public static final String ERR_TIME_SYS_MSG = ""; // -1602;
-    public static final String ERR_TIME_SAVE_MSG = ""; // -1603;
-    public static final String ERR_WIRELESS_MSG = ""; // -1701;
-    public static final String ERR_WIRELESS_UNSUPPORTED_MSG = ""; // -1702;
-    public static final String ERR_SCHEDULE_MSG = ""; // -1801;
-    public static final String ERR_SCHEDULE_FULL_MSG = ""; // -1802;
-    public static final String ERR_SCHEDULE_CONFLICT_MSG = ""; // -1803;
-    public static final String ERR_SCHEDULE_SAVE_MSG = ""; // -1804;
-    public static final String ERR_SCHEDULE_INDEX_MSG = ""; // -1805;
-    public static final String ERR_COUNTDOWN_MSG = ""; // -1901;
-    public static final String ERR_COUNTDOWN_CONFLICT_MSG = ""; // -1902;
-    public static final String ERR_COUNTDOWN_SAVE_MSG = ""; // -1903;
-    public static final String ERR_ANTITHEFT_MSG = ""; // -2001;
-    public static final String ERR_ANTITHEFT_CONFLICT_MSG = ""; // -2002;
-    public static final String ERR_ANTITHEFT_SAVE_MSG = ""; // -2003;
-    public static final String ERR_ACCOUNT_MSG = ""; // -2101;
-    public static final String ERR_STAT_MSG = ""; // -2201;
-    public static final String ERR_STAT_SAVE_MSG = ""; // -2202;
-    public static final String ERR_DST_MSG = ""; // -2301;
-    public static final String ERR_DST_SAVE_MSG = ""; // -2302;
-
-    // List of Binding-Error-Messages
-    public static final String ERR_HTTP_RESPONSE_MSG = "Invalid HTTP-Response"; // 9001
-    public static final String ERR_COOKIE_MSG = "Cookie Error"; // 9002
-    public static final String ERR_DEVICE_OFFLINE_MSG = "Device Offline"; // 9009
-    public static final String ERR_CREDENTIALS_MSG = "Invalid Request or Credentials";
-    public static final String ERR_CONNECT_TIMEOUT_MSG = "Connection Timeout - device not reachable";
-
-    // List of Config-Error-Messages
-    public static final String ERR_CONF_IP_MSG = "IP-Address not valid"; // 10001;
-    public static final String ERR_CONF_CREDENTIALS_MSG = "credentials not set (bridge)"; // 10002;
-    public static final String ERR_NO_BRIDGE_MSG = "no bridge configured"; // 10003;
-
-    /****************************************
-     * ErrorTypes
-     ****************************************/
-    // communication errors - set device to offline (retry connect)
-    public static final Set<Integer> LIST_COMMUNICATION_ERRORS = Set.of(ERR_HTTP_RESPONSE, ERR_COOKIE,
-            ERR_DEVICE_OFFLINE, ERR_CONNECT_TIMEOUT);
-    // configuration errors - set device to state configuration error (don't retry)
-    public static final Set<Integer> LIST_CONFIGURATION_ERRORS = Set.of(ERR_CREDENTIALS);
-    // reauthenticate errors (trying login immediatly)
-    public static final Set<Integer> LIST_REAUTH_ERRORS = Set.of(ERR_SESSION_TIMEOUT, ERR_HAND_SHAKE_FAILED);
-}
diff --git a/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorType.java b/bundles/org.openhab.binding.tapocontrol/src/main/java/org/openhab/binding/tapocontrol/internal/constants/TapoErrorType.java
new file mode 100644 (file)
index 0000000..ee7288d
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2023 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.tapocontrol.internal.constants;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link TapoErrorType} enum lists known errortypes can be received or thrown by binding
+ *
+ * @author Christian Wild - Initial contribution
+ */
+@NonNullByDefault
+public enum TapoErrorType {
+    COMMUNICATION_ERROR, // communication error
+    COMMUNICATION_RETRY, // communication error - retry to connect immediately
+    CONFIGURATION_ERROR, // configuration error
+    GENERAL, // general error (e.g. known api err)
+    UNKNOWN // unknown error
+}
index d169c0fd055c526d2405a7aed5394a6e2db843ca..dc2455f3380950740c134b5846a5a4483985fbaf 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.tapocontrol.internal.device;
 
 import static org.openhab.binding.tapocontrol.internal.constants.TapoBindingSettings.*;
-import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants.*;
+import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 import static org.openhab.binding.tapocontrol.internal.constants.TapoThingConstants.*;
 import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
 
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.tapocontrol.internal.api.TapoDeviceConnector;
+import org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode;
 import org.openhab.binding.tapocontrol.internal.helpers.TapoErrorHandler;
 import org.openhab.binding.tapocontrol.internal.structures.TapoChildData;
 import org.openhab.binding.tapocontrol.internal.structures.TapoDeviceConfiguration;
@@ -140,17 +141,17 @@ public abstract class TapoDevice extends BaseThingHandler {
 
         /* check bridge */
         if (bridge == null || !(bridge instanceof TapoBridgeHandler)) {
-            configErr.raiseError(ERR_NO_BRIDGE);
+            configErr.raiseError(ERR_CONFIG_NO_BRIDGE);
             return configErr;
         }
         /* check ip-address */
         if (!config.ipAddress.matches(IPV4_REGEX)) {
-            configErr.raiseError(ERR_CONF_IP);
+            configErr.raiseError(ERR_CONFIG_IP);
             return configErr;
         }
         /* check credentials */
         if (!bridge.getCredentials().areSet()) {
-            configErr.raiseError(ERR_CONF_CREDENTIALS);
+            configErr.raiseError(ERR_CONFIG_CREDENTIALS);
             return configErr;
         }
         return configErr;
@@ -232,10 +233,14 @@ public abstract class TapoDevice extends BaseThingHandler {
      *
      * @return
      */
-    public TapoErrorHandler getError() {
+    public TapoErrorHandler getErrorHandler() {
         return this.deviceError;
     }
 
+    public TapoErrorCode getError() {
+        return this.deviceError.getError();
+    }
+
     /**
      * set device error
      *
@@ -456,21 +461,27 @@ public abstract class TapoDevice extends BaseThingHandler {
      */
     public void handleConnectionState() {
         ThingStatus deviceState = getThing().getStatus();
-        Integer errorCode = deviceError.getCode();
+        TapoErrorCode errorCode = deviceError.getError();
 
-        if (errorCode == 0) {
+        if (errorCode == TapoErrorCode.NO_ERROR) {
             if (deviceState != ThingStatus.ONLINE) {
                 updateStatus(ThingStatus.ONLINE);
             }
-        } else if (LIST_REAUTH_ERRORS.contains(errorCode)) {
-            connect();
-        } else if (LIST_COMMUNICATION_ERRORS.contains(errorCode)) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, deviceError.getMessage());
-            disconnect();
-        } else if (LIST_CONFIGURATION_ERRORS.contains(errorCode)) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, deviceError.getMessage());
         } else {
-            updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, deviceError.getMessage());
+            switch (errorCode.getType()) {
+                case COMMUNICATION_RETRY:
+                    connect();
+                    break;
+                case COMMUNICATION_ERROR:
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, deviceError.getMessage());
+                    disconnect();
+                    break;
+                case CONFIGURATION_ERROR:
+                    updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, deviceError.getMessage());
+                    break;
+                default:
+                    updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, deviceError.getMessage());
+            }
         }
     }
 
index 69710e10acac27b74ea9aefe326b1737a24f8dd4..7efa99280ba3d3f809237a9597683cbd31aaa1cd 100644 (file)
  */
 package org.openhab.binding.tapocontrol.internal.helpers;
 
-import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
-
-import java.lang.reflect.Field;
+import static org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode.*;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.tapocontrol.internal.constants.TapoErrorConstants;
+import org.openhab.binding.tapocontrol.internal.constants.TapoErrorCode;
 
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
@@ -30,9 +28,8 @@ import com.google.gson.JsonObject;
  */
 @NonNullByDefault
 public class TapoErrorHandler extends Exception {
+    private TapoErrorCode errorCode = TapoErrorCode.NO_ERROR;
     private static final long serialVersionUID = 0L;
-    private Integer errorCode = 0;
-    private String errorMessage = "";
     private String infoMessage = "";
     private Gson gson = new Gson();
 
@@ -81,6 +78,25 @@ public class TapoErrorHandler extends Exception {
         raiseError(ex, infoMessage);
     }
 
+    /**
+     * Constructor TapoErrorCodeEnum
+     * 
+     * @param errorCode error code (TapoErrorCodeEnum)
+     */
+    public TapoErrorHandler(TapoErrorCode errorCode) {
+        raiseError(errorCode);
+    }
+
+    /**
+     * Constructor
+     * 
+     * @param errorCode error code (TapoErrorCodeEnum)
+     * @param infoMessage optional info-message
+     */
+    public TapoErrorHandler(TapoErrorCode errorCode, String infoMessage) {
+        raiseError(errorCode, infoMessage);
+    }
+
     /***********************************
      *
      * Private Functions
@@ -90,30 +106,12 @@ public class TapoErrorHandler extends Exception {
     /**
      * GET ERROR-MESSAGE
      * 
-     * @param errCode error Number (or constant ERR_CODE )
-     * @return error-message if set constant ERR_CODE_MSG. if not name of ERR_CODE is returned
+     * @param errCode error Number (or constant ERR_API_CODE )
+     * @return error-message if code found in i18n, else return code
      */
     private String getErrorMessage(Integer errCode) {
-        Field[] fields = TapoErrorConstants.class.getDeclaredFields();
-        /* loop ErrorConstants and search for code in value */
-        for (Field f : fields) {
-            String constName = f.getName();
-            try {
-                Integer val = (Integer) f.get(this);
-                if (val != null && val.equals(errCode)) {
-                    Field constantName = TapoErrorConstants.class.getDeclaredField(constName + "_MSG");
-                    String msg = getValueOrDefault(constantName.get(null), "").toString();
-                    if (msg.length() > 2) {
-                        return msg;
-                    } else {
-                        return infoMessage + " (" + constName + ")";
-                    }
-                }
-            } catch (Exception e) {
-                // next loop
-            }
-        }
-        return infoMessage + " (" + errCode.toString() + ")";
+        String key = TapoErrorCode.fromCode(errCode).name().replace("ERR_", "error-").replace("_", "-").toLowerCase();
+        return String.format("@text/%s [ \"%s\" ]", key, errCode.toString());
     }
 
     /***********************************
@@ -138,9 +136,7 @@ public class TapoErrorHandler extends Exception {
      * @param infoMessage optional info-message
      */
     public void raiseError(Integer errorCode, String infoMessage) {
-        this.errorCode = errorCode;
-        this.infoMessage = infoMessage;
-        this.errorMessage = getErrorMessage(errorCode);
+        raiseError(TapoErrorCode.fromCode(errorCode), infoMessage);
     }
 
     /**
@@ -159,9 +155,27 @@ public class TapoErrorHandler extends Exception {
      * @param infoMessage optional info-message
      */
     public void raiseError(Exception ex, String infoMessage) {
-        this.errorCode = ex.hashCode();
+        raiseError(TapoErrorCode.fromCode(ex.hashCode()), infoMessage);
+    }
+
+    /**
+     * Raises new error
+     * 
+     * @param errorCode error code (TapoErrorCodeEnum)
+     */
+    public void raiseError(TapoErrorCode errorCode) {
+        raiseError(errorCode, "");
+    }
+
+    /**
+     * Raises new error
+     * 
+     * @param errorCode error code (TapoErrorCodeEnum)
+     * @param infoMessage optional info-message
+     */
+    public void raiseError(TapoErrorCode errorCode, String infoMessage) {
+        this.errorCode = errorCode;
         this.infoMessage = infoMessage;
-        this.errorMessage = getValueOrDefault(ex.getMessage(), ex.toString());
     }
 
     /**
@@ -170,17 +184,15 @@ public class TapoErrorHandler extends Exception {
      * @param tapoError
      */
     public void set(TapoErrorHandler tapoError) {
-        this.errorCode = tapoError.getNumber();
+        this.errorCode = TapoErrorCode.fromCode(tapoError.getCode());
         this.infoMessage = tapoError.getExtendedInfo();
-        this.errorMessage = getErrorMessage(this.errorCode);
     }
 
     /**
      * Reset Error
      */
     public void reset() {
-        this.errorCode = 0;
-        this.errorMessage = "";
+        this.errorCode = NO_ERROR;
         this.infoMessage = "";
     }
 
@@ -198,7 +210,7 @@ public class TapoErrorHandler extends Exception {
     @Override
     @Nullable
     public String getMessage() {
-        return this.errorMessage;
+        return getErrorMessage(errorCode.getCode());
     }
 
     /**
@@ -217,7 +229,7 @@ public class TapoErrorHandler extends Exception {
      * @return error code (integer)
      */
     public Integer getCode() {
-        return this.errorCode;
+        return this.errorCode.getCode();
     }
 
     /**
@@ -230,11 +242,11 @@ public class TapoErrorHandler extends Exception {
     }
 
     /**
-     * Get Error Number
+     * Get Error Code
      * 
-     * @return error number
+     * @return error code
      */
-    public Integer getNumber() {
+    public TapoErrorCode getError() {
         return this.errorCode;
     }
 
@@ -244,7 +256,7 @@ public class TapoErrorHandler extends Exception {
      * @return true if has error
      */
     public Boolean hasError() {
-        return this.errorCode != 0;
+        return this.errorCode != NO_ERROR;
     }
 
     /**
@@ -254,7 +266,8 @@ public class TapoErrorHandler extends Exception {
      */
     public JsonObject getJson() {
         JsonObject json;
-        json = gson.fromJson("{'error_code': '" + errorCode + "', 'error_message':'" + errorMessage + "'}",
+        json = gson.fromJson(
+                "{'error_code': '" + errorCode + "', 'error_message':'" + getErrorMessage(getCode()) + "'}",
                 JsonObject.class);
         if (json == null) {
             json = new JsonObject();
index 8210fd844dda52539119a31782a67859f1fd0a34..71fd9804fb1cbf18433fab4630db3b66be850d0f 100644 (file)
@@ -63,7 +63,7 @@ public class TapoEnergyData {
         if (jso.has(JSON_KEY_ENERGY_POWER)) {
             this.jsonObject = jso;
         } else {
-            jsonObject = new JsonObject();
+            this.jsonObject = new JsonObject();
         }
         setData();
         return this;
@@ -88,42 +88,42 @@ public class TapoEnergyData {
      ************************************/
 
     public Number getCurrentPower() {
-        return this.currentPower;
+        return currentPower;
     }
 
     public Number getTodayEnergy() {
-        return this.todayEnergy;
+        return todayEnergy;
     }
 
     public Number getMonthEnergy() {
-        return this.monthEnergy;
+        return monthEnergy;
     }
 
     public Number getYearEnergy() {
         int sum = 0;
-        for (int i = 0; i < this.past1y.length; i++) {
-            sum += this.past1y[i].intValue();
+        for (int i = 0; i < past1y.length; i++) {
+            sum += past1y[i].intValue();
         }
         return sum;
     }
 
     public Number getTodayRuntime() {
-        return this.todayRuntime;
+        return todayRuntime;
     }
 
     public Number getMonthRuntime() {
-        return this.monthRuntime;
+        return monthRuntime;
     }
 
     public Number[] getPast24hUsage() {
-        return this.past24h;
+        return past24h;
     }
 
     public Number[] getPast30dUsage() {
-        return this.past30d;
+        return past30d;
     }
 
     public Number[] getPast1yUsage() {
-        return this.past1y;
+        return past1y;
     }
 }
index 396160f217152327de096e93bb616f80fe47d4b8..d618fefdc7986cb4024a4bd1f820ad8917d4dd91 100644 (file)
@@ -118,31 +118,31 @@ public class TapoLightEffect {
      ************************************/
 
     public Boolean getEnable() {
-        return this.enable;
+        return enable;
     }
 
     public String getId() {
-        return this.id;
+        return id;
     }
 
     public String getName() {
-        return this.name;
+        return name;
     }
 
     public Boolean getCustom() {
-        return this.custom;
+        return custom;
     }
 
     public Integer getBrightness() {
-        return this.brightness;
+        return brightness;
     }
 
     public Integer[] getColorTempRange() {
-        return this.colorTempRange;
+        return colorTempRange;
     }
 
     public Color[] getDisplayColors() {
-        return this.displayColors;
+        return displayColors;
     }
 
     @Override
index 755a90a6b86133351e401b0bc44b23616f7e0a41..c53e9bb902f779fb54cf70ee2744296e4ebf9923 100644 (file)
@@ -163,3 +163,63 @@ channel-type.tapocontrol.effectName.label = Effect Name
 channel-type.tapocontrol.effectName.description = Name of LightningEffect
 channel-type.tapocontrol.effectOn.label = Lightning Effect Enable
 channel-type.tapocontrol.effectOn.description = Switches the lightning effect on/off
+
+# error messages
+
+error-api-account = received account error (-2101)
+error-api-aes-decode-fail = aes decode failed (-1005)
+error-api-antitheft-conflict = device antitheft conflict (-2002)
+error-api-antitheft = device antitheft error (-2001)
+error-api-antitheft-save = antitheft save error (-2003)
+error-api-cloud-failed = cloud failed (-1007)
+error-api-countdown-conflict = api-countdown-conflict (-1902)
+error-api-countdown = api-countdown error (-1901)
+error-api-countdown-save = api-countdown-save error (-1903)
+error-api-device = received device error (-1301)
+error-api-device-next-event = device next event error (-1302)
+error-api-dst = received dst error (-2301)
+error-api-dst-save = received dst-save error (-2302)
+error-api-firmware = firmware error (-1401)
+error-api-firmware-ver-error = firmware version error (-1402)
+error-api-hand-shake-failed = can't create handshake (1100)
+error-api-http-transport-failed = http transport failed (1112)
+error-api-json-decode-fail = json decode failed (-1003)
+error-api-json-encode-fail = json encode failed (-1004)
+error-api-login-failed = login failed (1111)
+error-api-login = invalid request or credentials (-1501)
+error-api-multi-request-failed = multi request failed (1200)
+error-api-null-transport = null transport error (1000)
+error-api-params = received invalid parameter (-1008)
+error-api-quick-setup = quick setup error (-1201)
+error-api-request-len-error = request length error (-1006)
+error-api-request = invalid request or command (1002)
+error-api-rsa-key-length = invalid public key length (-1010)
+error-api-schedule-conflict = schedule conflict error (-1803)
+error-api-schedule-full = schedule full error (-1802)
+error-api-schedule-index = schedule index error (-1805)
+error-api-schedule = schedule error (-1801)
+error-api-schedule-save = saving schedule rule failed (-1804)
+error-api-session-param = invalid session key (-1101)
+error-api-session-timeout = device session expired (9999)
+error-api-stat = state failed (-2201)
+error-api-stat-save = saving state failed (-2202)
+error-api-time = device time error (-1601)
+error-api-time-save = saving time failed (-1603)
+error-api-time-sys = time system error (-1602)
+error-api-wireless = wireless error (-1701)
+error-api-wireless-unsupported = wireless unsuported error (-1702)
+error-binding-connect-timeout = connection timeout - device not reachable (9010)
+error-binding-cookie = cookie error (9002)
+error-binding-credentials = invalid request or credentials (9003)
+error-binding-device-offline = device offline (9009)
+error-binding-http-response = invalid http-response (9001)
+error-cloud-api-rate = api rate limit exceeded (-20004)
+error-cloud-credentials = incorrect email or password (-20601)
+error-cloud-json-format = json format error (-10100)
+error-cloud-method-missing = method does not exist or is not available (-20103)
+error-cloud-parameter-missing = parameter doesn't exist (-20104)
+error-cloud-token-expired = token expired (-20651)
+error-config-credentials = credentials not set (bridge) (10002)
+error-config-ip = ip-address not valid (10001)
+error-config-no-bridge = no bridge configured (10003)
+error-unknown = unknown api error ({0})