Skip to content

Commit 68e10ad

Browse files
committed
modules: location: Use CONFIG_LOCATION_SERVICE_EXTERNAL
Enable CONFIG_LOCATION_SERVICE_EXTERNAL so that all location requests are routed through the application instead of letting the location library communicate directly with nRF Cloud library. This is needed to be able to buffer locations while offline. Test cases are updated and added to cover the new configuration. Signed-off-by: Jan Tore Guggedal <jantore.guggedal@nordicsemi.no>
1 parent 4eac4db commit 68e10ad

File tree

13 files changed

+953
-60
lines changed

13 files changed

+953
-60
lines changed

app/prj.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ CONFIG_SMF_INITIAL_TRANSITION=y
168168
CONFIG_LOCATION=y
169169
CONFIG_LOCATION_DATA_DETAILS=y
170170
CONFIG_LOCATION_METHOD_GNSS=y
171-
CONFIG_LOCATION_SERVICE_NRF_CLOUD_GNSS_POS_SEND=y
171+
CONFIG_LOCATION_METHOD_CELLULAR=y
172+
CONFIG_LOCATION_SERVICE_EXTERNAL=y
172173
CONFIG_LOCATION_REQUEST_DEFAULT_GNSS_TIMEOUT=60000
173174
CONFIG_LOCATION_REQUEST_DEFAULT_CELLULAR_TIMEOUT=30000
174175
CONFIG_LOCATION_REQUEST_DEFAULT_TIMEOUT=120000

app/src/modules/cloud/Kconfig.cloud

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ config APP_CLOUD_BACKOFF_MAX_SECONDS
8282

8383
config APP_CLOUD_THREAD_STACK_SIZE
8484
int "Thread stack size"
85-
default 3328
85+
default 6144
8686

8787
config APP_CLOUD_MESSAGE_QUEUE_SIZE
8888
int "Message queue size"

app/src/modules/cloud/cloud.c

Lines changed: 143 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/task_wdt/task_wdt.h>
1212
#include <net/nrf_cloud.h>
1313
#include <net/nrf_cloud_coap.h>
14+
#include <net/nrf_cloud_rest.h>
1415
#include <nrf_cloud_coap_transport.h>
1516
#include <zephyr/net/coap.h>
1617
#include <app_version.h>
@@ -24,6 +25,7 @@
2425
#include "cloud.h"
2526
#include "app_common.h"
2627
#include "network.h"
28+
#include "location.h"
2729

2830
#if defined(CONFIG_APP_POWER)
2931
#include "power.h"
@@ -48,14 +50,15 @@ ZBUS_MSG_SUBSCRIBER_DEFINE(cloud_subscriber);
4850

4951
/* Define the channels that the module subscribes to, their associated message types
5052
* and the subscriber that will receive the messages on the channel.
51-
* ENVIRONMENTAL_CHAN and POWER_CHAN are optional and are only included if the
53+
* ENVIRONMENTAL_CHAN, POWER_CHAN, and LOCATION_CHAN are optional and are only included if the
5254
* corresponding module is enabled.
5355
*/
5456
#define CHANNEL_LIST(X) \
5557
X(NETWORK_CHAN, struct network_msg) \
5658
X(CLOUD_CHAN, struct cloud_msg) \
5759
IF_ENABLED(CONFIG_APP_ENVIRONMENTAL, (X(ENVIRONMENTAL_CHAN, struct environmental_msg))) \
58-
IF_ENABLED(CONFIG_APP_POWER, (X(POWER_CHAN, struct power_msg)))
60+
IF_ENABLED(CONFIG_APP_POWER, (X(POWER_CHAN, struct power_msg))) \
61+
IF_ENABLED(CONFIG_APP_LOCATION, (X(LOCATION_CHAN, struct location_msg)))
5962

6063
/* Calculate the maximum message size from the list of channels */
6164
#define MAX_MSG_SIZE MAX_MSG_SIZE_FROM_LIST(CHANNEL_LIST)
@@ -443,6 +446,118 @@ static void state_connected_exit(void *obj)
443446
}
444447
}
445448

