diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5c3606a..3c06140 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## v1.1.0 (2024-07-02)
+- Updated documentation
+
## v1.0.0 (2023-11-23)
- Initial release
- New documentation
diff --git a/README.md b/README.md
index 699f328..9076ee2 100644
--- a/README.md
+++ b/README.md
@@ -113,14 +113,12 @@ To reset the saved skin, you can use the `Reset settings` button in the control
> [!NOTE]
> To debug Javascript and network errors, use the browser's developer tools console (F12).
-### ⚪ Emulate hardware connection
-To emulate a hardware connection, you can use the `Server connection` toggle in the control panel.
+### ⚪ Emulate Server connection
+To emulate a hardware connection, you can use the `Toggle Server connection` button in the control panel.
This will toggle the `connected` class on the `container` element, which you can use to style and animate your skin accordingly.
Use this flag to set your skin in a "connected" state, meaning the UI successfully connects to the hardware.
-### ⚪ Emulate Real-time data
-You can use the `Real-time data` toggle in the control panel to emulate hardware data.
-This will trigger a simulated data stream that you can use to test your skin's UI.
+This will also trigger a simulated data stream that you can use to test your skin's UI.
Make sure to test your skin thoroughly with different combinations of settings, since they can change the behaviour of the UI.
### ⚪ Emulate animations
@@ -526,6 +524,21 @@ const bindRealtimeData = () => {
```
+### `checkSource(): void`
+Shortcut method to check if the CAN source is still available and update the most common channels based on the user's settings - RPM, VSS and CLT.
+
+This method is a wrapper around `useCanChannel` and should be called inside your `bindRealtimeData` method. It will update the `useCANForRPM`, `useCANForVSS` and `useCANForCLT` variables, which you can use to get the data from the correct data set.
+
+```js
+const bindRealtimeData = () => {
+ if (!checkCache('useCAN', useCanChannel())) checkSource();
+ updateRPM(useCANForRPM ? canData.rpm : safeReturn(basicData, 'rpm'))
+ updateVSS(useCANForVSS ? canData.vss : safeReturn(basicData, 'kmh'))
+ updateCLT(useCANForCLT ? canData.clt : safeReturn(basicData, 'clt'))
+}
+```
+
+
### ⚡ Available data sets
### ⚪ **Basic** data set
diff --git a/assets/client.js b/assets/client.js
index 6cf0975..c932e98 100644
--- a/assets/client.js
+++ b/assets/client.js
@@ -1 +1 @@
-const resetData={canData:{rpm:0,vss:0,tps:0,map:0,clt:0,mat:0,oilPress:0,oilTemp:0,fuelPress:0,gear:"N",lambda:0,afr:0,batt:0,boost:0,odoNow:0,mapbar:0},basicData:{rpm:0,kmh:0,kmhF:0,clt:0,lvlFuel:0,lvlFuelF:0,turnLeft:1,turnRight:1,parkLights:1,fogLights:1,auxLights:1,highBeam:1,eBrake:1,battAlt:1,ECUErr:1,oilSwitch:1,rearDefrost:1,fan:1,openDoor:1,airbag:1,odoNow:0}};let canData=resetData.canData,basicData=resetData.basicData,isECUOnline=!1,isBasicOnline=!1,odoDebounce=!1,DASH_OPTIONS={...defaultOptions,...JSON.parse(localStorage.getItem(CONFIG.CONFIG_STORAGE_KEY))||{}},lastTime=0,tick=0,enableSimulator=!1;const COLORS=DASH_OPTIONS.theme.colors,elemCache={},root=document.documentElement,mainContainer=document.getElementById("container"),saveSettings=a=>{DASH_OPTIONS=JSON.parse(localStorage.getItem(CONFIG.CONFIG_STORAGE_KEY))||{},DASH_OPTIONS={...defaultOptions,...DASH_OPTIONS,...a},localStorage.setItem(CONFIG.CONFIG_STORAGE_KEY,JSON.stringify(DASH_OPTIONS))},disconnect=()=>{enableSimulator=!1,setTimeout((()=>{isECUOnline=!1,isBasicOnline=!1}),100),mainContainer.classList.remove("connected")},openConnection=a=>{enableSimulator=!0,isECUOnline=!0,isBasicOnline=!0,mainContainer.classList.add("connected"),requestAnimationFrame(a)},checkCache=(a,t)=>{const e="string"==typeof a?a:a.getAttribute("id");return elemCache[e]===t||(elemCache[e]=t,!1)},etoggle=(a,t)=>{a&&!checkCache(a,t)&&a.setAttribute("data-etoggle",1-t)},setText=(a,t)=>{a&&!checkCache(a,t)&&(a.textContent=t)},setRootCSS=(a,t)=>{a&&!checkCache(a,t)&&root.style.setProperty(a,t)},setGaugeValue=(a,t,e=null)=>{a&&a.value&&!checkCache(`${a.id}-now`,t)&&(e&&root.style.setProperty(`--${a.id}-bar`,e),a.value.textContent=t)},setIconOpacity=(a,t)=>setRootCSS(`--${a}-icon`,1-t),zeroFixed=a=>Math.round(a||0),oneFixed=a=>Math.round(10*(a||0))/10,twoFixed=a=>Math.round(100*(a||0))/100,mapFormat=a=>+a<1?`-${(""+a).substring(1,4)}`:(+a-1).toFixed(2),boostFormat=a=>+a<1?0:twoFixed(+a-1),safeReturn=(a,t,e=0)=>a[t]||e,mapBarFormat=a=>a<0?a/2:a/(2*DASH_OPTIONS.pBoost),setGaugeBar=(a,t,e=!1,o)=>{a&&!checkCache(`${a}-gauge-bar`,t)&&root.style.setProperty(`--${a}-gauge-bar`,e?+t/(o||DASH_OPTIONS[a])*100+"%":+t/(o||DASH_OPTIONS[a]))},setCLTBar=(a,t)=>setGaugeBar("clt",a,t),setMATBar=(a,t)=>setGaugeBar("mat",a,t),setOilPressBar=(a,t)=>setGaugeBar("pOil",a,t),setFuelPressBar=(a,t)=>setGaugeBar("pFuel",a,t),setBoostBar=(a,t)=>setGaugeBar("pBoost",a,t),setOilTempBar=(a,t)=>setGaugeBar("tOil",a,t),setFuelLevelBar=(a,t)=>setGaugeBar("lFuel",a,t,100),setBatteryBar=(a,t)=>setGaugeBar("batt",a,t),setSpeedBar=(a,t)=>setGaugeBar("spdM",a,t),setRPMBar=(a,t)=>setGaugeBar("rpmM",a,t,1e3*DASH_OPTIONS.rpmM),setTPSBar=(a,t)=>setGaugeBar("tps",a,t,100),setAFRBar=(a,t)=>setGaugeBar("afr",a,t,20),setLambdaBar=(a,t)=>setGaugeBar("lambda",a,t,2),fuelLevelFormat=(a,t)=>{const e=safeReturn(a,t);return zeroFixed(e>100?100:e<0?0:e)},loadOdo=(a,t,e,o=!1)=>{const s=DASH_OPTIONS.kmTrip+e,r=DASH_OPTIONS.kmTotal+e;setText(t,zeroFixed(s)),setText(a,zeroFixed(+DASH_OPTIONS.tKm+r)),o&&saveSettings({kmTrip:s,kmTotal:r})},updateOdo=(a,t,e)=>{0===DASH_OPTIONS.kmTrip&&setText(t,0),0===e||odoDebounce||isNaN(e)||(odoDebounce=!0,loadOdo(a,t,e,!0),setTimeout((()=>{odoDebounce=!1}),1e3))},resetOdo=()=>saveSettings({kmTrip:0}),useCanChannel=(a=null)=>isECUOnline&&DASH_OPTIONS.sCan<2&&(!a||DASH_OPTIONS[a]>1),randomStatus=a=>Math.floor(20*Math.random())>18?!a:a,simulateGear=a=>a>2?a-2:["P","N","R"][a],simulator=a=>{if(a-lastTime>33&&enableSimulator){tick=tick>999?0:tick+1;const e=tick>499?(1e3-tick)/500:tick/500;canData={rpm:e*+DASH_OPTIONS.rpmM*1e3,vss:e*+DASH_OPTIONS.spdM,tps:(100*e).toFixed(1),map:(e*(+DASH_OPTIONS.pBoost+1)).toFixed(2),clt:(e*+DASH_OPTIONS.clt).toFixed(0),mat:(e*+DASH_OPTIONS.mat).toFixed(0),oilPress:(e*+DASH_OPTIONS.pOil).toFixed(1),oilTemp:(e*+DASH_OPTIONS.tOil).toFixed(0),fuelPress:(e*+DASH_OPTIONS.pFuel).toFixed(1),gear:(t=zeroFixed(10*e),t>2?t-2:["P","N","R"][t]),boost:e*+DASH_OPTIONS.pBoost,batt:(e*+DASH_OPTIONS.batt).toFixed(1),lambda:(2*e).toFixed(2),afr:(8+12*e).toFixed(2),odoNow:tick%250==0?1:0},basicData={rpm:canData.rpm,kmh:canData.vss,kmhF:canData.vss,clt:canData.clt,lvlFuel:100*e,lvlFuelF:100*e,odoNow:canData.odoNow,turnLeft:randomStatus(basicData.turnLeft),turnRight:randomStatus(basicData.turnRight),parkLights:randomStatus(basicData.parkLights),fogLights:randomStatus(basicData.fogLights),auxLights:randomStatus(basicData.auxLights),highBeam:randomStatus(basicData.highBeam),eBrake:randomStatus(basicData.eBrake),battAlt:randomStatus(basicData.battAlt),ECUErr:randomStatus(basicData.ECUErr),oilSwitch:randomStatus(basicData.oilSwitch),rearDefrost:randomStatus(basicData.rearDefrost),fan:randomStatus(basicData.fan),openDoor:randomStatus(basicData.openDoor),airbag:randomStatus(basicData.airbag)},lastTime=a}var t;enableSimulator||(canData=resetData.canData,basicData=resetData.basicData,tick=0),requestAnimationFrame(simulator)};requestAnimationFrame(simulator);const toggleSimulator=()=>{if(enableSimulator)return enableSimulator=!1,void disconnect();enableSimulator=!0,openConnection((()=>null))};window.addEventListener("load",(()=>{window.addEventListener("message",(a=>{switch(a.data.action){case"odoreset":saveSettings({kmTrip:0});break;case"toggleSimulator":toggleSimulator();break;case"animIn":setTimeout((()=>openConnection((()=>null))),6500),mainContainer.classList.replace("anim-out","anim-in");break;case"animOut":disconnect(),mainContainer.classList.replace("anim-in","anim-out");break;default:break}}),!1)}));
+const resetData={canData:{rpm:0,vss:0,tps:0,map:0,clt:0,mat:0,oilPress:0,oilTemp:0,fuelPress:0,gear:"N",lambda:0,afr:0,batt:0,boost:0,odoNow:0,mapbar:0,afrbar:0,oilPressBar:0,fuelPressBar:0},basicData:{rpm:0,kmh:0,kmhF:0,clt:0,lvlFuel:0,lvlFuelF:0,turnLeft:1,turnRight:1,parkLights:1,fogLights:1,auxLights:1,highBeam:1,eBrake:1,battAlt:1,ECUErr:1,oilSwitch:1,rearDefrost:1,fan:1,openDoor:1,airbag:1,odoNow:0}};let canData=resetData.canData,basicData=resetData.basicData,isECUOnline=!1,isBasicOnline=!1,odoDebounce=!1,DASH_OPTIONS={...defaultOptions,...JSON.parse(localStorage.getItem(CONFIG.CONFIG_STORAGE_KEY))||{}},lastTime=0,tick=0,enableSimulator=!1,useCAN=!1,useCANForRPM=!1,useCANForVSS=!1,useCANForCLT=!1;const COLORS=DASH_OPTIONS.theme.colors,elemCache={},root=document.documentElement,mainContainer=document.getElementById("container"),iconStyle=+DASH_OPTIONS.icon,saveSettings=a=>{DASH_OPTIONS=JSON.parse(localStorage.getItem(CONFIG.CONFIG_STORAGE_KEY))||{},DASH_OPTIONS={...defaultOptions,...DASH_OPTIONS,...a},localStorage.setItem(CONFIG.CONFIG_STORAGE_KEY,JSON.stringify(DASH_OPTIONS))},disconnect=()=>{enableSimulator=!1,setTimeout((()=>{isECUOnline=!1,isBasicOnline=!1}),100),mainContainer.classList.remove("connected")},openConnection=a=>{enableSimulator=!0,isECUOnline=!0,isBasicOnline=!0,mainContainer.classList.add("connected"),requestAnimationFrame(a)},checkCache=(a,e)=>{const t="string"==typeof a?a:a.getAttribute("id");return elemCache[t]===e||(elemCache[t]=e,!1)},etoggle=(a,e)=>{a&&!checkCache(a,e)&&a.setAttribute("data-etoggle",1-e)},setText=(a,e)=>{a&&!checkCache(a,e)&&(a.textContent=e)},setRootCSS=(a,e)=>{a&&!checkCache(a,e)&&root.style.setProperty(a,e)},setGaugeValue=(a,e,t=null)=>{a&&a.value&&!checkCache(`${a.id}-now`,e)&&(t&&root.style.setProperty(`--${a.id}-bar`,t),a.value.textContent=e)},setSVGGaugeValue=(a,e,t)=>{a&&e&&!checkCache(e,t)&&a.setValue(t)},setIconOpacity=(a,e)=>setRootCSS(`--${a}-icon`,1-e),zeroFixed=a=>Math.round(a||0),oneFixed=a=>Math.round(10*(a||0))/10,twoFixed=a=>Math.round(100*(a||0))/100,mapFormat=a=>+a<1?`-${(""+a).substring(1,4)}`:(+a-1).toFixed(2),boostFormat=a=>+a<1?0:twoFixed(+a-1),gtZero=a=>+a<0?0:a,safeReturn=(a,e,t=0)=>a[e]||t,mapBarFormat=a=>a<0?a/2:a/(2*DASH_OPTIONS.pBoost),setGaugeBar=(a,e,t=!1,s)=>{a&&!checkCache(`${a}-gauge-bar`,e)&&root.style.setProperty(`--${a}-gauge-bar`,t?+e/(s||DASH_OPTIONS[a])*100+"%":+e/(s||DASH_OPTIONS[a]))},setCLTBar=(a,e)=>setGaugeBar("clt",a,e),setMATBar=(a,e)=>setGaugeBar("mat",a,e),setOilPressBar=(a,e)=>setGaugeBar("pOil",a,e),setFuelPressBar=(a,e)=>setGaugeBar("pFuel",a,e),setBoostBar=(a,e)=>setGaugeBar("pBoost",a,e),setOilTempBar=(a,e)=>setGaugeBar("tOil",a,e),setFuelLevelBar=(a,e)=>setGaugeBar("lFuel",a,e,100),setBatteryBar=(a,e)=>setGaugeBar("batt",a,e),setSpeedBar=(a,e)=>setGaugeBar("spdM",a,e),setRPMBar=(a,e)=>setGaugeBar("rpmM",a,e,1e3*DASH_OPTIONS.rpmM),setTPSBar=(a,e)=>setGaugeBar("tps",a,e,100),setAFRBar=(a,e)=>setGaugeBar("afr",a,e,20),setLambdaBar=(a,e)=>setGaugeBar("lambda",a,e,2),fuelLevelFormat=(a,e,t=100)=>{const s=safeReturn(a,e);return zeroFixed(s>t?t:s<0?0:s)},loadOdo=(a,e,t,s=!1)=>{const o=DASH_OPTIONS.kmTrip+t,r=DASH_OPTIONS.kmTotal+t;setText(e,zeroFixed(o)),setText(a,zeroFixed(+DASH_OPTIONS.tKm+r)),s&&saveSettings({kmTrip:o,kmTotal:r})},updateOdo=(a,e,t)=>{0===DASH_OPTIONS.kmTrip&&setText(e,0),0===t||odoDebounce||isNaN(t)||(odoDebounce=!0,loadOdo(a,e,t,!0),setTimeout((()=>{odoDebounce=!1}),1e3))},resetOdo=()=>saveSettings({kmTrip:0}),useCanChannel=(a=null)=>isECUOnline&&DASH_OPTIONS.sCan<2&&(!a||DASH_OPTIONS[a]>1),randomStatus=a=>Math.floor(20*Math.random())>18?!a:a,simulateGear=a=>a>2?a-2:["P","N","R"][a],simulator=a=>{if(a-lastTime>33&&enableSimulator){tick=tick>999?0:tick+1;const t=tick>499?(1e3-tick)/500:tick/500;canData={rpm:t*+DASH_OPTIONS.rpmM*1e3,vss:t*+DASH_OPTIONS.spdM,tps:(100*t).toFixed(1),map:(t*(+DASH_OPTIONS.pBoost+1)).toFixed(2),clt:(t*+DASH_OPTIONS.clt).toFixed(0),mat:(t*+DASH_OPTIONS.mat).toFixed(0),oilPress:(t*+DASH_OPTIONS.pOil).toFixed(1),oilTemp:(t*+DASH_OPTIONS.tOil).toFixed(0),fuelPress:(t*+DASH_OPTIONS.pFuel).toFixed(1),gear:(e=zeroFixed(10*t),e>2?e-2:["P","N","R"][e]),boost:t*+DASH_OPTIONS.pBoost,batt:(t*+DASH_OPTIONS.batt).toFixed(1),lambda:(2*t).toFixed(2),afr:(8+12*t).toFixed(2),odoNow:tick%250==0?1:0,mapbar:3*t-1,afrbar:100*t,oilPressBar:1*t,fuelPressBar:1*t},basicData={rpm:canData.rpm,kmh:canData.vss,kmhF:canData.vss,clt:canData.clt,lvlFuel:100*t,lvlFuelF:100*t,odoNow:canData.odoNow,turnLeft:randomStatus(basicData.turnLeft),turnRight:randomStatus(basicData.turnRight),parkLights:randomStatus(basicData.parkLights),fogLights:randomStatus(basicData.fogLights),auxLights:randomStatus(basicData.auxLights),highBeam:randomStatus(basicData.highBeam),eBrake:randomStatus(basicData.eBrake),battAlt:randomStatus(basicData.battAlt),ECUErr:randomStatus(basicData.ECUErr),oilSwitch:randomStatus(basicData.oilSwitch),rearDefrost:randomStatus(basicData.rearDefrost),fan:randomStatus(basicData.fan),openDoor:randomStatus(basicData.openDoor),airbag:randomStatus(basicData.airbag)},lastTime=a}var e;enableSimulator||(canData=resetData.canData,basicData=resetData.basicData,tick=0),requestAnimationFrame(simulator)};requestAnimationFrame(simulator);const toggleSimulator=()=>{if(enableSimulator)return enableSimulator=!1,void disconnect();enableSimulator=!0,openConnection((()=>null))},switchIcons=a=>{for(let e=0;e[useCAN,useCANForRPM,useCANForVSS,useCANForCLT]=[useCanChannel(),useCanChannel("sRpm"),useCanChannel("sVss"),useCanChannel("sClt")],userBackground=()=>DASH_OPTIONS.bgImage?`${CONFIG.USER_IMAGE_PATH}${DASH_OPTIONS.bgImage}`:null;window.addEventListener("load",(()=>{window.addEventListener("message",(a=>{switch(a.data.action){case"odoreset":saveSettings({kmTrip:0});break;case"toggleSimulator":toggleSimulator();break;case"animIn":setTimeout((()=>openConnection((()=>null))),6500),mainContainer.classList.replace("anim-out","anim-in");break;case"animOut":disconnect(),mainContainer.classList.replace("anim-in","anim-out");break;default:break}}),!1)}));
diff --git a/assets/defaultSettings.js b/assets/defaultSettings.js
index 4abf96a..de6aabc 100644
--- a/assets/defaultSettings.js
+++ b/assets/defaultSettings.js
@@ -1 +1 @@
-const CONFIG={EXAMPLE_PATH:"./community",BASE_PATH:"./base/",CONFIG_STORAGE_KEY:"config",DEV_PATH_KEY:"devpath"},defaultOptions={rpmM:8,sLigt:"5250",redline:"5500",icon:1,clt:"110",mat:"110",pOil:"10",tOil:"120",pFuel:"6",pBoost:"2",tKm:"0",sCan:1,aSpd:1,sRpm:2,sVss:1,sClt:2,theme:{colors:{cMain:"#00d3ff",cSec:"#e43f01",cRed:"#b70000",cBg:"#000000",cRpm:"#00d3ff"},active:"base"},kmTrip:0,kmTotal:0,batt:"20",spdM:"300"};
+const CONFIG={EXAMPLE_PATH:"./community",BASE_PATH:"./base/",CONFIG_STORAGE_KEY:"config",DEV_PATH_KEY:"devpath"},defaultOptions={rpmM:8,sLigt:"5250",redline:"5500",icon:1,clt:"110",mat:"110",pOil:"10",tOil:"120",pFuel:"6",pBoost:"2",tKm:"0",sCan:1,aSpd:1,sRpm:2,sVss:1,sClt:2,theme:{colors:{cMain:"#00d3ff",cSec:"#e43f01",cRed:"#b70000",cBg:"#000000",cRpm:"#00d3ff"},active:"base"},kmTrip:0,kmTotal:0,batt:"20",spdM:"300",demo:0,bgImage:null,inVideo:null,inMsg:null,oilSwM:2,thVar:1};
diff --git a/assets/fonts/7segment.ttf b/assets/fonts/7segment.ttf
new file mode 100644
index 0000000..a6e1730
Binary files /dev/null and b/assets/fonts/7segment.ttf differ
diff --git a/assets/svgGauges.js b/assets/svgGauges.js
new file mode 100644
index 0000000..e8ca0b2
--- /dev/null
+++ b/assets/svgGauges.js
@@ -0,0 +1 @@
+!function(e,t){let n=function(e,t){function n(e){let t=e.duration,n=1,a=60*t,i=e.start||0,o=e.end,u=o-i,r=e.step,s=e.easing||function(e){return(e/=.5)<1?.5*Math.pow(e,3):.5*(Math.pow(e-2,3)+2)};l(function e(){let t=n/a,o=u*s(t)+i;r(o,n),n+=1,t<1&&l(e)})}let a=e.document,i=Array.prototype.slice,l=e.requestAnimationFrame||e.mozRequestAnimationFrame||e.webkitRequestAnimationFrame||e.msRequestAnimationFrame||function(e){return setTimeout(e,1e3/60)};return function(){function e(){let e=arguments[0],t=i.call(arguments,1);return t.forEach(function(t){for(k in t)t.hasOwnProperty(k)&&(e[k]=t[k])}),e}function t(e,t,n){let i=a.createElementNS(s,e);for(let e in t)i.setAttribute(e,t[e]);return n&&n.forEach(function(e){i.appendChild(e)}),i}function l(e,t){return e*t/100}function o(e,t,n){let a=Number(e);return a>n?n:a--e*e*e+1}))},getValue:function(){return A}},function(e){f=t("text",{x:50,y:50,fill:"#999",class:y,"font-size":"100%","font-family":"sans-serif","font-weight":"normal","text-anchor":"middle","alignment-baseline":"middle","dominant-baseline":"central"}),m=t("path",{class:k,fill:"none",stroke:"#666","stroke-width":2.5,d:u(x,b,b)});let n=l(100,360-Math.abs(b-C)),a=t("svg",{viewBox:q||"0 0 100 100",class:V},[t("path",{class:M,fill:"none",stroke:"#eee","stroke-width":2,d:u(x,b,C,n<=180?0:1)}),f,m]);e.appendChild(a)}(h),g.setValue(A),g}}()}(e);"function"==typeof define&&define.amd?define(function(){return n}):"object"==typeof module&&module.exports?module.exports=n:e.Gauge=n}("undefined"==typeof window?this:window);
diff --git a/base/script.js b/base/script.js
index b878561..1e9885e 100644
--- a/base/script.js
+++ b/base/script.js
@@ -15,7 +15,6 @@ const callback = () => {
const { cMain, cSec, cRed } = COLORS
const { aSpd, redline, icon } = DASH_OPTIONS
const maxRPM = 8000;
- let [useCAN, useCANForRPM, useCANForVSS, useCANForCLT] = [false, false, false, false]
// Set static parameters
setRootCSS('--background-color', cMain);
@@ -40,14 +39,6 @@ const callback = () => {
setRootCSS('--kmh-deg', `${(155 + ((val/160)*230))}deg`)
}
- // Cache the settings for channel sources locally
- const checkSource = () => [useCAN, useCANForRPM, useCANForVSS, useCANForCLT] = [
- useCanChannel(),
- useCanChannel('sRpm'),
- useCanChannel('sVss'),
- useCanChannel('sClt'),
- ]
-
// Bind the realtime data to the DOM
const bindRealtimeData = () => {
// Check if the source has changed and update the cache
diff --git a/community/147/147.cdr b/community/147/147.cdr
new file mode 100644
index 0000000..d82d1b8
Binary files /dev/null and b/community/147/147.cdr differ
diff --git "a/community/147/C\303\263pia_de_seguran\303\247a_de_147.cdr" "b/community/147/C\303\263pia_de_seguran\303\247a_de_147.cdr"
new file mode 100644
index 0000000..65fa021
Binary files /dev/null and "b/community/147/C\303\263pia_de_seguran\303\247a_de_147.cdr" differ
diff --git a/community/digifiz/img/bottom-mask.png b/community/digifiz/img/bottom-mask.png
new file mode 100644
index 0000000..9bca7fc
Binary files /dev/null and b/community/digifiz/img/bottom-mask.png differ
diff --git a/community/digifiz/img/clt-meter.svg b/community/digifiz/img/clt-meter.svg
new file mode 100644
index 0000000..0eaf8be
--- /dev/null
+++ b/community/digifiz/img/clt-meter.svg
@@ -0,0 +1,8 @@
+
diff --git a/community/digifiz/img/rpm-bar.png b/community/digifiz/img/rpm-bar.png
new file mode 100644
index 0000000..e432e1c
Binary files /dev/null and b/community/digifiz/img/rpm-bar.png differ
diff --git a/community/digifiz/img/rpm-mask.svg b/community/digifiz/img/rpm-mask.svg
new file mode 100644
index 0000000..4966dea
--- /dev/null
+++ b/community/digifiz/img/rpm-mask.svg
@@ -0,0 +1,6 @@
+
diff --git a/community/digifiz/img/spd-bg.svg b/community/digifiz/img/spd-bg.svg
new file mode 100644
index 0000000..eeb4563
--- /dev/null
+++ b/community/digifiz/img/spd-bg.svg
@@ -0,0 +1,5 @@
+
diff --git a/community/digifiz/img/turbo-meter.svg b/community/digifiz/img/turbo-meter.svg
new file mode 100644
index 0000000..ffadae6
--- /dev/null
+++ b/community/digifiz/img/turbo-meter.svg
@@ -0,0 +1,5 @@
+
diff --git a/community/digifiz/index.html b/community/digifiz/index.html
new file mode 100644
index 0000000..6d40680
--- /dev/null
+++ b/community/digifiz/index.html
@@ -0,0 +1,148 @@
+
+
+
+
+
+ Dashboard
+
+
+
+
+
+