diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index 378848093..0896d6798 100644 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -354,4 +354,119 @@ 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 { + 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($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); + ::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 $message = new Insteon::InsteonMessage('insteon_send', $parent, 'status_request', '03'); + $parent->_send_cmd($message); + } +} + +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 diff --git a/lib/read_table_A.pl b/lib/read_table_A.pl index 26df768a9..630ab2348 100644 --- a/lib/read_table_A.pl +++ b/lib/read_table_A.pl @@ -138,6 +138,12 @@ 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;