76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support

Begonnen von DS_Starter, 11 Februar 2024, 14:11:00

Vorheriges Thema - Nächstes Thema

ch.eick

Zitat von: TheTrumpeter am 13 März 2024, 10:00:27< snip >
Derzeit noch kaum, weil ich erst seit 2 Wochen den variablen Tarif habe.
Mit dem alten Tarif war's immer besser, den PV-Eigenverbrauch zu optimieren, d.h. der größte Verbraucher (Wärmepumpe für Heizung und Warmwasser) ist ohnehin nur tagsüber gelaufen.
Mit dem neuen Tarif könnte es Situationen geben, in denen es günstiger wäre den Verbrauch zu einem Zeitpunkt eines niedrigen Bezugstarifs trotz fehlender PV-Abdeckung zu legen. Mit der Visualisierung könnte ich das zumindest mal händisch machen.
Das ist bereits im EVU_Tibber Device dargestellt, es gibt SVGs für fc0 und fc1, sowie ein Zeitfenster mit Trigger Preis. Mit dem Trigger reagierst Du in einem DOIF direkt, oder verwendest die Uhrzeiten zur Planung. Es gibt auch ein Fenster für das Maximum, um dort keine Großverbraucher zu betreiben, bzw bewust den Speicher zu verwenden.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Dracolein

Expertise gewünscht zu folgendem Problemchen, was ich über den Winter nicht so recht in den Griff bekommen habe:

Die Steckdose eines Luftentfeuchters soll bei genügend PV-Überschuss UND Luftfeuchtigkeit größer 65% eingeschaltet und bei zu wenig Überschuss ABgeschaltet werden.

Ist die Luftfeuchte jedoch größer 67%, soll die Steckdose unabhängig vorhandener PV-Leistung einschalten und bei Unterschreitung kleiner Y wieder abschalten. Ich vermute meine regulären Ausdrücke sind weiterhin fehlerbehaftet? So siehts bisher aus.
Mein Problem: ich beobachte ständig niedrige Luftfeuchtigkeit und trotzdem ist die Steckdose eingeschaltet.

Zitatattr PVVorschau consumer06 ShellyPlug1
type=other
power=300
mode=can
on=on
off=off
pcurr=power:W
swstate=state:on:off
mintime=SunPath
locktime=900
notbefore=07
notafter=22
icon=Ventilator_fett
spignorecond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[7-9]|[7-9][0-9]
swoncond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[5-9]|[5-9][0-9]

100|6[7-9]|[7-9][0-9] = true, wenn größer "67", oder?
Raspberry Pi 4 mit FHEM; FTUI Dashboard auf Asus 15,6" VT168H Touchscreen; ZigBee mit ConBee2 USB-Stick; div. Shelly 2.5; integr. Gaszähler mit ESP8266 & ESPEasy;

DS_Starter

ZitatDie Steckdose eines Luftentfeuchters soll bei genügend PV-Überschuss UND Luftfeuchtigkeit größer 65% eingeschaltet und bei zu wenig Überschuss ABgeschaltet werden.
Da dieses Verfahren zw. 07-22 laufen soll, bietet sich an zunächst die Schlüssel power=0 und mintime=900 zu setzen. Für die Einplanung wäre evtl. auch mode=must sinnvoll.
Dann die Schlüssel spignorecond, swoncond löschen und dafür interruptable einsetzen:

interruptable=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[7-9]|[7-9][0-9]

Der Regex sollte soweit passen. Kann man sicher noch verbessern, habe mir jetzt aber auf die Schnelle nicht näher angeschaut, nur getestet auf https://regex101.com.
Die Seite bietet sich an um seine Regex zu testen und zu optimieren.

LG



ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

300P

Zitat von: DS_Starter am 13 März 2024, 09:43:59Neben der visuellen Aufbereitung könnten sich Synergien bei der Einplanung von Cosumern höherer Leistung ergeben wenn man solche Daten zur Verfügung hat und berücksichtigen kann.

Wieder ein spannendes Thema.
Wie verarbeitet ihr diese Daten zur Zeit? Mal abgesehen von dem reinen Informationsaspekt.



Hier (m)eine Version die (ohne/mit) SQL auskommen kann.


Sinn des Programmes:     
Bereitstellung der aktuellen EVU-Bezugs-Preise.
Preise abholen in Höhe von x.yyyyy Euro/kWh für den aktuellen Tag und ab 13:00 Uhr beginnend auch für den nächsten Tag (stündlich jeweils ab 00:00 ... 23:00 Uhr)

Holt (derzeitig) alle 30 Sekunden die aktuell bereitgestellten Daten (API von der Tibber-Website) ab.
Bei Tibber ist es notwendig einen laufenden Vertrag um die "Echt"-Daten abzuholen.
->>Ansonsten geht es nur über einen Dummy-Zugang der in schwedischen Kronen (SEK) läuft.

Zusätzlich werden die noch Doif-Module "diTibberDaten" und passender Code in 99_myUtils benötigt.

defmod myTibber HTTPMOD https://api.tibber.com/v1-beta/gql 30
attr myTibber DbLogExclude .*.    (somit dann ohne DBLog)
attr myTibber DbLogInclude Strompreis,BatteryCharge.*,TomorrowTotal
attr myTibber alignTime 00:01


attr myTibber comment _homes_01 \
############comment################\
DEMO-Token :   5K4MVS-OjfWhK_4yrjOlFe1F6kJXPVf7eQYggo8ebAE\
############comment################\
\
attr myTibber enableControlSet 1
attr myTibber event-on-change-reading Strompreis, TodayAverage, TodayMin, BatteryCharge.*, TomorrowTotal
attr myTibber group Tibber
attr myTibber reading1JSON data_viewer_homes_01_currentSubscription_priceInfo_current_total
attr myTibber reading1Name Strompreis
attr myTibber reading1OExpr $val
attr myTibber reading2-1Name Datum
attr myTibber reading2-2Name Uhrzeit
attr myTibber reading2JSON data_viewer_homes_01_currentSubscription_priceInfo_current_startsAt
attr myTibber reading2Regex startsAt":"([\d+-]+)T(\d\d:\d\d)
attr myTibber replacement1Mode text
attr myTibber replacement1Regex %%Token%%
attr myTibber replacement1Value >hier den eigenen Token oder den Dummy-Token für SEK einsetzen<
attr myTibber requestData { "query": "{viewer {homes {currentSubscription {priceInfo {current {total energy tax startsAt} today {total energy tax startsAt } tomorrow {total energy tax startsAt }}}}}}" }
attr myTibber requestHeader1 Content-Type: application/json
attr myTibber requestHeader2 Authorization: Bearer %%Token%%
attr myTibber room 025_Tibber
attr myTibber showBody 1
attr myTibber showError 1
attr myTibber stateFormat Je nachdem BatteryChargeProcess (0-off/1=on) wird das berechnete Zeitfenster zum Laden genutzt. (BatteryChargeStartAt Uhr bis BatteryChargeStartAtEnd:00 Uhr / BatteryChargeUpTime Stunden)
attr myTibber userReadings TodayAverage {use List::Util qw(sum);;;;\
my @Preise = split /\|/, ReadingsVal("myTibber","TodayTotal",0.25);;;; return (sum(@Preise) / @Preise);;;; },\
TomorrowAverage {use List::Util qw(sum);;;;\
my @Preise = split /\|/, ReadingsVal("myTibber","TomorrowTotal",0.25);;;; return $Preise[0] eq "NV" ? "NV" : (sum(@Preise) / @Preise);;;; },\
TodayMin {use List::Util qw(min);;;; my @Preise = split /\|/, ReadingsVal("myTibber","TodayTotal",0.25);;;; return (min @Preise);;;; },\
TomorrowMin {use List::Util qw(min);;;; my @Preise = split /\|/, ReadingsVal("myTibber","TomorrowTotal",0.25);;;; return (min @Preise);;;; },\
BatteryChargeGriduntil;;;;\
BatteryChargeStartAt;;;;\
BatteryChargeStartAtEnd;;;;\
BatteryChargeStartMinIndex;;;;\
BatteryChargeUpMinTime;;;;\
BatteryChargeUpTime;;;;\
BatteryChargeUpTimeDuration;;;;\
BatteryChargeProcess;;;;\
MinTibberStartMinIndex;;;;\
MinTibberStartMinPreis;;;;\
MinTibberStartZeitfenster;;;;
attr myTibber verbose 3

setstate myTibber Je nachdem 0 (0-off/1=on) wird das berechnete Zeitfenster zum Laden genutzt. (04:00 Uhr bis 6:00 Uhr / 2 Stunden)
setstate myTibber 2024-01-24 19:32:50 BatteryChargeGriduntil 85
setstate myTibber 2024-03-12 23:41:39 BatteryChargeProcess 0
setstate myTibber 2024-03-12 18:27:44 BatteryChargeStartAt 04:00
setstate myTibber 2024-03-12 18:28:07 BatteryChargeStartAtEnd 6
setstate myTibber 2024-03-12 16:14:00 BatteryChargeStartMinIndex 0
setstate myTibber 2024-03-03 19:18:09 BatteryChargeUpMinTime 17
setstate myTibber 2024-02-05 12:44:38 BatteryChargeUpTime 2
setstate myTibber 2024-03-03 19:18:44 BatteryChargeUpTimeDuration 21
setstate myTibber 2024-03-13 10:39:00 Datum 2024-03-13
setstate myTibber 2024-03-12 10:22:02 LAST_ERROR read from https://api.tibber.com:443 timed out
setstate myTibber 2024-03-12 16:14:00 MinTibberStartMinIndex 0
setstate myTibber 2024-03-12 16:14:00 MinTibberStartMinPreis 0.4434
setstate myTibber 2024-03-12 16:14:00 MinTibberStartZeitfenster 17:16
setstate myTibber 2024-03-13 10:39:00 Strompreis 0.2217
setstate myTibber 2024-03-13 10:39:00 TodayAverage 0.2217
setstate myTibber 2024-03-13 10:39:00 TodayMin 0.2217
setstate myTibber 2024-03-13 00:01:00 TodayTotal 0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|0.2217|
setstate myTibber 2024-03-13 10:39:00 TomorrowAverage 999999
setstate myTibber 2024-03-13 10:39:00 TomorrowMin 999999
setstate myTibber 2024-03-13 00:01:00 TomorrowTotal 999999
setstate myTibber 2024-03-13 10:39:00 Uhrzeit 10:00


