diff --git a/lib/Insteon/Security.pm b/lib/Insteon/Security.pm index ede4466e3..fe97e4014 100644 --- a/lib/Insteon/Security.pm +++ b/lib/Insteon/Security.pm @@ -703,5 +703,219 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +=head1 B + +=head2 SYNOPSIS + +Configuration: + +In user code: + + use Insteon::TriggerLinc; + $trigger = new Insteon::TriggerLinc('12.34.56:01',$myPLM); + +In items.mht: + + INSTEON_TRIGGERLINC, 12.34.56:01, $trigger, $trigger_group + +=head2 DESCRIPTION + +Provides support for Insteon TriggerLinc devices. These are relatively simple +devices that provide open and closed messages but not much else. Other than the +awake time, there are no other software configurable options. + +NOTE: There is a hardware configurable option which allows ON messages to be sent +as group 1 and OFF messages to be sent as group 2. If you enable this function +you will likely want to define and link the group 2 object by replacing ":01" +with ":02" in the above examples. + +=head3 Link Management + +As battery operated devices, these devices are generally asleep. If you want +MH to manage the links on these devices you need to wake them up, generally this +involves holding down the set button until the light flashes. + +Alternatively, if you set the awake time sufficiently high MH will be able to +initiate a communication with these devices for that many seconds after there +is activity (open/close) from these devices. This of course comes at the +expense of additional battery usage. + +=head2 INHERITS + +L, +L + +=head2 METHODS + +=over + +=cut + +package Insteon::TriggerLinc; + +use strict; +use Insteon::BaseInsteon; + +@Insteon::TriggerLinc::ISA = ('Insteon::BaseDevice','Insteon::DeviceController'); + +my %message_types = ( + %Insteon::BaseDevice::message_types +); + +=item C + +Instantiates a new object. + =cut -1 + +sub new +{ + my ($class,$p_deviceid,$p_interface) = @_; + + my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); + $$self{message_types} = \%message_types; + bless $self,$class; + return $self; +} + +=item C + +Handles messages received from the device. Calls C. + +=cut + +sub set +{ + my ($self,$p_state,$p_setby,$p_response) = @_; + return if &main::check_for_tied_filters($self, $p_state); + + # Override any set_with_timer requests + if ($$self{set_timer}) { + &Timer::unset($$self{set_timer}); + delete $$self{set_timer}; + } + + my $setby_name = $p_setby; + $setby_name = $p_setby->get_object_name() if (ref $p_setby and $p_setby->can('get_object_name')); + &::print_log("[Insteon::TriggerLinc] " . $self->get_object_name() + . "::set_receive($p_state, $setby_name)") if $main::Debug{insteon}; + $self->set_receive($p_state,$p_setby); + return; +} + +=item C + +Sets the amount of time, in seconds, that the TriggerLinc will remain "awake" +after sending a command. While awake, the device can be queried by MH such as +with scan link table or sync links. + +=cut + +sub set_awake_time { + my ($self, $awake) = @_; + $awake = sprintf("%02x", $awake); + my $root = $self->get_root(); + my $extra = '000102' . $awake . '0000000000000000000000'; + $$root{_ext_set_get_action} = "set"; + my $message = new Insteon::InsteonMessage('insteon_ext_send', $root, 'extended_set_get', $extra); + $root->_send_cmd($message); + return; +} + +=item C + +Requests the status of various settings on the device. Currently this is only +used to obtain the awake time. If the device is awake, the awake time setting +will be printed to the log. + +=cut + +sub get_extended_info { + my ($self,$no_retry) = @_; + my $root = $self->get_root(); + my $extra = '000100000000000000000000000000'; + $$root{_ext_set_get_action} = "get"; + my $message = new Insteon::InsteonMessage('insteon_ext_send', $root, 'extended_set_get', $extra); + if ($no_retry){ + $message->retry_count(1); + } + $root->_send_cmd($message); + return; +} + +=item C<_process_message()> + +Checks for and handles unique TriggerLinc messages. +All other messages are transferred to L. + +=cut + +sub _process_message { + my ($self,$p_setby,%msg) = @_; + my $clear_message = 0; + my $root = $self->get_root(); + my $pending_cmd = ($$self{_prior_msg}) ? $$self{_prior_msg}->command : $msg{command}; + my $ack_setby = (ref $$self{m_status_request_pending}) ? $$self{m_status_request_pending} : $p_setby; + if ($msg{is_ack} && $self->_is_info_request($pending_cmd,$ack_setby,%msg)) { + $clear_message = 1; + $$self{m_status_request_pending} = 0; + $self->_process_command_stack(%msg); + } + elsif ($msg{command} eq "extended_set_get" && $msg{is_ack}){ + $self->default_hop_count($msg{maxhops}-$msg{hopsleft}); + #If this was a get request don't clear until data packet received + main::print_log("[Insteon::TriggerLinc] Extended Set/Get ACK Received for " . $self->get_object_name) if $main::Debug{insteon}; + if ($$self{_ext_set_get_action} eq 'set'){ + main::print_log("[Insteon::TriggerLinc] Clearing active message") if $main::Debug{insteon}; + $clear_message = 1; + $$self{_ext_set_get_action} = undef; + $self->_process_command_stack(%msg); + } + } + elsif ($msg{command} eq "extended_set_get" && $msg{is_extended}) { + if (substr($msg{extra},0,6) eq "000001") { + $self->default_hop_count($msg{maxhops}-$msg{hopsleft}); + #D3 = Awake Time; + my $awake = (hex(substr($msg{extra}, 6, 2))); + main::print_log("[Insteon::TriggerLinc] The awake seconds ". + "for device ". $self->get_object_name . " is set to: ". + $awake); + $clear_message = 1; + $self->_process_command_stack(%msg); + } else { + main::print_log("[Insteon::TriggerLinc] WARN: Corrupt Extended " + ."Set/Get Data Received for ". $self->get_object_name) if $main::Debug{insteon}; + } + } + else { + $clear_message = $self->SUPER::_process_message($p_setby,%msg); + } + return $clear_message; +} + +sub is_responder +{ + return 0; +} + +=back + +=head2 INI PARAMETERS + +None. + +=head2 AUTHOR + +Kevin Robert Keegan + +=head2 LICENSE + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +=cut + +1; diff --git a/lib/read_table_A.pl b/lib/read_table_A.pl index 8e28ae6c0..2cf4ab553 100644 --- a/lib/read_table_A.pl +++ b/lib/read_table_A.pl @@ -140,6 +140,12 @@ sub read_table_A { $other = join ', ', (map {"'$_'"} @other); # Quote data $object = "Insteon::MotionSensor(\'$address\', $other)"; } + elsif($type eq "INSTEON_TRIGGERLINC") { + require Insteon::Security; + ($address, $name, $grouplist, @other) = @item_info; + $other = join ', ', (map {"'$_'"} @other); # Quote data + $object = "Insteon::TriggerLinc(\'$address\', $other)"; + } elsif($type eq "INSTEON_IOLINC") { require Insteon::IOLinc; ($address, $name, $grouplist, @other) = @item_info;