Einheit energy beim Shelly 1 PM

Begonnen von Andi.Riese, 08 Dezember 2020, 11:03:31

Vorheriges Thema - Nächstes Thema

Andi.Riese

Hallo,

nach meiner Ansicht ist die Einheit bei energy: Wh (Watt Stunde)
Im fhem-Wiki findet man nix. Könnte "man" ergänzen.

In https://shelly-api-docs.shelly.cloud/#shelly1-1pm-mqtt  heisst es :
Zitatenergy counter in Watt-minute
Das ist falsch.

Nur zur Info.
Andreas


Otto123

#1
Zitat von: Andi.Riese am 08 Dezember 2020, 11:03:31
Das ist falsch.

Nur zur Info.
Andreas
Hi Andreas,

für meinen Shelly plugS kann ich das nicht bestätigen und ich denke nicht, dass die alle anders gestrickt sind:
Zitat2020-12-08_12:02:59 MQTT2_shellyplug_s_040E41 relay_0_energy: 129809
2020-12-08_12:02:59 MQTT2_shellyplug_s_040E41 relay_0_energy_total: 659727
2020-12-08_12:03:09 MQTT2_shellyplug_s_040E41 relay_0_power: 3.74

2020-12-08_21:50:00 MQTT2_shellyplug_s_040E41 relay_0_energy: 131997
2020-12-08_21:50:00 MQTT2_shellyplug_s_040E41 relay_0_energy_total: 661915
2020-12-08_21:50:12 MQTT2_shellyplug_s_040E41 relay_0_power: 3.68
relay_0_power: 3.68  -> ist in Watt
(131997-129809)/(9*60+48)=3,72 (2188 Watt (Edit) Watt-minute in 9 Stunden und 48 Minuten)
Für die FHEM Kommandozeile:
{(131997-129809)/(9*60+48)}
Energy ist in WattMinute :)

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Nobbynews

#2
Shelly Plug und Plug S liefern von Haus aus den Verbrauch in Wattminuten.
Im Modul 36_Shelly erfolgt eine Umrechnung in die "üblichen" Wattstunden.
MQTT liefert, wie Otto geschrieben hat, Wattminuten.

@Otto: Müsste es nicht heißen: 2188 Wmin in 9h und 48min??

Andi.Riese

Hi Otto,

wir haben beide recht.
Ich habe allerdings nicht das MQTT-Protokoll genommen, sondern das FHEM-Modul Shelly.

Ich hab Deine Zahlen nachgerechnet und es sind tatsächlich Wmin wie in der Dokumentation.

Ich habe noch einmal bei mir gemessen und auch ein Energiekostenmessgerät dazwischen geschaltet
und die Angaben des Shelly-Moduls sind offensichtlich Wh.

Ich dachte, dass es vielleicht vom Polling-Interval abhängt (was ein Witz wäre), aber die Zahlen sind die gleichen.

Vielleicht binde ich es ein anderes Mal über MQTT ein, aber pah schreibt ja in seinem (übrigens sehr hilfreichen) Buch, dass die Einbindung in FHEM möglichst einfach erfolgen sollte. Das sehe ich auch so.

Gruß
Andreas

Otto123

Zitat von: Nobbynews am 09 Dezember 2020, 05:01:48
@Otto: Müsste es nicht heißen: 2188 Wmin in 9h und 48min??
Klar muss es :D
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Prof. Dr. Peter Henning

ZitatIch dachte, dass es vielleicht vom Polling-Interval abhängt (was ein Witz wäre), aber die Zahlen sind die gleichen.

Das nicht. Aber das API ist hier nicht konsistent, wie oben schon bemerkt wurde.

in 36_Shelly.pm wird der Datenwert aus dem Device durch 60 geteilt, also Wmin in Wh umgerechnet

LG

pah

Nogga

#6
Ich hänge mich mal hier in den Verlauf rein.
Ich habe den Shelly 1PM angeschlossen zur Messung des Solarertrags meiner kleinen Balkon-Anlage.
Da das Energie-Reading bei Stromverlust ja reseted wird, dachte ich mir, dass ich einfach für mich relevante Werte in separate Readings schreibe (Gesamt-Ertrag und Tagesertrag - jeweils als Wh und kWh).
Mit oberer Diskussion verstehe ich, dass das energy-Reading bereits Wattstunden ausgibt.