Die zugehörige DOIF

defmod diTibberDaten DOIF ([00:01]) (set myTibber reread) ({TibberDaten()})\
DOELSEIF (([12:00-12:15, +0:01]) and [myTibber:TomorrowTotal] ne 999999) (setreading myTibber TomorrowTotal 999999)\
DOELSEIF (([13:00-15:15, +0:05] or [15:15-23:40, +0:15]) and [myTibber:TomorrowTotal] eq 999999) (set myTibber reread) ({TibberDaten()})\
DOELSEIF ({MinStromTime(16,2,24)})\
DOELSEIF ( ([13:00-15:15, +0:05]) and [myTibber:TomorrowTotal] eq "999999") ([{MinStromTime(16,2,24)}])\

attr diTibberDaten do always
attr diTibberDaten group Tibber
attr diTibberDaten room 025_Tibber,Strompreis->Dynamisch
attr diTibberDaten verbose 3

setstate diTibberDaten cmd_1
setstate diTibberDaten 2024-03-13 00:01:00 cmd 1.2
setstate diTibberDaten 2024-03-13 00:01:00 cmd_event timer_1
setstate diTibberDaten 2024-03-13 00:01:00 cmd_nr 1
setstate diTibberDaten 2024-03-13 00:01:00 cmd_seqnr 2
setstate diTibberDaten 2024-03-11 09:47:41 mode enabled
setstate diTibberDaten 2024-03-13 00:01:00 state cmd_1
setstate diTibberDaten 2024-03-13 00:01:00 timer_01_c01 14.03.2024 00:01:00
setstate diTibberDaten 2024-03-12 12:15:00 timer_02_c02 13.03.2024 12:00:00
setstate diTibberDaten 2024-03-12 12:15:00 timer_03_c02 13.03.2024 12:15:00
setstate diTibberDaten 2024-03-12 15:15:00 timer_05_c03 13.03.2024 13:00:00
setstate diTibberDaten 2024-03-12 15:15:00 timer_06_c03 13.03.2024 15:15:00
setstate diTibberDaten 2024-03-12 23:40:00 timer_08_c03 13.03.2024 15:15:00
setstate diTibberDaten 2024-03-12 23:40:00 timer_09_c03 13.03.2024 23:40:00
setstate diTibberDaten 2024-03-12 15:15:00 timer_11_c05 13.03.2024 13:00:00
setstate diTibberDaten 2024-03-12 15:15:00 timer_12_c05 13.03.2024 15:15:00




und hier die zugehörige 99_myUtils in der aktuellen Test-Version.

##############################################
# $Id: myUtils.pm 21509 2024-02-09 16:30:00Z 300P $
# Status 2024-02-09 16:30
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.
# Hinweis :
# diverse Anregungen und Programmteile genutzt von https://www.juergenstechnikwelt.de/smarthome-2/tibber-in-fhem-einbinden-beste-zeiten-fuer-niedrige-strompreise-ermitteln/Original
#

package main;

use strict;
use warnings;
use List::MoreUtils qw{
true first_index
};
use List::Util qw( sum );


sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.
sub SMABatteryChargewithTibber()
{
#########################################################################################################################################
# Aufruf erfolgt über Notify "N.PV.TotalConsumption.Dum.Energy" ca. alle 15 sekunden
# Voraussetzung:
# Device myTibber muss installiert sein
# zugehörige sub MinTibberZeitfenster muss in myUtils vorhanden sein
# zugehörige sub TibberDaten muss in myUtils vorhanden sein
# zugehörige sub MinStromTime muss in myUtils vorhanden sein
# myTibber ->>> Aus dem Array mit den Strompreisen des definierten Zeitfenster wird der Zeitraum mit dem niedrigsten Preis ermittelt
# Parameter1: Preisarray
# Parameter2: Laufzeit in Stunden
# Return: Der StartIndex innerhalb der übergebenen Strompreise
# Aufruf erfolgt über ein existierendes Notify bei Berechnung der aktuellen Energie- und PV-Datenstatistik im ca. 15 Sekundentakt
#########################################################################################################################################


  ###############################################################################
  # Gleich halten wie in sub SMABatteryChargewithTibberinMinTibberZeitfenster
  # 2023-02-03 17:28
  ###############################################################################
  my $Battery_Device = "BatteryDummy"; # aus Modul Solarforecast-Batteriedummy
  my $Battery_Device_rated_capacity = "bat_rated_capacity"; ### aktuell hinterlegter Batteriekapazitätswert
 
  my $Battery_Current_rated_capacity = ReadingsNum( $Battery_Device, $Battery_Device_rated_capacity, 0);; ### aktuell hinterlegter Batteriekapazitätswert

  my $Forecast_Device = "Forecast"; # aus Modul Solarforecast
  my $Forecast_Device_StatusCharge = "Current_BatCharge"; ### aktuell hinterlegter Batterie SOC-Wert
  my $Forecast_Device_Tomorrow_PVforecast = "Tomorrow_PVforecast"; ### aktuell hinterlegter Forecast
  my $Forecast_Device_RestOfDayPVforecast = "RestOfDayPVforecast"; ### aktuell hinterlegt
 
  my $Forecast_Current_BatCharge = ReadingsNum( $Forecast_Device, $Forecast_Device_StatusCharge, 0);
  # Ladestatus in Summe von (allen) vorhandenen Batterien
  my $Forecast_Current_Tomorrow_PVforecast = ReadingsNum( $Forecast_Device, $Forecast_Device_Tomorrow_PVforecast, 0);
  # PV-Ertrag am nächsten Tag
  my $Forecast_Current_RestOfDayPVforecast = ReadingsNum( $Forecast_Device, $Forecast_Device_RestOfDayPVforecast, 0);
  # restlicher PV-Ertrag am heutigen Tag Tag
 

  my $Tibber_Device = "myTibber";
  my $Tibber_Device_BatteryChargeGriduntil = "BatteryChargeGriduntil"; ### Batterie SOC-Wert Ladesteuerung - Reading in myTibber
  #    Griduntil = jewiels aktueller SOC-Wert bis zu dem weiter geladen werden sollte( 85 %)
  my $Tibber_Device_BatteryChargeUpMinTime = "BatteryChargeUpMinTime"; ### Uhrzeit ab wann frühestens geladen werden soll - Reading in myTibber
  #    MinTime = MinHour: FrühesterStart (Beispiel: 15 für 15:00 Uhr),
  my $Tibber_Device_BatteryChargeStartMinIndex = "BatteryChargeStartMinIndex"; ### aktueller Zeitindex in Stunden 0-24 bis zum Ladezeitstartzeitpunkt - Reading in myTibber
  #    StartMinIndex = Anzahl Stunden nach MinTime
  my $Tibber_Device_BatteryChargeStartAt = "BatteryChargeStartAt";
  #    StartAt = um wieviel Uhr soll gestartet werden - Reading in myTibber
  my $Tibber_Device_BatteryChargeStartAtEnd = "BatteryChargeStartAtEnd";
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber
  my $Tibber_Device_BatteryChargeUpTime = "BatteryChargeUpTime"; ### Ladungsdauer in Stunden - Reading in myTibber
  #    UpTime = Laufzeit: Laufzeit in Stunden, (Da es nur Stundenpreise gibt, kann die Laufzeit immer auf Stunden aufgerundet werden)
  my $Tibber_Device_BatteryChargeUpTimeDuration = "BatteryChargeUpTimeDuration"; ### Zeitdauer der Preisprüfung - Reading in myTibber
  #    UpTimeDuration = Zeitdauer der Preisprüfung
  my $Tibber_Device_BatteryChargeProcess = "BatteryChargeProcess"; ### Ladung ein = 1 - Ladung per Modul aus = 0  - Reading in myTibber

  ###############################################################################
  # Gleich halten wie in sub SMABatteryChargewithTibberinMinTibberZeitfenster
  # 2023-02-04 18:28
  ###############################################################################

 
  my $Tibber_BatteryChargeGriduntil = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeGriduntil, 0);
  # hinterlegte max. Grenze Batterie SOC-Wert (85%) für die Tibber-Steuerung
  my $Tibber_BatteryChargeUpMinTime = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpMinTime, 0);
  ### später als z.B. 14 Uhr wegen Bekanntgabe der Tommorrow-Werte
  my $Tibber_BatteryChargeStartAt = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartAt, 0);
  #    StartAt = um wieviel Uhr soll gestartet werden - Reading in myTibber
  my $Tibber_BatteryChargeStartMinIndex = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartMinIndex, 0);
  ### aktueller Zeitindex in Stunden 0-24 bis zum Ladezeitstartzeitpunkt
  my $Tibber_BatteryChargeUpTime = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpTime, 0);
  ### UpTime = Laufzeit: Laufzeit in Stunden
# my $Tibber_BatteryChargeStartAtEnd = $Tibber_BatteryChargeStartAt + $Tibber_BatteryChargeStartMinIndex + $Tibber_BatteryChargeUpTime;
  #    StartAtEnd = Neuberechnung um wieviel Uhr soll Ladung beendet werden
  #if ($Tibber_BatteryChargeStartAtEnd > "23")  # ist Lade-Endzeit später als 23 Uhr ??? dann Abzug von 24
  #{
  #  $Tibber_BatteryChargeStartAtEnd = ($Tibber_BatteryChargeStartAtEnd - "24");
  #}
