Etude simulateur photovoltaïque

Dans le cadre de mon stage au sein de Sun R Solutions, j’ai eu l’opportunité de contribuer au développement d’un outil novateur : un simulateur d’étude de projet solaire. Cet outil, intégré dans un formulaire interactif en ligne, vise à accompagner les commerciaux dans l’évaluation et la conception des projet photovoltaïque. Les données sont utilisées pour générer une estimation précise de la production d’énergie solaire, ainsi que des informations financières pertinentes telles que le coût initial du projet, les économies potentielles sur les factures d’électricité, et les éventuelles subventions ou incitations fiscales.

En combinant des fonctionnalités de modélisation, d’estimation de production et de calcul financier, ce simulateur offre une approche complète et personnalisée pour chaque projet solaire.

 

Barre de progression

Nous avons intégré une barre de progression dynamique pour suivre l’évolution des étapes du formulaire. Elle est composée de plusieurs étapes, chacune représentée par une icône correspondant à la nature de l’information demandée.

Structure HTML

<div class="progress-bar-wrapper">
        <div class="progress-label etapes-form ">ÉTAPE 1 SUR 7<br>
            <div class="titlebarre">
                <img src="asset/image/icon-navbarre/projet.svg" alt="Votre projet">
            </div>
        </div>
        <div class="progress">
            <div class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="20" aria-valuemin="0"
                aria-valuemax="100"></div>
        </div>
    </div>

Fonctionnalités JavaScript

Cette barre de progression est mise à jour dynamiquement à mesure que l’utilisateur progresse dans les différentes étapes du formulaire.

let currentStep = 1;
const form = document.getElementById('form');
const progressBar = document.querySelector('.progress-bar');
// Fonction pour revenir à l'étape précédente
function previousStep() {
    currentStep--;
    updateStepVisibility();
    updateProgressBar();
}
// Fonction pour mettre à jour la visibilité des étapes
function updateStepVisibility() {
    const steps = document.getElementsByClassName('step');
    for (let i = 0; i < steps.length; i++) {
        if (i === currentStep - 1) {
            steps[i].classList.add('active');
        } else {
            steps[i].classList.remove('active');
        }
    }
}
// Fonction pour mettre à jour la barre de progression
function updateProgressBar() {
    const totalSteps = document.getElementsByClassName('step').length;
    const progress = ((currentStep - 1) / (totalSteps - 1)) * 100;
    progressBar.style.width = progress + '%';
    progressBar.setAttribute('aria-valuenow', progress);
    document.querySelector('.progress-label').innerHTML = `<p class="etapes-form">ÉTAPE ${currentStep} SUR ${totalSteps}</p><p class="titlebarre">${getStepTitle(currentStep)}</p>`;
}


Votre projet ( slide 1 )

La première étape de notre simulateur, intitulée “Votre projet”, est conçue pour collecter des informations de base sur le projet solaire envisagé par l’utilisateur. Cette étape est cruciale car elle établit le contexte initial du projet et permet à l’utilisateur de définir les paramètres de base nécessaires à l’analyse ultérieure.

Sélection du type de projet (maison ou bâtiment collectif) :

Dans cette sous-étape, nous avons introduit l’utilisateur à deux options principales : Maison individuelle et Bâtiment collectif ou commercial. Nous avons utilisé des éléments HTML tels que les boutons radio pour permettre à l’utilisateur de faire son choix.

         <input type="radio" id="house" name="projectType" value="Maison">

                        <label for="house"><img src="./asset/image/icon/clarity--building-line.svg" alt="une maison individuelle"> une maison individuelle</label><br>

                        <input type="radio" id="building" name="projectType" value="building">

                        <label for="building"><img src="./asset/image/icon/mi--home.svg" alt="un bâtiment collectif ou commercial">un bâtiment collectif ou commercial</label><br><br>

En JavaScript, nous avons ajouté des événements d’écoute pour détecter quand l’utilisateur sélectionne l’une des options et pour afficher les éléments pertinents en fonction de son choix. Par exemple, si l’utilisateur choisit “Bâtiment collectif ou commercial”, nous affichons un menu déroulant supplémentaire pour obtenir plus de détails sur le type de bâtiment.

// Code pour afficher le menu déroulant lorsque "bâtiment collectif ou commercial" est sélectionné

const buildingInput = document.getElementById('building');

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

buildingInput.addEventListener('change', function() {

    if (this.checked && this.value === 'building') {

        buildingOptions.classList.add('show-dropdown');

    } else {

        buildingOptions.classList.remove('show-dropdown');

    }

});


Rôle du client (Propriétaire) :

Nous demandons à au commercial de préciser le statut client le projet, en tant que propriétaire.

<label class="labelsim" for="ownerType">et vous êtes :</label <br>

<input type="radio" id="owner" name="ownerType" value="Propriétaire">

 <label for="owner"><img src="./asset/image/icon/uis--house-user.svg">propriétaire</label><br>

Saisie de l'adresse

