From 43c9882a4eef5d812f1dc85e903aae31498a58c3 Mon Sep 17 00:00:00 2001 From: LeonGaultier Date: Fri, 26 Nov 2021 09:36:50 +0000 Subject: [PATCH] 73_NUKIBridge: add support for new generation smart lock 3 git-svn-id: https://svn.fhem.de/fhem/trunk@25263 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/FHEM/73_NUKIBridge.pm | 134 +++++++++++++++++++++++++++++-------- fhem/FHEM/74_NUKIDevice.pm | 72 +++++++++++++------- 3 files changed, 155 insertions(+), 53 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index 8279cc553..83b5b2733 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. + - feature: 73_NUKIBridge 74_NUKIDevice: add support for + new SmartLock Generation 3 - bugfix: 88_HMCCU: Fixed delayed init and readingname bugs - feature: 93_DbRep: new attr numDecimalPlaces, Forum:#/topic,53584.msg1178063.html#msg1178063 diff --git a/fhem/FHEM/73_NUKIBridge.pm b/fhem/FHEM/73_NUKIBridge.pm index ec039fc20..4c6d1a700 100644 --- a/fhem/FHEM/73_NUKIBridge.pm +++ b/fhem/FHEM/73_NUKIBridge.pm @@ -2,7 +2,7 @@ # # Developed with Kate # -# (c) 2016-2020 Copyright: Marko Oldenburg (leongaultier at gmail dot com) +# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # All rights reserved # # This script is free software; you can redistribute it and/or modify @@ -370,7 +370,8 @@ sub Attr(@) { . $hash->{WEBHOOK_URI}; Log3( $name, 3, "NUKIBridge ($name) - URL ist: $url" ); - Write( $hash, 'callback/add', $url, undef, undef ) +# Write( $hash, 'callback/add', $url, undef, undef ) + Write( $hash, 'callback/add', '{"param":"' . $url . '"}' ) if ($init_done); $hash->{WEBHOOK_REGISTER} = 'sent'; } @@ -444,54 +445,48 @@ sub Set($@) { my ( $hash, $name, $cmd, @args ) = @_; my ( $arg, @params ) = @args; + my $endpoint; if ( lc($cmd) eq 'getdevicelist' ) { return 'usage: getDeviceList' if ( @args != 0 ); - Write( $hash, 'list', undef, undef, undef ) - if ( !IsDisabled($name) ); - return undef; + $endpoint = 'list'; } elsif ( $cmd eq 'info' ) { return 'usage: statusRequest' if ( @args != 0 ); - Write( $hash, 'info', undef, undef, undef ) - if ( !IsDisabled($name) ); - return undef; + $endpoint = 'info'; } elsif ( lc($cmd) eq 'fwupdate' ) { return 'usage: fwUpdate' if ( @args != 0 ); - Write( $hash, 'fwupdate', undef, undef, undef ) - if ( !IsDisabled($name) ); - return undef; + $endpoint = 'fwupdate'; } elsif ( $cmd eq 'reboot' ) { return 'usage: reboot' if ( @args != 0 ); - Write( $hash, 'reboot', undef, undef, undef ) - if ( !IsDisabled($name) ); - return undef; + $endpoint = 'reboot'; } elsif ( lc($cmd) eq 'clearlog' ) { return 'usage: clearLog' if ( @args != 0 ); - Write( $hash, 'clearlog', undef, undef, undef ) - if ( !IsDisabled($name) ); + $endpoint = 'clearlog'; } elsif ( lc($cmd) eq 'factoryreset' ) { return 'usage: clearLog' if ( @args != 0 ); - Write( $hash, 'factoryReset', undef, undef, undef ) - if ( !IsDisabled($name) ); + $endpoint = 'factoryReset'; } elsif ( lc($cmd) eq 'callbackremove' ) { return 'usage: callbackRemove' if ( @args > 1 ); my $id = ( @args > 0 ? join( ' ', @args ) : 0 ); - Write( $hash, 'callback/remove', $id, undef, undef ) +# Write( $hash, 'callback/remove', $id, undef, undef ) + Write( $hash, 'callback/remove', '{"param":"' . $id . '"}' ) if ( !IsDisabled($name) ); + + return undef; } else { my $list = ''; @@ -500,22 +495,26 @@ sub Set($@) { if ( ReadingsVal( $name, 'bridgeType', 'Software' ) eq 'Hardware' ); return ( 'Unknown argument ' . $cmd . ', choose one of ' . $list ); } + + Write( $hash, $endpoint, undef ) + if ( !IsDisabled($name) ); } sub Get($@) { my ( $hash, $name, $cmd, @args ) = @_; my ( $arg, @params ) = @args; + my $endpoint; if ( lc($cmd) eq 'logfile' ) { return 'usage: logFile' if ( @args != 0 ); - Write( $hash, 'log', undef, undef, undef ); + $endpoint = 'log'; } elsif ( lc($cmd) eq 'callbacklist' ) { return 'usage: callbackList' if ( @args != 0 ); - Write( $hash, 'callback/list', undef, undef, undef ); + $endpoint = 'callback/list'; } else { my $list = ''; @@ -525,6 +524,8 @@ sub Get($@) { return 'Unknown argument ' . $cmd . ', choose one of ' . $list; } + + Write( $hash, $endpoint, undef ) } sub GetCheckBridgeAlive($) { @@ -539,7 +540,7 @@ sub GetCheckBridgeAlive($) { and $hash->{helper}->{iowrite} == 0 ) { - Write( $hash, 'info', undef, undef, undef ); + Write( $hash, 'info', undef); Log3( $name, 4, "NUKIBridge ($name) - run Write" ); } @@ -557,7 +558,7 @@ sub FirstRun($) { my $name = $hash->{NAME}; RemoveInternalTimer($hash); - Write( $hash, 'list', undef, undef, undef ) + Write( $hash, 'list', undef ) if ( !IsDisabled($name) ); InternalTimer( gettimeofday() + 5, 'NUKIBridge_GetCheckBridgeAlive', $hash ); @@ -566,7 +567,14 @@ sub FirstRun($) { } sub Write($@) { - my ( $hash, $endpoint, $param, $nukiId, $deviceType ) = @_; + my ( $hash, $endpoint, $json ) = @_; + + my $decode_json = eval { decode_json($json) } + if ( defined($json) ); + + my $nukiId = $decode_json->{nukiId} // undef; + my $deviceType = $decode_json->{deviceType} // undef; + my $param = $decode_json->{param} // undef; my $obj = { endpoint => $endpoint, @@ -608,7 +616,8 @@ sub CreateUri($$) { { $uri .= '&action=' . $lockActionsSmartLock{$param} if ( $endpoint ne 'callback/add' - and $deviceType == 0 ); + and ($deviceType == 0 + || $deviceType == 4) ); $uri .= '&action=' . $lockActionsOpener{$param} if ( $endpoint ne 'callback/add' @@ -910,7 +919,7 @@ sub ResponseProcessing($$$) { } } - InfoProcessing( $hash, $decode_json ) + WriteReadings( $hash, $decode_json ) if ( $endpoint eq 'info' ); } else { @@ -979,7 +988,7 @@ matching NukiId at device $name" return ( 'text/plain; charset=utf-8', 'Call failure: ' . $request ); } -sub InfoProcessing($$) { +sub WriteReadings($$) { my ( $hash, $decode_json ) = @_; my $name = $hash->{NAME}; @@ -1002,7 +1011,7 @@ sub InfoProcessing($$) { readingsBulkUpdate( $hash, 'hardwareId', $decode_json->{ids}{hardwareId} ); readingsBulkUpdate( $hash, 'serverId', $decode_json->{ids}{serverId} ); readingsBulkUpdate( $hash, 'uptime', $decode_json->{uptime} ); - readingsBulkUpdate( $hash, 'currentTime', $decode_json->{currentTime} ); + readingsBulkUpdate( $hash, 'currentGMTime', $decode_json->{currentTime} ); readingsBulkUpdate( $hash, 'serverConnected', $decode_json->{serverConnected} ); readingsEndUpdate( $hash, 1 ); @@ -1137,6 +1146,73 @@ sub getCallbackList($$) { } } +sub getCallbackList2($$) { + my ( $param, $json ) = @_; + + my $hash = $param->{hash}; + my $name = $hash->{NAME}; + + my $decode_json = eval { decode_json($json) }; + if ($@) { + Log3( $name, 3, "NUKIBridge ($name) - JSON error while request: $@" ); + return; + } + + Log3( $name, 4, + "NUKIBridge ($name) - Callback data are collected and processed" ); + + if ( $param->{cl} and $param->{cl}->{TYPE} eq 'FHEMWEB' ) { + if ( ref( $decode_json->{callbacks} ) eq 'ARRAY' ) { + Log3( $name, 4, + "NUKIBridge ($name) - created Table with Callback List" ); + + + my $j1 = ''; + +# FW_cmd(FW_root+"?cmd="+type+" "+dev+ +# (params[0]=="state" ? "":" "+params[0])+" "+arg+"&XHR=1"); + + + my $header = ''; + my $footer = ''; + + my $ret = '
Callback List
' + . ''; + $ret .= '
' + . '' + . '' + . '' + . '' + . ''; + + if ( scalar( @{ $decode_json->{callbacks} } ) > 0 ) { + foreach my $cb ( @{ $decode_json->{callbacks} } ) { + $ret .= ''; + $ret .= ""; + $ret .= ''; + } + } + else { + $ret .= ''; + $ret .= ''; + $ret .= ''; + $ret .= ''; + } + + $ret .= '
URLRemove
' . $cb->{url} . '
nonenone
'; + + Log3( $name, 4, + "NUKIBridge ($name) - Callback List Table created and call asyncOutput Fn" ); + + asyncOutput( $param->{cl}, $header . $ret . $j1 . $footer ) + if ( $param->{cl} and $param->{cl}{canAsyncOutput} ); + return; + } + } +} + sub ParseJSON($$) { my ( $hash, $buffer ) = @_; @@ -1356,7 +1432,7 @@ sub ParseJSON($$) { ], "release_status": "stable", "license": "GPL_2", - "version": "v1.9.16", + "version": "v1.9.50", "x_apiversion": "1.9", "author": [ "Marko Oldenburg " diff --git a/fhem/FHEM/74_NUKIDevice.pm b/fhem/FHEM/74_NUKIDevice.pm index 519f6f087..ad99e94c1 100644 --- a/fhem/FHEM/74_NUKIDevice.pm +++ b/fhem/FHEM/74_NUKIDevice.pm @@ -2,7 +2,7 @@ # # Developed with Kate # -# (c) 2016-2020 Copyright: Marko Oldenburg (leongaultier at gmail dot com) +# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # All rights reserved # # This script is free software; you can redistribute it and/or modify @@ -127,7 +127,6 @@ BEGIN { modules Log3 CommandAttr - CommandDefMod AttrVal IsDisabled deviceEvents @@ -149,7 +148,8 @@ GP_Export( my %deviceTypes = ( 0 => 'smartlock', - 2 => 'opener' + 2 => 'opener', + 4 => 'smartlockNG' ); my %modes = ( @@ -166,47 +166,58 @@ my %modes = ( my %lockStates = ( 0 => { 0 => 'uncalibrated', - 2 => 'untrained' + 2 => 'untrained', + 4 => 'uncalibrated' }, 1 => { 0 => 'locked', - 2 => 'online' + 2 => 'online', + 4 => 'locked' }, 2 => { 0 => 'unlocking', - 2 => '-' + 2 => '-', + 4 => 'unlocking' }, 3 => { 0 => 'unlocked', - 2 => 'rto active' + 2 => 'rto active', + 4 => 'unlocked' }, 4 => { 0 => 'locking', - 2 => '-' + 2 => '-', + 4 => 'locking' }, 5 => { 0 => 'unlatched', - 2 => 'open' + 2 => 'open', + 4 => 'unlatched' }, 6 => { 0 => 'unlocked (lock ā€˜nā€™ go)', - 2 => '-' + 2 => '-', + 4 => 'unlocked (lock ā€˜nā€™ go)' }, 7 => { 0 => 'unlatching', - 2 => 'opening' + 2 => 'opening', + 4 => 'unlatching' }, 253 => { 0 => '-', - 2 => 'boot run' + 2 => 'boot run', + 4 => '-' }, 254 => { 0 => 'motor blocked', - 2 => '-' + 2 => '-', + 4 => 'motor blocked' }, 255 => { 0 => 'undefined', - 2 => 'undefined' + 2 => 'undefined', + 4 => 'undefined' } ); @@ -412,7 +423,8 @@ sub Set($$@) { my $list = ''; $list = 'statusRequest:noArg unlock:noArg lock:noArg unlatch:noArg locknGo:noArg locknGoWithUnlatch:noArg unpair:noArg' - if ( $hash->{DEVICETYPE} == 0 ); + if ( $hash->{DEVICETYPE} == 0 + || $hash->{DEVICETYPE} == 4 ); $list = 'statusRequest:noArg activateRto:noArg deactivateRto:noArg electricStrikeActuation:noArg activateContinuousMode:noArg deactivateContinuousMode:noArg unpair:noArg' if ( $hash->{DEVICETYPE} == 2 ); @@ -422,8 +434,11 @@ sub Set($$@) { $hash->{helper}{lockAction} = $lockAction; - IOWrite( $hash, 'lockAction', $lockAction, $hash->{NUKIID}, - $hash->{DEVICETYPE} ); +# IOWrite( $hash, 'lockAction', $lockAction, $hash->{NUKIID}, +# $hash->{DEVICETYPE} ); + + IOWrite( $hash, 'lockAction', '{"param":"' . $lockAction + . '","nukiId":' . $hash->{NUKIID} . ',"deviceType":' . $hash->{DEVICETYPE} . '}' ); return undef; } @@ -434,8 +449,12 @@ sub GetUpdate($) { my $name = $hash->{NAME}; if ( !IsDisabled($name) ) { - IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, - $hash->{DEVICETYPE} ); +# IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, +# $hash->{DEVICETYPE} ); + + IOWrite( $hash, 'lockState', '{"nukiId":' . $hash->{NUKIID} + . ',"deviceType":' . $hash->{DEVICETYPE} . '}' ); + Log3( $name, 2, "NUKIDevice ($name) - GetUpdate Call IOWrite" ); } @@ -498,7 +517,7 @@ sub Parse($$) { return $hash->{NAME}; } else { - Log3( $name, 3, + Log3( $name, 4, "NUKIDevice ($name) - autocreate new device " . makeDeviceName( $decode_json->{name} ) . " with nukiId $decode_json->{nukiId}, model $decode_json->{deviceType}" @@ -532,7 +551,10 @@ sub WriteReadings($$) { ) { $state = $hash->{helper}{lockAction}; - IOWrite( $hash, 'lockState', undef, $hash->{NUKIID} ) +# IOWrite( $hash, 'lockState', undef, $hash->{NUKIID} ) + + IOWrite( $hash, 'lockState', '{"nukiId":' . $hash->{NUKIID} + . ',"deviceType":' . $hash->{DEVICETYPE} . '}' ) if ( ReadingsVal( $hash->{IODev}->{NAME}, 'bridgeType', 'Software' ) eq 'Software' ); @@ -546,8 +568,10 @@ sub WriteReadings($$) { { $state = $deviceTypes{ $hash->{DEVICETYPE} } . ' response error'; - IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, - $hash->{DEVICETYPE} ); +# IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, +# $hash->{DEVICETYPE} ); + IOWrite( $hash, 'lockState', '{"nukiId":' . $hash->{NUKIID} + . ',"deviceType":' . $hash->{DEVICETYPE} . '}' ); } $decode_json->{'state'} = $state; @@ -745,7 +769,7 @@ sub WriteReadings($$) { ], "release_status": "stable", "license": "GPL_2", - "version": "v1.9.12", + "version": "v1.9.50", "author": [ "Marko Oldenburg " ],