Meine Reading-"Auslagerung" realisiere ich über folgendes DOIF. Habe ich einen Denkfehler? Weil 10kWh am Morgen mit 60 Watt Momentan-Leistung kann ich nicht wirklich glauben...


defmod Doif_Solarertrag DOIF ([EG_Shelly_Solaranlage:energy])\
(\
## update the total counter\
{fhem('setreading EG_Shelly_Solaranlage energyTotal_Wh '.(ReadingsVal("EG_Shelly_Solaranlage", "energyTotal_Wh", 0) + ReadingsVal("EG_Shelly_Solaranlage", "energy", 0)));;;; }\
{fhem('setreading EG_Shelly_Solaranlage energyTotal_kWh '.(ReadingsVal("EG_Shelly_Solaranlage", "energyTotal_Wh", 0)/1000));;;; }\
\
## update daily counter\
{fhem('setreading EG_Shelly_Solaranlage energyToday_Wh '.(ReadingsVal("EG_Shelly_Solaranlage", "energyToday_Wh", 0) + ReadingsVal("EG_Shelly_Solaranlage", "energy", 0)));;;; }\
{fhem('setreading EG_Shelly_Solaranlage energyToday_kWh '.(ReadingsVal("EG_Shelly_Solaranlage", "energyToday_Wh", 0)/1000));;;; }\
\
## reset Shelly's counter\
setreading EG_Shelly_Solaranlage energy 0, \
)\
DOELSEIF ([00:00])\
(\
setreading EG_Shelly_Solaranlage energyToday_Wh 0, \
setreading EG_Shelly_Solaranlage energyToday_kWh 0, \
)\
DOELSE\
()
attr Doif_Solarertrag do always
attr Doif_Solarertrag group Automatisch
attr Doif_Solarertrag room Automatisierung



Das ist übrigens auch noch der Shelly:

Internals:
   CFGFN     
   DEF        192.168.178.166
   DURATION   0
   FUUID      60623dcf-f33f-bfba-f6c9-563522d2bd6c083d
   INTERVAL   30
   NAME       EG_Shelly_Solaranlage
   NR         43104
   STATE      on<br>
Momentan: 105.49 W<br>
Heute: 11.9905 kWh<br>
Gesamt: 11.9905 kWh
   TCPIP      192.168.178.166
   TYPE       Shelly
   OLDREADINGS:
   READINGS:
     2021-04-01 09:00:05   cloud           disabled
     2021-04-01 10:17:20   energy          0
     2021-04-01 10:17:20   energyToday_Wh  11990.5
     2021-04-01 10:17:20   energyToday_kWh 11.9905
     2021-04-01 10:17:20   energyTotal_Wh  11990.5
     2021-04-01 10:17:20   energyTotal_kWh 11.9905
     2021-04-01 09:00:05   network         <html>connected to <a href="http://192.168.178.166">192.168.178.166</a></html>
     2021-04-01 09:00:05   overpower       0
     2021-04-01 10:17:20   power           105.49
     2021-04-01 09:00:05   relay           on
     2021-04-01 09:00:05   state           on
   helper:
     _98_statistics myStatDevice
Attributes:
   alias      Solaranlage
   cmdIcon    on:general_an off:general_aus
   group      Außen
   interval   30
   mode       relay
   model      shelly1pm
   room       Steuerung
   shellyuser admin
   stateFormat state<br>
Momentan: power W<br>
Heute: energyToday_kWh kWh<br>
Gesamt: energyTotal_kWh kWh


Update: wenn ich die rund 12.000 Wattstunden durch 100 teile, dann passt es wieder?! habe ich einen Denkfehler?

Otto123

Also oben war mW die Erkenntnis: Reading energy ist in WattMin - Du gehst in Deiner Rechnung von WattStunde aus?
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Nogga

#8
Ja, ich nutze aber auch das Shelly Modul und pah hat explizit geschrieben:

Zitatin 36_Shelly.pm wird der Datenwert aus dem Device durch 60 geteilt, also Wmin in Wh umgerechnet

