change modules to use packages

This commit is contained in:
Marko Oldenburg 2020-01-13 13:56:57 +01:00
parent 9d610f5ee8
commit 8e393b1bd1
2 changed files with 282 additions and 197 deletions

View File

@ -38,10 +38,16 @@
package main; package main;
use strict;
use warnings;
package FHEM::NUKIBridge;
use strict; use strict;
use warnings; use warnings;
use HttpUtils; use HttpUtils;
use FHEM::Meta; use FHEM::Meta;
use GPUtils qw(GP_Import GP_Export);
# try to use JSON::MaybeXS wrapper # try to use JSON::MaybeXS wrapper
# for chance of better performance + open code # for chance of better performance + open code
@ -114,6 +120,49 @@ if ($@) {
} }
} }
## Import der FHEM Funktionen
#-- Run before package compilation
BEGIN {
# Import from main context
GP_Import(
qw(
readingsSingleUpdate
readingsBulkUpdate
readingsBeginUpdate
readingsEndUpdate
readingFnAttributes
defs
modules
Log3
CommandAttr
AttrVal
IsDisabled
deviceEvents
init_done
gettimeofday
InternalTimer
InternalVal
ReadingsVal
RemoveInternalTimer
HttpUtils_NonblockingGet
asyncOutput
data
TimeNow
devspec2array
Dispatch)
);
}
#-- Export to main context with different name
GP_Export(
qw(
GetCheckBridgeAlive
Initialize
CGI
BridgeCall
)
);
my %bridgeType = ( my %bridgeType = (
'1' => 'Hardware', '1' => 'Hardware',
@ -136,31 +185,11 @@ my %lockActionsOpener = (
'deactivateContinuousMode' => 5 'deactivateContinuousMode' => 5
); );
# Declare functions sub Initialize($) {
sub NUKIBridge_Initialize ($);
sub NUKIBridge_Define ($$);
sub NUKIBridge_Undef ($$);
sub NUKIBridge_Attr(@);
sub NUKIBridge_addExtension($$$);
sub NUKIBridge_removeExtension($);
sub NUKIBridge_Set($@);
sub NUKIBridge_Get($@);
sub NUKIBridge_GetCheckBridgeAlive($);
sub NUKIBridge_firstRun($);
sub NUKIBridge_Write($@);
sub NUKIBridge_Call($);
sub NUKIBridge_Distribution($$$);
sub NUKIBridge_ResponseProcessing($$$);
sub NUKIBridge_CGI();
sub NUKIBridge_InfoProcessing($$);
sub NUKIBridge_getLogfile($$);
sub NUKIBridge_getCallbackList($$);
sub NUKIBridge_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
# Provider # Provider
$hash->{WriteFn} = 'NUKIBridge_Write'; $hash->{WriteFn} = 'FHEM::NUKIBridge::Write';
$hash->{Clients} = ':NUKIDevice:'; $hash->{Clients} = ':NUKIDevice:';
$hash->{MatchList} = { '1:NUKIDevice' => '^{.*}$' }; $hash->{MatchList} = { '1:NUKIDevice' => '^{.*}$' };
@ -168,11 +197,12 @@ sub NUKIBridge_Initialize($) {
join( ",", devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') ); join( ",", devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') );
# Consumer # Consumer
$hash->{SetFn} = 'NUKIBridge_Set'; $hash->{SetFn} = 'FHEM::NUKIBridge::Set';
$hash->{GetFn} = 'NUKIBridge_Get'; $hash->{GetFn} = 'FHEM::NUKIBridge::Get';
$hash->{DefFn} = 'NUKIBridge_Define'; $hash->{DefFn} = 'FHEM::NUKIBridge::Define';
$hash->{UndefFn} = 'NUKIBridge_Undef'; $hash->{UndefFn} = 'FHEM::NUKIBridge::Undef';
$hash->{AttrFn} = 'NUKIBridge_Attr'; $hash->{NotifyFn} = 'FHEM::NUKIBridge::Notify';
$hash->{AttrFn} = 'FHEM::NUKIBridge::Attr';
$hash->{AttrList} = $hash->{AttrList} =
'disable:1 ' 'disable:1 '
. 'webhookFWinstance:' . 'webhookFWinstance:'
@ -183,7 +213,7 @@ sub NUKIBridge_Initialize($) {
return FHEM::Meta::InitMod( __FILE__, $hash ); return FHEM::Meta::InitMod( __FILE__, $hash );
} }
sub NUKIBridge_Define($$) { sub Define($$) {
my ( $hash, $def ) = @_; my ( $hash, $def ) = @_;
my @a = split( "[ \t][ \t]*", $def ); my @a = split( "[ \t][ \t]*", $def );
@ -202,8 +232,9 @@ sub NUKIBridge_Define($$) {
$hash->{HOST} = $host; $hash->{HOST} = $host;
$hash->{PORT} = $port; $hash->{PORT} = $port;
$hash->{TOKEN} = $token; $hash->{TOKEN} = $token;
$hash->{NOTIFYDEV} = 'global,' . $name;
$hash->{VERSION} = version->parse($VERSION)->normal; $hash->{VERSION} = version->parse($VERSION)->normal;
$hash->{BRIDGEAPI} = FHEM::Meta::Get( $hash, 'x_apiversion' );; $hash->{BRIDGEAPI} = FHEM::Meta::Get( $hash, 'x_apiversion' );
$hash->{helper}->{aliveCount} = 0; $hash->{helper}->{aliveCount} = 0;
$hash->{helper}->{actionQueue} = []; $hash->{helper}->{actionQueue} = [];
$hash->{helper}->{iowrite} = 0; $hash->{helper}->{iowrite} = 0;
@ -216,12 +247,7 @@ sub NUKIBridge_Define($$) {
CommandAttr( undef, $name . ' room NUKI' ) CommandAttr( undef, $name . ' room NUKI' )
if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
if ( if ( addExtension( $name, 'NUKIBridge_CGI', $infix . "-" . $host ) ) {
NUKIBridge_addExtension(
$name, 'NUKIBridge_CGI', $infix . "-" . $host
)
)
{
$hash->{fhem}{infix} = $infix; $hash->{fhem}{infix} = $infix;
} }
@ -231,28 +257,19 @@ sub NUKIBridge_Define($$) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
if ($init_done) {
NUKIBridge_firstRun($hash)
if ( ( $hash->{HOST} ) and ( $hash->{TOKEN} ) );
}
else {
InternalTimer( gettimeofday() + 15, 'NUKIBridge_firstRun', $hash )
if ( ( $hash->{HOST} ) and ( $hash->{TOKEN} ) );
}
$modules{NUKIBridge}{defptr}{ $hash->{HOST} } = $hash; $modules{NUKIBridge}{defptr}{ $hash->{HOST} } = $hash;
return undef; return undef;
} }
sub NUKIBridge_Undef($$) { sub Undef($$) {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
my $host = $hash->{HOST}; my $host = $hash->{HOST};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if ( defined( $hash->{fhem}{infix} ) ) { if ( defined( $hash->{fhem}{infix} ) ) {
NUKIBridge_removeExtension( $hash->{fhem}{infix} ); removeExtension( $hash->{fhem}{infix} );
} }
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
@ -261,7 +278,7 @@ sub NUKIBridge_Undef($$) {
return undef; return undef;
} }
sub NUKIBridge_Attr(@) { sub Attr(@) {
my ( $cmd, $name, $attrName, $attrVal ) = @_; my ( $cmd, $name, $attrName, $attrVal ) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -354,7 +371,7 @@ sub NUKIBridge_Attr(@) {
. $hash->{WEBHOOK_URI}; . $hash->{WEBHOOK_URI};
Log3( $name, 3, "NUKIBridge ($name) - URL ist: $url" ); Log3( $name, 3, "NUKIBridge ($name) - URL ist: $url" );
NUKIBridge_Write( $hash, 'callback/add', $url, undef, undef ) Write( $hash, 'callback/add', $url, undef, undef )
if ($init_done); if ($init_done);
$hash->{WEBHOOK_REGISTER} = 'sent'; $hash->{WEBHOOK_REGISTER} = 'sent';
} }
@ -366,7 +383,33 @@ sub NUKIBridge_Attr(@) {
return undef; return undef;
} }
sub NUKIBridge_addExtension($$$) { sub Notify($$) {
my ( $hash, $dev ) = @_;
my $name = $hash->{NAME};
return if ( IsDisabled($name) );
my $devname = $dev->{NAME};
my $devtype = $dev->{TYPE};
my $events = deviceEvents( $dev, 1 );
return if ( !$events );
FirstRun($hash)
if (
(
grep /^INITIALIZED$/, @{$events}
or grep /^REREADCFG$/, @{$events}
or grep /^MODIFIED.$name$/, @{$events}
or grep /^DEFINED.$name$/, @{$events}
)
and $devname eq 'global'
and $init_done
);
return;
}
sub addExtension($$$) {
my ( $name, $func, $link ) = @_; my ( $name, $func, $link ) = @_;
my $url = '/' . $link; my $url = '/' . $link;
@ -382,7 +425,7 @@ sub NUKIBridge_addExtension($$$) {
return 1; return 1;
} }
sub NUKIBridge_removeExtension($) { sub removeExtension($) {
my ($link) = @_; my ($link) = @_;
my $url = '/' . $link; my $url = '/' . $link;
@ -394,7 +437,7 @@ sub NUKIBridge_removeExtension($) {
delete $data{FWEXT}{$url}; delete $data{FWEXT}{$url};
} }
sub NUKIBridge_Set($@) { sub Set($@) {
my ( $hash, $name, $cmd, @args ) = @_; my ( $hash, $name, $cmd, @args ) = @_;
my ( $arg, @params ) = @args; my ( $arg, @params ) = @args;
@ -402,41 +445,41 @@ sub NUKIBridge_Set($@) {
if ( lc($cmd) eq 'getdevicelist' ) { if ( lc($cmd) eq 'getdevicelist' ) {
return 'usage: getDeviceList' if ( @args != 0 ); return 'usage: getDeviceList' if ( @args != 0 );
NUKIBridge_Write( $hash, 'list', undef, undef, undef ) Write( $hash, 'list', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
return undef; return undef;
} }
elsif ( $cmd eq 'info' ) { elsif ( $cmd eq 'info' ) {
return 'usage: statusRequest' if ( @args != 0 ); return 'usage: statusRequest' if ( @args != 0 );
NUKIBridge_Write( $hash, 'info', undef, undef, undef ) Write( $hash, 'info', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
return undef; return undef;
} }
elsif ( lc($cmd) eq 'fwupdate' ) { elsif ( lc($cmd) eq 'fwupdate' ) {
return 'usage: fwUpdate' if ( @args != 0 ); return 'usage: fwUpdate' if ( @args != 0 );
NUKIBridge_Write( $hash, 'fwupdate', undef, undef, undef ) Write( $hash, 'fwupdate', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
return undef; return undef;
} }
elsif ( $cmd eq 'reboot' ) { elsif ( $cmd eq 'reboot' ) {
return 'usage: reboot' if ( @args != 0 ); return 'usage: reboot' if ( @args != 0 );
NUKIBridge_Write( $hash, 'reboot', undef, undef, undef ) Write( $hash, 'reboot', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
return undef; return undef;
} }
elsif ( lc($cmd) eq 'clearlog' ) { elsif ( lc($cmd) eq 'clearlog' ) {
return 'usage: clearLog' if ( @args != 0 ); return 'usage: clearLog' if ( @args != 0 );
NUKIBridge_Write( $hash, 'clearlog', undef, undef, undef ) Write( $hash, 'clearlog', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
} }
elsif ( lc($cmd) eq 'factoryreset' ) { elsif ( lc($cmd) eq 'factoryreset' ) {
return 'usage: clearLog' if ( @args != 0 ); return 'usage: clearLog' if ( @args != 0 );
NUKIBridge_Write( $hash, 'factoryReset', undef, undef, undef ) Write( $hash, 'factoryReset', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
} }
elsif ( lc($cmd) eq 'callbackremove' ) { elsif ( lc($cmd) eq 'callbackremove' ) {
@ -444,26 +487,8 @@ sub NUKIBridge_Set($@) {
my $id = ( @args > 0 ? join( ' ', @args ) : 0 ); my $id = ( @args > 0 ? join( ' ', @args ) : 0 );
NUKIBridge_Write( $hash, 'callback/remove', $id, undef, undef ) Write( $hash, 'callback/remove', $id, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
# my $resp = NUKIBridge_CallBlocking( $hash, 'callback/remove', $id )
# if ( !IsDisabled($name) );
#
# if (
# (
# $resp->{success} eq 'true'
# or $resp->{success} == 1
# )
# and !IsDisabled($name)
# )
# {
# return ( 'Success Callback ' . $id . ' removed' );
# }
# else {
# return ('remove Callback failed');
# }
} }
else { else {
my $list = ''; my $list = '';
@ -474,7 +499,7 @@ sub NUKIBridge_Set($@) {
} }
} }
sub NUKIBridge_Get($@) { sub Get($@) {
my ( $hash, $name, $cmd, @args ) = @_; my ( $hash, $name, $cmd, @args ) = @_;
my ( $arg, @params ) = @args; my ( $arg, @params ) = @args;
@ -482,12 +507,12 @@ sub NUKIBridge_Get($@) {
if ( lc($cmd) eq 'logfile' ) { if ( lc($cmd) eq 'logfile' ) {
return 'usage: logFile' if ( @args != 0 ); return 'usage: logFile' if ( @args != 0 );
NUKIBridge_Write($hash,'log',undef,undef,undef); Write( $hash, 'log', undef, undef, undef );
} }
elsif ( lc($cmd) eq 'callbacklist' ) { elsif ( lc($cmd) eq 'callbacklist' ) {
return 'usage: callbackList' if ( @args != 0 ); return 'usage: callbackList' if ( @args != 0 );
NUKIBridge_Write($hash,'callback/list',undef,undef,undef); Write( $hash, 'callback/list', undef, undef, undef );
} }
else { else {
my $list = ''; my $list = '';
@ -499,47 +524,45 @@ sub NUKIBridge_Get($@) {
} }
} }
sub NUKIBridge_GetCheckBridgeAlive($) { sub GetCheckBridgeAlive($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
Log3( $name, 4, "NUKIBridge ($name) - NUKIBridge_GetCheckBridgeAlive" ); Log3( $name, 4, "NUKIBridge ($name) - GetCheckBridgeAlive" );
if ( !IsDisabled($name) if ( !IsDisabled($name)
and $hash->{helper}->{iowrite} == 0 ) { and $hash->{helper}->{iowrite} == 0 )
{
NUKIBridge_Write( $hash, 'info', undef, undef, undef ); Write( $hash, 'info', undef, undef, undef );
Log3( $name, 4, "NUKIBridge ($name) - run NUKIBridge_Write" ); Log3( $name, 4, "NUKIBridge ($name) - run Write" );
} }
# InternalTimer( gettimeofday() + 15 + int( rand(15) ), InternalTimer( gettimeofday() + 30,
# 'NUKIBridge_GetCheckBridgeAlive', $hash );
InternalTimer( gettimeofday() + 10,
'NUKIBridge_GetCheckBridgeAlive', $hash ); 'NUKIBridge_GetCheckBridgeAlive', $hash );
Log3( $name, 4, Log3( $name, 4,
"NUKIBridge ($name) - Call InternalTimer for NUKIBridge_GetCheckBridgeAlive" "NUKIBridge ($name) - Call InternalTimer for GetCheckBridgeAlive" );
);
} }
sub NUKIBridge_firstRun($) { sub FirstRun($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
NUKIBridge_Write( $hash, 'list', undef, undef, undef ) Write( $hash, 'list', undef, undef, undef )
if ( !IsDisabled($name) ); if ( !IsDisabled($name) );
InternalTimer( gettimeofday() + 15, InternalTimer( gettimeofday() + 5,
'NUKIBridge_GetCheckBridgeAlive', $hash ); 'NUKIBridge_GetCheckBridgeAlive', $hash );
return undef; return undef;
} }
sub NUKIBridge_Write($@) { sub Write($@) {
my ( $hash, $endpoint, $param, $nukiId, $deviceType ) = @_; my ( $hash, $endpoint, $param, $nukiId, $deviceType ) = @_;
my $obj = { my $obj = {
@ -550,15 +573,17 @@ sub NUKIBridge_Write($@) {
}; };
$hash->{helper}->{lastDeviceAction} = $obj $hash->{helper}->{lastDeviceAction} = $obj
if ( defined($param) if ( ( defined($param)
and $param ); and $param)
or (defined($nukiId)
and $nukiId) );
unshift( @{ $hash->{helper}->{actionQueue} }, $obj ); unshift( @{ $hash->{helper}->{actionQueue} }, $obj );
NUKIBridge_Call($hash); BridgeCall($hash);
} }
sub NUKIBridge_CreateUri($$) { sub CreateUri($$) {
my ( $hash, $obj ) = @_; my ( $hash, $obj ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -571,11 +596,11 @@ sub NUKIBridge_CreateUri($$) {
my $deviceType = $obj->{deviceType}; my $deviceType = $obj->{deviceType};
my $uri = 'http://' . $host . ':' . $port; my $uri = 'http://' . $host . ':' . $port;
$uri .= '/' . $endpoint if ( defined $endpoint ); $uri .= '/' . $endpoint if ( defined $endpoint );
$uri .= '?token=' . $token if ( defined($token) ); $uri .= '?token=' . $token if ( defined($token) );
if ( defined($param) if ( defined($param)
and defined($deviceType) ) and defined($deviceType) )
{ {
$uri .= '&action=' . $lockActionsSmartLock{$param} $uri .= '&action=' . $lockActionsSmartLock{$param}
if ( $endpoint ne 'callback/add' if ( $endpoint ne 'callback/add'
@ -603,7 +628,7 @@ sub NUKIBridge_CreateUri($$) {
return $uri; return $uri;
} }
sub NUKIBridge_Call($) { sub BridgeCall($) {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -612,39 +637,44 @@ sub NUKIBridge_Call($) {
my $nukiId = $obj->{nukiId}; my $nukiId = $obj->{nukiId};
if ( $hash->{helper}->{iowrite} == 0 ) { if ( $hash->{helper}->{iowrite} == 0 ) {
my $uri = NUKIBridge_CreateUri( $hash, $obj ); my $uri = CreateUri( $hash, $obj );
if ( defined($uri) and $uri ) { if ( defined($uri) and $uri ) {
$hash->{helper}->{iowrite} = 1; $hash->{helper}->{iowrite} = 1;
my $param = { my $param = {
url => $uri, url => $uri,
timeout => 30, timeout => 30,
hash => $hash, hash => $hash,
nukiId => $nukiId, nukiId => $nukiId,
endpoint => $endpoint, endpoint => $endpoint,
header => 'Accept: application/json', header => 'Accept: application/json',
method => 'GET', method => 'GET',
callback => \&NUKIBridge_Distribution, callback => \&Distribution,
}; };
$param->{cl} = $hash->{CL} $param->{cl} = $hash->{CL}
if ( ($endpoint eq 'callback/list' if (
or $endpoint eq 'log') (
and ref( $hash->{CL} ) eq 'HASH' ); $endpoint eq 'callback/list'
or $endpoint eq 'log'
)
and ref( $hash->{CL} ) eq 'HASH'
);
HttpUtils_NonblockingGet($param); HttpUtils_NonblockingGet($param);
Log3( $name, 4, "NUKIBridge ($name) - Send HTTP POST with URL $uri" ); Log3( $name, 4,
"NUKIBridge ($name) - Send HTTP POST with URL $uri" );
} }
} }
else { else {
push( @{ $hash->{helper}->{actionQueue} },$obj ) push( @{ $hash->{helper}->{actionQueue} }, $obj )
if ( defined($endpoint) if ( defined($endpoint)
and $endpoint eq 'lockAction' ); and $endpoint eq 'lockAction' );
} }
} }
sub NUKIBridge_Distribution($$$) { sub Distribution($$$) {
my ( $param, $err, $json ) = @_; my ( $param, $err, $json ) = @_;
my $hash = $param->{hash}; my $hash = $param->{hash};
@ -672,10 +702,10 @@ sub NUKIBridge_Distribution($$$) {
if ( defined($err) ) { if ( defined($err) ) {
if ( $err ne '' ) { if ( $err ne '' ) {
if ( $param->{endpoint} eq 'info' ) { if ( $param->{endpoint} eq 'info' ) {
readingsBulkUpdate( $hash, 'state', 'not connected' ) readingsBulkUpdate( $hash, 'state', 'not connected' );
if ( $hash->{helper}{aliveCount} > 1 ); # if ( $hash->{helper}{aliveCount} > 1 );
Log3( $name, 5, "NUKIBridge ($name) - Bridge ist offline" ); Log3( $name, 5, "NUKIBridge ($name) - Bridge ist offline" );
$hash->{helper}{aliveCount} = $hash->{helper}{aliveCount} + 1; # $hash->{helper}{aliveCount} = $hash->{helper}{aliveCount} + 1;
} }
readingsBulkUpdate( $hash, 'lastError', $err ) readingsBulkUpdate( $hash, 'lastError', $err )
@ -710,7 +740,9 @@ sub NUKIBridge_Distribution($$$) {
@{ $hash->{helper}->{actionQueue} }, @{ $hash->{helper}->{actionQueue} },
$hash->{helper}->{lastDeviceAction} $hash->{helper}->{lastDeviceAction}
); );
delete $hash->{helper}->{lastDeviceAction};
InternalTimer( gettimeofday() + 1,
'NUKIBridge_BridgeCall', $hash );
} }
asyncOutput( $param->{cl}, "Request Error: $err\r\n" ) asyncOutput( $param->{cl}, "Request Error: $err\r\n" )
@ -732,7 +764,7 @@ sub NUKIBridge_Distribution($$$) {
. ' without any data after requesting' ); . ' without any data after requesting' );
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} );
} }
if ( ( $json =~ /Error/i ) and exists( $param->{code} ) ) { if ( ( $json =~ /Error/i ) and exists( $param->{code} ) ) {
@ -752,7 +784,7 @@ sub NUKIBridge_Distribution($$$) {
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
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 $param->{code}; return $param->{code};
} }
@ -763,17 +795,20 @@ sub NUKIBridge_Distribution($$$) {
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
readingsSingleUpdate( $hash, 'state', 'connected', 1 );
Log3( $name, 5, "NUKIBridge ($name) - Bridge ist online" );
if ( $param->{endpoint} eq 'callback/list' ) { if ( $param->{endpoint} eq 'callback/list' ) {
NUKIBridge_getCallbackList($param,$json); getCallbackList( $param, $json );
return undef; return undef;
} }
elsif ( $param->{endpoint} eq 'log' ) { elsif ( $param->{endpoint} eq 'log' ) {
NUKIBridge_getLogfile($param,$json); getLogfile( $param, $json );
return undef; return undef;
} }
if ( $hash == $dhash ) { if ( $hash == $dhash ) {
NUKIBridge_ResponseProcessing( $hash, $json, $param->{endpoint} ); ResponseProcessing( $hash, $json, $param->{endpoint} );
} }
else { else {
my $decode_json = eval { decode_json($json) }; my $decode_json = eval { decode_json($json) };
@ -788,14 +823,14 @@ sub NUKIBridge_Distribution($$$) {
Dispatch( $hash, $json, undef ); Dispatch( $hash, $json, undef );
} }
InternalTimer( gettimeofday() + 1, 'NUKIBridge_Call', $hash ) InternalTimer( gettimeofday() + 3, 'NUKIBridge_BridgeCall', $hash )
if ( defined( $hash->{helper}->{actionQueue} ) if ( defined( $hash->{helper}->{actionQueue} )
and scalar( @{ $hash->{helper}->{actionQueue} } ) > 0 ); and scalar( @{ $hash->{helper}->{actionQueue} } ) > 0 );
return undef; return undef;
} }
sub NUKIBridge_ResponseProcessing($$$) { sub ResponseProcessing($$$) {
my ( $hash, $json, $endpoint ) = @_; my ( $hash, $json, $endpoint ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -840,7 +875,7 @@ sub NUKIBridge_ResponseProcessing($$$) {
@buffer = split( '"scanResults": \[', $json ) @buffer = split( '"scanResults": \[', $json )
if ( $endpoint eq 'info' ); if ( $endpoint eq 'info' );
my ( $json, $tail ) = NUKIBridge_ParseJSON( $hash, $buffer[1] ); my ( $json, $tail ) = ParseJSON( $hash, $buffer[1] );
while ($json) { while ($json) {
Log3( $name, 5, Log3( $name, 5,
@ -860,7 +895,7 @@ sub NUKIBridge_ResponseProcessing($$$) {
Dispatch( $hash, $json, undef ) Dispatch( $hash, $json, undef )
unless ( not defined($tail) and not($tail) ); unless ( not defined($tail) and not($tail) );
( $json, $tail ) = NUKIBridge_ParseJSON( $hash, $tail ); ( $json, $tail ) = ParseJSON( $hash, $tail );
Log3( $name, 5, Log3( $name, 5,
"NUKIBridge ($name) - Nach Sub: Laenge JSON: " "NUKIBridge ($name) - Nach Sub: Laenge JSON: "
@ -872,12 +907,9 @@ sub NUKIBridge_ResponseProcessing($$$) {
} }
} }
NUKIBridge_InfoProcessing( $hash, $decode_json ) InfoProcessing( $hash, $decode_json )
if ( $endpoint eq 'info' ); if ( $endpoint eq 'info' );
readingsSingleUpdate( $hash, 'state', 'connected', 1 );
Log3( $name, 5, "NUKIBridge ($name) - Bridge ist online" );
$hash->{helper}{aliveCount} = 0; $hash->{helper}{aliveCount} = 0;
} }
else { else {
@ -891,7 +923,7 @@ $json"
return undef; return undef;
} }
sub NUKIBridge_CGI() { sub CGI() {
my ($request) = @_; my ($request) = @_;
my $hash; my $hash;
@ -946,7 +978,7 @@ matching NukiId at device $name"
return ( 'text/plain; charset=utf-8', 'Call failure: ' . $request ); return ( 'text/plain; charset=utf-8', 'Call failure: ' . $request );
} }
sub NUKIBridge_InfoProcessing($$) { sub InfoProcessing($$) {
my ( $hash, $decode_json ) = @_; my ( $hash, $decode_json ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -975,8 +1007,8 @@ sub NUKIBridge_InfoProcessing($$) {
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
} }
sub NUKIBridge_getLogfile($$) { sub getLogfile($$) {
my ($param,$json) = @_; my ( $param, $json ) = @_;
my $hash = $param->{hash}; my $hash = $param->{hash};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -992,7 +1024,8 @@ sub NUKIBridge_getLogfile($$) {
if ( $param->{cl} and $param->{cl}->{TYPE} eq 'FHEMWEB' ) { if ( $param->{cl} and $param->{cl}->{TYPE} eq 'FHEMWEB' ) {
if ( ref($decode_json) eq 'ARRAY' and scalar( @{$decode_json} ) > 0 ) { if ( ref($decode_json) eq 'ARRAY' and scalar( @{$decode_json} ) > 0 ) {
Log3( $name, 4, "NUKIBridge ($name) - created Table with log file" ); Log3( $name, 4,
"NUKIBridge ($name) - created Table with log file" );
my $ret = '<html><table width=100%><tr><td>'; my $ret = '<html><table width=100%><tr><td>';
$ret .= '<table class="block wide">'; $ret .= '<table class="block wide">';
@ -1034,8 +1067,8 @@ sub NUKIBridge_getLogfile($$) {
} }
} }
sub NUKIBridge_getCallbackList($$) { sub getCallbackList($$) {
my ($param,$json) = @_; my ( $param, $json ) = @_;
my $hash = $param->{hash}; my $hash = $param->{hash};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1053,7 +1086,8 @@ sub NUKIBridge_getCallbackList($$) {
if ( ref( $decode_json->{callbacks} ) eq 'ARRAY' if ( ref( $decode_json->{callbacks} ) eq 'ARRAY'
and scalar( @{ $decode_json->{callbacks} } ) > 0 ) and scalar( @{ $decode_json->{callbacks} } ) > 0 )
{ {
Log3( $name, 4, "NUKIBridge ($name) - created Table with log file" ); Log3( $name, 4,
"NUKIBridge ($name) - created Table with log file" );
my $ret = '<html><table width=100%><tr><td>'; my $ret = '<html><table width=100%><tr><td>';
@ -1083,7 +1117,7 @@ sub NUKIBridge_getCallbackList($$) {
} }
} }
sub NUKIBridge_ParseJSON($$) { sub ParseJSON($$) {
my ( $hash, $buffer ) = @_; my ( $hash, $buffer ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1302,7 +1336,7 @@ sub NUKIBridge_ParseJSON($$) {
], ],
"release_status": "under develop", "release_status": "under develop",
"license": "GPL_2", "license": "GPL_2",
"version": "v1.9.4", "version": "v1.9.13",
"x_apiversion": "1.9", "x_apiversion": "1.9",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"

View File

@ -27,9 +27,16 @@
package main; package main;
use strict;
use warnings;
package FHEM::NUKIDevice;
use strict; use strict;
use warnings; use warnings;
use FHEM::Meta; use FHEM::Meta;
use GPUtils qw(GP_Import GP_Export);
main::LoadModule('NUKIBridge'); main::LoadModule('NUKIBridge');
@ -104,16 +111,41 @@ if ($@) {
} }
} }
## Import der FHEM Funktionen
#-- Run before package compilation
BEGIN {
# Declare functions # Import from main context
sub NUKIDevice_Initialize($); GP_Import(
sub NUKIDevice_Define($$); qw(
sub NUKIDevice_Undef($$); readingsSingleUpdate
sub NUKIDevice_Attr(@); readingsBulkUpdate
sub NUKIDevice_Set($$@); readingsBeginUpdate
sub NUKIDevice_GetUpdate($); readingsEndUpdate
sub NUKIDevice_Parse($$); readingFnAttributes
sub NUKIDevice_WriteReadings($$); makeDeviceName
defs
modules
Log3
CommandAttr
AttrVal
IsDisabled
deviceEvents
init_done
InternalVal
ReadingsVal
AssignIoPort
IOWrite
data)
);
}
#-- Export to main context with different name
GP_Export(
qw(
Initialize
)
);
my %deviceTypes = ( my %deviceTypes = (
0 => 'smartlock', 0 => 'smartlock',
@ -180,18 +212,19 @@ my %lockStates = (
my %deviceTypeIds = reverse(%deviceTypes); my %deviceTypeIds = reverse(%deviceTypes);
sub NUKIDevice_Initialize($) { sub Initialize($) {
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = '^{.*}$'; $hash->{Match} = '^{.*}$';
$hash->{SetFn} = 'NUKIDevice_Set'; $hash->{SetFn} = 'FHEM::NUKIDevice::Set';
$hash->{DefFn} = 'NUKIDevice_Define'; $hash->{DefFn} = 'FHEM::NUKIDevice::Define';
$hash->{UndefFn} = 'NUKIDevice_Undef'; $hash->{UndefFn} = 'FHEM::NUKIDevice::Undef';
$hash->{AttrFn} = 'NUKIDevice_Attr'; $hash->{NotifyFn} = 'FHEM::NUKIDevice::Notify';
$hash->{ParseFn} = 'NUKIDevice_Parse'; $hash->{AttrFn} = 'FHEM::NUKIDevice::Attr';
$hash->{ParseFn} = 'FHEM::NUKIDevice::Parse';
$hash->{AttrList} = $hash->{AttrList} =
'IODev ' 'IODev '
. 'model:opener,smartlock ' . 'model:opener,smartlock '
. 'disable:1 ' . 'disable:1 '
@ -200,7 +233,7 @@ sub NUKIDevice_Initialize($) {
return FHEM::Meta::InitMod( __FILE__, $hash ); return FHEM::Meta::InitMod( __FILE__, $hash );
} }
sub NUKIDevice_Define($$) { sub Define($$) {
my ( $hash, $def ) = @_; my ( $hash, $def ) = @_;
my @a = split( '[ \t][ \t]*', $def ); my @a = split( '[ \t][ \t]*', $def );
@ -218,6 +251,7 @@ sub NUKIDevice_Define($$) {
$hash->{DEVICETYPE} = ( defined $deviceType ) ? $deviceType : 0; $hash->{DEVICETYPE} = ( defined $deviceType ) ? $deviceType : 0;
$hash->{VERSION} = version->parse($VERSION)->normal; $hash->{VERSION} = version->parse($VERSION)->normal;
$hash->{STATE} = 'Initialized'; $hash->{STATE} = 'Initialized';
$hash->{NOTIFYDEV} = 'global,autocreate,' . $name;
my $iodev = AttrVal( $name, 'IODev', 'none' ); my $iodev = AttrVal( $name, 'IODev', 'none' );
@ -254,35 +288,28 @@ sub NUKIDevice_Define($$) {
CommandAttr( undef, $name . ' model ' . $deviceTypes{$deviceType} ) CommandAttr( undef, $name . ' model ' . $deviceTypes{$deviceType} )
if ( AttrVal( $name, 'model', 'none' ) eq 'none' ); if ( AttrVal( $name, 'model', 'none' ) eq 'none' );
if ($init_done) {
InternalTimer( gettimeofday() + int( rand(10) ),
"NUKIDevice_GetUpdate", $hash );
}
else {
InternalTimer( gettimeofday() + 15 + int( rand(5) ),
"NUKIDevice_GetUpdate", $hash );
}
$modules{NUKIDevice}{defptr}{$nukiId} = $hash; $modules{NUKIDevice}{defptr}{$nukiId} = $hash;
GetUpdate($hash)
if ( ReadingsVal($name,'success','none') eq 'none'
and $init_done );
return undef; return undef;
} }
sub NUKIDevice_Undef($$) { sub Undef($$) {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
my $nukiId = $hash->{NUKIID}; my $nukiId = $hash->{NUKIID};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash);
Log3( $name, 3, "NUKIDevice ($name) - undefined with NukiId: $nukiId" ); Log3( $name, 3, "NUKIDevice ($name) - undefined with NukiId: $nukiId" );
delete( $modules{NUKIDevice}{defptr}{$nukiId} ); delete( $modules{NUKIDevice}{defptr}{$nukiId} );
return undef; return undef;
} }
sub NUKIDevice_Attr(@) { sub Attr(@) {
my ( $cmd, $name, $attrName, $attrVal ) = @_; my ( $cmd, $name, $attrName, $attrVal ) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -322,7 +349,33 @@ sub NUKIDevice_Attr(@) {
return undef; return undef;
} }
sub NUKIDevice_Set($$@) { sub Notify($$) {
my ( $hash, $dev ) = @_;
my $name = $hash->{NAME};
return if ( IsDisabled($name) );
my $devname = $dev->{NAME};
my $devtype = $dev->{TYPE};
my $events = deviceEvents( $dev, 1 );
return if ( !$events );
GetUpdate($hash)
if (
(
grep /^INITIALIZED$/, @{$events}
or grep /^REREADCFG$/, @{$events}
or grep /^MODIFIED.$name$/, @{$events}
or grep /^DEFINED.$name$/, @{$events}
)
and $devname eq 'global'
and $init_done
);
return;
}
sub Set($$@) {
my ( $hash, $name, @aa ) = @_; my ( $hash, $name, @aa ) = @_;
my ( $cmd, @args ) = @aa; my ( $cmd, @args ) = @aa;
@ -331,7 +384,7 @@ sub NUKIDevice_Set($$@) {
if ( lc($cmd) eq 'statusrequest' ) { if ( lc($cmd) eq 'statusrequest' ) {
return ('usage: statusRequest') if ( @args != 0 ); return ('usage: statusRequest') if ( @args != 0 );
NUKIDevice_GetUpdate($hash); GetUpdate($hash);
return undef; return undef;
} }
elsif ($cmd eq 'lock' elsif ($cmd eq 'lock'
@ -371,22 +424,20 @@ sub NUKIDevice_Set($$@) {
return undef; return undef;
} }
sub NUKIDevice_GetUpdate($) { sub GetUpdate($) {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
RemoveInternalTimer($hash); if ( !IsDisabled($name) ) {
IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, $hash->{DEVICETYPE} );
IOWrite( $hash, 'lockState', undef, $hash->{NUKIID}, $hash->{DEVICETYPE} ) Log3( $name, 2, "NUKIDevice ($name) - GetUpdate Call IOWrite" );
if ( !IsDisabled($name) ); }
Log3( $name, 5, "NUKIDevice ($name) - NUKIDevice_GetUpdate Call IOWrite" )
if ( !IsDisabled($name) );
return undef; return undef;
} }
sub NUKIDevice_Parse($$) { sub Parse($$) {
my ( $hash, $json ) = @_; my ( $hash, $json ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -420,7 +471,7 @@ sub NUKIDevice_Parse($$) {
if ( my $hash = $modules{NUKIDevice}{defptr}{$nukiId} ) { if ( my $hash = $modules{NUKIDevice}{defptr}{$nukiId} ) {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
NUKIDevice_WriteReadings( $hash, $decode_json ); WriteReadings( $hash, $decode_json );
Log3( $name, 4, Log3( $name, 4,
"NUKIDevice ($name) - find logical device: $hash->{NAME}" ); "NUKIDevice ($name) - find logical device: $hash->{NAME}" );
@ -455,10 +506,10 @@ sub NUKIDevice_Parse($$) {
Log3( $name, 5, "NUKIDevice ($name) - parse status message for $name" ); Log3( $name, 5, "NUKIDevice ($name) - parse status message for $name" );
NUKIDevice_WriteReadings( $hash, $decode_json ); WriteReadings( $hash, $decode_json );
} }
sub NUKIDevice_WriteReadings($$) { sub WriteReadings($$) {
my ( $hash, $decode_json ) = @_; my ( $hash, $decode_json ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -689,7 +740,7 @@ sub NUKIDevice_WriteReadings($$) {
], ],
"release_status": "under develop", "release_status": "under develop",
"license": "GPL_2", "license": "GPL_2",
"version": "v1.9.1", "version": "v1.9.10",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"
], ],