6

gpsdデーモンとのインターフェースにlibgpsを使用したかったのです。そのため、特定の衛星から値を抽出するために、小さなテスト アプリケーションを実装しました。

HOWTOページのドキュメントは、それを教えてくれます

注意が必要な部分は、ブロッキング読み取りから取得したものを解釈することです。注意が必要な理由は、すべての読み取りがデーモンから完全な JSON オブジェクトを 1 つだけ取得することが保証されていないためです。1 つの応答オブジェクト、複数、またはその一部、または 1 つ以上の後にフラグメントが続く場合があります。

ドキュメントで推奨されているように、他のPACKET_SET処理を行う前にマスク ビットがチェックされます。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <gps.h>
#include <pthread.h>

pthread_t t_thread;

struct t_args {
   unsigned int ID;
};

unsigned int status = 0;
int elevation;

int p_nmea(void *targs);

void start_test(void)
{
    struct t_args *args = malloc(sizeof *args);
    status = 1;
    args->ID = 10;

    pthread_attr_t attr;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    if (pthread_create(&t_thread, &attr, (void *)&p_nmea, args) != 0)
    {
        perror("create: \n");
    }
}

int test_result(int * Svalue)
{
    int res;

    if(status == 1)
    {
        void * t_res;
        if(pthread_tryjoin_np(t_thread, &t_res) != 0)
        {
            status = 1;
        }
        else
        {       
            if((int)t_res == 1)
            {
                res = 3;
                *Svalue = elevation;
                elevation = 0;
            }
            else
            {
                res = 4;            
            }
        }
    }
    return res;
}

int p_nmea(void *targs)
{
    struct t_args *thread_args = targs;     
    struct gps_data_t gpsdata;
    int ret = -1;
    int count = 10;
    int i,j;

   if(gps_open((char *)"localhost", (char *)DEFAULT_GPSD_PORT, &gpsdata) != 0)
   {
        (void)fprintf(stderr, "cgps: no gpsd running or network error: %d, %s\n", errno, gps_errstr(errno));
        return (-1);
   }
   else
   {
        (void)gps_stream(&gpsdata, WATCH_ENABLE, NULL);
        do 
        {
            if(!gps_waiting(&gpsdata, 1000000))
            {       
                (void)gps_close(&gpsdata);
            }
            else
            {
                if(gps_read(&gpsdata) == -1)
                {
                    return (-1);
                }
                else
                {
                    if(gpsdata.set & PACKET_SET)
                    {
                       for (i = 0; i < MAXCHANNELS; i++)
                       {
                            for (j = 0; j < gpsdata->satellites_visible; j++)
                            {
                                if(gpsdata->PRN[i] == thread_args.ID) 
                                {
                                    elevation = (int)gpsdata->elevation[i];
                                    ret = 1;
                                    break;
                                }       
                            }
                            if(gpsdata->PRN[i] == thread_args.ID)
                            {
                                break;
                            }
                       }
                    }
                }
            }
            --count;
        }while(count != 0);
    }
    (void)gps_stream(&gpsdata, WATCH_DISABLE, NULL);
    (void)gps_close(&gpsdata);
    (void)free(thread_args);
    (void)pthread_exit((void*) ret);
}

ドキュメンテーションでも推奨されているように、コード例として cgps と gpxlogger を調べましたが、libgps の微妙な点はわかりません。gps_waiting()少なくとも 1 つの応答オブジェクト全体を取得するために、前に while ループが追加されました。pthread を導入する前に、応答を返すまでに数秒かかるtest_result()直後に関数を呼び出すことに注意しました。スレッドを使用すると、すぐに返されるstart_test()と思っていましたが、そうではありません。私はまだ数秒を失っています。さらに、マニュアルページにあるので、私は自発的に使用します334pthread_tryjoin_np()

pthread_tryjoin_np() 関数は、スレッドとの非ブロック結合を実行します

誰か助けてくれませんか、何か間違っていると思いますが、まだどの部分については言えませんか? 基本的に、最初の値を返す前に do while ループを少なくとも 4 回実行するのはなぜですか?

編集1:

ドキュメント HOWTO をもう一度読んだ後、次の行を強調表示します。

データ待機チェックと両方の読み取りブロックがあるという事実は、アプリケーションが GPS 以外の入力ソースを処理する必要がある場合、おそらく gps_data 構造体のミューテックス ロックを使用してスレッドで読み取りループを分離する必要があることを意味します。 .

私は少し混乱しています。それは本当にどういう意味ですか?

4

1 に答える 1