Skip to content

Commit 1e8d76e

Browse files
committed
location: Refactor cloud request data handling
Introduce a unified `location_cloud_request_data` struct for improved data transfer between modules. Changes: - Add `location_helper.[ch]` with `location_cloud_request_data_copy()` to convert location library data to module format - Update `location.c` and `location.h` to use new struct and helper - Refactor `cloud_location.c` to reconstruct cellular and Wi-Fi data from the new struct, improving modularity and clarity - Increase thread stack sizes for cloud, location, and storage modules - Add Kconfig options for max Wi-Fi APs and neighbor cells - Update CMakeLists.txt to include new helper source This fixes an issue where the cloud location request would point to memory allocated in the location library and not use actual data copies. This broke storage of location because all the entries would point to the same memory location. Signed-off-by: Simen S. Røstad <[email protected]>
1 parent f27f197 commit 1e8d76e

File tree

21 files changed

+1063
-105
lines changed

21 files changed

+1063
-105
lines changed

app/src/main.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,6 @@ static void sampling_begin_common(struct main_state *state_object)
477477

478478
return;
479479
}
480-
481-
LOG_ERR("LED pattern published");
482480
#endif /* CONFIG_APP_LED */
483481

484482
state_object->sample_start_time = k_uptime_seconds();

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 6144
85+
default 6272
8686

8787
config APP_CLOUD_MESSAGE_QUEUE_SIZE
8888
int "Message queue size"

app/src/modules/cloud/cloud_location.c

Lines changed: 142 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,111 @@ LOG_MODULE_DECLARE(cloud, CONFIG_APP_CLOUD_LOG_LEVEL);
2121

2222
#define AGNSS_MAX_DATA_SIZE 3800
2323

24+
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
25+
static int cellular_cell_data_construct(struct lte_lc_cells_info *dest,
26+
struct lte_lc_ncell *neighbor_cells,
27+
size_t neighbor_cells_count,
28+
struct lte_lc_cell *gci_cells,
29+
size_t gci_cells_count,
30+
const struct location_cloud_request_data *src)
31+
{
32+
if (!dest || !src || !neighbor_cells || !gci_cells) {
33+
LOG_ERR("Invalid NULL parameter(s) provided");
34+
return -EINVAL;
35+
}
36+
37+
if (neighbor_cells_count < src->ncells_count) {
38+
LOG_ERR("Insufficient neighbor_cells_count: %zu, required: %d",
39+
neighbor_cells_count, src->ncells_count);
40+
return -ENOMEM;
41+
}
42+
43+
if (gci_cells_count < src->gci_cells_count) {
44+
LOG_ERR("Insufficient gci_cells_count: %zu, required: %d",
45+
gci_cells_count, src->gci_cells_count);
46+
return -ENOMEM;
47+
}
48+
49+
/* Copy current cell information */
50+
dest->current_cell.mcc = src->current_cell.mcc;
51+
dest->current_cell.mnc = src->current_cell.mnc;
52+
dest->current_cell.id = src->current_cell.id;
53+
dest->current_cell.tac = src->current_cell.tac;
54+
dest->current_cell.timing_advance = src->current_cell.timing_advance;
55+
dest->current_cell.earfcn = src->current_cell.earfcn;
56+
dest->current_cell.rsrp = src->current_cell.rsrp;
57+
dest->current_cell.rsrq = src->current_cell.rsrq;
58+
59+
dest->ncells_count = src->ncells_count;
60+
dest->gci_cells_count = src->gci_cells_count;
61+
62+
/* Copy neighbor cells */
63+
for (uint8_t i = 0; i < src->ncells_count; i++) {
64+
neighbor_cells[i].earfcn = src->neighbor_cells[i].earfcn;
65+
neighbor_cells[i].time_diff = src->neighbor_cells[i].time_diff;
66+
neighbor_cells[i].phys_cell_id = src->neighbor_cells[i].phys_cell_id;
67+
neighbor_cells[i].rsrp = src->neighbor_cells[i].rsrp;
68+
neighbor_cells[i].rsrq = src->neighbor_cells[i].rsrq;
69+
}
70+
71+
dest->neighbor_cells = neighbor_cells;
72+
73+
/* Copy GCI cells */
74+
for (uint8_t i = 0; i < src->gci_cells_count; i++) {
75+
gci_cells[i].id = src->gci_cells[i].id;
76+
gci_cells[i].mcc = src->gci_cells[i].mcc;
77+
gci_cells[i].mnc = src->gci_cells[i].mnc;
78+
gci_cells[i].tac = src->gci_cells[i].tac;
79+
gci_cells[i].timing_advance = src->gci_cells[i].timing_advance;
80+
gci_cells[i].earfcn = src->gci_cells[i].earfcn;
81+
gci_cells[i].rsrp = src->gci_cells[i].rsrp;
82+
gci_cells[i].rsrq = src->gci_cells[i].rsrq;
83+
}
84+
85+
dest->gci_cells = gci_cells;
86+
87+
return 0;
88+
}
89+
#endif /* CONFIG_LOCATION_METHOD_CELLULAR */
90+
91+
#if defined(CONFIG_LOCATION_METHOD_WIFI)
92+
static int wifi_ap_data_construct(struct wifi_scan_info *dest,
93+
struct wifi_scan_result *ap_info,
94+
size_t ap_info_count,
95+
const struct location_cloud_request_data *src)
96+
{
97+
if (!dest || !src || !ap_info) {
98+
LOG_ERR("Invalid NULL parameter(s) provided");
99+
return -EINVAL;
100+
}
101+
102+
if ((ap_info_count < src->wifi_cnt)) {
103+
LOG_ERR("Insufficient ap_info_count: %zu, required: %d",
104+
ap_info_count, src->wifi_cnt);
105+
return -ENOMEM;
106+
}
107+
108+
if (sizeof(ap_info->mac) < sizeof(src->wifi_aps->mac)) {
109+
LOG_ERR("Insufficient mac length in wifi_scan_result");
110+
return -EINVAL;
111+
}
112+
113+
/* Copy WiFi AP data */
114+
for (uint16_t i = 0; i < ap_info_count; i++) {
115+
ap_info[i].rssi = src->wifi_aps[i].rssi;
116+
memcpy(ap_info[i].mac,
117+
src->wifi_aps[i].mac,
118+
WIFI_MAC_ADDR_LEN);
119+
ap_info[i].mac_length = src->wifi_aps[i].mac_length;
120+
}
121+
122+
dest->ap_info = ap_info;
123+
dest->cnt = ap_info_count;
124+
125+
return 0;
126+
}
127+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
128+
24129
static void send_request_failed(void)
25130
{
26131
int err;
@@ -34,7 +139,7 @@ static void send_request_failed(void)
34139
}
35140

