Skip to content

Commit 24b3cf2

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 <simen.rostad@nordicsemi.no>
1 parent f27f197 commit 24b3cf2

File tree

10 files changed

+448
-28
lines changed

10 files changed

+448
-28
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: 179 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,149 @@ LOG_MODULE_DECLARE(cloud, CONFIG_APP_CLOUD_LOG_LEVEL);
2121

2222
#define AGNSS_MAX_DATA_SIZE 3800
2323

24+
/**
25+
* @brief Reconstruct cellular network information from location module format
26+
*
27+
* This function converts cellular network data from the location module's format
28+
* (location_cloud_request_data) to the LTE link controller's format (lte_lc_cells_info).
29+
* It copies the current cell information, neighbor cells, and GCI (Global Cell Identity)
30+
* cells into the provided destination structures.
31+
*
32+
* The function performs validation to ensure sufficient buffer sizes are provided for
33+
* both neighbor cells and GCI cells arrays before performing the copy operation.
34+
*
35+
* @param[out] dest Pointer to destination lte_lc_cells_info structure to be populated
36+
* @param[out] neighbor_cells Array to store reconstructed neighbor cell information
37+
* @param[in] neighbor_cells_count Size of the neighbor_cells array
38+
* @param[out] gci_cells Array to store reconstructed GCI cell information
39+
* @param[in] gci_cells_count Size of the gci_cells array
40+
* @param[in] src Pointer to source location_cloud_request_data structure containing
41+
* the cellular data to be converted
42+
*
43+
* @retval 0 Success
44+
* @retval -EINVAL Invalid NULL parameter provided
45+
* @retval -ENOMEM Insufficient buffer size for neighbor_cells or gci_cells arrays
46+
*/
47+
#if defined(CONFIG_LOCATION_METHOD_CELLULAR)
48+
static int reconstruct_cellular_data(struct lte_lc_cells_info *dest,
49+
struct lte_lc_ncell *neighbor_cells,
50+
size_t neighbor_cells_count,
51+
struct lte_lc_cell *gci_cells,
52+
size_t gci_cells_count,
53+
const struct location_cloud_request_data *src)
54+
{
55+
if (!dest || !src || !neighbor_cells || !gci_cells) {
56+
LOG_ERR("Invalid NULL parameter(s) provided");
57+
return -EINVAL;
58+
}
59+
60+
if (neighbor_cells_count < src->ncells_count) {
61+
LOG_ERR("Insufficient neighbor_cells_count: %zu, required: %d",
62+
neighbor_cells_count, src->ncells_count);
63+
return -ENOMEM;
64+
}
65+
66+
if (gci_cells_count < src->gci_cells_count) {
67+
LOG_ERR("Insufficient gci_cells_count: %zu, required: %d",
68+
gci_cells_count, src->gci_cells_count);
69+
return -ENOMEM;
70+
}
71+
72+
/* Copy current cell information */
73+
dest->current_cell.mcc = src->current_cell.mcc;
74+
dest->current_cell.mnc = src->current_cell.mnc;
75+
dest->current_cell.id = src->current_cell.id;
76+
dest->current_cell.tac = src->current_cell.tac;
77+
dest->current_cell.timing_advance = src->current_cell.timing_advance;
78+
dest->current_cell.earfcn = src->current_cell.earfcn;
79+
dest->current_cell.rsrp = src->current_cell.rsrp;
80+
dest->current_cell.rsrq = src->current_cell.rsrq;
81+
82+
dest->ncells_count = src->ncells_count;
83+
dest->gci_cells_count = src->gci_cells_count;
84+
85+
/* Copy neighbor cells */
86+
for (uint8_t i = 0; i < src->ncells_count; i++) {
87+
neighbor_cells[i].earfcn = src->neighbor_cells[i].earfcn;
88+
neighbor_cells[i].time_diff = src->neighbor_cells[i].time_diff;
89+
neighbor_cells[i].phys_cell_id = src->neighbor_cells[i].phys_cell_id;
90+
neighbor_cells[i].rsrp = src->neighbor_cells[i].rsrp;
91+
neighbor_cells[i].rsrq = src->neighbor_cells[i].rsrq;
92+
}
93+
94+
dest->neighbor_cells = neighbor_cells;
95+
96+
/* Copy GCI cells */
97+
for (uint8_t i = 0; i < src->gci_cells_count; i++) {
98+
gci_cells[i].id = src->gci_cells[i].id;
99+
gci_cells[i].mcc = src->gci_cells[i].mcc;
100+
gci_cells[i].mnc = src->gci_cells[i].mnc;
101+
gci_cells[i].tac = src->gci_cells[i].tac;
102+
gci_cells[i].timing_advance = src->gci_cells[i].timing_advance;
103+
gci_cells[i].earfcn = src->gci_cells[i].earfcn;
104+
gci_cells[i].rsrp = src->gci_cells[i].rsrp;
105+
gci_cells[i].rsrq = src->gci_cells[i].rsrq;
106+
}
107+
108+
dest->gci_cells = gci_cells;
109+
110+
return 0;
111+
}
112+
#endif /* CONFIG_LOCATION_METHOD_CELLULAR */
113+
114+
#if defined(CONFIG_LOCATION_METHOD_WIFI)
115+
/**
116+
* @brief Reconstruct wifi_scan_info structure from location module format
117+
*
118+
* This function converts location module's WiFi access point data format into
119+
* the wifi_scan_info structure format. It copies RSSI values, MAC addresses,
120+
* and MAC address lengths for each access point.
121+
*
122+
* @param[out] dest Pointer to destination wifi_scan_info structure to populate
123+
* @param[out] ap_info Array to store wifi_scan_result entries
124+
* @param[in] ap_info_count Size of the ap_info array (number of entries)
125+
* @param[in] src Pointer to source location_cloud_request_data structure
126+
*
127+
* @retval 0 On success
128+
* @retval -EINVAL If any pointer parameter is NULL
129+
* @retval -ENOMEM If ap_info_count is insufficient to hold all WiFi APs from src
130+
*
131+
* @note This function is only available when CONFIG_LOCATION_METHOD_WIFI is defined
132+
* @note The dest->ap_info will point to the provided ap_info array
133+
* @note WiFi MAC addresses are expected to be WIFI_MAC_ADDR_LEN bytes long
134+
*/
135+
static int reconstruct_wifi_data(struct wifi_scan_info *dest,
136+
struct wifi_scan_result *ap_info,
137+
size_t ap_info_count,
138+
const struct location_cloud_request_data *src)
139+
{
140+
if (!dest || !src || !ap_info) {
141+
LOG_ERR("Invalid NULL parameter(s) provided");
142+
return -EINVAL;
143+
}
144+
145+
if ((ap_info_count < src->wifi_cnt)) {
146+
LOG_ERR("Insufficient ap_info_count: %zu, required: %d",
147+
ap_info_count, src->wifi_cnt);
148+
return -ENOMEM;
149+
}
150+
151+
/* Copy WiFi AP data */
152+
for (uint16_t i = 0; i < ap_info_count; i++) {
153+
ap_info[i].rssi = src->wifi_aps[i].rssi;
154+
memcpy(ap_info[i].mac,
155+
src->wifi_aps[i].mac,
156+
WIFI_MAC_ADDR_LEN);
157+
ap_info[i].mac_length = src->wifi_aps[i].mac_length;
158+
}
159+
160+
dest->ap_info = ap_info;
161+
dest->cnt = ap_info_count;
162+
163+
return 0;
164+
}
165+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
166+
24167
static void send_request_failed(void)
25168
{
26169
int err;
@@ -34,7 +177,7 @@ static void send_request_failed(void)
34177
}
35178