HTML : J’ai créé un champ de texte pour l’adresse et une division pour afficher les suggestions d’adresse.

<!-- Saisie de l'adresse --> 

<label class="labelsim" for="address">Votre bâtiment se situe au (Adresse)</label><br>

<input type="text" id="address" name="address" class="form-control" placeholder="Entrez votre adresse" required>

<div id="addressSuggestions" class="mt-2"></div>

JavaScript : J’ai ajouté une fonctionnalité de saisie automatique qui suggère des adresses à mesure que l’utilisateur tape, en utilisant une API d’adresse.

const addressInput = document.getElementById(‘address’);
const addressSuggestions = document.getElementById(‘addressSuggestions’);

addressInput.addEventListener(‘input’, function() {
    const query = this.value.trim();
    if (query.length > 2) {
        fetch(`https://api-adresse.data.gouv.fr/search/?q=${query}&limit=5`)
            .then(response => response.json())
            .then(data => {
                addressSuggestions.innerHTML = ”;
                data.features.forEach(feature => {
                    const suggestion = document.createElement(‘div’);
                    suggestion.classList.add(‘suggestion’);
                    suggestion.textContent = feature.properties.label;
                    suggestion.addEventListener(‘click’, function() {
                        addressInput.value = feature.properties.label;
                        addressSuggestions.innerHTML = ”;
                    });
                    addressSuggestions.appendChild(suggestion);
                });
            })
            .catch(error => {
                console.error(‘Erreur lors de la récupération des suggestions d\’adresse:’, error);
            });
    } else {
        addressSuggestions.innerHTML = ”;
    }
});

Votre toiture ( slide 2 )

L’étape 2 de notre processus concerne l’évaluation de la toiture pour déterminer sa viabilité pour l’installation de panneaux solaires. Dans cette section, vous pouvez spécifier le type d’installation photovoltaïque en choisissant parmi différentes options telles que toit plat, toit terrasse, ombrière, sur-imposition ou installation au sol. De plus, on peux sélectionner le type de surface de votre toiture parmi les options disponibles telles que tuiles, bac acier, PST, ou autres. Enfin, il est possible d’indiquer la surface de la toiture en mètres carrés.

Votre toiture

Dans cette partie, l’utilisateur est invité à choisir type d’installation parmi plusieurs options prédéfinies, telles que toit plat, toit terrasse, ombrière, etc. Le code HTML associe des images et des labels à des boutons radio pour permettre à l’utilisateur de sélectionner son type de toiture.

<input type="radio" id="toit-plat" name="roofType" value="toit-plat"  class="invisible-radio">        

<label for="toit-plat" class="fondtoiture">

        <img class="roof-image" src="./asset/image/roof/solar-plat.jpg" alt="Toit plat">

        <p class="titreroof">Toit plat</p>

</label><br>

Choix du type de surface

Les utilisateurs peuvent choisir le type de surface de leur toiture à partir d’une liste déroulante (<select>). Les options incluent des choix pré-définis comme “Tuiles”, “Bac acier”, etc.

<h2>Type de surface</h2>
     <label for="surfaceType"></label>
     <select id="surfaceType" name="surfaceType" class="form-control">
         <option value="Tuiles">Tuiles</option>
         <option value="Bac acier">Bac acier</option>
         <option value="PST">PST</option>
         <option value="Autres">Autres</option>
         <option value="">Aucune</option>
     </select>

Saisie de la surface

La partie “Quelle est la surface ?” utilise un champ de saisie <input> de type number pour permettre à l’utilisateur de saisir une valeur numérique. L’attribut min définit la valeur minimale autorisée, tandis que l’attribut placeholder fournit un texte indicatif pour guider l’utilisateur sur ce qu’il doit entrer. Un <span> est utilisé pour afficher une unité de mesure () à côté du champ de saisie.

<label for="surface"></label>
<input class="surfaceKW" type="number" id="surfacekW" name="surface" min="0"  placeholder="Entrez la surface en mètres carrés" required>
<span class="span-label"> m²</span>

Votre exposition (slide 3)

Pour cette troisième étape, j’ai travaillé sur la fonctionnalité permettant à l’utilisateur de spécifier l’exposition du toit ainsi que la pente de celui-ci, des facteurs cruciaux pour l’évaluation de la viabilité d’une installation solaire.

