2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 06:36:04 +00:00

FRM_IN,FRM_OUT: fix skipped updates during init and reconnect. Add attribute 'activeLow'

git-svn-id: https://svn.fhem.de/fhem/trunk@5054 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
ntruchsess 2014-02-26 17:21:18 +00:00
parent a9404010f3
commit 77e1ec9d2e
3 changed files with 61 additions and 36 deletions

View File

@ -41,7 +41,7 @@ FRM_IN_Initialize($)
$hash->{InitFn} = "FRM_IN_Init"; $hash->{InitFn} = "FRM_IN_Init";
$hash->{UndefFn} = "FRM_Client_Undef"; $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 $main::readingFnAttributes"; $hash->{AttrList} = "IODev count-mode:none,rising,falling,both count-threshold reset-on-threshold-reached:yes,no internal-pullup:on,off activeLow:yes,no $main::readingFnAttributes";
main::LoadModule("FRM"); main::LoadModule("FRM");
} }
@ -53,10 +53,11 @@ FRM_IN_Init($$)
return $ret if (defined $ret); return $ret if (defined $ret);
eval { eval {
my $firmata = FRM_Client_FirmataDevice($hash); my $firmata = FRM_Client_FirmataDevice($hash);
$firmata->observe_digital($hash->{PIN},\&FRM_IN_observer,$hash); my $pin = $hash->{PIN};
if (defined (my $pullup = AttrVal($hash->{NAME},"internal-pullup",undef))) { if (defined (my $pullup = AttrVal($hash->{NAME},"internal-pullup",undef))) {
$firmata->digital_write($hash->{PIN},$pullup eq "on" ? 1 : 0); $firmata->digital_write($pin,$pullup eq "on" ? 1 : 0);
} }
$firmata->observe_digital($pin,\&FRM_IN_observer,$hash);
}; };
if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) { if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) {
$main::attr{$hash->{NAME}}{"stateFormat"} = "reading"; $main::attr{$hash->{NAME}}{"stateFormat"} = "reading";
@ -71,13 +72,17 @@ FRM_IN_observer
my ($pin,$old,$new,$hash) = @_; my ($pin,$old,$new,$hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
Log3 $name,5,"onDigitalMessage for pin ".$pin.", old: ".(defined $old ? $old : "--").", new: ".(defined $new ? $new : "--"); Log3 $name,5,"onDigitalMessage for pin ".$pin.", old: ".(defined $old ? $old : "--").", new: ".(defined $new ? $new : "--");
if (AttrVal($hash->{NAME},"activeLow","no") eq "yes") {
$old = $old == PIN_LOW ? PIN_HIGH : PIN_LOW if (defined $old);
$new = $new == PIN_LOW ? PIN_HIGH : PIN_LOW;
}
my $changed = ((!(defined $old)) or ($old != $new)); my $changed = ((!(defined $old)) or ($old != $new));
main::readingsBeginUpdate($hash); main::readingsBeginUpdate($hash);
if ($changed) { if ($changed) {
if (defined (my $mode = main::AttrVal($name,"count-mode",undef))) { if (defined (my $mode = main::AttrVal($name,"count-mode",undef))) {
if (($mode eq "both") if (($mode eq "both")
or (($mode eq "rising") and ($old == PIN_LOW)) or (($mode eq "rising") and ($new == PIN_HIGH))
or (($mode eq "falling") and ($old == PIN_HIGH))) { or (($mode eq "falling") and ($new == PIN_LOW))) {
my $count = main::ReadingsVal($name,"count",0); my $count = main::ReadingsVal($name,"count",0);
$count++; $count++;
if (defined (my $threshold = main::AttrVal($name,"count-threshold",undef))) { if (defined (my $threshold = main::AttrVal($name,"count-threshold",undef))) {
@ -146,10 +151,11 @@ FRM_IN_Get($)
sub sub
FRM_IN_Attr($$$$) { FRM_IN_Attr($$$$) {
my ($command,$name,$attribute,$value) = @_; my ($command,$name,$attribute,$value) = @_;
my $hash = $main::defs{$name};
my $pin = $hash->{PIN};
if ($command eq "set") { if ($command eq "set") {
ARGUMENT_HANDLER: { ARGUMENT_HANDLER: {
$attribute eq "IODev" and do { $attribute eq "IODev" and do {
my $hash = $main::defs{$name};
if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) { if (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $value) {
$hash->{IODev} = $defs{$value}; $hash->{IODev} = $defs{$value};
FRM_Init_Client($hash) if (defined ($hash->{IODev})); FRM_Init_Client($hash) if (defined ($hash->{IODev}));
@ -173,7 +179,6 @@ FRM_IN_Attr($$$$) {
}; };
$attribute eq "count-threshold" and do { $attribute eq "count-threshold" and do {
if (main::ReadingsVal($name,"count",0) > $value) { if (main::ReadingsVal($name,"count",0) > $value) {
my $hash = $main::defs{$name};
main::readingsBeginUpdate($hash); main::readingsBeginUpdate($hash);
if (main::ReadingsVal($name,"alarm","off") ne "on") { if (main::ReadingsVal($name,"alarm","off") ne "on") {
main::readingsBulkUpdate($hash,"alarm","on",1); main::readingsBulkUpdate($hash,"alarm","on",1);
@ -186,25 +191,44 @@ FRM_IN_Attr($$$$) {
last; last;
}; };
$attribute eq "internal-pullup" and do { $attribute eq "internal-pullup" and do {
eval { eval {
my $hash = $main::defs{$name};
my $firmata = FRM_Client_FirmataDevice($hash); my $firmata = FRM_Client_FirmataDevice($hash);
$firmata->digital_write($hash->{PIN},$value eq "on" ? 1 : 0); $firmata->digital_write($pin,$value eq "on" ? 1 : 0);
}; };
#ignore any errors here, the attribute-value will be applied next time FRM_IN_init() is called. #ignore any errors here, the attribute-value will be applied next time FRM_IN_init() is called.
last; last;
}; };
$attribute eq "activeLow" and do {
my $oldval = AttrVal($hash->{NAME},"activeLow","no");
if ($oldval ne $value) {
$main::attr{$hash->{NAME}}{activeLow} = $value;
eval {
my $firmata = FRM_Client_FirmataDevice($hash);
FRM_IN_observer($pin,undef,$firmata->digital_read($pin),$hash);
};
};
last;
};
} }
} elsif ($command eq "del") { } elsif ($command eq "del") {
ARGUMENT_HANDLER: { ARGUMENT_HANDLER: {
$attribute eq "internal-pullup" and do { $attribute eq "internal-pullup" and do {
eval { eval {
my $hash = $main::defs{$name};
my $firmata = FRM_Client_FirmataDevice($hash); my $firmata = FRM_Client_FirmataDevice($hash);
$firmata->digital_write($hash->{PIN},0); $firmata->digital_write($pin,0);
}; };
last; last;
}; };
$attribute eq "activeLow" and do {
if (AttrVal($hash->{NAME},"activeLow","no") eq "yes") {
delete $main::attr{$hash->{NAME}}{activeLow};
eval {
my $firmata = FRM_Client_FirmataDevice($hash);
FRM_IN_observer($pin,undef,$firmata->digital_read($pin),$hash);
};
};
last;
};
} }
} }
} }
@ -254,6 +278,7 @@ FRM_IN_Attr($$$$) {
<a name="FRM_INattr"></a> <a name="FRM_INattr"></a>
<b>Attributes</b><br> <b>Attributes</b><br>
<ul> <ul>
<li>activeLow &lt;yes|no&gt;</li>
<li>count-mode none|rising|falling|both<br> <li>count-mode none|rising|falling|both<br>
Determines whether 'rising' (transitions from 'off' to 'on') of falling (transitions from 'on' to 'off')<br> Determines whether 'rising' (transitions from 'off' to 'on') of falling (transitions from 'on' to 'off')<br>
edges (or 'both') are counted. Defaults to 'none'</li> edges (or 'both') are counted. Defaults to 'none'</li>

View File

@ -29,7 +29,7 @@ FRM_OUT_Initialize($)
$hash->{AttrFn} = "FRM_OUT_Attr"; $hash->{AttrFn} = "FRM_OUT_Attr";
$hash->{StateFn} = "FRM_OUT_State"; $hash->{StateFn} = "FRM_OUT_State";
$hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off IODev $main::readingFnAttributes"; $hash->{AttrList} = "restoreOnReconnect:on,off restoreOnStartup:on,off activeLow:yes,no IODev $main::readingFnAttributes";
main::LoadModule("FRM"); main::LoadModule("FRM");
} }
@ -56,10 +56,11 @@ FRM_OUT_Set($$$)
{ {
my ($hash, $name, $cmd, @a) = @_; my ($hash, $name, $cmd, @a) = @_;
my $value; my $value;
my $invert = AttrVal($hash->{NAME},"activeLow","no");
if ($cmd eq "on") { if ($cmd eq "on") {
$value=PIN_HIGH; $value = $invert eq "yes" ? PIN_LOW : PIN_HIGH;
} elsif ($cmd eq "off") { } elsif ($cmd eq "off") {
$value=PIN_LOW; $value = $invert eq "yes" ? PIN_HIGH : PIN_LOW;
} else { } else {
my $list = "on off"; my $list = "on off";
return SetExtensions($hash, $list, $name, $cmd, @a); return SetExtensions($hash, $list, $name, $cmd, @a);
@ -141,6 +142,7 @@ FRM_OUT_Attr($$$$) {
<ul> <ul>
<li>restoreOnStartup &lt;on|off&gt;</li> <li>restoreOnStartup &lt;on|off&gt;</li>
<li>restoreOnReconnect &lt;on|off&gt;</li> <li>restoreOnReconnect &lt;on|off&gt;</li>
<li>activeLow &lt;yes|no&gt;</li>
<li><a href="#IODev">IODev</a><br> <li><a href="#IODev">IODev</a><br>
Specify which <a href="#FRM">FRM</a> to use. (Optional, only required if there is more Specify which <a href="#FRM">FRM</a> to use. (Optional, only required if there is more
than one FRM-device defined.) than one FRM-device defined.)

View File

@ -138,8 +138,6 @@ sub messages_handle {
my $port_number = $message->{command} & 0x0f; my $port_number = $message->{command} & 0x0f;
my $port_state = $data->[0] | ( $data->[1] << 7 ); my $port_state = $data->[0] | ( $data->[1] << 7 );
my $old_state = $self->{ports}[$port_number]; my $old_state = $self->{ports}[$port_number];
my $changed_state =
defined $old_state ? $old_state ^ $port_state : 0xFF;
my $observers = $self->{digital_observer}; my $observers = $self->{digital_observer};
my $pinbase = $port_number << 3; my $pinbase = $port_number << 3;
for ( my $i = 0 ; $i < 8 ; $i++ ) { for ( my $i = 0 ; $i < 8 ; $i++ ) {
@ -147,18 +145,16 @@ sub messages_handle {
my $observer = $observers->[$pin]; my $observer = $observers->[$pin];
if ($observer) { if ($observer) {
my $pin_mask = 1 << $i; my $pin_mask = 1 << $i;
if ( $changed_state & $pin_mask ) { $observer->{method}(
$observer->{method}( $pin,
$pin, defined $old_state
defined $old_state ? ( $old_state & $pin_mask ) > 0
? ( $old_state & $pin_mask ) > 0 ? 1
? 1 : 0
: 0 : undef,
: undef, ( $port_state & $pin_mask ) > 0 ? 1 : 0,
( $port_state & $pin_mask ) > 0 ? 1 : 0, $observer->{context}
$observer->{context} );
);
}
} }
} }
$self->{ports}[$port_number] = $port_state; $self->{ports}[$port_number] = $port_state;
@ -404,9 +400,8 @@ sub pin_mode {
}; };
$mode == PIN_ANALOG and do { $mode == PIN_ANALOG and do {
my $port_number = $pin >> 3;
$self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode )); $self->{io}->data_write($self->{protocol}->message_prepare( SET_PIN_MODE => 0, $pin, $mode ));
$self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $port_number, 1 )); $self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 ));
last; last;
}; };
@ -769,6 +764,8 @@ sub observe_digital {
method => $observer, method => $observer,
context => $context, context => $context,
}; };
my $port_number = $pin >> 3;
$self->{io}->data_write($self->{protocol}->message_prepare( REPORT_DIGITAL => $port_number, 1 ));
return 1; return 1;
} }
@ -779,6 +776,7 @@ sub observe_analog {
method => $observer, method => $observer,
context => $context, context => $context,
}; };
$self->{io}->data_write($self->{protocol}->message_prepare( REPORT_ANALOG => $pin, 1 ));
return 1; return 1;
} }