JAVA - GPS-РЕЦЕПТОР отправляет странные/закодированные кадры в консоль

У меня есть приемник GPS, который отправляет мне кадры NMEA. Мой код извлекает их, но в очень странной форме:

введите здесь описание изображения

Я использую PuTTY для просмотра кадров NMEA, полученных моим приемником, и проблем нет.

введите здесь описание изображения

EDIT. Вот код, который я использую:

public class GPSFrame extends Observable implements Runnable
{
    static Thread myThread=null;
    static BufferedReader br;
    static BufferedWriter wr;
    static PrintWriter out;
    static InputStreamReader isr;
    static OutputStreamWriter osw;
    static java.io.RandomAccessFile port; 


    /**  CONSTRUCTOR **/
    public  GPSFrame()
    {    
         myThread=new Thread(this);
    }

    public void start()
    {
        try 
        {
            port=new java.io.RandomAccessFile("COM5","rwd");
            port.writeBytes("\r\n");
            port.writeBytes("c,31,0,0,5\r\n");
            port.writeBytes("T,1000,1\r\n");
        }
        catch (Exception e){ System.out.println("start "+e.toString()); }
        // The thread start automatically run() method
        myThread.start();
    }

/**********************************************************************************************
 *************************** RETRIEVE GPS FRAMES AND SEND TO SERVEUR **************************
 **********************************************************************************************/
    public void run() 
    {
        System.out.println("lecture COM...");
        // INFINIT LOOP - GPSFrame is always listening for the GPS receptor
        for(;;)
        {
            String st = null;
            try 
            {
                st=port.readLine();
                String[]gpsframe=st.split(",");

                /* IMPORTANT - DON'T FORGET SETCHANGED() or GPSFrame'll never
                 * notify UPDATE() ServerBoard method - We'll never see any changes */
                setChanged();
                notifyObservers(st);

            } 
            catch (IOException e){ System.out.println(e.getMessage()); }
            // Show in console
            System.out.println(st);
        }
    }   
}

ИЗМЕНИТЬ:

Когда я впервые читаю кадры GPS с PuTTY затем запускаю мое приложение, я вижу правильные кадры GPS в консоли. Но когда я пытаюсь сначала прочитать кадр GPS с помощью своего приложения, я закодировал кадры.

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

Спасибо вам заранее!

С уважением,

тофу


person Tofuw    schedule 17.12.2013    source источник
comment
Пожалуйста, добавьте свой код к вопросу.   -  person aphex    schedule 17.12.2013
comment
@aphex извините, я только что добавил свой код.   -  person Tofuw    schedule 17.12.2013
comment
Я думаю, что вы неправильно читаете из COM-порта... Попробуйте использовать readUTF8() или посмотрите этот пример из оракула: blogs.oracle.com/hinkmond/entry/rpi_and_java_embedded_gpio8   -  person aphex    schedule 17.12.2013
comment
Проверьте скорость передачи, уверен, что GPS отправляет на этой скорости?   -  person AlexWien    schedule 17.12.2013
comment
@AlexWien, думаю проблема не в этом, а скорость передачи 1000 мс. В противном случае, когда я впервые читаю кадр GPS с помощью PuTTY, а затем запускаю свое приложение, я могу правильно получить кадр GPS.   -  person Tofuw    schedule 18.12.2013
comment
@aphex, я пытался использовать readUTF(), но он отправляет мне null null null null null... для каждого кадра   -  person Tofuw    schedule 18.12.2013


Ответы (2)


Как я уже сказал в своем комментарии, вы неправильно читаете из COM-порта. Я нашел библиотеку, которая может помочь вам понять, как читать из com-порта. Код довольно старый, но я думаю, что он все еще полезен: http://javanmea.sourceforge.net/

Ознакомьтесь с этими классами: NMEAReader и CustomReader.

Существует также аналогичный поток С++, который может быть полезен. Получить данные NMEA0183 с COM-ПОРТ C++

Если найдете решение, отпишитесь. Было бы интересно на это посмотреть :)

person aphex    schedule 18.12.2013
comment
Привет @aphex, спасибо за помощь. Я только что опубликовал возможное решение :) - person Tofuw; 20.12.2013

Я нашел решение своей проблемы! :D

