Colored volume bar

Dashticz, alternative dashboard based on HTML, CSS, jQuery

Moderators: leecollings, htilburgs, robgeerts

Post Reply
Beschuitje
Posts: 32
Joined: Saturday 24 February 2018 12:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Colored volume bar

Post by Beschuitje »

Searched the forum and readthedocs but doesn't seem to be there. Tried some stuf but getting nowhere.
Is it possible to make a 'colored volume bar' in Dashticz from lets say the solar panels or P1 like the one on Eneco Toon?

The volume bar showing the actual usage but when you click on it, it opens the 24h graph?

Image
Attachments
Toon graph.png
Toon graph.png (8.65 KiB) Viewed 471 times
Lokonli
Posts: 2271
Joined: Monday 29 August 2016 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Colored volume bar

Post by Lokonli »

yes :)

Can you find some js and/or CSS examples?
Beschuitje
Posts: 32
Joined: Saturday 24 February 2018 12:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Colored volume bar

Post by Beschuitje »

Nice!

It's a challenging search which got me;
https://stackoverflow.com/questions/621 ... ical-linea
https://www.anychart.com/blog/2021/10/2 ... avascript/

Some on LED gauge meters;
https://www.fusioncharts.com/dev/chart- ... /led-gauge

which has html example;

Code: Select all

<html>
<head>
	<title>My first chart using FusionCharts Suite XT</title>
	<script type="text/javascript" src="https://cdn.fusioncharts.com/fusioncharts/latest/fusioncharts.js"></script>
	<script type="text/javascript" src="https://cdn.fusioncharts.com/fusioncharts/latest/themes/fusioncharts.theme.fusion.js"></script>
	<script type="text/javascript">
		FusionCharts.ready(function(){
			var chartObj = new FusionCharts({
    type: 'hled',
    renderAt: 'chart-container',
    width: '400',
    height: '150',
    dataFormat: 'json',
    dataSource: {
        "chart": {
            "caption": "Fuel Level Indicator",
            "lowerLimit": "0",
            "upperLimit": "100",
            "lowerLimitDisplay": "Empty",
            "upperLimitDisplay": "Full",
            "numberSuffix": "%",
            "valueFontSize": "12",
            "showhovereffect": "1",
            "origW": "400",
            "origH": "150",
            "ledSize": "3",
            "ledGap": "2",
            "manageResize": "1",
            "theme": "fusion"
        },
        //All annotations are grouped under this element
        "annotations": {
            "showbelow": "1",
            "groups": [{
                //Each group needs a unique ID
                "id": "indicator",
                "items": [

                    {
                        "id": "bgRectAngle",
                        //Polygon item
                        "type": "rectangle",
                        "alpha": "90",
                        "radius": "1",
                        "fillColor": "#6baa01",
                        "x": "$gaugeCenterX - 20",
                        "tox": "$gaugeCenterX + 20",
                        "y": "$gaugeEndY + 25",
                        "toy": "$gaugeEndY + 45"
                    }
                ]
            }]

        },
        "colorRange": {
            "color": [{
                "minValue": "0",
                "maxValue": "45",
                "code": "#e44a00"
            }, {
                "minValue": "45",
                "maxValue": "75",
                "code": "#f8bd19"
            }, {
                "minValue": "75",
                "maxValue": "100",
                "code": "#6baa01"
            }]
        },
        "value": "92"
    },
    "events": {
        "drawComplete": function(evt, arg) {
            var i,
                //Annotation
                annotations = evt.sender.annotations,
                //Value
                val = evt.sender.getData(),
                //Color Range Array
                crArr = evt.sender.args.dataSource.colorRange.color;

            for (var i = crArr.length - 1; i >= 0; i--) {
                //When value falls within the color range
                if (val >= crArr[i].minValue && val <= crArr[i].maxValue) {
                    annotations.update('bgRectAngle', {
                        "fillColor": crArr[i].code
                    });
                }
            }

        }
    }

}
);
			chartObj.render();
		});
	</script>
	</head>
	<body>
		<div id="chart-container">FusionCharts XT will load here!</div>
	</body>
</html>
Hope this works?
Lokonli
Posts: 2271
Joined: Monday 29 August 2016 22:40
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Colored volume bar

Post by Lokonli »

All the examples above use a paid charting library.

Dashticz is using chart.js, but that doesn't contain a good looking linear gauge chart.

If anyone knows a nice free example, please share here.
HvdW
Posts: 525
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: Colored volume bar

Post by HvdW »

And this?

Code: Select all

