A command-line tool and collection of .NET libraries to simplify interacting with Ruuvi IoT sensors.
The repository contains a core library that defines common types, and listener implementations that observe the Bluetooth LE advertisements emitted by Ruuvi devices. Samples can be automatically published to an MQTT server, to an Azure Event Hub, or to an HTTP endpoint. A command-line tool provides a turnkey solution to start receiving and publishing RuuviTag sensor data to an MQTT server or Azure Event Hub.
The following Ruuvi data formats are supported:
- RAWv2 - RuuviTag
- Extended v1 - Ruuvi Air
- Data Format 6 - Ruuvi Air compatibility mode for Bluetooth adapters that do not support extended advertisements
The repository contains the following listener implementations:
- Windows (using the Windows SDK)
- Linux (using Linux.Bluetooth to receive advertisements from BlueZ's D-Bus APIs)
nruuvitag is a command-line tool for Windows and Linux that can scan for nearby RuuviTags, and publish device readings to the console, or to an MQTT server or Azure Event Hub.
Starting from v6, executables for Windows and Linux are available on the releases page. Linux container images (see below) are available on ghcr.io.
Tip
Add --help to any command to view help.
Examples:
# Scan for nearby devices
nruuvitag devices scan# Write sensor readings from all nearby devices to the console
nruuvitag publish console# Add a device to the known devices list
nruuvitag devices add \
"AB:CD:EF:01:23:45" \
--id "bedroom-1" \
--name "Master Bedroom"# Publish readings from known devices to an MQTT server
nruuvitag publish mqtt \
my-mqtt-service.local:1883 \
--client-id "MY_CLIENT_ID" \
--topic "{clientId}/my-ruuvi-tags/{deviceId}" \
--known-devices# Publish readings from nearby devices to an Azure Event Hub in batches of
# up to 100 samples
nruuvitag publish az \
"MY_CONNECTION_STRING" \
"MY_EVENT_HUB" \
--batch-size-limit 100# Publish readings from known devices to an HTTP endpoint, including
# devices using the extended advertising data format E1
nruuvitag publish http \
"https://my-receiver.local" \
--header "X-API-Key: MY_API_KEY" \
--known-devices \
--extended-advertisementsThe command-line application can be run on Linux as a container image.
Warning
Note that the container runs as the root user to allow BlueZ to access the Bluetooth adapter.
Download and run the container bootstrap script to create an executable nruuvitag command on your host machine in ~/.local/bin that bootstraps the container image for you:
curl -fsSL https://github.com/raw/wazzamatazz/NRuuviTag/refs/heads/main/scripts/bootstrap_container.sh | bashYou can then invoke the nruuvitag command as if it were installed locally on your host machine:
# List known devices
nruuvitag devices list
# Pull the latest container image
nruuvitag updateThe container requires that /var/run/dbus is mapped from host to container to enable communication with DBus in order to receive Bluetooth advertisements. The container writes configuration files to /root/.local/share/nruuvitag; it's a good idea to map a volume to this directory as well:
# Create ~/.local/share/nruuvitag/ if it does not already exist
mkdir -p $HOME/.local/share/nruuvitag
# Run the container
docker run -it --rm \
-v /var/run/dbus:/var/run/dbus \
-v $HOME/.local/share/nruuvitag:/root/.local/share/nruuvitag \
ghcr.io/wazzamatazz/nruuvitag:latestYou can append the command arguments to the end of the call to docker run e.g. to list known devices:
docker run -it --rm \
-v /var/run/dbus:/var/run/dbus \
-v $HOME/.local/share/nruuvitag:/root/.local/share/nruuvitag \
ghcr.io/wazzamatazz/nruuvitag:latest \
devices listYou can find information about the available container images here. See here for details about how to build the image locally.
The command-line application can be run as a Linux service using systemd. See here for details.
The CLI tool automatically exports logs and metrics to an OTLP-compatible endpoint if standard OpenTelemetry environment variables are set. See here for details about configuring OpenTelemetry.
Tip
See the samples folder for more detailed examples of usage.
Using the .NET libraries is very straightforward. For example, to listen via the Windows SDK using the NRuuviTag.Listener.Windows NuGet package (source):
IRuuviTagListener client = new WindowsSdkListener(new WindowsSdkListenerOptions());
await foreach (var sample in client.ListenAsync(cancellationToken)) {
// sample is a RuuviTagSample object.
}To listen via BlueZ on Linux using the NRuuviTag.Listener.Linux NuGet package (source):
IRuuviTagListener client = new BlueZListener(new BlueZListenerOptions() {
AdapterName = "hci0" // Optional, defaults to "hci0"
});
await foreach (var sample in client.ListenAsync(cancellationToken)) {
// sample is a RuuviTagSample object.
}The NRuuviTag.Publisher.Mqtt NuGet package (source) can be used to observe RuuviTag broadcasts and forward the samples to an MQTT server:
public async Task RunMqttPublisherAsync(
IRuuviTagListener listener,
ILoggerFactory? loggerFactory = null,
CancellationToken cancellationToken = default
) {
var options = new MqttPublisherOptions() {
Hostname = "my-mqtt-service.local:1883",
ClientId = "MY_CLIENT_ID"
};
await using var publisher = new MqttPublisher(
listener,
options,
new MQTTnet.MqttClientFactory(),
loggerFactory?.CreateLogger<MqttPublisher>());
await publisher.RunAsync(cancellationToken);
}The NRuuviTag.Publisher.AzureEventHubs NuGet package (source) can be used to observe RuuviTag broadcasts and forward the samples to an Azure Event Hub:
public async Task RunAzureEventHubPublisherAsync(
IRuuviTagListener listener,
ILoggerFactory? loggerFactory = null,
CancellationToken cancellationToken = default
) {
var options = new AzureEventHubPublisherOptions() {
ConnectionString = "Endpoint=sb://MY_NAMESPACE.servicebus.windows.net/;SharedAccessKeyName=MY_KEY_NAME;SharedAccessKey=MY_KEY",
EventHubName = "MY_EVENT_HUB"
};
await using var publisher = new AzureEventHubPublisher(
listener,
options,
loggerFactory?.CreateLogger<AzureEventHubPublisher>());
await publisher.RunAsync(cancellationToken);
}The NRuuviTag.Publisher.Http NuGet package (source) can be used to observe RuuviTag broadcasts and forward the samples to an HTTP endpoint:
public async Task RunHttpPublisherAsync(
IRuuviTagListener listener,
IHttpClientFactory httpClientFactory,
ILoggerFactory? loggerFactory = null,
CancellationToken cancellationToken = default
) {
var options = new HttpPublisherOptions() {
Endpoint = "https://my-receiver.local",
Headers = new Dictionary<string, string>() {
["X-API-Key"] = "MY_API_KEY"
}
};
await using var publisher = new HttpPublisher(
listener,
options,
httpClientFactory,
loggerFactory?.CreateLogger<HttpPublisher>());
await publisher.RunAsync(cancellationToken);
}In addition to specifying the endpoint URL and request headers, you can use the HttpPublisherOptions to control whether HTTP POST or PUT is used, and the maximum number of samples to send in a single request.
The repository uses Cake for cross-platform build automation.
A build can be run from the command line using the build.ps1 PowerShell script or the build.sh Bash script. For documentation about the available build script parameters, run the script without any arguments.