diff --git a/lib/Insteon.pm b/lib/Insteon.pm index 5147cc965..23e1f38d4 100755 --- a/lib/Insteon.pm +++ b/lib/Insteon.pm @@ -488,6 +488,156 @@ sub log_all_ADLB_status } } +=item C + +Walks through every Insteon device and prints statistical information about +its message handling, as well as a summary average of the entire network. See +L +for more detailed information. + +This command adds the following extra data points: + +=back + +=over8 + +=item * + +Unk_Error - The number of messages which have arrived at the PLM which cannot +be associated with any know device. + +=back + +=over + +=cut + +sub print_all_message_stats +{ + my @_log_devices = (); + push @_log_devices, Insteon::find_members("Insteon::BaseDevice"); + + if (@_log_devices) + { + #Initialize all of the tracking variables + my $retry_average = 0; + my $fail_percentage = 0; + my $corrupt_percentage = 0; + my $dupe_percentage = 0; + my $avg_hops_left = 0; + my $avg_max_hops = 0; + my $avg_out_hops = 0; + my $curr_hops_avg = 0; + + my $incoming_count_log = 0; + my $corrupt_count_log = 0; + my $dupe_count_log = 0; + my $retry_count_log = 0; + my $outgoing_count_log = 0; + my $fail_count_log = 0; + my $default_hop_count = 0; + my $hops_left_count = 0; + my $max_hops_count = 0; + my $outgoing_hop_count =0; + + my $device_count = 0; + + foreach my $current_log_device (@_log_devices) + { + #Skip non-root items + next unless $current_log_device->is_root; + + $device_count++; + + #Prints the Individual Message for the Device + $current_log_device->print_message_stats; + + #Add values for each device to the master count + $incoming_count_log += $current_log_device->incoming_count_log; + $corrupt_count_log += $current_log_device->corrupt_count_log; + $dupe_count_log += $current_log_device->dupe_count_log; + $retry_count_log += $current_log_device->retry_count_log; + $outgoing_count_log += $current_log_device->outgoing_count_log; + $fail_count_log += $current_log_device->fail_count_log; + $default_hop_count += $current_log_device->default_hop_count; + $hops_left_count += $current_log_device->hops_left_count; + $max_hops_count += $current_log_device->max_hops_count; + $outgoing_hop_count += $current_log_device->outgoing_hop_count; + } + + #Calculate the averages + $retry_average = sprintf("%.1f", ($retry_count_log / + $outgoing_count_log) + 1) if ($outgoing_count_log > 0); + $fail_percentage = sprintf("%.1f", ($fail_count_log / + $outgoing_count_log) * 100 ) if ($outgoing_count_log > 0); + $corrupt_percentage = sprintf("%.1f", ($corrupt_count_log / + $incoming_count_log) * 100 ) if ($incoming_count_log > 0); + $dupe_percentage = sprintf("%.1f", ($dupe_count_log / + $incoming_count_log) * 100 ) if ($incoming_count_log > 0); + $avg_hops_left = sprintf("%.1f", ($hops_left_count / + $incoming_count_log)) if ($incoming_count_log > 0); + $avg_max_hops = sprintf("%.1f", ($max_hops_count / + $incoming_count_log)) if ($incoming_count_log > 0); + $avg_out_hops = sprintf("%.1f", ($outgoing_hop_count / + $outgoing_count_log)) if ($outgoing_count_log > 0); + $curr_hops_avg = sprintf("%.1f", ($default_hop_count / + $device_count)) if ($device_count > 0); + ::print_log( + "[Insteon] Average Network Statistics:\n" + . " In Corrupt %Corrpt Dupe %Dupe HopsLeft Max_Hops Act_Hops Unk_Error\n" + . sprintf("%6s", $incoming_count_log) + . sprintf("%8s", $corrupt_count_log) + . sprintf("%8s", $corrupt_percentage . '%') + . sprintf("%6s", $dupe_count_log) + . sprintf("%8s", $dupe_percentage . '%') + . sprintf("%9s", $avg_hops_left) + . sprintf("%9s", $avg_max_hops) + . sprintf("%9s", $avg_max_hops - $avg_hops_left) + . sprintf("%10s", &Insteon::active_interface->corrupt_count_log) + . "\n" + . " Out Fail %Fail Retry AvgSend Avg_Hops CurrHops\n" + . sprintf("%6s", $outgoing_count_log) + . sprintf("%8s", $fail_count_log) + . sprintf("%8s", $fail_percentage . '%') + . sprintf("%6s", $retry_count_log) + . sprintf("%8s", $retry_average) + . sprintf("%9s", $avg_out_hops) + . sprintf("%9s", $curr_hops_avg) + ); + main::print_log("[Insteon::Print_All_Message_Stats] All devices have completed logging"); + } else + { + main::print_log("[Insteon::Print_All_Message_Stats] WARN: No insteon devices could be found"); + } +} + +=item C + +Walks through every Insteon device and resets the statistical information about +its message handling. + +=cut + +sub reset_all_message_stats +{ + my @_log_devices = (); + &Insteon::active_interface->reset_message_stats; + push @_log_devices, Insteon::find_members("Insteon::BaseDevice"); + + if (@_log_devices) + { + foreach my $current_log_device (@_log_devices) + { + $current_log_device->reset_message_stats + if $current_log_device->can('reset_message_stats'); + } + main::print_log("[Insteon::Reset_All_Message_Stats] All devices have been reset"); + } else + { + main::print_log("[Insteon::Reset_All_Message_Stats] WARN: No insteon devices could be found"); + } +} + =item C Initiates the insteon stack, mostly just sets the trigger. diff --git a/lib/Insteon/AllLinkDatabase.pm b/lib/Insteon/AllLinkDatabase.pm index eed61071a..332f203b0 100644 --- a/lib/Insteon/AllLinkDatabase.pm +++ b/lib/Insteon/AllLinkDatabase.pm @@ -2146,7 +2146,8 @@ sub on_read_write_aldb . $$self{device}->get_object_name . " [0x" . $$self{_mem_msb} . $$self{_mem_lsb} . "] received: " . lc $msg{extra} . " for " . $$self{_mem_action}) if $main::Debug{insteon} >= 3; - #retry previous address again + $$self{device}->corrupt_count_log(1) if $$self{device}->can('corrupt_count_log'); + #retry previous address again $self->send_read_aldb(sprintf("%04x", hex($$self{_mem_msb} . $$self{_mem_lsb}))); } elsif ($$self{_mem_msb} . $$self{_mem_lsb} ne '0000' and $$self{_mem_msb} . $$self{_mem_lsb} ne substr($msg{extra},6,4)){ @@ -2155,6 +2156,7 @@ sub on_read_write_aldb . $$self{device}->get_object_name . " [0x" . $$self{_mem_msb} . $$self{_mem_lsb} . "] received: " . lc $msg{extra} . " for " . $$self{_mem_action}) if $main::Debug{insteon} >= 3; + $$self{device}->corrupt_count_log(1) if $$self{device}->can('corrupt_count_log'); #retry previous address again $self->send_read_aldb(sprintf("%04x", hex($$self{_mem_msb} . $$self{_mem_lsb}))); } diff --git a/lib/Insteon/BaseInsteon.pm b/lib/Insteon/BaseInsteon.pm index eff675a33..ea17ae646 100644 --- a/lib/Insteon/BaseInsteon.pm +++ b/lib/Insteon/BaseInsteon.pm @@ -833,6 +833,7 @@ sub _process_message . $self->get_object_name . " in response to a " . $pending_cmd . " command, but the command code " . $msg{cmd_code} . " is incorrect. Ignorring received message."); + $self->corrupt_count_log(1) if $self->can('corrupt_count_log'); $p_setby->active_message->no_hop_increase(1); } } @@ -934,6 +935,7 @@ sub _process_message } else { main::print_log("[Insteon::BaseObject] Ignoring unsupported command from " . $self->{object_name}) if $main::Debug{insteon}; + $self->corrupt_count_log(1) if $self->can('corrupt_count_log'); } } return $clear_message; @@ -1230,7 +1232,10 @@ sub new $$self{aldb} = new Insteon::ALDB_i1($self); } - $self->restore_data('level'); + $self->restore_data('level', 'retry_count_log', 'fail_count_log', + 'outgoing_count_log', 'incoming_count_log', 'corrupt_count_log', + 'dupe_count_log', 'hops_left_count', 'max_hops_count', + 'outgoing_hop_count'); $self->initialize(); $self->rate(undef); @@ -1244,6 +1249,15 @@ sub new @{$$self{command_stack}} = (); $$self{_onlevel} = undef; $$self{is_responder} = 1; + $$self{retry_count_log} = 0; + $$self{fail_count_log} = 0; + $$self{outgoing_count_log} = 0; + $$self{incoming_count_log} = 0; + $$self{corrupt_count_log} = 0; + $$self{dupe_count_log} = 0; + $$self{hops_left_count} = 0; + $$self{max_hops_count} = 0; + $$self{outgoing_hop_count} = 0; return $self; } @@ -2028,7 +2042,337 @@ sub engine_version return $engine_version; } -=item C +=item C + +Sets or gets the number of message retries that have occured for this device +since the last time C was called. + +If type is set, to any value, will increment retry log by one. + +Returns: current retry count. + +=cut + +sub retry_count_log +{ + my ($self, $retry_count_log) = @_; + $self = $self->get_root; + $$self{retry_count_log}++ if $retry_count_log; + return $$self{retry_count_log}; +} + +=item C + +Sets or gets the number of message failures that have occured for this device +since the last time C was called. + +If type is set, to any value, will increment fail log by one. + +Returns: current fail count. + +=cut + +sub fail_count_log +{ + my ($self, $fail_count_log) = @_; + $self = $self->get_root; + $$self{fail_count_log}++ if $fail_count_log; + return $$self{fail_count_log}; +} + +=item C + +Sets or gets the number of outgoing message that have occured for this device +since the last time C was called. + +If type is set, to any value, will increment output count by one. + +Returns: current output count. + +=cut + +sub outgoing_count_log +{ + my ($self, $outgoing_count_log) = @_; + $self = $self->get_root; + $$self{outgoing_count_log}++ if $outgoing_count_log; + return $$self{outgoing_count_log}; +} + +=item C + +Sets or gets the number of hops that have been used in all outgoing messages +since the last time C was called. + +If type is set, to any value, will increment output count by that value. + +Returns: current hop count. + +=cut + +sub outgoing_hop_count +{ + my ($self, $outgoing_hop_count) = @_; + $self = $self->get_root; + $$self{outgoing_hop_count} += $outgoing_hop_count if $outgoing_hop_count; + return $$self{outgoing_hop_count}; +} + +=item C + +Sets or gets the number of incoming message that have occured for this device +since the last time C was called. + +If type is set, to any value, will increment incoming count by one. + +Returns: current incoming count. + +=cut + +sub incoming_count_log +{ + my ($self, $incoming_count_log) = @_; + $self = $self->get_root; + $$self{incoming_count_log}++ if $incoming_count_log; + return $$self{incoming_count_log}; +} + +=item C + +Sets or gets the number of currupt message that have arrived from this device +since the last time C was called. + +If type is set, to any value, will increment corrupt count by one. + +Returns: current corrupt count. + +=cut + +sub corrupt_count_log +{ + my ($self, $corrupt_count_log) = @_; + $self = $self->get_root; + $$self{corrupt_count_log}++ if $corrupt_count_log; + return $$self{corrupt_count_log}; +} + +=item C + +Sets or gets the number of duplicate message that have arrived from this device +since the last time C was called. + +If type is set, to any value, will increment corrupt count by one. + +Returns: current duplicate count. + +=cut + +sub dupe_count_log +{ + my ($self, $dupe_count_log) = @_; + $self = $self->get_root; + $$self{dupe_count_log}++ if $dupe_count_log; + return $$self{dupe_count_log}; +} + +=item C + +Sets or gets the number of hops_left for messages that arrive from this device +since the last time C was called. + +If type is set, to any value, will increment corrupt count by one. + +Returns: current hops_left count. + +=cut + +sub hops_left_count +{ + my ($self, $hops_left_count) = @_; + $self = $self->get_root; + $$self{hops_left_count} += $hops_left_count if $hops_left_count; + return $$self{hops_left_count}; +} + +=item C + +Sets or gets the number of max_hops for messages that arrive from this device +since the last time C was called. + +If type is set, to any value, will increment corrupt count by one. + +Returns: current duplicate count. + +=cut + +sub max_hops_count +{ + my ($self, $max_hops_count) = @_; + $self = $self->get_root; + $$self{max_hops_count} += $max_hops_count if $max_hops_count; + return $$self{max_hops_count}; +} + + +=item C + +Resets the retry, fail, outgoing, incoming, and corrupt message counters. + +=cut + +sub reset_message_stats +{ + my ($self) = @_; + $self = $self->get_root; + $$self{retry_count_log} = 0; + $$self{fail_count_log} = 0; + $$self{outgoing_count_log} = 0; + $$self{incoming_count_log} = 0; + $$self{corrupt_count_log} = 0; + $$self{dupe_count_log} = 0; + $$self{hops_left_count} = 0; + $$self{max_hops_count} = 0; + $$self{outgoing_hop_count} = 0; +} + +=item C + +Prints message statistics for this device to the print log. The output contains: + +=back + +=over8 + +=item * + +In - The number of incoming messages received + +=item * + +Corrupt - The number of incoming corrupt messages received + +=item * + +%Corrpt - Of the incoming messages received, the percentage that were +corrupt + +=item * + +Dupe - The number of duplicate messages that have been received from this +device. + +=item * + +%Dupe - The percentage of duplilicate incoming messages received. + +=item * + +Hops_Left - The average hops left in the messages received from this device. + +=item * + +Max_Hops - The average maximum hops in the messages received from this device. + +=item * + +Act_Hops - Max_Hops - Hops_Left, this is the average number of hops that have +been required for a message sent from the device to reach MisterHouse. + +=item * + +Out - The number of unique outgoing messages, without retries, sent. + +=item * + +Fail - The number times that all retries were exhausted without a successful +delivery of a message. + +=item * + +%Fail - Of the outgoing messages sent, the percentage that failed. + +=item * + +Retry - The number of retry attempts that have been made to deliver a message. +Ideally this is 0, but Sends/Msg is a better indication of this parameter. + +=item * + +AvgSend - The average number of send attempts that must be made in order to +successfully deliver a message. Ideally this would be 1.0. + +NOTE: If the number of retries exceeds the value set in the configuration file +for Insteon_retry_count, MisterHouse will abandon sending the message. As a +result, as this number approaches Insteon_retry_count it becomes a less accurate +representation of the number of retries needed to reach a device. + +=item * + +Avg_Hops - The average number of hops that have been used by MisterHouse when +sending messages to this device. + +=item * + +Hop_Count - The current hop count being used by MH. This count is dynamically +controlled by MH and is not reset by calling C + +=back + +=over + +=cut + +sub print_message_stats +{ + my ($self) = @_; + $self = $self->get_root; + my $object_name = $self->get_object_name; + my $retry_average = 0; + $retry_average = sprintf("%.1f", ($$self{retry_count_log} / + $$self{outgoing_count_log}) + 1) if ($$self{outgoing_count_log} > 0); + my $fail_percentage = 0; + $fail_percentage = sprintf("%.1f", ($$self{fail_count_log} / + $$self{outgoing_count_log}) * 100 ) if ($$self{outgoing_count_log} > 0); + my $corrupt_percentage = 0; + $corrupt_percentage = sprintf("%.1f", ($$self{corrupt_count_log} / + $$self{incoming_count_log}) * 100 ) if ($$self{incoming_count_log} > 0); + my $dupe_percentage = 0; + $dupe_percentage = sprintf("%.1f", ($$self{dupe_count_log} / + $$self{incoming_count_log}) * 100 ) if ($$self{incoming_count_log} > 0); + my $avg_hops_left = 0; + $avg_hops_left = sprintf("%.1f", ($$self{hops_left_count} / + $$self{incoming_count_log})) if ($$self{incoming_count_log} > 0); + my $avg_max_hops = 0; + $avg_max_hops = sprintf("%.1f", ($$self{max_hops_count} / + $$self{incoming_count_log})) if ($$self{incoming_count_log} > 0); + my $avg_out_hops = 0; + $avg_out_hops = sprintf("%.1f", ($$self{outgoing_hop_count} / + $$self{outgoing_count_log})) if ($$self{outgoing_count_log} > 0); + ::print_log( + "[Insteon::BaseDevice] Message statistics for $object_name:\n" + . " In Corrupt %Corrpt Dupe %Dupe HopsLeft Max_Hops Act_Hops\n" + . sprintf("%6s", $$self{incoming_count_log}) + . sprintf("%8s", $$self{corrupt_count_log}) + . sprintf("%8s", $corrupt_percentage . '%') + . sprintf("%6s", $$self{dupe_count_log}) + . sprintf("%8s", $dupe_percentage . '%') + . sprintf("%9s", $avg_hops_left) + . sprintf("%9s", $avg_max_hops) + . sprintf("%9s", $avg_max_hops - $avg_hops_left) + . "\n" + . " Out Fail %Fail Retry AvgSend Avg_Hops CurrHops\n" + . sprintf("%6s", $$self{outgoing_count_log}) + . sprintf("%8s", $$self{fail_count_log}) + . sprintf("%8s", $fail_percentage . '%') + . sprintf("%6s", $$self{retry_count_log}) + . sprintf("%8s", $retry_average) + . sprintf("%9s", $avg_out_hops) + . sprintf("%9s", $self->default_hop_count) + ); +} + + +=item C Because of the way MH saves / restores states "after" object creation the aldb must be initially created before the engine_version is restored. @@ -2113,6 +2457,8 @@ sub get_voice_cmds 'status' => "$object_name->request_status", 'get engine version' => "$object_name->get_engine_version", 'scan link table' => "$object_name->scan_link_table(\"" . '\$self->log_alllink_table' . "\")", + 'print message stats' => "$object_name->print_message_stats", + 'reset message stats' => "$object_name->reset_message_stats", 'log links' => "$object_name->log_alllink_table()" ) } diff --git a/lib/Insteon/BaseInterface.pm b/lib/Insteon/BaseInterface.pm index c12e9bbd6..79519a1f2 100644 --- a/lib/Insteon/BaseInterface.pm +++ b/lib/Insteon/BaseInterface.pm @@ -365,6 +365,8 @@ sub process_queue if (defined($failed_message->setby) and $failed_message->setby->can('is_acknowledged')) { $failed_message->setby->is_acknowledged(0); + $failed_message->setby->fail_count_log(1) + if $failed_message->setby->can('fail_count_log'); } else { @@ -530,6 +532,9 @@ sub on_standard_insteon_received my $object = &Insteon::get_object($msg{source}, $msg{group}); if (defined $object) { + $object->max_hops_count($msg{maxhops}) if $object->can('max_hops_count'); + $object->hops_left_count($msg{hopsleft}) if $object->can('hops_left_count'); + $object->incoming_count_log(1) if $object->can('incoming_count_log'); if ($msg{type} ne 'broadcast') { $msg{command} = $object->message_type($msg{cmd_code}); @@ -569,10 +574,13 @@ sub on_standard_insteon_received &main::print_log("[Insteon::BaseInterface] WARN: deviceid of " . "active message != received message source (" . $object->get_object_name() . "). IGNORING received message!!"); + #These generally seem to be duplicate messages + $object->dupe_count_log(1) if $object->can('dupe_count_log'); } } elsif ($msg{type} eq 'cleanup') { + my $setby_object = $object; $object = &Insteon::get_object('000000', $msg{extra}); if ($object) { @@ -581,7 +589,7 @@ sub on_standard_insteon_received # Don't clear active message as ACK is only one of many if (($msg{extra} == $self->active_message->setby->group)){ &main::print_log("[Insteon::BaseInterface] DEBUG3: Cleanup message received for scene " - . $object->get_object_name . " from source " . uc($msg{source})) + . $object->get_object_name . " from " . $setby_object->get_object_name) if $main::Debug{insteon} >= 3; } elsif ($self->active_message->command_type eq 'all_link_direct_cleanup' && lc($self->active_message->setby->device_id) eq $msg{source}) @@ -591,7 +599,7 @@ sub on_standard_insteon_received } else { &main::print_log("[Insteon::BaseInterface] DEBUG3: Cleanup message received from " - . $msg{source} . " for scene " + . $setby_object->get_object_name . " for scene " . $object->get_object_name . ", but group in recent message " . $msg{extra}. " did not match group in " . "prior sent message group " . $self->active_message->setby->group) @@ -604,8 +612,9 @@ sub on_standard_insteon_received else { &main::print_log("[Insteon::BaseInterface] ERROR: received cleanup message from " - . $msg{source} . "that does not correspond to a valid PLM group. Corrupted message is assumed " + . $setby_object->get_object_name . "that does not correspond to a valid PLM group. Corrupted message is assumed " . "and will be skipped! Was group " . $msg{extra}); + $setby_object->corrupt_count_log(1) if $setby_object->can('corrupt_count_log'); } } else #not direct or cleanup @@ -614,6 +623,7 @@ sub on_standard_insteon_received . $object->get_object_name . " but unable to process $msg{type} message type." . " IGNORING received message!!"); $self->active_message->no_hop_increase(1); + $object->corrupt_count_log(1) if $object->can('corrupt_count_log'); } } else #does not correspond to current active message @@ -649,6 +659,7 @@ sub on_standard_insteon_received else { &::print_log("[Insteon::BaseInterface] Warn! Unable to locate object for source: $msg{source} and group: $msg{group}"); + $self->corrupt_count_log(1); } # treat the message as legitimate even if an object match did not occur } @@ -690,6 +701,9 @@ sub on_extended_insteon_received my $object = &Insteon::get_object($msg{source}, $msg{group}); if (defined $object) { + $object->max_hops_count($msg{maxhops}) if $object->can('max_hops_count'); + $object->hops_left_count($msg{hopsleft}) if $object->can('hops_left_count'); + $object->incoming_count_log(1) if $object->can('incoming_count_log'); if ($msg{type} ne 'broadcast') { $msg{command} = $object->message_type($msg{cmd_code}); @@ -842,7 +856,16 @@ sub _is_duplicate_received { #Make a nicer name my $source = $msg{source}; my $object = &Insteon::get_object($msg{source}, $msg{group}); - $source = $object->get_object_name() if (defined $object); + if (defined $object) { + $source = $object->get_object_name(); + $object->dupe_count_log(1) if $object->can('dupe_count_log'); + $object->max_hops_count($msg{maxhops}) if $object->can('max_hops_count'); + $object->hops_left_count($msg{hopsleft}) if $object->can('hops_left_count'); + $object->incoming_count_log(1) if $object->can('incoming_count_log'); + #This message still provides a data point on how many hops it is + #taking for messages to arrive. + $object->default_hop_count($msg{maxhops}-$msg{hopsleft}) if $object->can('default_hop_count'); + }; ::print_log("[Insteon::BaseInterface] WARN! Dropped duplicate incoming message " . $message_data . ", from $source.") if $main::Debug{insteon}; } else { @@ -882,6 +905,8 @@ sub get_voice_cmds 'scan all device link tables' => "Insteon::scan_all_linktables", 'sync all links' => "Insteon::sync_all_links(0)", 'AUDIT - sync all links' => "Insteon::sync_all_links(1)", + 'print all message stats' => "Insteon::print_all_message_stats", + 'reset all message stats' => "Insteon::reset_all_message_stats", 'log all device ALDB status' => "Insteon::log_all_ADLB_status" ); return \%voice_cmds; diff --git a/lib/Insteon/Message.pm b/lib/Insteon/Message.pm index c9567afb0..31d48510a 100644 --- a/lib/Insteon/Message.pm +++ b/lib/Insteon/Message.pm @@ -218,6 +218,7 @@ sub send &::print_log("[Insteon::BaseMessage] WARN: now resending " . $self->to_string() . " after " . $self->send_attempts . " attempts.") if $main::Debug{insteon}; + $self->setby->retry_count_log(1) if $self->setby->can('retry_count_log'); # revise default hop count to reflect retries if (ref $self->setby && $self->setby->isa('Insteon::BaseObject') && !defined($$self{no_hop_increase})) @@ -237,6 +238,11 @@ sub send } # need to set timeout as a function of retries; also need to alter hop count + if ($self->send_attempts <= 0) { + $self->setby->outgoing_count_log(1) if $self->setby->can('outgoing_count_log'); + $self->setby->outgoing_hop_count($self->setby->default_hop_count) + if $self->setby->can('outgoing_hop_count'); + } $self->send_attempts($self->send_attempts + 1); $interface->_send_cmd($self, $self->send_timeout); if ($self->callback) diff --git a/lib/Insteon_PLM.pm b/lib/Insteon_PLM.pm index 90e670463..ad7bd8e3b 100644 --- a/lib/Insteon_PLM.pm +++ b/lib/Insteon_PLM.pm @@ -99,7 +99,8 @@ sub new { $$self{last_command} = ''; $$self{_prior_data_fragment} = ''; bless $self, $class; - $self->restore_data('debug'); + $self->restore_data('debug', 'corrupt_count_log'); + $$self{corrupt_count_log} = 0; $$self{aldb} = new Insteon::ALDB_PLM($self); &Insteon::add($self); @@ -118,6 +119,37 @@ sub new { return $self; } +=item C + +Sets or gets the number of corrupt message that have arrived that could not be +associated with any device since the last time C was called. +These are generally instances in which the from device ID is corrupt. + +If type is set, to any value, will increment corrupt count by one. + +Returns: current corrupt count. + +=cut + +sub corrupt_count_log +{ + my ($self, $corrupt_count_log) = @_; + $$self{corrupt_count_log}++ if $corrupt_count_log; + return $$self{corrupt_count_log}; +} + +=item C + +Resets the retry, fail, outgoing, incoming, and corrupt message counters. + +=cut + +sub reset_message_stats +{ + my ($self) = @_; + $$self{corrupt_count_log} = 0; +} + =item C This is called by mh on exit to save the cached ALDB of a device to persistant data.