Difference Bearing Calculator in PHP

A long standing application checks the actual weather reports for various UK airfileds and then compares to a forecast. One of the variables is the wind direction.

The application compares a compass bearing for the actual and forecasted wind direction and then states the difference in degrees. All sounds easy. Alas the first release of PHP code for this seemed to be incorrect for the fourth quarter (i.e. Q4 is between 270 and 360 degrees).

Here’s the code that has now been proven to work.

Function FindBearing( $forecast, $actual )
{

    if ($actual == "VRB") { 
        // the forecast has variable so we return zero 
        // as it could be anything given the winds are light, 
        // that's not something we can handle
        return 0;
    }
    
    if  ($forecast <= 180 ) { // in Q1 or Q2
        if ( $actual <= 180 ) { // in Q1 or Q2
            return abs($actual - $forecast);
        } 
        // forecast in Q3 or Q4
        return 180-abs((360-$actual)-abs(180-$forecast));
        
    } else { // forecast in Q3 or Q4
        if ( $actual > 180 ) { // forecast in Q3 and Q4 as well so easy
            return abs($actual - $forecast);
        }
        
        // forecast in Q3 or Q4 and forecast in Q1 and Q2
        $result = abs($actual - $forecast);
        
        if ($result <= 180){
            return $result;
        }
        return 180 - abs(180-$result);
    }

    // else return a bearing that isn't possible     
    return "-1";
}

The function can be tested by using this simple PHP script:


