mirror of
https://gitlab.com/mobian1/eg25-manager.git
synced 2025-08-29 15:22:20 +02:00
Merge branch 'gnss_cleanup' into 'master'
Fix various small issues in the gnss assistance data upload code Closes #20 See merge request mobian1/devices/eg25-manager!29
This commit is contained in:
149
src/gnss.c
149
src/gnss.c
@@ -8,8 +8,13 @@
|
|||||||
#include "manager.h"
|
#include "manager.h"
|
||||||
#include "at.h"
|
#include "at.h"
|
||||||
|
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#define BUFFER_SIZE 256
|
#define BUFFER_SIZE 256
|
||||||
#define UPLOAD_DELAY 100000
|
#define UPLOAD_DELAY_US 10000
|
||||||
|
#define UPLOAD_TIMEOUT_S 10
|
||||||
#define RESCHEDULE_IN_SECS 30
|
#define RESCHEDULE_IN_SECS 30
|
||||||
|
|
||||||
static void gnss_step(struct EG25Manager *manager);
|
static void gnss_step(struct EG25Manager *manager);
|
||||||
@@ -195,71 +200,71 @@ static void state_at_gnss(struct EG25Manager *manager)
|
|||||||
|
|
||||||
static void fetch_assistance_data(struct EG25Manager *manager)
|
static void fetch_assistance_data(struct EG25Manager *manager)
|
||||||
{
|
{
|
||||||
CURL *curl;
|
|
||||||
CURLcode response;
|
CURLcode response;
|
||||||
long status_code;
|
curl_off_t downloaded;
|
||||||
gchar *url = NULL;
|
CURL *curl = NULL;
|
||||||
|
g_autofree gchar *url = NULL;
|
||||||
FILE *tmp_file = NULL;
|
FILE *tmp_file = NULL;
|
||||||
long int size;
|
gchar errbuf[CURL_ERROR_SIZE];
|
||||||
|
errbuf[0] = 0;
|
||||||
|
|
||||||
/* Fetch assistance data with curl */
|
/* Fetch assistance data with curl */
|
||||||
tmp_file = fdopen(manager->gnss_assistance_fd, "wb+");
|
tmp_file = fdopen(manager->gnss_assistance_fd, "wb+");
|
||||||
|
if (tmp_file == NULL) {
|
||||||
|
g_critical("Unable to open file to save assistance data: %s",
|
||||||
|
g_strerror(errno));
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
|
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
|
||||||
ftruncate(manager->gnss_assistance_fd, 0);
|
ftruncate(manager->gnss_assistance_fd, 0);
|
||||||
url = g_strconcat(manager->gnss_assistance_url, "/",
|
url = g_strconcat(manager->gnss_assistance_url, "/",
|
||||||
manager->gnss_assistance_file, NULL);
|
manager->gnss_assistance_file, NULL);
|
||||||
|
|
||||||
curl = curl_easy_init();
|
curl = curl_easy_init();
|
||||||
if (!curl)
|
if (!curl) {
|
||||||
g_error ("Unable to initialize curl");
|
g_critical("Unable to initialize curl");
|
||||||
|
goto bail;
|
||||||
|
}
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmp_file);
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmp_file);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
|
||||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
||||||
response = curl_easy_perform(curl);
|
|
||||||
if (response == CURLE_HTTP_RETURNED_ERROR) {
|
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
g_warning ("Unable to fetch GNSS assistance data from %s (HTTP %ld)",
|
|
||||||
url, status_code);
|
|
||||||
|
|
||||||
/* Restart upload on HTTP error status code */
|
response = curl_easy_perform(curl);
|
||||||
g_message ("Rescheduling upload because of failure in %ds",
|
if (response != CURLE_OK) {
|
||||||
RESCHEDULE_IN_SECS);
|
g_warning("Unable to fetch GNSS assistance data from %s: %s",
|
||||||
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
url, strlen(errbuf) ? errbuf : curl_easy_strerror(response));
|
||||||
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
|
goto bail;
|
||||||
G_SOURCE_FUNC(gnss_upload_assistance_data),
|
|
||||||
manager);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get file size in bytes */
|
response = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &downloaded);
|
||||||
size = (long int)lseek(manager->gnss_assistance_fd, 0, SEEK_END);
|
if (response) {
|
||||||
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
|
g_critical("Unable to get number of downloaded bytes from curl");
|
||||||
|
goto bail;
|
||||||
if (size <= 0) {
|
} else if (downloaded <= 0) {
|
||||||
g_warning ("GNSS assistance data contains 0 bytes,"
|
g_warning("Downloaded empty assistance data file");
|
||||||
"check network connection.");
|
goto bail;
|
||||||
/*
|
|
||||||
* Restart upload when file does not contain any data,
|
|
||||||
* mostly because of no network connection.
|
|
||||||
*/
|
|
||||||
g_message ("Rescheduling upload because of failure in %ds",
|
|
||||||
RESCHEDULE_IN_SECS);
|
|
||||||
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
|
||||||
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
|
|
||||||
G_SOURCE_FUNC(gnss_upload_assistance_data),
|
|
||||||
manager);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_message("Fetching GNSS assistance data from %s was successfull", url);
|
g_message("Fetching GNSS assistance data from %s was successfull", url);
|
||||||
|
|
||||||
|
fflush(tmp_file);
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
g_free(url);
|
g_free(url);
|
||||||
|
|
||||||
/* Go to the next step */
|
/* Go to the next step */
|
||||||
manager->gnss_assistance_step++;
|
manager->gnss_assistance_step++;
|
||||||
gnss_step(manager);
|
gnss_step(manager);
|
||||||
|
return;
|
||||||
|
|
||||||
|
bail:
|
||||||
|
if (curl != NULL)
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -279,18 +284,24 @@ static void init_assistance_data_upload_start(struct EG25Manager *manager,
|
|||||||
const char *response)
|
const char *response)
|
||||||
{
|
{
|
||||||
gchar value[BUFFER_SIZE];
|
gchar value[BUFFER_SIZE];
|
||||||
long int size;
|
off_t size;
|
||||||
|
|
||||||
/* Process AT response */
|
/* Process AT response */
|
||||||
at_process_result(manager, response);
|
at_process_result(manager, response);
|
||||||
|
|
||||||
/* Get file size in bytes */
|
/* Get file size in bytes */
|
||||||
size = (long int)lseek(manager->gnss_assistance_fd, 0, SEEK_END);
|
size = lseek(manager->gnss_assistance_fd, 0, SEEK_END);
|
||||||
|
if (size == -1) {
|
||||||
|
g_critical("gnss: unable to read size of xtra data file: %s", g_strerror(errno));
|
||||||
|
|
||||||
|
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
|
lseek(manager->gnss_assistance_fd, 0, SEEK_SET);
|
||||||
|
|
||||||
/* Start upload */
|
/* Start upload */
|
||||||
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld\r\n",
|
g_snprintf(value, BUFFER_SIZE, "\"RAM:%s\",%ld,%d",
|
||||||
manager->gnss_assistance_file, size);
|
manager->gnss_assistance_file, size, UPLOAD_TIMEOUT_S);
|
||||||
g_message("Initiate GNSS assistance data upload: %s", value);
|
g_message("Initiate GNSS assistance data upload: %s", value);
|
||||||
at_append_command(manager, "QFUPL", NULL, value, NULL,
|
at_append_command(manager, "QFUPL", NULL, value, NULL,
|
||||||
init_assistance_data_upload_ready);
|
init_assistance_data_upload_ready);
|
||||||
@@ -310,39 +321,39 @@ static void init_assistance_data_upload(struct EG25Manager *manager)
|
|||||||
|
|
||||||
static void upload_assistance_data(struct EG25Manager *manager)
|
static void upload_assistance_data(struct EG25Manager *manager)
|
||||||
{
|
{
|
||||||
char buffer[2*BUFFER_SIZE];
|
gint error;
|
||||||
gint len;
|
glong written_total = 0;
|
||||||
gboolean success = TRUE;
|
gint ret;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
/* Copy downloaded XTRA assistance data to the modem over serial */
|
if (fstat(manager->gnss_assistance_fd, &sb) != 0) {
|
||||||
while((len = read(manager->gnss_assistance_fd, buffer, 2*BUFFER_SIZE)) > 0)
|
g_critical("gnss: unable to stat xtra data file: %s", g_strerror(errno));
|
||||||
{
|
|
||||||
len = write(manager->at_fd, buffer, len);
|
/* Make sure the upload times out and the modem goes back to AT command mode */
|
||||||
if (len < 0) {
|
sleep(UPLOAD_TIMEOUT_S + 1);
|
||||||
success = FALSE;
|
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
||||||
g_error("Writing GNSS assistance data failed: %d", len);
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
usleep(UPLOAD_DELAY);
|
|
||||||
g_message("Uploaded %d bytes", len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
errno = 0;
|
||||||
|
/* Copy downloaded XTRA assistance data to the modem over serial */
|
||||||
|
ret = sendfile(manager->at_fd, manager->gnss_assistance_fd, &written_total, sb.st_size);
|
||||||
|
error = errno;
|
||||||
|
usleep(UPLOAD_DELAY_US);
|
||||||
|
} while ((!error && written_total < sb.st_size) || (ret == -1 && error == EAGAIN));
|
||||||
|
|
||||||
/* Clear QFUPL AT command and process next */
|
/* Clear QFUPL AT command and process next */
|
||||||
at_next_command(manager);
|
at_next_command(manager);
|
||||||
|
|
||||||
/* Go to the next step if successful */
|
/* Go to the next step if successful */
|
||||||
if (success) {
|
if (!error) {
|
||||||
|
g_message("Successfully uploaded %ld bytes to the modem", written_total);
|
||||||
manager->gnss_assistance_step++;
|
manager->gnss_assistance_step++;
|
||||||
gnss_step(manager);
|
gnss_step(manager);
|
||||||
}
|
} else {
|
||||||
/* Restart upload */
|
g_critical("Unable to upload xtra data: %s", g_strerror(error));
|
||||||
else {
|
|
||||||
g_message ("Rescheduling upload because of failure in %ds",
|
|
||||||
RESCHEDULE_IN_SECS);
|
|
||||||
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
manager->gnss_assistance_step = EG25_GNSS_STEP_LAST;
|
||||||
g_timeout_add_seconds(RESCHEDULE_IN_SECS,
|
|
||||||
G_SOURCE_FUNC(gnss_upload_assistance_data),
|
|
||||||
manager);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,9 +396,9 @@ static void finish_assistance_data_upload(struct EG25Manager *manager)
|
|||||||
#ifdef HAVE_MMGLIB
|
#ifdef HAVE_MMGLIB
|
||||||
static void enable_mm_gnss(struct EG25Manager *manager)
|
static void enable_mm_gnss(struct EG25Manager *manager)
|
||||||
{
|
{
|
||||||
MMModemLocationSource sources;
|
|
||||||
gboolean signal_location;
|
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
|
MMModemLocationSource sources = mm_modem_location_get_enabled(manager->mm_location);
|
||||||
|
gboolean signal_location = mm_modem_location_signals_location(manager->mm_location);
|
||||||
|
|
||||||
if (manager->gnss_sources & EG25_GNSS_SOURCE_UNMANAGED)
|
if (manager->gnss_sources & EG25_GNSS_SOURCE_UNMANAGED)
|
||||||
sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED;
|
sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED;
|
||||||
@@ -396,8 +407,6 @@ static void enable_mm_gnss(struct EG25Manager *manager)
|
|||||||
if (manager->gnss_sources & EG25_GNSS_SOURCE_RAW)
|
if (manager->gnss_sources & EG25_GNSS_SOURCE_RAW)
|
||||||
sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW;
|
sources |= MM_MODEM_LOCATION_SOURCE_GPS_RAW;
|
||||||
|
|
||||||
sources = mm_modem_location_get_enabled(manager->mm_location);
|
|
||||||
signal_location = mm_modem_location_signals_location(manager->mm_location);
|
|
||||||
mm_modem_location_setup_sync(manager->mm_location, sources,
|
mm_modem_location_setup_sync(manager->mm_location, sources,
|
||||||
signal_location, NULL, &error);
|
signal_location, NULL, &error);
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
|
Reference in New Issue
Block a user