The Lake Level Box on the Website

This note explains how the small box on the deepcreekanswers.com website, that shows the current level of the lake, is created.

Every 10 minutes the deepcreekhydro website is queried for the lake level and generator status information by a Ruby script called "lakelevel.rb". This script is described in a separate note. The result is a new data record that is appended to the existing "hydroreadings.txt" file. Also created is a tiny file with that same latest record. This file is called "levelstatus.txt". An example of the content of this file is:

Mon Feb 11 08:25:23 -0500 2013  OFF 2457.9  2/7/2013 23:00  OFF  2/11/2013 08:23

This record contains the following pieces of information:

  1. The date and time this data record was created
  2. The status of the hydro-electricgenerator
  3. The level of the lake in ft above mean sea level
  4. The date and time the generator status last changed
  5. The status of the generator
  6. The date and time the lake level gage was last read

The information in this tiny file forms the basis for the lake level box on the website.

After this tiny file is created the script "lakelevelbox.rb" is launched. It reads the "levelstatus.txt" and the "Rule_Band.csv" files, processes them, and writes the file "i_leveldata.php" file. This file is then uploaded to the website, where it is automatically integrated with the website.

A shell script, "lakelevel.sh" that is regularly run by a system deamon every 10 minutes, controls this sequence of script launches. It's a fairly simple file containing the following instructions:

#!/bin/bash
ruby /Users/frostypiet/ruby/lake_level.rb
R < /Users/frostypiet/ruby/lakelevelbox.R --no-save

/usr/bin/ftp -d www.ridgeviewvalley.com << ftpEOF
   prompt
   asci
   cd public_html/deepcreekanswers/i_files
   lcd /Users/frostypiet/ruby
   put i_leveldata.php
   quit
ftpEOF

What follows is the description of the "lakelevelbox.rb" script.

As with all of the scripts it starts with a bit of authorship and history information.

# Title:       The data file for the water level box
# Description: Create the file with the JavaScript settings for the alert box on the home page of Deep Creek Answers
# Date:        30/1/2013
# Project:     Deep Creek Answers website data
# File:        lakelevelbox.R
# Author:      Pete Versteegen
# Revised:     3/5/2013

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

Next are the specifications of the varioua files that are used and some initialization

# File specifications:
#singlerecord <- "/Users/frostypiet/ruby/levelstatus.txt"     # File with a single record of the most recent lake level reading
#rule_band    <- "/Users/frostypiet/ruby/Rule_Band.csv"       # File with rule band limits
#levelbox     <- "/Users/frostypiet/ruby/i_leveldata.php"     # File name with the results of the data for the water level box

singlerecord <- "/Users/frostypiet/ruby/levelstatus.txt"     # File with a single record of the most recent lake level reading
rule_band    <- "/Users/frostypiet/ruby/Rule_Band.csv"       # File with rule band limits
levelbox     <- "/Users/frostypiet/ruby/i_leveldata.php"     # File name with the results of the data for the water level box

months <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Dec")

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

Both the rule band data and the current lake level information is read in next

# Read the upper and lower rule band data
ruleband <- read.csv(file=rule_band, head=TRUE, sep=",")
attach(ruleband)
low_band <- LOWER_BAND
upr_band <- UPPER_BAND

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2
# Read the record of the most recent lake level reading
con     <- file(singlerecord, "rt")
nowlevel <- readLines(con,1)
close(con)

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

Next the lake level record is decoded into the four elements that are needed:

  1. The date of the last gage reading
  2. The status of the generator
  3. The month of the latest reading (needed to retrieve the rule band data)
  4. The water level of the lake
# Extract the needed information from the latest record

# Split the record at the tab values
x <- unlist(strsplit(nowlevel, "\t"))

s <- unlist(strsplit(x[4], " "))

status <- paste("Status: ", s[4], sep="")

x[5] # Holds date and time fields for water level 
y <- unlist(strsplit(x[5], split=" "))

dat <- as.Date(y[1], "%m/%d/%Y")  # Converts to internal date format - must know character format

leveldate <- as.character(dat, "%d %b %Y")  # Convert to print format
level     <- as.numeric(x[3])
mo        <- as.character(dat, "%b")
index     <- which(months==mo)

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

Next we check to see if the rule bands are violated. If they are the coloring of the appropriate elements are set.

Also the box elements are positioned in the appropriate locations.

# Check for upper or lower rule bands transgression and set color if there is

upr_b <- print(formatC(upr_band[index], digits=1,format="f", flag="#"))

levl <- print(formatC(level, digits=1,format="f", flag="#"))

low_b <- print(formatC(low_band[index], digits=1,format="f", flag="#"))

clr1 <- "black"
clr2 <- "black"
clr3 <- "black"
if(as.numeric(level) > as.numeric(upr_band[index])) clr1 <- "lime"
if(as.numeric(level) < as.numeric(low_band[index])) clr2 <- "lime"
if(s[4] == "ON") clr2 <- "white"

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

Since the website is slowly migrating towards HTML5 the box is created with the canvas element which require its instructions to be in JavaScript. This is done in the section below.

# Create JavaScript representations
a1 <- paste("var cdate = '", leveldate, "';", sep="")   # JavaScript - date
a2 <- paste("var ctime = '", y[2], "';", sep="")        # JavaScript - time
a3 <- paste("var uband = '", upr_b, "';", sep="")       # JavaScript - upper rule band limit
a4 <- paste("var level = '", levl, "';", sep="")        # JavaScript - lakelevel
a5 <- paste("var lband = '", low_b, "';", sep="")       # JavaScript - lower rule band limit
a6 <- paste("var status = '", status, "';", sep="")     # JavaScript - generator status
a7 <- paste("var clr1 = '", clr1, "';", sep="")         # JavaScript - upper rule band limit color
a8 <- paste("var clr2 = '", clr2, "';", sep="")         # JavaScript - lower rule band limit color
a9 <- paste("var clr3 = '", clr3, "';", sep="")         # JavaScript - generator status color

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

An finally the results are written to the file "i_leveldata.php".

# Write the php file
fileConn <- file(levelbox, "w")  # open an output file connection
writeLines(a1, fileConn)
writeLines(a2, fileConn)
writeLines(a3, fileConn)
writeLines(a4, fileConn)
writeLines(a5, fileConn)
writeLines(a6, fileConn)
writeLines(a7, fileConn)
writeLines(a8, fileConn)
writeLines(a9, fileConn)
close(fileConn)

#########1#########2#########3#########4#########5#########6#########7#########8#########9#########9#########1#########2

An example result of the content of the "i_leveldata.php" file is:

var cdate = '11 Feb 2013';
var ctime = '09:34';
var uband = '2457.9';
var level = '2458.0';
var lband = '2456.0';
var status = 'Status: OFF';
var clr1 = 'lime';
var clr2 = 'black';
var clr3 = 'black';