449+
#if defined(CONFIG_APP_LOCATION)
450+
/* Handle cloud location requests from the location module */
451+
static void handle_cloud_location_request(const struct location_data_cloud *request)
452+
{
453+
int err;
454+
struct location_data location = { 0 };
455+
struct nrf_cloud_rest_location_request loc_req = {
456+
.cell_info = (struct lte_lc_cells_info *)request->cell_data,
457+
.wifi_info = (struct wifi_scan_info *)request->wifi_data,
458+
.config = NULL
459+
};
460+
struct nrf_cloud_location_result result = { 0 };
461+
462+
LOG_DBG("Handling cloud location request");
463+
464+
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
465+
if (request->cell_data != NULL) {
466+
LOG_DBG("Cellular data present: current cell ID: %d, neighbor cells: %d",
467+
request->cell_data->current_cell.id,
468+
request->cell_data->ncells_count);
469+
}
470+
#endif
471+
472+
#if defined(CONFIG_LOCATION_METHOD_WIFI)
473+
if (request->wifi_data != NULL) {
474+
LOG_DBG("Wi-Fi data present: %d APs", request->wifi_data->cnt);
475+
}
476+
#endif
477+
478+
/* Send location request to nRF Cloud */
479+
err = nrf_cloud_coap_location_get(&loc_req, &result);
480+
if (err == -EACCES) {
481+
LOG_WRN("Not connected to nRF Cloud, error: %d", err);
482+
location_cloud_location_ext_result_set(LOCATION_EXT_RESULT_ERROR, NULL);
483+
return;
484+
} else if (err == -ETIMEDOUT) {
485+
LOG_WRN("Location request timed out, error: %d", err);
486+
location_cloud_location_ext_result_set(LOCATION_EXT_RESULT_ERROR, NULL);
487+
return;
488+
} else if (err == -ENETUNREACH) {
489+
LOG_WRN("Network is unreachable, error: %d", err);
490+
location_cloud_location_ext_result_set(LOCATION_EXT_RESULT_ERROR, NULL);
491+
return;
492+
} else if (err) {
493+
LOG_ERR("nrf_cloud_coap_location_get failed, error: %d", err);
494+
location_cloud_location_ext_result_set(LOCATION_EXT_RESULT_ERROR, NULL);
495+
return;
496+
}
497+
498+
LOG_INF("Location result: lat: %f, lon: %f, accuracy: %f",
499+
result.lat, result.lon, (double)result.unc);
500+
501+
/* Convert result to location_data format */
502+
location.latitude = result.lat;
503+
location.longitude = result.lon;
504+
location.accuracy = (double)result.unc;
505+
506+
/* Send successful result back to location library */
507+
location_cloud_location_ext_result_set(LOCATION_EXT_RESULT_SUCCESS, &location);
508+
}
509+
510+
#if defined(CONFIG_NRF_CLOUD_AGNSS)
511+
/* Handle A-GNSS data requests from the location module */
512+
static void handle_agnss_request(const struct nrf_modem_gnss_agnss_data_frame *request)
513+
{
514+
int err;
515+
static char agnss_buf[NRF_CLOUD_AGNSS_MAX_DATA_SIZE];
516+
struct nrf_cloud_rest_agnss_request agnss_req = {
517+
.type = NRF_CLOUD_REST_AGNSS_REQ_CUSTOM,
518+
.agnss_req = (struct nrf_modem_gnss_agnss_data_frame *)request,
519+
.net_info = NULL,
520+
.filtered = false,
521+
.mask_angle = 0
522+
};
523+
struct nrf_cloud_rest_agnss_result result = {
524+
.buf = agnss_buf,
525+
.buf_sz = sizeof(agnss_buf),
526+
.agnss_sz = 0
527+
};
528+
529+
LOG_DBG("Handling A-GNSS data request");
530+
531+
/* Send A-GNSS request to nRF Cloud */
532+
err = nrf_cloud_coap_agnss_data_get(&agnss_req, &result);
533+
if (err == -EACCES) {
534+
LOG_WRN("Not connected to nRF Cloud, error: %d", err);
535+
return;
536+
} else if (err == -ETIMEDOUT) {
537+
LOG_WRN("A-GNSS request timed out, error: %d", err);
538+
return;
539+
} else if (err == -ENETUNREACH) {
540+
LOG_WRN("Network is unreachable, error: %d", err);
541+
return;
542+
} else if (err) {
543+
LOG_ERR("nrf_cloud_coap_agnss_data_get failed, error: %d", err);
544+
return;
545+
}
546+
547+
LOG_DBG("A-GNSS data received, size: %d bytes", result.agnss_sz);
548+
549+
/* Process the A-GNSS data */
550+
err = location_agnss_data_process(result.buf, result.agnss_sz);
551+
if (err) {
552+
LOG_ERR("Failed to process A-GNSS data, error: %d", err);
553+
return;
554+
}
555+
556+
LOG_DBG("A-GNSS data processed successfully");
557+
}
558+
#endif /* CONFIG_NRF_CLOUD_AGNSS */
559+
#endif /* CONFIG_APP_LOCATION */
560+
446561
static void shadow_get(bool delta_only)
447562
{
448563
int err;
@@ -659,6 +774,32 @@ static void state_connected_ready_run(void *obj)
659774
}
660775
#endif /* CONFIG_APP_ENVIRONMENTAL */
661776

