Hallo zusammen,
ich möchte gerne den dyn. Strompreis von Octopus Energy über deren API in Fhem verfügbar machen. Ich haben Gemini um Unterstützung gefragt:
# --------- Octopus Strompreis auslesen -------
use HttpUtils;
use JSON::PP;
use Time::Local;
sub getOctopusPrices {
# ------------------ KONFIGURATION HIER EINTRAGEN ------------------
my $email = 'tollemailadresse@mail.de';
my $accountNo = 'A-xxxxxx';
# -----------------------------------------------------------------
# Passwort sicher aus dem FHEM-Speicher auslesen
my ($pwdErr, $password) = getKeyValue("octopus_password");
if ($pwdErr || !$password) {
Log 2, "Octopus SMGW Fehler: Passwort konnte nicht aus FHEM-KeyValue-Speicher gelesen werden!";
return;
}
my $gqlUrl = "https://api.oeg-kraken.energy/v1/graphql/";
# Schritt 1: Login-Mutation mit dem dynamisch geladenen Passwort
my $loginQuery = {
query => 'mutation ($email: String!, $password: String!) { obtainKrakenToken(input: { email: $email, password: $password }) { token } }',
variables => { email => $email, password => $password }
};
my $loginParam = {
url => $gqlUrl,
timeout => 10,
header => "Content-Type: application/json",
data => encode_json($loginQuery),
callback => sub {
my ($param, $err, $data) = @_;
if ($err ne "") { Log 3, "Octopus SMGW-Login-Fehler: $err"; return; }
my $decodedLogin = eval { decode_json($data) };
my $token = $decodedLogin->{data}{obtainKrakenToken}{token};
if (!$token) { Log 3, "Octopus SMGW: Token-Generierung fehlgeschlagen."; return; }
# Schritt 2: Abfrage der Marktpreise für iMSys (Smart Meter Gateway)
my $dataQuery = {
query => 'query ($accountNo: String!) {
account(accountNumber: $accountNo) {
properties {
electricityMeteringPoints {
agreements {
tariff {
... on MarketIndexedTarif {
unitRates {
valueWithTax
validFrom
validTo
}
}
}
}
}
}
}
}',
variables => { accountNo => $accountNo }
};
my $dataParam = {
url => $gqlUrl,
timeout => 10,
header => "Authorization: Bearer $token\r\nContent-Type: application/json",
data => encode_json($dataQuery),
callback => sub {
my ($dParam, $dErr, $dData) = @_;
if ($dErr ne "") { Log 3, "Octopus SMGW-Datenabruf-Fehler: $dErr"; return; }
my $decodedData = eval { decode_json($dData) };
if (!$decodedData || $decodedData->{errors}) {
Log 3, "Octopus API Fehler: " . ($decodedData->{errors}{message} // "Unbekannt");
return;
}
my $points = eval { $decodedData->{data}{account}{properties}{electricityMeteringPoints}{agreements}{tariff}{unitRates} };
if (!$points || ref($points) ne 'ARRAY') {
Log 2, "Octopus SMGW Fehler: Konnte unitRates im JSON nicht finden.";
return;
}
my $now = time();
my $price_current = undef;
my $price_next = undef;
foreach my $rate (@$points) {
my $from = parseIsoToEpoch($rate->{validFrom});
my $to = parseIsoToEpoch($rate->{validTo});
if ($now >= $from && $now < $to) {
$price_current = $rate->{valueWithTax};
}
if (($now + 3600) >= $from && ($now + 3600) < $to) {
$price_next = $rate->{valueWithTax};
}
}
if (defined($price_current)) {
fhem("setreading Octopus_Strompreis price_current " . sprintf("%.2f", $price_current));
fhem("setreading Octopus_Strompreis price_next_hour " . sprintf("%.2f", $price_next)) if defined($price_next);
fhem("setreading Octopus_Strompreis meter_type LandisGyr_iMSys");
fhem("setreading Octopus_Strompreis last_update " . localtime());
Log 3, "Octopus SMGW (Landis+Gyr) erfolgreich aktualisiert: $price_current Cent/kWh.";
} else {
Log 3, "Octopus SMGW: Kein Preis für die aktuelle Stunde im Datensatz vorhanden.";
}
}
};
HttpUtils_NonblockingGet($dataParam);
}
};
HttpUtils_NonblockingGet($loginParam);
}
sub parseIsoToEpoch {
my ($iso) = @_;
if ($iso =~ /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/) {
return timegm($6, $5, $4, $3, $2 - 1, $1 - 1900);
}
return 0;
}
Nun ist es so, wenn ich die Funktion triggere stürzt FHEM komplett ab und startet neu. Die Werte sollen in ein Dummy geschrieben werden:
[code]define Octopus_Strompreis dummy
attr Octopus_Strompreis readingList price_current price_next_hour last_update
attr Octopus_Strompreis room Energie,MiniPV,Zähler
attr Octopus_Strompreis stateFormat Aktuell: price_current ct/kWh </br> Nächste Stunde: price_next_hour ct/kWh
# FUUID 6a3a73f7-f33f-54a1-8d84-f2bfb88940d33850
# FVERSION 98_dummy.pm:0.256060/2022-02-01
# NAME Octopus_Strompreis
# NR 435
# STATE Aktuell: price_current ct/kWh </br> Nächste Stunde: price_next_hour ct/kWh
# TYPE dummy
#
setstate Octopus_Strompreis Aktuell: price_current ct/kWh </br> Nächste Stunde: price_next_hour ct/kWh
[/code]
Getriggert wird die Funktion alle 60min um 1min nach Ganz.
Hat jemand eine Idee warum das Skript auf die Bretter geht?
Vielen Dank
viele Grüße
Martin
Meldung im Logfile zum Absturz?
FHEM schonmal in Debug Modus gestartet und dann getestet?
Hi betateilchen,
das ist ja das Problem, im Logfile steht nix dazu. Aber Evtl. ist das ein Hinweis:
Not a HASH reference at ./FHEM/99_myUtils.pm line 164.
2026.06.23 15:02:37 1: reload: Error:Modul 99_myUtils deactivated:
Leider steht dann nix nach dem Doppelpunkt. Achtung die Zeile 164 stimmt nicht mit dem Skript oben überein. Das steht in Realität noch Zeug davor.