From f2c7945ee64718cd972ba10ccb575c972d4908d1 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Thu, 2 May 2013 21:28:21 -0700 Subject: [PATCH 1/6] Insteon_FanLinc: Initial Code --- lib/Insteon/Lighting.pm | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index 378848093..42b11df35 100755 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -354,4 +354,35 @@ sub set } +package Insteon::FanLinc; + +use strict; +use Insteon::BaseInsteon; + +@Insteon::FanLinc::ISA = ('Insteon::DimmableLight','Insteon::DeviceController'); + +sub new +{ + my ($class,$p_deviceid,$p_interface) = @_; + my $self = new Insteon::DimmableLight($p_deviceid,$p_interface); + bless $self,$class; + return $self; +} + +sub set +{ + my ($self, $p_state, $p_setby, $p_respond) = @_; + if ($self->is_root()){ + return $self->Insteon::DeviceController::set($p_state, $p_setby, $p_respond); + } else { + my $parent = $self->get_root(); + #$$parent{child_status_request_pending} = $self->group; + #$$self{m_status_request_pending} = ($requestor) ? $requestor : 1; + my $extra = $p_state ."0200000000000000000000000000"; + ### need to convert $p_state to hexedecimal ### + my $message = new Insteon::InsteonMessage('insteon_ext_send', $parent, 'on', $extra); + $parent->_send_cmd($message); + } +} + 1 \ No newline at end of file From 618df2194202972a4d1c44438f8351efde130099 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sun, 3 Mar 2013 18:55:25 -0700 Subject: [PATCH 2/6] Insteon_FanLinc: Add FanLinc to Read Table A --- lib/read_table_A.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/read_table_A.pl b/lib/read_table_A.pl index 26df768a9..d47466fc3 100644 --- a/lib/read_table_A.pl +++ b/lib/read_table_A.pl @@ -138,6 +138,11 @@ sub read_table_A { $other = join ', ', (map {"'$_'"} @other); # Quote data $object = "Insteon::MotionSensor(\'$address\', $other)"; } + elsif($type eq "INSTEON_FANLINC") { + require Insteon::Lighting; + ($address, $name, $grouplist, @other) = @item_info; + $other = join ', ', (map {"'$_'"} @other); # Quote data + $object = "Insteon::FanLinc(\'$address\', $other)"; elsif($type eq "INSTEON_ICONTROLLER") { require Insteon::BaseInsteon; ($address, $name, $grouplist, @other) = @item_info; From 6e6b1b51f296f3fc58237eddc95aeb54d588c97e Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sun, 3 Mar 2013 18:55:25 -0700 Subject: [PATCH 3/6] Insteon_FanLinc: Add Complex Set Routine for Fan A little bit of rebuilding the wheel here. There was no way to seperate out the set command in BaseObject to accomplish what we needed. --- lib/Insteon/Lighting.pm | 52 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index 42b11df35..5862b87ea 100755 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -375,12 +375,54 @@ sub set if ($self->is_root()){ return $self->Insteon::DeviceController::set($p_state, $p_setby, $p_respond); } else { + if ($self->_is_valid_state($p_state)) { + # always reset the is_locally_set property unless set_by is the device + $$self{m_is_locally_set} = 0 unless ref $p_setby and $p_setby eq $self; + + # handle invalid state for non-dimmable devices + my $level = $p_state; + if ($p_state eq 'dim' or $p_state eq 'bright') { + $p_state = 'on'; + } + elsif ($p_state eq 'toggle') + { + $p_state = 'off' if ($self->state eq 'on'); + $p_state = 'on' if ($self->state eq 'off'); + } + $level = '00' if ($p_state eq 'off'); + $level = 'ff' if ($p_state eq 'on'); + # Setting Fan Level + my $setby_name = $p_setby; + $setby_name = $p_setby->get_object_name() if (ref $p_setby and $p_setby->can('get_object_name')); + my $parent = $self->get_root(); + $level = ::Insteon::DimmableLight::convert_level($p_state) if ($p_state ne '00' && $p_state ne 'ff'); + my $extra = $level ."0200000000000000000000000000"; + my $message = new Insteon::InsteonMessage('insteon_ext_send', $parent, 'on', $extra); + $parent->_send_cmd($message); + ::print_log("[Insteon::FanLinc] " . $self->get_object_name() . "::set($p_state, $setby_name)") + if $main::Debug{insteon}; + $self->is_acknowledged(0); + $$self{pending_state} = $p_state; + $$self{pending_setby} = $p_setby; + $$self{pending_response} = $p_respond; + $$parent{child_pending_state} = $self->group(); + } else { + ::print_log("[Insteon::FanLinc] failed state validation with state=$p_state"); + } + } +} + +sub request_status +{ + my ($self,$requestor) = @_; + if ($self->is_root()){ + return $self->SUPER::request_status($requestor); + } else { + # Setting Fan Level my $parent = $self->get_root(); - #$$parent{child_status_request_pending} = $self->group; - #$$self{m_status_request_pending} = ($requestor) ? $requestor : 1; - my $extra = $p_state ."0200000000000000000000000000"; - ### need to convert $p_state to hexedecimal ### - my $message = new Insteon::InsteonMessage('insteon_ext_send', $parent, 'on', $extra); + $$parent{child_status_request_pending} = $self->group; + $$self{m_status_request_pending} = ($requestor) ? $requestor : 1; + my $message = new Insteon::InsteonMessage('insteon_send', $parent, 'status_request', '03'); $parent->_send_cmd($message); } } From d52aa545be43e206898dc206db73d1fa231d4abb Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sun, 3 Mar 2013 18:55:25 -0700 Subject: [PATCH 4/6] Insteon_FanLinc: Add Function to Catch and Process Ack for Fan Again, a bit of rebuilding the wheel. But need to catch a message destined for the parent item and use it to update the child. --- lib/Insteon/Lighting.pm | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index 5862b87ea..7b958f2f8 100755 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -427,4 +427,46 @@ sub request_status } } +sub _is_info_request +{ + my ($self, $cmd, $ack_setby, %msg) = @_; + my $is_info_request = 0; + my $parent = $self->get_root(); + if ($$parent{child_status_request_pending}) { + $is_info_request++; + my $child_obj = Insteon::get_object($self->device_id, '02'); + my $child_state = &Insteon::BaseObject::derive_link_state(hex($msg{extra})); + &::print_log("[Insteon::FanLinc] received status for " . + $child_obj->{object_name} . " of: $child_state " + . "hops left: $msg{hopsleft}") if $main::Debug{insteon}; + $ack_setby = $$child_obj{m_status_request_pending} if ref $$child_obj{m_status_request_pending}; + $child_obj->SUPER::set($child_state, $ack_setby); + delete($$parent{child_status_request_pending}); + } else { + $is_info_request = $self->SUPER::_is_info_request($cmd, $ack_setby, %msg); + } + return $is_info_request; +} + +sub is_acknowledged +{ + my ($self, $p_ack) = @_; + my $parent = $self->get_root(); + if ($p_ack && $$parent{child_pending_state}) + { + my $child_obj = Insteon::get_object($self->device_id, '02'); + $child_obj->set_receive($$child_obj{pending_state},$$child_obj{pending_setby}, $$child_obj{pending_response}) if defined $$child_obj{pending_state}; + $$child_obj{is_acknowledged} = $p_ack; + $$child_obj{pending_state} = undef; + $$child_obj{pending_setby} = undef; + $$child_obj{pending_response} = undef; + $$parent{child_pending_state} = undef; + &::print_log("[Insteon::FanLinc] received command/state acknowledge from " . $child_obj->{object_name}) if $main::Debug{insteon}; + return $$self{is_acknowledged}; + } else { + return $self->SUPER::is_acknowledged($p_ack); + } +} + + 1 \ No newline at end of file From 3a1dd7bf27f070c85a964cd4907b1b82660bbaba Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sun, 3 Mar 2013 18:55:25 -0700 Subject: [PATCH 5/6] Insteon_FanLinc: Fix Typo in Read Table A --- lib/read_table_A.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/read_table_A.pl b/lib/read_table_A.pl index d47466fc3..630ab2348 100644 --- a/lib/read_table_A.pl +++ b/lib/read_table_A.pl @@ -143,6 +143,7 @@ sub read_table_A { ($address, $name, $grouplist, @other) = @item_info; $other = join ', ', (map {"'$_'"} @other); # Quote data $object = "Insteon::FanLinc(\'$address\', $other)"; + } elsif($type eq "INSTEON_ICONTROLLER") { require Insteon::BaseInsteon; ($address, $name, $grouplist, @other) = @item_info; From 2660b55209b5fe58b1f30bd85309fac9424d8e25 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Tue, 7 May 2013 18:15:25 -0700 Subject: [PATCH 6/6] Insteon_FanLinc: Fix Level Error in Child Set Command Was incorrectly calling convert_level on a bad value --- lib/Insteon/Lighting.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index 7b958f2f8..0896d6798 100755 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -395,7 +395,7 @@ sub set my $setby_name = $p_setby; $setby_name = $p_setby->get_object_name() if (ref $p_setby and $p_setby->can('get_object_name')); my $parent = $self->get_root(); - $level = ::Insteon::DimmableLight::convert_level($p_state) if ($p_state ne '00' && $p_state ne 'ff'); + $level = ::Insteon::DimmableLight::convert_level($level) if ($level ne '00' && $level ne 'ff'); my $extra = $level ."0200000000000000000000000000"; my $message = new Insteon::InsteonMessage('insteon_ext_send', $parent, 'on', $extra); $parent->_send_cmd($message);