diff --git a/fhem/contrib/ch.eick/Strombörse/EVU_Tibber/RAW_EVU_Tibber_connect15_test.txt b/fhem/contrib/ch.eick/Strombörse/EVU_Tibber/RAW_EVU_Tibber_connect15_test.txt new file mode 100644 index 000000000..7ac827421 --- /dev/null +++ b/fhem/contrib/ch.eick/Strombörse/EVU_Tibber/RAW_EVU_Tibber_connect15_test.txt @@ -0,0 +1,1407 @@ +defmod EVU_Tibber_connect15 HTTPMOD https://api.tibber.com/v1-beta/gql 0 +attr EVU_Tibber_connect15 userattr ws_homeId ws_minInterval ws_myId ws_token ws_websocketURL +attr EVU_Tibber_connect15 DbLogExclude .* +attr EVU_Tibber_connect15 DbLogInclude total_cost_.*,fc0_trigger.* +attr EVU_Tibber_connect15 DbLogValueFn {\ + if ($READING =~ /fc0_trigger/) {\ + my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time_str2num($TIMESTAMP));;\ + $year += 1900;;\ + $mon += 1;;\ + my $quarter = int($min / 15) * 15;; # Minuten auf 0, 15, 30 oder 45 runden\ +\ + $TIMESTAMP = sprintf("%04d-%02d-%02d %02d:%02d:00", $year, $mon, $mday, $hour, $quarter*15);;\ +\ + }\ +} +attr EVU_Tibber_connect15 comment Version 2025.10.30 11:00 \ +https://developer.tibber.com/explorer\ +\ +In der FHEM Kommandozeile könnt Ihr das token und die homeID im KeyStore ablegen.\ +Bitte lest dazu das Thema KeyStore im Wiki und legt die Funktion in Eure 99_myUtils.\ +\ +{KeyValue("store","EVU_Tibber_connect_token","5K4MVS-OjfWhK_4yrjOlFe1F6kJXPVf7eQYggo8ebAE")}\ +{KeyValue("store","EVU_Tibber_connect_homeID","96a14971-525a-4420-aae9-e5aedaa129ff")}\ +\ +Hierduch kann man einen wirtschaftlicheren trigger_price berechnen lassen:\ +setreading EVU_Tibber compensation_grid \ +\ +# Berechnung eines Default Schwellwertes als täglicher Niedrigpreis\ + (fc_avg - fc_min) /2 + fc_min\ +\ +# Abschätzung von Wirtschaftlichkeit beim Speicher Laden, falls Tibber zu teuer wird\ +# compensation_grid kann auch auf einen für Euch passenden Wert gesetzt werden\ + (fc_avg - compensation_grid) *0.85 +attr EVU_Tibber_connect15 disable 0 +attr EVU_Tibber_connect15 enableControlSet 1 +attr EVU_Tibber_connect15 get01-1Name current_currency +attr EVU_Tibber_connect15 get01-2Name current_level +attr EVU_Tibber_connect15 get01-3Name current_date +attr EVU_Tibber_connect15 get01-3OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get01-4Name current_price +attr EVU_Tibber_connect15 get01-4OExpr $val *100 +attr EVU_Tibber_connect15 get01Data { "query": "{viewer {home(id:\"%%homeID%%\") {currentSubscription {priceInfo (resolution: QUARTER_HOURLY){current {total startsAt currency level}}}}}}" } +attr EVU_Tibber_connect15 get01Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get01Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get01JSON data_viewer_home_currentSubscription_priceInfo_current +attr EVU_Tibber_connect15 get01Name 01_priceInfo +attr EVU_Tibber_connect15 get01URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get02-101Name fc0_0545_total +attr EVU_Tibber_connect15 get02-105Name fc0_0600_total +attr EVU_Tibber_connect15 get02-109Name fc0_0615_total +attr EVU_Tibber_connect15 get02-113Name fc0_0630_total +attr EVU_Tibber_connect15 get02-117Name fc0_0645_total +attr EVU_Tibber_connect15 get02-11Name fc0_0000_total +attr EVU_Tibber_connect15 get02-121Name fc0_0700_total +attr EVU_Tibber_connect15 get02-125Name fc0_0715_total +attr EVU_Tibber_connect15 get02-129Name fc0_0730_total +attr EVU_Tibber_connect15 get02-12Name fc0_0000_startsAt +attr EVU_Tibber_connect15 get02-12OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get02-133Name fc0_0745_total +attr EVU_Tibber_connect15 get02-137Name fc0_0800_total +attr EVU_Tibber_connect15 get02-13Name fc0_0015_total +attr EVU_Tibber_connect15 get02-141Name fc0_0815_total +attr EVU_Tibber_connect15 get02-145Name fc0_0830_total +attr EVU_Tibber_connect15 get02-149Name fc0_0845_total +attr EVU_Tibber_connect15 get02-153Name fc0_0900_total +attr EVU_Tibber_connect15 get02-157Name fc0_0915_total +attr EVU_Tibber_connect15 get02-161Name fc0_0930_total +attr EVU_Tibber_connect15 get02-165Name fc0_0945_total +attr EVU_Tibber_connect15 get02-169Name fc0_1000_total +attr EVU_Tibber_connect15 get02-173Name fc0_1015_total +attr EVU_Tibber_connect15 get02-177Name fc0_1030_total +attr EVU_Tibber_connect15 get02-17Name fc0_0030_total +attr EVU_Tibber_connect15 get02-181Name fc0_1045_total +attr EVU_Tibber_connect15 get02-185Name fc0_1100_total +attr EVU_Tibber_connect15 get02-189Name fc0_1115_total +attr EVU_Tibber_connect15 get02-193Name fc0_1130_total +attr EVU_Tibber_connect15 get02-197Name fc0_1145_total +attr EVU_Tibber_connect15 get02-1Name current_price +attr EVU_Tibber_connect15 get02-1OExpr $val *100 +attr EVU_Tibber_connect15 get02-201Name fc0_1200_total +attr EVU_Tibber_connect15 get02-205Name fc0_1215_total +attr EVU_Tibber_connect15 get02-209Name fc0_1230_total +attr EVU_Tibber_connect15 get02-213Name fc0_1245_total +attr EVU_Tibber_connect15 get02-217Name fc0_1300_total +attr EVU_Tibber_connect15 get02-21Name fc0_0045_total +attr EVU_Tibber_connect15 get02-221Name fc0_1315_total +attr EVU_Tibber_connect15 get02-225Name fc0_1330_total +attr EVU_Tibber_connect15 get02-229Name fc0_1345_total +attr EVU_Tibber_connect15 get02-233Name fc0_1400_total +attr EVU_Tibber_connect15 get02-237Name fc0_1415_total +attr EVU_Tibber_connect15 get02-241Name fc0_1430_total +attr EVU_Tibber_connect15 get02-245Name fc0_1445_total +attr EVU_Tibber_connect15 get02-249Name fc0_1500_total +attr EVU_Tibber_connect15 get02-253Name fc0_1515_total +attr EVU_Tibber_connect15 get02-257Name fc0_1530_total +attr EVU_Tibber_connect15 get02-25Name fc0_0100_total +attr EVU_Tibber_connect15 get02-261Name fc0_1545_total +attr EVU_Tibber_connect15 get02-265Name fc0_1600_total +attr EVU_Tibber_connect15 get02-269Name fc0_1615_total +attr EVU_Tibber_connect15 get02-273Name fc0_1630_total +attr EVU_Tibber_connect15 get02-277Name fc0_1645_total +attr EVU_Tibber_connect15 get02-281Name fc0_1700_total +attr EVU_Tibber_connect15 get02-285Name fc0_1715_total +attr EVU_Tibber_connect15 get02-289Name fc0_1730_total +attr EVU_Tibber_connect15 get02-293Name fc0_1745_total +attr EVU_Tibber_connect15 get02-297Name fc0_1800_total +attr EVU_Tibber_connect15 get02-29Name fc0_0115_total +attr EVU_Tibber_connect15 get02-301Name fc0_1815_total +attr EVU_Tibber_connect15 get02-305Name fc0_1830_total +attr EVU_Tibber_connect15 get02-309Name fc0_1845_total +attr EVU_Tibber_connect15 get02-313Name fc0_1900_total +attr EVU_Tibber_connect15 get02-317Name fc0_1915_total +attr EVU_Tibber_connect15 get02-321Name fc0_1930_total +attr EVU_Tibber_connect15 get02-325Name fc0_1945_total +attr EVU_Tibber_connect15 get02-329Name fc0_2000_total +attr EVU_Tibber_connect15 get02-333Name fc0_2015_total +attr EVU_Tibber_connect15 get02-337Name fc0_2030_total +attr EVU_Tibber_connect15 get02-33Name fc0_0130_total +attr EVU_Tibber_connect15 get02-341Name fc0_2045_total +attr EVU_Tibber_connect15 get02-345Name fc0_2100_total +attr EVU_Tibber_connect15 get02-349Name fc0_2115_total +attr EVU_Tibber_connect15 get02-353Name fc0_2130_total +attr EVU_Tibber_connect15 get02-357Name fc0_2145_total +attr EVU_Tibber_connect15 get02-361Name fc0_2200_total +attr EVU_Tibber_connect15 get02-365Name fc0_2215_total +attr EVU_Tibber_connect15 get02-369Name fc0_2230_total +attr EVU_Tibber_connect15 get02-373Name fc0_2245_total +attr EVU_Tibber_connect15 get02-377Name fc0_2300_total +attr EVU_Tibber_connect15 get02-37Name fc0_0145_total +attr EVU_Tibber_connect15 get02-381Name fc0_2315_total +attr EVU_Tibber_connect15 get02-385Name fc0_2330_total +attr EVU_Tibber_connect15 get02-389Name fc0_2345_total +attr EVU_Tibber_connect15 get02-395Name fc1_0000_total +attr EVU_Tibber_connect15 get02-396Name fc1_0000_startsAt +attr EVU_Tibber_connect15 get02-396OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get02-397Name fc1_0015_total +attr EVU_Tibber_connect15 get02-401Name fc1_0030_total +attr EVU_Tibber_connect15 get02-405Name fc1_0045_total +attr EVU_Tibber_connect15 get02-409Name fc1_0100_total +attr EVU_Tibber_connect15 get02-413Name fc1_0115_total +attr EVU_Tibber_connect15 get02-417Name fc1_0130_total +attr EVU_Tibber_connect15 get02-41Name fc0_0200_total +attr EVU_Tibber_connect15 get02-421Name fc1_0145_total +attr EVU_Tibber_connect15 get02-425Name fc1_0200_total +attr EVU_Tibber_connect15 get02-429Name fc1_0215_total +attr EVU_Tibber_connect15 get02-433Name fc1_0230_total +attr EVU_Tibber_connect15 get02-437Name fc1_0245_total +attr EVU_Tibber_connect15 get02-441Name fc1_0300_total +attr EVU_Tibber_connect15 get02-445Name fc1_0315_total +attr EVU_Tibber_connect15 get02-449Name fc1_0330_total +attr EVU_Tibber_connect15 get02-453Name fc1_0345_total +attr EVU_Tibber_connect15 get02-457Name fc1_0400_total +attr EVU_Tibber_connect15 get02-45Name fc0_0215_total +attr EVU_Tibber_connect15 get02-461Name fc1_0415_total +attr EVU_Tibber_connect15 get02-465Name fc1_0430_total +attr EVU_Tibber_connect15 get02-469Name fc1_0445_total +attr EVU_Tibber_connect15 get02-473Name fc1_0500_total +attr EVU_Tibber_connect15 get02-477Name fc1_0515_total +attr EVU_Tibber_connect15 get02-481Name fc1_0530_total +attr EVU_Tibber_connect15 get02-485Name fc1_0545_total +attr EVU_Tibber_connect15 get02-489Name fc1_0600_total +attr EVU_Tibber_connect15 get02-493Name fc1_0615_total +attr EVU_Tibber_connect15 get02-497Name fc1_0630_total +attr EVU_Tibber_connect15 get02-49Name fc0_0230_total +attr EVU_Tibber_connect15 get02-501Name fc1_0645_total +attr EVU_Tibber_connect15 get02-505Name fc1_0700_total +attr EVU_Tibber_connect15 get02-509Name fc1_0715_total +attr EVU_Tibber_connect15 get02-513Name fc1_0730_total +attr EVU_Tibber_connect15 get02-517Name fc1_0745_total +attr EVU_Tibber_connect15 get02-521Name fc1_0800_total +attr EVU_Tibber_connect15 get02-525Name fc1_0815_total +attr EVU_Tibber_connect15 get02-529Name fc1_0830_total +attr EVU_Tibber_connect15 get02-533Name fc1_0845_total +attr EVU_Tibber_connect15 get02-537Name fc1_0900_total +attr EVU_Tibber_connect15 get02-53Name fc0_0245_total +attr EVU_Tibber_connect15 get02-541Name fc1_0915_total +attr EVU_Tibber_connect15 get02-545Name fc1_0930_total +attr EVU_Tibber_connect15 get02-549Name fc1_0945_total +attr EVU_Tibber_connect15 get02-553Name fc1_1000_total +attr EVU_Tibber_connect15 get02-557Name fc1_1015_total +attr EVU_Tibber_connect15 get02-561Name fc1_1030_total +attr EVU_Tibber_connect15 get02-565Name fc1_1045_total +attr EVU_Tibber_connect15 get02-569Name fc1_1100_total +attr EVU_Tibber_connect15 get02-573Name fc1_1115_total +attr EVU_Tibber_connect15 get02-577Name fc1_1130_total +attr EVU_Tibber_connect15 get02-57Name fc0_0300_total +attr EVU_Tibber_connect15 get02-581Name fc1_1145_total +attr EVU_Tibber_connect15 get02-585Name fc1_1200_total +attr EVU_Tibber_connect15 get02-589Name fc1_1215_total +attr EVU_Tibber_connect15 get02-593Name fc1_1230_total +attr EVU_Tibber_connect15 get02-597Name fc1_1245_total +attr EVU_Tibber_connect15 get02-601Name fc1_1300_total +attr EVU_Tibber_connect15 get02-605Name fc1_1315_total +attr EVU_Tibber_connect15 get02-609Name fc1_1330_total +attr EVU_Tibber_connect15 get02-613Name fc1_1345_total +attr EVU_Tibber_connect15 get02-617Name fc1_1400_total +attr EVU_Tibber_connect15 get02-61Name fc0_0315_total +attr EVU_Tibber_connect15 get02-621Name fc1_1415_total +attr EVU_Tibber_connect15 get02-625Name fc1_1430_total +attr EVU_Tibber_connect15 get02-629Name fc1_1445_total +attr EVU_Tibber_connect15 get02-633Name fc1_1500_total +attr EVU_Tibber_connect15 get02-637Name fc1_1515_total +attr EVU_Tibber_connect15 get02-641Name fc1_1530_total +attr EVU_Tibber_connect15 get02-645Name fc1_1545_total +attr EVU_Tibber_connect15 get02-649Name fc1_1600_total +attr EVU_Tibber_connect15 get02-653Name fc1_1615_total +attr EVU_Tibber_connect15 get02-657Name fc1_1630_total +attr EVU_Tibber_connect15 get02-65Name fc0_0330_total +attr EVU_Tibber_connect15 get02-661Name fc1_1645_total +attr EVU_Tibber_connect15 get02-665Name fc1_1700_total +attr EVU_Tibber_connect15 get02-669Name fc1_1715_total +attr EVU_Tibber_connect15 get02-673Name fc1_1730_total +attr EVU_Tibber_connect15 get02-677Name fc1_1745_total +attr EVU_Tibber_connect15 get02-681Name fc1_1800_total +attr EVU_Tibber_connect15 get02-685Name fc1_1815_total +attr EVU_Tibber_connect15 get02-689Name fc1_1830_total +attr EVU_Tibber_connect15 get02-693Name fc1_1845_total +attr EVU_Tibber_connect15 get02-697Name fc1_1900_total +attr EVU_Tibber_connect15 get02-69Name fc0_0345_total +attr EVU_Tibber_connect15 get02-6Name current_date +attr EVU_Tibber_connect15 get02-6OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get02-701Name fc1_1915_total +attr EVU_Tibber_connect15 get02-705Name fc1_1930_total +attr EVU_Tibber_connect15 get02-709Name fc1_1945_total +attr EVU_Tibber_connect15 get02-713Name fc1_2000_total +attr EVU_Tibber_connect15 get02-717Name fc1_2015_total +attr EVU_Tibber_connect15 get02-721Name fc1_2030_total +attr EVU_Tibber_connect15 get02-725Name fc1_2045_total +attr EVU_Tibber_connect15 get02-729Name fc1_2100_total +attr EVU_Tibber_connect15 get02-733Name fc1_2115_total +attr EVU_Tibber_connect15 get02-737Name fc1_2130_total +attr EVU_Tibber_connect15 get02-73Name fc0_0400_total +attr EVU_Tibber_connect15 get02-741Name fc1_2145_total +attr EVU_Tibber_connect15 get02-745Name fc1_2200_total +attr EVU_Tibber_connect15 get02-749Name fc1_2215_total +attr EVU_Tibber_connect15 get02-753Name fc1_2230_total +attr EVU_Tibber_connect15 get02-757Name fc1_2245_total +attr EVU_Tibber_connect15 get02-761Name fc1_2300_total +attr EVU_Tibber_connect15 get02-765Name fc1_2315_total +attr EVU_Tibber_connect15 get02-769Name fc1_2330_total +attr EVU_Tibber_connect15 get02-773Name fc1_2345_total +attr EVU_Tibber_connect15 get02-77Name fc0_0415_total +attr EVU_Tibber_connect15 get02-81Name fc0_0430_total +attr EVU_Tibber_connect15 get02-85Name fc0_0445_total +attr EVU_Tibber_connect15 get02-89Name fc0_0500_total +attr EVU_Tibber_connect15 get02-93Name fc0_0515_total +attr EVU_Tibber_connect15 get02-97Name fc0_0530_total +attr EVU_Tibber_connect15 get02Data { "query": "{viewer {home(id:\"%%homeID%%\") {currentSubscription {priceInfo (resolution: QUARTER_HOURLY) {current {total startsAt} today {total startsAt} tomorrow {total startsAt}}}}}}" } +attr EVU_Tibber_connect15 get02DeleteIfUnmatched 1 +attr EVU_Tibber_connect15 get02FollowGet 01_priceInfo +attr EVU_Tibber_connect15 get02Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get02Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get02Name 02_priceAll +attr EVU_Tibber_connect15 get02RegOpt g +attr EVU_Tibber_connect15 get02Regex "total":(-*\d+.\d+)|"startsAt":"(\d+-\d+-\d+T\d+:\d+:\d+).*(?="today")|\[\{"total":(-*\d+.\d+),"startsAt":"(\d+-\d+-\d+T\d+:\d+:\d+) +attr EVU_Tibber_connect15 get02URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get03-1Name nodes_00_00_from +attr EVU_Tibber_connect15 get03-1OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get03-2Name nodes_00_00_cost +attr EVU_Tibber_connect15 get03-2OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get03-3Name nodes_00_00_consumption +attr EVU_Tibber_connect15 get03-4Name nodes_00_01_from +attr EVU_Tibber_connect15 get03-4OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get03-50OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get03-5Name nodes_00_01_cost +attr EVU_Tibber_connect15 get03-5OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get03-6Name nodes_00_01_consumption +attr EVU_Tibber_connect15 get03-7Name nodes_00_02_from +attr EVU_Tibber_connect15 get03-7OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get03-8Name nodes_00_02_cost +attr EVU_Tibber_connect15 get03-8OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get03-9Name nodes_00_02_consumption +attr EVU_Tibber_connect15 get03Data { "query": "{viewer {home(id:\"%%homeID%%\") {consumption(resolution: HOURLY, last: 3) {nodes {from cost consumption }}}}}"} +attr EVU_Tibber_connect15 get03Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get03Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get03Name 03_consumption_hour +attr EVU_Tibber_connect15 get03RegOpt g +attr EVU_Tibber_connect15 get03Regex \{"from":"([\d+-]+T[\d+:]+\.000[+-][\d+:]+)","cost":(null|-*\d+\.\d+|0),"consumption":(null|\d+\.\d+|0)\} +attr EVU_Tibber_connect15 get03URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get04-10Name nodes_24_03_from +attr EVU_Tibber_connect15 get04-10OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-11Name nodes_24_03_cost +attr EVU_Tibber_connect15 get04-11OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-12Name nodes_24_03_consumption +attr EVU_Tibber_connect15 get04-13Name nodes_24_04_from +attr EVU_Tibber_connect15 get04-13OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-14Name nodes_24_04_cost +attr EVU_Tibber_connect15 get04-14OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-15Name nodes_24_04_consumption +attr EVU_Tibber_connect15 get04-16Name nodes_24_05_from +attr EVU_Tibber_connect15 get04-16OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-17Name nodes_24_05_cost +attr EVU_Tibber_connect15 get04-17OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-18Name nodes_24_05_consumption +attr EVU_Tibber_connect15 get04-19Name nodes_24_06_from +attr EVU_Tibber_connect15 get04-19OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-1Name nodes_24_00_from +attr EVU_Tibber_connect15 get04-1OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-20Name nodes_24_06_cost +attr EVU_Tibber_connect15 get04-20OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-21Name nodes_24_06_consumption +attr EVU_Tibber_connect15 get04-22Name nodes_24_07_from +attr EVU_Tibber_connect15 get04-22OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-23Name nodes_24_07_cost +attr EVU_Tibber_connect15 get04-23OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-24Name nodes_24_07_consumption +attr EVU_Tibber_connect15 get04-25Name nodes_24_08_from +attr EVU_Tibber_connect15 get04-25OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-26Name nodes_24_08_cost +attr EVU_Tibber_connect15 get04-26OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-27Name nodes_24_08_consumption +attr EVU_Tibber_connect15 get04-28Name nodes_24_09_from +attr EVU_Tibber_connect15 get04-28OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-29Name nodes_24_09_cost +attr EVU_Tibber_connect15 get04-29OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-2Name nodes_24_00_cost +attr EVU_Tibber_connect15 get04-2OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-30Name nodes_24_09_consumption +attr EVU_Tibber_connect15 get04-31Name nodes_24_10_from +attr EVU_Tibber_connect15 get04-31OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-32Name nodes_24_10_cost +attr EVU_Tibber_connect15 get04-32OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-33Name nodes_24_10_consumption +attr EVU_Tibber_connect15 get04-34Name nodes_24_11_from +attr EVU_Tibber_connect15 get04-34OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-35Name nodes_24_11_cost +attr EVU_Tibber_connect15 get04-35OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-36Name nodes_24_11_consumption +attr EVU_Tibber_connect15 get04-37Name nodes_24_12_from +attr EVU_Tibber_connect15 get04-37OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-38Name nodes_24_12_cost +attr EVU_Tibber_connect15 get04-38OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-39Name nodes_24_12_consumption +attr EVU_Tibber_connect15 get04-3Name nodes_24_00_consumption +attr EVU_Tibber_connect15 get04-40Name nodes_24_13_from +attr EVU_Tibber_connect15 get04-40OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-41Name nodes_24_13_cost +attr EVU_Tibber_connect15 get04-41OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-42Name nodes_24_13_consumption +attr EVU_Tibber_connect15 get04-43Name nodes_24_14_from +attr EVU_Tibber_connect15 get04-43OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-44Name nodes_24_14_cost +attr EVU_Tibber_connect15 get04-44OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-45Name nodes_24_14_consumption +attr EVU_Tibber_connect15 get04-46Name nodes_24_15_from +attr EVU_Tibber_connect15 get04-46OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-47Name nodes_24_15_cost +attr EVU_Tibber_connect15 get04-47OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-48Name nodes_24_15_consumption +attr EVU_Tibber_connect15 get04-49Name nodes_24_16_from +attr EVU_Tibber_connect15 get04-49OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-4Name nodes_24_01_from +attr EVU_Tibber_connect15 get04-4OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-50Name nodes_24_16_cost +attr EVU_Tibber_connect15 get04-50OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-51Name nodes_24_16_consumption +attr EVU_Tibber_connect15 get04-52Name nodes_24_17_from +attr EVU_Tibber_connect15 get04-52OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-53Name nodes_24_17_cost +attr EVU_Tibber_connect15 get04-53OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-54Name nodes_24_17_consumption +attr EVU_Tibber_connect15 get04-55Name nodes_24_18_from +attr EVU_Tibber_connect15 get04-55OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-56Name nodes_24_18_cost +attr EVU_Tibber_connect15 get04-56OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-57Name nodes_24_18_consumption +attr EVU_Tibber_connect15 get04-58Name nodes_24_19_from +attr EVU_Tibber_connect15 get04-58OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-59Name nodes_24_19_cost +attr EVU_Tibber_connect15 get04-59OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-5Name nodes_24_01_cost +attr EVU_Tibber_connect15 get04-5OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-60Name nodes_24_19_consumption +attr EVU_Tibber_connect15 get04-61Name nodes_24_20_from +attr EVU_Tibber_connect15 get04-61OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-62Name nodes_24_20_cost +attr EVU_Tibber_connect15 get04-62OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-63Name nodes_24_20_consumption +attr EVU_Tibber_connect15 get04-64Name nodes_24_21_from +attr EVU_Tibber_connect15 get04-64OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-65Name nodes_24_21_cost +attr EVU_Tibber_connect15 get04-65OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-66Name nodes_24_21_consumption +attr EVU_Tibber_connect15 get04-67Name nodes_24_22_from +attr EVU_Tibber_connect15 get04-67OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-68Name nodes_24_22_cost +attr EVU_Tibber_connect15 get04-68OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-69Name nodes_24_22_consumption +attr EVU_Tibber_connect15 get04-6Name nodes_24_01_consumption +attr EVU_Tibber_connect15 get04-70Name nodes_24_23_from +attr EVU_Tibber_connect15 get04-70OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-71Name nodes_24_23_cost +attr EVU_Tibber_connect15 get04-71OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-72Name nodes_24_23_consumption +attr EVU_Tibber_connect15 get04-7Name nodes_24_02_from +attr EVU_Tibber_connect15 get04-7OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get04-8Name nodes_24_02_cost +attr EVU_Tibber_connect15 get04-8OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get04-9Name nodes_24_02_consumption +attr EVU_Tibber_connect15 get04Data { "query": "{viewer {home(id:\"%%homeID%%\") {consumption(resolution: HOURLY, last: 24) {nodes {from cost consumption}}}}}"} +attr EVU_Tibber_connect15 get04Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get04Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get04Name 04_consumption_hour_24 +attr EVU_Tibber_connect15 get04RegOpt g +attr EVU_Tibber_connect15 get04Regex \{"from":"([\d+-]+T[\d+:]+\.000[+-][\d+:]+)","cost":(null|-*\d+\.\d+|0),"consumption":(null|\d+\.\d+|0)\} +attr EVU_Tibber_connect15 get04URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get05AutoNumLen 4 +attr EVU_Tibber_connect15 get05Data { "query": "{viewer {home(id:\"%%homeID%%\") {consumption(resolution: HOURLY, last: 100) {nodes {from cost consumption}}}}}"} +attr EVU_Tibber_connect15 get05Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get05Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get05JSON data_viewer_home +attr EVU_Tibber_connect15 get05Name 05_consumption_hourly_100 +attr EVU_Tibber_connect15 get05URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get06-10Name Adresse_07_Telefon +attr EVU_Tibber_connect15 get06-11Name Adresse_01_Vorname +attr EVU_Tibber_connect15 get06-12Name Adresse_02_Nachname +attr EVU_Tibber_connect15 get06-1Name Adresse_03_Strasse +attr EVU_Tibber_connect15 get06-2Name Adresse_05_Ort +attr EVU_Tibber_connect15 get06-3Name Adresse_06_Land +attr EVU_Tibber_connect15 get06-4Name Adresse_05_Ort +attr EVU_Tibber_connect15 get06-5Name Adresse_06_Land +attr EVU_Tibber_connect15 get06-6Name Adresse_09_latitude +attr EVU_Tibber_connect15 get06-7Name Adresse_10_longitude +attr EVU_Tibber_connect15 get06-8Name Adresse_04_Plz +attr EVU_Tibber_connect15 get06-9Name Adresse_08_eMail +attr EVU_Tibber_connect15 get06Data { "query": "{viewer {home(id:\"%%homeID%%\") {address {address1 address2 address3 postalCode city country latitude longitude} owner {firstName lastName contactInfo {email mobile}}}}}" } +attr EVU_Tibber_connect15 get06Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get06Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get06JSON data_viewer_home +attr EVU_Tibber_connect15 get06Name 06_address +attr EVU_Tibber_connect15 get06URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 get07-10Name nodes_24_03_from +attr EVU_Tibber_connect15 get07-10OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-11Name nodes_24_03_cost +attr EVU_Tibber_connect15 get07-11OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-12Name nodes_24_03_consumption +attr EVU_Tibber_connect15 get07-13Name nodes_24_04_from +attr EVU_Tibber_connect15 get07-13OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-14Name nodes_24_04_cost +attr EVU_Tibber_connect15 get07-14OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-15Name nodes_24_04_consumption +attr EVU_Tibber_connect15 get07-16Name nodes_24_05_from +attr EVU_Tibber_connect15 get07-16OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-17Name nodes_24_05_cost +attr EVU_Tibber_connect15 get07-17OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-18Name nodes_24_05_consumption +attr EVU_Tibber_connect15 get07-19Name nodes_24_06_from +attr EVU_Tibber_connect15 get07-19OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-1Name features_realTimeConsumptionEnabled +attr EVU_Tibber_connect15 get07-1OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-20Name nodes_24_06_cost +attr EVU_Tibber_connect15 get07-20OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-21Name nodes_24_06_consumption +attr EVU_Tibber_connect15 get07-22Name nodes_24_07_from +attr EVU_Tibber_connect15 get07-22OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-23Name nodes_24_07_cost +attr EVU_Tibber_connect15 get07-23OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-24Name nodes_24_07_consumption +attr EVU_Tibber_connect15 get07-25Name nodes_24_08_from +attr EVU_Tibber_connect15 get07-25OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-26Name nodes_24_08_cost +attr EVU_Tibber_connect15 get07-26OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-27Name nodes_24_08_consumption +attr EVU_Tibber_connect15 get07-28Name nodes_24_09_from +attr EVU_Tibber_connect15 get07-28OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-29Name nodes_24_09_cost +attr EVU_Tibber_connect15 get07-29OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-2Name features_id +attr EVU_Tibber_connect15 get07-2OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-30Name nodes_24_09_consumption +attr EVU_Tibber_connect15 get07-31Name nodes_24_10_from +attr EVU_Tibber_connect15 get07-31OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-32Name nodes_24_10_cost +attr EVU_Tibber_connect15 get07-32OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-33Name nodes_24_10_consumption +attr EVU_Tibber_connect15 get07-34Name nodes_24_11_from +attr EVU_Tibber_connect15 get07-34OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-35Name nodes_24_11_cost +attr EVU_Tibber_connect15 get07-35OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-36Name nodes_24_11_consumption +attr EVU_Tibber_connect15 get07-37Name nodes_24_12_from +attr EVU_Tibber_connect15 get07-37OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-38Name nodes_24_12_cost +attr EVU_Tibber_connect15 get07-38OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-39Name nodes_24_12_consumption +attr EVU_Tibber_connect15 get07-3Name nodes_24_00_consumption +attr EVU_Tibber_connect15 get07-40Name nodes_24_13_from +attr EVU_Tibber_connect15 get07-40OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-41Name nodes_24_13_cost +attr EVU_Tibber_connect15 get07-41OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-42Name nodes_24_13_consumption +attr EVU_Tibber_connect15 get07-43Name nodes_24_14_from +attr EVU_Tibber_connect15 get07-43OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-44Name nodes_24_14_cost +attr EVU_Tibber_connect15 get07-44OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-45Name nodes_24_14_consumption +attr EVU_Tibber_connect15 get07-46Name nodes_24_15_from +attr EVU_Tibber_connect15 get07-46OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-47Name nodes_24_15_cost +attr EVU_Tibber_connect15 get07-47OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-48Name nodes_24_15_consumption +attr EVU_Tibber_connect15 get07-49Name nodes_24_16_from +attr EVU_Tibber_connect15 get07-49OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-4Name nodes_24_01_from +attr EVU_Tibber_connect15 get07-4OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-50Name nodes_24_16_cost +attr EVU_Tibber_connect15 get07-50OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-51Name nodes_24_16_consumption +attr EVU_Tibber_connect15 get07-52Name nodes_24_17_from +attr EVU_Tibber_connect15 get07-52OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-53Name nodes_24_17_cost +attr EVU_Tibber_connect15 get07-53OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-54Name nodes_24_17_consumption +attr EVU_Tibber_connect15 get07-55Name nodes_24_18_from +attr EVU_Tibber_connect15 get07-55OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-56Name nodes_24_18_cost +attr EVU_Tibber_connect15 get07-56OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-57Name nodes_24_18_consumption +attr EVU_Tibber_connect15 get07-58Name nodes_24_19_from +attr EVU_Tibber_connect15 get07-58OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-59Name nodes_24_19_cost +attr EVU_Tibber_connect15 get07-59OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-5Name nodes_24_01_cost +attr EVU_Tibber_connect15 get07-5OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-60Name nodes_24_19_consumption +attr EVU_Tibber_connect15 get07-61Name nodes_24_20_from +attr EVU_Tibber_connect15 get07-61OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-62Name nodes_24_20_cost +attr EVU_Tibber_connect15 get07-62OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-63Name nodes_24_20_consumption +attr EVU_Tibber_connect15 get07-64Name nodes_24_21_from +attr EVU_Tibber_connect15 get07-64OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-65Name nodes_24_21_cost +attr EVU_Tibber_connect15 get07-65OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-66Name nodes_24_21_consumption +attr EVU_Tibber_connect15 get07-67Name nodes_24_22_from +attr EVU_Tibber_connect15 get07-67OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-68Name nodes_24_22_cost +attr EVU_Tibber_connect15 get07-68OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-69Name nodes_24_22_consumption +attr EVU_Tibber_connect15 get07-6Name nodes_24_01_consumption +attr EVU_Tibber_connect15 get07-70Name nodes_24_23_from +attr EVU_Tibber_connect15 get07-70OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-71Name nodes_24_23_cost +attr EVU_Tibber_connect15 get07-71OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-72Name nodes_24_23_consumption +attr EVU_Tibber_connect15 get07-7Name nodes_24_02_from +attr EVU_Tibber_connect15 get07-7OExpr $val =~ s/T/ /g ;; substr($val,0,19) +attr EVU_Tibber_connect15 get07-8Name nodes_24_02_cost +attr EVU_Tibber_connect15 get07-8OExpr ($val ne "0" and $val ne "null")? round($val*1.19,4) : $val +attr EVU_Tibber_connect15 get07-9Name nodes_24_02_consumption +attr EVU_Tibber_connect15 get07Data { "query": "{viewer {home(id:\"%%homeID%%\") {id features{realTimeConsumptionEnabled} } } }" } +attr EVU_Tibber_connect15 get07Header01 Content-Type: application/json +attr EVU_Tibber_connect15 get07Header02 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 get07JSON data_viewer_home +attr EVU_Tibber_connect15 get07Name 07_realTimeConsumptionEnabled +attr EVU_Tibber_connect15 get07RegOpt g +attr EVU_Tibber_connect15 get07Regex \{"from":"([\d+-]+T[\d+:]+\.000[+-][\d+:]+)","cost":(null|-*\d+\.\d+|0),"consumption":(null|\d+\.\d+|0)\} +attr EVU_Tibber_connect15 get07URL https://api.tibber.com/v1-beta/gql +attr EVU_Tibber_connect15 group PV Steuerung EVU +attr EVU_Tibber_connect15 icon stromzaehler_icon +attr EVU_Tibber_connect15 replacement01Mode expression +attr EVU_Tibber_connect15 replacement01Regex %%token%% +attr EVU_Tibber_connect15 replacement01Value {KeyValue("read","EVU_Tibber_connect_token")} +attr EVU_Tibber_connect15 replacement02Mode expression +attr EVU_Tibber_connect15 replacement02Regex %%homeID%% +attr EVU_Tibber_connect15 replacement02Value {KeyValue("read","EVU_Tibber_connect_homeID")} +attr EVU_Tibber_connect15 requestData { "query": "{viewer {home(id:\"%%homeID%%\") {currentSubscription {priceInfo {current {total energy tax startsAt }}}}}}" } +attr EVU_Tibber_connect15 requestHeader1 Content-Type: application/json +attr EVU_Tibber_connect15 requestHeader2 Authorization: Bearer %%token%% +attr EVU_Tibber_connect15 room Strom->Boerse +attr EVU_Tibber_connect15 showBody 1 +attr EVU_Tibber_connect15 showError 1 +attr EVU_Tibber_connect15 sortby 313 +attr EVU_Tibber_connect15 timeout 30 +attr EVU_Tibber_connect15 userReadings ws_connect:ws_cmd:.connect {\ + my $hash = $defs{$name};;\ + my $devState = DevIo_IsOpen($hash);;\ + return "Device already open" if (defined($devState));;\ + \ + # establish connection to websocket\ + # format must also include portnumber if a path is to be specified\ + $hash->{DeviceName} = AttrVal($name, "ws_websocketURL", "wss:echo.websocket.org:443");;\ + \ + # special headers needed for Tibber, see also Developer Tools in Browser\ + $hash->{header}{'Sec-WebSocket-Protocol'} = 'graphql-transport-ws';;\ + $hash->{header}{'Host'} = 'websocket-api.tibber.com';;\ + $hash->{header}{'Origin'} = 'https://developer.tibber.com';;\ + \ + # callback function when "select()" signals data for us\ + # websocket Ping/Pongs are treated in DevIo but still call this function\ + $hash->{directReadFn} = sub () {\ + my $hash = $defs{$name};;\ + \ + # we can read without closing the DevIo, because select() signalled data\ + my $buf = DevIo_SimpleRead($hash);;\ + \ + # if read fails, close device\ + if(!defined($buf)) {\ + DevIo_CloseDev($hash);;\ + $buf = "not_connected";;\ + }\ + \ + #Log(3, "$name:$reading: websocket data: >>>$buf<<<");;\ + \ + # only update our reading if buffer is not empty and if last update is older than minInterval\ + if ($buf ne "") {\ + my $websocketDataAge = ReadingsAge($name, "ws_websocketData", 3600);;\ + my $minInterval = AttrVal($name, "ws_minInterval", 0);;\ + my $isNext = ($buf =~ /.*id.*type.*next.*payload.*data.*liveMeasurement.*/s);;\ + \ + readingsBeginUpdate($hash);;\ + readingsBulkUpdate($hash, "ws_websocketData", "$buf") if ($isNext && $websocketDataAge > $minInterval);;\ + readingsBulkUpdate($hash, "ws_websocketData", "$buf") if (!$isNext);;\ + readingsEndUpdate($hash, 1);;\ + #Log(3, "$name:$reading: websocket data written to reading");;\ + }\ + };;\ + \ + # open DevIo websocket\ + DevIo_OpenDev($hash, 0, undef, sub(){\ + my ($hash, $error) = @_;;\ + return "$error" if ($error);;\ + \ + my $token = AttrVal($name, "ws_token", "???");;\ + $token = KeyValue("read","EVU_Tibber_connect_token") if ($token eq "???");;\ +\ + DevIo_SimpleWrite($hash, '{"type":"connection_init","payload":{"token":"'.$token.'"}}', 2);;\ + });;\ + readingsBulkUpdate($hash, "ws_websocketData", "");;\ + #Log(3, "$name:$reading: websocket data cleared in reading");;\ + \ + return POSIX::strftime("%H:%M:%S",localtime(time()));;\ +},\ +\ +ws_disconnect:ws_cmd:.disconnect {\ + Log(3, "$name: disconnect");;\ + my $hash = $defs{$name};;\ + RemoveInternalTimer($hash);;\ + DevIo_SimpleRead($hash);;\ + DevIo_CloseDev($hash);;\ +\ + return POSIX::strftime("%H:%M:%S",localtime(time()));;\ +},\ +\ +ws_onDisconnect {\ + my $myState = ReadingsVal($name, "state", "???");;\ + my $myData = ReadingsVal($name, "ws_websocketData", "???");;\ + return if ($myState ne "disconnected" and $myData ne "not_connected");;\ + \ + ## timer callback function, called after a few seconds to initiate a reconnect\ + my $timerFunction = sub() {\ + my ($arg) = @_;;\ + my $hash = $defs{$name};;\ + my $devState = DevIo_IsOpen($hash);;\ + \ + # only re-connect if device is not connected\ + readingsSingleUpdate($hash, "ws_cmd", "connect", 1) if (!defined($devState));;\ + };;\ + RemoveInternalTimer($name.$reading.'Timer');;\ + \ + # wait a random time before reconnect (exponential backoff TBD):\ + my $rwait = int(rand(200)) + 30;;\ + InternalTimer(gettimeofday() + $rwait, $timerFunction, $name.$reading.'Timer');;\ + \ + #set cmd to a new value, informs user and allows to retrigger when timer expires\ + my $hash = $defs{$name};;\ + readingsBulkUpdate($hash, "ws_cmd", "reconnect attempt in $rwait seconds");;\ + \ + return POSIX::strftime("%H:%M:%S",localtime(time()));;\ +},\ +\ +ws_onTimeout:ws_websocketData:.* {\ + #re-establish websocket connection if no data received in the past ten minutes\ + #but only if our reading "ws_cmd" was not set to the value "disconnect"\ +\ + #Log(3, "$name:$reading: websocket data triggert ws_onTimeout");;\ +\ + #timeout in seconds when the connection is considered dead\ + my $timeoutTime = 600;;\ + \ + # function to execute when timeout expired\ + # defining the function here in the userReading, allows us to insert variables directly\ + my $timerFunction = sub() {\ + my ($arg) = @_;;\ + my $hash = $defs{$name};;\ + my $rCmd = ReadingsVal($name, "ws_cmd", "???");;\ + my $age = ReadingsAge($name, "ws_websocketData", 0);;\ + \ + Log(3, "$name: onTimeoutTimer triggered >>$arg<<");;\ + \ + #do not do anything further if disconnect is on purpose\ + if ( $rCmd eq "disconnect" ) {\ + Log(3, "$name: ws_cmd was set to disconnect");;\ + return;;\ + }\ + \ + # for whatever reason, we triggered to soon (80%)\ + if ( $age < $timeoutTime*0.8 ) {\ + Log(3, "$name: ws_websocketData is not outdated");;\ + return;;\ + }\ + \ + DevIo_CloseDev($hash);;\ + Log(3, "$name: onTimeoutTimer closed DevIo...");;\ + \ + readingsSingleUpdate($hash, "ws_cmd", "connect", 1);;\ + Log(3, "$name: onTimeoutTimer set ws_cmd to value 'connect'");;\ + };;\ +\ + #Log(3, "$name:$reading: onTimeout function defined");;\ +\ + #remove/cancel previous timers, because we got fresh data and countdown starts again\ + RemoveInternalTimer($name.$reading.'Timer');;\ + \ + #set timer to expire and execute function defined above, give special arg as identifier\ + InternalTimer(gettimeofday() + $timeoutTime, $timerFunction, $name.$reading.'Timer');;\ + \ + return POSIX::strftime("%H:%M:%S",localtime(time()));;\ +},\ +\ +ws_onConnectionAck:ws_websocketData:.*connection_ack.* {\ + #ws_websocketData contains the string "connection_ack"\ + Log(3, "$name:$reading: got connection ack");;\ + \ + # do not proceed if connection is lost\ + my $hash = $defs{$name};;\ + my $devState = DevIo_IsOpen($hash);;\ + return "Device not open" if (!defined($devState));;\ +\ + readingsBulkUpdate($hash, "ws_cmd", "got connection ack");;\ + \ + my $homeId = AttrVal($name, "ws_homeId", "???");;\ + $homeId = KeyValue("read","EVU_Tibber_connect_homeID") if ($homeId eq "???");;\ +\ + my $myId = AttrVal($name, "ws_myId", "???");;\ + $myId = KeyValue("read","EVU_Tibber_connect_homeID") if ($myId eq "???");;\ + \ + # build the query, do it in pieces, the comma at the end caused perl errors\ + # so we put it together in this not very elegant way\ + my $json = '{ "id":"'. $myId .'", "type":"subscribe"'.", ";;\ + $json .= '"payload":{';;\ + $json .= '"variables":{}'.", ";;\ + $json .= '"extensions":{}'.", ";;\ + $json .= '"query":"subscription { liveMeasurement( homeId: \"'.$homeId.'\" ) ';;\ + #$json .= '{ timestamp power accumulatedConsumption accumulatedCost currency minPower averagePower maxPower signalStrength }}"';;\ + $json .= '{ timestamp power lastMeterConsumption accumulatedConsumption accumulatedProduction ';;\ + $json .= 'accumulatedProductionLastHour accumulatedCost accumulatedReward currency minPower averagePower maxPower ';;\ + $json .= 'powerProduction powerReactive powerProductionReactive minPowerProduction maxPowerProduction lastMeterProduction ';;\ + $json .= 'powerFactor voltagePhase1 voltagePhase2 voltagePhase3 signalStrength }}"';;\ + $json .= '}}';;\ + \ + #send the string via websocket as ASCII\ + #Log(3, "$name:$reading: sending JSON: >>>$json<<<");;\ + DevIo_SimpleWrite($hash, $json, 2);;\ + \ + return POSIX::strftime("%H:%M:%S",localtime(time()));;\ +},\ +\ +ws_onNextLiveMeasurement:ws_websocketData:.*next.*payload.*data.*liveMeasurement.* {\ + #websocketData contains next-live-measurement-data\ + my $val = ReadingsVal($name, "ws_websocketData", "{}");;\ + my %res = %{json2nameValue($val, undef, undef, "payload_data_liveMeasurement.*")};;\ + \ + my $ret = "got values for:\n";;\ + foreach my $k (sort keys %res) {\ + $ret .= "$k\n";;\ + readingsBulkUpdate($hash, makeReadingName($k), $res{$k});;\ + }\ + return $ret;;\ +},\ +\ +nodes_TIMESTAMP:nodes_00_00_cost.* {\ +my ($timestamp,$value) = 2x0;;\ +my $tmp = 0;;\ +\ +for (my $loop_last = 0;; $loop_last <= 2;; $loop_last++) {\ + $timestamp = ReadingsVal("$NAME","nodes_00_".sprintf("%02d",$loop_last)."_from","null");;\ + $value = ReadingsVal("$NAME","nodes_00_".sprintf("%02d",$loop_last)."_cost","null");;\ +\ + if ( $value ne "null" ) {\ + # Eintragen der Kosten für die Stunde\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_cost','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + # Eintragen des Verbrauchs für die Stunde\ + $value = ReadingsVal("$NAME","nodes_00_".sprintf("%02d",$loop_last)."_consumption","null");;\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_consumption','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + } else {\ + $tmp = "null";;\ + }\ +} # end for\ +if ($tmp eq "null") {\ + $timestamp = $tmp\ +}\ +$timestamp;;\ +},\ +\ +nodes_TIMESTAMP:nodes_24_00_cost.* {\ +my ($timestamp,$value) = 2x0;;\ +my $tmp = 0;;\ +\ +for (my $loop_last = 0;; $loop_last <= 23;; $loop_last++) {\ + $timestamp = ReadingsVal("$NAME","nodes_24_".sprintf("%02d",$loop_last)."_from","null");;\ + $value = ReadingsVal("$NAME","nodes_24_".sprintf("%02d",$loop_last)."_cost","null");;\ +\ + if ( $value ne "null" ) {\ + # Eintragen der Kosten für die Stunde\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_cost','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + # Eintragen des Verbrauchs für die Stunde\ + $value = ReadingsVal("$NAME","nodes_24_".sprintf("%02d",$loop_last)."_consumption","null");;\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_consumption','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + } else {\ + $tmp = "null";;\ + }\ +} # end for\ +if ($tmp eq "null") {\ + $timestamp = $tmp\ +}\ +$timestamp;;\ +},\ +\ +nodes_TIMESTAMP:05_consumption_hourly_100-0001.* {\ +my ($timestamp,$value) = 2x0;;\ +\ +for (my $loop_last = 1;; $loop_last <= 300;; $loop_last += 3) {\ +\ + $timestamp = ReadingsVal("$NAME","05_consumption_hourly_100-".sprintf("%04d",$loop_last+2),"null");; # timestamp\ + $timestamp =~ s/T/ /g ;;\ + $timestamp = substr($timestamp,0,19);;\ +\ + # cost aus tibber-Api ohne MwSt\ + $value = ReadingsVal("$NAME","05_consumption_hourly_100-".sprintf("%04d",$loop_last+1),"null");;\ +\ + if ( $value ne "" ) {\ +\ + # Berechnung der Kosten inkl. 19% MwSt für die Stunde\ + $value = round($value*1.19,4);;\ +# print $timestamp." ".$value."\n";;\ +\ + # Schreiben der Kosten für die Stunde in die Datenbank\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_cost','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + # Schreiben des Verbrauchs für die Stunde in die Datenbank\ + $value = ReadingsVal("$NAME","05_consumption_hourly_100-".sprintf("%04d",$loop_last),"null");; # consumption\ + $value = round($value,4);;\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','nodes_consumption','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + }\ +} # end for\ +\ +$timestamp;;\ +},\ +\ +nodes_cost_avg:nodes_TIMESTAMP.* {\ +## Berechnung des Tages Wertes\ + if ( ReadingsVal("$NAME","nodes_TIMESTAMP","null") ne "null" ) {\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(avg(VALUE)*100 AS DECIMAL(4,2)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND TIMESTAMP >= curdate() ;;") ;;\ + } else {\ + ReadingsVal("$NAME","nodes_cost_avg","null")\ + }\ +},\ +\ +nodes_cost_min:nodes_TIMESTAMP.* {\ +## Ermittlung des minimal Wertes\ +if ( ReadingsVal("$NAME","nodes_TIMESTAMP","null") ne "null" ) {\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(min(VALUE)*100 AS DECIMAL(4,2)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND TIMESTAMP >= curdate() ;;") ;;\ +} else {\ + ReadingsVal("$NAME","nodes_cost_min","null")\ +}\ +},\ +\ +nodes_cost_max:nodes_TIMESTAMP.* {\ +## Ermittlung des maximal Wertes\ + if ( ReadingsVal("$NAME","nodes_TIMESTAMP","null") ne "null" ) {\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(max(VALUE)*100 AS DECIMAL(4,2)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND TIMESTAMP >= curdate() ;;") ;;\ + } else {\ + ReadingsVal("$NAME","nodes_cost_max","null")\ + }\ +},\ +\ +nodes_consumption_day:nodes_TIMESTAMP.* {\ +## Berechnung des Tages Verbrauches\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(sum(VALUE) AS DECIMAL(10,4)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_consumption'\ + AND date(TIMESTAMP) = curdate() ;;") ;;\ +},\ +\ +nodes_consumption_month:nodes_TIMESTAMP.* {\ +## Berechnung des Monats Verbrauches\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(sum(VALUE) AS DECIMAL(10,4)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_consumption'\ + AND YEAR(TIMESTAMP) = YEAR(curdate())\ + AND MONTH(TIMESTAMP) = MONTH(curdate()) ;;") ;;\ +},\ +\ +nodes_consumption_year:nodes_TIMESTAMP.* {\ +## Berechnung des Jahres Verbrauches\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT cast(sum(VALUE) AS DECIMAL(10,4)) FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_consumption'\ + AND YEAR(TIMESTAMP) = YEAR(curdate()) ;;") ;;\ +},\ +\ +fc_avg:current_price.* {\ +## Berechnung des durchschnitt Wertes über alle Werte von fc0 und fc1\ + my $fc = 0;; # fc0_ = heute, passt sich an wenn es über Mitternacht geht\ + my $fc_avg = 0;;\ +\ + if (ReadingsVal("$NAME","fc1_0000_startsAt","null") ne "null") { ## Der nächste Tag ist bereits da\ + if (AttrVal("$NAME","verbose",0) >=3) {\ + Log 3, "$NAME cmd_1 : Tibber Daten für fc1 sind bereits da";;\ + }\ + $fc = 1;;\ + } # end if\ +\ + for (my $j=0;;$j<=$fc ;;$j++){ # heute und eventuell morgen durchlaufen\ + for (my $k=0;;$k<=23;;$k++) { ## Summe berechnen\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_avg += ReadingsVal("$NAME",sprintf("fc%d_%02d%02d_total",$j, $k, $quarter*15),0);;\ + } # end $quarter\ + } # end $k\ + } # end $j\ +\ + return round($fc_avg / (96 *(1+$fc)) *100 ,2);; ## Durchschnitt berechnen\ +},\ +\ +fc_med:current_price.* {\ +## Berechnung des median Wertes\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT\ + cast( ( (SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(VALUE order by VALUE), ',', floor(1+((count(VALUE)-1) / 2))) , ',', -1))\ + + (SUBSTRING_INDEX(SUBSTRING_INDEX(group_concat(VALUE order by VALUE), ',', ceiling(1+((count(VALUE)-1) / 2))), ',', -1))\ + )/2 *100\ + AS DECIMAL(4,2))\ + FROM history\ + WHERE DEVICE='".$NAME."'\ + AND ( READING='fc0_total' AND TIMESTAMP >= DATE_FORMAT(NOW(), '%Y-%m-%d 00:00:00')\ + OR READING='fc1_total' AND TIMESTAMP >= DATE_FORMAT(NOW() + INTERVAL 1 DAY, '%Y-%m-%d 00:00:00') ) ;;") ;;\ +},\ +\ +fc_min:current_price.* {\ +## Ermittlung des minimal Wertes\ + my $fc = 0;; # fc0_ = heute, passt sich an wenn es über Mitternacht geht\ + my $fc_min = 0;;\ + my $fc_tmp = 0;;\ +\ + if (ReadingsVal("$NAME","fc1_0000_startsAt","null") ne "null") { ## Der nächste Tag ist bereits da\ + $fc = 1;;\ + } # end if\ +\ + for (my $j=0;;$j<=$fc;;$j++){\ + for (my $k=0;;$k<=23;;$k++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_tmp = ReadingsVal("$NAME",sprintf("fc%d_%02d%02d_total",$j,$k, $quarter*15),0);;\ + if (($fc_tmp < $fc_min) or ($j == 0 and $k == 0 and $quarter == 0)) {\ + $fc_min = $fc_tmp;;\ + }\ + } # end $quarter\ + } # end $k\ + } # end $j\ +\ + return round($fc_min *100 ,2);; ## Von Euro auf Cent umrechnen\ +},\ +\ +fc_max:current_price.* {\ +## Ermittlung des minimal Wertes\ + my $fc = 0;; # fc0_ = heute, passt sich an wenn es über Mitternacht geht\ + my $fc_max = 0;;\ + my $fc_tmp = 0;;\ +\ + if (ReadingsVal("$NAME","fc1_0000_startsAt","null") ne "null") { ## Der nächste Tag ist bereits da\ + $fc = 1;;\ + } # end if\ +\ + for (my $j=0;;$j<=$fc;;$j++){\ + for (my $k=0;;$k<=23;;$k++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_tmp = ReadingsVal("$NAME",sprintf("fc%d_%02d%02d_total",$j,$k, $quarter*15),0);;\ + if (($fc_tmp > $fc_max) or ($j == 0 and $k == 0 and $quarter == 0)) {\ + $fc_max = $fc_tmp;;\ + }\ + } # end $quarter\ + } # end $k\ + } # end $j\ +\ + return round($fc_max *100 ,2);; ## Von Euro auf Cent umrechnen\ +},\ +\ +fc_trigger_price:fc_avg.* {\ +## fc_trigger_price:[fc_avg|compensation_grid].* {\ + my $fc_avg = ReadingsVal("$NAME","fc_avg",0);;\ + my $fc_min = ReadingsVal("$NAME","fc_min",0);;\ +\ + # Berechnung eines Default Schwellwertes als täglicher Niedrigpreis\ + my $price_level = round( ($fc_avg - $fc_min)/2 + $fc_min , 1);;\ + \ + # Abschätzung von Wirtschaftlichkeit beim Speicher Laden, falls Tibber zu teuer wird\ + if ( ReadingsVal("$NAME","compensation_grid",0) != 0 ) {\ + my $price_level_battery = round( ($fc_avg - ReadingsVal("$NAME","compensation_grid",0)) *0.85 , 1) ;;\ + if ( $price_level > $price_level_battery ) {\ + $price_level = $price_level_battery;;\ + }\ + }\ + return($price_level);;\ +},\ +\ +fc0_trigger_start:fc_trigger_price.* {\ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\ + my $fc_trigger_price = ReadingsVal("$NAME","fc_trigger_price",0) /100;;\ +\ + # Ermitteln des nächsten Trigger Fensters\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = $hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc0_%02d%02d_total",$loop_hour , $quarter*15),0);;\ +# print sprintf("fc0 Start %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_price."\n";;\ + if ( $fc_total < $fc_trigger_price ) {\ + return(sprintf("%02d:%02d",$loop_hour ,$quarter*15)) ;;\ + }\ + } # end $quarter\ + } # end for loop_hour\ +\ + return("null");;\ +},\ +\ +fc0_trigger_stop:fc0_trigger_start.* {\ + my $fc = 0;;\ + my $loop_hour = 0;;\ + my $fc_trigger_price = ReadingsVal("$NAME","fc_trigger_price",0) /100;;\ +\ + # Ermitteln des nächsten Trigger Fensters\ + my $fc_trigger_start = ReadingsVal("$NAME","fc0_trigger_start","null");;\ + my $fc_trigger_stop = $fc_trigger_start;;\ +\ + my ($fc_trigger_start_hour, $fc_trigger_start_quarter);;\ +\ + if ( $fc_trigger_start ne "null" ) {\ + $fc_trigger_start =~ /(\d\d):(\d\d)/;;\ + $fc_trigger_start_hour = $1;;\ + $fc_trigger_start_quarter = $2 / 15;;\ + my $fc_total = 0;;\ +\ + for ($loop_hour = $fc_trigger_start_hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = $fc_trigger_start_quarter;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc0_%02d%02d_total",$loop_hour , $quarter*15),0);;\ +# print sprintf("fc0 Stop %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_price."\n";;\ + if ( $fc_total < $fc_trigger_price ) {\ + $fc_trigger_stop = sprintf("%02d:%02d",$loop_hour, $quarter*15) ;;\ + } else {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15));;\ + }\ +\ + # wenn es 23:45 is wechsel zum nächsten Tag\ + if ( $loop_hour == 23 and $fc == 0 and $quarter == 3) {\ + $fc = 1;;\ + $loop_hour = -1;; # beginne wieder bei 00:00\ + }\ +\ + if ( $quarter == 3 ) { $fc_trigger_start_quarter = 0 }\ +\ + } # end $quarter\ + } # end for loop_hour\ + }\ + \ + return($fc_trigger_stop);;\ +},\ +\ +fc0_trigger:fc0_trigger_stop.* {\ + # Setzen des Triggers für die aktuelle viertel Stunde\ + if ( ReadingsVal("$NAME","current_price",100) < ReadingsVal("$NAME","fc_trigger_price",0) ) {\ + return("on")\ + } else {\ + return("off")\ + }\ +},\ +\ +fc1_trigger_start:fc_trigger_price.* {\ + if (ReadingsVal("$NAME","fc1_0000_startsAt","null") ne "null") {\ + my $fc_trigger_price = ReadingsVal("$NAME","fc_trigger_price",0) /100;;\ +\ + # Ermitteln des nächsten Trigger Fensters\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = 0;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc1_%02d%02d_total",$loop_hour , $quarter*15),0);;\ +# print sprintf("fc1 Start %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_price."\n";;\ + if ( $fc_total < $fc_trigger_price ) {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15)) ;;\ + }\ + } # end $quarter\ + } # end for loop_hour\ + }\ + return("null");;\ +},\ +\ +fc1_trigger_stop:fc0_trigger_start.* {\ + # Ermitteln des nächsten Trigger Fensters\ + my $loop_hour;;\ + my $fc_trigger_price = ReadingsVal("$NAME","fc_trigger_price",0) /100;;\ +\ + my $fc_trigger_start = ReadingsVal("$NAME","fc1_trigger_start","null");;\ + my $fc_trigger_stop = $fc_trigger_start;;\ +\ + my ($fc_trigger_start_hour, $fc_trigger_start_quarter);;\ +\ + if ( $fc_trigger_start ne "null" ) {\ + $fc_trigger_start =~ /(\d\d):(\d\d)/;;\ + $fc_trigger_start_hour = $1;;\ + $fc_trigger_start_quarter = $2 / 15;;\ + my $fc_total = 0;;\ +\ + for ($loop_hour = $fc_trigger_start_hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = $fc_trigger_start_quarter;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc1_%02d%02d_total", $loop_hour, $quarter*15),0);;\ +# print sprintf("fc1 Stop %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_price."\n";;\ + if ( $fc_total < $fc_trigger_price ) {\ + $fc_trigger_stop = sprintf("%02d:%02d",$loop_hour, $quarter*15) ;;\ + } else {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15));;\ + }\ +\ + if ( $quarter == 3 ) { $fc_trigger_start_quarter = 0 }\ +\ + } # end $quarter\ + } # end for loop_hour\ + }\ + \ + return($fc_trigger_stop);;\ +},\ +\ +fc_trigger_max:fc_avg.* {\ + my $fc_avg = ReadingsVal("$NAME","fc_avg",0);;\ + my $fc_max = ReadingsVal("$NAME","fc_max",0);;\ +\ + # Berechnung eines Schwellwertes als täglichen Maximalpreises\ + my $price_level = round( ($fc_max - $fc_avg)/2 + $fc_avg , 0);;\ + \ +$price_level;;\ +},\ +\ +fc0_trigger_max_start:fc_trigger_max.* {\ + # Ermitteln des nächsten Trigger_max Fensters\ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\ + my $fc_trigger_max = ReadingsVal("$NAME","fc_trigger_max",0) /100;;\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = $hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc0_%02d%02d_total",$loop_hour , $quarter*15),0);;\ +# print sprintf("fc0 Start max %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_max."\n";;\ + if ( $fc_total > $fc_trigger_max ) {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15)) ;;\ + }\ + } # end $quarter\ + } # end for loop_hour\ +\ + return("null");;\ +},\ +\ +fc0_trigger_max_stop:fc0_trigger_max_start.* {\ + # Ermitteln des nächsten Trigger Fensters\ + my $fc = 0;;\ + my $fc_trigger_max = ReadingsVal("$NAME","fc_trigger_max",0) /100;;\ +\ + my $fc_trigger_max_start = ReadingsVal("$NAME","fc0_trigger_max_start","null");;\ + my $fc_trigger_max_stop = $fc_trigger_max_start;;\ +\ + my ($fc_trigger_max_start_hour, $fc_trigger_max_start_quarter);;\ +\ + if ( $fc_trigger_max_start ne "null" ) {\ + $fc_trigger_max_start =~ /(\d\d):(\d\d)/;;\ + $fc_trigger_max_start_hour = $1;;\ + $fc_trigger_max_start_quarter = $2 / 15;;\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = $fc_trigger_max_start_hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = $fc_trigger_max_start_quarter;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc%d_%02d%02d_total", $fc, $loop_hour, $quarter*15),0);;\ +# print sprintf("fc0 Stop max %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_max."\n";;\ + if ( $fc_total > $fc_trigger_max ) {\ + $fc_trigger_max_stop = sprintf("%02d:%02d",$loop_hour, $quarter*15) ;;\ + } else {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15));;\ + }\ +\ + if ( $quarter == 3 ) { $fc_trigger_max_start_quarter = 0 }\ +\ + } # end $quarter\ +\ + # wechsel zum nächsten Tag\ + if ( $loop_hour == 23 and $fc == 0 ) {\ + $fc = 1;;\ + $loop_hour = -1;;\ + }\ +\ + } # end for loop_hour\ + }\ + \ + return($fc_trigger_max_stop);;\ +},\ +\ +fc0_trigger_max:fc0_trigger_max_stop.* {\ +\ + # Setzen des maximum Triggers für die aktuelle Stunde\ + if ( ReadingsVal("$NAME","current_price",0) > ReadingsVal("$NAME","fc_trigger_max",0) ) {\ + return("on")\ + } else {\ + return("off")\ + }\ +},\ +\ +fc1_trigger_max_start:fc_trigger_max.* {\ + if (ReadingsVal("$NAME","fc1_0000_startsAt","null") ne "null") {\ + my $fc_trigger_max = ReadingsVal("$NAME","fc_trigger_max",0) /100;;\ +\ + # Ermitteln des nächsten Trigger Fensters\ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = 0;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc1_%02d%02d_total",$loop_hour , $quarter*15),0);;\ +# print sprintf("fc1 Start max %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_max."\n";;\ + if ( $fc_total > $fc_trigger_max ) {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15)) ;;\ + }\ + } # end $quarter\ + } # end for loop_hour\ + }\ + return("null");;\ +},\ +\ +fc1_trigger_max_stop:fc1_trigger_max_start.* {\ + # Ermitteln des nächsten Trigger Fensters\ + my $fc_trigger_max = ReadingsVal("$NAME","fc_trigger_max",0) /100;;\ +\ + my $fc_trigger_max_start = ReadingsVal("$NAME","fc1_trigger_max_start","null");;\ + my $fc_trigger_max_stop = $fc_trigger_max_start;;\ +\ + my ($fc_trigger_max_start_hour, $fc_trigger_max_start_quarter);;\ +\ + if ( $fc_trigger_max_start ne "null" ) {\ + $fc_trigger_max_start =~ /(\d\d):(\d\d)/;;\ + $fc_trigger_max_start_hour = $1;;\ + $fc_trigger_max_start_quarter = $2 / 15;;\ + my $fc_total = 0;;\ +\ + for (my $loop_hour = $fc_trigger_max_start_hour;; $loop_hour <= 23;; $loop_hour++) {\ + for (my $quarter = $fc_trigger_max_start_quarter;; $quarter <= 3;; $quarter++) {\ + $fc_total = ReadingsVal("$NAME",sprintf("fc1_%02d%02d_total", $loop_hour, $quarter*15),0);;\ +# print sprintf("fc1 Stop max %02d:%02d",$loop_hour, $quarter*15)." ".$fc_total." ".$fc_trigger_max."\n";;\ + if ( $fc_total > $fc_trigger_max ) {\ + $fc_trigger_max_stop = sprintf("%02d:%02d",$loop_hour, $quarter*15) ;;\ + } else {\ + return(sprintf("%02d:%02d",$loop_hour, $quarter*15));;\ + }\ +\ + if ( $quarter == 3 ) { $fc_trigger_max_start_quarter = 0 }\ +\ + } # end $quarter\ + } # end for loop_hour\ + }\ + \ + return($fc_trigger_max_stop);;\ +},\ +\ +total_cost_day:nodes_TIMESTAMP.* {\ +## Berechnung des Tages Wertes\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT CAST(SUM(VALUE) AS DECIMAL(8,2)) AS VALUE\ + FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND date(TIMESTAMP) = curdate() ;;") ;;\ +},\ +\ +total_cost_month:nodes_TIMESTAMP.* {\ +## Berechnung des monats Wertes\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT CAST(SUM(VALUE) AS DECIMAL(8,2)) AS VALUE\ + FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND YEAR(TIMESTAMP) = YEAR(curdate())\ + AND MONTH(TIMESTAMP) = MONTH(curdate()) ;;") ;;\ +},\ +\ +total_cost_year:nodes_TIMESTAMP.* {\ +## Berechnung des Jahres Wertes\ +::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + SELECT CAST(SUM(VALUE) AS DECIMAL(8,2)) AS VALUE\ + FROM history\ + WHERE DEVICE='".$NAME."'\ + AND READING='nodes_cost'\ + AND YEAR(TIMESTAMP) = YEAR(curdate()) ;;") ;;\ +},\ +\ +fc_DbLog:fc0_0000_total.* {\ +# Schreibt die redings fc*_hhmm_total als fc*_total mit passendem TIMESTAMP in die Datenbank\ +my ($timestamp,$date,$hour,$value,$loop_fc_next) = 5x0;;\ +\ +for (my $loop_fc = 0;; $loop_fc <= 1;; $loop_fc++) {\ + $loop_fc_next = $loop_fc +1;;\ + $date = ReadingsVal("$NAME","fc".$loop_fc."_0000_startsAt","null");;\ + if ($date ne "null" and $date ne "") {\ + $date =~ /([\d+-]+)/;; $date = $1 ;;\ + for (my $loop_hour = 0;; $loop_hour <= 23;; $loop_hour++) {\ + $hour = sprintf("%02d",$loop_hour);;\ + for (my $quarter = 0;; $quarter <= 3;; $quarter++) {\ + $timestamp = $date." ".$hour.":".($quarter*15).":00";;\ + $value = ReadingsVal("$NAME","fc".$loop_fc."_".$hour.sprintf("%02d",$quarter*15)."_total","null");;\ + ::CommandGet(undef, "LogDBRep_".$NAME."_SQL sqlCmdBlocking\ + INSERT INTO history (TIMESTAMP,DEVICE,TYPE,READING,VALUE)\ + VALUES('".$timestamp."','$NAME','Tibber','fc".$loop_fc."_total','".$value."')\ + ON DUPLICATE KEY UPDATE\ + VALUE='".$value."';;") ;;\ + }\ + }\ + if (ReadingsVal("$NAME","fc".$loop_fc."_0000_startsAt","null") eq ReadingsVal("$NAME","fc".$loop_fc_next."_0000_startsAt","null")) {\ + fhem("deletereading $NAME fc".$loop_fc_next."_.*");;\ + }\ + } else {\ + fhem("deletereading $NAME fc1_\\d.*");;\ + }\ +}\ +ReadingsTimestamp("$NAME","fc0_0000_startsAt","null");;\ +},\ +\ +next1_quarter:current_price.* {\ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\ + my $quarter = int($min / 15);; # aktuelle Viertelstunde 0–3\ + my $next_quarter = ($quarter + 1) % 4;; # nächste Viertelstunde\ + my $hour_offset = $hour;; # passen sich an wenn es über Mitternacht geht\ + my $fc = 0;; # fc0_ = # heute passen sich an wenn es über Mitternacht geht\ +\ + if ($quarter == 3) { # wenn wir in 23:45 sind nächste Viertelstunde gehört zur nächsten Stunde \ + $hour_offset++;;\ + if ($hour_offset >= 24) { \ + $hour_offset -= 24;;\ + $fc = 1;; # fc1_ = morgen\ + }\ + }\ +\ + return round(ReadingsVal($NAME,sprintf("fc%d_%02d%02d_total",$fc, $hour_offset, $next_quarter*15),0)*100,1);;\ + },\ +\ +next1_hour:current_price.* {\ + my $j;;\ + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);; $year += 1900;; $mon += 1 ;;\ + my $quarter = int($min / 15);; # aktuelle Viertelstunde 0–3\ + my $next_quarter = ($quarter + 1) % 4;; # nächste Viertelstunde\ + my $hour_offset = $hour;; # passt sich an wenn es über Mitternacht geht\ + my $fc = 0;; # fc0_ = # heute, passt sich an wenn es über Mitternacht geht\ +\ + if ($hour_offset == 23) { # wenn wir bei 23:00 sind gehört die nächste Stunde zum nächsten Tag\ + $hour_offset = 0;;\ + $fc = 1;; # fc1_ = morgen\ + }\ + for ($quarter = 0;; $quarter <= 3;; $quarter++) {\ + $j += ReadingsVal("$NAME",sprintf("fc%d_%02d%02d_total",$fc, $hour_offset, $quarter*15),0);;\ + }\ +\ + return round($j/4*100,1);; # Für die nächste Stunde wird der Durchschnitt ausgegeben\ + } +attr EVU_Tibber_connect15 verbose 0 +attr EVU_Tibber_connect15 ws_minInterval 54 +attr EVU_Tibber_connect15 ws_websocketURL wss:websocket-api.tibber.com:443/v1-beta/gql/subscriptions \ No newline at end of file