Nogga

Ich glaube das Problem liegt am Aufaddieren.
Ich nehme ja quasi den Wh Wert aus dem Shelly, addiere ihn zu meinem eigenen Reading (energyTotal, bzw. energyToday) und lösche anschließend das energy-Reading aus dem Shelly.
Vermutlich addiere ich dann mehrfach die gleiche Energiemenge, aber mein Physikunterricht ist schon sooo lange her :-(

Nogga

Jetzt hab ich den Denkfehler...
Ich addiere immer das energy Reading (was durchaus Wh sind) zu meinem eigenen Reading.
Danach lösche ich es.
Beim nächsten Update fängt er aber nicht bei 0 an, sondern holt sich den Shelly-Wert - der hat natürlich noch den "alten" Wert gespeichert...

Damit hab ich exponentielle Erträge! Wenn es so einfach wäre...

Prof. Dr. Peter Henning

Das ist mitnichten ein exponentielles Wachstum. Nur weil gewisse $)(//&(/)((-Politiker mit diesem Begriff um sich werfen, sollte man dem nicht anhängen.

Allerding ist diese Vorgehensweise ein starkes Argument gegen das Löschen von Readings aus aktiven Devices.

Ich verstehe immer noch nicht so ganz den Sinn dahinter.

LG

pah

gvzdus

#12
Der Shelly resettet ja den Zählstand bei FW-Update oder Reboot.
Ich würde Dir meine Vorgehensweise empfehlen:

  • Du hast ein Dummy-Device mit angehängtem FileLog, um die Werte zu archivieren
  • In das Dummy-Device werden der letzte Zählerstand bei der Ablesung und die errechneten Deltas geschrieben. Ich logge z.B. lieber die "Durchschnittwatts", also Wh / 24h bei Tageswerten.

Das kannst Du so umsetzen:
define powerday dummy
define FileLog_Verbrauch_day FileLog ./log/stromverbrauchday-%Y.log powerday


Jetzt der "Ablesejob":
Erst mal grob einrichten:

define powerdayjob at *00:01:00 {}


Und dann das schöne Frontend nutzen, um das Perl auszuweiten:
{
my $wertneu=ReadingsVal("solarshelly","energy","0");
my $wertalt=ReadingsVal("powerday","wh_last","0");
my $werttotal=ReadingsVal("powerday","wh_total","0");
$wertalt = 0 if ($wertalt > $wertneu);
$werttotal += $wertneu-$wertalt;
my $delta=($wertneu-$wertalt)/24;
fhem("setreading powerday wh_last $wertneu");
fhem("setreading powerday watt_avg $delta");
fhem("setreading powerday wh_total $werttotal");
}


Damit "merkst" Du Dir den letzten Stand für den Fall des Reset (verlierst dann allerdings die Erzeugung bis zum Reset für den Tag). Und erhälst als "Logfile" täglich die Durchschnittserzeugungsleistung auf 24 h sowie die Gesamtzahl Deiner erzeugten Wh als "ewig fortgeschriebenen" Wert. Achtung, der Code ist ungetestet - da könnte ein Typo drin sein.

Alternativ kannst Du das natürlich auch auf Stunden- oder 10-Minuten-Basis machen.

Otto123

Und einfach ein userReadings mit monotonic? Mach ich bei verschiedenen "Zählern" so, das läuft sehr gut.
Wenn man es in kWh haben will kann man gleich noch rechnen:
Zaehler:energy.* monotonic {ReadingsNum($name,'energy','')/1000}
Mit setreading <device> Zaehler 123456 kann man einmalig den gewünschten Anfangswert des Zählers setzen.
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Prof. Dr. Peter Henning

Was um Himmels Willen spricht denn gegen ein userReading? Auf diese Weise bestimme ich auch in meiner Solarthermieanlage bei jeder Änderung des Readings flow den Zuwachs und die Gesamtenergie:
delta-E:.*flow.* {HKSOLV_deltaE()},energy:.*flow.* {HKSOLV_energy()},vol {ReadingsVal("HK.SOL.V","volume",0)}

Die aufgerufenen Perl-Funktionen sind natürlich sehr viel komplizierter, als es es hier nötig wäre - weil darin die physikalischen Eigenschaften der Solarflüssigkeit Tyfocor LS verwendet werden (siehe hier: https://wiki.fhem.de/wiki/Ertragsmessung_Solarthermie). Ich bin jetzt aber ehrich gesagt zu faul, um das für den hier gesuchten Anwendungsfall zu vereinfachen, und poste nachstehend einfach mal kommentarlos diese Perl-Funktionen. Übrigens wird darin auch das monatliche und jährliche Logging gemacht.

LG

pah

sub HKSOLV_deltaE()
{
  #-- properties of TYFOCOR LS
  # delta-E [in Wh/l] = C11 +
  #                    (C21 + C22*(TR-20)+C23*(TR-20)^2)*(TV-TR) +
  #                     C31 * (TV-TR)^2
  # wobei
  # C11 = -0.00064
  # C21 = 1.03392
  # C22 = 0.00055
  # C23 = 0.000002
  # C31 = 0.00057
  #
  my $tv = ReadingsVal("HK.SOL.Flow.T","temperature",0);
  my $tr = ReadingsVal("HK.SOL.Return.T","temperature",0);
  my $e  = -0.00064 + (1.03392 + 0.00055*($tr-20) + 0.000002*($tr-20)*($tr-20))*($tv-$tr) + 0.00057*($tv-$tr)*($tv-$tr);
 
  #-- transported volume = rate (l/h) * interval (s) * 1/3600
  my $t = (AttrVal("HK.SOL.V","interval",undef))?AttrVal("HK.SOL.V","interval",undef):300;
 
  #-- BUT only if interval has been kept ! What if the interval has been longer due to some delay ??
  #  TODO
 
  my $v = ReadingsVal("HK.SOL.V","flow",0)*$t/3600.;
  #Log 1,"solarTHy called. tv=$tv tr=$tr e=$e t=$t v=$v";

  #-- transported energy in Wh
  $e = $e*$v;
  return($e)

}

sub HKSOLV_energy()
{
  #-- zero the energy at the start of the day ist done by a FHEM routine Solar.N.morning
  return sprintf('%5.2f',(ReadingsVal("HK.SOL.V","energy",0)+ReadingsVal("HK.SOL.V","delta-E",0)/1000))
}

sub HKSOLV_month()
{
  my ($str,$line,$day);
  my $lf = $defs{'SolarTHM'}{currentlogfile};
  if( !(defined($lf))){
    Log 1,"[HKSOLV_month] logfile of SolarTHM is missing";
  }
  my @linarr = ();
  my @month  = ();
     
  #-- current date
  my ($csec,$cmin,$chour,$cday,$cmonth,$cyear,$cwday,$cyday,$cisdst) = localtime(time);
 
  my $ret  = open(SOLFILE, "< $lf" ); 
  my $nolines=0;
  if( $ret) {
    while( <SOLFILE> ){
      #-- line looks as
      #   2015-06-13_21:13:37 HK.SOL.V D 13 Wd  2.77 kWh  70.77 kWh
      $line = $_;
      $nolines++;
      chomp($line);
      if ( $line =~ m/.*HK.SOL.V.*/i){ 
        @linarr = split(' ',$line);
        if( int(@linarr)==9 ){
          $day = $linarr[3];
          $day =~ s/0+//;
          push(@month,$linarr[5]);
        }
      }
    }
    if( int(@month)==0 ){
       Log 1,"[HKSOLV_month] invalid logfile format"
        if( $cday!=1 );
    }
  } else {
     Log 1,"[HKSOLV_month] cannot open logfile";
  }
  Log 1,"[HKSOLV_month] $nolines lines read, ".int(@month)." have the proper format";
 
 
  #-- sum and average
  my $total = 0.0;
  for (my $j=0;$j<int(@month);$j++){
    $total += $month[$j];
  }
  #-- add data from current day
  $total = int($total*100)/100;
  my $total2 = int(100*($total+ ReadingsVal('HK.SOL.V','energy',0)))/100;
 
  #-- number of days so far, including the present day
  my $deltim = int(@month)+($chour+$cmin/60.0 + $csec/3600.0)/24.0;
  my $av = $deltim>0 ? int(100*$total2/$deltim)/100 : -1;
  #-- assemble string for HK.SOL
  $str = sprintf('trigger HK.SOL   d %02d Wd %5.2f kWh %6.2f kWh Pump %s',
     $cday,
     substr(ReadingsVal('HK.SOL','Wd',0),0,-4),
     (substr(ReadingsVal('HK.SOL','Wm',0),0,-4)  + substr(ReadingsVal('HK.SOL','Wd',0),0,-4)),
     ReadingsVal('HK.SOL','Pump.time',0));
  fhem($str);
 
  #-- assemble string for HK.SOL.V monthly statistics
  $str = sprintf('trigger HK.SOL.V D %02d Wd %5.2f kWh %6.2f kWh',
     $cday,
     ReadingsVal('HK.SOL.V','energy',0),
     $total2); 
  fhem($str);
   
  $str  = "\nWm ".$total2." kWh (monthly sum until now)\n";
  $str .= "Wa ".$av." kWh/d (average until yesterday)\n";
  return $str;   
   
}

sub HKSOLV_year()
{
  my ($str,$line,$month);
  my $lf = $defs{'SolarTHY'}{currentlogfile};
  if( !(defined($lf))){
    Log 1,"[HKSOLV_year] logfile of SolarTHY is missing";
  }
  my @linarr = ();
  my @year  = ();
     
   #-- current date
  my ($csec,$cmin,$chour,$cday,$cmonth,$cyear,$cwday,$cyday,$cisdst) = localtime(time);
 
  my $ret  = open(SOLFILE, "< $lf" );
  my $nolines = 0;
  if( $ret) {
    while( <SOLFILE> ){
      #-- line looks as
      #   2015-06-13_21:13:37 HK.SOL.V D 13 Wd  2.77 kWh  70.77 kWh
      $line = $_;
      $nolines++;
      chomp($line);
      if ( $line =~ m/.*HK.SOL.V.*/i){ 
        @linarr = split(' ',$line);
        if( int(@linarr)==9 ){
          $month = $linarr[3];
          $month =~ s/0+//;
          push(@year,$linarr[5]);
        }
      }
    }
    if( int(@year)==0 ){
       Log 1,"[HKSOLV_year] invalid logfile format"
        if( $cday!=1 );
    }
  } else {
     Log 1,"[HKSOLV_year] cannot open logfile";
  }
  Log 1,"[HKSOLV_year] $nolines lines read, ".int(@year)." have the proper format";
 
 
  #-- sum and average
  my $total = 0.0;
  for (my $j=0;$j<int(@year);$j++){
    $total += $year[$j];
  }
  #-- add data from current day
  $total = int($total*100)/100;
  #my $total2 = int(100*($total+ ReadingsVal('HK.SOL.V','energy',0)))/100;
 
  #-- number of days so far, including the present day
  #my $deltim = int(@month)+($chour+$cmin/60.0 + $csec/3600.0)/24.0;
  #my $av = $deltim>0 ? int(100*$total2/$deltim)/100 : -1;
  #-- assemble string for HK.SOL
  #$str = sprintf('trigger HK.SOL d %02d Wd %5.2f kWh %6.2f kWh Pump %s',
  #   $cday,
  #   substr(ReadingsVal('HK.SOL','Wd',0),0,-4),
  #   (substr(ReadingsVal('HK.SOL','Wm',0),0,-4)  + substr(ReadingsVal('HK.SOL','Wd',0),0,-4)),
  #   ReadingsVal('HK.SOL','Pump.time',0));
  #fhem($str);
 
  #-- assemble string for HK.SOL.V
  #$str = sprintf('trigger HK.SOL.V D %02d Wd %5.2f kWh %6.2f kWh',
  #   $cday,
  #   ReadingsVal('HK.SOL.V','energy',0),
  #   $total2); 
  #fhem($str);
   
  $str  = "\nWy ".$total." kWh (yearly sum until now)\n";
  #$str .= "Wa ".$av." kWh/d (average until yesterday)\n";
  return $str;   
   
}