2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

98_Arducounter.pm: Bugfixes

git-svn-id: https://svn.fhem.de/fhem/trunk@13487 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
StefanStrobel 2017-02-22 18:31:47 +00:00
parent 76f874b3d2
commit 2f90ffa189

View File

@ -41,8 +41,11 @@
# 2017-01-02 modification for sketch 1.7, monitor clock drift difference between ardino and Fhem
# 2017-01-04 some more beatification in logging
# 2017-01-06 avoid reopening when disable=0 is set during startup
# 2017-02-06 Doku korrigiert
# 2017-02-18 fixed a bug that caused a missing open when the device is defined while fhem is already initialized
# ideas / todo:
#
@ -62,7 +65,7 @@ my %ArduCounter_gets = (
"info" => ""
);
my $ArduCounter_Version = '4.5 - 6.1.2017';
my $ArduCounter_Version = '4.7 - 18.2.2017';
#
# FHEM module intitialisation
@ -114,7 +117,12 @@ sub ArduCounter_Define($$)
my $name = $a[0];
my $dev = $a[2];
$dev .= '@38400' if ($dev !~ /.+@[0-9]+/);
if ($dev !~ /.+@([0-9]+)/) {
$dev .= '@38400';
} else {
Log3 $name, 3, "$name: Warning: connection speed $1 is not the default for the ArduCounter firmware"
if ($1 != 38400);
}
$hash->{buffer} = "";
$hash->{DeviceName} = $dev;
$hash->{VersionModule} = $ArduCounter_Version;
@ -127,6 +135,10 @@ sub ArduCounter_Define($$)
#$attr{$name}{'flashCommand'} = 'avrdude -p atmega328P -b 57600 -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]';
$attr{$name}{'flashCommand'} = 'avrdude -p atmega328P -c arduino -P [PORT] -D -U flash:w:[HEXFILE] 2>[LOGFILE]';
}
if ($init_done) {
ArduCounter_Open($hash);
}
return;
}
@ -161,7 +173,26 @@ sub ArduCounter_Undef($$)
########################################################
# Notify for INITIALIZED
# Open Device
sub ArduCounter_Open($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
DevIo_OpenDev($hash, 0, 0);
if ($hash->{FD}) {
my $now = gettimeofday();
my $hdl = AttrVal($name, "helloSendDelay", 3);
# send hello if device doesn't say "Started" withing $hdl seconds
RemoveInternalTimer ("sendHello:$name");
InternalTimer($now+$hdl, "ArduCounter_SendHello", "sendHello:$name", 0);
}
}
########################################################
# Notify for INITIALIZED or Modified
# -> Open connection to device
sub ArduCounter_Notify($$)
{
my ($hash, $source) = @_;
@ -181,12 +212,7 @@ sub ArduCounter_Notify($$)
}
Log3 $name, 5, "$name: Notify called with events: @{$events}, open device and set timer to send hello to device";
DevIo_OpenDev( $hash, 0, 0);
my $now = gettimeofday();
RemoveInternalTimer ("sendHello:$name");
my $helloDelay = AttrVal($name, "helloSendDelay", 3);
InternalTimer($now+$helloDelay, "ArduCounter_SendHello", "sendHello:$name", 0);
ArduCounter_Open($hash);
}
@ -211,20 +237,21 @@ sub ArduCounter_Write ($$)
#######################################
# Aufruf aus InternalTimer
# send "h" to ask for "Hello" since device didn't say "Started" so fae - maybe it's still counting ...
sub ArduCounter_SendHello($)
{
my $param = shift;
my (undef,$name) = split(':',$param);
my $hash = $defs{$name};
my $now = gettimeofday();
Log3 $name, 3, "$name: sending h(ello) to device to ask for version";
return if (!ArduCounter_Write( $hash, "h"));
$hash->{WaitForHello} = 1;
my $now = gettimeofday();
my $hwt = AttrVal($name, "helloWaitTime ", 3);
RemoveInternalTimer ("hwait:$name");
my $helloWait= AttrVal($name, "helloWaitTime ", 3);
InternalTimer($now+$helloWait, "ArduCounter_HelloTimeout", "hwait:$name", 0);
InternalTimer($now+$hwt, "ArduCounter_HelloTimeout", "hwait:$name", 0);
$hash->{WaitForHello} = 1;
}
@ -235,7 +262,7 @@ sub ArduCounter_HelloTimeout($)
my $param = shift;
my (undef,$name) = split(':',$param);
my $hash = $defs{$name};
Log3 $name, 3, "$name: device didn't reply to h(ello). Is the right sketch flashed?";
Log3 $name, 3, "$name: device didn't reply to h(ello). Is the right sketch flashed? Is speed set to 38400?";
delete $hash->{WaitForHello};
}
@ -313,11 +340,7 @@ sub ArduCounter_Attr(@)
return;
} else {
Log3 $name, 3, "$name: disable attribute cleared";
DevIo_OpenDev( $hash, 0, 0) if ($hash->{Initialized});
my $now = gettimeofday();
RemoveInternalTimer ("sendHello:$name");
my $helloDelay = AttrVal($name, "helloSendDelay", 1);
InternalTimer($now+$helloDelay, "ArduCounter_SendHello", "sendHello:$name", 0);
ArduCounter_Open($hash) if ($init_done); # only if fhem is initialized
}
}
@ -363,16 +386,17 @@ sub ArduCounter_Attr(@)
return "Invalid pin name $aName";
}
my $pin = $1;
# this cannot come from fhem.cfg and waiting for initialized doesnt help so send it
if ($hash->{Initialized}) { # did device already report its version?
ArduCounter_Write( $hash, "${pin}d");
} else {
Log3 $name, 5, "$name: pin config can not be deleted since device is not initialized yet";
return "device is not initialized yet";
}
} elsif ($aName eq 'disable') {
Log3 $name, 3, "$name: disable attribute removed";
DevIo_OpenDev( $hash, 0, 0) if ($hash->{Initialized});
my $now = gettimeofday();
RemoveInternalTimer ("sendHello:$name");
my $helloDelay = AttrVal($name, "helloSendDelay", 1);
InternalTimer($now+$helloDelay, "ArduCounter_SendHello", "sendHello:$name", 0);
ArduCounter_Open($hash) if ($hash->{$init_done}); # if fhem is initialized
}
}
return undef;
@ -471,6 +495,7 @@ sub ArduCounter_Set($@)
}
DevIo_OpenDev($hash, 0, 0);
$log .= "$name opened\n";
delete $hash->{Initialized};
}
return $log;
}
@ -525,6 +550,9 @@ sub ArduCounter_HandleVersion($$)
if ($version < "1.7") {
$version .= " - not compatible with this Module version - please flash new sketch";
Log3 $name, 3, "$name: device reported outdated Arducounter Firmware - please update!";
delete $hash->{Initialized};
} else {
$hash->{Initialized} = 1; # now device is initialized
}
$hash->{VersionFirmware} = $version;
Log3 $name, 4, "$name: device reported firmware $version";
@ -647,21 +675,20 @@ sub ArduCounter_Parse($)
"s in " . sprintf("%.3f", $drTime) . "s" .
($drTime > 0 ? ", " . sprintf("%.2f", $hash->{'.Drift2'} / $drTime * 100) . "%" : "");
if (!$hash->{Initialized}) {
Log3 $name, 3, "$name: device reported count";
if (!$hash->{WaitForHello}) {
if (!$hash->{Initialized}) { # device has not sent Started / hello yet
Log3 $name, 3, "$name: device is still counting";
if (!$hash->{WaitForHello}) { # if hello has not already been sent, send it now
ArduCounter_SendHello("direct:$name");
}
$hash->{Initialized} = 1;
RemoveInternalTimer ("sendHello:$name");
RemoveInternalTimer ("sendHello:$name"); # don't send hello again
}
} elsif ($line =~ /ArduCounter V([\d\.]+).?Hello/) { # response to h(ello)
Log3 $name, 3, "$name: device replied to hello, V$1";
ArduCounter_HandleVersion($hash, $line);
$hash->{Initialized} = 1;
ArduCounter_ConfigureDevice($hash) if ($hash->{WaitForHello});
if ($hash->{Initialized}) {
ArduCounter_ConfigureDevice($hash) # send pin configuration
}
delete $hash->{WaitForHello};
RemoveInternalTimer ("hwait:$name");
RemoveInternalTimer ("sendHello:$name");
@ -671,7 +698,6 @@ sub ArduCounter_Parse($)
$retStr .= $line;
ArduCounter_HandleVersion($hash, $line);
#todo: remove here?
delete $hash->{WaitForHello};
RemoveInternalTimer ("hwait:$name"); # dont wait for hello reply if already sent
RemoveInternalTimer ("sendHello:$name"); # Hello not needed anymore if not sent yet
@ -680,8 +706,9 @@ sub ArduCounter_Parse($)
} elsif ($line =~ /ArduCounter V([\d\.]+).?Started/) { # setup message
Log3 $name, 3, "$name: device sent setup message, V$1";
ArduCounter_HandleVersion($hash, $line);
$hash->{Initialized} = 1;
ArduCounter_ConfigureDevice($hash);
if ($hash->{Initialized}) {
ArduCounter_ConfigureDevice($hash) # send pin configuration
}
delete $hash->{WaitForHello};
RemoveInternalTimer ("hwait:$name"); # dont wait for hello reply if already sent
@ -821,13 +848,14 @@ sub ArduCounter_Ready($)
# try to reopen if state is disconnected
if ( $hash->{STATE} eq "disconnected" ) {
#Log3 $name, 3, "$name: ReadyFN tries to open"; # debug
delete $hash->{Initialized};
DevIo_OpenDev( $hash, 1, undef );
if ($hash->{FD} && !$hash->{Initialized}) {
Log3 $name, 3, "$name: device not initialized yet, set timer to send h(ello";
if ($hash->{FD}) {
Log3 $name, 3, "$name: device maybe not initialized yet, set timer to send h(ello";
my $now = gettimeofday();
my $hdl = AttrVal($name, "helloSendDelay", 3);
RemoveInternalTimer ("sendHello:$name");
my $helloDelay = AttrVal($name, "helloSendDelay", 3);
InternalTimer($now+$helloDelay, "ArduCounter_SendHello", "sendHello:$name", 0);
InternalTimer($now+$hdl, "ArduCounter_SendHello", "sendHello:$name", 0);
}
return;
}
@ -862,7 +890,8 @@ sub ArduCounter_Ready($)
<ul>
<br>
<li>
This module requires an Arduino uno, nano, Jeenode or similar device running the ArduCounter sketch provided with this module
This module requires an Arduino uno, nano, Jeenode or similar device running the ArduCounter sketch provided with this module<br>
In order to flash an arduino board with the corresponding ArduCounter firmware, avrdude needs to be installed.
</li>
</ul>
<br>