scene02 mit liste als Json beim öffnen der Scene

This commit is contained in:
atseirjo
2026-05-29 11:09:04 +02:00
parent 0dc4ba616b
commit c083a30be7
4 changed files with 677 additions and 90 deletions

View File

@@ -6,18 +6,63 @@
-----------------------------------------------------------------------------------------
local composer = require("composer")
local json = require("json")
local widget = require("widget")
local AskiRepository = require("askirepository")
local scene = composer.newScene()
-- Globale Variablen für Datenabruf
local selectedDate = nil
local devices = nil
local currentCookie = nil
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
-- Hilfsfunktion: Hole Gestern als Datum
local function getYesterdayDate()
local currentTime = os.time()
print("Aktuelle Zeit (Timestamp): " .. currentTime)
local yesterdayTime = currentTime - (24 * 60 * 60) -- 1 Tag zurück
print("Gestern Zeit (Timestamp): " .. yesterdayTime)
return os.date("*t", yesterdayTime)
end
-- Hilfsfunktion: Formatiere Datum für API
local function formatDateForAPI(dateTable, isEndOfDay)
if isEndOfDay then
return string.format("%04d-%02d-%02dT23:59:59.999Z",
dateTable.year, dateTable.month, dateTable.day)
else
return string.format("%04d-%02d-%02dT00:00:00.000Z",
dateTable.year, dateTable.month, dateTable.day)
end
end
-- Go to Week scene02
local function gotoWeek()
composer.gotoScene("scenen.scene02", {
effect = "fade",
time = 500,
params = {
devices = devices,
cookie = currentCookie
}
})
end
-- create()
function scene:create(event)
local sceneGroup = self.view
-- Kein Hintergrund, keine UI-Elemente
-- Hintergrund
local bg = display.newRect(sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight)
bg:setFillColor(0.95, 0.95, 0.95)
-- Setze Standard-Datum auf gestern
selectedDate = getYesterdayDate()
end
-- show()
@@ -31,97 +76,323 @@ function scene:show(event)
elseif phase == "did" then
-- Code hier wird ausgeführt, wenn die Scene komplett on-screen ist
-- Hole die übergebenen Daten
local deviceDataSets = event.params.deviceDataSets
local devices = event.params.devices
-- Hole die übergebenen Daten (falls neu übermittelt)
local deviceDataSets = event.params and event.params.deviceDataSets or nil
if event.params then
if event.params.devices then
devices = event.params.devices
end
if event.params.cookie then
currentCookie = event.params.cookie
end
end
if deviceDataSets and devices then
-- Berechne Layout
local itemHeight = 90
local cardWidth = display.contentWidth - 60
local totalHeight = #devices * itemHeight
local startY = (display.contentHeight - totalHeight) / 2 + (itemHeight / 2)
for i, device in ipairs(devices) do
local yPos = startY + ((i - 1) * itemHeight)
-- Container für jedes Device (zentral)
local itemBg = display.newRoundedRect(sceneGroup, display.contentCenterX, yPos, cardWidth, itemHeight - 10, 8)
itemBg:setFillColor(1, 1, 1)
itemBg.strokeWidth = 2
itemBg:setStrokeColor(0.85, 0.85, 0.85)
-- Device Name (Titel)
local nameText = display.newText({
parent = sceneGroup,
text = device.name,
x = display.contentCenterX,
y = yPos - 25,
fontSize = 18,
font = native.systemFontBold,
align = "center"
})
nameText:setFillColor(0.2, 0.2, 0.2)
-- Daten extrahieren
local dataSet = deviceDataSets[device.name]
local valueText = "Keine Daten"
local dateText = ""
if dataSet and not dataSet.error then
if type(dataSet) == "table" and #dataSet > 0 then
local meterData = nil
for _, meter in ipairs(dataSet) do
if meter.deviceId == device.deviceId then
meterData = meter
break
end
end
if meterData and meterData.values and #meterData.values > 0 then
local firstValue = meterData.values[1]
if firstValue.value then
valueText = string.format("%.2f kW", firstValue.value)
end
if firstValue.datetime then
dateText = firstValue.datetime
end
end
end
elseif dataSet and dataSet.error then
valueText = "Fehler: " .. dataSet.error
end
-- Wert anzeigen
local valueLabel = display.newText({
parent = sceneGroup,
text = valueText,
x = display.contentCenterX,
y = yPos,
fontSize = 16,
align = "center"
})
valueLabel:setFillColor(0.3, 0.6, 0.3)
-- Datum anzeigen (falls vorhanden)
if dateText ~= "" then
local formattedDate = dateText:match("(%d%d%d%d%-%d%d%-%d%d)")
if formattedDate then
local dateLabel = display.newText({
parent = sceneGroup,
text = "📅 " .. formattedDate,
x = display.contentCenterX,
y = yPos + 25,
fontSize = 12,
align = "center"
})
dateLabel:setFillColor(0.5, 0.5, 0.5)
end
-- Funktion zum Anzeigen der Daten
local function displayData(dataSets)
-- Entferne alte Daten-Anzeigen (aber nicht Datepicker und Button)
for i = sceneGroup.numChildren, 1, -1 do
local child = sceneGroup[i]
if child._isDataDisplay then
child:removeSelf()
end
end
print("✓ Scene01 geladen mit zentral angeordneten Datenboxen")
if dataSets and devices then
-- Kompaktes Layout
local itemHeight = 60
local cardWidth = display.contentWidth - 40
local startY = 190 -- Start nach Datepicker und Button
for i, device in ipairs(devices) do
local yPos = startY + ((i - 1) * itemHeight)
-- Container für jedes Device
local itemBg = display.newRoundedRect(sceneGroup, display.contentCenterX, yPos, cardWidth, itemHeight - 8, 6)
itemBg:setFillColor(1, 1, 1)
itemBg.strokeWidth = 1
itemBg:setStrokeColor(0.85, 0.85, 0.85)
itemBg._isDataDisplay = true
-- Device Name
local nameText = display.newText({
parent = sceneGroup,
text = device.name,
x = display.contentCenterX - cardWidth/2 + 80,
y = yPos - 5,
fontSize = 14,
font = native.systemFontBold,
align = "left"
})
nameText:setFillColor(0.2, 0.2, 0.2)
nameText._isDataDisplay = true
-- Daten extrahieren
local dataSet = dataSets[device.name]
local valueText = "Keine Daten"
local dateText = ""
if dataSet and not dataSet.error then
if type(dataSet) == "table" and #dataSet > 0 then
local meterData = nil
for _, meter in ipairs(dataSet) do
if meter.deviceId == device.deviceId then
meterData = meter
break
end
end
if meterData and meterData.values and #meterData.values > 0 then
local firstValue = meterData.values[1]
if firstValue.value then
valueText = string.format("%.2f kW", firstValue.value)
end
if firstValue.datetime then
dateText = firstValue.datetime:match("(%d%d%d%d%-%d%d%-%d%d)") or ""
end
end
end
elseif dataSet and dataSet.error then
valueText = "Fehler"
end
-- Wert anzeigen
local valueLabel = display.newText({
parent = sceneGroup,
text = valueText,
x = display.contentCenterX - cardWidth/2 + 80,
y = yPos + 12,
fontSize = 13,
align = "left"
})
valueLabel:setFillColor(0.3, 0.6, 0.3)
valueLabel._isDataDisplay = true
-- Datum (rechts)
if dateText ~= "" then
local dateLabel = display.newText({
parent = sceneGroup,
text = dateText,
x = display.contentCenterX + cardWidth/2 - 60,
y = yPos,
fontSize = 11,
align = "right"
})
dateLabel:setFillColor(0.5, 0.5, 0.5)
dateLabel._isDataDisplay = true
end
end
end
end
-- Funktion zum Neuladen der Daten
local function reloadData()
if not currentCookie or not devices or not selectedDate then
print("Fehler: Cookie, Devices oder Datum fehlt")
return
end
print("Lade Daten für " .. string.format("%04d-%02d-%02d", selectedDate.year, selectedDate.month, selectedDate.day))
local fromDate = formatDateForAPI(selectedDate, false)
local toDate = formatDateForAPI(selectedDate, true)
local newDeviceDataSets = {}
local completedRequests = 0
local totalRequests = #devices
-- Lade-Anzeige
local loadingOverlay = display.newRect(sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight)
loadingOverlay:setFillColor(0, 0, 0, 0.5)
loadingOverlay._isDataDisplay = true
local loadingText = display.newText({
parent = sceneGroup,
text = "Lade Daten...",
x = display.contentCenterX,
y = display.contentCenterY,
fontSize = 20,
font = native.systemFontBold
})
loadingText:setFillColor(1, 1, 1)
loadingText._isDataDisplay = true
-- Callback für jeden Device
local function onDataComplete(deviceName, success, dataSet, response)
completedRequests = completedRequests + 1
if success then
newDeviceDataSets[deviceName] = dataSet
print("✓ Daten empfangen für: " .. deviceName)
print(" Typ: " .. type(dataSet))
if type(dataSet) == "table" then
print(" Anzahl Einträge: " .. #dataSet)
end
else
newDeviceDataSets[deviceName] = { error = tostring(response) }
print("✗ Fehler für " .. deviceName .. ": " .. tostring(response))
end
if completedRequests >= totalRequests then
-- Entferne Lade-Anzeige
loadingOverlay:removeSelf()
loadingText:removeSelf()
-- Zeige neue Daten
displayData(newDeviceDataSets)
print("✓ Daten erfolgreich geladen")
end
end
-- Lade Daten für alle Devices
for i, device in ipairs(devices) do
local function deviceCallback(success, dataSet, response)
onDataComplete(device.name, success, dataSet, response)
end
AskiRepository.getPostHistoricData(
"https://api.portal.aski.at/historical_values/power",
device.deviceId,
fromDate,
toDate,
currentCookie,
deviceCallback
)
end
end
-- Datepicker-Bereich (oben)
local datePickerBg = display.newRoundedRect(sceneGroup, display.contentCenterX, 50,
display.contentWidth - 40, 60, 8)
datePickerBg:setFillColor(1, 1, 1)
datePickerBg.strokeWidth = 2
datePickerBg:setStrokeColor(0.3, 0.5, 0.8)
local dateLabel = display.newText({
parent = sceneGroup,
text = "Datum Auswahl:",
x = display.contentCenterX - 80,
y = 40,
fontSize = 14,
font = native.systemFontBold
})
dateLabel:setFillColor(0.2, 0.2, 0.2)
-- Datum-Anzeige (klickbar)
local dateDisplay = display.newText({
parent = sceneGroup,
text = string.format("%04d-%02d-%02d", selectedDate.year, selectedDate.month, selectedDate.day),
x = display.contentCenterX - 80,
y = 60,
fontSize = 16,
font = native.systemFont
})
dateDisplay:setFillColor(0.3, 0.5, 0.8)
-- Pfeile zum Datum ändern
local prevDayBtn = display.newText({
parent = sceneGroup,
text = "",
x = display.contentCenterX + 30,
y = 50,
fontSize = 24
})
prevDayBtn:setFillColor(0.3, 0.5, 0.8)
local nextDayBtn = display.newText({
parent = sceneGroup,
text = "",
x = display.contentCenterX + 90,
y = 50,
fontSize = 24
})
nextDayBtn:setFillColor(0.5, 0.5, 0.5) -- Ausgegraut, falls am Maximum
-- Funktion zum Aktualisieren der Datumsanzeige
local function updateDateDisplay()
dateDisplay.text = string.format("%04d-%02d-%02d", selectedDate.year, selectedDate.month, selectedDate.day)
-- Prüfe ob "nächster Tag" erlaubt ist
local yesterday = getYesterdayDate()
local yesterdayTimestamp = os.time(yesterday)
local selectedTimestamp = os.time(selectedDate)
if selectedTimestamp >= yesterdayTimestamp then
nextDayBtn:setFillColor(0.5, 0.5, 0.5) -- Ausgegraut
else
nextDayBtn:setFillColor(0.3, 0.5, 0.8) -- Aktiv
end
end
-- Event-Handler für Datum-Änderung
prevDayBtn:addEventListener("tap", function()
local currentTimestamp = os.time(selectedDate)
local newTimestamp = currentTimestamp - (24 * 60 * 60)
selectedDate = os.date("*t", newTimestamp)
updateDateDisplay()
end)
nextDayBtn:addEventListener("tap", function()
local yesterday = getYesterdayDate()
local yesterdayTimestamp = os.time(yesterday)
local currentTimestamp = os.time(selectedDate)
if currentTimestamp < yesterdayTimestamp then
local newTimestamp = currentTimestamp + (24 * 60 * 60)
selectedDate = os.date("*t", newTimestamp)
updateDateDisplay()
end
end)
-- Reload-Button
local reloadBtn = widget.newButton({
label = "Daten laden",
onRelease = reloadData,
emboss = false,
shape = "roundedRect",
width = 200,
height = 40,
cornerRadius = 8,
fillColor = { default={0.3, 0.6, 0.3, 1}, over={0.2, 0.5, 0.2, 1} },
strokeColor = { default={0.2, 0.4, 0.2, 1}, over={0.1, 0.3, 0.1, 1} },
strokeWidth = 2,
labelColor = { default={1, 1, 1}, over={1, 1, 1} },
fontSize = 16,
x = display.contentCenterX,
y = 120
})
sceneGroup:insert(reloadBtn)
-- Zeige initiale Daten oder lade sie neu
if deviceDataSets and devices then
displayData(deviceDataSets)
print("✓ Scene01 geladen mit Datepicker und kompakter Ansicht")
elseif devices and currentCookie then
-- Wenn wir von einer anderen Scene zurückkommen (z.B. Scene02),
-- aber keine neuen Daten mitgebracht haben, lade die Daten neu
print("✓ Zurück zu Scene01 - Lade Daten neu...")
reloadData()
end
-- Design für Wochenübersicht Button
local weekBtn = widget.newButton({
label = "Zu den letzten 7 Tagen",
emboss = false,
shape = "roundedRect",
width = 200,
height = 40,
cornerRadius = 8,
fillColor = { default = { 0.3, 0.5, 0.8, 1 }, over = { 0.2, 0.4, 0.7, 1 } },
strokeColor = { default = { 0.2, 0.4, 0.2, 1 }, over = { 0.1, 0.3, 0.1, 1 } },
strokeWidth = 2,
labelColor = { default = { 1, 1, 1 }, over = { 1, 1, 1 } },
fontSize = 16,
x = display.contentCenterX,
y = 380
})
-- Event-Listener für Wochenübersicht Button
sceneGroup:insert(weekBtn)
weekBtn:addEventListener("tap", gotoWeek)
end
end

238
scenen/scene02.lua Normal file
View File

@@ -0,0 +1,238 @@
local composer = require( "composer" )
local json = require("json")
local widget = require("widget")
local AskiRepository = require("askirepository")
local scene = composer.newScene()
-- Globale Variablen für Datenabruf
local yesterdayDate = nil
local selectedDate = nil
-- -----------------------------------------------------------------------------------
-- Code outside of the scene event functions below will only be executed ONCE unless
-- the scene is removed entirely (not recycled) via "composer.removeScene()"
-- -----------------------------------------------------------------------------------
-- Hilfsfunktion: Hole Datum minus 7 Tage Datum
local function getCurrentAndLastDate(isCurrentDate)
local currentTime = os.time()
--print("Aktuelle Zeit (Timestamp): " .. currentTime)
local lastSevenDayTime = currentTime - (24 * 60 * 60 * 7) -- 7 Tage zurück
--print("Vor 7 Tagen Zeit (Timestamp): " .. lastSevenDayTime)
if isCurrentDate then
return os.date("*t", currentTime - (24 * 60 * 60)) -- minus 1 Tag für gestern
else
return os.date("*t", lastSevenDayTime - (24 * 60 * 60)) -- nochmal minus 1 Tag für vor 7 Tage
end
end
-- Hilfsfunktion: Formatiere Datum für API
local function formatDateForAPI(dateTable, isEndOfDay)
if isEndOfDay then
return string.format("%04d-%02d-%02dT23:59:59.999Z",
dateTable.year, dateTable.month, dateTable.day)
else
return string.format("%04d-%02d-%02dT00:00:00.000Z",
dateTable.year, dateTable.month, dateTable.day)
end
end
-- Go to Day scene02
local function gotoDay()
composer.gotoScene("scenen.scene01", {
effect = "fade",
time = 500
})
end
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
-- create()
function scene:create( event )
local sceneGroup = self.view
-- Code here runs when the scene is first created but has not yet appeared on screen
-- Hintergrund
local bg = display.newRect(sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight)
bg:setFillColor(0.95, 0.95, 0.95)
-- aktuelles Tagesdatum -1 Tag für gestern
yesterdayDate = getCurrentAndLastDate(true)
-- Setze Standard-Datum auf vor 8 Tagen
selectedDate = getCurrentAndLastDate(false)
end
-- show()
function scene:show( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif ( phase == "did" ) then
-- Hole die übergebenen Daten
local devices = event.params.devices
local currentCookie = event.params.cookie
-- Formatiere die Daten für die API
local fromDate = formatDateForAPI(selectedDate, false)
local toDate = formatDateForAPI(yesterdayDate, true)
local completedRequests = 0
local totalRequests = #devices
local currentDataSets = {}
-- Ausgabe der übergebenen Daten für Debugging
print("Scene02 ist jetzt sichtbar - Zeige Daten an")
print("Entspricht einer Woche von Gestern 7 Tage zurück")
print("Formatiertes Start-Datum für API: " .. fromDate)
print("Formatiertes End-Datum für API: " .. toDate)
print("Übergebene Geräte: " .. (devices and #devices or "Keine"))
print("Cookie:" .. tostring(currentCookie))
-- Funktion zum Neuladen der Daten
local function reloadDataFromSevenDays()
if not currentCookie or not devices or not selectedDate then
print("Fehler: Cookie, Devices oder Datum fehlt")
return
end
print("Lade Daten von " ..
string.format("%04d-%02d-%02d", selectedDate.year, selectedDate.month, selectedDate.day) ..
" bis " ..
string.format("%04d-%02d-%02d", yesterdayDate.year, yesterdayDate.month, yesterdayDate.day) ..
" für " .. #devices .. " Geräte")
-- Lade-Anzeige
local loadingOverlay = display.newRect(sceneGroup, display.contentCenterX, display.contentCenterY,
display.contentWidth, display.contentHeight)
loadingOverlay:setFillColor(0, 0, 0, 0.5)
loadingOverlay._isDataDisplay = true
local loadingText = display.newText({
parent = sceneGroup,
text = "Lade Daten...",
x = display.contentCenterX,
y = display.contentCenterY,
fontSize = 20,
font = native.systemFontBold
})
loadingText:setFillColor(1, 1, 1)
loadingText._isDataDisplay = true
-- Callback für jeden Device
local function onDataComplete(deviceName, success, dataSet, response)
completedRequests = completedRequests + 1
if success then
currentDataSets[deviceName] = dataSet
else
currentDataSets[deviceName] = { error = tostring(response) }
end
if completedRequests >= totalRequests then
-- Entferne Lade-Anzeige
loadingOverlay:removeSelf()
loadingText:removeSelf()
-- Ausgabe der kompletten newDeviceDataSets Table
print("\n========== ALLE GELADENEN DATEN (newDeviceDataSets) ==========")
print("JSON-Format:")
print(json.prettify(currentDataSets))
print("===============================================================\n")
-- Zeige neue Daten
print("✓ Daten erfolgreich geladen")
end
end
-- Lade Daten für alle Devices
for i, device in ipairs(devices) do
local function deviceCallback(success, dataSet, response)
onDataComplete(device.name, success, dataSet, response)
end
AskiRepository.getPostHistoricData(
"https://api.portal.aski.at/historical_values/power",
device.deviceId,
fromDate,
toDate,
currentCookie,
deviceCallback
)
end
end
-- Code here runs when the scene is entirely on screen
reloadDataFromSevenDays() -- Lade die Daten direkt beim Anzeigen der Scene02
-- Inhalt Diagramm anzeigen
-- Button für zurück zu Scene01
-- Design für Tagesansicht Button
local dayBtn = widget.newButton({
label = "Vortagesansicht",
emboss = false,
shape = "roundedRect",
width = 200,
height = 40,
cornerRadius = 8,
fillColor = { default = { 0.3, 0.5, 0.8, 1 }, over = { 0.2, 0.4, 0.7, 1 } },
strokeColor = { default = { 0.2, 0.4, 0.2, 1 }, over = { 0.1, 0.3, 0.1, 1 } },
strokeWidth = 2,
labelColor = { default = { 1, 1, 1 }, over = { 1, 1, 1 } },
fontSize = 16,
x = display.contentCenterX,
y = 380
})
-- Event-Listener für Tagesansicht Button
sceneGroup:insert(dayBtn)
dayBtn:addEventListener("tap", gotoDay)
end
end
-- hide()
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if ( phase == "will" ) then
-- Code here runs when the scene is on screen (but is about to go off screen)
elseif ( phase == "did" ) then
-- Code here runs immediately after the scene goes entirely off screen
end
end
-- destroy()
function scene:destroy( event )
local sceneGroup = self.view
-- Code here runs prior to the removal of scene's view
print("Scene02 zerstört")
end
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
return scene