Skip to main content

Tutorial: Send Telemetry from Teltonika RUTX Router

This tutorial will show you how to:

  • Create a custom Rust application that uses the Spotflow Device SDK and compile it for the Teltonika RUTX router.
  • Install the application on the Teltonika RUTX router as a background service.
  • Visualize the telemetry data in the instance of Grafana integrated into the Spotflow IoT Platform.

Send Telemetry schema

Requirements

  • Teltonika RUTX router (tested with RUTX50)
  • Development machine running on Linux, Windows or macOS with the following software:
    • Rust
    • cross which itself requires either Docker or Podman
    • SCP client (for example, scp on Linux and WinSCP on Windows)
    • Optional SSH client (for example, ssh on Linux and PuTTY on older versions of Windows)
  • If you are not registered to the Spotflow IoT Platform yet, Sign Up.
  • You need to have an existing Stream. A Stream called default-stream in Stream Group default-stream-group is created automatically after you register. Create a new one if you want to use a different Stream.
  • You need to have an existing Provisioning Token.

1. Configure Route to Spotflow Grafana

The Start Workspace, created when you registered, already contains an Egress Route to the Spotflow Grafana. If you're using a different Workspace, you must create the Egress Route manually.

2. Build Application

tip

You can download the precompiled binary if you don't want to build the application. In this case, skip to the next section.

Run these commands on your development machine to create a new Rust project with the necessary dependencies:

cargo new spotflow_service --bin
cd spotflow_service
cargo add chrono env_logger serde_json sysinfo
cargo add spotflow --features=openssl-vendored

Replace the contents of spotflow_service/src/main.rs with the following code (download):

spotflow_service/src/main.rs
use std::env;

use serde_json::json;
use spotflow::{DeviceClientBuilder, MessageContext};
use sysinfo::{Disks, System};

fn main() {
if env::args().len() != 3 {
eprintln!("Usage: spotflow_service <Device ID> <Provisioning Token>");
std::process::exit(1);
}

let device_id = env::args().nth(1).unwrap();
let provisioning_token = env::args().nth(2).unwrap();

// Enable logging
env_logger::Builder::from_env(
env_logger::Env::default()
.default_filter_or("sqlx=warn,ureq=warn,rumqtt=warn,ingress=info,spotflow=info,info"),
)
.init();

// Connect to the Platform (starts Device Provisioning if the Device is not already registered)
let client = DeviceClientBuilder::new(Some(device_id), provisioning_token, "spotflow.db")
.build()
.expect("Unable to build connection to the Platform");

// Create a Message context to send Messages to the default Stream of the default Stream Group
let message_context = MessageContext::new(
Some(String::from("default-stream-group")),
Some(String::from("default-stream")),
);

// Initialize the holder of the system information
let mut system = System::new();

loop {
// Send the system information to the platform:

system.refresh_cpu_usage();
system.refresh_memory();

let disks = Disks::new_with_refreshed_list();
let disk = disks
.iter()
.find(|d| d.mount_point().as_os_str() == "/")
.unwrap();

let payload = json!({
"timestamp": chrono::offset::Utc::now().to_rfc3339(),
"cpuUsagePercent": system.global_cpu_usage(),
"memoryFreeBytes": system.total_memory() - system.used_memory(),
"memoryUsedBytes": system.used_memory(),
"diskFreeBytes": disk.available_space(),
"diskUsedBytes": disk.total_space() - disk.available_space(),
})
.to_string();

client
.enqueue_message(&message_context, None, None, payload.clone().into_bytes())
.expect("Unable to send message");

println!("{payload}");

// Pause till next iteration
std::thread::sleep(std::time::Duration::from_secs(60));
}
}

The application uses the Device SDK to connect to the Spotflow IoT Platform using the provided unique Device ID and the Provisioning Token. Then, it acquires the usage of system resources using the sysinfo crate and sends this data to the Platform periodically.

This tutorial uses cross to compile the application for the processor and operating system used in Teltonika RUTX routers. Create a new file called Cross.toml in the project folder spotflow_service with the following content (download):

spotflow_service/Cross.toml
[target.armv7-unknown-linux-musleabihf]
pre-build = [
"apt-get update && apt-get install --assume-yes libssl-dev"
]

This configuration file ensures that cross will install the necessary dependencies during compilation. Finally, build the application with the following command:

cross build --release --target armv7-unknown-linux-musleabihf

The build may take a while because cross needs to download the target armv7-unknown-linux-musleabihf and compile all dependencies such as OpenSSL. Eventually, it compiles the application into the single file spotflow_service/target/armv7-unknown-linux-musleabihf/release/spotflow_service.

3. Install Application on Teltonika RUTX Router

In order to install the application, you must be able to transfer files to the Teltonika RUTX router and execute commands on its operating system. See the Teltonika Wiki for the recommended approaches according to your operating system:

First, create a new directory /root/spotflow/ on the Teltonika RUTX router and transfer the compiled binary spotflow_service to it.

Next, replace the placeholder <Your Provisioning Token> in the following code (download) with your actual Provisioning Token and create a new file /root/spotflow/start_spotflow.sh:

/root/spotflow/start_spotflow.sh
cd /root/spotflow/
./spotflow_service rutx50 <Your Provisioning Token>

This script allows you to modify the parameters of the application without recompiling it. It also uses the cd command to select which directory the application will run in, hence where the Device SDK will create the local database file spotflow.db.

The last file you'll need to create is the service init script /etc/init.d/spotflow:

/etc/init.d/spotflow
#!/bin/sh /etc/rc.common

USE_PROCD=1
START=99
STOP=01

start_service() {
procd_open_instance
procd_set_param command /bin/sh "/root/spotflow/start_spotflow.sh"
procd_set_param stdout 1
procd_set_param stderr 1
procd_close_instance
}

Later in the tutorial, you'll register the service using /etc/init.d/spotflow enable. Then, the init script will ensure that the service starts automatically whenever the Teltonika RUTX router boots up. Furthermore, the application output will be redirected to the system log.

tip

Refer to the OpenWrt procd init script tutorial for more information on how to customize the behavior of the service.

If you want to observe the output of the service, run logread -f in a separate terminal. You can also check that the service is running by executing ps | grep spotflow_service.

Eventually, you should have transferred the following files to the Teltonika RUTX router:

/root/
└── spotflow/
├── start_spotflow.sh
└── spotflow_service
/etc/
└── init.d/
└── spotflow

Run the following commands on the Teltonika RUTX router to make all the files executable, register the service and start it:

chmod +x /root/spotflow/start_spotflow.sh
chmod +x /root/spotflow/spotflow_service
chmod +x /etc/init.d/spotflow

/etc/init.d/spotflow enable
/etc/init.d/spotflow start

After you approve the Device to the Spotflow IoT Platform (see Approve Device), the service will start sending telemetry.

4. Visualize Data in Spotflow Grafana

You should see the telemetry data in the integrated instance of Grafana. See Visualize Data in Spotflow Grafana for more information on exploring the data.

We provide a custom dashboard for the telemetry:

Teltonika RUTX Dashboard

If you want to use it, download its JSON file and import it into Grafana. You'll need to select the data source device_metrics_workspace_<Your Workspace ID> from the list of available data sources. If Grafana shows Page not found right after the import, refreshing the page should help.