[amazonechocontrol] improvements and bug fixes (#9057)

* fixed: InterrupedException
* changed: single and group queues to device queue
added: standard volume to speak request
* changed: log from info to debug
* fix compile warnings
* remove dependency on StringUtils
* more improvements
* fix HandlerPowerController
* attempt to solve stopping tts
* logging powercontroller
* fix smarthome devices not updating
* finalize smarthome device update fix
* additional device information logging for discovery
* fix color channel for smarthome devices

Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>

Co-authored-by: Tom Blum <trinitus01@googlemail.com>
Co-authored-by: Connor Petty <mistercpp2000@gmail.com>
pull/9134/head
J-N-K 2020-11-25 21:15:29 +01:00 committed by GitHub
parent 62523e135a
commit 1b588bc4fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 805 additions and 771 deletions

View File

@ -13,10 +13,10 @@
package org.openhab.binding.amazonechocontrol.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
/**
* The {@link AccountHandlerConfig} holds the configuration for the {@link AccountHandler}
* The {@link AccountHandlerConfig} holds the configuration for the
* {@link org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler}
*
* @author Jan N. Klug - Initial contribution
*/

View File

@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
@ -128,15 +127,18 @@ public class AccountServlet extends HttpServlet {
doVerb("POST", req, resp);
}
void doVerb(String verb, @Nullable HttpServletRequest req, @Nullable HttpServletResponse resp)
throws ServletException, IOException {
void doVerb(String verb, @Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) throws IOException {
if (req == null) {
return;
}
if (resp == null) {
return;
}
String baseUrl = req.getRequestURI().substring(servletUrl.length());
String requestUri = req.getRequestURI();
if (requestUri == null) {
return;
}
String baseUrl = requestUri.substring(servletUrl.length());
String uri = baseUrl;
String queryString = req.getQueryString();
if (queryString != null && queryString.length() > 0) {
@ -146,7 +148,12 @@ public class AccountServlet extends HttpServlet {
Connection connection = this.account.findConnection();
if (connection != null && uri.equals("/changedomain")) {
Map<String, String[]> map = req.getParameterMap();
String domain = map.get("domain")[0];
String[] domainArray = map.get("domain");
if (domainArray == null) {
logger.warn("Could not determine domain");
return;
}
String domain = domainArray[0];
String loginData = connection.serializeLoginData();
Connection newConnection = new Connection(null, this.gson);
if (newConnection.tryRestoreLogin(loginData, domain)) {
@ -192,15 +199,20 @@ public class AccountServlet extends HttpServlet {
postDataBuilder.append(name);
postDataBuilder.append('=');
String value = map.get(name)[0];
String value = "";
if (name.equals("failedSignInCount")) {
value = "ape:AA==";
} else {
String[] strings = map.get(name);
if (strings != null && strings.length > 0 && strings[0] != null) {
value = strings[0];
}
}
postDataBuilder.append(URLEncoder.encode(value, StandardCharsets.UTF_8.name()));
}
uri = req.getRequestURI();
if (!uri.startsWith(servletUrl)) {
if (uri == null || !uri.startsWith(servletUrl)) {
returnError(resp, "Invalid request uri '" + uri + "'");
return;
}
@ -221,15 +233,18 @@ public class AccountServlet extends HttpServlet {
}
@Override
protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp)
throws ServletException, IOException {
protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp) throws IOException {
if (req == null) {
return;
}
if (resp == null) {
return;
}
String baseUrl = req.getRequestURI().substring(servletUrl.length());
String requestUri = req.getRequestURI();
if (requestUri == null) {
return;
}
String baseUrl = requestUri.substring(servletUrl.length());
String uri = baseUrl;
String queryString = req.getQueryString();
if (queryString != null && queryString.length() > 0) {
@ -312,7 +327,7 @@ public class AccountServlet extends HttpServlet {
String html = connection.getLoginPage();
returnHtml(connection, resp, html, "amazon.com");
} catch (URISyntaxException e) {
} catch (URISyntaxException | InterruptedException e) {
logger.warn("get failed with uri syntax error", e);
}
}
@ -419,7 +434,8 @@ public class AccountServlet extends HttpServlet {
createPageEndAndSent(resp, html);
}
private void handleDevices(HttpServletResponse resp, Connection connection) throws IOException, URISyntaxException {
private void handleDevices(HttpServletResponse resp, Connection connection)
throws IOException, URISyntaxException, InterruptedException {
returnHtml(connection, resp,
"<html>" + StringEscapeUtils.escapeHtml(connection.getDeviceListJson()) + "</html>");
}
@ -435,13 +451,13 @@ public class AccountServlet extends HttpServlet {
StringBuilder html = new StringBuilder();
html.append("<html><head><title>"
+ StringEscapeUtils.escapeHtml(BINDING_NAME + " - " + this.account.getThing().getLabel()));
if (StringUtils.isNotEmpty(title)) {
if (!title.isEmpty()) {
html.append(" - ");
html.append(StringEscapeUtils.escapeHtml(title));
}
html.append("</title><head><body>");
html.append("<h1>" + StringEscapeUtils.escapeHtml(BINDING_NAME + " - " + this.account.getThing().getLabel()));
if (StringUtils.isNotEmpty(title)) {
if (!title.isEmpty()) {
html.append(" - ");
html.append(StringEscapeUtils.escapeHtml(title));
}
@ -502,9 +518,9 @@ public class AccountServlet extends HttpServlet {
List<String> properties = musicProvider.supportedProperties;
String providerId = musicProvider.id;
String displayName = musicProvider.displayName;
if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase")
&& StringUtils.isNotEmpty(providerId) && StringUtils.equals(musicProvider.availability, "AVAILABLE")
&& StringUtils.isNotEmpty(displayName)) {
if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase") && providerId != null
&& !providerId.isEmpty() && "AVAILABLE".equals(musicProvider.availability) && displayName != null
&& !displayName.isEmpty()) {
html.append("<tr><td>");
html.append(StringEscapeUtils.escapeHtml(displayName));
html.append("</td><td>");
@ -521,7 +537,8 @@ public class AccountServlet extends HttpServlet {
String errorMessage = "No notifications sounds found";
try {
notificationSounds = connection.getNotificationSounds(device);
} catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) {
} catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException
| InterruptedException e) {
errorMessage = e.getLocalizedMessage();
}
if (notificationSounds != null) {
@ -551,7 +568,8 @@ public class AccountServlet extends HttpServlet {
String errorMessage = "No playlists found";
try {
playLists = connection.getPlaylists(device);
} catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException e) {
} catch (IOException | HttpException | URISyntaxException | JsonSyntaxException | ConnectionException
| InterruptedException e) {
errorMessage = e.getLocalizedMessage();
}
@ -595,8 +613,9 @@ public class AccountServlet extends HttpServlet {
if (state == null) {
continue;
}
if ((state.deviceSerialNumber == null && device.serialNumber == null)
|| (state.deviceSerialNumber != null && state.deviceSerialNumber.equals(device.serialNumber))) {
String stateDeviceSerialNumber = state.deviceSerialNumber;
if ((stateDeviceSerialNumber == null && device.serialNumber == null)
|| (stateDeviceSerialNumber != null && stateDeviceSerialNumber.equals(device.serialNumber))) {
PairedDevice[] pairedDeviceList = state.pairedDeviceList;
if (pairedDeviceList != null && pairedDeviceList.length > 0) {
html.append("<table><tr><th align='left'>Name</th><th align='left'>Value</th></tr>");
@ -666,7 +685,7 @@ public class AccountServlet extends HttpServlet {
return;
}
}
} catch (URISyntaxException | ConnectionException e) {
} catch (URISyntaxException | ConnectionException | InterruptedException e) {
returnError(resp, e.getLocalizedMessage());
return;
}

View File

@ -14,13 +14,7 @@ package org.openhab.binding.amazonechocontrol.internal;
import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -117,8 +111,8 @@ public class AmazonEchoControlHandlerFactory extends BaseThingHandlerFactory {
}
private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) {
List<ServiceRegistration<?>> discoveryServiceRegistration = discoveryServiceRegistrations
.computeIfAbsent(bridgeHandler.getThing().getUID(), k -> new ArrayList<>());
List<ServiceRegistration<?>> discoveryServiceRegistration = Objects.requireNonNull(discoveryServiceRegistrations
.computeIfAbsent(bridgeHandler.getThing().getUID(), k -> new ArrayList<>()));
SmartHomeDevicesDiscovery smartHomeDevicesDiscovery = new SmartHomeDevicesDiscovery(bridgeHandler);
smartHomeDevicesDiscovery.activate();
discoveryServiceRegistration.add(bundleContext.registerService(DiscoveryService.class.getName(),

View File

@ -20,7 +20,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
@ -220,10 +219,9 @@ public class AmazonEchoDynamicStateDescriptionProvider implements DynamicStateDe
List<String> properties = musicProvider.supportedProperties;
String providerId = musicProvider.id;
String displayName = musicProvider.displayName;
if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase")
&& StringUtils.isNotEmpty(providerId)
&& StringUtils.equals(musicProvider.availability, "AVAILABLE")
&& StringUtils.isNotEmpty(displayName) && providerId != null) {
if (properties != null && properties.contains("Alexa.Music.PlaySearchPhrase") && providerId != null
&& !providerId.isEmpty() && "AVAILABLE".equals(musicProvider.availability)
&& displayName != null && !displayName.isEmpty()) {
options.add(new StateOption(providerId, displayName));
}
}

View File

@ -40,7 +40,6 @@ import org.slf4j.LoggerFactory;
*/
@NonNullByDefault
public class BindingServlet extends HttpServlet {
private static final long serialVersionUID = -1453738923337413163L;
private final Logger logger = LoggerFactory.getLogger(BindingServlet.class);
@ -87,7 +86,11 @@ public class BindingServlet extends HttpServlet {
if (resp == null) {
return;
}
String uri = req.getRequestURI().substring(servletUrl.length());
String requestUri = req.getRequestURI();
if (requestUri == null) {
return;
}
String uri = requestUri.substring(servletUrl.length());
String queryString = req.getQueryString();
if (queryString != null && queryString.length() > 0) {
uri += "?" + queryString;

View File

@ -28,7 +28,6 @@ import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -79,7 +78,7 @@ public class WebSocketConnection {
webSocketClient = new WebSocketClient(sslContextFactory);
try {
String host;
if (StringUtils.equalsIgnoreCase(amazonSite, "amazon.com")) {
if (amazonSite.equalsIgnoreCase("amazon.com")) {
host = "dp-gw-na-js." + amazonSite;
} else {
host = "dp-gw-na." + amazonSite;
@ -196,7 +195,6 @@ public class WebSocketConnection {
}
@WebSocket(maxTextMessageSize = 64 * 1024, maxBinaryMessageSize = 64 * 1024)
@SuppressWarnings("unused")
public class AmazonEchoControlWebSocket {
int msgCounter = -1;
int messageId;
@ -349,19 +347,17 @@ public class WebSocketConnection {
if (idDataElements.length == 2) {
payload = idDataElements[1];
}
if (message.content.payload == null) {
if (payload == null) {
payload = readString(data, idx, data.length - 4 - idx);
}
message.content.payload = payload;
if (StringUtils.isNotEmpty(payload)) {
if (!payload.isEmpty()) {
try {
message.content.pushCommand = gson.fromJson(message.content.payload,
JsonPushCommand.class);
message.content.pushCommand = gson.fromJson(payload, JsonPushCommand.class);
} catch (JsonSyntaxException e) {
logger.info("Parsing json failed", e);
logger.info("Illegal json: {}", payload);
logger.info("Parsing json failed, illegal JSON: {}", payload, e);
}
}
message.content.payload = payload;
}
}
} else if (message.channel == 0x65) { // CHANNEL_FOR_HEARTBEAT

View File

@ -35,7 +35,7 @@ import com.google.gson.JsonSyntaxException;
public abstract class ChannelHandler {
public abstract boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command)
throws IOException, URISyntaxException;
throws IOException, URISyntaxException, InterruptedException;
protected final IAmazonThingHandler thingHandler;
protected final Gson gson;

View File

@ -44,7 +44,7 @@ public class ChannelHandlerSendMessage extends ChannelHandler {
@Override
public boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command)
throws IOException, URISyntaxException {
throws IOException, URISyntaxException, InterruptedException {
if (channelId.equals(CHANNEL_NAME)) {
if (command instanceof StringType) {
String commandValue = ((StringType) command).toFullString();

View File

@ -30,6 +30,7 @@ import org.openhab.binding.amazonechocontrol.internal.Connection;
import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler;
import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDeviceAlias;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.DriverIdentity;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup;
@ -145,6 +146,7 @@ public class SmartHomeDevicesDiscovery extends AbstractDiscoveryService {
if (smartHomeDevice instanceof SmartHomeDevice) {
SmartHomeDevice shd = (SmartHomeDevice) smartHomeDevice;
logger.trace("Found SmartHome device: {}", shd);
String entityId = shd.entityId;
if (entityId == null) {
@ -178,23 +180,24 @@ public class SmartHomeDevicesDiscovery extends AbstractDiscoveryService {
thingUID = new ThingUID(THING_TYPE_SMART_HOME_DEVICE, bridgeThingUID, entityId.replace(".", "-"));
JsonSmartHomeDeviceAlias[] aliases = shd.aliases;
if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
&& "SonarCloudService".equals(driverIdentity.identifier)) {
deviceName = "Alexa Guard on " + shd.friendlyName;
} else if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
&& "OnGuardSmartHomeBridgeService".equals(driverIdentity.identifier)) {
deviceName = "Alexa Guard";
} else if (shd.aliases != null && shd.aliases.length > 0 && shd.aliases[0] != null
&& shd.aliases[0].friendlyName != null) {
deviceName = shd.aliases[0].friendlyName;
} else if (aliases != null && aliases.length > 0 && aliases[0] != null
&& aliases[0].friendlyName != null) {
deviceName = aliases[0].friendlyName;
} else {
deviceName = shd.friendlyName;
}
props.put(DEVICE_PROPERTY_ID, id);
}
if (smartHomeDevice instanceof SmartHomeGroup) {
} else if (smartHomeDevice instanceof SmartHomeGroup) {
SmartHomeGroup shg = (SmartHomeGroup) smartHomeDevice;
logger.trace("Found SmartHome device: {}", shg);
String id = shg.findId();
if (id == null) {
// No id

View File

@ -104,7 +104,6 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
private final Object synchronizeConnection = new Object();
private Map<String, Device> jsonSerialNumberDeviceMapping = new HashMap<>();
private Map<String, SmartHomeBaseDevice> jsonIdSmartHomeDeviceMapping = new HashMap<>();
private Map<String, SmartHomeDevice> jsonSerialNumberSmartHomeDeviceMapping = new HashMap<>();
private @Nullable ScheduledFuture<?> checkDataJob;
private @Nullable ScheduledFuture<?> checkLoginJob;
@ -193,7 +192,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (command instanceof RefreshType) {
refreshData();
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("handleCommand fails", e);
}
}
@ -479,7 +478,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
ZonedDateTime timeStamp = ZonedDateTime.now();
try {
notifications = currentConnection.notifications();
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.debug("refreshNotifications failed", e);
return;
}
@ -632,7 +631,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection.getIsLoggedIn()) {
devices = currentConnection.getDeviceList();
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
}
if (devices != null) {
@ -655,7 +654,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
String deviceWakeWord = null;
for (WakeWord wakeWord : wakeWords) {
if (wakeWord != null) {
if (serialNumber != null && serialNumber.equals(wakeWord.deviceSerialNumber)) {
if (serialNumber.equals(wakeWord.deviceSerialNumber)) {
deviceWakeWord = wakeWord.wakeWord;
break;
}
@ -676,7 +675,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection != null && feeds != null) {
try {
currentConnection.setEnabledFlashBriefings(feeds);
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.warn("Set flashbriefing profile failed", e);
}
}
@ -736,7 +735,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
forSerializer[i] = copy;
}
this.currentFlashBriefingJson = gson.toJson(forSerializer);
} catch (HttpException | JsonSyntaxException | IOException | URISyntaxException | ConnectionException e) {
} catch (HttpException | JsonSyntaxException | IOException | URISyntaxException | ConnectionException
| InterruptedException e) {
logger.warn("get flash briefing profiles fails", e);
}
}
@ -780,8 +780,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
default:
String payload = pushCommand.payload;
if (payload != null && payload.startsWith("{") && payload.endsWith("}")) {
JsonCommandPayloadPushDevice devicePayload = gson.fromJson(payload,
JsonCommandPayloadPushDevice.class);
JsonCommandPayloadPushDevice devicePayload = Objects
.requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushDevice.class));
DopplerId dopplerId = devicePayload.dopplerId;
if (dopplerId != null) {
handlePushDeviceCommand(dopplerId, command, payload);
@ -800,7 +800,11 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
}
private void handlePushActivity(@Nullable String payload) {
JsonCommandPayloadPushActivity pushActivity = gson.fromJson(payload, JsonCommandPayloadPushActivity.class);
if (payload == null) {
return;
}
JsonCommandPayloadPushActivity pushActivity = Objects
.requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushActivity.class));
Key key = pushActivity.key;
if (key == null) {
@ -820,8 +824,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (sourceDeviceIds != null) {
Arrays.stream(sourceDeviceIds).filter(Objects::nonNull)
.map(sourceDeviceId -> findEchoHandlerBySerialNumber(sourceDeviceId.serialNumber))
.filter(Objects::nonNull)
.forEach(echoHandler -> echoHandler.handlePushActivity(currentActivity));
.filter(Objects::nonNull).forEach(echoHandler -> Objects.requireNonNull(echoHandler)
.handlePushActivity(currentActivity));
}
});
}
@ -857,7 +861,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection.getIsLoggedIn()) {
smartHomeDevices = currentConnection.getSmarthomeDeviceList();
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
}
if (smartHomeDevices != null) {
@ -878,19 +882,6 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
smartHomeDeviceHandlers
.forEach(child -> child.setDeviceAndUpdateThingState(this, findSmartDeviceHomeJson(child)));
if (smartHomeDevices != null) {
Map<String, SmartHomeDevice> newJsonSerialNumberSmartHomeDeviceMapping = new HashMap<>();
for (Object smartDevice : smartHomeDevices) {
if (smartDevice instanceof SmartHomeDevice) {
SmartHomeDevice shd = (SmartHomeDevice) smartDevice;
String entityId = shd.entityId;
if (entityId != null) {
newJsonSerialNumberSmartHomeDeviceMapping.put(entityId, shd);
}
}
}
jsonSerialNumberSmartHomeDeviceMapping = newJsonSerialNumberSmartHomeDeviceMapping;
}
if (smartHomeDevices != null) {
return smartHomeDevices;
}
@ -932,7 +923,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
private synchronized void updateSmartHomeState(@Nullable String deviceFilterId) {
try {
logger.debug("updateSmartHomeState started");
logger.debug("updateSmartHomeState started with deviceFilterId={}", deviceFilterId);
Connection connection = this.connection;
if (connection == null || !connection.getIsLoggedIn()) {
return;
@ -976,8 +967,10 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
logger.debug("Device update {} suspended", id);
continue;
}
if (id.equals(deviceFilterId)) {
if (deviceFilterId == null || id.equals(deviceFilterId)) {
smartHomeDeviceHandler.updateChannelStates(allDevices, applianceIdToCapabilityStates);
} else {
logger.trace("Id {} not matching filter {}", id, deviceFilterId);
}
}

View File

@ -20,17 +20,12 @@ import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.Connection;
@ -96,7 +91,6 @@ import com.google.gson.Gson;
*/
@NonNullByDefault
public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
private final Logger logger = LoggerFactory.getLogger(EchoHandler.class);
private Gson gson;
private @Nullable Device device;
@ -376,7 +370,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
}
if (volume != null) {
if (StringUtils.equals(device.deviceFamily, "WHA")) {
if ("WHA".equals(device.deviceFamily)) {
connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + volume
+ ",\"contentFocusClientId\":\"Default\"}");
} else {
@ -409,8 +403,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_MUSIC_PROVIDER_ID)) {
if (command instanceof StringType) {
waitForUpdate = 0;
String musicProviderId = ((StringType) command).toFullString();
if (!StringUtils.equals(musicProviderId, this.musicProviderId)) {
String musicProviderId = command.toFullString();
if (!musicProviderId.equals(this.musicProviderId)) {
this.musicProviderId = musicProviderId;
if (this.isPlaying) {
connection.playMusicVoiceCommand(device, this.musicProviderId, "!");
@ -421,7 +415,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
if (channelId.equals(CHANNEL_PLAY_MUSIC_VOICE_COMMAND)) {
if (command instanceof StringType) {
String voiceCommand = ((StringType) command).toFullString();
String voiceCommand = command.toFullString();
if (!this.musicProviderId.isEmpty()) {
connection.playMusicVoiceCommand(device, this.musicProviderId, voiceCommand);
waitForUpdate = 3000;
@ -447,21 +441,22 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
waitForUpdate = 4000;
String bluetoothId = lastKnownBluetoothMAC;
BluetoothState state = bluetoothState;
if (state != null && (StringUtils.isEmpty(bluetoothId))) {
if (state != null && (bluetoothId == null || bluetoothId.isEmpty())) {
PairedDevice[] pairedDeviceList = state.pairedDeviceList;
if (pairedDeviceList != null) {
for (PairedDevice paired : pairedDeviceList) {
if (paired == null) {
continue;
}
if (StringUtils.isNotEmpty(paired.address)) {
lastKnownBluetoothMAC = paired.address;
String pairedAddress = paired.address;
if (pairedAddress != null && !pairedAddress.isEmpty()) {
lastKnownBluetoothMAC = pairedAddress;
break;
}
}
}
}
if (StringUtils.isNotEmpty(lastKnownBluetoothMAC)) {
if (lastKnownBluetoothMAC != null && !lastKnownBluetoothMAC.isEmpty()) {
connection.bluetooth(device, lastKnownBluetoothMAC);
}
} else if (command == OnOffType.OFF) {
@ -474,8 +469,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// amazon music commands
if (channelId.equals(CHANNEL_AMAZON_MUSIC_TRACK_ID)) {
if (command instanceof StringType) {
String trackId = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(trackId)) {
String trackId = command.toFullString();
if (!trackId.isEmpty()) {
waitForUpdate = 3000;
}
connection.playAmazonMusicTrack(device, trackId);
@ -483,8 +478,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
if (channelId.equals(CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID)) {
if (command instanceof StringType) {
String playListId = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(playListId)) {
String playListId = command.toFullString();
if (!playListId.isEmpty()) {
waitForUpdate = 3000;
}
connection.playAmazonMusicPlayList(device, playListId);
@ -493,7 +488,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_AMAZON_MUSIC)) {
if (command == OnOffType.ON) {
String lastKnownAmazonMusicId = this.lastKnownAmazonMusicId;
if (StringUtils.isNotEmpty(lastKnownAmazonMusicId)) {
if (lastKnownAmazonMusicId != null && !lastKnownAmazonMusicId.isEmpty()) {
waitForUpdate = 3000;
}
connection.playAmazonMusicTrack(device, lastKnownAmazonMusicId);
@ -505,8 +500,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// radio commands
if (channelId.equals(CHANNEL_RADIO_STATION_ID)) {
if (command instanceof StringType) {
String stationId = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(stationId)) {
String stationId = command.toFullString();
if (!stationId.isEmpty()) {
waitForUpdate = 3000;
}
connection.playRadio(device, stationId);
@ -515,7 +510,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_RADIO)) {
if (command == OnOffType.ON) {
String lastKnownRadioStationId = this.lastKnownRadioStationId;
if (StringUtils.isNotEmpty(lastKnownRadioStationId)) {
if (lastKnownRadioStationId != null && !lastKnownRadioStationId.isEmpty()) {
waitForUpdate = 3000;
}
connection.playRadio(device, lastKnownRadioStationId);
@ -528,8 +523,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_REMIND)) {
if (command instanceof StringType) {
stopCurrentNotification();
String reminder = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(reminder)) {
String reminder = command.toFullString();
if (!reminder.isEmpty()) {
waitForUpdate = 3000;
updateRemind = true;
currentNotification = connection.notification(device, "Reminder", reminder, null);
@ -542,8 +537,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_PLAY_ALARM_SOUND)) {
if (command instanceof StringType) {
stopCurrentNotification();
String alarmSound = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(alarmSound)) {
String alarmSound = command.toFullString();
if (!alarmSound.isEmpty()) {
waitForUpdate = 3000;
updateAlarm = true;
String[] parts = alarmSound.split(":", 2);
@ -566,8 +561,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// routine commands
if (channelId.equals(CHANNEL_TEXT_TO_SPEECH)) {
if (command instanceof StringType) {
String text = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(text)) {
String text = command.toFullString();
if (!text.isEmpty()) {
waitForUpdate = 1000;
updateTextToSpeech = true;
startTextToSpeech(connection, device, text);
@ -595,8 +590,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
if (channelId.equals(CHANNEL_LAST_VOICE_COMMAND)) {
if (command instanceof StringType) {
String text = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(text)) {
String text = command.toFullString();
if (!text.isEmpty()) {
waitForUpdate = -1;
startTextToSpeech(connection, device, text);
}
@ -604,18 +599,18 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
if (channelId.equals(CHANNEL_START_COMMAND)) {
if (command instanceof StringType) {
String commandText = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(commandText)) {
String commandText = command.toFullString();
if (!commandText.isEmpty()) {
updateStartCommand = true;
if (commandText.startsWith(FLASH_BRIEFING_COMMAND_PREFIX)) {
// Handle custom flashbriefings commands
String flashbriefing = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length());
for (FlashBriefingProfileHandler flashBriefing : account
String flashBriefingId = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length());
for (FlashBriefingProfileHandler flashBriefingHandler : account
.getFlashBriefingProfileHandlers()) {
ThingUID flashBriefingId = flashBriefing.getThing().getUID();
if (StringUtils.equals(flashBriefing.getThing().getUID().getId(), flashbriefing)) {
flashBriefing.handleCommand(new ChannelUID(flashBriefingId, CHANNEL_PLAY_ON_DEVICE),
ThingUID flashBriefingUid = flashBriefingHandler.getThing().getUID();
if (flashBriefingId.equals(flashBriefingHandler.getThing().getUID().getId())) {
flashBriefingHandler.handleCommand(
new ChannelUID(flashBriefingUid, CHANNEL_PLAY_ON_DEVICE),
new StringType(device.serialNumber));
break;
}
@ -626,15 +621,15 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
commandText = "Alexa." + commandText + ".Play";
}
waitForUpdate = 1000;
connection.executeSequenceCommand(device, commandText, null);
connection.executeSequenceCommand(device, commandText, Map.of());
}
}
}
}
if (channelId.equals(CHANNEL_START_ROUTINE)) {
if (command instanceof StringType) {
String utterance = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(utterance)) {
String utterance = command.toFullString();
if (!utterance.isEmpty()) {
waitForUpdate = 1000;
updateRoutine = true;
connection.startRoutine(device, utterance);
@ -669,7 +664,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} else {
this.updateStateJob = scheduler.schedule(doRefresh, waitForUpdate, TimeUnit.MILLISECONDS);
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("handleCommand fails", e);
}
}
@ -699,7 +694,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
try {
connection.setEqualizer(device, newEqualizerSetting);
return true;
} catch (HttpException | IOException | ConnectionException e) {
} catch (HttpException | IOException | ConnectionException | InterruptedException e) {
logger.debug("Update equalizer failed", e);
this.lastKnownEqualizer = null;
}
@ -746,7 +741,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (currentConnection != null) {
try {
currentConnection.stopNotification(currentNotification);
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.warn("Stop notification failed", e);
}
}
@ -766,7 +761,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
}
}
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.warn("update notification state fails", e);
}
if (stopCurrentNotification) {
@ -855,20 +850,19 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (musicProviderId != null) {
musicProviderId = musicProviderId.toUpperCase();
if (StringUtils.equals(musicProviderId, "AMAZON MUSIC")) {
if (musicProviderId.equals("AMAZON MUSIC")) {
musicProviderId = "AMAZON_MUSIC";
}
if (StringUtils.equals(musicProviderId, "CLOUD_PLAYER")) {
if (musicProviderId.equals("CLOUD_PLAYER")) {
musicProviderId = "AMAZON_MUSIC";
}
if (StringUtils.startsWith(musicProviderId, "TUNEIN")) {
if (musicProviderId.startsWith("TUNEIN")) {
musicProviderId = "TUNEIN";
}
if (StringUtils.startsWithIgnoreCase(musicProviderId, "iHeartRadio")) {
if (musicProviderId.startsWith("IHEARTRADIO")) {
musicProviderId = "I_HEART_RADIO";
}
if (StringUtils.containsIgnoreCase(musicProviderId, "Apple")
&& StringUtils.containsIgnoreCase(musicProviderId, "Music")) {
if (musicProviderId.equals("APPLE") && musicProviderId.contains("MUSIC")) {
musicProviderId = "APPLE_MUSIC";
}
}
@ -880,13 +874,13 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (e.getCode() != 400) {
logger.info("getPlayer fails", e);
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("getPlayer fails", e);
}
// check playing
isPlaying = (playerInfo != null && StringUtils.equals(playerInfo.state, "PLAYING"));
isPlaying = (playerInfo != null && "PLAYING".equals(playerInfo.state));
isPaused = (playerInfo != null && StringUtils.equals(playerInfo.state, "PAUSED"));
isPaused = (playerInfo != null && "PAUSED".equals(playerInfo.state));
synchronized (progressLock) {
Boolean showTime = null;
Long mediaLength = null;
@ -919,8 +913,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
JsonMediaState mediaState = null;
try {
if (StringUtils.equalsIgnoreCase(musicProviderId, "AMAZON_MUSIC")
|| StringUtils.equalsIgnoreCase(musicProviderId, "TUNEIN")) {
if ("AMAZON_MUSIC".equalsIgnoreCase(musicProviderId) || "TUNEIN".equalsIgnoreCase(musicProviderId)) {
mediaState = connection.getMediaState(device);
}
} catch (HttpException e) {
@ -929,7 +922,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} else {
logger.info("getMediaState fails", e);
}
} catch (IOException | URISyntaxException e) {
} catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("getMediaState fails", e);
}
@ -944,11 +937,14 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String amazonMusicTrackId = "";
String amazonMusicPlayListId = "";
boolean amazonMusic = false;
if (mediaState != null && isPlaying && StringUtils.equals(mediaState.providerId, "CLOUD_PLAYER")
&& StringUtils.isNotEmpty(mediaState.contentId)) {
amazonMusicTrackId = mediaState.contentId;
lastKnownAmazonMusicId = amazonMusicTrackId;
amazonMusic = true;
if (mediaState != null) {
String contentId = mediaState.contentId;
if (isPlaying && "CLOUD_PLAYER".equals(mediaState.providerId) && contentId != null
&& !contentId.isEmpty()) {
amazonMusicTrackId = contentId;
lastKnownAmazonMusicId = amazonMusicTrackId;
amazonMusic = true;
}
}
// handle bluetooth
@ -963,34 +959,37 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (paired == null) {
continue;
}
if (paired.connected && paired.address != null) {
String pairedAddress = paired.address;
if (paired.connected && pairedAddress != null) {
bluetoothIsConnected = true;
bluetoothMAC = paired.address;
bluetoothMAC = pairedAddress;
bluetoothDeviceName = paired.friendlyName;
if (StringUtils.isEmpty(bluetoothDeviceName)) {
bluetoothDeviceName = paired.address;
if (bluetoothDeviceName == null || bluetoothDeviceName.isEmpty()) {
bluetoothDeviceName = pairedAddress;
}
break;
}
}
}
}
if (StringUtils.isNotEmpty(bluetoothMAC)) {
if (!bluetoothMAC.isEmpty()) {
lastKnownBluetoothMAC = bluetoothMAC;
}
// handle radio
boolean isRadio = false;
if (mediaState != null && StringUtils.isNotEmpty(mediaState.radioStationId)) {
lastKnownRadioStationId = mediaState.radioStationId;
if (StringUtils.equalsIgnoreCase(musicProviderId, "TUNEIN")) {
isRadio = true;
}
}
String radioStationId = "";
if (isRadio && mediaState != null && StringUtils.equals(mediaState.currentState, "PLAYING")
&& mediaState.radioStationId != null) {
radioStationId = mediaState.radioStationId;
if (mediaState != null) {
radioStationId = Objects.requireNonNullElse(mediaState.radioStationId, "");
if (!radioStationId.isEmpty()) {
lastKnownRadioStationId = radioStationId;
if ("TUNEIN".equalsIgnoreCase(musicProviderId)) {
isRadio = true;
if (!"PLAYING".equals(mediaState.currentState)) {
radioStationId = "";
}
}
}
}
// handle title, subtitle, imageUrl
@ -1021,13 +1020,13 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
QueueEntry entry = queueEntries[0];
if (entry != null) {
if (isRadio) {
if (StringUtils.isEmpty(imageUrl) && entry.imageURL != null) {
if ((imageUrl == null || imageUrl.isEmpty()) && entry.imageURL != null) {
imageUrl = entry.imageURL;
}
if (StringUtils.isEmpty(subTitle1) && entry.radioStationSlogan != null) {
if ((subTitle1 == null || subTitle1.isEmpty()) && entry.radioStationSlogan != null) {
subTitle1 = entry.radioStationSlogan;
}
if (StringUtils.isEmpty(subTitle2) && entry.radioStationLocation != null) {
if ((subTitle2 == null || subTitle2.isEmpty()) && entry.radioStationLocation != null) {
subTitle2 = entry.radioStationLocation;
}
}
@ -1039,9 +1038,10 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String providerDisplayName = "";
if (provider != null) {
if (provider.providerDisplayName != null) {
providerDisplayName = provider.providerDisplayName;
providerDisplayName = Objects.requireNonNullElse(provider.providerDisplayName, providerDisplayName);
}
if (StringUtils.isNotEmpty(provider.providerName) && StringUtils.isEmpty(providerDisplayName)) {
String providerName = provider.providerName;
if (providerName != null && !providerName.isEmpty() && providerDisplayName.isEmpty()) {
providerDisplayName = provider.providerName;
}
}
@ -1153,7 +1153,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
treble = equalizer.treble;
}
this.lastKnownEqualizer = equalizer;
} catch (IOException | URISyntaxException | HttpException | ConnectionException e) {
} catch (IOException | URISyntaxException | HttpException | ConnectionException | InterruptedException e) {
logger.debug("Get equalizer failes", e);
return;
}
@ -1204,20 +1204,22 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
return;
}
Description description = pushActivity.parseDescription();
if (StringUtils.isEmpty(description.firstUtteranceId)
|| StringUtils.startsWithIgnoreCase(description.firstUtteranceId, "TextClient:")) {
String firstUtteranceId = description.firstUtteranceId;
if (firstUtteranceId == null || firstUtteranceId.isEmpty()
|| firstUtteranceId.toLowerCase().startsWith("textclient:")) {
return;
}
if (StringUtils.isEmpty(description.firstStreamId)) {
String firstStreamId = description.firstStreamId;
if (firstStreamId == null || firstStreamId.isEmpty()) {
return;
}
String spokenText = description.summary;
if (spokenText != null && StringUtils.isNotEmpty(spokenText)) {
if (spokenText != null && !spokenText.isEmpty()) {
// remove wake word
String wakeWordPrefix = this.wakeWord;
if (wakeWordPrefix != null) {
wakeWordPrefix += " ";
if (StringUtils.startsWithIgnoreCase(spokenText, wakeWordPrefix)) {
if (spokenText.toLowerCase().startsWith(wakeWordPrefix.toLowerCase())) {
spokenText = spokenText.substring(wakeWordPrefix.length());
}
}
@ -1234,12 +1236,10 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
this.logger.debug("Handle push command {}", command);
switch (command) {
case "PUSH_VOLUME_CHANGE":
JsonCommandPayloadPushVolumeChange volumeChange = gson.fromJson(payload,
JsonCommandPayloadPushVolumeChange.class);
JsonCommandPayloadPushVolumeChange volumeChange = Objects
.requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushVolumeChange.class));
Connection connection = this.findConnection();
@Nullable
Integer volumeSetting = volumeChange.volumeSetting;
@Nullable
Boolean muted = volumeChange.isMuted;
if (muted != null && muted) {
updateState(CHANNEL_VOLUME, new PercentType(0));
@ -1274,14 +1274,15 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
ZonedDateTime nextMusicAlarm = null;
ZonedDateTime nextTimer = null;
for (JsonNotificationResponse notification : notifications) {
if (StringUtils.equals(notification.deviceSerialNumber, device.serialNumber)) {
if (Objects.equals(notification.deviceSerialNumber, device.serialNumber)) {
// notification for this device
if (StringUtils.equals(notification.status, "ON")) {
if ("ON".equals(notification.status)) {
if ("Reminder".equals(notification.type)) {
String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset);
if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) {
String recurringPattern = notification.recurringPattern;
if (recurringPattern != null && !recurringPattern.isBlank() && alarmTime.isBefore(now)) {
continue; // Ignore recurring entry if alarm time is before now
}
if (nextReminder == null || alarmTime.isBefore(nextReminder)) {
@ -1297,7 +1298,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset);
if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) {
String recurringPattern = notification.recurringPattern;
if (recurringPattern != null && !recurringPattern.isBlank() && alarmTime.isBefore(now)) {
continue; // Ignore recurring entry if alarm time is before now
}
if (nextAlarm == null || alarmTime.isBefore(nextAlarm)) {
@ -1307,7 +1309,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset);
if (StringUtils.isNotBlank(notification.recurringPattern) && alarmTime.isBefore(now)) {
String recurringPattern = notification.recurringPattern;
if (recurringPattern != null && !recurringPattern.isBlank() && alarmTime.isBefore(now)) {
continue; // Ignore recurring entry if alarm time is before now
}
if (nextMusicAlarm == null || alarmTime.isBefore(nextMusicAlarm)) {

View File

@ -14,12 +14,10 @@ package org.openhab.binding.amazonechocontrol.internal.handler;
import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.Connection;
@ -104,59 +102,54 @@ public class FlashBriefingProfileHandler extends BaseThingHandler {
if (updateStateJob != null) {
updateStateJob.cancel(false);
}
try {
String channelId = channelUID.getId();
if (command instanceof RefreshType) {
waitForUpdate = 0;
String channelId = channelUID.getId();
if (command instanceof RefreshType) {
waitForUpdate = 0;
}
if (channelId.equals(CHANNEL_SAVE)) {
if (command.equals(OnOffType.ON)) {
saveCurrentProfile(accountHandler);
waitForUpdate = 500;
}
if (channelId.equals(CHANNEL_SAVE)) {
if (command.equals(OnOffType.ON)) {
saveCurrentProfile(accountHandler);
}
if (channelId.equals(CHANNEL_ACTIVE)) {
if (command.equals(OnOffType.ON)) {
String currentConfigurationJson = this.currentConfigurationJson;
if (!currentConfigurationJson.isEmpty()) {
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
updateState(CHANNEL_ACTIVE, OnOffType.ON);
waitForUpdate = 500;
}
}
if (channelId.equals(CHANNEL_ACTIVE)) {
if (command.equals(OnOffType.ON)) {
String currentConfigurationJson = this.currentConfigurationJson;
if (!currentConfigurationJson.isEmpty()) {
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
updateState(CHANNEL_ACTIVE, OnOffType.ON);
waitForUpdate = 500;
}
}
}
if (channelId.equals(CHANNEL_PLAY_ON_DEVICE)) {
if (command instanceof StringType) {
String deviceSerialOrName = ((StringType) command).toFullString();
String currentConfigurationJson = this.currentConfigurationJson;
if (!currentConfigurationJson.isEmpty()) {
String old = accountHandler.getEnabledFlashBriefingsJson();
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
Device device = accountHandler.findDeviceJsonBySerialOrName(deviceSerialOrName);
if (device == null) {
logger.warn("Device '{}' not found", deviceSerialOrName);
}
if (channelId.equals(CHANNEL_PLAY_ON_DEVICE)) {
if (command instanceof StringType) {
String deviceSerialOrName = command.toFullString();
String currentConfigurationJson = this.currentConfigurationJson;
if (!currentConfigurationJson.isEmpty()) {
String old = accountHandler.getEnabledFlashBriefingsJson();
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
Device device = accountHandler.findDeviceJsonBySerialOrName(deviceSerialOrName);
if (device == null) {
logger.warn("Device '{}' not found", deviceSerialOrName);
} else {
@Nullable
Connection connection = accountHandler.findConnection();
if (connection == null) {
logger.warn("Connection for '{}' not found", accountHandler.getThing().getUID().getId());
} else {
@Nullable
Connection connection = accountHandler.findConnection();
if (connection == null) {
logger.warn("Connection for '{}' not found",
accountHandler.getThing().getUID().getId());
} else {
connection.executeSequenceCommand(device, "Alexa.FlashBriefing.Play", null);
connection.executeSequenceCommand(device, "Alexa.FlashBriefing.Play", Map.of());
scheduler.schedule(() -> accountHandler.setEnabledFlashBriefingsJson(old), 1000,
TimeUnit.MILLISECONDS);
scheduler.schedule(() -> accountHandler.setEnabledFlashBriefingsJson(old), 1000,
TimeUnit.MILLISECONDS);
updateState(CHANNEL_ACTIVE, OnOffType.ON);
}
updateState(CHANNEL_ACTIVE, OnOffType.ON);
}
updatePlayOnDevice = true;
waitForUpdate = 1000;
}
updatePlayOnDevice = true;
waitForUpdate = 1000;
}
}
} catch (IOException | URISyntaxException e) {
logger.warn("Handle command failed", e);
}
if (waitForUpdate >= 0) {
this.updateStateJob = scheduler.schedule(() -> accountHandler.updateFlashBriefingHandlers(), waitForUpdate,
@ -189,7 +182,7 @@ public class FlashBriefingProfileHandler extends BaseThingHandler {
} else {
updateState(CHANNEL_ACTIVE, OnOffType.OFF);
}
return StringUtils.equals(this.currentConfigurationJson, currentConfigurationJson);
return this.currentConfigurationJson.equals(currentConfigurationJson);
}
private String saveCurrentProfile(AccountHandler connection) {

View File

@ -15,16 +15,7 @@ package org.openhab.binding.amazonechocontrol.internal.handler;
import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.DEVICE_PROPERTY_ID;
import static org.openhab.binding.amazonechocontrol.internal.smarthome.Constants.SUPPORTED_INTERFACES;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.function.Supplier;
import org.eclipse.jdt.annotation.NonNullByDefault;
@ -32,7 +23,10 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.Connection;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroupIdentifiers;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroupIdentity;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeTags;
import org.openhab.binding.amazonechocontrol.internal.jsons.SmartHomeBaseDevice;
import org.openhab.binding.amazonechocontrol.internal.smarthome.Constants;
import org.openhab.binding.amazonechocontrol.internal.smarthome.HandlerBase;
@ -56,10 +50,7 @@ import org.openhab.core.types.StateDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.*;
/**
* @author Lukas Knoeller - Initial contribution
@ -176,6 +167,7 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
public void updateChannelStates(List<SmartHomeBaseDevice> allDevices,
Map<String, JsonArray> applianceIdToCapabilityStates) {
logger.trace("Updating {} with {}", allDevices, applianceIdToCapabilityStates);
AccountHandler accountHandler = getAccountHandler();
SmartHomeBaseDevice smartHomeBaseDevice = this.smartHomeBaseDevice;
if (smartHomeBaseDevice == null) {
@ -187,11 +179,11 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
Map<String, List<JsonObject>> mapInterfaceToStates = new HashMap<>();
SmartHomeDevice firstDevice = null;
for (SmartHomeDevice shd : getSupportedSmartHomeDevices(smartHomeBaseDevice, allDevices)) {
JsonArray states = applianceIdToCapabilityStates.get(shd.applianceId);
String applianceId = shd.applianceId;
if (applianceId == null) {
continue;
}
JsonArray states = applianceIdToCapabilityStates.get(applianceId);
if (states != null) {
stateFound = true;
if (smartHomeBaseDevice.isGroup()) {
@ -210,26 +202,28 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
for (JsonElement stateElement : states) {
String stateJson = stateElement.getAsString();
if (stateJson.startsWith("{") && stateJson.endsWith("}")) {
JsonObject state = gson.fromJson(stateJson, JsonObject.class);
String interfaceName = state.get("namespace").getAsString();
mapInterfaceToStates.computeIfAbsent(interfaceName, k -> new ArrayList<>()).add(state);
JsonObject state = Objects.requireNonNull(gson.fromJson(stateJson, JsonObject.class));
String interfaceName = Objects.requireNonNullElse(state.get("namespace"), JsonNull.INSTANCE)
.getAsString();
Objects.requireNonNull(mapInterfaceToStates.computeIfAbsent(interfaceName, k -> new ArrayList<>()))
.add(state);
}
}
}
for (HandlerBase handlerBase : handlers.values()) {
if (handlerBase == null) {
continue;
}
UpdateChannelResult result = new UpdateChannelResult();
for (HandlerBase handlerBase : handlers.values()) {
UpdateChannelResult result = new UpdateChannelResult();
for (String interfaceName : handlerBase.getSupportedInterface()) {
List<JsonObject> stateList = mapInterfaceToStates.getOrDefault(interfaceName, Collections.emptyList());
try {
handlerBase.updateChannels(interfaceName, stateList, result);
} catch (Exception e) {
// We catch all exceptions, otherwise all other things are not updated!
logger.debug("Updating states failed", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
List<JsonObject> stateList = mapInterfaceToStates.get(interfaceName);
if (stateList != null) {
try {
handlerBase.updateChannels(interfaceName, stateList, result);
} catch (Exception e) {
// We catch all exceptions, otherwise all other things are not updated!
logger.debug("Updating states failed", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
e.getLocalizedMessage());
}
}
}
@ -325,7 +319,8 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
for (SmartHomeCapability capability : capabilities) {
String interfaceName = capability.interfaceName;
if (interfaceName != null) {
result.computeIfAbsent(interfaceName, name -> new ArrayList<>()).add(capability);
Objects.requireNonNull(result.computeIfAbsent(interfaceName, name -> new ArrayList<>()))
.add(capability);
}
}
}
@ -357,16 +352,20 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
for (SmartHomeBaseDevice device : allDevices) {
if (device instanceof SmartHomeDevice) {
SmartHomeDevice shd = (SmartHomeDevice) device;
if (shd.tags != null && shd.tags.tagNameToValueSetMap != null
&& shd.tags.tagNameToValueSetMap.groupIdentity != null
&& shg.applianceGroupIdentifier != null && shg.applianceGroupIdentifier.value != null
&& Arrays.asList(shd.tags.tagNameToValueSetMap.groupIdentity)
.contains(shg.applianceGroupIdentifier.value)) {
SmartHomeCapability[] capabilities = shd.capabilities;
if (capabilities != null) {
if (Arrays.stream(capabilities).map(capability -> capability.interfaceName)
.anyMatch(SUPPORTED_INTERFACES::contains)) {
result.add(shd);
JsonSmartHomeTags.JsonSmartHomeTag tags = shd.tags;
if (tags != null) {
JsonSmartHomeGroupIdentity.SmartHomeGroupIdentity tagNameToValueSetMap = tags.tagNameToValueSetMap;
JsonSmartHomeGroupIdentifiers.SmartHomeGroupIdentifier applianceGroupIdentifier = shg.applianceGroupIdentifier;
if (tagNameToValueSetMap != null && tagNameToValueSetMap.groupIdentity != null
&& applianceGroupIdentifier != null && applianceGroupIdentifier.value != null
&& Arrays.asList(tagNameToValueSetMap.groupIdentity)
.contains(applianceGroupIdentifier.value)) {
SmartHomeCapability[] capabilities = shd.capabilities;
if (capabilities != null) {
if (Arrays.stream(capabilities).map(capability -> capability.interfaceName)
.anyMatch(SUPPORTED_INTERFACES::contains)) {
result.add(shd);
}
}
}
}
@ -380,7 +379,7 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
@Nullable Locale locale) {
String channelId = channel.getUID().getId();
for (HandlerBase handler : handlers.values()) {
if (handler != null && handler.hasChannel(channelId)) {
if (handler.hasChannel(channelId)) {
return handler.findStateDescription(channelId, originalStateDescription, locale);
}
}

View File

@ -12,7 +12,8 @@
*/
package org.openhab.binding.amazonechocontrol.internal.jsons;
import org.apache.commons.lang.StringUtils;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonDevices.Device;
@ -35,7 +36,7 @@ public class JsonBluetoothStates {
return null;
}
for (BluetoothState state : bluetoothStates) {
if (state != null && StringUtils.equals(state.deviceSerialNumber, device.serialNumber)) {
if (state != null && Objects.equals(state.deviceSerialNumber, device.serialNumber)) {
return state;
}
}

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.amazonechocontrol.internal.jsons;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability;
@ -24,7 +26,6 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeTags.Js
@NonNullByDefault
public class JsonSmartHomeDevices {
public static class SmartHomeDevice implements SmartHomeBaseDevice {
public @Nullable Integer updateIntervalInSeconds;
@Override
@ -52,11 +53,29 @@ public class JsonSmartHomeDevices {
public @Nullable SmartHomeDevice @Nullable [] groupDevices;
public @Nullable String connectedVia;
public @Nullable DriverIdentity driverIdentity;
@Override
public String toString() {
return "SmartHomeDevice{" + "updateIntervalInSeconds=" + updateIntervalInSeconds + ", applianceId='"
+ applianceId + '\'' + ", manufacturerName='" + manufacturerName + '\'' + ", friendlyDescription='"
+ friendlyDescription + '\'' + ", modelName='" + modelName + '\'' + ", friendlyName='"
+ friendlyName + '\'' + ", reachability='" + reachability + '\'' + ", entityId='" + entityId + '\''
+ ", applianceNetworkState=" + applianceNetworkState + ", capabilities="
+ Arrays.toString(capabilities) + ", tags=" + tags + ", applianceTypes="
+ Arrays.toString(applianceTypes) + ", aliases=" + Arrays.toString(aliases) + ", groupDevices="
+ Arrays.toString(groupDevices) + ", connectedVia='" + connectedVia + '\'' + ", driverIdentity="
+ driverIdentity + '}';
}
}
public static class DriverIdentity {
public @Nullable String namespace;
public @Nullable String identifier;
@Override
public String toString() {
return "DriverIdentity{" + "namespace='" + namespace + '\'' + ", identifier='" + identifier + '\'' + '}';
}
}
public @Nullable SmartHomeDevice @Nullable [] smarthomeDevices;

View File

@ -46,6 +46,12 @@ public class JsonSmartHomeGroups {
public @Nullable Boolean isSpace;
public @Nullable Boolean space;
public @Nullable SmartHomeGroupIdentifier applianceGroupIdentifier;
@Override
public String toString() {
return "SmartHomeGroup{" + "applianceGroupName='" + applianceGroupName + '\'' + ", isSpace=" + isSpace
+ ", space=" + space + ", applianceGroupIdentifier=" + applianceGroupIdentifier + '}';
}
}
public @Nullable SmartHomeGroup @Nullable [] groups;

View File

@ -47,7 +47,8 @@ public abstract class HandlerBase {
public abstract void updateChannels(String interfaceName, List<JsonObject> stateList, UpdateChannelResult result);
public abstract boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException;
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException;
public abstract @Nullable StateDescription findStateDescription(String channelId,
StateDescription originalStateDescription, @Nullable Locale locale);

View File

@ -91,7 +91,8 @@ public class HandlerBrightnessController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(BRIGHTNESS.channelId)) {
if (containsCapabilityProperty(capabilties, BRIGHTNESS.propertyName)) {
if (command.equals(IncreaseDecreaseType.INCREASE)) {

View File

@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants;
@ -113,11 +112,10 @@ public class HandlerColorController extends HandlerBase {
}
}
}
if (lastColorName == null) {
lastColorName = colorNameValue;
} else if (colorNameValue == null && lastColorName != null) {
if (colorNameValue == null && lastColorName != null) {
colorNameValue = lastColorName;
}
lastColorName = colorNameValue;
updateState(COLOR_PROPERTIES.channelId,
lastColorName == null ? UnDefType.UNDEF : new StringType(lastColorName));
}
@ -125,7 +123,8 @@ public class HandlerColorController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(COLOR.channelId)) {
if (containsCapabilityProperty(capabilties, COLOR.propertyName)) {
if (command instanceof HSBType) {
@ -134,15 +133,15 @@ public class HandlerColorController extends HandlerBase {
colorObject.addProperty("hue", color.getHue());
colorObject.addProperty("saturation", color.getSaturation().floatValue() / 100);
colorObject.addProperty("brightness", color.getBrightness().floatValue() / 100);
connection.smartHomeCommand(entityId, "setColor", "color", colorObject);
connection.smartHomeCommand(entityId, "setColor", "value", colorObject);
}
}
}
if (channelId.equals(COLOR_PROPERTIES.channelId)) {
if (containsCapabilityProperty(capabilties, COLOR.propertyName)) {
if (command instanceof StringType) {
String colorName = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(colorName)) {
String colorName = command.toFullString();
if (!colorName.isEmpty()) {
lastColorName = colorName;
connection.smartHomeCommand(entityId, "setColor", "colorName", colorName);
return true;

View File

@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants;
@ -121,7 +120,8 @@ public class HandlerColorTemperatureController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(COLOR_TEMPERATURE_IN_KELVIN.channelId)) {
// WRITING TO THIS CHANNEL DOES CURRENTLY NOT WORK, BUT WE LEAVE THE CODE FOR FUTURE USE!
if (containsCapabilityProperty(capabilties, COLOR_TEMPERATURE_IN_KELVIN.propertyName)) {
@ -141,8 +141,8 @@ public class HandlerColorTemperatureController extends HandlerBase {
if (channelId.equals(COLOR_TEMPERATURE_NAME.channelId)) {
if (containsCapabilityProperty(capabilties, COLOR_TEMPERATURE_IN_KELVIN.propertyName)) {
if (command instanceof StringType) {
String colorTemperatureName = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(colorTemperatureName)) {
String colorTemperatureName = command.toFullString();
if (!colorTemperatureName.isEmpty()) {
lastColorName = colorTemperatureName;
connection.smartHomeCommand(entityId, "setColorTemperature", "colorTemperatureName",
colorTemperatureName);

View File

@ -91,7 +91,8 @@ public class HandlerPercentageController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(PERCENTAGE.channelId)) {
if (containsCapabilityProperty(capabilties, PERCENTAGE.propertyName)) {
if (command.equals(IncreaseDecreaseType.INCREASE)) {

View File

@ -29,6 +29,8 @@ import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.StateDescription;
import org.openhab.core.types.UnDefType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
@ -40,6 +42,8 @@ import com.google.gson.JsonObject;
*/
@NonNullByDefault
public class HandlerPowerController extends HandlerBase {
private final Logger logger = LoggerFactory.getLogger(HandlerPowerController.class);
// Interface
public static final String INTERFACE = "Alexa.PowerController";
@ -67,6 +71,7 @@ public class HandlerPowerController extends HandlerBase {
@Override
public void updateChannels(String interfaceName, List<JsonObject> stateList, UpdateChannelResult result) {
logger.trace("{} received {}", this.smartHomeDeviceHandler.getId(), stateList);
Boolean powerStateValue = null;
for (JsonObject state : stateList) {
if (POWER_STATE.propertyName.equals(state.get("name").getAsString())) {
@ -74,19 +79,20 @@ public class HandlerPowerController extends HandlerBase {
// For groups take true if all true
if ("ON".equals(value)) {
powerStateValue = true;
} else if (powerStateValue == null) {
} else {
powerStateValue = false;
}
}
}
updateState(POWER_STATE.channelId,
powerStateValue == null ? UnDefType.UNDEF : (powerStateValue ? OnOffType.ON : OnOffType.OFF));
logger.trace("{} final state {}", this.smartHomeDeviceHandler.getId(), powerStateValue);
updateState(POWER_STATE.channelId, powerStateValue == null ? UnDefType.UNDEF : OnOffType.from(powerStateValue));
}
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilities, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilities, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(POWER_STATE.channelId)) {
if (containsCapabilityProperty(capabilities, POWER_STATE.propertyName)) {
if (command.equals(OnOffType.ON)) {

View File

@ -92,7 +92,8 @@ public class HandlerPowerLevelController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilties, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(POWER_LEVEL.channelId)) {
if (containsCapabilityProperty(capabilties, POWER_LEVEL.propertyName)) {
if (command.equals(IncreaseDecreaseType.INCREASE)) {

View File

@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants;
@ -147,12 +146,13 @@ public class HandlerSecurityPanelController extends HandlerBase {
@Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId,
SmartHomeCapability[] capabilties, String channelId, Command command) throws IOException {
SmartHomeCapability[] capabilities, String channelId, Command command)
throws IOException, InterruptedException {
if (channelId.equals(ARM_STATE.channelId)) {
if (containsCapabilityProperty(capabilties, ARM_STATE.propertyName)) {
if (containsCapabilityProperty(capabilities, ARM_STATE.propertyName)) {
if (command instanceof StringType) {
String armStateValue = ((StringType) command).toFullString();
if (StringUtils.isNotEmpty(armStateValue)) {
String armStateValue = command.toFullString();
if (!armStateValue.isEmpty()) {
connection.smartHomeCommand(entityId, "controlSecurityPanel", ARM_STATE.propertyName,
armStateValue);
return true;

View File

@ -19,7 +19,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.DriverIdentity;
@ -75,8 +74,9 @@ public class SmartHomeDeviceStateGroupUpdateCalculator {
}
}
if (updateIntervalInSeconds == null) {
if ("openHAB".equalsIgnoreCase(shd.manufacturerName)
|| StringUtils.startsWithIgnoreCase(shd.manufacturerName, "ioBroker")) {
String manufacturerName = shd.manufacturerName;
if (manufacturerName != null && ("openHAB".equalsIgnoreCase(manufacturerName)
|| manufacturerName.toLowerCase().startsWith("iobroker"))) {
// OpenHAB or ioBroker skill
if (logger.isTraceEnabled()) {
updateIntervalInSeconds = UPDATE_INTERVAL_PRIVATE_SKILLS_IN_SECONDS_TRACE;