Skip to content

Commit

Permalink
Merge pull request #301 from krkeegan/fix_issue_85
Browse files Browse the repository at this point in the history
Insteon: Add Sync_All_Links Routine for Multigroup items; Add MultigroupDevice Package
  • Loading branch information
krkeegan committed Nov 13, 2013
2 parents 29e89bf + 65b63b0 commit 72c06b8
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 9 deletions.
147 changes: 147 additions & 0 deletions lib/Insteon/BaseInsteon.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2740,6 +2740,153 @@ You should have received a copy of the GNU General Public License along with thi
=cut

####################################
### ###############
### MultigroupDevice ###############
### ###############
####################################

=head1 B<Insteon::MultigroupDevice>
=head2 DESCRIPTION
Contains functions which are unique to insteon devices which have more than
one group. This includes, KeyPadLincs, RemoteLincs, FanLincs, Thermostats
(i2 versions).
=head2 INHERITS
Nothing.
This package is meant to provide supplemental support and should only be added
as a secondary inheritance to an object.
=head2 METHODS
=over
=cut

package Insteon::MultigroupDevice;

=item C<sync_all_links(audit_mode)>
Syncs all links on the object, including all subgroups such as additional
buttons.
Paramter B<audit_mode> - Causes sync to walk through but not actually
send any commands to the devices. Useful with the insteon:3 debug setting for
troubleshooting.
=cut

sub sync_all_links
{
my ($self, $audit_mode) = @_;
$self = $self->get_root();
@{$$self{_sync_devices}} = ();
@{$$self{_sync_device_failures}} = ();
my $device_id = $self->device_id();
my ($subgroup_object, $group, $dec_group);

::print_log("[Insteon::MultigroupDevice] Sync All Links on device "
.$self->get_object_name . " starting ...");
# Find all subgroup items check groups from 02 - FF;
for ($dec_group = 01; $dec_group <= 255; $dec_group++) {
$group = sprintf("%02X", $dec_group);
$subgroup_object = Insteon::get_object($device_id, $group);
if (ref $subgroup_object){
my %sync_req = ('sync_object' => $subgroup_object,
'audit_mode' => ($audit_mode) ? 1 : 0);
::print_log("[Insteon::MultigroupDevice] "
."Adding " . $subgroup_object->get_object_name
." to sync queue.");
push @{$$self{_sync_devices}}, \%sync_req
}
}
$$self{_sync_cnt} = scalar @{$$self{_sync_devices}};
$self->_get_next_linksync();
}

=item C<_get_next_linksync()>
Calls the sync_links() function for each device identified by sync_all_link.
This function will be called recursively since the callback passed to sync_links()
is this function again. Will also ask sync_links() to call
_get_next_linksync_failure() if sync_links() fails.
=cut

sub _get_next_linksync
{
my ($self) = @_;
$self = $self->get_root();
my $sync_req_ptr = shift(@{$$self{_sync_devices}});
my %sync_req = ($sync_req_ptr) ? %$sync_req_ptr : undef;
my $current_sync_device;
if (%sync_req) {
$current_sync_device = $sync_req{'sync_object'};
}
else {
$current_sync_device = undef;
}

if ($current_sync_device) {
::print_log("[Insteon::MultigroupDevice] Now syncing: "
. $current_sync_device->get_object_name . " ("
. ($$self{_sync_cnt} - scalar @{$$self{_sync_devices}})
. " of ".$$self{_sync_cnt}.")");
$current_sync_device->sync_links($sync_req{'audit_mode'},
$self->get_object_name . '->_get_next_linksync()',
$self->get_object_name . '->_get_next_linksync_failure('.$current_sync_device->get_object_name.')');
}
else {
::print_log("[Insteon::MultigroupDevice] All links have completed syncing "
. "on device " . $self->get_object_name);
my $_sync_failure_cnt = scalar @{$$self{_sync_device_failures}};
if ($_sync_failure_cnt) {
::print_log("[Insteon::MultigroupDevice] However, some failures were noted:");
for my $failed_obj (@{$$self{_sync_device_failures}}) {
::print_log("[Insteon::MultigroupDevice] WARN: failure occurred when syncing "
. $failed_obj->get_object_name);
}
}
}
}

=item C<_get_next_linksync()>
Called by the failure callback in a device's sync_links() function. Will add
the failed device to the module global variable @_sync_device_failures.
=cut

sub _get_next_linksync_failure
{
my ($self, $current_sync_device) = @_;
$self = $self->get_root();
push @{$$self{_sync_device_failures}}, $current_sync_device;
::print_log("[Insteon::MultigroupDevice] WARN: failure occurred when syncing "
. $current_sync_device->get_object_name . ". Moving on...");
$self->_get_next_linksync();
}

=back
=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

####################################
### #################
### BaseController #################
Expand Down
33 changes: 32 additions & 1 deletion lib/Insteon/Controller.pm
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ must first be put into "awake mode."
L<Insteon::BaseDevice|Insteon::BaseInsteon/Insteon::BaseDevice>,
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>,
L<Insteon::Insteon::MultigroupDevice|Insteon::BaseInsteon/Insteon::Insteon::MultigroupDevice>
=head2 METHODS
Expand All @@ -54,7 +55,7 @@ package Insteon::RemoteLinc;
use strict;
use Insteon::BaseInsteon;

@Insteon::RemoteLinc::ISA = ('Insteon::BaseDevice','Insteon::DeviceController');
@Insteon::RemoteLinc::ISA = ('Insteon::BaseDevice','Insteon::DeviceController', 'Insteon::MultigroupDevice');