36141
/* Handle cloud location requests from the location module */
37-
static void handle_cloud_location_request(const struct location_data_cloud *request)
142+
static void handle_cloud_location_request(const struct location_cloud_request_data *request)
38143
{
39144
int err;
40145
struct nrf_cloud_location_config loc_config = {
@@ -48,32 +153,48 @@ static void handle_cloud_location_request(const struct location_data_cloud *requ
48153
LOG_DBG("Handling cloud location request");
49154

50155
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
51-
if (request->cell_data != NULL) {
52-
/* Cast away const: nRF Cloud API limitation - struct fields are non-const
53-
* but the data is not modified by the API
54-
*/
55-
loc_req.cell_info = (struct lte_lc_cells_info *)request->cell_data; /* NOSONAR */
156+
struct lte_lc_cells_info cell_info = { 0 };
157+
struct lte_lc_ncell neighbor_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
158+
struct lte_lc_cell gci_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
159+
160+
if ((request->current_cell.id != LTE_LC_CELL_EUTRAN_ID_INVALID) &&
161+
(request->ncells_count > 0)) {
162+
err = cellular_cell_data_construct(&cell_info, neighbor_cells,
163+
ARRAY_SIZE(neighbor_cells),
164+
gci_cells,
165+
ARRAY_SIZE(gci_cells),
166+
request);
167+
if (err) {
168+
LOG_ERR("Failed to reconstruct cellular data, error: %d", err);
169+
SEND_FATAL_ERROR();
170+
return;
171+
}
56172

57-
LOG_DBG("Cellular data present: current cell ID: %d, neighbor cells: %d, "
58-
"GCI cells count: %d",
59-
request->cell_data->current_cell.id,
60-
request->cell_data->ncells_count,
61-
request->cell_data->gci_cells_count);
173+
loc_req.cell_info = &cell_info;
62174
}
63-
#endif
175+
#endif /* CONFIG_LOCATION_METHOD_CELLULAR */
64176

65177
#if defined(CONFIG_LOCATION_METHOD_WIFI)
66-
if (request->wifi_data != NULL) {
67-
/* Cast away const: nRF Cloud API limitation - struct fields are non-const
68-
* but the data is not modified by the API
69-
*/
70-
loc_req.wifi_info = (struct wifi_scan_info *)request->wifi_data; /* NOSONAR */
178+
struct wifi_scan_result ap_info[CONFIG_LOCATION_METHOD_WIFI_SCANNING_RESULTS_MAX_CNT];
179+
struct wifi_scan_info wifi_info = { 0 };
180+
181+
if (request->wifi_cnt > 0) {
182+
err = wifi_ap_data_construct(&wifi_info, ap_info, ARRAY_SIZE(ap_info), request);
183+
if (err) {
184+
LOG_ERR("Failed to reconstruct Wi-Fi data, error: %d", err);
185+
SEND_FATAL_ERROR();
186+
return;
187+
}
188+
189+
loc_req.wifi_info = &wifi_info;
190+
}
191+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
71192

72-
LOG_DBG("Wi-Fi data present: %d APs", request->wifi_data->cnt);
193+
if (!loc_req.cell_info && !loc_req.wifi_info) {
194+
LOG_ERR("No cellular or Wi-Fi data provided for location request");
195+
return;
73196
}
74-
#endif
75197

76-
/* Send location request to nRF Cloud */
77198
err = nrf_cloud_coap_location_get(&loc_req, &result);
78199
if (err == COAP_RESPONSE_CODE_NOT_FOUND) {
79200
LOG_WRN("nRF Cloud CoAP location coordinates not found, error: %d", err);
@@ -95,12 +216,9 @@ static void handle_agnss_request(const struct nrf_modem_gnss_agnss_data_frame *r
95216
{
96217
int err;
97218
static char agnss_buf[AGNSS_MAX_DATA_SIZE];
98-
/* Cast away const: nRF Cloud API limitation - struct fields are non-const
99-
* but the data is not modified by the API
100-
*/
101219
struct nrf_cloud_rest_agnss_request agnss_req = {
102220
.type = NRF_CLOUD_REST_AGNSS_REQ_CUSTOM,
103-
.agnss_req = (struct nrf_modem_gnss_agnss_data_frame *)request, /* NOSONAR */
221+
.agnss_req = (struct nrf_modem_gnss_agnss_data_frame *)request,
104222
.net_info = NULL,
105223
.filtered = false,
106224
.mask_angle = 0

app/src/modules/location/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
#
66

7-
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/location.c)
7+
target_sources(app PRIVATE
8+
${CMAKE_CURRENT_SOURCE_DIR}/location.c
9+
${CMAKE_CURRENT_SOURCE_DIR}/location_helper.c
10+
)
811
target_include_directories(app PRIVATE .)

app/src/modules/location/Kconfig.location

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ if APP_LOCATION
1212

1313
config APP_LOCATION_THREAD_STACK_SIZE
1414
int "Thread stack size"
15-
default 2048
15+
default 4096
1616

1717
config APP_LOCATION_WATCHDOG_TIMEOUT_SECONDS
1818
int "Watchdog timeout"
@@ -34,6 +34,18 @@ config APP_LOCATION_MSG_PROCESSING_TIMEOUT_SECONDS
3434
Maximum time allowed for processing a single message in the module's state machine.
3535
The value must be smaller than CONFIG_APP_LOCATION_WATCHDOG_TIMEOUT_SECONDS.
3636

37+
config APP_LOCATION_WIFI_APS_MAX
38+
int "Maximum number of Wi-Fi APs"
39+
default 10
40+
help
41+
Maximum number of Wi-Fi access points to store in a location request.
42+
43+
config APP_LOCATION_NEIGHBOR_CELLS_MAX
44+
int "Maximum number of neighbor cells"
45+
default 10
46+
help
47+
Maximum number of neighbor cells to store in a location request.
48+
3749
module = APP_LOCATION
3850
module-str = Location
3951
source "subsys/logging/Kconfig.template.log_config"

app/src/modules/location/location.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,23 @@
1818
#include "app_common.h"
1919
#include "modem/lte_lc.h"
2020
#include "location.h"
21+
#include "location_helper.h"
2122

2223
LOG_MODULE_REGISTER(location_module, CONFIG_APP_LOCATION_LOG_LEVEL);
2324

2425
BUILD_ASSERT(CONFIG_APP_LOCATION_WATCHDOG_TIMEOUT_SECONDS >
2526
CONFIG_APP_LOCATION_MSG_PROCESSING_TIMEOUT_SECONDS,
2627
"Watchdog timeout must be greater than maximum message processing time");
2728

29+
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
30+
BUILD_ASSERT(CONFIG_APP_LOCATION_NEIGHBOR_CELLS_MAX >= CONFIG_LTE_NEIGHBOR_CELLS_MAX);
31+
#endif /* CONFIG_LOCATION_METHOD_CELLULAR */
32+
33+
#if defined(CONFIG_LOCATION_METHOD_WIFI)
34+
BUILD_ASSERT(CONFIG_APP_LOCATION_WIFI_APS_MAX >=
35+
CONFIG_LOCATION_METHOD_WIFI_SCANNING_RESULTS_MAX_CNT);
36+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
37+
2838
/* Define channels provided by this module */
2939
ZBUS_CHAN_DEFINE(LOCATION_CHAN,
3040
struct location_msg,
@@ -111,21 +121,29 @@ static void location_wdt_callback(int channel_id, void *user_data)
111121
SEND_FATAL_ERROR_WATCHDOG_TIMEOUT();
112122
}
113123

124+
#if defined(CONFIG_LOCATION_METHOD_WIFI) || defined(CONFIG_LOCATION_METHOD_CELLULAR)
114125
static void cloud_request_send(const struct location_data_cloud *cloud_request)
115126
{
116127
int err;
117128
struct location_msg location_msg = {
118129
.type = LOCATION_CLOUD_REQUEST,
119-
.cloud_request = *cloud_request
120130
};
121131

132+
err = location_cloud_request_data_copy(&location_msg.cloud_request, cloud_request);
133+
if (err) {
134+
LOG_ERR("location_cloud_request_data_copy, error: %d", err);
135+
SEND_FATAL_ERROR();
136+
return;
137+
}
138+
122139
err = zbus_chan_pub(&LOCATION_CHAN, &location_msg, K_SECONDS(1));
123140
if (err) {
124141
LOG_ERR("zbus_chan_pub, error: %d", err);
125142
SEND_FATAL_ERROR();
126143
return;
127144
}
128145
}
146+
#endif /* defined(CONFIG_LOCATION_METHOD_WIFI) || defined(CONFIG_LOCATION_METHOD_CELLULAR) */
129147

130148
#if defined(CONFIG_NRF_CLOUD_AGNSS)
131149
static void agnss_request_send(const struct nrf_modem_gnss_agnss_data_frame *agnss_request)
@@ -415,27 +433,31 @@ static void location_event_handler(const struct location_event_data *event_data)
415433

416434
location_print_data_details(event_data->method, &event_data->fallback.details);
417435
break;
436+
#if defined(CONFIG_LOCATION_METHOD_WIFI) || defined(CONFIG_LOCATION_METHOD_CELLULAR)
418437
case LOCATION_EVT_CLOUD_LOCATION_EXT_REQUEST:
419438
LOG_DBG("Cloud location request received from location library");
420439

421-
/* Cancel the current location request since we're now using cloud-based location */
440+
/* Cancel the current location request to avoid falling back to the next
441+
* location source. Treat the fact that we have found Wi-Fi APs and/or cellular data
442+
* as a successful location request, even if we don't know whether the
443+
* cloud is able to resolve data to a location or not.
444+
*/
422445
int err = location_request_cancel();
423446

424447
if (err) {
425448
LOG_ERR("Unable to cancel location request: %d", err);
426-
} else {
427-
LOG_DBG("Location request cancelled successfully");
428449
}
429450

430451
cloud_request_send(&event_data->cloud_location_request);
431452
status_send(LOCATION_SEARCH_DONE);
432453
break;
454+
#endif /* CONFIG_LOCATION_METHOD_WIFI || CONFIG_LOCATION_METHOD_CELLULAR */
433455
#if defined(CONFIG_NRF_CLOUD_AGNSS)
434456
case LOCATION_EVT_GNSS_ASSISTANCE_REQUEST:
435457
LOG_DBG("A-GNSS assistance request received from location library");
436458
agnss_request_send(&event_data->agnss_request);
437459
break;
438-
#endif
460+
#endif /* CONFIG_NRF_CLOUD_AGNSS */
439461
case LOCATION_EVT_RESULT_UNKNOWN:
440462
LOG_DBG("Location result unknown");
441463
status_send(LOCATION_SEARCH_DONE);

0 commit comments

Comments
 (0)