Compare commits
	
		
			6 Commits
		
	
	
		
			298bf70d93
			...
			dev
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 728319d81e | |||
| feb1e1fdd5 | |||
| e166a51c45 | |||
| 8524d188d7 | |||
| 7c45784c1f | |||
| deeecfec7e | 
@@ -267,7 +267,7 @@ sub Initialize {
 | 
			
		||||
  ],
 | 
			
		||||
  "release_status": "stable",
 | 
			
		||||
  "license": "GPL_2",
 | 
			
		||||
  "version": "v2.0.2",
 | 
			
		||||
  "version": "v2.1.1",
 | 
			
		||||
  "x_apiversion": "1.13.0",
 | 
			
		||||
  "author": [
 | 
			
		||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
			
		||||
 
 | 
			
		||||
@@ -271,7 +271,7 @@ sub Initialize {
 | 
			
		||||
  ],
 | 
			
		||||
  "release_status": "stable",
 | 
			
		||||
  "license": "GPL_2",
 | 
			
		||||
  "version": "v2.0.2",
 | 
			
		||||
  "version": "v2.1.1",
 | 
			
		||||
  "author": [
 | 
			
		||||
    "Marko Oldenburg <leongaultier@gmail.com>"
 | 
			
		||||
  ],
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
UPD 2021-12-17_12:18:33 10358 FHEM/73_NUKIBridge.pm
 | 
			
		||||
UPD 2021-12-17_12:44:59 11100 FHEM/74_NUKIDevice.pm
 | 
			
		||||
UPD 2022-09-26_11:59:12 42767 lib/FHEM/Devices/Nuki/Bridge.pm
 | 
			
		||||
UPD 2021-12-17_12:18:33 16338 lib/FHEM/Devices/Nuki/Device.pm
 | 
			
		||||
UPD 2025-10-16_18:43:02 10358 FHEM/73_NUKIBridge.pm
 | 
			
		||||
UPD 2025-10-15_06:55:14 11100 FHEM/74_NUKIDevice.pm
 | 
			
		||||
UPD 2025-10-16_19:50:02 43040 lib/FHEM/Devices/Nuki/Bridge.pm
 | 
			
		||||
UPD 2025-10-15_06:55:14 16775 lib/FHEM/Devices/Nuki/Device.pm
 | 
			
		||||
 
 | 
			
		||||
@@ -39,7 +39,8 @@ package FHEM::Devices::Nuki::Bridge;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use experimental qw( switch );
 | 
			
		||||
 | 
			
		||||
#use experimental qw( switch );
 | 
			
		||||
 | 
			
		||||
use FHEM::Meta;
 | 
			
		||||
use HttpUtils;
 | 
			
		||||
@@ -54,7 +55,7 @@ BEGIN {
 | 
			
		||||
          defs
 | 
			
		||||
          modules
 | 
			
		||||
          data
 | 
			
		||||
          )
 | 
			
		||||
        )
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -422,59 +423,68 @@ sub Set {
 | 
			
		||||
    my $endpoint;
 | 
			
		||||
    my $param;
 | 
			
		||||
 | 
			
		||||
    $cmd = lc($cmd);
 | 
			
		||||
    $cmd = lc $cmd;
 | 
			
		||||
 | 
			
		||||
    given ($cmd) {
 | 
			
		||||
        when ('getdevicelist') {
 | 
			
		||||
            return 'usage: getDeviceList' if ($arg);
 | 
			
		||||
    my %handlers = (
 | 
			
		||||
        getdevicelist => sub {
 | 
			
		||||
            return 'usage: getDeviceList' if $arg;
 | 
			
		||||
            $endpoint = 'list';
 | 
			
		||||
        }
 | 
			
		||||
        when ('info') {
 | 
			
		||||
            return 'usage: info' if ($arg);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        info => sub {
 | 
			
		||||
            return 'usage: info' if $arg;
 | 
			
		||||
            $endpoint = 'info';
 | 
			
		||||
        }
 | 
			
		||||
        when ('fwupdate') {
 | 
			
		||||
            return 'usage: fwUpdate' if ($arg);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        fwupdate => sub {
 | 
			
		||||
            return 'usage: fwUpdate' if $arg;
 | 
			
		||||
            $endpoint = 'fwupdate';
 | 
			
		||||
        }
 | 
			
		||||
        when ('reboot') {
 | 
			
		||||
            return 'usage: freboot' if ($arg);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        reboot => sub {
 | 
			
		||||
            return 'usage: reboot' if $arg;
 | 
			
		||||
            $endpoint = 'reboot';
 | 
			
		||||
        }
 | 
			
		||||
        when ('clearlog') {
 | 
			
		||||
            return 'usage: clearLog' if ($arg);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        clearlog => sub {
 | 
			
		||||
            return 'usage: clearLog' if $arg;
 | 
			
		||||
            $endpoint = 'clearlog';
 | 
			
		||||
        }
 | 
			
		||||
        when ('factoryreset') {
 | 
			
		||||
            return 'usage: factoryReset' if ($arg);
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        factoryreset => sub {
 | 
			
		||||
            return 'usage: factoryReset' if $arg;
 | 
			
		||||
            $endpoint = 'factoryreset';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        when ('callbackremove') {
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        callbackremove => sub {
 | 
			
		||||
            return 'usage: callbackRemove'
 | 
			
		||||
              if ( split( m{\s+}xms, $arg ) > 1 );
 | 
			
		||||
            my $id = ( defined($arg) ? $arg : 0 );
 | 
			
		||||
            my $id = defined $arg ? $arg : 0;
 | 
			
		||||
            $endpoint = 'callback/remove';
 | 
			
		||||
            $param    = '{"param":"' . $id . '"}';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        when ('configauth') {
 | 
			
		||||
            return 'usage: configAuth' if ( split( m{\s+}xms, $arg ) > 1 );
 | 
			
		||||
            $endpoint = 'clearlog';
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        configauth => sub {
 | 
			
		||||
            return 'usage: configAuth'
 | 
			
		||||
              if ( split( m{\s+}xms, $arg ) > 1 );
 | 
			
		||||
            my $configAuth = 'enable=' . ( $arg eq 'enable' ? 1 : 0 );
 | 
			
		||||
            $endpoint = 'configAuth';
 | 
			
		||||
            $param    = '{"param":"' . $configAuth . '"}';
 | 
			
		||||
        }
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
        default {
 | 
			
		||||
            my $list = '';
 | 
			
		||||
            $list .= 'info:noArg getDeviceList:noArg ';
 | 
			
		||||
            $list .=
 | 
			
		||||
    if ( exists $handlers{$cmd} ) {
 | 
			
		||||
        my $result = $handlers{$cmd}->();
 | 
			
		||||
        return $result
 | 
			
		||||
          if defined $result && length $result;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        my $list = 'info:noArg getDeviceList:noArg ';
 | 
			
		||||
        $list .=
 | 
			
		||||
'clearLog:noArg fwUpdate:noArg reboot:noArg factoryReset:noArg configAuth:enable,disable'
 | 
			
		||||
              if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq
 | 
			
		||||
                'Hardware' );
 | 
			
		||||
            return ( 'Unknown argument ' . $cmd . ', choose one of ' . $list );
 | 
			
		||||
        }
 | 
			
		||||
          if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq 'Hardware' );
 | 
			
		||||
        return "Unknown argument $cmd, choose one of $list";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Write( $hash, $endpoint, $param )
 | 
			
		||||
@@ -486,30 +496,37 @@ sub Set {
 | 
			
		||||
sub Get {
 | 
			
		||||
    my $hash = shift;
 | 
			
		||||
    my $name = shift;
 | 
			
		||||
    my $cmd  = shift // return "set $name needs at least one argument !";
 | 
			
		||||
    my $cmd  = shift // return "get $name needs at least one argument !";
 | 
			
		||||
    my $arg  = shift;
 | 
			
		||||
 | 
			
		||||
    my $endpoint;
 | 
			
		||||
 | 
			
		||||
    $cmd = lc($cmd);
 | 
			
		||||
    given ($cmd) {
 | 
			
		||||
        when ( $cmd eq 'logfile' ) {
 | 
			
		||||
            return 'usage: logFile' if ( defined($arg) );
 | 
			
		||||
            $endpoint = 'log';
 | 
			
		||||
        }
 | 
			
		||||
        when ( $cmd eq 'callbacklist' ) {
 | 
			
		||||
            return 'usage: callbackList' if ( defined($arg) );
 | 
			
		||||
            $endpoint = 'callback/list';
 | 
			
		||||
        }
 | 
			
		||||
        default {
 | 
			
		||||
            my $list = '';
 | 
			
		||||
            $list .= 'callbackList:noArg ';
 | 
			
		||||
            $list .= 'logFile:noArg'
 | 
			
		||||
              if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq
 | 
			
		||||
                'Hardware' );
 | 
			
		||||
    $cmd = lc $cmd;
 | 
			
		||||
 | 
			
		||||
            return 'Unknown argument ' . $cmd . ', choose one of ' . $list;
 | 
			
		||||
        }
 | 
			
		||||
    my %handlers = (
 | 
			
		||||
        logfile => sub {
 | 
			
		||||
            return 'usage: logFile' if defined $arg;
 | 
			
		||||
            $endpoint = 'log';
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
        callbacklist => sub {
 | 
			
		||||
            return 'usage: callbackList' if defined $arg;
 | 
			
		||||
            $endpoint = 'callback/list';
 | 
			
		||||
            return;
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if ( exists $handlers{$cmd} ) {
 | 
			
		||||
        my $result = $handlers{$cmd}->();
 | 
			
		||||
        return $result
 | 
			
		||||
          if defined $result && length $result;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        my $list = 'callbackList:noArg ';
 | 
			
		||||
        $list .= 'logFile:noArg'
 | 
			
		||||
          if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq 'Hardware' );
 | 
			
		||||
 | 
			
		||||
        return "Unknown argument $cmd, choose one of $list";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Write( $hash, $endpoint, undef );
 | 
			
		||||
@@ -765,7 +782,7 @@ sub DistributionErrHandle2 {
 | 
			
		||||
        ::asyncOutput( $param->{cl}, "Request Error: $err\r\n" )
 | 
			
		||||
          if ( $param->{cl} && $param->{cl}{canAsyncOutput} );
 | 
			
		||||
 | 
			
		||||
        return ('received http code '
 | 
			
		||||
        return ( 'received http code '
 | 
			
		||||
              . $param->{code}
 | 
			
		||||
              . ' without any data after requesting' );
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,9 @@ package FHEM::Devices::Nuki::Device;
 | 
			
		||||
 | 
			
		||||
use strict;
 | 
			
		||||
use warnings;
 | 
			
		||||
use experimental qw( switch );
 | 
			
		||||
 | 
			
		||||
#use experimental qw( switch );
 | 
			
		||||
use Encode;
 | 
			
		||||
use FHEM::Meta;
 | 
			
		||||
 | 
			
		||||
use GPUtils qw(GP_Import);
 | 
			
		||||
@@ -41,7 +42,7 @@ BEGIN {
 | 
			
		||||
        qw( init_done
 | 
			
		||||
          defs
 | 
			
		||||
          modules
 | 
			
		||||
          )
 | 
			
		||||
        )
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -355,7 +356,7 @@ sub Set {
 | 
			
		||||
        GetUpdate($hash);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($cmd eq 'lock'
 | 
			
		||||
    elsif ( $cmd eq 'lock'
 | 
			
		||||
        || lc($cmd) eq 'deactivaterto'
 | 
			
		||||
        || $cmd eq 'unlock'
 | 
			
		||||
        || lc($cmd) eq 'activaterto'
 | 
			
		||||
@@ -534,21 +535,23 @@ sub WriteReadings {
 | 
			
		||||
 | 
			
		||||
    ::readingsBeginUpdate($hash);
 | 
			
		||||
 | 
			
		||||
    my $t;
 | 
			
		||||
    my $v;
 | 
			
		||||
    my ( $t, $v );
 | 
			
		||||
 | 
			
		||||
    if ( defined( $decode_json->{lastKnownState} )
 | 
			
		||||
    # falls lastKnownState als Hash vorliegt, direkt integrieren
 | 
			
		||||
    if ( defined $decode_json->{lastKnownState}
 | 
			
		||||
        && ref( $decode_json->{lastKnownState} ) eq 'HASH' )
 | 
			
		||||
    {
 | 
			
		||||
        while ( ( $t, $v ) = each %{ $decode_json->{lastKnownState} } ) {
 | 
			
		||||
            $decode_json->{$t} = $v;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        delete $decode_json->{lastKnownState};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ( ( $t, $v ) = each %{$decode_json} ) {
 | 
			
		||||
        ::readingsBulkUpdate( $hash, $t, $v )
 | 
			
		||||
 | 
			
		||||
        # generische readings (alles außer spezielle Felder)
 | 
			
		||||
        ::readingsBulkUpdate( $hash, $t,
 | 
			
		||||
            Encode::is_utf8($v) ? Encode::encode( "UTF-8", $v ) : $v )
 | 
			
		||||
          if ( $t ne 'state'
 | 
			
		||||
            && $t ne 'mode'
 | 
			
		||||
            && $t ne 'deviceType'
 | 
			
		||||
@@ -560,42 +563,48 @@ sub WriteReadings {
 | 
			
		||||
            && $t ne 'doorsensorState'
 | 
			
		||||
            && $t ne 'doorsensorStateName' );
 | 
			
		||||
 | 
			
		||||
        given ($t) {
 | 
			
		||||
            when ('state') {
 | 
			
		||||
                ::readingsBulkUpdate(
 | 
			
		||||
                    $hash, $t,
 | 
			
		||||
                    (
 | 
			
		||||
                          $v =~ m{\A[0-9]\z}xms
 | 
			
		||||
                        ? $lockStates{$v}->{ $hash->{DEVICETYPEID} }
 | 
			
		||||
                        : $v
 | 
			
		||||
                    )
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            when ('mode') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, $t,
 | 
			
		||||
        # Dispatch-Tabelle für Spezialfälle
 | 
			
		||||
        my %handlers = (
 | 
			
		||||
            state => sub {
 | 
			
		||||
                my $val =
 | 
			
		||||
                  ( $v =~ m{\A[0-9]\z}xms )
 | 
			
		||||
                  ? $lockStates{$v}->{ $hash->{DEVICETYPEID} }
 | 
			
		||||
                  : $v;
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'state', $val );
 | 
			
		||||
            },
 | 
			
		||||
            mode => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'mode',
 | 
			
		||||
                    $modes{$v}{ $hash->{DEVICETYPEID} } );
 | 
			
		||||
            }
 | 
			
		||||
            when ('deviceType') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, $t, $deviceTypes{$v} );
 | 
			
		||||
            }
 | 
			
		||||
            when ('doorsensorState') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, $t, $doorsensorStates{$v} );
 | 
			
		||||
            }
 | 
			
		||||
            when ('paired') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, $t,
 | 
			
		||||
            },
 | 
			
		||||
            devicetype => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'deviceType', $deviceTypes{$v} );
 | 
			
		||||
            },
 | 
			
		||||
            doorsensorstate => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'doorsensorState',
 | 
			
		||||
                    $doorsensorStates{$v} );
 | 
			
		||||
            },
 | 
			
		||||
            paired => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'paired',
 | 
			
		||||
                    ( $v == 1 ? 'true' : 'false' ) );
 | 
			
		||||
            }
 | 
			
		||||
            when ('batteryCharging') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, $t,
 | 
			
		||||
            },
 | 
			
		||||
            batterycharging => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'batteryCharging',
 | 
			
		||||
                    ( $v == 1 ? 'true' : 'false' ) );
 | 
			
		||||
            }
 | 
			
		||||
            when ('batteryCritical') {
 | 
			
		||||
            },
 | 
			
		||||
            batterycritical => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'batteryState',
 | 
			
		||||
                    ( $v == 1 ? 'low' : 'ok' ) );
 | 
			
		||||
            }
 | 
			
		||||
            when ('batteryChargeState') {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'batteryPercent', $v )
 | 
			
		||||
            }
 | 
			
		||||
            },
 | 
			
		||||
            batterychargestate => sub {
 | 
			
		||||
                ::readingsBulkUpdate( $hash, 'batteryPercent', $v );
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        my $key =
 | 
			
		||||
          lc $t;    # damit Vergleiche robust gegen Groß-/Kleinschreibung sind
 | 
			
		||||
 | 
			
		||||
        if ( exists $handlers{$key} ) {
 | 
			
		||||
            $handlers{$key}->();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user