]> git.basschouten.com Git - openhab-addons.git/commitdiff
[shelly] Vibration event for DW2 (#10618)
authorMarkus Michels <markus7017@gmail.com>
Sun, 9 May 2021 18:21:35 +0000 (20:21 +0200)
committerGitHub <noreply@github.com>
Sun, 9 May 2021 18:21:35 +0000 (20:21 +0200)
* Adapted to new checkstyle

Signed-off-by: Markus Michels <markus7017@gmail.com>
* stylecheck cnages; fix CoIoT update for vibration, url encode user+pw on
"set login credentials"

Signed-off-by: Markus Michels <markus7017@gmail.com>
* #10617 Vibration event added for DW2

Signed-off-by: Markus Michels <markus7017@gmail.com>
* brackets

Signed-off-by: Markus Michels <markus7017@gmail.com>
* some unused stuff/code removed

Signed-off-by: Markus Michels <markus7017@gmail.com>
21 files changed:
bundles/org.openhab.binding.shelly/README.md
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/ShellyBindingConstants.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiException.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiJsonDTO.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyHttpApi.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoIoTProtocol.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoIoTVersion1.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoIoTVersion2.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/coap/ShellyCoapHandler.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyDiscoveryParticipant.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManager.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerActionPage.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOtaPage.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerOverviewPage.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerServlet.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java
bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/util/ShellyUtils.java

index 459036cb55aa117b3ae1bfe78f74664757c7efcb..501e9dd3226950dcce58fcb35f835ace9eab4202 100644 (file)
@@ -17,6 +17,7 @@ The binding gets in sync with the next status refresh.
 Refer to [Advanced Users](doc/AdvancedUsers.md) for more information on openHAB Shelly integration, e.g. firmware update, network communication or log filtering.
 
 Also check out the [Shelly Manager](doc/ShellyManager.md), which
+
 - provides detailed information on your Shellys
 - helps to diagnose WiFi issues or device instabilities
 - includes some common actions and 
@@ -276,6 +277,7 @@ Check the channel definitions for the various devices to see if the device suppo
 You could use the Shelly App to set the timing for those events. 
 
 If you want to use those events triggering a rule:
+
 - If a physical switch is connected to the Shelly use the input channel(`input` or `input1`/`input2`) to trigger a rule
 - For a momentary button use the `button` trigger channel as trigger, channels `lastEvent` and `eventCount` will provide details on the event 
 
@@ -309,7 +311,7 @@ A new alarm will be triggered on a new condition or every 5 minutes if the condi
 |BATTERY     |Device reported an update to the battery status.                                                                 |
 |TEMP_UNDER  |Below "temperature under" threshold                                                                              |
 |TEMP_OVER   |Above "temperature over" threshold                                                                               |
-
+|VIBRATION   |A vibration/tamper was detected (DW2 only)                                                                       |
 
 Refer to section [Full Example:shelly.rules](#shelly-rules) for examples how to catch alarm triggers in openHAB rules
 
@@ -803,6 +805,7 @@ You can define 2 items (1 Switch, 1 Number) mapping to the same channel, see exa
 |          |lastError    |String   |yes      |Last device error.                                                     |
 |battery   |batteryLevel |Number   |yes      |Battery Level in %                                                     |
 |          |lowBattery   |Switch   |yes      |Low battery alert (< 20%)                                              |
+|device    |alarm        |Trigger  |yes      |Will receive trigger VIBRATION if DW2 detects vibration                |
 
 ### Shelly Motion (thing-type: shellymotion)
 
@@ -1090,8 +1093,8 @@ when
     Channel "shelly:shelly25-roller:XXXXXX:device#alarm"    triggered
 then
     if (receivedEvent !== null) { // A (channel) event triggered the rule
-        eventSource = receivedEvent.getChannel().asString 
-        eventType = receivedEvent.getEvent()
+        eventSource = triggeredChannel
+        eventType = receivedEvent
         ...
     } 
 end
index 09ca61a5301ec87d858c5f4cafb248e2c61c939f..16256635ed062c5e8fabf43d7923084365ab9dcc 100755 (executable)
@@ -191,8 +191,6 @@ public class ShellyBindingConstants {
     public static final String PROPERTY_UPDATE_NEW_VERS = "updateNewVersion";
     public static final String PROPERTY_COAP_DESCR = "coapDeviceDescr";
     public static final String PROPERTY_COAP_VERSION = "coapVersion";
-    public static final String PROPERTY_STATS_TIMEOUTS = "statsTimeoutErrors";
-    public static final String PROPERTY_STATS_TRECOVERED = "statsTimeoutsRecovered";
     public static final String PROPERTY_COIOTAUTO = "coiotAutoEnable";
 
     // Relay
@@ -337,6 +335,7 @@ public class ShellyBindingConstants {
     public static final String ALARM_TYPE_LOADERR = "LOAD_ERROR";
     public static final String ALARM_TYPE_SENSOR_ERROR = "SENSOR_ERROR";
     public static final String ALARM_TYPE_LOW_BATTERY = "LOW_BATTERY";
+    public static final String EVENT_TYPE_VIBRATION = "VIBRATION";
 
     // Event types
     public static final String EVENT_TYPE_RELAY = "relay";
@@ -364,4 +363,5 @@ public class ShellyBindingConstants {
     public static final int UPDATE_MIN_DELAY = 15;// update every x triggers or when a key was pressed
     public static final int UPDATE_SETTINGS_INTERVAL_SECONDS = 60; // check for updates every x sec
     public static final int HEALTH_CHECK_INTERVAL_SEC = 300; // Health check interval, 5min
+    public static final int VIBRATION_FILTER_SEC = 5; // Absore duplicate vibration events for xx sec
 }
index 0e7df9d5a3829db4b5940125172209d5d1202472..0cf28c4d1a6b07b2a9e8884e9adea67f87de3f30 100644 (file)
@@ -34,7 +34,7 @@ public class ShellyApiException extends Exception {
     private static final long serialVersionUID = -5809459454769761821L;
 
     private ShellyApiResult apiResult = new ShellyApiResult();
-    private static String NONE = "none";
+    private static final String NONE = "none";
 
     public ShellyApiException(Exception exception) {
         super(exception);
@@ -117,7 +117,7 @@ public class ShellyApiException extends Exception {
     }
 
     private boolean isEmpty() {
-        return nonNullString(super.getMessage()).equals(NONE);
+        return NONE.equals(nonNullString(super.getMessage()));
     }
 
     private static String nonNullString(@Nullable String s) {
index ca1d1379a93a49ef27e756f6b6c123641302fbdd..d103ee9b112375f7ca38416f274f0753e7b67b21 100644 (file)
@@ -379,9 +379,6 @@ public class ShellyApiJsonDTO {
         public String pushLongUrl; // to access when roller stopped
         @SerializedName("shortpush_url")
         public String pushShortUrl; // to access when roller stopped
-
-        public Boolean schedule;
-        // ArrayList<ShellySettingsScheduleRules> schedule_rules;
     }
 
     public static class ShellySettingsDimmer {
@@ -442,8 +439,6 @@ public class ShellyApiJsonDTO {
         public Boolean isValid;
         @SerializedName("safety_switch")
         public Boolean safetySwitch;
-        public Boolean schedule;
-        // ArrayList<ShellySettingsScheduleRules> schedule_rules; // not used for now
         @SerializedName("obstacle_mode")
         public String obstaclMode; // SHELLY_OBSTMODE_
         @SerializedName("obstacle_action")
@@ -468,7 +463,8 @@ public class ShellyApiJsonDTO {
         public Boolean ison; // true: output is ON
         public Integer brightness;
         public Integer transition;
-        public String default_state;
+        @SerializedName("default_state")
+        public String defaultState;
         @SerializedName("auto_on")
         public Double autoOn; // Automatic flip back timer, seconds. Will engage after turning Shelly1 OFF.
         @SerializedName("auto_off")
@@ -565,20 +561,14 @@ public class ShellyApiJsonDTO {
         public ShellySensorSleepMode sleepMode; // FW 1.6
         @SerializedName("external_power")
         public Integer externalPower; // H&T FW 1.6, seems to be the same like charger for the Sense
-        public Boolean debug_enable; // FW 1.10+
+        @SerializedName("debug_enable") // FW 1.10+
+        public Boolean debugEnable;
 
         public String timezone;
         public Double lat;
         public Double lng;
         public Boolean tzautodetect;
         public String time;
-        // @SerializedName("tz_utc_offset")
-        // public Integer tzUTCOoffset; // FW 1.6+
-        // @SerializedName("tz_dst")
-        // public Boolean tzDdst; // FW 1.6+
-        // @SerializedName("tz_dst_auto")
-        // public Boolean tzDstAuto; // FW 1.6+
-        // public Long unixtime; // FW 1.6+
 
         public ShellySettingsHwInfo hwinfo;
         public String mode;
@@ -619,15 +609,6 @@ public class ShellyApiJsonDTO {
         @SerializedName("vibration_url")
         public String vibrationUrl; // URL reports when DW detects vibration FW 1.6.5+
 
-        // @SerializedName("tilt_enabled")
-        // public Boolean tiltEnabled; // Whether tilt monitoring is activated
-        // @SerializedName("tilt_calibrated")
-        // public Boolean tiltCalibrated; // Whether calibration data is valid
-        // @SerializedName("vibration_enabled")
-        // public Boolean vibrationEnabled; // Whether vibration monitoring is activated
-        // @SerializedName("reverse_open_close")
-        // public Boolean reverseOpenClose; // Whether to reverse which position the sensor consideres "open"
-
         // Gas FW 1.7
         @SerializedName("set_volume")
         public Integer volume; // Speaker volume for alarm
@@ -700,8 +681,6 @@ public class ShellyApiJsonDTO {
         public Integer input; // RGBW2 has no JSON array
         public ArrayList<ShellyInputState> inputs;
         public ArrayList<ShellySettingsLight> lights;
-        // @SerializedName("night_mode") // FW 1.5.7+
-        // public ShellySettingsNightMode nightMode;
         public ArrayList<ShellyShortLightStatus> dimmers;
         public ArrayList<ShellySettingsMeter> meters;
         public ArrayList<ShellySettingsEMeter> emeters;
@@ -735,27 +714,6 @@ public class ShellyApiJsonDTO {
     public static class ShellySettingsInput {
         @SerializedName("btn_type")
         public String btnType;
-
-        // attributes not yet processed
-        // public String name;
-        // @SerializedName("btn_reverse")
-        // public Integer btnReverse;
-        // @SerializedName("btn_on_url")
-        // public String btnOnUrl;
-        // @SerializedName("btn_off_url")
-        // public String btnOffUrl;
-        // @SerializedName("shortpush_url")
-        // public String shortpushUrl;
-        // @SerializedName("longpush_url")
-        // public String longpushUrl;
-        // @SerializedName("double_shortpush_url")
-        // public String doubleShortpushUrl;
-        // @SerializedName("triple_shortpush_url")
-        // public String tripleShortpushUrl;
-        // @SerializedName("shortpush_longpush_url")
-        // public String shortpushLongpushUrl;
-        // @SerializedName("longpush_shortpush_url")
-        // public String longpushShortpushUrl;
     }
 
     public static class ShellyControlRelay {
@@ -791,12 +749,6 @@ public class ShellyApiJsonDTO {
         public Boolean ison; // Whether output channel is on or off
         public String mode; // color or white - valid only for Bulb and RGBW2 even Dimmer returns it also
         public Integer brightness; // brightness: 0.100%
-        // @SerializedName("has_timer")
-        // public Boolean hasTimer; // Whether a timer is currently armed for this channel
-        // @SerializedName("timer_remaining")
-        // public Integer timerRemaining;
-        // public Integer wgite;
-        // public Integer temp; // light temp
     }
 
     public static class ShellyStatusRelay {
@@ -804,10 +756,7 @@ public class ShellyApiJsonDTO {
 
         @SerializedName("wifi_sta")
         public ShellySettingsWiFiNetwork wifiSta; // WiFi status
-        // public ShellyStatusCloud cloud; // Cloud status
-        // public ShellyStatusMqtt mqtt; // mqtt status
         public ShellySettingsCoiot coiot; // Firmware 1.6+
-        // public String time; // current time
         public Integer serial;
         public String mac; // MAC
         public ArrayList<ShellyShortStatusRelay> relays; // relay status
@@ -821,30 +770,11 @@ public class ShellyApiJsonDTO {
 
         public Double temperature; // device temp acc. on the selected temp unit
         public ShellyStatusSensor.ShellySensorTmp tmp;
-
-        @SerializedName("has_update")
-        public Boolean hasUpdate; // If a newer firmware version is available
-        public ShellySettingsUpdate update; // /status/firmware value
-
-        @SerializedName("ram_total")
-        public Integer ramTotal; // Total and available amount of system memory in bytes
-        @SerializedName("ram_free")
-        public Integer ramFree;
-        @SerializedName("fs_size")
-        public Integer fsSize;
-        @SerializedName("fs_free")
-        public Integer fsFree; // Total and available amount of file system space in bytes
-        public Integer uptime; // econds elapsed since boot
     }
 
     public static class ShellyStatusDimmer {
         @SerializedName("wifi_sta")
         public ShellySettingsWiFiNetwork wifiSta; // WiFi status
-        // public ShellyStatusCloud cloud; // Cloud status
-        // public ShellyStatusMqtt mqtt; // mqtt status
-        public String time; // current time
-        public Integer serial;
-        public String mac; // MAC
         public ArrayList<ShellyShortLightStatus> lights; // relay status
         public ArrayList<ShellySettingsMeter> meters; // current meter value
 
@@ -853,21 +783,6 @@ public class ShellyApiJsonDTO {
 
         public Boolean loaderror;
         public Boolean overload;
-
-        @SerializedName("has_update")
-        public Boolean hasUpdate; // If a newer firmware version is available
-        public ShellySettingsUpdate update; // /status/firmware value
-
-        @SerializedName("ram_total")
-        public Integer ramTotal; // Total and available amount of system memory in
-                                 // bytes
-        @SerializedName("ram_free")
-        public Integer ramFree;
-        @SerializedName("fs_size")
-        public Integer fsSize;
-        @SerializedName("fs_free")
-        public Integer fsFree; // Total and available amount of file system space in bytes
-        public Integer uptime; // seconds elapsed since boot
     }
 
     public static class ShellyControlRoller {
index 45cc461cf527c97f646e3ffd7154fca6d3691db0..555f3d294a49a6acdb7e41c0587e0ba5f643e9ca 100644 (file)
@@ -45,7 +45,7 @@ import com.google.gson.Gson;
 @NonNullByDefault
 public class ShellyDeviceProfile {
     private final Logger logger = LoggerFactory.getLogger(ShellyDeviceProfile.class);
-    private final static Pattern VERSION_PATTERN = Pattern.compile("v\\d+\\.\\d+\\.\\d+(-[a-z0-9]*)?");
+    private static final Pattern VERSION_PATTERN = Pattern.compile("v\\d+\\.\\d+\\.\\d+(-[a-z0-9]*)?");
 
     public boolean initialized = false; // true when initialized
 
@@ -131,6 +131,7 @@ public class ShellyDeviceProfile {
         extFeatures = version.compare(fwVersion, SHELLY_API_FW_110) >= 0;
         discoverable = (settings.discoverable == null) || settings.discoverable;
 
+        isRoller = mode.equalsIgnoreCase(SHELLY_MODE_ROLLER);
         inColor = isLight && mode.equalsIgnoreCase(SHELLY_MODE_COLOR);
 
         numRelays = !isLight ? getInteger(settings.device.numOutputs) : 0;
@@ -184,8 +185,6 @@ public class ShellyDeviceProfile {
         }
 
         isDimmer = deviceType.equalsIgnoreCase(SHELLYDT_DIMMER) || deviceType.equalsIgnoreCase(SHELLYDT_DIMMER2);
-        isRoller = mode.equalsIgnoreCase(SHELLY_MODE_ROLLER);
-
         isBulb = thingType.equals(THING_TYPE_SHELLYBULB_STR);
         isDuo = thingType.equals(THING_TYPE_SHELLYDUO_STR) || thingType.equals(THING_TYPE_SHELLYVINTAGE_STR)
                 || thingType.equals(THING_TYPE_SHELLYDUORGBW_STR);
index df7bd8a9437f9480db62ff7f236b0a3ba3f3a871..13c5b8ede95ec2d2de05772c03f47c48349cf8d4 100644 (file)
@@ -246,8 +246,8 @@ public class ShellyHttpApi {
     }
 
     public ShellySettingsLogin setLoginCredentials(String user, String password) throws ShellyApiException {
-        return callApi(SHELLY_URL_SETTINGS + "/login?enabled=yes&username=" + user + "&password=" + password,
-                ShellySettingsLogin.class);
+        return callApi(SHELLY_URL_SETTINGS + "/login?enabled=yes&username=" + urlEncode(user) + "&password="
+                + urlEncode(password), ShellySettingsLogin.class);
     }
 
     public String getCoIoTDescription() throws ShellyApiException {
index 723f7607985bddf2245a1fff71e0a1305c804a9f..eaa1881c3550d8262d9c63c5ce3ac514f36b5544 100644 (file)
@@ -76,9 +76,6 @@ public class ShellyCoIoTProtocol {
     protected boolean handleStatusUpdate(List<CoIotSensor> sensorUpdates, CoIotDescrSen sen, CoIotSensor s,
             Map<String, State> updates, ShellyColorUtils col) {
         // Process status information and convert into channel updates
-        // Integer rIndex = Integer.parseInt(sen.links) + 1;
-        // String rGroup = getProfile().numRelays <= 1 ? CHANNEL_GROUP_RELAY_CONTROL
-        // : CHANNEL_GROUP_RELAY_CONTROL + rIndex;
         int rIndex = getIdFromBlk(sen);
         String rGroup = getProfile().numRelays <= 1 ? CHANNEL_GROUP_RELAY_CONTROL
                 : CHANNEL_GROUP_RELAY_CONTROL + rIndex;
@@ -130,8 +127,10 @@ public class ShellyCoIoTProtocol {
                                 s.value == 1 ? OnOffType.ON : OnOffType.OFF);
                         break;
                     case "vibration": // DW with FW1.6.5+
-                        updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
-                                s.value == 1 ? OnOffType.ON : OnOffType.OFF);
+                        if (s.value == 1) {
+                            thingHandler.triggerChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ALARM_STATE,
+                                    EVENT_TYPE_VIBRATION);
+                        }
                         break;
                     case "luminositylevel": // +
                         updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ILLUM, getStringType(s.valueStr));
@@ -166,7 +165,7 @@ public class ShellyCoIoTProtocol {
                         updateChannel(updates, CHANNEL_GROUP_COLOR_CONTROL, CHANNEL_COLOR_GAIN,
                                 ShellyColorUtils.toPercent((int) s.value, SHELLY_MIN_GAIN, SHELLY_MAX_GAIN));
                         break;
-                    case "sensorerror": // +
+                    case "sensorerror":
                         updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ERROR, getStringType(s.valueStr));
                         break;
                     default:
index c650efeea7fdbf7def898f76012e94bd039c811f..3a1ed6c07c027202cf3295cfbe6c92968445b010 100644 (file)
@@ -177,8 +177,15 @@ public class ShellyCoIoTVersion1 extends ShellyCoIoTProtocol implements ShellyCo
                                 toQuantityType(s.value, DIGITS_NONE, Units.DEGREE_ANGLE));
                         break;
                     case "vibration": // DW with FW1.6.5+
-                        updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
-                                s.value == 1 ? OnOffType.ON : OnOffType.OFF);
+                        if (profile.isMotion) {
+                            // handle as status
+                            updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
+                                    s.value == 1 ? OnOffType.ON : OnOffType.OFF);
+                        } else if (s.value == 1) {
+                            // handle as event
+                            thingHandler.triggerChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ALARM_STATE,
+                                    EVENT_TYPE_VIBRATION);
+                        }
                         break;
                     case "temp": // Shelly Bulb
                     case "colortemperature": // Shelly Duo
index a239f41e0f2fa91a73d0c4e4f5b86248881424e7..c600c1c9b9067762226a7b1628d07f3556d5ba69 100644 (file)
@@ -103,7 +103,10 @@ public class ShellyCoIoTVersion2 extends ShellyCoIoTProtocol implements ShellyCo
                 // skip, could check against thing mode...
                 break;
 
-            case "1101": // S, output, 0/1
+            case "1101": // relay_0: output, 0/1
+            case "1201": // relay_1: output, 0/1
+            case "1301": // relay_2: output, 0/1
+            case "1401": // relay_3: output, 0/1
                 updatePower(profile, updates, rIndex, sen, s, sensorUpdates);
                 break;
             case "1102": // roler_0: S, roller, open/close/stop -> roller state
@@ -316,8 +319,14 @@ public class ShellyCoIoTVersion2 extends ShellyCoIoTProtocol implements ShellyCo
                 updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_ALARM_STATE, getStringType(s.valueStr));
                 break;
             case "6110": // A, vibration, 0/1, -1=unknown
-                updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
-                        value == 1 ? OnOffType.ON : OnOffType.OFF);
+                if (profile.isMotion) {
+                    // handle as status
+                    updateChannel(updates, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
+                            s.value == 1 ? OnOffType.ON : OnOffType.OFF);
+                } else if (s.value == 1) {
+                    // handle as event
+                    thingHandler.triggerChannel(CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ALARM, EVENT_TYPE_VIBRATION);
+                }
                 break;
             case "9102": // EV, wakeupEvent, battery/button/periodic/poweron/sensor/ext_power, "unknown"=unknown
                 if (s.valueArray.size() > 0) {
index a35dc157fa1a90bff95c33149d2581d82bafd366..ff3fe72d74b37f4933b986c45654239c40993967 100644 (file)
@@ -133,8 +133,9 @@ public class ShellyCoapHandler implements ShellyCoapListener {
                     .setTimeout((long) SHELLY_API_TIMEOUT_MS).useNONs().setEndpoint(coapServer.getEndpoint());
             @Nullable
             Endpoint endpoint = null;
-            if (statusClient != null) {
-                endpoint = statusClient.getEndpoint();
+            CoapClient client = statusClient;
+            if (client != null) {
+                endpoint = client.getEndpoint();
             }
             if ((endpoint == null) || !endpoint.isStarted()) {
                 logger.warn("{}: Unable to initialize CoAP access (network error)", thingName);
index 72c7148877201d4d2a6c11dd84b1891208ed0a0f..f6978d56e63672909a20977c2a4e55a8a35c5d8b 100755 (executable)
@@ -115,8 +115,11 @@ public class ShellyDiscoveryParticipant implements MDNSDiscoveryParticipant {
             Map<String, Object> properties = new TreeMap<>();
 
             name = service.getName().toLowerCase();
-            address = service.getHostAddress();
-            if ((address == null) || address.isEmpty()) {
+            String[] hostAddresses = service.getHostAddresses();
+            if ((hostAddresses != null) && (hostAddresses.length > 0)) {
+                address = hostAddresses[0];
+            }
+            if (address.isEmpty()) {
                 logger.trace("{}: Shelly device discovered with empty IP address (service-name={})", name, service);
                 return null;
             }
index 5307e6a3727e58bf0148ac046abd485174f10d5f..5d1642f20897500fa348a7c3b91be558ea976655 100755 (executable)
@@ -101,8 +101,6 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
     private int skipUpdate = 0;
     private boolean refreshSettings = false;
 
-    private @Nullable ScheduledFuture<?> asyncButtonRelease;
-
     // delay before enabling channel
     private final int cacheCount = UPDATE_SETTINGS_INTERVAL_SECONDS / UPDATE_STATUS_INTERVAL_SECONDS;
     protected final ShellyChannelCache cache;
@@ -111,6 +109,7 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
     private String localPort = "";
 
     private String lastWakeupReason = "";
+    private int vibrationFilter = 0;
 
     /**
      * Constructor
@@ -274,9 +273,7 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
                     logger.debug("{}: Unable to set CoIoT peer: {}", thingName, e.toString());
                 }
             } else if (!devpeer.isEmpty() && !devpeer.equals(ourpeer)) {
-                logger.warn("{}: CoIoT peer in device settings does not point this to this host, disabling CoIoT",
-                        thingName);
-                config.eventsCoIoT = autoCoIoT = false;
+                logger.warn("{}: CoIoT peer in device settings does not point this to this host", thingName);
             }
         }
         if (autoCoIoT) {
@@ -385,6 +382,12 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
         try {
             boolean updated = false;
 
+            if (vibrationFilter > 0) {
+                vibrationFilter--;
+                logger.debug("{}: Vibration events are absorbed for {} more seconds", thingName,
+                        vibrationFilter * UPDATE_STATUS_INTERVAL_SECONDS);
+            }
+
             skipUpdate++;
             ThingStatus thingStatus = getThing().getStatus();
             if (refreshSettings || (scheduledUpdates > 0) || (skipUpdate % skipCount == 0)) {
@@ -483,7 +486,7 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
             updateStatus(ThingStatus.ONLINE);
 
             // request 3 updates in a row (during the first 2+3*3 sec)
-            requestUpdates(profile.alwaysOn ? 3 : 1, channelsCreated == false);
+            requestUpdates(profile.alwaysOn ? 3 : 1, !channelsCreated);
         }
         restartWatchdog();
     }
@@ -575,8 +578,9 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
      */
 
     private boolean checkRestarted(ShellySettingsStatus status) {
-        if (profile.isInitialized() && (status.uptime < stats.lastUptime || !profile.status.update.oldVersion.isEmpty()
-                && !status.update.oldVersion.equals(profile.status.update.oldVersion))) {
+        if (profile.isInitialized() && profile.alwaysOn /* exclude battery powered devices */
+                && (status.uptime < stats.lastUptime || !profile.status.update.oldVersion.isEmpty()
+                        && !status.update.oldVersion.equals(profile.status.update.oldVersion))) {
             updateProperties(profile, status);
             return true;
         }
@@ -706,13 +710,10 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
                         updateChannel(group, CHANNEL_SENSOR_ILLUM, getStringType(event));
                         break;
 
-                    case SHELLY_EVENT_VIBRATION:
-                        updateChannel(group, CHANNEL_SENSOR_VIBRATION, OnOffType.ON);
-                        break;
-
                     case SHELLY_EVENT_ALARM_MILD: // Shelly Gas
                     case SHELLY_EVENT_ALARM_HEAVY:
                     case SHELLY_EVENT_ALARM_OFF:
+                    case SHELLY_EVENT_VIBRATION: // DW2
                         channel = CHANNEL_SENSOR_ALARM_STATE;
                         payload = event.toUpperCase();
                         break;
@@ -1195,7 +1196,21 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
     }
 
     public void triggerChannel(String group, String channel, String payload) {
-        triggerChannel(mkChannelId(group, channel), payload);
+        String triggerCh = mkChannelId(group, channel);
+        logger.debug("{}: Send event {} to channel {}", thingName, triggerCh, payload);
+        if (EVENT_TYPE_VIBRATION.contentEquals(payload)) {
+            if (vibrationFilter == 0) {
+                vibrationFilter = VIBRATION_FILTER_SEC / UPDATE_STATUS_INTERVAL_SECONDS + 1;
+                logger.debug("{}: Duplicate vibration events will be absorbed for the next {} sec", thingName,
+                        vibrationFilter * UPDATE_STATUS_INTERVAL_SECONDS);
+            } else {
+                logger.debug("{}: Vibration event absorbed, {} sec remaining", thingName,
+                        vibrationFilter * UPDATE_STATUS_INTERVAL_SECONDS);
+                return;
+            }
+        }
+
+        triggerChannel(triggerCh, payload);
     }
 
     public void stop() {
@@ -1206,11 +1221,6 @@ public class ShellyBaseHandler extends BaseThingHandler implements ShellyDeviceL
             statusJob = null;
             logger.debug("{}: Shelly statusJob stopped", thingName);
         }
-        job = asyncButtonRelease;
-        if (job != null) {
-            job.cancel(true);
-            asyncButtonRelease = null;
-        }
 
         coap.stop();
         profile.initialized = false;
index 8b8ab9d9b338b9b4cef02ba8d62519110786c33c..82d1e661a051bfd31ec6191916792b29c705f1ac 100644 (file)
@@ -300,8 +300,6 @@ public class ShellyComponents {
             if (sdata.accel != null) {
                 updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TILT,
                         toQuantityType(getDouble(sdata.accel.tilt.doubleValue()), DIGITS_NONE, Units.DEGREE_ANGLE));
-                updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
-                        getInteger(sdata.accel.vibration) == 1 ? OnOffType.ON : OnOffType.OFF);
             }
             if (sdata.flood != null) {
                 updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_FLOOD,
@@ -365,8 +363,6 @@ public class ShellyComponents {
                     updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_MOTION_TS,
                             getTimestamp(getString(profile.settings.timezone), timestamp));
                 }
-                updated |= thingHandler.updateChannel(CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_VIBRATION,
-                        getOnOff(sdata.sensor.vibration));
             }
 
             updated |= thingHandler.updateInputs(status);
index 388b2a36b71bf1783c0111bd3b08b189f2f7c28f..5ebf9b70b92aaec092acdc20c4750214d44e77da 100644 (file)
@@ -34,11 +34,9 @@ import org.osgi.service.cm.ConfigurationAdmin;
 @NonNullByDefault
 public class ShellyManager {
     private final Map<String, ShellyManagerPage> pages = new LinkedHashMap<>();
-    private final ShellyHandlerFactory handlerFactory;
 
     public ShellyManager(ConfigurationAdmin configurationAdmin, ShellyTranslationProvider translationProvider,
             HttpClient httpClient, String localIp, int localPort, ShellyHandlerFactory handlerFactory) {
-        this.handlerFactory = handlerFactory;
         pages.put(SHELLY_MGR_OVERVIEW_URI, new ShellyManagerOverviewPage(configurationAdmin, translationProvider,
                 httpClient, localIp, localPort, handlerFactory));
         pages.put(SHELLY_MGR_ACTION_URI, new ShellyManagerActionPage(configurationAdmin, translationProvider,
index 38ede361c61fdb65d2a3cc934438adefd7a8f8d5..017fcae9f909b2a4ef21a5fada151cd2562ab7af 100644 (file)
@@ -92,7 +92,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     refreshTimer = 3;
                     break;
                 case ACTION_RESTART:
-                    if (update.equalsIgnoreCase("yes")) {
+                    if ("yes".equalsIgnoreCase(update)) {
                         message = getMessageP("action.restart.info", MCINFO);
                         actionButtonLabel = "Ok";
                         new Thread(() -> { // schedule asynchronous reboot
@@ -116,7 +116,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                         break;
                     }
 
-                    if (!update.equalsIgnoreCase("yes")) {
+                    if (!"yes".equalsIgnoreCase(update)) {
                         ShellySettingsLogin status = api.getLoginSettings();
                         message = getMessage("action.protect.status", getBool(status.enabled) ? "enabled" : "disabled",
                                 status.username)
@@ -137,7 +137,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     }
 
                     String peer = getString(profile.settings.coiot.peer);
-                    boolean mcast = peer.isEmpty() || peer.equalsIgnoreCase(SHELLY_COIOT_MCAST);
+                    boolean mcast = peer.isEmpty() || SHELLY_COIOT_MCAST.equalsIgnoreCase(peer);
                     String newPeer = mcast ? localIp + ":" + ShellyCoapJSonDTO.COIOT_PORT : SHELLY_COIOT_MCAST;
                     String displayPeer = mcast ? newPeer : "Multicast";
 
@@ -147,7 +147,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                         break;
                     }
 
-                    if (!update.equalsIgnoreCase("yes")) {
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessageP("coiot.current-peer", MCMESSAGE, mcast ? "Multicast" : peer)
                                 + getMessageP("coiot.new-peer", MCINFO, displayPeer)
                                 + getMessageP(mcast ? "coiot.mode-peer" : "coiot.mode-mcast", MCMESSAGE);
@@ -176,7 +176,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     refreshTimer = 20;
                     break;
                 case ACTION_RESET:
-                    if (!update.equalsIgnoreCase("yes")) {
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessageP("action.reset.warning", MCWARNING, serviceName);
                         actionUrl = buildActionUrl(uid, action);
                     } else {
@@ -204,8 +204,8 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     break;
                 case ACTION_ENDEBUG:
                 case ACTION_DISDEBUG:
-                    boolean enable = action.equalsIgnoreCase(ACTION_ENDEBUG);
-                    if (!update.equalsIgnoreCase("yes")) {
+                    boolean enable = ACTION_ENDEBUG.equalsIgnoreCase(action);
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessage(enable ? "action.debug-enable" : "action.debug-disable");
                         actionUrl = buildActionUrl(uid, action);
                     } else {
@@ -222,7 +222,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     }
                     break;
                 case ACTION_RESSTA:
-                    if (!update.equalsIgnoreCase("yes")) {
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessage("action.resetsta-info");
                         actionUrl = buildActionUrl(uid, action);
                     } else {
@@ -237,8 +237,8 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                     break;
                 case ACTION_ENWIFIREC:
                 case ACTION_DISWIFIREC:
-                    enable = action.equalsIgnoreCase(ACTION_ENWIFIREC);
-                    if (!update.equalsIgnoreCase("yes")) {
+                    enable = ACTION_ENWIFIREC.equalsIgnoreCase(action);
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessage(enable ? "action.setwifirec-enable" : "action.setwifirec-disable");
                         actionUrl = buildActionUrl(uid, action);
                     } else {
@@ -254,8 +254,8 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
 
                 case ACTION_ENAPROAMING:
                 case ACTION_DISAPROAMING:
-                    enable = action.equalsIgnoreCase(ACTION_ENAPROAMING);
-                    if (!update.equalsIgnoreCase("yes")) {
+                    enable = ACTION_ENAPROAMING.equalsIgnoreCase(action);
+                    if (!"yes".equalsIgnoreCase(update)) {
                         message = getMessage(enable ? "action.aproaming-enable" : "action.aproaming-disable");
                         actionUrl = buildActionUrl(uid, action);
                     } else {
@@ -272,7 +272,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
                 case ACTION_GETDEB:
                 case ACTION_GETDEB1:
                     try {
-                        message = api.getDebugLog(action.equalsIgnoreCase(ACTION_GETDEB) ? "log" : "log1");
+                        message = api.getDebugLog(ACTION_GETDEB.equalsIgnoreCase(action) ? "log" : "log1");
                         message = message.replaceAll("[\r]", "").replaceAll("[\r\n]", "<br>");
                     } catch (ShellyApiException e) {
                         message = getMessage("action.getdebug-failed", e.toString());
@@ -308,7 +308,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
 
         if ((profile.settings.coiot != null) && (profile.settings.coiot.peer != null) && !profile.isMotion) {
             boolean mcast = profile.settings.coiot.peer.isEmpty()
-                    || profile.settings.coiot.peer.equalsIgnoreCase(SHELLY_COIOT_MCAST);
+                    || SHELLY_COIOT_MCAST.equalsIgnoreCase(profile.settings.coiot.peer);
             list.put(mcast ? ACTION_SETCOIOT_PEER : ACTION_SETCOIOT_MCAST,
                     mcast ? "Set CoIoT Peer Mode" : "Set CoIoT Multicast Mode");
         }
@@ -332,7 +332,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
         list.put(ACTION_RESET, "-Factory Reset");
         if (profile.extFeatures) {
             list.put(ACTION_OTACHECK, "Check for Update");
-            boolean debug_enable = getBool(profile.settings.debug_enable);
+            boolean debug_enable = getBool(profile.settings.debugEnable);
             list.put(!debug_enable ? ACTION_ENDEBUG : ACTION_DISDEBUG,
                     !debug_enable ? "Enable Debug" : "Disable Debug");
             if (debug_enable) {
index 8ba73b023c57d262e03a94c2392cd856e078ce61..8a0d8da259be7facb191f91abe4d2ed5899f6bf6 100644 (file)
@@ -115,7 +115,7 @@ public class ShellyManagerOtaPage extends ShellyManagerPage {
             properties.put(ATTRIBUTE_UPDATE_URL, "http://" + getDeviceIp(properties) + "/ota?" + updateUrl);
             properties.put(URLPARM_CONNECTION, connection);
 
-            if (update.equalsIgnoreCase("yes")) {
+            if ("yes".equalsIgnoreCase(update)) {
                 // do the update
                 th.setThingOffline(ThingStatusDetail.FIRMWARE_UPDATING, "offline.status-error-fwupgrade");
                 html += loadHTML(FWUPDATE2_HTML, properties);
@@ -199,9 +199,9 @@ public class ShellyManagerOtaPage extends ShellyManagerPage {
                 } else {
                     // convert prod/beta to full url
                     FwRepoEntry fw = getFirmwareRepoEntry(deviceType, mode);
-                    String url = getString(prod ? fw.url : fw.beta_url);
-                    logger.debug("ShellyManager: Map {} release to url {}, version {}", url,
-                            prod ? fw.url : fw.beta_url, prod ? fw.version : fw.beta_ver);
+                    String url = getString(prod ? fw.url : fw.betaUrl);
+                    logger.debug("ShellyManager: Map {} release to url {}, version {}", url, prod ? fw.url : fw.betaUrl,
+                            prod ? fw.version : fw.betaVer);
                     return url;
                 }
             default: // Update from firmware archive
index b7932602c002b4676c95e7acef242de212d7dd14..bdadcf21215655b7b5ef4674a8d1db20bfe069a1 100644 (file)
@@ -148,7 +148,7 @@ public class ShellyManagerOverviewPage extends ShellyManagerPage {
                 html += "\t\t\t\t\t<option value=\"" + updateUrl + "&" + URLPARM_VERSION + "=" + FWPROD + "\">Release "
                         + pVersion + "</option>\n";
             }
-            bVersion = extractFwVersion(fw.beta_ver);
+            bVersion = extractFwVersion(fw.betaVer);
             if (!bVersion.isEmpty()) {
                 html += "\t\t\t\t\t<option value=\"" + updateUrl + "&" + URLPARM_VERSION + "=" + FWBETA + "\">Beta "
                         + bVersion + "</option>\n";
index cbe79cb79ff6f087e155fcb8e4b936e78475eced..772ffd98d3ee0eb152942b73f9f0a47304f2d110 100644 (file)
@@ -63,6 +63,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.gson.Gson;
+import com.google.gson.annotations.SerializedName;
 
 /**
  * {@link ShellyManagerOtaPage} implements the Shelly Manager's page template
@@ -136,8 +137,10 @@ public class ShellyManagerPage {
         public @Nullable String url; // prod
         public @Nullable String version;
 
-        public @Nullable String beta_url; // beta version if avilable
-        public @Nullable String beta_ver;
+        @SerializedName("beta_url")
+        public @Nullable String betaUrl; // beta version if avilable
+        @SerializedName("beta_ver")
+        public @Nullable String betaVer;
     }
 
     public ShellyManagerPage(ConfigurationAdmin configurationAdmin, ShellyTranslationProvider translationProvider,
@@ -242,7 +245,7 @@ public class ShellyManagerPage {
         addAttribute(properties, th, CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_ALARM);
         addAttribute(properties, th, CHANNEL_GROUP_DEV_STATUS, CHANNEL_DEVST_CHARGER);
 
-        properties.put(ATTRIBUTE_DEBUG_MODE, getOption(profile.settings.debug_enable));
+        properties.put(ATTRIBUTE_DEBUG_MODE, getOption(profile.settings.debugEnable));
         properties.put(ATTRIBUTE_DISCOVERABLE, String.valueOf(getBool(profile.settings.discoverable)));
         properties.put(ATTRIBUTE_WIFI_RECOVERY, String.valueOf(getBool(profile.settings.wifiRecoveryReboot)));
         properties.put(ATTRIBUTE_APR_MODE,
@@ -414,9 +417,9 @@ public class ShellyManagerPage {
                     fw.url = url;
                     logger.debug("ShellyManager: Release Split-URL for device type {} is {}", deviceType, url);
                 }
-                url = substringBefore(fw.beta_url, ".zip") + "-" + mode + ".zip";
+                url = substringBefore(fw.betaUrl, ".zip") + "-" + mode + ".zip";
                 if (testUrl(url)) {
-                    fw.beta_url = url;
+                    fw.betaUrl = url;
                     logger.debug("ShellyManager: Beta Split-URL for device type {} is {}", deviceType, url);
                 }
             }
index d6083cd1dfdbeebf06bd241537f1f5e7033e6b15..66aa8d09b300cfdea8f66c1c2e3a2a3df3f9adea 100644 (file)
@@ -125,9 +125,11 @@ public class ShellyManagerServlet extends HttpServlet {
             } else {
                 // binary data
                 byte[] data = (byte[]) output.data;
-                response.setContentLength(data.length);
-                bin = response.getOutputStream();
-                bin.write(data, 0, data.length);
+                if (data != null) {
+                    response.setContentLength(data.length);
+                    bin = response.getOutputStream();
+                    bin.write(data, 0, data.length);
+                }
             }
         } catch (ShellyApiException | RuntimeException e) {
             logger.debug("{}: Exception uri={}, parameters={}", className, path, request.getParameterMap().toString(),
index e3e4308a3ae06d646b76b25855917b3917bd6634..50f21cbd2b8042c657542f339d7a5a91c202bff4 100644 (file)
@@ -175,7 +175,6 @@ public class ShellyChannelDefinitions {
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VOLTAGE, "sensorADC", ITEMT_VOLT))
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_CONTACT, "sensorContact", ITEMT_CONTACT))
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_SSTATE, "sensorState", ITEMT_STRING))
-                .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_VIBRATION, "sensorVibration", ITEMT_SWITCH))
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_TILT, "sensorTilt", ITEMT_ANGLE))
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION, "sensorMotion", ITEMT_SWITCH))
                 .add(new ShellyChannel(m, CHGR_SENSOR, CHANNEL_SENSOR_MOTION_TS, "motionTimestamp", ITEMT_DATETIME))
@@ -424,8 +423,6 @@ public class ShellyChannelDefinitions {
                     CHANNEL_SENSOR_VIBRATION);
         }
         if (sdata.accel != null) { // DW2
-            addChannel(thing, newChannels, sdata.accel.vibration != null, CHANNEL_GROUP_SENSOR,
-                    CHANNEL_SENSOR_VIBRATION);
             addChannel(thing, newChannels, sdata.accel.tilt != null, CHANNEL_GROUP_SENSOR, CHANNEL_SENSOR_TILT);
         }
 
@@ -564,18 +561,17 @@ public class ShellyChannelDefinitions {
         public String getGroupAttribute(String attribute) {
             String key = PREFIX_GROUP + group + "." + attribute;
             String value = messages.getText(key);
-            return value != null && !value.equals(key) ? value : "";
+            return !value.equals(key) ? value : "";
         }
 
         public String getChannelAttribute(String attribute) {
             String key = PREFIX_CHANNEL + channel + "." + attribute;
             String value = messages.getText(key);
-            return value != null && !value.equals(key) ? value : "";
+            return !value.equals(key) ? value : "";
         }
 
         private String getText(String key) {
-            String text = messages.get(key);
-            return text != null ? text : "";
+            return messages.get(key);
         }
     }
 
index 749e36f742715c706b38416b9dcc6c7e829dd382..d37b4a4ee5bd6f731abf19eebd9feefcb57be0b0 100644 (file)
@@ -52,8 +52,8 @@ import com.google.gson.JsonSyntaxException;
  */
 @NonNullByDefault
 public class ShellyUtils {
-    private final static String PRE = "Unable to create object of type ";
-    public final static DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern(DateTimeType.DATE_PATTERN);
+    private static final String PRE = "Unable to create object of type ";
+    public static final DateTimeFormatter DATE_TIME = DateTimeFormatter.ofPattern(DateTimeType.DATE_PATTERN);
 
     public static <T> T fromJson(Gson gson, @Nullable String json, Class<T> classOfT) throws ShellyApiException {
         @Nullable
@@ -96,6 +96,7 @@ public class ShellyUtils {
         }
     }
 
+    @SuppressWarnings("unchecked")
     private static <T> Class<T> wrap(Class<T> type) {
         if (type == int.class) {
             return (Class<T>) Integer.class;