diff --git a/fhem/CHANGED b/fhem/CHANGED index b6edcf094..a9aafda33 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,10 @@ # 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. + - deleted: 52_I2C_GY30_BH1750FVI: Arno Augustin hatte fast zeitgleich + eine technisch bessere Variante entwickelt. Diese ist + nicht mehr notwendig + - updated: 52_I2C_HDC1008: Umbau auf asynchrones I2C lesen, + alle sleeps entfernt - feature: 74_AMAD: new Feature change current volume + or - value set TABLET volume -5 - updated: 74_AMAD: New Minor Release 2.2 real state for deviceState Reading, diff --git a/fhem/FHEM/52_I2C_GY30_BH1750FVI.pm b/fhem/FHEM/52_I2C_GY30_BH1750FVI.pm deleted file mode 100644 index 79226c2e4..000000000 --- a/fhem/FHEM/52_I2C_GY30_BH1750FVI.pm +++ /dev/null @@ -1,640 +0,0 @@ -# Modul für I2C Lichtsensor GY-30 mit dem AD-Wandler BH1750FVI -# Autor : Karsten Grüttner -# $Id$ -# Technische Dokumention für den Sensor befindet sich http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf - - -package main; -use strict; -use warnings; -use Time::HiRes qw(usleep); - - - - - -# Konfigurationsparameter Auflösung, delay nur im Continuously-Mode nach erstem Lesen, ansonsten delayInit -my %I2C_GY30_BH1750FVI_resParams = # -( - 'HalfLux' => {delay => 120000, code => 1, delayInit => 180000 }, - '1Lux' => {delay => 120000, code => 0, delayInit => 180000 } , - '4Lux' => {delay => 16000, code => 3, delayInit => 24000, } -); - - -# Konfigurationsparameter Betriebsmode -my %I2C_GY30_BH1750FVI_CodeMode = -( - 'Continuously' => 0x10, # einmalig initialisiert, kann immer gelesen werden, geeignet für Dauerüberwachung z.B. Lichtschranke - 'One' => 0x20 # wacht zum einmaligen Lesen auf und legt sich wieder schlafen, geeignet z.B. die Lichtverhältnisse draußen zu messen -); - -# Konfigurationsparameter Befehle -my %I2C_GY30_BH1750FVI_CodeCmd = -( - 'PowerDown' => 0, - 'PowerOn' => 1, - 'Reset' => 7 -); - - -sub I2C_GY30_BH1750FVI_Initialize($) { - my ($hash) = @_; - - $hash->{DefFn} = 'I2C_GY30_BH1750FVI_Define'; - $hash->{UndefFn} = 'I2C_GY30_BH1750FVI_Undef'; - $hash->{SetFn} = 'I2C_GY30_BH1750FVI_Set'; - $hash->{GetFn} = 'I2C_GY30_BH1750FVI_Get'; - $hash->{AttrFn} = 'I2C_GY30_BH1750FVI_Attr'; - $hash->{ReadFn} = 'I2C_GY30_BH1750FVI_Read'; - $hash->{I2CRecFn} = 'I2C_GY30_BH1750FVI_I2CRec'; - $hash->{AttrList} = - "interval ". - "IODev ". - "Resolution:HalfLux,1Lux,4Lux ". # als Dropdown - "OperationMode:Continuously,One ". # als Dropdown - "roundLightIntensityDecimal ". - $readingFnAttributes; - - -} - - -sub I2C_GY30_BH1750FVI_Define($$) { - my ($hash, $def) = @_; - my @a = split('[ \t][ \t]*', $def); - - $hash->{MODUL_STATE} = "defined"; - $hash->{RESOLUTION} = 'HalfLux'; - $hash->{OPERATION_MODE} = 'One'; - $hash->{INTERVAL} = 0; - - - if ($main::init_done) { - eval { I2C_GY30_BH1750FVI_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); }; - return I2C_GY30_BH1750FVI_Catch($@) if $@; - } - else - { - Log3 $hash, 5, "[$hash->{NAME}] I2C_GY30_BH1750FVI_Define main::init_done was false"; - } - - return undef; -} - -sub I2C_GY30_BH1750FVI_Init($$) { - my ( $hash, $args ) = @_; - - my $name = $hash->{NAME}; - - - - if (defined $args && int(@$args) > 1) - { - return "Define: Wrong syntax. Usage:\n" . - "define I2C_GY30_BH1750FVI []"; - } - - if (defined (my $address = shift @$args)) - { - $address = $address =~ /^0.*$/ ? oct($address) : $address; - if (! ($address == 35 || $address == 92)) # nur 0x23 (ohne Jumper) oder 0x5C (mit Jumper auf Pin "Add" gegen UCC) - { - Log3 $hash, 5, "[$name] I2C Address not valid for GY-30 BH1750FVI"; - return "$name I2C Address not valid for GY-30 BH1750FVI"; - } - else - { - $hash->{I2C_Address} = $address; - } - - } - else - { - $hash->{I2C_Address} = oct('0x23'); - Log3 $name, 5, "[$name] I2C_GY30_BH1750FVI_Init default-I2C-addresse 0x23 used"; - } - - - my $msg = ''; - - $msg = CommandAttr(undef, $name . ' interval 5'); - if ($msg) { - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_Init interval:".$msg; - return $msg; - } - - AssignIoPort($hash); - - if (defined AttrVal($hash->{NAME}, "IODev", undef)) - { - $hash->{MODUL_STATE} = 'Initialized'; - I2C_GY30_BH1750FVI_InitDevice($hash); - - } - else - { - $hash->{MODUL_STATE} = "Error: Missing Attr 'IODev'"; - } - - return undef; -} - -sub I2C_GY30_BH1750FVI_Catch($) { - my $exception = shift; - if ($exception) { - $exception =~ /^(.*)( at.*FHEM.*)$/; - return $1; - } - return undef; -} - -sub I2C_GY30_BH1750FVI_I2CRec ($$) { - my ($hash, $clientmsg) = @_; - my $name = $hash->{NAME}; - my $phash = $hash->{IODev}; - my $pname = $phash->{NAME}; - while ( my ( $k, $v ) = each %$clientmsg ) - { #erzeugen von Internals fuer alle Keys in $clientmsg die mit dem physical Namen beginnen - my $upper_k = uc $k; - $hash->{$upper_k} = $v if $k =~ /^$pname/ ; - } - if ($clientmsg->{direction} && $clientmsg->{type} && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") { - if ( $clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received}) ) - { - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_I2CRec received: $clientmsg->{type} $clientmsg->{received}"; - I2C_GY30_BH1750FVI_GetLightIntensity ($hash, $clientmsg->{received}) if $clientmsg->{type} eq "light" && $clientmsg->{nbyte} == 2; - - } - } -} - -sub I2C_GY30_BH1750FVI_GetLightIntensity ($$) -{ - my ($hash, $rawdata) = @_; - my $name = $hash->{NAME}; - - my @raw = split(" ",$rawdata); - - - my $LightIntensity = ($raw[1] + $raw[0] * 256) /1.2; - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_I2CRec ".$raw[1].'x'.$raw[0]." calced Light: $LightIntensity"; - - - $LightIntensity = sprintf( '%.' . AttrVal($hash->{NAME}, 'roundLightIntensityDecimal', 1) . 'f', $LightIntensity ); - - - - readingsBeginUpdate($hash); - readingsBulkUpdate($hash, 'light_intensity', $LightIntensity); - - readingsBulkUpdate( - $hash, - 'state', - 'L: ' . $LightIntensity - ); - - - readingsEndUpdate($hash, 1); - -} - - - -sub I2C_GY30_BH1750FVI_Undef($$) -{ - my ($hash, $name) = @_; - - if ( defined (AttrVal($hash->{NAME}, "interval", undef)) ) - { - RemoveInternalTimer($hash); - } - - return undef; -} - -# schickt ein Reset, PowerDown oder PowerOn zum Sensor -sub I2C_GY30_BH1750FVI_Command($$) -{ - my ($hash, $cmd) = @_; - my $name = $hash->{NAME}; - - if ($hash->{MODUL_STATE} ne 'Initialized') { return "Error MODULE_STATE in $name is not 'Initialized' " }; - return "$name: no IO device defined" unless ($hash->{IODev}); - - my $iodev = $hash->{IODev}; - my $i2caddress = $hash->{I2C_Address}; - - my $code = $I2C_GY30_BH1750FVI_CodeCmd{$cmd}; - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - data => $code - }); - Time::HiRes::usleep(5); # sollte schnell gehen, aber ob die mikrosekunde ausreicht, wird man sehen. -} - -# initialisiert das Gerät -# bei One-Modus, legt er den Sensor schlafen, ansonsten wird er Anhand Auflösung-Parameter in Dauerbetrieb gesetzt - -sub I2C_GY30_BH1750FVI_InitDevice($) -{ - my ($hash) = @_; - my $name = $hash->{NAME}; - if ($hash->{MODUL_STATE} ne 'Initialized') { return "Error MODULE_STATE in $name is not 'Initialized' " }; - return "$name: no IO device defined" unless ($hash->{IODev}); - - - if ($hash->{OPERATION_MODE} eq 'One') - { - I2C_GY30_BH1750FVI_Command($hash, 'PowerDown'); # bei One kann das Gerät ausgeschalten werden - - } - elsif ($hash->{OPERATION_MODE} eq 'Continuously') - { - - my $resolutionIndex = $hash->{RESOLUTION}; - - my $codeCont = $I2C_GY30_BH1750FVI_CodeMode{'Continuously'}; - my $codeResolution = $I2C_GY30_BH1750FVI_resParams{$resolutionIndex}{code}; - my $code = $codeCont | $codeResolution; - - - my $delay = $I2C_GY30_BH1750FVI_resParams{$resolutionIndex}{delayInit}; - - my $iodev = $hash->{IODev}; - my $i2caddress = $hash->{I2C_Address}; - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_InitDevice send config with ".sprintf("0x%X", $code); - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - data => $code - }); - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_InitDevice wait for ".($delay/1000)." ms" ; - Time::HiRes::usleep($delay); - } - -} - -sub I2C_GY30_BH1750FVI_UpdateValues($) -{ - my ($hash) = @_; - my $name = $hash->{NAME}; - - if ($hash->{MODUL_STATE} ne 'Initialized') { return "Error MODULE_STATE in $name is not 'Initialized' " }; - - my $iodev = $hash->{IODev}; - my $i2caddress = $hash->{I2C_Address}; - - - my $resolutionIndex = $hash->{RESOLUTION}; - my $delay = $I2C_GY30_BH1750FVI_resParams{$resolutionIndex}{delay}; - - if ($hash->{OPERATION_MODE} eq 'One') - { - - - my $codeCont = $I2C_GY30_BH1750FVI_CodeMode{'One'}; - my $codeResolution = $I2C_GY30_BH1750FVI_resParams{$resolutionIndex}{code}; - my $code = $codeCont | $codeResolution; - - - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_UpdateValues send config with ".sprintf("0x%X", $code); - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - data => $code - }); - $delay = $I2C_GY30_BH1750FVI_resParams{$resolutionIndex}{delayInit}; - } - - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_UpdateValues wait for ".($delay/1000)." ms" ; - - Time::HiRes::usleep($delay); - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { # Leider fehlt es hier an Doku. daher hier der Hinweis bei erfolgreichem Lesen wird die Funktion in $hash->{I2CRecFn} aufgerufen - direction => "i2cread", - i2caddress => $i2caddress, - type => "light", - nbyte => 2 - }); - - - return "$name: no IO device defined" unless ($hash->{IODev}); - - - -} - -sub I2C_GY30_BH1750FVI_Get($@) { - my ($hash, @param) = @_; - - - - - I2C_GY30_BH1750FVI_UpdateValues($hash); - - -} - -# set wenn Befehl gesetzt wurde und nicht '?' ist, -# dann führe Befehl aus und gib den Status zurück -# ansonsten gib alle Befehle und deren Optionen zurück - -sub I2C_GY30_BH1750FVI_Set($@) -{ - my ($hash, @param) = @_; - - - - return '"set GY30_BH1750FVI" needs at least one argument' if (int(@param) < 2); - - my $name = shift @param; - my $cmd = shift @param; - my $val = join("", @param); - - if (defined $cmd && $cmd ne '?') # falls set mit Kommand aufgerufen wurde - { - if (defined($I2C_GY30_BH1750FVI_CodeCmd{$cmd})) - { - I2C_GY30_BH1750FVI_Command($hash,$cmd); - return undef; - } - elsif ($cmd eq 'Update') - { - I2C_GY30_BH1750FVI_UpdateValues($hash); - return undef; - } - elsif ($cmd eq 'ReConfig') - { - I2C_GY30_BH1750FVI_InitDevice($hash); - return undef; - } - - return "unknown command"; - - # Debug("Set GY30_BH1750FVI $cmd"); - - } - else # Ansonsten Rückgabe was an set - Optionen möglich ist - { - return "Update:noArg PowerDown:noArg PowerOn:noArg Reset:noArg ReConfig:noArg"; - } - - -} - -sub I2C_GY30_BH1750FVI_CheckState -{ - my ($hash) = @_; - if ($hash->{MODUL_STATE} ne 'Initialized') - { - - my @def = split (' ',$hash->{DEF}); - I2C_GY30_BH1750FVI_Init($hash,\@def) if (defined ($hash->{IODev})); - } -} - -sub I2C_GY30_BH1750FVI_Poll -{ - my ($hash) = @_; - I2C_GY30_BH1750FVI_CheckState($hash); - my $name = $hash->{NAME}; - - - - I2C_GY30_BH1750FVI_UpdateValues($hash); - - my $ret = I2C_GY30_BH1750FVI_Catch($@) if $@; - - # Debug("Update Werte"); - my $pollInterval = AttrVal($hash->{NAME}, 'interval', 0); - if ($pollInterval > 0) - { - Log3 $hash, 5, "[$name] I2C_GY30_BH1750FVI_Poll call InternalTimer with $pollInterval minutes"; - InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_GY30_BH1750FVI_Poll', $hash, 0); - } - else - { - Log3 $name, 5, "[$name] I2C_GY30_BH1750FVI_Poll dont call InternalTimer, not valid pollInterval"; - } - return; -} - -sub I2C_GY30_BH1750FVI_Attr(@) { - - my ($command, $name, $attr, $val) = @_; - my $hash = $defs{$name}; - my $msg = ''; - - if ($attr eq 'interval') - { - if ( defined($val) ) - { - if ( looks_like_number($val) && $val > 0) - { - RemoveInternalTimer($hash); - InternalTimer(1, 'I2C_GY30_BH1750FVI_Poll', $hash, 0); - $hash->{INTERVAL} = $val; - Log3 $hash, 5, "[$hash->{NAME}] I2C_GY30_BH1750FVI_Poll dont call InternalTimer, not valid pollInterval"; - } else - { - $msg .= "$hash->{NAME}: Wrong poll intervall defined. interval must be a number > 0"; - Log3 $hash, 5, "[$hash->{NAME}] I2C_GY30_BH1750FVI_Attr Wrong poll intervall defined. interval must be a number > 0"; - $hash->{INTERVAL} = 0; - } - } - else - { #wird auch aufgerufen wenn $val leer ist, aber der attribut wert wird auf 1 gesetzt - RemoveInternalTimer($hash); - $hash->{INTERVAL} = 0; - } - } - - elsif ($attr eq 'Resolution') - { - if (!defined($val)) - { - $hash->{RESOLUTION} = 'HalfLux'; - I2C_GY30_BH1750FVI_InitDevice($hash); - } - elsif ( defined($I2C_GY30_BH1750FVI_resParams{$val}{code}) ) - { - $hash->{RESOLUTION} = $val; - I2C_GY30_BH1750FVI_InitDevice($hash); - } - else - { - $msg .= "invalid value for attribute $attr"; - } - } - - elsif ($attr eq 'OperationMode') - { - if (!defined($val)) - { - $hash->{OPERATION_MODE} = 'One'; - I2C_GY30_BH1750FVI_InitDevice($hash); - } - elsif ( defined($I2C_GY30_BH1750FVI_CodeMode{$val}) ) - { - $hash->{OPERATION_MODE} = $val; - I2C_GY30_BH1750FVI_InitDevice($hash); - } - else - { - $msg .= "invalid value for attribute $attr"; - } - } - - elsif ($command && $command eq "set" && $attr && $attr eq "IODev") - { - if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) - { - main::AssignIoPort($hash,$val); - my @def = split (' ',$hash->{DEF}); - I2C_GY30_BH1750FVI_Init($hash,\@def) if (defined ($hash->{IODev})); - - } - } - - elsif ( $attr eq 'roundLightIntensityDecimal' ) - { - if (!defined($val)) - { - return undef; - } - elsif (!(looks_like_number($val) && ($val>=0 ))) - { - $msg .= "$attr must be a number >= 0" - } - } - - return ($msg) ? $msg : undef; -} - -1; - -=pod -=begin html - - -