return {
    on = {
        devices = { 'Volume_Sensor' } -- Replace with your actual volume sensor device name
    },
    execute = function(domoticz, device)
        local volume = device.level
        local volumeBar = ""

        if volume <= 20 then
            volumeBar = "<font color='red'>█</font>"
        elseif volume <= 40 then
            volumeBar = "<font color='orange'>██</font>"
        elseif volume <= 60 then
            volumeBar = "<font color='yellow'>███</font>"
        elseif volume <= 80 then
            volumeBar = "<font color='lightgreen'>████</font>"
        else
            volumeBar = "<font color='green'>█████</font>"
        end

        domoticz.devices('Volume_Text_Device').updateText(volumeBar) -- Replace with your actual text device name
    end
}
Bugs bug me.
Beschuitje
Posts: 32
Joined: Saturday 24 February 2018 12:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Colored volume bar

Post by Beschuitje »

JBN
Posts: 40
Joined: Saturday 13 July 2013 8:00
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: Sweden
Contact:

Re: Colored volume bar

Post by JBN »

Interesting, I made a simple version for temperature (but didn't bother with a click function etc). Perhaps not something to build on, but an example where a linear gauge chart also might be applicable.
Skärmbild 2024-12-19 214749.png
Skärmbild 2024-12-19 214749.png (1.43 KiB) Viewed 336 times
Beschuitje
Posts: 32
Joined: Saturday 24 February 2018 12:07
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Colored volume bar

Post by Beschuitje »

Been looking into this but not my cup of tea so i used AI and it came up with this HTML code.

Code: Select all

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Live Power Meter</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
    <style>
        :root {
            --container-width: 200px; /* Standaard breedte */
            --container-height: 200px; /* Standaard hoogte */
        }

         body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: flex-start; /* Voor links uitlijning */
            align-items: center;
            height: 94vh;
            margin: 0;
            background-color: transparant;
		}

	.icon {
    	position: absolute;
    	top: 10px;  /* Pas de afstand van de bovenkant aan */
    	left: 10px; /* Pas de afstand van de linkerzijde aan */
    	font-size: 22px; /* Groote van het icoon */
    	color: grey;
   	cursor: pointer; /* Zorg ervoor dat de cursor verandert als je over het icoon beweegt */
	}

	.container {
    	position: relative;
    	width: 200px;
    	height: 180px;
    	display: flex;
    	flex-direction: column;
    	justify-content: center;
    	align-items: center;
    	border: 0px solid #ddd;
    	border-radius: 10px;
    	box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    	padding: 10px;
    	text-align: center;
	}

        .bar {
            display: flex;
            flex-direction: column-reverse;
            align-items: center;
            width: 60px;
            height: calc(var(--container-height) * 0.5); /* Dynamische hoogte */
            gap: 2px;
            cursor: pointer; /* Handje om te laten zien dat je erop kunt klikken */
        }

        .bar-segment {
            width: 100%;
            height: 15px;
            border-radius: 2px;
            background-color: lightgray;
        }

        /* Kleuren voor actieve streepjes */
        .level-1 { background-color: #004d40; } /* Donkergroen */
        .level-2 { background-color: #00796b; } /* Groen */
        .level-3 { background-color: #4caf50; } /* Lichtgroen */
        .level-4 { background-color: #cddc39; } /* Geelgroen */
        .level-5 { background-color: #ffeb3b; } /* Geel */
        .level-6 { background-color: #ffc107; } /* Oranjegeel */
        .level-7 { background-color: #ff9800; } /* Oranje */
        .level-8 { background-color: #f44336; } /* Rood */
        .level-9 { background-color: #d32f2f; } /* Donkerrood */
       
        #chartModal {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: white;
            border: 1px solid #ccc;
            padding: 20px;
            z-index: 1000;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }

        #chartModal canvas {
            max-width: 100%;
        }

        #chartModal .close {
            position: absolute;
            top: 5px;
            right: 10px;
            font-size: 20px;
            cursor: pointer;
        }

        #overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            z-index: 999;
        }
    	h1 {
    	font-size: 24px;  
    	margin-bottom: 10px;
	}

	.label {
    	margin-top: 10px;
	}
   	 </style>
   	 <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
	</head>
	<body>
    <div class="container" style="--container-width: 200px; --container-height: 180px;">
	<i class="fas fa-bolt icon"></i>
        <h1>Elektra</h1> <div class="bar" onclick="showChart()">
            <div class="bar-segment level-9"></div>
            <div class="bar-segment level-8"></div>
            <div class="bar-segment level-7"></div>
            <div class="bar-segment level-6"></div>
            <div class="bar-segment level-5"></div>
            <div class="bar-segment level-4"></div>
            <div class="bar-segment level-3"></div>
            <div class="bar-segment level-2"></div>
            <div class="bar-segment level-1"></div>
        </div>
        <div class="label" id="power-label">0 Watt</div>
    </div>

    <!-- Modal voor grafiek -->
    <div id="overlay"></div>
    <div id="chartModal">
        <span class="close" onclick="hideChart()">×</span>
        <canvas id="powerChart"></canvas>
    </div>

    <script>
        const historicalData = []; // Array voor historische data
        const maxHistory = 50; // Maximaal aantal datapunten in grafiek

        // Functie om sensorwaarde op te halen via de Domoticz API
        async function fetchSensorData() {
            const domoticzUrl = 'http://Domoticz-IP:8080/json.htm?type=devices&rid=1';
            try {
                const response = await fetch(domoticzUrl);
                const data = await response.json();

                // Controleer of de data correct is
                if (data.result && data.result.length > 0) {
                    const sensorValue = parseFloat(data.result[0].Usage) || 0; // Haal Watt waarde op
                    return sensorValue;
                } else {
                    console.error('Geen sensorgegevens gevonden');
                    return 0;
                }
            } catch (error) {
                console.error('Fout bij het ophalen van sensorgegevens:', error);
                return 0;
            }
        }

        // Update de grafiek met de sensorwaarde
        function updateGraph(power) {
            // Verwerk de waarde en bereken hoeveel streepjes actief moeten zijn
            const maxPower = 10000; // Maximum vermogen
            const numSegments = 9; // Aantal streepjes
            const activeSegments = Math.ceil((power / maxPower) * numSegments);

            // Update de streepjes
            const segments = document.querySelectorAll('.bar-segment');
            segments.forEach((segment, index) => {
                if (index < activeSegments) {
                    segment.style.backgroundColor = getColor(index + 1);
                } else {
                    segment.style.backgroundColor = 'lightgray';
                }
            });

            // Update de wattage-label
            document.getElementById('power-label').textContent = `${power} Watt`;

            // Update historische data
            historicalData.push(power);
            if (historicalData.length > maxHistory) {
                historicalData.shift();
            }
        }

        // Bepaal de kleur op basis van het niveau
        function getColor(level) {
            const colors = [
                '#004d40', '#00796b', '#4caf50',
                '#cddc39', '#ffeb3b', '#ffc107',
                '#ff9800', '#f44336', '#d32f2f'
            ];
            return colors[level - 1];
        }

        // Regelmatige updates van de sensorwaarde
        setInterval(async () => {
            const sensorValue = await fetchSensorData();
            updateGraph(sensorValue);
        }, 1000); // Update elke seconde

        // Functies om de grafiek te tonen/verbergen
        function showChart() {
            const modal = document.getElementById('chartModal');
            const overlay = document.getElementById('overlay');
            const ctx = document.getElementById('powerChart').getContext('2d');

            // Toon de modal
            modal.style.display = 'block';
            overlay.style.display = 'block';

            // Maak een nieuwe Chart.js-grafiek
            new Chart(ctx, {
                type: 'line',
                data: {
                    labels: historicalData.map((_, index) => `T-${historicalData.length - index}s`),
                    datasets: [{
                        label: 'Power Usage (Watt)',
                        data: historicalData,
                        borderColor: '#4caf50',
                        backgroundColor: 'rgba(76, 175, 80, 0.2)',
                        fill: true,
                        tension: 0.2,
                    }],
                },
                options: {
                    scales: {
                        x: { title: { display: true, text: 'Tijd (seconden geleden)' } },
                        y: { title: { display: true, text: 'Watt' } },
                    },
                },
            });
        }

        function hideChart() {
            const modal = document.getElementById('chartModal');
            const overlay = document.getElementById('overlay');
            modal.style.display = 'none';
            overlay.style.display = 'none';
        }
    </script>
</body>
</html>
Made a new file in the image folder of Dashticz, put the code in and saved it as a HTM file.
Made a frame in Dashticz with reference to the HTM file.

Code: Select all

frames.volumegraph = {
	frameurl: "/img/volumegraph.htm",
	height: 215,
	scrollbars: false,
	width: 4
}
It's not ideal but it works, the data from the P1 cable is transfered to the LED gauge graphic. Changing the size of things to fit it nicely into the container and column in Dashticz is some work though. What doesn't work is opening a second graph when you click on the volume graph.

Would be better to do this in Javascript but that's out of my league.
Image
Attachments
LED gauge.png
LED gauge.png (128.17 KiB) Viewed 171 times
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 0 guests