[Tutoriel] Prévision des couleurs Tempo à J+9

Une variante en prenant un json plus complet : https://open-dpe.fr/assets/tempo_days.json

  • affichage de la consommation brute nationale prévue par RTE, consommation réelle à fournir par les centrales, apport estimé du solaire et de l’éolien, probabilité des couleurs par jour, jours blancs et rouges restants pour la saison
  • description des champs affichés par infobulle
  • possibilité d’afficher ou non les différents champs par paramètres optionnels
  • affichage proportionnel ou non des pourcentages de couleur

Ajout de paramètres optionnels :

Avec des champs cachés (par paramètres optionnels) :

Il suffit de reprendre le post [Tutoriel] Prévision des couleurs Tempo à J+9 - #7 par noodom avec le contenu suivant :

Code du fichier tempo.php
<?php
//$url = "https://open-dpe.fr/assets/tempo_days_lite.json";
$url = "https://open-dpe.fr/assets/tempo_days.json";
$json = file_get_contents($url);

if ($json === false) {
    echo "Erreur de récupération";
} else {
    echo $json;
}
?>
Code du widget
<div class="cmd cmd-widget #history#" data-type="info" data-subtype="other" data-cmd_id="#id#" data-cmd_uid="#uid#" data-version="#version#" data-eqLogic_id="#eqLogic_id#">
  <!-- ################ nooTempo ################ 
       ********** Paramètres Optionnels ***************
		
         nbJours : Nombre de jours affichés (Défaut 9).
         showTotal : Afficher la ligne Total Brut (1:oui, 0:non).
         showBalance : Afficher la barre Net/EnR et sa légende (1:oui, 0:non).
         showStocks : Afficher Jours restants (1:oui, 0:non).
         proportional : Affichage probabilités proportionnel (1:oui, 0:non).

        Pensez au café pour les nuits blanches de codage ;) 
        https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=noodom.fr%40gmail.com&currency_code=EUR&source=url
       ########### by @noodom ;)  ############# -->
  
  <div class="title #hide_name#">
    <div class="cmdName" style="font-weight: bold; margin-bottom: 5px;">#name_display#</div>
  </div>
  
  <div class="tempo-forecast-wrapper" id="tempo_container_#id#"></div>

  <template>
      <div>
         <div>nbJours : Nombre de jours affichés (Défaut 9).</div>
         <div>showTotal : Afficher la ligne Total Brut (1:oui, 0:non).</div>
         <div>showBalance : Afficher la barre Net/EnR et sa légende (1:oui, 0:non).</div>
         <div>showStocks : Afficher Jours restants (1:oui, 0:non).</div>
         <div>proportional : Affichage probabilités proportionnel (1:oui, 0:non).</div>
      </div>
  </template>

  <style>
    .tempo-forecast-wrapper {
      display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; padding: 10px;
    }
    .tempo-day-card {
      display: flex; flex-direction: column; align-items: center; border-radius: 10px;
      padding: 10px; min-width: 135px; box-shadow: 0 4px 6px rgba(0,0,0,0.3);
      border: 1px solid rgba(255,255,255,0.15);
    }
    .t-date { font-size: 1em; font-weight: bold; margin-bottom: 8px; border-bottom: 1px solid rgba(0,0,0,0.1); width: 100%; text-align: center; }
    
    .t-power-zone { font-size: 0.75em; margin-bottom: 8px; width: 100%; }
    .t-power-line { display: flex; justify-content: space-between; margin-bottom: 4px; cursor: help; }
    
    .t-balance-container { margin: 8px 0; width: 100%; }
    .t-balance-bar {
      display: flex; width: 100%; height: 8px; background: rgba(0,0,0,0.1);
      border-radius: 4px; overflow: hidden; border: 1px solid rgba(0,0,0,0.05); cursor: help;
    }
    .bar-net { background: #2d3436; height: 100%; }
    .bar-enr { background: #00b894; height: 100%; }
    
    .t-balance-legend {
      display: flex; justify-content: space-between; font-size: 0.85em; 
      margin-top: 4px; line-height: 1.1;
    }
    .leg-item { display: flex; flex-direction: column; cursor: help; }
    .leg-label { font-size: 0.75em; opacity: 0.8; margin-bottom: 1px; }
    .leg-net { font-weight: bold; text-align: left; }
    .leg-enr { font-weight: 500; text-align: right; }
    .t-arrow-down { font-size: 0.9em; font-weight: bold; margin-right: 1px; }

    .t-probas-row {
      display: flex; gap: 3px; margin-bottom: 10px; background: rgba(0,0,0,0.15);
      padding: 4px; border-radius: 6px; min-height: 28px; width:100%; box-sizing: border-box; align-items: center; justify-content: center;
    }
    .t-mini-box {
      display: inline-flex !important; align-items: center !important; justify-content: center !important;
      height: 20px !important; border-radius: 3px !important; font-size: 8px !important; font-weight: 900 !important; color: white !important;
    }
    .t-fixe { width: 20px !important; }
    .t-prop { width: 100%; }

    .t-bleu { background-color: #0055b8 !important; color: white !important; }
    .t-blanc { background-color: #f8f9fa !important; color: #1e272e !important; }
    .t-rouge { background-color: #ce0501 !important; color: white !important; }
    
    .mini-b { background-color: #003a7e !important; }
    .mini-w { background-color: #ffffff !important; color: #1e272e !important; border: 1px solid #ced4da; }
    .mini-r { background-color: #920401 !important; }

    .t-stock-footer {
      display: flex; gap: 8px; font-size: 0.75em; font-weight: bold; border-top: 1px solid rgba(0,0,0,0.1);
      padding-top: 6px; width: 100%; justify-content: space-around;
    }
  </style>

  <script>
    jeedom.cmd.update['#id#'] = function(_options) {
      try {
        let data = JSON.parse(_options.display_value);
        let container = $('#tempo_container_#id#');
        container.empty();

        let limit = (is_numeric('#nbJours#')) ? parseInt('#nbJours#') : 9;
        let showTotal = ('#showTotal#' == '0') ? false : true;
        let showBalance = ('#showBalance#' == '0') ? false : true;
        let showStocks = ('#showStocks#' == '0') ? false : true;
        let isProp = ('#proportional#' == '1') ? true : false;

        data.slice(0, limit).forEach(item => {
          let dateParts = item.date.split('-');
          let shortDate = dateParts[2] + '/' + dateParts[1];
          
          let f_gross = (item.forecast / 1000).toFixed(1);
          let f_net = (item.consumption_net / 1000).toFixed(1);
          let f_enr = (f_gross - f_net).toFixed(1);
          
          let pctNet = (item.consumption_net / item.forecast * 100).toFixed(0);
          let pctEnR = (100 - pctNet).toFixed(0);

          let html = `<div class="tempo-day-card t-${item.tempo_color.toLowerCase()}">`;
          html += `<span class="t-date">${shortDate}</span>`;
          
          if (showTotal || showBalance) {
            html += `<div class="t-power-zone">`;
            
            // PARAMETRE 1 : LIGNE TOTAL
            if (showTotal) {
              html += `<div class="t-power-line" title="Consommation brute totale prévue sur le réseau (en Gigawatts)"><span>Total:</span><b>${f_gross} GW</b></div>`;
            }
            
            // PARAMETRE 2 : BARRE + NET + ENR
            if (showBalance) {
              html += `<div class="t-balance-container">
                        <div class="t-balance-bar" title="Répartition : ${pctNet}% Pilotable / ${pctEnR}% Renouvelable">
                          <div class="bar-net" style="width:${pctNet}%"></div>
                          <div class="bar-enr" style="width:${pctEnR}%"></div>
                        </div>
                        <div class="t-balance-legend">
                          <div class="leg-item" title="Consommation NETTE : effort réel demandé aux centrales pilotables (Nucléaire, Gaz, etc.)">
                             <span class="leg-label">Net</span>
                             <span class="leg-net">${f_net}G</span>
                          </div>
                          <div class="leg-item" title="Apport EnR : part de la consommation couverte par le Solaire et l'Éolien (déduite du Total)">
                             <span class="leg-label">EnR</span>
                             <span class="leg-enr"><span class="t-arrow-down">↓</span>${f_enr}G</span>
                          </div>
                        </div>
                      </div>`;
            }
            html += `</div>`;
          }

          html += `<div class="t-probas-row ${isProp ? 't-prop' : ''}">`;
          const probas = [
            {v:Math.round(item.probability_bleu * 100),c:'mini-b',t:'Bleu'},
            {v:Math.round(item.probability_blanc * 100),c:'mini-w',t:'Blanc'},
            {v:Math.round(item.probability_rouge * 100),c:'mini-r',t:'Rouge'}
          ];
          probas.forEach(p => {
            if (isProp) {
              if (p.v > 0) html += `<div class="t-mini-box ${p.c}" style="flex:${p.v};margin:0 1px;" title="Probabilité ${p.t}: ${p.v}%">${p.v}</div>`;
            } else {
              html += `<div class="t-mini-box ${p.c} t-fixe" style="margin:0 2px;" title="Probabilité ${p.t}: ${p.v}%">${p.v}</div>`;
            }
          });
          html += `</div>`;

          if (showStocks) {
            html += `<div class="t-stock-footer">
                      <div title="Jours Blancs restants dans la saison (Total 43)">⚪ ${item.stock_blanc}</div>
                      <div title="Jours Rouges restants dans la saison (Total 22)">🔴 ${item.stock_rouge}</div>
                    </div>`;
          }

          html += `</div>`;
          container.append(html);
        });
      } catch (e) {
        $('#tempo_container_#id#').html('Erreur JSON');
      }
    }
    jeedom.cmd.update['#id#']({display_value:'#state#'});
  </script>
</div>
4 « J'aime »