我正在解析GNSS数据,我使用的模块QuecTel BG96具有UART串口.当试图提取与消息相关联的数据时,除了时间之外,大部分数据都可以使用sscanf
来提取.
下面是一个示例消息,与下面代码中使用的相同:
"\r\n+QGPSLOC: 010842.0,32.04415,5.31028,1.7,55.0,2,150.36,0.0,0.0,
060224,03\r\n\r\nOK\r\n"
为了完整起见,以下是对这些字段的解释,如手册所示:
+QGPSLOC:<UTC>,<latitude>,<longitude>,<hdop>,<altitude>,<fix>,<cog>,<spkm>,<spkn>,<date>,<nsat> OK
- UTC是UTC时间.
格式:
hhmmss.sss
(引自GPGGA句子).
问题是,第一组数字表示时间为hhmmss.sss
,提取时始终为0
.
Expected output:个
240206-010842.000, 32.04415, 5.31028, 1.7, 55.0, 0002, 150.6000, 0.0000, 00000003
My code:
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
const char* utc_datetime_format =
"%02u%02u%02u-%02u%02u%02u.%03u";
const char* print_format =
"%18.18s, %14.5f, %15.5f, %8.1f, %10.1f, %04u, %14.4f, "
"%14.4f, %08u\n";
typedef struct
{
uint64_t year : 12;
uint64_t month : 4;
uint64_t day : 8;
uint64_t hour : 8;
uint64_t minutes : 8;
uint64_t seconds : 8;
uint64_t msec : 16;
} DateAndTime_Compressed;
typedef struct
{
float latitude;
float longitude;
} GNSS_Coordinates;
typedef struct
{
GNSS_Coordinates coordinates;
float horizontal_precision;
float altitude;
float course_over_ground;
float speed_over_ground_mps; // m/s
DateAndTime_Compressed utc_time;
uint8_t fix_type;
uint8_t num_satellites;
} GNSS_Data;
int GNSS_ParseData(char* buf, GNSS_Data* data)
{
const char* format =
"%s %2" PRIu16 "%2" PRIu16 "%2" PRIu16 ".%3" PRIu16
",%f,%f,%f,%f,%" PRIu8 ",%3" PRIu16 ".%2" PRIu16
",%f,%f,%2" PRIu8 "%2" PRIu8 "%2" PRIu8 ",%" PRIu32
"%s";
char front_padding[128] = {0}, back_padding[128] = {0};
uint16_t year, month, day, hour, minute, second,
millisecond, cog_deg, cog_min;
float tmp;
// For some reason cannot extract hhmmss.sss from
// message directly
int ret = sscanf(
buf, format, front_padding, &hour, &minute, &second,
&millisecond, &(data->coordinates.latitude),
&(data->coordinates.longitude),
&data->horizontal_precision, &data->altitude,
&data->fix_type, &cog_deg, &cog_min,
&data->speed_over_ground_mps, &tmp, &day, &month,
&year, &data->num_satellites, back_padding);
if (ret != 19)
{
// Handle Error (but no error occurs here)
return -1;
}
data->utc_time = (DateAndTime_Compressed){
.year = year,
.month = month,
.day = day,
.hour = hour,
.minutes = minute,
.seconds = second,
.msec = millisecond};
data->speed_over_ground_mps *=
(1000.0f / 3600.0f); // kph to mps
data->course_over_ground =
(float)cog_deg + (((float)cog_min) / 60.0f) /
100.0f; // ddd.mm to ddd.dd
return 0;
}
int main(int argc, char** argv)
{
char msg[] =
"\r\n+QGPSLOC: "
"010842.0,32.04415,5.31028,1.7,55.0,2,150.36,0.0,0."
"0,060224,03\r\n\r\nOK\r\n";
GNSS_Data gnss_data = {0};
int ret = GNSS_ParseData(
msg,
&gnss_data); // ret = 0 but data.utc_time wrong
// (dates are correct, times wrong)
if (ret != 0)
{
printf("Failed to parse data\n");
exit(-1);
}
char utc_date_string[64] = {0};
snprintf(
utc_date_string, 32, utc_datetime_format,
gnss_data.utc_time.year, gnss_data.utc_time.month,
gnss_data.utc_time.day, gnss_data.utc_time.hour,
gnss_data.utc_time.minutes,
gnss_data.utc_time.seconds,
gnss_data.utc_time.msec);
printf(
print_format, utc_date_string,
gnss_data.coordinates.latitude,
gnss_data.coordinates.longitude,
gnss_data.horizontal_precision, gnss_data.altitude,
gnss_data.fix_type, gnss_data.course_over_ground,
gnss_data.speed_over_ground_mps,
gnss_data.num_satellites);
return 0;
}