#  fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeStartAtEnd $Tibber_BatteryChargeStartAtEnd");     
  #    StartAtEnd ->> aktuell neu berechnetes Reading in myTibber setzen
  #my $Tibber_BatteryChargeStartAtEnd = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartAtEnd, 0);
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber wird zyklisch neu gesetz
  # nur in anderem SUB ->>> fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeStartAtEnd $Tibber_BatteryChargeStartAtEnd");     
  #    StartAtEnd ->> aktuell neu berechnetes Reading in myTibber setzen
  my $Tibber_BatteryChargeStartAtEnd = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartAtEnd, 0);
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber zyklisch neu setzen
  my $Tibber_BatteryChargeProcess = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeProcess, 0);
  #    Process = soll per Tibber geladen werden ?? - Reading in myTibber
  my $Tibber_BatteryChargeUpTimeDuration = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpTimeDuration, 0);
  ### UpTimeDuration = Zeitdauer der Preisprüfung
 

  ###############################################################
  # bis hier gleich halten wie in sub SMABatteryChargewithTibber
  ###############################################################


  my ($sec,$min,$hour,$mday,$mon,$year) = localtime; #??????????
   
  ################################################################
  # Laden beenden bzw. gar nicht nicht anfangen
  # denn die Batterie ist mehr geladen als vorgegeben
  ################################################################
 
  if ( $Forecast_Current_BatCharge > ($Tibber_BatteryChargeGriduntil + 5))  ### aktueller Batterieladestatus aus Forecast SOC > Vorgabewert + 5 %  ?? wenn ja Ladung beenden und zurück
  {
    # Ladestatus in Summe von (allen) vorhandenen Batterien groesser als  XY ??  dann Ende
    Log3 undef, 5, "SMABatteryChargewithTibber : 1001  SOC : $Forecast_Current_BatCharge ist >= Tibber_BatteryChargeGriduntil : $Tibber_BatteryChargeGriduntil";
    Log3 undef, 5, "SMABatteryChargewithTibber : 1001  SOC : Ende Battery-Ladezyklus : $year-$mon-$mday  $hour:$min:$sec";
    Log3 undef, 5, "SMABatteryChargewithTibber : 1001  SOC : Ende der Batterieladung_weil voll genug";
    SMABatteryChargeOFF();
  return;  # ???? evtl. irgenwann mal noch Fehlermitteilung zurück mitgeben
  }

  ##############################
  # evtl. noch .....ist die Beladung schon eingeschaltet ???? Reading ????
  # evtl. zukünftig prüfen ist es Sommer oder Winter (Monat >10 oder < 3) dann wird mit hoher wahrscheinlichkeit Strom für die Battery benötigt
  ##############################

  ###############################################################
  # prüfen ob aktueller Rest-PVForecast + tomorrowForecast für 24 Stunden (bis morgen xy Uhr)ausreicht oder nicht - dann keine Ladung
  ###############################################################
  my $tempStundenverbrauch = "850"; # allgemeiner Durchschnittsverbrauch pro Stunde (evtl. noch irgenwoher ableiten oder errechnen)
  my $tempStundenanzahl = ( (24 - $hour) + "18"); # Verbrauchszeitraum bis Morgen 18 Uhr berücsichtigen (evtl. noch irgenwoher ableiten oder errechnen)
  my $tempVerbrauchsbedarf = ($tempStundenanzahl * $tempStundenverbrauch); # allgemeiner Durchschnittsverbrauch pro Stunde mal Zeitraum bis tempstundenanzahl Uhr
 
  Log3 undef, 4, "SMABatteryChargewithTibber : xx2 Es ist $hour Uhr - Verbrauchsprognose bis Morgen um 14 Uhr ist $tempVerbrauchsbedarf";
  Log3 undef, 4, "SMABatteryChargewithTibber : xx3 Heute noch $Forecast_Current_RestOfDayPVforecast PV-Ertrag";
  Log3 undef, 4, "SMABatteryChargewithTibber : xx4 Morgen noch $Forecast_Current_Tomorrow_PVforecast PV-Ertrag";
  Log3 undef, 4, "SMABatteryChargewithTibber : xx5 BatteryCapacity $Battery_Current_rated_capacity   $Forecast_Current_Tomorrow_PVforecast + $Forecast_Current_RestOfDayPVforecast ";
 
  if (( $hour >= "14") and ($hour <= "24" ))  # ab 14 Uhr und heute
  {
    my $temp001 = $Forecast_Current_Tomorrow_PVforecast + $Forecast_Current_RestOfDayPVforecast + ($Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge / 100);
    my $tempbatterieladung = ($Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge / 100);
    Log3 undef, 4, "SMABatteryChargewithTibber : xx5a Forecastrestoftoday + Forecasttomorrow + Batterieladung temp001 = $temp001 = $Forecast_Current_Tomorrow_PVforecast + $Forecast_Current_RestOfDayPVforecast + $Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge : 100";
    Log3 undef, 4, "SMABatteryChargewithTibber : xx5b $Forecast_Current_BatCharge  Batterieladung $tempbatterieladung ";

    if ( $temp001 > $tempVerbrauchsbedarf ) 
    # PV-Ertrag  zu  Verbrauch sollte für bis morgen xy Uhr reichen
    {
      Log3 undef, 4, "SMABatteryChargewithTibber : xx6 Batterieladung + Erwarteter PV-Ertrag von Heute (Rest) und Morgen wird hoch genug sein - Kein EVU-Strombezug notwendig";
      Log3 undef, 4, "SMABatteryChargewithTibber : xx6a  Tibber_Device_BatteryChargeProcess = $Tibber_Device_BatteryChargeProcess   Tibber_BatteryChargeProcess = $Tibber_BatteryChargeProcess";
     
      if ( $Tibber_BatteryChargeProcess == "1" )
      {
      #    Tibber-Ladung aussetzen - Reading wird in myTibber auf OFF gesetzt
      $Tibber_BatteryChargeProcess = 0;
      fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeProcess $Tibber_BatteryChargeProcess");
      Log3 undef, 1, "SMABatteryChargewithTibber : xx6b  SET Tibber_Device_BatteryChargeProcess OFF = $Tibber_Device_BatteryChargeProcess   Tibber_BatteryChargeProcess $Tibber_BatteryChargeProcess";
      #return; # zu erwartende heutige (Rest) und morgige Solarleistung beträgt weit mehr mehr als genug
      }
    }

    if ( $temp001 <= $tempVerbrauchsbedarf ) 
    # PV-Ertrag  zu  Verbrauch sollte für bis morgen xy Uhr nicht reichen
    {
      Log3 undef, 4, "SMABatteryChargewithTibber : xx6d Erwarteter PV-Ertrag von Heute (Rest) und Morgen wird wohl NICHT hoch genug sein - EVU-Strombezug notwendig";

      if ($Tibber_BatteryChargeProcess == "0")
      {
      #    Tibber-Ladung  - Reading wird in myTibber auf ON gesetzt
      $Tibber_BatteryChargeProcess = "1";
      fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeProcess $Tibber_BatteryChargeProcess");
      Log3 undef, 1, "SMABatteryChargewithTibber : xx6c  14 bis 24 Uhr - SET Tibber_Device_BatteryChargeProcess ON = $Tibber_Device_BatteryChargeProcess    Tibber_BatteryChargeProcess $Tibber_BatteryChargeProcess";
      }     
    }
  }
 
  if (( $hour >= "0") and ($hour < "14"))   # nachts nach Mitternach schauen ob sich daran noch was ändert bis heute 14 Uhr (mittags)
  {
    $tempStundenanzahl = ( (14 - $hour)); # Verbrauchszeitraum bis heute 14 Uhr !!!!!
    $tempVerbrauchsbedarf = ($tempStundenanzahl * $tempStundenverbrauch); # allgemeiner Durchschnittsverbrauch pro Stunde mal Zeitraum bis 14 Uhr

    my $temp001 =  $Forecast_Current_RestOfDayPVforecast + ($Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge / 100);  # nur Heute betrachten !!!
    my $tempbatterieladung = ($Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge / 100);
    Log3 undef, 4, "SMABatteryChargewithTibber : xx7a Forecastrestoftoday + Batterieladung temp001 = $temp001 = $Forecast_Current_RestOfDayPVforecast + $Battery_Current_rated_capacity * 1000 * $Forecast_Current_BatCharge : 100";
    Log3 undef, 4, "SMABatteryChargewithTibber : xx7b $Forecast_Current_BatCharge  Batterieladung $tempbatterieladung ";


    if ( $temp001 >  $tempVerbrauchsbedarf)   
    # PV-Ertrag sollte für bis heute (14)  reichen
    {

      if ($Tibber_BatteryChargeProcess == "1")
      {
      #    Tibber-Ladung  - Reading wird in myTibber auf OFF gesetzt
      $Tibber_BatteryChargeProcess = "0";
      fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeProcess $Tibber_BatteryChargeProcess");
      Log3 undef, 1, "SMABatteryChargewithTibber : xx8  0 bis 14 Uhr - SET Tibber_Device_BatteryChargeProcess OFF = $Tibber_Device_BatteryChargeProcess";
      #return; # zu erwartende heutige (Rest) Solarleistung beträgt weit mehr mehr als genug
      }
     
    Log3 undef, 4, "SMABatteryChargewithTibber : xx8a Erwarteter PV-Ertrag von Heute bis 14 Uhr wird hoch genug sein - Kein EVU-Strombezug notwendig";
    #return; # zu erwartende heutige Solarleistung bis 14 Uhr beträgt mehr als genug
    }
     
    if ( $temp001 <=  $tempVerbrauchsbedarf)   
    # PV-Ertrag sollte für bis heute (14) nicht reichen
    {
    Log3 undef, 4, "SMABatteryChargewithTibber : xx9 Erwarteter PV-Ertrag von Heute bis 14 Uhr wird NICHT hoch genug sein - EVU-Strombezug ist notwendig";

      if ($Tibber_BatteryChargeProcess == "0")
      {
      #    Tibber-Ladung  - Reading wird in myTibber auf ON gesetzt
      $Tibber_BatteryChargeProcess = "1";
      fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeProcess $Tibber_BatteryChargeProcess");
      Log3 undef, 1, "SMABatteryChargewithTibber : xx9a  00 bis 14 Uhr - SET Tibber_Device_BatteryChargeProcess ON = $Tibber_Device_BatteryChargeProcess";
      }
      Log3 undef, 4, "SMABatteryChargewithTibber : xx10 Erwarteter PV-Ertrag von Heute bis 14 Uhr (Rest)  wird wohl NICHT hoch genug sein - EVU-Strombezug notwendig";
    }
  }

