From 1d006ec6e28ec9e07810e51ca02e79086969991f Mon Sep 17 00:00:00 2001 From: doriangc <59543436+doriangc@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:46:46 -0700 Subject: [PATCH 1/3] Hopeful fix for the demo --- CMakeLists.txt | 5 +- prj.conf | 3 + src/main.c | 8 +- src/main.cpp | 5 +- src/modules/tracking_module/tracking_module.c | 90 ++++++++++++++++++- src/modules/tracking_module/tracking_module.h | 5 ++ 6 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 src/modules/tracking_module/tracking_module.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c2d08cf..7f92c23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,11 +18,14 @@ set(SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/common/tools.cpp ## Modules - # Server Module + # Net Module ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/net_module/socket.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/net_module/nrf9160_setup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/net_module/net_module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/net_module/net_scheduler.cpp + + # Tracking Module + ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/tracking_module/tracking_module.c ) # target_include_directories(app PRIVATE diff --git a/prj.conf b/prj.conf index 995d37b..11ca691 100644 --- a/prj.conf +++ b/prj.conf @@ -26,6 +26,9 @@ CONFIG_LTE_LINK_CONTROL=y CONFIG_PDN=y CONFIG_PDN_ESM_STRERROR=y +CONFIG_LOCATION=y +CONFIG_NRF_CLOUD_AGNSS=y + CONFIG_SPI=y CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/src/main.c b/src/main.c index ec2c76b..2f6083f 100644 --- a/src/main.c +++ b/src/main.c @@ -46,12 +46,10 @@ int main() { }; while (1) { - // printk("Beep\r\n"); - #ifndef POSIX_MODE - gpio_pin_toggle_dt(&led); - #endif + + server_send_van_location(&van_info, (struct Location){.lat = 213.12, .lon=20.123}, 100); - k_sleep(K_SECONDS(50)); + k_sleep(K_SECONDS(1)); } while (1) { diff --git a/src/main.cpp b/src/main.cpp index 161afa1..28badf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "common/location.h" #include "modules/net_module/net_module.h" +#include "modules/tracking_module/tracking_module.h" #define LED0_NODE DT_ALIAS(led0) static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); @@ -32,11 +33,13 @@ int main() { .van_id = 1 }; + // Default location. struct Location location = {.lat=213.12, .lon=20.123}; while (1) { + location_gnss_high_accuracy_get(void) forward_van_location(van_info, location, 100); - k_sleep(K_SECONDS(20)); + k_sleep(K_SECONDS(1)); } while (1) { diff --git a/src/modules/tracking_module/tracking_module.c b/src/modules/tracking_module/tracking_module.c index 0ffdd02..b5e9c78 100644 --- a/src/modules/tracking_module/tracking_module.c +++ b/src/modules/tracking_module/tracking_module.c @@ -1 +1,89 @@ -// TODO \ No newline at end of file +#include +#include + +#include "tracking_module.h" +#include "../../common/location.h" + +Location last_location; + +static void _location_event_wait(); + +static void location_event_handler(const struct location_event_data *event_data) { + switch (event_data->id) { + case LOCATION_EVT_LOCATION: + printk("Got location:\n"); + printk(" method: %s\n", location_method_str(event_data->method)); + printk(" latitude: %.06f\n", event_data->location.latitude); + printk(" longitude: %.06f\n", event_data->location.longitude); + printk(" accuracy: %.01f m\n", event_data->location.accuracy); + + last_location.latitude = event_data->location.latitude; + last_location.longitude = event_data->location.longitude; + + if (event_data->location.datetime.valid) { + printk(" date: %04d-%02d-%02d\n", + event_data->location.datetime.year, + event_data->location.datetime.month, + event_data->location.datetime.day); + printk(" time: %02d:%02d:%02d.%03d UTC\n", + event_data->location.datetime.hour, + event_data->location.datetime.minute, + event_data->location.datetime.second, + event_data->location.datetime.ms); + } + printk(" Google maps URL: https://maps.google.com/?q=%.06f,%.06f\n\n", + event_data->location.latitude, event_data->location.longitude); + break; + + case LOCATION_EVT_TIMEOUT: + printk("Getting location timed out\n\n"); + break; + + case LOCATION_EVT_ERROR: + printk("Getting location failed\n\n"); + break; + + case LOCATION_EVT_GNSS_ASSISTANCE_REQUEST: + printk("Getting location assistance requested (A-GNSS). Not doing anything.\n\n"); + break; + + case LOCATION_EVT_GNSS_PREDICTION_REQUEST: + printk("Getting location assistance requested (P-GPS). Not doing anything.\n\n"); + break; + + default: + printk("Getting location: Unknown event\n\n"); + break; + } + + k_sem_give(&location_event); +} + +void tracking_module_init() { + err = location_init(location_event_handler); +} + +static Location location_gnss_high_accuracy_get() { + int err; + struct location_config config; + enum location_method methods[] = {LOCATION_METHOD_GNSS}; + + location_config_defaults_set(&config, ARRAY_SIZE(methods), methods); + config.methods[0].gnss.accuracy = LOCATION_ACCURACY_HIGH; + + printk("Requesting high accuracy GNSS location...\n"); + + err = location_request(&config); + if (err) { + printk("Requesting location failed, error: %d\n", err); + return; + } + + _location_event_wait(); + + return last_location; +} + +static void _location_event_wait() { + k_sem_take(&location_event, K_FOREVER); +} diff --git a/src/modules/tracking_module/tracking_module.h b/src/modules/tracking_module/tracking_module.h new file mode 100644 index 0000000..444100b --- /dev/null +++ b/src/modules/tracking_module/tracking_module.h @@ -0,0 +1,5 @@ +#pragma once + +void tracking_module_init(); + +static Location location_gnss_high_accuracy_get(); \ No newline at end of file From 6c6e0288341747d29ce9796cec05ca9f99e7c86b Mon Sep 17 00:00:00 2001 From: Dorian Cauwe Date: Wed, 14 Feb 2024 17:46:02 +0000 Subject: [PATCH 2/3] Fix tracking module --- CMakeLists.txt | 2 +- prj.conf | 9 +++++++- src/main.cpp | 2 +- ...{tracking_module.c => tracking_module.cpp} | 22 ++++++++++++++----- src/modules/tracking_module/tracking_module.h | 4 +++- 5 files changed, 29 insertions(+), 10 deletions(-) rename src/modules/tracking_module/{tracking_module.c => tracking_module.cpp} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f92c23..359ef71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ set(SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/net_module/net_scheduler.cpp # Tracking Module - ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/tracking_module/tracking_module.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/modules/tracking_module/tracking_module.cpp ) # target_include_directories(app PRIVATE diff --git a/prj.conf b/prj.conf index 11ca691..b0a3058 100644 --- a/prj.conf +++ b/prj.conf @@ -26,8 +26,15 @@ CONFIG_LTE_LINK_CONTROL=y CONFIG_PDN=y CONFIG_PDN_ESM_STRERROR=y -CONFIG_LOCATION=y +CONFIG_NRF_CLOUD_REST=y +CONFIG_MODEM_INFO=y CONFIG_NRF_CLOUD_AGNSS=y +CONFIG_LOCATION=y +CONFIG_LOCATION_SERVICE_NRF_CLOUD=y + +CONFIG_MODEM_JWT=y + +CONFIG_POSIX_CLOCK=y CONFIG_SPI=y diff --git a/src/main.cpp b/src/main.cpp index 28badf4..0e3eb78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,7 +37,7 @@ int main() { struct Location location = {.lat=213.12, .lon=20.123}; while (1) { - location_gnss_high_accuracy_get(void) + location = location_gnss_high_accuracy_get(); forward_van_location(van_info, location, 100); k_sleep(K_SECONDS(1)); } diff --git a/src/modules/tracking_module/tracking_module.c b/src/modules/tracking_module/tracking_module.cpp similarity index 84% rename from src/modules/tracking_module/tracking_module.c rename to src/modules/tracking_module/tracking_module.cpp index b5e9c78..bb48576 100644 --- a/src/modules/tracking_module/tracking_module.c +++ b/src/modules/tracking_module/tracking_module.cpp @@ -2,7 +2,8 @@ #include #include "tracking_module.h" -#include "../../common/location.h" + +static K_SEM_DEFINE(location_event, 0, 1); Location last_location; @@ -17,8 +18,8 @@ static void location_event_handler(const struct location_event_data *event_data) printk(" longitude: %.06f\n", event_data->location.longitude); printk(" accuracy: %.01f m\n", event_data->location.accuracy); - last_location.latitude = event_data->location.latitude; - last_location.longitude = event_data->location.longitude; + last_location.lat = event_data->location.latitude; + last_location.lon = event_data->location.longitude; if (event_data->location.datetime.valid) { printk(" date: %04d-%02d-%02d\n", @@ -60,10 +61,15 @@ static void location_event_handler(const struct location_event_data *event_data) } void tracking_module_init() { - err = location_init(location_event_handler); + int err = location_init(location_event_handler); + + if (err) { + printk("Error initializing the tracking module\r\n"); + return; + } } -static Location location_gnss_high_accuracy_get() { +Location location_gnss_high_accuracy_get() { int err; struct location_config config; enum location_method methods[] = {LOCATION_METHOD_GNSS}; @@ -76,7 +82,11 @@ static Location location_gnss_high_accuracy_get() { err = location_request(&config); if (err) { printk("Requesting location failed, error: %d\n", err); - return; + + Location location; + location.lat = 0.0; + location.lon = 0.0; + return location; } _location_event_wait(); diff --git a/src/modules/tracking_module/tracking_module.h b/src/modules/tracking_module/tracking_module.h index 444100b..40b7501 100644 --- a/src/modules/tracking_module/tracking_module.h +++ b/src/modules/tracking_module/tracking_module.h @@ -1,5 +1,7 @@ #pragma once +#include "../../common/location.h" + void tracking_module_init(); -static Location location_gnss_high_accuracy_get(); \ No newline at end of file +Location location_gnss_high_accuracy_get(); \ No newline at end of file From e1e48bcd97bd17b1f94ff532ab30e0ecf4348560 Mon Sep 17 00:00:00 2001 From: Dorian Cauwe Date: Fri, 16 Feb 2024 07:28:24 +0000 Subject: [PATCH 3/3] Fix GPS support --- src/common/location.h | 4 +- src/main.c | 60 ----- src/main.cpp | 64 +++-- src/modules/server_module/nrf9160_setup.c | 135 ---------- src/modules/server_module/nrf9160_setup.h | 3 - src/modules/server_module/server_module.c | 238 ------------------ src/modules/server_module/server_module.h | 35 --- src/modules/server_module/socket.c | 81 ------ src/modules/server_module/socket.h | 4 - src/modules/tracking_module/tracking_event.h | 17 ++ .../tracking_module/tracking_exception.h | 14 ++ .../tracking_module/tracking_module.cpp | 199 ++++++++------- src/modules/tracking_module/tracking_module.h | 4 +- 13 files changed, 177 insertions(+), 681 deletions(-) delete mode 100644 src/main.c delete mode 100644 src/modules/server_module/nrf9160_setup.c delete mode 100644 src/modules/server_module/nrf9160_setup.h delete mode 100644 src/modules/server_module/server_module.c delete mode 100644 src/modules/server_module/server_module.h delete mode 100644 src/modules/server_module/socket.c delete mode 100644 src/modules/server_module/socket.h create mode 100644 src/modules/tracking_module/tracking_event.h create mode 100644 src/modules/tracking_module/tracking_exception.h diff --git a/src/common/location.h b/src/common/location.h index 21273a1..3128846 100644 --- a/src/common/location.h +++ b/src/common/location.h @@ -1,6 +1,6 @@ #pragma once struct Location { - double lat; - double lon; + double lat; + double lon; }; diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 2f6083f..0000000 --- a/src/main.c +++ /dev/null @@ -1,60 +0,0 @@ -#include - - -#include "modules/server_module/nrf9160_setup.h" -#include "modules/server_module/server_module.h" - -#include "common/van_info.h" -#include "common/location.h" - -#define POSIX_MODE - -#ifndef POSIX_MODE -#include -#define LED0_NODE DT_ALIAS(led0) -static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); -#endif - -#define SLEEP_TIME_MS 2000 - - -VanInfo van_info; - -int main() { - printk("Welcome to the OreCart Hardware Project!\r\n"); - int ret; - - server_module_init(); - -#ifndef POSIX_MODE - if (!gpio_is_ready_dt(&led)) { - return 0; - } - - ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); - if (ret < 0) { - return 0; - } -#endif - -#if defined(CONFIG_NRF_MODEM_LIB) - init_nrf9160_modem(); -#endif - - struct VanInfo van_info = { - .van_id = 1 - }; - - while (1) { - - - server_send_van_location(&van_info, (struct Location){.lat = 213.12, .lon=20.123}, 100); - k_sleep(K_SECONDS(1)); - } - - while (1) { - k_sleep(K_SECONDS(15)); - } - - return 0; -} diff --git a/src/main.cpp b/src/main.cpp index 0e3eb78..3cbdeab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,50 +1,42 @@ #include #include +#include + #include "common/van_info.h" #include "common/location.h" #include "modules/net_module/net_module.h" #include "modules/tracking_module/tracking_module.h" - -#define LED0_NODE DT_ALIAS(led0) -static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); - -#define SLEEP_TIME_MS 2000 +#include "modules/tracking_module/tracking_event.h" +#include "modules/tracking_module/tracking_exception.h" VanInfo van_info; int main() { - OC_LOG_INFO("Welcome to the OreCart Hardware Project!"); - int ret; - - net_module_init(); - - if (!gpio_is_ready_dt(&led)) { - return 0; - } - - ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); - if (ret < 0) { - return 0; - } - - struct VanInfo van_info = { - .van_id = 1 - }; - - // Default location. - struct Location location = {.lat=213.12, .lon=20.123}; - - while (1) { - location = location_gnss_high_accuracy_get(); - forward_van_location(van_info, location, 100); - k_sleep(K_SECONDS(1)); - } - - while (1) { - k_sleep(K_SECONDS(15)); - } + OC_LOG_INFO("Welcome to the OreCart Hardware Project!"); + int ret; + + net_module_init(); + + try { + tracking_module_init(); + } catch (TrackingException e) { + OC_LOG_ERROR(e.toStr()); + } + + while (true) { + k_sleep(K_SECONDS(1)); + } + + return 0; +} - return 0; +static bool _app_event_handler(const struct app_event_header *aeh) { + if (is_tracking_event(aeh)) { + + } } + +APP_EVENT_LISTENER(main, _app_event_handler); +APP_EVENT_SUBSCRIBE(main, tracking_event); \ No newline at end of file diff --git a/src/modules/server_module/nrf9160_setup.c b/src/modules/server_module/nrf9160_setup.c deleted file mode 100644 index 324e603..0000000 --- a/src/modules/server_module/nrf9160_setup.c +++ /dev/null @@ -1,135 +0,0 @@ -// The nRF9160 is one odd duck in the flock. -// Unlike its friends, it refuses to bring a driver dish to the kernel potluck, so we're DIY-ing it right here. - -#if defined(CONFIG_NRF_MODEM_LIB) - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "server_module.h" - -static const char cert[] = { -#include "../../../res/cert/DigiCertGlobalRootCA.pem" -}; - -// NRF_MODEM_LIB_ON_INIT(orecart_init_hook, on_modem_lib_init, NULL); - -#define TLS_SEC_TAG 42 - -void pdn_event_handler(uint8_t cid, enum pdn_event event, int reason) -{ - switch (event) { - case PDN_EVENT_CNEC_ESM: - printk("PDP context %d error, %s\n", cid, pdn_esm_strerror(reason)); - break; - case PDN_EVENT_ACTIVATED: - printk("PDP context %d activated\n", cid); - break; - case PDN_EVENT_DEACTIVATED: - printk("PDP context %d deactivated\n", cid); - break; - case PDN_EVENT_NETWORK_DETACH: - printk("PDP context %d network detached\n", cid); - break; - case PDN_EVENT_IPV6_UP: - printk("PDP context %d IPv6 up\n", cid); - break; - case PDN_EVENT_IPV6_DOWN: - printk("PDP context %d IPv6 down\n", cid); - break; - default: - printk("PDP context %d, unknown event %d\n", cid, event); - break; - } -} - -int cert_provision(void) -{ - int err; - bool exists; - int mismatch; - - /* It may be sufficient for you application to check whether the correct - * certificate is provisioned with a given tag directly using modem_key_mgmt_cmp(). - * Here, for the sake of the completeness, we check that a certificate exists - * before comparing it with what we expect it to be. - */ - err = modem_key_mgmt_exists(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, &exists); - if (err) { - printk("Failed to check for certificates err %d\n", err); - return err; - } - - if (exists) { - mismatch = modem_key_mgmt_cmp(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert, - strlen(cert)); - if (!mismatch) { - printk("Certificate match!\n"); - return 0; - } - - printk("Certificate mismatch\n"); - err = modem_key_mgmt_delete(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN); - if (err) { - printk("Failed to delete existing certificate, err %d\n", err); - } - } - - printk("Provisioning certificate\n"); - - /* Provision certificate to the modem */ - err = modem_key_mgmt_write(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert, - sizeof(cert) - 1); - if (err) { - printk("Failed to provision certificate, err %d\n", err); - return err; - } - - return 0; -} - -void init_nrf9160_modem() { - printk("Initializing the nRF910 modem....\r\n"); - int err; - - err = nrf_modem_lib_init(); - if (err) { - printk("Modem library initialization failed, error: %d\n", err); - return; - } - - err = pdn_default_ctx_cb_reg(pdn_event_handler); - if (err) { - printk("pdn_default_ctx_cb_reg, error: %d", err); - return; - } - - err = cert_provision(); - if (err) { - return; - } - - printk("Waiting for network.. \r\n"); - - err = lte_lc_init_and_connect(); - if (err) { - printk("Failed to connect to the LTE network, err %d\n", err); - return; - } - - printk("nRF9160 successfully connected to the LTE network!\r\n"); - - - k_sem_give(&is_modem_available); -} - -#endif \ No newline at end of file diff --git a/src/modules/server_module/nrf9160_setup.h b/src/modules/server_module/nrf9160_setup.h deleted file mode 100644 index 2f68e15..0000000 --- a/src/modules/server_module/nrf9160_setup.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void init_nrf9160_modem(); diff --git a/src/modules/server_module/server_module.c b/src/modules/server_module/server_module.c deleted file mode 100644 index c10d4e1..0000000 --- a/src/modules/server_module/server_module.c +++ /dev/null @@ -1,238 +0,0 @@ -#include -#include -#include -#include - -#include - -#include "server_module.h" -#include "socket.h" -#include "../../common/van_info.h" -#include "../../common/tools.h" - -#define MAX_INFLIGHT_REQUESTS 3 -#define PAYLOAD_MAX_SIZE 64 -#define MAX_URL_LEN 32 -#define MAX_RESP_LEN 128 - -#define _STACK_SIZE 256 -#define _PRIORITY 5 - -K_THREAD_STACK_DEFINE(server_stack_area, _STACK_SIZE); -K_SEM_DEFINE(http_requests_sem, MAX_INFLIGHT_REQUESTS, MAX_INFLIGHT_REQUESTS); - -struct k_work_q server_work_q; - -// What should we do if a request fails (runs out of tries or expires)? -enum RequestFailedAction { - // Drop the request (forget it forever) - DROP, - - // Try to upload it when the OreCart is in downtime (ie: parked). This can - // be useful for analytical data that we want still want but don't quickly - // (ie: fine to send later). - DOWNTIME_UPLOAD -}; - -struct OreCartRequest { - struct k_work work; - struct http_request http_req; - - char payload[PAYLOAD_MAX_SIZE]; - char url[MAX_URL_LEN]; - int sock; - - // Some expiration (in UNIX epoch milliseconds) after which it's no longer worth sending this request. - // A lot of the requests here (like location) need to be processed quickly an quickly expire. We don't - // want to be sending the location from 3 minutes ago. This saves on networking resources and allows - uint64_t expiration; - uint8_t tries; // Number of times we'll retry sending this request before we give up. - - enum RequestFailedAction request_failed_action; - - char resp_buffer[MAX_RESP_LEN]; -}; - -typedef struct OreCartRequest OreCartRequest; - -OreCartRequest* inflight_requests[MAX_INFLIGHT_REQUESTS]; // All buffers available by default - -K_SEM_DEFINE(is_modem_available, 0, 1); - -static void on_http_response(struct http_response *rsp, - enum http_final_call final_data, - void *user_data) { - if (final_data == HTTP_DATA_FINAL) { - // printk("\r\nresp: %d\r\n", rsp->http_status_code); - uint32_t inflight_index = (uint32_t)user_data; - - - // If we failed, let's try and this back to the request queue. - if (rsp->http_status_code != 200) { - printk("\r\nResponse failed with status code: %d\r\n", rsp->http_status_code); - inflight_requests[inflight_index]->tries--; - k_work_submit_to_queue(&server_work_q, &inflight_requests[inflight_index]->work); - } else { - printk("\r\nResponse success with status code: %d\r\n", rsp->http_status_code); - - // Some response processing (TBD). - // for (int i=0; icontent_length; i++) { - // printk("%X ", rsp->recv_buf[i]); - // } - - free(inflight_requests[inflight_index]); - } - - close(inflight_requests[inflight_index]->sock); - - inflight_requests[inflight_index] = NULL; - k_sem_give(&http_requests_sem); - - } else { - printk("."); - } -} - - -// Process queue items, send them over to the server. -static void server_work_handler(struct k_work* work) { - printk("New work handle called.\r\n"); - - struct OreCartRequest *request = CONTAINER_OF( - work, struct OreCartRequest, work - ); - - uint64_t uptime = k_uptime_get(); - - if (request->tries == 0 || uptime > request->expiration) { - printk("Request expired, discarding...\r\n"); - - free(request); - return; - } - - // Semaphore limits inflight requests, this makes us wait - // if there are still requests that haven't been handled. - k_sem_take(&http_requests_sem, K_FOREVER); // TODO: Add some sane timeout. - - - // Pick first available buffer (TODO: THIS IS NOT THREAD SAFE YET!!!!) - uint32_t i = 0; - while (inflight_requests[i] != NULL) { - i++; - if (i > MAX_INFLIGHT_REQUESTS - 1) return; // Something bad happened, should never be true. - } - - - inflight_requests[i] = request; - - struct http_request* http_req = &request->http_req; - - http_req->response = on_http_response; - http_req->recv_buf_len = sizeof(MAX_RESP_LEN); - http_req->recv_buf = request->resp_buffer; - - struct addrinfo *res; - struct addrinfo hints = { - .ai_flags = AI_NUMERICSERV, /* Let getaddrinfo() set port */ - .ai_socktype = SOCK_STREAM, - }; - - int err = getaddrinfo(SERVER_HOST, NULL, &hints, &res); - if (err) { - printk("getaddrinfo() failed, err %d %d\n", errno, err); - return; - } - - char peer_addr[INET6_ADDRSTRLEN]; - - inet_ntop(res->ai_family, &((struct sockaddr_in *)(res->ai_addr))->sin_addr, peer_addr, - INET6_ADDRSTRLEN); - - printk("Address Resolved!!! %s\r\n", peer_addr); - - struct sockaddr_in addr4; - - // err = connect(request->sock, res->ai_addr, res->ai_addrlen); - err = connect_socket(AF_INET, peer_addr, SERVER_PORT, - &request->sock, (struct sockaddr *)&addr4, - sizeof(addr4)); - - if (err) { - printk("connect_socket() failed, err: %d\n", errno); - - // Not creating a socket is real bad, means we probably have 0 connectivity. - k_sleep(K_MSEC(400)); // Wait some amount of time for things to resolve themselves. - - close(request->sock); - - // Push current item back to the queue. - inflight_requests[i] = NULL; - request->tries--; - k_work_submit_to_queue(&server_work_q, &request->work); - k_sem_give(&http_requests_sem); // Don't block future requests - return; - } - - // request->sock = socket(res->ai_family, SOCK_STREAM | SOCK_NATIVE_TLS, IPPROTO_TLS_1_2); // TLS - // request->sock = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP); - int ret = http_client_req(request->sock, &request->http_req, TIMEOUT, (void*)i); -} - -void server_module_init() { - k_work_queue_init(&server_work_q); - - k_work_queue_start(&server_work_q, server_stack_area, - K_THREAD_STACK_SIZEOF(server_stack_area), _PRIORITY, - NULL - ); -} - -bool server_send_van_location(VanInfo* vanInfo, struct Location location, uint64_t ts) { - // This will need to stay allocated until the work is finished (ie: HTTP response received) - OreCartRequest* request = malloc(sizeof(OreCartRequest)); - - printk("Sending location...\r\n"); - - // Handle memory allocation failure - if (request == NULL) { - printk("Memory allocation failure.\r\n"); - return false; - } - - // Order types from largest to smallest for data packing. - struct VanLocationPayload { - double lat; - double lon; - uint64_t ts; - } payload; - - payload.lat = location.lat; - payload.lon = location.lon; - payload.ts = ts; - - memcpy(&request->payload, &payload, sizeof(struct VanLocationPayload)); - - char vanIdStr[4]; - uint8_t_to_str(vanInfo->van_id, vanIdStr); - - // Construct the route url, we need to append the van id at the end - strcpy(request->url, SEND_VAN_LOCATION_ROUTE); - strcat(request->url, vanIdStr); - request->expiration = k_uptime_get() + 10000; // 10 second expiration - request->tries = 10; // Try maximum 10 times. - - struct http_request* http_req = &request->http_req; - http_req->method = HTTP_POST; - http_req->url = request->url; - http_req->host = SERVER_HOST; - http_req->protocol = PROTOCOL; - http_req->payload_len = sizeof(struct VanLocationPayload); - http_req->payload = request->payload; - - k_work_init(&request->work, server_work_handler); - k_work_submit_to_queue(&server_work_q, &request->work); - - return true; -} - diff --git a/src/modules/server_module/server_module.h b/src/modules/server_module/server_module.h deleted file mode 100644 index 64538b7..0000000 --- a/src/modules/server_module/server_module.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -#include "../../common/location.h" -#include "../../common/van_info.h" - -#define SERVER_HOST "orecart.local" -#define SERVER_PORT 8000 - -// #define SERVER_HOST "142.251.41.14" -// #define SERVER_PORT 80 - -#define PROTOCOL "HTTP/1.1" -#define TIMEOUT 5000 - -#define SEND_VAN_LOCATION_ROUTE "/location/" -// #define SEND_VAN_LOCATION_ROUTE "/" -#define SEND_OCCUPANCY_ROUTE "/states/ridership/" - -extern struct k_sem is_modem_available; - -// Lock semaphore until initialized. - -void server_module_init(); - -// Send the current van location to the server. -// @location - a lat/long position of the van -// returns success boolean -bool server_send_van_location(VanInfo* vanInfo, struct Location location, uint64_t ts); - -// Send the current ridership to the server. -// @ridership_delta - how many people got on/off the bus, negative for off and positive for on. -// returns success boolean -// bool server_send_ridership(VanInfo* vanInfo, int8_t ridership_delta, uint64_t ts); diff --git a/src/modules/server_module/socket.c b/src/modules/server_module/socket.c deleted file mode 100644 index ba6277b..0000000 --- a/src/modules/server_module/socket.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "server_module.h" - -#define TLS_SEC_TAG 42 - -static int setup_socket(sa_family_t family, const char *server, int port, - int *sock, struct sockaddr *addr, socklen_t addr_len) -{ - const char *family_str = family == AF_INET ? "IPv4" : "IPv6"; - int ret = 0; - - memset(addr, 0, addr_len); - - if (family == AF_INET) { - net_sin(addr)->sin_family = AF_INET; - net_sin(addr)->sin_port = htons(port); - inet_pton(family, server, &net_sin(addr)->sin_addr); - } else { - net_sin6(addr)->sin6_family = AF_INET6; - net_sin6(addr)->sin6_port = htons(port); - inet_pton(family, server, &net_sin6(addr)->sin6_addr); - } - - if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) { - sec_tag_t sec_tag_list[] = { - TLS_SEC_TAG, - }; - - *sock = socket(family, SOCK_STREAM, IPPROTO_TLS_1_2); - if (*sock >= 0) { - ret = setsockopt(*sock, SOL_TLS, TLS_SEC_TAG_LIST, - sec_tag_list, sizeof(sec_tag_list)); - if (ret < 0) { - printk("Failed to set %s secure option (%d)", - family_str, -errno); - ret = -errno; - } - - ret = setsockopt(*sock, SOL_TLS, TLS_HOSTNAME, - SERVER_HOST, - sizeof(SERVER_HOST)); - if (ret < 0) { - printk("Failed to set %s TLS_HOSTNAME " - "option (%d)", family_str, -errno); - ret = -errno; - } - } - } else { - *sock = socket(family, SOCK_STREAM, IPPROTO_TCP); - } - - if (*sock < 0) { - printk("Failed to create %s HTTP socket (%d)", family_str, - -errno); - } - - return ret; -} - - -int connect_socket(sa_family_t family, const char *server, int port, - int *sock, struct sockaddr *addr, socklen_t addr_len) { - int ret; - - ret = setup_socket(family, server, port, sock, addr, addr_len); - if (ret < 0 || *sock < 0) { - return -1; - } - - ret = connect(*sock, addr, addr_len); - if (ret < 0) { - printk("Cannot connect to %s remote (%d)", - family == AF_INET ? "IPv4" : "IPv6", - -errno); - ret = -errno; - } - - return ret; -} \ No newline at end of file diff --git a/src/modules/server_module/socket.h b/src/modules/server_module/socket.h deleted file mode 100644 index 6386c9f..0000000 --- a/src/modules/server_module/socket.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -int connect_socket(sa_family_t family, const char *server, int port, - int *sock, struct sockaddr *addr, socklen_t addr_len); \ No newline at end of file diff --git a/src/modules/tracking_module/tracking_event.h b/src/modules/tracking_module/tracking_event.h new file mode 100644 index 0000000..5ee3dbe --- /dev/null +++ b/src/modules/tracking_module/tracking_event.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include "../../common/location.h" + +struct tracking_event { + /** Data module application event header. */ + struct app_event_header header; + /** Data module event type. */ + enum data_module_event_type type; + + union { + Location location; + } data; +}; \ No newline at end of file diff --git a/src/modules/tracking_module/tracking_exception.h b/src/modules/tracking_module/tracking_exception.h new file mode 100644 index 0000000..c206c6e --- /dev/null +++ b/src/modules/tracking_module/tracking_exception.h @@ -0,0 +1,14 @@ +#pragma once +#include + +class TrackingException { + std::string _exception; + +public: + TrackingException(std::string & exception); + TrackingException(const char * exception); + + const char* toStr() { + return _exception.c_str(); + } +}; diff --git a/src/modules/tracking_module/tracking_module.cpp b/src/modules/tracking_module/tracking_module.cpp index bb48576..368965f 100644 --- a/src/modules/tracking_module/tracking_module.cpp +++ b/src/modules/tracking_module/tracking_module.cpp @@ -1,99 +1,126 @@ -#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include -#include "tracking_module.h" - -static K_SEM_DEFINE(location_event, 0, 1); - -Location last_location; - -static void _location_event_wait(); - -static void location_event_handler(const struct location_event_data *event_data) { - switch (event_data->id) { - case LOCATION_EVT_LOCATION: - printk("Got location:\n"); - printk(" method: %s\n", location_method_str(event_data->method)); - printk(" latitude: %.06f\n", event_data->location.latitude); - printk(" longitude: %.06f\n", event_data->location.longitude); - printk(" accuracy: %.01f m\n", event_data->location.accuracy); - - last_location.lat = event_data->location.latitude; - last_location.lon = event_data->location.longitude; - - if (event_data->location.datetime.valid) { - printk(" date: %04d-%02d-%02d\n", - event_data->location.datetime.year, - event_data->location.datetime.month, - event_data->location.datetime.day); - printk(" time: %02d:%02d:%02d.%03d UTC\n", - event_data->location.datetime.hour, - event_data->location.datetime.minute, - event_data->location.datetime.second, - event_data->location.datetime.ms); - } - printk(" Google maps URL: https://maps.google.com/?q=%.06f,%.06f\n\n", - event_data->location.latitude, event_data->location.longitude); - break; - - case LOCATION_EVT_TIMEOUT: - printk("Getting location timed out\n\n"); - break; - - case LOCATION_EVT_ERROR: - printk("Getting location failed\n\n"); - break; - - case LOCATION_EVT_GNSS_ASSISTANCE_REQUEST: - printk("Getting location assistance requested (A-GNSS). Not doing anything.\n\n"); - break; - - case LOCATION_EVT_GNSS_PREDICTION_REQUEST: - printk("Getting location assistance requested (P-GPS). Not doing anything.\n\n"); - break; - - default: - printk("Getting location: Unknown event\n\n"); - break; - } - - k_sem_give(&location_event); -} +#include "tracking_exception.h" +#include "../../common/location.h" -void tracking_module_init() { - int err = location_init(location_event_handler); +static nrf_modem_gnss_pvt_data_frame last_pvt; +K_MSGQ_DEFINE(nmea_queue, sizeof(struct nrf_modem_gnss_nmea_data_frame *), 10, 4); +static K_SEM_DEFINE(pvt_data_sem, 0, 1); +static K_SEM_DEFINE(time_sem, 0, 1); + +TrackingException::TrackingException(std::string & exception) : _exception(exception) {} +TrackingException::TrackingException(const char * exception) : _exception(exception) {} - if (err) { - printk("Error initializing the tracking module\r\n"); - return; - } +static void _gnss_event_handler(int event); + +void tracking_module_init() { + if (nrf_modem_gnss_event_handler_set(_gnss_event_handler) != 0) { + throw TrackingException("Failed to set GNSS event handler"); + } + + // Enable all NMEA messages. + uint16_t nmea_mask = NRF_MODEM_GNSS_NMEA_RMC_MASK | + NRF_MODEM_GNSS_NMEA_GGA_MASK | + NRF_MODEM_GNSS_NMEA_GLL_MASK | + NRF_MODEM_GNSS_NMEA_GSA_MASK | + NRF_MODEM_GNSS_NMEA_GSV_MASK; + + if (nrf_modem_gnss_nmea_mask_set(nmea_mask) != 0) { + throw TrackingException("Failed to set GNSS mask"); + } + + /* Make QZSS satellites visible in the NMEA output. */ + if (nrf_modem_gnss_qzss_nmea_mode_set(NRF_MODEM_GNSS_QZSS_NMEA_MODE_CUSTOM) != 0) { + LOG_WRN("Failed to enable custom QZSS NMEA mode"); + } + + /* This use case flag should always be set. */ + uint8_t use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START; + + if (IS_ENABLED(CONFIG_GNSS_SAMPLE_LOW_ACCURACY)) { + use_case |= NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY; + } + + if (nrf_modem_gnss_use_case_set(use_case) != 0) { + LOG_WRN("Failed to set GNSS use case"); + } + + /* Default to no power saving. */ + uint8_t power_mode = NRF_MODEM_GNSS_PSM_DISABLED; + + if (nrf_modem_gnss_power_mode_set(power_mode) != 0) { + throw TrackingException("Failed to set GNSS power saving mode"); + } + + // Continuous Tracking + uint16_t fix_retry = 0; + uint16_t fix_interval = 1; + + if (nrf_modem_gnss_fix_retry_set(fix_retry) != 0) { + throw TrackingException("Failed to set GNSS fix retry"); + } + + if (nrf_modem_gnss_fix_interval_set(fix_interval) != 0) { + throw TrackingException("Failed to set GNSS fix interval"); + } + + if (nrf_modem_gnss_start() != 0) { + throw TrackingException("Failed to start GNSS"); + } } -Location location_gnss_high_accuracy_get() { - int err; - struct location_config config; - enum location_method methods[] = {LOCATION_METHOD_GNSS}; +static void _gnss_event_handler(int event) { + int retval; - location_config_defaults_set(&config, ARRAY_SIZE(methods), methods); - config.methods[0].gnss.accuracy = LOCATION_ACCURACY_HIGH; + switch (event) { + case NRF_MODEM_GNSS_EVT_PVT: + retval = nrf_modem_gnss_read(&last_pvt, sizeof(last_pvt), NRF_MODEM_GNSS_DATA_PVT); - printk("Requesting high accuracy GNSS location...\n"); + Location location; + location.lat = last_pvt.latitude; + location.lon = last_pvt.longitude; - err = location_request(&config); - if (err) { - printk("Requesting location failed, error: %d\n", err); + auto time = last_pvt.datetime; - Location location; - location.lat = 0.0; - location.lon = 0.0; - return location; - } + // printk("Latitude: %d Longitude: %d\r\n", location.lat, location.lon); - _location_event_wait(); + if (retval == 0) { + k_sem_give(&pvt_data_sem); + } + break; - return last_location; -} + case NRF_MODEM_GNSS_EVT_NMEA: + nrf_modem_gnss_nmea_data_frame* nmea_data = new nrf_modem_gnss_nmea_data_frame; -static void _location_event_wait() { - k_sem_take(&location_event, K_FOREVER); -} + retval = nrf_modem_gnss_read( + nmea_data, + sizeof(nrf_modem_gnss_nmea_data_frame), + NRF_MODEM_GNSS_DATA_NMEA + ); + + if (retval == 0) { + retval = k_msgq_put(&nmea_queue, nmea_data, K_NO_WAIT); + } + + if (retval != 0) { + delete nmea_data; + } + + break; + + case NRF_MODEM_GNSS_EVT_AGNSS_REQ: + break; + + default: + break; + } +} \ No newline at end of file diff --git a/src/modules/tracking_module/tracking_module.h b/src/modules/tracking_module/tracking_module.h index 40b7501..a272f9c 100644 --- a/src/modules/tracking_module/tracking_module.h +++ b/src/modules/tracking_module/tracking_module.h @@ -4,4 +4,6 @@ void tracking_module_init(); -Location location_gnss_high_accuracy_get(); \ No newline at end of file +Location location_gnss_high_accuracy_get(); + +void location_with_fallback_get(); \ No newline at end of file