I2C_GY30_BH1750FVI

- - -=end html - -=begin html_DE - - -

I2C_GY30_BH1750FVI

- - -=end html - -=cut \ No newline at end of file diff --git a/fhem/FHEM/52_I2C_HDC1008.pm b/fhem/FHEM/52_I2C_HDC1008.pm index b1e08cbd4..0f446201a 100644 --- a/fhem/FHEM/52_I2C_HDC1008.pm +++ b/fhem/FHEM/52_I2C_HDC1008.pm @@ -7,7 +7,7 @@ package main; use strict; use warnings; -use Time::HiRes qw(usleep); + @@ -42,7 +42,7 @@ sub I2C_HDC1008_Initialize($) { $hash->{DefFn} = 'I2C_HDC1008_Define'; $hash->{UndefFn} = 'I2C_HDC1008_Undef'; $hash->{SetFn} = 'I2C_HDC1008_Set'; - $hash->{GetFn} = 'I2C_HDC1008_Get'; + $hash->{AttrFn} = 'I2C_HDC1008_Attr'; $hash->{ReadFn} = 'I2C_HDC1008_Read'; $hash->{I2CRecFn} = 'I2C_HDC1008_I2CRec'; @@ -68,6 +68,8 @@ sub I2C_HDC1008_Define($$) { $hash->{RESOLUTION_HUMIDITY} = '14Bit'; $hash->{HEATER} = 'off'; $hash->{INTERVAL} = 0; + $hash->{DEVICE_STATE} = 'UNKNOWN'; + if ($main::init_done) { eval { I2C_HDC1008_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); }; @@ -130,6 +132,7 @@ sub I2C_HDC1008_Init($$) { if (defined AttrVal($hash->{NAME}, "IODev", undef)) { $hash->{MODUL_STATE} = 'Initialized'; + $hash->{DEVICE_STATE} = 'READY'; } else @@ -213,6 +216,8 @@ sub I2C_HDC1008_GetHum ($$) readingsEndUpdate($hash, 1); + + } sub I2C_HDC1008_Undef($$) @@ -251,9 +256,19 @@ sub I2C_HDC1008_Reset($) reg => 2, data => $high_byte. " ".$low_byte }); - Time::HiRes::usleep(15000); # Sensor braucht bis 15 ms bis er bereit ist + + RemoveInternalTimer($hash); + $hash->{DEVICE_STATE} ='READY'; + InternalTimer(gettimeofday() + 15.0/1000, 'I2C_HDC1008_Poll', $hash, 0); # Sensor braucht bis 15 ms bis er bereit ist + } + +# Funktion holt die Werte vom Sensor via I2C +# asynchrones Lesen, über Status-Wechsel in $hash->{DEVICE_STATE} und Rückgabe der notwendigen Dauer des aktuellen Schritts in Sekunden, +# die dann an den Timer gegeben wird. Der schaut nach Ablauf der Zeit hier wieder vorbei und weiß als nächstes zu tun ist, +# andere Prozesse werden dabei nicht mehr blockiert. + sub I2C_HDC1008_UpdateValues($) { my ($hash) = @_; @@ -264,6 +279,8 @@ sub I2C_HDC1008_UpdateValues($) return "$name: no IO device defined" unless ($hash->{IODev}); + Log3 $name, 5, "[$name] I2C_HDC1008_UpdateValues starts with state: $hash->{DEVICE_STATE}"; + # baue Konfigurationsparameter zusammen my $modeReading = 1 << 12; # lies beides gleichzeitig @@ -276,78 +293,111 @@ sub I2C_HDC1008_UpdateValues($) my $resHumParam = $I2C_HDC1008_humParams{$resHumIndex}{code}; my $heaterParam = $I2C_HDC1008_validsHeater{$heaterIndex}; - my $Param = $modeReading | $resTempParam | $resHumParam | $heaterParam; - - - # schicke Konfiguration zum HDC1008-Sensor - # -------------------------------------------------------- - - my $low_byte = $Param & 0xff; - my $high_byte = ($Param & 0xff00) >> 8; - my $iodev = $hash->{IODev}; my $i2caddress = $hash->{I2C_Address}; + + + if ($hash->{DEVICE_STATE} eq 'READY') + { - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - reg => 2, - data => $high_byte. " ".$low_byte # Leider fehlt es hier an Doku. Laut Quellcode (00_RPII2C.pm, ab Zeile 369), werden die dezimale Zahlen durch Leerzeichen getrennt, binär gewandelt und zum I2C-Bus geschickt - }); - Time::HiRes::usleep(15000); # Sensor braucht bis 15 ms bis er bereit ist + my $Param = $modeReading | $resTempParam | $resHumParam | $heaterParam; + + + # schicke Konfiguration zum HDC1008-Sensor + # -------------------------------------------------------- + my $low_byte = $Param & 0xff; + my $high_byte = ($Param & 0xff00) >> 8; + + CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { + direction => "i2cwrite", + i2caddress => $i2caddress, + reg => 2, + data => $high_byte. " ".$low_byte # Leider fehlt es hier an Doku. Laut Quellcode (00_RPII2C.pm, ab Zeile 369), werden die dezimale Zahlen durch Leerzeichen getrennt, binär gewandelt und zum I2C-Bus geschickt + }); + $hash->{DEVICE_STATE} = 'CONFIGURING'; + return 15.0/1000; # Sensor braucht bis 15 ms bis er bereit ist + } + elsif($hash->{DEVICE_STATE} eq 'CONFIGURING') + { + # HDC1008-Sensor soll Temperatur messen + # -------------------------------------------------------- + + CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { + direction => "i2cwrite", + i2caddress => $i2caddress, + data => (0) + }); + + $hash->{DEVICE_STATE} = 'MEASURING_TEMPERATURE'; + + my $tempWait = $I2C_HDC1008_tempParams{$resTempIndex}{delay}; # in ns + return $tempWait/1000000.0; + + } + elsif($hash->{DEVICE_STATE} eq 'MEASURING_TEMPERATURE') + { - - # lese Temperatur vom HDC1008-Sensor - # -------------------------------------------------------- - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - data => (0) - }); - - my $tempWait = $I2C_HDC1008_tempParams{$resTempIndex}{delay}; - Time::HiRes::usleep($tempWait); - - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { # Leider fehlt es hier an Doku. daher hier der Hinweis bei erfolgreichem Lesen wird die Funktion in $hash->{I2CRecFn} aufgerufen + # Temperatur vom HDC1008-Sensor lesen + # -------------------------------------------------------- + + CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { # Leider fehlt es hier an Doku. daher hier der Hinweis bei erfolgreichem Lesen wird die Funktion in $hash->{I2CRecFn} aufgerufen direction => "i2cread", i2caddress => $i2caddress, type => "temp", nbyte => 2 - }); + }); + + + # HDC1008-Sensor soll Feuchtigkeit messen + # -------------------------------------------------------- + + CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { + direction => "i2cwrite", + i2caddress => $i2caddress, + data => 1 + }); + + $hash->{DEVICE_STATE} = 'MEASURING_HUMIDITY'; + + my $humWait = $I2C_HDC1008_humParams{$resTempIndex}{delay}; - # lese Feuchtigkeit vom HDC1008-Sensor - # -------------------------------------------------------- - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { - direction => "i2cwrite", - i2caddress => $i2caddress, - data => 1 - }); - my $humWait = $I2C_HDC1008_humParams{$resTempIndex}{delay}; - Time::HiRes::usleep($humWait); - - CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { + return $humWait/1000000.0; + } + elsif($hash->{DEVICE_STATE} eq 'MEASURING_HUMIDITY') + { + # lese Feuchtigkeit vom HDC1008-Sensor + # -------------------------------------------------------- + + CallFn($iodev->{NAME}, "I2CWrtFn", $iodev, { direction => "i2cread", i2caddress => $i2caddress, type => "hum", nbyte => 2 - }); + }); + + # fertig + + $hash->{DEVICE_STATE} = 'READY'; + my $pollInterval = AttrVal($hash->{NAME}, 'interval', 0); + return $pollInterval * 60; # Pollintervall in Minuten + } + else + { + Log3 $name, 5, "[$name] I2C_HDC1008_UpdateValues wtf... whats wrong !!!!!!!!!!!!!!"; + + $hash->{DEVICE_STATE} = 'READY'; + my $pollInterval = AttrVal($hash->{NAME}, 'interval', 0); + return $pollInterval * 60; # Pollintervall in Minuten + } + + + } -sub I2C_HDC1008_Get($@) { - my ($hash, @param) = @_; - - - I2C_HDC1008_UpdateValues($hash); - - -} # set wenn Befehl gesetzt wurde und nicht '?' ist, # dann führe Befehl aus und gib den Status zurück @@ -381,7 +431,12 @@ sub I2C_HDC1008_Set($@) { } elsif ($cmd eq 'Update') { - I2C_HDC1008_UpdateValues($hash); + + + RemoveInternalTimer($hash); + $hash->{DEVICE_STATE} ='READY'; + I2C_HDC1008_Poll($hash); + return undef; } elsif ($cmd eq 'Reset') @@ -421,25 +476,25 @@ sub I2C_HDC1008_Poll - I2C_HDC1008_UpdateValues($hash); + my $delay = I2C_HDC1008_UpdateValues($hash); my $ret = I2C_HDC1008_Catch($@) if $@; - # Debug("Update Werte"); - my $pollInterval = AttrVal($hash->{NAME}, 'interval', 0); - if ($pollInterval > 0) + + if ($delay > 0) { - Log3 $hash, 5, "[$name] I2C_HDC1008_Poll call InternalTimer with $pollInterval minutes"; - InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_HDC1008_Poll', $hash, 0); + Log3 $hash, 5, "[$name] I2C_HDC1008_Poll call InternalTimer with $delay seconds"; + InternalTimer(gettimeofday() + $delay, 'I2C_HDC1008_Poll', $hash, 0); } else { - Log3 $name, 5, "[$name] I2C_HDC1008_Poll dont call InternalTimer, not valid pollInterval"; + Log3 $name, 5, "[$name] I2C_HDC1008_Poll dont call InternalTimer, nothing todo"; } return; } -sub I2C_HDC1008_Attr(@) { +sub I2C_HDC1008_Attr(@) +{ my ($command, $name, $attr, $val) = @_; my $hash = $defs{$name}; @@ -452,6 +507,7 @@ sub I2C_HDC1008_Attr(@) { if ( looks_like_number($val) && $val > 0) { RemoveInternalTimer($hash); + $hash->{DEVICE_STATE} = 'READY'; InternalTimer(1, 'I2C_HDC1008_Poll', $hash, 0); $hash->{INTERVAL} = $val; Log3 $hash, 5, "[$hash->{NAME}] I2C_HDC1008_Attr call InternalTimer with new value $val ";