Мой код немного проблематичен, потому что я использовал RandomAccessFile для чтения моего COM-порта. С помощью этого метода я могу прочитать кадр, отправленный приемником, но не правильно. Чтобы решить эту проблему, мне нужно CONFIGURE the COM PORT, что невозможно с RandomAccessFile.

Я сделал тест конфигурации:

  • С DATABITS_5 или DATABITS_6 я получил такие кадры:

    $%() :2 ")1"2

  • #P5# <блочная цитата> #P6#

Я думаю, что по умолчанию Databits или настроено с 5 или 6. Это зависит от того. Поэтому лучше настроить Порт самостоятельно.

Способ (или один из способов?) для настройки COM-порта заключается в использовании SerialPort.

Вот решение, которое действительно полезно (в этом примере мы считываем данные в режиме событий, но вы можете использовать режим потока — см. 2-ю ссылку ниже для этого) :

public class GPScom implements SerialPortEventListener
{
    private String portcom;
    private CommPortIdentifier portid=null; 
    private SerialPort serialport; 
    private BufferedReader fluxgps; // Reading flow port where the GPS is connected

        public static void main(String[]args)
    {
        // Driver initialization
        Win32Driver driver=new Win32Driver();
        driver.initialize();

        GPScom gpscom=new GPScom();
        gpscom.listPort();
    }

    // Scanning all available ports
    public void listPort()
    {
        Enumeration listport=CommPortIdentifier.getPortIdentifiers();
        int typeport;
        String GPSPortCOM;

        while(listport.hasMoreElements())
        {
            portid=(CommPortIdentifier)(CommPortIdentifier)listport.nextElement();
            if(portid.getPortType()==CommPortIdentifier.PORT_SERIAL)
            {
                System.out.println("Port Name : "+portid.getName());
                System.out.println("User : "+portid.getCurrentOwner());
                System.out.println("Use ? : "+portid.isCurrentlyOwned());
                System.out.println("Port type : "+portid.getPortType());

                this.ModeEvenement(portid.getName());
            }
        }
    }

    // Initialization of the port
    public void ModeEvenement(String portcom)
    {
        // Retrieve ID Port
        try{portid=CommPortIdentifier.getPortIdentifier(portcom);}
        catch(NoSuchPortException e){System.out.println(e);}

        // Open Port
        try{serialport=(SerialPort)portid.open("ModeEvenement",2000);}
        catch(PortInUseException e){System.out.println(e);}

        // Retrieve data flow
        try{fluxgps=new BufferedReader(new InputStreamReader(serialport.getInputStream()));}
        catch(IOException e){System.out.println(e);}

        // Add listener
        try{serialport.addEventListener(this);}
        catch(TooManyListenersException e){System.out.println(e);}

        // Configure Port
        serialport.notifyOnDataAvailable(true);
        try{serialport.setSerialPortParams(4800, SerialPort.DATABITS_6, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);}
        catch(UnsupportedCommOperationException e){System.out.println(e);}

        System.out.println("Port is open, waiting for the reading");
    }

    // Here we are reading 7 frames for test
    public void ReadSerialPort()
    {
        int i=7;
        String reponse=new String();

        try
        {
            System.out.println("i="+i);
            while(i!=0)
            {
                System.out.println("Reading the COM port \n");
                reponse=(String)fluxgps.readLine();
                System.out.println(reponse);
                i--;
                System.out.println("i="+i);
            }           
        }
        catch(IOException e){System.out.println(e);}

        // On ferme le flux de lecture
        try{fluxgps.close();}
        catch(IOException e){System.out.println(e);}

        serialport.close();
    }

    public void serialEvent(SerialPortEvent event)
    {
        // We are only reading data if available
        switch(event.getEventType())
        {
            case SerialPortEvent.DATA_AVAILABLE:
                this.ReadSerialPort(); // Launching the reading if data are available
                break;
            default:
                break; // Else, do nothing
        }
    }   
}

Вот где я нашел это решение (/!\ Французские сайты: D):

Я надеюсь, что это поможет вам, если вы столкнетесь с той же проблемой, что и я

Хорошего дня !!!

тофу

PS: спасибо Aphex и AlexWien, которые помогли мне

person Tofuw    schedule 20.12.2013