777+
#if defined(CONFIG_APP_LOCATION)
778+
if (state_object->chan == &LOCATION_CHAN) {
779+
const struct location_msg *msg = MSG_TO_LOCATION_MSG_PTR(state_object->msg_buf);
780+
781+
switch (msg->type) {
782+
case LOCATION_CLOUD_REQUEST:
783+
LOG_DBG("Cloud location request received");
784+
handle_cloud_location_request(&msg->cloud_request);
785+
break;
786+
787+
#if defined(CONFIG_NRF_CLOUD_AGNSS)
788+
case LOCATION_AGNSS_REQUEST:
789+
LOG_DBG("A-GNSS data request received");
790+
handle_agnss_request(&msg->agnss_request);
791+
break;
792+
#endif /* CONFIG_NRF_CLOUD_AGNSS */
793+
794+
default:
795+
LOG_DBG("Unhandled location message type: %d", msg->type);
796+
break;
797+
}
798+
799+
return;
800+
}
801+
#endif /* CONFIG_APP_LOCATION */
802+
662803
if (state_object->chan == &CLOUD_CHAN) {
663804
const struct cloud_msg *msg = MSG_TO_CLOUD_MSG_PTR(state_object->msg_buf);
664805

app/src/modules/location/location.c

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <modem/location.h>
1414
#include <nrf_modem_gnss.h>
1515
#include <date_time.h>
16-
#include <net/nrf_cloud.h>
1716
#include <modem/nrf_modem_lib.h>
1817

1918
#include "app_common.h"
@@ -28,21 +27,21 @@ BUILD_ASSERT(CONFIG_APP_LOCATION_WATCHDOG_TIMEOUT_SECONDS >
2827

2928
/* Define channels provided by this module */
3029
ZBUS_CHAN_DEFINE(LOCATION_CHAN,
31-
enum location_msg_type,
30+
struct location_msg,
3231
NULL,
3332
NULL,
3433
ZBUS_OBSERVERS_EMPTY,
3534
ZBUS_MSG_INIT(0)
3635
);
3736

37+
#define MAX_MSG_SIZE sizeof(struct location_msg)
38+
3839
/* Define listener for this module */
3940
ZBUS_MSG_SUBSCRIBER_DEFINE(location);
4041

4142
/* Observe channels */
4243
ZBUS_CHAN_ADD_OBS(LOCATION_CHAN, location, 0);
4344

44-
#define MAX_MSG_SIZE sizeof(enum location_msg_type)
45-
4645
/* Forward declarations */
4746
static void location_event_handler(const struct location_event_data *event_data);
4847

@@ -129,9 +128,43 @@ static void location_wdt_callback(int channel_id, void *user_data)
129128
static void status_send(enum location_msg_type status)
130129
{
131130
int err;
132-
enum location_msg_type location_status = status;
131+
struct location_msg location_msg = {
132+
.type = status
133+
};
133134

134-
err = zbus_chan_pub(&LOCATION_CHAN, &location_status, K_SECONDS(1));
135+
err = zbus_chan_pub(&LOCATION_CHAN, &location_msg, K_SECONDS(1));
136+
if (err) {
137+
LOG_ERR("zbus_chan_pub, error: %d", err);
138+
SEND_FATAL_ERROR();
139+
return;
140+
}
141+
}
142+
143+
static void cloud_request_send(const struct location_data_cloud *cloud_request)
144+
{
145+
int err;
146+
struct location_msg location_msg = {
147+
.type = LOCATION_CLOUD_REQUEST,
148+
.cloud_request = *cloud_request
149+
};
150+
151+
err = zbus_chan_pub(&LOCATION_CHAN, &location_msg, K_SECONDS(1));
152+
if (err) {
153+
LOG_ERR("zbus_chan_pub, error: %d", err);
154+
SEND_FATAL_ERROR();
155+
return;
156+
}
157+
}
158+
159+
static void agnss_request_send(const struct nrf_modem_gnss_agnss_data_frame *agnss_request)
160+
{
161+
int err;
162+
struct location_msg location_msg = {
163+
.type = LOCATION_AGNSS_REQUEST,
164+
.agnss_request = *agnss_request
165+
};
166+
167+
err = zbus_chan_pub(&LOCATION_CHAN, &location_msg, K_SECONDS(1));
135168
if (err) {
136169
LOG_ERR("zbus_chan_pub, error: %d", err);
137170
SEND_FATAL_ERROR();
@@ -152,9 +185,9 @@ void trigger_location_update(void)
152185
}
153186
}
154187

155-
void handle_location_chan(enum location_msg_type location_msg_type)
188+
void handle_location_chan(const struct location_msg *location_msg)
156189
{
157-
if (location_msg_type == LOCATION_SEARCH_TRIGGER) {
190+
if (location_msg->type == LOCATION_SEARCH_TRIGGER) {
158191
LOG_DBG("Location search trigger received, getting location");
159192
trigger_location_update();
160193
}
@@ -184,14 +217,15 @@ static void state_running_run(void *obj)
184217
struct location_state_object const *state_object = obj;
185218

186219
if (state_object->chan == &LOCATION_CHAN) {
187-
handle_location_chan(MSG_TO_LOCATION_TYPE(state_object->msg_buf));
220+
handle_location_chan(MSG_TO_LOCATION_MSG_PTR(state_object->msg_buf));
188221
}
189222
}
190223

191224
static void location_print_data_details(enum location_method method,
192225
const struct location_data_details *details)
193226
{
194227
LOG_DBG("Elapsed method time: %d ms", details->elapsed_time_method);
228+
195229
#if defined(CONFIG_LOCATION_METHOD_GNSS)
196230
if (method == LOCATION_METHOD_GNSS) {
197231
LOG_DBG("Satellites tracked: %d", details->gnss.satellites_tracked);
@@ -200,12 +234,14 @@ static void location_print_data_details(enum location_method method,
200234
LOG_DBG("GNSS execution time: %d ms", details->gnss.pvt_data.execution_time);
201235
}
202236
#endif
237+
203238
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
204239
if (method == LOCATION_METHOD_CELLULAR || method == LOCATION_METHOD_WIFI_CELLULAR) {
205240
LOG_DBG("Neighbor cells: %d", details->cellular.ncells_count);
206241
LOG_DBG("GCI cells: %d", details->cellular.gci_cells_count);
207242
}
208243
#endif
244+
209245
#if defined(CONFIG_LOCATION_METHOD_WIFI)
210246
if (method == LOCATION_METHOD_WIFI || method == LOCATION_METHOD_WIFI_CELLULAR) {
211247
LOG_DBG("Wi-Fi APs: %d", details->wifi.ap_count);
@@ -282,6 +318,20 @@ static void location_event_handler(const struct location_event_data *event_data)
282318

283319
location_print_data_details(event_data->method, &event_data->fallback.details);
284320
break;
321+
case LOCATION_EVT_CLOUD_LOCATION_EXT_REQUEST:
322+
LOG_DBG("Cloud location request received from location library");
323+
cloud_request_send(&event_data->cloud_location_request);
324+
break;
325+
#if defined(CONFIG_NRF_CLOUD_AGNSS)
326+
case LOCATION_EVT_GNSS_ASSISTANCE_REQUEST:
327+
LOG_DBG("A-GNSS assistance request received from location library");
328+
agnss_request_send(&event_data->agnss_request);
329+
break;
330+
#endif
331+
case LOCATION_EVT_RESULT_UNKNOWN:
332+
LOG_DBG("Location result unknown");
333+
status_send(LOCATION_SEARCH_DONE);
334+
break;
285335
default:
286336
LOG_DBG("Getting location: Unknown event %d", event_data->id);
287337
break;

app/src/modules/location/location.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <zephyr/kernel.h>
1111
#include <zephyr/zbus/zbus.h>
12+
#include <modem/location.h>
1213

1314
#ifdef __cplusplus
1415
extern "C" {
@@ -23,9 +24,21 @@ enum location_msg_type {
2324
LOCATION_SEARCH_STARTED = 0x1,
2425
LOCATION_SEARCH_DONE,
2526
LOCATION_SEARCH_TRIGGER,
27+
LOCATION_CLOUD_REQUEST,
28+
LOCATION_AGNSS_REQUEST,
2629
};
2730

28-
#define MSG_TO_LOCATION_TYPE(_msg) (*(const enum location_msg_type *)_msg)
31+
/* Structure to pass location data through zbus */
32+
struct location_msg {
33+
enum location_msg_type type;
34+
union {
35+
struct location_data_cloud cloud_request;
36+
struct nrf_modem_gnss_agnss_data_frame agnss_request;
37+
};
38+
};
39+
40+
#define MSG_TO_LOCATION_TYPE(_msg) (((const struct location_msg *)_msg)->type)
41+
#define MSG_TO_LOCATION_MSG_PTR(_msg) (((const struct location_msg *)_msg))
2942

3043
#ifdef __cplusplus
3144
}

0 commit comments

Comments
 (0)