Bonjour,
J’aimerai utiliser le visuel du Widget Energie Tarification
de @Phpvarious pour un besoin autre tel que la visualisation planning du On/Off de la filtration de ma piscine sur les 24h de la journée. Je pense aussi à d’autres utilisations comme une vision tri état type : On Forcé, Off Forcé, Manuel.
Donc rien a voir avec le besoin initial…
Je pense que l’effort n’est pas important pour y parvenir mais je n’ai pas les compétences nécessaires. J’ai quand même tenté quelque chose et ne doit pas être très loin. Toutefois, je pense que le code initial pourrait être épuré de ce qui n’est pas utile et là je sèche
Ma tentative :
<div class="cmd cmd-widget #history#" data-type="info" data-subtype="string" data-cmd_id="#id#" data-cmd_uid="#uid#" data-version="#version#" data-eqLogic_id="#eqLogic_id#">
<!-- ################ Energie Tarification ################
Widget name : cmd.info.string.energie_tarification
Author : PStatut2various
Last Update : 2024/02/02 13h10 - PStatut2various
Lien : https://pStatut2various.github.io/documentation/widget/fr_FR/widget_scenario/energie_tarification/
Adaptation SILKARION pour avoir 3 statut paramétrables
-->
<template>
<div>heightBar : Hauteur des barres [ Exemple : 12, 14 ... | défaut : 12]</div>
<div>stepWidth : Largueur des pas pour 1 heure [ Exemple : 20, 25 ... | défaut : 20]</div>
<div>MyTxtStatut1 : Texte Statut1 [ Exemple : ON, Marche ... ]</div>
<div>MyTxtStatut2 : Texte Statut2 [ Exemple : OFF, Arrêt ... ]</div>
<div>MyTxtStatut3 : Texte Statut3 [ Exemple : Unknown, Inconnu ... ]</div>
<div>colorStatut1 : Couleur de la barre Statut1 [ Exemple : #fffff, white ... ]</div>
<div>colorStatut2 : Couleur de la barre Statut2 [ Exemple : #fffff, white ... ]</div>
<div>colorStatut3 : Couleur de la barre Statut3 [ Exemple : #fffff, white ... ]</div>
<div>colorTxtStatut1 : Couleur texte Statut1 [ Exemple : #fffff, white ... ]</div>
<div>colorTxtStatut2 : Couleur texte Statut2 [ Exemple : #fffff, white ... ]</div>
<div>colorTxtStatut3 : Couleur texte Statut3 [ Exemple : #fffff, white ... ]</div>
<div>radius : Taille des arrondis [ Exemple : 5, 10 ... | défaut : 10 ]</div>
<div>hideTexte : Cache le texte [ 1 = Cacher | defaut : 0 ]</div>
<div>hideBar : Cache les barres [ 1 = Cacher | defaut : 0 ]</div>
<div>sizeSelector : Taille du selecteur [ Exemple : 10, 12 ... | défaut : 18]</div>
<div>colorSelector : Le selecteur suit la couleur du tarif ou couleur du jour(tempo) [ tarif ou tempo ]</div>
<div>noTempoInText : Masquer la bordure "tempo" sur la partie texte. </div>
<div>noTempoInBar : Masquer la bordure "tempo" sur la partie barre. </div>
<div>-----------------------------------------------------</div>
<div>timeslots : Définition des plages horaires. (défaut : 7h|23h|2h|6h)</div>
<div>labels : Définition des plages horaires. (défaut : Statut2|Statut1|Statut3|Statut1)</div>
<div>diagonalText : Angle de l'heure des plages horaires, ex : 45 pour 45 degrés d'inclinaStatut1. (défaut : 0)</div>
<div> </div>
<div>//////////////////////////////////</div>
<div>│────── Statut2 ──────│─── Statut1 ──│──── Statut3 ────│── Statut1 ──│</div>
<div>7h ───────────── 23h ────── 2h ────────── 6h ───── 7h</div>
<div> </div>
<div>//////////////////////////////////</div>
<div>│──── Statut2 ────│── Statut1 ──│────── Statut2 ─────│──── Statut1 ───│</div>
<div>7h30 ─────── 12h30 ─── 14h ──────────── 1h30 ────── 7h30</div>
<div> </div>
<div>//////////////////////////////////</div>
<div>│───────────── Statut2 ────────────│────── Statut1 ──────│</div>
<div>6h ────────────────────────── 22h ───────────── 6h </div>
</template>
<div id="typeBar#id#" class="graph#id# type_#id#" style="margin: 10px;text-align: left;">
<div class="day#id#">
<span class="iconSel#id#" id="my-hour#id#">#name_display#</span>
</div>
<div id="content#id#">
</div>
<div id="days#id#" class="day#id# day-grid#id#">
</div>
</div>
<div class="day#id# texte#id#"></div>
<script>
function log(text) {
if (debug#id#) console.log(text);
}
function add0(val){
return((val < 10) ? "0" : "") + val;
}
function getTxt(key){
return labelsList.find(item => item.key.toLowerCase() === key.toLowerCase())?labelsList.find(item => item.key.toLowerCase() === key.toLowerCase()).data.txt:'Erreur'
}
function getLabel(key){
return labelsList.find(item => item.key.toLowerCase() === key.toLowerCase())?labelsList.find(item => item.key.toLowerCase() === key.toLowerCase()).data.label:'label-error#id#'
}
function getBar(key){
return labelsList.find(item => item.key.toLowerCase() === key.toLowerCase())?labelsList.find(item => item.key.toLowerCase() === key.toLowerCase()).data.bar:'bar-error#id#'
}
var debug#id# = ('#debug#' == 1) ? true : false;
var versionWidget#id# = '02/02/2024 13h10'
log('┌─────────────────── Widget Energie Tarification [#id#] Compatibilité V4.3 V4.4 [' + versionWidget#id# + '] ───────────────')
/* Compatibilité V4.2 V4.3 V4.4 */
/**/ if (typeof jeedom.cmd.addUpdateFunction !== 'function') { // a partir de la 4.3
/**/ if (debug#id#) console.log('| jeedom.cmd.addUpdateFunction no exist')
/**/ jeedom.cmd.addUpdateFunction = function(id,func) { jeedom.cmd.update[id]=func; }
/**/ }
var separators = '| '
if ('#colorStatut1#' != '#'+'colorStatut1#') document.documentElement.style.setProperty('--color-Statut1#id#', '#colorStatut1#')
if ('#colorStatut2#' != '#'+'colorStatut2#') document.documentElement.style.setProperty('--color-Statut2#id#', '#colorStatut2#')
if ('#colorStatut3#' != '#'+'colorStatut3#') document.documentElement.style.setProperty('--color-Statut3#id#', '#colorStatut3#')
if ('#colorTxtStatut1#' != '#'+'colorTxtStatut1#') document.documentElement.style.setProperty('--color-txt-Statut1#id#', '#colorTxtStatut1#')
if ('#colorTxtStatut2#' != '#'+'colorTxtStatut2#') document.documentElement.style.setProperty('--color-txt-Statut2#id#', '#colorTxtStatut2#')
if ('#colorTxtStatut3#' != '#'+'colorTxtStatut3#') document.documentElement.style.setProperty('--color-txt-Statut3#id#', '#colorTxtStatut3#')
if ('#sizeSelector#' != '#'+'sizeSelector#' && !isNaN('#sizeSelector#')) document.documentElement.style.setProperty('--size-selector#id#', '#sizeSelector#px')
if ('#heightBar#' != '#'+'heightBar#' && !isNaN('#heightBar#')) document.documentElement.style.setProperty('--height-bar#id#', '#heightBar#px')
if ('#radius#' != '#'+'radius#' && !isNaN('#radius#')) document.documentElement.style.setProperty('--border-radius#id#', '#radius#px')
if ('#stepWidth#' != '#'+'stepWidth#' && !isNaN('#stepWidth#')) document.documentElement.style.setProperty('--width#id#', '#stepWidth#px')
if ('#noTempoInText#' == '1') document.documentElement.style.setProperty('--color-tempo-text#id#', 'transparent')
if ('#noTempoInBar#' == '1') document.documentElement.style.setProperty('--color-tempo-bar#id#', 'transparent')
var diagonalText = '0deg'
if ('#diagonalText#' != '#'+'diagonalText#' && !isNaN('#diagonalText#')) {
diagonalText = '#diagonalText#deg';
}
document.documentElement.style.setProperty('--diagonal-text#id#', diagonalText)
var icone#id# = '#name_display#';
if(icone#id#.indexOf('<i ') === -1) {
icone#id# = '<i class="fas fa-map-marker-alt "></i>'
}
log('| icone : ' + icone#id#)
if (is_object(cmd = document.querySelector('.cmd[data-cmd_uid="#uid#"]'))) {
cmd.querySelector('.iconSel#id#').innerHTML = icone#id#
document.documentElement.style.setProperty('--offsetWidth#id#', cmd.querySelector('.iconSel#id# i').offsetWidth + 'px')
if ('#hideTexte#' == 1) cmd.querySelector('.texte#id#').style.display = 'none'
else cmd.querySelector('.texte#id#').style.display = ''
if ('#hideBar#' == 1) cmd.querySelector('.graph#id#').style.display = 'none'
else cmd.querySelector('.graph#id#').style.display = ''
}
var timeslots = '7h|23h|2h|6h'
var labels = 'Statut2|Statut1|Statut3|Statut1'
var labelsList = [
{ key: 'Statut1', data: { txt: '#MyTxtStatut1#', label: 'label-Statut1#id#', bar:'bar-Statut1#id#' }},
{ key: 'Statut2', data: { txt: '#MyTxtStatut2#', label: 'label-Statut2#id#', bar:'bar-Statut2#id#' }},
{ key: 'Statut3', data: { txt: '#MyTxtStatut3#', label: 'label-Statut3#id#', bar:'bar-Statut3#id#' }}
];
if ('#timeslots#' != '#'+'timeslots#') timeslots = '#timeslots#'
if ('#labels#' != '#'+'labels#') labels = '#labels#'
var timeslotsArray = timeslots.split(new RegExp("[" + separators + "]"))
var timeslotsIntArray = []
var timeslotsDurationArray = []
var labelsArray = labels.split(new RegExp("[" + separators + "]"))
var cssContent = document.styleSheets[0]
var daysDiv = document.getElementById("days#id#")
var dayDiv = document.createElement("div")
var cssDayGrid = ""
var durationId = ""
var durationValue = ""
timeslotsArray.map(function(timeslot, index){
let contentDiv = document.getElementById("content#id#");
let barDiv = document.createElement("div");
barDiv.id = "bar" + (index+1) + "_#id#";
barDiv.classList.add("bar#id#", "bar" + (index+1) + "_#id#");
contentDiv.appendChild(barDiv);
daysDiv = document.getElementById("days#id#");
dayDiv = document.createElement("div");
dayDiv.classList.add("diagonal-text");
daysDiv.appendChild(dayDiv);
let cssBar = "#bar" + (index+1) + "_#id# {";
cssBar += "color: var(--color-txt-Statut2#id#);";
cssBar += "width: calc(var(--width#id#) * var(--duration" + (index+1) + "#id#));";
cssBar += (index == 0)?"border-radius: var(--border-radius#id#) 0px 0px var(--border-radius#id#);":"";
cssBar += "}";
cssContent.insertRule(cssBar, cssContent.cssRules.length);
if (index != 0) {
cssDayGrid = ".type_#id# .day-grid#id# div:nth-child(" + (index+1) + ") {";
cssDayGrid += "left: calc(var(--width#id#) * (";
for (let i=1;i<(index+1);i++){
cssDayGrid += "var(--duration" + i + "#id#)";
cssDayGrid += (i != index)?" + ":"";
}
cssDayGrid += "));}";
cssContent.insertRule(cssDayGrid, cssContent.cssRules.length);
}
document.querySelectorAll('.day#id#.day-grid#id# div')[index].innerHTML = timeslot;
if (diagonalText != '0deg') {
document.querySelectorAll('.day#id#.day-grid#id# div')[index].style.marginLeft = "0px"
}
const timeslotSplit = timeslot.split(/[hH]/);
const hoursTimeslot = timeslotSplit[0];
const minutesTimeslot = timeslotSplit[1];
timeslotsIntArray[index] = parseInt(hoursTimeslot) + ((minutesTimeslot == '')?0:parseInt(minutesTimeslot)/60);
if (index != 0) {
durationId = '--duration' + index + '#id#';
durationValue = (timeslotsIntArray[index] > timeslotsIntArray[index-1])? (timeslotsIntArray[index] - timeslotsIntArray[index-1]):(24 - timeslotsIntArray[index-1] + timeslotsIntArray[index]);
timeslotsDurationArray[index-1] = durationValue;
document.documentElement.style.setProperty(durationId, durationValue);
}
})
daysDiv = document.getElementById("days#id#");
dayDiv = document.createElement("div");
dayDiv.classList.add("diagonal-text");
daysDiv.appendChild(dayDiv);
cssDayGrid = ".type_#id# .day-grid#id# div:nth-child(" + (timeslotsArray.length+1) + ") {";
cssDayGrid += " left: calc(var(--width#id#) * 24);";
cssDayGrid += "}";
cssContent.insertRule(cssDayGrid, cssContent.cssRules.length);
labelsArray.map(function(label, index){
cmd.querySelector('#bar' +(index+1) + '_#id#').classList.remove('bar-Statut2#id#','bar-Statut1#id#','bar-Statut3#id#')
cmd.querySelector('#bar' +(index+1) + '_#id#').classList.add(getBar(label))
})
durationId = '--duration' + timeslotsArray.length + '#id#';
durationValue = (timeslotsIntArray[0] > timeslotsIntArray[timeslotsArray.length-1])? (timeslotsIntArray[0] - timeslotsIntArray[timeslotsArray.length-1]):(24 - timeslotsIntArray[timeslotsArray.length-1] + timeslotsIntArray[0]);
timeslotsDurationArray[timeslotsArray.length-1] = durationValue;
document.documentElement.style.setProperty(durationId, durationValue);
document.querySelectorAll('.day#id#.day-grid#id# div')[timeslotsArray.length].innerHTML = timeslotsArray[0]
if (diagonalText != '0deg') {
document.querySelectorAll('.day#id#.day-grid#id# div')[timeslotsArray.length].style.marginLeft = "0px"
}
document.getElementById('bar' + timeslotsArray.length + '_#id#').classList.add('radius#id#')
function isCurrentTimeslot(currentDate, beginDate, endDate) {
if (beginDate > endDate) {
endDate += 24;
}
if (beginDate > currentDate) {
currentDate += 24;
}
return currentDate >= beginDate && currentDate < endDate;
}
log('└────────────────────────────────────')
function getTime#id# () {
log('┌─────────────────── Widget Energie Tarification [#id#] en debug [getTime()] ───────────────')
let date = new Date();
let hours = date.getHours();
//hours = 1
let minutes = date.getMinutes();
//minutes = 30
let seconds = date.getSeconds();
let numDay = date.getDate();
let day = date.getDay();
let month = date.getMonth();
let year = date.getFullYear();
let weekday = ["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"];
let weekmonth = ["Janvier","Février","Mars","Avril","Mais","Juin","Juillet","Aout","Septembre","Octobre","Novembre","Décembre"];
let label, txt, nextTxt, nextLabel, ecartMin, ecart, ecartHours
let ecartTxt = ''
let ecartTitle = ''
let posx = 0
let myHour#id# = document.getElementById("my-hour#id#")
const hoursDec = hours + ( minutes / 60 )
log('| hoursDec : ' + hoursDec)
if (hoursDec >= timeslotsIntArray[0]) posx = hoursDec - timeslotsIntArray[0]
else posx = 24 - timeslotsIntArray[0] + hoursDec
log('| posx : ' + posx)
hours = add0(hours);
minutes = add0(minutes);
seconds = add0(seconds);
numDay = add0(numDay);
const iMax = labelsArray.length;
let indexPos = iMax-1;
let indexTimesolt = 0;
for (let i=0 ; i<iMax ; i++) {
if (isCurrentTimeslot(hoursDec, timeslotsIntArray[i], timeslotsIntArray[(i+1)%iMax])) {
indexPos = i;
break;
}
}
txt = getTxt(labelsArray[indexPos]);
label = getLabel(labelsArray[indexPos]);
const nextTimeslotIndex = (getLabel(labelsArray[indexPos]) === getLabel(labelsArray[(indexPos+1)%iMax]))?(indexPos+2)%iMax:(indexPos+1)%iMax
const nextTimeslot = (timeslotsIntArray[nextTimeslotIndex] > hoursDec)?timeslotsIntArray[nextTimeslotIndex]:timeslotsIntArray[nextTimeslotIndex] + 24;
ecart = nextTimeslot - hoursDec
nextTxt = getTxt(labelsArray[nextTimeslotIndex]);
nextLabel = getLabel(labelsArray[nextTimeslotIndex]);
ecartHours = Math.trunc(ecart)
ecartMin = Math.round((ecart - ecartHours) * 60)
log('| ecart : ' + ecart)
ecartTxt += weekday[day] + ' ' + numDay + ' ' + weekmonth[month] + ' ' + year + ' à ' + hours + ':' + minutes + ', dans '
if(ecartHours > 0) ecartTxt += ecartHours + 'h'
if(ecartMin > 0) ecartTxt += add0(ecartMin) + ' min'
ecartTitle = ecartTxt + ', je serai en ' + nextTxt
ecartTxt += ', je serai en <span class="label ' + nextLabel + '">' + nextTxt + '</span>'
if (is_object(cmd = document.querySelector('.cmd[data-cmd_uid="#uid#"]'))) {
cmd.querySelector('.texte#id#').innerHTML = '<span class="iconTxt#id#"><i class="fa fa-circle fa-lg"></i></span> ' + ecartTxt
cmd.querySelector('.iconSel#id#').setAttribute('title', ecartTitle)
cmd.querySelector(".iconSel#id#").classList.remove('label-Statut2#id#','label-Statut1#id#','label-Statut3#id#')
cmd.querySelector(".texte#id#").classList.remove('label-Statut2#id#','label-Statut1#id#','label-Statut3#id#')
cmd.querySelector(".texte#id#").classList.add(label)
cmd.querySelector('.iconTxt#id#').setAttribute('title', txt)
if ('#colorSelector#' == 'tarif' ) {
cmd.querySelector(".iconSel#id#").classList.add(label)
}
else if ('#colorSelector#' == 'tempo') {
cmd.querySelector(".iconSel#id#").classList.add('selectorTempo#id#')
}
}
if (myHour#id#) {
document.documentElement.style.setProperty('--posx#id#', posx)
setTimeout("getTime#id#()",60000)
}
log('└────────────────────────────────────')
}
getTime#id#()
jeedom.cmd.addUpdateFunction('#id#', function(_options) {
log('┌─────────────────── Widget Energie Tarification [#id#] en debug [addUpdateFunction()] ───────────────')
log('| value : ' + _options.value)
if (is_object(cmd = document.querySelector('.cmd[data-cmd_uid="#uid#"]'))) {
cmd.querySelector(".iconSel#id#").classList.remove('error#id#')
let value = _options.display_value.toLowerCase()
if (value.includes('red') || value.includes('rouge')){
document.documentElement.style.setProperty('--color-tempo#id#', 'red')
}
else if (value.includes('blue') || value.includes('bleu')){
document.documentElement.style.setProperty('--color-tempo#id#', 'blue')
}
else if (value.includes('white') || value.includes('blanc')){
document.documentElement.style.setProperty('--color-tempo#id#', 'white')
}
else {
document.documentElement.style.setProperty('--color-tempo#id#', 'transparent')
cmd.querySelector(".iconSel#id#").classList.add('error#id#')
}
}
log('└────────────────────────────────────')
})
jeedom.cmd.refreshValue([{ cmd_id: '#id#', value: '#value#', display_value: '#state#', valueDate: '#valueDate#', collectDate: '#collectDate#', alertLevel: '#alertLevel#', unit: '#unite#' }])
</script>
<style>
:root {
--titleColor#id# : #ffffff;
--width#id# : 22px;
--posx#id# : 1;
--border-radius#id# : 10px;
--offsetWidth#id# : 9px;
--color-Statut1#id# : var(--al-success-color);
--color-txt-Statut1#id# : var(--sc-lightTxt-color);
--color-Statut2#id# : var(--al-warning-color);
--color-txt-Statut2#id# : var(--sc-lightTxt-color);
--color-Statut3#id# : var(--lb-info-color);
--color-txt-Statut3#id# : var(--sc-lightTxt-color);
--color-icone#id# : var(--link-color);
--size-selector#id#: 18px;
--height-bar#id#: 12px;
--color-tempo#id#: transparent;
--color-tempo-text#id#: var(--color-tempo#id#);
--color-tempo-bar#id#: var(--color-tempo#id#);
--diagonal-text#id: Odeg;
}
.iconSel#id# {
position: relative;
left: calc(var(--posx#id#) * var(--width#id#) - (var(--offsetWidth#id#) / 2));
color: var(--color-icone#id#);
}
.iconSel#id# > i {
font-size: var(--size-selector#id#);
}
.iconSel#id#.label-Statut2#id#, .texte#id#.label-Statut2#id# i {
color: var(--color-Statut2#id#);
}
.iconSel#id#.label-Statut1#id#, .texte#id#.label-Statut1#id# i {
color: var(--color-Statut1#id#);
}
.iconSel#id#.label-Statut3#id#, .texte#id#.label-Statut3#id# i {
color: var(--color-Statut3#id#);
}
.iconSel#id#.label-error#id#, .texte#id#.label-error#id# i {
color: transparent;
}
.iconSel#id#.selectorTempo#id#:not(.error#id#){
color: var(--color-tempo#id#);
}
.bar#id#{
height: var(--height-bar#id#);
float: left;
display: block;
border: 3px solid var(--color-tempo-bar#id#);
}
.day#id#{
width: calc(var(--width#id#) * 24);
position: relative;
margin-bottom: 2px;
}
.day-grid#id#{
margin: 2px 0 5px;
height: 8px;
display: inline-block;
}
.texte#id#{
margin: 3px 10px 20px;
padding: 5px;
/* height: 8px; */
border: 3px solid var(--color-tempo-text#id#);
border-radius: var(--border-radius#id#);
}
.day-grid#id# div {
position: absolute;
display: block;
width: 30px;
margin-left: -14px;
font-size: 10px;
text-align: center;
}
.texte#id# .label-Statut2#id#, .bar-Statut2#id# {
background-color: var(--color-Statut2#id#) !important;
color: var(--color-txt-Statut2#id#) !important;
}
.texte#id# .label-Statut1#id#, .bar-Statut1#id# {
background-color: var(--color-Statut1#id#) !important;
color: var(--color-txt-Statut1#id#) !important;
}
.texte#id# .label-Statut3#id#, .bar-Statut3#id# {
background-color: var(--color-Statut3#id#) !important;
color: var(--color-txt-Statut3#id#) !important;
}
.texte#id# .bar-error#id#, .bar-error#id#,.texte#id# .label-error#id# {
background-size: 30px 30px;
background-image: linear-gradient(135deg,
rgba(255, 0, 0, 0.5) 25%,
rgba(255, 255, 255, 0.5) 25%,
rgba(255, 255, 255, 0.5) 50%,
rgba(255, 0, 0, 0.5) 50%,
rgba(255, 0, 0, 0.5) 75%,
rgba(255, 255, 255, 0.5) 75%,
rgba(255, 255, 255, 0.5)
);
}
.radius#id#{
border-radius: 0px var(--border-radius#id#) var(--border-radius#id#) 0px;
}
.type_#id# .day-grid#id# div:nth-child(1) {
left: 0px;
}
.bar#id#:first-child {
border-right-width: 0px;
}
.bar#id#:last-child {
border-left-width: 0px;
}
.bar#id#:not(:first-child):not(:last-child) {
border-left-width: 0px;
border-right-width: 0px;
}
.diagonal-text {
transform: rotate(var(--diagonal-text#id#));
transform-origin: 0 0;
white-space: nowrap;
}
</style>
</div>
J’ai ajouté 3 statuts MyTxtStatut1,2 et 3 pour pouvoir remplacer HC/HSC et HP et gérer des libellés comme ON/OFF, Marche Forcée/Arrêt forcé/Manuel,…
Je fais varier les données « timeslots » et « labels » en utilisant le « Scénario de modification de paramètre d’une commande » de @noodom quand je change l’heure de début de filtration ou la durée.
J’ai un message d’erreur /!\ « Uncaught TypeError: cmd.find is not a function » quand j’active sur le même dashboard le sliderButton de @Salvialf.
@Phpvarious, pourrais tu m’aider a obtenir un widget adéquat stp.
Merci d’avance,
Silkarion