mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
10_FRM: Fix Errors when TCP-connection is lost (changes by jensb)
git-svn-id: https://svn.fhem.de/fhem/trunk@10416 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
627ecac590
commit
8d17241d33
@ -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($@) {
|
||||
my ($hash, @a) = @_;
|
||||
@ -173,7 +179,7 @@ sub FRM_Set($@) {
|
||||
|
||||
COMMAND_HANDLER: {
|
||||
$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();
|
||||
if (defined $hash->{SERVERSOCKET}) {
|
||||
# dispose preexisting connections
|
||||
@ -210,20 +216,20 @@ sub FRM_Get($@) {
|
||||
my $cmd = shift @a;
|
||||
ARGUMENT_HANDLER: {
|
||||
$cmd eq "firmware" and do {
|
||||
if (defined $hash->{FirmataDevice}) {
|
||||
if (FRM_is_firmata_connected($hash)) {
|
||||
return $hash->{FirmataDevice}->{metadata}->{firmware};
|
||||
} else {
|
||||
return "not connected to FirmataDevice";
|
||||
}
|
||||
};
|
||||
$cmd eq "version" and do {
|
||||
if (defined $hash->{FirmataDevice}) {
|
||||
return $hash->{FirmataDevice}->{metadata}->{firmware_version};
|
||||
} else {
|
||||
return "not connected to FirmataDevice";
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$cmd eq "version" and do {
|
||||
if (FRM_is_firmata_connected($hash)) {
|
||||
return $hash->{FirmataDevice}->{metadata}->{firmware_version};
|
||||
} else {
|
||||
return "not connected to FirmataDevice";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -278,7 +284,10 @@ sub FRM_Tcp_Connection_Close($) {
|
||||
TcpServer_Close($hash);
|
||||
if ($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 $name = $hash->{NAME};
|
||||
@ -354,7 +363,7 @@ sub FRM_DoInit($) {
|
||||
|
||||
my $name = $shash->{NAME};
|
||||
|
||||
my $firmata_io = Firmata_IO->new($hash,$name);
|
||||
my $firmata_io = Firmata_IO->new($hash,$name);
|
||||
my $device = Device::Firmata::Platform->attach($firmata_io) or return 1;
|
||||
|
||||
$shash->{FirmataDevice} = $device;
|
||||
@ -667,7 +676,8 @@ sub FRM_I2C_Write
|
||||
{
|
||||
my ($hash,$package) = @_;
|
||||
|
||||
if (defined (my $firmata = $hash->{FirmataDevice})) {
|
||||
if (FRM_is_firmata_connected($hash)) {
|
||||
my $firmata = $hash->{FirmataDevice};
|
||||
COMMANDHANDLER: {
|
||||
$package->{direction} eq "i2cwrite" and do {
|
||||
if (defined $package->{reg}) {
|
||||
@ -730,36 +740,36 @@ sub FRM_string_observer
|
||||
|
||||
sub FRM_poll
|
||||
{
|
||||
my ($hash) = @_;
|
||||
if (defined $hash->{SocketDevice} and defined $hash->{SocketDevice}->{FD}) {
|
||||
my ($rout, $rin) = ('', '');
|
||||
vec($rin, $hash->{SocketDevice}->{FD}, 1) = 1;
|
||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||
my $mfound = vec($rout, $hash->{SocketDevice}->{FD}, 1);
|
||||
if($mfound && defined $hash->{FirmataDevice}) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
return $mfound;
|
||||
} elsif (defined $hash->{FD}) {
|
||||
my ($rout, $rin) = ('', '');
|
||||
vec($rin, $hash->{FD}, 1) = 1;
|
||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||
my $mfound = vec($rout, $hash->{FD}, 1);
|
||||
if($mfound && defined $hash->{FirmataDevice}) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
return $mfound;
|
||||
} else {
|
||||
# This is relevant for windows/USB only
|
||||
my $po = $hash->{USBDev};
|
||||
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
|
||||
if($po) {
|
||||
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
||||
}
|
||||
if ($InBytes && $InBytes>0 && defined $hash->{FirmataDevice}) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
}
|
||||
my ($hash) = @_;
|
||||
if (defined $hash->{SocketDevice} and defined $hash->{SocketDevice}->{FD}) {
|
||||
my ($rout, $rin) = ('', '');
|
||||
vec($rin, $hash->{SocketDevice}->{FD}, 1) = 1;
|
||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||
my $mfound = vec($rout, $hash->{SocketDevice}->{FD}, 1);
|
||||
if($mfound && FRM_is_firmata_connected($hash)) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
return $mfound;
|
||||
} elsif (defined $hash->{FD}) {
|
||||
my ($rout, $rin) = ('', '');
|
||||
vec($rin, $hash->{FD}, 1) = 1;
|
||||
my $nfound = select($rout=$rin, undef, undef, 0.1);
|
||||
my $mfound = vec($rout, $hash->{FD}, 1);
|
||||
if($mfound && FRM_is_firmata_connected($hash)) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
return $mfound;
|
||||
} else {
|
||||
# This is relevant for windows/USB only
|
||||
my $po = $hash->{USBDev};
|
||||
my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags);
|
||||
if($po) {
|
||||
($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
|
||||
}
|
||||
if ($InBytes && $InBytes>0 && FRM_is_firmata_connected($hash)) {
|
||||
$hash->{FirmataDevice}->poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
######### following is code to be called from OWX: ##########
|
||||
@ -1019,6 +1029,24 @@ sub FRM_OWX_Discover ($) {
|
||||
|
||||
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
|
||||
=begin html
|
||||
|
||||
@ -1079,8 +1107,7 @@ sub FRM_OWX_Discover ($) {
|
||||
|
||||
The Arduino has to run either 'StandardFirmata' or 'ConfigurableFirmata'.
|
||||
StandardFirmata supports Digital and Analog-I/O, Servo and I2C. In addition
|
||||
to that ConfigurableFirmata supports 1-Wire, Stepper-motors and allows to
|
||||
connect via ethernet in client mode. <br><br>
|
||||
to that ConfigurableFirmata supports 1-Wire and Stepper-motors.<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">
|
||||
@ -1089,14 +1116,20 @@ sub FRM_OWX_Discover ($) {
|
||||
<br>
|
||||
<li>Network-connected devices:<br><br>
|
||||
<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
|
||||
only.<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
|
||||
configured an the arduino, so it knows where to connect to.<br>
|
||||
specified the socket is bound to all local IP addresses, otherwise to localhost
|
||||
only.<br><br>
|
||||
|
||||
The Arduino has to run either 'StandardFirmataEthernet' or 'ConfigurableFirmata'.
|
||||
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
|
||||
Arduinos may connect to different FRM-devices configured for different ports.<br>
|
||||
ConfigurableFirmata has to be installed manualy. See <a href="https://github.com/firmata/arduino/tree/configurable/examples/ConfigurableFirmata">
|
||||
Arduinos may connect to different FRM-devices configured for different ports.<br><br>
|
||||
|
||||
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>
|
||||
</li>
|
||||
<br>
|
||||
@ -1125,14 +1158,18 @@ sub FRM_OWX_Discover ($) {
|
||||
<b>Attributes</b><br>
|
||||
<ul>
|
||||
<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>
|
||||
As of Firmata 2.3 you can set a delay-time (in microseconds) that will be inserted into i2c
|
||||
protocol when switching from write to read.<br>
|
||||
As of Firmata 2.3 you can set a delay-time (in microseconds, max. 65535, default 0) that will be
|
||||
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>
|
||||
</li><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>
|
||||
</li>
|
||||
</ul>
|
||||
|
Loading…
x
Reference in New Issue
Block a user