Pour permettre aux utilisateurs de spécifier l’orientation de leur toit, j’ai mis en place une interface intuitive comprenant des boutons radio pour les différentes orientations possibles : Nord, Ouest, Est, Sud-Ouest, Sud et Sud-Est. 

                      <div class="custom-container-center-expo">
                            <div class="inlineroofdeg">
                                <input type="radio" id="nord" name="orientation" value="0">
                                <label for="nord">Nord</label><br>
                            </div>
                        </div>
                        <div class="custom-container-center-expo">
                            <div class="inlineroofdeg">
                                <input type="radio" id="ouest" name="orientation" value="270">
                                <label for="ouest">Ouest</label><br>
                            </div>
                            <div class="inlineroofdeg">
                                <input type="radio" id="est" name="orientation" value="90">
                                <label for="est">Est</label><br>
                            </div>
                        </div>
                        <div class="custom-container-center-expo">
                            <div class="inlineroofdeg">
                                <input type="radio" id="sud-ouest" name="orientation" value="225">
                                <label for="sud-ouest">Sud-Ouest</label><br>
                            </div>
                            <div class="inlineroofdeg">
                                <input type="radio" id="sud" name="orientation" value="180">
                                <label for="sud">Sud</label><br>
                            </div>
                            <div class="inlineroofdeg">
                                <input type="radio" id="sud-est" name="orientation" value="135">
                                <label for="sud-est">Sud - Est</label><br>
                            </div>
                        </div>
                        <br>
                        

En plus de cela, j’ai intégré une barre de défilement pour que les utilisateurs puissent indiquer la pente de leur toit. Cette barre est configurée pour afficher des valeurs allant de 0 à 90 degrés, permettant ainsi une précision dans la saisie.

<div class="text-center"> <h2 class="etape1">Quelle est la pente de votre toit</h2><br>
<input class="barreangle" type="range" id="pitch" name="pitch" min="0" max="90" value="0" onchange="updatePitchLabel(this.value)">
<p class="pitchLabel" id="pitchLabel"></p> <br> </div>

Voici comment nous avons fait pour mettre à jour l’étiquette affichant la valeur de la pente du toit en temps réel.

function updatePitchLabel(value) {
    const pitchLabel = document.getElementById('pitchLabel');
    pitchLabel.textContent = value + '°';
    const pitchInput = document.getElementById('pitch');
    pitchInput.value = value;
}
document.getElementById('pitch').addEventListener('input', function() {
   updatePitchLabel(this.value);
});

 

Votre contrat ( slide 4 )

À l’étape 4 du formulaire,j’ai travaillé sur la conception et l’implémentation d’une fonctionnalité appelée “Votre contrat”. Mon objectif était de permettre aux utilisateurs de calculer le coût de leur facture d’électricité en fonction de différents paramètres, tels que le prix du kilowattheure et leur consommation annuelle.

Prix achat kWh

La première partie de cette section était dédiée à la facture d’électricité. Pour cela, j’ai mis en place un formulaire interactif qui permet aux utilisateurs de saisir le prix du kilowattheure de leur contrat. J’ai utilisé une balise <input> avec le type “number” pour garantir que l’utilisateur saisisse une valeur numérique. J’ai également prévu une valeur par défaut de 0.25 € par kWh.

<p>* Prix du kilowattheure de votre contrat </p>
<label for="contrat-edfoa">Entrez le prix du kilowattheure :</label><br>
<input class="custom-label " type="number" id="contrat-edfoa" name="contrat-edfoa" min="0" value="0.25" step="0.01">
<span class="custom-label1">€ / kWh</span>

 

Facture ou consommation annuelle ?

Pour permettre à l’utilisateur de choisir s’il connaît sa facture annuelle, sa consommation annuelle ou aucun des deux, j’ai utilisé des boutons radio. Chaque option déclenche l’affichage d’un contenu spécifique grâce à la fonction JavaScript showContent().

<input type="radio" id="option1" name="menu" value="facture_annuelle" onclick="showContent()" checked>
<label for="option1">Je connais la facture annuelle (hors abonnement)</label><br>                    
<input type="radio" id="option2" name="menu" value="consommation_annuelle" onclick="showContent()">
<label for="option2">Je connais la consommation annuelle</label><br>
<input type="radio" id="option3" name="menu" value="inconnu" onclick="showContent()">
<label for="option3">Je ne les connais pas</label><br>

La fonction showContent() affiche le contenu correspondant à l’option sélectionnée (facture annuelle, consommation annuelle, ou inconnue).

function showContent() { 

option1 = document.getElementById("option1"); 
var option2 = document.getElementById("option2");
var option3 = document.getElementById("option3"); 
var content1 = document.getElementById("content1");
var content2 = document.getElementById("content2");
var content3 = document.getElementById("content3");

if (option1.checked) { content1.style.display = "block"; content2.style.display = "none"; content3.style.display = "none"; } 
else if (option2.checked) { content1.style.display = "none"; content2.style.display = "block"; content3.style.display = "none"; } 
else if (option3.checked) { content1.style.display = "none"; content2.style.display = "none"; content3.style.display = "block"; } }

Option de la facture annuelle

Lorsque l’utilisateur choisit de saisir sa facture annuelle, j’affiche un champ pour entrer le coût en euros et une estimation de la consommation en kilowattheures.

<div id="content1" style="display: none;">
     <label for="euroInput">Entrez le coût en euros :</label><br>
     <input class="custom-label " type="number" id="euroInput" name="euroInput" min="0" step="any">
     <span class="custom-label1">€ / An</span><br>
     <div class="resultPrice">
     <p class="resultDisplay">Estimation de votre consommation</p>
     <p class="costDisplay" id="kwDisplay"></p>
      <p>Estimation calculée sur la base d'un prix moyen de <span id="kwprice"></span> euro par kWh électrique.</p>
      </div>
