10_FRM: Fix Errors when TCP-connection is lost (changes by jensb)
git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@10416 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -162,6 +162,12 @@ sub FRM_Notify {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub FRM_is_firmata_connected {
|
||||||
|
my ($hash) = @_;
|
||||||
|
return defined($hash->{FirmataDevice}) && defined ($hash->{FirmataDevice}->{io});
|
||||||
|
}
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub FRM_Set($@) {
|
sub FRM_Set($@) {
|
||||||
my ($hash, @a) = @_;
|
my ($hash, @a) = @_;
|
||||||
@@ -173,7 +179,7 @@ sub FRM_Set($@) {
|
|||||||
|
|
||||||
COMMAND_HANDLER: {
|
COMMAND_HANDLER: {
|
||||||
$command eq "reset" and do {
|
$command eq "reset" and do {
|
||||||
return $hash->{NAME}." is not connected" unless (defined $hash->{FirmataDevice} and (defined $hash->{FD} or ($^O=~/Win/ and defined $hash->{USBDev})));
|
return $hash->{NAME}." is not connected" unless (FRM_is_firmata_connected($hash) && (defined $hash->{FD} or ($^O=~/Win/ and defined $hash->{USBDev})));
|
||||||
$hash->{FirmataDevice}->system_reset();
|
$hash->{FirmataDevice}->system_reset();
|
||||||
if (defined $hash->{SERVERSOCKET}) {
|
if (defined $hash->{SERVERSOCKET}) {
|
||||||
# dispose preexisting connections
|
# dispose preexisting connections
|
||||||
@@ -210,14 +216,14 @@ sub FRM_Get($@) {
|
|||||||
my $cmd = shift @a;
|
my $cmd = shift @a;
|
||||||
ARGUMENT_HANDLER: {
|
ARGUMENT_HANDLER: {
|
||||||
$cmd eq "firmware" and do {
|
$cmd eq "firmware" and do {
|
||||||
if (defined $hash->{FirmataDevice}) {
|
if (FRM_is_firmata_connected($hash)) {
|
||||||
return $hash->{FirmataDevice}->{metadata}->{firmware};
|
return $hash->{FirmataDevice}->{metadata}->{firmware};
|
||||||
} else {
|
} else {
|
||||||
return "not connected to FirmataDevice";
|
return "not connected to FirmataDevice";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$cmd eq "version" and do {
|
$cmd eq "version" and do {
|
||||||
if (defined $hash->{FirmataDevice}) {
|
if (FRM_is_firmata_connected($hash)) {
|
||||||
return $hash->{FirmataDevice}->{metadata}->{firmware_version};
|
return $hash->{FirmataDevice}->{metadata}->{firmware_version};
|
||||||
} else {
|
} else {
|
||||||
return "not connected to FirmataDevice";
|
return "not connected to FirmataDevice";
|
||||||
@@ -278,7 +284,10 @@ sub FRM_Tcp_Connection_Close($) {
|
|||||||
TcpServer_Close($hash);
|
TcpServer_Close($hash);
|
||||||
if ($hash->{SNAME}) {
|
if ($hash->{SNAME}) {
|
||||||
my $shash = $main::defs{$hash->{SNAME}};
|
my $shash = $main::defs{$hash->{SNAME}};
|
||||||
$hash->{SocketDevice} = undef if (defined $shash);
|
if (defined $shash) {
|
||||||
|
$shash->{STATE}="listening";
|
||||||
|
delete $shash->{SocketDevice} if (defined $shash->{SocketDevice});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
my $dev = $hash->{DeviceName};
|
my $dev = $hash->{DeviceName};
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
@@ -667,7 +676,8 @@ sub FRM_I2C_Write
|
|||||||
{
|
{
|
||||||
my ($hash,$package) = @_;
|
my ($hash,$package) = @_;
|
||||||
|
|
||||||
if (defined (my $firmata = $hash->{FirmataDevice})) {
|
if (FRM_is_firmata_connected($hash)) {
|
||||||
|
my $firmata = $hash->{FirmataDevice};
|
||||||
COMMANDHANDLER: {
|
COMMANDHANDLER: {
|
||||||
$package->{direction} eq "i2cwrite" and do {
|
$package->{direction} eq "i2cwrite" and do {
|
||||||
if (defined $package->{reg}) {
|
if (defined $package->{reg}) {
|
||||||
@@ -736,7 +746,7 @@ sub FRM_poll
|
|||||||
vec($rin, $hash->{SocketDevice}->{FD}, 1) = 1;
|
vec($rin, $hash->{SocketDevice}->{FD}, 1) = 1;
|
||||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||||
my $mfound = vec($rout, $hash->{SocketDevice}->{FD}, 1);
|
my $mfound = vec($rout, $hash->{SocketDevice}->{FD}, 1);
|
||||||
if($mfound && defined $hash->{FirmataDevice}) {
|
if($mfound && FRM_is_firmata_connected($hash)) {
|
||||||
$hash->{FirmataDevice}->poll();
|
$hash->{FirmataDevice}->poll();
|
||||||
}
|
}
|
||||||
return $mfound;
|
return $mfound;
|
||||||
@@ -745,7 +755,7 @@ sub FRM_poll
|
|||||||
vec($rin, $hash->{FD}, 1) = 1;
|
vec($rin, $hash->{FD}, 1) = 1;
|
||||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||||
my $mfound = vec($rout, $hash->{FD}, 1);
|
my $mfound = vec($rout, $hash->{FD}, 1);
|
||||||
if($mfound && defined $hash->{FirmataDevice}) {
|
if($mfound && FRM_is_firmata_connected($hash)) {
|
||||||
$hash->{FirmataDevice}->poll();
|
$hash->{FirmataDevice}->poll();
|
||||||
}
|
}
|
||||||
return $mfound;
|
return $mfound;
|
||||||
@@ -756,7 +766,7 @@ sub FRM_poll
|
|||||||
if($po) {
|
if($po) {
|
||||||
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
||||||
}
|
}
|
||||||
if ($InBytes && $InBytes>0 && defined $hash->{FirmataDevice}) {
|
if ($InBytes && $InBytes>0 && FRM_is_firmata_connected($hash)) {
|
||||||
$hash->{FirmataDevice}->poll();
|
$hash->{FirmataDevice}->poll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1019,6 +1029,24 @@ sub FRM_OWX_Discover ($) {
|
|||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
=pod
|
||||||
|
CHANGES
|
||||||
|
|
||||||
|
18.12.2015 jensb
|
||||||
|
o added sub FRM_is_firmata_connected
|
||||||
|
- extended connection check including {FirmataDevice}->{io} (gets
|
||||||
|
deleted by FRM_FirmataDevice_Close on TCP disconnect while FHEM
|
||||||
|
has still a valid reference to {FirmataDevice} when calling
|
||||||
|
I2CWrtFn)
|
||||||
|
o modified sub FRM_Set, FRM_Get, FRM_I2C_Write, FRM_poll:
|
||||||
|
- use sub FRM_is_firmata_connected to check if Firmata is still
|
||||||
|
connected before performing IO operations (to prevent FHEM crash)
|
||||||
|
o modified sub FRM_Tcp_Connection_Close:
|
||||||
|
- set STATE to listening and delete SocketDevice (to present same
|
||||||
|
idle state as FRM_Start)
|
||||||
|
o help updated
|
||||||
|
=cut
|
||||||
|
|
||||||
=pod
|
=pod
|
||||||
=begin html
|
=begin html
|
||||||
|
|
||||||
@@ -1079,8 +1107,7 @@ sub FRM_OWX_Discover ($) {
|
|||||||
|
|
||||||
The Arduino has to run either 'StandardFirmata' or 'ConfigurableFirmata'.
|
The Arduino has to run either 'StandardFirmata' or 'ConfigurableFirmata'.
|
||||||
StandardFirmata supports Digital and Analog-I/O, Servo and I2C. In addition
|
StandardFirmata supports Digital and Analog-I/O, Servo and I2C. In addition
|
||||||
to that ConfigurableFirmata supports 1-Wire, Stepper-motors and allows to
|
to that ConfigurableFirmata supports 1-Wire and Stepper-motors.<br><br>
|
||||||
connect via ethernet in client mode. <br><br>
|
|
||||||
|
|
||||||
You can find StandardFirmata in the Arduino-IDE under 'Examples->Firmata->StandardFirmata<br><br>
|
You can find StandardFirmata in the Arduino-IDE under 'Examples->Firmata->StandardFirmata<br><br>
|
||||||
ConfigurableFirmata has to be installed manualy. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
|
ConfigurableFirmata has to be installed manualy. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
|
||||||
@@ -1089,14 +1116,20 @@ sub FRM_OWX_Discover ($) {
|
|||||||
<br>
|
<br>
|
||||||
<li>Network-connected devices:<br><br>
|
<li>Network-connected devices:<br><br>
|
||||||
<code><port></code> specifies the port the FRM device listens on. If <code>global</code> is
|
<code><port></code> specifies the port the FRM device listens on. If <code>global</code> is
|
||||||
specified the socket is bound to all local ip-addresses, otherwise to localhost
|
specified the socket is bound to all local IP addresses, otherwise to localhost
|
||||||
only.<br>
|
only.<br><br>
|
||||||
The Arduino must ConfigurableFirmata. The connection is initiated by the arduino
|
|
||||||
in client-mode. Therefor the ip-address and port of the fhem-server has to be
|
The Arduino has to run either 'StandardFirmataEthernet' or 'ConfigurableFirmata'.
|
||||||
configured an the arduino, so it knows where to connect to.<br>
|
StandardFirmataEthernet supports Digital and Analog-I/O, Servo and I2C. In addition
|
||||||
|
to that ConfigurableFirmata supports 1-Wire and Stepper-motors.<br><br>
|
||||||
|
|
||||||
|
The connection is initiated by the Arduino in client-mode. Therefore the IP address and port
|
||||||
|
of the fhem-server has to be configured in the Arduino, so it knows where to connect to.<br>
|
||||||
As of now only a single Arduino per FRM-device configured is supported. Multiple
|
As of now only a single Arduino per FRM-device configured is supported. Multiple
|
||||||
Arduinos may connect to different FRM-devices configured for different ports.<br>
|
Arduinos may connect to different FRM-devices configured for different ports.<br><br>
|
||||||
ConfigurableFirmata has to be installed manualy. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
|
|
||||||
|
You can find StandardFirmataEthernet in the Arduino-IDE under 'Examples->Firmata->StandardFirmataEthernet<br><br>
|
||||||
|
ConfigurableFirmata has to be installed manually. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
|
||||||
ConfigurableFirmata</a> on GitHub or <a href="http://www.fhemwiki.de/wiki/Arduino_Firmata#Installation_ConfigurableFirmata">FHEM-Wiki</a><br>
|
ConfigurableFirmata</a> on GitHub or <a href="http://www.fhemwiki.de/wiki/Arduino_Firmata#Installation_ConfigurableFirmata">FHEM-Wiki</a><br>
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
@@ -1125,14 +1158,18 @@ sub FRM_OWX_Discover ($) {
|
|||||||
<b>Attributes</b><br>
|
<b>Attributes</b><br>
|
||||||
<ul>
|
<ul>
|
||||||
<li>i2c-config<br>
|
<li>i2c-config<br>
|
||||||
Configure the arduino for ic2 communication. This will enable i2c on the
|
Configure the Arduino for ic2 communication. This will enable i2c on the
|
||||||
i2c_pins received by the capability-query issued during initialization of FRM.<br>
|
i2c_pins received by the capability-query issued during initialization of FRM.<br>
|
||||||
As of Firmata 2.3 you can set a delay-time (in microseconds) that will be inserted into i2c
|
As of Firmata 2.3 you can set a delay-time (in microseconds, max. 65535, default 0) that will be
|
||||||
protocol when switching from write to read.<br>
|
inserted into i2c protocol when switching from write to read. This may be necessary because Firmata
|
||||||
|
i2c write does not block on the fhem side so consecutive i2c write/read operations get queued and
|
||||||
|
will be executed on the Firmata device in a different time sequence. Use the maximum operation
|
||||||
|
time required by the connected i2c devices (e.g. 30000 for the BMP180 with triple oversampling,
|
||||||
|
see i2c device manufacturer documentation for details). <br>
|
||||||
See: <a href="http://www.firmata.org/wiki/Protocol#I2C">Firmata Protocol details about I2C</a><br>
|
See: <a href="http://www.firmata.org/wiki/Protocol#I2C">Firmata Protocol details about I2C</a><br>
|
||||||
</li><br>
|
</li><br>
|
||||||
<li>sampling-interval<br>
|
<li>sampling-interval<br>
|
||||||
Configure the interval Firmata reports data to FRM. Unit is milliseconds.<br>
|
Configure the interval Firmata reports analog data to FRM (in milliseconds, max. 65535). <br>
|
||||||
See: <a href="http://www.firmata.org/wiki/Protocol#Sampling_Interval">Firmata Protocol details about Sampling Interval</a></br>
|
See: <a href="http://www.firmata.org/wiki/Protocol#Sampling_Interval">Firmata Protocol details about Sampling Interval</a></br>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user