diff options
Diffstat (limited to 'htdocs')
-rw-r--r-- | htdocs/AFB.js | 3 | ||||
-rw-r--r-- | htdocs/CMakeLists.txt | 33 | ||||
-rw-r--r-- | htdocs/amazon.js | 323 | ||||
-rw-r--r-- | htdocs/binding.js | 88 | ||||
-rw-r--r-- | htdocs/index.html | 61 |
5 files changed, 36 insertions, 472 deletions
diff --git a/htdocs/AFB.js b/htdocs/AFB.js index b07efc5..2cf3aec 100644 --- a/htdocs/AFB.js +++ b/htdocs/AFB.js @@ -210,7 +210,8 @@ var AFB_websocket; /*********************************************/ return { context: AFB_context, - ws: AFB_websocket + ws: AFB_websocket, + url: urlws }; }; diff --git a/htdocs/CMakeLists.txt b/htdocs/CMakeLists.txt deleted file mode 100644 index 7aa0ce1..0000000 --- a/htdocs/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -########################################################################### -# Copyright 2015, 2016, 2017 IoT.bzh -# -# author: Fulup Ar Foll <fulup@iot.bzh> -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -########################################################################### - - - -################################################## -# HTML Testing Files -################################################## -PROJECT_TARGET_ADD(htdocs) - - file(GLOB SOURCE_FILES "*.html" "*.js" "*.jpg" "*.css" "assets") - - add_input_files("${SOURCE_FILES}") - - SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES - LABELS "HTDOCS" - OUTPUT_NAME ${TARGET_NAME} - ) diff --git a/htdocs/amazon.js b/htdocs/amazon.js deleted file mode 100644 index 05704f1..0000000 --- a/htdocs/amazon.js +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0/ - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -AMAZON = function() { - -var afb; -var alexaWs; - -var base = { - base: "api", - token: "HELLO", -}; - -// GUID generator for generating device serial number. -function guid() { - function s4() { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); - } - return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); -} - -/*********************************************/ -/**** ****/ -/**** AMAZON_cbl ****/ -/**** ****/ -/*********************************************/ -var AMAZON_Cbl; -{ - const amazonHostUrl = "https://api.amazon.com"; - const amazonCodePairUrl = amazonHostUrl + "/auth/O2/create/codepair"; - const amazonTokenUrl = amazonHostUrl + "/auth/O2/token"; - const deviceSerialNumber = guid(); - var clientID = localStorage.getItem("client_id"); - var productID = localStorage.getItem("product_id"); - var alexaVAAddress = localStorage.getItem("alexa_va_address"); - var alexaVAConnected = false; - var alexaVAAddressInput; - var clientIDInput; - var productIDInput; - - AMAZON_Cbl = function() { - // Alexa VA Address - const alexaVAAddressInput = document.getElementById('alexa-va-address'); - alexaVAAddress = alexaVAAddressInput.value; - connectToAlexaVA(alexaVAAddress); - - alexaVAAddressInput.addEventListener("change",(evt) => { - var newAlexaVAAddress = alexaVAAddressInput.value; - if (alexaVAAddress != newAlexaVAAddress) { - connectToAlexaVA(newAlexaVAAddress); - localStorage.setItem("alexa_va_address", newAlexaVAAddress); - } - }); - - // Client ID - const clientIDInput = document.getElementById('client-id'); - clientIDInput.addEventListener("change",(evt) => { - var newClientID = clientIDInput.value; - if (clientID != newClientID) { - clientID = newClientID; - localStorage.setItem("client_id", newClientID); - } - }); - - // Product ID - const productIDInput = document.getElementById('product-id'); - productIDInput.addEventListener("change",(evt) => { - var newProductID = productIDInput.value; - if (productID != newProductID) { - productID = newProductID; - localStorage.setItem("product_id", newProductID); - } - }); - } - - function connectToAlexaVA(address) { - base.host = address; - afb = new AFB(base, "secret"); - - function onopen() { - console.log("Connected to Alexa VA"); - alexaVAConnected = true; - } - - function onabort() { - console.log("Alexa VA connection aborted."); - alexaVAConnected = false; - } - - alexaWs = new afb.ws(onopen, onabort); - } - - function sendRequest(httpReq, paramsJson, url, responseCb) { - httpReq.onreadystatechange = responseCb; - var paramsQueryString = Object.keys(paramsJson).map(key => key + '=' + paramsJson[key]).join('&'); - httpReq.open("POST", url, true); - httpReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - httpReq.send(paramsQueryString); - } - - //********************************************** - // Generic function to call VA binder - //*********************************************** - function callVABinder(voiceAgent, verb, query) { - console.log(voiceAgent.api, verb, query); - - // ws.call return a Promise - return alexaWs.call(voiceAgent.api + '/' + verb, query) - .then(function (res) { - log.reply(res); - count++; - return res; - }) - .catch(function (err) { - log.reply(err); - count++; - throw err; - }); - }; - - function updateAccessToken(voiceAgent, tokenResponseJson) { - if (alexaVAAddress === undefined || alexaVAAddress === null) { - console.log("No Alexa VA. So not updating the access token."); - return; - } - - // store the access and refresh tokens. - if (typeof(Storage) !== "undefined") { - localStorage.setItem("access_token", tokenResponseJson["access_token"]); - localStorage.setItem("refresh_token", tokenResponseJson["refresh_token"]); - } - - // Set the auth token - if (alexaVAConnected) { - // Set new token - const query = {"token": tokenResponseJson["access_token"]}; - callVABinder(voiceAgent, 'setAuthToken', query); - } - - // Refresh the token as soon as it expires. - setTimeout(refreshToken, tokenResponseJson["expires_in"] * 1000); - } - - function refreshToken(voiceAgent) { - if (voiceAgent == "undefined") { - console.log("Error: VoiceAgent undefined"); - return; - } - - var refreshToken = localStorage.getItem("refresh_token"); - if (refreshToken == null) { - console.log("Error: No refresh token"); - return; - } - - var paramsJson = { - "grant_type":"refresh_token", - "refresh_token":refreshToken, - "client_id":clientID, - }; - - const tokenRefreshReq = new XMLHttpRequest(); - sendRequest(tokenRefreshReq, paramsJson, amazonTokenUrl, function() { - if (tokenRefreshReq.readyState == 4) { - if (tokenRefreshReq.status == 200) { - console.log("Got access token " + tokenRefreshReq.responseText); - var tokenResponseJson = JSON.parse(tokenRefreshReq.responseText); - updateAccessToken(voiceAgent, tokenResponseJson); - } else { - console.log("Failed to refresh access token: " + tokenRefreshReq.responseText); - } - } - }); - } - - function displayUserCodeAndURI(authResponseJson) { - const modal = document.getElementById('login-with-amazon'); - const cblStatusDiv = document.createElement("div"); - const cblStatusMsg = document.createElement("p"); - const blank = "_blank"; - - var cblPage = authResponseJson["verification_uri"] + "?cbl-code=" + authResponseJson["user_code"] - var msg = "To use Alexa,you must sign in to Amazon.<br> Go to " + - "<a href=" + cblPage + " target="+ blank+ " >" + - cblPage + "</a>"; - cblStatusMsg.innerHTML = msg; - cblStatusDiv.appendChild(cblStatusMsg); - modal.appendChild(cblStatusDiv); - - const closeBtn = document.createElement("button"); - closeBtn.addEventListener('click', (evt) => { - modal.close(); - }); - closeBtn.style = "margin: 10px"; - closeBtn.innerHTML = "Close"; - modal.appendChild(closeBtn); - } - - function hideLoginUI() { - const loginDiv = document.getElementById('login-area'); - loginDiv.style.display = "none"; - } - - function login(voiceAgent) { - if (voiceAgent == undefined) { - console.log("Error: VoiceAgent undefined"); - return; - } - - const modal = document.getElementById('login-with-amazon'); - const submitBtn = document.getElementById('submit-btn'); - const cancelBtn = document.getElementById('cancel-btn'); - submitBtn.addEventListener('click', (evt) => { - console.log("Alexa Destination address set to: " + alexaVAAddress); - startLoginProcess(voiceAgent); - }); - - cancelBtn.addEventListener('click', (evt) => { - modal.close(); - }); - - const alexaVAAddressInput = document.getElementById('alexa-va-address'); - alexaVAAddressInput.value = alexaVAAddress; - - const clientIDInput = document.getElementById('client-id'); - clientIDInput.value = clientID; - - const productIDInput = document.getElementById('product-id'); - productIDInput.value = productID; - - modal.showModal(); - } - - function startLoginProcess(voiceAgent) { - if (clientID == null || productID == null || alexaVAAddress == null) { - console.log("Required information missing to start login process."); - return; - } - - var reqJson = { - "response_type": "device_code", - "client_id": clientID, - "scope":"alexa:all", - "scope_data": JSON.stringify({ - "alexa:all": { - "productID":productID, - "productInstanceAttributes" : { - "deviceSerialNumber": deviceSerialNumber - } - } - }) - }; - - const authReq = new XMLHttpRequest(); - var tokenUrl = amazonTokenUrl; - sendRequest(authReq, reqJson, amazonCodePairUrl, function() { - if (authReq.readyState == 4) { - if (authReq.status == 200) { - var authResponse = JSON.parse(authReq.responseText); - console.log("Got auth codepair " + authReq.responseText); - hideLoginUI(); - displayUserCodeAndURI(authResponse); - var maxTokenReqCnt = authResponse["expires_in"] / authResponse["interval"]; - var tokenReqFuncId = setTimeout(function tokenReqFunc() { - var reqJson = { - "grant_type":"device_code", - "device_code":authResponse["device_code"], - "user_code":authResponse["user_code"] - }; - const tokenReq = new XMLHttpRequest(); - sendRequest(tokenReq, reqJson, tokenUrl, function() { - if (tokenReq.readyState == 4) { - if (tokenReq.status == 200) { - console.log("Got access token " + tokenReq.responseText); - var tokenResponseJson = JSON.parse(tokenReq.responseText); - updateAccessToken(voiceAgent, tokenResponseJson); - } - else { - maxTokenReqCnt--; - console.log("Retrying... " + tokenReq.responseText); - setTimeout(tokenReqFunc, authResponse["interval"] * 1000); - } - } - }); - }, authResponse["interval"] * 1000); - // Cancel if max token request attempts are reached. - if (maxTokenReqCnt == 0) { - console.log("Reached max token request attemps limit."); - } - } else { - console.log(authReq.status); - } - } - }); - } - - AMAZON_Cbl.prototype = { - login: login, - refreshToken: refreshToken, - }; -} -/*********************************************/ -/**** ****/ -/**** ****/ -/**** ****/ -/*********************************************/ -return { - cbl: AMAZON_Cbl -}; -};
\ No newline at end of file diff --git a/htdocs/binding.js b/htdocs/binding.js index 7e7439b..c5ceb06 100644 --- a/htdocs/binding.js +++ b/htdocs/binding.js @@ -1,18 +1,14 @@ -var afb = new AFB("api", "mysecret"); +var afbVshlCore; var ws; var evtIdx = 0; var count = 0; - -var amazon = new AMAZON(); -var amazonCbl; - //********************************************** // Logger //********************************************** var log = { - command: function (api, verb, query) { + command: function (url, api, verb, query) { console.log("subscribe api=" + api + " verb=" + verb + " query=", query); - var question = afb.url + "/" + api + "/" + verb + "?query=" + JSON.stringify(query); + var question = url + "/" + api + "/" + verb + "?query=" + JSON.stringify(query); log._write("question", count + ": " + log.syntaxHighlight(question)); }, @@ -67,8 +63,8 @@ var log = { //********************************************** // Generic function to call binder //*********************************************** -function callbinder(api, verb, query) { - log.command(api, verb, query); +function callbinder(url, api, verb, query) { + log.command(url, api, verb, query); // ws.call return a Promise return ws.call(api + '/' + verb, query) @@ -84,10 +80,15 @@ function callbinder(api, verb, query) { }); }; + //********************************************** -// Init - establish Websocket connection +// connect - establish Websocket connection //********************************************** -function init(elemID, api, verb, query) { +function connect(elemID, api, verb, query) { + connectVshlCore(elemID, api, verb, query); +} + +function connectVshlCore(elemID, api, verb, query) { function onopen() { document.getElementById("main").style.visibility = "visible"; @@ -104,7 +105,15 @@ function init(elemID, api, verb, query) { document.getElementById("connected").style.background = "red"; } - ws = new afb.ws(onopen, onabort); + var urlparams = { + base: "api", + token: "HELLO", + }; + const vshlCoreAddressInput = document.getElementById('vshl-core-address'); + urlparams.host = vshlCoreAddressInput.value; + + afbVshlCore = new AFB(urlparams, "HELLO"); + ws = new afbVshlCore.ws(onopen, onabort); } function clearPre(preId) { @@ -120,11 +129,11 @@ function fetchAndRenderVoiceAgents() { agentsDiv.removeChild(agentsDiv.firstChild); } - const api = 'vshl'; + const api = 'vshl-core'; const verb = 'enumerateVoiceAgents'; const query = {}; - log.command(api, verb, query); + log.command(afbVshlCore.url, api, verb, query); return ws.call(api + '/' + verb, query) .then(function (res) { @@ -155,7 +164,7 @@ function addVoiceAgent(containerDiv, voiceAgent, isDefault) { const setDefaultBtn = document.createElement("button"); setDefaultBtn.addEventListener('click', (evt) => { const query = {"id": voiceAgent.id}; - callbinder('vshl', 'setDefaultVoiceAgent', query); + callbinder(afbVshlCore.url, 'vshl-core', 'setDefaultVoiceAgent', query); fetchAndRenderVoiceAgents(); }); setDefaultBtn.innerHTML = 'SetDefault'; @@ -169,24 +178,6 @@ function addVoiceAgent(containerDiv, voiceAgent, isDefault) { subscribeBtn.innerHTML = 'Subscribe'; agentDiv.appendChild(subscribeBtn); - // Login implementation for Alexa Voice Agent - if (voiceAgent.name == "Alexa") { - amazonCbl = new amazon.cbl(); - if (typeof(Storage) !== "undefined" && - localStorage.getItem("access_token") !== null && - localStorage.getItem("refresh_token") !== null) { - amazonCbl.refreshToken(voiceAgent); - } else { - const loginWithAmazonBtn = document.createElement("button"); - loginWithAmazonBtn.addEventListener('click', (evt) => { - loginWithAmazonBtn.style.visibility = "hidden"; - amazonCbl.login(voiceAgent); - }); - loginWithAmazonBtn.innerHTML = 'Login With Amazon!!'; - agentDiv.appendChild(loginWithAmazonBtn); - } - } - containerDiv.appendChild(agentDiv); } @@ -210,7 +201,7 @@ function showAgentEventChooserDialog(voiceAgentId) { if (connectionState) query.events.push('voice_connectionstate_event'); - callbinder('vshl', 'subscribe', query); + callbinder(afbVshlCore.url, 'vshl-core', 'subscribe', query); modal.close(); }); @@ -218,31 +209,6 @@ function showAgentEventChooserDialog(voiceAgentId) { modal.showModal(); } -function showTemplateUIEventChooserDialog() { - const modal = document.getElementById('templateui-event-chooser'); - const subscribeBtn = document.getElementById('templateui-subscribe-btn'); - - subscribeBtn.addEventListener('click', (evt) => { - const renderTemplate = document.getElementById('render_template').checked; - const clearTemplate = document.getElementById('clear_template').checked; - const renderPlayerInfo = document.getElementById('render_player_info').checked; - const clearPlayerInfo = document.getElementById('clear_player_info').checked; - - const query = {"actions":[]}; - - if (renderTemplate) - query.actions.push('render_template'); - if (clearTemplate) - query.actions.push('clear_template'); - if (renderPlayerInfo) - query.actions.push('render_player_info'); - if (clearPlayerInfo) - query.actions.push('clear_player_info'); - - callbinder('vshl', 'guiMetadata/subscribe', query); - modal.close(); - }); - - // makes modal appear (adds `open` attribute) - modal.showModal(); +function startListening() { + callbinder(afbVshlCore.url, 'vshl-core', 'startListening', {}); }
\ No newline at end of file diff --git a/htdocs/index.html b/htdocs/index.html index bf5f840..4e10f66 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -1,22 +1,22 @@ <html> <head> - <title>VSHL API Test</title> + <title>VSHL CORE API Test</title> <link rel="stylesheet" href="binding.css"> <script type="text/javascript" src="AFB.js"></script> <script type="text/javascript" src="amazon.js"></script> <script type="text/javascript" src="binding.js"></script> </head> -<body class="page-content" onload="init()"> +<body class="page-content" onload="connect()"> <h1>Voice Service High Level API Tester</h1> <button id="connected" onclick="init()">Binder WS Fail</button> <button id="monitoring" onclick="window.open('/monitoring/monitor.html','_monitor_ctl')">Debug/Monitoring</a> </button> - <button onclick="clearPre('question'); clearPre('output'); clearPre('outevt');">Clear</button> - + <button onclick="clearPre('question'); clearPre('output'); clearPre('outevt');">Clear</button> <br><br> + VSHL CORE URL: <input type="text" id="vshl-core-address" value="localhost:1111" onchange="connectVshlCore()"> <br><br> <br> <br> @@ -43,60 +43,13 @@ </footer> </dialog> - <dialog id="templateui-event-chooser"> - <h3 class="dialogheader">Subscribe to the following GUI Metadata Messages</h3> - <div> - <ol> - <li> - <input type="checkbox" id="render_template" checked> - <label>render_template</label> - </li> - <li> - <input type="checkbox" id="clear_template" checked> - <label>clear_template</label> - </li> - <li> - <input type="checkbox" id="render_player_info" checked> - <label>render_player_info</label> - </li> - <li> - <input type="checkbox" id="clear_player_info" checked> - <label>clear_player_info</label> - </li> - </ol> - </div> - <footer> - <button id="templateui-subscribe-btn" type="button" style="margin: 10px">Subscribe</button> - </footer> - </dialog> - - <dialog id="login-with-amazon"> - <h3 class="dialogheader">Login with Amazon !!</h3> - <div id="login-area"> - <div> - Alexa VA URL: <input type="text" id="alexa-va-address" value="localhost:1111"> <br><br> - Client ID : <input type="text" id="client-id"> <br><br> - Product ID : <input type="text" id="product-id"> <br><br> - To generate client and product ID, please register a new AVS product for - <i><b>Other devices and platforms</b></i> using instructions in - <a href="https://developer.amazon.com/docs/alexa-voice-service/register-a-product.html" target="_blank">this </a> - link.<br><br> - </div> - <footer id ="login-with-amazon-footer"> - <button id="submit-btn" type="button" style="margin: 10px">Login</button> - <button id="cancel-btn" type="button" style="margin: 10px">Cancel</button> - </footer> - </div> - </dialog> - <div id="top" class="row"> <div id='actions' class="col1"> <div> - <h2>VSHL APIs</h2> - <p>APIs that are voiceagent agnostic</p> - <button onclick="callbinder('vshl','startListening',{});">startListening</button> + <h2>VSHL CORE APIs</h2> + <p>Speech framework's VSHL Core APIs</p> + <button onclick="startListening()">startListening</button> <button onclick="fetchAndRenderVoiceAgents();">enumerateAgents</button> - <button onclick="showTemplateUIEventChooserDialog();">Subscribe to GUI Metadata</button> </div> <div id="agentsDiv"> |