</div>

La fonction calculateKw() calcule la consommation en kWh à partir du coût en euros saisi par l’utilisateur, en utilisant le prix du kWh.

function calculateKw() {
      // Extraire le prix du kilowatt depuis les données récupérées
      const prixKw = document.getElementById("contrat-edfoa").value;
      localStorage.setItem('prixKw', prixKw);
      // Utiliser le prix récupéré pour effectuer le calcul
      var euroInput = document.getElementById("euroInput").value;
      var kwCost = euroInput / prixKw; // Conversion des euros en kilowatts
      document.getElementById("kwDisplay").innerHTML = kwCost.toFixed(0) + " kWh";
}

Option de la consommation annuelle

Si l’utilisateur connaît sa consommation annuelle, il peut entrer cette information pour obtenir une estimation du coût en euros.

                            <div id="content2" style="display: none;">

                                <label for="kwInput">Consommation électrique annuelle :</label><br>
                                <input class="custom-label" type="number" id="kwInput" name="kwInput" min="0" class="custom-input">
                                <span class="custom-label1">kWh / An</span>

                                <div class="resultPrice">
                                    <p class="resultDisplay">Estimation de votre consommation</p>
                                    <p class="costDisplay" id="costDisplay"></p>
                                    <p>Estimation calculée sur la base d'un prix moyen de <span id="kwprice"></span>
                                        centimes d'euro par kWh
                                        électrique.</p>
                                </div>
                            </div>

La fonction calculateCost() calcule le coût en euros à partir de la consommation en kWh saisie par l’utilisateur, en utilisant le prix du kWh.

function calculateCost() {
  // Extraire le prix du kilowatt depuis les données récupérées
  const prixKw = document.getElementById("contrat-edfoa").value;
  var kwInput = document.getElementById("kwInput").value;
  var euroCost = kwInput * prixKw; // Conversion des kW en euros (0.25 euro par kWh)
  document.getElementById("costDisplay").innerHTML = euroCost.toFixed(0) + " €";
}

 

Nos solutions ( slide 5 )

À l’étape 5 de notre simulateur d’étude, nous avons ajouté des fonctionnalités pour permettre à l’utilisateur de spécifier les détails de son projet, en se concentrant sur la puissance de l’installation, le prix du projet, le type de contrat, la valorisation immobilière et le nombre de modules.

1. Saisie de la Puissance de l'Installation

Nous avons ajouté un champ de saisie où l’utilisateur peut entrer la puissance de son installation solaire en kilowatts (kW). Cela lui permet de définir la capacité de production d’énergie de son installation.

<input class="kw-install" type="number" id="manual_kw_input" name="manual_kw_input" min="0" step="any" placeholder="ex : 9 KW">

2. Spécification du Prix du Projet

Nous avons inclus deux champs permettant à l’utilisateur de spécifier le prix total du projet, comprenant à la fois le coût du matériel et celui de l’installation. De plus, il peut indiquer le prix par mois de la solution s’il opte pour un paiement mensuel.

<input class="solution-prix" type="number" id="prix_solution_input" name="prix_solution_input" min="0" step="any" placeholder="Saisir le prix de l'installation"> 
<span class="prix-symbole"></span>
...
<input class="solution-prix" type="number" id="prix_solution_mois_input" name="prix_solution_mois_input" min="0" step="any" placeholder="Saisir le prix par mois de la solution">
<span class="prix-symbole">€/mois</span>

3. Choix du Type de Contrat

Nous avons ajouté des options de choix pour que l’utilisateur puisse spécifier le type de contrat qu’il préfère, parmi l’autoconsommation, l’autoconsommation avec vente, et la vente totale de l’électricité produite.

<input class="form-check-input" type="radio" name="contrat" id="autoconsommation" value="autoconsommation"> 
<label class="form-check-label" for="autoconsommation">Autoconsommation</label>

<input class="form-check-input" type="radio" name="contrat" id="autoconsommationVente" value="autoconsommation et vente">
<label class="form-check-label" for="autoconsommationRevente">Autoconsommation avec vente</label>

<input class="form-check-input" type="radio" name="contrat" id="Ventetotale" value="vente totale">
<label class="form-check-label" for="ventetotale">Vente totale</label>

4. Valorisation Immobilière

Nous avons ajouté un champ où l’utilisateur peut entrer le pourcentage supplémentaire de valorisation immobilière que son bien pourrait acquérir grâce à l’installation solaire.

<input class="solution-prix" type="number" id="valorisation_immobiliere" name="valorisation_immobiliere" min="0" max="100" step="any" placeholder="ex : 20%">

5. Spécification du Nombre de Modules

