use crate::{DeviceError, DeviceResult};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{Duration, SystemTime};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ProtocolType {
Http,
WebSocket,
Tcp,
Serial,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProtocolConfig {
pub protocol_type: ProtocolType,
pub connection_params: ConnectionParams,
pub authentication: AuthenticationConfig,
pub timeouts: TimeoutConfig,
pub retry_config: RetryConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionParams {
pub host: String,
pub port: u16,
pub secure: bool,
pub endpoint: String,
pub parameters: HashMap<String, String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthenticationConfig {
pub auth_type: AuthenticationType,
pub username: Option<String>,
pub credentials: Option<String>,
pub api_key: Option<String>,
pub certificate_path: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AuthenticationType {
None,
Basic,
Bearer,
ApiKey,
ClientCertificate,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeoutConfig {
pub connection_timeout: Duration,
pub request_timeout: Duration,
pub response_timeout: Duration,
pub keepalive_timeout: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetryConfig {
pub max_retries: usize,
pub initial_delay: Duration,
pub max_delay: Duration,
pub backoff_multiplier: f64,
pub jitter_factor: f64,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageType {
Discovery,
Status,
Execute,
Configure,
Calibrate,
EmergencyStop,
HealthCheck,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProtocolMessage {
pub message_id: String,
pub message_type: MessageType,
pub timestamp: SystemTime,
pub sender: String,
pub recipient: String,
pub payload: HashMap<String, serde_json::Value>,
pub priority: MessagePriority,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum MessagePriority {
Low,
Normal,
High,
Critical,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProtocolResponse {
pub response_id: String,
pub timestamp: SystemTime,
pub success: bool,
pub status_code: u16,
pub status_message: String,
pub data: HashMap<String, serde_json::Value>,
pub execution_time: Duration,
}
pub struct DeviceDiscoveryProtocol {
config: ProtocolConfig,
discovered_devices: Vec<DiscoveredDevice>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscoveredDevice {
pub device_id: String,
pub device_name: String,
pub device_type: String,
pub address: String,
pub port: u16,
pub capabilities: Vec<String>,
pub status: DeviceStatus,
pub last_seen: SystemTime,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum DeviceStatus {
Online,
Busy,
Offline,
Maintenance,
Error,
Unknown,
}
impl DeviceDiscoveryProtocol {
pub const fn new(config: ProtocolConfig) -> Self {
Self {
config,
discovered_devices: Vec::new(),
}
}
pub async fn discover_devices(&mut self) -> DeviceResult<Vec<DiscoveredDevice>> {
let mock_device = DiscoveredDevice {
device_id: "neutral_atom_1".to_string(),
device_name: "Neutral Atom Device 1".to_string(),
device_type: "NeutralAtom".to_string(),
address: "192.168.1.100".to_string(),
port: 8080,
capabilities: vec![
"rydberg_gates".to_string(),
"optical_tweezers".to_string(),
"hyperfine_manipulation".to_string(),
],
status: DeviceStatus::Online,
last_seen: SystemTime::now(),
};
self.discovered_devices = vec![mock_device.clone()];
Ok(vec![mock_device])
}
pub fn get_discovered_devices(&self) -> &[DiscoveredDevice] {
&self.discovered_devices
}
pub async fn refresh_device_status(&mut self, device_id: &str) -> DeviceResult<DeviceStatus> {
for device in &mut self.discovered_devices {
if device.device_id == device_id {
device.last_seen = SystemTime::now();
return Ok(device.status.clone());
}
}
Err(DeviceError::DeviceNotFound(format!(
"Device {device_id} not found"
)))
}
}
pub struct CommandExecutionProtocol {
config: ProtocolConfig,
pending_commands: HashMap<String, PendingCommand>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingCommand {
pub command_id: String,
pub command_type: String,
pub target_device: String,
pub parameters: HashMap<String, serde_json::Value>,
pub submitted_at: SystemTime,
pub expected_completion: Option<SystemTime>,
pub status: CommandStatus,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CommandStatus {
Queued,
Executing,
Completed,
Failed,
Cancelled,
TimedOut,
}
impl CommandExecutionProtocol {
pub fn new(config: ProtocolConfig) -> Self {
Self {
config,
pending_commands: HashMap::new(),
}
}
pub async fn submit_command(
&mut self,
command_type: &str,
target_device: &str,
parameters: HashMap<String, serde_json::Value>,
) -> DeviceResult<String> {
let command_id = format!("cmd_{}", uuid::Uuid::new_v4());
let pending_command = PendingCommand {
command_id: command_id.clone(),
command_type: command_type.to_string(),
target_device: target_device.to_string(),
parameters,
submitted_at: SystemTime::now(),
expected_completion: None,
status: CommandStatus::Queued,
};
self.pending_commands
.insert(command_id.clone(), pending_command);
Ok(command_id)
}
pub fn get_command_status(&self, command_id: &str) -> DeviceResult<CommandStatus> {
self.pending_commands
.get(command_id)
.map(|cmd| cmd.status.clone())
.ok_or_else(|| DeviceError::InvalidInput(format!("Command {command_id} not found")))
}
pub async fn cancel_command(&mut self, command_id: &str) -> DeviceResult<()> {
if let Some(command) = self.pending_commands.get_mut(command_id) {
command.status = CommandStatus::Cancelled;
Ok(())
} else {
Err(DeviceError::InvalidInput(format!(
"Command {command_id} not found"
)))
}
}
pub fn get_pending_commands(&self) -> Vec<&PendingCommand> {
self.pending_commands.values().collect()
}
}
pub struct StatusMonitoringProtocol {
config: ProtocolConfig,
monitored_devices: HashMap<String, DeviceMonitoringInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceMonitoringInfo {
pub device_id: String,
pub last_update: SystemTime,
pub current_status: DeviceStatus,
pub status_history: Vec<StatusHistoryEntry>,
pub metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusHistoryEntry {
pub timestamp: SystemTime,
pub status: DeviceStatus,
pub info: Option<String>,
}
impl StatusMonitoringProtocol {
pub fn new(config: ProtocolConfig) -> Self {
Self {
config,
monitored_devices: HashMap::new(),
}
}
pub fn start_monitoring(&mut self, device_id: &str) -> DeviceResult<()> {
let monitoring_info = DeviceMonitoringInfo {
device_id: device_id.to_string(),
last_update: SystemTime::now(),
current_status: DeviceStatus::Unknown,
status_history: Vec::new(),
metrics: HashMap::new(),
};
self.monitored_devices
.insert(device_id.to_string(), monitoring_info);
Ok(())
}
pub fn stop_monitoring(&mut self, device_id: &str) -> DeviceResult<()> {
self.monitored_devices.remove(device_id);
Ok(())
}
pub fn update_device_status(
&mut self,
device_id: &str,
status: DeviceStatus,
info: Option<String>,
) -> DeviceResult<()> {
if let Some(monitoring_info) = self.monitored_devices.get_mut(device_id) {
let history_entry = StatusHistoryEntry {
timestamp: SystemTime::now(),
status: status.clone(),
info,
};
monitoring_info.current_status = status;
monitoring_info.last_update = SystemTime::now();
monitoring_info.status_history.push(history_entry);
if monitoring_info.status_history.len() > 1000 {
monitoring_info.status_history.drain(0..500);
}
Ok(())
} else {
Err(DeviceError::DeviceNotFound(format!(
"Device {device_id} not found in monitoring list"
)))
}
}
pub fn get_device_status(&self, device_id: &str) -> DeviceResult<&DeviceMonitoringInfo> {
self.monitored_devices.get(device_id).ok_or_else(|| {
DeviceError::DeviceNotFound(format!("Device {device_id} not found in monitoring list"))
})
}
pub fn get_monitored_devices(&self) -> Vec<&DeviceMonitoringInfo> {
self.monitored_devices.values().collect()
}
}
impl Default for ProtocolConfig {
fn default() -> Self {
Self {
protocol_type: ProtocolType::Http,
connection_params: ConnectionParams::default(),
authentication: AuthenticationConfig::default(),
timeouts: TimeoutConfig::default(),
retry_config: RetryConfig::default(),
}
}
}
impl Default for ConnectionParams {
fn default() -> Self {
Self {
host: "localhost".to_string(),
port: 8080,
secure: false,
endpoint: "/api/v1".to_string(),
parameters: HashMap::new(),
}
}
}
impl Default for AuthenticationConfig {
fn default() -> Self {
Self {
auth_type: AuthenticationType::None,
username: None,
credentials: None,
api_key: None,
certificate_path: None,
}
}
}
impl Default for TimeoutConfig {
fn default() -> Self {
Self {
connection_timeout: Duration::from_secs(30),
request_timeout: Duration::from_secs(60),
response_timeout: Duration::from_secs(120),
keepalive_timeout: Duration::from_secs(300),
}
}
}
impl Default for RetryConfig {
fn default() -> Self {
Self {
max_retries: 3,
initial_delay: Duration::from_millis(100),
max_delay: Duration::from_secs(30),
backoff_multiplier: 2.0,
jitter_factor: 0.1,
}
}
}
pub fn create_protocol_message(
message_type: MessageType,
sender: &str,
recipient: &str,
payload: HashMap<String, serde_json::Value>,
priority: MessagePriority,
) -> ProtocolMessage {
ProtocolMessage {
message_id: uuid::Uuid::new_v4().to_string(),
message_type,
timestamp: SystemTime::now(),
sender: sender.to_string(),
recipient: recipient.to_string(),
payload,
priority,
}
}
pub fn create_protocol_response(
request_id: &str,
success: bool,
status_code: u16,
status_message: &str,
data: HashMap<String, serde_json::Value>,
execution_time: Duration,
) -> ProtocolResponse {
ProtocolResponse {
response_id: request_id.to_string(),
timestamp: SystemTime::now(),
success,
status_code,
status_message: status_message.to_string(),
data,
execution_time,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_protocol_config_creation() {
let config = ProtocolConfig::default();
assert_eq!(config.protocol_type, ProtocolType::Http);
assert_eq!(config.connection_params.host, "localhost");
assert_eq!(config.connection_params.port, 8080);
}
#[test]
fn test_protocol_message_creation() {
let payload = HashMap::new();
let message = create_protocol_message(
MessageType::Status,
"client",
"device_1",
payload,
MessagePriority::Normal,
);
assert_eq!(message.message_type, MessageType::Status);
assert_eq!(message.sender, "client");
assert_eq!(message.recipient, "device_1");
assert_eq!(message.priority, MessagePriority::Normal);
}
#[test]
fn test_device_discovery() {
let config = ProtocolConfig::default();
let discovery = DeviceDiscoveryProtocol::new(config);
assert_eq!(discovery.get_discovered_devices().len(), 0);
}
}
mod uuid {
use std::fmt;
pub struct Uuid([u8; 16]);
impl Uuid {
pub fn new_v4() -> Self {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::time::SystemTime;
let mut hasher = DefaultHasher::new();
SystemTime::now().hash(&mut hasher);
let hash = hasher.finish();
let mut bytes = [0u8; 16];
bytes[0..8].copy_from_slice(&hash.to_le_bytes());
bytes[8..16].copy_from_slice(&hash.to_be_bytes());
Self(bytes)
}
}
impl fmt::Display for Uuid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
self.0[0], self.0[1], self.0[2], self.0[3],
self.0[4], self.0[5],
self.0[6], self.0[7],
self.0[8], self.0[9],
self.0[10], self.0[11], self.0[12], self.0[13], self.0[14], self.0[15])
}
}
}