# pamoja-sim
Hardware-free device simulators for pamoja: fake sensors with configurable noise and drift, a recording actuator, a lossy-link transport, and a drivable differential-drive robot, behind the core Sensor and Actuator traits.
<a href="https://pamoja.molex.cloud/docs/reference/rust/pamoja_sim/index.html"><img height="28" alt="API reference" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-api.svg"></a>
<a href="https://pamoja.molex.cloud/docs/guides/sim.html"><img height="28" alt="read the guide" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-guide.svg"></a>
<a href="https://crates.io/crates/pamoja-sim"><img height="28" alt="crates.io" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-cratesio.svg"></a>
<a href="https://docs.rs/pamoja-sim"><img height="28" alt="docs.rs" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-docsrs.svg"></a>
## The same capability in every language
| Rust | [`pamoja-sim`](https://crates.io/crates/pamoja-sim) | [reference](https://pamoja.molex.cloud/docs/reference/rust/pamoja_sim/index.html), [docs.rs](https://docs.rs/pamoja-sim), [install](https://pamoja.molex.cloud/docs/reference/rust.html#rust-sim) |
| TypeScript | [`@pamoja/sim`](https://www.npmjs.com/package/@pamoja/sim) | [reference](https://pamoja.molex.cloud/docs/reference/node/modules/_pamoja_sim.html), [install](https://pamoja.molex.cloud/docs/reference/node.html#node-sim) |
| Python | [`pamoja-sim`](https://pypi.org/project/pamoja-sim/) | [reference](https://pamoja.molex.cloud/docs/reference/python/pamoja/sim.html), [install](https://pamoja.molex.cloud/docs/reference/python.html#python-sim) |
| C# | [`Pamoja.Sim`](https://www.nuget.org/packages/Pamoja.Sim) | [reference](https://pamoja.molex.cloud/docs/reference/dotnet/api/Pamoja.Sim.html), [install](https://pamoja.molex.cloud/docs/reference/dotnet.html#dotnet-sim) |
Hardware-free device simulators for the pamoja SDK.
The SDK is meant to be built and tested with no hardware at all, and that promise
only holds if there are convincing stand-ins for the parts a device would have.
This crate provides those stand-ins as ordinary implementations of the core
`Sensor` and `Actuator` traits, so
they drop into a `Node`, a profile, or a test exactly where a real driver will go
once the hardware-I/O layer lands:
- `SimSensor` - a fake sensor that generates a lifelike signal from a baseline,
a drift, and bounded, seedable noise, so a control loop meets the kind of messy
input it will see in the field.
- `Replay` - a fake sensor that plays back an exact sequence of readings, for
deterministic tests and scripted demos.
- `RecordingActuator` - a fake actuator that logs every command instead of
driving hardware, so a test can assert what a control loop decided to do.
- `DegradedLink` - a `Transport` decorator that
simulates a lossy and intermittent radio link, so offline-first store-and-
forward can be proven against a realistic bad network rather than assumed.
- `SimRobot` - a hardware-free differential-drive robot driven by a `Twist` and read back as
a `Pose`, so a robot control loop can be developed and tested with no robot.
**Examples**
Drive a recording relay from a scripted probe, with no hardware:
```rust
use pamoja_core::{Actuator, Sensor};
use pamoja_sim::{RecordingActuator, Replay};
let mut probe = Replay::new(vec![3.0, 7.0]);
let mut relay = RecordingActuator::new();
let log = relay.log();
// Switch the relay on whenever the probe reads warm.
while let Ok(reading) = probe.read().await {
relay.apply(reading > 5.0).await?;
}
assert_eq!(log.commands(), vec![false, true]);
```
## License
MIT - part of the [pamoja](https://github.com/molexxxx/pamoja) workspace: one memory-safe Rust core with bindings for every language.