From 7d98c752c40afec8e7f8550596e692128f7fb7f8 Mon Sep 17 00:00:00 2001 From: Maximilian Deubel Date: Thu, 18 Apr 2024 16:37:43 +0200 Subject: [PATCH] feat: simple nrf cloud coap tracker Signed-off-by: Maximilian Deubel --- firmware/CMakeLists.txt | 4 +- firmware/Kconfig | 6 +- .../boards/nrf7002dk_nrf5340_cpuapp_ns.conf | 65 ---- firmware/boards/nrf9151dk_nrf9151_ns.conf | 35 --- firmware/boards/nrf9151dk_nrf9151_ns.overlay | 18 -- firmware/boards/nrf9160dk_nrf9160_ns.conf | 36 --- firmware/boards/nrf9160dk_nrf9160_ns.overlay | 18 -- firmware/boards/nrf9161dk_nrf9161_ns.conf | 35 --- firmware/boards/nrf9161dk_nrf9161_ns.overlay | 18 -- firmware/boards/thingy91_nrf9160_ns.conf | 36 --- firmware/boards/thingy91_nrf9160_ns.overlay | 18 -- firmware/boards/thingy91x_nrf9151_ns.conf | 36 --- firmware/boards/thingy91x_nrf9151_ns.overlay | 18 -- firmware/doc/architecture.rst | 6 +- firmware/doc/description.rst | 36 +-- firmware/overlay-tls-native_posix.conf | 30 -- firmware/overlay-tls-nrf70.conf | 30 -- firmware/overlay-tls-nrf91.conf | 17 -- firmware/prj.conf | 144 +++++++-- firmware/src/common/message_channel.c | 22 +- firmware/src/common/message_channel.h | 17 +- firmware/src/modules/app/CMakeLists.txt | 7 + firmware/src/modules/app/Kconfig.app | 17 ++ firmware/src/modules/app/app.c | 116 +++++++ firmware/src/modules/error/Kconfig.error | 4 +- firmware/src/modules/error/error.c | 4 +- firmware/src/modules/led/Kconfig.led | 8 +- firmware/src/modules/led/led.c | 18 +- firmware/src/modules/location/CMakeLists.txt | 7 + .../src/modules/location/Kconfig.location | 18 ++ firmware/src/modules/location/location.c | 181 +++++++++++ firmware/src/modules/network/Kconfig.network | 4 +- firmware/src/modules/network/network.c | 4 +- firmware/src/modules/sampler/Kconfig.sampler | 6 +- firmware/src/modules/sampler/sampler.c | 7 +- firmware/src/modules/transport/CMakeLists.txt | 21 -- .../src/modules/transport/Kconfig.transport | 42 +-- .../transport/client_id/CMakeLists.txt | 9 - .../modules/transport/client_id/client_id.c | 33 -- .../modules/transport/client_id/client_id.h | 19 -- .../modules/transport/credentials/ca-cert.pem | 26 -- .../credentials_provision/CMakeLists.txt | 7 - .../credentials_provision.c | 140 --------- firmware/src/modules/transport/transport.c | 287 +++++++----------- firmware/src/modules/trigger/Kconfig.trigger | 8 +- firmware/src/modules/trigger/trigger.c | 6 +- 46 files changed, 676 insertions(+), 968 deletions(-) delete mode 100644 firmware/boards/nrf7002dk_nrf5340_cpuapp_ns.conf delete mode 100644 firmware/boards/nrf9151dk_nrf9151_ns.conf delete mode 100644 firmware/boards/nrf9151dk_nrf9151_ns.overlay delete mode 100644 firmware/boards/nrf9160dk_nrf9160_ns.conf delete mode 100644 firmware/boards/nrf9160dk_nrf9160_ns.overlay delete mode 100644 firmware/boards/nrf9161dk_nrf9161_ns.conf delete mode 100644 firmware/boards/nrf9161dk_nrf9161_ns.overlay delete mode 100644 firmware/boards/thingy91_nrf9160_ns.conf delete mode 100644 firmware/boards/thingy91_nrf9160_ns.overlay delete mode 100644 firmware/boards/thingy91x_nrf9151_ns.conf delete mode 100644 firmware/boards/thingy91x_nrf9151_ns.overlay delete mode 100644 firmware/overlay-tls-native_posix.conf delete mode 100644 firmware/overlay-tls-nrf70.conf delete mode 100644 firmware/overlay-tls-nrf91.conf create mode 100644 firmware/src/modules/app/CMakeLists.txt create mode 100644 firmware/src/modules/app/Kconfig.app create mode 100644 firmware/src/modules/app/app.c create mode 100644 firmware/src/modules/location/CMakeLists.txt create mode 100644 firmware/src/modules/location/Kconfig.location create mode 100644 firmware/src/modules/location/location.c delete mode 100644 firmware/src/modules/transport/client_id/CMakeLists.txt delete mode 100644 firmware/src/modules/transport/client_id/client_id.c delete mode 100644 firmware/src/modules/transport/client_id/client_id.h delete mode 100644 firmware/src/modules/transport/credentials/ca-cert.pem delete mode 100644 firmware/src/modules/transport/credentials_provision/CMakeLists.txt delete mode 100644 firmware/src/modules/transport/credentials_provision/credentials_provision.c diff --git a/firmware/CMakeLists.txt b/firmware/CMakeLists.txt index 67fab10a..a9e0258b 100644 --- a/firmware/CMakeLists.txt +++ b/firmware/CMakeLists.txt @@ -18,6 +18,8 @@ add_subdirectory(src/modules/sampler) add_subdirectory(src/modules/network) add_subdirectory(src/modules/transport) add_subdirectory(src/modules/error) +add_subdirectory(src/modules/location) +add_subdirectory(src/modules/app) # Optional modules -add_subdirectory_ifdef(CONFIG_MQTT_SAMPLE_LED src/modules/led) +add_subdirectory_ifdef(CONFIG_APP_LED src/modules/led) diff --git a/firmware/Kconfig b/firmware/Kconfig index fce5d08f..e0fbd89f 100644 --- a/firmware/Kconfig +++ b/firmware/Kconfig @@ -4,9 +4,9 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -menu "MQTT sample" +menu "Thingy Out-of-Box Application" -config MQTT_SAMPLE_PAYLOAD_CHANNEL_STRING_MAX_SIZE +config APP_PAYLOAD_CHANNEL_STRING_MAX_SIZE int "Payload maximum string size" default 100 help @@ -17,7 +17,9 @@ rsource "src/modules/sampler/Kconfig.sampler" rsource "src/modules/network/Kconfig.network" rsource "src/modules/transport/Kconfig.transport" rsource "src/modules/error/Kconfig.error" +rsource "src/modules/location/Kconfig.location" rsource "src/modules/led/Kconfig.led" +rsource "src/modules/app/Kconfig.app" endmenu diff --git a/firmware/boards/nrf7002dk_nrf5340_cpuapp_ns.conf b/firmware/boards/nrf7002dk_nrf5340_cpuapp_ns.conf deleted file mode 100644 index b6aa314f..00000000 --- a/firmware/boards/nrf7002dk_nrf5340_cpuapp_ns.conf +++ /dev/null @@ -1,65 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for nRF7002 DK -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_POSIX_CLOCK=y -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_LOG_BUFFER_SIZE=3072 -CONFIG_HEAP_MEM_POOL_SIZE=81920 -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC=y -CONFIG_DK_LIBRARY=y - -# Optimize Wi-Fi stack to save some memory -CONFIG_NRF700X_RX_NUM_BUFS=16 -CONFIG_NRF700X_MAX_TX_AGGREGATION=4 - -# Set newlib C to prevent build error complaining that string.h is not supported -CONFIG_NEWLIB_LIBC=y - -# Wi-Fi -CONFIG_WIFI=y -CONFIG_WIFI_NRF700X=y -CONFIG_WIFI_NRF700X_LOG_LEVEL_ERR=y -CONFIG_WIFI_MGMT_EXT=y -CONFIG_WIFI_CREDENTIALS=y - -# Shell -CONFIG_SHELL=y -CONFIG_SHELL_STACK_SIZE=6144 - -# Zephyr NET Connection Manager Connectivity layer. -CONFIG_L2_WIFI_CONNECTIVITY=y -CONFIG_L2_WIFI_CONNECTIVITY_AUTO_CONNECT=n -CONFIG_L2_WIFI_CONNECTIVITY_AUTO_DOWN=n - -# WPA -CONFIG_WPA_SUPP=y -CONFIG_WPA_SUPP_LOG_LEVEL_ERR=y -CONFIG_MBEDTLS_HEAP_SIZE=16384 - -# NET sockets -CONFIG_NET_L2_ETHERNET=y -CONFIG_NET_TCP_WORKQ_STACK_SIZE=2048 -CONFIG_NET_UDP=y -CONFIG_NET_SOCKETS_OFFLOAD=n -CONFIG_NET_DHCPV4=y -CONFIG_NET_CONTEXT_SNDTIMEO=y -CONFIG_NET_MGMT_EVENT_STACK_SIZE=4096 - -# DNS -CONFIG_DNS_RESOLVER=y -CONFIG_NET_SOCKETS_DNS_TIMEOUT=30000 - -# Optimize TF-M -CONFIG_TFM_PROFILE_TYPE_SMALL=y -CONFIG_PM_PARTITION_SIZE_TFM_SRAM=0xc000 -CONFIG_PM_PARTITION_SIZE_TFM=0x20000 diff --git a/firmware/boards/nrf9151dk_nrf9151_ns.conf b/firmware/boards/nrf9151dk_nrf9151_ns.conf deleted file mode 100644 index c7e08882..00000000 --- a/firmware/boards/nrf9151dk_nrf9151_ns.conf +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for nRF9151 DK -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y -CONFIG_PICOLIBC=y -CONFIG_DK_LIBRARY=y -CONFIG_AT_HOST_LIBRARY=y - -# Modem trace -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR=y -CONFIG_SERIAL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_1_ASYNC=y -CONFIG_UART_1_INTERRUPT_DRIVEN=n - -# Disable Duplicate Address Detection (DAD) -# due to not being properly implemented for offloaded interfaces. -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Zephyr NET Connection Manager and Connectivity layer. -CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 -CONFIG_NRF_MODEM_LIB_NET_IF=y -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y diff --git a/firmware/boards/nrf9151dk_nrf9151_ns.overlay b/firmware/boards/nrf9151dk_nrf9151_ns.overlay deleted file mode 100644 index 5d85357b..00000000 --- a/firmware/boards/nrf9151dk_nrf9151_ns.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* Enable uart1 for tracing. */ -&uart1 { - status = "okay"; - current-speed = < 1000000 >; - hw-flow-control; -}; - -/ { - chosen { - nordic,modem-trace-uart = &uart1; - }; -}; diff --git a/firmware/boards/nrf9160dk_nrf9160_ns.conf b/firmware/boards/nrf9160dk_nrf9160_ns.conf deleted file mode 100644 index 3be245fb..00000000 --- a/firmware/boards/nrf9160dk_nrf9160_ns.conf +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for nRF9160 DK -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y -CONFIG_PICOLIBC=y -CONFIG_DK_LIBRARY=y -CONFIG_AT_HOST_LIBRARY=y - -# Modem trace -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR=y -CONFIG_SERIAL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_1_ASYNC=y -CONFIG_UART_1_INTERRUPT_DRIVEN=n - -# Disable Duplicate Address Detection (DAD) -# due to not being properly implemented for offloaded interfaces. -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Connection Manager and Connectivity layer -CONFIG_NET_CONNECTION_MANAGER=y -CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 -CONFIG_NRF_MODEM_LIB_NET_IF=y -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y diff --git a/firmware/boards/nrf9160dk_nrf9160_ns.overlay b/firmware/boards/nrf9160dk_nrf9160_ns.overlay deleted file mode 100644 index 3213bc5d..00000000 --- a/firmware/boards/nrf9160dk_nrf9160_ns.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* Enable uart1 for tracing. */ -&uart1 { - status = "okay"; - current-speed = < 1000000 >; - hw-flow-control; -}; - -/ { - chosen { - nordic,modem-trace-uart = &uart1; - }; -}; diff --git a/firmware/boards/nrf9161dk_nrf9161_ns.conf b/firmware/boards/nrf9161dk_nrf9161_ns.conf deleted file mode 100644 index bc6b7cbe..00000000 --- a/firmware/boards/nrf9161dk_nrf9161_ns.conf +++ /dev/null @@ -1,35 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for nRF9161 DK -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y -CONFIG_PICOLIBC=y -CONFIG_DK_LIBRARY=y -CONFIG_AT_HOST_LIBRARY=y - -# Modem trace -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR=y -CONFIG_SERIAL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_1_ASYNC=y -CONFIG_UART_1_INTERRUPT_DRIVEN=n - -# Disable Duplicate Address Detection (DAD) -# due to not being properly implemented for offloaded interfaces. -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Zephyr NET Connection Manager and Connectivity layer. -CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 -CONFIG_NRF_MODEM_LIB_NET_IF=y -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y diff --git a/firmware/boards/nrf9161dk_nrf9161_ns.overlay b/firmware/boards/nrf9161dk_nrf9161_ns.overlay deleted file mode 100644 index 3213bc5d..00000000 --- a/firmware/boards/nrf9161dk_nrf9161_ns.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* Enable uart1 for tracing. */ -&uart1 { - status = "okay"; - current-speed = < 1000000 >; - hw-flow-control; -}; - -/ { - chosen { - nordic,modem-trace-uart = &uart1; - }; -}; diff --git a/firmware/boards/thingy91_nrf9160_ns.conf b/firmware/boards/thingy91_nrf9160_ns.conf deleted file mode 100644 index 1f68a440..00000000 --- a/firmware/boards/thingy91_nrf9160_ns.conf +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for Thingy:91 -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y -CONFIG_PICOLIBC=y -CONFIG_DK_LIBRARY=y -CONFIG_AT_HOST_LIBRARY=y - -# Modem trace -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR=y -CONFIG_SERIAL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_1_ASYNC=y -CONFIG_UART_1_INTERRUPT_DRIVEN=n - -# Disable Duplicate Address Detection (DAD) -# due to not being properly implemented for offloaded interfaces. -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Connection Manager and Connectivity layer -CONFIG_NET_CONNECTION_MANAGER=y -CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 -CONFIG_NRF_MODEM_LIB_NET_IF=y -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y diff --git a/firmware/boards/thingy91_nrf9160_ns.overlay b/firmware/boards/thingy91_nrf9160_ns.overlay deleted file mode 100644 index 3213bc5d..00000000 --- a/firmware/boards/thingy91_nrf9160_ns.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* Enable uart1 for tracing. */ -&uart1 { - status = "okay"; - current-speed = < 1000000 >; - hw-flow-control; -}; - -/ { - chosen { - nordic,modem-trace-uart = &uart1; - }; -}; diff --git a/firmware/boards/thingy91x_nrf9151_ns.conf b/firmware/boards/thingy91x_nrf9151_ns.conf deleted file mode 100644 index a5019162..00000000 --- a/firmware/boards/thingy91x_nrf9151_ns.conf +++ /dev/null @@ -1,36 +0,0 @@ -# -# Copyright (c) 2024 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Configuration file for Thingy:91 X -# This file is merged with prj.conf in the application folder, and options -# set here will take precedence if they are present in both files. - -# General -CONFIG_HW_STACK_PROTECTION=y -CONFIG_HW_ID_LIBRARY_SOURCE_IMEI=y -CONFIG_PICOLIBC=y -CONFIG_DK_LIBRARY=y -CONFIG_AT_HOST_LIBRARY=y - -# Modem trace -CONFIG_NRF_MODEM_LIB_TRACE=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART=y -CONFIG_NRF_MODEM_LIB_TRACE_BACKEND_UART_ZEPHYR=y -CONFIG_SERIAL=y -CONFIG_UART_ASYNC_API=y -CONFIG_UART_1_ASYNC=y -CONFIG_UART_1_INTERRUPT_DRIVEN=n - -# Disable Duplicate Address Detection (DAD) -# due to not being properly implemented for offloaded interfaces. -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Connection Manager and Connectivity layer -CONFIG_NET_CONNECTION_MANAGER=y -CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 -CONFIG_NRF_MODEM_LIB_NET_IF=y -CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y diff --git a/firmware/boards/thingy91x_nrf9151_ns.overlay b/firmware/boards/thingy91x_nrf9151_ns.overlay deleted file mode 100644 index 5d85357b..00000000 --- a/firmware/boards/thingy91x_nrf9151_ns.overlay +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -/* Enable uart1 for tracing. */ -&uart1 { - status = "okay"; - current-speed = < 1000000 >; - hw-flow-control; -}; - -/ { - chosen { - nordic,modem-trace-uart = &uart1; - }; -}; diff --git a/firmware/doc/architecture.rst b/firmware/doc/architecture.rst index b376c84a..631fe6cd 100644 --- a/firmware/doc/architecture.rst +++ b/firmware/doc/architecture.rst @@ -51,14 +51,14 @@ The following code snippet shows how a module thread polls for incoming messages } K_THREAD_DEFINE(sampler_task_id, - CONFIG_MQTT_SAMPLE_SAMPLER_THREAD_STACK_SIZE, + CONFIG_APP_SAMPLER_THREAD_STACK_SIZE, sampler_task, NULL, NULL, NULL, 3, 0, 0); .. note:: Zbus implements internal message queues for subscribers. In some cases, depending on the use case, it might be necessary to increase the queue size for a particular subscriber. Especially if the module thread can block for some time. - To increase the message queue associated with a subscriber, increase the value of the corresponding Kconfig option, ``CONFIG_MQTT_SAMPLE__MESSAGE_QUEUE_SIZE``. + To increase the message queue associated with a subscriber, increase the value of the corresponding Kconfig option, ``CONFIG_APP__MESSAGE_QUEUE_SIZE``. Modules that are setup as listeners have dedicated callbacks that are invoked every time there is a change to an observing channel. The difference between a listener and a subscriber is that listeners do not require a dedicated thread to process incoming messages. @@ -118,7 +118,7 @@ The following code snippet shows how this is typically carried out throughout th +-------------+------------------+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Module name | Observes channel | Subscriber / Listener | Description | +=============+==================+=======================+==========================================================================================================================================================================================+ -| Trigger | None | | Sends messages on the trigger channel at an interval set by the :ref:`CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS ` and upon a button press. | +| Trigger | None | | Sends messages on the trigger channel at an interval set by the :ref:`CONFIG_APP_TRIGGER_TIMEOUT_SECONDS ` and upon a button press. | +-------------+------------------+-----------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Sampler | Trigger | Subscriber | Samples data every time a message is received on the trigger channel. | | | | | The sampled payload is sent on the payload channel. | diff --git a/firmware/doc/description.rst b/firmware/doc/description.rst index 8981c83a..3f28b1c1 100644 --- a/firmware/doc/description.rst +++ b/firmware/doc/description.rst @@ -51,37 +51,37 @@ Check and configure the following Kconfig options: General options --------------- -.. _CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS: +.. _CONFIG_APP_TRIGGER_TIMEOUT_SECONDS: -CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS - Trigger timeout +CONFIG_APP_TRIGGER_TIMEOUT_SECONDS - Trigger timeout This configuration option sets the interval at which the sample publishes a message to the MQTT broker. -.. _CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS: +.. _CONFIG_APP_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS: -CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS - Transport reconnection timeout +CONFIG_APP_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS - Transport reconnection timeout This configuration option sets the interval at which the sample tries to reconnect to the MQTT broker upon a lost connection. -.. _CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME: +.. _CONFIG_APP_TRANSPORT_BROKER_HOSTNAME: -CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME - MQTT broker hostname +CONFIG_APP_TRANSPORT_BROKER_HOSTNAME - MQTT broker hostname This configuration sets the MQTT broker hostname. Default is `test.mosquitto.org`_. -.. _CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID: +.. _CONFIG_APP_TRANSPORT_CLIENT_ID: -CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID - MQTT client ID +CONFIG_APP_TRANSPORT_CLIENT_ID - MQTT client ID This configuration sets the MQTT client ID name. If not set, the client ID will default to the modem's IMEI number for nRF91 Series devices, MAC address for nRF70 Series devices, or a random number for Native Posix. -.. _CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC: +.. _CONFIG_APP_TRANSPORT_PUBLISH_TOPIC: -CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC - MQTT publish topic +CONFIG_APP_TRANSPORT_PUBLISH_TOPIC - MQTT publish topic This configuration option sets the topic to which the sample publishes messages. Default is ``/my/publish/topic``. -.. _CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC: +.. _CONFIG_APP_TRANSPORT_SUBSCRIBE_TOPIC: -CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC - MQTT subscribe topic +CONFIG_APP_TRANSPORT_SUBSCRIBE_TOPIC - MQTT subscribe topic This configuration option sets the topic to which the sample subscribes. Default is ``/my/subscribe/topic``. @@ -154,11 +154,11 @@ Testing 1. |connect_kit| #. |connect_terminal| #. Reset your board. -#. Observe that the board connects to the network and the configured MQTT broker (:ref:`CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME `). +#. Observe that the board connects to the network and the configured MQTT broker (:ref:`CONFIG_APP_TRANSPORT_BROKER_HOSTNAME `). When a network connection has been established, LED 1 (green) on the board lights up. - After the connection has been established the board starts to publish messages to the topic set by :ref:`CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC `. - The frequency of the messages that are published to the broker can be set by :ref:`CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS ` or triggered asynchronously by pressing any of the buttons on the board. - At any time, the sample can receive messages published to the subscribe topic set by :ref:`CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC `. + After the connection has been established the board starts to publish messages to the topic set by :ref:`CONFIG_APP_TRANSPORT_PUBLISH_TOPIC `. + The frequency of the messages that are published to the broker can be set by :ref:`CONFIG_APP_TRIGGER_TIMEOUT_SECONDS ` or triggered asynchronously by pressing any of the buttons on the board. + At any time, the sample can receive messages published to the subscribe topic set by :ref:`CONFIG_APP_TRANSPORT_SUBSCRIBE_TOPIC `. #. Use an MQTT client like `Mosquitto`_ or `VSMQTT`_ to subscribe to, and publish data to the broker. Sample output @@ -262,7 +262,7 @@ If the TCP/IP (MQTT) connection is lost, the following log output is displayed: transport: Disconnected from MQTT broker If this occurs, the sample's transport module has built-in reconnection logic that will try to reconnect at the frequency set by -:ref:`CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS `. +:ref:`CONFIG_APP_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS `. Emulation ========= @@ -285,7 +285,7 @@ To enable more verbose logging from the MQTT helper library, enable the :kconfig * If you have issues with connectivity on nRF91 Series devices, see the `Cellular Monitor`_ documentation to learn how to capture modem traces in order to debug network traffic in Wireshark. The sample enables modem traces by default. * Public MQTT brokers might be unstable. - If you have trouble connecting to the MQTT broker, try switching to another broker by changing the value of the :ref:`CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME ` configuration option. + If you have trouble connecting to the MQTT broker, try switching to another broker by changing the value of the :ref:`CONFIG_APP_TRANSPORT_BROKER_HOSTNAME ` configuration option. If you are switching to another broker, remember to update the CA certificate. To know more on certificates and provisioning, see :ref:`mqtt_sample_provisioning`. Dependencies diff --git a/firmware/overlay-tls-native_posix.conf b/firmware/overlay-tls-native_posix.conf deleted file mode 100644 index e6aadc01..00000000 --- a/firmware/overlay-tls-native_posix.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Overlay file that enables TLS for Native Posix builds - -# TLS -CONFIG_MQTT_LIB_TLS=y -CONFIG_MQTT_HELPER_PORT=8883 -CONFIG_MQTT_KEEPALIVE=30 - -# Credentials located under /src/modules/transport/credentials/ will be automatically -# provisioned prior to connecting to the server. -CONFIG_MQTT_HELPER_SEC_TAG=955 -CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES=y - -# Native network stack -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_BUILTIN=y -CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=120000 -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 -CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y -CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y -CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y - -# NET Sockets -CONFIG_NET_SOCKETS_SOCKOPT_TLS=y diff --git a/firmware/overlay-tls-nrf70.conf b/firmware/overlay-tls-nrf70.conf deleted file mode 100644 index 9a7418b6..00000000 --- a/firmware/overlay-tls-nrf70.conf +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Overlay file that enables TLS for nRF70 Series builds - -# TLS -CONFIG_MQTT_LIB_TLS=y -CONFIG_MQTT_HELPER_PORT=8883 -CONFIG_MQTT_KEEPALIVE=30 - -# Credentials located under /src/modules/transport/credentials/ will be automatically -# provisioned prior to connecting to the server. -CONFIG_MQTT_HELPER_SEC_TAG=955 -CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES=y - -# Native network stack -CONFIG_NRF_SECURITY=y -CONFIG_MBEDTLS=y -CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_HEAP_SIZE=81920 -CONFIG_MBEDTLS_RSA_C=y - -# NET Sockets -CONFIG_NET_SOCKETS_SOCKOPT_TLS=y - -# TLS credentials -CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE=y diff --git a/firmware/overlay-tls-nrf91.conf b/firmware/overlay-tls-nrf91.conf deleted file mode 100644 index 566c7740..00000000 --- a/firmware/overlay-tls-nrf91.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -# Overlay file that enbles TLS for hardware builds - -# TLS -CONFIG_MQTT_LIB_TLS=y -CONFIG_MQTT_HELPER_PORT=8883 -CONFIG_MQTT_KEEPALIVE=30 - -# Credentials located under /src/modules/transport/credentials/ will be automatically -# provisioned to the nRF91 modem prior to connecting to the server. -CONFIG_MODEM_KEY_MGMT=y -CONFIG_MQTT_HELPER_SEC_TAG=955 diff --git a/firmware/prj.conf b/firmware/prj.conf index 422e1b18..b9ec2f11 100644 --- a/firmware/prj.conf +++ b/firmware/prj.conf @@ -1,34 +1,134 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# +CONFIG_NCS_SAMPLES_DEFAULTS=y -# Common configurations for all boards +CONFIG_RESET_ON_FATAL_ERROR=n +# Improved Logging +# CONFIG_LOG_MODE_DEFERRED allows logging from multiple threads simultaneously without creating +# splintered log entries, at the cost of needing a buffer for storing logs. +CONFIG_LOG=y -# General -CONFIG_HW_ID_LIBRARY=y -CONFIG_ASSERT=y +# CONFIG_LOG_BUFFER_SIZE is the aforementioned buffer. A size of 4096 bytes is useful for debugging +# and prototyping, but is probably more than necessary for production-ready firmware. +CONFIG_LOG_BUFFER_SIZE=4096 -# Logging -CONFIG_LOG=y +# Heap and stacks +# Extended AT host/monitor stack/heap sizes since some nrf_cloud credentials are longer than 1024 bytes. +CONFIG_AT_MONITOR_HEAP_SIZE=2048 +CONFIG_AT_HOST_STACK_SIZE=2048 +# Extended memory heap size needed both for PGPS and for encoding JSON-based nRF Cloud Device Messages. +CONFIG_HEAP_MEM_POOL_SIZE=24576 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 -# Networking +# Enable Networking and Connection Manager. CONFIG_NETWORKING=y -CONFIG_NET_SOCKETS_OFFLOAD=y CONFIG_NET_SOCKETS=y -CONFIG_NET_SOCKETS_POSIX_NAMES=y +CONFIG_NET_SOCKETS_OFFLOAD=y +CONFIG_NET_MGMT_EVENT_STACK_SIZE=2048 +CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 +CONFIG_MAIN_STACK_SIZE=2048 + +# Enable LTE Connectivity using Connection Manager CONFIG_NET_IPV4=y -CONFIG_NET_TCP=y -CONFIG_NET_NATIVE=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_MLD=n CONFIG_NET_CONNECTION_MANAGER=y +CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y +CONFIG_NRF_MODEM_LIB_NET_IF=y +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_DOWN=y +CONFIG_NRF_MODEM_LIB_NET_IF_DOWN_DEFAULT_LTE_DISCONNECT=y -# ZBus -CONFIG_ZBUS=y +# Enable power savings mode +CONFIG_LTE_PSM_REQ=y +# Set the PSM Requested Active Time to 20 seconds +CONFIG_LTE_PSM_REQ_RAT="00001010" + +# Modem library +CONFIG_NRF_MODEM_LIB=y + +# AT commands interface +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_AT_HOST_LIBRARY=y + +# nRF Cloud +CONFIG_MQTT_KEEPALIVE=120 +CONFIG_NRF_CLOUD_MQTT=n # This also enables FOTA by implicitly setting CONFIG_NRF_CLOUD_FOTA=y +CONFIG_NRF_CLOUD_COAP=y +CONFIG_MODEM_JWT=y + +# On initial connection to the cloud, add info sections to the shadow +CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS=y +CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_NETWORK=y +CONFIG_NRF_CLOUD_SEND_DEVICE_STATUS_SIM=y +CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_FOTA=y +CONFIG_NRF_CLOUD_SEND_SERVICE_INFO_UI=y + +# MCUBOOT - Needed by FOTA +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUBOOT_IMG_MANAGER=y +CONFIG_STREAM_FLASH_ERASE=y + +# Date Time lib - Used by PGPS and main application +CONFIG_DATE_TIME=y -# Zephyr state framework +CONFIG_SETTINGS=y +CONFIG_SETTINGS_FCB=y +CONFIG_FCB=y + +# Download Client - used by FOTA and PGPS +CONFIG_DOWNLOAD_CLIENT=y +CONFIG_DOWNLOAD_CLIENT_HTTP_FRAG_SIZE_1024=y +CONFIG_DOWNLOAD_CLIENT_STACK_SIZE=4096 +CONFIG_DOWNLOAD_CLIENT_BUF_SIZE=2300 +CONFIG_DOWNLOAD_CLIENT_MAX_HOSTNAME_SIZE=128 + +# Flash - Used by FOTA and PGPS +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_STREAM_FLASH=y +CONFIG_MPU_ALLOW_FLASH_WRITE=y +CONFIG_NRF_CLOUD_ALERT=y +CONFIG_NRF_CLOUD_LOG_DIRECT=y +CONFIG_NRF_CLOUD_LOG_OUTPUT_LEVEL=3 + +# These options are required because the defaults will result in errors (cool..) +CONFIG_COAP_CLIENT_THREAD_PRIORITY=0 +CONFIG_COAP_CLIENT_BLOCK_SIZE=1024 +CONFIG_COAP_CLIENT_MESSAGE_SIZE=1024 +CONFIG_COAP_CLIENT_STACK_SIZE=6144 +CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE=40 + +CONFIG_SIMPLE_CONFIG=y +CONFIG_DK_LIBRARY=y + +CONFIG_SIMPLE_CONFIG_LOG_LEVEL_DBG=y + +CONFIG_ASSERT=y +CONFIG_REBOOT=y + +# needed for processing floats +CONFIG_PICOLIBC=y +CONFIG_FPU=y + +CONFIG_ZBUS=y CONFIG_SMF=y -# MQTT -CONFIG_MQTT_HELPER=y -CONFIG_MQTT_CLEAN_SESSION=y +# Location +CONFIG_LOCATION=y +CONFIG_LOCATION_DATA_DETAILS=y +CONFIG_LOCATION_METHOD_GNSS=y +CONFIG_LOCATION_METHOD_WIFI=n +CONFIG_LOCATION_REQUEST_DEFAULT_GNSS_TIMEOUT=200000 +CONFIG_LOCATION_REQUEST_DEFAULT_TIMEOUT=300000 +CONFIG_LTE_NETWORK_MODE_LTE_M_NBIOT_GPS=y + +# debug stuff +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_THREAD_NAME=y +CONFIG_DEBUG=y +CONFIG_TFM_CMAKE_BUILD_TYPE_MINSIZEREL=y +CONFIG_LOCATION_LOG_LEVEL_DBG=y +CONFIG_APP_LOCATION_LOG_LEVEL_DBG=y + +CONFIG_DK_LIBRARY=y diff --git a/firmware/src/common/message_channel.c b/firmware/src/common/message_channel.c index 3ddfe8b3..92c0fda5 100644 --- a/firmware/src/common/message_channel.c +++ b/firmware/src/common/message_channel.c @@ -14,7 +14,7 @@ ZBUS_CHAN_DEFINE(TRIGGER_CHAN, /* Name */ int, /* Message type */ NULL, /* Validator */ NULL, /* User data */ - ZBUS_OBSERVERS(sampler), /* Observers */ + ZBUS_OBSERVERS(sampler, app, location), /* Observers */ ZBUS_MSG_INIT(0) /* Initial value {0} */ ); @@ -30,8 +30,8 @@ ZBUS_CHAN_DEFINE(NETWORK_CHAN, enum network_status, NULL, NULL, - ZBUS_OBSERVERS(transport IF_ENABLED(CONFIG_MQTT_SAMPLE_LED, (, led)), sampler), - ZBUS_MSG_INIT(0) + ZBUS_OBSERVERS(transport, sampler), + NETWORK_DISCONNECTED ); ZBUS_CHAN_DEFINE(FATAL_ERROR_CHAN, @@ -41,3 +41,19 @@ ZBUS_CHAN_DEFINE(FATAL_ERROR_CHAN, ZBUS_OBSERVERS(error), ZBUS_MSG_INIT(0) ); + +ZBUS_CHAN_DEFINE(LED_CHAN, + int, + NULL, + NULL, + ZBUS_OBSERVERS(led), + ZBUS_MSG_INIT(0) +); + +ZBUS_CHAN_DEFINE(CLOUD_CHAN, + enum cloud_status, + NULL, + NULL, + ZBUS_OBSERVERS(app, location), + CLOUD_DISCONNECTED +); diff --git a/firmware/src/common/message_channel.h b/firmware/src/common/message_channel.h index 239f5473..33367f57 100644 --- a/firmware/src/common/message_channel.h +++ b/firmware/src/common/message_channel.h @@ -27,7 +27,8 @@ extern "C" { } struct payload { - char string[CONFIG_MQTT_SAMPLE_PAYLOAD_CHANNEL_STRING_MAX_SIZE]; + char string[CONFIG_APP_PAYLOAD_CHANNEL_STRING_MAX_SIZE]; + size_t string_len; }; enum network_status { @@ -35,7 +36,19 @@ enum network_status { NETWORK_CONNECTED, }; -ZBUS_CHAN_DECLARE(TRIGGER_CHAN, PAYLOAD_CHAN, NETWORK_CHAN, FATAL_ERROR_CHAN); +enum cloud_status { + CLOUD_CONNECTED, + CLOUD_DISCONNECTED, +}; + +ZBUS_CHAN_DECLARE( + TRIGGER_CHAN, + PAYLOAD_CHAN, + NETWORK_CHAN, + FATAL_ERROR_CHAN, + LED_CHAN, + CLOUD_CHAN +); #ifdef __cplusplus } diff --git a/firmware/src/modules/app/CMakeLists.txt b/firmware/src/modules/app/CMakeLists.txt new file mode 100644 index 00000000..969d8d82 --- /dev/null +++ b/firmware/src/modules/app/CMakeLists.txt @@ -0,0 +1,7 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/app.c) diff --git a/firmware/src/modules/app/Kconfig.app b/firmware/src/modules/app/Kconfig.app new file mode 100644 index 00000000..eeca8aef --- /dev/null +++ b/firmware/src/modules/app/Kconfig.app @@ -0,0 +1,17 @@ +module = APP +module-str = APP +source "subsys/logging/Kconfig.template.log_config" + +menu "App" + +config APP_MODULE_THREAD_STACK_SIZE + int "Thread stack size" + default 4096 + +config APP_MODULE_MESSAGE_QUEUE_SIZE + int "Message queue size" + default 5 + help + ZBus subscriber message queue size. + +endmenu diff --git a/firmware/src/modules/app/app.c b/firmware/src/modules/app/app.c new file mode 100644 index 00000000..3916edba --- /dev/null +++ b/firmware/src/modules/app/app.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include + +#include "message_channel.h" + +/* Register log module */ +LOG_MODULE_REGISTER(app, CONFIG_APP_LOG_LEVEL); + +/* Register subscriber */ +ZBUS_SUBSCRIBER_DEFINE(app, CONFIG_APP_MODULE_MESSAGE_QUEUE_SIZE); + +// TODO: configure simple_config, forward received led status to led module + +int config_cb(const char *key, const struct simple_config_val *val) +{ + int err; + + if (val->type == SIMPLE_CONFIG_VAL_STRING) { + LOG_DBG("\"%s\" = %s", key, val->val._str); + } else if (val->type == SIMPLE_CONFIG_VAL_BOOL) { + LOG_DBG("\"%s\" = %s", key, val->val._bool ? "true" : "false"); + } else if (val->type == SIMPLE_CONFIG_VAL_DOUBLE) { + LOG_DBG("\"%s\" = %f", key, val->val._double); + } else { + return -EINVAL; + } + + if (strcmp(key, "led_red") == 0) { + int status = val->val._bool; + + err = zbus_chan_pub(&LED_CHAN, &status, K_NO_WAIT); + if (err) { + LOG_ERR("zbus_chan_pub, error:%d", err); + SEND_FATAL_ERROR(); + } + + return 0; + } + + return -EINVAL; +} + +static bool check_cloud_connection(void) +{ + enum cloud_status cloud_status; + int err = zbus_chan_read(&CLOUD_CHAN, &cloud_status, K_FOREVER); + + if (err) { + LOG_ERR("zbus_chan_read, error: %d", err); + SEND_FATAL_ERROR(); + } + return cloud_status == CLOUD_CONNECTED; +} + +static void init_app_settings(void) +{ + struct simple_config_val val = {.type = SIMPLE_CONFIG_VAL_BOOL, .val._bool = true}; + int err = simple_config_set("led_red", &val); + if (err) { + LOG_ERR("simple_config_set, error: %d", err); + SEND_FATAL_ERROR(); + } +} + +static void wait_for_cloud_connection(void) +{ + const struct zbus_channel *chan; + + while (!zbus_sub_wait(&app, &chan, K_FOREVER)) { + if (&CLOUD_CHAN == chan) { + if (check_cloud_connection()) { + return; + } + } + } +} + +static void app_task(void) +{ + const struct zbus_channel *chan; + + /* Set up callback for runtime config changes from cloud */ + simple_config_set_callback(config_cb); + + /* Wait for cloud connection */ + wait_for_cloud_connection(); + + /* Set initial settting values (can be skipped if cloud initializes shadow) */ + init_app_settings(); + + /* Initial config update */ + simple_config_update(); + + while (!zbus_sub_wait(&app, &chan, K_FOREVER)) { + if (&CLOUD_CHAN == chan) { + if (!check_cloud_connection()) { + wait_for_cloud_connection(); + } + } else if (&TRIGGER_CHAN == chan) { + /* handle incoming cloud settings */ + simple_config_update(); + } + } +} + +K_THREAD_DEFINE(app_task_id, + CONFIG_APP_MODULE_THREAD_STACK_SIZE, + app_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/firmware/src/modules/error/Kconfig.error b/firmware/src/modules/error/Kconfig.error index a380e12a..66bbcf99 100644 --- a/firmware/src/modules/error/Kconfig.error +++ b/firmware/src/modules/error/Kconfig.error @@ -6,7 +6,7 @@ menu "Error" -config MQTT_SAMPLE_ERROR_REBOOT_ON_FATAL +config APP_ERROR_REBOOT_ON_FATAL bool "Reboot on fatal error" depends on REBOOT default y @@ -16,7 +16,7 @@ config MQTT_SAMPLE_ERROR_REBOOT_ON_FATAL Other parts of the stack will still reboot or not based on the CONFIG_RESET_ON_FATAL_ERROR option. -module = MQTT_SAMPLE_ERROR +module = APP_ERROR module-str = Error source "subsys/logging/Kconfig.template.log_config" diff --git a/firmware/src/modules/error/error.c b/firmware/src/modules/error/error.c index 9f0aa97e..abcddcd3 100644 --- a/firmware/src/modules/error/error.c +++ b/firmware/src/modules/error/error.c @@ -11,12 +11,12 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(error, CONFIG_MQTT_SAMPLE_ERROR_LOG_LEVEL); +LOG_MODULE_REGISTER(error, CONFIG_APP_ERROR_LOG_LEVEL); void error_callback(const struct zbus_channel *chan) { if (&FATAL_ERROR_CHAN == chan) { - if (IS_ENABLED(CONFIG_MQTT_SAMPLE_ERROR_REBOOT_ON_FATAL)) { + if (IS_ENABLED(CONFIG_APP_ERROR_REBOOT_ON_FATAL)) { LOG_ERR("FATAL error, rebooting"); LOG_PANIC(); sys_reboot(0); diff --git a/firmware/src/modules/led/Kconfig.led b/firmware/src/modules/led/Kconfig.led index dfaf52eb..ca79d7f7 100644 --- a/firmware/src/modules/led/Kconfig.led +++ b/firmware/src/modules/led/Kconfig.led @@ -4,15 +4,15 @@ # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause # -menuconfig MQTT_SAMPLE_LED +menuconfig APP_LED bool "LED" select LED default y if !BOARD_NATIVE_POSIX -if MQTT_SAMPLE_LED +if APP_LED -module = MQTT_SAMPLE_LED +module = APP_LED module-str = LED source "subsys/logging/Kconfig.template.log_config" -endif # MQTT_SAMPLE_LED +endif # APP_LED diff --git a/firmware/src/modules/led/led.c b/firmware/src/modules/led/led.c index 30f8aee5..c090044f 100644 --- a/firmware/src/modules/led/led.c +++ b/firmware/src/modules/led/led.c @@ -12,19 +12,19 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(led, CONFIG_MQTT_SAMPLE_LED_LOG_LEVEL); +LOG_MODULE_REGISTER(led, CONFIG_APP_LED_LOG_LEVEL); const static struct device *led_device = DEVICE_DT_GET_ANY(gpio_leds); /* LED 1, green on Thingy:91 boards. */ -#define LED_1_GREEN 1 +#define LED_1_GREEN 0 void led_callback(const struct zbus_channel *chan) { int err = 0; - const enum network_status *status; + const int *status; - if (&NETWORK_CHAN == chan) { + if (&LED_CHAN == chan) { if (!device_is_ready(led_device)) { LOG_ERR("LED device is not ready"); @@ -34,22 +34,16 @@ void led_callback(const struct zbus_channel *chan) /* Get network status from channel. */ status = zbus_chan_const_msg(chan); - switch (*status) { - case NETWORK_CONNECTED: + if (*status) { err = led_on(led_device, LED_1_GREEN); if (err) { LOG_ERR("led_on, error: %d", err); } - break; - case NETWORK_DISCONNECTED: + } else { err = led_off(led_device, LED_1_GREEN); if (err) { LOG_ERR("led_off, error: %d", err); } - break; - default: - LOG_ERR("Unknown event: %d", *status); - break; } } } diff --git a/firmware/src/modules/location/CMakeLists.txt b/firmware/src/modules/location/CMakeLists.txt new file mode 100644 index 00000000..18d8745d --- /dev/null +++ b/firmware/src/modules/location/CMakeLists.txt @@ -0,0 +1,7 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/location.c) diff --git a/firmware/src/modules/location/Kconfig.location b/firmware/src/modules/location/Kconfig.location new file mode 100644 index 00000000..93172492 --- /dev/null +++ b/firmware/src/modules/location/Kconfig.location @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menu "Location" + depends on LOCATION + depends on LOCATION_DATA_DETAILS + +config APP_LOCATION_THREAD_STACK_SIZE + int "Thread stack size" + default 4096 + +module = APP_LOCATION +module-str = Location +source "subsys/logging/Kconfig.template.log_config" + +endmenu # Network diff --git a/firmware/src/modules/location/location.c b/firmware/src/modules/location/location.c new file mode 100644 index 00000000..2af13d62 --- /dev/null +++ b/firmware/src/modules/location/location.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "message_channel.h" +#include "modem/lte_lc.h" + +#include + +LOG_MODULE_REGISTER(location_module, CONFIG_APP_LOCATION_LOG_LEVEL); + +static K_SEM_DEFINE(location_lib_sem, 1, 1); +static K_SEM_DEFINE(modem_init_sem, 0, 1); +static K_SEM_DEFINE(trigger_sem, 0, 1); + +static void location_event_handler(const struct location_event_data *event_data); + +int nrf_cloud_coap_location_send(const struct nrf_cloud_gnss_data *gnss, bool confirmable); + +void location_module_entry(void) +{ + int err = 0; + struct location_config config = {0}; + + k_sem_take(&modem_init_sem, K_FOREVER); + + err = location_init(location_event_handler); + if (err) + { + LOG_ERR("Unable to init location library: %d", err); + } + LOG_DBG("location library initialized"); + +#if defined(CONFIG_LOCATION_METHOD_GNSS) + err = lte_lc_func_mode_set(LTE_LC_FUNC_MODE_ACTIVATE_GNSS); + if (err) + { + LOG_ERR("Unable to init GNSS: %d", err); + } else { + LOG_DBG("GNSS initialized"); + } +#endif + + while (true) + { + k_sem_take(&trigger_sem, K_FOREVER); + location_config_defaults_set(&config, 0, NULL); + config.mode = LOCATION_REQ_MODE_ALL; + err = location_request(&config); + if (err) + { + LOG_ERR("Unable to send location request: %d", err); + } + k_sem_take(&location_lib_sem, K_FOREVER); + } +} + +K_THREAD_DEFINE(location_module_tid, CONFIG_APP_LOCATION_THREAD_STACK_SIZE, + location_module_entry, NULL, NULL, NULL, + K_HIGHEST_APPLICATION_THREAD_PRIO, 0, 0); + +static void trigger_callback(const struct zbus_channel *chan) +{ + if (&TRIGGER_CHAN == chan) + { + k_sem_give(&trigger_sem); + } + if (&CLOUD_CHAN == chan) + { + enum cloud_status status = CLOUD_DISCONNECTED; + int err = zbus_chan_read(chan, &status, K_NO_WAIT); + + if (!err && status == CLOUD_CONNECTED) + { + k_sem_give(&modem_init_sem); + } + } +} + +ZBUS_LISTENER_DEFINE(location, trigger_callback); + +/* Take time from PVT data and apply it to system time. */ +static void apply_gnss_time(const struct nrf_modem_gnss_pvt_data_frame *pvt_data) +{ + struct tm gnss_time = { + .tm_year = pvt_data->datetime.year - 1900, + .tm_mon = pvt_data->datetime.month - 1, + .tm_mday = pvt_data->datetime.day, + .tm_hour = pvt_data->datetime.hour, + .tm_min = pvt_data->datetime.minute, + .tm_sec = pvt_data->datetime.seconds, + }; + + date_time_set(&gnss_time); +} + +static void report_gnss_location(const struct nrf_modem_gnss_pvt_data_frame *pvt_data) +{ + int err; + /* speed (velocity) and heading are only available when there are multiple fixes */ + /* we assume an altitude to be available (can only be missing on low-accuracy mode) */ + struct nrf_cloud_gnss_data gnss_pvt = { + .type = NRF_CLOUD_GNSS_TYPE_PVT, + .ts_ms = NRF_CLOUD_NO_TIMESTAMP, + .pvt = { + .lon = pvt_data->longitude, + .lat = pvt_data->latitude, + .accuracy = pvt_data->accuracy, + .alt = pvt_data->altitude, + .has_alt = 1, + .speed = pvt_data->speed, + .has_speed = pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_VELOCITY_VALID, + .heading = pvt_data->heading, + .has_heading = pvt_data->flags & NRF_MODEM_GNSS_PVT_FLAG_VELOCITY_VALID + } + }; + + err = nrf_cloud_coap_location_send(&gnss_pvt, true); + if (err) + { + LOG_ERR("Failed to send location data: %d", err); + } +} + +static void location_event_handler(const struct location_event_data *event_data) +{ + switch (event_data->id) + { + case LOCATION_EVT_LOCATION: + LOG_DBG("Got location: lat: %f, lon: %f, acc: %f", + event_data->location.latitude, + event_data->location.longitude, + event_data->location.accuracy); + + /* GNSS location needs to be reported manually */ + if (event_data->method == LOCATION_METHOD_GNSS) { + struct nrf_modem_gnss_pvt_data_frame pvt_data = + event_data->location.details.gnss.pvt_data; + if (event_data->location.datetime.valid) { + /* GNSS is the most accurate time source - use it. */ + apply_gnss_time(&pvt_data); + } else { + /* this should not happen */ + LOG_WRN("Got GNSS location without valid time data"); + } + report_gnss_location(&pvt_data); + } + break; + case LOCATION_EVT_RESULT_UNKNOWN: + LOG_DBG("Getting location completed with undefined result"); + break; + case LOCATION_EVT_TIMEOUT: + LOG_DBG("Getting location timed out"); + break; + case LOCATION_EVT_ERROR: + LOG_WRN("Getting location failed"); + break; + default: + LOG_DBG("Getting location: Unknown event %d", event_data->id); + break; + } + if (event_data->id == LOCATION_EVT_LOCATION || + event_data->id == LOCATION_EVT_RESULT_UNKNOWN || + event_data->id == LOCATION_EVT_TIMEOUT || + event_data->id == LOCATION_EVT_ERROR) + { + /* request completed */ + k_sem_give(&location_lib_sem); + } +} diff --git a/firmware/src/modules/network/Kconfig.network b/firmware/src/modules/network/Kconfig.network index 581268c6..fb3bfd0b 100644 --- a/firmware/src/modules/network/Kconfig.network +++ b/firmware/src/modules/network/Kconfig.network @@ -7,11 +7,11 @@ menu "Network" depends on NRF_MODEM_LIB_NET_IF || (WIFI_NRF700X && WIFI_MGMT_EXT) || BOARD_NATIVE_POSIX -config MQTT_SAMPLE_NETWORK_THREAD_STACK_SIZE +config APP_NETWORK_THREAD_STACK_SIZE int "Thread stack size" default 4096 -module = MQTT_SAMPLE_NETWORK +module = APP_NETWORK module-str = Network source "subsys/logging/Kconfig.template.log_config" diff --git a/firmware/src/modules/network/network.c b/firmware/src/modules/network/network.c index ec163e5a..3cf14c54 100644 --- a/firmware/src/modules/network/network.c +++ b/firmware/src/modules/network/network.c @@ -13,7 +13,7 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(network, CONFIG_MQTT_SAMPLE_NETWORK_LOG_LEVEL); +LOG_MODULE_REGISTER(network, CONFIG_APP_NETWORK_LOG_LEVEL); /* This module does not subscribe to any channels */ @@ -107,5 +107,5 @@ static void network_task(void) } K_THREAD_DEFINE(network_task_id, - CONFIG_MQTT_SAMPLE_NETWORK_THREAD_STACK_SIZE, + CONFIG_APP_NETWORK_THREAD_STACK_SIZE, network_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/firmware/src/modules/sampler/Kconfig.sampler b/firmware/src/modules/sampler/Kconfig.sampler index 87cba4a1..0869de90 100644 --- a/firmware/src/modules/sampler/Kconfig.sampler +++ b/firmware/src/modules/sampler/Kconfig.sampler @@ -6,17 +6,17 @@ menu "Sampler" -config MQTT_SAMPLE_SAMPLER_THREAD_STACK_SIZE +config APP_SAMPLER_THREAD_STACK_SIZE int "Thread stack size" default 1024 -config MQTT_SAMPLE_SAMPLER_MESSAGE_QUEUE_SIZE +config APP_SAMPLER_MESSAGE_QUEUE_SIZE int "Message queue size" default 5 help ZBus subscriber message queue size. -module = MQTT_SAMPLE_SAMPLER +module = APP_SAMPLER module-str = Sampler source "subsys/logging/Kconfig.template.log_config" diff --git a/firmware/src/modules/sampler/sampler.c b/firmware/src/modules/sampler/sampler.c index e1305c9e..7e2c31ef 100644 --- a/firmware/src/modules/sampler/sampler.c +++ b/firmware/src/modules/sampler/sampler.c @@ -13,10 +13,10 @@ #define FORMAT_STRING "Hello MQTT! Current uptime is: %d" /* Register log module */ -LOG_MODULE_REGISTER(sampler, CONFIG_MQTT_SAMPLE_SAMPLER_LOG_LEVEL); +LOG_MODULE_REGISTER(sampler, CONFIG_APP_SAMPLER_LOG_LEVEL); /* Register subscriber */ -ZBUS_SUBSCRIBER_DEFINE(sampler, CONFIG_MQTT_SAMPLE_SAMPLER_MESSAGE_QUEUE_SIZE); +ZBUS_SUBSCRIBER_DEFINE(sampler, CONFIG_APP_SAMPLER_MESSAGE_QUEUE_SIZE); static void sample(void) { @@ -34,6 +34,7 @@ static void sample(void) SEND_FATAL_ERROR(); return; } + payload.string_len = len; err = zbus_chan_pub(&PAYLOAD_CHAN, &payload, K_SECONDS(1)); if (err) { @@ -54,5 +55,5 @@ static void sampler_task(void) } K_THREAD_DEFINE(sampler_task_id, - CONFIG_MQTT_SAMPLE_SAMPLER_THREAD_STACK_SIZE, + CONFIG_APP_SAMPLER_THREAD_STACK_SIZE, sampler_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/firmware/src/modules/transport/CMakeLists.txt b/firmware/src/modules/transport/CMakeLists.txt index 69b22d8f..fd151927 100644 --- a/firmware/src/modules/transport/CMakeLists.txt +++ b/firmware/src/modules/transport/CMakeLists.txt @@ -6,24 +6,3 @@ target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/transport.c) -# Add Client ID helper library -add_subdirectory(client_id) - -# Add credentials provision library if the Modem key Management API is enabled. -# The library provisions credentials placed in the src/transport/credentials/ folder to -# the nRF91 modem. -add_subdirectory_ifdef(CONFIG_MODEM_KEY_MGMT credentials_provision) - -# Make the folder that contains the CA certificate for "test.mosquitto.org" global so that it can -# be located by the MQTT helper library / local credential provision library. -# -# The MQTT helper library provisions the certificate -# to the Mbed TLS stack for Native Posix and nRF7 Series devices. -# -# The credential provision library provisions the certificate -# to the modem's network stack for nRF91 Series builds. -# -# CONFIG_MODEM_KEY_MGMT and CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES are mutually exclusive. -# -zephyr_include_directories_ifdef(CONFIG_MODEM_KEY_MGMT credentials) -zephyr_include_directories_ifdef(CONFIG_MQTT_HELPER_PROVISION_CERTIFICATES credentials) diff --git a/firmware/src/modules/transport/Kconfig.transport b/firmware/src/modules/transport/Kconfig.transport index b546e8a7..3bf5f154 100644 --- a/firmware/src/modules/transport/Kconfig.transport +++ b/firmware/src/modules/transport/Kconfig.transport @@ -5,58 +5,38 @@ # menu "Transport" - depends on MQTT_HELPER - depends on HW_ID_LIBRARY + depends on NRF_CLOUD_COAP + depends on SIMPLE_CONFIG -config MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS +config APP_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS int "Reconnection timeout in seconds" default 60 help Time in between reconnection attempts to the MQTT broker. -config MQTT_SAMPLE_TRANSPORT_THREAD_STACK_SIZE +config APP_TRANSPORT_THREAD_STACK_SIZE int "Thread stack size" default 2048 -config MQTT_SAMPLE_TRANSPORT_MESSAGE_QUEUE_SIZE +config APP_TRANSPORT_MESSAGE_QUEUE_SIZE int "Message queue size" default 5 help ZBus subscriber message queue size. -config MQTT_SAMPLE_TRANSPORT_WORKQUEUE_STACK_SIZE +config APP_TRANSPORT_WORKQUEUE_STACK_SIZE int "Workqueue stack size" default 4096 help Stack size of the module's internal workqueue. -config MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME - string "MQTT broker hostname" - default "test.mosquitto.org" - -config MQTT_SAMPLE_TRANSPORT_CLIENT_ID - string "MQTT Client ID" - default "" - help - Use a custom client ID string. If not set, the client ID will default to the - modem's IMEI number for nRF91 Series devices, MAC address for nRF7 Series devices, - or a random number for Native Posix. - -config MQTT_SAMPLE_TRANSPORT_CLIENT_ID_BUFFER_SIZE - int "MQTT Client ID buffer size" - default 50 +config APP_TRANSPORT_POLL_INTERVAL_SECONDS + int "Poll interval in seconds" + default 10 help - Size of buffer used to store the MQTT client ID. - -config MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC - string "MQTT publish topic" - default "my/publish/topic" - -config MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC - string "MQTT subscribe topic" - default "my/subscribe/topic" + Interval in seconds between polling nRF Cloud CoAP. -module = MQTT_SAMPLE_TRANSPORT +module = APP_TRANSPORT module-str = Transport source "subsys/logging/Kconfig.template.log_config" diff --git a/firmware/src/modules/transport/client_id/CMakeLists.txt b/firmware/src/modules/transport/client_id/CMakeLists.txt deleted file mode 100644 index af3f4340..00000000 --- a/firmware/src/modules/transport/client_id/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_include_directories(app PRIVATE .) - -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/client_id.c) diff --git a/firmware/src/modules/transport/client_id/client_id.c b/firmware/src/modules/transport/client_id/client_id.c deleted file mode 100644 index 61c7c0eb..00000000 --- a/firmware/src/modules/transport/client_id/client_id.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include -#include -#include -#include - -int client_id_get(char *const buffer, size_t buffer_size) -{ - int ret; - - if (sizeof(CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID) - 1 > 0) { - ret = snprintk(buffer, buffer_size, "%s", CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID); - if ((ret < 0) || (ret >= buffer_size)) { - return -EMSGSIZE; - } - } else if (IS_ENABLED(CONFIG_BOARD_NATIVE_POSIX)) { - ret = snprintk(buffer, buffer_size, "%d", sys_rand32_get()); - if ((ret < 0) || (ret >= buffer_size)) { - return -EMSGSIZE; - } - } else { - ret = hw_id_get(buffer, buffer_size); - if (ret) { - return ret; - } - } - - return 0; -} diff --git a/firmware/src/modules/transport/client_id/client_id.h b/firmware/src/modules/transport/client_id/client_id.h deleted file mode 100644 index f3a307a9..00000000 --- a/firmware/src/modules/transport/client_id/client_id.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ -#include - -/** @brief Get Client ID name. Either retrieved from the HW ID library or - * CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID if set. - * For Native Posix builds a random uint32 bit value is returned. - * - * @param buffer Pointer to buffer that the Client ID will be written to. - * @param buffer_size Size of buffer. - * - * @return 0 If successful. Otherwise, a negative error code is returned. - * @retval -EMSGSIZE if the passed in buffer is too small. - * @retval -EINVAL If the passed in pointer is NULL or buffer is too small. - */ -int client_id_get(char *const buffer, size_t buffer_size); diff --git a/firmware/src/modules/transport/credentials/ca-cert.pem b/firmware/src/modules/transport/credentials/ca-cert.pem deleted file mode 100644 index 7b0cbc7d..00000000 --- a/firmware/src/modules/transport/credentials/ca-cert.pem +++ /dev/null @@ -1,26 +0,0 @@ -/* Certificate Authority (CA) for mosquitto.org */ - -"-----BEGIN CERTIFICATE-----\n" -"MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL\n" -"BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG\n" -"A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU\n" -"BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv\n" -"by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE\n" -"BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES\n" -"MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp\n" -"dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ\n" -"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg\n" -"UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW\n" -"Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA\n" -"s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH\n" -"3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo\n" -"E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT\n" -"MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV\n" -"6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n" -"BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC\n" -"6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf\n" -"+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK\n" -"sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839\n" -"LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE\n" -"m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=\n" -"-----END CERTIFICATE-----" diff --git a/firmware/src/modules/transport/credentials_provision/CMakeLists.txt b/firmware/src/modules/transport/credentials_provision/CMakeLists.txt deleted file mode 100644 index 68950a0c..00000000 --- a/firmware/src/modules/transport/credentials_provision/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause -# - -target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/credentials_provision.c) diff --git a/firmware/src/modules/transport/credentials_provision/credentials_provision.c b/firmware/src/modules/transport/credentials_provision/credentials_provision.c deleted file mode 100644 index f4c4d052..00000000 --- a/firmware/src/modules/transport/credentials_provision/credentials_provision.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause - */ - -#include -#include - -static const unsigned char ca_certificate[] = { -#if __has_include("ca-cert.pem") -#include "ca-cert.pem" -#else -"" -#endif -}; - -static const unsigned char device_certificate[] = { -#if __has_include("client-cert.pem") -#include "client-cert.pem" -#else -"" -#endif -}; - -static const unsigned char private_key[] = { -#if __has_include("private-key.pem") -#include "private-key.pem" -#else -"" -#endif -}; - -#if CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG != -1 - -static const unsigned char ca_certificate_2[] = { -#if __has_include("ca-cert-2.pem") -#include "ca-cert-2.pem" -#else -"" -#endif -}; - -static const unsigned char private_key_2[] = { -#if __has_include("private-key-2.pem") -#include "private-key-2.pem" -#else -"" -#endif -}; - -static const unsigned char device_certificate_2[] = { -#if __has_include("client-cert-2.pem") -#include "client-cert-2.pem" -#else -"" -#endif -}; - -#endif /* CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG != -1 */ - -static int credentials_provision(void) -{ - int err = 0; - - if (sizeof(ca_certificate) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, - ca_certificate, - sizeof(ca_certificate) - 1); - if (err) { - return err; - } - } - - if (sizeof(device_certificate) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_PUBLIC_CERT, - device_certificate, - sizeof(device_certificate) - 1); - if (err) { - return err; - } - } - - if (sizeof(private_key) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_PRIVATE_CERT, - private_key, - sizeof(private_key) - 1); - if (err) { - return err; - } - } - - /* Secondary security tag entries. */ - -#if CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG != -1 - - if (sizeof(ca_certificate_2) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, - ca_certificate_2, - sizeof(ca_certificate_2) - 1); - if (err) { - return err; - } - } - - if (sizeof(device_certificate_2) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_PUBLIC_CERT, - device_certificate_2, - sizeof(device_certificate_2) - 1); - if (err) { - return err; - } - } - - if (sizeof(private_key_2) > 1) { - err = modem_key_mgmt_write(CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG, - MODEM_KEY_MGMT_CRED_TYPE_PRIVATE_CERT, - private_key_2, - sizeof(private_key_2) - 1); - if (err) { - return err; - } - } - -#endif /* CONFIG_MQTT_HELPER_SECONDARY_SEC_TAG != -1 */ - - return err; -} - -NRF_MODEM_LIB_ON_INIT(mqtt_sample_init_hook, on_modem_lib_init, NULL); - -static void on_modem_lib_init(int ret, void *ctx) -{ - credentials_provision(); -} diff --git a/firmware/src/modules/transport/transport.c b/firmware/src/modules/transport/transport.c index abb90976..4a55403d 100644 --- a/firmware/src/modules/transport/transport.c +++ b/firmware/src/modules/transport/transport.c @@ -8,19 +8,17 @@ #include #include #include -#include +#include +#include +#include -#include "client_id.h" #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(transport, CONFIG_MQTT_SAMPLE_TRANSPORT_LOG_LEVEL); +LOG_MODULE_REGISTER(transport, CONFIG_APP_TRANSPORT_LOG_LEVEL); /* Register subscriber */ -ZBUS_SUBSCRIBER_DEFINE(transport, CONFIG_MQTT_SAMPLE_TRANSPORT_MESSAGE_QUEUE_SIZE); - -/* ID for subscribe topic - Used to verify that a subscription succeeded in on_mqtt_suback(). */ -#define SUBSCRIBE_TOPIC_ID 2469 +ZBUS_SUBSCRIBER_DEFINE(transport, CONFIG_APP_TRANSPORT_MESSAGE_QUEUE_SIZE); /* Forward declarations */ static const struct smf_state state[]; @@ -30,21 +28,15 @@ static void connect_work_fn(struct k_work *work); static K_WORK_DELAYABLE_DEFINE(connect_work, connect_work_fn); /* Define stack_area of application workqueue */ -K_THREAD_STACK_DEFINE(stack_area, CONFIG_MQTT_SAMPLE_TRANSPORT_WORKQUEUE_STACK_SIZE); +K_THREAD_STACK_DEFINE(stack_area, CONFIG_APP_TRANSPORT_WORKQUEUE_STACK_SIZE); /* Declare application workqueue. This workqueue is used to call mqtt_helper_connect(), and * schedule reconnectionn attempts upon network loss or disconnection from MQTT. */ static struct k_work_q transport_queue; -/* Internal states */ -enum module_state { MQTT_CONNECTED, MQTT_DISCONNECTED }; - -/* MQTT client ID buffer */ -static char client_id[CONFIG_MQTT_SAMPLE_TRANSPORT_CLIENT_ID_BUFFER_SIZE]; - -static uint8_t pub_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC)]; -static uint8_t sub_topic[sizeof(client_id) + sizeof(CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC)]; +/* Semaphore to mark when we have a valid time */ +K_SEM_DEFINE(date_time_ready_sem, 0, 1); /* User defined state object. * Used to transfer data between state changes. @@ -63,119 +55,6 @@ static struct s_object { struct payload payload; } s_obj; -/* Callback handlers from MQTT helper library. - * The functions are called whenever specific MQTT packets are received from the broker, or - * some library state has changed. - */ -static void on_mqtt_connack(enum mqtt_conn_return_code return_code, bool session_present) -{ - ARG_UNUSED(return_code); - - smf_set_state(SMF_CTX(&s_obj), &state[MQTT_CONNECTED]); -} - -static void on_mqtt_disconnect(int result) -{ - ARG_UNUSED(result); - - smf_set_state(SMF_CTX(&s_obj), &state[MQTT_DISCONNECTED]); -} - -static void on_mqtt_publish(struct mqtt_helper_buf topic, struct mqtt_helper_buf payload) -{ - LOG_INF("Received payload: %.*s on topic: %.*s", payload.size, - payload.ptr, - topic.size, - topic.ptr); -} - -static void on_mqtt_suback(uint16_t message_id, int result) -{ - if ((message_id == SUBSCRIBE_TOPIC_ID) && (result == 0)) { - LOG_INF("Subscribed to topic %s", sub_topic); - } else if (result) { - LOG_ERR("Topic subscription failed, error: %d", result); - } else { - LOG_WRN("Subscribed to unknown topic, id: %d", message_id); - } -} - -/* Local convenience functions */ - -/* Function that prefixes topics with the Client ID. */ -static int topics_prefix(void) -{ - int len; - - len = snprintk(pub_topic, sizeof(pub_topic), "%s/%s", client_id, - CONFIG_MQTT_SAMPLE_TRANSPORT_PUBLISH_TOPIC); - if ((len < 0) || (len >= sizeof(pub_topic))) { - LOG_ERR("Publish topic buffer too small"); - return -EMSGSIZE; - } - - len = snprintk(sub_topic, sizeof(sub_topic), "%s/%s", client_id, - CONFIG_MQTT_SAMPLE_TRANSPORT_SUBSCRIBE_TOPIC); - if ((len < 0) || (len >= sizeof(sub_topic))) { - LOG_ERR("Subscribe topic buffer too small"); - return -EMSGSIZE; - } - - return 0; -} - -static void publish(struct payload *payload) -{ - int err; - - struct mqtt_publish_param param = { - .message.payload.data = payload->string, - .message.payload.len = strlen(payload->string), - .message.topic.qos = MQTT_QOS_1_AT_LEAST_ONCE, - .message_id = k_uptime_get_32(), - .message.topic.topic.utf8 = pub_topic, - .message.topic.topic.size = strlen(pub_topic), - }; - - err = mqtt_helper_publish(¶m); - if (err) { - LOG_WRN("Failed to send payload, err: %d", err); - return; - } - - LOG_INF("Published message: \"%.*s\" on topic: \"%.*s\"", param.message.payload.len, - param.message.payload.data, - param.message.topic.topic.size, - param.message.topic.topic.utf8); -} - -static void subscribe(void) -{ - int err; - - struct mqtt_topic topics[] = { - { - .topic.utf8 = sub_topic, - .topic.size = strlen(sub_topic), - }, - }; - struct mqtt_subscription_list list = { - .list = topics, - .list_count = ARRAY_SIZE(topics), - .message_id = SUBSCRIBE_TOPIC_ID, - }; - - for (size_t i = 0; i < list.list_count; i++) { - LOG_INF("Subscribing to: %s", (char *)list.list[i].topic.utf8); - } - - err = mqtt_helper_subscribe(&list); - if (err) { - LOG_ERR("Failed to subscribe to topics, error: %d", err); - return; - } -} - /* Connect work - Used to establish a connection to the MQTT broker and schedule reconnection * attempts. */ @@ -184,34 +63,52 @@ static void connect_work_fn(struct k_work *work) ARG_UNUSED(work); int err; - struct mqtt_helper_conn_params conn_params = { - .hostname.ptr = CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME, - .hostname.size = strlen(CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME), - .device_id.ptr = client_id, - .device_id.size = strlen(client_id), - }; + char buf[NRF_CLOUD_CLIENT_ID_MAX_LEN]; - err = client_id_get(client_id, sizeof(client_id)); - if (err) { - LOG_ERR("client_id_get, error: %d", err); + err = nrf_cloud_client_id_get(buf, sizeof(buf)); + if (!err) { + LOG_INF("Connecting to nRF Cloud CoAP with client ID: %s", buf); + } else { + LOG_ERR("nrf_cloud_client_id_get, error: %d", err); SEND_FATAL_ERROR(); - return; } - err = topics_prefix(); - if (err) { - LOG_ERR("topics_prefix, error: %d", err); - SEND_FATAL_ERROR(); - return; + err = nrf_cloud_coap_connect(NULL); + if (err) + { + LOG_ERR("nrf_cloud_coap_connect, error: %d", err); + goto retry; + } else { + LOG_INF("Connected to Cloud"); } - err = mqtt_helper_connect(&conn_params); - if (err) { - LOG_ERR("Failed connecting to MQTT, error code: %d", err); + struct nrf_cloud_svc_info_ui ui_info = { + .gnss = true, + }; + struct nrf_cloud_svc_info service_info = { + .ui = &ui_info}; + struct nrf_cloud_modem_info modem_info = { + .device = NRF_CLOUD_INFO_SET, + .network = NRF_CLOUD_INFO_SET, + }; + struct nrf_cloud_device_status device_status = { + .modem = &modem_info, + .svc = &service_info}; + + /* sending device info to shadow */ + err = nrf_cloud_coap_shadow_device_status_update(&device_status); + if (err) + { + LOG_ERR("nrf_cloud_coap_shadow_device_status_update, error: %d", err); + SEND_FATAL_ERROR(); + } else { + smf_set_state(SMF_CTX(&s_obj), &state[CLOUD_CONNECTED]); + return; } +retry: k_work_reschedule_for_queue(&transport_queue, &connect_work, - K_SECONDS(CONFIG_MQTT_SAMPLE_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS)); + K_SECONDS(CONFIG_APP_TRANSPORT_RECONNECTION_TIMEOUT_SECONDS)); } /* Zephyr State Machine framework handlers */ @@ -220,12 +117,27 @@ static void connect_work_fn(struct k_work *work) static void disconnected_entry(void *o) { struct s_object *user_object = o; + int err; + + enum cloud_status status = CLOUD_DISCONNECTED; + err = zbus_chan_pub(&CLOUD_CHAN, &status, K_NO_WAIT); + + if (err) { + LOG_ERR("zbus_chan_pub, error: %d", err); + SEND_FATAL_ERROR(); + } /* Reschedule a connection attempt if we are connected to network and we enter the * disconnected state. */ if (user_object->status == NETWORK_CONNECTED) { k_work_reschedule_for_queue(&transport_queue, &connect_work, K_NO_WAIT); + } else { + err = nrf_cloud_coap_disconnect(); + if (err && (err != -ENOTCONN)) { + LOG_ERR("nrf_cloud_coap_disconnect, error: %d", err); + SEND_FATAL_ERROR(); + } } } @@ -249,23 +161,27 @@ static void disconnected_run(void *o) */ k_work_reschedule_for_queue(&transport_queue, &connect_work, K_SECONDS(5)); } + + if (user_object->chan == &PAYLOAD_CHAN) { + LOG_ERR("Discarding payload since we are not connected to cloud."); + } } /* Function executed when the module enters the connected state. */ static void connected_entry(void *o) { - LOG_INF("Connected to MQTT broker"); - LOG_INF("Hostname: %s", CONFIG_MQTT_SAMPLE_TRANSPORT_BROKER_HOSTNAME); - LOG_INF("Client ID: %s", client_id); - LOG_INF("Port: %d", CONFIG_MQTT_HELPER_PORT); - LOG_INF("TLS: %s", IS_ENABLED(CONFIG_MQTT_LIB_TLS) ? "Yes" : "No"); - ARG_UNUSED(o); + enum cloud_status status = CLOUD_CONNECTED; + int err = zbus_chan_pub(&CLOUD_CHAN, &status, K_NO_WAIT); + + if (err) { + LOG_ERR("zbus_chan_pub, error: %d", err); + SEND_FATAL_ERROR(); + } + /* Cancel any ongoing connect work when we enter connected state */ k_work_cancel_delayable(&connect_work); - - subscribe(); } /* Function executed when the module is in the connected state. */ @@ -274,19 +190,16 @@ static void connected_run(void *o) struct s_object *user_object = o; if ((user_object->status == NETWORK_DISCONNECTED) && (user_object->chan == &NETWORK_CHAN)) { - /* Explicitly disconnect the MQTT transport when losing network connectivity. - * This is to cleanup any internal library state. - * The call to this function will cause on_mqtt_disconnect() to be called. - */ - (void)mqtt_helper_disconnect(); + smf_set_state(SMF_CTX(&s_obj), &state[CLOUD_DISCONNECTED]); return; } - if (user_object->chan != &PAYLOAD_CHAN) { - return; + if (user_object->chan == &PAYLOAD_CHAN) { + LOG_INF("Sending payload to cloud"); + nrf_cloud_coap_bytes_send(user_object->payload.string, + user_object->payload.string_len, + false); } - - publish(&user_object->payload); } /* Function executed when the module exits the connected state. */ @@ -294,29 +207,30 @@ static void connected_exit(void *o) { ARG_UNUSED(o); - LOG_INF("Disconnected from MQTT broker"); + LOG_INF("Disconnected from Cloud"); } /* Construct state table */ static const struct smf_state state[] = { - [MQTT_DISCONNECTED] = SMF_CREATE_STATE(disconnected_entry, disconnected_run, NULL), - [MQTT_CONNECTED] = SMF_CREATE_STATE(connected_entry, connected_run, connected_exit), + [CLOUD_DISCONNECTED] = SMF_CREATE_STATE(disconnected_entry, disconnected_run, NULL), + [CLOUD_CONNECTED] = SMF_CREATE_STATE(connected_entry, connected_run, connected_exit), }; +static void date_time_handler(const struct date_time_evt *evt) { + if (evt->type != DATE_TIME_NOT_OBTAINED) { + k_sem_give(&date_time_ready_sem); + } +} + static void transport_task(void) { int err; const struct zbus_channel *chan; enum network_status status; struct payload payload; - struct mqtt_helper_cfg cfg = { - .cb = { - .on_connack = on_mqtt_connack, - .on_disconnect = on_mqtt_disconnect, - .on_publish = on_mqtt_publish, - .on_suback = on_mqtt_suback, - }, - }; + + /* Setup handler for date_time library */ + date_time_register_handler(date_time_handler); /* Initialize and start application workqueue. * This workqueue can be used to offload tasks and/or as a timer when wanting to @@ -328,16 +242,19 @@ static void transport_task(void) K_HIGHEST_APPLICATION_THREAD_PRIO, NULL); - err = mqtt_helper_init(&cfg); - if (err) { - LOG_ERR("mqtt_helper_init, error: %d", err); + /* Set initial state */ + smf_set_initial(SMF_CTX(&s_obj), &state[CLOUD_DISCONNECTED]); + + /* Wait for initial time */ + k_sem_take(&date_time_ready_sem, K_FOREVER); + + err = nrf_cloud_coap_init(); + if (err) + { + LOG_ERR("nrf_cloud_coap_init, error: %d", err); SEND_FATAL_ERROR(); - return; } - /* Set initial state */ - smf_set_initial(SMF_CTX(&s_obj), &state[MQTT_DISCONNECTED]); - while (!zbus_sub_wait(&transport, &chan, K_FOREVER)) { s_obj.chan = chan; @@ -353,6 +270,8 @@ static void transport_task(void) s_obj.status = status; + /* connect/disconnect depending on network state */ + /* TODO: run provisioning service */ err = smf_run_state(SMF_CTX(&s_obj)); if (err) { LOG_ERR("smf_run_state, error: %d", err); @@ -383,5 +302,5 @@ static void transport_task(void) } K_THREAD_DEFINE(transport_task_id, - CONFIG_MQTT_SAMPLE_TRANSPORT_THREAD_STACK_SIZE, + CONFIG_APP_TRANSPORT_THREAD_STACK_SIZE, transport_task, NULL, NULL, NULL, 3, 0, 0); diff --git a/firmware/src/modules/trigger/Kconfig.trigger b/firmware/src/modules/trigger/Kconfig.trigger index bce43d84..f25f4a98 100644 --- a/firmware/src/modules/trigger/Kconfig.trigger +++ b/firmware/src/modules/trigger/Kconfig.trigger @@ -6,15 +6,15 @@ menu "Trigger" -config MQTT_SAMPLE_TRIGGER_THREAD_STACK_SIZE +config APP_TRIGGER_THREAD_STACK_SIZE int "Thread stack size" default 512 -config MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS +config APP_TRIGGER_TIMEOUT_SECONDS int "Trigger timer timeout" - default 60 + default 300 -module = MQTT_SAMPLE_TRIGGER +module = APP_TRIGGER module-str = Trigger source "subsys/logging/Kconfig.template.log_config" diff --git a/firmware/src/modules/trigger/trigger.c b/firmware/src/modules/trigger/trigger.c index f89ad86c..b4769450 100644 --- a/firmware/src/modules/trigger/trigger.c +++ b/firmware/src/modules/trigger/trigger.c @@ -14,7 +14,7 @@ #include "message_channel.h" /* Register log module */ -LOG_MODULE_REGISTER(trigger, CONFIG_MQTT_SAMPLE_TRIGGER_LOG_LEVEL); +LOG_MODULE_REGISTER(trigger, CONFIG_APP_TRIGGER_LOG_LEVEL); static void message_send(void) { @@ -51,10 +51,10 @@ static void trigger_task(void) while (true) { message_send(); - k_sleep(K_SECONDS(CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS)); + k_sleep(K_SECONDS(CONFIG_APP_TRIGGER_TIMEOUT_SECONDS)); } } K_THREAD_DEFINE(trigger_task_id, - CONFIG_MQTT_SAMPLE_TRIGGER_THREAD_STACK_SIZE, + CONFIG_APP_TRIGGER_THREAD_STACK_SIZE, trigger_task, NULL, NULL, NULL, 3, 0, 0);