2b14e5d84a
This commit adds generic matches and handlers for the RMC, GGA and GSV messages to be implemented as part of all NMEA0183 based GNSS modems. NMEA0183 based GNSS modems must place the struct gnss_nmea0183_match_data struct as the first struct in their data struct. Their data struct shall then be set as the user_data for the modem_chat instance. Lastly, the gnss_nmea0183_match callbacks must be included in the unsolicited matches for the modem_chat instance. The GNSS modems will initialize the NMEA0183 match instance using gnss_nmea0183_match_init. Signed-off-by: Bjarki Arge Andreasen <bjarkix123@gmail.com>
138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
/*
|
|
* Copyright (c) 2023 Trackunit Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/modem/chat.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "gnss_nmea0183.h"
|
|
#include "gnss_nmea0183_match.h"
|
|
#include "gnss_publish.h"
|
|
|
|
static bool gnss_nmea0183_match_timed_out(struct gnss_nmea0183_match_data *data)
|
|
{
|
|
int64_t delta;
|
|
|
|
delta = k_uptime_delta(&data->timestamp);
|
|
data->timestamp = k_uptime_get();
|
|
return ((uint16_t)delta) > data->timeout_ms;
|
|
}
|
|
|
|
#if CONFIG_GNSS_SATELLITES
|
|
static void gnss_nmea0183_match_reset_gsv(struct gnss_nmea0183_match_data *data)
|
|
{
|
|
data->satellites_length = 0;
|
|
data->gsv_message_number = 1;
|
|
}
|
|
#endif
|
|
|
|
static void gnss_nmea0183_match_reset(struct gnss_nmea0183_match_data *data)
|
|
{
|
|
data->gga_received = false;
|
|
data->rmc_received = false;
|
|
}
|
|
|
|
void gnss_nmea0183_match_gga_callback(struct modem_chat *chat, char **argv, uint16_t argc,
|
|
void *user_data)
|
|
{
|
|
struct gnss_nmea0183_match_data *data = user_data;
|
|
|
|
if (gnss_nmea0183_match_timed_out(data)) {
|
|
gnss_nmea0183_match_reset(data);
|
|
}
|
|
|
|
if (gnss_nmea0183_parse_gga((const char **)argv, argc, &data->data) < 0) {
|
|
return;
|
|
}
|
|
|
|
data->gga_received = true;
|
|
|
|
if (data->gga_received && data->rmc_received) {
|
|
gnss_publish_data(data->gnss, &data->data);
|
|
}
|
|
}
|
|
|
|
void gnss_nmea0183_match_rmc_callback(struct modem_chat *chat, char **argv, uint16_t argc,
|
|
void *user_data)
|
|
{
|
|
struct gnss_nmea0183_match_data *data = user_data;
|
|
|
|
if (gnss_nmea0183_match_timed_out(data)) {
|
|
gnss_nmea0183_match_reset(data);
|
|
}
|
|
|
|
if (gnss_nmea0183_parse_rmc((const char **)argv, argc, &data->data) < 0) {
|
|
return;
|
|
}
|
|
|
|
data->rmc_received = true;
|
|
|
|
if (data->gga_received && data->rmc_received) {
|
|
gnss_publish_data(data->gnss, &data->data);
|
|
}
|
|
}
|
|
|
|
#if CONFIG_GNSS_SATELLITES
|
|
void gnss_nmea0183_match_gsv_callback(struct modem_chat *chat, char **argv, uint16_t argc,
|
|
void *user_data)
|
|
{
|
|
struct gnss_nmea0183_match_data *data = user_data;
|
|
struct gnss_nmea0183_gsv_header header;
|
|
int ret;
|
|
|
|
if (gnss_nmea0183_match_timed_out(data)) {
|
|
gnss_nmea0183_match_reset(data);
|
|
}
|
|
|
|
if (gnss_nmea0183_parse_gsv_header((const char **)argv, argc, &header) < 0) {
|
|
return;
|
|
}
|
|
|
|
if (header.number_of_svs == 0) {
|
|
return;
|
|
}
|
|
|
|
if (header.message_number != data->gsv_message_number) {
|
|
gnss_nmea0183_match_reset_gsv(data);
|
|
return;
|
|
}
|
|
|
|
data->gsv_message_number++;
|
|
|
|
ret = gnss_nmea0183_parse_gsv_svs((const char **)argv, argc,
|
|
&data->satellites[data->satellites_length],
|
|
data->satellites_size - data->satellites_length);
|
|
if (ret < 0) {
|
|
gnss_nmea0183_match_reset_gsv(data);
|
|
return;
|
|
}
|
|
|
|
data->satellites_length += (uint16_t)ret;
|
|
|
|
if (data->satellites_length == header.number_of_svs) {
|
|
gnss_publish_satellites(data->gnss, data->satellites, data->satellites_length);
|
|
gnss_nmea0183_match_reset_gsv(data);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int gnss_nmea0183_match_init(struct gnss_nmea0183_match_data *data,
|
|
const struct gnss_nmea0183_match_config *config)
|
|
{
|
|
__ASSERT(data != NULL, "data argument must be provided");
|
|
__ASSERT(config != NULL, "data argument must be provided");
|
|
|
|
memset(data, 0, sizeof(struct gnss_nmea0183_match_data));
|
|
data->gnss = config->gnss;
|
|
#if CONFIG_GNSS_SATELLITES
|
|
data->satellites = config->satellites;
|
|
data->satellites_size = config->satellites_size;
|
|
#endif
|
|
data->timeout_ms = config->timeout_ms;
|
|
return 0;
|
|
}
|