Filament dryer page
This commit is contained in:
512
public/filamentDryer.php
Normal file
512
public/filamentDryer.php
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
<?php include '../src/session_check.php';
|
||||||
|
checkUserRole(['admin']);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<html lang="en" data-bs-theme="light">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!--favicon-->
|
||||||
|
<link rel="icon" href="../assets/images/favicon-32x32.png" type="image/png">
|
||||||
|
<!--plugins-->
|
||||||
|
<link href="../assets/plugins/vectormap/jquery-jvectormap-2.0.2.css" rel="stylesheet">
|
||||||
|
<link href="../assets/plugins/simplebar/css/simplebar.css" rel="stylesheet">
|
||||||
|
<link href="../assets/plugins/perfect-scrollbar/css/perfect-scrollbar.css" rel="stylesheet">
|
||||||
|
<link href="../assets/plugins/metismenu/css/metisMenu.min.css" rel="stylesheet">
|
||||||
|
<!-- loader-->
|
||||||
|
<link href="../assets/css/pace.min.css" rel="stylesheet"/>
|
||||||
|
<script src="../assets/js/pace.min.js"></script>
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link href="../assets/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="../assets/css/bootstrap-extended.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<link href="../assets/sass/app.css" rel="stylesheet">
|
||||||
|
<link href="../assets/css/icons.css" rel="stylesheet">
|
||||||
|
<link href='https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css' rel='stylesheet'>
|
||||||
|
<!-- Theme Style CSS -->
|
||||||
|
<link rel="stylesheet" href="../assets/sass/dark-theme.css">
|
||||||
|
<link rel="stylesheet" href="../assets/sass/semi-dark.css">
|
||||||
|
<link rel="stylesheet" href="../assets/sass/bordered-theme.css">
|
||||||
|
|
||||||
|
<title>TOD Dashboard</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!--wrapper-->
|
||||||
|
<div class="wrapper">
|
||||||
|
<!--sidebar wrapper -->
|
||||||
|
<?php include '../src/nav.php'; ?>
|
||||||
|
<!--end sidebar wrapper -->
|
||||||
|
<!--start header -->
|
||||||
|
<?php include '../src/header.php'; ?>
|
||||||
|
<!--end header -->
|
||||||
|
|
||||||
|
<!--start page wrapper -->
|
||||||
|
<div class="page-wrapper">
|
||||||
|
<div class="page-content">
|
||||||
|
<!--start page content -->
|
||||||
|
<div class="container mt-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card bg-danger radius-10 overflow-hidden">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0">Dryer Status</p>
|
||||||
|
<h5 class="mb-0">STATUS</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card bg-danger radius-10 overflow-hidden" id="heaterRelayStatus">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0">Heater Status</p>
|
||||||
|
<h5 class="mb-0">STATUS</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card bg-danger radius-10 overflow-hidden" id="fanRelayStatus">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0">Fan Status</p>
|
||||||
|
<h5 class="mb-0">STATUS</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<!-- Left Column - Charts -->
|
||||||
|
<div class="col-lg-7">
|
||||||
|
<div class="row">
|
||||||
|
<!-- Temperature Chart -->
|
||||||
|
<div class="col-lg-12 mb-4">
|
||||||
|
<div class="card radius-10 overflow-hidden">
|
||||||
|
<div class="card-body d-flex align-items-center justify-content-between">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 filament-name">Temp:</p>
|
||||||
|
<h5 class="mb-0" id="temperatureValue">--°C</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="tempChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Humidity Chart -->
|
||||||
|
<div class="col-lg-12 mb-4">
|
||||||
|
<div class="card radius-10 overflow-hidden">
|
||||||
|
<div class="card-body d-flex align-items-center justify-content-between">
|
||||||
|
<div>
|
||||||
|
<p class="mb-0 filament-name">Humidity:</p>
|
||||||
|
<h5 class="mb-0" id="humidityValue">--%</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="humidityChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Column - Dryer Control Form -->
|
||||||
|
<div class="col-lg-5">
|
||||||
|
<div class="card radius-10 overflow-hidden">
|
||||||
|
<div class="card-header bg-primary text-white">
|
||||||
|
<h5 class="mb-0">Filament Dryer Control</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form id="dryerControlForm">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="filamentPreset" class="form-label">Filament Preset</label>
|
||||||
|
<select class="form-select" id="filamentPreset" name="filamentPreset" required>
|
||||||
|
<option value="">Select Filament Type</option>
|
||||||
|
<option value="PLA" data-temp="50">PLA</option>
|
||||||
|
<option value="ABS" data-temp="70">ABS</option>
|
||||||
|
<option value="PETG" data-temp="65">PETG</option>
|
||||||
|
<option value="Nylon" data-temp="80">Nylon</option>
|
||||||
|
<option value="TPU" data-temp="45">TPU</option>
|
||||||
|
<option value="Custom" data-temp="">Custom</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="dryingTime" class="form-label">Drying Time (Hours)</label>
|
||||||
|
<input type="number" class="form-control" id="dryingTime" name="dryingTime" min="1" max="24" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="temperature" class="form-label">Drying Temperature (°C)</label>
|
||||||
|
<input type="number" class="form-control" id="temperature" name="temperature" min="30" max="100" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<button type="submit" class="btn btn-success">Start Drying</button>
|
||||||
|
<button type="button" class="btn btn-danger" id="dryerOff">Turn Off Dryer</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Progress Bar Section -->
|
||||||
|
<div class="card mt-4 radius-10 overflow-hidden">
|
||||||
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
||||||
|
<h5 class="mb-0">Drying Progress</h5>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="progress mb-2">
|
||||||
|
<div class="progress-bar bg-success" id="dryingProgress" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||||||
|
</div>
|
||||||
|
<p class="mb-0">Time Set: <span id="dryingTimeDisplay">--</span></p>
|
||||||
|
<p class="mb-0">Remaining Time: <span id="remainingTimeDisplay">--</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--end page content -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--end page wrapper -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- search modal -->
|
||||||
|
<div class="modal" id="SearchModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-fullscreen-md-down">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header gap-2">
|
||||||
|
<div class="position-relative popup-search w-100">
|
||||||
|
<input class="form-control form-control-lg ps-5 border border-3 border-primary" type="search" placeholder="Search">
|
||||||
|
<span class="position-absolute top-50 search-show ms-3 translate-middle-y start-0 top-50 fs-4"><i class='bx bx-search'></i></span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close d-md-none" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- end search modal -->
|
||||||
|
|
||||||
|
<!-- Bootstrap JS -->
|
||||||
|
<script src="../assets/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<!--plugins-->
|
||||||
|
<script src="../assets/js/jquery.min.js"></script>
|
||||||
|
<script src="../assets/plugins/simplebar/js/simplebar.min.js"></script>
|
||||||
|
<script src="../assets/plugins/metismenu/js/metisMenu.min.js"></script>
|
||||||
|
<script src="../assets/plugins/perfect-scrollbar/js/perfect-scrollbar.js"></script>
|
||||||
|
<script src="../assets/plugins/apexcharts-bundle/js/apexcharts.min.js"></script>
|
||||||
|
<!--app JS-->
|
||||||
|
<script src="../assets/js/app.js"></script>
|
||||||
|
|
||||||
|
<script src="../assets/js/index.js"></script>
|
||||||
|
<script src="../assets/plugins/peity/jquery.peity.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(".data-attributes span").peity("donut")
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const ESP32_IP = 'https://filamentdry.hickmeister.uk'; // Replace with your ESP32 IP
|
||||||
|
let tempChart, humidityChart;
|
||||||
|
|
||||||
|
// Fetch ESP32 Status Data
|
||||||
|
function fetchDryerStatus() {
|
||||||
|
fetch(`${ESP32_IP}/status`)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (data.dryerOn !== undefined) {
|
||||||
|
updateTemperatureCard(data);
|
||||||
|
updateHumidityCard(data);
|
||||||
|
updateStatusCards(data);
|
||||||
|
updateProgressBar(data); // Update progress bar and time displays
|
||||||
|
} else {
|
||||||
|
console.error("Dryer offline or no data available");
|
||||||
|
showOfflineStatus();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Failed to fetch dryer status:", error);
|
||||||
|
showOfflineStatus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Control Dryer
|
||||||
|
function controlDryer(dryerOn, targetTemperature, dryingTimeInMinutes) {
|
||||||
|
const formData = new URLSearchParams();
|
||||||
|
formData.append("dryerOn", dryerOn);
|
||||||
|
formData.append("targetTemperature", targetTemperature);
|
||||||
|
formData.append("dryingTime", dryingTimeInMinutes);
|
||||||
|
|
||||||
|
fetch(`${ESP32_IP}/control`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
body: formData.toString(),
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
console.log('Dryer control updated:', data);
|
||||||
|
fetchDryerStatus(); // Refresh status after control update
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Failed to update dryer control:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent Form Submission Refresh
|
||||||
|
const dryerControlForm = document.getElementById("dryerControlForm");
|
||||||
|
if (dryerControlForm) {
|
||||||
|
dryerControlForm.addEventListener("submit", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// Collect form data
|
||||||
|
const formData = new FormData(dryerControlForm);
|
||||||
|
const dryerOn = true; // Always true when starting the dryer
|
||||||
|
const filamentPreset = formData.get("filamentPreset");
|
||||||
|
const dryingTimeInHours = parseFloat(formData.get("dryingTime"));
|
||||||
|
const targetTemperature = parseFloat(formData.get("temperature"));
|
||||||
|
|
||||||
|
// Validate Input
|
||||||
|
if (!filamentPreset || isNaN(dryingTimeInHours) || isNaN(targetTemperature)) {
|
||||||
|
alert("Please complete all required fields.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert drying time to minutes
|
||||||
|
const dryingTimeInMinutes = Math.round(dryingTimeInHours * 60);
|
||||||
|
|
||||||
|
// Control Dryer
|
||||||
|
controlDryer(dryerOn, targetTemperature, dryingTimeInMinutes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Turn Off Dryer
|
||||||
|
const dryerOffButton = document.getElementById("dryerOff");
|
||||||
|
if (dryerOffButton) {
|
||||||
|
dryerOffButton.addEventListener("click", function () {
|
||||||
|
controlDryer(false, 0, 0); // Turn off the dryer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-Fill Temperature Input Based on Filament Preset
|
||||||
|
const filamentPresetSelect = document.getElementById("filamentPreset");
|
||||||
|
const temperatureInput = document.getElementById("temperature");
|
||||||
|
|
||||||
|
if (filamentPresetSelect && temperatureInput) {
|
||||||
|
filamentPresetSelect.addEventListener("change", function () {
|
||||||
|
const selectedOption = filamentPresetSelect.options[filamentPresetSelect.selectedIndex];
|
||||||
|
const presetTemperature = selectedOption.getAttribute("data-temp");
|
||||||
|
|
||||||
|
if (presetTemperature) {
|
||||||
|
temperatureInput.value = presetTemperature; // Auto-fill temperature input
|
||||||
|
} else {
|
||||||
|
temperatureInput.value = ""; // Clear the temperature input for "Custom"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Progress Bar and Time Display
|
||||||
|
function updateProgressBar(data) {
|
||||||
|
const progressBar = document.getElementById("dryingProgress");
|
||||||
|
const dryingTimeEl = document.getElementById("dryingTimeDisplay"); // Total drying time display
|
||||||
|
const remainingTimeDisplay = document.getElementById("remainingTimeDisplay"); // Remaining time display
|
||||||
|
|
||||||
|
const dryingTime = data.dryingTime || 0; // Total drying time in minutes
|
||||||
|
const remainingTime = data.remainingTime || 0; // Remaining time in minutes
|
||||||
|
|
||||||
|
// Reset progress bar if the dryer is turned off
|
||||||
|
if (!data.dryerOn) {
|
||||||
|
if (progressBar) {
|
||||||
|
progressBar.style.width = "0%";
|
||||||
|
progressBar.setAttribute("aria-valuenow", 0);
|
||||||
|
}
|
||||||
|
if (dryingTimeEl) {
|
||||||
|
dryingTimeEl.innerText = "Total: 0h 0m";
|
||||||
|
}
|
||||||
|
if (remainingTimeDisplay) {
|
||||||
|
remainingTimeDisplay.innerText = "Remaining: 0h 0m";
|
||||||
|
}
|
||||||
|
return; // Exit early as no further updates are needed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update progress bar when the dryer is on
|
||||||
|
if (progressBar && dryingTime > 0) {
|
||||||
|
const progressPercent = ((dryingTime - remainingTime) / dryingTime) * 100;
|
||||||
|
progressBar.style.width = `${progressPercent}%`;
|
||||||
|
progressBar.setAttribute("aria-valuenow", progressPercent.toFixed(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update time displays
|
||||||
|
if (dryingTimeEl) {
|
||||||
|
dryingTimeEl.innerText = `Total: ${convertToHoursAndMinutes(dryingTime)}`;
|
||||||
|
}
|
||||||
|
if (remainingTimeDisplay) {
|
||||||
|
remainingTimeDisplay.innerText = `Remaining: ${convertToHoursAndMinutes(remainingTime)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert minutes to hours and minutes
|
||||||
|
function convertToHoursAndMinutes(minutes) {
|
||||||
|
const hours = Math.floor(minutes / 60);
|
||||||
|
const mins = minutes % 60;
|
||||||
|
return `${hours}h ${mins}m`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Temperature Card and Chart
|
||||||
|
function updateTemperatureCard(data) {
|
||||||
|
const temperature = data.temperature.toFixed(1); // Limit temperature to 1 decimal place
|
||||||
|
const tempHistory = data.tempHistory.map(temp => parseFloat(temp.toFixed(1))); // Limit history data
|
||||||
|
const timestamps = Array.from({ length: tempHistory.length }, (_, i) => `${i + 1}`);
|
||||||
|
|
||||||
|
document.getElementById('temperatureValue').innerText = `${temperature}°C`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
series: [{ name: "Temperature", data: tempHistory }],
|
||||||
|
chart: {
|
||||||
|
type: 'area',
|
||||||
|
height: 150,
|
||||||
|
toolbar: { show: false },
|
||||||
|
sparkline: { enabled: true },
|
||||||
|
id: 'tempChart',
|
||||||
|
},
|
||||||
|
stroke: { curve: 'smooth' },
|
||||||
|
xaxis: { categories: timestamps, labels: { show: false } },
|
||||||
|
tooltip: {
|
||||||
|
theme: 'dark',
|
||||||
|
x: { show: false },
|
||||||
|
y: { formatter: value => `${value.toFixed(1)}°C` },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!tempChart) {
|
||||||
|
tempChart = new ApexCharts(document.querySelector("#tempChart"), options);
|
||||||
|
tempChart.render();
|
||||||
|
} else {
|
||||||
|
tempChart.updateSeries([{ data: tempHistory }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Humidity Card and Chart
|
||||||
|
function updateHumidityCard(data) {
|
||||||
|
const humidity = data.humidity.toFixed(1);
|
||||||
|
const humidityHistory = data.humidityHistory || [];
|
||||||
|
const timestamps = Array.from({ length: humidityHistory.length }, (_, i) => `${i + 1}`);
|
||||||
|
|
||||||
|
document.getElementById('humidityValue').innerText = `${humidity}%`;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
series: [{ name: "Humidity", data: humidityHistory }],
|
||||||
|
chart: {
|
||||||
|
type: 'area',
|
||||||
|
height: 150,
|
||||||
|
toolbar: { show: false },
|
||||||
|
sparkline: { enabled: true },
|
||||||
|
id: 'humidityChart',
|
||||||
|
},
|
||||||
|
stroke: { curve: 'smooth' },
|
||||||
|
xaxis: { categories: timestamps, labels: { show: false } },
|
||||||
|
tooltip: {
|
||||||
|
theme: 'dark',
|
||||||
|
x: { show: false },
|
||||||
|
y: { formatter: value => `${value.toFixed(1)}%` },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!humidityChart) {
|
||||||
|
humidityChart = new ApexCharts(document.querySelector("#humidityChart"), options);
|
||||||
|
humidityChart.render();
|
||||||
|
} else {
|
||||||
|
humidityChart.updateSeries([{ data: humidityHistory }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Status Cards
|
||||||
|
function updateStatusCards(data) {
|
||||||
|
const dryerStatusCard = document.querySelector('.card:nth-child(1)');
|
||||||
|
const heaterStatusCard = document.getElementById('heaterRelayStatus');
|
||||||
|
const fanStatusCard = document.getElementById('fanRelayStatus');
|
||||||
|
|
||||||
|
const dryerState = data.dryerOn ? "On" : "Off";
|
||||||
|
const fanRelayState = data.fanRelayState ? "On" : "Off";
|
||||||
|
const heaterRelayState = data.heaterRelayState ? "On" : "Off";
|
||||||
|
|
||||||
|
if (dryerStatusCard) {
|
||||||
|
dryerStatusCard.classList.toggle("bg-success", dryerState === "On");
|
||||||
|
dryerStatusCard.classList.toggle("bg-danger", dryerState === "Off");
|
||||||
|
dryerStatusCard.querySelector("h5").innerText = dryerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heaterStatusCard) {
|
||||||
|
heaterStatusCard.classList.toggle("bg-success", heaterRelayState === "On");
|
||||||
|
heaterStatusCard.classList.toggle("bg-danger", heaterRelayState === "Off");
|
||||||
|
heaterStatusCard.querySelector("h5").innerText = heaterRelayState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanStatusCard) {
|
||||||
|
fanStatusCard.classList.toggle("bg-success", fanRelayState === "On");
|
||||||
|
fanStatusCard.classList.toggle("bg-danger", fanRelayState === "Off");
|
||||||
|
fanStatusCard.querySelector("h5").innerText = fanRelayState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show Offline Status
|
||||||
|
function showOfflineStatus() {
|
||||||
|
const dryerStatusCard = document.querySelector('.card:nth-child(1)');
|
||||||
|
const heaterStatusCard = document.getElementById('heaterRelayStatus');
|
||||||
|
const fanStatusCard = document.getElementById('fanRelayStatus');
|
||||||
|
const progressBar = document.getElementById("dryingProgress");
|
||||||
|
|
||||||
|
if (dryerStatusCard) {
|
||||||
|
dryerStatusCard.classList.remove("bg-success");
|
||||||
|
dryerStatusCard.classList.add("bg-danger");
|
||||||
|
dryerStatusCard.querySelector("h5").innerText = "Offline";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heaterStatusCard) {
|
||||||
|
heaterStatusCard.classList.remove("bg-success");
|
||||||
|
heaterStatusCard.classList.add("bg-danger");
|
||||||
|
heaterStatusCard.querySelector("h5").innerText = "Offline";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fanStatusCard) {
|
||||||
|
fanStatusCard.classList.remove("bg-success");
|
||||||
|
fanStatusCard.classList.add("bg-danger");
|
||||||
|
fanStatusCard.querySelector("h5").innerText = "Offline";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progressBar) {
|
||||||
|
progressBar.style.width = "0%";
|
||||||
|
progressBar.setAttribute("aria-valuenow", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch data every 10 seconds
|
||||||
|
fetchDryerStatus();
|
||||||
|
setInterval(fetchDryerStatus, 10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- Printing Section -->
|
||||||
|
<li class="menu-label">Printing Control</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="viewPrinters.php">
|
<a href="viewPrinters.php">
|
||||||
<div class="parent-icon"><i class='bx bx-code-alt'></i>
|
<div class="parent-icon"><i class='bx bx-code-alt'></i>
|
||||||
@@ -28,6 +30,13 @@
|
|||||||
<div class="menu-title">Printer Dashboard</div>
|
<div class="menu-title">Printer Dashboard</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="filamentDryer.php">
|
||||||
|
<div class="parent-icon"><i class='bx bx-plus-circle'></i>
|
||||||
|
</div>
|
||||||
|
<div class="menu-title">Dryer Control</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<!-- Filament Tracking Section -->
|
<!-- Filament Tracking Section -->
|
||||||
<li class="menu-label">Filament Tracker</li>
|
<li class="menu-label">Filament Tracker</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user