I would like to see a enhancement in sitemap for displaying Grafana views. I wrote with my knowledge the code below to make it possible to move back in time in the same window as selected. Something like this would be perfect. Ignore the test under the IFrames.
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tijdweergave en COP Warmtepomp</title>
<!-- <link rel="stylesheet" href="css/index.css"> -->
<style>
:root {
--buttonBackgroudColor: #d9d9d9;
--buttonBackgroudSelectedColor: #4CAF50;
--buttonTextSelectedColor: white;
--buttonTextColor: black;
--buttonTextNotSelectableColor: lightGray;
--buttonBoxColor: rgb(59, 25, 151);
--buttonBorderColor: rgb(71, 62, 94);
--borderColor: #ddd;
}
body,
html {
font-family: Arial, sans-serif;
width: 100vw;
height: 100vh;
overflow-y: auto;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
width: calc(100vw - 20px);
height: calc(100vh - 20px);
padding: 10px;
box-sizing: border-box;
}
section {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
/* Control buttons and time selector */
.control-buttons {
display: flex;
gap: 15px;
justify-content: center;
margin-bottom: 10px;
}
.control-buttons #minBtn,
.control-buttons #plusBtn {
padding: 6px 12px;
font-size: 0.8rem;
border-radius: 4px;
cursor: pointer;
border: none;
background-color: var(--buttonBackgroudColor);
}
.time-selector {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin-bottom: 10px;
}
.time-selector label {
cursor: pointer;
padding: 6px 12px;
font-size: 14px;
border-radius: 4px;
background-color: var(--buttonBackgroudColor);
color: var(--buttonTextColor);
}
.time-selector input[type="radio"] {
display: none;
}
.time-selector input[type="radio"]:checked+label {
background-color: var(--buttonBackgroudSelectedColor);
color: var(--buttonTextSelectedColor);
}
/* Grid for iframes */
.grid-container {
display: grid;
gap: 15px;
width: 100%;
height: 100%;
grid-template-columns: 1fr;
}
.grid-item iframe {
width: 100%;
height: 100%;
border: 1px solid var(--borderColor);
border-radius: 4px;
}
/* Layout for very small screens */
@media (max-width: 375px) {
.control-buttons {
gap: 3px;
margin-bottom: 10px;
}
.time-selector {
flex-direction: row;
gap: 3px;
}
.time-selector label {
cursor: pointer;
padding: 6px 10px;
font-size: 1rem;
}
}
/* Responsive styling */
@media (min-width: 768px) {
/* Control-buttons and time-selector centered on one row */
.button-container {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 100%;
gap: 15px;
}
.grid-container {
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: 1024px) {
.grid-container {
grid-template-columns: 1fr 1fr 1fr;
}
}
</style>
<!-- <script src="script.js"></script> -->
<script>
document.addEventListener('DOMContentLoaded', function () {
const iframeIds = ["WarmtepompIframe", "VandaagIframe", "OmvormersIframe", "OmvormersSpanningIframe", "WeerIframe"];
const minBtn = document.getElementById('minBtn');
const plusBtn = document.getElementById('plusBtn');
const timeSelector = document.getElementById('timeSelector');
const timeSettings = {
"now-1h": { unit: "h", display: "1u" },
"now-4h": { unit: "h", display: "4u" },
"now-12h": { unit: "h", display: "12u" },
"now-24h": { unit: "h", display: "24u" },
"now-1w": { unit: "w", display: "1W" },
"now-1M": { unit: "M", display: "1M" },
"now-1y": { unit: "y", display: "1J" }
};
let offset = 0;
let currentTimeRange = "now-1h";
// Functies voor het dynamisch instellen van tijd, iframes, en knoppen
function generateTimeOptions() {
Object.keys(timeSettings).forEach((key, index) => {
const input = document.createElement('input');
input.type = 'radio';
input.id = `option${index}`;
input.name = 'time';
input.value = key;
if (key === currentTimeRange) input.checked = true;
const label = document.createElement('label');
label.setAttribute('for', `option${index}`);
label.innerText = timeSettings[key].display;
timeSelector.appendChild(input);
timeSelector.appendChild(label);
input.addEventListener('change', function () {
currentTimeRange = input.value;
offset = 0;
updateButtons();
iframeIds.forEach(updateIframe);
});
});
}
function updateIframe(iframeId) {
const iframe = document.getElementById(iframeId);
let currentSrc = iframe.src;
const { unit } = timeSettings[currentTimeRange];
const intervalValue = parseInt(currentTimeRange.slice(4));
const newFrom = `now-${(offset + 1) * intervalValue}${unit}`;
const newTo = `now-${offset * intervalValue}${unit}`;
currentSrc = currentSrc
.replace(/from=[^&]*/, `from=${newFrom}`)
.replace(/to=[^&]*/, `to=${newTo}`);
iframe.src = currentSrc;
}
function updateButtons() {
const { display } = timeSettings[currentTimeRange];
minBtn.innerText = `- ${display}`;
plusBtn.innerText = `+ ${display}`;
plusBtn.style.color = offset === 0 ? 'var(--buttonTextNotSelectableColor)' : 'var(--buttonTextColor)'
plusBtn.disabled = offset === 0;
}
function adjustIframeHeights() {
let ratio;
if (window.innerWidth <= 375) {
ratio = 0.8;
} else if (window.innerWidth <= 768) {
ratio = 0.6;
} else if (window.innerWidth <= 1024) {
ratio = 0.7;
} else {
ratio = 0.4;
}
iframeIds.forEach((iframeId) => {
const iframe = document.getElementById(iframeId);
if (iframe) {
const width = iframe.clientWidth;
iframe.style.height = (width * ratio) + 'px';
}
});
}
// Eventlisteners voor de knoppen
minBtn.addEventListener('click', function () {
offset++;
updateButtons();
iframeIds.forEach(updateIframe);
});
plusBtn.addEventListener('click', function () {
if (offset > 0) offset--;
updateButtons();
iframeIds.forEach(updateIframe);
});
// Tijdweergave functie
function updateTime() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
document.getElementById('time').innerText = `${hours}:${minutes}:${seconds}`;
}
// Initialisaties bij het laden van de pagina
generateTimeOptions();
updateButtons();
iframeIds.forEach(updateIframe);
adjustIframeHeights();
updateTime();
// Eventlisteners voor dynamische aanpassingen bij schermverandering
window.addEventListener('resize', adjustIframeHeights);
setInterval(updateTime, 1000); // Tijd update elke seconde
});
// Functie om de COP waarde op te halen van OpenHAB
function fetchCOPValue() {
fetch('http://192.168.100.50:8080/rest/items/COPWarmtepomp/state')
/* fetch('/rest/items/COPWarmtepomp/state')*/
.then(response => response.text())
.then(data => {
document.getElementById('copValue').innerText = `${parseFloat(data).toFixed(3)}`;
})
.catch(error => {
console.error('Error fetching COP value:', error);
document.getElementById('copValue').innerText = 'Error';
});
}
// Haal de waarde elke 10 seconden op
setInterval(fetchCOPValue, 10000);
fetchCOPValue();
// Functie om de geselecteerde tijd om te zetten naar cron-formaat en naar OpenHAB te sturen
function sendCron() {
const timePicker = document.getElementById('timePicker').value;
if (!timePicker) {
alert("Selecteer een tijd voordat je deze verstuurt!");
return;
}
const [hours, minutes] = timePicker.split(":");
// Cron-formaat: 0 MM HH * * ?
const cronExpression = `0 ${minutes} ${hours} * * ?`;
console.log("Cron expression:", cronExpression);
// Stuur de cron-uitdrukking naar OpenHAB (vervang OpenHAB-item met jouw item)
fetch('http://192.168.100.50:8080/rest/items/WarmtepompAvondTijd', {
method: 'POST',
headers: {
'Content-Type': 'text/plain'
},
body: cronExpression
})
.then(response => {
if (response.ok) {
alert("Cron tijd succesvol verstuurd naar OpenHAB!");
} else {
alert("Er ging iets mis met het versturen van de tijd naar OpenHAB.");
}
})
.catch(error => {
console.error('Error sending cron to OpenHAB:', error);
alert('Error bij het versturen van de tijd naar OpenHAB.');
});
}
</script>
</head>
<body>
<div class="control-buttons">
<button id="minBtn"></button>
<button id="plusBtn"></button>
</div>
<div class="time-selector" id="timeSelector"></div>
<div class="container">
<section>
<div class="grid-container">
<div class="grid-item">
<iframe id="WarmtepompIframe"
src="http://192.168.100.92:3000/d-solo/b1e3d190-620d-4b9a-9aba-4fe921aa8860/warmtepomp?orgId=1&panelId=1&from=${from}&to=${to}"
frameborder="0">
</iframe>
</div>
<div class="grid-item">
<iframe id="VandaagIframe"
src="http://192.168.100.92:3000/d-solo/ec543d7f-787a-4eb0-ae2b-7651285c96a3/new-dashboard?orgId=1&from=${from}&to=${to}&panelId=1"
frameborder="0">
</iframe>
</div>
<div class="grid-item">
<iframe id="OmvormersIframe"
src="http://192.168.100.92:3000/d-solo/dfbb21ae-feaa-4ae7-ac01-b352fdce08c2/omvormers-actueel?orgId=1&from=${from}&to=${to}&panelId=1"
frameborder="0">
</iframe>
</div>
<div class="grid-item">
<iframe id="OmvormersSpanningIframe"
src="http://192.168.100.92:3000/d-solo/fb8c184b-c0c3-48b8-bc12-7c55af8e0840/omvormer-netwerkspanning?orgId=1&panelId=1&from=${from}&to=${to}"
frameborder="0">
</iframe>
</div>
<div class="grid-item">
<iframe id="WeerIframe"
src="http://192.168.100.92:3000/d-solo/d73ec2e4-b54b-45a6-b676-7e651071a6b2/weer?orgId=1&from=${from}&to=${to}&panelId=1"
frameborder="0">
</iframe>
</div>
</div>
</section>
<h2>De huidige tijd is:</h2>
<div id="time"></div>
<div class="container">
<h2>COP Warmtepomp waarde zo kan het ook:</h2>
<div id="copValue">Laden...</div>
</div>
<div class="container">
<h2>Selecteer een tijd:</h2>
<input type="time" id="timePicker">
<button onclick="sendCron()">Stuur tijd naar OpenHAB</button>
</div>
</body>
</html>