Skip to content

Commit

Permalink
x
Browse files Browse the repository at this point in the history
Signed-off-by: Jan N. Klug <[email protected]>
  • Loading branch information
J-N-K committed Oct 18, 2023
1 parent f6632bd commit 160374f
Show file tree
Hide file tree
Showing 128 changed files with 2,857 additions and 2,315 deletions.
6 changes: 6 additions & 0 deletions bundles/org.smarthomej.binding.amazonechocontrol/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
<version>1.1.6.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.annotation</artifactId>
<version>2.2.600</version>
<scope>compile</scope>
</dependency>
</dependencies>

</project>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ public class AmazonEchoControlBindingConstants {
public static final ThingTypeUID THING_TYPE_ECHO_SPOT = new ThingTypeUID(BINDING_ID, "echospot");
public static final ThingTypeUID THING_TYPE_ECHO_SHOW = new ThingTypeUID(BINDING_ID, "echoshow");
public static final ThingTypeUID THING_TYPE_ECHO_WHA = new ThingTypeUID(BINDING_ID, "wha");

public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID,
"flashbriefingprofile");

public static final ThingTypeUID THING_TYPE_SMART_HOME_DEVICE = new ThingTypeUID(BINDING_ID, "smartHomeDevice");
public static final ThingTypeUID THING_TYPE_SMART_HOME_DEVICE_GROUP = new ThingTypeUID(BINDING_ID,
"smartHomeDeviceGroup");
Expand Down Expand Up @@ -103,7 +101,6 @@ public class AmazonEchoControlBindingConstants {
public static final String CHANNEL_NEXT_ALARM = "nextAlarm";
public static final String CHANNEL_NEXT_MUSIC_ALARM = "nextMusicAlarm";
public static final String CHANNEL_NEXT_TIMER = "nextTimer";

public static final String CHANNEL_SAVE = "save";
public static final String CHANNEL_ACTIVE = "active";
public static final String CHANNEL_PLAY_ON_DEVICE = "playOnDevice";
Expand All @@ -124,86 +121,8 @@ public class AmazonEchoControlBindingConstants {
public static final String DI_OS_VERSION = "16.6";
public static final String DI_SDK_VERSION = "6.12.4";

// DeviceTypeIds to human readable description
// originally found here: https://github.com/Apollon77/ioBroker.alexa2/blob/master/main.js
public static final Map<String, String> DEVICE_TYPES = Map.<String, String> ofEntries( //
Map.entry("A10A33FOX2NUBK", "Echo Spot"), //
Map.entry("A10L5JEZTKKCZ8", "Vobot-Clock"), //
Map.entry("A12GXV8XMS007S", "FireTV"), //
Map.entry("A15ERDAKK5HQQG", "Sonos"), //
Map.entry("A17LGWINFBUTZZ", "Anker Roav Viva Alexa"), //
Map.entry("A18O6U1UQFJ0XK", "Echo Plus 2nd Gen"), //
Map.entry("A1C66CX2XD756O", "Fire HD 8"), //
Map.entry("A1DL2DVDQVK3Q", "Apps"), //
Map.entry("A1ETW4IXK2PYBP", "Echo Auto"), //
Map.entry("A1H0CMF1XM0ZP4", "Echo Dot/Bose"), //
Map.entry("A1J16TEDOYCZTN", "Fire Tab"), //
Map.entry("A1JJ0KFC4ZPNJ3", "Echo Input"), //
Map.entry("A1NL4BVLQ4L3N3", "Echo Show"), //
Map.entry("A1P31Q3MOWSHOD", "Anker Zalo Halo Speaker"), //
Map.entry("A1Q7QCGNMXAKYW", "Fire Tab 7"), //
Map.entry("A1QKZ9D0IJY332", "Samsung QLED"), //
Map.entry("A1RABVCI4QCIKC", "Echo Dot 3rd Gen"), //
Map.entry("A1RTAM01W29CUP", "Windows App"), //
Map.entry("A1X7HJX9QL16M5", "Bespoken.io"), //
Map.entry("A1Z88NGR2BK6A2", "Echo Show 8"), //
Map.entry("A1ZB65LA390I4K", "Fire HD 10"), //
Map.entry("A21Z3CGI8UIP0F", "Apps"), //
Map.entry("A265XOI9586NML", "FireTV Stick v3"), //
Map.entry("A2825NDLA7WDZV", "Apps"), //
Map.entry("A2E0SNTXJVT7WK", "FireTV V1"), //
Map.entry("A2GFL5ZMWNE0PX", "FireTV"), //
Map.entry("A2H4LV5GIZ1JFT", "Echo 4 Clock"), //
Map.entry("A2IVLV5VM2W81", "Apps"), //
Map.entry("A2J0R2SD7G9LPA", "Tablet"), //
Map.entry("A2JKHJ0PX4J3L3", "FireTV Cube"), //
Map.entry("A2L8KG0CT86ADW", "RaspPi"), //
Map.entry("A2LWARUGJLBYEW", "FireTV Stick V2"), //
Map.entry("A2M35JJZWCQOMZ", "Echo Plus"), //
Map.entry("A2M4YX06LWP8WI", "Fire Tab"), //
Map.entry("A2OSP3UA4VC85F", "Sonos"), //
Map.entry("A2T0P32DY3F7VB", "echosim.io"), //
Map.entry("A2TF17PFR55MTB", "Apps"), //
Map.entry("A2U21SRK4QGSE1", "Echo Dot 4th Gen"), //
Map.entry("A2Z8O30CD35N8F", "Sonos Arc"), //
Map.entry("A303PJF6ISQ7IC", "Echo Auto"), //
Map.entry("A30YDR2MK8HMRV", "Echo Dot 3rd Gen Clock"), //
Map.entry("A31DTMEEVDDOIV", "FireTV Stick Lite 2020"), //
Map.entry("A32DOYMUN6DTXA", "Echo Dot 3rd Gen"), //
Map.entry("A378ND93PD0NC4", "VR Radio"), //
Map.entry("A37SHHQ3NUL7B5", "Bose Homespeaker"), //
Map.entry("A38BPK7OW001EX", "Raspberry Alexa"), //
Map.entry("A38EHHIB10L47V", "Echo Dot"), //
Map.entry("A39Y3UG1XLEJLZ", "Fitbit Sense"), //
Map.entry("A3C9PE6TNYLTCH", "Multiroom"), //
Map.entry("A3FX4UWTP28V1P", "Echo 3"), //
Map.entry("A3GZUE7F9MEB4U", "FireTV Cube"), //
Map.entry("A3H674413M2EKB", "echosim.io"), //
Map.entry("A3HF4YRA2L7XGC", "FireTV Cube"), //
Map.entry("A3NPD82ABCPIDP", "Sonos Beam"), //
Map.entry("A3R8XIAIU4HJAX", "Echo Show"), //
Map.entry("A3R9S4ZZECZ6YL", "Fire Tab HD 10"), //
Map.entry("A3RBAYBE7VM004", "Echo Studio"), //
Map.entry("A3RMGO6LYLH7YN", "Echo 4 Bridge"), //
Map.entry("A3S5BH2HU6VAYF", "Echo Dot 2nd Gen"), //
Map.entry("A3SSG6GR8UU7SN", "Echo Sub"), //
Map.entry("A3TCJ8RTT3NVI7", "Listens for Alexa"), //
Map.entry("A3V3VA38K169FO", "Fire Tab"), //
Map.entry("A3VRME03NAXFUB", "Echo Flex"), //
Map.entry("A4ZP7ZC4PI6TO", "Echo Show 5th Gen"), //
Map.entry("A7WXQPH584YP", "Echo 2nd Gen"), //
Map.entry("A8DM4FYR6D3HT", "LG WebOS TV"), //
Map.entry("AB72C64C86AW2", "Echo"), //
Map.entry("ADVBD696BHNV5", "FireTV Stick V1"), //
Map.entry("AILBSA2LNTOYL", "reverb App"), //
Map.entry("AINRG27IL8AS0", "Megablast Speaker"), //
Map.entry("AKOAGQTKAS9YB", "Echo Connect"), //
Map.entry("AKPGW064GI9HE", "FireTV Stick 4K"), //
Map.entry("AP1F6KUH00XPV", "Stereo/Subwoofer Pair"), //
Map.entry("AVD3HM0HOJAAL", "Sonos One 2nd Gen"), //
Map.entry("AVE5HX13UR5NO", "Logitech Zero Touch"), //
Map.entry("AVU7CPPF2ZRAS", "Fire HD 8"), //
Map.entry("AWZZ5CVHX2CD", "Echo Show 2nd Gen"));
public static final Map<String, String> DEVICE_TYPES = ResourceUtil
.readProperties(AmazonEchoControlBindingConstants.class, "device_type.properties");

public static final JsonObject CAPABILITY_REGISTRATION = Objects.requireNonNull(
ResourceUtil.getResourceStream(AmazonEchoControlBindingConstants.class, "registration_capabilities.json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
Expand All @@ -41,6 +40,7 @@
import org.smarthomej.binding.amazonechocontrol.internal.handler.EchoHandler;
import org.smarthomej.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler;
import org.smarthomej.binding.amazonechocontrol.internal.handler.SmartHomeDeviceHandler;
import org.smarthomej.binding.amazonechocontrol.internal.util.NonNullListTypeAdapterFactory;
import org.smarthomej.binding.amazonechocontrol.internal.util.SerializeNullTypeAdapterFactory;
import org.smarthomej.commons.SimpleDynamicCommandDescriptionProvider;
import org.smarthomej.commons.SimpleDynamicStateDescriptionProvider;
Expand All @@ -62,7 +62,6 @@ public class AmazonEchoControlHandlerFactory extends BaseThingHandlerFactory {
private final HttpService httpService;
private final StorageService storageService;

private final BindingServlet bindingServlet;
private final Gson gson;
private final HttpClient httpClient;
private final HTTP2Client http2Client;
Expand All @@ -77,7 +76,8 @@ public AmazonEchoControlHandlerFactory(@Reference HttpService httpService, @Refe
@Reference HttpClientFactory httpClientFactory) throws Exception {
this.storageService = storageService;
this.httpService = httpService;
this.gson = new GsonBuilder().registerTypeAdapterFactory(new SerializeNullTypeAdapterFactory()).create();
this.gson = new GsonBuilder().registerTypeAdapterFactory(new NonNullListTypeAdapterFactory())
.registerTypeAdapterFactory(new SerializeNullTypeAdapterFactory()).create();
this.dynamicCommandDescriptionProvider = dynamicCommandDescriptionProvider;
this.dynamicStateDescriptionProvider = dynamicStateDescriptionProvider;

Expand All @@ -86,8 +86,6 @@ public AmazonEchoControlHandlerFactory(@Reference HttpService httpService, @Refe
http2Client.setConnectTimeout(10000);
http2Client.setIdleTimeout(-1);

this.bindingServlet = new BindingServlet(httpService);

httpClient.start();
http2Client.start();
}
Expand All @@ -105,12 +103,6 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|| SUPPORTED_SMART_HOME_THING_TYPES_UIDS.contains(thingTypeUID);
}

@Override
protected void deactivate(ComponentContext componentContext) {
bindingServlet.dispose();
super.deactivate(componentContext);
}

@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
Expand All @@ -121,7 +113,6 @@ protected void deactivate(ComponentContext componentContext) {
AccountHandler bridgeHandler = new AccountHandler((Bridge) thing, httpService, storage, gson, httpClient,
http2Client);
accountHandlers.add(bridgeHandler);
bindingServlet.addAccountThing(thing);
return bridgeHandler;
} else if (thingTypeUID.equals(THING_TYPE_FLASH_BRIEFING_PROFILE)) {
Storage<String> storage = storageService.getStorage(thing.getUID().toString(),
Expand All @@ -140,8 +131,6 @@ protected void deactivate(ComponentContext componentContext) {
protected synchronized void removeHandler(ThingHandler thingHandler) {
if (thingHandler instanceof AccountHandler) {
accountHandlers.remove(thingHandler);
BindingServlet bindingServlet = this.bindingServlet;
bindingServlet.removeAccountThing(thingHandler.getThing());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,87 +13,65 @@
*/
package org.smarthomej.binding.amazonechocontrol.internal;

import static org.smarthomej.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.BINDING_ID;
import static org.smarthomej.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.BINDING_NAME;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;

import javax.servlet.ServletException;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.Thing;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.MimeTypes;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardServletName;
import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardServletPattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smarthomej.binding.amazonechocontrol.internal.handler.AccountHandler;
import org.unbescape.html.HtmlEscape;

/**
* This servlet provides the base navigation page, with hyperlinks for the defined account things
*
* @author Michael Geramb - Initial Contribution
*/

@Component(service = Servlet.class, immediate = true)
@HttpWhiteboardServletName(BindingServlet.SERVLET_PATH)
@HttpWhiteboardServletPattern({ BindingServlet.SERVLET_PATH, BindingServlet.SERVLET_PATH + "/" })
@NonNullByDefault
public class BindingServlet extends HttpServlet {
public static final String SERVLET_PATH = "/" + BINDING_ID;
private static final long serialVersionUID = -1453738923337413163L;

private final Logger logger = LoggerFactory.getLogger(BindingServlet.class);

private final String servletUrl;
private final HttpService httpService;

private final List<Thing> accountHandlers = new ArrayList<>();
private final AmazonEchoControlHandlerFactory handlerFactory;

public BindingServlet(HttpService httpService) {
this.httpService = httpService;
String servletUrlWithoutRoot = "amazonechocontrol";
servletUrl = "/" + servletUrlWithoutRoot;
try {
httpService.registerServlet(servletUrl, this, null, httpService.createDefaultHttpContext());
} catch (NamespaceException | ServletException e) {
logger.warn("Register servlet fails", e);
}
}

public void addAccountThing(Thing accountThing) {
synchronized (accountHandlers) {
accountHandlers.add(accountThing);
}
}

public void removeAccountThing(Thing accountThing) {
synchronized (accountHandlers) {
accountHandlers.remove(accountThing);
}
}

public void dispose() {
httpService.unregister(servletUrl);
@Activate
public BindingServlet(@Reference AmazonEchoControlHandlerFactory handlerFactory) {
this.handlerFactory = handlerFactory;
}

@Override
protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp)
throws ServletException, IOException {
if (req == null) {
return;
}
if (resp == null) {
return;
}
protected void doGet(@NonNullByDefault({}) HttpServletRequest req, @NonNullByDefault({}) HttpServletResponse resp)
throws IOException {
String requestUri = req.getRequestURI();
if (requestUri == null) {
return;
}
String uri = requestUri.substring(servletUrl.length());
String uri = requestUri.substring(SERVLET_PATH.length());
String queryString = req.getQueryString();
if (queryString != null && queryString.length() > 0) {
if (queryString != null && !queryString.isEmpty()) {
uri += "?" + queryString;
}
logger.debug("doGet {}", uri);
Expand All @@ -105,23 +83,22 @@ protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResp
}

StringBuilder html = new StringBuilder();
html.append("<html><head><title>").append(HtmlEscape.escapeHtml4(BINDING_NAME)).append("</title><head><body>");
html.append("<h1>").append(HtmlEscape.escapeHtml4(BINDING_NAME)).append("</h1>");

synchronized (accountHandlers) {
if (accountHandlers.isEmpty()) {
html.append("No Account thing created.");
} else {
for (Thing accountHandler : accountHandlers) {
String url = URLEncoder.encode(accountHandler.getUID().getId(), StandardCharsets.UTF_8);
html.append("<a href='./").append(url).append(" '>")
.append(HtmlEscape.escapeHtml4(accountHandler.getLabel())).append("</a><br>");
}
html.append("<html><head><title>").append(BINDING_NAME).append("</title><head><body>");
html.append("<h1>").append(BINDING_NAME).append("</h1>");

Collection<AccountHandler> accountHandlers = handlerFactory.getAccountHandlers();
if (accountHandlers.isEmpty()) {
html.append("No Account thing created.");
} else {
for (AccountHandler accountHandler : accountHandlers) {
String url = URLEncoder.encode(accountHandler.getThing().getUID().getId(), StandardCharsets.UTF_8);
html.append("<a href='./").append(url).append(" '>")
.append(HtmlEscape.escapeHtml4(accountHandler.getThing().getLabel())).append("</a><br>");
}
}
html.append("</body></html>");

resp.addHeader("content-type", "text/html;charset=UTF-8");
resp.addHeader(HttpHeader.CONTENT_TYPE.asString(), MimeTypes.Type.TEXT_HTML_UTF_8.asString());
try {
resp.getWriter().write(html.toString());
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
*/
package org.smarthomej.binding.amazonechocontrol.internal;

import static org.smarthomej.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.BINDING_ID;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -41,8 +43,7 @@ public class ConsoleCommandExtension extends AbstractConsoleCommandExtension {

@Activate
public ConsoleCommandExtension(@Reference AmazonEchoControlHandlerFactory handlerFactory) {
super("amazonechocontrol", "Manage the AmazonEchoControl account");

super(BINDING_ID, "Manage the AmazonEchoControl account");
this.handlerFactory = handlerFactory;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.State;
import org.smarthomej.binding.amazonechocontrol.internal.dto.JsonDevices.Device;
import org.smarthomej.binding.amazonechocontrol.internal.dto.DeviceTO;

/**
* The {@link AmazonHandlerCallback} is used from ChannelHandlers to communicate
Expand All @@ -32,6 +32,6 @@ public interface AmazonHandlerCallback {

void updateChannelState(String channelId, State state);

void startAnnouncement(Device device, String speak, String bodyText, @Nullable String title,
void startAnnouncement(DeviceTO device, String speak, String bodyText, @Nullable String title,
@Nullable Integer volume) throws IOException, URISyntaxException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.openhab.core.types.Command;
import org.smarthomej.binding.amazonechocontrol.internal.ConnectionException;
import org.smarthomej.binding.amazonechocontrol.internal.connection.Connection;
import org.smarthomej.binding.amazonechocontrol.internal.dto.JsonDevices.Device;
import org.smarthomej.binding.amazonechocontrol.internal.dto.DeviceTO;

/**
* The {@link ChannelHandler} is the base class for all channel handlers
Expand All @@ -27,6 +27,6 @@
@NonNullByDefault
public interface ChannelHandler {

boolean tryHandleCommand(Device device, Connection connection, String channelId, Command command)
boolean tryHandleCommand(DeviceTO device, Connection connection, String channelId, Command command)
throws ConnectionException;
}
Loading

0 comments on commit 160374f

Please sign in to comment.