diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiResult.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiResult.java index 4768c67b6cd..d68906e5f3b 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiResult.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyApiResult.java @@ -92,10 +92,8 @@ public class ShellyApiResult { httpReason = contentResponse.getReason(); Request request = contentResponse.getRequest(); - if (request != null) { - url = request.getURI().toString(); - method = request.getMethod(); - } + url = request.getURI().toString(); + method = request.getMethod(); } } } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java index c43565ee395..584667f4349 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyDeviceProfile.java @@ -18,6 +18,7 @@ import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.* import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -115,13 +116,11 @@ public class ShellyDeviceProfile { public ShellyDeviceProfile() { } - public ShellyDeviceProfile initialize(String thingType, String jsonIn, @Nullable ShellySettingsDevice device) + public ShellyDeviceProfile initialize(String thingType, String jsonIn, ShellySettingsDevice device) throws ShellyApiException { Gson gson = new Gson(); initialized = false; - if (device != null) { - this.device = device; - } + this.device = device; initFromThingType(thingType); @@ -165,7 +164,8 @@ public class ShellyDeviceProfile { } hasRelays = (numRelays > 0) || isDimmer; numRollers = getInteger(device.numRollers); - numInputs = settings.inputs != null ? settings.inputs.size() : hasRelays ? isRoller ? 2 : 1 : 0; + List inputs = settings.inputs; + numInputs = inputs != null ? inputs.size() : hasRelays ? isRoller ? 2 : 1 : 0; isEMeter = settings.emeters != null; numMeters = !isEMeter ? getInteger(device.numMeters) : getInteger(device.numEMeters); @@ -269,8 +269,8 @@ public class ShellyDeviceProfile { } else if (hasRelays) { return numRelays <= 1 ? CHANNEL_GROUP_RELAY_CONTROL : CHANNEL_GROUP_RELAY_CONTROL + idx; } else if (isRGBW2) { - return settings.lights == null || settings.lights != null && settings.lights.size() <= 1 - ? CHANNEL_GROUP_LIGHT_CONTROL + List lights = settings.lights; + return lights == null || lights.size() <= 1 ? CHANNEL_GROUP_LIGHT_CONTROL : CHANNEL_GROUP_LIGHT_CHANNEL + idx; } else if (isLight) { return CHANNEL_GROUP_LIGHT_CONTROL; @@ -317,39 +317,42 @@ public class ShellyDeviceProfile { return ""; } - @SuppressWarnings("null") public boolean inButtonMode(int idx) { if (idx < 0) { logger.debug("{}: Invalid index {} for inButtonMode()", thingName, idx); return false; } String btnType = ""; + List inputs = settings.inputs; + List dimmers = settings.dimmers; + List relays = settings.relays; + List lights = settings.lights; if (isButton) { return true; - } else if (isIX && settings.inputs != null && idx < settings.inputs.size()) { - ShellySettingsInput input = settings.inputs.get(idx); + } else if (isIX && inputs != null && idx < inputs.size()) { + ShellySettingsInput input = inputs.get(idx); btnType = getString(input.btnType); } else if (isDimmer) { - if (settings.dimmers != null) { - ShellySettingsDimmer dimmer = settings.dimmers.get(0); + if (dimmers != null) { + ShellySettingsDimmer dimmer = dimmers.get(0); btnType = getString(dimmer.btnType); } - } else if (settings.relays != null) { + } else if (relays != null) { if (numRelays == 1) { - ShellySettingsRelay relay = settings.relays.get(0); + ShellySettingsRelay relay = relays.get(0); if (relay.btnType != null) { btnType = getString(relay.btnType); } else { // Shelly 1L has 2 inputs btnType = idx == 0 ? getString(relay.btnType1) : getString(relay.btnType2); } - } else if (idx < settings.relays.size()) { + } else if (idx < relays.size()) { // only one input channel - ShellySettingsRelay relay = settings.relays.get(idx); + ShellySettingsRelay relay = relays.get(idx); btnType = getString(relay.btnType); } - } else if (isRGBW2 && (settings.lights != null) && (idx < settings.lights.size())) { - ShellySettingsRgbwLight light = settings.lights.get(idx); + } else if (isRGBW2 && lights != null && idx < lights.size()) { + ShellySettingsRgbwLight light = lights.get(idx); btnType = getString(light.btnType); } @@ -367,13 +370,12 @@ public class ShellyDeviceProfile { } public String[] getValveProfileList(int valveId) { - if (isTRV && settings.thermostats != null) { - int sz = settings.thermostats.size(); + List thermostats = settings.thermostats; + if (isTRV && thermostats != null) { + int sz = thermostats.size(); if (valveId <= sz) { - if (settings.thermostats != null) { - ShellyThermnostat t = settings.thermostats.get(valveId); - return t.profileNames; - } + ShellyThermnostat t = thermostats.get(valveId); + return t.profileNames; } } return new String[0]; @@ -381,8 +383,9 @@ public class ShellyDeviceProfile { public String getValueProfile(int valveId, int profileId) { int id = profileId; - if (id <= 0 && settings.thermostats != null) { - id = settings.thermostats.get(0).profile; + List thermostats = settings.thermostats; + if (id <= 0 && thermostats != null) { + id = thermostats.get(0).profile; } return "" + id; } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyEventServlet.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyEventServlet.java index 9e3609e2d48..ee403509a77 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyEventServlet.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api/ShellyEventServlet.java @@ -77,9 +77,13 @@ public class ShellyEventServlet extends WebSocketServlet { @Override protected void service(@Nullable HttpServletRequest request, @Nullable HttpServletResponse resp) throws ServletException, IOException, IllegalArgumentException { + if (request == null) { + logger.trace("ShellyEventServlet.service unexpectedly received a null request. Request not processed"); + return; + } String path = getString(request.getRequestURI()).toLowerCase(); if (path.equals(SHELLY2_CALLBACK_URI)) { // Shelly2 WebSocket - if (request != null && resp != null) { + if (resp != null) { super.service(request, resp); } return; @@ -123,8 +127,10 @@ public class ShellyEventServlet extends WebSocketServlet { logger.debug("{}: Exception processing callback: path={}; index={}, type={}, parameters={}", deviceName, path, index, type, request.getParameterMap().toString()); } finally { - resp.setCharacterEncoding(StandardCharsets.UTF_8.toString()); - resp.getWriter().write(""); + if (resp != null) { + resp.setCharacterEncoding(StandardCharsets.UTF_8.toString()); + resp.getWriter().write(""); + } } } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java index 3b568b156fb..b423d58b655 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api1/Shelly1HttpApi.java @@ -19,6 +19,7 @@ import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -33,6 +34,7 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerSt import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySendKeyList; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySenseKeyCode; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLight; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; @@ -53,8 +55,7 @@ import com.google.gson.JsonSyntaxException; /** * {@link Shelly1HttpApi} wraps the Shelly REST API and provides various low level function to access the device api - * (not - * cloud api). + * (not cloud api). * * @author Markus Michels - Initial contribution */ @@ -279,8 +280,9 @@ public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterfa @Override public void setValveMode(int valveId, boolean auto) throws ShellyApiException { String uri = "/settings/thermostat/" + valveId + "?target_t_enabled=" + (auto ? "1" : "0"); - if (auto && profile.settings.thermostats != null) { - uri = uri + "&target_t=" + getDouble(profile.settings.thermostats.get(0).targetTemp.value); + List thermostats = profile.settings.thermostats; + if (auto && thermostats != null) { + uri = uri + "&target_t=" + getDouble(thermostats.get(0).targetTemp.value); } httpRequest(uri); // percentage to open the valve } @@ -303,8 +305,9 @@ public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterfa @Override public void startValveBoost(int valveId, int value) throws ShellyApiException { - if (profile.settings.thermostats != null) { - ShellyThermnostat t = profile.settings.thermostats.get(0); + List thermostats = profile.settings.thermostats; + if (thermostats != null) { + ShellyThermnostat t = thermostats.get(0); int minutes = value != -1 ? value : getInteger(t.boostMinutes); httpRequest("/thermostat/0?boost_minutes=" + minutes); } @@ -541,8 +544,9 @@ public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterfa } private void setDimmerEvents() throws ShellyApiException { - if (profile.settings.dimmers != null) { - int sz = profile.settings.dimmers.size(); + List dimmers = profile.settings.dimmers; + if (dimmers != null) { + int sz = dimmers.size(); for (int i = 0; i < sz; i++) { setEventUrls(i); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java index 79aec4d3791..5e139a33149 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiClient.java @@ -18,6 +18,7 @@ import static org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.*; import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Random; @@ -296,9 +297,10 @@ public class Shelly2ApiClient extends ShellyHttpClient { } private int getRelayIdx(ShellyDeviceProfile profile, @Nullable Integer id) { - if (id != null && profile.settings.relays != null) { + List relays = profile.settings.relays; + if (id != null && relays != null) { int idx = 0; - for (ShellySettingsRelay relay : profile.settings.relays) { + for (ShellySettingsRelay relay : relays) { if (relay.isValid && relay.id != null && relay.id.intValue() == id.intValue()) { return idx; } @@ -561,12 +563,13 @@ public class Shelly2ApiClient extends ShellyHttpClient { return; } - if (profile.settings.dimmers != null) { - ShellySettingsDimmer ds = profile.settings.dimmers.get(0); + List dimmers = profile.settings.dimmers; + if (dimmers != null) { + ShellySettingsDimmer ds = dimmers.get(0); ds.autoOn = dc.light0.autoOnDelay; ds.autoOff = dc.light0.autoOffDelay; ds.name = dc.light0.name; - profile.settings.dimmers.set(0, ds); + dimmers.set(0, ds); } } @@ -709,21 +712,22 @@ public class Shelly2ApiClient extends ShellyHttpClient { } } - protected @Nullable ArrayList fillInputSettings(ShellyDeviceProfile profile, + protected @Nullable ArrayList<@Nullable ShellySettingsInput> fillInputSettings(ShellyDeviceProfile profile, Shelly2GetConfigResult dc) { if (dc.input0 == null) { return null; // device has no input } - ArrayList inputs = new ArrayList<>(); + ArrayList<@Nullable ShellySettingsInput> inputs = new ArrayList<>(); addInputSettings(inputs, dc.input0); addInputSettings(inputs, dc.input1); addInputSettings(inputs, dc.input2); addInputSettings(inputs, dc.input3); + return inputs; } - private void addInputSettings(ArrayList inputs, @Nullable Shelly2DevConfigInput ic) { + private void addInputSettings(List<@Nullable ShellySettingsInput> inputs, @Nullable Shelly2DevConfigInput ic) { if (ic == null) { return; } @@ -807,6 +811,7 @@ public class Shelly2ApiClient extends ShellyHttpClient { } protected ShellyDeviceProfile getProfile() throws ShellyApiException { + ShellyThingInterface thing = this.thing; if (thing != null) { return thing.getProfile(); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java index b78257d1ef0..fee00d32463 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2ApiRpc.java @@ -44,9 +44,11 @@ import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySensorSl import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay; +import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRoller; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsUpdate; import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsWiFiNetwork; @@ -158,7 +160,6 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } } - @SuppressWarnings("null") @Override public ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice devInfo) throws ShellyApiException { @@ -197,9 +198,15 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac profile.settings.rollers = fillRollerSettings(profile, dc); profile.isEMeter = true; - profile.numInputs = profile.settings.inputs != null ? profile.settings.inputs.size() : 0; - profile.numRelays = profile.settings.relays != null ? profile.settings.relays.size() : 0; - profile.numRollers = profile.settings.rollers != null ? profile.settings.rollers.size() : 0; + List inputs = profile.settings.inputs; + profile.numInputs = inputs != null ? inputs.size() : 0; + + List relays = profile.settings.relays; + profile.numRelays = relays != null ? relays.size() : 0; + + List rollers = profile.settings.rollers; + profile.numRollers = rollers != null ? rollers.size() : 0; + profile.hasRelays = profile.numRelays > 0 || profile.numRollers > 0; if (getString(profile.device.mode).isEmpty() && profile.hasRelays) { profile.device.mode = profile.isRoller ? SHELLY_CLASS_ROLLER : SHELLY_CLASS_RELAY; @@ -291,8 +298,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } if (profile.isDimmer) { - profile.settings.dimmers = new ArrayList<>(); - profile.settings.dimmers.add(new ShellySettingsDimmer()); + ArrayList<@Nullable ShellySettingsDimmer> dimmers = new ArrayList<>(); + dimmers.add(new ShellySettingsDimmer()); + profile.settings.dimmers = dimmers; profile.status.dimmers = new ArrayList<>(); profile.status.dimmers.add(new ShellyShortLightStatus()); fillDimmerSettings(profile, dc); @@ -318,7 +326,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac asyncApiRequest(SHELLYRPC_METHOD_GETSTATUS); // request periodic status updates from device try { - if (profile.alwaysOn && config.enableBluGateway != null && dc.ble != null) { + if (profile.alwaysOn && dc.ble != null) { logger.debug("{}: BLU Gateway support is {} for this device", thingName, config.enableBluGateway ? "enabled" : "disabled"); if (config.enableBluGateway) { @@ -556,6 +564,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac @Override public void onConnect(String deviceIp, boolean connected) { + ShellyThingTable thingTable = this.thingTable; if (thing == null && thingTable != null) { thing = thingTable.getThing(deviceIp); logger.debug("{}: Get thing from thingTable", thingName); @@ -751,12 +760,14 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac @Override public void onError(Throwable cause) { logger.debug("{}: WebSocket error: {}", thingName, cause.getMessage()); + ShellyThingInterface thing = this.thing; if (thing != null && thing.getProfile().alwaysOn) { thingOffline("WebSocket error"); } } private void thingOffline(String reason) { + ShellyThingInterface thing = this.thing; if (thing != null) { // do not reinit of battery powered devices with sleep mode thing.setThingOfflineAndDisconnect(ThingStatusDetail.COMMUNICATION_ERROR, "offline.status-error-unexpected-error", reason); @@ -862,8 +873,9 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac public void setRelayTurn(int id, String turnMode) throws ShellyApiException { ShellyDeviceProfile profile = getProfile(); int rIdx = id; - if (profile.settings.relays != null) { - Integer rid = profile.settings.relays.get(id).id; + List relays = profile.settings.relays; + if (relays != null) { + Integer rid = relays.get(id).id; if (rid != null) { rIdx = rid; } @@ -1190,7 +1202,6 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac rpcSocket.sendMessage(gson.toJson(request)); // submit, result wull be async } - @SuppressWarnings("null") public T apiRequest(String method, @Nullable Object params, Class classOfT) throws ShellyApiException { String json = ""; Shelly2RpcBaseMessage req = buildRequest(method, params); @@ -1202,7 +1213,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac String auth = getString(res.authChallenge); if (res.isHttpAccessUnauthorized() && !auth.isEmpty()) { String[] options = auth.split(","); - authInfo = new Shelly2AuthChallenge(); + Shelly2AuthChallenge authInfo = this.authInfo = new Shelly2AuthChallenge(); for (String o : options) { String key = substringBefore(o, "=").stripLeading().trim(); String value = substringAfter(o, "=").replace("\"", "").trim(); @@ -1229,17 +1240,22 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } Shelly2RpcBaseMessage response = gson.fromJson(json, Shelly2RpcBaseMessage.class); if (response == null) { - throw new IllegalArgumentException("Unable to cover API result to obhect"); + throw new ShellyApiException("Unable to convert API result to object"); } if (response.result != null) { // return sub element result as requested class type - json = gson.toJson(gson.fromJson(json, Shelly2RpcBaseMessage.class).result); + json = gson.toJson(response.result); boolean isString = response.result instanceof String; return fromJson(gson, isString && "null".equalsIgnoreCase(((String) response.result)) ? "{}" : json, classOfT); } else { // return direct format - return gson.fromJson(json, classOfT == String.class ? Shelly2RpcBaseMessage.class : classOfT); + @Nullable + T result = gson.fromJson(json, classOfT == String.class ? Shelly2RpcBaseMessage.class : classOfT); + if (result == null) { + throw new ShellyApiException("Unable to convert API result to object"); + } + return result; } } @@ -1284,6 +1300,7 @@ public class Shelly2ApiRpc extends Shelly2ApiClient implements ShellyApiInterfac } private void incProtErrors() { + ShellyThingInterface thing = this.thing; if (thing != null) { thing.incProtErrors(); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java index 5c5480f9310..edb8622d2cd 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/Shelly2RpcSocket.java @@ -33,7 +33,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.openhab.binding.shelly.internal.api.ShellyApiException; -import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2NotifyEvent; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2RpcBaseMessage; import org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.Shelly2RpcNotifyEvent; @@ -47,10 +46,6 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; /** - * {@link Shelly1HttpApi} wraps the Shelly REST API and provides various low level function to access the device api - * (not - * cloud api). - * * @author Markus Michels - Initial contribution */ @NonNullByDefault @@ -151,11 +146,13 @@ public class Shelly2RpcSocket { // This is the inbound event web socket deviceIp = session.getRemoteAddress().getAddress().getHostAddress(); } + Shelly2RpctInterface websocketHandler = this.websocketHandler; if (websocketHandler == null) { + ShellyThingTable thingTable = this.thingTable; if (thingTable != null) { ShellyThingInterface thing = thingTable.getThing(deviceIp); Shelly2ApiRpc api = (Shelly2ApiRpc) thing.getApi(); - websocketHandler = api.getRpcHandler(); + websocketHandler = this.websocketHandler = api.getRpcHandler(); } } connectLatch.countDown(); @@ -182,8 +179,8 @@ public class Shelly2RpcSocket { * @param str API request message * @throws ShellyApiException */ - @SuppressWarnings("null") public void sendMessage(String str) throws ShellyApiException { + Session session = this.session; if (session != null) { try { connectLatch.await(); @@ -201,15 +198,15 @@ public class Shelly2RpcSocket { */ public void disconnect() { try { + Session session = this.session; if (session != null) { - Session s = session; - if (s.isOpen()) { - logger.debug("{}: Disconnecting WebSocket ({} -> {})", thingName, s.getLocalAddress(), - s.getRemoteAddress()); + if (session.isOpen()) { + logger.debug("{}: Disconnecting WebSocket ({} -> {})", thingName, session.getLocalAddress(), + session.getRemoteAddress()); } - s.disconnect(); - s.close(StatusCode.NORMAL, "Socket closed"); - session = null; + session.disconnect(); + session.close(StatusCode.NORMAL, "Socket closed"); + this.session = null; } } catch (Exception e) { if (e.getCause() instanceof InterruptedException) { @@ -230,7 +227,7 @@ public class Shelly2RpcSocket { /** * Inbound WebSocket message * - * @param session WebSpcket session + * @param session WebSocket session * @param receivedMessage Textial API message */ @OnWebSocketMessage @@ -263,17 +260,18 @@ public class Shelly2RpcSocket { } else { for (Shelly2NotifyEvent e : events.params.events) { if (getString(e.event).startsWith(SHELLY2_EVENT_BLUPREFIX)) { - String address = getString(e.data.addr).replace(":", ""); + String address = getString(e.data != null ? e.data.addr : "").replace(":", ""); + ShellyThingTable thingTable = this.thingTable; if (thingTable != null && thingTable.findThing(address) != null) { - if (thingTable != null) { // known device - ShellyThingInterface thing = thingTable.getThing(address); - Shelly2ApiRpc api = (Shelly2ApiRpc) thing.getApi(); - handler = api.getRpcHandler(); - handler.onNotifyEvent( - fromJson(gson, receivedMessage, Shelly2RpcNotifyEvent.class)); - } - } else { // new device - if (e.event.equals(SHELLY2_EVENT_BLUSCAN)) { + // known device + ShellyThingInterface thing = thingTable.getThing(address); + Shelly2ApiRpc api = (Shelly2ApiRpc) thing.getApi(); + handler = api.getRpcHandler(); + handler.onNotifyEvent( + fromJson(gson, receivedMessage, Shelly2RpcNotifyEvent.class)); + } else { + // new device + if (SHELLY2_EVENT_BLUSCAN.equals(e.event)) { ShellyBluSensorHandler.addBluThing(message.src, e, thingTable); } else { logger.debug("{}: NotifyEvent {} for unknown device {}", message.src, @@ -295,12 +293,11 @@ public class Shelly2RpcSocket { } } catch (ShellyApiException | IllegalArgumentException e) { logger.debug("{}: Unable to process Rpc message ({}): {}", thingName, e.getMessage(), receivedMessage); - } catch (NullPointerException e) { - logger.debug("{}: Unable to process Rpc message: {}", thingName, receivedMessage, e); } } public boolean isConnected() { + Session session = this.session; return session != null && session.isOpen(); } @@ -324,6 +321,7 @@ public class Shelly2RpcSocket { return; } disconnect(); + Shelly2RpctInterface websocketHandler = this.websocketHandler; if (websocketHandler != null) { websocketHandler.onClose(statusCode, reason); } @@ -340,6 +338,7 @@ public class Shelly2RpcSocket { // Ignore disconnect: Device establishes the socket, sends NotifyxFullStatus and disconnects return; } + Shelly2RpctInterface websocketHandler = this.websocketHandler; if (websocketHandler != null) { websocketHandler.onError(cause); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java index 8fcb53a6f7d..1ef791d311f 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/api2/ShellyBluApi.java @@ -18,6 +18,7 @@ import static org.openhab.binding.shelly.internal.api2.Shelly2ApiJsonDTO.*; import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -154,11 +155,12 @@ public class ShellyBluApi extends Shelly2ApiRpc { profile.numInputs = 1; settings.btnType = SHELLY_BTNT_MOMENTARY; - if (profile.settings.inputs != null) { - profile.settings.inputs.set(0, settings); + List inputs = profile.settings.inputs; + if (inputs != null) { + inputs.set(0, settings); } else { - profile.settings.inputs = new ArrayList<>(); - profile.settings.inputs.add(settings); + inputs = profile.settings.inputs = new ArrayList<>(); + inputs.add(settings); } profile.status = deviceStatus; } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyBasicDiscoveryService.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyBasicDiscoveryService.java index 27b234cc080..054dd4eaba0 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyBasicDiscoveryService.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/discovery/ShellyBasicDiscoveryService.java @@ -97,6 +97,7 @@ public class ShellyBasicDiscoveryService extends AbstractDiscoveryService { } public void unregisterDeviceDiscoveryService() { + ServiceRegistration discoveryService = this.discoveryService; if (discoveryService != null) { discoveryService.unregister(); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java index 52f9a53917b..36ff91f8682 100755 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyBaseHandler.java @@ -269,6 +269,7 @@ public abstract class ShellyBaseHandler extends BaseThingHandler public void handleConfigurationUpdate(Map configurationParameters) { super.handleConfigurationUpdate(configurationParameters); logger.debug("{}: Thing config updated, re-initialize", thingName); + Shelly1CoapHandler coap = this.coap; if (coap != null) { coap.stop(); } @@ -315,6 +316,7 @@ public abstract class ShellyBaseHandler extends BaseThingHandler // Gen 1 only: Setup CoAP listener to we get the CoAP message, which triggers initialization even the thing // could not be fully initialized here. In this case the CoAP messages triggers auto-initialization (like the // Action URL does when enabled) + Shelly1CoapHandler coap = this.coap; if (coap != null && config.eventsCoIoT && !profile.alwaysOn) { coap.start(thingName, config); } @@ -453,10 +455,11 @@ public abstract class ShellyBaseHandler extends BaseThingHandler id = getNumber(command).intValue(); } else { String cmd = command.toString(); + List thermostats = profile.settings.thermostats; if (isDigit(cmd.charAt(0))) { id = Integer.parseInt(cmd); - } else if (profile.settings.thermostats != null) { - ShellyThermnostat t = profile.settings.thermostats.get(0); + } else if (thermostats != null) { + ShellyThermnostat t = thermostats.get(0); for (int i = 0; i < t.profileNames.length; i++) { if (t.profileNames[i].equalsIgnoreCase(cmd)) { id = i + 1; @@ -1077,35 +1080,30 @@ public abstract class ShellyBaseHandler extends BaseThingHandler } private void checkVersion(ShellyDeviceProfile prf, ShellySettingsStatus status) { - try { - if (prf.fwVersion.isEmpty()) { - // no fw version available (e.g. BLU device) - return; + if (prf.fwVersion.isEmpty()) { + // no fw version available (e.g. BLU device) + return; + } + ShellyVersionDTO version = new ShellyVersionDTO(); + if (version.checkBeta(getString(prf.fwVersion))) { + logger.info("{}: {}", prf.device.hostname, messages.get("versioncheck.beta", prf.fwVersion, prf.fwDate)); + } else { + String minVersion = !gen2 ? SHELLY_API_MIN_FWVERSION : SHELLY2_API_MIN_FWVERSION; + if (version.compare(prf.fwVersion, minVersion) < 0) { + logger.warn("{}: {}", prf.device.hostname, + messages.get("versioncheck.tooold", prf.fwVersion, prf.fwDate, minVersion)); } - ShellyVersionDTO version = new ShellyVersionDTO(); - if (version.checkBeta(getString(prf.fwVersion))) { - logger.info("{}: {}", prf.device.hostname, - messages.get("versioncheck.beta", prf.fwVersion, prf.fwDate)); - } else { - String minVersion = !gen2 ? SHELLY_API_MIN_FWVERSION : SHELLY2_API_MIN_FWVERSION; - if (version.compare(prf.fwVersion, minVersion) < 0) { - logger.warn("{}: {}", prf.device.hostname, - messages.get("versioncheck.tooold", prf.fwVersion, prf.fwDate, minVersion)); - } + } + if (!gen2 && bindingConfig.autoCoIoT && ((version.compare(prf.fwVersion, SHELLY_API_MIN_FWCOIOT)) >= 0) + || ("production_test".equalsIgnoreCase(prf.fwVersion))) { + if (!config.eventsCoIoT) { + logger.info("{}: {}", thingName, messages.get("versioncheck.autocoiot")); } - if (!gen2 && bindingConfig.autoCoIoT && ((version.compare(prf.fwVersion, SHELLY_API_MIN_FWCOIOT)) >= 0) - || ("production_test".equalsIgnoreCase(prf.fwVersion))) { - if (!config.eventsCoIoT) { - logger.info("{}: {}", thingName, messages.get("versioncheck.autocoiot")); - } - autoCoIoT = true; - } - if (status.update.hasUpdate && !version.checkBeta(getString(prf.fwVersion))) { - logger.info("{}: {}", thingName, - messages.get("versioncheck.update", status.update.oldVersion, status.update.newVersion)); - } - } catch (NullPointerException e) { // could be inconsistant format of beta version - logger.debug("{}: {}", thingName, messages.get("versioncheck.failed", prf.fwVersion)); + autoCoIoT = true; + } + if (Boolean.TRUE.equals(status.update.hasUpdate) && !version.checkBeta(getString(prf.fwVersion))) { + logger.info("{}: {}", thingName, + messages.get("versioncheck.update", status.update.oldVersion, status.update.newVersion)); } } @@ -1148,6 +1146,7 @@ public abstract class ShellyBaseHandler extends BaseThingHandler } logger.debug("{}: Starting CoIoT (autoCoIoT={}/{})", thingName, bindingConfig.autoCoIoT, autoCoIoT); + Shelly1CoapHandler coap = this.coap; if (coap != null) { coap.start(thingName, config); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java index c49f36eff3f..cfbe08415eb 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyColorUtils.java @@ -149,9 +149,9 @@ public class ShellyColorUtils { for (int i = 0; i < rgbw.length; i++) { values[i] = Integer.parseInt(rgbw[i]); } - } catch (NullPointerException e) { // might be a format problem + } catch (NumberFormatException e) { // might be a format problem throw new IllegalArgumentException( - "Unable to convert fullColor value: " + rgbwString + ", " + e.getMessage()); + "Unable to convert fullColor value: " + rgbwString + ", " + e.getMessage(), e); } if (values[0] != -1) { setRed(values[0]); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java index 979ecf7e875..a62b1752894 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyComponents.java @@ -16,6 +16,8 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*; import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; +import java.util.List; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.shelly.internal.api.ShellyApiException; @@ -100,8 +102,9 @@ public class ShellyComponents { ShellyDeviceProfile profile = thingHandler.getProfile(); ShellySettingsRelay relay = status.relays.get(id); ShellySettingsRelay rsettings; - if (profile.settings.relays != null) { - rsettings = profile.settings.relays.get(id); + List relays = profile.settings.relays; + if (relays != null) { + rsettings = relays.get(id); } else { throw new IllegalArgumentException("No relay settings"); } @@ -409,8 +412,9 @@ public class ShellyComponents { temp.doubleValue(), getString(sdata.tmp.units)); } else if (status.thermostats != null) { // Shelly TRV - if (profile.settings.thermostats != null) { - ShellyThermnostat ps = profile.settings.thermostats.get(0); + List thermostats = profile.settings.thermostats; + if (thermostats != null) { + ShellyThermnostat ps = thermostats.get(0); ShellyThermnostat t = status.thermostats.get(0); int bminutes = getInteger(t.boostMinutes) >= 0 ? getInteger(t.boostMinutes) : getInteger(ps.boostMinutes); @@ -586,9 +590,12 @@ public class ShellyComponents { .createDimmerChannels(thingHandler.getThing(), profile, dstatus, l)); } - ShellySettingsDimmer ds = profile.settings.dimmers.get(l); - if (ds.name != null) { - updated |= thingHandler.updateChannel(groupName, CHANNEL_OUTPUT_NAME, getStringType(ds.name)); + List dimmers = profile.settings.dimmers; + if (dimmers != null) { + ShellySettingsDimmer ds = dimmers.get(l); + if (ds.name != null) { + updated |= thingHandler.updateChannel(groupName, CHANNEL_OUTPUT_NAME, getStringType(ds.name)); + } } // On a status update we map a dimmer.ison = false to brightness 0 rather than the device's brightness @@ -606,14 +613,12 @@ public class ShellyComponents { } } - if (profile.settings.dimmers != null) { - ShellySettingsDimmer dsettings = profile.settings.dimmers.get(l); - if (dsettings != null) { - updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOON, - toQuantityType(getDouble(dsettings.autoOn), Units.SECOND)); - updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOOFF, - toQuantityType(getDouble(dsettings.autoOff), Units.SECOND)); - } + if (dimmers != null) { + ShellySettingsDimmer dsettings = dimmers.get(l); + updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOON, + toQuantityType(getDouble(dsettings.autoOn), Units.SECOND)); + updated |= thingHandler.updateChannel(groupName, CHANNEL_TIMER_AUTOOFF, + toQuantityType(getDouble(dsettings.autoOff), Units.SECOND)); } l++; diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java index 70012d5bc16..15bd9cf2d6f 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyLightHandler.java @@ -16,6 +16,7 @@ import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*; import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*; import static org.openhab.binding.shelly.internal.util.ShellyUtils.*; +import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -335,9 +336,10 @@ public class ShellyLightHandler extends ShellyBaseHandler { ShellyColorUtils col = getCurrentColors(lightId); col.power = getOnOff(light.ison); - if (profile.settings.lights != null) { + List lights = profile.settings.lights; + if (lights != null) { // Channel control/timer - ShellySettingsRgbwLight ls = profile.settings.lights.get(lightId); + ShellySettingsRgbwLight ls = lights.get(lightId); updated |= updateChannel(controlGroup, CHANNEL_TIMER_AUTOON, toQuantityType(getDouble(ls.autoOn), Units.SECOND)); updated |= updateChannel(controlGroup, CHANNEL_TIMER_AUTOOFF, diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingTable.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingTable.java index 1be5407c200..1b95041bb35 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingTable.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/handler/ShellyThingTable.java @@ -82,7 +82,8 @@ public class ShellyThingTable { public void startDiscoveryService(BundleContext bundleContext) { if (discoveryService == null) { - discoveryService = new ShellyBasicDiscoveryService(bundleContext, this); + ShellyBasicDiscoveryService discoveryService = this.discoveryService = new ShellyBasicDiscoveryService( + bundleContext, this); discoveryService.registerDeviceDiscoveryService(); } } @@ -94,20 +95,23 @@ public class ShellyThingTable { } public void stopDiscoveryService() { + ShellyBasicDiscoveryService discoveryService = this.discoveryService; if (discoveryService != null) { discoveryService.unregisterDeviceDiscoveryService(); - discoveryService = null; + this.discoveryService = null; } } public void discoveredResult(ThingTypeUID uid, String model, String serviceName, String address, Map properties) { + ShellyBasicDiscoveryService discoveryService = this.discoveryService; if (discoveryService != null) { discoveryService.discoveredResult(uid, model, serviceName, address, properties); } } public void discoveredResult(DiscoveryResult result) { + ShellyBasicDiscoveryService discoveryService = this.discoveryService; if (discoveryService != null) { discoveryService.discoveredResult(result); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerCache.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerCache.java index ef39f19ea90..a9681677610 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerCache.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerCache.java @@ -16,6 +16,7 @@ import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; /** @@ -23,6 +24,7 @@ import org.eclipse.jdt.annotation.Nullable; * * @author Markus Michels - Initial contribution */ +@NonNullByDefault public class ShellyManagerCache extends ConcurrentHashMap { private static final long serialVersionUID = 1L; @@ -56,8 +58,9 @@ public class ShellyManagerCache extends ConcurrentHashMap { throw new IllegalArgumentException(); } for (K key : m.keySet()) { + @Nullable V value = m.get(key); - if (value != null) { // don't allow null values + if (key != null && value != null) { // don't allow null values put(key, value); } } @@ -87,7 +90,8 @@ public class ShellyManagerCache extends ConcurrentHashMap { private void cleanMap() { long currentTime = new Date().getTime(); for (K key : timeMap.keySet()) { - if (currentTime > (timeMap.get(key) + expiryInMillis)) { + Long timeValue = timeMap.get(key); + if (key != null && (timeValue == null || currentTime > (timeValue + expiryInMillis))) { remove(key); timeMap.remove(key); } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java index 9f52b55a0ab..fc35d708b1a 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/manager/ShellyManagerPage.java @@ -591,12 +591,11 @@ public class ShellyManagerPage { timer.schedule(task, delay * 1000); } - protected @Nullable Map getThingHandlers() { + protected Map getThingHandlers() { return handlerFactory.getThingHandlers(); } protected @Nullable ShellyManagerInterface getThingHandler(String uid) { - Map th = getThingHandlers(); - return th != null ? th.get(uid) : null; + return getThingHandlers().get(uid); } } diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java index d6468589e6b..b5c911ec649 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyChannelDefinitions.java @@ -360,8 +360,9 @@ public class ShellyChannelDefinitions { Map add = new LinkedHashMap<>(); String group = profile.getControlGroup(idx); - if (profile.settings.relays != null) { - ShellySettingsRelay rs = profile.settings.relays.get(idx); + List relays = profile.settings.relays; + if (relays != null) { + ShellySettingsRelay rs = relays.get(idx); addChannel(thing, add, rs.ison != null, group, CHANNEL_OUTPUT); addChannel(thing, add, rs.name != null, group, CHANNEL_OUTPUT_NAME); @@ -408,8 +409,9 @@ public class ShellyChannelDefinitions { // Shelly Dimmer has an additional brightness channel addChannel(thing, add, profile.isDimmer, group, CHANNEL_BRIGHTNESS); - if (profile.settings.dimmers != null) { - ShellySettingsDimmer ds = profile.settings.dimmers.get(idx); + List dimmers = profile.settings.dimmers; + if (dimmers != null) { + ShellySettingsDimmer ds = dimmers.get(idx); addChannel(thing, add, ds.name != null, group, CHANNEL_OUTPUT_NAME); addChannel(thing, add, ds.autoOn != null, group, CHANNEL_TIMER_AUTOON); addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF); @@ -424,8 +426,9 @@ public class ShellyChannelDefinitions { Map add = new LinkedHashMap<>(); String group = profile.getControlGroup(idx); - if (profile.settings.lights != null) { - ShellySettingsRgbwLight light = profile.settings.lights.get(idx); + List lights = profile.settings.lights; + if (lights != null) { + ShellySettingsRgbwLight light = lights.get(idx); String whiteGroup = profile.isRGBW2 ? group : CHANNEL_GROUP_WHITE_CONTROL; // Create power channel in color mode and brightness channel in white mode addChannel(thing, add, profile.inColor, group, CHANNEL_LIGHT_POWER); diff --git a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyStateDescriptionProvider.java b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyStateDescriptionProvider.java index aef857eb546..714984e3944 100644 --- a/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyStateDescriptionProvider.java +++ b/bundles/org.openhab.binding.shelly/src/main/java/org/openhab/binding/shelly/internal/provider/ShellyStateDescriptionProvider.java @@ -58,7 +58,6 @@ public class ShellyStateDescriptionProvider extends BaseDynamicStateDescriptionP this.thingRegistry = thingRegistry; } - @SuppressWarnings("null") @Override public @Nullable StateDescription getStateDescription(Channel channel, @Nullable StateDescription originalStateDescription, @Nullable Locale locale) { @@ -68,6 +67,9 @@ public class ShellyStateDescriptionProvider extends BaseDynamicStateDescriptionP } Thing thing = thingRegistry.get(channel.getUID().getThingUID()); + if (thing == null) { + return null; + } ShellyThingInterface handler = (ShellyThingInterface) thing.getHandler(); if (handler == null) { return null; diff --git a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties index ff97262c0f7..934f815b44e 100644 --- a/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties +++ b/bundles/org.openhab.binding.shelly/src/main/resources/OH-INF/i18n/shelly.properties @@ -29,7 +29,6 @@ message.offline.status-error-fwupgrade = Firmware upgrade in progress. message.offline.status-error-fwcompleted = Firmware upgrade completed, device is restarting. # General messages -message.versioncheck.failed = Unable to check firmware version: {0} message.versioncheck.beta = Device is running a Beta version: {0}/{1} message.versioncheck.tooold = WARNING: Firmware might be too old, installed: {0}/{1}, minimal required {2} message.versioncheck.update = INFO: New firmware available: current version: {0}, new version: {1}