Skip to content

Commit 26543a4

Browse files
simensrostadjtguggedal
authored andcommitted
modules: main: Add CDDL CBOR encoding of device shadow
Add missing CDDL CBOR decoding of incoming data. Used to decode update interval set in cloud. Tests are updated to check new configuration, in addition to using some convenience functions for expected events. Signed-off-by: Simen S. Røstad <simen.rostad@nordicsemi.no>
1 parent 6fce775 commit 26543a4

File tree

9 files changed

+331
-110
lines changed

9 files changed

+331
-110
lines changed

app/src/cbor/CMakeLists.txt

+28
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,31 @@
66

77
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cbor_helper.c)
88
target_include_directories(app PRIVATE .)
9+
10+
# generate encoder code using zcbor
11+
set(zcbor_command
12+
zcbor code # Invoke code generation
13+
--cddl ${CMAKE_CURRENT_SOURCE_DIR}/device_shadow.cddl
14+
--decode # Generate decoding functions
15+
--short-names # Attempt to make generated symbol names shorter (at the risk of collision)
16+
-t config-object # Create a public API for decoding the "config-object" type from the cddl file
17+
--output-cmake device_shadow.cmake # The generated cmake file will be placed here
18+
)
19+
execute_process(COMMAND ${zcbor_command}
20+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
21+
COMMAND_ERROR_IS_FATAL ANY)
22+
23+
# Include the cmake file generated by zcbor. It adds the
24+
# generated code and the necessary zcbor C code files.
25+
include(${CMAKE_CURRENT_BINARY_DIR}/device_shadow.cmake)
26+
27+
# Ensure that the cmake reconfiguration is triggerred everytime the cddl file changes.
28+
# This ensures that the codec generation is triggered.
29+
set_property(
30+
DIRECTORY
31+
PROPERTY
32+
CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/device_shadow.cddl
33+
)
34+
35+
zephyr_link_libraries(device_shadow)
36+
target_link_libraries(device_shadow PRIVATE zephyr_interface)

app/src/cbor/cbor_helper.c

+13-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@
33
*
44
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
*/
6-
7-
#include <zephyr/logging/log.h>
8-
9-
LOG_MODULE_DECLARE(main, CONFIG_APP_LOG_LEVEL);
6+
#include <errno.h>
7+
#include "device_shadow_decode.h"
108

119
int get_update_interval_from_cbor_response(const uint8_t *cbor,
1210
size_t len,
1311
uint64_t *interval_sec)
1412
{
15-
*interval_sec = 1800;
13+
struct config_object object = { 0 };
14+
size_t not_used;
15+
16+
int err = cbor_decode_config_object(cbor, len, &object, &not_used);
17+
18+
if (err) {
19+
return -EFAULT;
20+
}
21+
22+
*interval_sec = object.update_interval;
23+
1624
return 0;
1725
}

app/src/cbor/cbor_helper.h

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66

77
#include <zephyr/types.h>
88

9+
/**
10+
* @brief Get the update interval from a CBOR buffer.
11+
*
12+
* @param[in] cbor The CBOR buffer.
13+
* @param[in] len The length of the CBOR buffer.
14+
* @param[out] interval_sec The update interval in seconds.
15+
*
16+
* @returns 0 If the operation was successful.
17+
* Otherwise, a (negative) error code is returned.
18+
* @retval -EFAULT if the CBOR buffer is invalid.
19+
*
20+
*/
921
int get_update_interval_from_cbor_response(const uint8_t *cbor,
1022
size_t len,
1123
uint64_t *interval_sec);

app/src/cbor/device_shadow.cddl

