diff --git a/askirepository.lua b/askirepository.lua new file mode 100644 index 0000000..637da0e --- /dev/null +++ b/askirepository.lua @@ -0,0 +1,143 @@ +----------------------------------------------------------------------------------------- +-- +-- askirepository.lua +-- ASKI Portal API Repository +-- +----------------------------------------------------------------------------------------- + +local json = require("json") + +local AskiRepository = {} + +-- Cookie-Authentifizierungsfunktion +function AskiRepository.getPostCookieAuth(url, email, password, code, callback) + -- Erstelle den Request Body + local requestBody = json.encode({ + email = email, + password = password, + code = code + }) + + -- Callback-Funktion für die Antwort + local function networkListener(event) + if event.isError then + print("Netzwerkfehler: " .. tostring(event.response)) + if callback then + callback(false, nil, "Netzwerkfehler: " .. tostring(event.response)) + end + else + print("Status Code: " .. event.status) + --print("Response: " .. event.response) + + -- Extrahiere Cookie aus den Headers + if event.responseHeaders then + local cookie = event.responseHeaders["Set-Cookie"] or + event.responseHeaders["set-cookie"] + + if cookie then + --print("Cookie: " .. cookie) + if callback then + callback(true, cookie, event.response) + end + else + print("Kein Cookie in der Antwort gefunden") + if callback then + callback(false, nil, "Kein Cookie gefunden") + end + end + else + if callback then + callback(false, nil, "Keine Headers in der Antwort") + end + end + end + end + + -- POST Request Parameter + local params = { + headers = { + ["Content-Type"] = "application/json", + ["Content-Length"] = tostring(#requestBody) + }, + body = requestBody + } + + -- Führe den POST Request aus + network.request(url, "POST", networkListener, params) +end + +-- Post Pv Data +function AskiRepository.getPostHistoricData(url, deviceId, fromDate, toDate, cookie, callback) + -- Erstelle den Request Body + local requestBody = json.encode({ + meters = { + { + deviceId = deviceId, + meterId = 40, + meterSubId = 0 + } + }, + sumTariffs = true, + type = 1, + tariff = 0, + from = fromDate, + to = toDate + }) + + -- Callback-Funktion für die Antwort + local function networkListener(event) + if event.isError then + print("Netzwerkfehler: " .. tostring(event.response)) + if callback then + callback(false, nil, "Netzwerkfehler: " .. tostring(event.response)) + end + else + print("Status Code: " .. event.status) + print("Response: " .. event.response) + + -- Prüfe ob Status Code erfolgreich ist (200-299) + if event.status >= 200 and event.status < 300 then + -- Parse die JSON Response + if event.response and event.response ~= "" then + local dataSet = json.decode(event.response) + if dataSet then + print("DataSet erfolgreich empfangen") + if callback then + callback(true, dataSet, event.response) + end + else + print("Fehler beim Parsen der Response") + if callback then + callback(false, nil, "JSON Parse Fehler") + end + end + else + print("Leere Response erhalten") + if callback then + callback(false, nil, "Leere Response") + end + end + else + print("HTTP Fehler: " .. event.status) + if callback then + callback(false, nil, "HTTP Fehler " .. event.status .. ": " .. tostring(event.response)) + end + end + end + end + + -- POST Request Parameter + local params = { + headers = { + ["Content-Type"] = "application/json", + ["Content-Length"] = tostring(#requestBody), + ["Cookie"] = cookie + }, + body = requestBody + } + + -- Führe den POST Request aus + network.request(url, "POST", networkListener, params) +end + +return AskiRepository diff --git a/main.lua b/main.lua index f4cca92..eb3f562 100644 --- a/main.lua +++ b/main.lua @@ -4,5 +4,122 @@ -- ----------------------------------------------------------------------------------------- --- Your code here +-- Importiere das ASKI Repository +local AskiRepository = require("askirepository") local json = require("json") +local composer = require("composer") + +-- Konfiguration Authentifizierungsfunktion +local postAuthUrl = "https://api.portal.aski.at/auth/login" +local email = "David.aschl@ifn-holding.com" +local password = "20IFN25" +local code = "" +local cookie = nil + +-- Konfiguration für den Abruf von Daten mit Cookie-Authentifizierungsfunktion +local fromDate = "2026-05-07T00:00:00.000Z" +local toDate = "2026-05-07T23:59:59.999Z" +local postDataUrl = "https://api.portal.aski.at/historical_values/power" +local devices = { + { + deviceId = "08dd1489-1129-4774-81ed-9bf1ce3f580d", + name = "Traun" + }, + { + deviceId = "08dd20cd-9d7f-4a2e-897a-3be55c3bfec3", + name = "Lannach" + }, + { + deviceId = "08dd0ac5-7510-4990-8124-39cf64ec7e71", + name = "Sarleinsbach" + } +} + +local deviceDataSets = {} +local completedRequests = 0 +local totalRequests = 0 + +-- Einfache Lade-Anzeige +local background = display.newRect(display.contentCenterX, display.contentCenterY, display.contentWidth, display.contentHeight) +background:setFillColor(0.95, 0.95, 0.95) + +local loadingText = display.newText({ + text = "Verbinde mit Server...", + x = display.contentCenterX, + y = display.contentCenterY, + fontSize = 24, + font = native.systemFont +}) +loadingText:setFillColor(0.3, 0.3, 0.8) + +-- Callback-Funktion für den Datenabruf (wird für jedes Device aufgerufen) +local function onDataComplete(deviceName, success, dataSet, response) + completedRequests = completedRequests + 1 + + if success then + print("✓ Datenabruf für " .. deviceName .. " erfolgreich!") + deviceDataSets[deviceName] = dataSet + else + print("✗ Datenabruf für " .. deviceName .. " fehlgeschlagen: " .. tostring(response)) + deviceDataSets[deviceName] = { error = tostring(response) } + end + + -- Aktualisiere Status + loadingText.text = string.format("Lade Daten... (%d/%d)", completedRequests, totalRequests) + + -- Wenn alle Requests abgeschlossen sind, wechsle zur Scene + if completedRequests >= totalRequests then + print("✓ Alle DataSets geladen - Wechsle zur Scene01") + + -- Entferne Lade-Anzeige + loadingText:removeSelf() + background:removeSelf() + + -- Wechsle zur Datenansicht-Scene und übergebe die Daten + composer.gotoScene("scenen.scene01", { + effect = "fade", + time = 500, + params = { + deviceDataSets = deviceDataSets, + devices = devices + } + }) + end +end + +-- Callback-Funktion für die Authentifizierung +local function onAuthComplete(success, receivedCookie, response) + if success then + print("✓ Authentifizierung erfolgreich!") + print("✓ Cookie erhalten und kann verwendet werden") + + loadingText.text = "Authentifiziert - Lade Daten..." + + -- Hier kannst du mit dem Cookie weiterarbeiten + cookie = receivedCookie + print("✓ Cookie: " .. cookie) + + -- Setze die Anzahl der erwarteten Requests + totalRequests = #devices + completedRequests = 0 + + -- Rufe die Datenabruf-Funktion für alle Devices auf + for i, device in ipairs(devices) do + print("Lade Daten für " .. device.name .. " (" .. device.deviceId .. ")") + + -- Erstelle einen spezifischen Callback für dieses Device + local function deviceCallback(success, dataSet, response) + onDataComplete(device.name, success, dataSet, response) + end + + AskiRepository.getPostHistoricData(postDataUrl, device.deviceId, fromDate, toDate, cookie, deviceCallback) + end + else + print("✗ Authentifizierung fehlgeschlagen: " .. tostring(response)) + loadingText.text = "✗ Authentifizierung fehlgeschlagen" + loadingText:setFillColor(0.8, 0.2, 0.2) + end +end + +-- Rufe die Authentifizierungsfunktion auf +AskiRepository.getPostCookieAuth(postAuthUrl, email, password, code, onAuthComplete) \ No newline at end of file diff --git a/scenen/scene01.lua b/scenen/scene01.lua new file mode 100644 index 0000000..4ba2335 --- /dev/null +++ b/scenen/scene01.lua @@ -0,0 +1,157 @@ +----------------------------------------------------------------------------------------- +-- +-- scene01.lua +-- Datenansicht Scene +-- +----------------------------------------------------------------------------------------- + +local composer = require("composer") +local json = require("json") + +local scene = composer.newScene() + +-- ----------------------------------------------------------------------------------- +-- Scene event functions +-- ----------------------------------------------------------------------------------- + +-- create() +function scene:create(event) + local sceneGroup = self.view + -- Kein Hintergrund, keine UI-Elemente +end + +-- show() +function scene:show(event) + local sceneGroup = self.view + local phase = event.phase + + if phase == "will" then + -- Code hier wird ausgeführt, wenn die Scene noch off-screen ist (aber im Begriff ist, on-screen zu kommen) + + 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 + + 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 + end + end + + print("✓ Scene01 geladen mit zentral angeordneten Datenboxen") + end + end +end + +-- hide() +function scene:hide(event) + local sceneGroup = self.view + local phase = event.phase + + if phase == "will" then + -- Code hier wird ausgeführt, wenn die Scene on-screen ist (aber im Begriff ist, off-screen zu gehen) + + elseif phase == "did" then + -- Code hier wird ausgeführt, unmittelbar nachdem die Scene off-screen gegangen ist + -- ScrollView-Inhalt wird automatisch mit der Scene entfernt + end +end + +-- destroy() +function scene:destroy(event) + local sceneGroup = self.view + print("Scene01 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