Подмена данных в ttyUSB, ошибка считывания

Рейтинг: 3Ответов: 1Опубликовано: 05.07.2023

Суть такова что есть gsm/gps модем подключенный по usb, в котором заложена ошибка счета недель. Время и позицию показывает правильно, но дата неправильно работает (отставание ровно на 1024недели) Для исправления данной проблемы на уже готовом устройстве от стороннего производителя решили написать программу которая будет получать данные из порта ttyUSB2 подменять неправильную дату на правильную и передавать их например в tty3. В устройстве найдено /dev/gps0 что является прямой ссылкой на ttyUSB2. Поэтому есть надежда что это должно сработать после изменения ссылки на подменный источник

Создана была программа:

#include <stdio.h>
        #include <fcntl.h>   /* File Control Definitions           */
        #include <termios.h> /* POSIX Terminal Control Definitions */
        #include <unistd.h>  /* UNIX Standard Definitions          */
        #include <errno.h>   /* ERROR Number Definitions           */
        #include <stdlib.h>

        int main(void)
        {
                int fd;/*File Descriptor*/
                int fd2;

                fd = open("/dev/ttyUSB2",O_RDWR | O_NOCTTY);
                fd2 = open("/dev/tty3",O_RDWR);

           

                struct termios SerialPortSettings;     

                tcgetattr(fd, &SerialPortSettings);
                cfmakeraw(&SerialPortSettings);
                if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
                    printf("\n  ERROR ! in Setting attributes");
              

                char read_buffer[512];   /* Buffer to store the data received              */
                int  bytes_read = 0;    /* Number of bytes read by the read() system call */
                int  retr;
                int i;
                while (1) {

                        retr= write(fd2,read_buffer,bytes_read);
                        tcflush(fd, TCIFLUSH);   /* Discards old data in the rx buffer  */
                        bytes_read = read(fd,&read_buffer,512); /* Read the data                   */
                        for(i=0;i<bytes_read;i++)        /*printing only the received characters*/
                                printf("%c",read_buffer[i]);

                        }
                printf("\n +----------------------------------+\n\n\n");
                close(fd); /* Close the serial port */
                return 0;
        }

Но проблема, вывод /dev/gps0 (он же и есть ttyUSB2):

>cat /dev/gps0
$GPGSV,1,1,00*79

$GPGGA,,,,,,0,,,,,,,,*66

$GPGLL,,,,,,,*7C

$GPRMC,,V,,,,,,,,,,N*53

$GPGSA,A,1,,,,,,,,,,,,,,,,*32

$GPVTG,,T,,M,,N,,K*4E

$GPGSV,1,1,00*79

$GPGGA,,,,,,0,,,,,,,,*66

$GPGLL,,,,,,,*7C

$GPRMC,,V,,,,,,,,,,N*53

$GPGSA,A,1,,,,,,,,,,,,,,,,*32

$GPVTG,,T,,M,,N,,K*4E

$GPGSV,1,1,00*79

$GPGGA,,,,,,0,,,,,,,,*66

$GPGLL,,,,,,,*7C

$GPRMC,,V,,,,,,,,,,N*53

$GPGSA,A,1,,,,,,,,,,,,,,,,*32

$GPVTG,,T,,M,,N,,K*4E

$GPGSV,1,1,00*79

Вывод и результата выполнения программы и результата cat /dev/tty3

$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPVTG,,T,,M,,N,,K*4E
$GPGSV,1,1,00*79
$GPGGA,,,,,,0,,,,,,,,*66
$GPGLL,,,,,,,*7C
$GPRMC,,V,,,,,,,,,,N*53
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPVTG,,T,,M,,N,,K*4E
$GPGSV,1,1,00*79
$GPGGA,,,,,,0,,,,,,,,*66
$GGLL,,,,,,,*7C
$GPRMC,,V,,,,,,,,,,N*53
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPVTG,,T,,M,,N,,K*4E
$GPGSV,1,1,00*79
$GPGGA,,,,,,0,,,,,,,,*66
$GPGLL,,,,,,,*7C
$GPRMC,,V,,,,,,,,,,N*53

И при этом во время запуска применяются флаги на ttyUSB2, поэтому тот становится точно таким же как и выход с программы до перезапуска устройства. Если удалить cfmakeraw (&SerialPortSettings) или вообще не применять атрибуты tcsetattr То первоисточник не страдает, но вывод программы превращается в полную кашу, с потерянными началом и концом строки и переходами

Вопрос что я делаю не так? Какой подход использовать? PS. в примерах GPS еще не нашел спутники, поэтому вывод пустой, но структура понятна, на деле там мелькает дата 191103 которая шагает каждый день, в последующем следующим шагом ее и буду подменять на нужную

Ответы

▲ 1

В вашей программе нет установки скорости порта. Если читать на 9600 порт который шлет 112500 получается каша.

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

Попробуй использовать fifo ( mkfifo('/run/gps0', 0o666) ) вместо tty. Попробуй использовать пару pty/pts если вышестоящая программа шлет команды иногда. tty совсем не то что вам нужно.