Nous avons créé une section intitulée “Nombre de Modules” avec une description expliquant à quoi correspond ce champ de saisie. L’utilisateur peut entrer un nombre spécifique de panneaux solaires dans la zone de texte.

<h3 class="titlepanel">Nombres de modules </h3> 
<div class="div-prix">
<p>* Le nombre de panneaux de votre installation</p>
<input class="solution-prix" type="number" id="nombre_panneaux_input" name="nombre_panneaux_input" min="0" step="any" placeholder="ex : 10 panneaux">
</div>

Informations personnelles ( slide 6 )

Dans cette section, on a créé des champs de saisie pour collecter des informations telles que le nom, le genre, l’e-mail et le numéro de téléphone du client, ainsi que les détails de l’entreprise, tels que le prénom et le nom du commercial, son numéro de téléphone et son adresse e-mail. Tous les champs sont requis pour soumettre le formulaire.

Une fois que l’utilisateur a rempli ce formulaire et appuyé sur le bouton “Valider”, les données seront traitées dans l’étape suivante pour générer un récapitulatif de l’étude.

Informations Client :

  • Nom : Un champ de saisie (<input type="text">) où le client peut entrer son nom.
<input type="text" placeholder="ex: Dupont" class="form-control" id="last-name"name="last-name" required>
  • Genre : Une liste déroulante (<select>) permettant au client de sélectionner son genre parmi les options Madame, Monsieur ou Madame et Monsieur.
<select class="form-control" id="gender" name="gender" required>
    <option value="">Sélectionnez</option>
    <option value="Madame">Madame</option>
    <option value="Monsieur">Monsieur</option>
    <option value="Madame et Monsieur">Madame et Monsieur</option>
</select>
  • E-mail : Un champ de saisie pour l’e-mail du client.
<input type="text" placeholder="ex: nom@duclient.fr" class="form-control" id="email" name="email" required>
  • Numéro de téléphone : Un champ de saisie pour le numéro de téléphone du client.
<input type="text" placeholder="ex: 0123456789" class="form-control" id="phone" name="phone_number">

Informations Commercial :

  • Prénom du commercial : Un champ de saisie pour le prénom du commercial de l’entreprise.
<input type="text" placeholder="ex: Emilie" class="form-control" id="commercial_first_name" name="commercial_first_name">
  • Nom du commercial : Un champ de saisie pour le nom du commercial de l’entreprise.
<input type="text" placeholder="ex: Dupont" class="form-control" id="commercial_last_name" name="commercial_last_name">
  • Numéro de téléphone du commercial : Un champ de saisie pour le numéro de téléphone du commercial de l’entreprise.
<input type="text" placeholder="ex: 0123456789" class="form-control" id="commercial_phone" name="commercial_phone_number">
  • E-mail du commercial : Un champ de saisie pour l’e-mail du commercial de l’entreprise.
<input type="text" placeholder="ex: adressemail@sunrsolutions.fr" class="form-control" id="commercial_email" name="commercial_email">

Récapitulatif ( slide 7 )

Le récapitulatif final est divisé en plusieurs sections, chacune fournissant des informations spécifiques sur différents aspects du projet solaire. Ces sections comprennent une présentation des informations du commercial et du client, un aperçu du projet, des détails sur les caractéristiques techniques de l’installation solaire, ainsi que des estimations financières détaillées, y compris les primes potentielles et les coûts mensuels. En outre, le récapitulatif final intègre les résultats des fonctionnalités interactives précédantes permettant aux utilisateurs de visualiser et de comprendre facilement leurs choix  d’installation solaire.

Récupération des Informations

Dans cette partie du code, nous avons la fonction recapprofil(), nous utilisons document.getElementById() pour obtenir les valeurs saisies par l’utilisateur dans les champs correspondants du formulaire. Ces valeurs sont récupérées à l’aide de l’attribut value. .

const numCom = document.getElementById('commercial_phone').value; 
const emailCom = document.getElementById('commercial_email').value;
const lastNameCom = document.getElementById('commercial_last_name').value;
const firstNameCom = document.getElementById('commercial_first_name').value;

Stockage des informations

Une fois les valeurs récupérées, nous les stockons dans le stockage local à l’aide de localStorage.setItem() pour une utilisation ultérieure.

localStorage.setItem('numCom', numCom); 
localStorage.setItem('emailCom', emailCom);
localStorage.setItem('lastNameCom', lastNameCom);
localStorage.setItem('firstNameCom', firstNameCom);

Affichage des informations

