Files
Arduino/ESP8266_BATTERIE_INJECTION/html.h
2025-07-01 18:25:48 +02:00

458 lines
17 KiB
C

// Linear Regression Equation: y = 80.9356x + -2086.7172
// R^2 for Linear Regression: 0.8820
// Polynomial Regression (Degree 2) Equation: y = 65.2734x^2 + -3353.2872x + 43075.5362
// R^2 for Polynomial Regression (Degree 2): 0.9724
// Polynomial Regression (Degree 3) Equation: y = -71.35479595x^3 + 5699.68320483x^2 + -151636.19028283x + 1343695.66923927
// R^2 for Polynomial Regression (Degree 3): 0.9821
String to_include = R"=(
<SCRIPT>
var xmlHttp01=createXmlHttpObject();
var chart;
// Fonction pour envoyer la valeur du slider au serveur
function sendSliderValue(sliderId, value) {
fetch('/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ slider: sliderId, value: value })
})
//.then(response => response.json())
.then(data => {showNotification('Consigne mise à jour'); console.log('Succès:', data)})
.catch(error => console.error('Erreur:', error));
}
function createXmlHttpObject(){
if(window.XMLHttpRequest){
xmlHttp=new XMLHttpRequest();
}else{
xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');
}
return xmlHttp;
}
function getCurrentTimeString() {
var now = new Date();
var hours = now.getHours().toString().padStart(2, '0');
var minutes = now.getMinutes().toString().padStart(2, '0');
var seconds = now.getSeconds().toString().padStart(2, '0');
var currentTime = hours + ':' + minutes + ':' + seconds;
return currentTime;
}
function process(){
if(xmlHttp01.readyState==0 || xmlHttp01.readyState==4){
xmlHttp01.open('GET','getVictron',true);
xmlHttp01.onreadystatechange=handleServerResponse;
xmlHttp01.send(null);
}
setTimeout('process()', 5000);
}
function handleServerResponse(){
var field = document.getElementById('response_items');
if(field && xmlHttp01.readyState == 4 && xmlHttp01.status == 200){
const json_obj = JSON.parse(xmlHttp01.response);
console.log(xmlHttp01.response);
// Vérifiez si la table existe déjà, sinon créez-en une
var table = document.getElementById('response_table');
if (!table) {
table = document.createElement('table');
table.id = 'response_table';
// Insérez une seule ligne pour les données
var dataRow = table.insertRow();
dataRow.id = 'data_row';
document.getElementById('response_items').appendChild(table);
// Ajoutez les id
dataRow.insertCell().innerHTML = "Date";
for (var i = 3; i < json_obj.length - 1; i++){
var obj = json_obj[i];
dataRow.insertCell().innerHTML = obj.key_label ? obj.key_label : obj.id;
}
}
var dataRow = table.insertRow(1);
dataRow.id = 'data_row';
document.getElementById('response_items').appendChild(table);
// Initialiser le graphique
var field_chart = document.getElementById('chartCanvas');
// Ajoutez les nouvelles données dans la même ligne
dataRow.insertCell().innerHTML = getCurrentTimeString();
var time_field = document.getElementById('hour');
time_field.textContent= getCurrentTimeString();
var tensions = "";
for (var i = 3; i < json_obj.length - 1; i++){
var obj = json_obj[i];
if (obj.id == "tensions") {
if (field_chart && chart) {
var tensions = obj.value.split(',');
var numerictensions = tensions.map(Number);
var labels = obj.labels.split(',');
chart.data.labels = labels;
chart.data.datasets[0].data = numerictensions;
// var ctx = chart.ctx;
// var yAxis = chart.scales.y;
// var yValues = [25.7, 26.12, 26.42, 26.44, 26.46, 26.56, 26.66, 26.7, 26.74, 26.92 ];
// var yPercentages = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"];
//
// ctx.save();
// ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
// ctx.lineWidth = 1;
// yValues.forEach(function(value, index) {
// var y = yAxis.getPixelForValue(value);
// ctx.beginPath();
// ctx.moveTo(chart.chartArea.left, y);
// ctx.lineTo(chart.chartArea.right, y);
// ctx.stroke();
// ctx.fillStyle = 'white';
// ctx.fillText(yPercentages[index], chart.chartArea.right + 5, y + 3);
// });
// ctx.restore();
chart.update();
}
}
else {
//dataRow.insertCell().innerHTML = obj.id;
dataRow.insertCell().innerHTML = obj.label ? obj.label : obj.value;
var field = document.getElementById(obj.id);
if (field) {
field.textContent = obj.value ;
}
field = document.getElementById("IND_" + obj.id);
if (field) {
field.textContent = obj.value ;
}
}
}
// Conservez uniquement les 10 dernières entrées
while (table.rows.length > 31) { // 1 pour l'en-tête + 10 pour les données
table.deleteRow(-1); // Supprime la dernière ligne
}
if (field_chart && !chart) {
var ctx = field_chart.getContext('2d');
chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['25 mai', '24 mai', '23 mai', '22 mai', '21 mai', '20 mai', '19 mai', '18 mai', '17 mai', '16 mai'],
datasets: [{
label: 'Tensions (mV)',
data: [20, 10, 5, 0, 0, 0, 0, 0, 0, 0],
backgroundColor: 'rgba(255, 255, 255, 0.6)',
borderColor: 'rgba(255, 255, 255, 1)',
borderWidth: 1
}]
},
options: {
plugins: {
legend: {
labels: {
color: 'white',
font: {
size: 30
}
}
},
beforeDraw: function(chart) {
var ctx = chart.ctx;
var yAxis = chart.scales.y;
var yValues = [25.7, 25.87, 26.04, 26.21, 26.38, 26.55, 26.72, 26.89];
var yPercentages = ["10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"];
ctx.save();
ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
ctx.lineWidth = 1;
yValues.forEach(function(value, index) {
var y = yAxis.getPixelForValue(value);
ctx.beginPath();
ctx.moveTo(chart.chartArea.left, y);
ctx.lineTo(chart.chartArea.right, y);
ctx.stroke();
ctx.fillStyle = 'white';
ctx.fillText(yPercentages[index], chart.chartArea.right + 5, y + 3);
});
ctx.restore();
}
},
scales: {
y: {
ticks: {
color: 'white',
beginAtZero: false
},
afterBuildTicks: function(scale) {
return [25.7, 25.87, 26.04, 26.21, 26.38, 26.55, 26.72, 26.89];
}
},
x: {
ticks: {
color: 'white'
}
}
}
}
});
}
}
}
document.addEventListener('DOMContentLoaded', function() {
// function updateChart(newLabels, newData) {
// if (chart) {
// chart.data.labels = newLabels;
// chart.data.datasets[0].data = newData;
// chart.update();
// }
// }
//
// // Example of updating the chart with new values
// setTimeout(function() {
// var newLabels = ['26 mai', '25 mai', '24 mai', '23 mai', '22 mai', '21 mai', '20 mai', '19 mai', '18 mai', '17 mai'];
// var newData = [15, 20, 10, 5, 0, 0, 0, 0, 0, 0];
// updateChart(newLabels, newData);
// }, 5000);
//
});
// document.getElementById('slider2').addEventListener('change', function() {
// sendSliderValue('slider2', this.value);
// });
</SCRIPT>
)=";
String webpage = R"=(
<div class="container">
<header>
<h1>Controle des batteries : MPPT 100/20 48V</h1>
<div class="header_info">
<h2>@@IP@@</h2>
<h2 id="hour">@@TIME@@</h2>
<div>
<span class="connection-indicator">@@CONNECTION_INDICATOR@@</span>
<button onclick="location.href='/settings'">Paramétrage</button>
</div>
</div>
</header>
<div class="tab-buttons">
<div class="tab-button" onclick="showTab('main-section')">Main</div>
<div class="tab-button" onclick="showTab('graph-section')">Graph</div>
<div class="tab-button" onclick="showTab('data-section')">Data</div>
</div>
<main>
<div id="main-section" class="tab">
<div class="buttons_section">
@@BUTTONS@@
</div>
<div class="slider-container">
<div class="slider-wrapper">
<span class="slider-label">Courant charge:</span>
<input type="range" class="slider" id="sliderCurrent" min="0" max="20" value="@@CC@@">
</div>
</div>
<div class="slider-container">
<div class="slider-wrapper">
<span class="slider-label">Courant injection:</span>
<input type="range" class="slider" id="sliderCurrent2" min="0" max="20" value="@@CC2@@">
</div>
</div>
<ul class="power-displays">
@@INDICATORS@@
</ul>
<aside>
<div class="status">
<h2>Statut</h2>
<div class="status-section">
<h3>Solaire</h3>
e<p><span>Tension:</span> <span id="VPV">@@VPV@@</span><span> mV</span></p>
<p><span>Courant:</span> <span id="PPV">@@PPV@@</span><span> mA</span></p>
</div>
<div class="status-section">
<h3>Batterie</h3>
<p><span>Tension:</span> <span id="V">@@V@@</span><span> mV</span></p>
<p><span>Courant:</span> <span id="I">@@I@@</span><span> mA</span></p>
<p><span>État:</span> <span id="CS">Absorption</span></p>
</div>
<div class="status-section">
<h3>Sortie de charge</h3>
<p><span>État:</span> <span id="LOAD">@@LOAD@@</span></p>
<p><span>Courant:</span> <span id="IL">@@IL@@</span><span> mA</span></p>
<p><span>Puissance:</span> <span id="output-power">3</span><span> W</span></p>
</div>
</div>
</aside>
</div>
<div id="graph-section" class="tab">
<div class="chart">
<h2>5 dernières heures</h2>
<canvas id="chartCanvas"></canvas>
</div>
</div>
<div id="data-section" class="tab">
<div class='victron_data'>
<span><A id='response_items'></A>
</span>
</div>
</div>
</main>
</div>
)=";
String indicator = R"=(
<li class="power-display">
<div class="power-indicator">
<div id="@@KEY@@" class="power-value">@@VALUE@@</div>
<div id="power-source" class="power-source">@@LABEL@@</div>
</div>
</li>
)=";
String end_script_to_add = R"=(
<script>
function showTab(tabId) {
var tabs = document.getElementsByClassName('tab');
for (var i = 0; i < tabs.length; i++) {
tabs[i].style.display = 'none';
}
var tab = document.getElementById(tabId)
if (tab) {
tab.style.display = 'block';
var tabButtons = document.getElementsByClassName('tab-button');
for (var i = 0; i < tabButtons.length; i++) {
tabButtons[i].classList.remove('active');
}
tab.classList.add('active');
}
}
document.addEventListener('DOMContentLoaded', function() {
showTab('main-section'); // Affiche le premier onglet par défaut
});
// // Ajouter un écouteur d'événement pour chaque slider
// document.getElementById('sliderCurrent').addEventListener('change', function() {
// sendSliderValue('sliderCurrent', this.value);
// });
// // Ajouter un écouteur d'événement pour chaque slider
// document.getElementById('sliderCurrent2').addEventListener('change', function() {
// sendSliderValue('sliderCurrent2', this.value);
// });
</script>
)=";
void handleSettings() {
String html = "<html>\
<head>\
<style>\
body {\
font-family: Arial, sans-serif;\
background-color: #f4f4f4;\
display: flex;\
justify-content: center;\
align-items: center;\
height: 100vh;\
margin: 0;\
}\
.form-container {\
background-color: #fff;\
padding: 20px;\
border-radius: 8px;\
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\
width: 600px;\
}\
h2 {\
color: #333;\
text-align: center;\
}\
.form-content {\
display: flex;\
justify-content: space-between;\
}\
.column {\
display: flex;\
flex-direction: column;\
width: 48%;\
}\
label {\
margin-bottom: 5px;\
font-weight: bold;\
color: #555;\
}\
input[type='text'] {\
padding: 10px;\
margin-bottom: 15px;\
border: 1px solid #ccc;\
border-radius: 4px;\
font-size: 16px;\
}\
input[type='submit'] {\
background-color: #28a745;\
color: white;\
border: none;\
padding: 10px;\
border-radius: 4px;\
cursor: pointer;\
font-size: 16px;\
margin-top: 10px;\
width: 100%;\
}\
input[type='submit']:hover {\
background-color: #218838;\
}\
</style>\
</head>\
<body>\
<div class=\"form-container\">\
<h2>Configuration</h2>\
<form action=\"/save\" method=\"POST\">\
<div class=\"form-content\">\
<div class=\"column\">\
<label for=\"max_current_charge\">MAX CHARGE :</label>\
<input type=\"number\" id=\"max_current_charge\" name=\"max_current_charge\" min=\"0\" max=\"20\" value=\"" + String(config.max_current_charge) + "\">\
<label for=\"voltage_charge\">VOLTAGE CHARGE :</label>\
<input type=\"number\" id=\"voltage_charge\" name=\"voltage_charge\" min=\"0\" max=\"48\" step=\"0.1\" value=\"" + String(config.voltage_charge) + "\">\
<label for=\"max_current_injection\">MAX INJECTION :</label>\
<input type=\"number\" id=\"max_current_injection\" name=\"max_current_injection\" min=\"0\" max=\"20\" value=\"" + String(config.max_current_injection) + "\">\
<label for=\"voltage_injection\">VOLTAGE INJECTION :</label>\
<input type=\"number\" id=\"voltage_injection\" name=\"voltage_injection\" min=\"0\" max=\"48\" step=\"0.1\" value=\"" + String(config.voltage_injection) + "\">\
<label for=\"configured\">Configur&eacute; :</label>\
<input type=\"checkbox\" id=\"configured\" name=\"configured\" readonly=\"readonly\" @@checked@@>\
</div>\
</div>\
<input type=\"submit\" value=\"Save\">\
</form>\
</div>\
</body>\
</html>";
html.replace("@@checked@@", (config.configured ? "checked" : ""));
server.send(200, "text/html", html);
}