Pulse SDK collects device metrics using libmcu/metrics and sends them to the Pulse ingest server.
#include "pulse/pulse.h"
static void update_metrics(void *ctx)
{
metrics_set(SensorValue, get_your_sensor_value());
}
void example(void)
{
struct pulse conf = {
.token = "example-token",
.serial_number = "device-1234",
.software_version = "1.0.0",
};
if (pulse_init(&conf) != PULSE_STATUS_OK) {
return;
}
pulse_set_prepare_handler(update_metrics, NULL);
metrics_increase(RunCount);
pulse_report();
}Note
Create or copy your authentication token from product setup on
Pulse. Pass that token to pulse_init() or
set it later via pulse_update_token().
token, serial_number, and software_version are required fields in
struct pulse. All three must be non-NULL, non-empty, null-terminated
strings. The null terminator is not encoded into the payload.
Example metrics.def file:
METRICS_DEFINE_COUNTER(RunCount)
METRICS_DEFINE(SensorValue)Pulse SDK supports two transports:
coaps— default. Uses CoAP over DTLS PSK.https— uses HTTPS over TLS.
When coaps is selected, the token passed to pulse_init() is reused as the
DTLS PSK, and the SDK derives the DTLS PSK identity internally.
Platform-specific selection methods:
- Zephyr: choose
CONFIG_PULSE_TRANSPORT_COAPS=y(default) orCONFIG_PULSE_TRANSPORT_HTTPS=yinprj.conf. - ESP-IDF: choose the transport in
menuconfig. - Generic CMake / Linux: set
PULSE_TRANSPORTbefore adding the SDK subdirectory. - Baremetal Make: the Make integration auto-adds the HTTPS transport only. To use CoAPS, add the CoAPS transport source manually.
Add as a west module in your manifest:
manifest:
projects:
- name: pulse
url: https://github.com/libmcu/pulse-sdk.git
revision: main
path: modules/lib/pulseEnable the module in prj.conf:
CONFIG_PULSE=y
CONFIG_PULSE_TRANSPORT_COAPS=y
#CONFIG_PULSE_TRANSPORT_HTTPS=y
#CONFIG_PULSE_METRICS_USER_DEFINES=/path/to/metrics.defNote
The path to the metric definition file is set by CONFIG_PULSE_METRICS_USER_DEFINES.
The default value is include/metrics.def.
Clone or add as a git submodule under your project's components/ directory:
cd components
git submodule add https://github.com/libmcu/pulse-sdk.git pulseSelect the transport in menuconfig:
Component config --->
Pulse --->
(X) CoAPS (CoAP over DTLS PSK)
( ) HTTPS
CoAPS is the default.
Note
The metric definition file must be placed at main/metrics.def.
Add Pulse SDK as a subdirectory and link it to your target.
set(METRICS_USER_DEFINES "${CMAKE_CURRENT_SOURCE_DIR}/metrics.def")
set(PULSE_TRANSPORT coaps CACHE STRING "") # default
# set(PULSE_TRANSPORT https CACHE STRING "")
add_subdirectory(path/to/pulse)
target_link_libraries(your_target PRIVATE pulse)If dependency roots are not discoverable from your project layout, set them explicitly before adding the subdirectory:
set(PULSE_LIBMCU_ROOT /path/to/libmcu)
set(PULSE_CBOR_ROOT /path/to/cbor)
set(METRICS_USER_DEFINES "${CMAKE_CURRENT_SOURCE_DIR}/metrics.def")
add_subdirectory(path/to/pulse)
target_link_libraries(your_target PRIVATE pulse)If your application already builds and links libmcu on its own, keep doing so.
Pulse SDK uses libmcu as a public dependency, while cbor stays internal to
the SDK build.
If your application wants to use regular libmcu modules such as retry or
ratelim, prefer reusing the dependency target resolved by Pulse SDK instead of
cloning and linking a second libmcu copy:
target_link_libraries(your_target PRIVATE
pulse
pulse::libmcu)On Linux, pulse_collect() adds:
ports/linux/pulse_overrides.cports/linux/pulse_transport_<transport>.c
Basic integration is the same as generic CMake:
set(METRICS_USER_DEFINES "${CMAKE_CURRENT_SOURCE_DIR}/metrics.def")
set(PULSE_TRANSPORT coaps CACHE STRING "") # default
# set(PULSE_TRANSPORT https CACHE STRING "")
add_subdirectory(path/to/pulse)
add_executable(app main.c)
target_link_libraries(app PRIVATE pulse)For Make-based baremetal projects, include pulse.mk and append the exported source and include lists.
PULSE_ROOT ?= path/to/pulse
LIBMCU_ROOT ?= path/to/libmcu
CBOR_ROOT ?= path/to/cbor
include $(PULSE_ROOT)/pulse.mk
APP_SRCS += $(PULSE_SRCS)
APP_INCS += $(PULSE_INCS)
# LDFLAGS += $(PULSE_LDFLAGS) # only needed if you archive Pulse SDK separatelyWhen LIBMCU_ROOT resolves to $(PULSE_ROOT)/external/libmcu, the Make integration also pulls in:
ports/baremetal/pulse_overrides.cports/baremetal/pulse_transport_https.c- required bundled
libmcumetrics sources
If your project already builds cbor separately, switch from PULSE_SRCS
to PULSE_CORE_SRCS and keep your existing cbor ownership:
APP_SRCS += $(PULSE_CORE_SRCS)
APP_SRCS += $(YOUR_CBOR_SRCS)
APP_INCS += $(PULSE_INCS)To switch the baremetal Make integration to CoAPS, remove
ports/baremetal/pulse_transport_https.c from your build and add
ports/baremetal/pulse_transport_coaps.c instead.
METRICS_DEFINE_COUNTER(name)- Monotonically increasing integer. Use for event counts.
METRICS_DEFINE_GAUGE(name, min, max)- Bounded numeric value. Specify min and max.
METRICS_DEFINE_PERCENTAGE(name)- Integer value in the 0–100 range.
METRICS_DEFINE_TIMER(name, unit)- Time duration. Units: s, ms.
METRICS_DEFINE_STATE(name)- Discrete state code.
METRICS_DEFINE_BINARY(name)- Boolean flag: 0 or 1.
METRICS_DEFINE_BYTES(name)- Byte count.
METRICS_DEFINE(name)- Raw numeric value with no semantic constraint.
metrics_set(name, val)- Set the metric value.
metrics_increase(name)- Increment a counter by 1.
metrics_increase_by(name, val)- Increment a counter by a given amount.
metrics_reset(name)- Reset a metric to its initial value.
Pulse SDK depends on libmcu and cbor.
libmcuis a public dependency.pulse/pulse.hexposes libmcu metrics types and applications are expected to callmetrics_*()directly.cboris an internal dependency. Pulse SDK builds against it privately and does not expose it in the public API.
When CMake integration is used, dependency roots are resolved in this order:
PULSE_LIBMCU_ROOT/PULSE_CBOR_ROOTLIBMCU_ROOT/CBOR_ROOTexternal/libmcu/external/cbor- standalone CMake fetch fallback
When Make integration is used, pulse.mk resolves dependencies through:
PULSE_LIBMCU_ROOT/PULSE_CBOR_ROOTLIBMCU_ROOT/CBOR_ROOTexternal/libmcu/external/cbor
Your application must provide required Pulse metadata directly via struct pulse:
tokenserial_numbersoftware_version
Important
When PULSE_LIBMCU_ROOT or LIBMCU_ROOT points to an external libmcu root
(i.e. not the bundled external/libmcu), pulse_collect() still adds
Pulse SDK's own platform override and transport sources automatically.
You only need to ensure the following libmcu implementation is linked into the
final application, either from your existing libmcu target/library or by
adding these sources manually:
<libmcu>/modules/metrics/src/metrics.c<libmcu>/modules/metrics/src/metricfs.c<libmcu>/modules/common/src/assert.c<libmcu>/modules/common/src/base64.c(whenPULSE_TRANSPORT=coaps)