Skip to content

Commit

Permalink
Added charge dischage guage
Browse files Browse the repository at this point in the history
  • Loading branch information
ieb committed Jun 23, 2024
1 parent 78600f5 commit 9b55727
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 1 deletion.
1 change: 1 addition & 0 deletions ui/lifepo4/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ The Bluetooth adapter for these BMS exposes Modbus RTE from the BMS UART over 2
- [x] Convert into a PWA.
- [x] Extend time window to 24h and allow zooming into the graphs.
- [-] ~~Make the BLE work in the background ~~ The Web Bluetooth API is not available in any background task.
- [x] Add charge discharge gauge in svg

110 changes: 110 additions & 0 deletions ui/lifepo4/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,117 @@
<button id="disconnect" class="hidden">Disconnect</button>
<div>

<div>
</div>

<div class="bms">
<svg id="currentWidget" height="200" width="200" class="guage" >
<defs>
<linearGradient id="currentGradCharge" x1="0" y1="0" x2="1" y2="1">
<stop offset="15%" stop-color="orange" stop-opacity="1"></stop>
<stop offset="85%" stop-color="yellow" stop-opacity="1"></stop>
</linearGradient>
<linearGradient id="currentGradDischarge" x1="0" y1="0" x2="1" y2="1">
<stop offset="15%" stop-color="red" stop-opacity="1"></stop>
<stop offset="85%" stop-color="blue" stop-opacity="1"></stop>
</linearGradient>
<path
id="guageCurrentTextPath"
fill="none"
stroke="red"
d="M64.64,64.64 A 50 50 0 0 1 135.35,64.64" />

<path
id="guageStateOfChargeTextPath"
fill="none"
stroke="red"
d="M64.64,135.35 A 50 50 0 0 0 135.35,135.35" />
</defs>

<!-- the stroke color indicates charg vs discharge
the dasharray dash is the %, full scale is pi*d*270/360.
dash is percent*full scale is pi*d*270/360
-->

<circle
class="guageBase"
id="currentBase"
cx="100"
cy="100"
fill="transparent"
stroke="gray"
r="75"
stroke-width="25"
stroke-dasharray="353 471"
transform="rotate(135, 100, 100)"
/>
<circle
class="guagePercent"
id="currentGuage"
cx="100"
cy="100"
fill="transparent"
r=75
stroke="url(#currentGradCharge)"
stroke-width="25"
stroke-dasharray="87 471"
transform="rotate(135, 100, 100)"
style="transition: stroke-dasharray 0.3s"
/>

<!-- bottom arc charge
green filling the whole arc
overlayed by dark grey giving the impression that the green
sector is the qauge, easier to do but the dash array for the grey sector has
to be adjusted to 1-%
full scale is 0 dash
0 is pi*d*90/360
dash is (1-percent)*(p*d*90/360)
-->
<circle
class="guageSubBase"
id="stateOfChargeBase"
cx="100"
cy="100"
fill="transparent"
stroke="green"
r="75"
stroke-width="25"
stroke-dasharray="120 471"
transform="rotate(45, 100, 100)"
style="transition: stroke 0.3s"
/>

<circle
class="guageSubPercent"
id="chargeGuage"
cx="100"
cy="100"
fill="transparent"
stroke="darkgrey"
r="75"
stroke-width="25"
stroke-dasharray="90 471"
transform="rotate(45, 100, 100)"
style="transition: stroke-dasharray 0.3s"
/>



<!-- annotations
current in the center.
soc and voltage below that.
-->
<text id="guageVoltageText" x="100" y="100" alignment-baseline="middle" text-anchor="middle">?v</text>
<text text-anchor="middle" >
<textPath id="guageCurrentText" startOffset="50%" alignment-baseline="middle" href="#guageCurrentTextPath">?A</textPath>
</text>
<text text-anchor="middle" >
<textPath id="guageStateOfChargeText" startOffset="50%" alignment-baseline="middle" href="#guageStateOfChargeTextPath">?Ah</textPath>
</text>


</svg>
<ul class="state">
<li>State</li>
<li>Voltage: <span id="status.voltage">?</span> V</li>
Expand Down
32 changes: 32 additions & 0 deletions ui/lifepo4/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ window.addEventListener('load', () => {
document.getElementById('connect').addEventListener('click', bleReader.connectBMS);
document.getElementById('disconnect').addEventListener('click', bleReader.disconnectBMS);


const setInnerHtmlById = (id, value) => {
const el = document.getElementById(id);
if (el) {
Expand All @@ -69,7 +70,38 @@ window.addEventListener('load', () => {
setClass('disconnect', connected, '', 'hidden');
});

const updateGuage = (statusUpdate) => {
setInnerHtmlById('guageVoltageText', `${statusUpdate.voltage.toFixed(2)}V`);
setInnerHtmlById('guageCurrentText', `${statusUpdate.current.toFixed(1)}A`);
const stateOfChargeAh = (statusUpdate.capacity.stateOfCharge / 100)
* statusUpdate.capacity.fullCapacity;
setInnerHtmlById('guageStateOfChargeText', `${stateOfChargeAh.toFixed(0)}Ah`);
setClass('currentWidget', (statusUpdate.current > 0), 'charging', 'discharging');


const currentGuage = document.getElementById('currentGuage');

const currentGuageLength = (Math.abs(statusUpdate.current) / 100) * 353;
currentGuage.setAttribute('stroke-dasharray', `${currentGuageLength} 471`);
if (statusUpdate.current > 0) {
currentGuage.setAttribute('stroke', 'url(#currentGradCharge)');
} else {
currentGuage.setAttribute('stroke', 'url(#currentGradDischarge)');
}

const stateOfChargeGauge = document.getElementById('chargeGuage');
const stateOfChargeBase = document.getElementById('stateOfChargeBase');

const stateOfChageLength = 120 - (statusUpdate.capacity.stateOfCharge / 100) * 120;
stateOfChargeGauge.setAttribute('stroke-dasharray', `${stateOfChageLength} 471`);

const socp = Math.min(100, 10 * Math.floor((statusUpdate.capacity.stateOfCharge + 5) / 10));
stateOfChargeBase.setAttribute('class', `guageSubBase_${socp}`);
};

bleReader.on('statusUpdate', (statusUpdate) => {
updateGuage(statusUpdate);

setInnerHtmlById('status.voltage', statusUpdate.voltage.toFixed(2));
setInnerHtmlById('status.current', statusUpdate.current.toFixed(1));
setInnerHtmlById('status.capacity.stateOfCharge', statusUpdate.capacity.stateOfCharge.toFixed(0));
Expand Down
44 changes: 43 additions & 1 deletion ui/lifepo4/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,46 @@ body {

.hidden {
display: none;
}
}

.guage text {
fill: white;
}

#guageVoltageText {
font-size: 2rem;
}

.guageSubBase_0 {
stroke: #ff1f00;
}
.guageSubBase_10 {
stroke: #ff5b00f7;
}
.guageSubBase_20 {
stroke: #ff8b00f7;
}
.guageSubBase_30 {
stroke: #ffba00f7;
}
.guageSubBase_40 {
stroke: #ffdf00f7;
}
.guageSubBase_50 {
stroke: #daff00f7;
}
.guageSubBase_60 {
stroke: #5fd80bf7;
}
.guageSubBase_70 {
stroke: #24d80bf7;
}
.guageSubBase_80 {
stroke: #14c20af7;
}
.guageSubBase_90 {
stroke: #1ba213f7;
}
.guageSubBase_100 {
stroke: #228c1cf7;
}

0 comments on commit 9b55727

Please sign in to comment.