Cette partie du code vérifie si toutes les informations du commercial ont été saisies par l’utilisateur. Si c’est le cas, ces informations sont ajoutées à la variable recapprofilHTML, qui contient le code HTML du récapitulatif final.

    if (lastName && gender && email && ownerType && address) {
        recapprofilHTML += `
        <div class="profil-recap">
            <h2>Profil Client</h2>
            <p><img class="icon-recap" src="./asset/image/icon/name.svg" alt="nom du client"><strong>Nom :</strong> ${lastName}</p>
            <p><img class="icon-recap" src="./asset/image/icon/genre.svg" alt="genre"><strong>Genre :</strong> ${gender}</p>
            <p><img class="icon-recap" src="./asset/image/icon/email.svg" alt="Email"><strong>E-mail : </strong>${email}</p>
            <p><img class="icon-recap" src="./asset/image/icon/phone.svg" alt="Téléphone du client"><strong>Téléphone : </strong>${num </p>
            <p><img class="icon-recap" src="./asset/image/icon/adresse.svg" alt="Adresse du projet"><strong>Adresse :</strong> ${address}</p>
            <p><img class="icon-recap" src="./asset/image/icon/locataire.svg" alt="Propriétaire ou locataire"><strong>Type de client:</strong> ${ownerType.value}</p>
        </div>
        `;
    }

 

Affichage du récapitulatif dans l'élément HTML

Le récapitulatif final est affiché dans l’élément HTML avec l’ID “recap-profil”.

document.getElementById('recap-profil').innerHTML = recapprofilHTML;

Estimation & Résultats ( slide 7 )

Dans notre simulateur d’étude, nous utilisons PVwatts, une API fournie par le National Renewable Energy Laboratory (NREL) des États-Unis. PVwatts est un outil  utilisé pour estimer les performances et la production d’énergie des systèmes photovoltaïques (PV) à partir de divers paramètres, tels que l’emplacement géographique, l’orientation des panneaux solaires, l’inclinaison du toit et de la puissance en kW de l’installation.

1. Récupération des données du formulaire

On récupère les données de l’utilisateur depuis le formulaire : Cela inclut l’adresse, l’inclinaison du toit, l’orientation des panneaux solaires et la capacité du système solaire. Elles sont essentielles pour personnaliser les estimations de production d’énergie solaire. Chaque installation est unique, et des informations précises permettent de générer des résultats adaptés à la situation spécifique du client.

const address = document.getElementById('address').value
const degresToit = document.getElementById('pitch').value
const orientation = document.querySelector('input[name="orientation"]:checked'); 
const powerInstallation = document.getElementById('manual_kw_input').value;

On a construit les paramètres pour la requête à l’API PVwatts : En utilisant les données de l’utilisateur et des valeurs par défaut pour d’autres paramètres nécessaires à l’estimation de la production d’énergie solaire.

const params = {
  azimuth: `${orientation.value}`,
  system_capacity: `${powerInstallation}`,
  losses: 14.08,
  array_type: 0,
  module_type: 0,
  gcr: 0.4,
  dc_ac_ratio: 1.2,
  inv_eff: 96.0,
  radius: 0,
  dataset: 'intl',
  tilt: `${degresToit}`,
  address: `${address}`,
};

On a créé une requête HTTP pour récupérer les données de production d’énergie solaire : En envoyant les paramètres construits à l’API PVwatts et en gérant les éventuelles erreurs de réseau.

// Construction de l'URL avec les paramètres
const url = new URL(apiUrl);
url.searchParams.append('api_key', apiKey);
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
// Effectuer la requête HTTP
fetch(url)
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })

 

Traitement des données

On a extrait les données mensuelles de production d’énergie (acMonthly) et la production annuelle (annualProduction) à partir de la réponse de l’API.

.then(data => { 
const acMonthly = data.outputs.ac_monthly;
const annualProduction = data.outputs.ac_annual.toFixed(0);
...
})

Affichage du graphiques

L’affichage du graphique dans notre application repose sur l’utilisation de la bibliothèque Chart.js, qui nous permet de créer des graphiques interactifs à partir des données récupérées de l’API PVwatts. Nous configurons d’abord les données du graphique, telles que les étiquettes des axes et les valeurs de données, puis définissons les options de personnalisation comme les couleurs et les échelles. Ensuite, nous utilisons l’objet Chart pour créer le graphique dans un élément HTML spécifié. Une fois le graphique créé, il est affiché sur la page, offrant ainsi une représentation visuelle claire et informative de la production mensuelle d’énergie solaire.

// Créer un tableau des données pour le graphique
    const chartData = {
      labels: months,
      datasets: [{
        label: 'Production mensuelle (kW/h)',
        data: acMonthly,
        backgroundColor: 'rgba(255, 132, 0, 0.2)',
        borderColor: 'rgba(255, 132, 0, 1)',
        borderWidth: 1
      }]
    };
    // Configurer les options du graphique
    const chartOptions = {
      scales: {
        y: {
          beginAtZero: true
        }
      }
    };
    // Créer le graphique
    const ctx = document.getElementById('productionChart').getContext('2d');
    const productionChart = new Chart(ctx, {
      type: 'bar',
      data: chartData,
      options: chartOptions
    });

 

 

Emissions de CO2 évitées

Le calcul des émissions de CO2 évitées repose sur la production annuelle d’énergie solaire et un facteur de conversion qui représente la quantité de CO2 émise par la production d’électricité conventionnelle. Dans le code, cette fonctionnalité est implémentée dans la fonction CO2Avoided.

