A typed, transport-independent Rust SDK for Chessnut Move boards.
Demo
use Error;
use io;
use Duration;
use Peripheral;
use BoardEvent;
use BtleplugTransport;
use ;
use ;
type AnyError = ;
async
async
async
Installation
The SDK is published on crates.io under chessnut-move.
Overview
chessnut-move is an SDK for interfacing with Chessnut Move boards, allowing you to interact with your boards via a type-safe Rust interface.
I was looking for a way to interact with my board via Rust, but none of the existing libraries offered support for the Move boards (only the Evo + other chessnut offerings).
This SDK also offers no_std support, and is runtime agnostic; so you can use whatever bluetooth
library you'd like.
[!Note] This is an independent community project and is not affiliated with or endorsed by Chessnut.
Usage
Architecture
The crate separates the Chessnut Move protocol from Bluetooth and runtime choices. This results in the crate being seperated into two layers:
| Layer | Purpose |
|---|---|
protocol |
Commands, decoded events, positions, squares, pieces, LED patterns, and protocol errors |
transport |
Notification decoding, runtime-neutral sessions, and traits for Bluetooth adapters |
The protocol layer is just a raw interface of the wire protcol for the Chessnut Move board. It makes no assumptions
about what you'll be using to talk with the board; it just provides the necessary types to do so.
The transport layer offers the actual transport mechanisim for interacting with the Chessnut Move board. It uses the
protocol layer under the hood, and facilitates the Bluetooth connections.
This separation allows protocol tests and embedded integrations to avoid specific Bluetooth dependencies, and keeps things extensible. It also keeps scan duration, device selection, pairing and reconnection in your application; where those policies can be chosen deliberately.
Transports
Transports are delibrated defined in a way that you can provide your own (eg; for your own embedded hardware or a custom Bluetooth library).
But the crate does provide a few common transports out of the box.
Tokio
[!TIP] You can find a more comprehensive example of this in the basic.rs example.
If you're using the popular async library tokio, you can take advantage of the tokio feature flag and the transports
it provides.
use Error;
use io;
use Duration;
use BoardEvent;
use ;
use timeout;
type AnyError = ;
async
Async
[!TIP] You can find a more comprehensive example of this in the async_without_tokio.rs example.
If you're using native async, but don't want to use tokio, you can use the async feature flag to access a
runtime-netural async transport.
use ;
use ;
async
btleplug
[!TIP] You can find a more comprehensive example of this in the basic.rs example.
If you're using the popular Bluetooth library blteplug, we offer additional
adapters for using it as a transport via the blteplug feature flag.
use Error;
use io;
use ;
use ;
use BtleplugTransport;
use DEVICE_NAME;
async
Blocking
[!TIP] You can find a more comprehensive example of this in the blocking_no_std.rs example.
For no_std environvments, you can use the blocking feature flag to access the Allocation-free BlockingTransport and BlockingBoard.
use ;
use ;
Custom Bluetooth Transports
If you want to add support for a custom Bluetooth library, you'll need to intregrate through one of three public traits:
- Implement
AsyncTransportfor runtime-neutral async programs. - Implement
BlockingTransportfor synchronous or embedded programs. - Implement
TokioTransportwhen the transport futures areSendand will run inside the Tokio actor.
Each trait exposes the same essential operations:
- Subscribe to a
NotificationSource. - Write a typed
Command. - Copy the next notification into the supplied buffer and return a borrowed
Notification.
Additionally, it's worth noting that unsubscribe
and close
hooks have no-op defaults for transports that do not
need explicit cleanup. The board sessions also own fixed-size notification buffers,
so a transport does not need to allocate or expose its Bluetooth library's
channel and notification-session types.
The UUIDs and characteristic mapping are public in transport::gatt.
Implementations use Command::bytes() and Command::write_kind()
and do not
need access to the actual (private) wire-format types.
To learn more, you can look at how the AsyncTransport is implemented.
Commands
Commands are transport-independent values; they can be created before a board is connected and sent through async, blocking, or Tokio-backed sessions.
These represent the actual "commands" you'll be sending to the Chessnut Move board.
Square lights
use ;
let mut leds = default ;
leds.set_color;
leds.set_color;
let command = set_leds;
board.send.await?;
Board information
let battery = board.battery_status.await?;
let pieces = board.piece_status.await?;
println!;
for tracked in pieces.pieces
Auto Move
[!NOTE] The Chessnut Move baord requires the full board FEN for auto-moves.
This means you have to provide the full
Positionwhen executing auto-moves.In a real application, derive the target from the board's latest reported position.
use ;
let stop = stop_auto_move;
Tracing
For tracing support, we provide structured diagnostics for protocol decoding, transport I/O, lifecycle transitions, actor queries, timeouts, and
recoverable failures via the tracing feature.
The SDK never installs a global subscriber; applications decide how events are formatted, filtered, and collected.
fmt
.with_env_filter
.init;
Use chessnut_move=trace to include routine command and notification traffic.
[!NOTE] Raw command and notification payloads are not recorded.
no-std usage
Disable the default features to use protocol types and notification decoding
without std, allocation, async, or a Bluetooth dependency:
[]
= {
version = "*",
= false,
}
If you don't want to implement your own transport, you can use the allocation-free blocking session:
[]
= {
version = "*",
= false,
= ["blocking"],
}
Then implement BlockingTransport and use BlockingBoard.
Note that enabling tracing in a no_std application also enables alloc.
Feature flags
| Feature | Default | Enables |
|---|---|---|
std |
Yes | Standard-library error integration |
async |
Yes | AsyncTransport, AsyncBoard, and the Board alias |
blocking |
No | Allocation-free BlockingTransport and BlockingBoard |
btleplug |
No | BtleplugTransport; also enables std and async |
tokio |
No | Actor task, cloneable handles, request helpers, lifecycle state, and event streams; also enables std, alloc, and async |
tracing |
No | Structured spans and events; also enables alloc |
alloc |
No | Allocation-dependent integrations without otherwise requiring std |
Examples
You can find example implementations under the
examples directory:
| Example | Configuration | Purpose |
|---|---|---|
basic.rs |
btleplug,tokio,tracing |
Complete desktop BLE application with scanning, status queries, events, tracing, and graceful shutdown |
blocking_no_std.rs |
--no-default-features --features blocking |
Allocation-free firmware integration using a platform-provided blocking BLE transport |
async_without_tokio.rs |
--no-default-features --features async |
Runtime-neutral async integration for a non-Tokio executor and BLE transport |
The blocking and runtime-neutral async examples are compiled as libraries
because the crate cannot select an embedded platform entry point, BLE stack, or
executor for the application. Each exposes a run function that accepts a
platform connector and demonstrates connection, initialization, battery and
tracked-piece queries, position updates, shutdown, and disconnection.
Additional Notes
- The Chessnut Move boards only allow a single bluetooth connection; so ensure you're not connecting with the native app when using the SDK.
- Bluetooth discovery and connection behavior varies by operating system and
adapter. The
btleplugadapter inherits the platform behavior ofbtleplug. Add support for your own bluetooth adapter ifblteplugdoesn't fit your requirements. - The protocol implementation is based on Chessnut's published Move API, and some manual testing.
- This library is specifically made for the Chessnut Move boards. I'm willing to adapt the library for other Chessnut boards, but I would need someone else with the boards available for testing purposes.
Support
Use the GitHub's issue tracker for reproducible bugs and feature request.
Issue templates are provided for both.
Contributing
If you're interested in contributing to the SDK, give the CONTRIBUTING doc a read.
Contributors using AI-assisted tools must also follow our AI policy.