2016-02-14 3 views
0

Недавно я купил фрагмент радиостанции - https://www.wirelessthings.net/slice-of-radio-wireless-rf-transciever-for-the-raspberry-pi, с которым я подключился к своему серийному порту в RPi с Raspbian.RPi: скрипт Bash при прохождении цикла чтения после первой строки

У меня есть датчик температуры + влажности, который подключается к Slice of Radio и периодически отправляет строку символов с несколькими данными, которые могут быть прочитаны в RPi из последовательного порта (/ dev/ttyAMA0).

Чтобы прочитать эту информацию и использовать ее, я решил написать сценарий Bash. Эта информация передается в конкатенации с 12-символьными строками, и каждая строка всегда начинается с фиксированного набора символов (в случае aSD).

Этот сценарий Bash должен работать в бесконечном цикле, чтобы гарантировать, что вся информация, которая отправляется периодически, захватывается и обрабатывается как следует.

Для этой цели небольшой скрипт работает правильно:

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

и выводит следующее (каждая строка 4 является информация, мне нужно):

[email protected]:06:12 
    1= 
    2= 
    3= 
    4= RHUM77.0- 
    5= 
    [email protected]:06:12 
    1= 
    2= 
    3= 
    4= TEMP20.0- 
    5= 
    [email protected]:11:08 
    1= 
    2= 
    3= 
    4= RHUM77.0- 
    5= 
    [email protected]:11:08 
    1= 
    2= 
    3= 
    4= TEMP19.9- 
    5= 
    [email protected]:11:08 
    1= 
    2= 
    3= 
    4= BATT3.32- 
    5= 
    [email protected]:11:08 
    1= 
    2= 
    3= 
    4= 
    5= LEEPING- 

Еще тогда, если я бегу следующий сценарий (упрощенная версия):

!/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 +%[email protected]%X` 
    msgid=$(/bin/echo $value | cut -c1-4) 
    echo $msgid 
    if [ "$msgid" = "TEMP" ]; then 

    #Write current temperature to log file 
    log=`/bin/date -u +%[email protected]%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 +%[email protected]%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 +%[email protected]%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 +%[email protected]%X` 
    log+=" | Values sent to xively.com" 
    /bin/echo $log>>$log_file 

    done < /dev/ttyAMA0 

Это все, что он обрабатывает эс:

RHUM 
    RHUM 
    RHUM 

Если я вынимаю последний блок кода (для отправки значения в xively.com), он показывает (что мне нужно):

RHUM 
    TEMP 
    RHUM 
    TEMP 
    RHUM 
    TEMP 

я провел много времени, пытаясь выяснить, почему цикл не проходит через все записи и обрабатывает только первый.

Может ли кто-нибудь пролить свет или предоставить любую рабочую альтернативу?

Заранее благодарим за любую помощь.

+0

Можете ли вы показать исходный вход? Когда вы говорите: «Это все, что он обрабатывает» - вы имеете в виду, что «RHUM» является выходом? «он показывает [...], что мне нужно» - не могли бы вы быть конкретными в том, что вам нужно? – dancancode

+0

RHUM - это выход для первой строки, так как это результат только ECHO, который у меня есть в программе.TEMP - это выход для второй строки, поэтому я ожидаю, что он появится сразу после RHUM. В принципе, мне нужно обработать каждые 12 символов в виде строки ... – user5923286

ответ

1

Я редактировал сценарий для ясности и запускал его против ввода, который я сделал на основе вашего первого набора выходных данных. Я не думаю, что цикл пропускал записи - возможно, вход не соответствовал ожидаемому. Следующая версия отображает исходные данные в файл, поэтому вы можете проверить результаты по исходным данным.

#!/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 +%[email protected]%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 

Важным изменением является то, что этот скрипт не изменяет IFS. Каждый символ IFS является разделителем. Хорошим примером этого является LEEPING- для char5, когда вход был (предположительно) aSDSLEEPING-. Вместо этого этот скрипт использует встроенную функцию подстроки bash для расширения параметров.

Я оставил вращение журнала, потому что я хочу предложить вам войти в syslog в долгосрочной перспективе. Команда logger отправит сообщение в syslog. В большинстве систем эти журналы уже повернуты на регулярной основе.

+0

Ваше предложение отлично работает: переход от IFS для использования встроенной подстроки bash для расширения параметров определенно сделал трюк. У меня есть дополнительный вопрос для вас: учитывая, что я никогда не знаю, сколько всего числа отправлено на каждой итерации (может быть 24 - RHUM и TEMP или более - RHUM, TEMP, BATT), есть ли способ определить, когда я достиг конец строки, чтобы узнать, что моя обработка для этой строки завершена? – user5923286

+0

Угадайте (у меня нет ни одного из них), если вы сделали одно чтение без ограничения по размеру, оно будет потреблять все имеющиеся в то время символы. Затем вы можете использовать цикл for для работы по каждому десятку символов, например 'while read -r buf; do for ((i = 0; i <$ {# buf}; i + = 12)); do echo $ {buf: i: 12}; сделанный; done dancancode

+0

К сожалению, запуск 'read -r' on/dev/ttyAMA0 никогда не заканчивается (из того, что я мог понять из запуска скрипта с' bash -x'), поэтому ваш пример не дает данных. Любая другая идея? – user5923286

Смежные вопросы