diff --git a/lib/Insteon.pm b/lib/Insteon.pm index 9038ff491..84fabc82b 100755 --- a/lib/Insteon.pm +++ b/lib/Insteon.pm @@ -400,9 +400,8 @@ sub scan_all_linktables { my $candidate_object = $_; if ($candidate_object->is_root and - !($candidate_object->isa('Insteon::RemoteLinc') - or $candidate_object->isa('Insteon::InterfaceController') - or $candidate_object->isa('Insteon::MotionSensor'))) + !($candidate_object->is_deaf + or $candidate_object->isa('Insteon::InterfaceController'))) { push @_scan_devices, $candidate_object; &main::print_log("[Scan all linktables] INFO1: " @@ -511,7 +510,7 @@ sub sync_all_links # iterate over all registered objects and compare whether the link tables match defined scene linkages in known Insteon_Links for my $obj (&Insteon::find_members('Insteon::BaseController')) { - if ($obj->isa('Insteon::RemoteLinc') or $obj->isa('Insteon::MotionSensor')) + if (!$obj->isa('Insteon::InterfaceController') && $obj->is_deaf) { &main::print_log("[Sync all links] Ignoring links from 'deaf' device: " . $obj->get_object_name); } diff --git a/lib/Insteon/AllLinkDatabase.pm b/lib/Insteon/AllLinkDatabase.pm index aa47c807b..003db8636 100644 --- a/lib/Insteon/AllLinkDatabase.pm +++ b/lib/Insteon/AllLinkDatabase.pm @@ -421,7 +421,7 @@ sub delete_orphan_links # first, make sure that the health of ALDB is ok if ($self->health ne 'good') { - if ($$self{device}->isa('Insteon::RemoteLinc') or $$self{device}->isa('Insteon::MotionSensor')) + if ($self->is_deaf) { &::print_log("[Insteon::AllLinkDatabase] Delete orphan links: ignoring link from deaf device: $selfname"); @@ -588,7 +588,7 @@ sub delete_orphan_links } else # is a non-PLM device { - if ($linked_device->isa('Insteon::RemoteLinc') or $linked_device->isa('Insteon::MotionSensor')) + if ($linked_device->is_deaf) { &::print_log("[Insteon::AllLinkDatabase] Delete orphan links: ignoring link from $selfname to 'deaf' device: " . $linked_device->get_object_name); } @@ -754,7 +754,7 @@ sub delete_orphan_links { $member = $member->get_root; } - if ($member->isa('Insteon::RemoteLinc') or $member->isa('Insteon::MotionSensor')) + if ($member->is_deaf) { &::print_log("[Insteon::AllLinkDatabase] ignoring link from " . $link->get_object_name . " to " . $member->get_object_name); @@ -2830,7 +2830,7 @@ sub delete_orphan_links } if ($member->isa('Insteon::BaseDevice')) { - if ($member->isa('Insteon::RemoteLinc') or $member->isa('Insteon::MotionSensor')) + if ($member->is_deaf) { &::print_log("[Insteon::ALDB_PLM] ignoring link from PLM to " . $member->get_object_name); diff --git a/lib/Insteon/BaseInsteon.pm b/lib/Insteon/BaseInsteon.pm index c4e909cc5..68ba714e8 100644 --- a/lib/Insteon/BaseInsteon.pm +++ b/lib/Insteon/BaseInsteon.pm @@ -270,22 +270,31 @@ Returns the highest hop count of the past 20 hop counts sub default_hop_count { my ($self, $hop_count) = @_; - unshift(@{$$self{hop_array}}, $$self{default_hop_count}) if (!defined(@{$$self{hop_array}})); if (defined($hop_count)){ ::print_log("[Insteon::BaseObject] DEBUG3: Adding hop count of " . $hop_count . " to hop_array of " . $self->get_object_name) if $main::Debug{insteon} >= 3; - unshift(@{$$self{hop_array}}, $hop_count) + if (!defined(@{$$self{hop_array}})) { + unshift(@{$$self{hop_array}}, $$self{default_hop_count}); + $$self{hop_sum} = $$self{default_hop_count}; + } + #Calculate a simple moving average + unshift(@{$$self{hop_array}}, $hop_count); + $$self{hop_sum} += ${$$self{hop_array}}[0]; + $$self{hop_sum} -= pop(@{$$self{hop_array}}) if (scalar(@{$$self{hop_array}}) >10); + $$self{default_hop_count} = int(($$self{hop_sum} / scalar(@{$$self{hop_array}})) + 0.5); + + ::print_log("[Insteon::BaseObject] DEBUG4: ".$self->get_object_name + ."->default_hop_count()=".$$self{default_hop_count} + ." :: hop_array[]=". join("",@{$$self{hop_array}})) + if $main::Debug{insteon} >= 4; } - pop(@{$$self{hop_array}}) if (scalar(@{$$self{hop_array}}) >20); - my $high = 0; - foreach (@{$$self{hop_array}}){ - $high = $_ if ($high < $_);; - } - $$self{default_hop_count} = $high; + + #Allow for per-device settings $$self{default_hop_count} = $$self{max_hops} if ($$self{max_hops} && $$self{default_hop_count} > $$self{max_hops}); $$self{default_hop_count} = $$self{min_hops} if ($$self{min_hops} && - $$self{default_hop_count} < $$self{min_hops}); + $$self{default_hop_count} < $$self{min_hops}); + return $$self{default_hop_count}; } @@ -1278,6 +1287,7 @@ sub new $$self{hops_left_count} = 0; $$self{max_hops_count} = 0; $$self{outgoing_hop_count} = 0; + $$self{is_deaf} = 0; return $self; } @@ -1312,6 +1322,23 @@ sub rate return $$self{rate}; } +=item C + +Returns true if the device must be awake in order to respond to messages. Most +devices are not deaf, currently devices that are deaf are battery operated +devices such as the Motion Sensor, RemoteLinc and TriggerLinc. + +At the BaseObject level all devices are defined as not deaf. Objects which +inherit BaseObject should redefine is_deaf as necessary. + +=cut + +sub is_deaf +{ + my ($self) = @_; + return $$self{is_deaf}; +} + =item C Returns true if the device is a controller. @@ -1465,7 +1492,7 @@ sub link_to_interface_i2cs case (2) { #Scan device to get an accurate link table #return to normal link_to_interface routine if successful $success_callback_prefix = $self->get_object_name."->link_to_interface('$p_group','$p_data3',"; - $success_callback = $success_callback_prefix . "'2')"; + $success_callback = $success_callback_prefix . "'1')"; $self->scan_link_table($success_callback, $failure_callback); } } @@ -1848,7 +1875,8 @@ Hop Count, Engine Version, ALDB Type, ALDB Health, and Last ALDB Scan Time sub log_aldb_status { my ($self) = @_; - main::print_log( " Hop Count: ".$self->default_hop_count()); + main::print_log( " Device ID: ".$self->device_id()); + main::print_log( " Hop Count: ".$self->default_hop_count()." :: [". join("",@{$$self{hop_array}})."]"); main::print_log( "Engine Version: ".$self->engine_version()); my $aldb = $self->get_root()->_aldb; if ($aldb) @@ -1941,6 +1969,8 @@ sub _get_engine_version_failure ."linked; Please use 'link to interface' voice command"); $self->engine_version('I2CS'); } + #Clear success callback, otherwise it will run when message is cleared + $self->interface->active_message->success_callback('0'); } =item C diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 368de52ae..4c1c67e30 100644 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -80,6 +80,7 @@ sub new } bless $self,$class; $$self{is_responder} = 0; + $$self{is_deaf} = 1; return $self; } diff --git a/lib/Insteon/Message.pm b/lib/Insteon/Message.pm index 38e4e43fd..beb4ad1cb 100644 --- a/lib/Insteon/Message.pm +++ b/lib/Insteon/Message.pm @@ -113,7 +113,7 @@ Data will be evaluated after the receipt of an ACK from the device for this comm sub success_callback { my ($self, $callback) = @_; - if ($callback) + if (defined $callback) { $$self{success_callback} = $callback; } diff --git a/lib/Insteon/Security.pm b/lib/Insteon/Security.pm index a51be4db7..f79090003 100644 --- a/lib/Insteon/Security.pm +++ b/lib/Insteon/Security.pm @@ -127,6 +127,7 @@ sub new } bless $self,$class; $$self{is_responder} = 0; + $$self{is_deaf} = 1; return $self; } @@ -751,6 +752,7 @@ sub new $$self{message_types} = \%message_types; bless $self,$class; $$self{is_responder} = 0; + $$self{is_deaf} = 1; return $self; } diff --git a/lib/Insteon_PLM.pm b/lib/Insteon_PLM.pm index c97637985..9181f3d85 100644 --- a/lib/Insteon_PLM.pm +++ b/lib/Insteon_PLM.pm @@ -815,7 +815,7 @@ sub _parse_data { my $message_to_string = ($self->active_message) ? $self->active_message->to_string() : ""; &::print_log("[Insteon_PLM] Received all-link cleanup success: $message_to_string") if $main::Debug{insteon}; - if (ref $self->active_message->setby){ + if (ref $self->active_message && ref $self->active_message->setby){ my $object = $self->active_message->setby; $object->is_acknowledged(1); $object->_process_command_stack();