koprogo_api/application/ports/
iot_repository.rs

1use crate::application::dto::{ConsumptionStatsDto, DailyAggregateDto, MonthlyAggregateDto};
2use crate::domain::entities::{DeviceType, IoTReading, LinkyDevice, MetricType};
3use async_trait::async_trait;
4use chrono::{DateTime, Utc};
5use uuid::Uuid;
6
7/// Repository port for IoT readings and Linky devices
8#[async_trait]
9pub trait IoTRepository: Send + Sync {
10    // ========================================
11    // IoT Readings
12    // ========================================
13
14    /// Create a new IoT reading
15    async fn create_reading(&self, reading: &IoTReading) -> Result<IoTReading, String>;
16
17    /// Create multiple IoT readings (bulk insert)
18    async fn create_readings_bulk(&self, readings: &[IoTReading]) -> Result<usize, String>;
19
20    /// Find readings by building and time range
21    async fn find_readings_by_building(
22        &self,
23        building_id: Uuid,
24        device_type: Option<DeviceType>,
25        metric_type: Option<MetricType>,
26        start_date: DateTime<Utc>,
27        end_date: DateTime<Utc>,
28        limit: Option<usize>,
29    ) -> Result<Vec<IoTReading>, String>;
30
31    /// Get consumption statistics for a building
32    async fn get_consumption_stats(
33        &self,
34        building_id: Uuid,
35        metric_type: MetricType,
36        start_date: DateTime<Utc>,
37        end_date: DateTime<Utc>,
38    ) -> Result<ConsumptionStatsDto, String>;
39
40    /// Get daily aggregated readings
41    async fn get_daily_aggregates(
42        &self,
43        building_id: Uuid,
44        device_type: DeviceType,
45        metric_type: MetricType,
46        start_date: DateTime<Utc>,
47        end_date: DateTime<Utc>,
48    ) -> Result<Vec<DailyAggregateDto>, String>;
49
50    /// Get monthly aggregated readings
51    async fn get_monthly_aggregates(
52        &self,
53        building_id: Uuid,
54        device_type: DeviceType,
55        metric_type: MetricType,
56        start_date: DateTime<Utc>,
57        end_date: DateTime<Utc>,
58    ) -> Result<Vec<MonthlyAggregateDto>, String>;
59
60    /// Detect anomalies (readings exceeding average by threshold percentage)
61    async fn detect_anomalies(
62        &self,
63        building_id: Uuid,
64        metric_type: MetricType,
65        threshold_percentage: f64,
66        lookback_days: i64,
67    ) -> Result<Vec<IoTReading>, String>;
68
69    // ========================================
70    // Linky Devices
71    // ========================================
72
73    /// Create a new Linky device configuration
74    async fn create_linky_device(&self, device: &LinkyDevice) -> Result<LinkyDevice, String>;
75
76    /// Find Linky device by ID
77    async fn find_linky_device_by_id(&self, device_id: Uuid)
78        -> Result<Option<LinkyDevice>, String>;
79
80    /// Find Linky device by building ID
81    async fn find_linky_device_by_building(
82        &self,
83        building_id: Uuid,
84    ) -> Result<Option<LinkyDevice>, String>;
85
86    /// Find Linky device by PRM and provider
87    async fn find_linky_device_by_prm(
88        &self,
89        prm: &str,
90        provider: &str,
91    ) -> Result<Option<LinkyDevice>, String>;
92
93    /// Update Linky device (tokens, sync status, etc.)
94    async fn update_linky_device(&self, device: &LinkyDevice) -> Result<LinkyDevice, String>;
95
96    /// Delete Linky device
97    async fn delete_linky_device(&self, device_id: Uuid) -> Result<(), String>;
98
99    /// Find all Linky devices that need sync (sync_enabled=true AND (never synced OR last_sync > 24h))
100    async fn find_devices_needing_sync(&self) -> Result<Vec<LinkyDevice>, String>;
101
102    /// Find all Linky devices with expired tokens (token_expires_at <= NOW + 5 minutes)
103    async fn find_devices_with_expired_tokens(&self) -> Result<Vec<LinkyDevice>, String>;
104}