###############################################################
# Ende
# evtl. jetzt erst mal prüfen ob aktueller PVForecast + aktueller BatteryChargestatus für die nächsten 24 Stunden bereits ausreicht oder nicht
###############################################################

############################################################# 
  if ( $Tibber_BatteryChargeProcess eq "0" )
  {
    Log3 undef, 5, "SMABatteryChargewithTibber : 6789 Tibber_BatteryChargeProcess ist $Tibber_BatteryChargeProcess  => kein Laden / Modulaufruf errechnet / gewünscht";
    return;
  }
#############################################################




 
    if ($Forecast_Current_BatCharge < $Tibber_BatteryChargeGriduntil) #### aktueller Batterieladestatus unterhalb Vorgabewert ???
    {
      if ($hour >= ($Tibber_BatteryChargeUpMinTime))
      {
        if ($hour <= "24")
        {
          ##############
          Log3 undef, 5, "SMABatteryChargewithTibber : 1002  SOC : $Forecast_Current_BatCharge < $Tibber_BatteryChargeGriduntil- hour aktuell (14-24) : $hour ist kleiner als 24 ....$Tibber_BatteryChargeUpMinTime";
          Log3 undef, 5, "SMABatteryChargewithTibber : 1002  SOC : Jetzt wird wohl HEUTE PLANMÄßIG geladen wenn .......";
          # unter 85 %     AND     Uhrzeit > Wert     AND  Uhrzeit max 24 Uhr
          if ($hour >= $Tibber_BatteryChargeStartAt)
          {
          Log3 undef, 5, "SMABatteryChargewithTibber : 1002a  Jetzt ist es spät genug : Uhrzeit $hour  BatteryChargeStartAt : $Tibber_BatteryChargeStartAt BatteryChargeUpTime : $Tibber_BatteryChargeUpTime    BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAtEnd";
            if ($hour < $Tibber_BatteryChargeStartAtEnd)
            {
                my $tempdaten = (24 - $hour)*(800/19600*100) + (19600*$Forecast_Current_BatCharge/100);
#              if ($Forecast_Current_BatCharge <= ($Forecast_Current_BatCharge + $tempdaten)
#              {
                Log3 undef, 5, "SMABatteryChargewithTibber : 1002a1  Jetzt ist es wohl wirklich spät genug : Uhrzeit $hour  Forecast_Current_BatCharge $Forecast_Current_BatCharge ist kleiner als $tempdaten";
                SMABatteryChargeON();
                Log3 undef, 5, "SMABatteryChargewithTibber : 1002b  Jetzt wird HEUTE PLANMÄßIG geladen : Uhrzeit $hour  BatteryChargeStartAt + BatteryChargeUpTime ist <= BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAt + $Tibber_BatteryChargeUpTime = $Tibber_BatteryChargeStartAtEnd";
#              }
            }
            else
            {
              SMABatteryChargeOFF();
          Log3 undef, 5, "SMABatteryChargewithTibber : 1002c  HEUTE ABEND wird NICHT mehr PLANMÄßIG geladen : Uhrzeit $hour  BatteryChargeStartAt : $Tibber_BatteryChargeStartAt BatteryChargeUpTime : $Tibber_BatteryChargeUpTime    BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAtEnd";
          Log3 undef, 5, "SMABatteryChargewithTibber : 1002d  .........wäre HEUTE PLANMÄßIG geladen worden aber : Uhrzeit $hour  BatteryChargeStartAt + BatteryChargeUpTime ist <= BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAt + $Tibber_BatteryChargeUpTime = $Tibber_BatteryChargeStartAtEnd";
            }
#            return; # raus ?
          }
        }
      }
      if ($hour < ($Tibber_BatteryChargeUpMinTime))
      {
        if ($hour >= "00")  # also beide Fragen ähnlich bzw. gleich ->> zwischen 00:00 Uhr bis 13:59 Uhr  (< 14 Uhr)
        {
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003  SOC : $Forecast_Current_BatCharge < $Tibber_BatteryChargeGriduntil- hour (00-13) : $hour : ist kleiner als $Tibber_BatteryChargeUpMinTime";
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003  SOC : Jetzt wird wohl heute Nacht / MORGEN PLANMÄßIG geladen wenn .......";
          # unter 85 %     AND  Uhrzeit kleiner (14) Uhr     AND     Uhrzeit > Startuhrzeit (?? und wenn vor 23 Uhr gestartet ??? unklar)
          if ($hour >= $Tibber_BatteryChargeStartAt)
          {
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003a  Jetzt ist es wohl spät genug zum Laden : Uhrzeit $hour  BatteryChargeStartAt : $Tibber_BatteryChargeStartAt BatteryChargeUpTime : $Tibber_BatteryChargeUpTime   BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAtEnd";
            if ($hour < $Tibber_BatteryChargeStartAtEnd) # weiter laden (???? was wenn gestartet am Vortag ???)
            {
              SMABatteryChargeON();
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003b  Jetzt wird ab sofort HEUTE PLANMÄßIG geladen : Uhrzeit $hour  BatteryChargeStartAt : $Tibber_BatteryChargeStartAt BatteryChargeUpTime : $Tibber_BatteryChargeUpTime   BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAtEnd";
            }
            else
            {
              SMABatteryChargeOFF();  # laden jetzt sofort zeitnah beenden
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003c  HEUTE NACHT bzw. am MORGEN wird NICHT mehr PLANMÄßIG geladen : Uhrzeit $hour  BatteryChargeStartAt : $Tibber_BatteryChargeStartAt BatteryChargeUpTime : $Tibber_BatteryChargeUpTime    BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAtEnd";
          Log3 undef, 5, "SMABatteryChargewithTibber : 1003d  .........wäre HEUTE PLANMÄßIG geladen worden aber : Uhrzeit $hour  BatteryChargeStartAt + BatteryChargeUpTime ist <= BatteryChargeStartAtEnd : $Tibber_BatteryChargeStartAt + $Tibber_BatteryChargeUpTime = $Tibber_BatteryChargeStartAtEnd";
            }
          }
        }
      }

    }
}



