Skip to main content

mabi_scenario/
lib.rs

1//! # mabi-scenario
2//!
3//! Scenario engine for the OTSIM protocol simulator.
4//!
5//! This crate provides:
6//! - Scenario definition and parsing (YAML/JSON)
7//! - Pattern generators (Sine, Ramp, Step, Random, Follow, Replay)
8//! - Scenario player with time scaling
9//! - Event triggers and conditions
10//! - Comprehensive schema validation
11//! - Industrial scenario templates
12//!
13//! ## Architecture
14//!
15//! ```text
16//! ┌─────────────────────────────────────────────────────────────┐
17//! │                    Scenario Engine                          │
18//! │       (Parser, Validator, Player, Event Manager)            │
19//! └─────────────────────────────────────────────────────────────┘
20//!                              │
21//!           ┌──────────────────┼──────────────────┐
22//!           ▼                  ▼                  ▼
23//! ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
24//! │    Patterns     │ │     Events      │ │    Templates    │
25//! │ (Generator)     │ │ (Triggers/Acts) │ │ (Industrial)    │
26//! └─────────────────┘ └─────────────────┘ └─────────────────┘
27//!           │                  │
28//!           ▼                  ▼
29//! ┌─────────────────┐ ┌─────────────────┐
30//! │  Follow/Replay  │ │   Validation    │
31//! │ (Advanced)      │ │ (Schema Check)  │
32//! └─────────────────┘ └─────────────────┘
33//! ```
34//!
35//! ## Quick Start
36//!
37//! ```rust,ignore
38//! use mabi_scenario::prelude::*;
39//!
40//! // Load scenario from file
41//! let scenario = ScenarioParser::parse_file("scenario.yaml")?;
42//!
43//! // Validate
44//! let validator = ScenarioValidator::new();
45//! let result = validator.validate(&scenario);
46//! if !result.is_valid() {
47//!     for error in result.errors() {
48//!         eprintln!("{}: {}", error.path, error.message);
49//!     }
50//! }
51//!
52//! // Create player and run
53//! let mut player = ScenarioPlayer::new(scenario, PlayerConfig::default());
54//! let mut rx = player.subscribe();
55//!
56//! tokio::spawn(async move {
57//!     player.run().await;
58//! });
59//!
60//! // Process updates
61//! while let Ok(update) = rx.recv().await {
62//!     println!("{}: {}", update.point_id, update.value);
63//! }
64//! ```
65
66pub mod event;
67pub mod executor;
68pub mod follow;
69pub mod generator;
70pub mod parser;
71pub mod player;
72pub mod replay;
73pub mod schema;
74pub mod templates;
75pub mod bacnet_templates;
76pub mod validation;
77
78pub use generator::{PatternGenerator, PatternType};
79pub use parser::ScenarioParser;
80pub use player::{PlayerConfig, ScenarioPlayer};
81pub use schema::{Scenario, ScenarioEvent, ScenarioPoint};
82
83// Prelude for common imports
84pub mod prelude {
85    pub use crate::event::{
86        ActionCommand, ActionResult, ComparisonOperator, EventBuilder, EventContext,
87        EventInstance, EventManager, LogLevel,
88    };
89    pub use crate::executor::{
90        DeviceRegistry, ExecutorBuilder, ExecutorConfig, ExecutorMetrics, ExecutorState,
91        ScenarioExecutor,
92    };
93    pub use crate::follow::{
94        DelayBuffer, FollowConfig, FollowManager, FollowState, SourceRegistry, TimestampedValue,
95    };
96    pub use crate::generator::{PatternGenerator, PatternType};
97    pub use crate::parser::ScenarioParser;
98    pub use crate::player::{PlayerConfig, PlayerState, ScenarioPlayer, ValueUpdate};
99    pub use crate::replay::{
100        InterpolationMethod, ReplayConfig, ReplayDataPoint, ReplayLoader, ReplayManager,
101        ReplaySeries, ReplayState,
102    };
103    pub use crate::schema::{
104        EventAction, EventTrigger, PatternConfig, Scenario, ScenarioEvent, ScenarioPoint,
105    };
106    pub use crate::templates::{
107        Template, TemplateCategory, TemplateInfo, TemplateOptions, TemplateRegistry,
108    };
109    pub use crate::bacnet_templates::register_bacnet_templates;
110    pub use crate::validation::{
111        ScenarioValidator, ValidationCode, ValidationIssue, ValidationOptions, ValidationResult,
112        ValidationSeverity,
113    };
114    pub use crate::{ScenarioError, ScenarioResult};
115}
116
117use thiserror::Error;
118use mabi_core::Error as CoreError;
119
120/// Scenario result type.
121pub type ScenarioResult<T> = Result<T, ScenarioError>;
122
123/// Scenario error types.
124#[derive(Debug, Error)]
125pub enum ScenarioError {
126    #[error("Parse error: {0}")]
127    Parse(String),
128
129    #[error("Invalid pattern: {0}")]
130    InvalidPattern(String),
131
132    #[error("Scenario not found: {0}")]
133    NotFound(String),
134
135    #[error("Player error: {0}")]
136    Player(String),
137
138    #[error("I/O error: {0}")]
139    Io(#[from] std::io::Error),
140
141    #[error("YAML error: {0}")]
142    Yaml(#[from] serde_yaml::Error),
143
144    #[error("JSON error: {0}")]
145    Json(#[from] serde_json::Error),
146
147    #[error("Core error: {0}")]
148    Core(#[from] CoreError),
149}