for ($i = 0; $i <= 360; $i=$i + 1) {
        for ($j = 0; $j <= 360; $j=$j + 1) {
            $diff = FindBearing( $i, $j );
            
            echo "
forecast=$i, actual=$j, diff=$diff"; if (($diff < 0) || ($diff>180)){ echo "ERROR"; } } }

Unix Shell CGI Script using find, stat or xarg for File Listing

This little code snippet was required to find out the date and time for files for use in a CGI script.

It uses a conventional shell script to start with, setting some local variables to use in the script. It then outputs the HTML content type to enable CGI working.

After that it it uses find with the output as a printf statement. The nice thing about using printf is that we can just select the name of the file without the full path (you don’t want to tell the world exactly where it lives!).

 #!/bin/sh
 RUNPATH=/home/
 PATTERN=
 NOW=$(date +"%H:%M:%S %d-%h-%Y")
 echo "Content-type: text/html"
 echo ""
 echo ""
 echo "
"
 echo "

Production Times and Sizes at $NOW

" echo "
"
 find $RUNPATH -name "$PATTERN*" -printf "%AD %Ar %10s %f\n"
 echo "
"

And that’s it!

You can change the format specifiers in the printf to suit what you want.

A sample output looks like this:

Production Times and Sizes at 13:31:07 04-Jul-2013

07/04/13 08:04:31 AM      77956 00fcst-movie-FULL-UK2.flv
07/04/13 06:20:23 AM      61540 00fcst-movie-FULL-UK2.wmv
07/04/13 06:20:22 AM     124996 00fcst-movie-FULL-UK2.avi
07/04/13 11:30:06 AM    8061942 00fcst-movie-FULL-UKEA62-WINDOW.wmv
07/04/13 11:30:05 AM    6447314 00fcst-movie-FULL-UKEA62-WINDOW.avi
07/04/13 11:30:06 AM    4371525 00fcst-movie-FULL-UKEA62-WINDOW.flv
07/04/13 11:41:05 AM    4409202 00fcst-movie-FULL-UK4.flv
07/04/13 07:05:02 AM    8527096 00fcst-movie-FULL-UK4.wmv
07/04/13 07:05:02 AM   11068020 00fcst-movie-FULL-UK4.avi

You can of course consider using stat and xarg, by replacing the tail of the find like this if you do want the full path:

find $RUNPATH | grep $PATTERN | xargs stat -c "%y %10s %n"

Unix Shell Script Checking BST/GMT

A problem over the last weekend when the clocks went forward, showed there was a need to do resolve to how the GMT cron jobs should work on a few servers working together (when timing is important).

For a couple of years I simply changed the hour in the crontab on each server and left it at that, but alas this is open to error across multiple severs, so I decided to do something about it.

The first step was to put the cron table into GMT hours (i.e. ensure all jobs would run as GMT as normal). The next step was to introduce for the “morning run” of work, a check to sleep for an hour if the server is in British Summer Time (BST). We can find this out by using:

date

Which can give an output like this:

Mon Apr  1 12:17:55 BST 2013

All we want is the local time zone daylight savings flag and then do something if that is BST. We can get just this flag if we use the %Z parameter to the date command.

Here’s a little bit of code to wait if we’ve run in GMT but need to wait an hour due to BST:

# --- GMT checking - we assume run in GMT timeframe
SLEEPPERIOD=3600
GMTBST=`date '+%Z'`
if [ $GMTBST == BST ]
then
        # must be in summertime, so wait an hour
        echo "Found the date has $GMTBST. Sleeping for $SLEEPPERIOD seconds ..."
        sleep $SLEEPPERIOD
else
        echo "Not BST, carrying on"
fi

This is then done for the afternoon run and the same again for the evening run.

Note this may cause a problem if multiple scripts check this as they may get serial delays. This works best if you have one main job, and the check is done once.

So now the script will check if it is GMT or BST and wait an hour if BST.

Simple Shell Script – File if-then-else

Problem

An annoyance with one of my Raspbery Pi computers is that the two USB weather stations it is connected to sometimes lose USB connectivty and appear on a different file handle. The USB port (either /dev/ttyUSB0 or /dev/ttyUSB1 then re-enuermates on a different file handle in the /dev folder.

Aside from fixing the issue in the firmware or kernel on the Pi (being investigated), a temporary fix is to restart the Pi when /dev/ttyUSB2 appears.

Solution

The soultion used is to have a script that checks if a new USB file handle appears and then reboot if that happens. We also need to check every five minutes if this happens because the weather station sends reports every 10 minutes and we need to ensure that it continues to do that in time.

So, that means a cron job and a shell script and here they are …

Shell Script (check-usb.sh)

Here’s the script in full:

 #!/bin/sh
 LOGFILE=/home/pi/cgi-bin/log/check-usb.log
 USB0=/dev/ttyUSB0
 USB1=/dev/ttyUSB1
 USB2=/dev/ttyUSB2
 USB3=/dev/ttyUSB3
 TIMENOW=$(date)

 if [ -e "$USB0" ] && [ -e "$USB1" ]
 then
  echo "$TIMENOW: $USB0 and $USB1 found"
  echo "$TIMENOW: $USB0 and $USB1 found" >> $LOGFILE
  echo "$TIMENOW: Exit normally"
  echo "$TIMENOW: Exit normally" >> $LOGFILE
  exit 0
 fi
# If get to here check for others
 if [ -e "$USB2" ] || [ -e "$USB3 ]
 then
  echo "$TIMENOW: $USB2 or $USB3 found"
  echo "$TIMENOW: $USB2 or $USB3 found" >> $LOGFILE
  echo "$TIMENOW: USB re-numerated - reboot required"
  echo "$TIMENOW: USB re-numerated - reboot required" >> $LOGFILE
  /sbin/reboot
 fi

A log file is also included as that’s a useful diagnostic tool – don’t forget to use logrotate to chop it from time to time. The key bit is to do a shell if using -e to see if the file handle to the USB device is still there. As there are two USB devices to worry about (two file handles), use a logical or to ensure they are both there. Otherwise, something is broken so then do a reboot having logged that fact to the log file for later review.

Right, that takes care of the checking, now the cron job.

Cron Job

I set this to run as a root cron job (crontab -e to put this in your cron table for root). This ensures no problems with permissions and also means that root is rebooting and not anyone else.

#check every 5 mins if USB 0 or USB 1 get re-enumerated
#if USB0 or 1 disappears reboot to resync
*/5 * * * * /home/pi/cgi-bin/check-usb.sh

That should get around the problem until a patch is available for the loss of USB enumeration.

PHP: using from the shell command line (use php-cli)

A long-running project uses PHP for the somewhat slow creation of some databases tables and dynamic javascript arrays.

The shell script that calls the PHP uses curl to make the scripts work. Alas the hosting provider offers a shared service and the PHP scripts often time out.

A way to run your scripts that rely on HTTP $_GET, is to use php-cli as the engine and not the normal PHP processor. In this way, you can test your PHP scripts from the command line as if they are pulled using HTTP.

Be aware that this needs to be enabled for your system and that there is normally a separate php.ini file for it.

The original post has gone, but more info here.