From 7e6d6d0a37e37804e3a751e2bfde11a9c1e85b0b Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Sat, 29 Apr 2017 18:17:08 +0200 Subject: Adding HTML5 UI with cpu stat binding Change-Id: Id63b7d338140097a5f2f0943f1b63ee978141829 Signed-off-by: Romain Forlot --- .../app/Frontend/images/car-top-view.png | Bin 0 -> 2424 bytes .../low-can-demo/app/Frontend/images/cluster.png | Bin 0 -> 409895 bytes .../low-can-demo/app/Frontend/images/favicon.ico | Bin 0 -> 1150 bytes .../app/Frontend/images/gas-pump-black.png | Bin 0 -> 2429 bytes .../app/Frontend/images/gas-pump-green.png | Bin 0 -> 1826 bytes .../app/Frontend/images/gas-pump-red.png | Bin 0 -> 2174 bytes .../images/logo_iot_bzh_lightgrey_325x90_50dpi.png | Bin 0 -> 14605 bytes CAN-binder/low-can-demo/app/Frontend/index.html | 137 ++++++++ CAN-binder/low-can-demo/app/Frontend/js/AFB.js | 170 ++++++++++ .../low-can-demo/app/Frontend/js/low-can-demo.js | 351 +++++++++++++++++++++ .../app/Frontend/styles/bootstrap.scss | 56 ++++ .../app/Frontend/styles/low-can-demo.scss | 187 +++++++++++ 12 files changed, 901 insertions(+) create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/car-top-view.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/cluster.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/favicon.ico create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/gas-pump-black.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/gas-pump-green.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/gas-pump-red.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/images/logo_iot_bzh_lightgrey_325x90_50dpi.png create mode 100644 CAN-binder/low-can-demo/app/Frontend/index.html create mode 100644 CAN-binder/low-can-demo/app/Frontend/js/AFB.js create mode 100644 CAN-binder/low-can-demo/app/Frontend/js/low-can-demo.js create mode 100644 CAN-binder/low-can-demo/app/Frontend/styles/bootstrap.scss create mode 100644 CAN-binder/low-can-demo/app/Frontend/styles/low-can-demo.scss (limited to 'CAN-binder/low-can-demo/app/Frontend') diff --git a/CAN-binder/low-can-demo/app/Frontend/images/car-top-view.png b/CAN-binder/low-can-demo/app/Frontend/images/car-top-view.png new file mode 100644 index 00000000..a5ad0966 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/car-top-view.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/cluster.png b/CAN-binder/low-can-demo/app/Frontend/images/cluster.png new file mode 100644 index 00000000..c6b8d908 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/cluster.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/favicon.ico b/CAN-binder/low-can-demo/app/Frontend/images/favicon.ico new file mode 100644 index 00000000..eeb7ab7a Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/favicon.ico differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-black.png b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-black.png new file mode 100644 index 00000000..46e875e1 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-black.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-green.png b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-green.png new file mode 100644 index 00000000..c3aebad6 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-green.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-red.png b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-red.png new file mode 100644 index 00000000..ad842839 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/gas-pump-red.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/images/logo_iot_bzh_lightgrey_325x90_50dpi.png b/CAN-binder/low-can-demo/app/Frontend/images/logo_iot_bzh_lightgrey_325x90_50dpi.png new file mode 100644 index 00000000..7ba41960 Binary files /dev/null and b/CAN-binder/low-can-demo/app/Frontend/images/logo_iot_bzh_lightgrey_325x90_50dpi.png differ diff --git a/CAN-binder/low-can-demo/app/Frontend/index.html b/CAN-binder/low-can-demo/app/Frontend/index.html new file mode 100644 index 00000000..b1b8a810 --- /dev/null +++ b/CAN-binder/low-can-demo/app/Frontend/index.html @@ -0,0 +1,137 @@ + + + + + + + + AGL Low CAN binding demo + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + + + + +
+
+ + +
+ + + + + + + + + + + + + + +
AGL CAN messages Details
DataValue
Vehicle Speed ? km/h
Engine Speed ? tr/mn
Engine Load ? %
MAF air flow rate ? grams/sec
Intake Air temp ? °C
Messages rate ? received events/s
CPU load ? %
+
+ + +
+ + diff --git a/CAN-binder/low-can-demo/app/Frontend/js/AFB.js b/CAN-binder/low-can-demo/app/Frontend/js/AFB.js new file mode 100644 index 00000000..aa1198cb --- /dev/null +++ b/CAN-binder/low-can-demo/app/Frontend/js/AFB.js @@ -0,0 +1,170 @@ +AFB = function(base, initialtoken){ + +var urlws = "ws://"+window.location.host+"/"+base; +var urlhttp = "http://"+window.location.host+"/"+base; + +/*********************************************/ +/**** ****/ +/**** AFB_context ****/ +/**** ****/ +/*********************************************/ +var AFB_context = (function() { + var UUID; + var TOKEN = initialtoken; + + 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;} + }; + + return new context(); +})(); +/*********************************************/ +/**** ****/ +/**** AFB_websocket ****/ +/**** ****/ +/*********************************************/ +var AFB_websocket = (function() { + var CALL = 2; + var RETOK = 3; + var RETERR = 4; + var EVENT = 5; + + var PROTO1 = "x-afb-ws-json1"; + + var result = function(onopen, onabort) { + var u = urlws; + if (AFB_context.token) { + u = u + '?x-afb-token=' + AFB_context.token; + if (AFB_context.uuid) + u = u + '&x-afb-uuid=' + AFB_context.uuid; + } + this.ws = new WebSocket(u, [ PROTO1 ]); + 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 = onopen; + this.onabort = onabort; + }; + + 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) { + for (var id in this.pendings) { + var ferr = this.pendings[id].onerror; + ferr && ferr(null, this); + } + 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]; + var f = p[offset]; + f && f(ans); + } + } + + 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(); + } + + function call(method, request, onsuccess, onfailure) { + var id, arr; + do { + id = String(this.counter = 4095 & (this.counter + 1)); + } while (id in this.pendings); + this.pendings[id] = [ onsuccess, onfailure ]; + arr = [CALL, id, method, request ]; + if (AFB_context.token) arr.push(AFB_context.token); + this.ws.send(JSON.stringify(arr)); + } + + function onevent(name, handler) { + var id = name; + var list = this.awaitens[id] || (this.awaitens[id] = []); + list.push(handler); + } + + result.prototype = { + close: close, + call: call, + onevent: onevent + }; + + return result; +})(); +/*********************************************/ +/**** ****/ +/**** ****/ +/**** ****/ +/*********************************************/ +return { + context: AFB_context, + ws: AFB_websocket +}; +}; + diff --git a/CAN-binder/low-can-demo/app/Frontend/js/low-can-demo.js b/CAN-binder/low-can-demo/app/Frontend/js/low-can-demo.js new file mode 100644 index 00000000..2e8b99e6 --- /dev/null +++ b/CAN-binder/low-can-demo/app/Frontend/js/low-can-demo.js @@ -0,0 +1,351 @@ +// parse location to get security token +var urlParams={}; +location.search.substr(1).split("&").forEach(function(item) { + var k = item.split("=")[0]; + var v = decodeURIComponent(item.split("=")[1]); + if (k in urlParams) urlParams[k].push(v); else urlParams[k] = [v]; +}); + +var afb = new AFB("api"/*root*/, urlParams.token[0]); +var ws; +var vspeed = 0, espeed = 0, torque = 0; +var R2D = 180.0 / Math.PI; +var D2R = Math.PI / 180.0; +var fuel; +var con,cons,consa = [ ]; +var minspeed = 5; +var temp = 18; +var wdgTem, wdgVsp, wdgEsp, wdgTrq; +var wdgFue, wdgGpred, wdgGpblack; +var conscale = 40; +var condt = 60000; + +/* gauges creation */ +var gauges={}; +function initGauges() { + gauges.speed = new steelseries.Radial('speedGauge', { + gaugeType: steelseries.GaugeType.TYPE4, + frameDesign: steelseries.FrameDesign.BLACK_METAL, + backgroundColor: steelseries.BackgroundColor.CARBON, + size: 250, + titleString: "Speed", + unitString: "Km/h", + lcdVisible: true, + niceScale: true, + maxValue: 200, + maxMeasuredValue: 0, + maxMeasuredValueVisible: true, + thresholdVisible: false, + ledVisible: false, + pointerType: steelseries.PointerType.TYPE11, + useOdometer: false, + odometerParams: { + digits: 6 + } + }); + + gauges.rpm = new steelseries.Radial('rpmGauge', { + gaugeType: steelseries.GaugeType.TYPE4, + frameDesign: steelseries.FrameDesign.BLACK_METAL, + backgroundColor: steelseries.BackgroundColor.CARBON, + size: 200, + titleString: "RPM", + unitString: "x1000", + lcdVisible: false, + niceScale: true, + maxValue: 5, + maxMeasuredValue: 0, + maxMeasuredValueVisible: false, + section: [ + steelseries.Section(4, 8, 'rgba(255, 0, 0, 0.7)') + ], + area: [ + steelseries.Section(5, 8, 'rgba(255, 0, 0, 0.3)') + ], + thresholdVisible: false, + ledVisible: false, + pointerType: steelseries.PointerType.TYPE11 + }); + + gauges.maf = new steelseries.Radial('MAFGauge', { + gaugeType: steelseries.GaugeType.TYPE4, + frameDesign: steelseries.FrameDesign.BLACK_METAL, + backgroundColor: steelseries.BackgroundColor.CARBON, + size: 200, + titleString: "Air flow Rate", + unitString: "grams/sec", + lcdVisible: true, + lcdColor: steelseries.LcdColor.STANDARD, + lcdDecimals: 1, + niceScale: true, + minValue: 0, + maxValue: 655, + minMeasuredValue: 0, + maxMeasuredValue: conscale, + maxMeasuredValueVisible: true, + section: [ + steelseries.Section(0, 255, 'rgba(0, 255, 0, 0.5)'), + steelseries.Section(256, 326, 'rgba(255, 255, 0, 0.5)'), + steelseries.Section(327, 600, 'rgba(255, 128, 0, 0.5)'), + steelseries.Section(601, 655, 'rgba(255, 0, 0, 0.5)') + ], + useValueGradient: true, + thresholdVisible: false, + ledVisible: false, + pointerType: steelseries.PointerType.TYPE11 + }); + + gauges.iatemp = new steelseries.Radial('IATempGauge', { + gaugeType: steelseries.GaugeType.TYPE4, + frameDesign: steelseries.FrameDesign.BLACK_METAL, + backgroundColor: steelseries.BackgroundColor.CARBON, + size: 200, + titleString: "Intake air temp", + unitString: "°C", + lcdVisible: true, + lcdColor: steelseries.LcdColor.STANDARD, + lcdDecimals: 1, + niceScale: true, + minValue: 0, + maxValue: 100, + minMeasuredValue: 0, + maxMeasuredValue: 100, + maxMeasuredValueVisible: true, + section: [ + steelseries.Section(0, 30, 'rgba(0, 255, 0, 0.5)'), + steelseries.Section(31, 50, 'rgba(255, 255, 0, 0.5)'), + steelseries.Section(51, 70, 'rgba(255, 128, 0, 0.5)'), + steelseries.Section(71, 100, 'rgba(255, 0, 0, 0.5)') + ], + useValueGradient: true, + thresholdVisible: false, + ledVisible: false, + pointerType: steelseries.PointerType.TYPE11 + }); + + gauges.torque = new steelseries.Radial('torqueGauge', { + gaugeType: steelseries.GaugeType.TYPE2, + frameDesign: steelseries.FrameDesign.BLACK_METAL, + backgroundColor: steelseries.BackgroundColor.CARBON, + size: 200, + titleString: "Load", + unitString: "%", + lcdVisible: false, + niceScale: true, + minValue: 0, + maxValue: 100, + maxMeasuredValue: 0, + maxMeasuredValueVisible: false, + section: [ + steelseries.Section(0, 0, 'rgba(0, 255, 0, 0.7)'), + steelseries.Section(50, 1500, 'rgba(255, 128, 0, 0.7)') + ], + area: [ + steelseries.Section(0, 0, 'rgba(0, 255, 0, 0.3)'), + steelseries.Section(50, 1500, 'rgba(255, 128, 0, 0.3)') + ], + threshold: 0, + thresholdVisible: true, + ledVisible: false, + pointerType: steelseries.PointerType.TYPE4 + }); + + /* adjust cluster background size upon resize */ + // TODO: could be doable through CSS, but a bit tricky + function adjustCluster() { + var qh=$("#quad1").outerHeight(); + var sh=$("#speedGauge").outerHeight(); + var pct=Math.ceil((1000*sh/qh))/10+1; + $('#cluster').css("height",pct+"%"); + } + $(window).resize(adjustCluster); + adjustCluster(); +} + +function clearGauges() { + for (var g in gauges) { + switch(g) { + case "clock": + gauges[g].setValue("-"); + break; + case "speed": + gauges[g].setValue(0); + break; + default: + gauges[g].setValue(0); + break; + } + } +} + +function gotVehicleSpeed(obj) { + vspeed = Math.round(obj.data.value); + wdgVsp.innerHTML = /* wdgVspeed.innerHTML = */ String(vspeed); + //gauges.speed.setValueAnimated(vspeed); + gauges.speed.setValue(vspeed); +} + +function gotTorque(obj) { + torque=Math.round(obj.data.value); + wdgTrq.innerHTML=String(torque); + gauges.torque.setValue(torque); +} + +function gotEngineSpeed(obj) { + espeed = Math.round(obj.data.value); + wdgEsp.innerHTML = /* wdgEspeed.innerHTML = */ String(espeed); + //gauges.rpm.setValueAnimated(espeed/1000); + gauges.rpm.setValue(espeed/1000); +} + +function gotFuelLevel(obj) { + fuel = Math.round(obj.data.value); + wdgFue.innerHTML = fuel; + gauges.maf.setValue(fuel); +} + +function gotTemp(obj) { + temp = Math.round(obj.data.value); + wdgTem.innerHTML = temp; + gauges.iatemp.setValue(temp); +} + +function gotStart(obj) { + document.body.className = "started"; + vspeed = 0; + espeed = 0; + heading = 0; + cons = undefined; + consa = [ ]; + + wdgVsp.innerHTML = /*wdgVspeed.innerHTML = */ + wdgEsp.innerHTML = /*wdgEspeed.innerHTML = */ + wdgTem.innerHTML = wdgFue.innerHTML = "?"; + for (var i = 0 ; i < 9 ; i++) { + wdgConX[i].style.height = "0%"; + wdgConX[i].innerHTML = ""; + } +} + +function gotStop(obj) { + document.body.className = "connected"; +} + +var msgcnt=0; +var msgprv=0; +var msgprvts=0; + +function gotAny(obj) { + if (obj.event != "low-can/STOP") { + document.body.className = "started"; + } + msgcnt++; + + wdgTem.innerHTML = temp; + gauges.iatemp.setValue(temp); +// updateClock(obj.data.timestamp); +} + +function updateMsgRate() { + var now=+new Date(); + if (msgprvts) { + var dt=now-msgprvts; + msgrate=Math.round((msgcnt-msgprv)*10000/dt)/10; + wdgMsg.innerHTML=String(msgrate); + } + + msgprv=msgcnt; + msgprvts=now; +} + +function gotStat(obj) { + wdgStat.innerHTML = obj.data; +} + +function onAbort() { + document.body.className = "not-connected"; +} + +function onOpen() { + ws.call("low-can/subscribe", {event:[ + "diagnostic_messages.vehicle.speed", + "diagnostic_messages.mass.airflow", + "diagnostic_messages.engine.speed", + "diagnostic_messages.engine.load", + "diagnostic_messages.intake.air.temperature"]}, + onSubscribed, onAbort); + ws.call("stat/subscribe", true); + ws.onevent("stat/stat", gotStat); +} + +function onClose() { + ws.call("low-can/unsubscribe", {event:[ + "diagnostic_messages.engine.speed", + "diagnostic_messages.mass.airflow", + "diagnostic_messages.vehicle.speed", + "diagnostic_messages.engine.load", + "diagnostic_messages.intake.air.temperature"]}, + onUnsubscribed, onAbort); + ws.call("stat/unsubscribe", true); + ws.onevent("stat/stat", gotStat); +} + +function onSubscribed() { + document.body.className = "connected"; + ws.onevent("low-can/diagnostic_messages.engine.speed", gotEngineSpeed); + ws.onevent("low-can/diagnostic_messages.mass.airflow", gotFuelLevel); + ws.onevent("low-can/diagnostic_messages.vehicle.speed", gotVehicleSpeed); + ws.onevent("low-can/diagnostic_messages.engine.load", gotTorque); + ws.onevent("low-can/diagnostic_messages.intake.air.temperature", gotTemp); + ws.onevent("low-can",gotAny); +} + +function onUnsubscribed() { + document.body.className = "disconnected"; + ws.onevent("low-can/diagnostic_messages.engine.speed", gotEngineSpeed); + ws.onevent("low-can/diagnostic_messages.mass.airflow", gotFuelLevel); + ws.onevent("low-can/diagnostic_messages.vehicle.speed", gotVehicleSpeed); + ws.onevent("low-can/diagnostic_messages.engine.load", gotTorque); + ws.onevent("low-can/diagnostic_messages.intake.air.temperature", gotTemp); + ws.onevent("low-can",gotAny); +} + +function replyok(obj) { + document.getElementById("output").innerHTML = "OK: "+JSON.stringify(obj); +} +function replyerr(obj) { + document.getElementById("output").innerHTML = "ERROR: "+JSON.stringify(obj); +} +function send(message) { + var api = document.getElementById("api").value; + var verb = document.getElementById("verb").value; + ws.call(api+"/"+verb, {data:message}, replyok, replyerr); +} + +function doConnect() { + document.body.className = "connecting"; + ws = new afb.ws(onOpen, onAbort); +} + +function doDisconnect() { + document.body.className = "connecting"; + ws = new afb.ws(onClose, onAbort); +} + +$(function() { + wdgVsp = document.getElementById("vsp"); + wdgEsp = document.getElementById("esp"); + wdgTrq = document.getElementById("trq"); + wdgFue = document.getElementById("fue"); + wdgTem = document.getElementById("tem"); + wdgStat = document.getElementById("stat"); + wdgMsg = document.getElementById("msg"); + + initGauges(); + + doConnect(); + + // init interval to compute message rate + setInterval(updateMsgRate,250); +}); + diff --git a/CAN-binder/low-can-demo/app/Frontend/styles/bootstrap.scss b/CAN-binder/low-can-demo/app/Frontend/styles/bootstrap.scss new file mode 100644 index 00000000..e72d1def --- /dev/null +++ b/CAN-binder/low-can-demo/app/Frontend/styles/bootstrap.scss @@ -0,0 +1,56 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +// Core variables and mixins +@import "bootstrap/variables"; +@import "bootstrap/mixins"; + +// Reset and dependencies +@import "bootstrap/normalize"; +@import "bootstrap/print"; +@import "bootstrap/glyphicons"; + +// Core CSS +@import "bootstrap/scaffolding"; +@import "bootstrap/type"; +@import "bootstrap/code"; +@import "bootstrap/grid"; +@import "bootstrap/tables"; +@import "bootstrap/forms"; +@import "bootstrap/buttons"; + +// Components +@import "bootstrap/component-animations"; +@import "bootstrap/dropdowns"; +@import "bootstrap/button-groups"; +@import "bootstrap/input-groups"; +@import "bootstrap/navs"; +@import "bootstrap/navbar"; +@import "bootstrap/breadcrumbs"; +@import "bootstrap/pagination"; +@import "bootstrap/pager"; +@import "bootstrap/labels"; +@import "bootstrap/badges"; +@import "bootstrap/jumbotron"; +@import "bootstrap/thumbnails"; +@import "bootstrap/alerts"; +@import "bootstrap/progress-bars"; +@import "bootstrap/media"; +@import "bootstrap/list-group"; +@import "bootstrap/panels"; +@import "bootstrap/responsive-embed"; +@import "bootstrap/wells"; +@import "bootstrap/close"; + +// Components w/ JavaScript +@import "bootstrap/modals"; +@import "bootstrap/tooltip"; +@import "bootstrap/popovers"; +@import "bootstrap/carousel"; + +// Utility classes +@import "bootstrap/utilities"; +@import "bootstrap/responsive-utilities"; diff --git a/CAN-binder/low-can-demo/app/Frontend/styles/low-can-demo.scss b/CAN-binder/low-can-demo/app/Frontend/styles/low-can-demo.scss new file mode 100644 index 00000000..d7e52130 --- /dev/null +++ b/CAN-binder/low-can-demo/app/Frontend/styles/low-can-demo.scss @@ -0,0 +1,187 @@ +html,body { + padding:0; + margin: 0 auto; + width:100%; + height:100%; + min-height:100%; + color: black; + background: #FFF; +} + +/* http://stackoverflow.com/questions/18474564/bootstrap-3-navbar-with-logo */ +.navbar-brand { + padding: 0px; +} +.navbar-brand>img { + height: 100%; + padding: 5px; + width: auto; +} +.navbar-right { + margin-right: 0; +} + +/* used in navbar to show/hide items depending on connection status */ +.not-connected .if-connecting { display: none; } +.not-connected .if-connected { display: none; } +.not-connected .if-started { display: none; } +.connecting .if-not-connected { display: none; } +.connecting .if-connected { display: none; } +.connecting .if-started { display: none; } +.connected .if-not-connected { display: none; } +.connected .if-connecting { display: none; } +.connected .if-started { display: none; } +.started .if-not-connected { display: none; } +.started .if-connecting { display: none; } +.started .if-connected { display: none; } + +.content{ + position: absolute; + left:0; + right:0; + bottom:0; + top: 50px; + padding:0; + overflow: hidden; +} + +.quad { + position: relative; + overflow: hidden; + width:100%; + height:50%; + padding:0; + margin: 0; + box-sizing:border-box; + -moz-box-sizing:border-box; + -webkit-box-sizing:border-box; + border: 4px ridge silver; + border-radius: 15px; + text-align: left; +} + +.center { + display: table-cell; + width:100%; + height:100%; + vertical-align: middle; +} + +#quad1 { border-bottom-right-radius: 0;} +#quad2 { border-bottom-left-radius: 0; } +#quad3 { border-top-right-radius: 0; overflow: auto; } +#quad4 { border-top-left-radius: 0; } + +/* in quad 1 */ +#view1,#view2 { + position: relative; + width: auto !important; + height: auto !important; + min-width: 100%; + min-height: 100%; + display: block; + top: 50%; + left: 50%; + transform: translate(-50%,-50%); + -webkit-transform: translate(-50%,-50%); +} + +.number { text-align: center; vertical-align: middle; font: italic bold 12px monospace; } + +/* +#espan { position: absolute; left: 1em; bottom: 1em; } +#espeed { position: absolute; top: 30px; width: 100px; color: green; font-size: 28px; } + +#vspan { position: absolute; right: 1em; bottom: 1em; } +#vspeed { position: absolute; top: 16px; width: 100px; color: cyan; font-size: 42px; } +*/ + +#cluster { + position: absolute; + bottom:0; + left:0; + right:0; + background: rgba(50,50,50,.4); + height: 43%; + border-top: 2px outset silver; + border-top-left-radius: 50%; + border-top-right-radius: 50%; +} + +#torqueGauge { position: absolute; bottom: -2%; left: 1%; width: 14%; } +#rpmGauge { position: absolute; bottom: -4%; left: 16%; width: 21%; } +#speedGauge { position: absolute; bottom: -3%; left: 38%; width: 24%; } +#MAFGauge { position: absolute; bottom: -4%; right: 16%; width: 21%; } +#IATempGauge { position: absolute; bottom: -2%; right: 1%; width: 14%; } + +/* in quad 2 */ +#mapstreet { + position: absolute; + width: 100%; + height: 100%; +} + +#car { + position: absolute; + top: 50%; + left: 50%; + z-index: 2000; + +} + +#gaspan { position: absolute; bottom:0; left:0; right:0; background: rgba(200,200,200,.3); padding: 1em; z-index: 2000;} + +#gas { position: relative; float: right; width: 69px; height: 92px; } +#gas div { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; overflow: hidden; } + +#copan { overflow: hidden; min-height: 50px; position: relative; height: 92px;} +#copan div { + display:inline; + position: absolute; + bottom: 0; + width: 10%; + height: 0%; + font-size: 10px; + color: black; + background: yellow; + border: 1px solid grey; + padding: 0; +} +#copan div p { + text-align: center; + position: absolute; + bottom: 2px; + margin: 0; + width: 100%; +} + +#con1 { left: 0%; } +#con2 { left: 11%; } +#con3 { left: 22%; } +#con4 { left: 33%; } +#con5 { left: 44%; } +#con6 { left: 55%; } +#con7 { left: 66%; } +#con8 { left: 77%; } +#con9 { left: 88%; } + +#gpblack { background: url(/images/gas-pump-black.png); } +#gpgreen { background: url(/images/gas-pump-green.png); } +#gpred { background: url(/images/gas-pump-red.png); visibility: hidden; } + +/* quad 3 */ +#xcdata { + text-align: left; +} + +.leaflet-control-layers-toggle { + background-image: url(/images/layers.png); +} + +/* quad 4 */ +#mapsat { + position: absolute; + width: 100%; + height: 100%; +} + -- cgit 1.2.3-korg