astrotools is a Rust library (v0.8.0) that provides base traits, types, and utilities for implementing the Lightspeed protocol — a framework for building drivers for astronomical equipment (cameras, mounts, focusers, filter wheels, power boxes). It uses MQTT as its communication layer and JSON/serde for message serialization.
astrotools/
├── src/
│ ├── lib.rs # Crate root: LightspeedError, Lightspeed trait, module exports
│ ├── base.rs # PropertyManager trait
│ ├── types.rs # DeviceType enum, DevType trait
│ ├── properties.rs # Property system: PropValue, Property<T>, RangeProperty<T>, ChoiceProperty<T>
│ └── filter_wheel.rs # FilterWheel trait
├── Cargo.toml # Package manifest (edition 2021, GPL-3.0-or-later)
├── Cargo.lock # Locked dependency versions (gitignored)
├── README.md # Minimal project description
└── LICENSE # GPL-3.0-or-later
| Trait | File | Purpose |
|---|---|---|
Lightspeed |
lib.rs |
Core device trait: sync_state, update_property |
PropertyManager |
base.rs |
Low-level property access: fetch_props, update_property |
Prop<T> |
properties.rs |
Property interface: validate, update, update_int |
DevType |
types.rs |
Device type identification: dev_type() -> DeviceType |
FilterWheel |
filter_wheel.rs |
Filter wheel operations: slot control, unidirectional mode |
The property system is central to this crate. Three property types are provided:
Property<T>— Basic property with a value and read/write permissionRangeProperty<T>— Property withmin/maxbounds validationChoiceProperty<T>— Property restricted to a set of valid choices
All properties use:
Permissionenum:ReadOnly|ReadWritePropValueenum (untagged serde):Int(u32),Bool(bool),Str(String),Float(f32)UpdatePropertyRequest— JSON-deserializable update payload from MQTT
LightspeedError (in lib.rs) wraps errors with serde serialization support:
- Converts from
PropertyErrorTypeandstd::io::Error PropertyErrorTypevariants:CannotUpdateReadOnlyProp,InvalidValue,InvalidChoice,ValueOutOfRange
- Rust toolchain (edition 2021, tested with 1.93.1+)
- Cargo (comes with Rust)
# Build
cargo build
# Run all tests (12 unit tests)
cargo test
# Build in release mode
cargo build --release
# Check for errors without producing artifacts
cargo check
# Format code (use before committing)
cargo fmt
# Run linter
cargo clippyTests are co-located with source code using Rust's built-in #[cfg(test)] modules:
properties.rs— 9 unit tests + 3 serialization tests in separateunit_testsandserialization_testsmoduleslib.rs— 1 error serialization test
All 12 tests must pass before committing. Run cargo test to verify.
main— stable release branch (on remoteorigin)master— local development branch- Feature branches follow:
claude/<description>-<id>pattern
- Types, Traits, Enums:
PascalCase— e.g.,PropertyErrorType,RangeProperty,UpdatePropertyRequest - Functions, Methods, Variables:
snake_case— e.g.,fetch_props,update_property,dev_type - Constants:
SCREAMING_SNAKE_CASE(if any added)
- Trait-based abstraction — Prefer traits over concrete types for device interfaces
- Generics for properties — Use
Property<T>,RangeProperty<T>,ChoiceProperty<T>with appropriate type bounds Result<T, LightspeedError>— All fallible operations return this error type- Validate before mutate — Call
validate()before applying changes in property updates serdeon public data — All types sent over MQTT must implementSerialize/Deserialize
- Use
#[derive(Serialize, Deserialize)]fromserdefor public data types PropValueuses#[serde(untagged)]for flexible JSON parsing- Error types use
serdeto produce JSON responses over MQTT
| Crate | Version | Purpose |
|---|---|---|
serde |
1.0 | Serialization framework (with serde_derive feature) |
serde_json |
1.0 | JSON encoding/decoding for MQTT messages |
No external test frameworks — Rust's built-in testing is used exclusively.
- This is a library crate — there is no
main.rsor binary. Changes should maintain API compatibility unless a breaking version bump is intended. - GPL-3.0-or-later license — any new code added must be compatible with this license.
- Keep dependencies minimal — the crate intentionally has only 2 direct dependencies. Justify any additions.
- Run
cargo testafter any change — all 12 tests must pass. - Run
cargo clippyandcargo fmt— the codebase follows standard Rust formatting; no warnings should be introduced. - Property permission is enforced at runtime —
ReadOnlyproperties must never be updatable; tests cover this. - MQTT integration context — this library is consumed by device drivers that communicate via MQTT. Properties map directly to MQTT topics/payloads.
- Versioning — currently at 0.8.0 in
Cargo.toml; bump appropriately for breaking vs non-breaking changes.