sub SMABatteryChargewithTibberinMinTibberZeitfenster()
{
#######################################################################################################################
# Voraussetzung:
# Device myTibber muss installiert sein
# zugehörige sub MinTibberZeitfenster muss in myUtils vorhanden sein
# zugehörige sub TibberDaten muss in myUtils vorhanden sein
# zugehörige sub MinStromTime muss in myUtils vorhanden sein
# myTibber ->>> Aus dem Array mit den Strompreisen des definierten Zeitfenster wird der Zeitraum mit dem niedrigsten Preis ermittelt
# Parameter1: Preisarray
# Parameter2: Laufzeit in Stunden
# Return: Der StartIndex innerhalb der übergebenen Strompreise
# Nutzung in myTibber
#######################################################################################################################

 
  ############################################################################
  #
  # Deklaration bitte gleich halten wie in der sub SMABatteryChargewithTibber
  #
  # wird stündlich um 13/14/15  XY:10 Uhr durch at.TibberLoadBattery aufgerufen
  # (ansonsten deaktiviert)
  # um die Tibber-Ladezeit für die beiden Batterien in der Garage zu ermitteln
  ############################################################################
  my $BatteryCharge_Device = "Forecast"; # aus Solarforecast
  my $BatteryCharge_StatusCharge = "Current_BatCharge"; ### aktuell hinterlegter Batterie SOC-Wert

  my $Forecast_Current_BatCharge = ReadingsNum( $BatteryCharge_Device, $BatteryCharge_StatusCharge, 0);
  # Ladestatus in Summe von (allen) vorhandenen Batterien

  my $Tibber_Device = "myTibber";
  my $Tibber_Device_BatteryChargeGriduntil = "BatteryChargeGriduntil"; ### Batterie SOC-Wert Ladesteuerung - Reading in myTibber
  #    Griduntil = jewiels aktueller SOC-Wert bis zu dem weiter geladen werden sollte( 85 %)
  my $Tibber_Device_BatteryChargeUpMinTime = "BatteryChargeUpMinTime"; ### Uhrzeit ab wann frühestens geladen werden soll - Reading in myTibber
  #    MinTime = MinHour: FrühesterStart (Beispiel: 15 für 15:00 Uhr),
  my $Tibber_Device_BatteryChargeStartMinIndex = "BatteryChargeStartMinIndex"; ### aktueller Zeitindex in Stunden 0-24 bis zum Ladezeitstartzeitpunkt - Reading in myTibber
  #    StartMinIndex = Anzahl Stunden nach MinTime
  my $Tibber_Device_BatteryChargeStartAt = "BatteryChargeStartAt";
  #    StartAt = um wieviel Uhr soll gestartet werden - Reading in myTibber
  my $Tibber_Device_BatteryChargeStartAtEnd = "BatteryChargeStartAtEnd";
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber
  my $Tibber_Device_BatteryChargeUpTime = "BatteryChargeUpTime"; ### Ladungsdauer in Stunden - Reading in myTibber
  #    UpTime = Laufzeit: Laufzeit in Stunden, (Da es nur Stundenpreise gibt, kann die Laufzeit immer auf Stunden aufgerundet werden)
  my $Tibber_Device_BatteryChargeUpTimeDuration = "BatteryChargeUpTimeDuration"; ### Zeitdauer der Preisprüfung - Reading in myTibber
  #    UpTimeDuration = Zeitdauer der Preisprüfung
  my $Tibber_Device_BatteryChargeProcess = "BatteryChargeProcess";
  #    Ladung ein = 1 - Ladungmodul aus = 0  - Reading in myTibber
  my $Tibber_Device_MinZeitIndex = "MinTibberStartMinIndex";
  #    xy Stunden bis zum Start bei aktueller Stunde

  ###############################################################################
  # Gleich halten wie in sub SMABatteryChargewithTibberinMinTibberZeitfenster
  # 2023-02-04 18:28
  ###############################################################################

  my $Tibber_BatteryChargeGriduntil = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeGriduntil, 0);
  # hinterlegte max. Grenze Batterie SOC-Wert (85%) für die Tibber-Steuerung
  my $Tibber_BatteryChargeUpMinTime = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpMinTime, 0);
  ### später als z.B. 14 Uhr wegen Bekanntgabe der Tommorrow-Werte
  my $Tibber_BatteryChargeStartAt = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartAt, 0);
  #    StartAt = um wieviel Uhr soll gestartet werden - Reading in myTibber
  my $Tibber_BatteryChargeStartMinIndex = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartMinIndex, 0);
  ### aktueller Zeitindex in Stunden 0-24 bis zum Ladezeitstartzeitpunkt
  my $Tibber_BatteryChargeUpTime = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpTime, 0);
  ### BatteryChargeUpTime = Laufzeit: Laufzeit in Stunden
  my $Tibber_BatteryChargeStartAtEnd = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeStartAtEnd, 0);
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber zyklisch neu setzen
  my $Tibber_BatteryChargeProcess = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeProcess, 0);
  #    Process = soll per Tibber geladen werden ?? - Reading in myTibber
  my $Tibber_BatteryChargeUpTimeDuration = ReadingsNum( $Tibber_Device, $Tibber_Device_BatteryChargeUpTimeDuration, 0);
  ### UpTimeDuration = Zeitdauer der Preisprüfung
 
  ###############################################################
  # bis hier gleich halten wie in sub SMABatteryChargewithTibber
  ###############################################################


  my ($sec,$min,$hour,$mday,$mon,$year) = localtime;
 
  my $Tibber_MinTibberStartZeitfenster = "";
 
  # Zeitraum für die nächsten 24 Stunden - sub MinStromTime($$$) -   (z.B. 14,3,24) holen
  $Tibber_MinTibberStartZeitfenster = MinStromTime($Tibber_BatteryChargeUpMinTime, $Tibber_BatteryChargeUpTime, $Tibber_BatteryChargeUpTimeDuration);

  # grad erzeugter und hinterlegter Zeitindex in  myTibber
  my $MinZeitIndex = ReadingsNum( $Tibber_Device, $Tibber_Device_MinZeitIndex, 0);
 
  # jetzt sollten die Daten feststehen
  Log3 undef, 4, "SMABatteryChargewithTibberinMinTibberZeitfenster : 1009  SSOC : $Forecast_Current_BatCharge ist ?? <= Tibber_BatteryChargeGriduntil : $Tibber_BatteryChargeGriduntil";
Log3 undef, 4, "SMABatteryChargewithTibberinMinTibberZeitfenster : 1009  MinTibberStartZeitfenster $Tibber_MinTibberStartZeitfenster  BatteryChargeStartMinIndex $MinZeitIndex   ";

  # wann wird am günstigsten geladen werden ??
  fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeStartAt $Tibber_MinTibberStartZeitfenster");  # hier leider noch mit "Uhrzeit:Minuten" deshalb später Wert rückrechnen !!!!
  fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeStartMinIndex $MinZeitIndex"); # aktuellen Wert schreiben - fest ab $Tibber_Device_BatteryChargeStartAt Uhr
  $Tibber_BatteryChargeStartAtEnd = $hour + $MinZeitIndex + $Tibber_BatteryChargeUpTime; # aktualisieren damit es auch wirklich die Stunden werden die es sein sollten
  #    StartAtEnd = Neuberechnung um wieviel Uhr soll Ladung beendet werden
Log3 undef, 4, "SMABatteryChargewithTibberinMinTibberZeitfenster : 1009a  hour $hour    + MinZeitIndex $MinZeitIndex + Tibber_BatteryChargeUpTime  $Tibber_BatteryChargeUpTime      Tibber_MinTibberStartZeitfenster  $Tibber_MinTibberStartZeitfenster  BatteryChargeStartMinIndex $MinZeitIndex   Tibber_BatteryChargeStartAtEnd $Tibber_BatteryChargeStartAtEnd";
  if ($Tibber_BatteryChargeStartAtEnd > "23")  # ist Lade-Endzeit später als 23 Uhr ??? dann Abzug von 24
  {
    $Tibber_BatteryChargeStartAtEnd = ($Tibber_BatteryChargeStartAtEnd - "24");
  }
  #    StartAtEnd = um wieviel Uhr soll beendet werden - Reading in myTibber wird zyklisch neu gesetz 
  fhem("setreading $Tibber_Device $Tibber_Device_BatteryChargeStartAtEnd $Tibber_BatteryChargeStartAtEnd");
Log3 undef, 1, "SMABatteryChargewithTibberinMinTibberZeitfenster : 1009b  MinTibberStartZeitfenster $Tibber_MinTibberStartZeitfenster  BatteryChargeStartMinIndex $MinZeitIndex   Tibber_BatteryChargeStartAtEnd $Tibber_BatteryChargeStartAtEnd";
 
 
}

sub SMABatteryChargeON()
{
    #Werte für Ladungsende per Modbus an Battery senden
    fhem("set MB_SBS25 Set_Leistung_W -8000"); # 0 Watt Netzleistung am Übergabemesspunkt (WR1)
    fhem("set MB_SBS25_2 Set_Leistung_W -8000");  # 0 Watt Netzleistung am Übergabemesspunkt (WR2)
    fhem("set MB_SBS25 Set_Aktiv 802");  # 802 - Steuerung aktiv (WR1)
    fhem("set MB_SBS25_2 Set_Aktiv 802");   # 802 - Steuerung aktiv (WR2)
    ###so geht es aber auch (für 30 Minuten - weil so im WR Wartezeit von 30 Minuten hinterlegt wenn kein Kontakt mehr zu Fremdsteuerung besteht)################
    #defmod di_Test_Batterie_Laden DOIF ([05:00-05:10]) (set MB_SBS25 Set_Leistung_W 5000) (set MB_SBS25_2 Set_Leistung_W 5000) (set MB_SBS25 Set_Aktiv 802) (set MB_SBS25_2 Set_Aktiv 802)
    #attr di_Test_Batterie_Laden comment ([22:10-22:20] and [BatteryDummy:chargestatus] > 85) (set MB_SBS25 Set_Leistung_W 5000) (set MB_SBS25_2 Set_Leistung_W 5000) (set MB_SBS25 Set_Aktiv 802) (set MB_SBS25_2 Set_Aktiv 802)
    #attr di_Test_Batterie_Laden room 011_MODBUS,025_Tibber,Strompreis->Dynamisch
    #attr di_Test_Batterie_Laden stateFormat timer_01_c01 bis timer_02_c01
    #attr di_Test_Batterie_Laden verbose 5
    #attr di_Test_Batterie_Laden wait 0,10,10,10
}

sub SMABatteryChargeOFF()
{
    #Werte für Ladungsende per Modbus an Battery senden  - (wenn nicht klappt evtl delay oder wait einbauen???)
    fhem("set MB_SBS25 Set_Leistung_W 0"); # 0 Watt Netzleistung am Übergabemesspunkt (WR1)
    fhem("set MB_SBS25_2 Set_Leistung_W 0");  # 0 Watt Netzleistung am Übergabemesspunkt (WR2)
    fhem("set MB_SBS25 Set_Aktiv 803");  # 803 - Steuerung nicht aktiv (WR1)
    fhem("set MB_SBS25_2 Set_Aktiv 803");   # 803 - Steuerung nicht aktiv (WR2)
    ###so geht es aber auch)################
    ###################
    #defmod di_Test_Batterie_Laden_Ende DOIF ([05:00-05:10]) (set MB_SBS25 Set_Leistung_W 0) (set MB_SBS25_2 Set_Leistung_W 0) (set MB_SBS25 Set_Aktiv 803) (set MB_SBS25_2 Set_Aktiv 803)
    #attr di_Test_Batterie_Laden_Ende comment ([22:10-22:20] and [BatteryDummy:chargestatus] > 85) (set MB_SBS25 Set_Leistung_W 0) (set MB_SBS25_2 Set_Leistung_W 0) (set MB_SBS25 Set_Aktiv 803) (set MB_SBS25_2 Set_Aktiv 803)
    #attr di_Test_Batterie_Laden_Ende room 011_MODBUS,025_Tibber,Strompreis->Dynamisch
    #attr di_Test_Batterie_Laden_Ende stateFormat timer_01_c01 bis timer_02_c01
    #attr di_Test_Batterie_Laden_Ende verbose 5
    #attr di_Test_Batterie_Laden_Ende wait 0,10,10,10
}


