diff options
author | Roger Zanoni <rzanoni@igalia.com> | 2023-12-28 20:07:05 -0300 |
---|---|---|
committer | Jan-Simon Moeller <jsmoeller@linuxfoundation.org> | 2024-01-29 12:07:20 +0000 |
commit | c323ab8fde212120d8d1914d453afeb55b3576e5 (patch) | |
tree | 2f3565da1e623d69297b00d2a5e1e2b261692810 /src/js/kuksa.js | |
parent | 5f1b6075982b872b5db4e2195e53d19529278d5c (diff) |
Update HVAC app to use grpc-web instead of websockets
Adapt the HTML5 applications to use kuksa.val service
Bug-AGL: SPEC-4599
Signed-off-by: Roger Zanoni <rzanoni@igalia.com>
Change-Id: I3e36a6c08041db8fb59fd7f20497c1c156bbb2f7
Diffstat (limited to 'src/js/kuksa.js')
-rw-r--r-- | src/js/kuksa.js | 232 |
1 files changed, 169 insertions, 63 deletions
diff --git a/src/js/kuksa.js b/src/js/kuksa.js index 9e9cc22..8542dcb 100644 --- a/src/js/kuksa.js +++ b/src/js/kuksa.js @@ -16,108 +16,214 @@ import { v4 as uuidv4 } from 'uuid'; -const DEFAULT_TARGET = "wss://localhost:8090"; +const DEFAULT_TARGET = "https://localhost:8888"; // TODO: use an application token when needed // currently using https://github.com/eclipse/kuksa.val/blob/master/kuksa_certificates/jwt/super-admin.json.token const TEST_TOKEN = - 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJrdWtzYS52YWwiLCJpc3MiOiJFY2xpcHNlIEtVS1NBIERldiIsImFkbWluIjp0cnVlLCJtb2RpZnlUcmVlIjp0cnVlLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTc2NzIyNTU5OSwia3Vrc2EtdnNzIjp7IioiOiJydyJ9fQ.p2cnFGH16QoQ14l6ljPVKggFXZKmD-vrw8G6Vs6DvAokjsUG8FHh-F53cMsE-GDjyZH_1_CrlDCnbGlqjsFbgAylqA7IAJWp9_N6dL5p8DHZTwlZ4IV8L1CtCALs7XVqvcQKHCCzB63Y8PgVDCAqpQSRb79JPVD4pZwkBKpOknfEY5y9wfbswZiRKdgz7o61_oFnd-yywpse-23HD6v0htThVF1SuGL1PuvGJ8p334nt9bpkZO3gaTh1xVD_uJMwHzbuBCF33_f-I5QMZO6bVooXqGfe1zvl3nDrPEjq1aPulvtP8RgREYEqE6b2hB8jouTiC_WpE3qrdMw9sfWGFbm04qC-2Zjoa1yYSXoxmYd0SnliSYHAad9aXoEmFENezQV-of7sc-NX1-2nAXRAEhaqh0IRuJwB4_sG7SvQmnanwkz-sBYxKqkoFpOsZ6hblgPDOPYY2NAsZlYkjvAL2mpiInrsmY_GzGsfwPeAx31iozImX75rao8rm-XucAmCIkRlpBz6MYKCjQgyRz3UtZCJ2DYF4lKqTjphEAgclbYZ7KiCuTn9HualwtEmVzHHFneHMKl7KnRQk-9wjgiyQ5nlsVpCCblg6JKr9of4utuPO3cBvbjhB4_ueQ40cpWVOICcOLS7_w0i3pCq1ZKDEMrYDJfz87r2sU9kw1zeFQk'; + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJsb2NhbCBkZXYiLCJpc3MiOiJjcmVhdGVUb2tlbi5weSIsImF1ZCI6WyJrdWtzYS52YWwiXSwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3NjcyMjU1OTksInNjb3BlIjoiYWN0dWF0ZSBwcm92aWRlIn0.x-bUZwDCC663wGYrWCYjQZwQWhN1CMuKgxuIN5dUF_izwMutiqF6Xc-tnXgZa93BbT3I74WOMk4awKHBUSTWekGs3-qF6gajorbat6n5180TOqvNu4CXuIPZN5zpngf4id3smMkKOT699tPnSEbmlkj4vk-mIjeOAU-FcYA-VbkKBTsjvfFgKa2OdB5h9uZARBg5Rx7uBN3JsH1I6j9zoLid184Ewa6bhU2qniFt5iPsGJniNsKsRrrndN1KzthO13My44s56yvwSHIOrgDGbXdja_eLuOVOq9pHCjCtorPScgEuUUE4aldIuML-_j397taNP9Y3VZYVvofEK7AuiePTbzwxrZ1RAjK74h1-4ued3A2gUTjr5BsRlc9b7eLZzxLJkrqdfGAzBh_rtrB7p32TbvpjeFP30NW6bB9JS43XACUUm_S_RcyI7BLuUdnFyQDQr6l6sRz9XayYXceilHdCxbAVN0HVnBeui5Bb0mUZYIRZeY8k6zcssmokANTD8ZviDMpKlOU3t5AlXJ0nLkgyMhV9IUTwPUv6F8BTPc-CquJCUNbTyo4ywTSoODWbm3PmQ3Y46gWF06xqnB4wehLscBdVk3iAihQp3tckGhMnx5PI_Oy7utIncr4pRCMos63TnBkfrl7d43cHQTuK0kO76EWtv4ODEHgLvEAv4HA'; var kuksa_context = { authToken: TEST_TOKEN, - socket: undefined, + client: undefined, target: DEFAULT_TARGET, + subscribe_entries: [], + subscribe_stream: null, + locks: new Map() } var pathToHandler = null; -function logReceivedMessage(data) { - console.log('Received message:', data) +function updateVehicleInfo(path, dp) { + if (!pathToHandler.has(path)) { + console.log('Handler not found for', path); + return; + } + + var handler = pathToHandler.get(path); + handler.update(path, dp) } -function logConnectionStatus(status, event) { - console.log('Connection status:', status); +function send(action, values) { } -function kuksaws_onopen(event) { - logConnectionStatus('Connected.', event); - - authorize(); - subscribe(PATHS.leftAirDistribution); - subscribe(PATHS.leftFanSpeed); - subscribe(PATHS.leftSeatWarmer); - subscribe(PATHS.rightSeatWarmer); - subscribe(PATHS.leftSeatTemperature); - subscribe(PATHS.rightSeatTemperature); - subscribe(PATHS.airConditioning); - subscribe(PATHS.recirculation); - subscribe(PATHS.frontDefroster); - subscribe(PATHS.rearDefroster); +function add_subscribe_entry(path) { + console.log('Adding subscribe entry for ' + path + '...') + var entry = new VAL.SubscribeEntry(); + entry.setPath(path); + entry.setView(TYPES.View.VIEW_ALL); + entry.addFields(TYPES.Field.FIELD_PATH); + entry.addFields(TYPES.Field.FIELD_VALUE); + kuksa_context.subscribe_entries.push(entry); } -function kuksaws_onerror(event) { - logConnectionStatus('Failed to connect:', event); +function subscribe() { + if (kuksa_context.client == undefined) { + console.log("Client not initialized."); + return; + } + var metadata = {'authorization': 'Bearer ' + kuksa_context.authToken }; + + var request = new VAL.SubscribeRequest(); + for (var i in kuksa_context.subscribe_entries) { + var entry = kuksa_context.subscribe_entries[i]; + entry.setView(TYPES.View.VIEW_CURRENT_VALUE); + request.addEntries(entry); + } + + kuksa_context.subscribe_stream = kuksa_context.client.subscribe(request, metadata); + + kuksa_context.subscribe_stream.on('data', function(response) { + var updates = response.getUpdatesList(); + for (var i in updates) { + var update = updates[i]; + var entry = update.getEntry(); + var path = entry.getPath(); + var dp = entry.getValue(); + + if (!(entry && path && dp)) { + continue; + } + + lock(path); + updateVehicleInfo(path, dp); + unlock(path); + } + }); + + kuksa_context.subscribe_stream.on('error', function(error) { + console.log("Error code: " + error.code + " message: " + error.message); + // if an error happens here, the databroker will drop the subscriber, so + // we need to subscribe again + subscribe(); + }); } -function kuksaws_onmessage(event) { - logReceivedMessage(event.data); +// TODO: investigate why an empty response is always being returned on the +// response +export function get(path) { + if (kuksa_context.client == undefined) { + console.log("Client not initialized."); + return; + } + if (isLocked(path)) { + return; + } - var jsonData = JSON.parse(event.data); + var metadata = {'authorization': 'Bearer ' + kuksa_context.authToken }; + + var request = new VAL.GetRequest(); + var entry = new VAL.EntryRequest(); + entry.setPath(path); + entry.setView(TYPES.View.VIEW_ALL); + entry.addFields(TYPES.Field.FIELD_METADATA); + entry.addFields(TYPES.Field.FIELD_VALUE); + request.addEntries(entry); + + kuksa_context.client.get(request, metadata, function(error, response) { + if (error) { + console.log("Get error, code: " + error.code); + return; + } + if (!response) { + return; + } + var entries = response.getEntriesList(); + for (var i in entries) { + var entry = entries[i]; + var path = entry.getPath(); + var dp = entry.getValue(); + + if (!(entry && path && dp)) { + continue; + } + lock(path); + updateVehicleInfo(path, dp); + unlock(path); + } + }); +} - if (jsonData.action == 'get' || - jsonData.action =='subscription') { - updateVehicleInfo(jsonData); +export function set(path, dp) { + if (kuksa_context.client == undefined) { + console.log("Client not initialized."); + return; + } + if (isLocked(path)) { + return; } + lock(path); + + var metadata = {'authorization': 'Bearer ' + kuksa_context.authToken }; + + var entry = new TYPES.DataEntry(); + entry.setPath(path); + entry.setValue(dp); + + var update = new VAL.EntryUpdate(); + update.addFields(TYPES.Field.FIELD_PATH); + update.addFields(TYPES.Field.FIELD_VALUE); + update.setEntry(entry); + + var request = new VAL.SetRequest(); + request.addUpdates(update); + + kuksa_context.client.set(request, metadata, function(error, response) { + // don't unlock updates here, only when we get a value from + // the subscription updates + }); } -function updateVehicleInfo(message) { - var value = message.data.dp.value; - var path = message.data.path; +export function init(handlers) { + console.log("Initializing kuka-val module..."); + pathToHandler = new Map(handlers); + pathToHandler.forEach(function(handler, path) { + add_subscribe_entry(path); + }); - if (!pathToHandler.has(path)) { - console.log('Handler not found for', path); - return; + if (kuksa_context.client == undefined) { + console.log("Creating kuksa-val client..."); + kuksa_context.client = new VAL_WEB.VALClient(kuksa_context.target); + + subscribe(); } +} - var handler = pathToHandler.get(path); - handler.update(path, value) +export function setInt32(path, value) { + var dp = new TYPES.Datapoint(); + dp.setInt32(value); + set(path, dp); } -function send(action, values) { - var uuid = uuidv4(); - var data = Object.assign({ - action: action, - tokens: kuksa_context.authToken, - requestId: uuid, - }, values); - var message = JSON.stringify(data); - console.log('Sent message:', message); - kuksa_context.socket.send(message); - return uuid; +export function setUInt32(path, value) { + var dp = new TYPES.Datapoint(); + dp.setUint32(value); + set(path, dp); } -function subscribe(path) { - return send('subscribe', { path: path }); +export function setBool(path, value) { + var dp = new TYPES.Datapoint(); + dp.setBool(value); + set(path, dp); } -function authorize() { - return send('authorize'); +export function setString(path, value) { + var dp = new TYPES.Datapoint(); + dp.setString(value); + set(path, dp); } -export function get(path) { - return send('get', { path: path }); +export function lock(path) { + kuksa_context.locks[path] = true; } -export function set(path, value) { - return send('set', { path: path, value: value }); +export function unlock(path) { + kuksa_context.locks[path] = false; } -export function init(handlers) { - pathToHandler = new Map(handlers); - if (kuksa_context.socket == undefined) { - kuksa_context.socket = new WebSocket(kuksa_context.target); - kuksa_context.socket.onopen = kuksaws_onopen; - kuksa_context.socket.onerror = kuksaws_onerror; - kuksa_context.socket.onmessage = kuksaws_onmessage; +export function isLocked(path) { + if (!kuksa_context.locks.has(path)) { + kuksa_context.locks[path] = false; } + return kuksa_context.locks[path]; } |