Count changes and save to log file

I own an electricity meter which is sending 800 impulses per kWh of the power usage. I used to connect it to the Arduino board which was counting these impulses and sending them to my server to save the amount of electricity used every minute. Unfortunately, my Arduino board is now broken. On the other hand, I found Onion Omega2+ lying in my drawer so I made use of it.

Basics

The script I wrote is designed to count changes on GPIO of the Onion Omega. The fact is that you can use it to track change to any value provided by any program in Linux. I wrote it for ash command interpreter which is used by most of BusyBox powered devices, but you can also adjust it to work with bash or sh in regular Linux distributions.

The command I’m using is fast-gpio read 11 which is simply reading the state of GPIO pin 11 and returns the information in such format: > Read GPIO11: 1 I had to extract only the value from this string so I used “awk ‘{print $4}'” to get 4th piece of the output. The whole command in my script is saving the value to the variable so it looks like CUR=$(fast-gpio read 11 | awk '{print $4}').

Change detection

My script is running in the infinite loop, checking the current value of the GPIO pin and if the value changed, it performs additional actions. To be precise – if the value changes from 0 to 1, it saves the information into the log file. The piece of code which is handling the whole operation looks like this:

PREV=0
CUR=1

while true
do
  CUR=$(fast-gpio read 11 | awk '{print $4}')
  if [ $CUR != $PREV ] ; then
    PREV=$CUR
    if [ $CUR == 1 ] ; then
      echo "1" >> gpio-$(date +"%Y%m%d")-$(date +"%H%M").log
    fi
  fi
done

I decided to write my logs in files which are named using date and time – one file per minute. This gives me precise information about the electricity usage but is also producing 1440 files per day – I will address this later.

The code above is running in the infinite loop. Theoretically, you can start it at the boot time and it will run forever. As you know, nothing in computers world lasts forever and this means that my script is crashing from time to time due to the error of some kind or simply freezes.

I tried to execute it using the cron job (every five minutes and stop it after these five minutes), but it surfaced that the cron on Omega is not that stable – it is skipped every now and then, I can not rely on the execution made by it.

Cron issue workaround

Finally, I decided to run my script every minute, but check if the older instance is still running or not. The script is saving the current date to the separate log file every now and then, which means that when the script is broken or freezes, the time in the log is not changed. The only thing I have to do now is to check last value saved in this separate log file and compare with the current time. If the difference is greater than 2 minutes, my script assumes that there is something wrong and another instance of GPIO script starts. Otherwise, the script assumes that the old instance is still running and exits.

#
# check if still runing
#
LOGFILENAME=lastrun.log
CURTIMESTAMP=$(date +"%Y%m%d%H%M")
while read -r LINE
do
  DIFFERENCE=$(($CURTIMESTAMP - $LINE))
  if [ "$DIFFERENCE" -lt "2" ] ; then
    echo "$(date +"%Y%m%d-%H%M%S") Still runing"
    exit 1
  fi
done < "$LOGFILENAME"
#
# check status
#
PREV=0
CUR=1
fast-gpio set-input 11
while true
do
  CUR=$(fast-gpio read 11 | awk '{print $4}')
  if [ $CUR != $PREV ] ; then
    PREV=$CUR
    if [ $CUR == 1 ] ; then
      echo "1" >> gpio-$(date +"%Y%m%d")-$(date +"%H%M").log
      echo "$(date +"%Y%m%d%H%M")" > lastrun.log
    fi
  fi
done

The above code shows the method I used. The script is reading the contents of the lastrun log and compares it with the current time. Please note that the lastrun log is now updated along with the GPIO status log in the very same loop.

Sending stats to the remote machine

I will not try to handle my electricity stats locally. I want them to be processed and stored on my remote server. This means that I have to send my log files and get rid of old files on regular basis. To handle this I created the separate cron job which is running every 30 minutes and which is performing the following operations:

rsync -urtv -e 'ssh -i .ssh/id_rsa' /gpiostats/ [email protected]:/gpiostats/
find /gpiostats/* -mtime +0 -exec rm '{}' \;

Rsync is taking care of sending files through SSH (please note that I’m using passwordless connection). The second line is the cleanup of the old files. The “-mtime +0” is causing find command to list files older than 24 hours – they are simply removed.

The next thing I have to do is to import contents of log files (number of impulses) to the database on the server. But this will be described in the separate article 🙂

Important update: 2018-07-11

It surfaced that the Onion Omega2+ is not working reliably with my script. Instead of adjusting it, I decided to switch to ESP8266 which is also really easy to handle.