#!/usr/bin/env perl
# -*- perl -*-
########################################################################
########################################################################
# A program to gather a CRaTER data stream and output an HTML page
# Input: hrml form with embedded rtlm-standard mnemonics
# Input: rtlm ASCII data stream piped through calcurve
# Output: html web page
########################################################################
########################################################################
########################################################################
# Initial Constants
########################################################################
require 5.6.0;
use Socket;
use Time::Local;
use Time::gmtime;
$PATH = $ENV{'CRATERTOOLS'};
$FORM = 'monitor.html';
$OUTPUT = 'index.html';
$SIG{'ALRM'} = 'Timer';
$TIME_OK = ''; # see style section of monitor for description
$TIME_NG = '
STALE';
$REFRESH = 8; # default refresh interval in seconds
########################################################################
# The following mnemonics are extracted from rtlm
# The array values result, after interpolation, in html values
# to be inserted in the output page table inside
... |
# NB the output of calcurve, which feeds this process (see Aquire() ) is
# ($name,$raw,$hex,$decimal,$units)
########################################################################
%Mnemonics = (
'SeqCount', '"Sequence Ct.
" . $raw', # Header data
'Time', '$raw . " " . $hex',
'TestMode',
'$raw ? q(
TEST MODE
) :
q(
Test Off
)',
'OneHertz',
'$raw ? q(
1Hz Absent
) :
q(
1Hz Sync
)',
'SerialNumber', '"S/N" . $raw',
'LastValue', '$raw', # Secondary science
'DiscThin', '$raw',
'DiscThick', '$raw',
'Mask',
'join(" ",($raw,$hex,$decimal,@units))',
# 'Mask2', '$raw',
# 'Mask3', '$raw',
# 'Mask4', '$raw',
'Single1', '$raw',
'Single2', '$raw',
'Single3', '$raw',
'Single4', '$raw',
'Single5', '$raw',
'Single6', '$raw',
'Good', '$raw',
'Reject', '$raw',
'Total', '$raw',
# 'BiasCntrl', '', # Secondary Science Discretes
'BiasCmd',
'$raw ? q(
Bias ON
) :
q(
Bias OFF
)',
'CalLow',
'$raw ? q(
Low ON
) :
q(
Low Off
)',
'CalHigh',
'$raw ? q(
High ON
) :
q(
High Off
)',
'CalRate',
'$raw ? q(
2 KHz
) :
q(
8 Hz
)',
'ProcD1',
'$raw ? q(
ON
) :
q(
OFF
)',
'ProcD2',
'$raw ? q(
ON
) :
q(
OFF
)',
'ProcD3',
'$raw ? q(
ON
) :
q(
OFF
)',
'ProcD4',
'$raw ? q(
ON
) :
q(
OFF
)',
'ProcD5',
'$raw ? q(
ON
) :
q(
OFF
)',
'ProcD6',
'$raw ? q(
ON
) :
q(
OFF
)',
'LastCmd', '$raw',
# 'V28bus', '$decimal', # Analog Housekeeping
'V5digital', '$decimal . " V(D)"',
'V5plus', '$decimal . " V(A)"',
'V5neg', '$decimal . " V(A)"',
# 'I28bus', '$decimal',
'BiasCurrentD1', '$decimal . " µA"',
'BiasCurrentD2', '$decimal . " µA"',
'BiasCurrentD3', '$decimal . " µA"',
'BiasCurrentD4', '$decimal . " µA"',
'BiasCurrentD5', '$decimal . " µA"',
'BiasCurrentD6', '$decimal . " µA"',
'BiasVoltThin', '$decimal . " VDC"',
'BiasVoltThick', '$decimal . " VDC"',
'CalAmp', '$decimal',
'LLDThin', '$DiscThin . q(: => ) . 1000*$decimal . " mv"',
'LLDThick', '$DiscThick . q(: => ) . 1000*$decimal . " mv"',
'Ttelescope', '"Telescope
" . $decimal . " C"',
'Tanalog', '"Analog Bd
" . $decimal . " C"',
'Tdigital', '"Digial Bd
" . $decimal . " C"',
'Tpower', '"DC Supply
" . $decimal . " C"',
'Tref', '"Bulkhead
" . $decimal . " C"',
'RadHighSens',
'($decimal=~/[0-9.]+/) ? $decimal . " mrad" : q(n/a)',
'RadMedSens',
'($decimal=~/[0-9.]+/) ? $decimal . " mrad" : q(n/a)',
'RadLowSens',
'($decimal=~/[0-9.]+/) ? $decimal . " rad" : q(n/a)',
# 'Tprt'
# 'Purge'
'BusVoltage', '$decimal . " VDC"',
'BusPower', '$decimal . " W"',
);
########################################################################
########################################################################
# Main Program executes here
# NB don't mix alarm() with sleep(); some implementation use the
# same counter for both
########################################################################
########################################################################
&Setup;
while(1) {
&Acquire;
&Post;
sleep($Slow) if ($Slow);
}
exit 0;
##########################That's all, folks! ###########################
########################################################################
########################################################################
# Process the input data
# This returns after each Housekeeping packet is processed
########################################################################
sub Acquire {
# Variable interpolation of a single-quoted string
# (which is what $_ is when we read a line in via <>).
# while(
) {
# eval '$_ ="' . $_ . '"';
# print;
# }
while () {
my ($name,$raw,$hex,$decimal,@units) = split;
if (defined($Mnemonics{$name})) {
$$name = eval $Mnemonics{$name};
}
# want to have last command, last value sticky
if ($name =~ /LastValue/) {
if ($LastCmd != 0) {
$EchoValue = &Translate($LastCmd,$LastValue);
}
} elsif ($name =~ /Time/) {
$TZ = $decimal; # save the timezone separately
} elsif ($name =~ /Purge/) { # this is the last in HK packet
$Stale = $TIME_OK; # mark as fresh data
alarm(60) if (!$Slow); # but set the alarm clock
$tick = 0;
return;
} elsif ($name =~ /^Total/ && $Refresh < 8 && $tick++ == $Refresh) {
$tick = 0;
return;
}
}
}
########################################################################
# Canonical help messages
########################################################################
sub Help {
print "
usage: $0 [-h] [-r htmlform] [-s] [-v] [-w webout]
Receives rtlm ASCII processed by calcurve and generates a web page; default
input is STDIN. Updates occur once per housekeeping packet (AppId 122).
If -f flag is used, packets are read once per second.
flag -h prints this help message
-r reads this file to get master HRML form [$FORM]
-s forces 1 second cadence in reading data packets
(16 second cadence if second -s flag is invoked)
-v verbose operation
-w writes HTML web page to filename [$OUTPUT]
";
}
########################################################################
# Post the current results
# NB @Form remains static as initially read in
# then we replace any _variableName_ with $variableName
# as we print each line in turn
########################################################################
sub Post {
my $jj,$line;
unlink("$Webfile"); # take the old link away
open(OUT,">$Working") || die "Could not open $Working for write\n";
for($jj=0; $jj<=$#Form; $jj++) {
$line = $Form[$jj];
$line =~ s/_([0-9A-z]+)_/$$1/;
print OUT $line;
}
close OUT;
link("$Working","$Webfile"); # link in the new one
return;
}
########################################################################
# Setup the program
# Read input form lines into @Form
########################################################################
sub Setup {
my $ii = 0;
$Slow = 0; # Used to flag file reads
$Refresh = $REFRESH; # Default refresh time
my $foo;
while ( $foo = shift(@ARGV) ) {
if ( $foo =~ /^-[hH]/) {
&Help;
exit 0;
}
if ( $foo =~ /^-[rR]/ ) {
if ( !defined($ARGV[0]) ) {
print STDERR "flag $foo requires an argument\n";
&Help;
exit 1;
}
$Formfile = shift(@ARGV);
next;
}
if ( $foo =~ /^-[sS]/ ) {
if (!$Slow) {
$Slow = 1;
} else {
$Slow = 16;
}
next;
}
if ( $foo =~ /^-[tT]/ ) {
$Refresh = shift(@ARGV);
if (!defined($Refresh) || $Refresh =~ /[^0-9]/) {
print STDERR "$foo flag requires a numberic argument\n";
&Help;
}
next;
}
if ( $foo =~ /^-[vV]/ ) {
$Verbose++;
next;
}
if ( $foo =~ /^-[wW]/ ) {
if ( !defined($ARGV[0]) ) {
print STDERR "flag $foo requires an argument\n";
&Help;
exit 1;
}
$Webfile = shift(@ARGV);
next;
}
print STDERR "Unknown argument: $foo\n";
&Help;
exit 1;
}
$Webfile = $OUTPUT if (!defined($Webfile));
$Working = $Webfile . ".wrk";
print STDERR "STAT: Writing output HTML to $Webfile\n" if $Verbose;
print STDERR "STAT: Using $Working as temporary HTML file\n" if $Verbose;
print STDERR "STAT: Forcing $Slow second delays on read\n" if ($Verbose && $Slow);
if (!defined($Formfile)) {
if ( -r $FORM ) {
$Formfile = $FORM;
} else {
$Formfile = $PATH . "/" . $FORM;
}
}
open(IN,"$Formfile") ||
die "Could not find $FORM to read either here or in CRATERTOOLS";
while () {
$Form[$ii++] = $_;
}
close IN;
print STDERR "STAT: Read $Formfile for HTML master\n" if $Verbose;
$Datafile = '-' if (!defined($Datafile));
open(DATA,"$Datafile") || die "Could not open $Datafile for data input\n";
print STDERR "STAT: Reading data from $Datafile\n" if $Verbose;
$EchoValue = ''; # declared NULL to start; see &Post
$Stale = $TIME_OK; # shouldn't actually need this here
&Post; # puts up blank page to start
}
########################################################################
# (Re)set a timer when we read stuff
########################################################################
sub Timer {
$Stale = $TIME_NG;
print STDERR "Caught alarm for stale data\n" if $Verbose;
&Post; # post last data as stale
alarm(60) if (!$Slow); # shouldn't actually get here because
# $Slow should have kept alarm from being set
}
########################################################################
# Translate echoed commands numbers into mnemonics
# Input args: command id, value
########################################################################
sub Translate {
my $cmd = $_[0];
my $val = $_[1];
my $retval = "*** error ***";
if ($cmd == 2) { $retval = sprintf("Echo 0x%04x (hex) %d (decimal)",$val,$val) } ;
if ($cmd == 3) {
$retval = "Detector Bias Off" if ($val == 1<<13);
$retval = "Detector Bias On" if ($val == 1<<12);
$retval = "Electrical Cal Low Off" if ($val == 1<<11);
$retval = "Electrical Cal Low On" if ($val == 1<<10);
$retval = "Electrical Cal High Off" if ($val == 1<<9);
$retval = "Electrical Cal High On" if ($val == 1<<8);
$retval = "Electrical Cal Rate 8Hz" if ($val == 1<<7);
$retval = "Electrical Cal Rate 2KHz" if ($val == 1<<6);
$retval = "Data Test Mode" if ($val == 1<<4);
$retval = "Clear all Commands" if ($val == 1<<1);
$retval = "System Reset" if ($val == 1);
}
if ($cmd == 4) {
$retval = "D1 Processing Off" if ($val == 1<<15);
$retval = "D1 Processing On" if ($val == 1<<14);
$retval = "D2 Processing Off" if ($val == 1<<13);
$retval = "D2 Processing On" if ($val == 1<<12);
$retval = "D3 Processing Off" if ($val == 1<<11);
$retval = "D3 Processing On" if ($val == 1<<10);
$retval = "D4 Processing Off" if ($val == 1<<9);
$retval = "D4 Processing On" if ($val == 1<<8);
$retval = "D5 Processing Off" if ($val == 1<<7);
$retval = "D5 Processing On" if ($val == 1<<6);
$retval = "D6 Processing Off" if ($val == 1<<5);
$retval = "D6 Processing On" if ($val == 1<<4);
}
if ($cmd == 5) {
$retval = sprintf("MaskMSW: 0x%04x",$val);
}
if ($cmd ==6) { $retval = sprintf("Thin Detector Amplitude Disc: %d",$val); }
if ($cmd ==7) { $retval = sprintf("Thick Detector Amplitude Disc: %d",$val); }
if ($cmd ==8) { $retval = sprintf("Electrical Cal Amplitude: %d",$val); }
return $retval;
}
########################################################################
# Pod follows
########################################################################
=for html
CRaTER -- c_monitor
=head2 NAME
c_monitor -- Receives CRaTER {tag,value} data from rtlm and formats an
HTML page with Secondary Science and Housekeeping information
=head2 USAGE
c_monitor [-h] [-s] [-r htmlform] [-v] [-w webout]
=head2 FLAGS
-h prints this help message
-r reads this file to get master HRML form [master.html]
-s forces 1 second cadence in processing input data packets
-v verbose operation
-w writes HTML to given file name [index.html]
=head2 DESCRIPTION
The program receives rtlm ASCII data processed by calcurve
and generates a web page. To do this it takes a master HTML form
which has embedded in it names of the form _tag_, where "tag" is
a data name defined by rtlm. The data values retrieved by this
program are formatted for display and replace the original name.
The master HTML form is only read once upon program start; if the
form is not specified in the command line, it is
taken from the current directory (first choice) or the directory
pointed to by the environment variable CRATERTOOLS.
By default data is taken from STDIN. The ouput is written only upon
receipt of a housekeeping packet (AppId 122), which is once every
16 seconds in the normal LRO configuration. The web page itself has
an embedded refresh command set to 8 seconds and, lacking a B<-s> flag,
will be written to STDOUT. If housekeeping packets fail to update in
less than a minute, a B message is set in the display.
If the B<-s> flag is used, a 1 second delay is imposed after each
housekeeping packet is read. (A second B<-s> flag will raise the
delay to 16 seconds.) This will be useful
for reading archived data files from an B<"rtlm -a -t -c | calcurve">
pipeline. NB that the B alarm is not implemented when this
flag is used.
=head2 BUGS
It's early.
=head2 SEE ALSO
=head4 High Level programs
CWeb
=head4 Low Level programs
calcurve, rtlm
=head2 AUTHOR
Bob Goeke
=head2 RCS Information
$Id: c_monitor,v 1.13 2008/08/26 19:05:20 goeke Exp goeke $
=cut
########################################################################
# history follows
########################################################################
# $Log: c_monitor,v $
# Revision 1.13 2008/08/26 19:05:20 goeke
# Use tmp file and (un)link to reduce the web uncertainty
#
# Revision 1.12 2008/06/30 14:27:16 goeke
# Added bus voltage, power
#
# Revision 1.11 2008/06/20 15:23:46 goeke
# Add time zone mnemonic
#
# Revision 1.10 2008/06/10 13:23:18 goeke
# Search for monitor.html
#
# Revision 1.9 2008/05/02 15:31:18 goeke
# Changed logic so that -t arg is used to force a repost
#
# Revision 1.8 2008/05/01 18:29:00 goeke
# Add Refresh variable
#
# Revision 1.7 2008/04/23 17:55:02 goeke
# Fixed bug in display of Mask feedback and echo cmd "mask"
#
# Revision 1.6 2008/04/22 19:51:38 goeke
# Simplify HTML structure by using ..
#
# Revision 1.5 2008/04/22 14:32:57 goeke
# Redefined flags, deleted read-from-file, added 16 second delay
# separated out sleep() and alarm() functions
#
# Revision 1.4 2008/04/22 12:42:17 goeke
# Changes in documentation, default output file
# Added "stale" flag timer
#
# Revision 1.3 2008/04/18 19:25:26 goeke
# A working package
#
# Revision 1.2 2008/04/17 20:17:58 goeke
# In progress; it works
#
# Revision 1.1 2008/04/17 18:02:49 goeke
# Initial revision
#