Crates.io | bissel |
lib.rs | bissel |
version | 0.2.0 |
source | src |
created_at | 2022-01-27 00:14:17.100371 |
updated_at | 2022-02-07 20:06:45.80392 |
description | Robotics-focused publish-subscribe/request-reply middleware for embedded Linux |
homepage | |
repository | https://github.com/quietlychris/bissel |
max_upload_size | |
id | 522289 |
size | 100,672 |
bissel
is an experimental robotics-focused middleware for embedded Linux. It uses a star-shaped network topology, with a focus on ease-of-use and transparent design and operation. It is more similar to ZeroMQ than to higher-level frameworks like ROS/2, but uses central coordination process similar to MOOS-IvP. Bissel currently supports both publish/subscribe and publish/request messaging patterns over TCP.
Under the hood, bissel
relies on:
sled
: High-performance embedded, thread-safe databasetokio
: Asynchronous runtime, enabling a large number of simultaneous connectionspostcard
: Efficient #![no_std]
-compatible, serde-based de/serializer designed for embedded or constrained environmentsuse bissel::*;
use serde::{Deserialize, Serialize};
// Any type implementing Debug and serde's De/Serialize traits are Bissel-compatible
// (the standard library Debug and Clone traits are also required)
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Coordinate {
x: f32,
y: f32,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// The Host is running on localhost, but any network interface such as WiFi
// or Ethernet are available as well
let mut host: Host = HostConfig::new("lo")
.socket_num(25_000)
.store_filename("store")
.build()
.unwrap();
host.start().unwrap();
// Other tasks can operate while the host is running in the background
// Build a Node
let addr = "127.0.0.1:25000".parse::<std::net::SocketAddr>().unwrap();
let node: Node<Idle, Coordinate> = NodeConfig::new("GPS_NODE")
.topic("position")
.host_addr(addr)
.build()?;
// Bissel Nodes use strict typestates; without using the connect() method first,
// the compiler won't let you use the publish() or request() methods on an Idle Node
let mut node: Node<Active, Coordinate> = node.connect()?;
// Nodes can also be subscribers, which will request topic updates from the Host
// at a given rate
let subscriber = NodeConfig::<Coordinate>::new("GPS_SUBSCRIBER")
.topic("position")
.host_addr(addr)
.build()?
.subscribe(std::time::Duration::from_millis(100))?;
let c = Coordinate { x: 4.0, y: 4.0 };
node.publish(c).unwrap();
// Since Nodes are statically-typed, the following lines would fail at
// compile-time due to type errors!
// node.publish(1usize).unwrap()
// let result: bool = node.request().unwrap();
for i in 0..5 {
// Could get this by reading a GPS, for example
let c = Coordinate { x: i as f32, y: i as f32 };
node.publish(c)?;
std::thread::sleep(std::time::Duration::from_millis(100));
let result = node.request()?;
// or could use the value held by the subscribed node
let subscription = subscriber.get_subscribed_data().unwrap();
println!("Got position: {:?}", result);
}
// host.stop()?;
Ok(())
}
Preliminary benchmark data is showing round-trip message times (publish-request-reply) on locahost
using the --release
compilation profile, on the README's Coordinate
data (strongly-typed, 8 bytes) to be ~100 microseconds.
Additional benchmarking information can be found using cargo run --release --example benchmark
.
This library is licensed under the Mozilla Public License, version 2.0 (MPL-2.0)