From 7c45784c1f72b238459d56864706a2e09caf6419 Mon Sep 17 00:00:00 2001 From: Marko Oldenburg Date: Tue, 14 Oct 2025 10:45:26 +0200 Subject: [PATCH] Update Nuki Bridge and Device to version 2.1.0 The Nuki Bridge and Device modules have been updated to version 2.1.0. Key changes include enhancements to the command handling within the Bridge module, replacing the `given/when` construct with a more flexible hash-based dispatcher for clarity and maintainability. Additionally, minor refinements have been made in the Device module, including improved reading updates and handling of last known device states. The experimental feature switch has been commented out, ensuring compatibility with standard Perl versions. These updates improve the overall robustness and readability of the code, making it easier to maintain and extend in future versions. No breaking changes have been introduced. --- FHEM/73_NUKIBridge.pm | 2 +- FHEM/74_NUKIDevice.pm | 2 +- controls_NukiSmart.txt | 8 +-- lib/FHEM/Devices/Nuki/Bridge.pm | 123 +++++++++++++++++--------------- lib/FHEM/Devices/Nuki/Device.pm | 84 ++++++++++++---------- 5 files changed, 116 insertions(+), 103 deletions(-) diff --git a/FHEM/73_NUKIBridge.pm b/FHEM/73_NUKIBridge.pm index 4719c8e..503734e 100644 --- a/FHEM/73_NUKIBridge.pm +++ b/FHEM/73_NUKIBridge.pm @@ -267,7 +267,7 @@ sub Initialize { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.0.2", + "version": "v2.1.0", "x_apiversion": "1.13.0", "author": [ "Marko Oldenburg " diff --git a/FHEM/74_NUKIDevice.pm b/FHEM/74_NUKIDevice.pm index 236e7c0..b795a4e 100644 --- a/FHEM/74_NUKIDevice.pm +++ b/FHEM/74_NUKIDevice.pm @@ -271,7 +271,7 @@ sub Initialize { ], "release_status": "stable", "license": "GPL_2", - "version": "v2.0.2", + "version": "v2.1.0", "author": [ "Marko Oldenburg " ], diff --git a/controls_NukiSmart.txt b/controls_NukiSmart.txt index c3dbd4c..ce9b57c 100644 --- a/controls_NukiSmart.txt +++ b/controls_NukiSmart.txt @@ -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-14_10:40:53 10358 FHEM/73_NUKIBridge.pm +UPD 2025-10-14_10:41:09 11100 FHEM/74_NUKIDevice.pm +UPD 2025-10-14_10:42:11 42820 lib/FHEM/Devices/Nuki/Bridge.pm +UPD 2025-10-14_10:42:04 16698 lib/FHEM/Devices/Nuki/Device.pm diff --git a/lib/FHEM/Devices/Nuki/Bridge.pm b/lib/FHEM/Devices/Nuki/Bridge.pm index d8095a1..03ba361 100644 --- a/lib/FHEM/Devices/Nuki/Bridge.pm +++ b/lib/FHEM/Devices/Nuki/Bridge.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,59 @@ 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); + }, + info => sub { + return 'usage: info' if $arg; $endpoint = 'info'; - } - when ('fwupdate') { - return 'usage: fwUpdate' if ($arg); + }, + fwupdate => sub { + return 'usage: fwUpdate' if $arg; $endpoint = 'fwupdate'; - } - when ('reboot') { - return 'usage: freboot' if ($arg); + }, + reboot => sub { + return 'usage: reboot' if $arg; $endpoint = 'reboot'; - } - when ('clearlog') { - return 'usage: clearLog' if ($arg); + }, + clearlog => sub { + return 'usage: clearLog' if $arg; $endpoint = 'clearlog'; - } - when ('factoryreset') { - return 'usage: factoryReset' if ($arg); + }, + factoryreset => sub { + return 'usage: factoryReset' if $arg; $endpoint = 'factoryreset'; - } - - when ('callbackremove') { + }, + 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'; + }, + 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 . '"}'; - } + }, + ); - 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 +487,34 @@ 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'; + }, + 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 ); @@ -765,7 +770,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' ); } diff --git a/lib/FHEM/Devices/Nuki/Device.pm b/lib/FHEM/Devices/Nuki/Device.pm index 61bf58b..91766f4 100644 --- a/lib/FHEM/Devices/Nuki/Device.pm +++ b/lib/FHEM/Devices/Nuki/Device.pm @@ -28,7 +28,8 @@ package FHEM::Devices::Nuki::Device; use strict; use warnings; -use experimental qw( switch ); + +#use experimental qw( switch ); use FHEM::Meta; @@ -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,20 +535,21 @@ 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} ) { + + # generische readings (alles außer spezielle Felder) ::readingsBulkUpdate( $hash, $t, $v ) if ( $t ne 'state' && $t ne 'mode' @@ -560,42 +562,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}->(); } }