my %message_types = (
%Insteon::BaseDevice::message_types,
Expand Down Expand Up @@ -243,6 +244,36 @@ sub _process_message {
return $clear_message;
}

=item C<get_voice_cmds>
Returns a hash of voice commands where the key is the voice command name and the
value is the perl code to run when the voice command name is called.
Higher classes which inherit this object may add to this list of voice commands by
redefining this routine while inheriting this routine using the SUPER function.
This routine is called by L<Insteon::generate_voice_commands> to generate the
necessary voice commands.
=cut

sub get_voice_cmds
{
my ($self) = @_;
my $object_name = $self->get_object_name;
my %voice_cmds = (
%{$self->SUPER::get_voice_cmds}
);
if ($self->is_root){
%voice_cmds = (
%voice_cmds,
'sync all device links' => "$object_name->sync_all_links()",
'AUDIT sync all device links' => "$object_name->sync_all_links(1)"
);
}
return \%voice_cmds;
}

=back
=head2 AUTHOR
Expand Down
44 changes: 39 additions & 5 deletions lib/Insteon/Lighting.pm
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,8 @@ Provides support for the Insteon KeypadLinc Relay.
=head2 INHERITS
L<Insteon::BaseLight|Insteon::Lighting/Insteon::BaseLight>,
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>,
L<Insteon::Insteon::MultigroupDevice|Insteon::BaseInsteon/Insteon::Insteon::MultigroupDevice>
=head2 METHODS
Expand All @@ -745,7 +746,7 @@ package Insteon::KeyPadLincRelay;
use strict;
use Insteon::BaseInsteon;

@Insteon::KeyPadLincRelay::ISA = ('Insteon::BaseLight','Insteon::DeviceController');
@Insteon::KeyPadLincRelay::ISA = ('Insteon::BaseLight','Insteon::DeviceController', 'Insteon::MultigroupDevice');

our %operating_flags = (
'program_lock_on' => '00',
Expand Down Expand Up @@ -875,7 +876,9 @@ sub get_voice_cmds
'set 8 button - backlight normal' => "$object_name->update_flags(\"02\")",
'set 6 button - backlight dim' => "$object_name->update_flags(\"08\")",
'set 6 button - backlight off' => "$object_name->update_flags(\"04\")",
'set 6 button - backlight normal' => "$object_name->update_flags(\"00\")"
'set 6 button - backlight normal' => "$object_name->update_flags(\"00\")",
'sync all device links' => "$object_name->sync_all_links()",
'AUDIT sync all device links' => "$object_name->sync_all_links(1)"
);
}
return \%voice_cmds;
Expand Down Expand Up @@ -1035,7 +1038,8 @@ Provides support for the Insteon FanLinc.
=head2 INHERITS
L<Insteon::DimmableLight|Insteon::Lighting/Insteon::DimmableLight>,
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>
L<Insteon::DeviceController|Insteon::BaseInsteon/Insteon::DeviceController>,
L<Insteon::Insteon::MultigroupDevice|Insteon::BaseInsteon/Insteon::Insteon::MultigroupDevice>
=head2 METHODS
Expand All @@ -1048,7 +1052,7 @@ package Insteon::FanLinc;
use strict;
use Insteon::BaseInsteon;

@Insteon::FanLinc::ISA = ('Insteon::DimmableLight','Insteon::DeviceController');
@Insteon::FanLinc::ISA = ('Insteon::DimmableLight','Insteon::DeviceController', 'Insteon::MultigroupDevice');

=item C<new()>
Expand Down Expand Up @@ -1177,6 +1181,36 @@ sub is_acknowledged
}
}

=item C<get_voice_cmds>
Returns a hash of voice commands where the key is the voice command name and the
value is the perl code to run when the voice command name is called.
Higher classes which inherit this object may add to this list of voice commands by
redefining this routine while inheriting this routine using the SUPER function.
This routine is called by L<Insteon::generate_voice_commands> to generate the
necessary voice commands.
=cut

sub get_voice_cmds
{
my ($self) = @_;
my $object_name = $self->get_object_name;
my %voice_cmds = (
%{$self->SUPER::get_voice_cmds}
);
if ($self->is_root){
%voice_cmds = (
%voice_cmds,
'sync all device links' => "$object_name->sync_all_links()",
'AUDIT sync all device links' => "$object_name->sync_all_links(1)"
);
}
return \%voice_cmds;
}

=back
=head2 AUTHOR
Expand Down
13 changes: 10 additions & 3 deletions lib/Insteon/Thermostat.pm
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ sub simple_message {
package Insteon::Thermo_i2CS;
use strict;

@Insteon::Thermo_i2CS::ISA = ('Insteon::Thermostat');
@Insteon::Thermo_i2CS::ISA = ('Insteon::Thermostat', 'Insteon::MultigroupDevice');

our %message_types = (
%Insteon::Thermostat::message_types,
Expand Down Expand Up @@ -1186,9 +1186,16 @@ sub get_voice_cmds
my ($self) = @_;
my $object_name = $self->get_object_name;
my %voice_cmds = (
%{$self->SUPER::get_voice_cmds},
'sync time' => "$object_name->sync_time()"
%{$self->SUPER::get_voice_cmds}
);
if ($self->is_root){
%voice_cmds = (
%{$self->SUPER::get_voice_cmds},
'sync time' => "$object_name->sync_time()",
'sync all device links' => "$object_name->sync_all_links()",
'AUDIT sync all device links' => "$object_name->sync_all_links(1)"
);
}
return \%voice_cmds;
}

Expand Down

0 comments on commit 72c06b8

Please sign in to comment.