Update Nuki Bridge and Device to version 2.1.0 #31

Merged
marko merged 1 commits from dev into main 2025-10-14 09:00:21 +00:00
5 changed files with 116 additions and 103 deletions

View File

@@ -267,7 +267,7 @@ sub Initialize {
], ],
"release_status": "stable", "release_status": "stable",
"license": "GPL_2", "license": "GPL_2",
"version": "v2.0.2", "version": "v2.1.0",
"x_apiversion": "1.13.0", "x_apiversion": "1.13.0",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"

View File

@@ -271,7 +271,7 @@ sub Initialize {
], ],
"release_status": "stable", "release_status": "stable",
"license": "GPL_2", "license": "GPL_2",
"version": "v2.0.2", "version": "v2.1.0",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"
], ],

View File

@@ -1,4 +1,4 @@
UPD 2021-12-17_12:18:33 10358 FHEM/73_NUKIBridge.pm UPD 2025-10-14_10:40:53 10358 FHEM/73_NUKIBridge.pm
UPD 2021-12-17_12:44:59 11100 FHEM/74_NUKIDevice.pm UPD 2025-10-14_10:41:09 11100 FHEM/74_NUKIDevice.pm
UPD 2022-09-26_11:59:12 42767 lib/FHEM/Devices/Nuki/Bridge.pm UPD 2025-10-14_10:42:11 42820 lib/FHEM/Devices/Nuki/Bridge.pm
UPD 2021-12-17_12:18:33 16338 lib/FHEM/Devices/Nuki/Device.pm UPD 2025-10-14_10:42:04 16698 lib/FHEM/Devices/Nuki/Device.pm

View File

