mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[innogysmarthome] NullPointerException fixed which could occur when no device state is available (#9660) (#9677)
* [innogysmarthome] Bug-fix - NPE solved which could occur when devices without a corresponding device state were returned by the API. That happened with the virtual device "NotificationSender" which is unimportant for the binding. Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] JavaDoc fixed Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimizations (warnings fixed) Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code refactoring (InnogyClient class split to make it smaller) Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization ; Potential bug with the reachable attribute solved (it was set multiple times within a loop) Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Tests added Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Tests added Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code changed to not overwrite the reachable state provided by the API (when no corresponding message is available) Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Copyright notice updated Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> * [innogysmarthome] Code and performance optimization Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com> Co-authored-by: Sven Strohschein <sven.strohschein@gmail.com>
This commit is contained in:
parent
fcb774ca35
commit
3557094c13
@ -12,19 +12,15 @@
|
||||
*/
|
||||
package org.openhab.binding.innogysmarthome.internal.client;
|
||||
|
||||
import static org.openhab.binding.innogysmarthome.internal.InnogyBindingConstants.*;
|
||||
import static org.openhab.binding.innogysmarthome.internal.client.Constants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -36,7 +32,6 @@ import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.openhab.binding.innogysmarthome.internal.InnogyBindingConstants;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.StatusResponse;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.action.Action;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.action.ShutterAction;
|
||||
@ -48,7 +43,6 @@ import org.openhab.binding.innogysmarthome.internal.client.entity.device.DeviceS
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.Gateway;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.State;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.error.ErrorResponse;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.link.Link;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.location.Location;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.message.Message;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.exception.ApiException;
|
||||
@ -103,13 +97,6 @@ public class InnogyClient {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the bridgeInfo
|
||||
*/
|
||||
public @Nullable Gateway getBridgeDetails() {
|
||||
return bridgeDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status
|
||||
*
|
||||
@ -117,8 +104,6 @@ public class InnogyClient {
|
||||
* the {@link #configVersion} is set.
|
||||
*
|
||||
* @throws SessionExistsException thrown, if a session already exists
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void refreshStatus() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Get innogy SmartHome status...");
|
||||
@ -133,12 +118,9 @@ public class InnogyClient {
|
||||
/**
|
||||
* Executes a HTTP GET request with default headers and returns data as object of type T.
|
||||
*
|
||||
* @param url
|
||||
* @param url request URL
|
||||
* @param clazz type of data to return
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws AuthenticationException
|
||||
* @throws ApiException
|
||||
* @return response content
|
||||
*/
|
||||
private <T> T executeGet(final String url, final Class<T> clazz)
|
||||
throws IOException, AuthenticationException, ApiException {
|
||||
@ -150,11 +132,9 @@ public class InnogyClient {
|
||||
/**
|
||||
* Executes a HTTP GET request with default headers and returns data as List of type T.
|
||||
*
|
||||
* @param url
|
||||
* @param url request URL
|
||||
* @param clazz array type of data to return as list
|
||||
* @throws IOException
|
||||
* @throws AuthenticationException
|
||||
* @throws ApiException
|
||||
* @return response content (as a List)
|
||||
*/
|
||||
private <T> List<T> executeGetList(final String url, final Class<T[]> clazz)
|
||||
throws IOException, AuthenticationException, ApiException {
|
||||
@ -164,19 +144,15 @@ public class InnogyClient {
|
||||
/**
|
||||
* Executes a HTTP POST request with the given {@link Action} as content.
|
||||
*
|
||||
* @param url
|
||||
* @param action
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws AuthenticationException
|
||||
* @throws ApiException
|
||||
* @param url request URL
|
||||
* @param action action to execute
|
||||
*/
|
||||
private ContentResponse executePost(final String url, final Action action)
|
||||
private void executePost(final String url, final Action action)
|
||||
throws IOException, AuthenticationException, ApiException {
|
||||
final String json = gson.toJson(action);
|
||||
logger.debug("Action {} JSON: {}", action.getType(), json);
|
||||
|
||||
return request(httpClient.newRequest(url).method(HttpMethod.POST)
|
||||
request(httpClient.newRequest(url).method(HttpMethod.POST)
|
||||
.content(new StringContentProvider(json), CONTENT_TYPE).accept(CONTENT_TYPE));
|
||||
}
|
||||
|
||||
@ -197,6 +173,7 @@ public class InnogyClient {
|
||||
}
|
||||
|
||||
public AccessTokenResponse getAccessTokenResponse() throws AuthenticationException, IOException {
|
||||
@Nullable
|
||||
final AccessTokenResponse accessTokenResponse;
|
||||
try {
|
||||
accessTokenResponse = oAuthService.getAccessTokenResponse();
|
||||
@ -212,17 +189,11 @@ public class InnogyClient {
|
||||
/**
|
||||
* Handles errors from the {@link ContentResponse} and throws the following errors:
|
||||
*
|
||||
* @param response
|
||||
* @param response response
|
||||
* @param uri uri of api call made
|
||||
* @throws SessionExistsException
|
||||
* @throws SessionNotFoundException
|
||||
* @throws ControllerOfflineException thrown, if the innogy SmartHome controller (SHC) is offline.
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
private void handleResponseErrors(final ContentResponse response, final URI uri)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
private void handleResponseErrors(final ContentResponse response, final URI uri) throws IOException, ApiException {
|
||||
String content = "";
|
||||
|
||||
switch (response.getStatus()) {
|
||||
@ -275,11 +246,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets a new state of a SwitchActuator.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param state
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setSwitchActuatorState(final String capabilityId, final boolean state)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -288,11 +254,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets the dimmer level of a DimmerActuator.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param dimLevel
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setDimmerActuatorState(final String capabilityId, final int dimLevel)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -301,12 +262,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets the roller shutter level of a RollerShutterActuator.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param rollerShutterLevel
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void setRollerShutterActuatorState(final String capabilityId, final int rollerShutterLevel)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -316,12 +271,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Starts or stops moving a RollerShutterActuator
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param rollerShutterAction
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void setRollerShutterAction(final String capabilityId,
|
||||
final ShutterAction.ShutterActions rollerShutterAction)
|
||||
@ -331,11 +280,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets a new state of a VariableActuator.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param state
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setVariableActuatorState(final String capabilityId, final boolean state)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -344,11 +288,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets the point temperature.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param pointTemperature
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setPointTemperatureState(final String capabilityId, final double pointTemperature)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -358,11 +297,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets the operation mode to "Auto" or "Manu".
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param autoMode
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setOperationMode(final String capabilityId, final boolean autoMode)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -374,11 +308,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Sets the alarm state.
|
||||
*
|
||||
* @param capabilityId
|
||||
* @param alarmState
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public void setAlarmActuatorState(final String capabilityId, final boolean alarmState)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -388,222 +317,26 @@ public class InnogyClient {
|
||||
/**
|
||||
* Load the device and returns a {@link List} of {@link Device}s..
|
||||
*
|
||||
* @param deviceIds Ids of the devices to return
|
||||
* @return List of Devices
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Device> getDevices() throws IOException, ApiException, AuthenticationException {
|
||||
public List<Device> getDevices(Collection<String> deviceIds)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading innogy devices...");
|
||||
return executeGetList(API_URL_DEVICE, Device[].class);
|
||||
List<Device> devices = executeGetList(API_URL_DEVICE, Device[].class);
|
||||
return devices.stream().filter(d -> deviceIds.contains(d.getId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the {@link Device} with the given deviceId.
|
||||
*
|
||||
* @param deviceId
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public Device getDeviceById(final String deviceId) throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading device with id {}...", deviceId);
|
||||
return executeGet(API_URL_DEVICE_ID.replace("{id}", deviceId), Device.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all {@link Device}s with the full configuration details, {@link Capability}s and
|
||||
* states. Calling this may take a while...
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Device> getFullDevices() throws IOException, ApiException, AuthenticationException {
|
||||
// LOCATIONS
|
||||
final List<Location> locationList = getLocations();
|
||||
final Map<String, Location> locationMap = new HashMap<>();
|
||||
for (final Location l : locationList) {
|
||||
locationMap.put(l.getId(), l);
|
||||
}
|
||||
|
||||
// CAPABILITIES
|
||||
final List<Capability> capabilityList = getCapabilities();
|
||||
final Map<String, Capability> capabilityMap = new HashMap<>();
|
||||
for (final Capability c : capabilityList) {
|
||||
capabilityMap.put(c.getId(), c);
|
||||
}
|
||||
|
||||
// CAPABILITY STATES
|
||||
final List<CapabilityState> capabilityStateList = getCapabilityStates();
|
||||
final Map<String, CapabilityState> capabilityStateMap = new HashMap<>();
|
||||
for (final CapabilityState cs : capabilityStateList) {
|
||||
capabilityStateMap.put(cs.getId(), cs);
|
||||
}
|
||||
|
||||
// DEVICE STATES
|
||||
final List<DeviceState> deviceStateList = getDeviceStates();
|
||||
final Map<String, DeviceState> deviceStateMap = new HashMap<>();
|
||||
for (final DeviceState es : deviceStateList) {
|
||||
deviceStateMap.put(es.getId(), es);
|
||||
}
|
||||
|
||||
// MESSAGES
|
||||
final List<Message> messageList = getMessages();
|
||||
final Map<String, List<Message>> deviceMessageMap = new HashMap<>();
|
||||
for (final Message m : messageList) {
|
||||
if (m.getDevices() != null && !m.getDevices().isEmpty()) {
|
||||
final String deviceId = m.getDevices().get(0).replace("/device/", "");
|
||||
List<Message> ml;
|
||||
if (deviceMessageMap.containsKey(deviceId)) {
|
||||
ml = deviceMessageMap.get(deviceId);
|
||||
} else {
|
||||
ml = new ArrayList<>();
|
||||
}
|
||||
ml.add(m);
|
||||
deviceMessageMap.put(deviceId, ml);
|
||||
}
|
||||
}
|
||||
|
||||
// DEVICES
|
||||
final List<Device> deviceList = getDevices();
|
||||
for (final Device d : deviceList) {
|
||||
if (InnogyBindingConstants.BATTERY_POWERED_DEVICES.contains(d.getType())) {
|
||||
d.setIsBatteryPowered(true);
|
||||
}
|
||||
|
||||
// location
|
||||
d.setLocation(locationMap.get(d.getLocationId()));
|
||||
final HashMap<String, Capability> deviceCapabilityMap = new HashMap<>();
|
||||
|
||||
// capabilities and their states
|
||||
for (final String cl : d.getCapabilityLinkList()) {
|
||||
final Capability c = capabilityMap.get(Link.getId(cl));
|
||||
final String capabilityId = c.getId();
|
||||
final CapabilityState capabilityState = capabilityStateMap.get(capabilityId);
|
||||
c.setCapabilityState(capabilityState);
|
||||
deviceCapabilityMap.put(capabilityId, c);
|
||||
}
|
||||
d.setCapabilityMap(deviceCapabilityMap);
|
||||
|
||||
// device states
|
||||
d.setDeviceState(deviceStateMap.get(d.getId()));
|
||||
|
||||
// messages
|
||||
if (deviceMessageMap.containsKey(d.getId())) {
|
||||
d.setMessageList(deviceMessageMap.get(d.getId()));
|
||||
for (final Message m : d.getMessageList()) {
|
||||
switch (m.getType()) {
|
||||
case Message.TYPE_DEVICE_LOW_BATTERY:
|
||||
d.setLowBattery(true);
|
||||
d.setLowBatteryMessageId(m.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Device} with the given deviceId with full configuration details, {@link Capability}s and
|
||||
* states. Calling this may take a little bit longer...
|
||||
*
|
||||
* @param deviceId
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public Device getFullDeviceById(final String deviceId) throws IOException, ApiException, AuthenticationException {
|
||||
// LOCATIONS
|
||||
final List<Location> locationList = getLocations();
|
||||
final Map<String, Location> locationMap = new HashMap<>();
|
||||
for (final Location l : locationList) {
|
||||
locationMap.put(l.getId(), l);
|
||||
}
|
||||
|
||||
// CAPABILITIES FOR DEVICE
|
||||
final List<Capability> capabilityList = getCapabilitiesForDevice(deviceId);
|
||||
final Map<String, Capability> capabilityMap = new HashMap<>();
|
||||
for (final Capability c : capabilityList) {
|
||||
capabilityMap.put(c.getId(), c);
|
||||
}
|
||||
|
||||
// CAPABILITY STATES
|
||||
final List<CapabilityState> capabilityStateList = getCapabilityStates();
|
||||
final Map<String, CapabilityState> capabilityStateMap = new HashMap<>();
|
||||
for (final CapabilityState cs : capabilityStateList) {
|
||||
capabilityStateMap.put(cs.getId(), cs);
|
||||
}
|
||||
|
||||
// DEVICE STATE
|
||||
final State state = getDeviceStateByDeviceId(deviceId);
|
||||
final DeviceState deviceState = new DeviceState();
|
||||
deviceState.setId(deviceId);
|
||||
deviceState.setState(state);
|
||||
|
||||
// MESSAGES
|
||||
final List<Message> messageList = getMessages();
|
||||
final List<Message> ml = new ArrayList<>();
|
||||
final String deviceIdPath = "/device/" + deviceId;
|
||||
|
||||
for (final Message m : messageList) {
|
||||
logger.trace("Message Type {} with ID {}", m.getType(), m.getId());
|
||||
if (m.getDevices() != null && !m.getDevices().isEmpty()) {
|
||||
for (final String li : m.getDevices()) {
|
||||
if (deviceIdPath.equals(li)) {
|
||||
ml.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DEVICE
|
||||
final Device d = getDeviceById(deviceId);
|
||||
if (BATTERY_POWERED_DEVICES.contains(d.getType())) {
|
||||
d.setIsBatteryPowered(true);
|
||||
d.setLowBattery(false);
|
||||
}
|
||||
|
||||
// location
|
||||
d.setLocation(locationMap.get(d.getLocationId()));
|
||||
|
||||
// capabilities and their states
|
||||
final HashMap<String, Capability> deviceCapabilityMap = new HashMap<>();
|
||||
for (final String cl : d.getCapabilityLinkList()) {
|
||||
|
||||
final Capability c = capabilityMap.get(Link.getId(cl));
|
||||
c.setCapabilityState(capabilityStateMap.get(c.getId()));
|
||||
deviceCapabilityMap.put(c.getId(), c);
|
||||
|
||||
}
|
||||
d.setCapabilityMap(deviceCapabilityMap);
|
||||
|
||||
// device states
|
||||
d.setDeviceState(deviceState);
|
||||
|
||||
// messages
|
||||
if (!ml.isEmpty()) {
|
||||
d.setMessageList(ml);
|
||||
for (final Message m : d.getMessageList()) {
|
||||
switch (m.getType()) {
|
||||
case Message.TYPE_DEVICE_LOW_BATTERY:
|
||||
d.setLowBattery(true);
|
||||
d.setLowBatteryMessageId(m.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the states for all {@link Device}s.
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<DeviceState> getDeviceStates() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading device states...");
|
||||
@ -612,11 +345,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Loads the device state for the given deviceId.
|
||||
*
|
||||
* @param deviceId
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public State getDeviceStateByDeviceId(final String deviceId)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -628,8 +356,6 @@ public class InnogyClient {
|
||||
* Loads the locations and returns a {@link List} of {@link Location}s.
|
||||
*
|
||||
* @return a List of Devices
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Location> getLocations() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading locations...");
|
||||
@ -640,9 +366,7 @@ public class InnogyClient {
|
||||
* Loads and returns a {@link List} of {@link Capability}s for the given deviceId.
|
||||
*
|
||||
* @param deviceId the id of the {@link Device}
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
* @return capabilities of the device
|
||||
*/
|
||||
public List<Capability> getCapabilitiesForDevice(final String deviceId)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
@ -652,10 +376,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Loads and returns a {@link List} of all {@link Capability}s.
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Capability> getCapabilities() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading capabilities...");
|
||||
@ -664,10 +384,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Loads and returns a {@link List} of all {@link Capability}States.
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<CapabilityState> getCapabilityStates() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading capability states...");
|
||||
@ -676,10 +392,6 @@ public class InnogyClient {
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all {@link Message}s.
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Message> getMessages() throws IOException, ApiException, AuthenticationException {
|
||||
logger.debug("Loading messages...");
|
||||
@ -692,11 +404,4 @@ public class InnogyClient {
|
||||
public String getConfigVersion() {
|
||||
return configVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configVersion the configVersion to set
|
||||
*/
|
||||
public void setConfigVersion(final String configVersion) {
|
||||
this.configVersion = configVersion;
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,7 @@ package org.openhab.binding.innogysmarthome.internal.client.entity.device;
|
||||
|
||||
import static org.openhab.binding.innogysmarthome.internal.InnogyBindingConstants.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.location.Location;
|
||||
@ -38,8 +36,6 @@ public class Device {
|
||||
protected static final String PROTOCOL_ID_VIRTUAL = "Virtual";
|
||||
protected static final String PROTOCOL_ID_WMBUS = "wMBus";
|
||||
|
||||
public static final List<String> EMPTY_CAPABILITY_LINK_LIST = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Unique id for the device, always available in model.
|
||||
*/
|
||||
@ -82,15 +78,9 @@ public class Device {
|
||||
|
||||
private DeviceConfig config;
|
||||
|
||||
/**
|
||||
* Contains a list of the device capabilities.
|
||||
*
|
||||
* Optional.
|
||||
*/
|
||||
@SerializedName("capabilities")
|
||||
private List<String> capabilityLinkList;
|
||||
private List<String> capabilities;
|
||||
|
||||
private HashMap<String, Capability> capabilityMap;
|
||||
private Map<String, Capability> capabilityMap;
|
||||
|
||||
private DeviceState deviceState;
|
||||
|
||||
@ -115,12 +105,6 @@ public class Device {
|
||||
private List<Message> messageList;
|
||||
|
||||
private boolean lowBattery;
|
||||
/**
|
||||
* Stores the message id, that contains the low battery state. This is needed to identify the device, when the
|
||||
* message
|
||||
* with that id is deleted (thus low battery state is false again).
|
||||
*/
|
||||
private String lowBatteryMessageId;
|
||||
|
||||
/**
|
||||
* Stores, if the {@link Device} is battery powered.
|
||||
@ -263,32 +247,28 @@ public class Device {
|
||||
/**
|
||||
* @return the capabilityList
|
||||
*/
|
||||
public List<String> getCapabilityLinkList() {
|
||||
if (capabilityLinkList != null) {
|
||||
return capabilityLinkList;
|
||||
} else {
|
||||
return EMPTY_CAPABILITY_LINK_LIST;
|
||||
}
|
||||
public List<String> getCapabilities() {
|
||||
return Objects.requireNonNullElse(capabilities, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param capabilityList the capabilityList to set
|
||||
*/
|
||||
public void setCapabilityList(List<String> capabilityList) {
|
||||
this.capabilityLinkList = capabilityList;
|
||||
public void setCapabilities(List<String> capabilityList) {
|
||||
this.capabilities = capabilityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param capabilityMap the capabilityMap to set
|
||||
*/
|
||||
public void setCapabilityMap(HashMap<String, Capability> capabilityMap) {
|
||||
public void setCapabilityMap(Map<String, Capability> capabilityMap) {
|
||||
this.capabilityMap = capabilityMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the capabilityMap
|
||||
*/
|
||||
public HashMap<String, Capability> getCapabilityMap() {
|
||||
public Map<String, Capability> getCapabilityMap() {
|
||||
return this.capabilityMap;
|
||||
}
|
||||
|
||||
@ -310,7 +290,7 @@ public class Device {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param locationList the locationList to set
|
||||
* @param locationLink the locationList to set
|
||||
*/
|
||||
public void setLocation(String locationLink) {
|
||||
this.locationLink = locationLink;
|
||||
@ -366,10 +346,31 @@ public class Device {
|
||||
*/
|
||||
public void setMessageList(List<Message> messageList) {
|
||||
this.messageList = messageList;
|
||||
applyMessageList(messageList);
|
||||
}
|
||||
|
||||
for (final Message m : messageList) {
|
||||
setLowBattery(Message.TYPE_DEVICE_LOW_BATTERY.equals(m.getType()));
|
||||
setReachable(!Message.TYPE_DEVICE_UNREACHABLE.equals(m.getType()));
|
||||
private void applyMessageList(List<Message> messageList) {
|
||||
if (messageList != null && !messageList.isEmpty()) {
|
||||
boolean isUnreachableMessageFound = false;
|
||||
boolean isLowBatteryMessageFound = false;
|
||||
for (final Message message : messageList) {
|
||||
switch (message.getType()) {
|
||||
case Message.TYPE_DEVICE_UNREACHABLE:
|
||||
isUnreachableMessageFound = true;
|
||||
break;
|
||||
case Message.TYPE_DEVICE_LOW_BATTERY:
|
||||
isLowBatteryMessageFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnreachableMessageFound) {
|
||||
setReachable(false); // overwrite only when there is a corresponding message (to keep the state of the
|
||||
// API in other cases)
|
||||
}
|
||||
if (isLowBatteryMessageFound) {
|
||||
setLowBattery(true); // overwrite only when there is a corresponding message (to keep the state of the
|
||||
// API in other cases)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +379,7 @@ public class Device {
|
||||
*
|
||||
* @param isReachable
|
||||
*/
|
||||
public void setReachable(boolean isReachable) {
|
||||
private void setReachable(boolean isReachable) {
|
||||
if (getDeviceState().hasIsReachableState()) {
|
||||
getDeviceState().setReachable(isReachable);
|
||||
}
|
||||
@ -398,7 +399,7 @@ public class Device {
|
||||
*
|
||||
* @param hasLowBattery
|
||||
*/
|
||||
public void setLowBattery(boolean hasLowBattery) {
|
||||
private void setLowBattery(boolean hasLowBattery) {
|
||||
this.lowBattery = hasLowBattery;
|
||||
}
|
||||
|
||||
@ -411,14 +412,6 @@ public class Device {
|
||||
return lowBattery;
|
||||
}
|
||||
|
||||
public String getLowBatteryMessageId() {
|
||||
return this.lowBatteryMessageId;
|
||||
}
|
||||
|
||||
public void setLowBatteryMessageId(String messageId) {
|
||||
this.lowBatteryMessageId = messageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, if the {@link Device} is battery powered.
|
||||
*
|
||||
|
@ -49,6 +49,7 @@ import org.openhab.binding.innogysmarthome.internal.discovery.InnogyDeviceDiscov
|
||||
import org.openhab.binding.innogysmarthome.internal.listener.DeviceStatusListener;
|
||||
import org.openhab.binding.innogysmarthome.internal.listener.EventListener;
|
||||
import org.openhab.binding.innogysmarthome.internal.manager.DeviceStructureManager;
|
||||
import org.openhab.binding.innogysmarthome.internal.manager.FullDeviceManager;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
|
||||
import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
@ -167,7 +168,7 @@ public class InnogyBridgeHandler extends BaseBridgeHandler
|
||||
if (checkOnAuthCode()) {
|
||||
final InnogyClient localClient = createInnogyClient(oAuthService, httpClient);
|
||||
client = localClient;
|
||||
deviceStructMan = new DeviceStructureManager(localClient);
|
||||
deviceStructMan = new DeviceStructureManager(createFullDeviceManager(localClient));
|
||||
oAuthService.addAccessTokenRefreshListener(this);
|
||||
registerDeviceStatusListener(InnogyBridgeHandler.this);
|
||||
scheduleRestartClient(false);
|
||||
@ -892,6 +893,10 @@ public class InnogyBridgeHandler extends BaseBridgeHandler
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
FullDeviceManager createFullDeviceManager(InnogyClient client) {
|
||||
return new FullDeviceManager(client);
|
||||
}
|
||||
|
||||
InnogyClient createInnogyClient(final OAuthClientService oAuthService, final HttpClient httpClient) {
|
||||
return new InnogyClient(oAuthService, httpClient);
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import static org.openhab.binding.innogysmarthome.internal.InnogyBindingConstant
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.FormatStyle;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
@ -708,7 +707,7 @@ public class InnogyDeviceHandler extends BaseThingHandler implements DeviceStatu
|
||||
boolean deviceChanged = false;
|
||||
final String linkedCapabilityId = event.getSourceId();
|
||||
|
||||
HashMap<String, Capability> capabilityMap = device.getCapabilityMap();
|
||||
Map<String, Capability> capabilityMap = device.getCapabilityMap();
|
||||
Capability capability = capabilityMap.get(linkedCapabilityId);
|
||||
logger.trace("Loaded Capability {}, {} with id {}, device {} from device id {}", capability.getType(),
|
||||
capability.getName(), capability.getId(), capability.getDeviceLink(), device.getId());
|
||||
|
@ -46,7 +46,7 @@ public class DeviceStructureManager {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(DeviceStructureManager.class);
|
||||
|
||||
private final InnogyClient client;
|
||||
private final FullDeviceManager deviceManager;
|
||||
private final Map<String, Device> deviceMap;
|
||||
private final Map<String, Device> capabilityIdToDeviceMap;
|
||||
private String bridgeDeviceId = "";
|
||||
@ -54,10 +54,10 @@ public class DeviceStructureManager {
|
||||
/**
|
||||
* Constructs the {@link DeviceStructureManager}.
|
||||
*
|
||||
* @param client the {@link InnogyClient}
|
||||
* @param deviceManager the {@link FullDeviceManager}
|
||||
*/
|
||||
public DeviceStructureManager(InnogyClient client) {
|
||||
this.client = client;
|
||||
public DeviceStructureManager(FullDeviceManager deviceManager) {
|
||||
this.deviceManager = deviceManager;
|
||||
deviceMap = Collections.synchronizedMap(new HashMap<>());
|
||||
capabilityIdToDeviceMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
@ -82,7 +82,7 @@ public class DeviceStructureManager {
|
||||
public void refreshDevices() throws IOException, ApiException, AuthenticationException {
|
||||
deviceMap.clear();
|
||||
capabilityIdToDeviceMap.clear();
|
||||
List<Device> devices = client.getFullDevices();
|
||||
List<Device> devices = deviceManager.getFullDevices();
|
||||
for (Device d : devices) {
|
||||
handleRefreshedDevice(d);
|
||||
}
|
||||
@ -98,7 +98,7 @@ public class DeviceStructureManager {
|
||||
*/
|
||||
public void refreshDevice(String deviceId) throws IOException, ApiException, AuthenticationException {
|
||||
logger.trace("Refreshing Device with id '{}'", deviceId);
|
||||
Device d = client.getFullDeviceById(deviceId);
|
||||
Device d = deviceManager.getFullDeviceById(deviceId);
|
||||
handleRefreshedDevice(d);
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ public class DeviceStructureManager {
|
||||
getDeviceMap().put(device.getId(), device);
|
||||
}
|
||||
|
||||
for (String cl : device.getCapabilityLinkList()) {
|
||||
for (String cl : device.getCapabilities()) {
|
||||
capabilityIdToDeviceMap.put(Link.getId(cl), device);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.innogysmarthome.internal.manager;
|
||||
|
||||
import static org.openhab.binding.innogysmarthome.internal.InnogyBindingConstants.BATTERY_POWERED_DEVICES;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.InnogyClient;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.capability.CapabilityState;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.DeviceState;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.link.Link;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.location.Location;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.message.Message;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.exception.ApiException;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.exception.AuthenticationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Sven Strohschein - Initial contribution (but only created by refactoring the InnogyClient class)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FullDeviceManager {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FullDeviceManager.class);
|
||||
|
||||
private final InnogyClient client;
|
||||
|
||||
public FullDeviceManager(InnogyClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of all {@link Device}s with the full configuration details, {@link Capability}s and
|
||||
* states. Calling this may take a while...
|
||||
*/
|
||||
public List<Device> getFullDevices() throws IOException, ApiException, AuthenticationException {
|
||||
|
||||
final Map<String, Location> locationMap = createLocationMap(client);
|
||||
final Map<String, Capability> capabilityMap = createCapabilityMap(client);
|
||||
final Map<String, DeviceState> deviceStateMap = createDeviceStateMap(client);
|
||||
final Map<String, List<Message>> messageMap = createMessageMap(client);
|
||||
|
||||
final List<Device> deviceList = client.getDevices(deviceStateMap.keySet());
|
||||
for (final Device device : deviceList) {
|
||||
final String deviceId = device.getId();
|
||||
initializeDevice(device, deviceStateMap.get(deviceId), locationMap, capabilityMap,
|
||||
getMessageList(device, messageMap));
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Device} with the given deviceId with full configuration details, {@link Capability}s and
|
||||
* states. Calling this may take a little bit longer...
|
||||
*/
|
||||
public Device getFullDeviceById(final String deviceId) throws IOException, ApiException, AuthenticationException {
|
||||
final Map<String, Location> locationMap = createLocationMap(client);
|
||||
final Map<String, Capability> capabilityMap = createCapabilityMap(deviceId, client);
|
||||
final List<Message> messageMap = createMessageMap(deviceId, client);
|
||||
|
||||
final DeviceState deviceState = new DeviceState();
|
||||
deviceState.setId(deviceId);
|
||||
deviceState.setState(client.getDeviceStateByDeviceId(deviceId));
|
||||
|
||||
final Device device = client.getDeviceById(deviceId);
|
||||
initializeDevice(device, deviceState, locationMap, capabilityMap, messageMap);
|
||||
return device;
|
||||
}
|
||||
|
||||
private void initializeDevice(Device device, @Nullable DeviceState deviceState, Map<String, Location> locationMap,
|
||||
Map<String, Capability> capabilityMap, List<Message> messageList) {
|
||||
|
||||
device.setDeviceState(deviceState);
|
||||
|
||||
if (isBatteryPowered(device)) {
|
||||
device.setIsBatteryPowered(true);
|
||||
}
|
||||
|
||||
device.setLocation(locationMap.get(device.getLocationId()));
|
||||
|
||||
device.setCapabilityMap(createDeviceCapabilityMap(device, capabilityMap));
|
||||
|
||||
device.setMessageList(messageList);
|
||||
}
|
||||
|
||||
private static boolean isBatteryPowered(Device device) {
|
||||
return BATTERY_POWERED_DEVICES.contains(device.getType());
|
||||
}
|
||||
|
||||
private List<Message> getMessageList(Device device, Map<String, List<Message>> messageMap) {
|
||||
return Objects.requireNonNullElse(messageMap.get(device.getId()), Collections.emptyList());
|
||||
}
|
||||
|
||||
private static Map<String, Location> createLocationMap(InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
final List<Location> locationList = client.getLocations();
|
||||
final Map<String, Location> locationMap = new HashMap<>(locationList.size());
|
||||
for (final Location location : locationList) {
|
||||
locationMap.put(location.getId(), location);
|
||||
}
|
||||
return locationMap;
|
||||
}
|
||||
|
||||
private static Map<String, CapabilityState> createCapabilityStateMap(InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
final List<CapabilityState> capabilityStateList = client.getCapabilityStates();
|
||||
final Map<String, CapabilityState> capabilityStateMap = new HashMap<>(capabilityStateList.size());
|
||||
for (final CapabilityState capabilityState : capabilityStateList) {
|
||||
capabilityStateMap.put(capabilityState.getId(), capabilityState);
|
||||
}
|
||||
return capabilityStateMap;
|
||||
}
|
||||
|
||||
private static Map<String, Capability> createCapabilityMap(InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
|
||||
final Map<String, CapabilityState> capabilityStateMap = createCapabilityStateMap(client);
|
||||
final List<Capability> capabilityList = client.getCapabilities();
|
||||
|
||||
return initializeCapabilities(capabilityStateMap, capabilityList);
|
||||
}
|
||||
|
||||
private static Map<String, Capability> createCapabilityMap(String deviceId, InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
|
||||
final Map<String, CapabilityState> capabilityStateMap = createCapabilityStateMap(client);
|
||||
final List<Capability> capabilityList = client.getCapabilitiesForDevice(deviceId);
|
||||
|
||||
return initializeCapabilities(capabilityStateMap, capabilityList);
|
||||
}
|
||||
|
||||
private static Map<String, Capability> initializeCapabilities(Map<String, CapabilityState> capabilityStateMap,
|
||||
List<Capability> capabilityList) {
|
||||
final Map<String, Capability> capabilityMap = new HashMap<>(capabilityList.size());
|
||||
for (final Capability capability : capabilityList) {
|
||||
String capabilityId = capability.getId();
|
||||
|
||||
CapabilityState capabilityState = capabilityStateMap.get(capabilityId);
|
||||
capability.setCapabilityState(capabilityState);
|
||||
|
||||
capabilityMap.put(capabilityId, capability);
|
||||
}
|
||||
return capabilityMap;
|
||||
}
|
||||
|
||||
private static Map<String, Capability> createDeviceCapabilityMap(Device device,
|
||||
Map<String, Capability> capabilityMap) {
|
||||
|
||||
final HashMap<String, Capability> deviceCapabilityMap = new HashMap<>();
|
||||
for (final String capabilityValue : device.getCapabilities()) {
|
||||
final Capability capability = capabilityMap.get(Link.getId(capabilityValue));
|
||||
final String capabilityId = capability.getId();
|
||||
deviceCapabilityMap.put(capabilityId, capability);
|
||||
}
|
||||
return deviceCapabilityMap;
|
||||
}
|
||||
|
||||
private static Map<String, DeviceState> createDeviceStateMap(InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
final List<DeviceState> deviceStateList = client.getDeviceStates();
|
||||
final Map<String, DeviceState> deviceStateMap = new HashMap<>(deviceStateList.size());
|
||||
for (final DeviceState deviceState : deviceStateList) {
|
||||
deviceStateMap.put(deviceState.getId(), deviceState);
|
||||
}
|
||||
return deviceStateMap;
|
||||
}
|
||||
|
||||
private List<Message> createMessageMap(String deviceId, InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
final List<Message> messages = client.getMessages();
|
||||
final List<Message> messageList = new ArrayList<>();
|
||||
final String deviceIdPath = "/device/" + deviceId;
|
||||
|
||||
for (final Message message : messages) {
|
||||
logger.trace("Message Type {} with ID {}", message.getType(), message.getId());
|
||||
if (message.getDevices() != null && !message.getDevices().isEmpty()) {
|
||||
for (final String li : message.getDevices()) {
|
||||
if (deviceIdPath.equals(li)) {
|
||||
messageList.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return messageList;
|
||||
}
|
||||
|
||||
private static Map<String, List<Message>> createMessageMap(InnogyClient client)
|
||||
throws IOException, ApiException, AuthenticationException {
|
||||
final List<Message> messageList = client.getMessages();
|
||||
final Map<String, List<Message>> deviceMessageMap = new HashMap<>();
|
||||
for (final Message message : messageList) {
|
||||
if (message.getDevices() != null && !message.getDevices().isEmpty()) {
|
||||
final String deviceId = message.getDevices().get(0).replace("/device/", "");
|
||||
List<Message> ml;
|
||||
if (deviceMessageMap.containsKey(deviceId)) {
|
||||
ml = deviceMessageMap.get(deviceId);
|
||||
} else {
|
||||
ml = new ArrayList<>();
|
||||
}
|
||||
ml.add(message);
|
||||
deviceMessageMap.put(deviceId, ml);
|
||||
}
|
||||
}
|
||||
return deviceMessageMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.innogysmarthome.internal.client.entity.device;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.message.Message;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.state.BooleanState;
|
||||
|
||||
/**
|
||||
* @author Sven Strohschein - Initial contribution
|
||||
*/
|
||||
public class DeviceTest {
|
||||
|
||||
@Test
|
||||
public void testSetMessageListLowBatteryMessage() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(Collections.singletonList(createMessage(Message.TYPE_DEVICE_LOW_BATTERY)));
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListUnreachableMessage() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(Collections.singletonList(createMessage(Message.TYPE_DEVICE_UNREACHABLE)));
|
||||
|
||||
assertFalse(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListResetByEmpty() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertNull(device.getMessageList());
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
List<Message> messages = Arrays.asList(createMessage(Message.TYPE_DEVICE_LOW_BATTERY),
|
||||
createMessage(Message.TYPE_DEVICE_UNREACHABLE));
|
||||
device.setMessageList(messages);
|
||||
|
||||
assertEquals(messages, device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(Collections.emptyList());
|
||||
|
||||
// Nothing should get changed.
|
||||
// New messages are only set in real-life when the device is refreshed with new data of the API.
|
||||
// Therefore the data of the API should be kept / not overwritten when no corresponding messages are available.
|
||||
assertEquals(Collections.emptyList(), device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListResetByNULL() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertNull(device.getMessageList());
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
List<Message> messages = Arrays.asList(createMessage(Message.TYPE_DEVICE_LOW_BATTERY),
|
||||
createMessage(Message.TYPE_DEVICE_UNREACHABLE));
|
||||
device.setMessageList(messages);
|
||||
|
||||
assertEquals(messages, device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(null);
|
||||
|
||||
// Nothing should get changed.
|
||||
// New messages are only set in real-life when the device is refreshed with new data of the API.
|
||||
// Therefore the data of the API should be kept / not overwritten when no corresponding messages are available.
|
||||
assertNull(device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListResetByUnimportantMessage() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertNull(device.getMessageList());
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
List<Message> messages = Arrays.asList(createMessage(Message.TYPE_DEVICE_LOW_BATTERY),
|
||||
createMessage(Message.TYPE_DEVICE_UNREACHABLE));
|
||||
device.setMessageList(messages);
|
||||
|
||||
assertEquals(messages, device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
|
||||
messages = Collections.singletonList(createMessage("UNKNOWN"));
|
||||
device.setMessageList(messages);
|
||||
|
||||
// Nothing should get changed.
|
||||
// New messages are only set in real-life when the device is refreshed with new data of the API.
|
||||
// Therefore the data of the API should be kept / not overwritten when no corresponding messages are available.
|
||||
assertEquals(messages, device.getMessageList());
|
||||
assertFalse(device.isReachable());
|
||||
assertTrue(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListUnimportantMessage() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(Collections.singletonList(createMessage("UNKNOWN")));
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
}
|
||||
|
||||
private Message createMessage(String messageType) {
|
||||
Message message = new Message();
|
||||
message.setType(messageType);
|
||||
return message;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListNULL() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(null);
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMessageListEmpty() {
|
||||
Device device = createDevice();
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
|
||||
device.setMessageList(Collections.emptyList());
|
||||
|
||||
assertTrue(device.isReachable());
|
||||
assertFalse(device.hasLowBattery());
|
||||
}
|
||||
|
||||
private static Device createDevice() {
|
||||
BooleanState isReachableState = new BooleanState();
|
||||
isReachableState.setValue(true);
|
||||
|
||||
State state = new State();
|
||||
state.setIsReachable(isReachableState);
|
||||
|
||||
DeviceState deviceState = new DeviceState();
|
||||
deviceState.setState(state);
|
||||
|
||||
Device device = new Device();
|
||||
device.setDeviceState(deviceState);
|
||||
return device;
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import org.openhab.binding.innogysmarthome.internal.InnogyWebSocket;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.InnogyClient;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device;
|
||||
import org.openhab.binding.innogysmarthome.internal.client.entity.device.DeviceConfig;
|
||||
import org.openhab.binding.innogysmarthome.internal.manager.FullDeviceManager;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthClientService;
|
||||
import org.openhab.core.auth.client.oauth2.OAuthFactory;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
@ -174,6 +175,7 @@ public class InnogyBridgeHandlerTest {
|
||||
private class InnogyBridgeHandlerAccessible extends InnogyBridgeHandler {
|
||||
|
||||
private final InnogyClient innogyClientMock;
|
||||
private final FullDeviceManager fullDeviceManagerMock;
|
||||
private final ScheduledExecutorService schedulerMock;
|
||||
private int executionCount;
|
||||
private int directExecutionCount;
|
||||
@ -188,7 +190,8 @@ public class InnogyBridgeHandlerTest {
|
||||
bridgeDevice.setConfig(new DeviceConfig());
|
||||
|
||||
innogyClientMock = mock(InnogyClient.class);
|
||||
when(innogyClientMock.getFullDevices()).thenReturn(Collections.singletonList(bridgeDevice));
|
||||
fullDeviceManagerMock = mock(FullDeviceManager.class);
|
||||
when(fullDeviceManagerMock.getFullDevices()).thenReturn(Collections.singletonList(bridgeDevice));
|
||||
|
||||
schedulerMock = mock(ScheduledExecutorService.class);
|
||||
|
||||
@ -218,6 +221,12 @@ public class InnogyBridgeHandlerTest {
|
||||
return directExecutionCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
FullDeviceManager createFullDeviceManager(@NonNull InnogyClient client) {
|
||||
return fullDeviceManagerMock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
InnogyClient createInnogyClient(@NonNull OAuthClientService oAuthService, @NonNull HttpClient httpClient) {
|
||||
|
Loading…
Reference in New Issue
Block a user