// fonction calcul les émissions évitées en kg CO2
function CO2Avoided(data) {    
    const carbonEmissionFactor = 0.48; // facteur de conversion (en kg CO2 / kWh)
    // Récupérer la production annuelle en kWh depuis les données
    const annualProductionKWh = data.outputs.ac_annual;
    // Calculer les émissions évitées en tonnes CO2
    const carbonEmissionsAvoided = ((annualProductionKWh * carbonEmissionFactor)/1000).toFixed(1); //conversion kg en tonnes
    localStorage.setItem('carbonEmissionsAvoided', carbonEmissionsAvoided);
    // Afficher les émissions évitées
    document.getElementById('CO2Avoided').innerHTML = `<img src="./asset/image/icon/ecologique.svg" alt="kg co2 évités"><br><p><strong>Total CO2 évités :</strong> ${carbonEmissionsAvoided} tonne(s)/année</p>`;
  }

 

Rentabilité économique

Nous avons mise en place une fonction appelée coutEnergie qui permet de calculer et d’afficher divers aspects financiers liés à la production d’énergie solaire. Cette fonction est importante dans l’estimation de la rentabilité économique d’une installation photovoltaïque en prenant en compte des éléments tels que le coût initial de la solution, les économies réalisées sur la facture d’électricité et les revenus potentiels de la revente d’énergie.

Coût kWh solaire

Nous avons implémenté une section dans notre code pour calculer les économies réalisées par l’utilisateur grâce à l’autoconsommation de l’énergie produite par ses panneaux solaires. L’idée est de montrer combien l’utilisateur économise en utilisant l’énergie solaire au lieu de l’acheter au réseau électrique.

 
    const annualProductionKWh = data.outputs.ac_annual;
    // Calculer la production totale sur 30 ans
    const totalProduction = (annualProductionKWh * 30).toFixed(0);
    // Récupérer le coût de la solution depuis un élément HTML avec l'ID "prix_solution_input"
    const coutSolutionInput = document.getElementById('prix_solution_input').value;
    // Convertir le coût de la solution en nombre
    const coutSolution = parseFloat(coutSolutionInput);
    // Calculer le coût total de l'énergie produite
    const coutEnergie = (coutSolution / totalProduction).toFixed(3);
    localStorage.setItem('coutEnergie', coutEnergie);
    // Afficher les résultats dans l'élément HTML avec l'ID "cout-elec"
    document.getElementById('cout-elec').innerHTML = `<img src="./asset/image/icon/money.svg" alt="Coût Kilowatt solaire"><br><p><strong>Coût Kilowatt solaire : </strong>${coutEnergie} €/kWh</p>`;

Revente EDF OA

j’ai travaillé sur le calcul des revenus de la revente d’énergie à EDF OA, ce qui implique de comprendre comment les tarifs de rachat varient en fonction de la puissance de l’installation (kW) et du type de contrat (autoconsommation && revente totale).

Les tarifs de rachat sont essentiels pour déterminer combien je pouvais potentiellement gagner en vendant l’excédent d’électricité produite par un système photovoltaïque à EDF OA. Pour ce faire, Nous avons créé une base de données JSON qui répertorie les différents tarifs de rachat en fonction des contrats proposés par EDF OA.

{
   
        "edfOa": {
          "edf3": {
            "vente_totale": 0.1178,
            "autoconsommation": 0.1301,
            "prime_autoconsommation": 300
          },
          "edf6": {
            "vente_totale": 0.1355,
            "autoconsommation": 0.1301,
            "prime_autoconsommation": 230
          },
          "edf9": {
            "vente_totale": 0.1215,
            "autoconsommation": 0.1301,
            "prime_autoconsommation": 230
          },
          "edf36": {
            "vente_totale": 0.1215,
            "autoconsommation": 0.0781,
            "prime_autoconsommation": 200
          },
          "edf100": {
            "vente_totale": 0.143,
            "autoconsommation": 0.0781,
            "prime_autoconsommation": 100
          }
        }
     
}

Ensuite, on a récupéré le tarif de revente d’électricité EDF OA stocké localement. On estime la quantité d’énergie vendue à EDF OA en considérant que 25% de la production annuelle totale serait vendue. En multipliant cette quantité d’énergie vendue par le tarif de revente, on a obtenu le montant total des revenus de la revente d’énergie à EDF OA. Ce montant a été ensuite stocké dans le local storage et affiché à l’utilisateur pour lui fournir une estimation des revenus annuels de la revente d’énergie.

const tarif_revente_edfoa = localStorage.getItem('tarif');
   
    const productionrevente = 0.25*annualProductionKWh;
    const reventeprix = (productionrevente * tarif_revente_edfoa).toFixed(0);
    localStorage.setItem('reventeprix', reventeprix);
    if(tarif_revente_edfoa){
        document.getElementById('energie-vendu').innerHTML = `<p><strong>Total EDF OA revente : </strong>${reventeprix} €/ans</p>`;
    }
 

