From: Michael S. <mi...@st...> - 2013-02-19 01:27:04
|
--- a/lib/Insteon/BaseInterface.pm +++ b/lib/Insteon/BaseInterface.pm @@ -33,6 +33,7 @@ sub poll_all { # don't request status for objects associated w/ other than the primary group # as they are psuedo links + $insteon_device->get_engine_version(); $insteon_device->request_status(); } if ($insteon_device->devcat) { @@ -192,7 +193,7 @@ sub queue_message } else { - my $queue_size = @{$$self{command_stack2}}; +# my $queue_size = @{$$self{command_stack2}}; # &main::print_log("[Insteon_PLM] Command stack size: $queue_size") if $queue_size > 0 and $main::Debug{insteon}; if ($setby and ref($setby) and $setby->can('set_retry_timeout') and $setby->get_object_name) @@ -352,11 +353,15 @@ sub on_standard_insteon_received if ($msg{type} ne 'broadcast') { $msg{command} = $object->message_type($msg{cmd_code}); - &::print_log("[Insteon::BaseInterface] command:$msg{command}; type:$msg{type}; group: $msg{group}") + main::print_log("[Insteon::BaseInterface] PLM command:insteon_received; " + . "Device command:$msg{command}; type:$msg{type}; group: $msg{group}") if (!($msg{is_ack} or $msg{is_nack})) and $main::Debug{insteon}; } if ($msg{is_ack} or $msg{is_nack}) { + main::print_log("[Insteon::BaseInterface] DEBUG3: PLM command:insteon_received; " + . "Device command:$msg{command}; type:$msg{type}; group: $msg{group}") + if $main::Debug{insteon} >=3; # need to confirm that this message corresponds to the current active one before clearing it # TO-DO!!! This is a brute force and poor compare technique; needs to be replaced by full compare if ($self->active_message && ref $self->active_message->setby) @@ -499,8 +504,10 @@ sub on_extended_insteon_received if ($msg{type} ne 'broadcast') { $msg{command} = $object->message_type($msg{cmd_code}); - &::print_log("[Insteon::BaseInterface] command:$msg{command}; type:$msg{type}; group: $msg{group}") - if (!($msg{is_ack} or $msg{is_nack})) and $main::Debug{insteon}; + main::print_log("[Insteon::BaseInterface] DEBUG: PLM command:insteon_ext_received; " + . "Device command:$msg{command}; type:$msg{type}; group: $msg{group}") + if( (!($msg{is_ack} or $msg{is_nack}) and $main::Debug{insteon}) + or $main::Debug{insteon} >= 3); } &::print_log("[Insteon::BaseInterface] Processing message for " . $object->get_object_name) if $main::Debug{insteon}; $object->_process_message($self, %msg); diff --git a/lib/Insteon_PLM.pm b/lib/Insteon_PLM.pm index 1ff749c..4d51fbd 100644 --- a/lib/Insteon_PLM.pm +++ b/lib/Insteon_PLM.pm @@ -41,6 +41,7 @@ Special Thanks to: package Insteon_PLM; use strict; +use Insteon; use Insteon::BaseInterface; use Insteon::BaseInsteon; use Insteon::AllLinkDatabase; @@ -238,7 +239,7 @@ sub initiate_linking_as_controller { my ($self, $group) = @_; - $group = 'FF' unless $group; + $group = '01' unless $group; # set up the PLM as the responder my $cmd = '01'; # controller code $cmd .= $group; # WARN - must be 2 digits and in hex!! diff --git a/lib/Insteon/Message.pm b/lib/Insteon/Message.pm index cc06a8b..2344da0 100755 --- a/lib/Insteon/Message.pm +++ b/lib/Insteon/Message.pm @@ -2,7 +2,7 @@ package Insteon::BaseMessage; use strict; -use Insteon; +#use Insteon; sub new { @@ -158,7 +158,7 @@ sub to_string package Insteon::InsteonMessage; use strict; -use Insteon; +#use Insteon; @Insteon::InsteonMessage::ISA = ('Insteon::BaseMessage'); @@ -186,11 +186,16 @@ sub command_to_hash $msg{hopsleft} = $hopflag >> 2; my $msgflag = hex(uc substr($p_state,12,1)); $msg{is_extended} = (0x01 & $msgflag) ? 1 : 0; + $msg{cmd_code} = substr($p_state,14,2); if ($msg{is_extended}) { + $msg{type} = 'direct'; $msg{source} = substr($p_state,0,6); $msg{destination} = substr($p_state,6,6); - $msg{extra} = substr($p_state,16,16); + $msg{extra} = substr($p_state,16,length($p_state)-16); + $msg{crc_valid} = (calculate_checksum($msg{cmd_code}.$msg{extra}) eq '00'); + main::print_log("[Insteon::InsteonMessage] WARN: Message has invalid checksum") + if( !($msg{crc_valid}) and $main::Debug{insteon}); } else { @@ -249,7 +254,6 @@ sub command_to_hash } } } - $msg{cmd_code} = substr($p_state,14,2); return %msg; } @@ -446,13 +450,45 @@ sub _derive_interface_data $cmd .= '00'; } + if( $self->command_type eq 'insteon_ext_send' and $self->setby->engine_version eq 'I2CS') { + #$message is the entire insteon command (no 0262 PLM command) + # i.e. '02622042d31f2e000107110000000000000000000000' + # 111111111122222222223333333333 + # 0123456789012345678901234567890123456789 + # '2042d31f2e000107110000000000000000000000' + if( length($cmd) < 40) { + main::print_log("[Insteon::InsteonMessage] WARN: insert_checksum " + . "failed; cmd to short: $cmd"); + } else { + $cmd = substr($cmd,0,38).calculate_checksum(substr($cmd,8,30)); + } + } + return $cmd; } +=item C<calculate_checksum( string )> + +Calculates a checksum of all hex bytes in the string. Returns two hex nibbles +that represent the checksum in hex. One useful characteristic of the checksum +is that summing over all the bytes "including" the checksum will always equal 00. +This makes it very easy to validate a checksum. + +=cut +sub calculate_checksum { + my ($string) = @_; + + #returns 2 characters as hex nibbles (e.g. AA) + my $sum = 0; + $sum += hex($_) for (unpack('(A2)*', $string)); + return unpack( 'H2', chr((~$sum + 1) & 0xff)); +} + + package Insteon::X10Message; use strict; -use Insteon; +#use Insteon; @Insteon::X10Message::ISA = ('Insteon::BaseMessage'); |