httpReason = contentResponse.getReason();
Request request = contentResponse.getRequest();
- if (request != null) {
- url = request.getURI().toString();
- method = request.getMethod();
- }
+ url = request.getURI().toString();
+ method = request.getMethod();
}
}
}
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;
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);
}
hasRelays = (numRelays > 0) || isDimmer;
numRollers = getInteger(device.numRollers);
- numInputs = settings.inputs != null ? settings.inputs.size() : hasRelays ? isRoller ? 2 : 1 : 0;
+ List<ShellySettingsInput> 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);
} 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<ShellySettingsRgbwLight> 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;
return "";
}
- @SuppressWarnings("null")
public boolean inButtonMode(int idx) {
if (idx < 0) {
logger.debug("{}: Invalid index {} for inButtonMode()", thingName, idx);
return false;
}
String btnType = "";
+ List<ShellySettingsInput> inputs = settings.inputs;
+ List<ShellySettingsDimmer> dimmers = settings.dimmers;
+ List<ShellySettingsRelay> relays = settings.relays;
+ List<ShellySettingsRgbwLight> 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);
}
}
public String[] getValveProfileList(int valveId) {
- if (isTRV && settings.thermostats != null) {
- int sz = settings.thermostats.size();
+ List<ShellyThermnostat> 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];
public String getValueProfile(int valveId, int profileId) {
int id = profileId;
- if (id <= 0 && settings.thermostats != null) {
- id = settings.thermostats.get(0).profile;
+ List<ShellyThermnostat> thermostats = settings.thermostats;
+ if (id <= 0 && thermostats != null) {
+ id = thermostats.get(0).profile;
}
return "" + id;
}
@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;
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("");
+ }
}
}
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;
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;
/**
* {@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
*/
@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<ShellyThermnostat> 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
}
@Override
public void startValveBoost(int valveId, int value) throws ShellyApiException {
- if (profile.settings.thermostats != null) {
- ShellyThermnostat t = profile.settings.thermostats.get(0);
+ List<ShellyThermnostat> 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);
}
}
private void setDimmerEvents() throws ShellyApiException {
- if (profile.settings.dimmers != null) {
- int sz = profile.settings.dimmers.size();
+ List<ShellySettingsDimmer> dimmers = profile.settings.dimmers;
+ if (dimmers != null) {
+ int sz = dimmers.size();
for (int i = 0; i < sz; i++) {
setEventUrls(i);
}
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;
}
private int getRelayIdx(ShellyDeviceProfile profile, @Nullable Integer id) {
- if (id != null && profile.settings.relays != null) {
+ List<ShellySettingsRelay> 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;
}
return;
}
- if (profile.settings.dimmers != null) {
- ShellySettingsDimmer ds = profile.settings.dimmers.get(0);
+ List<ShellySettingsDimmer> 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);
}
}
}
}
- protected @Nullable ArrayList<ShellySettingsInput> fillInputSettings(ShellyDeviceProfile profile,
+ protected @Nullable ArrayList<@Nullable ShellySettingsInput> fillInputSettings(ShellyDeviceProfile profile,
Shelly2GetConfigResult dc) {
if (dc.input0 == null) {
return null; // device has no input
}
- ArrayList<ShellySettingsInput> 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<ShellySettingsInput> inputs, @Nullable Shelly2DevConfigInput ic) {
+ private void addInputSettings(List<@Nullable ShellySettingsInput> inputs, @Nullable Shelly2DevConfigInput ic) {
if (ic == null) {
return;
}
}
protected ShellyDeviceProfile getProfile() throws ShellyApiException {
+ ShellyThingInterface thing = this.thing;
if (thing != null) {
return thing.getProfile();
}
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;
}
}
- @SuppressWarnings("null")
@Override
public ShellyDeviceProfile getDeviceProfile(String thingType, @Nullable ShellySettingsDevice devInfo)
throws ShellyApiException {
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<ShellySettingsInput> inputs = profile.settings.inputs;
+ profile.numInputs = inputs != null ? inputs.size() : 0;
+
+ List<ShellySettingsRelay> relays = profile.settings.relays;
+ profile.numRelays = relays != null ? relays.size() : 0;
+
+ List<ShellySettingsRoller> 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;
}
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);
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) {
@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);
@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);
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<ShellySettingsRelay> relays = profile.settings.relays;
+ if (relays != null) {
+ Integer rid = relays.get(id).id;
if (rid != null) {
rIdx = rid;
}
rpcSocket.sendMessage(gson.toJson(request)); // submit, result wull be async
}
- @SuppressWarnings("null")
public <T> T apiRequest(String method, @Nullable Object params, Class<T> classOfT) throws ShellyApiException {
String json = "";
Shelly2RpcBaseMessage req = buildRequest(method, params);
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();
}
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;
}
}
}
private void incProtErrors() {
+ ShellyThingInterface thing = this.thing;
if (thing != null) {
thing.incProtErrors();
}
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;
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
// 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();
* @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();
*/
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) {
/**
* Inbound WebSocket message
*
- * @param session WebSpcket session
+ * @param session WebSocket session
* @param receivedMessage Textial API message
*/
@OnWebSocketMessage
} 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,
}
} 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();
}
return;
}
disconnect();
+ Shelly2RpctInterface websocketHandler = this.websocketHandler;
if (websocketHandler != null) {
websocketHandler.onClose(statusCode, reason);
}
// Ignore disconnect: Device establishes the socket, sends NotifyxFullStatus and disconnects
return;
}
+ Shelly2RpctInterface websocketHandler = this.websocketHandler;
if (websocketHandler != null) {
websocketHandler.onError(cause);
}
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;
profile.numInputs = 1;
settings.btnType = SHELLY_BTNT_MOMENTARY;
- if (profile.settings.inputs != null) {
- profile.settings.inputs.set(0, settings);
+ List<ShellySettingsInput> 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;
}
}
public void unregisterDeviceDiscoveryService() {
+ ServiceRegistration<?> discoveryService = this.discoveryService;
if (discoveryService != null) {
discoveryService.unregister();
}
public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
super.handleConfigurationUpdate(configurationParameters);
logger.debug("{}: Thing config updated, re-initialize", thingName);
+ Shelly1CoapHandler coap = this.coap;
if (coap != null) {
coap.stop();
}
// 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);
}
id = getNumber(command).intValue();
} else {
String cmd = command.toString();
+ List<ShellyThermnostat> 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;
}
private void checkVersion(ShellyDeviceProfile prf, ShellySettingsStatus status) {
- try {
- 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));
- }
- }
- 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 (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));
}
- if (status.update.hasUpdate && !version.checkBeta(getString(prf.fwVersion))) {
- logger.info("{}: {}", thingName,
- messages.get("versioncheck.update", status.update.oldVersion, status.update.newVersion));
+ }
+ 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"));
}
- } 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));
}
}
}
logger.debug("{}: Starting CoIoT (autoCoIoT={}/{})", thingName, bindingConfig.autoCoIoT, autoCoIoT);
+ Shelly1CoapHandler coap = this.coap;
if (coap != null) {
coap.start(thingName, config);
}
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]);
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;
ShellyDeviceProfile profile = thingHandler.getProfile();
ShellySettingsRelay relay = status.relays.get(id);
ShellySettingsRelay rsettings;
- if (profile.settings.relays != null) {
- rsettings = profile.settings.relays.get(id);
+ List<ShellySettingsRelay> relays = profile.settings.relays;
+ if (relays != null) {
+ rsettings = relays.get(id);
} else {
throw new IllegalArgumentException("No relay settings");
}
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<ShellyThermnostat> 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);
.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<ShellySettingsDimmer> 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
}
}
- 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++;
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;
ShellyColorUtils col = getCurrentColors(lightId);
col.power = getOnOff(light.ison);
- if (profile.settings.lights != null) {
+ List<ShellySettingsRgbwLight> 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,
public void startDiscoveryService(BundleContext bundleContext) {
if (discoveryService == null) {
- discoveryService = new ShellyBasicDiscoveryService(bundleContext, this);
+ ShellyBasicDiscoveryService discoveryService = this.discoveryService = new ShellyBasicDiscoveryService(
+ bundleContext, this);
discoveryService.registerDeviceDiscoveryService();
}
}
}
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<String, Object> 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);
}
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
*
* @author Markus Michels - Initial contribution
*/
+@NonNullByDefault
public class ShellyManagerCache<K, V> extends ConcurrentHashMap<K, V> {
private static final long serialVersionUID = 1L;
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);
}
}
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);
}
timer.schedule(task, delay * 1000);
}
- protected @Nullable Map<String, ShellyManagerInterface> getThingHandlers() {
+ protected Map<String, ShellyManagerInterface> getThingHandlers() {
return handlerFactory.getThingHandlers();
}
protected @Nullable ShellyManagerInterface getThingHandler(String uid) {
- Map<String, ShellyManagerInterface> th = getThingHandlers();
- return th != null ? th.get(uid) : null;
+ return getThingHandlers().get(uid);
}
}
Map<String, Channel> add = new LinkedHashMap<>();
String group = profile.getControlGroup(idx);
- if (profile.settings.relays != null) {
- ShellySettingsRelay rs = profile.settings.relays.get(idx);
+ List<ShellySettingsRelay> 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);
// 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<ShellySettingsDimmer> 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);
Map<String, Channel> add = new LinkedHashMap<>();
String group = profile.getControlGroup(idx);
- if (profile.settings.lights != null) {
- ShellySettingsRgbwLight light = profile.settings.lights.get(idx);
+ List<ShellySettingsRgbwLight> 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);
this.thingRegistry = thingRegistry;
}
- @SuppressWarnings("null")
@Override
public @Nullable StateDescription getStateDescription(Channel channel,
@Nullable StateDescription originalStateDescription, @Nullable Locale locale) {
}
Thing thing = thingRegistry.get(channel.getUID().getThingUID());
+ if (thing == null) {
+ return null;
+ }
ShellyThingInterface handler = (ShellyThingInterface) thing.getHandler();
if (handler == null) {
return null;
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}