var BOILER_HEATING_HOURS = 3;
var FLOOR_HEATING_HOURS = 6;
var colors = ["FF0000","FF1100","FF2200","FF3300","FF4400","FF5500","FF6600","FF7700","FF8800","FF9900","FFAA00","FFBB00","FFCC00","FFDD00","FFEE00","FFFF00","EEFF00","DDFF00","CCFF00","BBFF00","AAFF00","99FF00","88FF00","77FF00","66FF00","55FF00","44FF00","33FF00","22FF00","11FF00","00FF00"];
var colors2 = ["00FF00", "32CD32", "22A12C", "228B22", "008000", "006400", "FFD700", "FFA500", "FF8C00", "FF5F1F","d71049", "C70039", "8B0000", "581845"];
async function startApp() {
let date = moment().format("YYYY-MM-DD");
await printPage(date);
}
async function printPage(date){
// Load data
console.log("___printPage(" + date + ")___");
let theMoment = moment(date);
let previousDate = theMoment.subtract(1, 'days').format("YYYY-MM-DD");
let nextDate = theMoment.add(2, 'days').format("YYYY-MM-DD");
let currentPrices = await fetchPrices(date);
let devices = await fetchDevices();
const deviceNameToDeviceScheduleMap = {};
for (let key in devices["devices"]) {
let deviceObject = devices["devices"][key];
// Fetch schedules for device
let deviceSchedules = await fetchDeviceSchedules(deviceObject.deviceId, date);
let scheduleData = {};
for (let row in deviceSchedules["schedules"]) {
let scheduleObject = deviceSchedules["schedules"][row];
scheduleData[scheduleObject.scheduleDate] = scheduleObject;
}
deviceNameToDeviceScheduleMap[deviceObject.deviceName] = scheduleData;
}
let savings = await fetchSavings();
let reports = await fetchReports();
// Print HTML
let html = "";
// Test colors
/*
for (let key in colors) {
html += "
";
}
html +="
\n";
for (let key in colors2) {
html += "";
}
*/
html += "Devices
\n";
html += "| Device | Energy hours | Last seen |
\n";
for (let key in devices["devices"]) {
let deviceObject = devices["devices"][key];
html += "| " + deviceObject.deviceName + " | " + deviceObject.energyHours + " | " + deviceObject.lastSeenString + " |
\n";
}
html += "
\n";
html += "Savings
";
html += "";
html += "Total of " + (Math.floor(savings.totalSavedMoney)/100) + " € saved!";
html += "
";
html += "";
html += "
| Device | Savings |
\n";
for (let key in savings["deviceReports"]) {
let deviceObject = savings["deviceReports"][key];
html += "| " + deviceObject.deviceName + " | " + (Math.floor(deviceObject.totalDeviceSavings)/100) + " € |
\n";
}
html += "
\n";
html += "";
html += "Prices
";
html += "";
html += "Prices " + date + "
";
html += "";
html += "" + previousDate + "\n";
html += " <-- Change date -->";
html += "" + nextDate + "\n";
html += "
";
html += "| Date | Price | ";
for (let key in devices["devices"]) {
let deviceObject = devices["devices"][key];
html += "" + deviceObject.deviceName + " | ";
}
html += "
";
let rowIndex = 0;
for (let key in currentPrices["prices"]) {
let priceObject = currentPrices["prices"][key];
let startDate = priceObject["startDate"];
let price = priceObject["price"];
let calculatedPrice = priceObject["calculatedPrice"];
let priceIndex = priceObject["priceIndex"];
let priceHTML = calculatedPrice !== price ? calculatedPrice + " (" + price + ")" : price;
/*
let changingColorValue = (255 - Math.floor(200*(priceIndex/26)));
let color = "rgb(30, " + changingColorValue + "," + changingColorValue+ ");"
*/
let color = "#" + colors2[Math.floor(priceIndex/2)] + ";";
priceHTML = "" + priceHTML + "";
html += "";
html += "| " + startDate + " | " + priceHTML + " | ";
for (let key in devices["devices"]) {
let deviceObject = devices["devices"][key];
let deviceName = deviceObject.deviceName;
let deviceScheduleData = deviceNameToDeviceScheduleMap[deviceName];
if (deviceScheduleData !== null) {
let scheduleDataObject = deviceScheduleData[startDate];
let isActive = false;
let isAutomated = false;
let isActiveDataFound = false;
if (typeof scheduleDataObject !== 'undefined') {
// {"2025.02.08 22:00:00":{"scheduleDate":"2025.02.08 22:00:00","device":"mock-Lattialammitys","active":null},"2025.02.08 23:00:00":{"scheduleDate":"2025.02.08 23:00:00","device":"mock-Lattialammitys","active":false},"
isActive = scheduleDataObject["active"];
isAutomated = scheduleDataObject["isAutomated"];
isActiveDataFound = true;
}
let linkClass = isActive ? "active" : isActiveDataFound ? "passive" : "unknown";
let buttonClass = isAutomated ? " automated" : "";
html += "";
html += "";
html += "";
html += "";
html += " | \n";
} else {
html += "Data missing for date " + startDate + " and device " + deviceName + " | ";
}
}
html += "
";
}
html += "
";
let deviceHeatingHoursHTML = "";
deviceHeatingHoursHTML += "Status
\n";
deviceHeatingHoursHTML += "\n";
deviceHeatingHoursHTML += "| Device | Analyse date | Heating status | Heating hours | Heating plan |
";
let index = 0;
for (let key in devices["devices"]) {
let deviceObject = devices["devices"][key];
let deviceName = deviceObject.deviceName;
let energyHours = deviceObject.energyHours;
let deviceStatusObject = await fetchDeviceStatusNow(date, deviceName, energyHours);
deviceHeatingHoursHTML += "";
deviceHeatingHoursHTML += "| " + deviceName + " | ";
deviceHeatingHoursHTML += "" + deviceStatusObject["heat"] + " | ";
deviceHeatingHoursHTML += "" + deviceStatusObject["statusDate"] + " | ";
deviceHeatingHoursHTML += "" + energyHours + " | ";
deviceHeatingHoursHTML += "";
for (let data in deviceStatusObject["data"]) {
let dataObject = deviceStatusObject["data"][data];
deviceHeatingHoursHTML += dataObject["timestamp"];
if (dataObject["automated"] === true) {
deviceHeatingHoursHTML += " autoscheduled";
} else if (dataObject["scheduled"] === true) {
deviceHeatingHoursHTML += " scheduled";
} else {
deviceHeatingHoursHTML += " low price " + dataObject["price"];
}
deviceHeatingHoursHTML += " \n";
}
deviceHeatingHoursHTML += " | ";
deviceHeatingHoursHTML += "
";
/*
"status":0,
"message":"No heating with now UTC Mon Feb 24 21:23:51 EET 2025. Analyze report : UTC 2025-02-24 02:00:00.0 => scheduled UTC 2025-02-24 03:00:00.0 => scheduled UTC 2025-02-24 04:00:00.0 => scheduled UTC 2025-02-24 05:00:00.0 => scheduled UTC 2025-02-24 06:00:00.0 => scheduled UTC 2025-02-24 07:00:00.0 => scheduled UTC 2025-02-24 22:00:00.0 => scheduled ",
"data":[
{"timestamp":"2025.02.24 02:00:00","price":0,"scheduled":true},{"timestamp":"2025.02.24 03:00:00","price":0,"scheduled":true},
{"timestamp":"2025.02.24 04:00:00","price":0,"scheduled":true},{"timestamp":"2025.02.24 05:00:00","price":0,"scheduled":true},
{"timestamp":"2025.02.24 06:00:00","price":0,"scheduled":true},{"timestamp":"2025.02.24 07:00:00","price":0,"scheduled":true},
{"timestamp":"2025.02.24 22:00:00","price":0,"scheduled":true}
],
"heat":false,
"statusDate":"2025.02.24 21:23:51"
*/
index++;
}
deviceHeatingHoursHTML += "
";
// Add status to page
html += deviceHeatingHoursHTML;
html += "Reports
";
html += "| Date | Message |
";
for (let key in reports["rows"]) {
let messageObject = reports["rows"][key];
let reportMessage = messageObject["reportMessage"];
let createdDate = messageObject["createdDate"];
html += "| " + createdDate + " | " + reportMessage + " |
";
}
html += "
";
document.getElementById('center').innerHTML = html;
}
async function fetchPrices(date) {
let time = date === null ? moment() : moment(date, "YYYY-MM-DD");
console.log("Reading prices " + time + "...");
const response = await fetch("/prices/" + time.format("YYYY-MM-DD"));
const data = await response.json();
console.log("==> fetchCurrentPrices: " + JSON.stringify(data));
return data;
}
async function fetchLowestHours(date,hours) {
const response = await fetch("/prices/lowest/" + date + "/" + hours);
const data = await response.json();
console.log("==> fetchLowestHours(" + date + "," + hours + "): " + JSON.stringify(data));
return data;
}
async function fetchReports() {
const response = await fetch("/report/all");
const data = await response.json();
console.log("==> fetchReport: " + JSON.stringify(data));
return data;
}
async function fetchDevices() {
const response = await fetch("/device/all");
const data = await response.json();
console.log("==> fetchDevices: " + JSON.stringify(data));
return data;
}
async function fetchSavings() {
const response = await fetch("/report/savings");
const data = await response.json();
console.log("==> fetchSavings: " + JSON.stringify(data));
return data;
}
async function fetchDeviceStatusNow(date, deviceName, hours) {
let today = moment().format("YYYY-MM-DD");
let url = today === date ? "/status/heat/" + deviceName + "/" + hours : "/status/heat/" + date + "/" + deviceName + "/" + hours;
console.log("Reading via URL " + url);
const response = await fetch(url);
const data = await response.json();
console.log("==> fetchDeviceStatusNow(" + date + "): " + JSON.stringify(data));
return data;
}
async function fetchDeviceSchedules(deviceId, date) {
const response = await fetch("/schedule/" + deviceId + "/" + date);
const data = await response.json();
console.log("==> fetchDeviceSchedules: " + JSON.stringify(data));
return data;
}
async function createSchedule(deviceId, date, isActive) {
const response = await fetch('/schedule/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({schedule: {scheduleDate: date, deviceId: deviceId, active: isActive}})
});
const data = await response.json();
console.log("==> fetchDeviceSchedules: " + JSON.stringify(data));
return data;
}
async function pressScheduleButton(link) {
let date = link.getAttribute("data-time");
let deviceId = link.getAttribute("data-device-id");
let currentState = link.className === "active";
let createResponse = await createSchedule(deviceId, date, !currentState);
if (createResponse.status === 0) {
link.className = currentState ? "passive" : "active";
} else {
alert('Error while communicating with server!');
}
//alert(createResponse);
}
function log(message) {
console.log("INFO : " + message);
}