Skip to content

Commit

Permalink
Insteon_TriggerLinc: Add Initial Support for TriggerLinc Devices
Browse files Browse the repository at this point in the history
Basically just a copy of code for RemoteLincs, however, TriggerLincs support even fewer commands so much of the code was cut down.

I put the code in the Security.pm file as these are ostensible security devices, however as noted above, these are very similar to RemoteLincs.  Although, they are not that dissimilar from Motion sensors which are also in this file.

I don't own a TriggerLinc so this coding is all done blind.

Thanks to @JaredF for his testing work.

Closes hollie#245
  • Loading branch information
krkeegan committed Oct 10, 2013
1 parent 5aac865 commit 8cbe4a9
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 1 deletion.
216 changes: 215 additions & 1 deletion lib/Insteon/Security.pm
Original file line number Diff line number Diff line change
Expand Up @@ -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<Insteon::TriggerLinc>
=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<Insteon::BaseDevice|Insteon::BaseInsteon/Insteon::BaseDevice>,
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>
=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<new()>
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<set(state[,setby,response])>
Handles messages received from the device. Calls C<set_receive()>.
=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<set_awake_time([0-255 seconds])>
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<get_extended_info()>
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<Insteon::BaseObject::_process_message()|Insteon::BaseInsteon/Insteon::BaseObject>.
=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;
6 changes: 6 additions & 0 deletions lib/read_table_A.pl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

4 comments on commit 8cbe4a9

@JaredF
Copy link

@JaredF JaredF commented on 8cbe4a9 Oct 10, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much for the new code--I will test it out tonight!

@JaredF
Copy link

@JaredF JaredF commented on 8cbe4a9 Oct 11, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested it out and everything works great so far! Thank you so much!

Actually, I'm not noticing any difference between using this or the MotionLinc declaration which is actually a good thing :) Thanks for working on this; even though it doesn't make a huge difference now, I think it's for the best since it was decided to create individual Insteon devices and move away from using the generic IPLL/IPLD system.

One thing I did notice (though this may be the desired functionality) is that this device is currently treated as a "non-deaf" device so it is included in the "Scan all devices" command which causes the device to be considered "out-of-sync" if it is not woken up at the right time when running the scan. Is this the desired behavior for now since we eventually plan to add the "Sync when device awakes" feature or should the device be made to be deaf until such time? I don't believe I saw this issue with the MotionLinc code, but I could be wrong.

@krkeegan
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is currently no is_deaf routine, but there should be. I will add it as an issue, it may take a day or so to code.

@JaredF
Copy link

@JaredF JaredF commented on 8cbe4a9 Oct 12, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another non-critical issue in case there are more important things to work on.

Please sign in to comment.