user5923286
user5923286

Reputation: 13

RPi: Bash script while read loop fails after first line

I recently bought a Slice of Radio - https://www.wirelessthings.net/slice-of-radio-wireless-rf-transciever-for-the-raspberry-pi, which I connected to my serial port in an RPi with Raspbian.

I have a temperature+humidity sensor which connects to the Slice of Radio and periodically sends a string of characters with several information, which can be read in the RPi from the serial port (/dev/ttyAMA0).

To read this information and make use of it, I decided to write a Bash script. This information is transmitted concatenated with 12-char strings and each string always starts with a fixed set of characters (in the case, aSD).

This Bash script is supposed to be running in an infinite loop, to make sure that all the information that is sent periodically, is captured and processed as it should.

For that purpose, the following small script works properly:

    #!/bin/bash
    IFS='aSD'
    while read -r -n 12 char1 char2 char3 char4 char5
    do
    date=`/bin/date -u +%F@%X`
    echo $date
    echo  "1= ""$char1"
    echo  "2= ""$char2"
    echo  "3= ""$char3"
    echo  "4= ""$char4"
    echo  "5= ""$char5"
    done < /dev/ttyAMA0

and outputs the following (every line 4 is the information I need):

    2016-02-13@23:06:12
    1= 
    2= 
    3= 
    4= RHUM77.0-
    5= 
    2016-02-13@23:06:12
    1= 
    2= 
    3= 
    4= TEMP20.0-
    5= 
    2016-02-13@23:11:08
    1= 
    2= 
    3= 
    4= RHUM77.0-
    5= 
    2016-02-13@23:11:08
    1= 
    2= 
    3= 
    4= TEMP19.9-
    5= 
    2016-02-13@23:11:08
    1= 
    2= 
    3= 
    4= BATT3.32-
    5= 
    2016-02-13@23:11:08
    1= 
    2= 
    3= 
    4= 
    5= LEEPING-

Still then, if I run the following script (a simplified version of mine):

    !/bin/bash
    log_file="/home/pi/logs/Temp_$(date +%Y%m%d).log"
    log_file_copy="/home/pi/logs/Temp_$(date +%Y%m%d)_copy.log"
    sensor="/home/pi/sensor"

    IFS='aSD'
    while read -r -n 12 char1 char2 char3 value char5
    do
    date=`/bin/date -u +%F@%X`
    msgid=$( /bin/echo $value | cut -c1-4 )
    echo $msgid
    if [ "$msgid" = "TEMP" ]; then

    #Write current temperature to log file
    log=`/bin/date -u +%F@%X`
    log+=" | Current Temperature: "
    temp=$( /bin/echo $value | cut -c5-8 )
    log+=$temp
    log+=" ºC"
    /bin/echo $log>>$log_file
    elif [ "$msgid" = "RHUM" ]; then

    #If log file backup still exists, start by deleting it
    if [ -f "$log_file_copy" ]; then
            /bin/rm $log_file_copy > /dev/null 2>&1 &
    fi
    #If log file already exists, start by creating a backup
    if [ -f "$log_file" ]; then
            /bin/mv $log_file $log_file_copy > /dev/null 2>&1 &
    fi

    #Write current relative humidity to log file
    log=`/bin/date -u +%F@%X`
    log+=" | Current Relative Humidity: "
    rhum=$( /bin/echo $value | cut -c5-8 ) 
    log+=$rhum
    log+=" %"
    /bin/echo $log>>$log_file
    elif [ "$msgid" = "BATT" ]; then

    #Write current battery voltage to log file
    log=`/bin/date -u +%F@%X`
    log+=" | Current Battery Voltage: "
    volt=$( /bin/echo $value | cut -c5-8 )
    if [ "$volt" != "LOW-" ]; then
            volt="LOW"
            log+=$volt
    else
            log+=$volt
            log+=" V"
    fi
    /bin/echo $log>>$log_file
    fi

    #Store values to display in website - personal.xively.com
    time=`/bin/date -u +%FT%XZ`
    if [ -n "$temp" ]; then
    /bin/echo "$time,$temp">>/home/pi/cosm/sensor/temperature/cosm.csv
    fi
    if [ -n "$rhum" ]; then
    /bin/echo "$time,$rhum">>/home/pi/cosm/sensor/humidity/cosm.csv
    fi
    if [ -n "$volt" ]; then
    /bin/echo "$time,$volt">>/home/pi/cosm/sensor/voltage/cosm.csv
    fi
    /bin/bash /home/pi/cosm/sensor/upload-cosm.sh > /dev/null 2>&1 &
    log=`/bin/date -u +%F@%X`
    log+=" | Values sent to xively.com"
    /bin/echo $log>>$log_file

    done < /dev/ttyAMA0

This is all that it processes:

    RHUM
    RHUM
    RHUM

If I take out the last block of code (to send the values to xively.com), it shows (which is what I need):

    RHUM
    TEMP
    RHUM
    TEMP
    RHUM
    TEMP

I've spent a lot of time trying to find out why doesn't the loop go through all the records and only processes the first one.

Can anyone shed a light or provide any working alternative?

Thanks in advance for any help.

Upvotes: 0

Views: 222

Answers (1)

dan4thewin
dan4thewin

Reputation: 1184

I edited the script for clarity, and ran it against input I made based on your first set of output. I don't think the loop skipped records - perhaps the input didn't match what you expected. The version below captures the raw data to a file, so you can verify the outcomes against the raw data.

#!/bin/bash

PATH=/bin:/usr/bin

log_file="/home/pi/logs/Temp_$(date +%Y%m%d).log"
log_file_raw=${log_file/./_raw.}

while read -r -n 12 dozen
do
    echo -n "$dozen" >> $log_file_raw

    date=`date -u +%F@%X`
    key=${dozen:3:4}
    val=${dozen:7}
    val=${val%-}

    case $key in
    TEMP)
        log="$date | Current Temperature: $val ºC"
        csv=/home/pi/cosm/sensor/temperature/cosm.csv
    ;;
    RHUM)
        log="$date | Current Relative Humidity: $val %"
        csv=/home/pi/cosm/sensor/humidity/cosm.csv
    ;;
    BATT)
        log="$date | Current Battery Voltage: $val V"
        csv=/home/pi/cosm/sensor/voltage/cosm.csv
    ;;
    *)
        continue
    ;;
    esac

    echo "$log" >> $log_file
    echo "${date/@/T}Z,$val" >> $csv

    /bin/bash /home/pi/cosm/sensor/upload-cosm.sh > /dev/null 2>&1 &
    echo "$date | Values sent to xively.com" >> $log_file

done < /dev/ttyAMA0

exit 0

One important change is that this script does not alter IFS. Each character of IFS is a separator. A good example of this is the LEEPING- for char5 when the input was (presumably) aSDSLEEPING-. Instead, this script uses the builtin bash substring feature of parameter expansion.

I left out the log rotation, because I want to suggest you log to syslog over the long term. The logger command will send a message to syslog. On most systems those logs are already rotated on a regular basis.

Upvotes: 1

Related Questions