first commit
This commit is contained in:
459
ESP8266_BATTERIE_INJECTION/html.h
Normal file
459
ESP8266_BATTERIE_INJECTION/html.h
Normal file
@@ -0,0 +1,459 @@
|
||||
|
||||
// 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é :</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);
|
||||
}
|
||||
Reference in New Issue
Block a user