From f32028a923304d4c959cd75e0523270fe524da62 Mon Sep 17 00:00:00 2001 From: "H.Plato" Date: Tue, 5 Sep 2017 21:43:34 -0600 Subject: [PATCH 1/5] v1.0.15 - fixed voice commands at reload --- lib/Nanoleaf_Aurora.pm | 81 ++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/lib/Nanoleaf_Aurora.pm b/lib/Nanoleaf_Aurora.pm index 9419ad762..149ebb5ae 100644 --- a/lib/Nanoleaf_Aurora.pm +++ b/lib/Nanoleaf_Aurora.pm @@ -3,7 +3,7 @@ package Nanoleaf_Aurora; #todo if poll queue exceeds 3, then just empty the queue #print and purge the command queue -# v1.0.14 +# v1.0.15 #if any effect is changed, by definition the static child should be set to off. #cmd data returns, need to check by command @@ -125,7 +125,7 @@ sub new { $self->{updating} = 0; $self->{data}->{retry} = 0; $self->{status} = ""; - $self->{module_version} = "v1.0.14"; + $self->{module_version} = "v1.0.15"; $self->{ssdp_timeout} = 4000; $self->{last_static} = ""; @@ -163,6 +163,7 @@ sub new { unlink "$::config_parms{data_dir}/Auroroa_cmd_" . $self->{name} . ".data"; $self->{cmd_process} = new Process_Item; $self->{cmd_process}->set_output( $self->{cmd_data_file} ); + $self->{generate_voice_cmds} = 0; &::MainLoop_post_add_hook( \&Nanoleaf_Aurora::process_check, 0, $self ); &::Reload_post_add_hook( \&Nanoleaf_Aurora::generate_voice_commands, 1, $self ); $self->get_data(); @@ -440,7 +441,8 @@ sub process_check { } else { - main::print_log( "[Aurora:" . $self->{name} . "] WARNING Issued command was unsuccessful, retrying..." ); + main::print_log( "[Aurora:" . $self->{name} . "] WARNING Issued command was unsuccessful, file data is " . $file_data ); + main::print_log( "[Aurora:" . $self->{name} . "] Retrying command..." ); if ( $self->{cmd_process_retry} > $self->{cmd_process_retry_limit} ) { main::print_log( "[Aurora:" . $self->{name} . "] ERROR Issued command max retries reached. Abandoning command attempt..." ); shift @{ $self->{cmd_queue} }; @@ -1102,41 +1104,43 @@ sub identify { sub generate_voice_commands { my ($self) = @_; - - my $object_string; - my $object_name = $self->get_object_name; - &main::print_log("Generating Voice commands for Nanoleaf Aurora Controller $object_name"); - - my $voice_cmds = $self->get_voice_cmds(); - my $i = 1; - foreach my $cmd ( keys %$voice_cmds ) { - - #get object name to use as part of variable in voice command - my $object_name_v = $object_name . '_' . $i . '_v'; - $object_string .= "use vars '${object_name}_${i}_v';\n"; - - #Convert object name into readable voice command words - my $command = $object_name; - $command =~ s/^\$//; - $command =~ tr/_/ /; - - #Initialize the voice command with all of the possible device commands - $object_string .= $object_name . "_" . $i . "_v = new Voice_Cmd '$command $cmd';\n"; - - #Tie the proper routine to each voice command - $object_string .= $object_name . "_" . $i . "_v -> tie_event('" . $voice_cmds->{$cmd} . "');\n\n"; #, '$command $cmd');\n\n"; - - #Add this object to the list of Insteon Voice Commands on the Web Interface - $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Nanoleaf_Aurora', 'Controller_commands' ); - $i++; + unless ($self->{generate_voice_cmds}) { + my $object_string; + $self->{generate_voice_cmds} = 1; + my $object_name = $self->get_object_name; + &main::print_log("Generating Voice commands for Nanoleaf Aurora Controller $object_name"); + + my $voice_cmds = $self->get_voice_cmds(); + my $i = 1; + foreach my $cmd ( keys %$voice_cmds ) { + + #get object name to use as part of variable in voice command + my $object_name_v = $object_name . '_' . $i . '_v'; + $object_string .= "use vars '${object_name}_${i}_v';\n"; + + #Convert object name into readable voice command words + my $command = $object_name; + $command =~ s/^\$//; + $command =~ tr/_/ /; + + #Initialize the voice command with all of the possible device commands + $object_string .= $object_name . "_" . $i . "_v = new Voice_Cmd '$command $cmd';\n"; + + #Tie the proper routine to each voice command + $object_string .= $object_name . "_" . $i . "_v -> tie_event('" . $voice_cmds->{$cmd} . "');\n\n"; #, '$command $cmd');\n\n"; + + #Add this object to the list of Insteon Voice Commands on the Web Interface + $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Nanoleaf_Aurora', 'Controller_commands' ); + $i++; + } + + #Evaluate the resulting object generating string + package main; + eval $object_string; + print "Error in nanoleaf_aurora_item_commands: $@\n" if $@; + + package Nanoleaf_Aurora; } - - #Evaluate the resulting object generating string - package main; - eval $object_string; - print "Error in nanoleaf_aurora_item_commands: $@\n" if $@; - - package Nanoleaf_Aurora; } sub get_voice_cmds { @@ -1322,4 +1326,5 @@ sub set { # v1.0.11 - cosmetic fixes for undefined variables # v1.0.12 - get_effects method to get array of available effects # v1.0.13 - ability to print and purge the command queue in case a network error prevents clearing, empty poll queue if max reached -# v1.0.14 - commands now queue properly \ No newline at end of file +# v1.0.14 - commands now queue properly +# v1.0.15 - only load voice commands at startup \ No newline at end of file From dbcd00044497ffce3666b50173747e2b88e9088b Mon Sep 17 00:00:00 2001 From: "H.Plato" Date: Tue, 5 Sep 2017 21:45:39 -0600 Subject: [PATCH 2/5] prevent voice commands from rerunning at reload --- lib/Insteon.pm | 80 +++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/lib/Insteon.pm b/lib/Insteon.pm index 8b543d985..193650766 100755 --- a/lib/Insteon.pm +++ b/lib/Insteon.pm @@ -942,48 +942,53 @@ so that each class can have its own unique set of voice commands. =cut sub generate_voice_commands { + my ($self) = @_; - &main::print_log("Generating Voice commands for all Insteon objects"); - my $object_string; - for my $object (&main::list_all_objects) { - next unless ref $object; - next - unless $object->isa('Insteon::BaseInterface') - or $object->isa('Insteon::BaseObject'); - - #get object name to use as part of variable in voice command - my $object_name = $object->get_object_name; - my $object_name_v = $object_name . '_v'; - $object_string .= "use vars '${object_name}_v';\n"; - - #Convert object name into readable voice command words - my $command = $object_name; - $command =~ s/^\$//; - $command =~ tr/_/ /; - - my $group = ( $object->isa('Insteon_PLM') ) ? '' : $object->group; - - #Get list of all voice commands from the object - my $voice_cmds = $object->get_voice_cmds(); - - #Initialize the voice command with all of the possible device commands - $object_string .= "$object_name_v = new Voice_Cmd '$command [" . join( ",", sort keys %$voice_cmds ) . "]';\n"; + unless ($self->{generate_voice_cmds}) { + &main::print_log("Generating Voice commands for all Insteon objects"); + my $object_string; + $self->{generate_voice_cmds} = 1; + + for my $object (&main::list_all_objects) { + next unless ref $object; + next + unless $object->isa('Insteon::BaseInterface') + or $object->isa('Insteon::BaseObject'); + + #get object name to use as part of variable in voice command + my $object_name = $object->get_object_name; + my $object_name_v = $object_name . '_v'; + $object_string .= "use vars '${object_name}_v';\n"; + + #Convert object name into readable voice command words + my $command = $object_name; + $command =~ s/^\$//; + $command =~ tr/_/ /; + + my $group = ( $object->isa('Insteon_PLM') ) ? '' : $object->group; + + #Get list of all voice commands from the object + my $voice_cmds = $object->get_voice_cmds(); + + #Initialize the voice command with all of the possible device commands + $object_string .= "$object_name_v = new Voice_Cmd '$command [" . join( ",", sort keys %$voice_cmds ) . "]';\n"; + + #Tie the proper routine to each voice command + foreach ( keys %$voice_cmds ) { + $object_string .= "$object_name_v -> tie_event('" . $voice_cmds->{$_} . "', '$_');\n\n"; + } - #Tie the proper routine to each voice command - foreach ( keys %$voice_cmds ) { - $object_string .= "$object_name_v -> tie_event('" . $voice_cmds->{$_} . "', '$_');\n\n"; + #Add this object to the list of Insteon Voice Commands on the Web Interface + $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Insteon', 'Insteon_PLM_commands' ); } - #Add this object to the list of Insteon Voice Commands on the Web Interface - $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Insteon', 'Insteon_PLM_commands' ); - } + #Evaluate the resulting object generating string + package main; + eval $object_string; + print "Error in insteon_item_commands: $@\n" if $@; - #Evaluate the resulting object generating string - package main; - eval $object_string; - print "Error in insteon_item_commands: $@\n" if $@; - - package Insteon; + package Insteon; + } } =item C @@ -1215,6 +1220,7 @@ sub _active_interface { &main::Reload_post_add_hook( \&Insteon::check_all_aldb_versions, 1 ); &main::Reload_post_add_hook( \&Insteon::BaseInterface::poll_all, 1 ); $init_complete = 0; + $self->{generate_voice_cmds} = 0; #prevent duplicate commands at startup &main::MainLoop_pre_add_hook( \&Insteon::init, 1 ); &main::Reload_post_add_hook( \&Insteon::check_thermo_versions, 1 ); &main::Reload_post_add_hook( \&Insteon::generate_voice_commands, 1 ); From f4c7fdcc6a4bf27813c8daaf8fa836c77dc8a2ef Mon Sep 17 00:00:00 2001 From: H Plato Date: Mon, 19 Feb 2018 13:36:09 -0700 Subject: [PATCH 3/5] ical2vsdb v5 - filter out bad ALARM dates, ability to override all user specified reminders for import into MH --- bin/ical2vsdb | 71 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/bin/ical2vsdb b/bin/ical2vsdb index 109e41033..00f79284b 100755 --- a/bin/ical2vsdb +++ b/bin/ical2vsdb @@ -22,6 +22,10 @@ use strict; ## NOTE: v4 requires the update 2014 vsdb calendar schema (adding a control attribute). ## Common module organizer 2014 and vsdb calendar.pl 1.6.0-3 required. ## +## v5 02-2018: Some ALARM DATA has wonky dates (ie BEGIN:VALARM TRIGGER;VALUE=DATE-TIME:19760401T005545Z) +## ignore these entries and use 15 minutes for notification +## also enable a override_alarms to set a standard for all notifications ignoring what's in the ical data +## set to 'all' to remove all user specified alarm settings use lib '../lib', '../lib/site'; use iCal::Parser; @@ -40,20 +44,21 @@ use vsLock; # verify locking works as expected my $progname = "ical2vsdb"; -my $progver = "v4 01-2014"; +my $progver = "v5 02-2018"; my $DB = 0; my $days_before = -180; # defaults to avoid large vsdb databases, can be overriden my $days_after = 180; # -my $config_file = ""; -my $config_version = 2; -my $vsdb_cal_file = "calendar.tab"; -my $vsdb_todo_file = "tasks.tab"; -my $sleep_time = 900; #poll cycle default is 15 minutes -my $md5file = ""; -my $local_cache = ""; -my $data = ""; +my $config_file = ""; +my $config_version = 2; +my $vsdb_cal_file = "calendar.tab"; +my $vsdb_todo_file = "tasks.tab"; +my $sleep_time = 900; #poll cycle default is 15 minutes +my $md5file = ""; +my $local_cache = ""; +my $data = ""; +my $override_alarms = "0"; #ignore ical alarms and always do $override_alarms in minutes speech events $config_file = $ARGV[0] if $ARGV[0]; @@ -89,13 +94,19 @@ if ( ( $count == 0 ) or ( $output_dir eq "" ) ) { &read_md5file if ( $md5file ne "" ); print "Writing http requests to local cache: $local_cache\n" if $local_cache; +if ($override_alarms) { + if (lc $override_alarms eq "all") { + print "** Removing custom alarms for all events\n"; + } else { + print "Using a standard " .$override_alarms . "m alarm for all events\n"; + } +} print "Processing $count iCals"; print ", $days_after days in the future" if $days_after; my $abs_days_before = abs $days_before; print ", $abs_days_before in the past" if $abs_days_before; print "\nTarget vsdb directory is :$output_dir\n" if ($DB); print "MD5 temp file is :$md5file\n" if ( $md5file ne "" and $DB ); - #------------- Main Processing Loop ----------------- #BEGIN while (1) { @@ -208,7 +219,6 @@ while (1) { else { $parser = $parser->calendar unless $ical_data[$loop]->{method} ne "dir"; - print "."; #print Dumper $parser; $ical_data[$loop]->{hash} = $digest; @@ -217,10 +227,9 @@ while (1) { push( @changed_icals, @$data_info[0] ); push( @master_cal, @$data_cals ); push( @master_todo, @$data_todos ); - print "."; &cache_local( $data, $ical_data[$loop]->{options}->{name} ) if $local_cache; - print "done\n"; + print "Processing Complete\n"; print "Calendar Info:" if $DB; print @$data_info[0] . "," . @$data_info[1] . "\n" if $DB; } @@ -239,7 +248,7 @@ while (1) { #print Dumper @master_cal; update_db( "$output_dir/$vsdb_cal_file", \@changed_icals, \@master_cal ); update_db( "$output_dir/$vsdb_todo_file", \@changed_icals, \@master_todo ); - print "done\n"; + print "DataBases Updated\n"; } #--------------- Empty data structures and sleep ------------ @@ -364,12 +373,13 @@ sub parse_cal { push @out_info, $calname; push @out_info, $caldesc; my $count = 0; - + my $ical_messages = ""; + #print Dumper $cal; while ( my $year = each %{ $cal->{events} } ) { while ( my $month = each %{ $cal->{events}->{$year} } ) { while ( my $day = each %{ $cal->{events}->{$year}->{$month} } ) { - print "."; #give some progress +# print "."; #give some progress while ( my $uid = each %{ $cal->{events}->{$year}->{$month}->{$day} } ) { my $delta; @@ -405,10 +415,14 @@ sub parse_cal { } my $reminder = ''; + my $bad_alarm = 0; if ( $event_ref->{VALARM} ) { foreach my $alarm ( @{ $event_ref->{VALARM} } ) { if ( $alarm->{when} && $event_ref->{DTSTART} ) { + $bad_alarm = $alarm->{when} if ($alarm->{when}->{local_c}->{year} < $event_ref->{DTSTART}->{local_c}->{year}); my $duration = $event_ref->{DTSTART} - $alarm->{when}; + print "db: D[" . $event_ref->{DESCRIPTION}. " S[" . $event_ref->{SUMMARY}. "]" if ($DB > 2); + print "db: [dt=" . $event_ref->{DTSTART} . " alarm=" , $alarm->{when} . " rem=$reminder dur=$duration]\n" if ($DB > 2); $reminder .= ($reminder) ? ',' : ''; if ( $duration->delta_days ) { $reminder .= $duration->delta_days . 'd'; @@ -418,6 +432,20 @@ sub parse_cal { } } } + if (lc $override_alarms eq 'all') { + $reminder = ''; + print ":"; + } elsif ($override_alarms) { + $reminder = $override_alarms . 'm'; + print "."; + } elsif ($bad_alarm) { + $reminder = '15m'; + $ical_messages .= "ical2vsdb: WARNING event " . $event_ref->{SUMMARY} . " on " . $event_ref->{DTSTART} . " has bad alarm date " . $bad_alarm . ". Using 15 minute default\n"; + print "!"; + } else { + print "."; + } + print "db2: rem2=$reminder\n" if ($DB > 2); } #MH Specific attributes @@ -458,6 +486,8 @@ sub parse_cal { } } } + print ".done\n"; + print $ical_messages if ($ical_messages); print "db: $count calendar records processed\n" if $DB; my @todos = $cal->{todos}; @@ -564,6 +594,7 @@ sub init { my $count = 0; my $version = 0; + my $dcsicals = ""; open( CFGFILE, $config_file ) || die "Error: Cannot open config file $config_file!"; @@ -601,7 +632,9 @@ sub init { } elsif ( lc $type eq "local_cache_dir" ) { $local_cache = $url; - + } + elsif ( lc $type eq "override_alarms" ) { + $override_alarms = $url; } else { $ical_data[$count]->{type} = $type; @@ -611,7 +644,7 @@ sub init { $ical_data[$count]->{options}->{$key} = $value; } $ical_data[$count]->{hash} = "none"; - print "Applying second level ical parsing (set nodscfix if this breaks anything) ...\n" + $dcsicals .= $ical_data[$count]->{options}->{name} . " " unless ( exists $ical_data[$count]->{options}->{nodcsfix} ); my ( $method, $loc ) = split( /:\/\//, $url ); @@ -636,6 +669,8 @@ sub init { } } close(CFGFILE); + + print "Applied second level ical parsing to ($dcsicals).\n" if ($dcsicals); die "Incompatible configuration file version!" if ( $version != $config_version ); From ba3b6bf2d6878bd9708f4c7565f89fd663d03735 Mon Sep 17 00:00:00 2001 From: H Plato Date: Mon, 19 Feb 2018 13:38:24 -0700 Subject: [PATCH 4/5] Updated Nanoleaf Aurora --- lib/Nanoleaf_Aurora.pm | 180 +++++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 87 deletions(-) diff --git a/lib/Nanoleaf_Aurora.pm b/lib/Nanoleaf_Aurora.pm index 149ebb5ae..5bd680310 100644 --- a/lib/Nanoleaf_Aurora.pm +++ b/lib/Nanoleaf_Aurora.pm @@ -1,9 +1,6 @@ package Nanoleaf_Aurora; -#todo if poll queue exceeds 3, then just empty the queue -#print and purge the command queue - -# v1.0.15 +# v1.1.01 #if any effect is changed, by definition the static child should be set to off. #cmd data returns, need to check by command @@ -34,10 +31,10 @@ use IO::Socket::INET; # the location URL and tokens are stored in the mh.ini file # Firmware supported -# 1.4.38 or earlier - no +# 2.2.0 - needs v1.1 +# 1.5.0 to 2.1.3 - yes # 1.4.39 - pass the option api=beta -# 1.5.0 - yes -# 1.5.1 - yes +# 1.4.38 or earlier - no # Nanoleaf_Aurora Objects # @@ -84,12 +81,17 @@ our %rest; $rest{info} = ""; $rest{effects} = "effects"; $rest{auth} = "new"; -$rest{on} = "state/on"; -$rest{off} = "state/on"; -$rest{set_effect} = "effects/select"; +#$rest{on} = "state/on"; +#$rest{off} = "state/on"; +$rest{on} = "state"; +$rest{off} = "state"; +#$rest{set_effect} = "effects/select"; +$rest{set_effect} = "effects"; $rest{set_static} = "effects"; -$rest{brightness} = "state/brightness"; -$rest{brightness2} = "state/brightness"; +#$rest{brightness} = "state/brightness"; +#$rest{brightness2} = "state/brightness"; +$rest{brightness} = "state"; +$rest{brightness2} = "state"; $rest{get_static} = "effects"; $rest{identify} = "identify"; @@ -100,8 +102,10 @@ $opts{on} = "-response_code -json -put '{\"on\":true}'"; $opts{off} = "-response_code -json -put '{\"on\":false}'"; $opts{set_effect} = "-response_code -json -put '{\"select\":"; $opts{set_static} = "-response_code -json -put '{\"write\":{\"command\":\"display\",\"version\":\"1.0\",\"animType\":\"static\",\"animData\":"; -$opts{brightness} = "-response_code -json -put '{\"value\":"; -$opts{brightness2} = "-response_code -json -put '{\"increment\":"; +#$opts{brightness} = "-response_code -json -put '{\"value\":"; +#$opts{brightness2} = "-response_code -json -put '{\"increment\":"; +$opts{brightness} = "-response_code -json -put '{\"brightness\":{\"value\":"; +$opts{brightness2} = "-response_code -json -put '{\"brightness\":{\"increment\":"; $opts{get_static} = "-response_code -json -put '{\"write\":{\"command\":\"request\",\"version\":\"1.0\",\"animName\":\"*Static*\"}}'"; $opts{identify} = "-response_code -json -put '{}'"; @@ -125,7 +129,7 @@ sub new { $self->{updating} = 0; $self->{data}->{retry} = 0; $self->{status} = ""; - $self->{module_version} = "v1.0.15"; + $self->{module_version} = "v1.1.01"; $self->{ssdp_timeout} = 4000; $self->{last_static} = ""; @@ -163,12 +167,12 @@ sub new { unlink "$::config_parms{data_dir}/Auroroa_cmd_" . $self->{name} . ".data"; $self->{cmd_process} = new Process_Item; $self->{cmd_process}->set_output( $self->{cmd_data_file} ); - $self->{generate_voice_cmds} = 0; - &::MainLoop_post_add_hook( \&Nanoleaf_Aurora::process_check, 0, $self ); - &::Reload_post_add_hook( \&Nanoleaf_Aurora::generate_voice_commands, 1, $self ); - $self->get_data(); $self->{init} = 0; $self->{init_data} = 0; + $self->{init_v_cmd} = 0; + &::MainLoop_post_add_hook( \&Nanoleaf_Aurora::process_check, 0, $self ); + &::Reload_post_add_hook( \&Nanoleaf_Aurora::generate_voice_commands, 1, $self ); + $self->get_data(); #push( @{ $$self{states} }, 'off', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', 'on' ); push( @{ $$self{states} }, 'off'); for my $i (1..99) { push @{ $$self{states} }, "$i%"; } @@ -258,7 +262,8 @@ sub process_check { if ( $self->{poll_process}->done_now() ) { - shift @{ $self->{poll_queue} }; #remove the poll since they are expendable. + #shift @{ $self->{poll_queue} }; #remove the poll since they are expendable. + @{ $self->{poll_queue} } = (); #clear the queue since process is done. my $com_status = "online"; main::print_log( "[Aurora:" . $self->{name} . "] Background poll " . $self->{poll_process_mode} . " process completed" ) if ( $self->{debug} ); @@ -314,6 +319,12 @@ sub process_check { else { $self->{data}->{panels} = $data->{panelLayout}->{layout}->{numPanels}; $self->{data}->{panel_size} = $data->{panelLayout}->{layout}->{sideLength}; + $self->{data}->{rhythm} = 0; + if (defined $data->{rhythm}->{rhythmConnected} and $data->{rhythm}->{rhythmConnected} eq "true") { + $self->{data}->{rhythm} = 1; + } + $self->{data}->{panels} = $self->{data}->{panels} - $self->{data}->{rhythm}; #Rhythm module counts as a panel + for ( my $i = 0; $i < $self->{data}->{panels}; $i++ ) { $self->{data}->{panel}->{ @{ $data->{panelLayout}->{layout}->{positionData} }[$i]->{panelId} }->{x} = @{ $data->{panelLayout}->{layout}->{positionData} }[$i]->{x}; @@ -339,18 +350,6 @@ sub process_check { } } -#polls are expendable and will always trigger on the timer, so don't keep a queue -# if ( scalar @{ $self->{poll_queue} } ) { -# my $cmd_string = shift @{ $self->{poll_queue} }; -# my ( $mode, $cmd ) = split /\|/, $cmd_string; -# $self->{poll_process}->set($cmd); -# $self->{poll_process}->start(); -# $self->{poll_process_pid}->{ $self->{poll_process}->pid() } = $mode; #capture the type of information requested in order to parse; -# $self->{poll_process_mode} = $mode; -# main::print_log( "[Aurora:" . $self->{name} . "] Poll Queue " . $self->{poll_process}->pid() . " mode=$mode cmd=$cmd" ) -# if ( $self->{debug} ); -# -# } if ( defined $self->{child_object}->{comm} ) { if ( $self->{status} ne $com_status ) { main::print_log "[Aurora:" @@ -441,8 +440,7 @@ sub process_check { } else { - main::print_log( "[Aurora:" . $self->{name} . "] WARNING Issued command was unsuccessful, file data is " . $file_data ); - main::print_log( "[Aurora:" . $self->{name} . "] Retrying command..." ); + main::print_log( "[Aurora:" . $self->{name} . "] WARNING Issued command was unsuccessful, retrying..." ); if ( $self->{cmd_process_retry} > $self->{cmd_process_retry_limit} ) { main::print_log( "[Aurora:" . $self->{name} . "] ERROR Issued command max retries reached. Abandoning command attempt..." ); shift @{ $self->{cmd_queue} }; @@ -490,20 +488,8 @@ sub _get_JSON_data { push @{ $self->{poll_queue} }, "$mode|$cmd"; } else { - main::print_log( "[Aurora:" . $self->{name} . "] WARNING. Queue has grown past " . $self->{max_poll_queue} . ". Clearing Polling Queue." ); - @{ $self->{poll_queue} } = (); #Polls are disposable - if ( defined $self->{child_object}->{comm} ) { - if ( $self->{status} ne "offline" ) { - main::print_log "[Aurora:" - . $self->{name} - . "] Communication Tracking object found. Updating from " - . $self->{child_object}->{comm}->state() - . " to offline..." - if ( $self->{loglevel} ); - $self->{status} = "offline"; - $self->{child_object}->{comm}->set( "offline", 'poll' ); - } - } + #the queue has grown past the max, so it might be down. Since polls are expendable, just don't do anything + #when the aurora is back it will process the backlog, and as soon as a poll is processed, the queue is cleared. } } } @@ -729,6 +715,14 @@ sub print_info { main::print_log( "[Aurora:" . $self->{name} . "] Manufacturer: " . $self->{data}->{info}->{manufacturer} ); main::print_log( "[Aurora:" . $self->{name} . "] Model: " . $self->{data}->{info}->{model} ); main::print_log( "[Aurora:" . $self->{name} . "] Firmware: " . $self->{data}->{info}->{firmwareVersion} ); + if ($self->{data}->{rhythm}) { + main::print_log( "[Aurora:" . $self->{name} . "] Rhythm Hardware: " . $self->{data}->{info}->{rhythm}->{hardwareVersion} ); + main::print_log( "[Aurora:" . $self->{name} . "] Rhythm Firmware: " . $self->{data}->{info}->{rhythm}->{firmwareVersion} ); + } else { + main::print_log( "[Aurora:" . $self->{name} . "] Rhythm Module: Not Present"); + } + main::print_log( "[Aurora:" . $self->{name} . "] Firmware: " . $self->{data}->{info}->{firmwareVersion} ); + main::print_log( "[Aurora:" . $self->{name} . "] Connected Panels: " . $self->{data}->{panels} ); main::print_log( "[Aurora:" . $self->{name} . "] Panel Size: " . $self->{data}->{panel_size} ); main::print_log( "[Aurora:" . $self->{name} . "] API Path: " . $self->{api_path} ); @@ -1022,11 +1016,11 @@ sub set { $self->_push_JSON_data($mode); } elsif ( $mode =~ /^(\d+)/ ) { - my $params = $opts{brightness} . $1 . '}' . "'"; + my $params = $opts{brightness} . $1 . '}}' . "'"; $self->_push_JSON_data( 'brightness', $params ); } elsif ( $mode =~ /^([-+]\d+)/ ) { - my $params = $opts{brightness2} . $1 . '}' . "'"; + my $params = $opts{brightness2} . $1 . '}}' . "'"; $self->_push_JSON_data( 'brightness2', $params ); } else { @@ -1066,6 +1060,16 @@ sub check_static { return ('1'); } +sub is_rhythm_effect { + my ( $self) = @_; + my $return = 0; + print "DB \$self->{data}->{info}->{rhythm}->{rhythmActive} = $self->{data}->{info}->{rhythm}->{rhythmActive}\n"; + print "DB \$self->{data}->{info}->{rhythm}->{rhythmMode} = $self->{data}->{info}->{rhythm}->{rhythmMode}\n"; + $return = 1 if ($self->{data}->{info}->{rhythm}->{rhythmActive}); + + return $return; +} + sub print_static { my ($self) = @_; @@ -1104,42 +1108,43 @@ sub identify { sub generate_voice_commands { my ($self) = @_; - unless ($self->{generate_voice_cmds}) { - my $object_string; - $self->{generate_voice_cmds} = 1; - my $object_name = $self->get_object_name; - &main::print_log("Generating Voice commands for Nanoleaf Aurora Controller $object_name"); - - my $voice_cmds = $self->get_voice_cmds(); - my $i = 1; - foreach my $cmd ( keys %$voice_cmds ) { - - #get object name to use as part of variable in voice command - my $object_name_v = $object_name . '_' . $i . '_v'; - $object_string .= "use vars '${object_name}_${i}_v';\n"; - - #Convert object name into readable voice command words - my $command = $object_name; - $command =~ s/^\$//; - $command =~ tr/_/ /; - - #Initialize the voice command with all of the possible device commands - $object_string .= $object_name . "_" . $i . "_v = new Voice_Cmd '$command $cmd';\n"; - - #Tie the proper routine to each voice command - $object_string .= $object_name . "_" . $i . "_v -> tie_event('" . $voice_cmds->{$cmd} . "');\n\n"; #, '$command $cmd');\n\n"; - - #Add this object to the list of Insteon Voice Commands on the Web Interface - $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Nanoleaf_Aurora', 'Controller_commands' ); - $i++; - } - - #Evaluate the resulting object generating string - package main; - eval $object_string; - print "Error in nanoleaf_aurora_item_commands: $@\n" if $@; - - package Nanoleaf_Aurora; + + if ($self->{init_v_cmd} == 0) { + my $object_string; + my $object_name = $self->get_object_name; + $self->{init_v_cmd} = 1; + &main::print_log("Generating Voice commands for Nanoleaf Aurora Controller $object_name"); + + my $voice_cmds = $self->get_voice_cmds(); + my $i = 1; + foreach my $cmd ( keys %$voice_cmds ) { + + #get object name to use as part of variable in voice command + my $object_name_v = $object_name . '_' . $i . '_v'; + $object_string .= "use vars '${object_name}_${i}_v';\n"; + + #Convert object name into readable voice command words + my $command = $object_name; + $command =~ s/^\$//; + $command =~ tr/_/ /; + + #Initialize the voice command with all of the possible device commands + $object_string .= $object_name . "_" . $i . "_v = new Voice_Cmd '$command $cmd';\n"; + + #Tie the proper routine to each voice command + $object_string .= $object_name . "_" . $i . "_v -> tie_event('" . $voice_cmds->{$cmd} . "');\n\n"; #, '$command $cmd');\n\n"; + + #Add this object to the list of Insteon Voice Commands on the Web Interface + $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Nanoleaf_Aurora', 'Controller_commands' ); + $i++; + } + + #Evaluate the resulting object generating string + package main; + eval $object_string; + print "Error in nanoleaf_aurora_item_commands: $@\n" if $@; + + package Nanoleaf_Aurora; } } @@ -1327,4 +1332,5 @@ sub set { # v1.0.12 - get_effects method to get array of available effects # v1.0.13 - ability to print and purge the command queue in case a network error prevents clearing, empty poll queue if max reached # v1.0.14 - commands now queue properly -# v1.0.15 - only load voice commands at startup \ No newline at end of file +# v1.0.15 - fixed polling +# v1.1.01 - firmware v2.2.0 and rhythm module \ No newline at end of file From 812a26008a43e34b468a866f5d863feb9a381810 Mon Sep 17 00:00:00 2001 From: H Plato Date: Mon, 19 Feb 2018 13:41:43 -0700 Subject: [PATCH 5/5] Revert voice command test for Insteon.pm --- lib/Insteon.pm | 80 +++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/lib/Insteon.pm b/lib/Insteon.pm index 193650766..8b543d985 100755 --- a/lib/Insteon.pm +++ b/lib/Insteon.pm @@ -942,53 +942,48 @@ so that each class can have its own unique set of voice commands. =cut sub generate_voice_commands { - my ($self) = @_; - unless ($self->{generate_voice_cmds}) { - &main::print_log("Generating Voice commands for all Insteon objects"); - my $object_string; - $self->{generate_voice_cmds} = 1; - - for my $object (&main::list_all_objects) { - next unless ref $object; - next - unless $object->isa('Insteon::BaseInterface') - or $object->isa('Insteon::BaseObject'); - - #get object name to use as part of variable in voice command - my $object_name = $object->get_object_name; - my $object_name_v = $object_name . '_v'; - $object_string .= "use vars '${object_name}_v';\n"; - - #Convert object name into readable voice command words - my $command = $object_name; - $command =~ s/^\$//; - $command =~ tr/_/ /; - - my $group = ( $object->isa('Insteon_PLM') ) ? '' : $object->group; - - #Get list of all voice commands from the object - my $voice_cmds = $object->get_voice_cmds(); - - #Initialize the voice command with all of the possible device commands - $object_string .= "$object_name_v = new Voice_Cmd '$command [" . join( ",", sort keys %$voice_cmds ) . "]';\n"; - - #Tie the proper routine to each voice command - foreach ( keys %$voice_cmds ) { - $object_string .= "$object_name_v -> tie_event('" . $voice_cmds->{$_} . "', '$_');\n\n"; - } + &main::print_log("Generating Voice commands for all Insteon objects"); + my $object_string; + for my $object (&main::list_all_objects) { + next unless ref $object; + next + unless $object->isa('Insteon::BaseInterface') + or $object->isa('Insteon::BaseObject'); - #Add this object to the list of Insteon Voice Commands on the Web Interface - $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Insteon', 'Insteon_PLM_commands' ); - } + #get object name to use as part of variable in voice command + my $object_name = $object->get_object_name; + my $object_name_v = $object_name . '_v'; + $object_string .= "use vars '${object_name}_v';\n"; + + #Convert object name into readable voice command words + my $command = $object_name; + $command =~ s/^\$//; + $command =~ tr/_/ /; + + my $group = ( $object->isa('Insteon_PLM') ) ? '' : $object->group; - #Evaluate the resulting object generating string - package main; - eval $object_string; - print "Error in insteon_item_commands: $@\n" if $@; + #Get list of all voice commands from the object + my $voice_cmds = $object->get_voice_cmds(); - package Insteon; + #Initialize the voice command with all of the possible device commands + $object_string .= "$object_name_v = new Voice_Cmd '$command [" . join( ",", sort keys %$voice_cmds ) . "]';\n"; + + #Tie the proper routine to each voice command + foreach ( keys %$voice_cmds ) { + $object_string .= "$object_name_v -> tie_event('" . $voice_cmds->{$_} . "', '$_');\n\n"; + } + + #Add this object to the list of Insteon Voice Commands on the Web Interface + $object_string .= ::store_object_data( $object_name_v, 'Voice_Cmd', 'Insteon', 'Insteon_PLM_commands' ); } + + #Evaluate the resulting object generating string + package main; + eval $object_string; + print "Error in insteon_item_commands: $@\n" if $@; + + package Insteon; } =item C @@ -1220,7 +1215,6 @@ sub _active_interface { &main::Reload_post_add_hook( \&Insteon::check_all_aldb_versions, 1 ); &main::Reload_post_add_hook( \&Insteon::BaseInterface::poll_all, 1 ); $init_complete = 0; - $self->{generate_voice_cmds} = 0; #prevent duplicate commands at startup &main::MainLoop_pre_add_hook( \&Insteon::init, 1 ); &main::Reload_post_add_hook( \&Insteon::check_thermo_versions, 1 ); &main::Reload_post_add_hook( \&Insteon::generate_voice_commands, 1 );