[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>
This commit is contained in:
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; package org.openhab.binding.amazonechocontrol.internal;
import org.eclipse.jdt.annotation.NonNullByDefault; 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 * @author Jan N. Klug - Initial contribution
*/ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -44,7 +44,7 @@ public class ChannelHandlerSendMessage extends ChannelHandler {
@Override @Override
public boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command) public boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command)
throws IOException, URISyntaxException { throws IOException, URISyntaxException, InterruptedException {
if (channelId.equals(CHANNEL_NAME)) { if (channelId.equals(CHANNEL_NAME)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String commandValue = ((StringType) command).toFullString(); 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.AccountHandler;
import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler; import org.openhab.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities; 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.DriverIdentity;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeDevices.SmartHomeDevice;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeGroups.SmartHomeGroup;
@ -145,6 +146,7 @@ public class SmartHomeDevicesDiscovery extends AbstractDiscoveryService {
if (smartHomeDevice instanceof SmartHomeDevice) { if (smartHomeDevice instanceof SmartHomeDevice) {
SmartHomeDevice shd = (SmartHomeDevice) smartHomeDevice; SmartHomeDevice shd = (SmartHomeDevice) smartHomeDevice;
logger.trace("Found SmartHome device: {}", shd);
String entityId = shd.entityId; String entityId = shd.entityId;
if (entityId == null) { if (entityId == null) {
@ -178,23 +180,24 @@ public class SmartHomeDevicesDiscovery extends AbstractDiscoveryService {
thingUID = new ThingUID(THING_TYPE_SMART_HOME_DEVICE, bridgeThingUID, entityId.replace(".", "-")); thingUID = new ThingUID(THING_TYPE_SMART_HOME_DEVICE, bridgeThingUID, entityId.replace(".", "-"));
JsonSmartHomeDeviceAlias[] aliases = shd.aliases;
if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
&& "SonarCloudService".equals(driverIdentity.identifier)) { && "SonarCloudService".equals(driverIdentity.identifier)) {
deviceName = "Alexa Guard on " + shd.friendlyName; deviceName = "Alexa Guard on " + shd.friendlyName;
} else if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null } else if ("Amazon".equals(shd.manufacturerName) && driverIdentity != null
&& "OnGuardSmartHomeBridgeService".equals(driverIdentity.identifier)) { && "OnGuardSmartHomeBridgeService".equals(driverIdentity.identifier)) {
deviceName = "Alexa Guard"; deviceName = "Alexa Guard";
} else if (shd.aliases != null && shd.aliases.length > 0 && shd.aliases[0] != null } else if (aliases != null && aliases.length > 0 && aliases[0] != null
&& shd.aliases[0].friendlyName != null) { && aliases[0].friendlyName != null) {
deviceName = shd.aliases[0].friendlyName; deviceName = aliases[0].friendlyName;
} else { } else {
deviceName = shd.friendlyName; deviceName = shd.friendlyName;
} }
props.put(DEVICE_PROPERTY_ID, id); props.put(DEVICE_PROPERTY_ID, id);
} } else if (smartHomeDevice instanceof SmartHomeGroup) {
if (smartHomeDevice instanceof SmartHomeGroup) {
SmartHomeGroup shg = (SmartHomeGroup) smartHomeDevice; SmartHomeGroup shg = (SmartHomeGroup) smartHomeDevice;
logger.trace("Found SmartHome device: {}", shg);
String id = shg.findId(); String id = shg.findId();
if (id == null) { if (id == null) {
// No id // No id

View File

@ -104,7 +104,6 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
private final Object synchronizeConnection = new Object(); private final Object synchronizeConnection = new Object();
private Map<String, Device> jsonSerialNumberDeviceMapping = new HashMap<>(); private Map<String, Device> jsonSerialNumberDeviceMapping = new HashMap<>();
private Map<String, SmartHomeBaseDevice> jsonIdSmartHomeDeviceMapping = new HashMap<>(); private Map<String, SmartHomeBaseDevice> jsonIdSmartHomeDeviceMapping = new HashMap<>();
private Map<String, SmartHomeDevice> jsonSerialNumberSmartHomeDeviceMapping = new HashMap<>();
private @Nullable ScheduledFuture<?> checkDataJob; private @Nullable ScheduledFuture<?> checkDataJob;
private @Nullable ScheduledFuture<?> checkLoginJob; private @Nullable ScheduledFuture<?> checkLoginJob;
@ -193,7 +192,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (command instanceof RefreshType) { if (command instanceof RefreshType) {
refreshData(); refreshData();
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("handleCommand fails", e); logger.info("handleCommand fails", e);
} }
} }
@ -479,7 +478,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
ZonedDateTime timeStamp = ZonedDateTime.now(); ZonedDateTime timeStamp = ZonedDateTime.now();
try { try {
notifications = currentConnection.notifications(); notifications = currentConnection.notifications();
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.debug("refreshNotifications failed", e); logger.debug("refreshNotifications failed", e);
return; return;
} }
@ -632,7 +631,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection.getIsLoggedIn()) { if (currentConnection.getIsLoggedIn()) {
devices = currentConnection.getDeviceList(); devices = currentConnection.getDeviceList();
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
} }
if (devices != null) { if (devices != null) {
@ -655,7 +654,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
String deviceWakeWord = null; String deviceWakeWord = null;
for (WakeWord wakeWord : wakeWords) { for (WakeWord wakeWord : wakeWords) {
if (wakeWord != null) { if (wakeWord != null) {
if (serialNumber != null && serialNumber.equals(wakeWord.deviceSerialNumber)) { if (serialNumber.equals(wakeWord.deviceSerialNumber)) {
deviceWakeWord = wakeWord.wakeWord; deviceWakeWord = wakeWord.wakeWord;
break; break;
} }
@ -676,7 +675,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection != null && feeds != null) { if (currentConnection != null && feeds != null) {
try { try {
currentConnection.setEnabledFlashBriefings(feeds); currentConnection.setEnabledFlashBriefings(feeds);
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.warn("Set flashbriefing profile failed", e); logger.warn("Set flashbriefing profile failed", e);
} }
} }
@ -736,7 +735,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
forSerializer[i] = copy; forSerializer[i] = copy;
} }
this.currentFlashBriefingJson = gson.toJson(forSerializer); 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); logger.warn("get flash briefing profiles fails", e);
} }
} }
@ -780,8 +780,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
default: default:
String payload = pushCommand.payload; String payload = pushCommand.payload;
if (payload != null && payload.startsWith("{") && payload.endsWith("}")) { if (payload != null && payload.startsWith("{") && payload.endsWith("}")) {
JsonCommandPayloadPushDevice devicePayload = gson.fromJson(payload, JsonCommandPayloadPushDevice devicePayload = Objects
JsonCommandPayloadPushDevice.class); .requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushDevice.class));
DopplerId dopplerId = devicePayload.dopplerId; DopplerId dopplerId = devicePayload.dopplerId;
if (dopplerId != null) { if (dopplerId != null) {
handlePushDeviceCommand(dopplerId, command, payload); handlePushDeviceCommand(dopplerId, command, payload);
@ -800,7 +800,11 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
} }
private void handlePushActivity(@Nullable String payload) { 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; Key key = pushActivity.key;
if (key == null) { if (key == null) {
@ -820,8 +824,8 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (sourceDeviceIds != null) { if (sourceDeviceIds != null) {
Arrays.stream(sourceDeviceIds).filter(Objects::nonNull) Arrays.stream(sourceDeviceIds).filter(Objects::nonNull)
.map(sourceDeviceId -> findEchoHandlerBySerialNumber(sourceDeviceId.serialNumber)) .map(sourceDeviceId -> findEchoHandlerBySerialNumber(sourceDeviceId.serialNumber))
.filter(Objects::nonNull) .filter(Objects::nonNull).forEach(echoHandler -> Objects.requireNonNull(echoHandler)
.forEach(echoHandler -> echoHandler.handlePushActivity(currentActivity)); .handlePushActivity(currentActivity));
} }
}); });
} }
@ -857,7 +861,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
if (currentConnection.getIsLoggedIn()) { if (currentConnection.getIsLoggedIn()) {
smartHomeDevices = currentConnection.getSmarthomeDeviceList(); smartHomeDevices = currentConnection.getSmarthomeDeviceList();
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
} }
if (smartHomeDevices != null) { if (smartHomeDevices != null) {
@ -878,19 +882,6 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
smartHomeDeviceHandlers smartHomeDeviceHandlers
.forEach(child -> child.setDeviceAndUpdateThingState(this, findSmartDeviceHomeJson(child))); .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) { if (smartHomeDevices != null) {
return smartHomeDevices; return smartHomeDevices;
} }
@ -932,7 +923,7 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
private synchronized void updateSmartHomeState(@Nullable String deviceFilterId) { private synchronized void updateSmartHomeState(@Nullable String deviceFilterId) {
try { try {
logger.debug("updateSmartHomeState started"); logger.debug("updateSmartHomeState started with deviceFilterId={}", deviceFilterId);
Connection connection = this.connection; Connection connection = this.connection;
if (connection == null || !connection.getIsLoggedIn()) { if (connection == null || !connection.getIsLoggedIn()) {
return; return;
@ -976,8 +967,10 @@ public class AccountHandler extends BaseBridgeHandler implements IWebSocketComma
logger.debug("Device update {} suspended", id); logger.debug("Device update {} suspended", id);
continue; continue;
} }
if (id.equals(deviceFilterId)) { if (deviceFilterId == null || id.equals(deviceFilterId)) {
smartHomeDeviceHandler.updateChannelStates(allDevices, applianceIdToCapabilityStates); 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.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.Connection; import org.openhab.binding.amazonechocontrol.internal.Connection;
@ -96,7 +91,6 @@ import com.google.gson.Gson;
*/ */
@NonNullByDefault @NonNullByDefault
public class EchoHandler extends BaseThingHandler implements IEchoThingHandler { public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
private final Logger logger = LoggerFactory.getLogger(EchoHandler.class); private final Logger logger = LoggerFactory.getLogger(EchoHandler.class);
private Gson gson; private Gson gson;
private @Nullable Device device; private @Nullable Device device;
@ -376,7 +370,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} }
} }
if (volume != null) { if (volume != null) {
if (StringUtils.equals(device.deviceFamily, "WHA")) { if ("WHA".equals(device.deviceFamily)) {
connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + volume connection.command(device, "{\"type\":\"VolumeLevelCommand\",\"volumeLevel\":" + volume
+ ",\"contentFocusClientId\":\"Default\"}"); + ",\"contentFocusClientId\":\"Default\"}");
} else { } else {
@ -409,8 +403,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_MUSIC_PROVIDER_ID)) { if (channelId.equals(CHANNEL_MUSIC_PROVIDER_ID)) {
if (command instanceof StringType) { if (command instanceof StringType) {
waitForUpdate = 0; waitForUpdate = 0;
String musicProviderId = ((StringType) command).toFullString(); String musicProviderId = command.toFullString();
if (!StringUtils.equals(musicProviderId, this.musicProviderId)) { if (!musicProviderId.equals(this.musicProviderId)) {
this.musicProviderId = musicProviderId; this.musicProviderId = musicProviderId;
if (this.isPlaying) { if (this.isPlaying) {
connection.playMusicVoiceCommand(device, this.musicProviderId, "!"); 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 (channelId.equals(CHANNEL_PLAY_MUSIC_VOICE_COMMAND)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String voiceCommand = ((StringType) command).toFullString(); String voiceCommand = command.toFullString();
if (!this.musicProviderId.isEmpty()) { if (!this.musicProviderId.isEmpty()) {
connection.playMusicVoiceCommand(device, this.musicProviderId, voiceCommand); connection.playMusicVoiceCommand(device, this.musicProviderId, voiceCommand);
waitForUpdate = 3000; waitForUpdate = 3000;
@ -447,21 +441,22 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
waitForUpdate = 4000; waitForUpdate = 4000;
String bluetoothId = lastKnownBluetoothMAC; String bluetoothId = lastKnownBluetoothMAC;
BluetoothState state = bluetoothState; BluetoothState state = bluetoothState;
if (state != null && (StringUtils.isEmpty(bluetoothId))) { if (state != null && (bluetoothId == null || bluetoothId.isEmpty())) {
PairedDevice[] pairedDeviceList = state.pairedDeviceList; PairedDevice[] pairedDeviceList = state.pairedDeviceList;
if (pairedDeviceList != null) { if (pairedDeviceList != null) {
for (PairedDevice paired : pairedDeviceList) { for (PairedDevice paired : pairedDeviceList) {
if (paired == null) { if (paired == null) {
continue; continue;
} }
if (StringUtils.isNotEmpty(paired.address)) { String pairedAddress = paired.address;
lastKnownBluetoothMAC = paired.address; if (pairedAddress != null && !pairedAddress.isEmpty()) {
lastKnownBluetoothMAC = pairedAddress;
break; break;
} }
} }
} }
} }
if (StringUtils.isNotEmpty(lastKnownBluetoothMAC)) { if (lastKnownBluetoothMAC != null && !lastKnownBluetoothMAC.isEmpty()) {
connection.bluetooth(device, lastKnownBluetoothMAC); connection.bluetooth(device, lastKnownBluetoothMAC);
} }
} else if (command == OnOffType.OFF) { } else if (command == OnOffType.OFF) {
@ -474,8 +469,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// amazon music commands // amazon music commands
if (channelId.equals(CHANNEL_AMAZON_MUSIC_TRACK_ID)) { if (channelId.equals(CHANNEL_AMAZON_MUSIC_TRACK_ID)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String trackId = ((StringType) command).toFullString(); String trackId = command.toFullString();
if (StringUtils.isNotEmpty(trackId)) { if (!trackId.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
} }
connection.playAmazonMusicTrack(device, trackId); 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 (channelId.equals(CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String playListId = ((StringType) command).toFullString(); String playListId = command.toFullString();
if (StringUtils.isNotEmpty(playListId)) { if (!playListId.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
} }
connection.playAmazonMusicPlayList(device, playListId); connection.playAmazonMusicPlayList(device, playListId);
@ -493,7 +488,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_AMAZON_MUSIC)) { if (channelId.equals(CHANNEL_AMAZON_MUSIC)) {
if (command == OnOffType.ON) { if (command == OnOffType.ON) {
String lastKnownAmazonMusicId = this.lastKnownAmazonMusicId; String lastKnownAmazonMusicId = this.lastKnownAmazonMusicId;
if (StringUtils.isNotEmpty(lastKnownAmazonMusicId)) { if (lastKnownAmazonMusicId != null && !lastKnownAmazonMusicId.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
} }
connection.playAmazonMusicTrack(device, lastKnownAmazonMusicId); connection.playAmazonMusicTrack(device, lastKnownAmazonMusicId);
@ -505,8 +500,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// radio commands // radio commands
if (channelId.equals(CHANNEL_RADIO_STATION_ID)) { if (channelId.equals(CHANNEL_RADIO_STATION_ID)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String stationId = ((StringType) command).toFullString(); String stationId = command.toFullString();
if (StringUtils.isNotEmpty(stationId)) { if (!stationId.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
} }
connection.playRadio(device, stationId); connection.playRadio(device, stationId);
@ -515,7 +510,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_RADIO)) { if (channelId.equals(CHANNEL_RADIO)) {
if (command == OnOffType.ON) { if (command == OnOffType.ON) {
String lastKnownRadioStationId = this.lastKnownRadioStationId; String lastKnownRadioStationId = this.lastKnownRadioStationId;
if (StringUtils.isNotEmpty(lastKnownRadioStationId)) { if (lastKnownRadioStationId != null && !lastKnownRadioStationId.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
} }
connection.playRadio(device, lastKnownRadioStationId); connection.playRadio(device, lastKnownRadioStationId);
@ -528,8 +523,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (channelId.equals(CHANNEL_REMIND)) { if (channelId.equals(CHANNEL_REMIND)) {
if (command instanceof StringType) { if (command instanceof StringType) {
stopCurrentNotification(); stopCurrentNotification();
String reminder = ((StringType) command).toFullString(); String reminder = command.toFullString();
if (StringUtils.isNotEmpty(reminder)) { if (!reminder.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
updateRemind = true; updateRemind = true;
currentNotification = connection.notification(device, "Reminder", reminder, null); 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 (channelId.equals(CHANNEL_PLAY_ALARM_SOUND)) {
if (command instanceof StringType) { if (command instanceof StringType) {
stopCurrentNotification(); stopCurrentNotification();
String alarmSound = ((StringType) command).toFullString(); String alarmSound = command.toFullString();
if (StringUtils.isNotEmpty(alarmSound)) { if (!alarmSound.isEmpty()) {
waitForUpdate = 3000; waitForUpdate = 3000;
updateAlarm = true; updateAlarm = true;
String[] parts = alarmSound.split(":", 2); String[] parts = alarmSound.split(":", 2);
@ -566,8 +561,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
// routine commands // routine commands
if (channelId.equals(CHANNEL_TEXT_TO_SPEECH)) { if (channelId.equals(CHANNEL_TEXT_TO_SPEECH)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String text = ((StringType) command).toFullString(); String text = command.toFullString();
if (StringUtils.isNotEmpty(text)) { if (!text.isEmpty()) {
waitForUpdate = 1000; waitForUpdate = 1000;
updateTextToSpeech = true; updateTextToSpeech = true;
startTextToSpeech(connection, device, text); startTextToSpeech(connection, device, text);
@ -595,8 +590,8 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} }
if (channelId.equals(CHANNEL_LAST_VOICE_COMMAND)) { if (channelId.equals(CHANNEL_LAST_VOICE_COMMAND)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String text = ((StringType) command).toFullString(); String text = command.toFullString();
if (StringUtils.isNotEmpty(text)) { if (!text.isEmpty()) {
waitForUpdate = -1; waitForUpdate = -1;
startTextToSpeech(connection, device, text); startTextToSpeech(connection, device, text);
} }
@ -604,18 +599,18 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} }
if (channelId.equals(CHANNEL_START_COMMAND)) { if (channelId.equals(CHANNEL_START_COMMAND)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String commandText = ((StringType) command).toFullString(); String commandText = command.toFullString();
if (StringUtils.isNotEmpty(commandText)) { if (!commandText.isEmpty()) {
updateStartCommand = true; updateStartCommand = true;
if (commandText.startsWith(FLASH_BRIEFING_COMMAND_PREFIX)) { if (commandText.startsWith(FLASH_BRIEFING_COMMAND_PREFIX)) {
// Handle custom flashbriefings commands // Handle custom flashbriefings commands
String flashbriefing = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length()); String flashBriefingId = commandText.substring(FLASH_BRIEFING_COMMAND_PREFIX.length());
for (FlashBriefingProfileHandler flashBriefingHandler : account
for (FlashBriefingProfileHandler flashBriefing : account
.getFlashBriefingProfileHandlers()) { .getFlashBriefingProfileHandlers()) {
ThingUID flashBriefingId = flashBriefing.getThing().getUID(); ThingUID flashBriefingUid = flashBriefingHandler.getThing().getUID();
if (StringUtils.equals(flashBriefing.getThing().getUID().getId(), flashbriefing)) { if (flashBriefingId.equals(flashBriefingHandler.getThing().getUID().getId())) {
flashBriefing.handleCommand(new ChannelUID(flashBriefingId, CHANNEL_PLAY_ON_DEVICE), flashBriefingHandler.handleCommand(
new ChannelUID(flashBriefingUid, CHANNEL_PLAY_ON_DEVICE),
new StringType(device.serialNumber)); new StringType(device.serialNumber));
break; break;
} }
@ -626,15 +621,15 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
commandText = "Alexa." + commandText + ".Play"; commandText = "Alexa." + commandText + ".Play";
} }
waitForUpdate = 1000; waitForUpdate = 1000;
connection.executeSequenceCommand(device, commandText, null); connection.executeSequenceCommand(device, commandText, Map.of());
} }
} }
} }
} }
if (channelId.equals(CHANNEL_START_ROUTINE)) { if (channelId.equals(CHANNEL_START_ROUTINE)) {
if (command instanceof StringType) { if (command instanceof StringType) {
String utterance = ((StringType) command).toFullString(); String utterance = command.toFullString();
if (StringUtils.isNotEmpty(utterance)) { if (!utterance.isEmpty()) {
waitForUpdate = 1000; waitForUpdate = 1000;
updateRoutine = true; updateRoutine = true;
connection.startRoutine(device, utterance); connection.startRoutine(device, utterance);
@ -669,7 +664,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} else { } else {
this.updateStateJob = scheduler.schedule(doRefresh, waitForUpdate, TimeUnit.MILLISECONDS); this.updateStateJob = scheduler.schedule(doRefresh, waitForUpdate, TimeUnit.MILLISECONDS);
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("handleCommand fails", e); logger.info("handleCommand fails", e);
} }
} }
@ -699,7 +694,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
try { try {
connection.setEqualizer(device, newEqualizerSetting); connection.setEqualizer(device, newEqualizerSetting);
return true; return true;
} catch (HttpException | IOException | ConnectionException e) { } catch (HttpException | IOException | ConnectionException | InterruptedException e) {
logger.debug("Update equalizer failed", e); logger.debug("Update equalizer failed", e);
this.lastKnownEqualizer = null; this.lastKnownEqualizer = null;
} }
@ -746,7 +741,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (currentConnection != null) { if (currentConnection != null) {
try { try {
currentConnection.stopNotification(currentNotification); currentConnection.stopNotification(currentNotification);
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.warn("Stop notification failed", 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); logger.warn("update notification state fails", e);
} }
if (stopCurrentNotification) { if (stopCurrentNotification) {
@ -855,20 +850,19 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (musicProviderId != null) { if (musicProviderId != null) {
musicProviderId = musicProviderId.toUpperCase(); musicProviderId = musicProviderId.toUpperCase();
if (StringUtils.equals(musicProviderId, "AMAZON MUSIC")) { if (musicProviderId.equals("AMAZON MUSIC")) {
musicProviderId = "AMAZON_MUSIC"; musicProviderId = "AMAZON_MUSIC";
} }
if (StringUtils.equals(musicProviderId, "CLOUD_PLAYER")) { if (musicProviderId.equals("CLOUD_PLAYER")) {
musicProviderId = "AMAZON_MUSIC"; musicProviderId = "AMAZON_MUSIC";
} }
if (StringUtils.startsWith(musicProviderId, "TUNEIN")) { if (musicProviderId.startsWith("TUNEIN")) {
musicProviderId = "TUNEIN"; musicProviderId = "TUNEIN";
} }
if (StringUtils.startsWithIgnoreCase(musicProviderId, "iHeartRadio")) { if (musicProviderId.startsWith("IHEARTRADIO")) {
musicProviderId = "I_HEART_RADIO"; musicProviderId = "I_HEART_RADIO";
} }
if (StringUtils.containsIgnoreCase(musicProviderId, "Apple") if (musicProviderId.equals("APPLE") && musicProviderId.contains("MUSIC")) {
&& StringUtils.containsIgnoreCase(musicProviderId, "Music")) {
musicProviderId = "APPLE_MUSIC"; musicProviderId = "APPLE_MUSIC";
} }
} }
@ -880,13 +874,13 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (e.getCode() != 400) { if (e.getCode() != 400) {
logger.info("getPlayer fails", e); logger.info("getPlayer fails", e);
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("getPlayer fails", e); logger.info("getPlayer fails", e);
} }
// check playing // 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) { synchronized (progressLock) {
Boolean showTime = null; Boolean showTime = null;
Long mediaLength = null; Long mediaLength = null;
@ -919,8 +913,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
JsonMediaState mediaState = null; JsonMediaState mediaState = null;
try { try {
if (StringUtils.equalsIgnoreCase(musicProviderId, "AMAZON_MUSIC") if ("AMAZON_MUSIC".equalsIgnoreCase(musicProviderId) || "TUNEIN".equalsIgnoreCase(musicProviderId)) {
|| StringUtils.equalsIgnoreCase(musicProviderId, "TUNEIN")) {
mediaState = connection.getMediaState(device); mediaState = connection.getMediaState(device);
} }
} catch (HttpException e) { } catch (HttpException e) {
@ -929,7 +922,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
} else { } else {
logger.info("getMediaState fails", e); logger.info("getMediaState fails", e);
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException | InterruptedException e) {
logger.info("getMediaState fails", e); logger.info("getMediaState fails", e);
} }
@ -944,11 +937,14 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String amazonMusicTrackId = ""; String amazonMusicTrackId = "";
String amazonMusicPlayListId = ""; String amazonMusicPlayListId = "";
boolean amazonMusic = false; boolean amazonMusic = false;
if (mediaState != null && isPlaying && StringUtils.equals(mediaState.providerId, "CLOUD_PLAYER") if (mediaState != null) {
&& StringUtils.isNotEmpty(mediaState.contentId)) { String contentId = mediaState.contentId;
amazonMusicTrackId = mediaState.contentId; if (isPlaying && "CLOUD_PLAYER".equals(mediaState.providerId) && contentId != null
lastKnownAmazonMusicId = amazonMusicTrackId; && !contentId.isEmpty()) {
amazonMusic = true; amazonMusicTrackId = contentId;
lastKnownAmazonMusicId = amazonMusicTrackId;
amazonMusic = true;
}
} }
// handle bluetooth // handle bluetooth
@ -963,34 +959,37 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
if (paired == null) { if (paired == null) {
continue; continue;
} }
if (paired.connected && paired.address != null) { String pairedAddress = paired.address;
if (paired.connected && pairedAddress != null) {
bluetoothIsConnected = true; bluetoothIsConnected = true;
bluetoothMAC = paired.address; bluetoothMAC = pairedAddress;
bluetoothDeviceName = paired.friendlyName; bluetoothDeviceName = paired.friendlyName;
if (StringUtils.isEmpty(bluetoothDeviceName)) { if (bluetoothDeviceName == null || bluetoothDeviceName.isEmpty()) {
bluetoothDeviceName = paired.address; bluetoothDeviceName = pairedAddress;
} }
break; break;
} }
} }
} }
} }
if (StringUtils.isNotEmpty(bluetoothMAC)) { if (!bluetoothMAC.isEmpty()) {
lastKnownBluetoothMAC = bluetoothMAC; lastKnownBluetoothMAC = bluetoothMAC;
} }
// handle radio // handle radio
boolean isRadio = false; boolean isRadio = false;
if (mediaState != null && StringUtils.isNotEmpty(mediaState.radioStationId)) {
lastKnownRadioStationId = mediaState.radioStationId;
if (StringUtils.equalsIgnoreCase(musicProviderId, "TUNEIN")) {
isRadio = true;
}
}
String radioStationId = ""; String radioStationId = "";
if (isRadio && mediaState != null && StringUtils.equals(mediaState.currentState, "PLAYING") if (mediaState != null) {
&& mediaState.radioStationId != null) { radioStationId = Objects.requireNonNullElse(mediaState.radioStationId, "");
radioStationId = mediaState.radioStationId; if (!radioStationId.isEmpty()) {
lastKnownRadioStationId = radioStationId;
if ("TUNEIN".equalsIgnoreCase(musicProviderId)) {
isRadio = true;
if (!"PLAYING".equals(mediaState.currentState)) {
radioStationId = "";
}
}
}
} }
// handle title, subtitle, imageUrl // handle title, subtitle, imageUrl
@ -1021,13 +1020,13 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
QueueEntry entry = queueEntries[0]; QueueEntry entry = queueEntries[0];
if (entry != null) { if (entry != null) {
if (isRadio) { if (isRadio) {
if (StringUtils.isEmpty(imageUrl) && entry.imageURL != null) { if ((imageUrl == null || imageUrl.isEmpty()) && entry.imageURL != null) {
imageUrl = entry.imageURL; imageUrl = entry.imageURL;
} }
if (StringUtils.isEmpty(subTitle1) && entry.radioStationSlogan != null) { if ((subTitle1 == null || subTitle1.isEmpty()) && entry.radioStationSlogan != null) {
subTitle1 = entry.radioStationSlogan; subTitle1 = entry.radioStationSlogan;
} }
if (StringUtils.isEmpty(subTitle2) && entry.radioStationLocation != null) { if ((subTitle2 == null || subTitle2.isEmpty()) && entry.radioStationLocation != null) {
subTitle2 = entry.radioStationLocation; subTitle2 = entry.radioStationLocation;
} }
} }
@ -1039,9 +1038,10 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
String providerDisplayName = ""; String providerDisplayName = "";
if (provider != null) { if (provider != null) {
if (provider.providerDisplayName != 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; providerDisplayName = provider.providerName;
} }
} }
@ -1153,7 +1153,7 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
treble = equalizer.treble; treble = equalizer.treble;
} }
this.lastKnownEqualizer = equalizer; this.lastKnownEqualizer = equalizer;
} catch (IOException | URISyntaxException | HttpException | ConnectionException e) { } catch (IOException | URISyntaxException | HttpException | ConnectionException | InterruptedException e) {
logger.debug("Get equalizer failes", e); logger.debug("Get equalizer failes", e);
return; return;
} }
@ -1204,20 +1204,22 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
return; return;
} }
Description description = pushActivity.parseDescription(); Description description = pushActivity.parseDescription();
if (StringUtils.isEmpty(description.firstUtteranceId) String firstUtteranceId = description.firstUtteranceId;
|| StringUtils.startsWithIgnoreCase(description.firstUtteranceId, "TextClient:")) { if (firstUtteranceId == null || firstUtteranceId.isEmpty()
|| firstUtteranceId.toLowerCase().startsWith("textclient:")) {
return; return;
} }
if (StringUtils.isEmpty(description.firstStreamId)) { String firstStreamId = description.firstStreamId;
if (firstStreamId == null || firstStreamId.isEmpty()) {
return; return;
} }
String spokenText = description.summary; String spokenText = description.summary;
if (spokenText != null && StringUtils.isNotEmpty(spokenText)) { if (spokenText != null && !spokenText.isEmpty()) {
// remove wake word // remove wake word
String wakeWordPrefix = this.wakeWord; String wakeWordPrefix = this.wakeWord;
if (wakeWordPrefix != null) { if (wakeWordPrefix != null) {
wakeWordPrefix += " "; wakeWordPrefix += " ";
if (StringUtils.startsWithIgnoreCase(spokenText, wakeWordPrefix)) { if (spokenText.toLowerCase().startsWith(wakeWordPrefix.toLowerCase())) {
spokenText = spokenText.substring(wakeWordPrefix.length()); spokenText = spokenText.substring(wakeWordPrefix.length());
} }
} }
@ -1234,12 +1236,10 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
this.logger.debug("Handle push command {}", command); this.logger.debug("Handle push command {}", command);
switch (command) { switch (command) {
case "PUSH_VOLUME_CHANGE": case "PUSH_VOLUME_CHANGE":
JsonCommandPayloadPushVolumeChange volumeChange = gson.fromJson(payload, JsonCommandPayloadPushVolumeChange volumeChange = Objects
JsonCommandPayloadPushVolumeChange.class); .requireNonNull(gson.fromJson(payload, JsonCommandPayloadPushVolumeChange.class));
Connection connection = this.findConnection(); Connection connection = this.findConnection();
@Nullable
Integer volumeSetting = volumeChange.volumeSetting; Integer volumeSetting = volumeChange.volumeSetting;
@Nullable
Boolean muted = volumeChange.isMuted; Boolean muted = volumeChange.isMuted;
if (muted != null && muted) { if (muted != null && muted) {
updateState(CHANNEL_VOLUME, new PercentType(0)); updateState(CHANNEL_VOLUME, new PercentType(0));
@ -1274,14 +1274,15 @@ public class EchoHandler extends BaseThingHandler implements IEchoThingHandler {
ZonedDateTime nextMusicAlarm = null; ZonedDateTime nextMusicAlarm = null;
ZonedDateTime nextTimer = null; ZonedDateTime nextTimer = null;
for (JsonNotificationResponse notification : notifications) { for (JsonNotificationResponse notification : notifications) {
if (StringUtils.equals(notification.deviceSerialNumber, device.serialNumber)) { if (Objects.equals(notification.deviceSerialNumber, device.serialNumber)) {
// notification for this device // notification for this device
if (StringUtils.equals(notification.status, "ON")) { if ("ON".equals(notification.status)) {
if ("Reminder".equals(notification.type)) { if ("Reminder".equals(notification.type)) {
String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString(); String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset); .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 continue; // Ignore recurring entry if alarm time is before now
} }
if (nextReminder == null || alarmTime.isBefore(nextReminder)) { 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(); String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset); .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 continue; // Ignore recurring entry if alarm time is before now
} }
if (nextAlarm == null || alarmTime.isBefore(nextAlarm)) { 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(); String offset = ZoneId.systemDefault().getRules().getOffset(Instant.now()).toString();
ZonedDateTime alarmTime = ZonedDateTime ZonedDateTime alarmTime = ZonedDateTime
.parse(notification.originalDate + "T" + notification.originalTime + offset); .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 continue; // Ignore recurring entry if alarm time is before now
} }
if (nextMusicAlarm == null || alarmTime.isBefore(nextMusicAlarm)) { 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 static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*;
import java.io.IOException; import java.util.Map;
import java.net.URISyntaxException;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.Connection; import org.openhab.binding.amazonechocontrol.internal.Connection;
@ -104,59 +102,54 @@ public class FlashBriefingProfileHandler extends BaseThingHandler {
if (updateStateJob != null) { if (updateStateJob != null) {
updateStateJob.cancel(false); updateStateJob.cancel(false);
} }
try { String channelId = channelUID.getId();
String channelId = channelUID.getId(); if (command instanceof RefreshType) {
if (command instanceof RefreshType) { waitForUpdate = 0;
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)) { if (channelId.equals(CHANNEL_ACTIVE)) {
saveCurrentProfile(accountHandler); if (command.equals(OnOffType.ON)) {
String currentConfigurationJson = this.currentConfigurationJson;
if (!currentConfigurationJson.isEmpty()) {
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
updateState(CHANNEL_ACTIVE, OnOffType.ON);
waitForUpdate = 500; waitForUpdate = 500;
} }
} }
if (channelId.equals(CHANNEL_ACTIVE)) { }
if (command.equals(OnOffType.ON)) { if (channelId.equals(CHANNEL_PLAY_ON_DEVICE)) {
String currentConfigurationJson = this.currentConfigurationJson; if (command instanceof StringType) {
if (!currentConfigurationJson.isEmpty()) { String deviceSerialOrName = command.toFullString();
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson); String currentConfigurationJson = this.currentConfigurationJson;
updateState(CHANNEL_ACTIVE, OnOffType.ON); if (!currentConfigurationJson.isEmpty()) {
waitForUpdate = 500; String old = accountHandler.getEnabledFlashBriefingsJson();
} accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
} Device device = accountHandler.findDeviceJsonBySerialOrName(deviceSerialOrName);
} if (device == null) {
if (channelId.equals(CHANNEL_PLAY_ON_DEVICE)) { logger.warn("Device '{}' not found", deviceSerialOrName);
if (command instanceof StringType) { } else {
String deviceSerialOrName = ((StringType) command).toFullString(); @Nullable
String currentConfigurationJson = this.currentConfigurationJson; Connection connection = accountHandler.findConnection();
if (!currentConfigurationJson.isEmpty()) { if (connection == null) {
String old = accountHandler.getEnabledFlashBriefingsJson(); logger.warn("Connection for '{}' not found", accountHandler.getThing().getUID().getId());
accountHandler.setEnabledFlashBriefingsJson(currentConfigurationJson);
Device device = accountHandler.findDeviceJsonBySerialOrName(deviceSerialOrName);
if (device == null) {
logger.warn("Device '{}' not found", deviceSerialOrName);
} else { } else {
@Nullable connection.executeSequenceCommand(device, "Alexa.FlashBriefing.Play", Map.of());
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);
scheduler.schedule(() -> accountHandler.setEnabledFlashBriefingsJson(old), 1000, scheduler.schedule(() -> accountHandler.setEnabledFlashBriefingsJson(old), 1000,
TimeUnit.MILLISECONDS); 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) { if (waitForUpdate >= 0) {
this.updateStateJob = scheduler.schedule(() -> accountHandler.updateFlashBriefingHandlers(), waitForUpdate, this.updateStateJob = scheduler.schedule(() -> accountHandler.updateFlashBriefingHandlers(), waitForUpdate,
@ -189,7 +182,7 @@ public class FlashBriefingProfileHandler extends BaseThingHandler {
} else { } else {
updateState(CHANNEL_ACTIVE, OnOffType.OFF); updateState(CHANNEL_ACTIVE, OnOffType.OFF);
} }
return StringUtils.equals(this.currentConfigurationJson, currentConfigurationJson); return this.currentConfigurationJson.equals(currentConfigurationJson);
} }
private String saveCurrentProfile(AccountHandler connection) { 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.AmazonEchoControlBindingConstants.DEVICE_PROPERTY_ID;
import static org.openhab.binding.amazonechocontrol.internal.smarthome.Constants.SUPPORTED_INTERFACES; import static org.openhab.binding.amazonechocontrol.internal.smarthome.Constants.SUPPORTED_INTERFACES;
import java.util.ArrayList; import java.util.*;
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.function.Supplier; import java.util.function.Supplier;
import org.eclipse.jdt.annotation.NonNullByDefault; 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.Connection;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability; 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.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.JsonSmartHomeGroups.SmartHomeGroup;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeTags;
import org.openhab.binding.amazonechocontrol.internal.jsons.SmartHomeBaseDevice; import org.openhab.binding.amazonechocontrol.internal.jsons.SmartHomeBaseDevice;
import org.openhab.binding.amazonechocontrol.internal.smarthome.Constants; import org.openhab.binding.amazonechocontrol.internal.smarthome.Constants;
import org.openhab.binding.amazonechocontrol.internal.smarthome.HandlerBase; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.gson.Gson; import com.google.gson.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/** /**
* @author Lukas Knoeller - Initial contribution * @author Lukas Knoeller - Initial contribution
@ -176,6 +167,7 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
public void updateChannelStates(List<SmartHomeBaseDevice> allDevices, public void updateChannelStates(List<SmartHomeBaseDevice> allDevices,
Map<String, JsonArray> applianceIdToCapabilityStates) { Map<String, JsonArray> applianceIdToCapabilityStates) {
logger.trace("Updating {} with {}", allDevices, applianceIdToCapabilityStates);
AccountHandler accountHandler = getAccountHandler(); AccountHandler accountHandler = getAccountHandler();
SmartHomeBaseDevice smartHomeBaseDevice = this.smartHomeBaseDevice; SmartHomeBaseDevice smartHomeBaseDevice = this.smartHomeBaseDevice;
if (smartHomeBaseDevice == null) { if (smartHomeBaseDevice == null) {
@ -187,11 +179,11 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
Map<String, List<JsonObject>> mapInterfaceToStates = new HashMap<>(); Map<String, List<JsonObject>> mapInterfaceToStates = new HashMap<>();
SmartHomeDevice firstDevice = null; SmartHomeDevice firstDevice = null;
for (SmartHomeDevice shd : getSupportedSmartHomeDevices(smartHomeBaseDevice, allDevices)) { for (SmartHomeDevice shd : getSupportedSmartHomeDevices(smartHomeBaseDevice, allDevices)) {
JsonArray states = applianceIdToCapabilityStates.get(shd.applianceId);
String applianceId = shd.applianceId; String applianceId = shd.applianceId;
if (applianceId == null) { if (applianceId == null) {
continue; continue;
} }
JsonArray states = applianceIdToCapabilityStates.get(applianceId);
if (states != null) { if (states != null) {
stateFound = true; stateFound = true;
if (smartHomeBaseDevice.isGroup()) { if (smartHomeBaseDevice.isGroup()) {
@ -210,26 +202,28 @@ public class SmartHomeDeviceHandler extends BaseThingHandler {
for (JsonElement stateElement : states) { for (JsonElement stateElement : states) {
String stateJson = stateElement.getAsString(); String stateJson = stateElement.getAsString();
if (stateJson.startsWith("{") && stateJson.endsWith("}")) { if (stateJson.startsWith("{") && stateJson.endsWith("}")) {
JsonObject state = gson.fromJson(stateJson, JsonObject.class); JsonObject state = Objects.requireNonNull(gson.fromJson(stateJson, JsonObject.class));
String interfaceName = state.get("namespace").getAsString(); String interfaceName = Objects.requireNonNullElse(state.get("namespace"), JsonNull.INSTANCE)
mapInterfaceToStates.computeIfAbsent(interfaceName, k -> new ArrayList<>()).add(state); .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()) { for (String interfaceName : handlerBase.getSupportedInterface()) {
List<JsonObject> stateList = mapInterfaceToStates.getOrDefault(interfaceName, Collections.emptyList()); List<JsonObject> stateList = mapInterfaceToStates.get(interfaceName);
try { if (stateList != null) {
handlerBase.updateChannels(interfaceName, stateList, result); try {
} catch (Exception e) { handlerBase.updateChannels(interfaceName, stateList, result);
// We catch all exceptions, otherwise all other things are not updated! } catch (Exception e) {
logger.debug("Updating states failed", e); // We catch all exceptions, otherwise all other things are not updated!
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage()); 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) { for (SmartHomeCapability capability : capabilities) {
String interfaceName = capability.interfaceName; String interfaceName = capability.interfaceName;
if (interfaceName != null) { 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) { for (SmartHomeBaseDevice device : allDevices) {
if (device instanceof SmartHomeDevice) { if (device instanceof SmartHomeDevice) {
SmartHomeDevice shd = (SmartHomeDevice) device; SmartHomeDevice shd = (SmartHomeDevice) device;
if (shd.tags != null && shd.tags.tagNameToValueSetMap != null JsonSmartHomeTags.JsonSmartHomeTag tags = shd.tags;
&& shd.tags.tagNameToValueSetMap.groupIdentity != null if (tags != null) {
&& shg.applianceGroupIdentifier != null && shg.applianceGroupIdentifier.value != null JsonSmartHomeGroupIdentity.SmartHomeGroupIdentity tagNameToValueSetMap = tags.tagNameToValueSetMap;
&& Arrays.asList(shd.tags.tagNameToValueSetMap.groupIdentity) JsonSmartHomeGroupIdentifiers.SmartHomeGroupIdentifier applianceGroupIdentifier = shg.applianceGroupIdentifier;
.contains(shg.applianceGroupIdentifier.value)) { if (tagNameToValueSetMap != null && tagNameToValueSetMap.groupIdentity != null
SmartHomeCapability[] capabilities = shd.capabilities; && applianceGroupIdentifier != null && applianceGroupIdentifier.value != null
if (capabilities != null) { && Arrays.asList(tagNameToValueSetMap.groupIdentity)
if (Arrays.stream(capabilities).map(capability -> capability.interfaceName) .contains(applianceGroupIdentifier.value)) {
.anyMatch(SUPPORTED_INTERFACES::contains)) { SmartHomeCapability[] capabilities = shd.capabilities;
result.add(shd); 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) { @Nullable Locale locale) {
String channelId = channel.getUID().getId(); String channelId = channel.getUID().getId();
for (HandlerBase handler : handlers.values()) { for (HandlerBase handler : handlers.values()) {
if (handler != null && handler.hasChannel(channelId)) { if (handler.hasChannel(channelId)) {
return handler.findStateDescription(channelId, originalStateDescription, locale); return handler.findStateDescription(channelId, originalStateDescription, locale);
} }
} }

View File

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

View File

@ -12,6 +12,8 @@
*/ */
package org.openhab.binding.amazonechocontrol.internal.jsons; package org.openhab.binding.amazonechocontrol.internal.jsons;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability; import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeCapabilities.SmartHomeCapability;
@ -24,7 +26,6 @@ import org.openhab.binding.amazonechocontrol.internal.jsons.JsonSmartHomeTags.Js
@NonNullByDefault @NonNullByDefault
public class JsonSmartHomeDevices { public class JsonSmartHomeDevices {
public static class SmartHomeDevice implements SmartHomeBaseDevice { public static class SmartHomeDevice implements SmartHomeBaseDevice {
public @Nullable Integer updateIntervalInSeconds; public @Nullable Integer updateIntervalInSeconds;
@Override @Override
@ -52,11 +53,29 @@ public class JsonSmartHomeDevices {
public @Nullable SmartHomeDevice @Nullable [] groupDevices; public @Nullable SmartHomeDevice @Nullable [] groupDevices;
public @Nullable String connectedVia; public @Nullable String connectedVia;
public @Nullable DriverIdentity driverIdentity; 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 static class DriverIdentity {
public @Nullable String namespace; public @Nullable String namespace;
public @Nullable String identifier; public @Nullable String identifier;
@Override
public String toString() {
return "DriverIdentity{" + "namespace='" + namespace + '\'' + ", identifier='" + identifier + '\'' + '}';
}
} }
public @Nullable SmartHomeDevice @Nullable [] smarthomeDevices; public @Nullable SmartHomeDevice @Nullable [] smarthomeDevices;

View File

@ -46,6 +46,12 @@ public class JsonSmartHomeGroups {
public @Nullable Boolean isSpace; public @Nullable Boolean isSpace;
public @Nullable Boolean space; public @Nullable Boolean space;
public @Nullable SmartHomeGroupIdentifier applianceGroupIdentifier; public @Nullable SmartHomeGroupIdentifier applianceGroupIdentifier;
@Override
public String toString() {
return "SmartHomeGroup{" + "applianceGroupName='" + applianceGroupName + '\'' + ", isSpace=" + isSpace
+ ", space=" + space + ", applianceGroupIdentifier=" + applianceGroupIdentifier + '}';
}
} }
public @Nullable SmartHomeGroup @Nullable [] groups; 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 void updateChannels(String interfaceName, List<JsonObject> stateList, UpdateChannelResult result);
public abstract boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId, 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, public abstract @Nullable StateDescription findStateDescription(String channelId,
StateDescription originalStateDescription, @Nullable Locale locale); StateDescription originalStateDescription, @Nullable Locale locale);

View File

@ -91,7 +91,8 @@ public class HandlerBrightnessController extends HandlerBase {
@Override @Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId, 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 (channelId.equals(BRIGHTNESS.channelId)) {
if (containsCapabilityProperty(capabilties, BRIGHTNESS.propertyName)) { if (containsCapabilityProperty(capabilties, BRIGHTNESS.propertyName)) {
if (command.equals(IncreaseDecreaseType.INCREASE)) { if (command.equals(IncreaseDecreaseType.INCREASE)) {

View File

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

View File

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

View File

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

View File

@ -92,7 +92,8 @@ public class HandlerPowerLevelController extends HandlerBase {
@Override @Override
public boolean handleCommand(Connection connection, SmartHomeDevice shd, String entityId, 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 (channelId.equals(POWER_LEVEL.channelId)) {
if (containsCapabilityProperty(capabilties, POWER_LEVEL.propertyName)) { if (containsCapabilityProperty(capabilties, POWER_LEVEL.propertyName)) {
if (command.equals(IncreaseDecreaseType.INCREASE)) { if (command.equals(IncreaseDecreaseType.INCREASE)) {

View File

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

View File

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