2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-16 04:36:02 +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->{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");
}
@ -53,10 +53,11 @@ FRM_IN_Init($$)
return $ret if (defined $ret);
eval {
my $firmata = FRM_Client_FirmataDevice($hash);
$firmata->observe_digital($hash->{PIN},\&FRM_IN_observer,$hash);
if (defined (my $pullup = AttrVal($hash->{NAME},"internal-pullup",undef))) {
$firmata->digital_write($hash->{PIN},$pullup eq "on" ? 1 : 0);
}
my $pin = $hash->{PIN};
if (defined (my $pullup = AttrVal($hash->{NAME},"internal-pullup",undef))) {
$firmata->digital_write($pin,$pullup eq "on" ? 1 : 0);
}
$firmata->observe_digital($pin,\&FRM_IN_observer,$hash);
};
if (! (defined AttrVal($hash->{NAME},"stateFormat",undef))) {
$main::attr{$hash->{NAME}}{"stateFormat"} = "reading";
@ -69,15 +70,19 @@ sub
FRM_IN_observer
{
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 : "--");
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));
main::readingsBeginUpdate($hash);
if ($changed) {
if ($changed) {
if (defined (my $mode = main::AttrVal($name,"count-mode",undef))) {
if (($mode eq "both")
or (($mode eq "rising") and ($old == PIN_LOW))
or (($mode eq "falling") and ($old == PIN_HIGH))) {
or (($mode eq "rising") and ($new == PIN_HIGH))
or (($mode eq "falling") and ($new == PIN_LOW))) {
my $count = main::ReadingsVal($name,"count",0);
$count++;
if (defined (my $threshold = main::AttrVal($name,"count-threshold",undef))) {
@ -146,10 +151,11 @@ FRM_IN_Get($)
sub
FRM_IN_Attr($$$$) {
my ($command,$name,$attribute,$value) = @_;
my $hash = $main::defs{$name};
my $pin = $hash->{PIN};
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}));
@ -173,7 +179,6 @@ FRM_IN_Attr($$$$) {
};
$attribute eq "count-threshold" and do {
if (main::ReadingsVal($name,"count",0) > $value) {
my $hash = $main::defs{$name};
main::readingsBeginUpdate($hash);
if (main::ReadingsVal($name,"alarm","off") ne "on") {
main::readingsBulkUpdate($hash,"alarm","on",1);
@ -186,25 +191,44 @@ FRM_IN_Attr($$$$) {
last;
};
$attribute eq "internal-pullup" and do {
eval {
my $hash = $main::defs{$name};
eval {
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.
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") {
ARGUMENT_HANDLER: {
$attribute eq "internal-pullup" and do {
eval {
my $hash = $main::defs{$name};
my $firmata = FRM_Client_FirmataDevice($hash);
$firmata->digital_write($hash->{PIN},0);
$firmata->digital_write($pin,0);
};
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>
<b>Attributes</b><br>
<ul>
<li>activeLow &lt;yes|no&gt;</li>
<li>count-mode none|rising|falling|both<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>

View File

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

View File

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