Économie sur la Facture

Nous avons calculé les potentiels économies réalisées sur la facture d’électricité grâce à l’autoconsommation de l’énergie produite par ses panneaux solaires. L’idée est de montrer combien le client économise en utilisant l’énergie solaire au lieu de l’acheter au réseau électrique.

    const prix_KWcontrat = localStorage.getItem('prixKw');

    const eco_production_autoconsommation = 0.75 * annualProductionKWh;

    const economie_facture = (prix_KWcontrat * eco_production_autoconsommation).toFixed(0);

    document.getElementById('economie_facture').innerHTML = `<img src="./asset/image/icon/revente.svg" alt="Économie facture électricité"><br><p><strong>Économie facture: </strong>${economie_facture} €/an</p>`;

Nous avons récupéré le prix par kilowattheure (kWh) contractuel depuis le local storage pour utiliser le tarif actuel que l’utilisateur paie. Ensuite, nous avons estimé que 75% de la production annuelle d’électricité serait autoconsommée, représentant l’énergie utilisée par l’utilisateur. Les économies réalisées sont calculées en multipliant la quantité d’énergie autoconsommée par le prix du kWh, donnant le montant des économies annuelles sur la facture d’électricité.

Gain Financier Total

Enfin, nous avons calculé le gain financier total en ajoutant les économies sur la facture d’électricité et les revenus de la revente d’énergie.

const totalEconomie = parseInt(economie_facture) + parseInt(reventeprix);
    localStorage.setItem('totalEconomie', totalEconomie);
    if(economie_facture && reventeprix){
        document.getElementById('totalEconomie').innerHTML = `<p><strong>Gain financier total : </strong>${totalEconomie} €/an</p>`;
    }

Téléchargement de l'étude

Pour conclure notre projet, nous avons implémenté une fonctionnalité de génération et de téléchargement de PDF personnalisé. Cette étape a permis aux utilisateurs d’obtenir un rapport complet et adapté à leur projet d’installation de panneaux photovoltaïques. Pour cela, nous avons utilisé la bibliothèque PDF-Lib pour modifier un PDF existant avec des données spécifiques à chaque utilisateur. 

Initialisation et Récupération des Données

Nous avons commencé par inclure la bibliothèque PDF-Lib et ajouté un écouteur d’événements sur un bouton de téléchargement. Lorsqu’un utilisateur clique sur ce bouton, les informations stockées dans le localStorage sont récupérées.

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.17.1/pdf-lib.min.js"></script>
 // ... (autres informations récupérées de localStorage

Chargement et Modification du PDF

Nous avons utilisé fetch pour récupérer le PDF modèle et PDFDocument.load pour le charger. Ensuite, nous avons modifié des pages spécifiques du PDF en ajoutant des textes personnalisés. nous avons utilisé la méthode drawText pour ajouter des textes personnalisés. Sur la première page, nous avons inclus des informations telles que le nom du client, son genre, son adresse et la puissance d’installation des panneaux solaires. Sur d’autres pages, nous avons ajouté des détails sur le projet, tels que le type de toit, la production annuelle d’électricité, le type de contrat, etc.

const pdfUrl = 'asset/PDF/etude_1.pdf';
    const response = await fetch(pdfUrl);
    const arrayBuffer = await response.arrayBuffer();

    const pdfDoc = await PDFDocument.load(arrayBuffer);

    const pages = pdfDoc.getPages();
    const firstPage = pages[0];
    const thirdPage = pages[2];
    const fourthPage = pages[3];
    // ... (autres pages)

    const helveticaBoldFont = await pdfDoc.embedFont(PDFLib.StandardFonts.HelveticaBold);
    // Ajouter les informations à la première page

    firstPage.drawText(`${gender || ''}`, { x: width -540, y: height - 455, size: 57, color: blue, font: helveticaBoldFont });
    firstPage.drawText(`${lastname || ''}`, { x: width -540, y: height - 530, size: 57, color: blue, font: helveticaBoldFont });
    firstPage.drawText(`${powerInstallation || ''} kWc`, { x: width -383, y: height - 579, size: 16, color: orange, font: helveticaBoldFont });
    firstPage.drawText(`${address || ''}`, { x: width -535, y: height - 665, size: 14, color: blue });
    // ... (ajout d'autres informations)

Sauvegarde et Téléchargement du PDF

 Une fois que toutes les modifications ont été apportées au PDF, nous le sauvegardons avec pdfDoc.save(). Ensuite, nous créons un lien de téléchargement en créant un objet Blob contenant les données PDF, puis en créant un lien <a> avec l’URL du Blob. Enfin, nous définissons le nom du fichier PDF téléchargé à l’aide de l’attribut download, et déclenchons le téléchargement en cliquant sur ce lien.

// Sauvegarde du PDF modifié
    const pdfBytes = await pdfDoc.save();
    // Téléchargement du PDF modifié
    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = `installation ${powerInstallation}kWc  ${lastname} .pdf`;
    link.click();