sub TibberDaten()
{
#######################################################################################################################
# Tibber per HTTP auswerten
# Nutzung erfolgt durch myTibber und einige andere Device
#######################################################################################################################
  if(InternalVal("myTibber", "httpbody", "") eq "")
  {
    return;
  }
 
   my $json = decode_json(InternalVal("myTibber", "httpbody", "")); # wichtig showBody MUSS = 1 sein

   my $today_total = "";
#  my $today_energy = "";  # Energy und tax sind nicht notwendig für die Auswertung - mich interssiert nur der Endpreis inkl allem
#   my $today_tax = "";
   my $tomorrow_total = "";
#   my $tomorrow_energy = "";
#   my $tomorrow_tax = "";
   
   # Alte Einträge erst einmal löschen
   #my $timedelete = TimeNow();
   my $timedelete = strftime("%F",localtime(time))." 00:00";
   my $time_tomorrow = strftime("%F",localtime(time+86400));
   my ($year_today,$mon_today,$day_today) = $timedelete =~ m/(\d\d\d\d)-(\d\d)-(\d\d)/;
   my ($year_tomorrow,$mon_tomorrow,$day_tomorrow) = $time_tomorrow =~ m/(\d\d\d\d)-(\d\d)-(\d\d)/;
   
   Log3 undef, 5, "Aufruf (NO NO) von TibberDaten um ".localtime()." mit Löschzeit ".$timedelete." und time_tomorrow ".$time_tomorrow;
   
   ##fhem "set DBRep sqlCmd delete from history where DEVICE = 'myTibber' and READING like 'to%' AND TIMESTAMP>='".$timedelete."'";
     
   for(my $j=0; $j<24;$j++)
   {
      # Werte ermitteln
     my $value_today_total = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{today}[$j]->{total};
#     my $value_today_energy = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{today}[$j]->{energy};
#     my $value_today_tax = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{today}[$j]->{tax};
     my $value_tomorrow_total = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{tomorrow}[$j]->{total};
#     my $value_tomorrow_energy = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{tomorrow}[$j]->{energy};
#     my $value_tomorrow_tax = $json->{data}->{viewer}->{homes}[0]->{currentSubscription}->{priceInfo}->{tomorrow}[$j]->{tax};
     
     $today_total = $today_total.$value_today_total."|";
#     $today_energy = $today_energy.$value_today_energy."|";
#     $today_tax = $today_tax.$value_today_tax."|";
     
     if(defined $value_tomorrow_total)
     {
        $tomorrow_total = $tomorrow_total.$value_tomorrow_total."|";
#        $tomorrow_energy = $tomorrow_energy.$value_tomorrow_energy."|";
#        $tomorrow_tax = $tomorrow_tax.$value_tomorrow_tax."|";
     }
     else
     {
         $tomorrow_total = '999999';  #= $tomorrow_tax  = $tomorrow_energy = "NV"
   Log3 undef, 5, "TibberDaten: TomorrowTotal weil keine Werte da sind :  $tomorrow_total";
     }
   Log3 undef, 5, "TibberDaten: TomorrowTotal weil die Werte da sind :  $tomorrow_total";
     

     #Timestamp für den Stundenwert
     my $timestamp_today = ($j < 10) ? "$year_today-$mon_today-$day_today 0".$j.":00:00" : "$year_today-$mon_today-$day_today $j:00:00";
     my $timestamp_tomorrow = ($j < 10) ? "$year_tomorrow-$mon_tomorrow-$day_tomorrow 0".$j.":00:00" : "$year_tomorrow-$mon_tomorrow-$day_tomorrow $j:00:00";

   Log3 undef, 5, "TibberDaten: Timestamp tomorrow Stundenwert   : $timestamp_tomorrow mit $tomorrow_total                         Timestamp today Stundenwert: $timestamp_today  mit $today_total       ";;
 #  Log3 undef, 5, "TibberDaten: Timestamp tomorrow Stundenwert: $timestamp_today ";
     
          # Werte in der Datenbank loggen
     fhem "set myDbLog addCacheLine ".$timestamp_today."|myTibber|addlog|today_total:".$j.":00:00|today_total|".$value_today_total."|";
#     fhem "set myDBLog addCacheLine ".$timestamp_today."|myTibber|addlog|today_energy:".$j."|today_energy|".$value_today_energy."|";
#     fhem "set myDBLog addCacheLine ".$timestamp_today."|myTibber|addlog|today_tax:".$j."|today_tax|".$value_today_tax."|";
     
     if(defined $value_tomorrow_total)
     {
        fhem "set myDBLog addCacheLine ".$timestamp_tomorrow."|myTibber|addlog|tomorrow_total:".$j.":00:00|tomorrow_total|".$value_tomorrow_total."|";
#        fhem "set myDBLog addCacheLine ".$timestamp_tomorrow."|myTibber|addlog|tomorrow_energy:".$j."|tomorrow_energy|".$value_tomorrow_energy."|";
#        fhem "set myDBLog addCacheLine ".$timestamp_tomorrow."|myTibber|addlog|tomorrow_tax:".$j."|tomorrow_tax|".$value_tomorrow_tax."|";
      }
   }
   
   fhem("setreading myTibber TodayTotal $today_total");
#   fhem("setreading myTibber TodayEnergy $today_energy");
#   fhem("setreading myTibber TodayTax $today_tax");
   Log3 undef, 5, "TibberDaten: TodayTotal    :  $today_total";
   
   fhem("setreading myTibber TomorrowTotal $tomorrow_total");
#   fhem("setreading myTibber TomorrowEnergy $tomorrow_energy");
#   fhem("setreading myTibber TomorrowTax $tomorrow_tax");
   
   Log3 undef, 5, "TibberDaten: TomorrowTotal :  $tomorrow_total";

}


sub MinTibberZeitfenster
{
#######################################################################################################################
# Aus dem Array mit den Strompreisen des definierten Zeitfenster wird der Zeitraum mit dem niedrigsten Preis ermittelt
# Parameter1: Preisarray
# Parameter2: Laufzeit in Stunden
# Return: Der StartIndex innerhalb der übergebenen Strompreise
# Nutzung in MyTibber
#######################################################################################################################

my ($Strompreise, $Laufzeit) = @_;
my $anz = @{$Strompreise};
my @PreisIntervall;

# Log3 undef, 5, "MinTibberZeitfenster: Strompreise=@{$Strompreise}     Laufzeit=$Laufzeit     Anzahl Strompreise = $anz";

for (my $i = 0; $i < ($anz - $Laufzeit +1); $i++)
{
   @PreisIntervall[$i] = sum @{$Strompreise}[$i..$i+$Laufzeit-1];
   Log3 undef, 5, "Preisintervall Summe: $PreisIntervall[$i]";
}

my $MinPreis = "";
  $MinPreis = min @PreisIntervall;
my $MinIndex = "";
  $MinIndex = first_index { $_ eq $MinPreis } @PreisIntervall;

Log3 undef, 5, "MinTibberZeitfenster: $MinPreis MinIndex = $MinIndex";
  fhem("setreading myTibber MinTibberStartMinPreis $MinPreis");
  fhem("setreading myTibber MinTibberStartMinIndex $MinIndex");

return $MinIndex;
}


sub MinStromTime($$$)
{
#######################################################################################################################
# Günstigsten Strompreis für eine Dauer von X Minuten finden
# Parameter:
#    MinHour: FrühesterStart (Beispiel: 15 für 15:00 Uhr),
#    Laufzeit: Laufzeit in Stunden, (Da es nur Stundenpreise gibt, kann die Laufzeit immer auf Stunden aufgerundet werden)
#    Laufzeit_Ende: Anzahl Stunden nach frühestem Start (Beispiel: 12 für 12 Stunden nach frühester Start).
#                   Der Wert gibt dann quasi das Ende der Laufzeit an
# Es wird immer die Startzeit für den aktuellen Tag angenommen und wenn die aktuelle Zeit nach dem frühesten Start liegt,
# wird die früheste Startzeit auf die aktuelle Zeit zzgl. 2 Minuten gesetzt
# Die Funktion ermittelt dann die Uhrzeit, in der der günstigste Strom für die Dauer von Laufzeit zu erwarten ist
#
# Beispiel: MinStromTime(15, 3, 24) -> Ermittelt den günstigsten Strom für 3 Stunden Laufzeit,
# der am gleichen Tag nach 15:00 Uhr liegt und im Zeitfenster bis 15:00 + 24 Stunden - also am nächsten Tag um 15:00 Uhr liegt
#
#######################################################################################################################
my ($MinHour,$Laufzeit,$LaufzeitEnde) = @_;

my @PreiseHeute = split /\|/, ReadingsVal("myTibber","TodayTotal",0.25);
my @PreiseMorgen = split /\|/, ReadingsVal("myTibber","TomorrowTotal",0.25);
my @AllePreise = (@PreiseHeute, @PreiseMorgen);
my ($tmp, $m, $h, $tmp, $tmp, $tmp, $tmp, $tmp, $tmp) = localtime(time);
my $MinZeit = "";
 
Log3 undef, 5, "MindestStromPreis: Aktuelle Zeit:  $h:$m StartzeitbislangMinzeit:          $MinZeit 1";
Log3 undef, 5, "MindestStromPreis: Aktuelle Zeit:  $h:$m StartzeitbislangMinhour:$MinHour 2";

$h = $h >= $MinHour ? $h : $MinHour; # Falls die Mindestzeit vor der akt. Zeit liegt Mindestzeit auf akt. Zeit setzen

my $LaufzeitIndex = ($MinHour + $LaufzeitEnde) <= 48 ? $MinHour + $LaufzeitEnde - 1 : 47;
Log3 undef, 5, "MindestStromPreis: Aktuelle Zeit:$h:$m Startzeitbislang1:    $MinHour";

@AllePreise = @AllePreise[$h..$LaufzeitIndex];

my $MinZeitIndex = MinTibberZeitfenster(\@AllePreise, $Laufzeit);
Log3 undef, 1, "MindestStromPreis: MinZeitIndex $MinZeitIndex";
Log3 undef, 1, "MindestStromPreis: Aktuelle Zeit:$h:$m Startzeitbislang2:     $MinZeit";
fhem("setreading myTibber MinTibberStartZeitfenster $MinZeit"); #####xxxxxxxx $MinZeit zuletzt einmal eingefügt
fhem("setreading myTibber MinTibberStartMinIndex $MinZeitIndex");


if($MinZeitIndex + $h > 24) # Uhrzeit ist am nächsten Tag
{
$MinZeit = sprintf("%02d", $MinZeitIndex + $h - 24).":00";
    fhem("setreading myTibber MinTibberStartZeitfenster $MinZeit"); #hier feht Datum ect
Log3 undef, 5, "MindestStromPreis: MinTibberStartZeitfenster $MinZeit";
Log3 undef, 5, "MindestStromPreis: MinZeitIndexjetzt (Tomorrow) $MinZeitIndex Aktuelle Zeit:$h:$m Startzeit:$MinZeit";
}
else
{
$m = $MinZeitIndex == 0 ? $m + 2 : 0; # Uhrzeit entspricht Aufrufzeit, daher 2 Minuten aufschlagen
$MinZeit = sprintf("%02d", $MinZeitIndex + $h).":".sprintf("%02d", $m);
    fhem("setreading myTibber MinTibberStartZeitfenster $MinZeit");   #hier feht Datum ect
Log3 undef, 5, "MindestStromPreis: MinTibberStartZeitfenster $MinZeit";
Log3 undef, 5, "MindestStromPreis: MinZeitIndexjetzt (Today) $MinZeitIndex Aktuelle Zeit:$h:$m Startzeit:$MinZeit";
}

Log3 undef, 5, "MindestStromPreis: Aktuelle BeginnZeit:$h:$m  Startzeit:$MinZeit";

return $MinZeit;
}
1;


