Added its own http server for Google Assistant api

This commit is contained in:
Ziver Koc 2020-09-05 13:38:53 +02:00
parent 9bca47d566
commit 4a31b474c5
5 changed files with 80 additions and 55 deletions

View file

@ -23,20 +23,44 @@ import java.util.Map;
import java.util.logging.Logger;
import com.google.actions.api.smarthome.*;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.gson.Gson;
import com.google.home.graph.v1.DeviceProto;
import com.google.protobuf.Struct;
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.net.http.HttpServer;
public class MySmartHomeApp extends SmartHomeApp {
public class SmartHomeImpl extends SmartHomeApp {
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
public SyncResponse onSync(SyncRequest syncRequest, Map<?, ?> headers) {
SyncResponse res = new SyncResponse();
res.setRequestId(syncRequest.requestId);
res.setPayload(new SyncResponse.Payload());
@ -44,7 +68,6 @@ public class MySmartHomeApp extends SmartHomeApp {
int numOfDevices = 0;
res.payload.devices = new SyncResponse.Payload.Device[numOfDevices];
for (int i = 0; i < numOfDevices; i++) {
SyncResponse.Payload.Device.Builder deviceBuilder =
new SyncResponse.Payload.Device.Builder()
.setId(device.getId())

View file

@ -41,29 +41,32 @@
package se.hal.plugin.assistant.google.endpoint;
import se.hal.intf.HalJsonPage;
import se.hal.plugin.assistant.google.SmartHomeImpl;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
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
protected DataNode jsonRespond(
public void respond(
HttpPrintStream out,
HttpHeader headers,
Map<String,Object> session,
Map<String,String> cookie,
Map<String,String> request) throws Exception {
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
StringBuilder redirectURL = new StringBuilder();
redirectURL.append(URLDecoder.decode(request.get("redirect_uri"), StandardCharsets.UTF_8));
@ -73,7 +76,5 @@ public class FakeAuthServlet extends HalJsonPage {
out.setStatusCode(302);
out.setHeader("Location", URLEncoder.encode("/login?responseurl=" + redirectURL.toString(), StandardCharsets.UTF_8));
return new DataNode(DataNode.DataType.Map);
}
}

View file

@ -40,40 +40,47 @@
package se.hal.plugin.assistant.google.endpoint;
import java.io.IOException;
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.HttpPage;
import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode;
import zutil.parser.json.JSONWriter;
public class FakeTokenServlet extends HalJsonPage {
private static int secondsInDay = 86400;
public class AuthTokenServlet implements HttpPage {
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
protected DataNode jsonRespond(
public void respond(
HttpPrintStream out,
HttpHeader headers,
Map<String,Object> session,
Map<String,String> cookie,
Map<String,String> request) throws Exception {
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
String grantType = request.get("grant_type");
DataNode jsonRes = new DataNode(DataNode.DataType.Map);
jsonRes.set("token_type", "bearer");
jsonRes.set("access_token", "123access");
jsonRes.set("expires_in", secondsInDay);
jsonRes.set("expires_in", SECONDS_IN_DAY);
if (grantType.equals("authorization_code")) {
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));
}
}

View file

@ -41,68 +41,56 @@
package se.hal.plugin.assistant.google.endpoint;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import com.google.actions.api.smarthome.SmartHomeApp;
import com.google.auth.oauth2.GoogleCredentials;
import se.hal.intf.HalJsonPage;
import se.hal.plugin.assistant.google.MySmartHomeApp;
import se.hal.plugin.assistant.google.SmartHomeImpl;
import zutil.io.IOUtil;
import zutil.log.LogUtil;
import zutil.net.http.HttpHeader;
import zutil.net.http.HttpPage;
import zutil.net.http.HttpPrintStream;
import zutil.parser.DataNode;
/**
* Handles request received via HTTP POST and delegates it to your Actions app. See: [Request
* handling in Google App
* 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 final SmartHomeApp actionsApp = new MySmartHomeApp();
public static final String ENDPOINT_URL = "api/assistant/google/smarthome";
{
try {
GoogleCredentials credentials =
GoogleCredentials.fromStream(getClass().getResourceAsStream("/smart-home-key.json"));
actionsApp.setCredentials(credentials);
} catch (Exception e) {
logger.severe("couldn't load credentials");
}
}
private SmartHomeImpl smartHome;
public SmartHomeServlet() {
super("api/assistant/google/smarthome");
public SmartHomeServlet(SmartHomeImpl smartHome) {
this.smartHome = smartHome;
}
@Override
protected DataNode jsonRespond(
public void respond(
HttpPrintStream out,
HttpHeader headers,
Map<String,Object> session,
Map<String,String> cookie,
Map<String,String> request) throws Exception {
Map<String, Object> session,
Map<String, String> cookie,
Map<String, String> request) throws IOException {
String body = IOUtil.readContentAsString(headers.getInputStream());
logger.info("doPost, body = " + body);
try {
String response = actionsApp.handleRequest(body, request).get();
String response = smartHome.handleRequest(body, request).get();
System.out.println("response = " + asJson);
res.getWriter().write(asJson);
res.getWriter().flush();
} catch (ExecutionException | InterruptedException e) {
logger.log(Level.SEVERE, "Failed to handle fulfillment request", e);
out.setHeader("Content-Type", "application/json");
out.setHeader("Access-Control-Allow-Origin", "*");
out.setHeader("Pragma", "no-cache");
out.println(response);
} catch (Exception e) {
logger.log(Level.SEVERE, "Was unable to handle SmartHome request.", e);
}
}
}

View file

@ -0,0 +1,6 @@
{
"version": 0.1,
"name": "Hal-Assistant-Google",
"interfaces": [
]
}