From daf3dc47e8c13423fb28cb6d4ba7788e422bbf82 Mon Sep 17 00:00:00 2001 From: ntruchsess Date: Mon, 4 Aug 2014 21:08:27 +0000 Subject: [PATCH] OWX_DS9097: fix 1-Wire search algorithm git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@6362 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_OWX.pm | 10 ++++----- fhem/FHEM/00_OWX_ASYNC.pm | 45 +++++++++++++++++++++++++-------------- fhem/FHEM/OWX_DS9097.pm | 30 +++++++++++--------------- fhem/FHEM/OWX_SER.pm | 1 + 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/fhem/FHEM/00_OWX.pm b/fhem/FHEM/00_OWX.pm index b1bc9bb97..2c34f0b34 100644 --- a/fhem/FHEM/00_OWX.pm +++ b/fhem/FHEM/00_OWX.pm @@ -1198,9 +1198,12 @@ sub OWX_Complex_SER ($$$$) { sub OWX_First_SER ($$) { my ($hash,$mode) = @_; - + #-- clear 16 byte of search data @owx_search=(0,0,0,0 ,0,0,0,0, 0,0,0,0, 0,0,0,0); + #-- clear 8 bytes of romid: + @owx_ROM_ID = (0,0,0,0,0,0,0,0); + #-- reset the search state $owx_LastDiscrepancy = 0; $owx_LastDeviceFlag = 0; @@ -1915,9 +1918,6 @@ sub OWX_Search_9097 ($$) { #$response = OWX_TouchByte($hash,$sp1); - #-- clear 8 byte of device id for current search - @owx_ROM_ID =(0,0,0,0 ,0,0,0,0); - while ( $id_bit_number <= 64) { #loop until through all ROM bytes 0-7 my $id_bit = OWX_TouchBit_9097($hash,1); @@ -1977,8 +1977,8 @@ sub OWX_Search_9097 ($$) { $rom_byte_number++; $rom_byte_mask = 1; } - $owx_LastDiscrepancy = $last_zero; } + $owx_LastDiscrepancy = $last_zero; return 1; } diff --git a/fhem/FHEM/00_OWX_ASYNC.pm b/fhem/FHEM/00_OWX_ASYNC.pm index 0d9a615ff..d950990ae 100644 --- a/fhem/FHEM/00_OWX_ASYNC.pm +++ b/fhem/FHEM/00_OWX_ASYNC.pm @@ -3,38 +3,44 @@ # OWX_ASYNC.pm # # FHEM module to commmunicate with 1-Wire bus devices -# * via an active DS2480 bus master interface attached to an USB port +# * via an active DS2480 bus master interface attached to a serial port, USB or Ethernet<->Serial interface +# * via a passive DS9097 bus master interface attached to a serial port # * via an Arduino running ConfigurableFirmata attached to USB # * via an Arduino running ConfigurableFirmata connecting to FHEM via Ethernet # # Norbert Truchsess -# Prof. Dr. Peter A. Henning +# based on 00_OWX.pm written by Prof. Dr. Peter A. Henning # # $Id$ # ######################################################################################## # -# define OWX_ASYNC for USB interfaces or +# define OWX_ASYNC for serial or USB interfaces (both DS2480 and DS9097) +# define OWX_ASYNC for DS2480 over Ethernet # define OWX_ASYNC for a Arduino/Firmata (10_FRM.pm) interface # # where may be replaced by any name string # is a serial (USB) device # is an Arduino pin # -# get alarms => find alarmed 1-Wire devices (not with CUNO) -# get devices => find all 1-Wire devices -# get version => OWX_ASYNC version number +# get alarms => find alarmed 1-Wire devices (not with CUNO) +# get devices => find all 1-Wire devices +# get version => OWX_ASYNC version number # -# set interval => set period for temperature conversion and alarm testing -# set followAlarms on/off => determine whether an alarm is followed by a search for -# alarmed devices +# set interval => set period for temperature conversion and alarm testing +# set followAlarms on/off => determine whether an alarm is followed by a search for +# alarmed devices # -# attr dokick 0/1 => 1 if the interface regularly kicks thermometers on the -# bus to do a temperature conversion, -# and to make an alarm check -# 0 if not +# attr buspower real/parasitic => for devices that steal power from data-line # -# attr interval => set period for temperature conversion and alarm testing +# attr dokick 0/1 => 1 if the interface regularly kicks thermometers on the +# bus to do a temperature conversion, +# and to make an alarm check +# 0 if not +# +# attr interval => set period for temperature conversion and alarm testing +# +# attr IODev => required when there's more than a single frm-device defined. # ######################################################################################## # @@ -127,7 +133,7 @@ my %attrs = ( ); #-- some globals needed for the 1-Wire module -$owx_async_version=5.12; +$owx_async_version=5.13; #-- Debugging 0,1,2,3 $owx_async_debug=0; @@ -1054,6 +1060,12 @@ sub OWX_ASYNC_RunToCompletion($$) { return $task->PT_RETVAL(); } +sub OWX_ASYNC_TaskTimeout($$) { + my ( $master, $timeout ) = @_; + die "OWX_ASYNC_TaskTimeout: no task running" unless defined $master->{".runningtask"}; + $master->{".runningtask"}->{TimeoutTime} = $timeout; +} + sub OWX_ASYNC_RunTasks($) { my ( $master ) = @_; if ($master->{STATE} eq "Active") { @@ -1090,6 +1102,7 @@ sub OWX_ASYNC_RunTasks($) { } if (defined (my $current = @queue_waiting ? shift @queue_waiting : @queue_ready ? shift @queue_ready : @queue_initial ? shift @queue_initial : undef)) { my $task = $current->{queue}->[0]; + $master->{".runningtask"} = $task; my $timeout = $task->{TimeoutTime}; if ($task->PT_SCHEDULE()) { my $state = $task->PT_STATE(); @@ -1114,7 +1127,7 @@ sub OWX_ASYNC_RunTasks($) { Log3 $master->{NAME},5,"OWX_ASYNC_RunTasks: $current->{device} task waiting for data or timeout" if ($owx_async_debug>2); #new timeout or timeout did change: if (!defined $timeout or $timeout != $task->{TimeoutTime}) { - Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $current->{device} task schedule for timeout at %.6f",$task->{TimeoutTime}); + Log3 $master->{NAME},5,sprintf("OWX_ASYNC_RunTasks: $current->{device} task schedule for timeout at %.6f",$task->{TimeoutTime}) if ($owx_async_debug>1); InternalTimer($task->{TimeoutTime}, "OWX_ASYNC_RunTasks", $master,0); } last; diff --git a/fhem/FHEM/OWX_DS9097.pm b/fhem/FHEM/OWX_DS9097.pm index aa2b37483..ddd3f344e 100644 --- a/fhem/FHEM/OWX_DS9097.pm +++ b/fhem/FHEM/OWX_DS9097.pm @@ -125,13 +125,9 @@ sub reset() { sub block($) { my ( $serial, $block ) = @_; - if (defined (my $hwdevice = $serial->{hash}->{USBDev})) { - main::Log3($serial->{name},5, "OWX_DS9097 block: ".unpack "H*",$block) if ( $main::owx_async_debug > 1 ); - foreach my $bit (split //,unpack "b*",$block) { - $serial->bit($bit); - } - } else { - die "no USBDev"; + main::Log3($serial->{name},5, "OWX_DS9097 block: ".unpack "H*",$block) if ( $main::owx_async_debug > 1 ); + foreach my $bit (split //,unpack "b*",$block) { + $serial->bit($bit); } } @@ -149,20 +145,22 @@ sub bit($) { sub pt_query($) { my ( $serial, $query ) = @_; my @bitsout = split //,$query; + my $numbits = @bitsout; my $bitsin = ""; my $bit; return PT_THREAD(sub { my ( $thread ) = @_; PT_BEGIN($thread); - main::Log3($serial->{name},5, "OWX_DS9097 pt_query out: ".$query) if( $main::owx_async_debug > 1 ); + main::Log3($serial->{name},5, "OWX_DS9097 pt_query out: ".$query) if( $main::owx_async_debug ); + while ($serial->poll()) {}; + $serial->{string_raw} = ""; while (defined ($bit = shift @bitsout)) { - while ($serial->poll()) {}; - $serial->{string_raw} = ""; $serial->bit($bit); - PT_WAIT_UNTIL(length($serial->{string_raw}) > 0); - $bitsin .= substr($serial->{string_raw},0,1) eq ($bit == 1 ? "\xFF" : "\x00") ? "1" : "0"; }; - main::Log3($serial->{name},5,"OWX_DS9097 pt_query in: ".$bitsin) if ( $main::owx_async_debug > 1 ); + main::OWX_ASYNC_TaskTimeout($serial->{hash},gettimeofday+1); + PT_WAIT_UNTIL(length($serial->{string_raw}) >= $numbits); + $bitsin = join "", map { ($_ == 0xFF) ? "1" : "0" } unpack "C*",$serial->{string_raw}; + main::Log3($serial->{name},5,"OWX_DS9097 pt_query in: ".$bitsin) if ( $main::owx_async_debug ); PT_EXIT($bitsin); PT_END; }); @@ -207,8 +205,6 @@ sub pt_next ($$) { } else { $serial->block("\xEC"); } - #-- clear 8 byte of device id for current search - $context->{ROM_ID} = [0,0,0,0 ,0,0,0,0]; #-- Response search data parsing operates bitwise @@ -262,6 +258,7 @@ sub pt_next ($$) { } # serial number search direction write bit $serial->bit($search_direction); + main::Log3 ($serial->{name},5,"id_bit_number: $id_bit_number, search_direction: $search_direction, LastDiscrepancy: $last_zero ROM_ID: ".sprintf("%02X.%02X%02X%02X%02X%02X%02X.%02X",@{$context->{ROM_ID}})) if ($main::owx_async_debug); # increment the byte counter id_bit_number # and shift the mask rom_byte_mask $id_bit_number++; @@ -271,9 +268,8 @@ sub pt_next ($$) { $rom_byte_number++; $rom_byte_mask = 1; } - $context->{LastDiscrepancy} = $last_zero; - main::Log3 ($serial->{name},5,"id_bit_number: $id_bit_number, search_direction: $search_direction, LastDiscrepancy: $context->{LastDiscrepancy} ROM_ID: ".sprintf("%02X.%02X%02X%02X%02X%02X%02X.%02X",@{$context->{ROM_ID}})) if ($main::owx_async_debug > 2); } + $context->{LastDiscrepancy} = $last_zero; PT_END; }); } diff --git a/fhem/FHEM/OWX_SER.pm b/fhem/FHEM/OWX_SER.pm index 5cac771be..819c13d6b 100644 --- a/fhem/FHEM/OWX_SER.pm +++ b/fhem/FHEM/OWX_SER.pm @@ -368,6 +368,7 @@ sub first($) { $thread->{LastDiscrepancy} = 0; $thread->{LastDeviceFlag} = 0; $thread->{LastFamilyDiscrepancy} = 0; + $thread->{ROM_ID} = [0,0,0,0,0,0,0,0]; } sub next_response($) {