Reference for Rust Device SDK
You can use the crate spotflow
to integrate your Devices with the Spotflow IoT Platform.
Requirements
Compilation requirements:
- Rust toolchain for your operating system and CPU architecture.
We regularly test the compilation of the Device SDK on the following operating systems and CPU architectures:
- Linux: x86, x64, ARMv7, AArch64
- Windows: x64
- macOS: x64, AArch64
You don't need any additional software to run the Device SDK on your Device.
Installation
Navigate to your project directory and run the following command to add the dependency on the spotflow
crate to your project:
cargo add spotflow
Basic Usage
The following code connects the Device to the Platform and starts sending simulated sensor measurements.
Add the dependencies on chrono
and serde_json
(for example, using cargo add chrono serde_json
) to compile it.
You need to register to the Platform and set it up before you can use the code.
See Get Started for more information on configuring the Platform, registering your Device, and viewing the received data.
Don't forget to replace <Your Provisioning Token>
with the actual Provisioning Token from the Platform.
use serde_json::json;
use spotflow::{DeviceClientBuilder, MessageContext};
fn main() {
// Connect to the Platform (starts Device Provisioning if the Device is not already registered)
let provisioning_token = String::from("<Your Provisiniong Token>");
let client = DeviceClientBuilder::new(
Some(String::from("my-device")),
provisioning_token,
"spotflow.db",
)
.build()
.expect("Unable to build ingress connection");
// Create a Message context to send Messages to the Stream 'default' of the Stream Group 'default'
let message_context =
MessageContext::new(Some(String::from("default-stream-group")), Some(String::from("default-stream")));
// Your working code starts here. E.g. read data from your sensors and send it to the platform
for i in 0..60 {
// Example: Send sample data to the platform:
let payload = json!({
"timestamp": chrono::offset::Utc::now().to_rfc3339(),
"temperatureCelsius": 21.0 + (i as f64 * 0.05),
"humidityPercent": 50.0 + (i as f64 * 0.1),
})
.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(5));
}
// Your working code ends here.
// Wait for all the messages to be sent
loop {
let pending = client
.pending_messages_count()
.expect("Unable to obtain the number of pending messages");
if pending == 0 {
break;
}
println!("Waiting for {} more messages to be sent.", pending);
std::thread::sleep(std::time::Duration::from_secs(1));
}
}
Error Handling and Logging
The Device SDK uses anyhow::Result
to return any errors that occur when calling a method.
It uses the log
crate to log any events happening in the background.
You can use, for example, the env_logger
crate to configure 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();
Backward Compatibility
The Rust interface of the Device SDK hasn't reached the version 1.0 yet. Therefore, we might introduce minor breaking changes as we improve the interface according to user feedback. However, we don't plan to remove any existing functionality.
Reference
The API reference is available on docs.rs.
The most important types are DeviceClientBuilder
and DeviceClient
.