@@ -39,7 +39,8 @@ package FHEM::Devices::Nuki::Bridge;
use strict; use strict;
use warnings; use warnings;
use experimental qw( switch );
#use experimental qw( switch );
use FHEM::Meta; use FHEM::Meta;
use HttpUtils; use HttpUtils;
@@ -422,59 +423,59 @@ sub Set {
my $endpoint; my $endpoint;
my $param; my $param;
$cmd = lc($cmd); $cmd = lc $cmd;
given ($cmd) { my %handlers = (
when ('getdevicelist') { getdevicelist => sub {
return 'usage: getDeviceList' if ($arg); return 'usage: getDeviceList' if $arg;
$endpoint = 'list'; $endpoint = 'list';
} },
when ('info') { info => sub {
return 'usage: info' if ($arg); return 'usage: info' if $arg;
$endpoint = 'info'; $endpoint = 'info';
} },
when ('fwupdate') { fwupdate => sub {
return 'usage: fwUpdate' if ($arg); return 'usage: fwUpdate' if $arg;
$endpoint = 'fwupdate'; $endpoint = 'fwupdate';
} },
when ('reboot') { reboot => sub {
return 'usage: freboot' if ($arg); return 'usage: reboot' if $arg;
$endpoint = 'reboot'; $endpoint = 'reboot';
} },
when ('clearlog') { clearlog => sub {
return 'usage: clearLog' if ($arg); return 'usage: clearLog' if $arg;
$endpoint = 'clearlog'; $endpoint = 'clearlog';
} },
when ('factoryreset') { factoryreset => sub {
return 'usage: factoryReset' if ($arg); return 'usage: factoryReset' if $arg;
$endpoint = 'factoryreset'; $endpoint = 'factoryreset';
} },
callbackremove => sub {
when ('callbackremove') {
return 'usage: callbackRemove' return 'usage: callbackRemove'
if ( split( m{\s+}xms, $arg ) > 1 ); if ( split( m{\s+}xms, $arg ) > 1 );
my $id = ( defined($arg) ? $arg : 0 ); my $id = defined $arg ? $arg : 0;
$endpoint = 'callback/remove'; $endpoint = 'callback/remove';
$param = '{"param":"' . $id . '"}'; $param = '{"param":"' . $id . '"}';
} },
configauth => sub {
when ('configauth') { return 'usage: configAuth'
return 'usage: configAuth' if ( split( m{\s+}xms, $arg ) > 1 ); if ( split( m{\s+}xms, $arg ) > 1 );
$endpoint = 'clearlog';
my $configAuth = 'enable=' . ( $arg eq 'enable' ? 1 : 0 ); my $configAuth = 'enable=' . ( $arg eq 'enable' ? 1 : 0 );
$endpoint = 'configAuth'; $endpoint = 'configAuth';
$param = '{"param":"' . $configAuth . '"}'; $param = '{"param":"' . $configAuth . '"}';
} },
);
default { if ( exists $handlers{$cmd} ) {
my $list = ''; my $result = $handlers{$cmd}->();
$list .= 'info:noArg getDeviceList:noArg '; return $result if defined $result && length $result;
}
else {
my $list = 'info:noArg getDeviceList:noArg ';
$list .= $list .=
'clearLog:noArg fwUpdate:noArg reboot:noArg factoryReset:noArg configAuth:enable,disable' 'clearLog:noArg fwUpdate:noArg reboot:noArg factoryReset:noArg configAuth:enable,disable'
if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq if ( ::ReadingsVal( $name, 'bridgeType', 'Software' ) eq 'Hardware' );
'Hardware' ); return "Unknown argument $cmd, choose one of $list";
return ( 'Unknown argument ' . $cmd . ', choose one of ' . $list );
}
} }
Write( $hash, $endpoint, $param ) Write( $hash, $endpoint, $param )
@@ -486,30 +487,34 @@ sub Set {
sub Get { sub Get {
my $hash = shift; my $hash = shift;
my $name = 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 $arg = shift;
my $endpoint; my $endpoint;
$cmd = lc($cmd); $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' );
return 'Unknown argument ' . $cmd . ', choose one of ' . $list; my %handlers = (
logfile => sub {
return 'usage: logFile' if defined $arg;
$endpoint = 'log';
},
callbacklist => sub {
return 'usage: callbackList' if defined $arg;
$endpoint = 'callback/list';
},
);
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 ); return Write( $hash, $endpoint, undef );
@@ -765,7 +770,7 @@ sub DistributionErrHandle2 {
::asyncOutput( $param->{cl}, "Request Error: $err\r\n" ) ::asyncOutput( $param->{cl}, "Request Error: $err\r\n" )
if ( $param->{cl} && $param->{cl}{canAsyncOutput} ); if ( $param->{cl} && $param->{cl}{canAsyncOutput} );
return ('received http code ' return ( 'received http code '
. $param->{code} . $param->{code}
. ' without any data after requesting' ); . ' without any data after requesting' );
} }

View File

@@ -28,7 +28,8 @@ package FHEM::Devices::Nuki::Device;
use strict; use strict;
use warnings; use warnings;
use experimental qw( switch );
#use experimental qw( switch );
use FHEM::Meta; use FHEM::Meta;
@@ -355,7 +356,7 @@ sub Set {
GetUpdate($hash); GetUpdate($hash);
return; return;
} }
elsif ($cmd eq 'lock' elsif ( $cmd eq 'lock'
|| lc($cmd) eq 'deactivaterto' || lc($cmd) eq 'deactivaterto'
|| $cmd eq 'unlock' || $cmd eq 'unlock'
|| lc($cmd) eq 'activaterto' || lc($cmd) eq 'activaterto'
@@ -534,20 +535,21 @@ sub WriteReadings {
::readingsBeginUpdate($hash); ::readingsBeginUpdate($hash);
my $t; my ( $t, $v );
my $v;
if ( defined( $decode_json->{lastKnownState} ) # falls lastKnownState als Hash vorliegt, direkt integrieren
if ( defined $decode_json->{lastKnownState}
&& ref( $decode_json->{lastKnownState} ) eq 'HASH' ) && ref( $decode_json->{lastKnownState} ) eq 'HASH' )
{ {
while ( ( $t, $v ) = each %{ $decode_json->{lastKnownState} } ) { while ( ( $t, $v ) = each %{ $decode_json->{lastKnownState} } ) {
$decode_json->{$t} = $v; $decode_json->{$t} = $v;
} }
delete $decode_json->{lastKnownState}; delete $decode_json->{lastKnownState};
} }
while ( ( $t, $v ) = each %{$decode_json} ) { while ( ( $t, $v ) = each %{$decode_json} ) {
# generische readings (alles außer spezielle Felder)
::readingsBulkUpdate( $hash, $t, $v ) ::readingsBulkUpdate( $hash, $t, $v )
if ( $t ne 'state' if ( $t ne 'state'
&& $t ne 'mode' && $t ne 'mode'
@@ -560,42 +562,48 @@ sub WriteReadings {
&& $t ne 'doorsensorState' && $t ne 'doorsensorState'
&& $t ne 'doorsensorStateName' ); && $t ne 'doorsensorStateName' );
given ($t) { # Dispatch-Tabelle für Spezialfälle
when ('state') { my %handlers = (
::readingsBulkUpdate( state => sub {
$hash, $t, my $val =
( ( $v =~ m{\A[0-9]\z}xms )
$v =~ m{\A[0-9]\z}xms
? $lockStates{$v}->{ $hash->{DEVICETYPEID} } ? $lockStates{$v}->{ $hash->{DEVICETYPEID} }
: $v : $v;
) ::readingsBulkUpdate( $hash, 'state', $val );
); },
} mode => sub {
when ('mode') { ::readingsBulkUpdate( $hash, 'mode',
::readingsBulkUpdate( $hash, $t,
$modes{$v}{ $hash->{DEVICETYPEID} } ); $modes{$v}{ $hash->{DEVICETYPEID} } );
} },
when ('deviceType') { devicetype => sub {
::readingsBulkUpdate( $hash, $t, $deviceTypes{$v} ); ::readingsBulkUpdate( $hash, 'deviceType', $deviceTypes{$v} );
} },
when ('doorsensorState') { doorsensorstate => sub {
::readingsBulkUpdate( $hash, $t, $doorsensorStates{$v} ); ::readingsBulkUpdate( $hash, 'doorsensorState',
} $doorsensorStates{$v} );
when ('paired') { },
::readingsBulkUpdate( $hash, $t, paired => sub {
::readingsBulkUpdate( $hash, 'paired',
( $v == 1 ? 'true' : 'false' ) ); ( $v == 1 ? 'true' : 'false' ) );
} },
when ('batteryCharging') { batterycharging => sub {
::readingsBulkUpdate( $hash, $t, ::readingsBulkUpdate( $hash, 'batteryCharging',
( $v == 1 ? 'true' : 'false' ) ); ( $v == 1 ? 'true' : 'false' ) );
} },
when ('batteryCritical') { batterycritical => sub {
::readingsBulkUpdate( $hash, 'batteryState', ::readingsBulkUpdate( $hash, 'batteryState',
( $v == 1 ? 'low' : 'ok' ) ); ( $v == 1 ? 'low' : 'ok' ) );
} },
when ('batteryChargeState') { batterychargestate => sub {
::readingsBulkUpdate( $hash, 'batteryPercent', $v ) ::readingsBulkUpdate( $hash, 'batteryPercent', $v );
} },
);
my $key =
lc $t; # damit Vergleiche robust gegen Groß-/Kleinschreibung sind
if ( exists $handlers{$key} ) {
$handlers{$key}->();
} }
} }