Added its own http server for Google Assistant api
This commit is contained in:
parent
9bca47d566
commit
4a31b474c5
5 changed files with 80 additions and 55 deletions
|
|
@ -23,20 +23,44 @@ import java.util.Map;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import com.google.actions.api.smarthome.*;
|
import com.google.actions.api.smarthome.*;
|
||||||
|
import com.google.auth.oauth2.GoogleCredentials;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.home.graph.v1.DeviceProto;
|
import com.google.home.graph.v1.DeviceProto;
|
||||||
import com.google.protobuf.Struct;
|
import com.google.protobuf.Struct;
|
||||||
import com.google.protobuf.util.JsonFormat;
|
import com.google.protobuf.util.JsonFormat;
|
||||||
|
import se.hal.HalContext;
|
||||||
|
import se.hal.plugin.assistant.google.endpoint.AuthServlet;
|
||||||
|
import se.hal.plugin.assistant.google.endpoint.AuthTokenServlet;
|
||||||
|
import se.hal.plugin.assistant.google.endpoint.SmartHomeServlet;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
|
import zutil.net.http.HttpServer;
|
||||||
|
|
||||||
|
|
||||||
public class MySmartHomeApp extends SmartHomeApp {
|
public class SmartHomeImpl extends SmartHomeApp {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
private static final String PARAM_PORT = "assistant.google.api_port";
|
||||||
|
|
||||||
|
private HttpServer httpServer;
|
||||||
|
|
||||||
|
|
||||||
|
public SmartHomeImpl() {
|
||||||
|
try {
|
||||||
|
GoogleCredentials credentials = GoogleCredentials.fromStream(getClass().getResourceAsStream("assistant_google.conf"));
|
||||||
|
this.setCredentials(credentials);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.severe("couldn't load credentials");
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpServer = new HttpServer(HalContext.getIntegerProperty(PARAM_PORT));
|
||||||
|
httpServer.setPage(AuthServlet.ENDPOINT_URL, new AuthServlet(this));
|
||||||
|
httpServer.setPage(AuthTokenServlet.ENDPOINT_URL, new AuthTokenServlet(this));
|
||||||
|
httpServer.setPage(SmartHomeServlet.ENDPOINT_URL, new SmartHomeServlet(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SyncResponse onSync(SyncRequest syncRequest, Map<?, ?> headers) {
|
public SyncResponse onSync(SyncRequest syncRequest, Map<?, ?> headers) {
|
||||||
|
|
||||||
SyncResponse res = new SyncResponse();
|
SyncResponse res = new SyncResponse();
|
||||||
res.setRequestId(syncRequest.requestId);
|
res.setRequestId(syncRequest.requestId);
|
||||||
res.setPayload(new SyncResponse.Payload());
|
res.setPayload(new SyncResponse.Payload());
|
||||||
|
|
@ -44,7 +68,6 @@ public class MySmartHomeApp extends SmartHomeApp {
|
||||||
int numOfDevices = 0;
|
int numOfDevices = 0;
|
||||||
res.payload.devices = new SyncResponse.Payload.Device[numOfDevices];
|
res.payload.devices = new SyncResponse.Payload.Device[numOfDevices];
|
||||||
for (int i = 0; i < numOfDevices; i++) {
|
for (int i = 0; i < numOfDevices; i++) {
|
||||||
|
|
||||||
SyncResponse.Payload.Device.Builder deviceBuilder =
|
SyncResponse.Payload.Device.Builder deviceBuilder =
|
||||||
new SyncResponse.Payload.Device.Builder()
|
new SyncResponse.Payload.Device.Builder()
|
||||||
.setId(device.getId())
|
.setId(device.getId())
|
||||||
|
|
@ -41,29 +41,32 @@
|
||||||
package se.hal.plugin.assistant.google.endpoint;
|
package se.hal.plugin.assistant.google.endpoint;
|
||||||
|
|
||||||
import se.hal.intf.HalJsonPage;
|
import se.hal.intf.HalJsonPage;
|
||||||
|
import se.hal.plugin.assistant.google.SmartHomeImpl;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
|
import zutil.net.http.HttpPage;
|
||||||
import zutil.net.http.HttpPrintStream;
|
import zutil.net.http.HttpPrintStream;
|
||||||
import zutil.parser.DataNode;
|
import zutil.parser.DataNode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
public class FakeAuthServlet extends HalJsonPage {
|
public class AuthServlet implements HttpPage {
|
||||||
|
public static final String ENDPOINT_URL = "api/assistant/google/auth";
|
||||||
|
|
||||||
|
public AuthServlet(SmartHomeImpl smartHome) {}
|
||||||
|
|
||||||
public FakeAuthServlet() {
|
|
||||||
super("api/assistant/google/auth");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataNode jsonRespond(
|
public void respond(
|
||||||
HttpPrintStream out,
|
HttpPrintStream out,
|
||||||
HttpHeader headers,
|
HttpHeader headers,
|
||||||
Map<String,Object> session,
|
Map<String, Object> session,
|
||||||
Map<String,String> cookie,
|
Map<String, String> cookie,
|
||||||
Map<String,String> request) throws Exception {
|
Map<String, String> request) throws IOException {
|
||||||
|
|
||||||
StringBuilder redirectURL = new StringBuilder();
|
StringBuilder redirectURL = new StringBuilder();
|
||||||
redirectURL.append(URLDecoder.decode(request.get("redirect_uri"), StandardCharsets.UTF_8));
|
redirectURL.append(URLDecoder.decode(request.get("redirect_uri"), StandardCharsets.UTF_8));
|
||||||
|
|
@ -73,7 +76,5 @@ public class FakeAuthServlet extends HalJsonPage {
|
||||||
|
|
||||||
out.setStatusCode(302);
|
out.setStatusCode(302);
|
||||||
out.setHeader("Location", URLEncoder.encode("/login?responseurl=" + redirectURL.toString(), StandardCharsets.UTF_8));
|
out.setHeader("Location", URLEncoder.encode("/login?responseurl=" + redirectURL.toString(), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
return new DataNode(DataNode.DataType.Map);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,40 +40,47 @@
|
||||||
|
|
||||||
package se.hal.plugin.assistant.google.endpoint;
|
package se.hal.plugin.assistant.google.endpoint;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import se.hal.intf.HalJsonPage;
|
import se.hal.plugin.assistant.google.SmartHomeImpl;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
|
import zutil.net.http.HttpPage;
|
||||||
import zutil.net.http.HttpPrintStream;
|
import zutil.net.http.HttpPrintStream;
|
||||||
import zutil.parser.DataNode;
|
import zutil.parser.DataNode;
|
||||||
|
import zutil.parser.json.JSONWriter;
|
||||||
|
|
||||||
|
|
||||||
public class FakeTokenServlet extends HalJsonPage {
|
public class AuthTokenServlet implements HttpPage {
|
||||||
private static int secondsInDay = 86400;
|
private static final int SECONDS_IN_DAY = 86400;
|
||||||
|
public static final String ENDPOINT_URL = "api/assistant/google/auth_token";
|
||||||
|
|
||||||
|
|
||||||
|
public AuthTokenServlet(SmartHomeImpl smartHome) {}
|
||||||
|
|
||||||
public FakeTokenServlet() {
|
|
||||||
super("api/assistant/google/auth_token");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataNode jsonRespond(
|
public void respond(
|
||||||
HttpPrintStream out,
|
HttpPrintStream out,
|
||||||
HttpHeader headers,
|
HttpHeader headers,
|
||||||
Map<String,Object> session,
|
Map<String, Object> session,
|
||||||
Map<String,String> cookie,
|
Map<String, String> cookie,
|
||||||
Map<String,String> request) throws Exception {
|
Map<String, String> request) throws IOException {
|
||||||
|
|
||||||
String grantType = request.get("grant_type");
|
String grantType = request.get("grant_type");
|
||||||
|
|
||||||
DataNode jsonRes = new DataNode(DataNode.DataType.Map);
|
DataNode jsonRes = new DataNode(DataNode.DataType.Map);
|
||||||
jsonRes.set("token_type", "bearer");
|
jsonRes.set("token_type", "bearer");
|
||||||
jsonRes.set("access_token", "123access");
|
jsonRes.set("access_token", "123access");
|
||||||
jsonRes.set("expires_in", secondsInDay);
|
jsonRes.set("expires_in", SECONDS_IN_DAY);
|
||||||
|
|
||||||
if (grantType.equals("authorization_code")) {
|
if (grantType.equals("authorization_code")) {
|
||||||
jsonRes.set("refresh_token", "123refresh");
|
jsonRes.set("refresh_token", "123refresh");
|
||||||
}
|
}
|
||||||
|
|
||||||
return jsonRes;
|
out.setHeader("Content-Type", "application/json");
|
||||||
|
out.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
out.setHeader("Pragma", "no-cache");
|
||||||
|
out.println(JSONWriter.toString(jsonRes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,68 +41,56 @@
|
||||||
package se.hal.plugin.assistant.google.endpoint;
|
package se.hal.plugin.assistant.google.endpoint;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import com.google.actions.api.smarthome.SmartHomeApp;
|
import com.google.actions.api.smarthome.SmartHomeApp;
|
||||||
import com.google.auth.oauth2.GoogleCredentials;
|
import se.hal.plugin.assistant.google.SmartHomeImpl;
|
||||||
import se.hal.intf.HalJsonPage;
|
|
||||||
import se.hal.plugin.assistant.google.MySmartHomeApp;
|
|
||||||
import zutil.io.IOUtil;
|
import zutil.io.IOUtil;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
import zutil.net.http.HttpHeader;
|
import zutil.net.http.HttpHeader;
|
||||||
|
import zutil.net.http.HttpPage;
|
||||||
import zutil.net.http.HttpPrintStream;
|
import zutil.net.http.HttpPrintStream;
|
||||||
import zutil.parser.DataNode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles request received via HTTP POST and delegates it to your Actions app. See: [Request
|
* Handles request received via HTTP POST and delegates it to your Actions app. See: [Request
|
||||||
* handling in Google App
|
* handling in Google App
|
||||||
* Engine](https://cloud.google.com/appengine/docs/standard/java/how-requests-are-handled).
|
* Engine](https://cloud.google.com/appengine/docs/standard/java/how-requests-are-handled).
|
||||||
*/
|
*/
|
||||||
public class SmartHomeServlet extends HalJsonPage {
|
public class SmartHomeServlet implements HttpPage {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
private final SmartHomeApp actionsApp = new MySmartHomeApp();
|
public static final String ENDPOINT_URL = "api/assistant/google/smarthome";
|
||||||
|
|
||||||
{
|
private SmartHomeImpl smartHome;
|
||||||
try {
|
|
||||||
GoogleCredentials credentials =
|
|
||||||
GoogleCredentials.fromStream(getClass().getResourceAsStream("/smart-home-key.json"));
|
|
||||||
actionsApp.setCredentials(credentials);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.severe("couldn't load credentials");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SmartHomeServlet() {
|
public SmartHomeServlet(SmartHomeImpl smartHome) {
|
||||||
super("api/assistant/google/smarthome");
|
this.smartHome = smartHome;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DataNode jsonRespond(
|
public void respond(
|
||||||
HttpPrintStream out,
|
HttpPrintStream out,
|
||||||
HttpHeader headers,
|
HttpHeader headers,
|
||||||
Map<String,Object> session,
|
Map<String, Object> session,
|
||||||
Map<String,String> cookie,
|
Map<String, String> cookie,
|
||||||
Map<String,String> request) throws Exception {
|
Map<String, String> request) throws IOException {
|
||||||
|
|
||||||
String body = IOUtil.readContentAsString(headers.getInputStream());
|
String body = IOUtil.readContentAsString(headers.getInputStream());
|
||||||
logger.info("doPost, body = " + body);
|
logger.info("doPost, body = " + body);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String response = actionsApp.handleRequest(body, request).get();
|
String response = smartHome.handleRequest(body, request).get();
|
||||||
|
|
||||||
System.out.println("response = " + asJson);
|
out.setHeader("Content-Type", "application/json");
|
||||||
res.getWriter().write(asJson);
|
out.setHeader("Access-Control-Allow-Origin", "*");
|
||||||
res.getWriter().flush();
|
out.setHeader("Pragma", "no-cache");
|
||||||
} catch (ExecutionException | InterruptedException e) {
|
out.println(response);
|
||||||
logger.log(Level.SEVERE, "Failed to handle fulfillment request", e);
|
} catch (Exception e) {
|
||||||
|
logger.log(Level.SEVERE, "Was unable to handle SmartHome request.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"version": 0.1,
|
||||||
|
"name": "Hal-Assistant-Google",
|
||||||
|
"interfaces": [
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue