gpt4 book ai didi

c - libgps 用于从 gpsd 守护程序中提取数据

转载 作者:太空狗 更新时间:2023-10-29 17:26:22 27 4
gpt4 key购买 nike

我想使用 libgps 与 gpsd 守护进程交互。这就是为什么我实现了一个小测试应用程序以从特定卫星中提取值(value)的原因。

HOWTO 页面上的文档告诉我们

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 掩码位。

#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() 之前添加了一个 while 循环,以便至少获得一个完整的响应对象。在介绍 pthread 之前,我注意到在 start_test() 之后调用函数 test_result() 需要几秒钟才能返回答案。通过使用线程,我认为 3 会立即返回,然后是 34 .. 但事实并非如此!我还在失去几秒钟。此外,我自愿使用 pthread_tryjoin_np() 因为它的手册页说

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

任何人都可以给我他的帮助,我想我理解错了,但我还不能说是哪一部分?基本上,为什么我在返回第一个值之前至少进入 do while 循环四次?

编辑 1:

再次阅读文档 HOWTO 后,我突出显示以下行:

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.

我有点困惑。它的真正含义是什么?

最佳答案

您的循环在返回完整数据包之前执行了多次,因为您没有 sleep 条件。因此,每次守护程序注册一个数据包(即使不是完整的 NMEA 消息),gps_waiting() 函数都会返回。我建议至少在您的 GPS 记录完整消息所需的时间里 sleep 。

例如,如果您期望 GPPAT 消息,您可以合理地期望消息中有 12 个字符。因此,在 9600 波特率下,这将花费 1/17.5 秒或大约 57 毫秒。在这种情况下,您的代码可能如下所示:

#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);
}

或者,您可以将计数设置得更高并等待完整消息。

关于c - libgps 用于从 gpsd 守护程序中提取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35614417/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com