165 lines
5.5 KiB
YAML
165 lines
5.5 KiB
YAML
template: omie
|
|
products:
|
|
- brand: OMIE
|
|
description:
|
|
en: Iberian day-ahead market prices
|
|
de: Iberische Day-Ahead-Marktpreise
|
|
requirements:
|
|
evcc: ["skiptest"]
|
|
description:
|
|
en: "Day-ahead electricity prices from OMIE for Portugal and Spain. No API key is required."
|
|
de: "Day-Ahead-Strompreise von OMIE fuer Portugal und Spanien. Es ist kein API-Schluessel erforderlich."
|
|
group: price
|
|
countries: ["PT", "ES"]
|
|
params:
|
|
- name: country
|
|
description:
|
|
en: Country
|
|
de: Land
|
|
help:
|
|
en: Select whether to use the Portuguese or Spanish market price published by OMIE.
|
|
de: Waehlt aus, ob der von OMIE veroeffentlichte portugiesische oder spanische Marktpreis verwendet werden soll.
|
|
type: choice
|
|
choice: ["PT", "ES"]
|
|
default: PT
|
|
required: true
|
|
- preset: tariff-base
|
|
- preset: tariff-features
|
|
render: |
|
|
type: custom
|
|
{{ include "base" . }}
|
|
{{ include "features" . }}
|
|
forecast:
|
|
source: http
|
|
uri: https://www.omie.es/sites/default/files/dados/NUEVA_SECCION/INT_PBC_EV_H_ACUM.TXT
|
|
cache: 1h
|
|
regex: '(?ms)((?:^[0-9]{2}/[0-9]{2}/[0-9]{4};[^\r\n]*(?:\r?\n|$))+)'
|
|
default: ""
|
|
quote: true
|
|
jq: |
|
|
def market:
|
|
{{ if eq .country "PT" }}
|
|
{ code: "PT", priceIndex: 3 }
|
|
{{ else }}
|
|
{ code: "ES", priceIndex: 2 }
|
|
{{ end }};
|
|
|
|
def quarterHourSeconds: 900;
|
|
def dstStartMonth: 3;
|
|
def dstEndMonth: 10;
|
|
def standardOffsetSeconds: 3600;
|
|
def daylightOffsetSeconds: 7200;
|
|
def shortDayPeriodCount: 92;
|
|
def normalDayPeriodCount: 96;
|
|
def longDayPeriodCount: 100;
|
|
def minimumRequiredColumnCount: market.priceIndex + 1;
|
|
|
|
def pad2:
|
|
tostring | if length == 1 then "0" + . else . end;
|
|
|
|
def isoDate($y; $m; $d):
|
|
"\($y)-\($m | pad2)-\($d | pad2)";
|
|
|
|
def lastSunday($y; $m):
|
|
first([31, 30, 29, 28, 27, 26, 25][] | select(((isoDate($y; $m; .) + "T00:00:00Z") | fromdateiso8601 | gmtime | .[6]) == 0));
|
|
|
|
def daylightSavingSwitchDay($y; $m):
|
|
lastSunday($y; $m);
|
|
|
|
def isStandardOffsetMonth($m):
|
|
$m < dstStartMonth or $m > dstEndMonth;
|
|
|
|
def isDaylightOffsetMonth($m):
|
|
$m > dstStartMonth and $m < dstEndMonth;
|
|
|
|
def marketStartOffsetSeconds($y; $m; $d):
|
|
if isStandardOffsetMonth($m) then
|
|
standardOffsetSeconds
|
|
elif isDaylightOffsetMonth($m) then
|
|
daylightOffsetSeconds
|
|
elif $m == dstStartMonth then
|
|
if $d <= daylightSavingSwitchDay($y; dstStartMonth) then standardOffsetSeconds else daylightOffsetSeconds end
|
|
else
|
|
if $d <= daylightSavingSwitchDay($y; dstEndMonth) then daylightOffsetSeconds else standardOffsetSeconds end
|
|
end;
|
|
|
|
def marketStartUtc($y; $m; $d):
|
|
((isoDate($y; $m; $d) + "T00:00:00Z") | fromdateiso8601) - marketStartOffsetSeconds($y; $m; $d);
|
|
|
|
def isQuarterHourDay($day):
|
|
([ $day[].period ] | length) as $count
|
|
| select($count == shortDayPeriodCount or $count == normalDayPeriodCount or $count == longDayPeriodCount);
|
|
|
|
def parseDateParts:
|
|
split("/") | map(tonumber) | { d: .[0], m: .[1], y: .[2] };
|
|
|
|
def cutoffUtc:
|
|
((now / quarterHourSeconds) | floor) * quarterHourSeconds;
|
|
|
|
split("\n")
|
|
| map(gsub("\r"; ""))
|
|
| map(select(length > 0)) as $lines
|
|
| if ($lines | length) == 0 then
|
|
error("OMIE data rows not found")
|
|
elif (($lines[0] | split(";") | length) < minimumRequiredColumnCount) then
|
|
error("unexpected OMIE row layout")
|
|
else
|
|
($lines
|
|
| map(split(";"))
|
|
| map({
|
|
date: .[0],
|
|
dateParts: (.[0] | parseDateParts),
|
|
period: (.[1] | tonumber),
|
|
value: (.[(market.priceIndex)] | gsub(","; ".") | tonumber / 1000)
|
|
}
|
|
| . + .dateParts
|
|
| del(.dateParts)
|
|
)
|
|
) as $entries
|
|
| if ($entries | length) == 0 then
|
|
error("no OMIE rows parsed")
|
|
else
|
|
$entries
|
|
end
|
|
| ($entries
|
|
| sort_by(.date, .period)
|
|
| group_by(.date)
|
|
| map(isQuarterHourDay(.))
|
|
) as $quarterHourDays
|
|
| if ($quarterHourDays | length) == 0 then
|
|
error("no OMIE quarter-hour days parsed")
|
|
else
|
|
$quarterHourDays
|
|
end
|
|
| ($quarterHourDays
|
|
| all(
|
|
([.[].period] | sort) as $periods
|
|
| ($periods | length) as $count
|
|
| ($periods == [range(1; $count + 1)])
|
|
)
|
|
) as $validPeriods
|
|
| if ($validPeriods | not) then
|
|
error("unexpected OMIE period sequence")
|
|
else
|
|
($quarterHourDays
|
|
| add
|
|
| sort_by(.y, .m, .d, .period)
|
|
| map(
|
|
(marketStartUtc(.y; .m; .d) + ((.period - 1) * quarterHourSeconds)) as $start
|
|
| ($start + quarterHourSeconds) as $end
|
|
| select($end > cutoffUtc)
|
|
| {
|
|
start: ($start | todateiso8601),
|
|
end: ($end | todateiso8601),
|
|
value: .value
|
|
}
|
|
)
|
|
)
|
|
end
|
|
| if length == 0 then
|
|
error("no OMIE \(market.code) rates parsed")
|
|
else
|
|
.
|
|
end
|
|
| tostring
|
|
end
|