libgps从GPSD守护提取数据 [英] libgps for extract data from the gpsd daemon

查看:488
本文介绍了libgps从GPSD守护提取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用libgps与GPSD守护程序接口。这就是为什么我在为了从一个特定的卫星提取价值实现的一个小的测试应用程序。

I wanted to use libgps to interface with gpsd daemon. That's why I've implemented a little testing application in order to extract a value from a specific satellite.

其HOWTO页的文件告诉我们,

The documentation on its HOWTO page tells us that

最棘手的部分是跨preting您读取阻塞得到什么。
  它的棘手的原因是,你不能保证每一个阅读
  将搭载来自守护进程只有一个完整的JSON对象。它可能
  抓住一个响应对象,或一个以上的,或其中的一部分,或一种或
  更后跟一个片段。

The tricky part is interpreting what you get from the blocking read. The reason it’s tricky is that you’re not guaranteed that every read will pick up exactly one complete JSON object from the daemon. It may grab one response object, or more than one, or part of one, or one or more followed by a fragment.

根据建议的文件,做其他事情之前, PACKET_SET 屏蔽位被选中。

As recommended the documentation, the PACKET_SET mask bit is checked before doing anything else.

#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例如codeS,但libgps的精妙之处离我而去。 while循环以前添加gps_waiting(),以获得至少一个完整的响应对象。引进的pthread之前,我注意到,调用函数 test_result()就在 start_test()需要几秒钟返回一个前回答。通过使用一个线程我还以为 3 将imediately返回,那么 3 4 ..但它不是!我仍然失去了几秒钟。此外,本人自愿使用 pthread_tryjoin_np(),因为它的手册页说:

As recommended in the documentation too, I had a look at cgps and gpxlogger for example codes, but the subtleties of libgps escape me. A while loop has been added before gps_waiting() in order to get, at least, one entire response object. Before introducing pthread, I noted that call the function test_result() just after start_test() take few seconds before returning an answer. By using a thread I thought that 3 would be imediately returned, then 3 or 4 .. but it's not ! I am still losing few seconds. In addition, I voluntarily use pthread_tryjoin_np() because its man page says

该pthread_tryjoin_np()函数执行非阻塞与线程加入

The pthread_tryjoin_np() function performs a nonblocking join with the thread

任何人都可以给我他的帮助,我想我明白了什么错,但我不能说哪个部分吗?基本上,我为什么来到这个做,而返回的第一个值循环前至少四次?

Can anybody give me his help, I guess that I understand something wrongly but I am not able to say about which part yet? Basically, why I come into the do while loop at least four times before returning the first value ?

编辑1:

再次阅读文档HOWTO后,我强调的线条:

After reading the documentation HOWTO again I highlight the lines :

这是该数据等待检查和阅读这两个块意味着,如果你的应用程序来处理比GPS其他输入源,你可能要读循环用互斥锁隔离在一个线程锁定的事实在gps_data结构。

The fact that the data-waiting check and the read both block means that, if your application has to deal with other input sources than the GPS, you will probably have to isolate the read loop in a thread with a mutex lock on the gps_data structure.

我有点混乱。这是什么究竟意味着什么?

I am a little bit confusing. What does it really mean ?

推荐答案

您环路,是因为你没有睡眠状态返回一个完整的数据包之前执行多次。因此每次守护进程注册一个数据包(即使不是一个完整的NMEA消息),在 gps_waiting()函数返回。我建议你​​睡觉,只要需要您的GPS至少要注册一个完整的消息。

Your loop is executing multiple times before returning a full packet because you do not have a sleep condition. Therefore each time the daemon registers a packet (even when not a full NMEA message), the gps_waiting() function returns. I'd recommend sleeping at least as long as it takes your GPS to register a full message.

例如,如果你期望 GPPAT 消息,您可以合理预期将对邮件中12个字符。因此,在9600波特,这将需要1 /17.5秒或约57毫秒。在这种情况下,你的code可能是这样的:

For example, if you expect GPPAT messages, you could reasonably expect to have 12 characters in the message. Thus at 9600 baud, that would take 1/17.5 seconds or about 57 ms. In this case, your code could look like this:

#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 = 0;
    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 
        {
            ret = 0; // Set this here to allow breaking correctly
            usleep(50000); // Sleep here to wait for approx 1 msg
            if(!gps_waiting(&gpsdata, 1000000)) break;

            if(gps_read(&gpsdata) == -1) break;

            if(gpsdata.set & PACKET_SET)
            {
              for (i = 0; i < MAXCHANNELS && !ret; i++)
              {
                for (j = 0; j < gpsdata.satellites_visible; j++)
                {
                  if(gpsdata.PRN[i] == thread_args.ID) 
                  {
                     elevation = (int)gpsdata.elevation[i]; // Be sure to not deref structure here
                     ret = 1;
                     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);
}

另外,你可以只设置计数较高,等待完整的消息。

Alternatively, you could just set your count higher and wait for the full message.

这篇关于libgps从GPSD守护提取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