シリアルポートストリーミング/BashまたはCスクリプト

シリアルポートストリーミング/BashまたはCスクリプト

250ミリ秒ごとにデータを出力するシリアルデバイス(速度レーダ)があります。

これが私がデバイスに持っているものです:

1. Speed Packet Protocol
The Radar message packet consists of 7 bytes @ 1200 baud, no parity, 8 data bits, 1 start
bit. Messages are paced at 250mS intervals and are sent whether there is a target or not.
Char Description
1 <STX> Start of message
2 Status Radar status, as defined below
3 Patrol Speeds in binary from 4 to 255, Speed values below 4 are treated as
zero.
4 Target
5 Lock
6 Alt Alternate speed, as defined below
7 <ETX> End of message
1.1. Radar status byte
Bit Description/function if set
0 Low voltage error
1 Radio frequency interference error
2 Front antenna
3 Rear antenna
4 Moving mode
5 Alternate mode (fastest or slow)
6 Opposite direction mode
7 Always set (Indicated a speed packet)
Neither antenna being selected indicates standby.
Both antennae selected indicates a self-test is in progress. Test results are not sent, the
radar either returns to normal operation if successful or ceases communication in the
event of failure.
1.2. Alternate Speed
If the alternate mode bit is set, the alternate speed should be displayed. This will be
fastest if in opposite direction or slow if in same direction.
1.3. Message Receipt
Each message received should be time stamped and removed after 1 second if it has not
been replaced by a new message. The only exception is the self-test message, which
allows 8 seconds for the test to complete.
1.4. Example
Received sequence 02, 244(0xf4), 50, 99, 75, 01, 03.
Front antenna, moving mode, fastest mode, opposite direction mode, patrol speed of 50,
strongest target at 99, a locked speed of 75 and a no fastest target (since the value is
less that 4). 

使用:

minicom -b 1200 -D /dev/ttyUSB0 -8 -H -w

0を読み取ると、データは次のようになります。

02 c8 00 00 00 00 03

他の内容を読む場合:

02 c8 00 16 00 00 03

または

02 c8 00 0f 00 00 03

したがって、次のように見えます。

//How do I pipe the stream into the script??
"Get String Code Here"
//example string
$string=02 c8 00 16 00 00 03
//remove first part
$prefix=02 c8 00
//remove last part 
$suffix=00 00 03
//result which appears to be a hex value
$result=16 (22MPH)
//convert $result to decimal

echo $result to monitor/file/database

私はさらにうまく機能したいCスクリプトを見つけました。

    #include <stdio.h> /* Standard input/output definitions */
    #include <string.h> /* String function definitions */
    #include <unistd.h> /* UNIX standard function definitions */
    #include <fcntl.h> /* File control definitions */
    #include <errno.h> /* Error number definitions */
    #include <termios.h> /* POSIX terminal control definitions */



//Initialize serial port
int initport(int fd)
{
    int portstatus = 0;

    struct termios options;
    // Get the current options for the port...
    tcgetattr(fd, &options);
    // Set the baud rates to 115200...
    cfsetispeed(&options, B1200);
    cfsetospeed(&options, B1200);
    // Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);

    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    //options.c_cflag |= SerialDataBitsInterp(8);           /* CS8 - Selects 8 data bits */
    options.c_cflag &= ~CRTSCTS;                            // disable hardware flow control
    options.c_iflag &= ~(IXON | IXOFF | IXANY);           // disable XON XOFF (for transmit and receive)
    //options.c_cflag |= CRTSCTS;                     /* enable hardware flow control */


    options.c_cc[VMIN] = 0;     //min carachters to be read
    options.c_cc[VTIME] = 0;    //Time to wait for data (tenths of seconds)


    // Set the new options for the port...
    //tcsetattr(fd, TCSANOW, &options);


    //Set the new options for the port...
    tcflush(fd, TCIFLUSH);
    if (tcsetattr(fd, TCSANOW, &options)==-1)
    {
        perror("On tcsetattr:");
        portstatus = -1;
    }
    else
        portstatus = 1;


    return portstatus;
}


/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int open_port(void)
{
    int fd; /* File descriptor for the port */
    fd = open("/dev/ttyUSB0", O_RDONLY | O_NOCTTY | O_NDELAY);

    if (fd == -1)
    {
        /*
        * Could not open the port.
        */
        perror("open_port: Unable to open /dev/ttyUSB0 --- \n");
    }
    else
        fcntl(fd, F_SETFL, 0);

    return (fd);
}

int main(void)
{

    int serial_fd = open_port();

    if(serial_fd == -1)
        printf("Error opening serial port /dev/ttyUSB0 \n");
    else
    {
        printf("Serial Port /dev/ttyUSB0 is now open \n");

        // READ PORT DATA 


        if(initport(serial_fd) == -1)
        {
            printf("Error Initializing port");
            close(serial_fd);
            return 0;
        }

        sleep(.5);
        //usleep(500000);
        //printf("size of data being sent = %ld", sizeof("~ver~\n\r"));

        sleep(.5);
        //usleep(500000);

        printf("\n\nNow closing Serial Port /dev/ttyUSB0 \n\n");

        close(serial_fd);
    }


    return 0;
}

ベストアンサー1

私の考えに必要なものは次のとおりです。

"Get String Code Here"  
string="02 c8 00 16 00 00 03"  
result=$(echo ${string} | cut -w -f 3)  

ただし、これは16進数であるため、比較が難しくなります。

decimalresult=$(printf "%d" 0x${result})  

もちろん、これを一行で行うこともできますが、明確にするためにこの方法で行います。

修正バージョン

スクリプトの一部として読まなければならない連続ストリームがあると言われました。シェルスクリプトは通常1行ずつ読み取るので、次のようにします。

  • minicomその出力を使用してスクリプトにパイプすることができます。-Hシェルスクリプトはバイナリファイルをうまく処理できないため、このオプションを使用して16進出力を取得します。このように:
    minicom -b 1200 -D /dev/ttyUSB0 -8 -H -w | this_script
  • 入力はパイプで接続され、ddメッセージを構成する塊に分割され、最後に改行が追加されます。
  • これにより、1行に7つの項目を読み取り、4番目の項目を除くすべての項目を無視するループが始まります。
  • 16進数を10進数に変換して出力します。

    dd conv=unblock cbs=21 | while read x x x hexresult x x x ; do decimalresult=$(printf "%d" 0x${hexresult}) echo ${decimalresult} done

まだ連続ストリーミングを試していないため、少し調整が必要な場合があります。特に、obs=21パラメータを追加する必要があるかもしれませんdd(21ではなく20でもあります)。

おすすめ記事