Skip to content

Example Process item

ggodart edited this page Jan 16, 2021 · 8 revisions

Process Item

The process item allows you to run tasks in parallel to MisterHouse and is described in detail here.

The following are good practice and described in the code below;

  • Always define a timeout to trap runaway tasks e.g. $p_backup_data->set_timeout(600); # time out after 5 minutes
  • Always redirect output to a log file so you can tell what happened e.g. $p_backup_data->set_output($config_parms{data_dir} . "/logs/backup.txt" );
  • Always have a done_now handler to check if it timed out or successfully finished
  • It is a good idea to have a general purpose process logging routine as in the example below, the downside of this example is that the print log is only updated AFTER the process finished and your log may thus have out-of-sequence entries. If you need real-time logging, please see below
#-----------------------------------------------------------------------
# create the process item and a voice command to run it
# only needs to be run once so wrap in noloop
#-----------------------------------------------------------------------
#noloop=start
$v_backup_data        = new Voice_Cmd('{run, } backup');
$p_backup_data        = new Process_Item;
#noloop=stop

#-----------------------------------------------------------------------
# voice command handler to launch the backup
#-----------------------------------------------------------------------
if ( $state = said $v_backup_data) {
	print_log("Backup data launched");
        # set up the process and start it
	set $p_backup_data $config_parms{"code_dir"} . "/backup.sh";
	$p_backup_data->set_output(
		$config_parms{data_dir} . "/logs/backup.txt" );
	$p_backup_data->set_timeout(600);     # time out after 5 minutes
	start $p_backup_data;
}

#-----------------------------------------------------------------------
# handler to run after the backup process ands
#-----------------------------------------------------------------------
if ( done_now $p_backup_data) {
	if ( timed_out $p_backup_data) {
		print_log('ERROR: backup.sh - timed out after 5 minutes');
	}
	print_process_log( "backup.txt", "backup data" );
}

#-----------------------------------------------------------------------
# utility subroutine called after any process ends to append its output 
# to the print log, passed the name of the file to print
#-----------------------------------------------------------------------
sub print_process_log {
	my ( $filename, $process_name ) = @_;
	$filename = $config_parms{data_dir} . "/logs/" . $filename;
	open( SOURCE, $filename );
	while (<SOURCE>) {
		chomp;
		my $cline = $_;
	        print_log("$cline","DEBUG",$process_name );
	}
	close(SOURCE);
	truncate $filename, 0;
}

Real Time Process Logging

The most flexible way to do this is to call MiterHouse print_log via an http call to a routine you have created to call print_log, here is an example;

The CGI program print_log.pl in your web directories;

########################################################################
# File   :  print_log.pl
########################################################################
# This cgi script prints to the log, its passed the message, severity and source
# e.g. http://IP:port/my_mh/print_log.pl?message=test%201&severity=INFORMATIONAL&source=web%20print_log
########################################################################
use strict;
my (
	@t,       $message, $severity,    $source,	$returnPage, 
);
# get message, severity and source
my m$arg1     = shift;
@t        = split( /=/, $arg1 );
$message = $t[1];

my $arg2     = shift;
@t        = split( /=/, $arg2 );
$severity = $t[1];

my $arg3     = shift;
@t        = split( /=/, $arg3 );
$source = $t[1];

my $returnPage = <<'END';
<html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "https://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport"
	content="width=device-width, minimum-scale=1, maximum-scale=1"/>
<title>Get State</title>
</head>
<body>
END

$returnPage .= "Message=" . $message . "<br>\n";
$returnPage .= "Severity=" . $severity . "<br>\n";
$returnPage .= "Source = " . $source . "<br>\n";

print_log( $message, $severity, "web-" . $source );

$returnPage .= <<'END1';
</body>
</html>
END1

return &html_page( '', $returnPage );

In your process item

print_log("my message","DEBUG","my process item");

########################################################################
# General Purpose routine to use http to print a log in new format
# passed message, severity and source
# my_mh/print_log.pl?message=mymess&severity=WARNING&source=source
########################################################################

sub print_log {
    my ($message,$severity,$source) = @_;
    my $url = "my_mh/print_log.pl?message=" . $message 
	. "&severity=" . $severity 
	. "&source=" . $source;
    send_url_to_mh ($url);
}

########################################################################
# Minimal routine to send a url to MisterHouse, passed the url
# note my port is 8077
########################################################################
sub send_url_to_mh {
	my $URL = $_[0];
	my ($myIPaddress) = inet_ntoa( ( gethostbyname(hostname) )[4] );
	$URL = "http://" . $myIPaddress . ":8077/" . $URL;
	#if ( $debug == 1 ) { print "checking $URL\n"; }
	my $ua = LWP::UserAgent->new;
	$ua->timeout(5);
	my $response = $ua->get($URL);
	if ( $response->is_error ) {
		print("Error with $URL");
		return "error";
	}
	#if ( $debug == 1 ) { print "HTML response =" . $response->content . "\n"; }
	return $response->content;
}
Clone this wiki locally