Skip to main content

Applications

In the SDK subfolder applications\, you get access to the complete code of our Catalog Applications. You can adjust the code to edit, add functionality, or develop your own based on the project structure.

We split the application functions into specific files. You don't need to follow this style. However, it is suggested that you can later easily reuse improved functionality from Catalog Applications in your code in the future.

Project Files

In the text below, we explain what each file in the project does.

FileDescription
app_backup.c
app_backup.h
CHESTER-Z1 battery back-up functionality
app_cbor.c
app_cbor.h
Encoding binary data to CBOR, cloud will then do the JSON conversion (LTE only)
app_config.c
app_config.h
Configuration options used with shell app config command + custom shell commands handlers
app_data.c
app_data.h
Structures with measured data ready to be send
app_handler.c
app_handler.h
Callback handlers for LTE or CHESTER-Z1
app_init.c
app_init.h
Application initialization
app_power.c
app_power.h
CHESTER-M internal battery voltage measurement
app_send.c
app_send.h
LTE/LoRaWAN functions to send the data
app_sensor.c
app_sensor.h
Sampling and aggregation of application's sensors
app_shell.cShell commands
app_work.c
app_work.h
Workers and timers that trigger measurements
main.cApplication entry point, LED blinking
msg_key.hAutogenerated by west build based on codec/cbor-decoder.yaml

Application Flow

main.c

The code starts in main.c where the app_init() function is called. In this app_init() all other threads are created and all the main.c does after that is feeding the watchdog and blinking the LED.

app_init.c

In this file, all the subsystems and hardware is initialized. Also, the red LED is turned on, and the code is waiting until the LTE Attach is successful. The red LED is turned off, and the code continues.

Important code is called in app_work_init(), which creates timers for sending reports and sampling/aggregating of the sensors.

app_work.c

This file contains the main functionality and logic of the application.

Each periodic action (reporting, sampling, aggregation) has its own timer created. Timer handlers are called in interrupt context, so for each timer created by K_TIMER_DEFINE we have a corresponding worker created by K_WORK_DEFINE. This way we can call any functions from the worker and use delaying and blocking API.

In app_work_init(), the timers are set based on configuration options like g_app_config.interval_sample.

When the timer is triggered, the sampling or aggregating functions from app_sensor.c are called. When the report timer is triggered, the app_send() function in app_send.c is called.

app_sensor.c

If we look for example to CHESTER Clime app_sensor.h file, there are these functions for hygro sensor:

int app_sensor_hygro_sample(void);
int app_sensor_hygro_aggreg(void);
int app_sensor_hygro_clear(void);

These functions are called from the app_work.c workers.

Function with *_sample does measurement and adds measured value to its internal buffer (see app_data_hygro structure and sample_* arrays in app_data.h).

Function with *_aggreg does aggregation on measured data in the buffer. Computing minimum, maximum, average, and median values. These 4 values are put together with current timestamp to the app_data_hygro structure to the measurements structure in app_data.h.

Function with *_clear is called immediately after the measured data are sent to make room for new aggregations. This function is called from send_work_handler().

When the report timer is triggered the app_send() from app_send.c is called.

app_send.c

This function in some applications splits based on LTE or LoRaWAN variants. See the compose() functions.

For LTE/NB-IoT the app_cbor_encode() function from app_cbor.c file is called. This function encodes all the data in measurement structures to CBOR and HARDWARIO Cloud later converts this data to JSON representation.

For the LoRaWAN variant of the application we use ctr_buf functions to create LoRaWAN binary data. We do not use CBOR on LoRaWAN because the LoRaWAN payload should be really small in some specific regions. So we need maximal data efficiency.

Adding Sensor

  • Enable sensor in prj.conf or add shield in CMakeLists.txt
  • Add sensor initialization to the app_init()
  • Create sensor data structures for samples and measurements in app_data.h
  • Create *_sample, *_aggreg and *_clear functions in app_sensor.c/h
  • Use existing or create new timers in app_work.c that calls app_sensor functions above
  • Call *_clear function in the send_work_handler()
  • Create new YAML items in codec/cbor-decoder.yaml if necessary. msg_key.h will be regenerated after west build
  • Upload updated codec to HARDWARIO Cloud with hardwario cloud codec upload ...
  • Encode measured data to CBOR in app_cbor.c

Adding Shell Config Option

  • Add a new item to the app_config structure in app_config.h
  • To set a different default value than zero/false, add initialization to m_app_config_interim in app_config.c
  • Create new function app_config_cmd_config_* definition and implementation in the app_config.c/h files
  • Add new shell command by adding SHELL_CMD_ARG to the app_shell.c
  • Create and add a new print function to app_config_cmd_config_show, which is called when you type shell command app config show
  • Add created variable to the list of save and loaded config options using SETTINGS_SET_SCALAR and EXPORT_FUNC_SCALAR