36179
/* Handle cloud location requests from the location module */
37-
static void handle_cloud_location_request(const struct location_data_cloud *request)
180+
static void handle_cloud_location_request(const struct location_cloud_request_data *request)
38181
{
39182
int err;
40183
struct nrf_cloud_location_config loc_config = {
@@ -48,32 +191,48 @@ static void handle_cloud_location_request(const struct location_data_cloud *requ
48191
LOG_DBG("Handling cloud location request");
49192

50193
#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 */
194+
struct lte_lc_cells_info cell_info = { 0 };
195+
struct lte_lc_ncell neighbor_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
196+
struct lte_lc_cell gci_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
197+
198+
if ((request->current_cell.id != LTE_LC_CELL_EUTRAN_ID_INVALID) &&
199+
(request->ncells_count > 0)) {
200+
err = reconstruct_cellular_data(&cell_info, neighbor_cells,
201+
ARRAY_SIZE(neighbor_cells),
202+
gci_cells,
203+
ARRAY_SIZE(gci_cells),
204+
request);
205+
if (err) {
206+
LOG_ERR("Failed to reconstruct cellular data, error: %d", err);
207+
SEND_FATAL_ERROR();
208+
return;
209+
}
56210

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);
211+
loc_req.cell_info = &cell_info;
62212
}
63-
#endif
213+
#endif /* CONFIG_LOCATION_METHOD_CELLULAR */
64214

65215
#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 */
216+
struct wifi_scan_result ap_info[CONFIG_LOCATION_METHOD_WIFI_SCANNING_RESULTS_MAX_CNT];
217+
struct wifi_scan_info wifi_info = { 0 };
218+
219+
if (request->wifi_cnt > 0) {
220+
err = reconstruct_wifi_data(&wifi_info, ap_info, ARRAY_SIZE(ap_info), request);
221+
if (err) {
222+
LOG_ERR("Failed to reconstruct Wi-Fi data, error: %d", err);
223+
SEND_FATAL_ERROR();
224+
return;
225+
}
71226

72-
LOG_DBG("Wi-Fi data present: %d APs", request->wifi_data->cnt);
227+
loc_req.wifi_info = &wifi_info;
228+
}
229+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
230+
231+
if (!loc_req.cell_info && !loc_req.wifi_info) {
232+
LOG_ERR("No cellular or Wi-Fi data provided for location request");
233+
return;
73234
}
74-
#endif
75235

76-
/* Send location request to nRF Cloud */
77236
err = nrf_cloud_coap_location_get(&loc_req, &result);
78237
if (err == COAP_RESPONSE_CODE_NOT_FOUND) {
79238
LOG_WRN("nRF Cloud CoAP location coordinates not found, error: %d", err);

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: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,22 @@
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 >= CONFIG_LOCATION_METHOD_WIFI_SCANNING_RESULTS_MAX_CNT);
35+
#endif /* CONFIG_LOCATION_METHOD_WIFI */
36+
2837
/* Define channels provided by this module */
2938
ZBUS_CHAN_DEFINE(LOCATION_CHAN,
3039
struct location_msg,
@@ -116,9 +125,15 @@ static void cloud_request_send(const struct location_data_cloud *cloud_request)
116125
int err;
117126
struct location_msg location_msg = {
118127
.type = LOCATION_CLOUD_REQUEST,
119-
.cloud_request = *cloud_request
120128
};
121129

130+
err = location_cloud_request_data_copy(&location_msg.cloud_request, cloud_request);
131+
if (err) {
132+
LOG_ERR("location_cloud_request_data_copy, error: %d", err);
133+
SEND_FATAL_ERROR();
134+
return;
135+
}
136+
122137
err = zbus_chan_pub(&LOCATION_CHAN, &location_msg, K_SECONDS(1));
123138
if (err) {
124139
LOG_ERR("zbus_chan_pub, error: %d", err);

app/src/modules/location/location.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,56 @@ enum location_msg_type {
7979
LOCATION_SEARCH_CANCEL,
8080
};
8181

82+
struct location_wifi_ap_info {
83+
int8_t rssi;
84+
uint8_t mac[WIFI_MAC_ADDR_LEN];
85+
uint8_t mac_length;
86+
};
87+
88+
struct location_cell_info {
89+
uint32_t id; /* Cell ID (ECI) */
90+
int mcc; /* Mobile Country Code */
91+
int mnc; /* Mobile Network Code */
92+
uint32_t tac; /* Tracking area Code */
93+
94+
uint16_t timing_advance; /* Timing advance */
95+
uint32_t earfcn;
96+
int16_t rsrp;
97+
int16_t rsrq;
98+
};
99+
100+
struct location_neighbor_cell_info {
101+
uint32_t earfcn; /* E-UTRA Absolute Radio Frequency Channel Number */
102+
int time_diff; /* Time difference for neighbor cells */
103+
uint16_t phys_cell_id; /* Physical Cell ID (PCI) */
104+
int16_t rsrp; /* Reference Signal Received Power */
105+
int16_t rsrq; /* Reference Signal Received Quality */
106+
};
107+
108+
struct location_cloud_request_data {
109+
/* Current cell information, valid if current_cell.id != LTE_LC_CELL_EUTRAN_ID_INVALID */
110+
struct location_cell_info current_cell;
111+
112+
/* Neighboring and GCI cell information, valid if count > 0 */
113+
uint8_t ncells_count;
114+
struct location_neighbor_cell_info neighbor_cells[CONFIG_APP_LOCATION_NEIGHBOR_CELLS_MAX];
115+
116+
uint8_t gci_cells_count;
117+
struct location_cell_info gci_cells[CONFIG_APP_LOCATION_NEIGHBOR_CELLS_MAX];
118+
119+
/* Wi-Fi data, valid if wifi_cnt > 0 */
120+
uint16_t wifi_cnt;
121+
struct location_wifi_ap_info wifi_aps[CONFIG_APP_LOCATION_WIFI_APS_MAX];
122+
};
123+
82124
/* Structure to pass location data through zbus */
83125
struct location_msg {
84126
enum location_msg_type type;
85127
union {
86128
/** Contains cloud location request data with cellular and/or Wi-Fi information.
87129
* cloud_request is valid for LOCATION_CLOUD_REQUEST events.
88130
*/
89-
struct location_data_cloud cloud_request;
131+
struct location_cloud_request_data cloud_request;
90132

91133
/** Contains A-GNSS assistance data request parameters.
92134
* agnss_request is valid for LOCATION_AGNSS_REQUEST events.

0 commit comments

Comments
 (0)