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 += "\n"; for (let key in devices["devices"]) { let deviceObject = devices["devices"][key]; html += "\n"; } html += "
DeviceEnergy hoursLast seen
" + deviceObject.deviceName + "" + deviceObject.energyHours + "" + deviceObject.lastSeenString + "
\n"; html += "

Savings

"; html += "

"; html += "Total of " + (Math.floor(savings.totalSavedMoney)/100) + " € saved!"; html += "

"; html += "

"; html += "\n"; for (let key in savings["deviceReports"]) { let deviceObject = savings["deviceReports"][key]; html += "\n"; } html += "
DeviceSavings
" + deviceObject.deviceName + "" + (Math.floor(deviceObject.totalDeviceSavings)/100) + " €
\n"; html += "

"; html += "

Prices

"; html += "

"; html += "

Prices " + date + "

"; html += "

"; html += "" + previousDate + "\n"; html += " <-- Change date -->"; html += "" + nextDate + "\n"; html += "

"; html += ""; for (let key in devices["devices"]) { let deviceObject = devices["devices"][key]; html += ""; } 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 += ""; 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 += "\n"; } else { html += ""; } } html += ""; } html += "
DatePrice" + deviceObject.deviceName + "
" + startDate + "" + priceHTML + ""; html += ""; html += "
"; html += "
"; html += "
Data missing for date " + startDate + " and device " + deviceName + "
"; let deviceHeatingHoursHTML = ""; deviceHeatingHoursHTML += "

Status

\n"; deviceHeatingHoursHTML += "\n"; deviceHeatingHoursHTML += ""; 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 += ""; deviceHeatingHoursHTML += ""; deviceHeatingHoursHTML += ""; deviceHeatingHoursHTML += ""; 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 += "
DeviceAnalyse dateHeating statusHeating hoursHeating plan
" + deviceName + "" + deviceStatusObject["heat"] + "" + deviceStatusObject["statusDate"] + "" + energyHours + ""; 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 += "
"; // Add status to page html += deviceHeatingHoursHTML; html += "

Reports

"; html += ""; for (let key in reports["rows"]) { let messageObject = reports["rows"][key]; let reportMessage = messageObject["reportMessage"]; let createdDate = messageObject["createdDate"]; html += ""; } html += "
DateMessage
" + createdDate + "" + reportMessage + "
"; 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); }