Es soll nur als eine Anregung dienen - nicht als Paradebeispiel  ::)
Weil ->> Keine Datenbank notwendig - geringe (nur aktuelle) Datenvorhaltung für die Preise Today und die von Tommorrow.

Nicht auf schön oder ordentlich geschrieben weil alles erst im werden ist -aber insgesamt funktioniert es erst einmal (bei mir), ob woanders auch keine Ahnung ???
(Kann auch sein das ich woanders (innerhalb von FHEM) noch was zusätzlich dabei nutze was hier nicht mit dabei ist)

Gruß
300P
FHEM 6.3 - Raspberry Pi 3 / Pi 4 - VControl300 mit VITOVALOR 300P - SMAEM - SMAInverter - DbLog/DbRep - MariaDB/QNAP - div. HTTPMOD - div. Modbus ser+TCP - SolarForecast - Tibber + Ladung mit SMA-SBS25

Dracolein

Zitat von: DS_Starter am 13 März 2024, 10:51:37
ZitatDie Steckdose eines Luftentfeuchters soll bei genügend PV-Überschuss UND Luftfeuchtigkeit größer 65% eingeschaltet und bei zu wenig Überschuss ABgeschaltet werden.
Da dieses Verfahren zw. 07-22 laufen soll, bietet sich an zunächst die Schlüssel power=0 und mintime=900 zu setzen. Für die Einplanung wäre evtl. auch mode=must sinnvoll.
Dann die Schlüssel spignorecond, swoncond löschen und dafür interruptable einsetzen:

interruptable=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[7-9]|[7-9][0-9]

Der Regex sollte soweit passen. Kann man sicher noch verbessern, habe mir jetzt aber auf die Schnelle nicht näher angeschaut, nur getestet auf https://regex101.com.
Die Seite bietet sich an um seine Regex zu testen und zu optimieren.

LG




Hm, wodurch würde der Verbraucher außerhalb seiner Planungsphase bei zu wenig PV Überschuss eingeschaltet, wenn spignorecond fehlt?
Raspberry Pi 4 mit FHEM; FTUI Dashboard auf Asus 15,6" VT168H Touchscreen; ZigBee mit ConBee2 USB-Stick; div. Shelly 2.5; integr. Gaszähler mit ESP8266 & ESPEasy;

DS_Starter

ZitatHm, wodurch würde der Verbraucher außerhalb seiner Planungsphase bei zu wenig PV Überschuss eingeschaltet, wenn spignorecond fehlt?
Außerhalb nicht.
Wenn du den Lüfter im Prinzip rund um die Uhr planen willst, dann lösche die Schlüssel notbefore, notafter und setze dann mintime=1430, mode=must.
Aber ich habe natürlich übersehen die 95% (vs. 97%) -> daraus folgt:

interruptable=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[5-9]|[5-9][0-9]

Du hast recht mit spignorecond  :)  und setzt dann doch:

power=300
spignorecond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:100|6[7-9]|[7-9][0-9]


Der Verbraucher würde dann mit einer kleinen Unterbrechung 24h lang eingeplant, aber nur laufen wenn PV Überschuß.
Um zu analysieren, kannst du die ctrlDebug=consumerPlanning,consumerSwitching setzen.
Das macht es einfacher.

LG
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Reinschki

Ich habe mich die letzten Tage mit dem Modul auseinandergesetzt mit viel Fleiß konfiguriert und verstehe noch nicht alles.

Über die sonnenscheinreiche Zeit möchte ich mein Wasserbett als Energiespeicher und zur Eigenverbrauchsoptimierung nutzen.
Die Heizung des Wasserbetts soll Nachts ausgeschaltet und tagsüber auf jeden Fall eingeschaltet werden. Das aber zur zu erwartenden ertragreichsten Zeit und auch ohne Überschuss!

Hiermit habe ich es nicht hinbekommen. Der Verbraucher wird immer nur dann eingeplant wenn ich auf das Uhrensymbol klicke. Das verstehe ich nicht!
HM_ES_PMSw1_Pl_PEQ0411718 type=heater power=200 mode=must on="on" off="off" pcurr=2.POWER interruptable=1 mintime=SunPath icon=scene_sleeping_alternat notbefore=9 auto=Automatiksteuerung spignorecond=deCONZ_Multi_Schlafzimmer_T:water_temp:low etotal:2.ENERGY_COUNTER:Wh

Wofür braucht man das Uhrensymbol?
Wie muss ich consumer01 konfigurieren? 
Ich benötige jetzt dringend eine funktionierende Konfiguration weil es mittlerweile verdammt kalt im Bett wird :'(

Beste Grüße
Reiner

DS_Starter

Hallo Reiner,

ZitatIch benötige jetzt dringend eine funktionierende Konfiguration weil es mittlerweile verdammt kalt im Bett wird :'(
Das ist natürlich eine Motivation  :)

ZitatWofür braucht man das Uhrensymbol?
Falls man per "Klick" einen Verbraucher z.B. über ein Wandtablet manuell sofort einplanen möchte.
Mit einem Mouse-Over gibt es ein paar wesentliche Informationen.

ZitatDie Heizung des Wasserbetts soll Nachts ausgeschaltet und tagsüber auf jeden Fall eingeschaltet werden. Das aber zur zu erwartenden ertragreichsten Zeit und auch ohne Überschuss!
In dem Fall das interruptable=1 löschen und power=0 setzen. Mit power=0 brauchst du spignorecond nicht weil ein PV-Überschuß generell nicht beachtet werden soll.
Damit sollte die Einplanung gelingen, das entsprechende Planungsreading gesetzt werden. Die Schaltung des Verbauchers wird dann wie eingeplant vorgenommen ohne einen PV Überschuß zu der gegebenen Zeit zu erwarten.
Falls es nicht klappt das Attr ctrlDebug=consumerPlanning,consumerSwitching zur Auswertung setzen. Dann sieht man was ggf. noch nicht funktioniert.

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

kask

Irgendwie kommt es mir so vor das es Frühling wird.
Ein relativ hohes Aufkommen an neuen Stimmen hier rund um das Thema.
Es wird festgestellt das so eine PV-Anlage bzw. die Produktion und der Verbrauch optimiert werden will.
Vermutlich werden viele aus dem jahre 2022/23 beobachtet haben und festgestellt haben: "Da kann ich mehr nutzen raus ziehen".
Finde ich Gut!

Ich persönlich nutze das Modul eigentlich nur in seiner Kernfunktion. Das Modul gibt mir die möglichkeit etwas einzuplannen bzw. diverse Verfügbarkeiten zu progontizieren.
Sozusagen das Modul gibt mir prognostizierte Füllstandsanzeigen. Und nur die schnöden alten Analogen, nix mit Schaltausgang etc.

Wie voll ist mein Sonnenlichttank heute abend = wieviel pv ertrag ist zu erwarten.
Wie leer ist mein stromtank morgen früh zu sonnen aufgang/untergang/zu mitternacht. = was werde ich vermutlich verbraucht haben bis dahin.

Die funktionen was ich wie wo einschalte mache ich über doif's, notifies, events.
Das mache ich hauptsächlich aus 2 Gründen.
1. So Funktionen wie spignorecon etc. gibt es nur hier. Eventuell brauch ich sowas aber woanders und muss mir das dann selbst erfinden. Es kostet mich Zeit mich in den gesamten Funktionsumfang reinzuarbeiten. Da kann ich auch Zeit investieren und mir das gesamte Konstrukt anzueignen. Das hat auch den Vorteil eventuell was an/in dem Modul zuverstehen wenn man sich den code mal anguckt.
2. Es können Funktionen auf einmal wegfallen oder nicht mehr funtionieren weil umgebaut/modernisiert wurde. Und nur der Ersteller entscheidet was drin bleibt und was raus fliegt. Muß nicht kann aber immer möglich sein.

