diff --git a/fhem/CHANGED b/fhem/CHANGED index 15a85b5ba..059ef9561 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,7 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - bugfix: 72_XiaomiDevice: better handling of definition w/ missing token + - change: 32_withings: add in_bed for sleep trackers, ignore inactive users - change: 57_Calendar: new attribute quirks with ignoreDtStamp value. - change: 57_Calendar: cutoffOlderThan also removes recurring events when the series has ended. diff --git a/fhem/FHEM/32_withings.pm b/fhem/FHEM/32_withings.pm index bdd0415d2..9551c6af8 100644 --- a/fhem/FHEM/32_withings.pm +++ b/fhem/FHEM/32_withings.pm @@ -10,7 +10,7 @@ # # ############################################################################## -# Release 07 / 2018-09-18 +# Release 08 / 2018-09-28 package main; @@ -341,14 +341,18 @@ sub withings_Define($$) { CommandAttr(undef,"$name IODev $a[4]"); - } elsif( @a == 4 && $a[2] =~ m/^\d+$/ && $a[3] =~ m/^[\w-]+$/i ) { + } elsif( @a == 4 && $a[2] =~ m/^\d+$/ && $a[3] =~ m/^[\w:-]+$/i ) { $subtype = "USER"; my $user = $a[2]; my $key = $a[3]; + my $accesskey = withings_encrypt($key); + Log3 $name, 3, "$name: encrypt $key to $accesskey" if($key ne $accesskey); + $hash->{DEF} = "$user $accesskey"; + $hash->{User} = $user; - $hash->{Key} = $key; + #$hash->{Key} = $accesskey; #not needed my $d = $modules{$hash->{TYPE}}{defptr}{"U$user"}; return "device $user already defined as $d->{NAME}" if( defined($d) && $d->{NAME} ne $name ); @@ -380,7 +384,7 @@ sub withings_Define($$) { } $hash->{NAME} = $name; - $hash->{SUBTYPE} = $subtype; + $hash->{SUBTYPE} = $subtype if(defined($subtype)); #CommandAttr(undef,"$name DbLogExclude .*"); @@ -527,7 +531,7 @@ sub withings_getSessionKey($) { if(!defined($resolve)) { $hash->{SessionTimestamp} = 0; - Log3 "withings", 1, "$name: DNS error on getSessionData"; + Log3 $name, 1, "$name: DNS error on getSessionData"; return undef; } @@ -543,18 +547,18 @@ sub withings_getSessionKey($) { # }); # if($err0 || !defined($data0)) # { - # Log3 "withings", 1, "$name: appliver call failed! ".$err0; + # Log3 $name, 1, "$name: appliver call failed! ".$err0; # return undef; # } # $data1 = $data0; # $data0 =~ /appliver=([^.*]+)\&/; # $hash->{helper}{appliver} = $1; # if(!defined($hash->{helper}{appliver})) { - # Log3 "withings", 1, "$name: APPLIVER ERROR "; + # Log3 $name, 1, "$name: APPLIVER ERROR "; # $hash->{STATE} = "APPLIVER error"; # return undef; # } - # Log3 "withings", 4, "$name: appliver ".$hash->{helper}{appliver}; + # Log3 $name, 4, "$name: appliver ".$hash->{helper}{appliver}; # #} # # @@ -564,11 +568,11 @@ sub withings_getSessionKey($) { # $hash->{helper}{csrf_token} = $1; # # if(!defined($hash->{helper}{csrf_token})) { - # Log3 "withings", 1, "$name: CSRF ERROR "; + # Log3 $name, 1, "$name: CSRF ERROR "; # $hash->{STATE} = "CSRF error"; # return undef; # } - # Log3 "withings", 4, "$name: csrf_token ".$hash->{helper}{csrf_token}; + # Log3 $name, 4, "$name: csrf_token ".$hash->{helper}{csrf_token}; #} #my $ua = LWP::UserAgent->new; @@ -580,7 +584,7 @@ sub withings_getSessionKey($) { # $resolve = inet_aton("account.withings.com"); # if(!defined($resolve)) # { - # Log3 "withings", 1, "$name: DNS error on getSessionKey."; + # Log3 $name, 1, "$name: DNS error on getSessionKey."; # return undef; # } @@ -596,7 +600,7 @@ sub withings_getSessionKey($) { if ($err || !defined($data) || $data =~ /Authentification failed/ || $data =~ /not a valid/) { - Log3 "withings", 1, "$name: LOGIN ERROR "; + Log3 $name, 1, "$name: LOGIN ERROR "; $hash->{STATE} = "Login error"; return undef; } @@ -608,12 +612,12 @@ sub withings_getSessionKey($) { $hash->{SessionTimestamp} = (gettimeofday())[0] if( $hash->{SessionKey} ); $hash->{STATE} = "Connected" if( $hash->{SessionKey} ); $hash->{STATE} = "Session error" if( !$hash->{SessionKey} ); - Log3 "withings", 4, "$name: sessionkey ".$hash->{SessionKey}; + Log3 $name, 4, "$name: sessionkey ".$hash->{SessionKey}; } else { $hash->{STATE} = "Cookie error"; - Log3 "withings", 1, "$name: COOKIE ERROR "; + Log3 $name, 1, "$name: COOKIE ERROR "; $hash->{helper}{appliver} = '9855c478'; $hash->{helper}{csrf_token} = '9855c478'; return undef; @@ -648,15 +652,15 @@ sub withings_getSessionKey($) { } else { - Log3 "withings", 4, "$name: account email: ".$account->{email}; + Log3 $name, 4, "$name: account email: ".$account->{email}; } } - Log3 "withings", 4, "$name: accountid ".$hash->{AccountID}; + Log3 $name, 4, "$name: accountid ".$hash->{AccountID}; } else { $hash->{STATE} = "Account error"; - Log3 "withings", 1, "$name: ACCOUNT ERROR "; + Log3 $name, 1, "$name: ACCOUNT ERROR "; return undef; } } @@ -667,16 +671,15 @@ sub withings_getSessionKey($) { sub withings_connect($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: connect"; + Log3 $name, 5, "$name: connect"; $hash->{'.https'} = "https"; $hash->{'.https'} = "http" if( AttrVal($name, "nossl", 0) ); - #my $cmdret= CommandAttr(undef,"$name room WithingsTest"); - #$cmdret= CommandAttr(undef,"$name verbose 5"); - withings_getSessionKey( $hash ); + return undef; #no more autocreate on start + foreach my $d (keys %defs) { next if(!defined($defs{$d})); next if($defs{$d}{TYPE} ne "autocreate"); @@ -691,11 +694,12 @@ sub withings_connect($) { Log3 $name, 2, "$name: user '$user->{id}' already defined"; next; } - next if($user->{firstname} eq "Repository-User"); + next if($user->{usertype} ne "1" || $user->{status} ne "0"); my $id = $user->{id}; my $devname = "withings_U". $id; - my $define= "$devname withings $id $user->{publickey}"; + my $publickey = withings_encrypt($user->{publickey}); + my $define= "$devname withings $id $publickey"; Log3 $name, 2, "$name: create new device '$devname' for user '$id'"; @@ -761,7 +765,7 @@ sub withings_connect($) { sub withings_autocreate($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: autocreate"; + Log3 $name, 5, "$name: autocreate"; $hash->{'.https'} = "https"; $hash->{'.https'} = "http" if( AttrVal($name, "nossl", 0) ); @@ -777,11 +781,12 @@ sub withings_autocreate($) { Log3 $name, 2, "$name: user '$user->{id}' already defined"; next; } - next if($user->{firstname} eq "Repository-User"); + next if($user->{usertype} ne "1" || $user->{status} ne "0"); my $id = $user->{id}; my $devname = "withings_U". $id; - my $define= "$devname withings $id $user->{publickey}"; + my $publickey = withings_encrypt($user->{publickey}); + my $define= "$devname withings $id $publickey"; Log3 $name, 2, "$name: create new device '$devname' for user '$id'"; @@ -844,7 +849,7 @@ sub withings_autocreate($) { sub withings_initDevice($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: initdevice ".$hash->{Device}; + Log3 $name, 5, "$name: initdevice ".$hash->{Device}; AssignIoPort($hash); if(defined($hash->{IODev}->{NAME})) { @@ -904,7 +909,7 @@ sub withings_initDevice($) { sub withings_initUser($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: inituser ".$hash->{User}; + Log3 $name, 5, "$name: inituser ".$hash->{User}; AssignIoPort($hash); if(defined($hash->{IODev}->{NAME})) { @@ -936,7 +941,7 @@ sub withings_initUser($) { sub withings_getUsers($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getusers"; + Log3 $name, 5, "$name: getusers"; withings_getSessionKey($hash); @@ -977,7 +982,7 @@ sub withings_getUsers($) { sub withings_getDevices($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getdevices"; + Log3 $name, 5, "$name: getdevices"; withings_getSessionKey($hash); @@ -1002,7 +1007,7 @@ sub withings_getDevices($) { return undef; } Log3 $name, 1, "withings: getDevices json error ".$json->{error} if(defined($json->{error})); - Log3 "withings", 5, "$name: getdevices ".Dumper($json); + Log3 $name, 5, "$name: getdevices ".Dumper($json); my @devices = (); foreach my $association (@{$json->{body}{associations}}) { @@ -1018,7 +1023,7 @@ sub withings_getDevices($) { sub withings_getDeviceDetail($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getdevicedetail ".$hash->{Device}; + Log3 $name, 5, "$name: getdevicedetail ".$hash->{Device}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1030,7 +1035,7 @@ sub withings_getDeviceDetail($) { data => {sessionid => $hash->{IODev}->{SessionKey}, deviceid => $hash->{Device} , appname => 'my2', appliver=> $hash->{IODev}->{helper}{appliver}, apppfm => 'web', action => 'getproperties'}, }); - #Log3 "withings", 5, "$name: getdevicedetaildata ".Dumper($data); + #Log3 $name, 5, "$name: getdevicedetaildata ".Dumper($data); return undef if(!defined($data)); my $json = eval { JSON->new->utf8(0)->decode($data) }; @@ -1066,7 +1071,7 @@ sub withings_getDeviceDetail($) { sub withings_getDeviceLink($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getdevicelink ".$hash->{Device}; + Log3 $name, 5, "$name: getdevicelink ".$hash->{Device}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1110,7 +1115,7 @@ sub withings_getDeviceProperties($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getdeviceproperties ".$hash->{Device}; + Log3 $name, 5, "$name: getdeviceproperties ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1140,7 +1145,7 @@ sub withings_getDeviceProperties($) { sub withings_getDeviceReadingsScale($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getscalereadings ".$hash->{Device}; + Log3 $name, 5, "$name: getscalereadings ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1175,7 +1180,7 @@ sub withings_getDeviceReadingsScale($) { sub withings_getDeviceReadingsBedside($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getaurareadings ".$hash->{Device}; + Log3 $name, 5, "$name: getaurareadings ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1210,7 +1215,7 @@ sub withings_getDeviceReadingsBedside($) { sub withings_getDeviceReadingsHome($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: gethomereadings ".$hash->{Device}; + Log3 $name, 5, "$name: gethomereadings ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1245,7 +1250,7 @@ sub withings_getDeviceReadingsHome($) { sub withings_getDeviceEventsBaby($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getbabyevents ".$hash->{Device}; + Log3 $name, 5, "$name: getbabyevents ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1280,7 +1285,7 @@ sub withings_getDeviceEventsBaby($) { sub withings_getDeviceAlertsHome($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: gethomealerts ".$hash->{Device}; + Log3 $name, 5, "$name: gethomealerts ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1313,7 +1318,7 @@ sub withings_getDeviceAlertsHome($) { sub withings_getDeviceAlertsBaby($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getbabyevents ".$hash->{Device}; + Log3 $name, 5, "$name: getbabyevents ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1345,7 +1350,7 @@ sub withings_getDeviceAlertsBaby($) { sub withings_getVideoLink($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getbabyvideo ".$hash->{Device}; + Log3 $name, 5, "$name: getbabyvideo ".$hash->{Device}; return undef if( !defined($hash->{Device}) ); return undef if( !defined($hash->{IODev}) ); @@ -1384,7 +1389,7 @@ sub withings_getS3Credentials($) { return undef if( $hash->{sts_expiretime} && $hash->{sts_expiretime} > time - 3600 ); # min 1h return undef if( !defined($hash->{IODev}) ); - Log3 "withings", 5, "$name: gets3credentials ".$hash->{Device}; + Log3 $name, 5, "$name: gets3credentials ".$hash->{Device}; withings_getSessionKey( $hash->{IODev} ); @@ -1442,7 +1447,7 @@ sub withings_signS3Link($$$;$) { sub withings_getUserDetail($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getuserdetails ".$hash->{User}; + Log3 $name, 5, "$name: getuserdetails ".$hash->{User}; return undef if( !defined($hash->{User}) ); return undef if( $hash->{SUBTYPE} ne "USER" ); @@ -1495,14 +1500,14 @@ sub withings_poll($;$) { if( $hash->{SUBTYPE} eq "DEVICE" ) { my $intervalData = AttrVal($name,"intervalData",900); - my $intervalDebug = AttrVal($name,"intervalDebug",900); + my $intervalDebug = AttrVal($name,"intervalDebug",AttrVal($name,"intervalData",900)); + my $intervalProperties = AttrVal($name,"intervalProperties",AttrVal($name,"intervalData",900)); my $lastData = ReadingsVal( $name, ".pollData", 0 ); my $lastDebug = ReadingsVal( $name, ".pollDebug", 0 ); - my $intervalProperties = AttrVal($name,"intervalProperties",43200); my $lastProperties = ReadingsVal( $name, ".pollProperties", 0 ); if(defined($hash->{modelID}) && $hash->{modelID} eq '4') { - withings_getDeviceProperties($hash) if($force > 1 || $lastData <= ($now - $intervalData)); + withings_getDeviceProperties($hash) if($force > 1 || $lastProperties <= ($now - $intervalProperties)); withings_getDeviceReadingsScale($hash) if($force || $lastData <= ($now - $intervalData)); } elsif(defined($hash->{modelID}) && $hash->{modelID} eq '21') { @@ -1563,7 +1568,7 @@ sub withings_poll($;$) { sub withings_getUserReadingsDaily($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getuserdailystats ".$hash->{User}; + Log3 $name, 5, "$name: getuserdailystats ".$hash->{User}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1630,7 +1635,7 @@ sub withings_getUserReadingsDaily($) { sub withings_getUserReadingsCommon($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getuserreadings ".$hash->{User}; + Log3 $name, 5, "$name: getuserreadings ".$hash->{User}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1666,7 +1671,7 @@ sub withings_getUserReadingsCommon($) { sub withings_getUserReadingsSleep($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getsleepreadings ".$hash->{User}; + Log3 $name, 5, "$name: getsleepreadings ".$hash->{User}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1701,7 +1706,7 @@ sub withings_getUserReadingsSleep($) { sub withings_getUserReadingsSleepDebug($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getsleepreadingsdebug ".$hash->{User}; + Log3 $name, 5, "$name: getsleepreadingsdebug ".$hash->{User}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1737,7 +1742,7 @@ sub withings_getUserReadingsActivity($) { my ($hash) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: getactivityreadings ".$hash->{User}; + Log3 $name, 5, "$name: getactivityreadings ".$hash->{User}; return undef if( !defined($hash->{IODev}) ); withings_getSessionKey( $hash->{IODev} ); @@ -1748,7 +1753,7 @@ sub withings_getUserReadingsActivity($) { my $enddate = ($lastupdate+(8*60*60)); $enddate = $now if ($enddate > $now); - Log3 "withings", 5, "$name: getactivityreadings ".$lastupdate." to ".$enddate; + Log3 $name, 5, "$name: getactivityreadings ".$lastupdate." to ".$enddate; HttpUtils_NonblockingGet({ url => "https://scalews.withings.com/cgi-bin/v2/measure", @@ -1776,7 +1781,7 @@ sub withings_parseProperties($$) { my ($hash,$json) = @_; my $name = $hash->{NAME}; - Log3 "withings", 5, "$name: parsedevice"; + Log3 $name, 5, "$name: parsedevice"; #parse my $detail = $json->{body}; @@ -1799,7 +1804,7 @@ sub withings_parseMeasureGroups($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parsemeasuregroups"; + Log3 $name, 5, "$name: parsemeasuregroups"; my ($now) = int(time); my $lastupdate = ReadingsVal( $name, ".lastData", ($now-21*24*60*60) ); my $newlastupdate = $lastupdate; @@ -1858,7 +1863,7 @@ sub withings_parseMeasureGroups($$) { delete $hash->{CHANGETIME}; - Log3 $name, 3, "$name: got ".$i.' entries from MeasureGroups (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from MeasureGroups (latest: '.FmtDateTime($newlastupdate).')'; } @@ -1868,7 +1873,7 @@ sub withings_parseMeasurements($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 4, "$name: parsemeasurements"; + Log3 $name, 4, "$name: parsemeasurements"; my ($now) = time; my $lastupdate = ReadingsVal( $name, ".lastData", ($now-21*24*60*60) ); my $newlastupdate = $lastupdate; @@ -1940,7 +1945,7 @@ sub withings_parseMeasurements($$) { delete $hash->{CHANGETIME}; - Log3 $name, 3, "$name: got ".$i.' entries from Measurements (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Measurements (latest: '.FmtDateTime($newlastupdate).')'; } @@ -1956,7 +1961,7 @@ sub withings_parseAggregate($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parseaggregate"; + Log3 $name, 5, "$name: parseaggregate"; #return undef; my ($now) = time; @@ -2056,7 +2061,7 @@ sub withings_parseAggregate($$) { delete $hash->{CHANGETIME}; - Log3 $name, 4, "$name: got ".$i.' entries from Aggregate (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Aggregate (latest: '.FmtDateTime($newlastupdate).')'; } @@ -2071,7 +2076,7 @@ sub withings_parseActivity($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parseactivity"; + Log3 $name, 5, "$name: parseactivity"; my ($now) = time; my $lastupdate = ReadingsVal( $name, ".lastActivity", ($now-21*24*60*60) ); @@ -2152,7 +2157,7 @@ sub withings_parseActivity($$) { delete $hash->{CHANGETIME}; - Log3 $name, 4, "$name: got ".$i.' entries from Activity (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Activity (latest: '.FmtDateTime($newlastupdate).')'; } @@ -2167,7 +2172,7 @@ sub withings_parseWorkouts($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 1, "$name: parseworkouts\n".Dumper($json); + Log3 $name, 1, "$name: parseworkouts\n".Dumper($json); return undef; @@ -2180,7 +2185,7 @@ sub withings_parseVasistas($$;$) { my ($hash, $json, $datatype) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parsevasistas"; + Log3 $name, 5, "$name: parsevasistas"; my ($now) = time; my $lastupdate = ReadingsVal( $name, ".lastData", ($now-21*24*60*60) ); @@ -2196,7 +2201,7 @@ sub withings_parseVasistas($$;$) { my $readingsdate; my $newlastupdate = $lastupdate; - + my $iscurrent = 0; foreach my $series ( @{$json->{body}{series}}) { $j=0; @@ -2252,7 +2257,19 @@ sub withings_parseVasistas($$;$) { $newlastupdate = $readingsdate if($readingsdate > $newlastupdate); $i++; } - +#start in-bed detection + if($iscurrent == 0 && $datatype =~ /Sleep/){ + if($i>40 && $readingsdate > time()-3600){ + $iscurrent = 1; + #Log3 $name, 1, "$name: in-bed: ".FmtDateTime($readingsdate) if($i>0); + readingsBeginUpdate($hash); + $hash->{".updateTimestamp"} = FmtDateTime($readingsdate); + readingsBulkUpdate( $hash, "in_bed", 1, 1 ); + $hash->{CHANGETIME}[0] = FmtDateTime($readingsdate); + readingsEndUpdate($hash,1); + } + } +#end in-bed detection } } } @@ -2263,6 +2280,15 @@ sub withings_parseVasistas($$;$) { $newlastupdate = $device->{lastsessiondate} if($device->{lastsessiondate} and $device->{lastsessiondate} < $newlastupdate); $newlastupdate = $device->{lastweighindate} if($device->{lastweighindate} and $device->{lastweighindate} < $newlastupdate); + #start in-bed detection + if($datatype =~ /Sleep/ && $iscurrent == 0){ + if($device->{lastweighindate} > (time()-1800)){ + readingsSingleUpdate( $hash, "in_bed", 1, 1 ); + } else { + readingsSingleUpdate( $hash, "in_bed", 0, 1 ); + } + } + #end in-bed detection } $newlastupdate = $now if($newlastupdate > $now); if($newlastupdate < ($lastupdate-1)) @@ -2284,7 +2310,7 @@ sub withings_parseVasistas($$;$) { readingsSingleUpdate( $hash, ".lastData", $newlastupdate, 0 ); } - Log3 $name, 4, "$name: got ".$i.' entries from Vasistas (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Vasistas (latest: '.FmtDateTime($newlastupdate).')'; } } @@ -2297,7 +2323,7 @@ sub withings_parseTimeline($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parsemetimeline "; + Log3 $name, 5, "$name: parsemetimeline "; my ($now) = time; my $lastupdate = ReadingsVal( $name, ".lastAlert", ($now-21*24*60*60) ); @@ -2321,12 +2347,12 @@ sub withings_parseTimeline($$) { } elsif($event->{class} eq 'deleted') { - Log3 "withings", 5, "withings: event " . FmtDateTime($event->{epoch})." Event was deleted"; + Log3 $name, 5, "withings: event " . FmtDateTime($event->{epoch})." Event was deleted"; next; } elsif($event->{class} ne 'noise_detected' && $event->{class} ne 'movement_detected' && $event->{class} ne 'alert_environment' && $event->{class} ne 'offline' && $event->{class} ne 'online' && $event->{class} ne 'snapshot') { - Log3 "withings", 2, "withings: alert class unknown " . $event->{class}; + Log3 $name, 2, "withings: alert class unknown " . $event->{class}; next; } @@ -2377,7 +2403,7 @@ sub withings_parseTimeline($$) { delete $hash->{CHANGETIME}; - Log3 $name, 4, "$name: got ".$i.' entries from Timeline (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Timeline (latest: '.FmtDateTime($newlastupdate).')'; } @@ -2388,7 +2414,7 @@ sub withings_parseEvents($$) { my ($hash, $json) = @_; my $name = $hash->{NAME}; #parse - Log3 "withings", 5, "$name: parseevents"; + Log3 $name, 5, "$name: parseevents"; my ($now) = time; my $lastupdate = ReadingsVal( $name, ".lastData", ($now-21*24*60*60) ); my $lastalertupdate = ReadingsVal( $name, ".lastAlert", ($now-21*24*60*60) ); @@ -2410,7 +2436,7 @@ sub withings_parseEvents($$) { $hash->{".updateTimestamp"} = FmtDateTime($event->{date}); my $changeindex = 0; - #Log3 "withings", 5, "withings: event " . FmtDateTime($event->{date})." ".$event->{type}." ".$event->{activated}."/".$event->{measure}{value}; + #Log3 $name, 5, "withings: event " . FmtDateTime($event->{date})." ".$event->{type}." ".$event->{activated}."/".$event->{measure}{value}; my $reading = $event_types{$event->{type}}->{reading}; my $value = "notice"; @@ -2482,7 +2508,7 @@ sub withings_parseEvents($$) { delete $hash->{CHANGETIME}; - Log3 $name, 4, "$name: got ".$i.' entries from Events (latest: '.FmtDateTime($newlastupdate).')'; + Log3 $name, (($i>0)?3:4), "$name: got ".$i.' entries from Events (latest: '.FmtDateTime($newlastupdate).')'; } @@ -2550,10 +2576,10 @@ sub withings_Get($$@) { my $users = withings_getUsers($hash); my $ret; foreach my $user (@{$users}) { - $ret .= "$user->{id}\t\[$user->{shortname}\]\t$user->{publickey}\t$user->{firstname} $user->{lastname}\n"; + $ret .= "$user->{id}\t\[$user->{shortname}\]\t$user->{publickey} \t$user->{usertype}/$user->{status}\t$user->{firstname} $user->{lastname}\n"; } - $ret = "id\tshort\tpublickey\t\tname\n" . $ret if( $ret );; + $ret = "id\tshort\tpublickey\tusertype/status\tname\n" . $ret if( $ret );; $ret = "no users found" if( !$ret ); return $ret; } @@ -3172,7 +3198,7 @@ sub withings_Dispatch($$$) { Log3 $name, 2, "$name: json evaluation error on dispatch type ".$param->{type}." ".$@; return undef; } - Log3 $name, 1, "withings: Dispatch ".$param->{type}." json error ".$json->{error} if(defined($json->{error})); + Log3 $name, 1, "$name: Dispatch ".$param->{type}." json error ".$json->{error} if(defined($json->{error})); Log3 $name, 5, "$name: json returned: ".Dumper($json); diff --git a/fhem/FHEM/38_netatmo.pm b/fhem/FHEM/38_netatmo.pm index 0c679e29c..639aeec14 100644 --- a/fhem/FHEM/38_netatmo.pm +++ b/fhem/FHEM/38_netatmo.pm @@ -11,7 +11,7 @@ # # ############################################################################## -# Release 20 / 2018-09-09 +# Release 20 / 2018-09-20 package main; @@ -78,6 +78,8 @@ netatmo_Define($$) my $subtype; if($a[2] eq "WEBHOOK") { $subtype = "WEBHOOK"; + $hash->{model} = "WEBHOOK"; + my $d = $modules{$hash->{TYPE}}{defptr}{"WEBHOOK"}; return "Netatmo webkook already defined as $d->{NAME}" if( defined($d) && $d->{NAME} ne $name ); @@ -116,6 +118,7 @@ netatmo_Define($$) if( $a[3] && $a[3] =~ m/[\da-f]{2}(:[\da-f]{2}){5}/ ) { + $hash->{model} = "PUBLIC"; my $device = $a[3]; $hash->{Device} = $device; @@ -200,6 +203,8 @@ netatmo_Define($$) $hash->{Rad} = $rad; $subtype = "PUBLIC"; + $hash->{model} = "WEATHERMAP"; + $modules{$hash->{TYPE}}{defptr}{$hash->{Lat}.$hash->{Lon}.$hash->{Rad}} = $hash; my $account = $modules{$hash->{TYPE}}{defptr}{"account"}; @@ -233,6 +238,7 @@ netatmo_Define($$) } elsif( ($a[2] eq "FORECAST" && @a == 4 ) ) { $subtype = "FORECAST"; + $hash->{model} = "FORECAST"; my $device = $a[3]; @@ -291,6 +297,7 @@ netatmo_Define($$) } elsif( ($a[2] eq "HEATINGHOME" && @a == 4 ) ) { $subtype = "HEATINGHOME"; + $hash->{model} = "HEATINGHOME"; my $home = $a[@a-1]; @@ -307,6 +314,7 @@ netatmo_Define($$) } elsif( ($a[2] eq "HEATINGROOM" && @a == 5 ) ) { $subtype = "HEATINGROOM"; + $hash->{model} = "HEATINGROOM"; my $room = $a[@a-1]; my $home = $a[@a-2]; @@ -325,6 +333,7 @@ netatmo_Define($$) } elsif( ($a[2] eq "HOME" && @a == 4 ) ) { $subtype = "HOME"; + $hash->{model} = "HOME"; my $home = $a[@a-1]; @@ -341,6 +350,7 @@ netatmo_Define($$) } elsif( ($a[2] eq "PERSON" && @a == 5 ) ) { $subtype = "PERSON"; + $hash->{model} = "PERSON"; my $home = $a[@a-2]; my $person = $a[@a-1]; @@ -389,6 +399,7 @@ netatmo_Define($$) } elsif( @a == 6 || ($a[2] eq "ACCOUNT" && @a == 7 ) ) { $subtype = "ACCOUNT"; + $hash->{model} = "ACCOUNT"; $hash->{network} = "ok"; delete($hash->{access_token}); @@ -3723,14 +3734,14 @@ netatmo_parseGlobal($$) } if(defined($moduledata->{dashboard_data}{sum_rain_24})) { - my $rain_day = ReadingsVal($module->{NAME},"rain_day",0); - if($moduledata->{dashboard_data}{sum_rain_24} < $rain_day) - { - my $rain_total = ReadingsVal($module->{NAME},"rain_total",0); - $rain_total += $rain_day; - readingsSingleUpdate($module,"rain_total",$rain_total,1); - Log3 $name, 1, $module->{NAME}.":_added rain ".$rain_day." (to ".$rain_total.")"; - } + # my $rain_day = ReadingsVal($module->{NAME},"rain_day",0); + # if($moduledata->{dashboard_data}{sum_rain_24} < $rain_day) + # { + # my $rain_total = ReadingsVal($module->{NAME},"rain_total",0); + # $rain_total += $rain_day; + # readingsSingleUpdate($module,"rain_total",$rain_total,1); + # Log3 $name, 1, $module->{NAME}.":_added rain ".$rain_day." (to ".$rain_total.")"; + # } readingsBeginUpdate($module); $module->{".updateTimestamp"} = FmtDateTime($moduledata->{dashboard_data}{time_utc}); readingsBulkUpdate( $module, "rain_day", $moduledata->{dashboard_data}{sum_rain_24}, 1 ); diff --git a/fhem/FHEM/72_XiaomiDevice.pm b/fhem/FHEM/72_XiaomiDevice.pm index ad834c953..5aeceb59f 100755 --- a/fhem/FHEM/72_XiaomiDevice.pm +++ b/fhem/FHEM/72_XiaomiDevice.pm @@ -1,4 +1,4 @@ -############################################## +############################################## # $Id$$$ # # 72_XiaomiDevice.pm @@ -211,7 +211,7 @@ sub XiaomiDevice_Define($$$) { $hash->{helper}{delay} = 0; - #my $token = ''; + $a[3] = '' if(!defined($a[3])); if(length($a[3]) == 32) { $hash->{helper}{token} = $a[3]; } elsif(length($a[3]) == 96) { @@ -1587,12 +1587,12 @@ sub XiaomiDevice_GetUpdate($) elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "AirPurifier") { $hash->{helper}{packet}{$packetid} = "air_data"; - XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","motor1_speed","temp_dec","humidity","aqi","average_aqi","favorite_level","use_time","purify_volume","filter1_life"]}' ); + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","motor1_speed","temp_dec","humidity","aqi","average_aqi","favorite_level","use_time","purify_volume","filter1_life","f1_hour_used","f1_hour","button_pressed","motor2_speed"]}' ); } elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "Humidifier") { $hash->{helper}{packet}{$packetid} = "hum_data"; - XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","temp_dec","humidity"]}' ); + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","temp_dec","humidity","button_pressed"]}' ); } elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "SmartFan") { @@ -1612,7 +1612,7 @@ sub XiaomiDevice_GetUpdate($) elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "WaterPurifier") { $hash->{helper}{packet}{$packetid} = "water_data"; - XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","tds","filter1_life","filter1_state","filter_life","filter_state","life","state","level","volume","filter","usage","temperature","uv_life","uv_state","elecval_state"]}' ); + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","tds","filter1_life","filter1_state","filter_life","filter_state","life","state","level","volume","filter","usage","temperature","uv_life","uv_state","elecval_state","button_pressed"]}' ); } elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "Camera") { @@ -1622,7 +1622,7 @@ sub XiaomiDevice_GetUpdate($) elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "RiceCooker") { $hash->{helper}{packet}{$packetid} = "ricecooker_data"; - XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["func", "menu", "stage", "temp", "t_func", "t_precook", "t_cook", "setting", "delay", "version"]}' ); + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["func", "menu", "stage", "temp", "t_func", "t_precook", "t_cook", "setting", "delay", "version","button_pressed"]}' ); } elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "PowerPlug") { @@ -1648,7 +1648,7 @@ sub XiaomiDevice_GetSettings($) my $packetid = $hash->{helper}{packetid}; $hash->{helper}{packetid} = $packetid+1; $hash->{helper}{packet}{$packetid} = "air_settings"; - return XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["buzzer","led_b","child_lock","app_extra","act_sleep","sleep_time"]}' ); + return XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["buzzer","led_b","child_lock","app_extra","act_sleep","sleep_time","volume","rfid_product_id","rfid_tag"]}' ); } if( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "Humidifier") @@ -1733,6 +1733,16 @@ sub XiaomiDevice_GetSettings($) $hash->{helper}{packet}{$packetid} = "get_carpet_mode"; XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_carpet_mode","params":[""]}' ); + $packetid = $hash->{helper}{packetid}; + $hash->{helper}{packetid} = $packetid+1; + $hash->{helper}{packet}{$packetid} = "get_fw_features"; + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_fw_features","params":[""]}' ); + + $packetid = $hash->{helper}{packetid}; + $hash->{helper}{packetid} = $packetid+1; + $hash->{helper}{packet}{$packetid} = "app_get_locale"; + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"app_get_locale","params":[""]}' ); + return undef; } @@ -1794,7 +1804,7 @@ sub XiaomiDevice_GetSpeed($) elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "AirPurifier") { $hash->{helper}{packet}{$packetid} = "air_status"; - XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","motor1_speed","favorite_level"]}' ); + XiaomiDevice_WriteJSON($hash, '{"id":'.$packetid.',"method":"get_prop","params":["power","mode","motor1_speed","favorite_level","motor2_speed"]}' ); } elsif( defined($attr{$name}) && defined($attr{$name}{subType}) && $attr{$name}{subType} eq "Humidifier") { @@ -1961,8 +1971,12 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "pm25_average", $json->{result}[6], 1 ) if(defined($json->{result}[6])); readingsBulkUpdate( $hash, "favorite", $json->{result}[7], 1 ) if(defined($json->{result}[7])); readingsBulkUpdate( $hash, "usage", sprintf( "%.1f", $json->{result}[8]/3600), 1 ) if(defined($json->{result}[8])); - readingsBulkUpdate( $hash, "volume", $json->{result}[9], 1 ) if(defined($json->{result}[9])); + readingsBulkUpdate( $hash, "filter_volume", $json->{result}[9], 1 ) if(defined($json->{result}[9])); readingsBulkUpdate( $hash, "filter", $json->{result}[10], 1 ) if(defined($json->{result}[10])); + readingsBulkUpdate( $hash, "filter_used", $json->{result}[11], 1 ) if(defined($json->{result}[11])); + readingsBulkUpdate( $hash, "filter_life", $json->{result}[12], 1 ) if(defined($json->{result}[12])); + readingsBulkUpdate( $hash, "button_pressed", $json->{result}[13], 1 ) if(defined($json->{result}[13])); + readingsBulkUpdate( $hash, "speed2", $json->{result}[14], 1 ) if(defined($json->{result}[14])); readingsBulkUpdate( $hash, "state", $stateval, 1 ) if(defined($stateval)); readingsEndUpdate($hash,1); return undef; @@ -1978,6 +1992,9 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "turbo", ($json->{result}[3] eq "0" ? 'off' : 'on'), 1 ) if(defined($json->{result}[3])); readingsBulkUpdate( $hash, "sleep_auto", $json->{result}[4], 1 ) if(defined($json->{result}[4])); readingsBulkUpdate( $hash, "sleep_time", $json->{result}[6], 1 ) if(defined($json->{result}[6])); + readingsBulkUpdate( $hash, "filter_volume", $json->{result}[7], 1 ) if(defined($json->{result}[7])); + readingsBulkUpdate( $hash, "rfid_product_id", $json->{result}[8], 1 ) if(defined($json->{result}[8])); + readingsBulkUpdate( $hash, "rfid_tag", $json->{result}[9], 1 ) if(defined($json->{result}[9])); readingsEndUpdate($hash,1); return undef; } @@ -1992,6 +2009,7 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "mode", $json->{result}[1], 1 ) if(defined($json->{result}[1])); readingsBulkUpdate( $hash, "speed", $json->{result}[2], 1 ) if(defined($json->{result}[2])); readingsBulkUpdate( $hash, "favorite", $json->{result}[3], 1 ) if(defined($json->{result}[3])); + readingsBulkUpdate( $hash, "speed2", $json->{result}[4], 1 ) if(defined($json->{result}[4])); readingsBulkUpdate( $hash, "state", $stateval, 1 ) if(defined($stateval)); readingsEndUpdate($hash,1); return undef; @@ -2005,6 +2023,7 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "mode", ($json->{result}[0] eq "off") ? "idle" : $json->{result}[1], 1 ) if(defined($json->{result}[1])); readingsBulkUpdate( $hash, "temperature", ($json->{result}[2]/10), 1 ) if(defined($json->{result}[2])); readingsBulkUpdate( $hash, "humidity", $json->{result}[3], 1 ) if(defined($json->{result}[3])); + readingsBulkUpdate( $hash, "button_pressed", $json->{result}[4], 1 ) if(defined($json->{result}[4])); readingsEndUpdate($hash,1); return undef; } @@ -2177,13 +2196,14 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "life", $json->{result}[7], 1 ) if(defined($json->{result}[7])); readingsBulkUpdate( $hash, "state", $json->{result}[8], 1 ) if(defined($json->{result}[8])); readingsBulkUpdate( $hash, "level", $json->{result}[9], 1 ) if(defined($json->{result}[9])); - readingsBulkUpdate( $hash, "volume", $json->{result}[10], 1 ) if(defined($json->{result}[10])); + readingsBulkUpdate( $hash, "water_volume", $json->{result}[10], 1 ) if(defined($json->{result}[10])); readingsBulkUpdate( $hash, "filter", $json->{result}[11], 1 ) if(defined($json->{result}[11])); readingsBulkUpdate( $hash, "usage", $json->{result}[12], 1 ) if(defined($json->{result}[12])); readingsBulkUpdate( $hash, "temperature", $json->{result}[13], 1 ) if(defined($json->{result}[13])); readingsBulkUpdate( $hash, "uv_life", $json->{result}[14], 1 ) if(defined($json->{result}[14])); readingsBulkUpdate( $hash, "uv_state", $json->{result}[15], 1 ) if(defined($json->{result}[15])); readingsBulkUpdate( $hash, "elecval_state", $json->{result}[16], 1 ) if(defined($json->{result}[16])); + readingsBulkUpdate( $hash, "button_pressed", $json->{result}[17], 1 ) if(defined($json->{result}[17])); readingsEndUpdate($hash,1); return undef; } @@ -2216,6 +2236,7 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "setting", $json->{result}[7], 1 ) if(defined($json->{result}[7])); readingsBulkUpdate( $hash, "delay", $json->{result}[8], 1 ) if(defined($json->{result}[8])); readingsBulkUpdate( $hash, "version", $json->{result}[9], 1 ) if(defined($json->{result}[9])); + readingsBulkUpdate( $hash, "button_pressed", $json->{result}[10], 1 ) if(defined($json->{result}[10])); readingsEndUpdate($hash,1); return undef; } @@ -2236,6 +2257,7 @@ sub XiaomiDevice_ParseJSON($$) readingsBulkUpdate( $hash, "voltage", $json->{result}[0]{voltage}, 1 ) if(defined($json->{result}[0]{voltage})); readingsBulkUpdate( $hash, "power_factor", $json->{result}[0]{power_factor}, 1 ) if(defined($json->{result}[0]{power_factor})); readingsBulkUpdate( $hash, "elec_leakage", $json->{result}[0]{elec_leakage}, 1 ) if(defined($json->{result}[0]{elec_leakage})); + readingsBulkUpdate( $hash, "button_pressed", $json->{result}[0]{button_pressed}, 1 ) if(defined($json->{result}[0]{button_pressed})); #readingsBulkUpdate( $hash, "setting", (($json->{result}[0]{setting} eq "1")?"yes":"no"), 1 ) if(defined($json->{result}[0]{setting})); readingsEndUpdate($hash,1); return undef; @@ -2306,6 +2328,14 @@ sub XiaomiDevice_ParseJSON($$) readingsEndUpdate($hash,1); return undef; } + if($msgtype eq "get_sound_volume") + { + return undef if(!defined($json->{result})); + readingsSingleUpdate( $hash, "volume", "100", 0) if(($json->{result} eq "unknown_method") || (ref($json->{result}) ne "ARRAY" && $json->{result} eq "0")); + return undef if(ref($json->{result}) ne "ARRAY"); + readingsSingleUpdate( $hash, "volume", $json->{result}[0], 1 ) if(defined($json->{result}[0])); + return undef; + } if($msgtype eq "get_carpet_mode") { return undef if(!defined($json->{result})); @@ -2319,12 +2349,33 @@ sub XiaomiDevice_ParseJSON($$) readingsSingleUpdate( $hash, "carpet_integral", $json->{result}[0]{current_integral}, 1 ) if(defined($json->{result}[0]{current_integral})); return undef; } - if($msgtype eq "get_sound_volume") + if($msgtype eq "app_get_locale") { return undef if(!defined($json->{result})); - readingsSingleUpdate( $hash, "volume", "100", 0) if(($json->{result} eq "unknown_method") || (ref($json->{result}) ne "ARRAY" && $json->{result} eq "0")); return undef if(ref($json->{result}) ne "ARRAY"); - readingsSingleUpdate( $hash, "volume", $json->{result}[0], 1 ) if(defined($json->{result}[0])); + return undef if(ref($json->{result}[0]) ne "HASH"); + readingsSingleUpdate( $hash, "app_logserver", $json->{result}[0]{logserver}, 1 ) if(defined($json->{result}[0]{logserver})); + readingsSingleUpdate( $hash, "app_wifiplan", $json->{result}[0]{wifiplan}, 1 ) if(defined($json->{result}[0]{wifiplan}) && $json->{result}[0]{wifiplan} ne ""); + readingsSingleUpdate( $hash, "app_timezone", $json->{result}[0]{timezone}, 1 ) if(defined($json->{result}[0]{timezone})); + readingsSingleUpdate( $hash, "app_bom", $json->{result}[0]{bom}, 1 ) if(defined($json->{result}[0]{bom})); + readingsSingleUpdate( $hash, "app_language", $json->{result}[0]{language}, 1 ) if(defined($json->{result}[0]{language})); + readingsSingleUpdate( $hash, "app_name", $json->{result}[0]{name}, 1 ) if(defined($json->{result}[0]{name})); + readingsSingleUpdate( $hash, "app_location", $json->{result}[0]{location}, 1 ) if(defined($json->{result}[0]{location})); + return undef; + } + if($msgtype eq "get_fw_features") + { + return undef if(!defined($json->{result})); + return undef if(ref($json->{result}) ne "ARRAY"); + my $featurestring = ""; + $featurestring = $json->{result}[0] if(defined($json->{result}[0])); + my $i = 1; + while(defined($json->{result}[$i])){ + $featurestring .= ","; + $featurestring .= $json->{result}[$i]; + $i++; + } + readingsSingleUpdate( $hash, "device_fw_features", $featurestring, 1 ); return undef; } if($msgtype eq "get_custom_mode") @@ -2812,7 +2863,7 @@ sub XiaomiDevice_Read($) { if($len == 32) # token return { my $token = substr($data,-32,32); - if($token eq "ffffffffffffffffffffffffffffffff" && !defined($hash->{helper}{token})) + if(($token eq "00000000000000000000000000000000" || $token eq "ffffffffffffffffffffffffffffffff") && !defined($hash->{helper}{token})) { Log3 $name, 1, "$name: Token could not be retrieved automatically from already cloud-connected device!"; $attr{$name}{disable} = "1"; @@ -2822,7 +2873,10 @@ sub XiaomiDevice_Read($) { RemoveInternalTimer($hash, "XiaomiDevice_connectFail"); $hash->{helper}{delay} = 0; - $hash->{helper}{token} = $token if(!defined($hash->{helper}{token})); + if(!defined($hash->{helper}{token})){ + $hash->{helper}{token} = $token; + $hash->{DEF} = $hash->{DEF}." ".$hash->{helper}{token}; + } return undef; } @@ -2953,13 +3007,16 @@ sub XiaomiDevice_DbLog_splitFn($) { $value = $parts[1]; $unit = ""; - $unit = "%" if($reading =~ /filter/);; + $unit = "%" if($reading eq "filter");; $unit = "%" if($reading =~ /humidity/);; $unit = "µg/m³" if($reading =~ /pm25/);; $unit = "rpm" if($reading =~ /speed/); $unit = "˚C" if($reading =~ /temperature/); $unit = "h" if($reading =~ /usage/); - $unit = "m³" if($reading =~ /volume/); + $unit = "h" if($reading =~ /_life/); + $unit = "h" if($reading =~ /_used/); + $unit = "m³" if($reading eq "filter_volume"); + $unit = "l" if($reading eq "water_volume"); $unit = "%" if($reading =~ /batteryPercent/);; $unit = "%" if($reading =~ /fan_power/);; $unit = "h" if($reading =~ /clean_time/);; @@ -3219,7 +3276,7 @@ sub XiaomiDevice_DbLog_splitFn($) {
Usage time in h

-
  • volume (AirPurifier) +
  • filter_volume (AirPurifier)
    Total air volume in m³