2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 18:59:33 +00:00

OWX_SER: implement DevIo-based communication and reconnect

git-svn-id: https://svn.fhem.de/fhem/trunk@6271 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
ntruchsess 2014-07-18 21:50:39 +00:00
parent cf367e7e10
commit 8b87c26db5
3 changed files with 68 additions and 119 deletions

View File

@ -84,7 +84,6 @@ if( $^O =~ /Win/ ) {
use Time::HiRes qw( gettimeofday tv_interval );
require "$main::attr{global}{modpath}/FHEM/DevIo.pm";
sub Log3($$$);
use vars qw{%owg_family %gets %sets $owx_async_version $owx_async_debug};
@ -275,48 +274,25 @@ sub OWX_ASYNC_Ready ($) {
};
sub OWX_ASYNC_Read ($) {
my $hash = shift;
my ($hash) = @_;
Log3 ($hash->{NAME},5,"OWX_ASYNC_Read") if ($owx_async_debug > 2);
OWX_ASYNC_Poll($hash);
if (defined $hash->{ASYNC}) {
$hash->{ASYNC}->poll($hash);
};
OWX_ASYNC_RunTasks($hash);
};
sub OWX_ASYNC_Poll ($) {
my $hash = shift;
Log3 ($hash->{NAME},5,"OWX_ASYNC_Poll") if ($owx_async_debug > 2);
if (defined $hash->{ASYNC}) {
$hash->{ASYNC}->poll($hash);
};
};
sub OWX_ASYNC_Disconnect($) {
my ($hash) = @_;
my $async = $hash->{ASYNC};
Log3 ($hash->{NAME},3, "OWX_ASYNC_Disconnect");
if (defined $async) {
$async->exit($hash);
};
my $times = AttrVal($hash->{NAME},"timeout",5000) / 50; #timeout in ms, defaults to 1 sec?
for (my $i=0;$i<$times;$i++) {
OWX_ASYNC_Poll($hash);
if ($hash->{STATE} ne "Active") {
last;
}
};
my ($hash) = @_;
my $async = $hash->{ASYNC};
Log3 ($hash->{NAME},3, "OWX_ASYNC_Disconnect");
if (defined $async) {
$async->exit($hash);
delete $hash->{ASYNC};
};
$hash->{STATE} = "disconnected" if $hash->{STATE} eq "Active";
};
sub OWX_ASYNC_Disconnected($) {
my ($hash) = @_;
Log3 ($hash->{NAME},4, "OWX_ASYNC_Disconnected");
if ($hash->{ASYNC} and $hash->{ASYNC} != $hash->{OWX}) {
delete $hash->{ASYNC};
};
if (my $owx = $hash->{OWX}) {
$owx->Disconnect($hash);
};
$hash->{STATE} = "disconnected" if $hash->{STATE} eq "Active";
};
########################################################################################
#
# OWX_ASYNC_Alarms - Initiate search for devices on the 1-Wire bus which have the alarm flag set
@ -711,12 +687,12 @@ sub OWX_ASYNC_Init ($) {
RemoveInternalTimer($hash);
if (defined ($hash->{ASNYC})) {
$hash->{ASYNC}->exit($hash);
$hash->{ASYNC} = undef; #TODO should we call delete on $hash->{ASYNC}?
$hash->{ASYNC}->exit($hash);
delete $hash->{ASYNC}; #TODO should we call delete on $hash->{ASYNC}?
}
#-- get the interface
my $owx = $hash->{OWX};
if (defined $owx) {
$hash->{INTERFACE} = $owx->{interface};
my $ret;
@ -729,9 +705,10 @@ sub OWX_ASYNC_Init ($) {
$hash->{STATE} = "Init Failed: $err";
return "OWX_ASYNC_Init failed: $err";
};
$hash->{ASYNC} = $ret;
return undef unless $ret;
$hash->{ASYNC} = $ret ;
$hash->{ASYNC}->{debug} = $owx_async_debug;
$hash->{INTERFACE} = $owx->{interface};
$hash->{INTERFACE} = $owx->{interface};
} else {
return "OWX: Init called with undefined interface";
}
@ -1016,7 +993,8 @@ sub OWX_ASYNC_RunToCompletion($$) {
OWX_ASYNC_Schedule($hash,$task);
my $master = $hash->{TYPE} eq "OWX_ASYNC" ? $hash : $hash->{IODev};
do {
OWX_ASYNC_Poll($master);
die "interface $master->{INTERFACE} not active" unless defined $hash->{ASYNC};
$hash->{ASYNC}->poll($hash);
OWX_ASYNC_RunTasks($master);
$task_state = $task->PT_STATE();
} while ($task_state == PT_INITIAL or $task_state == PT_WAITING or $task_state == PT_YIELDED);

View File

@ -86,24 +86,8 @@ sub block ($) {
########################################################################################
sub query ($$$) {
my ($serial,$cmd,$retlen) = @_;
my ($i,$j,$k,$l,$m,$n);
#-- get hardware device
my $hwdevice = $serial->{hwdevice};
die "OWX_DS2480: query with no hwdevice" unless (defined $hwdevice);
$hwdevice->baudrate($serial->{baud});
$hwdevice->write_settings;
main::Log3($serial->{name},5, "OWX_DS2480.query sending out: ".unpack ("H*",$cmd));
my $count_out = $hwdevice->write($cmd);
die "OWX_DS2480: Write incomplete ".(defined $count_out ? $count_out : "undefined")." not equal ".(length($cmd))."" if (!(defined $count_out) or ($count_out ne length($cmd)));
main::DevIo_SimpleWrite($serial->{hash},$cmd,0);
$serial->{retlen} += $retlen;
}
@ -119,16 +103,12 @@ sub query ($$$) {
########################################################################################
sub read() {
my $serial = shift;
my ($i,$j,$k);
#-- get hardware device
my $hwdevice = $serial->{hwdevice};
return undef unless (defined $hwdevice);
my ($serial) = @_;
#-- read the data
my ($count_in, $string_part) = $hwdevice->read(255);
return undef if (not defined $count_in or not defined $string_part);
my $string_part = main::DevIo_DoSimpleRead($serial->{hash});
return undef unless defined $string_part;
my $count_in = length ($string_part);
$serial->{string_in} .= $string_part;
$serial->{retcount} += $count_in;
$serial->{num_reads}++;

View File

@ -30,6 +30,8 @@ use warnings;
use vars qw/@ISA/;
require "$main::attr{global}{modpath}/FHEM/DevIo.pm";
use Time::HiRes qw( gettimeofday );
use ProtoThreads;
no warnings 'deprecated';
@ -44,8 +46,6 @@ sub new() {
my $class = shift;
my $self = {
interface => "serial",
#-- baud rate serial interface
baud => 9600,
#-- 16 byte search string
search => [0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0],
ROM_ID => [0,0,0,0 ,0,0,0,0],
@ -64,7 +64,15 @@ sub new() {
sub poll($) {
my ( $self ) = @_;
$self->read();
my $hash = $self->{hash};
if(defined($hash->{FD})) {
my ($rin,$win);
vec($rin, $hash->{FD}, 1) = 1;
vec($win, $hash->{FD}, 1) = 1;
if (select($rin, $win, $rin | $win, 2)) { #TODO: implement attribute based timeout
main::OWX_ASYNC_Disconnect($hash) unless $self->read();
}
}
}
########################################################################################
@ -82,17 +90,17 @@ sub poll($) {
########################################################################################
sub Define ($$) {
my ($self,$hash,$def) = @_;
my @a = split("[ \t][ \t]*", $def);
my ($self,$hash,$def) = @_;
my @a = split("[ \t][ \t]*", $def);
$self->{name} = $hash->{NAME};
$self->{name} = $hash->{NAME};
#-- check syntax
if(int(@a) < 3){
return "OWX_SER: Syntax error - must be define <name> OWX <serial-device>"
}
my $dev = $a[2];
#-- check syntax
if(int(@a) < 3){
return "OWX_SER: Syntax error - must be define <name> OWX <serial-device>"
}
my $dev = $a[2];
#-- when the specified device name contains @<digits> already, use it as supplied
if ( $dev !~ m/\@\d*/ ){
$hash->{DeviceName} = $dev."\@9600";
@ -100,7 +108,10 @@ sub Define ($$) {
my ($device,$baudrate) = split('@',$dev);
#-- let fhem.pl MAIN call OWX_Ready when setup is done.
$main::readyfnlist{"$hash->{NAME}.$device"} = $hash;
$self->{baud} = $baudrate ? $baudrate : 9600;
$self->{hash} = $hash;
return undef;
}
@ -153,13 +164,6 @@ sub get_pt_execute($$$$) {
PT_BEGIN($thread);
$thread->{writedata} = $writedata;
#-- get the interface
my $interface = $self->{interface};
my $hwdevice = $self->{hwdevice};
unless (defined $hwdevice) {
PT_EXIT;
}
$self->reset() if ($reset);
if (defined $writedata or $numread) {
@ -263,30 +267,18 @@ sub get_pt_discover() {
#
########################################################################################
sub initialize($) {
my ($self,$hash) = @_;
sub initialize() {
my ($self) = @_;
my ($i,$j,$k,$l,$res,$ret,$ress);
#-- Second step in case of serial device: open the serial device to test it
my $hash = $self->{hash};
my $msg = "OWX_SER: Serial device $hash->{DeviceName}";
main::DevIo_OpenDev($hash,0,undef);
main::DevIo_OpenDev($hash,$self->{reopen},undef);
return undef unless $hash->{STATE} eq "opened";
my $hwdevice = $hash->{USBDev};
if(!defined($hwdevice)){
die $msg." not defined: $!";
} else {
main::Log3($hash->{NAME},2,$msg." defined");
}
$hwdevice->reset_error();
$hwdevice->baudrate(9600);
$hwdevice->databits(8);
$hwdevice->parity('none');
$hwdevice->stopbits(1);
$hwdevice->handshake('none');
$hwdevice->write_settings;
#-- store with OWX device
$self->{hwdevice} = $hwdevice;
#force master reset in DS2480
$hwdevice->reset_error();
$hwdevice->purge_all;
$hwdevice->baudrate(4800);
$hwdevice->write_settings;
@ -294,7 +286,7 @@ sub initialize($) {
select(undef,undef,undef,0.5);
#-- Third step detect busmaster on serial interface
my $name = $self->{name};
my $ress0 = "OWX_SER::Detect 1-Wire bus $name: interface ";
$ress = $ress0;
@ -303,16 +295,15 @@ sub initialize($) {
require "$main::attr{global}{modpath}/FHEM/OWX_DS2480.pm";
my $ds2480 = OWX_DS2480->new($self);
#-- timing byte for DS2480
$ds2480->start_query();
$hwdevice->baudrate(9600);
$hwdevice->write_settings;
$ds2480->query("\xC1",1);
eval { #ignore timeout
do {
$ds2480->read();
} while (!$ds2480->response_ready());
};
$hwdevice->baudrate($self->{baud});
$hwdevice->write_settings;
#-- Max 4 tries to detect an interface
for($l=0;$l<100;$l++) {
#-- write 1-Wire bus (Fig. 2 of Maxim AN192)
@ -377,11 +368,11 @@ sub initialize($) {
}
}
sub Disconnect($) {
my ($self,$hash) = @_;
main::DevIo_Disconnected($hash);
delete $self->{hwdevice};
$self->{interface} = "serial";
sub exit($) {
my ($self) = @_;
main::DevIo_Disconnected($self->{hash});
$self->{interface} = "serial";
$self->{reopen} = 1;
}
########################################################################################