Also baue ich mir so etwas selber, hat für mich den Vorteil das ich mich mit der Umgebung/Sprache auseinandersetzen muß. Zusammenhänge besser verstehe. Möglichkeiten einschätzen kann.
Das ermöglicht mir ein schnelleres adoptieren von Funktionen für andere Zwecke. Alles in allem wird man schneller mit der Zeit und hat mehr Verständniss.
Ich bin völlig frei mit dem wie/was/wo/warum ich das mache..denn ich setze die Parameter und Rahmenbedingungen. Ich kann schnell sachen umstricken wie ich diese brauche und denke das es sinnvoll ist. Ic muß zugeben das nicht alle Probleme die auf mich zukommen in dem prozess schnell abgearbeitet sind. Manche Hartenuss hat mich ganz schön Zeitgekostet. Der Weg ist das Ziel!

Ich möchte hier nicht bashen das diese Funktionen in dem Modul quatsch sind.
Aber das Modul ist so aufgebläht mit all seinen Funktionen das man da sicher auch 2-3 Module hätte draus machen können.
Hut ab für die Fleissarbeit zur Modulerstellung hier.

Und @DS_Starter, so wirklich selbsterklärend ist es jetzt auch nicht mehr mit der ganzen Konfiguration der Verbraucher & Bedingungen.
War früher einfacher jetzt sind die Möglichkeiten schon recht komplex geworden was ich immer so mitlese. Bin ja nicht erst seit gestern hier.

Das Modul funktioniert bei mir wirklich sehr gut (ausgenommen der ForcastSolarAPI, die will nicht so bei mir) was die Prognosen etc, angeht. Will ich garnicht mehr missen.


DS_Starter

ZitatUnd @DS_Starter, so wirklich selbsterklärend ist es jetzt auch nicht mehr mit der ganzen Konfiguration der Verbraucher & Bedingungen.
Kein Thema, genau aus diese Grund habe ich schon lange versprochen im Wiki mehr dazu zu schreiben.
Nur habe ich leider auch nur zwei Hande und immer zu wenig Zeit.  ;)
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

ch.eick

RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

300P

spignorecond   

Bedingung um einen fehlenden PV Überschuß zu ignorieren (optional). Bei erfüllter Bedingung wird der Verbraucher entsprechend
der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuß vorliegt.
ACHTUNG: Die Verwendung beider Schlüssel spignorecond und interruptable kann zu einem unerwünschten Verhalten führen!
Device - Device zur Lieferung der Bedingung
Reading - Reading welches die Bedingung enthält
Regex - regulärer Ausdruck der für eine 'wahre' Bedingung erfüllt sein muß
FHEM 6.3 - Raspberry Pi 3 / Pi 4 - VControl300 mit VITOVALOR 300P - SMAEM - SMAInverter - DbLog/DbRep - MariaDB/QNAP - div. HTTPMOD - div. Modbus ser+TCP - SolarForecast - Tibber + Ladung mit SMA-SBS25

Reinschki

Mit dieser Konfig:
HM_ES_PMSw1_Pl_PEQ0411718 type=heater power=0 mode=must on="on" off="off" pcurr=2.POWER mintime=SunPath icon=scene_sleeping_alternat notbefore=9 notafer= 18 auto=Automatiksteuerung etotal:2.ENERGY_COUNTER:Wh
Wird um 11:20 wird die Heizung immer noch nicht eingeschaltet. Trotz Überschuss welcher gar nicht gefordert ist.
Du darfst diesen Dateianhang nicht ansehen.

Der Geschirrspüler wird auch nicht eingeschaltet
di_remote_dishwasher type=dishwasher icon=scene_dishwasher power=1500 mode=must auto=Automatiksteuerung notbefore=10 notafter=17 on="washer on" off="washer off" swstate=state:on:off interruptable=0Erst wenn ich auf das Uhrensymbol klicke geht es los!?

Ich verstehe das System nicht!
Hier die letzten Log-Einträge...
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> ############### consumer "01" ###############
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - general switching parameters => auto mode: 1, current Consumption: 615 W, nompower: 0, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - isInLocktime: 0
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - device >HM_ES_PMSw1_Pl_PEQ0411718< is used as switching device
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:28:03.161 1: SolarForecast DEBUG> consumer "01" - current planning state: suspended

2024.03.14 11:28:03.162 1: SolarForecast DEBUG> ############### consumer "02" ###############
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - general switching parameters => auto mode: 1, current Consumption: 615 W, nompower: 45, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - isInLocktime: 0
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - device >HMIP_PSM_Kuehlschrank_2< is used as switching device
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "02" - current planning state: suspended

2024.03.14 11:28:03.162 1: SolarForecast DEBUG> ############### consumer "03" ###############
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - general switching parameters => auto mode: 1, current Consumption: 615 W, nompower: 0, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - isInLocktime: 0
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - device >deCONZ_zigbee_Osr_5< is used as switching device
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "03" - current planning state: suspended

2024.03.14 11:28:03.162 1: SolarForecast DEBUG> ############### consumer "04" ###############
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - general switching parameters => auto mode: 1, current Consumption: 615 W, nompower: 30, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - isInLocktime: 0
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - device >HM_ES_PMSw1_Pl_PEQ0411666< is used as switching device
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:28:03.162 1: SolarForecast DEBUG> consumer "04" - current planning state: suspended

2024.03.14 11:28:03.163 1: SolarForecast DEBUG> ############### consumer "05" ###############
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - general switching parameters => auto mode: 0, current Consumption: 615 W, nompower: 1500, surplus: 0 W, planstate: suspended:, starttime: 14.03.2024 07:38:39
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - isInLocktime: 0
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - current Context is >switch on< => swoncond: 1, on-command: washer on
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - device >di_remote_dishwasher< is used as switching device
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - current Context is >switch off< => swoffcond: 0, off-command: washer off
2024.03.14 11:28:03.163 1: SolarForecast DEBUG> consumer "05" - current planning state: suspended

Das gibt wieder eine kalte Nacht im unbeheiztem Wasserbett :-/

Reinschki

Aktuelle Beobachtung:
Nach dem letzten Post habe ich auf das Uhrensymbol für den Getränkekühlschrank geklickt. Da war aktuell Überschuss vorhanden.
Nach dem Klick wurde dieser sofort eingeschaltet.
So ist er konfiguriert:
HMIP_PSM_Kuehlschrank_2 type=other power=45 mode=can pcurr=6.POWER interruptable=1 auto=Automatiksteuerung mintime=SunPath icon=scene_wine_cellar notbefore=8 notafter=20 on="on" off="off" locktime=600 etotal=6.CURRENT_STATUS:Wh
Kurz danach, ohne Klick auf die Wasserbettenheizung würde das Symbol der Uhr Orange und das Wasserbett wurde eingeschaltet.
Da habe ich doch sicher noch an anderer Stelle irgendetwas falsch konfiguriert. Oder?

2024.03.14 11:37:13.180 1: SolarForecast DEBUG> ############### consumer "01" ###############
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - general switching parameters => auto mode: 1, current Consumption: 798 W, nompower: 0, surplus: 0 W, planstate: switched on: 2024-03-14 11:32:53 - 2024-03-14 18:29:00, starttime: 14.03.2024 11:32:53
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - isInLocktime: 0
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - device >HM_ES_PMSw1_Pl_PEQ0411718< is used as switching device
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "01" - current planning state: started

2024.03.14 11:37:13.180 1: SolarForecast DEBUG> ############### consumer "02" ###############
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - general switching parameters => auto mode: 1, current Consumption: 798 W, nompower: 45, surplus: 0 W, planstate: interrupted:, starttime: 14.03.2024 11:32:33
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - isInLocktime: 1, remainLockTime: 360 seconds
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - device >HMIP_PSM_Kuehlschrank_2< is used as switching device
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:37:13.180 1: SolarForecast DEBUG> consumer "02" - current planning state: interrupted

2024.03.14 11:37:13.181 1: SolarForecast DEBUG> ############### consumer "03" ###############
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - general switching parameters => auto mode: 1, current Consumption: 798 W, nompower: 0, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - isInLocktime: 0
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - device >deCONZ_zigbee_Osr_5< is used as switching device
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "03" - current planning state: suspended

2024.03.14 11:37:13.181 1: SolarForecast DEBUG> ############### consumer "04" ###############
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - general switching parameters => auto mode: 1, current Consumption: 798 W, nompower: 30, surplus: 0 W, planstate: suspended:, starttime: undef
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - isInLocktime: 0
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - current Context is >switch on< => swoncond: 1, on-command: on
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - device >HM_ES_PMSw1_Pl_PEQ0411666< is used as switching device
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - current Context is >switch off< => swoffcond: 0, off-command: off
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "04" - current planning state: suspended

2024.03.14 11:37:13.181 1: SolarForecast DEBUG> ############### consumer "05" ###############
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - general switching parameters => auto mode: 0, current Consumption: 798 W, nompower: 1500, surplus: 0 W, planstate: suspended:, starttime: 14.03.2024 07:38:39
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - isInLocktime: 0
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - current Context is >switch on< => swoncond: 1, on-command: washer on
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - device >di_remote_dishwasher< is used as switching device
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - current Context is >switch off< => swoffcond: 0, off-command: washer off
2024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - current planning state: suspended


DS_Starter

Der Getränkekühlschrank kann nicht schalten weil das auto ausgeschaltet ist:

024.03.14 11:37:13.181 1: SolarForecast DEBUG> consumer "05" - general switching parameters => auto mode: 0, current Consumption: 798 W, nompower: 1500, surplus: 0 W, planstate: suspended:, starttime: 14.03.2024 07:38:39

Hier ist das angegebene Reading auto=Automatiksteuerung im Device HMIP_PSM_Kuehlschrank_2 zu prüfen ob es auf "1" steht.

Welches Device ist dein Wasserbett?
Auf jeden Fall ist das Device nicht geplant weil kein Maximum Wert eines Überschusses für den aktuellen Tag gefunden wurde (ist für die Planung relevant).
Poste bitte noch die Ausgabe von "get ... solApiData".
Ist das Attr affectConsForecastInPlanning  gesetzt? Wenn ja auf welchen Wert?

LG
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter