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:
parent
a9404010f3
commit
77e1ec9d2e
@ -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 <yes|no></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>
|
||||||
|
@ -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 <on|off></li>
|
<li>restoreOnStartup <on|off></li>
|
||||||
<li>restoreOnReconnect <on|off></li>
|
<li>restoreOnReconnect <on|off></li>
|
||||||
|
<li>activeLow <yes|no></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.)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user