diff --git a/bin/mh.ini b/bin/mh.ini index 69d51a153..aa65a3df8 100644 --- a/bin/mh.ini +++ b/bin/mh.ini @@ -2058,7 +2058,7 @@ eib_errata=2 @ These are the states displayed on the tk and web menus @ French: insteon_menu_states=on,off,normal,eco,plus,moins,plus2,moins2,plus3,moins3,+40,-40,5%,30%,60%,100% -insteon_menu_states=on,off,+40,-40,5%,30%,60%,100% +insteon_menu_states=off,20%,40%,50%,60%,80%,on ****************************************************************************** # Category = Misc @@ -2451,4 +2451,4 @@ owfs_uom_temp = F # - add net parms. add cm11_serial parm. # -# \ No newline at end of file +# diff --git a/lib/Insteon.pm b/lib/Insteon.pm index eb3b59c47..799f26c3f 100755 --- a/lib/Insteon.pm +++ b/lib/Insteon.pm @@ -549,7 +549,6 @@ so that each class can have its own unique set of voice commands. sub generate_voice_commands { - my $insteon_menu_states = $main::config_parms{insteon_menu_states} if $main::config_parms{insteon_menu_states}; &main::print_log("Generating Voice commands for all Insteon objects"); my $object_string; for my $object (&main::list_all_objects) { @@ -594,8 +593,6 @@ sub generate_voice_commands $object_string .= &main::store_object_data($object_name_v, 'Voice_Cmd', 'Insteon', 'Insteon_link_commands'); push @_insteon_link, $object_name; } elsif ($object->isa('Insteon::BaseDevice')) { - $states = $insteon_menu_states if $insteon_menu_states - && ($object->can('is_dimmable') && $object->is_dimmable); my $cmd_states = "$states,status,get engine version,scan link table,log links,update onlevel/ramprate"; #,on level,ramp rate"; $cmd_states .= ",link to interface,unlink with interface" if $object->isa("Insteon::BaseController") || $object->is_controller; $object_string .= "$object_name_v = new Voice_Cmd '$command [$cmd_states]';\n"; diff --git a/lib/Insteon/BaseInsteon.pm b/lib/Insteon/BaseInsteon.pm index 3ea998f5d..4aaad4330 100644 --- a/lib/Insteon/BaseInsteon.pm +++ b/lib/Insteon/BaseInsteon.pm @@ -528,7 +528,7 @@ sub derive_message } else { if ($command eq 'on') { - $message->extra(sprintf("%02X",$level)); + $message->extra(sprintf("%02X",int($level+.5))); } else { $message->extra('00'); } @@ -594,7 +594,7 @@ sub _is_info_request my $is_info_request = 0; if ($cmd eq 'status_request') { $is_info_request++; - my $ack_on_level = (hex($msg{extra}) >= 254) ? 100 : sprintf("%d", hex($msg{extra}) * 100 / 255); + my $ack_on_level = sprintf("%d", int((hex($msg{extra}) * 100 / 255)+.5)); &::print_log("[Insteon::BaseObject] received status for " . $self->{object_name} . " with on-level: $ack_on_level%, " . "hops left: $msg{hopsleft}") if $main::Debug{insteon}; @@ -1756,33 +1756,23 @@ sub restore_string { $restore_string .= $self->_aldb->restore_string(); } - if ($$self{states}) - { - my $states = ''; - foreach my $state (@{$$self{states}}) - { - $states .= '|' if $states; - $states .= $state; - } - $restore_string .= $self->{object_name} . "->restore_states(q~$states~);\n"; - } return $restore_string; } =item C -Used to reload the persistent states of variables on restart. +Obsolete / do not use. + +Function should remain so that upgrading users will not have issues starting +MH from previous versions that referenced this function in the +mh_temp.saved_states file. =cut sub restore_states { my ($self, $states) = @_; - if ($states) - { - @{$$self{states}} = split(/\|/,$states); - } } =item C diff --git a/lib/Insteon/Lighting.pm b/lib/Insteon/Lighting.pm index c7660e965..92d69cf18 100644 --- a/lib/Insteon/Lighting.pm +++ b/lib/Insteon/Lighting.pm @@ -33,8 +33,8 @@ sub new my $self = new Insteon::BaseDevice($p_deviceid,$p_interface); bless $self,$class; - # include very basic states - @{$$self{states}} = ('on','off'); + # include very basic states; off first so web interface up/down works + $self->set_states('off','on'); return $self; } @@ -193,13 +193,7 @@ sub convert_level my $level = 'ff'; if (defined ($on_level)) { $on_level =~ s/(\d+)%?/$1/; - if ($on_level eq '100') { - $level = 'ff'; - } elsif ($on_level eq '0') { - $level = '00'; - } else { - $level = sprintf('%02X',$on_level * 2.55); - } + $level = sprintf('%02X',int(($on_level * 2.55) + .5)); } return $level; } @@ -216,6 +210,11 @@ sub new my $self = new Insteon::BaseLight($p_deviceid,$p_interface); bless $self,$class; + + if( $main::config_parms{insteon_menu_states}) { + $self->set_states(split( ',', $main::config_parms{insteon_menu_states})); + } + return $self; } diff --git a/lib/http_server.pl b/lib/http_server.pl index 9f44eb88a..4e3ff7e69 100644 --- a/lib/http_server.pl +++ b/lib/http_server.pl @@ -2367,9 +2367,7 @@ sub html_item_state { my $object_name = $object->{object_name}; my $object_name2 = &pretty_object_name($object_name); my $isa_X10 = UNIVERSAL::isa($object, 'X10_Item'); -# my $isa_X10 = $object->isa('X10_Item'); # This will abend if object is not an object my $isa_EIB2 = UNIVERSAL::isa($object, 'EIB2_Item'); - my $isa_insteon = UNIVERSAL::isa($object, 'Insteon_Device'); # If not a state item, just list it unless ($isa_X10 or UNIVERSAL::isa($object, 'Group') or exists $object->{state} or $object->{states}) { @@ -2384,9 +2382,7 @@ sub html_item_state { # If >2 possible states, add a Select pull down form my @states; @states = @{$object->{states}} if $object->{states}; -# print "db on=$object_name ix10=$isa_X10 s=@states\n"; @states = split ',', $config_parms{x10_menu_states} if $isa_X10; - @states = split ',', $config_parms{insteon_menu_states} if $isa_insteon; @states = qw(on off) if UNIVERSAL::isa($object, 'X10_Appliance'); diff --git a/web/bin/button.pl b/web/bin/button.pl index 2d779d090..9654b07b7 100644 --- a/web/bin/button.pl +++ b/web/bin/button.pl @@ -1,10 +1,15 @@ +# +# Create buttons with JPEG images generated on-the-fly using the GD module. +# +# For text buttons: +# Example: +# +# For item buttons: +# Example: +# $^W = 0; # Avoid redefined sub msgs -# Create jpeg buttons on-the-fly with GD module -# For text buttons: -# For item buttons: - # Authority: anyone my ($text, $type, $state, $bg_color, $file_name_only) = @ARGV; @@ -29,10 +34,14 @@ $image_file =~ s/ /_/g; # Blanks in file names are nasty $image_file = "/cache/$image_file.jpg"; - +# Set to 1 if you'd like to disable the image cache. Normally you should +# not need to do this because it affects performance (MisterHouse needs +# to re-generate the button image every time). This is only useful if you +# are tweaking your button images and need new images re-generated every +# time the button generation script (this script) is called. my $nocache = 0; -#$nocache = 1; -if (-e "$config_parms{data_dir}$image_file" or $nocache) { + +if (-e "$config_parms{data_dir}$image_file" && !$nocache) { return $image_file if $file_name_only; # print "Returning data from: $image_file\n"; my $data = file_read "$config_parms{data_dir}$image_file"; @@ -41,21 +50,27 @@ # Look for an icon my ($icon, $light); + if ($type eq 'item') { my $object = &get_object_by_name($text); ($icon) = &http_get_local_file(&html_find_icon_image($object, 'voice')); -# $light = 1 if $text =~ /light/i or $text =~ /lite/i; - $light = 1 if $object->isa('X10_Item') and !$object->isa('X10_Appliance'); - $light = 1 if $object->isa('EIB2_Item'); -} -else { -# Uncomment this to put in images into group, category icons. Seem too small to be useful. -# ($icon) = &http_get_local_file(&html_find_icon_image($text, 'text')); + + if ( ($object->isa('X10_Item') and !$object->isa('X10_Appliance') ) + || $object->isa('Insteon::BaseLight') + || $object->isa('EIB2_Item') + || $text =~ /light|lite/i) { + $light = 1; + } +} else { + # Uncomment this to put in images into group, category icons. Seem too small to be useful. + #($icon) = &http_get_local_file(&html_find_icon_image($text, 'text')); } + undef $icon if $icon and $icon !~ /.jpg$/i; # GD does not do gifs :( my $image_icon = GD::Image->newFromJpeg($icon) if $icon; my $image; + if ($image_icon or $type eq 'item') { # Template = blank_on/off/unk or blank_light_on/off/dim diff --git a/web/bin/button_action.pl b/web/bin/button_action.pl index 4c6fddf78..3d635755c 100644 --- a/web/bin/button_action.pl +++ b/web/bin/button_action.pl @@ -10,30 +10,62 @@ my ($state, $x, $y) = $state_xy =~ /(\S+)\?(\d+),(\d+)/; #print "db ln=$list_name, i=$item, s=$state_xy xy=$x,$y\n"; - # Do not dim the dishwasher :) -unless (eval qq|$item->isa('X10_Appliance') or $item->isa('Fan_Motor') or $item->isa('Insteon_Device')|) { - $state = 'dim' if $x < 40; # Left side of image - $state = 'brighten' if $x > 110; # Right side of image -} +my $object = &get_object_by_name($item); + +if ($object->isa('X10_Item') && !$object->isa('X10_Appliance') ) { + # Do not dim the dishwasher :) -if (eval qq|$item->isa('EIB7_Item')|) { # Motor/drive states are stop/up/down + # Dim if clicked on left side of image, brighten if clicked on right + # side of image, or use state passed through the button URL if clicked + # in the center of the image. + if ($x < 40) { + $state = 'dim'; + } elsif ($x > 110) { + $state = 'brighten'; + } +} elsif ($object->isa('EIB7_Item') ) { # Motor/drive states are stop/up/down $state = 'stop'; $state = 'down' if $x < 40; # Left side of image $state = 'up' if $x > 110; # Right side of image -} +} elsif ($object->isa('Insteon::DimmableLight') ) { + my @states = $object->get_states(); + my $curr_state = $object->state(); -#if (eval qq|$item->isa('Insteon_Device'|) { -# $state = "toggle"; -#} + # Find the index into @states for the element that corresponds to the + # current state. + my ($index) = grep { $states[$_] eq $curr_state } 0..$#states; -eval qq|$item->set("$state", 'web')|; -print "button_action.pl eval error: $@\n" if $@; + # Dim if clicked on left side of image, brighten if clicked on right + # side of image, or use state passed through the button URL if clicked + # in the center of the image. + if ($x < 40) { + $index-- if ($index); # Can't dim if light is off + $state = $states[$index]; + } elsif ($x > 110) { + $index++ if ($index != $#states); # Can't brighten if light is fully on + $state = $states[$index]; + } +} + +$object->set("$state", 'web'); # print "dbx4a i=$item s=$state\n"; # my $object = &get_object_by_name($item); # $state = $$object{state}; # print "dbx4b i=$item s=$state\n"; +# Internal state of INSTEON devices does not change immediately after +# clicking on the button. That is because, unlike X10 devices (for example), +# an acknowledgement from the INSTEON device needs to be received so MH +# can change the internal state. If we finish the HTTP transaction before +# the acknowledge comes back then the resulting HTML page will display the +# object that was just clicked on in the old state. This delay here prevents +# this problem at the expense of, well, an extra delay. As this is +# experimental, and this delay causes MH to pause for the duration of the +# delay, this is currently disabled by default. But feel free to enable +# to see if things improve. +#sleep(1); my $h = &referer("/bin/list_buttons.pl?$list_name"); + return &http_redirect($h); diff --git a/web/bin/list_buttons.pl b/web/bin/list_buttons.pl index 7bbc1c533..3dedf71f5 100644 --- a/web/bin/list_buttons.pl +++ b/web/bin/list_buttons.pl @@ -65,6 +65,8 @@ my $icon; if ($Info{module_GD}) { # Use custom icons if they exist + $state = 'on' if $state eq '100%'; + $state = 'off' if $state eq '0%'; $icon = $state; $icon = 'dim' if $state =~ /d+/; my $image = "/graphics/light-" . lc $item . "_" . $icon . ".gif";