aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoger Zanoni <rzanoni@igalia.com>2022-11-02 10:16:03 +0100
committerRoger Zanoni <rzanoni@igalia.com>2022-11-02 14:51:15 +0100
commitb0c869c0461741413af9e6a24f6e156717b6362f (patch)
tree1e7efd54e4c426d1b50dd7676e1186857b88802f
parent6abbe876aee09b225af9329e28b4fa2cc4d4c220 (diff)
Adapt the demo to use kuksa.val service
- The "AUTO" element was removed because there's no compatible VSS signal. - Removed the indicators below the seats and now they work only to toggle the state of the seat warmer. - The air distribution buttons now work as a radio group as there is only one AirDistribution setting per cabin. Bug-AGL: SPEC-4599 Signed-off-by: Roger Zanoni <rzanoni@igalia.com> Change-Id: Ibfaa477a7c27627ac524f39dd809b7a2195c7c9f
-rw-r--r--package.json4
-rw-r--r--src/index.html37
-rw-r--r--src/index.js21
-rw-r--r--src/js/AFB.js215
-rw-r--r--src/js/buttons.js69
-rw-r--r--src/js/chair.js33
-rw-r--r--src/js/fan_speed.js16
-rw-r--r--src/js/kuksa.js123
-rw-r--r--src/js/paths.js31
-rw-r--r--src/js/seats.js51
-rw-r--r--src/js/temperature.js116
-rw-r--r--src/styles/landscape.scss10
-rw-r--r--src/styles/main.scss32
-rw-r--r--webpack.config.js7
14 files changed, 392 insertions, 373 deletions
diff --git a/package.json b/package.json
index ba76bd5..06006e6 100644
--- a/package.json
+++ b/package.json
@@ -31,5 +31,7 @@
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.8.1"
},
- "dependencies": {}
+ "dependencies": {
+ "uuid": "^9.0.0"
+ }
}
diff --git a/src/index.html b/src/index.html
index 88ea3fa..c8a5eed 100644
--- a/src/index.html
+++ b/src/index.html
@@ -27,7 +27,7 @@
</div>
<div class="fanSpeed">
<div class="fanSpeedContainer">
- <input id="FanSpeed" type="range" min="1" value="1" max="100" onchange="FANSPEED.set(this)">
+ <input id="FanSpeed" type="range" min="1" value="1" max="100" onchange="FANSPEED.set()">
<progress value="1" max="100"></progress>
</div>
<div class="label">
@@ -36,39 +36,26 @@
</div>
</div>
<div class="center">
- <a id="LeftChair" value="0" class="seat left item button" onclick="CHAIR.left(this)">
+ <a id="LeftChair" value="false" class="seat left item button" onclick="SEATS.left()">
<img class="off" src="../images/HMI_HVAC_Left_Chair_OFF.svg"/>
- <img class="one two" src="../images/HMI_HVAC_Left_Chair_ON.svg"/>
- <img class="off" src="../images/HMI_HVAC_ChairIndicator_OFF.svg"/>
- <img class="one" src="../images/HMI_HVAC_ChairIndicator_One.svg"/>
- <img class="two" src="../images/HMI_HVAC_ChairIndicator_Two.svg"/>
+ <img class="on" src="../images/HMI_HVAC_Left_Chair_ON.svg"/>
</a>
- <a key="ac" value="false" class="ac item button" onclick="BUTTON.toggle(this)">
+ <a id="ac" key="ac" value="false" class="ac item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_Inactive.svg"/>
<img class="enabled" src="../images/HMI_HVAC_Active.svg"/>
<div class="label">
A/C
</div>
</a>
- <a id="RightChair" value="0" class="seat right item button" onclick="CHAIR.right(this)">
+ <a id="RightChair" value="false" class="seat right item button" onclick="SEATS.right()">
<img class="off" src="../images/HMI_HVAC_Right_Chair_OFF.svg"/>
- <img class="one two" src="../images/HMI_HVAC_Right_Chair_ON.svg"/>
- <img class="off" src="../images/HMI_HVAC_ChairIndicator_OFF.svg"/>
- <img class="one" src="../images/HMI_HVAC_ChairIndicator_One.svg"/>
- <img class="two" src="../images/HMI_HVAC_ChairIndicator_Two.svg"/>
+ <img class="on" src="../images/HMI_HVAC_Right_Chair_ON.svg"/>
</a>
<div class="temperatures item">
<div id="lefttemperature" class="temperatures-container" onscroll="TEMPERATURE.left(this)"></div>
</div>
<div class="block item">
- <a key="auto" value="false" class="auto item button" onclick="BUTTON.toggle(this)">
- <img class="disabled" src="../images/HMI_HVAC_Inactive.svg"/>
- <img class="enabled" src="../images/HMI_HVAC_Active.svg"/>
- <div class="label">
- AUTO
- </div>
- </a>
- <a key="circulation" value="false" class="circulation item button" onclick="BUTTON.toggle(this)">
+ <a id="recirculation" key="recirculation" value="false" class="circulation item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_Circulation_Inactive.svg"/>
<img class="enabled" src="../images/HMI_HVAC_Circulation_Active.svg"/>
</a>
@@ -78,23 +65,23 @@
</div>
</div>
<div class="bottom">
- <a key="down" value="false" class="down item button" onclick="BUTTON.toggle(this)">
+ <a id="down" key="down" value="false" class="down item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_AirDown_Inactive.svg">
<img class="enabled" src="../images/HMI_HVAC_AirDown_Active.svg">
</a>
- <a key="up" value="false" class="up item button" onclick="BUTTON.toggle(this)">
+ <a id="up" key="up" value="false" class="up item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_AirUp_Inactive.svg">
<img class="enabled" src="../images/HMI_HVAC_AirUp_Active.svg">
</a>
- <a key="right" value="false" class="right item button" onclick="BUTTON.toggle(this)">
+ <a id="right" key="right" value="false" class="right item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_AirRight_Inactive.svg">
<img class="enabled" src="../images/HMI_HVAC_AirRight_Active.svg">
</a>
- <a key="rear" value="false" class="rear item button" onclick="BUTTON.toggle(this)">
+ <a id="rear" key="rear" value="false" class="rear item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_Rear_Inactive.svg">
<img class="enabled" src="../images/HMI_HVAC_Rear_Active.svg">
</a>
- <a key="front" value="false" class="front item button" onclick="BUTTON.toggle(this)">
+ <a id="front" key="front" value="false" class="front item button" onclick="BUTTONS.toggle(this)">
<img class="disabled" src="../images/HMI_HVAC_Front_Inactive.svg">
<img class="enabled" src="../images/HMI_HVAC_Front_Active.svg">
</a>
diff --git a/src/index.js b/src/index.js
index 67f800a..53ee56b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -14,12 +14,25 @@
* limitations under the License.
*/
-/* JS */
-import './js/AFB.js';
-
/* CSS */
import './styles/app.scss';
document.addEventListener('DOMContentLoaded', function(){
+ SEATS.init();
TEMPERATURE.init();
-}); \ No newline at end of file
+ FANSPEED.init();
+ BUTTONS.init();
+
+ KUKSA.init([
+ [PATHS.leftSeatWarmer, SEATS],
+ [PATHS.rightSeatWarmer, SEATS],
+ [PATHS.leftSeatTemperature, TEMPERATURE],
+ [PATHS.rightSeatTemperature, TEMPERATURE],
+ [PATHS.leftFanSpeed, FANSPEED],
+ [PATHS.airConditioning, BUTTONS],
+ [PATHS.recirculation, BUTTONS],
+ [PATHS.frontDefroster, BUTTONS],
+ [PATHS.rearDefroster, BUTTONS],
+ [PATHS.leftAirDistribution, BUTTONS],
+ ]);
+});
diff --git a/src/js/AFB.js b/src/js/AFB.js
deleted file mode 100644
index d6e6bfa..0000000
--- a/src/js/AFB.js
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2017, 2018 "IoT.bzh"
- * Author: José Bollo <jose.bollo@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.
- */
-AFB = function(base, initialtoken){
-
-if (typeof base != "object")
- base = { base: base, token: initialtoken };
-
-var initial = {
- base: base.base || "api",
- token: base.token || initialtoken || "HELLO",
- host: base.host || window.location.host,
- url: base.url || undefined
-};
-
-var urlws = initial.url || "ws://"+initial.host+"/"+initial.base;
-
-/*********************************************/
-/**** ****/
-/**** AFB_context ****/
-/**** ****/
-/*********************************************/
-var AFB_context;
-{
- var UUID = undefined;
- var TOKEN = initial.token;
-
- var context = function(token, uuid) {
- this.token = token;
- this.uuid = uuid;
- }
-
- context.prototype = {
- get token() {return TOKEN;},
- set token(tok) {if(tok) TOKEN=tok;},
- get uuid() {return UUID;},
- set uuid(id) {if(id) UUID=id;}
- };
-
- AFB_context = new context();
-}
-/*********************************************/
-/**** ****/
-/**** AFB_websocket ****/
-/**** ****/
-/*********************************************/
-var AFB_websocket;
-{
- var CALL = 2;
- var RETOK = 3;
- var RETERR = 4;
- var EVENT = 5;
-
- var PROTO1 = "x-afb-ws-json1";
-
- AFB_websocket = function(on_open, on_abort) {
- var u = urlws, p = '?';
- if (AFB_context.token) {
- u = u + '?x-afb-token=' + AFB_context.token;
- p = '&';
- }
- if (AFB_context.uuid)
- u = u + p + 'x-afb-uuid=' + AFB_context.uuid;
- this.ws = new WebSocket(u, [ PROTO1 ]);
- this.url = u;
- this.pendings = {};
- this.awaitens = {};
- this.counter = 0;
- this.ws.onopen = onopen.bind(this);
- this.ws.onerror = onerror.bind(this);
- this.ws.onclose = onclose.bind(this);
- this.ws.onmessage = onmessage.bind(this);
- this.onopen = on_open;
- this.onabort = on_abort;
- }
-
- function onerror(event) {
- var f = this.onabort;
- if (f) {
- delete this.onopen;
- delete this.onabort;
- f && f(this);
- }
- this.onerror && this.onerror(this);
- }
-
- function onopen(event) {
- var f = this.onopen;
- delete this.onopen;
- delete this.onabort;
- f && f(this);
- }
-
- function onclose(event) {
- var err = {
- jtype: 'afb-reply',
- request: {
- status: 'disconnected',
- info: 'server hung up'
- }
- };
- for (var id in this.pendings) {
- try { this.pendings[id][1](err); } catch (x) {/*NOTHING*/}
- }
- this.pendings = {};
- this.onclose && this.onclose();
- }
-
- function fire(awaitens, name, data) {
- var a = awaitens[name];
- if (a)
- a.forEach(function(handler){handler(data);});
- var i = name.indexOf("/");
- if (i >= 0) {
- a = awaitens[name.substring(0,i)];
- if (a)
- a.forEach(function(handler){handler(data);});
- }
- a = awaitens["*"];
- if (a)
- a.forEach(function(handler){handler(data);});
- }
-
- function reply(pendings, id, ans, offset) {
- if (id in pendings) {
- var p = pendings[id];
- delete pendings[id];
- try { p[offset](ans); } catch (x) {/*TODO?*/}
- }
- }
-
- function onmessage(event) {
- var obj = JSON.parse(event.data);
- var code = obj[0];
- var id = obj[1];
- var ans = obj[2];
- AFB_context.token = obj[3];
- switch (code) {
- case RETOK:
- reply(this.pendings, id, ans, 0);
- break;
- case RETERR:
- reply(this.pendings, id, ans, 1);
- break;
- case EVENT:
- default:
- fire(this.awaitens, id, ans);
- break;
- }
- }
-
- function close() {
- this.ws.close();
- this.ws.onopen =
- this.ws.onerror =
- this.ws.onclose =
- this.ws.onmessage =
- this.onopen =
- this.onabort = function(){};
- }
-
- function call(method, request, callid) {
- return new Promise((function(resolve, reject){
- var id, arr;
- if (callid) {
- id = String(callid);
- if (id in this.pendings)
- throw new Error("pending callid("+id+") exists");
- } else {
- do {
- id = String(this.counter = 4095 & (this.counter + 1));
- } while (id in this.pendings);
- }
- this.pendings[id] = [ resolve, reject ];
- arr = [CALL, id, method, request ];
- if (AFB_context.token) arr.push(AFB_context.token);
- this.ws.send(JSON.stringify(arr));
- }).bind(this));
- }
-
- function onevent(name, handler) {
- var id = name;
- var list = this.awaitens[id] || (this.awaitens[id] = []);
- list.push(handler);
- }
-
- AFB_websocket.prototype = {
- close: close,
- call: call,
- onevent: onevent
- };
-}
-/*********************************************/
-/**** ****/
-/**** ****/
-/**** ****/
-/*********************************************/
-return {
- context: AFB_context,
- ws: AFB_websocket
-};
-};
diff --git a/src/js/buttons.js b/src/js/buttons.js
index 5fcb521..76d2143 100644
--- a/src/js/buttons.js
+++ b/src/js/buttons.js
@@ -14,25 +14,66 @@
* limitations under the License.
*/
-var buttons = {
+
+
+var values = {
ac: false,
- auto: false,
- circulation: false,
- down: false,
- up: false,
- right: false,
+ recirculation: false,
rear: false,
front: false
};
-function update(node, value) {
- node.setAttribute('value', value);
+var paths = {
+ ac: PATHS.airConditioning,
+ recirculation: PATHS.recirculation,
+ rear: PATHS.rearDefroster,
+ front: PATHS.frontDefroster,
+};
+
+var nodes = {}
+
+export function init() {
+ nodes[PATHS.airConditioning] = document.getElementById('ac');
+ nodes[PATHS.recirculation] = document.getElementById('recirculation');
+ nodes[PATHS.frontDefroster] = document.getElementById('front');
+ nodes[PATHS.rearDefroster] = document.getElementById('rear');
+ nodes['up'] = document.getElementById('up');
+ nodes['down'] = document.getElementById('down');
+ nodes['right'] = document.getElementById('right');
}
-module.exports = {
- toggle: function(node) {
- var key = node.getAttribute('key');
- buttons[key] = !buttons[key];
- update(node, buttons[key]);
+export function update(path, value) {
+ if (path == PATHS.leftAirDistribution) {
+ if (value == 'UP') {
+ nodes['up'].setAttribute('value', true);
+ nodes['down'].setAttribute('value', false);
+ nodes['right'].setAttribute('value', false);
+ } else if (value == 'DOWN') {
+ nodes['down'].setAttribute('value', true);
+ nodes['up'].setAttribute('value', false);
+ nodes['right'].setAttribute('value', false);
+
+ } else if (value == 'MIDDLE') {
+ nodes['right'].setAttribute('value', true);
+ nodes['up'].setAttribute('value', false);
+ nodes['down'].setAttribute('value', false);
+ }
+ } else {
+ var node = nodes[path];
+ node.setAttribute('value', value);
}
-} \ No newline at end of file
+}
+
+export function toggle(node) {
+ var key = node.getAttribute('key');
+ values[key] = !values[key];
+ if (key == 'up') {
+ KUKSA.set(PATHS.leftAirDistribution, 'UP');
+ } else if (key == 'down') {
+ KUKSA.set(PATHS.leftAirDistribution, 'DOWN');
+ } else if (key == 'right') {
+ KUKSA.set(PATHS.leftAirDistribution, 'MIDDLE');
+ } else {
+ KUKSA.set(paths[key], values[key]);
+ }
+}
diff --git a/src/js/chair.js b/src/js/chair.js
deleted file mode 100644
index 5cd26e8..0000000
--- a/src/js/chair.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2019 Igalia, S.L.
- *
- * 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.
- */
-
-var left = 0;
-var right = 0;
-
-function update(node, value){
- node.setAttribute('value', value);
-}
-
-module.exports = {
- left: function(node) {
- left = (left + 1) % 3;
- update(node, left);
- },
- right: function(node) {
- right = (right + 1) % 3;
- update(node, right);
- },
-} \ No newline at end of file
diff --git a/src/js/fan_speed.js b/src/js/fan_speed.js
index 8b131b5..fa0ed01 100644
--- a/src/js/fan_speed.js
+++ b/src/js/fan_speed.js
@@ -15,15 +15,17 @@
*/
var value = 0;
+var node = null;
-function update(node, value) {
+export function update(path, value) {
node.value = value;
node.parentNode.getElementsByTagName('progress')[0].value = value;
}
-module.exports = {
- set: function(node) {
- value = node.value;
- update(node, value);
- }
-} \ No newline at end of file
+export function init() {
+ node = document.getElementById('FanSpeed');
+}
+
+export function set() {
+ KUKSA.set(PATHS.leftFanSpeed, node.value);
+}
diff --git a/src/js/kuksa.js b/src/js/kuksa.js
new file mode 100644
index 0000000..9e9cc22
--- /dev/null
+++ b/src/js/kuksa.js
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2022 Igalia, S.L.
+ *
+ * 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.
+ */
+
+import { v4 as uuidv4 } from 'uuid';
+
+const DEFAULT_TARGET = "wss://localhost:8090";
+
+// 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';
+
+var kuksa_context = {
+ authToken: TEST_TOKEN,
+ socket: undefined,
+ target: DEFAULT_TARGET,
+}
+
+var pathToHandler = null;
+
+function logReceivedMessage(data) {
+ console.log('Received message:', data)
+}
+
+function logConnectionStatus(status, event) {
+ console.log('Connection status:', status);
+}
+
+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 kuksaws_onerror(event) {
+ logConnectionStatus('Failed to connect:', event);
+}
+
+function kuksaws_onmessage(event) {
+ logReceivedMessage(event.data);
+
+ var jsonData = JSON.parse(event.data);
+
+ if (jsonData.action == 'get' ||
+ jsonData.action =='subscription') {
+ updateVehicleInfo(jsonData);
+ }
+}
+
+function updateVehicleInfo(message) {
+ var value = message.data.dp.value;
+ var path = message.data.path;
+
+ if (!pathToHandler.has(path)) {
+ console.log('Handler not found for', path);
+ return;
+ }
+
+ var handler = pathToHandler.get(path);
+ handler.update(path, value)
+}
+
+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;
+}
+
+function subscribe(path) {
+ return send('subscribe', { path: path });
+}
+
+function authorize() {
+ return send('authorize');
+}
+
+export function get(path) {
+ return send('get', { path: path });
+}
+
+export function set(path, value) {
+ return send('set', { path: path, value: value });
+}
+
+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;
+ }
+}
diff --git a/src/js/paths.js b/src/js/paths.js
new file mode 100644
index 0000000..4f3c5d3
--- /dev/null
+++ b/src/js/paths.js
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 Igalia, S.L.
+ *
+ * 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.
+ */
+
+// https://github.com/COVESA/vehicle_signal_specification/blob/master/spec/Cabin/SingleHVACStation.vspec
+export const leftAirDistribution = 'Vehicle.Cabin.HVAC.Station.Row1.Left.AirDistribution';
+export const leftFanSpeed = 'Vehicle.Cabin.HVAC.Station.Row1.Left.FanSpeed';
+export const leftSeatTemperature = 'Vehicle.Cabin.Seat.Row1.Pos1.Heating';
+export const rightSeatTemperature = 'Vehicle.Cabin.Seat.Row1.Pos2.Heating';
+
+// https://github.com/COVESA/vehicle_signal_specification/blob/master/spec/Cabin/SingleSeat.vspec
+export const leftSeatWarmer = 'Vehicle.Cabin.Seat.Row1.Pos1.Switch.IsWarmerEngaged';
+export const rightSeatWarmer = 'Vehicle.Cabin.Seat.Row1.Pos2.Switch.IsWarmerEngaged';
+
+// https://github.com/COVESA/vehicle_signal_specification/blob/master/spec/Cabin/HVAC.vspec
+export const recirculation = 'Vehicle.Cabin.HVAC.IsRecirculationActive';
+export const airConditioning = 'Vehicle.Cabin.HVAC.IsAirConditioningActive';
+export const frontDefroster = 'Vehicle.Cabin.HVAC.IsFrontDefrosterActive';
+export const rearDefroster = 'Vehicle.Cabin.HVAC.IsRearDefrosterActive';
diff --git a/src/js/seats.js b/src/js/seats.js
new file mode 100644
index 0000000..3afc481
--- /dev/null
+++ b/src/js/seats.js
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 Igalia, S.L.
+ *
+ * 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.
+ */
+
+var values = {
+ leftAirDistribution: 'middle',
+ leftSeatWarmer: false,
+ rightSeatWarmer: false,
+};
+
+var controls = {
+ leftSeatWarmer: null,
+ rightSeatWarmer: null,
+};
+
+export function init() {
+ controls.leftSeatWarmer = document.getElementById('LeftChair');
+ controls.rightSeatWarmer = document.getElementById('RightChair');
+}
+
+export function update(path, value) {
+ switch (path) {
+ case PATHS.leftSeatWarmer:
+ values.leftSeatWarmer = value;
+ controls.leftSeatWarmer.setAttribute('value', values.leftSeatWarmer);
+ break;
+ case PATHS.rightSeatWarmer:
+ values.rightSeatWarmer = value;
+ controls.rightSeatWarmer.setAttribute('value', values.rightSeatWarmer);
+ break;
+ }
+}
+
+export function left() {
+ KUKSA.set(PATHS.leftSeatWarmer, !values.leftSeatWarmer);
+}
+export function right() {
+ KUKSA.set(PATHS.rightSeatWarmer, !values.rightSeatWarmer);
+}
diff --git a/src/js/temperature.js b/src/js/temperature.js
index 3a394a1..1e35ddf 100644
--- a/src/js/temperature.js
+++ b/src/js/temperature.js
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-var left = 22;
-var right = 22;
+var values = {
+ leftTemperature: 22,
+ rightTemperature: 22,
+}
var lowTemperature = 15;
var hiTemperature = 30;
@@ -24,6 +26,12 @@ var temperatures = [];
var isScrolling;
var elementHeight;
+var controls = {
+ leftTemperatureNode: null,
+ rightTemperatureNode: null,
+};
+
+
function createTemperatureElement() {
var element = document.createElement('div');
element.classList = ['temperature'];
@@ -32,7 +40,21 @@ function createTemperatureElement() {
return element;
}
-function update(node, index) {
+export function update(path, value) {
+ var temperature, node;
+ if (path == PATHS.rightSeatTemperature) {
+ values.rightTemperature = value;
+ temperature = values.rightTemperature;
+ node = controls.rightTemperatureNode;
+ } else {
+ values.leftTemperature = value;
+ temperature = values.leftTemperature;
+ node = controls.leftTemperatureNode;
+ }
+ setSemperature(node, temperatures.indexOf(temperature));
+}
+
+function setSemperature(node, index) {
node.scrollTop = index*elementHeight;
for( var i=0; i<node.children.length; i++) {
@@ -41,49 +63,49 @@ function update(node, index) {
node.children[index].setAttribute('enabled', true);
}
-module.exports = {
- left: function(node) {
- clearTimeout(isScrolling);
-
- isScrolling = setTimeout(function(){
- var index = Math.round(node.scrollTop/elementHeight);
- left = temperatures[index];
- update(node, index);
- console.log('LEFT', left);
- }, 100);
- },
- right: function(node) {
- clearTimeout(isScrolling);
-
- isScrolling = setTimeout(function(){
- var index = Math.round(node.scrollTop/elementHeight);
- right = temperatures[index];
- update(node, index);
- console.log('RIGHT', right);
- }, 100);
- },
- init: function() {
- var leftTemperature = document.getElementById('lefttemperature');
- var rightTemperature = document.getElementById('righttemperature');
- elementHeight = leftTemperature.offsetHeight/2;
-
- for( var i=lowTemperature; i<=hiTemperature; i++) {
- var element = createTemperatureElement();
- if( i === lowTemperature) {
- element.innerHTML = 'LO';
- } else if( i === hiTemperature ) {
- element.innerHTML = 'HI';
- } else {
- element.innerHTML = i+'º';
- }
- leftTemperature.appendChild(element);
- rightTemperature.appendChild(element.cloneNode(true));
- temperatures[temperatures.length] = i;
- }
- leftTemperature.appendChild(createTemperatureElement());
- rightTemperature.appendChild(createTemperatureElement());
+export function left() {
+ clearTimeout(isScrolling);
+
+ isScrolling = setTimeout(function() {
+ var index = Math.round(controls.leftTemperatureNode.scrollTop / elementHeight);
+ values.leftTemperature = temperatures[index];
+ console.log('LEFT', values.leftTemperature);
+ KUKSA.set(PATHS.leftSeatTemperature, values.leftTemperature);
+ }, 100);
+}
+
+export function right() {
+ clearTimeout(isScrolling);
+
+ isScrolling = setTimeout(function() {
+ var index = Math.round(controls.rightTemperatureNode.scrollTop / elementHeight);
+ values.rightTemperature = temperatures[index];
+ console.log('RIGHT', values.rightTemperature);
+ KUKSA.set(PATHS.rightSeatTemperature, values.rightTemperature);
+ }, 100);
+}
- update(leftTemperature, temperatures.indexOf(left));
- update(rightTemperature, temperatures.indexOf(right));
+export function init() {
+ controls.leftTemperatureNode = document.getElementById('lefttemperature');
+ controls.rightTemperatureNode = document.getElementById('righttemperature');
+ elementHeight = controls.leftTemperatureNode.offsetHeight / 2;
+
+ for (var i = lowTemperature; i <= hiTemperature; i++) {
+ var element = createTemperatureElement();
+ if (i === lowTemperature) {
+ element.innerHTML = 'LO';
+ } else if (i === hiTemperature) {
+ element.innerHTML = 'HI';
+ } else {
+ element.innerHTML = i + 'º';
+ }
+ controls.leftTemperatureNode.appendChild(element);
+ controls.rightTemperatureNode.appendChild(element.cloneNode(true));
+ temperatures[temperatures.length] = i;
}
-} \ No newline at end of file
+ controls.leftTemperatureNode.appendChild(createTemperatureElement());
+ controls.rightTemperatureNode.appendChild(createTemperatureElement());
+
+ setSemperature(controls.leftTemperatureNode, temperatures.indexOf(values.leftTemperature));
+ setSemperature(controls.rightTemperatureNode, temperatures.indexOf(values.rightTemperature));
+}
diff --git a/src/styles/landscape.scss b/src/styles/landscape.scss
index 7acca5e..765443c 100644
--- a/src/styles/landscape.scss
+++ b/src/styles/landscape.scss
@@ -14,9 +14,11 @@
}
.center {
+ width: 75%;
position: relative;
float: left;
height: 20%;
+ margin-left: 150px;
margin-top: 40px;
.item {
@@ -24,16 +26,14 @@
.button {
.label {
- font-size: 4em;
- margin-top: -45%;
+ font-size: 2.5em;
}
}
}
.item.ac {
.label {
- font-size: 4em;
- margin-top: -45%;
+ font-size: 2.5em;
}
}
}
@@ -58,4 +58,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/styles/main.scss b/src/styles/main.scss
index 5d2d950..7ab190f 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -133,48 +133,42 @@ body {
padding-top:75%;
}
- &.ac, &.auto {
+ &.ac {
+ position: relative;
+
.label {
font-weight: bold;
font-size: 2.5rem;
- text-align: center;
- margin-top: -50%;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
}
}
&.seat {
img {
width: 50%;
- margin: 0 25%;
+ margin: 10% 25%;
}
- &[value="0"] {
- .one, .two {
- display: none;
- }
+ &[value="false"] {
.off {
display: block;
}
- }
-
- &[value="1"] {
- .off, .two {
+ .on {
display: none;
}
- .one {
- display: block;
- }
}
- &[value="2"] {
- .one, .off {
+ &[value="true"] {
+ .off {
display: none;
}
- .two {
+ .on {
display: block;
}
}
-
}
&.circulation {
diff --git a/webpack.config.js b/webpack.config.js
index 9c87768..43bc54c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -9,9 +9,11 @@ module.exports = {
mode: 'production',
entry: {
index: './src/index.js',
+ PATHS: './src/js/paths.js',
+ SEATS: './src/js/seats.js',
FANSPEED: './src/js/fan_speed.js',
- CHAIR: './src/js/chair.js',
- BUTTON: './src/js/buttons.js',
+ KUKSA: './src/js/kuksa.js',
+ BUTTONS: './src/js/buttons.js',
TEMPERATURE: './src/js/temperature.js'
},
output: {
@@ -83,7 +85,6 @@ module.exports = {
]
},
devServer: {
- contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}