dev #25

Merged
marko merged 10 commits from dev into main 2021-12-17 11:18:11 +00:00
5 changed files with 128 additions and 99 deletions
Showing only changes of commit 6b75e5c9dc - Show all commits

View File

@ -1,6 +1,6 @@
############################################################################### ###############################################################################
# #
# Developed with Kate # Developed with VSCodium
# #
# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
# All rights reserved # All rights reserved
@ -43,6 +43,14 @@ use warnings;
use FHEM::Meta; use FHEM::Meta;
require FHEM::Devices::Nuki::Bridge; require FHEM::Devices::Nuki::Bridge;
use GPUtils qw(GP_Import);
BEGIN {
# Import from main context
GP_Import(qw( readingFnAttributes ));
}
sub ::NUKIBridge_Initialize { goto &Initialize } sub ::NUKIBridge_Initialize { goto &Initialize }
sub Initialize { sub Initialize {
@ -68,7 +76,7 @@ sub Initialize {
. 'webhookFWinstance:' . 'webhookFWinstance:'
. $webhookFWinstance . ' ' . $webhookFWinstance . ' '
. 'webhookHttpHostname ' . 'webhookHttpHostname '
. $::readingFnAttributes; . $readingFnAttributes;
return FHEM::Meta::InitMod( __FILE__, $hash ); return FHEM::Meta::InitMod( __FILE__, $hash );
} }

View File

@ -1,6 +1,6 @@
############################################################################### ###############################################################################
# #
# Developed with Kate # Developed with VSCodium
# #
# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
# All rights reserved # All rights reserved
@ -32,11 +32,19 @@ use warnings;
use FHEM::Meta; use FHEM::Meta;
require FHEM::Devices::Nuki::Device; require FHEM::Devices::Nuki::Device;
use GPUtils qw(GP_Import);
BEGIN {
# Import from main context
GP_Import(qw( readingFnAttributes ));
}
main::LoadModule('NUKIBridge'); main::LoadModule('NUKIBridge');
sub ::NUKIDevice_Initialize { goto &Initialize } sub ::NUKIDevice_Initialize { goto &Initialize }
sub Initialize($) { sub Initialize {
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = '^{.*}$'; $hash->{Match} = '^{.*}$';
@ -52,7 +60,7 @@ sub Initialize($) {
'IODev ' 'IODev '
. 'model:smartlock,opener,smartdoor,smartlock3 ' . 'model:smartlock,opener,smartdoor,smartlock3 '
. 'disable:1 ' . 'disable:1 '
. $::readingFnAttributes; . $readingFnAttributes;
return FHEM::Meta::InitMod( __FILE__, $hash ); return FHEM::Meta::InitMod( __FILE__, $hash );
} }

View File

@ -1,4 +1,4 @@
UPD 2021-12-05_12:27:18 9217 FHEM/73_NUKIBridge.pm UPD 2021-12-10_20:21:10 9332 FHEM/73_NUKIBridge.pm
UPD 2021-12-05_12:27:18 7569 FHEM/74_NUKIDevice.pm UPD 2021-12-10_20:22:28 7681 FHEM/74_NUKIDevice.pm
UPD 2021-12-10_13:24:18 42533 lib/FHEM/Devices/Nuki/Bridge.pm UPD 2021-12-10_19:44:48 42801 lib/FHEM/Devices/Nuki/Bridge.pm
UPD 2021-12-10_13:25:37 15802 lib/FHEM/Devices/Nuki/Device.pm UPD 2021-12-10_20:17:22 16247 lib/FHEM/Devices/Nuki/Device.pm

View File

@ -1,6 +1,6 @@
############################################################################### ###############################################################################
# #
# Developed with Kate # Developed with VSCodium
# #
# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
# All rights reserved # All rights reserved
@ -719,6 +719,8 @@ sub DistributionErrHandle2 {
my $json = shift; my $json = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
# 2021.12.10 13:55:43 1: PERL WARNING: Use of uninitialized value $json in string eq at lib/FHEM/Devices/Nuki/Bridge.pm line 722.
# Can't use string ("{"success": false}") as a HASH ref while "strict refs" in use at lib/FHEM/Devices/Nuki/Bridge.pm line 722.
if ( ( $json eq '' || $json =~ /Unavailable/i ) if ( ( $json eq '' || $json =~ /Unavailable/i )
&& exists( $param->{code} ) && exists( $param->{code} )
&& $param->{code} != 200 ) && $param->{code} != 200 )
@ -835,7 +837,7 @@ sub Distribution {
return $errHandle1 return $errHandle1
if ($errHandle1); if ($errHandle1);
$errHandle2 = DistributionErrHandle2( $hash, $param, $json ); $errHandle2 = DistributionErrHandle2( $hash, $err, $param, $json );
return $errHandle2 return $errHandle2
if ($errHandle2); if ($errHandle2);

View File

@ -1,6 +1,6 @@
############################################################################### ###############################################################################
# #
# Developed with Kate # Developed with VSCodium
# #
# (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net) # (c) 2016-2021 Copyright: Marko Oldenburg (fhemdevelopment at cooltux dot net)
# All rights reserved # All rights reserved
@ -28,24 +28,34 @@ package FHEM::Devices::Nuki::Device;
use strict; use strict;
use warnings; use warnings;
use experimental qw( switch );
use FHEM::Meta; use FHEM::Meta;
use GPUtils qw(GP_Import);
BEGIN {
# Import from main context
GP_Import(
qw( init_done
defs
modules
)
);
}
# 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
eval { eval {
require JSON::MaybeXS; require JSON::MaybeXS;
import JSON::MaybeXS qw( decode_json encode_json ); import JSON::MaybeXS qw( decode_json encode_json );
1; 1;
}; } or do {
if ($@) {
$@ = undef;
# try to use JSON wrapper # try to use JSON wrapper
# for chance of better performance # for chance of better performance
eval { eval {
# JSON preference order # JSON preference order
local $ENV{PERL_JSON_BACKEND} = local $ENV{PERL_JSON_BACKEND} =
'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP' 'Cpanel::JSON::XS,JSON::XS,JSON::PP,JSON::backportPP'
@ -54,10 +64,7 @@ if ($@) {
require JSON; require JSON;
import JSON qw( decode_json encode_json ); import JSON qw( decode_json encode_json );
1; 1;
}; } or do {
if ($@) {
$@ = undef;
# In rare cases, Cpanel::JSON::XS may # In rare cases, Cpanel::JSON::XS may
# be installed but JSON|JSON::MaybeXS not ... # be installed but JSON|JSON::MaybeXS not ...
@ -65,10 +72,7 @@ if ($@) {
require Cpanel::JSON::XS; require Cpanel::JSON::XS;
import Cpanel::JSON::XS qw(decode_json encode_json); import Cpanel::JSON::XS qw(decode_json encode_json);
1; 1;
}; } or do {
if ($@) {
$@ = undef;
# In rare cases, JSON::XS may # In rare cases, JSON::XS may
# be installed but JSON not ... # be installed but JSON not ...
@ -76,10 +80,7 @@ if ($@) {
require JSON::XS; require JSON::XS;
import JSON::XS qw(decode_json encode_json); import JSON::XS qw(decode_json encode_json);
1; 1;
}; } or do {
if ($@) {
$@ = undef;
# Fallback to built-in JSON which SHOULD # Fallback to built-in JSON which SHOULD
# be available since 5.014 ... # be available since 5.014 ...
@ -87,20 +88,17 @@ if ($@) {
require JSON::PP; require JSON::PP;
import JSON::PP qw(decode_json encode_json); import JSON::PP qw(decode_json encode_json);
1; 1;
}; } or do {
if ($@) {
$@ = undef;
# Fallback to JSON::backportPP in really rare cases # Fallback to JSON::backportPP in really rare cases
require JSON::backportPP; require JSON::backportPP;
import JSON::backportPP qw(decode_json encode_json); import JSON::backportPP qw(decode_json encode_json);
1; 1;
} };
} };
} };
} };
} };
######## Begin Device ######## Begin Device
@ -195,7 +193,9 @@ sub Define {
my $def = shift // return; my $def = shift // return;
return $@ unless ( FHEM::Meta::SetInternals($hash) ); return $@ unless ( FHEM::Meta::SetInternals($hash) );
use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
$version = FHEM::Meta::Get( $hash, 'version' );
our $VERSION = $version;
my ( $name, undef, $nukiId, $deviceType ) = split( m{\s+}xms, $def ); my ( $name, undef, $nukiId, $deviceType ) = split( m{\s+}xms, $def );
return 'too few parameters: define <name> NUKIDevice <nukiId> <deviceType>' return 'too few parameters: define <name> NUKIDevice <nukiId> <deviceType>'
@ -227,11 +227,11 @@ sub Define {
$iodev = $hash->{IODev}->{NAME}; $iodev = $hash->{IODev}->{NAME};
$hash->{BRIDGEAPI} = $::defs{$iodev}->{BRIDGEAPI} $hash->{BRIDGEAPI} = $defs{$iodev}->{BRIDGEAPI}
if ( defined($iodev) if ( defined($iodev)
&& $iodev ); && $iodev );
my $d = $::modules{NUKIDevice}{defptr}{$nukiId}; my $d = $modules{NUKIDevice}{defptr}{$nukiId};
return return
'NUKIDevice device ' 'NUKIDevice device '
@ -250,11 +250,11 @@ sub 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' );
$::modules{NUKIDevice}{defptr}{$nukiId} = $hash; $modules{NUKIDevice}{defptr}{$nukiId} = $hash;
GetUpdate($hash) GetUpdate($hash)
if ( ::ReadingsVal( $name, 'success', 'none' ) eq 'none' if ( ::ReadingsVal( $name, 'success', 'none' ) eq 'none'
&& $::init_done ); && $init_done );
return; return;
} }
@ -266,7 +266,7 @@ sub Undef {
my $name = $hash->{NAME}; my $name = $hash->{NAME};
::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; return;
} }
@ -277,7 +277,7 @@ sub Attr {
my $attrName = shift; my $attrName = shift;
my $attrVal = shift; my $attrVal = shift;
my $hash = $::defs{$name}; my $hash = $defs{$name};
my $token = $hash->{IODev}->{TOKEN}; my $token = $hash->{IODev}->{TOKEN};
if ( $attrName eq 'disable' ) { if ( $attrName eq 'disable' ) {
@ -330,17 +330,13 @@ sub Notify {
GetUpdate($hash) GetUpdate($hash)
if ( if (
( (
grep /^INITIALIZED$/, grep { /^INITIALIZED$/x } @{$events}
@{$events} or grep { /^REREADCFG$/x } @{$events}
or grep /^REREADCFG$/, or grep { /^MODIFIED.$name$/x } @{$events}
@{$events} or grep { /^DEFINED.$name$/x } @{$events}
or grep /^MODIFIED.$name$/,
@{$events}
or grep /^DEFINED.$name$/,
@{$events}
) )
&& $devname eq 'global' && $devname eq 'global'
&& $::init_done && $init_done
); );
return; return;
@ -427,7 +423,7 @@ sub Parse {
######################################### #########################################
####### Errorhandling ############# ####### Errorhandling #############
if ( $json !~ m/^[\[{].*[}\]]$/ ) { if ( $json !~ m{\A[\[{].*[}\]]\z}xms ) {
::Log3( $name, 3, "NUKIDevice ($name) - invalid json detected: $json" ); ::Log3( $name, 3, "NUKIDevice ($name) - invalid json detected: $json" );
return "NUKIDevice ($name) - invalid json detected: $json"; return "NUKIDevice ($name) - invalid json detected: $json";
} }
@ -449,18 +445,18 @@ sub Parse {
} }
my $nukiId = $decode_json->{nukiId}; my $nukiId = $decode_json->{nukiId};
if ( my $hash = $::modules{NUKIDevice}{defptr}{$nukiId} ) { if ( my $dhash = $modules{NUKIDevice}{defptr}{$nukiId} ) {
my $name = $hash->{NAME}; my $dname = $dhash->{NAME};
WriteReadings( $hash, $decode_json ); WriteReadings( $dhash, $decode_json );
::Log3( $name, 4, ::Log3( $dname, 4,
"NUKIDevice ($name) - find logical device: $hash->{NAME}" ); "NUKIDevice ($dname) - find logical device: $dhash->{NAME}" );
return $hash->{NAME}; return $dhash->{NAME};
} }
else { else {
::Log3( $name, 4, ::Log3( $dname, 4,
"NUKIDevice ($name) - autocreate new device " "NUKIDevice ($dname) - autocreate new device "
. ::makeDeviceName( $decode_json->{name} ) . ::makeDeviceName( $decode_json->{name} )
. " with nukiId $decode_json->{nukiId}, model $decode_json->{deviceType}" . " with nukiId $decode_json->{nukiId}, model $decode_json->{deviceType}"
); );
@ -472,16 +468,14 @@ sub Parse {
::Log3( $name, 5, "NUKIDevice ($name) - parse status message for $name" ); ::Log3( $name, 5, "NUKIDevice ($name) - parse status message for $name" );
WriteReadings( $hash, $decode_json ); return WriteReadings( $hash, $decode_json );
} }
sub WriteReadings { sub SmartlockState {
my $hash = shift;
my $decode_json = shift;
my $name = $hash->{NAME};
############################ ############################
#### Status des Smartlock #### Status des Smartlock
my $hash = shift;
my $decode_json = shift;
if ( defined( $hash->{helper}{lockAction} ) ) { if ( defined( $hash->{helper}{lockAction} ) ) {
my $state; my $state;
@ -527,6 +521,16 @@ sub WriteReadings {
delete $hash->{helper}{lockAction}; delete $hash->{helper}{lockAction};
} }
return;
}
sub WriteReadings {
my $hash = shift;
my $decode_json = shift;
my $name = $hash->{NAME};
SmartlockState();
::readingsBeginUpdate($hash); ::readingsBeginUpdate($hash);
my $t; my $t;
@ -555,36 +559,43 @@ sub WriteReadings {
&& $t ne 'doorsensorState' && $t ne 'doorsensorState'
&& $t ne 'doorsensorStateName' ); && $t ne 'doorsensorStateName' );
::readingsBulkUpdate( given ($t) {
$hash, $t, when ('state') {
( ::readingsBulkUpdate(
$v =~ m/^[0-9]$/ $hash, $t,
? $lockStates{$v}{ $hash->{DEVICETYPEID} } (
: $v $v =~ m{\A[0-9]\z}xms
) ? $lockStates{$v}->{ $hash->{DEVICETYPEID} }
) if ( $t eq 'state' ); : $v
)
::readingsBulkUpdate( $hash, $t, $modes{$v}{ $hash->{DEVICETYPEID} } ) );
if ( $t eq 'mode' ); }
when ('mode') {
::readingsBulkUpdate( $hash, $t, $deviceTypes{$v} ) ::readingsBulkUpdate( $hash, $t,
if ( $t eq 'deviceType' ); $modes{$v}{ $hash->{DEVICETYPEID} } );
}
::readingsBulkUpdate( $hash, $t, $doorsensorStates{$v} ) when ('deviceType') {
if ( $t eq 'doorsensorState' ); ::readingsBulkUpdate( $hash, $t, $deviceTypes{$v} );
}
::readingsBulkUpdate( $hash, $t, ( $v == 1 ? 'true' : 'false' ) ) when ('doorsensorState') {
if ( $t eq 'paired' ); ::readingsBulkUpdate( $hash, $t, $doorsensorStates{$v} );
}
::readingsBulkUpdate( $hash, $t, ( $v == 1 ? 'true' : 'false' ) ) when ('paired') {
if ( $t eq 'batteryCharging' ); ::readingsBulkUpdate( $hash, $t,
( $v == 1 ? 'true' : 'false' ) );
::readingsBulkUpdate( $hash, 'batteryState', }
( $v == 1 ? 'low' : 'ok' ) ) when ('batteryCharging') {
if ( $t eq 'batteryCritical' ); ::readingsBulkUpdate( $hash, $t,
( $v == 1 ? 'true' : 'false' ) );
::readingsBulkUpdate( $hash, 'batteryPercent', $v ) }
if ( $t eq 'batteryChargeState' ); when ('batteryCritical') {
::readingsBulkUpdate( $hash, 'batteryState',
( $v == 1 ? 'low' : 'ok' ) );
}
when ('batteryChargeState') {
::readingsBulkUpdate( $hash, 'batteryPercent', $v )
}
}
} }
::readingsEndUpdate( $hash, 1 ); ::readingsEndUpdate( $hash, 1 );