From b6de5baa1662a75876918281edef71cf3ce1d2db Mon Sep 17 00:00:00 2001 From: ntruchsess <> Date: Tue, 29 Oct 2013 23:34:43 +0000 Subject: [PATCH] rework assoziation of IODev to FRM clients git-svn-id: https://svn.fhem.de/fhem/trunk@4132 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_OWX.pm | 7 ++---- fhem/FHEM/10_FRM.pm | 46 +++++++++++++++++++++++---------------- fhem/FHEM/20_FRM_AD.pm | 30 ++++++++++++++++++++++++- fhem/FHEM/20_FRM_I2C.pm | 34 +++++++++++++++++++++++------ fhem/FHEM/20_FRM_IN.pm | 20 ++++++++++++++++- fhem/FHEM/20_FRM_LCD.pm | 36 +++++++++++++++++++++++------- fhem/FHEM/20_FRM_OUT.pm | 31 +++++++++++++++++++++++++- fhem/FHEM/20_FRM_PWM.pm | 31 +++++++++++++++++++++++++- fhem/FHEM/20_FRM_SERVO.pm | 39 +++++++++++++++++++++++++-------- 9 files changed, 222 insertions(+), 52 deletions(-) diff --git a/fhem/FHEM/00_OWX.pm b/fhem/FHEM/00_OWX.pm index c34facc11..114bd3085 100644 --- a/fhem/FHEM/00_OWX.pm +++ b/fhem/FHEM/00_OWX.pm @@ -194,11 +194,8 @@ sub OWX_Define ($$) { #-- check if we are connecting to Arduino (via FRM): } elsif ($dev =~ /^\d{1,2}$/) { $hash->{INTERFACE} = "firmata"; - if (defined $main::modules{FRM}) { - FRM_Client_Define($hash,$def); - } else { - Log 1,"module FRM not yet loaded, please define an FRM device first."; - } + main::LoadModule("FRM"); + FRM_Client_Define($hash,$def); } else { $hash->{DeviceName} = $dev; #-- Second step in case of CUNO: See if we can open it diff --git a/fhem/FHEM/10_FRM.pm b/fhem/FHEM/10_FRM.pm index 16ed20cb3..75e57383a 100755 --- a/fhem/FHEM/10_FRM.pm +++ b/fhem/FHEM/10_FRM.pm @@ -387,7 +387,7 @@ FRM_forall_clients($$$) } sub -FRM_Init_Client($$) { +FRM_Init_Client($@) { my ($hash,$args) = @_; if (!defined $args and defined $hash->{DEF}) { my @a = split("[ \t][ \t]*", $hash->{DEF}); @@ -406,25 +406,15 @@ FRM_Init_Pin_Client($$$) { return $u unless defined $args and int(@$args) > 0; my $pin = @$args[0]; - foreach my $d ( sort keys %main::defs ) { - if ( defined( my $dev = $main::defs{$d} )) { - if ( $dev != $hash - && defined( $dev->{IODev} ) - && defined( $dev->{PIN} ) - && $dev->{IODev} == $hash->{IODev} - && $dev->{PIN} == $pin ) { - die "Device $main::defs{$d}{NAME} allready defined for pin $pin"; - } - } - } $hash->{PIN} = $pin; eval { + FRM_Client_AssignIOPort($hash); FRM_Client_FirmataDevice($hash)->pin_mode($pin,$mode); }; if ($@) { - main::Log(2,"FRM_Init error setting pin_mode: ".$@); - #FRM_Client_Unassign($hash); - return "error setting ".$hash->{NAME}." pin_mode for pin ".$pin; + $@ =~ /^(.*)( at.*FHEM.*)$/; + $hash->{STATE} = "error initializing: ".$1; + return "error initializing '".$hash->{NAME}."': ".$1; } return undef; } @@ -437,10 +427,6 @@ FRM_Client_Define($$) $hash->{STATE}="defined"; - AssignIoPort($hash); - if ( defined($hash->{IODev}) && defined($hash->{IODev}->{SNAME})) { - $hash->{IODev} = $main::defs{$hash->{IODev}->{SNAME}}; - } eval { FRM_Init_Client($hash,[@a[2..scalar(@a)-1]]); }; @@ -474,6 +460,28 @@ FRM_Client_Unassign($) $dev->{STATE}="defined"; } +sub +FRM_Client_AssignIOPort($) +{ + my $hash = shift; + AssignIoPort($main::defs{$hash->{NAME}}); + die "unable to assign IODev to '$hash->{NAME}'" unless defined ($hash->{IODev}); + + $hash->{IODev} = $main::defs{$hash->{IODev}->{SNAME}} if (defined($hash->{IODev}->{SNAME})); + + foreach my $d ( sort keys %main::defs ) { + if ( defined( my $dev = $main::defs{$d} )) { + if ( $dev != $hash + && defined( $dev->{IODev} ) + && defined( $dev->{PIN} ) + && $dev->{IODev} == $hash->{IODev} + && $dev->{PIN} == $hash->{PIN} ) { + die "Device $main::defs{$d}{NAME} allready defined for pin $hash->{PIN}"; + } + } + } +} + sub FRM_Client_FirmataDevice($) { my $hash = shift; my $iodev = $hash->{IODev}; diff --git a/fhem/FHEM/20_FRM_AD.pm b/fhem/FHEM/20_FRM_AD.pm index 8b0d42280..83a6751e7 100755 --- a/fhem/FHEM/20_FRM_AD.pm +++ b/fhem/FHEM/20_FRM_AD.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -20,11 +29,13 @@ FRM_AD_Initialize($) { my ($hash) = @_; + $hash->{AttrFn} = "FRM_AD_Attr"; $hash->{GetFn} = "FRM_AD_Get"; $hash->{DefFn} = "FRM_Client_Define"; $hash->{InitFn} = "FRM_AD_Init"; $hash->{AttrList} = "IODev upper-threshold lower-threshold loglevel:0,1,2,3,4,5,6 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -99,6 +110,23 @@ FRM_AD_Get($) return undef; } +sub +FRM_AD_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + } + } +} + 1; =pod diff --git a/fhem/FHEM/20_FRM_I2C.pm b/fhem/FHEM/20_FRM_I2C.pm index 927d2cd56..ff3f833f2 100755 --- a/fhem/FHEM/20_FRM_I2C.pm +++ b/fhem/FHEM/20_FRM_I2C.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -18,6 +27,7 @@ FRM_I2C_Initialize($) $hash->{AttrFn} = "FRM_I2C_Attr"; $hash->{AttrList} = "IODev loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -42,12 +52,22 @@ FRM_I2C_Init($) return undef; } -sub FRM_I2C_Attr(@) { - my ($command,$name,$attribute,$value) = @_; - my $hash = $main::defs{$name}; - if ($command eq "set") { - $main::attr{$name}{$attribute}=$value; - } +sub +FRM_I2C_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + $main::attr{$name}{$attribute}=$value; + } + } } 1; diff --git a/fhem/FHEM/20_FRM_IN.pm b/fhem/FHEM/20_FRM_IN.pm index 30e73e691..4df05dc68 100755 --- a/fhem/FHEM/20_FRM_IN.pm +++ b/fhem/FHEM/20_FRM_IN.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -33,6 +42,7 @@ FRM_IN_Initialize($) $hash->{UndefFn} = "FRM_Client_Undef"; $hash->{AttrList} = "IODev count-mode:none,rising,falling,both count-threshold reset-on-threshold-reached:yes,no internal-pullup:on,off loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -138,6 +148,14 @@ FRM_IN_Attr($$$$) { my ($command,$name,$attribute,$value) = @_; if ($command eq "set") { ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; $attribute eq "count-mode" and do { if ($value ne "none" and !defined main::ReadingsVal($name,"count",undef)) { main::readingsSingleUpdate($main::defs{$name},"count",$sets{count},1); diff --git a/fhem/FHEM/20_FRM_LCD.pm b/fhem/FHEM/20_FRM_LCD.pm index 77e569d8e..886c01eae 100755 --- a/fhem/FHEM/20_FRM_LCD.pm +++ b/fhem/FHEM/20_FRM_LCD.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -33,6 +42,7 @@ FRM_LCD_Initialize($) $hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev model backLight:on,off blink:on,off autoClear:on,off autoBreak:on,off loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; # autoScroll:on,off direction:leftToRight,rightToLeft do not work reliably + main::LoadModule("FRM"); } sub @@ -75,13 +85,23 @@ FRM_LCD_Init($) return undef; } -sub FRM_LCD_Attr(@) { - my ($command,$name,$attribute,$value) = @_; - my $hash = $main::defs{$name}; - if ($command eq "set") { - $main::attr{$name}{$attribute}=$value; - FRM_LCD_Apply_Attribute($name,$attribute); - } +sub +FRM_LCD_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + $main::attr{$name}{$attribute}=$value; + FRM_LCD_Apply_Attribute($name,$attribute); + } + } } sub FRM_LCD_Apply_Attribute { diff --git a/fhem/FHEM/20_FRM_OUT.pm b/fhem/FHEM/20_FRM_OUT.pm index ab56ad9ed..37fc07353 100755 --- a/fhem/FHEM/20_FRM_OUT.pm +++ b/fhem/FHEM/20_FRM_OUT.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; use SetExtensions; @@ -17,9 +26,11 @@ FRM_OUT_Initialize($) $hash->{DefFn} = "FRM_Client_Define"; $hash->{InitFn} = "FRM_OUT_Init"; $hash->{UndefFn} = "FRM_Client_Undef"; + $hash->{AttrFn} = "FRM_OUT_Attr"; $hash->{StateFn} = "FRM_OUT_State"; $hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -74,6 +85,24 @@ STATEHANDLER: { } } +sub +FRM_OUT_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + $main::attr{$name}{$attribute}=$value; + } + } +} + 1; =pod diff --git a/fhem/FHEM/20_FRM_PWM.pm b/fhem/FHEM/20_FRM_PWM.pm index 7748e8b47..3cc197782 100755 --- a/fhem/FHEM/20_FRM_PWM.pm +++ b/fhem/FHEM/20_FRM_PWM.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -21,9 +30,11 @@ FRM_PWM_Initialize($) $hash->{DefFn} = "FRM_Client_Define"; $hash->{InitFn} = "FRM_PWM_Init"; $hash->{UndefFn} = "FRM_Client_Undef"; + $hash->{AttrFn} = "FRM_PWM_Attr"; $hash->{StateFn} = "FRM_PWM_State"; $hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -77,6 +88,24 @@ STATEHANDLER: { } } +sub +FRM_PWM_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + $main::attr{$name}{$attribute}=$value; + } + } +} + 1; =pod diff --git a/fhem/FHEM/20_FRM_SERVO.pm b/fhem/FHEM/20_FRM_SERVO.pm index 806fc21c9..659537139 100755 --- a/fhem/FHEM/20_FRM_SERVO.pm +++ b/fhem/FHEM/20_FRM_SERVO.pm @@ -3,7 +3,16 @@ package main; use strict; use warnings; -use Device::Firmata; + +#add FHEM/lib to @INC if it's not allready included. Should rather be in fhem.pl than here though... +BEGIN { + if (!grep(/FHEM\/lib$/,@INC)) { + foreach my $inc (grep(/FHEM$/,@INC)) { + push @INC,$inc."/lib"; + }; + }; +}; + use Device::Firmata::Constants qw/ :all /; ##################################### @@ -24,6 +33,7 @@ FRM_SERVO_Initialize($) $hash->{AttrFn} = "FRM_SERVO_Attr"; $hash->{AttrList} = "min-pulse max-pulse IODev loglevel:0,1,2,3,4,5 $main::readingFnAttributes"; + main::LoadModule("FRM"); } sub @@ -39,14 +49,25 @@ FRM_SERVO_Init($$) return undef; } -sub FRM_SERVO_Attr(@) { - my ($command,$name,$attribute,$value) = @_; - if ($command eq "set") { - $main::attr{$name}{$attribute}=$value; - if ( $attribute eq "min-pulse" || $attribute eq "max-pulse" ) { - FRM_SERVO_apply_attribute($main::defs{$name},$attribute); - } - } +sub +FRM_SERVO_Attr($$$$) { + my ($command,$name,$attribute,$value) = @_; + if ($command eq "set") { + ARGUMENT_HANDLER: { + $attribute eq "IODev" and do { + my $hash = $main::defs{$name}; + if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { + $hash->{IODev} = $defs{$value}; + FRM_Init_Client($hash) if (defined ($hash->{IODev})); + } + last; + }; + $main::attr{$name}{$attribute}=$value; + if ( $attribute eq "min-pulse" || $attribute eq "max-pulse" ) { + FRM_SERVO_apply_attribute($main::defs{$name},$attribute); + } + } + } } sub FRM_SERVO_apply_attribute {