diff --git a/fhem/contrib/DS_Starter/76_SMAPortal.pm b/fhem/contrib/DS_Starter/76_SMAPortal.pm index 64446b505..2f54caf55 100644 --- a/fhem/contrib/DS_Starter/76_SMAPortal.pm +++ b/fhem/contrib/DS_Starter/76_SMAPortal.pm @@ -105,6 +105,7 @@ BEGIN { addToAttrList BlockingCall BlockingKill + BlockingInformParent CommandAttr CommandDefine CommandDeleteAttr @@ -144,12 +145,13 @@ BEGIN { TimeNow Value json2nameValue + FW_cmd FW_directNotify FW_ME FW_subdir FW_room FW_detail - FW_wname + FW_wname ) ); } @@ -159,6 +161,7 @@ use vars qw($FW_ME); # webname (default is fh # Versions History intern our %vNotesIntern = ( + "2.3.0" => "12.06.2019 add set on,off,automatic cmd for controlled devices ", "2.2.0" => "10.06.2019 relocate RestOfDay and Tomorrow data from level 3 to level 2, change readings to start all with uppercase, ". "add consumer energy data of current day/month/year, new attribute \"verbose5Data\" ", "2.1.2" => "08.06.2019 correct planned time of consumer in PortalAsHtml if planned time is at next day ", @@ -197,6 +200,9 @@ sub Define($$) { $hash->{HELPER}{MODMETAABSENT} = 1 if($modMetaAbsent); # Modul Meta.pm nicht vorhanden + $hash->{HELPER}{GETTER} = "all"; + $hash->{HELPER}{SETTER} = "none"; + setVersionInfo($hash); # Versionsinformationen setzen getcredentials($hash,1); # Credentials lesen und in RAM laden ($boot=1) CallInfo($hash); # Start Daten Abrufschleife @@ -242,7 +248,8 @@ sub Set($@) { my $prop = $a[2]; my $prop1 = $a[3]; my ($setlist,$success); - + my $ad = ""; + return if(IsDisabled($name)); if(!$hash->{CREDENTIALS}) { @@ -256,6 +263,20 @@ sub Set($@) { "credentials ". "createPortalGraphic:Generation,Consumption,Generation_Consumption,Differential " ; + if($hash->{HELPER}{PLANTOID} && $hash->{HELPER}{CONSUMER}) { + my $lfd = 0; + foreach my $key (keys %{$hash->{HELPER}{CONSUMER}{$lfd}}) { + my $dev = $hash->{HELPER}{CONSUMER}{$lfd}{DeviceName}; + if($dev) { + $ad .= "|" if($lfd != 0); + $ad .= $dev; + } + if ($dev && $setlist !~ /$dev/) { + $setlist .= "$dev:on,off,auto "; + } + $lfd++; + } + } } if ($opt eq "credentials") { @@ -334,13 +355,57 @@ sub Set($@) { return "SMA Portal Graphics device \"$htmldev\" created and assigned to room \"$room\"."; + } elsif ($opt && $ad && $opt =~ /$ad/) { + # Verbraucher schalten + $hash->{HELPER}{GETTER} = "none"; + $hash->{HELPER}{SETTER} = "$opt:$prop"; + CallInfo($hash); + } else { return "$setlist"; - } + } return; } +############################################################### +# SMAPortal Get +############################################################### +sub Get($$) { + my ($hash, @a) = @_; + return "\"get X\" needs at least an argument" if ( @a < 2 ); + my $name = shift @a; + my $opt = shift @a; + + my $getlist = "Unknown argument $opt, choose one of ". + "storedCredentials:noArg ". + "data:noArg "; + + return "module is disabled" if(IsDisabled($name)); + + if ($opt eq "data") { + $hash->{HELPER}{GETTER} = "all"; + $hash->{HELPER}{SETTER} = "none"; + CallInfo($hash); + + } elsif ($opt eq "storedCredentials") { + if(!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials <username> <password>\"";} + # Credentials abrufen + my ($success, $username, $password) = getcredentials($hash,0); + unless ($success) {return "Credentials couldn't be retrieved successfully - see logfile"}; + + return "Stored Credentials to access SMA Portal:\n". + "========================================\n". + "Username: $username, Password: $password\n". + "\n"; + + } else { + return "$getlist"; + } + +return undef; +} + ############################################################### # SMAPortal DbLog_splitFn ############################################################### @@ -469,42 +534,6 @@ sub getcredentials ($$) { return ($success, $username, $passwd); } -############################################################### -# SMAPortal Get -############################################################### -sub Get($$) { - my ($hash, @a) = @_; - return "\"get X\" needs at least an argument" if ( @a < 2 ); - my $name = shift @a; - my $opt = shift @a; - - my $getlist = "Unknown argument $opt, choose one of ". - "storedCredentials:noArg ". - "data:noArg "; - - return "module is disabled" if(IsDisabled($name)); - - if ($opt eq "data") { - CallInfo($hash); - - } elsif ($opt eq "storedCredentials") { - if(!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials <username> <password>\"";} - # Credentials abrufen - my ($success, $username, $password) = getcredentials($hash,0); - unless ($success) {return "Credentials couldn't be retrieved successfully - see logfile"}; - - return "Stored Credentials to access SMA Portal:\n". - "========================================\n". - "Username: $username, Password: $password\n". - "\n"; - - } else { - return "$getlist"; - } - -return undef; -} - ############################################################### # SMAPortal Attr ############################################################### @@ -556,6 +585,8 @@ return undef; ################################################################ ## Hauptschleife BlockingCall +## $hash->{HELPER}{GETTER} -> Flag für get Informationen +## $hash->{HELPER}{SETTER} -> Parameter für set-Befehl ################################################################ sub CallInfo($) { my ($hash) = @_; @@ -588,8 +619,15 @@ sub CallInfo($) { delete($hash->{HELPER}{RUNNING_PID}); } + my $get = $hash->{HELPER}{GETTER}; + my $set = $hash->{HELPER}{SETTER}; + + Log3 ($name, 4, "$name -> ################################################################"); + Log3 ($name, 4, "$name -> ### start of set/get data from SMA Sunny Portal ###"); + Log3 ($name, 4, "$name -> ################################################################"); + $hash->{HELPER}{RETRIES} = AttrVal($name, "getDataRetries", 3); - $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetData", $name, "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); + $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetSetData", "$name|$get|$set", "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); $hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057 } else { @@ -601,23 +639,28 @@ return; ################################################################ ## Datenabruf SMA-Portal +## schaltet auch Verbraucher des Sunny Home Managers ################################################################ -sub GetData($) { - my ($name) = @_; - my $hash = $defs{$name}; - my ($livedata_content); - my $login_state = 0; - my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); - my $cookieLocation = AttrVal($name, "cookieLocation", "./log/mycookies.txt"); - my $v5d = AttrVal($name, "verbose5Data", "none"); +sub GetSetData($) { + my ($string) = @_; + my ($name,$get,$set) = split("\\|",$string); + my $hash = $defs{$name}; + my $login_state = 0; + my $useragent = AttrVal($name, "userAgent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)"); + my $cookieLocation = AttrVal($name, "cookieLocation", "./log/mycookies.txt"); + my $v5d = AttrVal($name, "verbose5Data", "none"); my ($forecast_content,$weatherdata_content,$consumerlivedata_content,$ccdaydata_content,$ccmonthdata_content) = ("","","","",""); my ($ccyeardata_content) = (""); + my $state = "ok"; + my ($livedata_content,$d,$op); - Log3 ($name, 5, "$name -> ################################################################"); - Log3 ($name, 5, "$name -> ### start of set/get data from SMA Sunny Portal ###"); - Log3 ($name, 5, "$name -> ################################################################"); - Log3 ($name, 5, "$name - verbose 5 data are specified by attribute \"verbose5Data\": $v5d"); - Log3 ($name, 5, "$name - Start getting data with CookieLocation: $cookieLocation and UserAgent: $useragent"); + if($set ne "none") { + # Verbraucher soll in den Status $op geschaltet werden + ($d,$op) = split(":",$set); + } + + Log3 ($name, 5, "$name - Start operation with CookieLocation: $cookieLocation and UserAgent: $useragent"); + Log3 ($name, 5, "$name - data get: $get, data set: ".(($d && $op)?($d." ".$op):$set)); my $ua = LWP::UserAgent->new; @@ -636,94 +679,119 @@ sub GetData($) { if(($livedata->content =~ m/FeedIn/i) && ($livedata->content !~ m/expired/i)) { Log3 $name, 4, "$name - Login to SMA-Portal succesful"; + # JSON Live Daten + $livedata_content = $livedata->content; + $login_state = 1; + Log3 ($name, 4, "$name - Getting live data"); + Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($livedata_content)) if($v5d eq "liveData"); - # JSON Live Daten - $livedata_content = $livedata->content; - $login_state = 1; - Log3 ($name, 4, "$name - Getting live data"); - Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($livedata_content)) if($v5d eq "liveData"); - - # JSON Wetterdaten - Log3 ($name, 4, "$name - Getting weather data"); - my $weatherdata = $ua->get('https://www.sunnyportal.com/Dashboard/Weather'); - $weatherdata_content = $weatherdata->content; - Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($weatherdata_content)) if($v5d eq "weatherData"); - - # JSON Forecast Daten - my $dl = AttrVal($name, "detailLevel", 1); - if($dl > 1) { - Log3 ($name, 4, "$name - Getting forecast data"); - - my $forecast_page = $ua->get('https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData'); - Log3 ($name, 5, "$name - Return Code: ".$forecast_page->code) if($v5d eq "forecastData"); - - if ($forecast_page->content =~ m/ForecastChartDataPoint/i) { - $forecast_content = $forecast_page->content; - Log3 ($name, 5, "$name - Forecast data received:\n".Dumper decode_json($forecast_content)) if($v5d eq "forecastData"); + ### einen Verbraucher schalten mit POST + if($set ne "none") { + my ($serial,$id); + foreach my $key (keys %{$hash->{HELPER}{CONSUMER}}) { + my $h = $hash->{HELPER}{CONSUMER}{$key}{DeviceName}; + if($h && $h eq $d) { + $serial = $hash->{HELPER}{CONSUMER}{$key}{SerialNumber}; + $id = $hash->{HELPER}{CONSUMER}{$key}{SUSyID}; + } + } + my $plantOid = $hash->{HELPER}{PLANTOID}; + my $res = $ua->post('https://www.sunnyportal.com/Homan/ConsumerBalance/SetOperatingMode', {'mode' => $op, 'serialNumber' => $serial, 'SUSyID' => $id, 'plantOid' => $plantOid} ); + $res = $res->decoded_content(); + Log3 ($name, 3, "$name - Set \"$d $op\" result: ".$res); + if($res eq "true") { + $state = "ok - switched consumer $d to $op"; + BlockingInformParent("FHEM::SMAPortal::setFromBlocking", [$name, "all", "none"], 0); + } else { + $state = "Error - couldn't switched consumer $d to $op"; } } - # JSON Consumer Livedaten und historische Energiedaten - if($dl > 2) { - Log3 ($name, 4, "$name - Getting consumer live data"); - - my $consumerlivedata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues'); + ### Daten abrufen mit GET + if($get ne "none") { - Log3 ($name, 5, "$name - Return Code: ".$consumerlivedata->code) if($v5d eq "consumerLiveData"); + # JSON Wetterdaten + Log3 ($name, 4, "$name - Getting weather data"); + my $weatherdata = $ua->get('https://www.sunnyportal.com/Dashboard/Weather'); + $weatherdata_content = $weatherdata->content; + Log3 ($name, 5, "$name - Data received:\n".Dumper decode_json($weatherdata_content)) if($v5d eq "weatherData"); + + # JSON Forecast Daten + my $dl = AttrVal($name, "detailLevel", 1); + if($dl > 1) { + Log3 ($name, 4, "$name - Getting forecast data"); - if ($consumerlivedata->content =~ m/HoManConsumerLiveData/i) { - $consumerlivedata_content = $consumerlivedata->content; - Log3 ($name, 5, "$name - Consumer live data received:\n".Dumper decode_json($consumerlivedata_content)) if($v5d eq "consumerLiveData"); + my $forecast_page = $ua->get('https://www.sunnyportal.com/HoMan/Forecast/LoadRecommendationData'); + Log3 ($name, 5, "$name - Return Code: ".$forecast_page->code) if($v5d eq "forecastData"); + + if ($forecast_page->content =~ m/ForecastChartDataPoint/i) { + $forecast_content = $forecast_page->content; + Log3 ($name, 5, "$name - Forecast data received:\n".Dumper decode_json($forecast_content)) if($v5d eq "forecastData"); + } } - if($hash->{HELPER}{PLANTOID}) { - my $PlantOid = $hash->{HELPER}{PLANTOID}; - my $dds = (split(/\s+/,TimeNow()))[0]; - my $dde = (split(/\s+/,FmtDateTime(time()+86400)))[0]; - $dds =~ /(.*)-(.*)-(.*)/; - my $mds = "$1-$2-01"; - my $me = (($2+1)<=12)?$2+1:1; - $me = sprintf("%02d", $me); - my $ye = ($2>$me)?$1+1:$1; - my $mde = "$ye-$me-01"; - my $yds = "$1-01-01"; - my $yde = ($1+1)."-01-01"; - - # Energiedaten aktueller Tag - Log3 ($name, 4, "$name - Getting consumer energy data of current day"); - Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde"); - my $ccdaydata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=2&'.$PlantOid.'&StartTime='.$dds.'&EndTime='.$dde.''); - - Log3 ($name, 5, "$name - Return Code: ".$ccdaydata->code) if($v5d eq "consumerDayData"); + # JSON Consumer Livedaten und historische Energiedaten + if($dl > 2) { + Log3 ($name, 4, "$name - Getting consumer live data"); - if ($ccdaydata->content =~ m/ConsumerBalanceDeviceInfo/i) { - $ccdaydata_content = $ccdaydata->content; - Log3 ($name, 5, "$name - Consumer energy data of current day received:\n".Dumper decode_json($ccdaydata_content)) if($v5d eq "consumerDayData"); + my $consumerlivedata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetLiveProxyValues'); + + Log3 ($name, 5, "$name - Return Code: ".$consumerlivedata->code) if($v5d eq "consumerLiveData"); + + if ($consumerlivedata->content =~ m/HoManConsumerLiveData/i) { + $consumerlivedata_content = $consumerlivedata->content; + Log3 ($name, 5, "$name - Consumer live data received:\n".Dumper decode_json($consumerlivedata_content)) if($v5d eq "consumerLiveData"); } - - # Energiedaten aktueller Monat - Log3 ($name, 4, "$name - Getting consumer energy data of current month"); - Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde"); - my $ccmonthdata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=4&'.$PlantOid.'&StartTime='.$mds.'&EndTime='.$mde.''); - Log3 ($name, 5, "$name - Return Code: ".$ccmonthdata->code) if($v5d eq "consumerMonthData"); + if($hash->{HELPER}{PLANTOID}) { + my $PlantOid = $hash->{HELPER}{PLANTOID}; + my $dds = (split(/\s+/,TimeNow()))[0]; + my $dde = (split(/\s+/,FmtDateTime(time()+86400)))[0]; + $dds =~ /(.*)-(.*)-(.*)/; + my $mds = "$1-$2-01"; + my $me = (($2+1)<=12)?$2+1:1; + $me = sprintf("%02d", $me); + my $ye = ($2>$me)?$1+1:$1; + my $mde = "$ye-$me-01"; + my $yds = "$1-01-01"; + my $yde = ($1+1)."-01-01"; + + # Energiedaten aktueller Tag + Log3 ($name, 4, "$name - Getting consumer energy data of current day"); + Log3 ($name, 4, "$name - Request date -> start: $dds, end: $dde"); + my $ccdaydata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=2&'.$PlantOid.'&StartTime='.$dds.'&EndTime='.$dde.''); + + Log3 ($name, 5, "$name - Return Code: ".$ccdaydata->code) if($v5d eq "consumerDayData"); - if ($ccmonthdata->content =~ m/ConsumerBalanceDeviceInfo/i) { - $ccmonthdata_content = $ccmonthdata->content; - Log3 ($name, 5, "$name - Consumer energy data of current month received:\n".Dumper decode_json($ccmonthdata_content)) if($v5d eq "consumerMonthData"); - } + if ($ccdaydata->content =~ m/ConsumerBalanceDeviceInfo/i) { + $ccdaydata_content = $ccdaydata->content; + Log3 ($name, 5, "$name - Consumer energy data of current day received:\n".Dumper decode_json($ccdaydata_content)) if($v5d eq "consumerDayData"); + } - # Energiedaten aktuelles Jahr - Log3 ($name, 4, "$name - Getting consumer energy data of current year"); - Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde"); - my $ccyeardata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=5&'.$PlantOid.'&StartTime='.$yds.'&EndTime='.$yde.''); - - Log3 ($name, 5, "$name - Return Code: ".$ccyeardata->code) if($v5d eq "consumerMonthData"); + # Energiedaten aktueller Monat + Log3 ($name, 4, "$name - Getting consumer energy data of current month"); + Log3 ($name, 4, "$name - Request date -> start: $mds, end: $mde"); + my $ccmonthdata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=4&'.$PlantOid.'&StartTime='.$mds.'&EndTime='.$mde.''); + + Log3 ($name, 5, "$name - Return Code: ".$ccmonthdata->code) if($v5d eq "consumerMonthData"); - if ($ccyeardata->content =~ m/ConsumerBalanceDeviceInfo/i) { - $ccyeardata_content = $ccyeardata->content; - Log3 ($name, 5, "$name - Consumer energy data of current year received:\n".Dumper decode_json($ccyeardata_content)) if($v5d eq "consumerYearData"); - } + if ($ccmonthdata->content =~ m/ConsumerBalanceDeviceInfo/i) { + $ccmonthdata_content = $ccmonthdata->content; + Log3 ($name, 5, "$name - Consumer energy data of current month received:\n".Dumper decode_json($ccmonthdata_content)) if($v5d eq "consumerMonthData"); + } + + # Energiedaten aktuelles Jahr + Log3 ($name, 4, "$name - Getting consumer energy data of current year"); + Log3 ($name, 4, "$name - Request date -> start: $yds, end: $yde"); + my $ccyeardata = $ua->get('https://www.sunnyportal.com/Homan/ConsumerBalance/GetMeasuredValues?IntervalId=5&'.$PlantOid.'&StartTime='.$yds.'&EndTime='.$yde.''); + + Log3 ($name, 5, "$name - Return Code: ".$ccyeardata->code) if($v5d eq "consumerMonthData"); + + if ($ccyeardata->content =~ m/ConsumerBalanceDeviceInfo/i) { + $ccyeardata_content = $ccyeardata->content; + Log3 ($name, 5, "$name - Consumer energy data of current year received:\n".Dumper decode_json($ccyeardata_content)) if($v5d eq "consumerYearData"); + } + } } } @@ -763,18 +831,19 @@ sub GetData($) { } my ($reread,$retry) = analivedat($hash,$livedata_content); - - # Daten müssen als Einzeiler zurückgegeben werden - my ($lc,$fc,$wc,$cl,$cd,$cm,$cy) = ("","","","","","",""); - $lc = encode_base64($livedata_content,""); - $fc = encode_base64($forecast_content,"") if($forecast_content); - $wc = encode_base64($weatherdata_content,"") if($weatherdata_content); - $cl = encode_base64($consumerlivedata_content,"") if($consumerlivedata_content); - $cd = encode_base64($ccdaydata_content,"") if($ccdaydata_content); - $cm = encode_base64($ccmonthdata_content,"") if($ccmonthdata_content); - $cy = encode_base64($ccyeardata_content,"") if($ccyeardata_content); -return "$name|$login_state|$reread|$retry|$lc|$fc|$wc|$cl|$cd|$cm|$cy"; + # Daten müssen als Einzeiler zurückgegeben werden + my ($st,$lc,$fc,$wc,$cl,$cd,$cm,$cy) = ("","","","","","","",""); + $st = encode_base64($state,""); + $lc = encode_base64($livedata_content,""); + $fc = encode_base64($forecast_content,"") if($forecast_content); + $wc = encode_base64($weatherdata_content,"") if($weatherdata_content); + $cl = encode_base64($consumerlivedata_content,"") if($consumerlivedata_content); + $cd = encode_base64($ccdaydata_content,"") if($ccdaydata_content); + $cm = encode_base64($ccmonthdata_content,"") if($ccmonthdata_content); + $cy = encode_base64($ccyeardata_content,"") if($ccyeardata_content); + +return "$name|$login_state|$reread|$retry|$get|$set|$st|$lc|$fc|$wc|$cl|$cd|$cm|$cy"; } ################################################################ @@ -788,13 +857,16 @@ sub ParseData($) { my $login_state = $a[1]; my $reread = $a[2]; my $retry = $a[3]; - my $lc = decode_base64($a[4]); - my $fc = decode_base64($a[5]) if($a[5]); - my $wc = decode_base64($a[6]) if($a[6]); - my $cl = decode_base64($a[7]) if($a[7]); - my $cd = decode_base64($a[8]) if($a[8]); - my $cm = decode_base64($a[9]) if($a[9]); - my $cy = decode_base64($a[10]) if($a[10]); + my $get = $a[4]; + my $set = $a[5]; + my $state = decode_base64($a[6]); + my $lc = decode_base64($a[7]); + my $fc = decode_base64($a[8]) if($a[8]); + my $wc = decode_base64($a[9]) if($a[9]); + my $cl = decode_base64($a[10]) if($a[10]); + my $cd = decode_base64($a[11]) if($a[11]); + my $cm = decode_base64($a[12]) if($a[12]); + my $cy = decode_base64($a[13]) if($a[13]); my $livedata_content = decode_json($lc); my $forecast_content = decode_json($fc) if($fc); @@ -804,15 +876,13 @@ sub ParseData($) { my $ccmonthdata_content = decode_json($cm) if($cm); my $ccyeardata_content = decode_json($cy) if($cy); - my $state = "ok"; - my $timeout = AttrVal($name, "timeout", 30); if($reread) { # login war erfolgreich, aber Daten müssen jetzt noch gelesen werden delete($hash->{HELPER}{RUNNING_PID}); readingsSingleUpdate($hash, "L1_Login-Status", "successful", 1); $hash->{HELPER}{oldlogintime} = gettimeofday(); - $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetData", $name, "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); + $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetSetData", "$name|$get|$set", "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); $hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057 return; } @@ -893,9 +963,9 @@ sub ParseData($) { $batteryout = 1; } - $errMsg = 1 if($k =~ /^ErrorMessages$/); - $warnMsg = 1 if($k =~ /^WarningMessages$/); - $infoMsg = 1 if($k =~ /^InfoMessages$/); + $errMsg = 1 if($k =~ /^ErrorMessages$/); + $warnMsg = 1 if($k =~ /^WarningMessages$/); + $infoMsg = 1 if($k =~ /^InfoMessages$/); Log3 $name, 4, "$name -> $k - $new_val"; readingsBulkUpdate($hash, "L1_$k", $new_val); @@ -965,12 +1035,19 @@ sub ParseData($) { readingsBeginUpdate($hash); if($login_state) { + if($set ne "none") { + my ($d,$op) = split(":",$set); + $op = ($op eq "auto")?"off (automatic)":$op; + readingsBulkUpdate($hash, "L3_${d}_Switch", $op); + } readingsBulkUpdate($hash, "state", $state); readingsBulkUpdate($hash, "summary", "$sum W"); } readingsEndUpdate($hash, 1); delete($hash->{HELPER}{RUNNING_PID}); + $hash->{HELPER}{GETTER} = "all"; + $hash->{HELPER}{SETTER} = "none"; SPGRefresh($hash,0,1); return; @@ -987,6 +1064,8 @@ sub ParseAborted($) { Log3 ($name, 1, "$name -> BlockingCall $hash->{HELPER}{RUNNING_PID}{fn} pid:$hash->{HELPER}{RUNNING_PID}{pid} $cause"); delete($hash->{HELPER}{RUNNING_PID}); + $hash->{HELPER}{GETTER} = "all"; + $hash->{HELPER}{SETTER} = "none"; return; } @@ -1567,6 +1646,19 @@ sub delread($;$) { return; } +################################################################ +# +################################################################ +sub setFromBlocking($$$) { + my ($name,$get,$set) = @_; + my $hash = $defs{$name}; + + $hash->{HELPER}{GETTER} = $get; + $hash->{HELPER}{SETTER} = $set; + +return; +} + ################################################################ # analysiere Livedaten ################################################################ @@ -1626,8 +1718,11 @@ sub retrygetdata($) { my ($hash) = @_; my $name = $hash->{NAME}; my $timeout = AttrVal($name, "timeout", 30); + + my $get = $hash->{HELPER}{GETTER}; + my $set = $hash->{HELPER}{SETTER}; - $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetData", $name, "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); + $hash->{HELPER}{RUNNING_PID} = BlockingCall("FHEM::SMAPortal::GetSetData", "$name|$get|$set", "FHEM::SMAPortal::ParseData", $timeout, "FHEM::SMAPortal::ParseAborted", $hash); $hash->{HELPER}{RUNNING_PID}{loglevel} = 5 if($hash->{HELPER}{RUNNING_PID}); # Forum #77057 return; @@ -1737,18 +1832,23 @@ sub PortalAsHtml ($$) { ($legend_style, $legend) = split('_',AttrVal($wlname,'consumerLegend','icon_top')); $legend = '' if(($legend_style eq 'none') || (!int(@pgCDev))); - + + # Verbraucherlegende und Steuerung if ($legend) { foreach (@pgCDev) { my($txt,$im) = split(':',$_); # $txt ist der Verbrauchername - my $swstate = ReadingsVal($name,"L3_".$txt."_Switch", "undef"); + my $cmdon = "\"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name $txt on')\""; + my $cmdoff = "\"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name $txt off')\""; + my $cmdauto = "\"FW_cmd('$FW_ME$FW_subdir?XHR=1&cmd=set $name $txt auto')\""; + + my $swstate = ReadingsVal($name,"L3_".$txt."_Switch", "undef"); my $swicon = ""; if($swstate eq "off") { - $swicon = ""; + $swicon = ""; } elsif ($swstate eq "on") { - $swicon = ""; + $swicon = ""; } elsif ($swstate =~ /off.*automatic.*/i) { - $swicon = ""; + $swicon = ""; } if ($legend_style eq 'icon') { # mögliche Umbruchstellen mit normalen Blanks vorsehen ! @@ -2531,6 +2631,15 @@ return;
  • set <name> credentials <username> <password>
  • Setzt Username / Passwort zum Login in das SMA Sunny Portal. +
    + + +