+4-52
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,5 @@
1-
; Define the basic structure of the JSON object
2-
3-
; The 'any' type is used in this schema to allow forward compatibility.
4-
; They are inserted into maps that may contain additional fields in the future.
5-
; This prevents cbor decoding from failing in the field when the cloud side has new fields.
6-
app-object = {
7-
? "nrfcloud_mqtt_topic_prefix": tstr,
8-
? "pairing": pairing-type,
9-
? "lwm2m": lwm2m-map,
10-
* tstr => any
11-
}
12-
13-
; Define the pairing object with nested topics
14-
pairing-type = {
15-
"state": tstr,
16-
"topics": {
17-
"d2c": tstr,
18-
"c2d": tstr,
19-
* tstr => any
20-
},
21-
* any => any
22-
}
23-
24-
lwm2m-map = {
25-
? "14240:1.0": led,
26-
? "14301:1.0": config,
27-
* tstr => any
28-
}
29-
30-
led = {
31-
"0": led_inner_object,
32-
* tstr => any
33-
}
34-
35-
led_inner_object = {
36-
? "0": int .size 4,
37-
? "1": int .size 4,
38-
? "2": int .size 4,
39-
"99": int .size 8,
40-
* tstr => any
41-
}
42-
43-
config = {
44-
"0": config_inner_object,
45-
* tstr => any
46-
}
47-
48-
config_inner_object = {
49-
? "0": int .size 8,
50-
? "1": bool,
51-
"99": int .size 8,
52-
* tstr => any
1+
config-object = {
2+
"config": {
3+
"update_interval": uint .size 8
4+
}
535
}

app/src/main.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,14 @@ static void fota_rebooting_entry(void *o);
106106
enum state {
107107
/* Normal operation */
108108
STATE_RUNNING,
109+
/* Disconnected from the cloud, no triggers are sent */
110+
STATE_IDLE,
109111
/* Triggers are periodically sent at a configured interval */
110112
STATE_TRIGGERING,
111113
/* Requesting location from the location module */
112114
STATE_REQUESTING_LOCATION,
113115
/* Requesting sensor values and polling for downlink data */
114116
STATE_REQUESTING_SENSORS_AND_POLLING,
115-
/* Disconnected from the network, no triggers are sent */
116-
STATE_IDLE,
117117
/* Ongoing FOTA process, triggers are blocked */
118118
STATE_FOTA,
119119
/* FOTA image is being downloaded */
@@ -157,6 +157,13 @@ static const struct smf_state states[] = {
157157
running_run,
158158
NULL,
159159
NULL,
160+
&states[STATE_IDLE]
161+
),
162+
[STATE_IDLE] = SMF_CREATE_STATE(
163+
idle_entry,
164+
idle_run,
165+
NULL,
166+
&states[STATE_RUNNING],
160167
NULL
161168
),
162169
[STATE_TRIGGERING] = SMF_CREATE_STATE(
@@ -180,13 +187,6 @@ static const struct smf_state states[] = {
180187
&states[STATE_TRIGGERING],
181188
NULL
182189
),
183-
[STATE_IDLE] = SMF_CREATE_STATE(
184-
idle_entry,
185-
idle_run,
186-
NULL,
187-
&states[STATE_RUNNING],
188-
NULL
189-
),
190190
[STATE_FOTA] = SMF_CREATE_STATE(
191191
fota_entry,
192192
fota_run,
@@ -460,7 +460,7 @@ static void triggering_run(void *o)
460460
msg.response.buffer_data_len,
461461
&state_object->interval_sec);
462462
if (err) {
463-
LOG_ERR("json_parse, error: %d", err);
463+
LOG_ERR("get_update_interval_from_cbor_response, error: %d", err);
464464
SEND_FATAL_ERROR();
465465
return;
466466
}

tests/module/main/CMakeLists.txt

+34-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ project(app_module_test)
1111

1212
test_runner_generate(src/main.c)
1313

14-
set(ASSET_TRACKER_TEMPLATE_DIR ../../..)
14+
set(ASSET_TRACKER_TEMPLATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
1515

1616
target_sources(app
1717
PRIVATE
@@ -67,3 +67,36 @@ target_compile_definitions(app PRIVATE
6767
-DZEPHYR_INCLUDE_SYS_REBOOT_H_
6868
-DCONFIG_APP_REQUEST_NETWORK_QUALITY=1
6969
)
70+
71+
# CONSIDER: REUSING THE CODEC GENERATION LOGIC FROM THE MAIN APP
72+
73+
# generate encoder code using zcbor
74+
set(zcbor_command
75+
zcbor code # Invoke code generation
76+
--cddl ${APPLICATION_SOURCE_DIR}/../../../app/src/cbor/device_shadow.cddl
77+
--decode # Generate decoding functions
78+
--short-names # Attempt to make generated symbol names shorter (at the risk of collision)
79+
-t config-object # Create a public API for decoding the "config-object" type from the cddl file
80+
--output-cmake device_shadow.cmake # The generated cmake file will be placed here
81+
)
82+
83+
message(WARNING ${zcbor_command})
84+
85+
execute_process(COMMAND ${zcbor_command}
86+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
87+
COMMAND_ERROR_IS_FATAL ANY)
88+
89+
# Include the cmake file generated by zcbor. It adds the
90+
# generated code and the necessary zcbor C code files.
91+
include(${CMAKE_CURRENT_BINARY_DIR}/device_shadow.cmake)
92+
93+
# # Ensure that the cmake reconfiguration is triggerred everytime the cddl file changes.
94+
# # This ensures that the codec generation is triggered.
95+
# set_property(
96+
# DIRECTORY
97+
# PROPERTY
98+
# CMAKE_CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/device_shadow.cddl
99+
# )
100+
101+
zephyr_link_libraries(device_shadow)
102+
target_link_libraries(device_shadow PRIVATE zephyr_interface)

0 commit comments

Comments
 (0)