From 43298d143b907717f2343ff41b8b0735e541d1fe Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Thu, 9 May 2013 21:53:27 -0700 Subject: [PATCH 01/15] Insteon_Remotelinc: Added Ability to Set Awake Time and To Request Battery Status The following likely only works for i2cs devices, I think all Remotelinc 2 devices are i2cs? It at least works on rev 1.4. - set_awake_time sets = sets the time in seconds that the remote will remain awake after sending a command. The default is 4, it can be set up to 254 seconds, with 255 being always awake. - get_extended_info = is primarily added to get the battery level. Battery level is returned as a byte, but the number does not immediately make sense. I will have to let the batter run down some to better understand what it means. At the moment, I have the code set to call get_extended_info whenever the all_link_report is received. This report represents the last message sent by the device before the awake time begins to run. In the future, an additional function can be added to only call get_extended_info if it hasn't been called in x hours. N.B. in order for set_awake_time to work properly, the engine version of the device must be known. hollie/misterhouse#172 --- lib/Insteon/Controller.pm | 62 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 45b77b9ad..263d96f28 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -9,7 +9,8 @@ use Insteon::BaseInsteon; my %message_types = ( %Insteon::BaseDevice::message_types, bright => 0x15, - dim => 0x16 + dim => 0x16, + extended_set_get => 0x2e ); sub new @@ -49,6 +50,65 @@ sub set return; } +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; +} + +sub get_extended_info { + my ($self) = @_; + 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); + $root->_send_cmd($message); + return; +} + +sub _process_message { + my ($self,$p_setby,%msg) = @_; + my $clear_message = 0; + if ($msg{command} eq 'link_cleanup_report'){ + #Queue an get_extended_info request + $self->get_extended_info(); + } + if ($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::RemoteLinc] 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::RemoteLinc] 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}); + #D10 = Battery; + main::print_log("[Insteon::RemoteLinc] The battery level ". + "for device ". $self->get_object_name . " is: ". + hex(substr($msg{extra}, 20, 2))); + $clear_message = 1; + $self->_process_command_stack(%msg); + } else { + main::print_log("[Insteon::RemoteLinc] 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; From 970c3343bc0643433ecf3da2d388e93403b1c70a Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:35:25 -0700 Subject: [PATCH 02/15] Insteon_RemoteLinc: Add Perl Documentation --- lib/Insteon/Controller.pm | 101 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 263d96f28..dc5e8d0ca 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -1,3 +1,52 @@ +=head1 B + +=head2 SYNOPSIS + +Configuration: + +Depending on your device and your settings, your remote may offer 1, 4, or 8 +groups. Your configuration should vary depeninding on you remote style. + +In user code: + + use Insteon::RemoteLinc; + $remote_1 = new Insteon::RemoteLinc('12.34.56:01',$myPLM); + $remote_2 = new Insteon::RemoteLinc('12.34.56:02',$myPLM); + $remote_3 = new Insteon::RemoteLinc('12.34.56:03',$myPLM); + $remote_4 = new Insteon::RemoteLinc('12.34.56:04',$myPLM); + +In items.mht: + + INSTEON_REMOTELINC, 12.34.56:01, $remote_1, $remote_group + INSTEON_REMOTELINC, 12.34.56:02, $remote_2, $remote_group + INSTEON_REMOTELINC, 12.34.56:03, $remote_3, $remote_group + INSTEON_REMOTELINC, 12.34.56:04, $remote_4, $remote_group + +=head2 DESCRIPTION + +Provides basic support for Insteon RemoteLinc models 1 and 2. Basic support +includes, linking and receiving set commands from the device. More advanced +support is offered for RemoteLinc 2 in the form of battery level notifications. + +MisterHouse is only able to communicate with a RemoteLinc when it is in "awake +mode." The device is in "awake mode" while in its linking state. To put the +RemoteLinc into "awake mode", follow the instructions for placing the device into +linking mode. In short, the instructions are to hold down the set button for 4-10 +seconds until you hear a beep and see the light flash. The RemoteLinc will now +remain in "awake mode" for approximately 4 minutes. + +To scan the link table, sync links, or set settings on the device, the RemoteLinc +must first be put into "awake mode." + +=head2 INHERITS + +B, B + +=head2 METHODS + +=over + +=cut package Insteon::RemoteLinc; @@ -50,6 +99,21 @@ sub set return; } +=item C + +Only available for RemoteLinc 2 models. + +Sets the amount of time, in seconds, that the RemoteLinc will remain "awake" +after sending a command. MH uses the awake time to send batter level requests +to the device. If the device is not responding to the battery level requests, +consider increasing this value. However, keep in mind that a longer awake time +will result in more battery usage. + +The factory setting is 4 seconds, 10 seconds seems to work with MisterHouse +without causing adverse battery drain. + +=cut + sub set_awake_time { my ($self, $awake) = @_; $awake = sprintf("%02x", $awake); @@ -61,6 +125,20 @@ sub set_awake_time { return; } +=item C + +Only available for RemoteLinc 2 models. + +Requests the status of various settings on the device. Currently this is only +used to obtain the battery level. If the device is awake, the battery level +will be printed to the log. + +You likely do not need to directly call this message, rather MisterHouse will issue +this request when it sees activity from the device and the C has +expired. + +=cut + sub get_extended_info { my ($self) = @_; my $root = $self->get_root(); @@ -114,4 +192,27 @@ sub is_responder return 0; } +=back + +=head2 INI PARAMETERS + +None. + +=head2 AUTHOR + +Bruce Winter, Gregg Limming, Kevin Robert Keegan + +=head2 SEE ALSO + + + +=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 \ No newline at end of file From b89d698bfe9d6b3eaf406ddbb2e1bdbce5bbeccc Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:39:25 -0700 Subject: [PATCH 03/15] Insteon_RemoteLinc: Add Set Battery Timer --- lib/Insteon/Controller.pm | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index dc5e8d0ca..06eda228f 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -68,6 +68,9 @@ sub new my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); $$self{message_types} = \%message_types; + if ($self->is_root){ + $self->restore_data('battery_timer', 'last_battery_time'); + } bless $self,$class; return $self; } @@ -104,7 +107,7 @@ sub set Only available for RemoteLinc 2 models. Sets the amount of time, in seconds, that the RemoteLinc will remain "awake" -after sending a command. MH uses the awake time to send batter level requests +after sending a command. MH uses the awake time to send battery level requests to the device. If the device is not responding to the battery level requests, consider increasing this value. However, keep in mind that a longer awake time will result in more battery usage. @@ -134,7 +137,7 @@ used to obtain the battery level. If the device is awake, the battery level will be printed to the log. You likely do not need to directly call this message, rather MisterHouse will issue -this request when it sees activity from the device and the C has +this request when it sees activity from the device and the C has expired. =cut @@ -149,6 +152,27 @@ sub get_extended_info { return; } +=item C + +Only available for RemoteLinc 2 models. + +Sets the minimum amount of time between battery level requests. When this time +expires, Misterhouse will request the battery level from the device the next time +MisterHouse sees activity from the device. Misterhouse will continue to request +the battery level until it gets a response from the device. + +This setting will be saved between MisterHouse reboots. + +=cut + +sub set_battery_timer { + my ($self, $minutes) = @_; + my $root = $self->get_root(); + $$root{battery_timer} = $minutes; + ::print_log("[Insteon::RemoteLinc] Set battery timer to $minutes minutes"); + return; +} + sub _process_message { my ($self,$p_setby,%msg) = @_; my $clear_message = 0; From c2fb74cf998c4be15156754b729fd68fd81c08ca Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:41:25 -0700 Subject: [PATCH 04/15] Insteon_RemoteLinc: Add Check for If Battery Timer Expired --- lib/Insteon/Controller.pm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 06eda228f..6ca200100 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -173,10 +173,20 @@ sub set_battery_timer { return; } +sub _is_battery_time_expired { + my ($self) = @_; + my $root = $self->get_root(); + if (defined $$root{battery_timer} && + (time - ($$root{last_battery_time} * 60)) > $$root{battery_timer}) { + return 1; + } + return 0; +} + sub _process_message { my ($self,$p_setby,%msg) = @_; my $clear_message = 0; - if ($msg{command} eq 'link_cleanup_report'){ + if ($msg{command} eq 'link_cleanup_report' && $self->_is_battery_time_expired){ #Queue an get_extended_info request $self->get_extended_info(); } From 42ec1da33e92b7f9726716da7809f0bfebe5ee2c Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:41:25 -0700 Subject: [PATCH 05/15] Insteon_RemoteLinc: Cleanup Battery Timer --- lib/Insteon/Controller.pm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 6ca200100..1f4914e3d 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -161,6 +161,8 @@ expires, Misterhouse will request the battery level from the device the next tim MisterHouse sees activity from the device. Misterhouse will continue to request the battery level until it gets a response from the device. +Setting to 0 will disable automatic battery level requests. + This setting will be saved between MisterHouse reboots. =cut @@ -168,15 +170,16 @@ This setting will be saved between MisterHouse reboots. sub set_battery_timer { my ($self, $minutes) = @_; my $root = $self->get_root(); - $$root{battery_timer} = $minutes; - ::print_log("[Insteon::RemoteLinc] Set battery timer to $minutes minutes"); + $$root{battery_timer} = sprintf("%u", $minutes); + ::print_log("[Insteon::RemoteLinc] Set battery timer to ". + $$root{battery_timer}." minutes"); return; } sub _is_battery_time_expired { my ($self) = @_; my $root = $self->get_root(); - if (defined $$root{battery_timer} && + if ($$root{battery_timer} > 0 && (time - ($$root{last_battery_time} * 60)) > $$root{battery_timer}) { return 1; } From 05e702f0af8de8c9ad574b74d32509d3ba63095f Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:45:25 -0700 Subject: [PATCH 06/15] Insteon_RemoteLinc: Add the Low Battery Level Indicator --- lib/Insteon/Controller.pm | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 1f4914e3d..fac8a93e5 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -69,7 +69,7 @@ sub new my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); $$self{message_types} = \%message_types; if ($self->is_root){ - $self->restore_data('battery_timer', 'last_battery_time'); + $self->restore_data('battery_timer', 'last_battery_time', 'low_battery_level'); } bless $self,$class; return $self; @@ -161,7 +161,7 @@ expires, Misterhouse will request the battery level from the device the next tim MisterHouse sees activity from the device. Misterhouse will continue to request the battery level until it gets a response from the device. -Setting to 0 will disable automatic battery level requests. +Setting to 0 will disable automatic battery level requests. 1440 equals a day. This setting will be saved between MisterHouse reboots. @@ -176,6 +176,25 @@ sub set_battery_timer { return; } +=item C + +Only available for RemoteLinc 2 models. + +If the battery level falls below this percentage, the C +command is run. + +=cut + +sub set_low_battery_level { + my ($self, $level) = @_; + $level =~ s/(\d+)%?/$1/; + my $root = $self->get_root(); + $$root{low_battery_level} = sprintf("%u", $level); + ::print_log("[Insteon::RemoteLinc] Set low battery level to ". + $$root{low_battery_level}."%"); + return; +} + sub _is_battery_time_expired { my ($self) = @_; my $root = $self->get_root(); From d3d70f54d9e1f034bc9f01bc42a03c9cfbcdec81 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:45:25 -0700 Subject: [PATCH 07/15] Insteon_RemoteLinc: Add Set Low Battery Event --- lib/Insteon/Controller.pm | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index fac8a93e5..561ddd8af 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -183,6 +183,8 @@ Only available for RemoteLinc 2 models. If the battery level falls below this percentage, the C command is run. +This setting will be saved between MisterHouse reboots. + =cut sub set_low_battery_level { @@ -195,6 +197,30 @@ sub set_low_battery_level { return; } +=item C + +Only available for RemoteLinc 2 models. + +If the battery level falls below the percentage defined by C +this command is evaluated. Works very similar to a C +eval. + +Example: + + $remote->battery_low_event('speak "Warning, Remote battery is low."'); + +This setting will be saved between MisterHouse reboots. + +=cut + +sub battery_low_event { + my ($self, $eval) = @_; + my $root = $self->get_root(); + $$root{low_battery_event} = $eval; + ::print_log("[Insteon::RemoteLinc] Set low battery event."); + return; +} + sub _is_battery_time_expired { my ($self) = @_; my $root = $self->get_root(); From 78db98be6684f4e571697e318d6d3731a5ffc3c0 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:55:25 -0700 Subject: [PATCH 08/15] Insteon_RemoteLinc: Add Eval to Battery Low Level Event --- lib/Insteon/Controller.pm | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 561ddd8af..952479ab9 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -69,7 +69,8 @@ sub new my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); $$self{message_types} = \%message_types; if ($self->is_root){ - $self->restore_data('battery_timer', 'last_battery_time', 'low_battery_level'); + $self->restore_data('battery_timer', 'last_battery_time', + 'low_battery_level', 'low_battery_event'); } bless $self,$class; return $self; @@ -183,6 +184,8 @@ Only available for RemoteLinc 2 models. If the battery level falls below this percentage, the C command is run. +Setting to 0 will prevent any low battery events from occuring. + This setting will be saved between MisterHouse reboots. =cut @@ -209,6 +212,8 @@ Example: $remote->battery_low_event('speak "Warning, Remote battery is low."'); +See C for more examples. + This setting will be saved between MisterHouse reboots. =cut @@ -231,9 +236,20 @@ sub _is_battery_time_expired { return 0; } +sub _is_battery_low { + my ($self, $percent) = @_; + my $root = $self->get_root(); + if ($$root{low_battery_level} > 0 && + ($$root{low_battery_level} > $percent)) { + return 1; + } + return 0; +} + sub _process_message { my ($self,$p_setby,%msg) = @_; my $clear_message = 0; + my $root = $self->get_root(); if ($msg{command} eq 'link_cleanup_report' && $self->_is_battery_time_expired){ #Queue an get_extended_info request $self->get_extended_info(); @@ -252,10 +268,18 @@ sub _process_message { 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}); - #D10 = Battery; + #D10 = Battery; + my $percent = hex(substr($msg{extra}, 20, 2)); main::print_log("[Insteon::RemoteLinc] The battery level ". "for device ". $self->get_object_name . " is: ". - hex(substr($msg{extra}, 20, 2))); + $percent . "%"); + if ($self->_is_battery_low){ + package main; + eval $$root{low_battery_event}; + ::print_log("[Insteon::RemoteLinc] " . $self->{device}->get_object_name . ": error during low battery event eval $@") + if $@; + package Insteon::RemoteLinc; + } $clear_message = 1; $self->_process_command_stack(%msg); } else { From 2f14a4b8d24ddc86c137919408e7ac87ac8cc100 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 10 May 2013 18:56:44 -0700 Subject: [PATCH 09/15] Insteon_Remotelinc: Change Battery Level to Volts; Cleanup Coding Errors I think that the battery level is reported is volts * 50. Online it lists the battery voltage as 3.7 and I am getting numbers like 177 right now. Finally, one stray comment from Insteon suggested that they believe 0xA3 or 163 to be the low voltage warning level. --- lib/Insteon/Controller.pm | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 952479ab9..537273afd 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -177,14 +177,15 @@ sub set_battery_timer { return; } -=item C +=item C Only available for RemoteLinc 2 models. -If the battery level falls below this percentage, the C -command is run. +If the battery level falls below this voltage, the C +command is run. The theoretical maximum voltage of the battery is 3.70 volts. +The recommended low battery setting by Insteon is 3.26 volts. -Setting to 0 will prevent any low battery events from occuring. +Setting to 0 will prevent any low battery events from occuring. This setting will be saved between MisterHouse reboots. @@ -192,11 +193,10 @@ This setting will be saved between MisterHouse reboots. sub set_low_battery_level { my ($self, $level) = @_; - $level =~ s/(\d+)%?/$1/; my $root = $self->get_root(); - $$root{low_battery_level} = sprintf("%u", $level); + $$root{low_battery_level} = sprintf("%.2f", $level); ::print_log("[Insteon::RemoteLinc] Set low battery level to ". - $$root{low_battery_level}."%"); + $$root{low_battery_level}." volts."); return; } @@ -230,17 +230,17 @@ sub _is_battery_time_expired { my ($self) = @_; my $root = $self->get_root(); if ($$root{battery_timer} > 0 && - (time - ($$root{last_battery_time} * 60)) > $$root{battery_timer}) { + (time - $$root{last_battery_time}) > ($$root{battery_timer} * 60)) { return 1; } return 0; } sub _is_battery_low { - my ($self, $percent) = @_; + my ($self, $voltage) = @_; my $root = $self->get_root(); if ($$root{low_battery_level} > 0 && - ($$root{low_battery_level} > $percent)) { + ($$root{low_battery_level} > $voltage)) { return 1; } return 0; @@ -269,11 +269,14 @@ sub _process_message { if (substr($msg{extra},0,6) eq "000001") { $self->default_hop_count($msg{maxhops}-$msg{hopsleft}); #D10 = Battery; - my $percent = hex(substr($msg{extra}, 20, 2)); + my $voltage = (hex(substr($msg{extra}, 20, 2))/50); main::print_log("[Insteon::RemoteLinc] The battery level ". "for device ". $self->get_object_name . " is: ". - $percent . "%"); - if ($self->_is_battery_low){ + $voltage . " of 3.70 volts."); + $$root{last_battery_time} = time; + if ($self->_is_battery_low($voltage)){ + main::print_log("[Insteon::RemoteLinc] The battery level ". + "is below the set threshold running low battery event."); package main; eval $$root{low_battery_event}; ::print_log("[Insteon::RemoteLinc] " . $self->{device}->get_object_name . ": error during low battery event eval $@") From d77f0373d856611ecd74391573db2c755f6a014e Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sat, 11 May 2013 09:18:19 -0700 Subject: [PATCH 10/15] Insteon_RemoteLinc: Add RemoteLinc_Battery Object This is a generic object that is "tied" to the battery events in the parent RemoteLinc. It can be used to display the battery voltage on the RemoteLinc on the MH web page or to directly tie events to rather than using the low_battery_event code. --- lib/Insteon/Controller.pm | 65 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 537273afd..c52f30784 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -183,7 +183,8 @@ Only available for RemoteLinc 2 models. If the battery level falls below this voltage, the C command is run. The theoretical maximum voltage of the battery is 3.70 volts. -The recommended low battery setting by Insteon is 3.26 volts. +Although practical experience shows it to be closer to 3.65 volts. The +recommended low battery setting by Insteon is 3.26 volts. Setting to 0 will prevent any low battery events from occuring. @@ -274,6 +275,10 @@ sub _process_message { "for device ". $self->get_object_name . " is: ". $voltage . " of 3.70 volts."); $$root{last_battery_time} = time; + if (ref $$root{battery_object} && $$root{battery_object}->can('set_receive')) + { + $$root{battery_object}->set_receive($voltage, $root); + } if ($self->_is_battery_low($voltage)){ main::print_log("[Insteon::RemoteLinc] The battery level ". "is below the set threshold running low battery event."); @@ -303,6 +308,64 @@ sub is_responder =back +=head1 B + +=head2 SYNOPSIS + +Configuration: + +Currently the object can only be defined in the user code. + +In user code: + + use Insteon::RemoteLinc_Battery; + $remote_battery = new Insteon::RemoteLinc_Battery($remote); + +Where $remote is the RemoteLinc device you wish to monitor. + +=head2 DESCRIPTION + +This basic class creates a simple object that displays the current battery voltage +as its state. This is helpful if you want to be able to view the battery level +through a web page. Battery level tracking is likely only available on RemoteLinc 2 +devices. + +This objects state will be updated based on interval defined for C +in the parent B object. + +Once created, you can tie_events directly to this object rather than using the +battery_low_event code in the parent B object. + +=head2 INHERITS + +B + +=head2 METHODS + +=over + +=cut + +package Insteon::RemoteLinc_Battery; +use strict; + +@Insteon::RemoteLinc_Battery::ISA = ('Generic_Item'); + +sub new { + my ($class, $parent) = @_; + my $self = new Generic_Item(); + bless $self, $class; + $$parent{battery_object} = $self; + return $self; +} + +sub set_receive { + my ($self, $p_state) = @_; + $self->SUPER::set($p_state); +} + +=back + =head2 INI PARAMETERS None. From 58dffe58b406907439d1c87b3ee9201cdfdf9eae Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Sat, 11 May 2013 09:29:50 -0700 Subject: [PATCH 11/15] Insteon_RemoteLinc: Make Battery Parent is the Root Item --- lib/Insteon/Controller.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index c52f30784..cbde9353a 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -354,8 +354,9 @@ use strict; sub new { my ($class, $parent) = @_; my $self = new Generic_Item(); + my $root = $parent->get_root(); bless $self, $class; - $$parent{battery_object} = $self; + $$root{battery_object} = $self; return $self; } From 2e2079f06eb30a40a8b7bdab65f601f3f1b47370 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Wed, 15 May 2013 20:07:45 -0700 Subject: [PATCH 12/15] Insteon_RemoteLinc: Remove Low Battery and Event Routines No need to reinvent the wheel, low batter events can be tracked using the child objects and tied events --- lib/Insteon/Controller.pm | 73 +++++---------------------------------- 1 file changed, 9 insertions(+), 64 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index cbde9353a..af2c7cab6 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -69,8 +69,8 @@ sub new my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); $$self{message_types} = \%message_types; if ($self->is_root){ - $self->restore_data('battery_timer', 'last_battery_time', - 'low_battery_level', 'low_battery_event'); + $self->restore_data('battery_timer', 'last_battery_time'); + $$self{queue_timer} = new Timer; } bless $self,$class; return $self; @@ -177,56 +177,6 @@ sub set_battery_timer { return; } -=item C - -Only available for RemoteLinc 2 models. - -If the battery level falls below this voltage, the C -command is run. The theoretical maximum voltage of the battery is 3.70 volts. -Although practical experience shows it to be closer to 3.65 volts. The -recommended low battery setting by Insteon is 3.26 volts. - -Setting to 0 will prevent any low battery events from occuring. - -This setting will be saved between MisterHouse reboots. - -=cut - -sub set_low_battery_level { - my ($self, $level) = @_; - my $root = $self->get_root(); - $$root{low_battery_level} = sprintf("%.2f", $level); - ::print_log("[Insteon::RemoteLinc] Set low battery level to ". - $$root{low_battery_level}." volts."); - return; -} - -=item C - -Only available for RemoteLinc 2 models. - -If the battery level falls below the percentage defined by C -this command is evaluated. Works very similar to a C -eval. - -Example: - - $remote->battery_low_event('speak "Warning, Remote battery is low."'); - -See C for more examples. - -This setting will be saved between MisterHouse reboots. - -=cut - -sub battery_low_event { - my ($self, $eval) = @_; - my $root = $self->get_root(); - $$root{low_battery_event} = $eval; - ::print_log("[Insteon::RemoteLinc] Set low battery event."); - return; -} - sub _is_battery_time_expired { my ($self) = @_; my $root = $self->get_root(); @@ -237,23 +187,18 @@ sub _is_battery_time_expired { return 0; } -sub _is_battery_low { - my ($self, $voltage) = @_; - my $root = $self->get_root(); - if ($$root{low_battery_level} > 0 && - ($$root{low_battery_level} > $voltage)) { - return 1; - } - return 0; -} - sub _process_message { my ($self,$p_setby,%msg) = @_; my $clear_message = 0; my $root = $self->get_root(); - if ($msg{command} eq 'link_cleanup_report' && $self->_is_battery_time_expired){ + if ($root->_is_battery_time_expired){ #Queue an get_extended_info request - $self->get_extended_info(); + if ($$root{queue_timer}->active){ + $$root{queue_timer}-restart(); + } + else { + $$root{queue_timer}->set(3, '$root->get_extended_info()'); + } } if ($msg{command} eq "extended_set_get" && $msg{is_ack}){ $self->default_hop_count($msg{maxhops}-$msg{hopsleft}); From ed84054c6335aa8a736a04deef066c4eca649a57 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Thu, 23 May 2013 20:59:25 -0700 Subject: [PATCH 13/15] Insteon_RemoteLinc: Fix Typos --- lib/Insteon/Controller.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index af2c7cab6..3fcaf60d2 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -17,10 +17,10 @@ In user code: In items.mht: - INSTEON_REMOTELINC, 12.34.56:01, $remote_1, $remote_group - INSTEON_REMOTELINC, 12.34.56:02, $remote_2, $remote_group - INSTEON_REMOTELINC, 12.34.56:03, $remote_3, $remote_group - INSTEON_REMOTELINC, 12.34.56:04, $remote_4, $remote_group + INSTEON_REMOTELINC, 12.34.56:01, remote_1, remote_group + INSTEON_REMOTELINC, 12.34.56:02, remote_2, remote_group + INSTEON_REMOTELINC, 12.34.56:03, remote_3, remote_group + INSTEON_REMOTELINC, 12.34.56:04, remote_4, remote_group =head2 DESCRIPTION From 2f18a353ee015d50891ce31759ff0d91fee87ba3 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Thu, 23 May 2013 21:01:43 -0700 Subject: [PATCH 14/15] Insteon_RemoteLinc: Only Send Battery Request Once If the device doesn't hear the first request, it won't be awake to hear subsequent ones. Sending subsequent messages only slows things down. --- lib/Insteon/Controller.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index 3fcaf60d2..cb87d19f8 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -144,11 +144,14 @@ expired. =cut sub get_extended_info { - my ($self) = @_; + 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; } @@ -197,7 +200,7 @@ sub _process_message { $$root{queue_timer}-restart(); } else { - $$root{queue_timer}->set(3, '$root->get_extended_info()'); + $$root{queue_timer}->set(3, '$root->get_extended_info(1)'); } } if ($msg{command} eq "extended_set_get" && $msg{is_ack}){ From 43f3030477d4d20c4f99d1d8da3b0ab01c5b94e7 Mon Sep 17 00:00:00 2001 From: KRKeegan Date: Fri, 31 May 2013 18:57:01 -0700 Subject: [PATCH 15/15] Insteon_RemoteLinc: Cleanup Documentation --- lib/Insteon/Controller.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Insteon/Controller.pm b/lib/Insteon/Controller.pm index cb87d19f8..bc005176a 100755 --- a/lib/Insteon/Controller.pm +++ b/lib/Insteon/Controller.pm @@ -113,7 +113,7 @@ to the device. If the device is not responding to the battery level requests, consider increasing this value. However, keep in mind that a longer awake time will result in more battery usage. -The factory setting is 4 seconds, 10 seconds seems to work with MisterHouse +The factory setting is 4 seconds, 10 seconds seems to work well with MisterHouse without causing adverse battery drain. =cut @@ -278,11 +278,11 @@ as its state. This is helpful if you want to be able to view the battery level through a web page. Battery level tracking is likely only available on RemoteLinc 2 devices. -This objects state will be updated based on interval defined for C +This object's state will be updated based on interval defined for C in the parent B object. -Once created, you can tie_events directly to this object rather than using the -battery_low_event code in the parent B object. +Once created, you can tie_events directly to this object, for example to alert +you when the battery is low. =head2 INHERITS