Skip to main content

ng_gateway_sdk/southward/
model.rs

1use super::{
2    super::{
3        supervision::{NoopObserverFactory, ObserverFactory},
4        NorthwardPublisher, RetryPolicy, Transform,
5    },
6    transport::{NoopSouthwardTransportMeter, SouthwardTransportMeter},
7    types::{AccessMode, CollectionType, DataPointType, DataType, ReportType, Status},
8    RuntimeChannel, RuntimeDevice, RuntimePoint,
9};
10use sea_orm::FromJsonQueryResult;
11use serde::{Deserialize, Serialize};
12use std::{collections::HashMap, sync::Arc, time::Duration};
13
14#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15pub struct ChannelModel {
16    pub id: i32,
17    /// Driver ID
18    pub driver_id: i32,
19    /// Name
20    pub name: String,
21    /// Collection type
22    pub collection_type: CollectionType,
23    /// Period
24    pub period: Option<u32>,
25    /// Report type
26    pub report_type: ReportType,
27    /// Status
28    pub status: Status,
29    /// Connection policy
30    pub connection_policy: ConnectionPolicy,
31    /// Driver configuration
32    pub driver_config: serde_json::Value,
33}
34
35#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
36pub struct DeviceModel {
37    pub id: i32,
38    /// Channel ID
39    pub channel_id: i32,
40    /// Device Name
41    pub device_name: String,
42    /// Device Type
43    pub device_type: String,
44    /// Enabled
45    pub status: Status,
46    /// Driver configuration
47    pub driver_config: Option<serde_json::Value>,
48}
49
50#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
51pub struct PointModel {
52    pub id: i32,
53    /// Device ID
54    pub device_id: i32,
55    /// Name
56    pub name: String,
57    /// Key
58    pub key: String,
59    /// Type
60    pub r#type: DataPointType,
61    /// Data Type
62    pub data_type: DataType,
63    /// Access Mode
64    pub access_mode: AccessMode,
65    /// Unit
66    pub unit: Option<String>,
67    /// Min Value
68    pub min_value: Option<f64>,
69    /// Max Value
70    pub max_value: Option<f64>,
71    /// Logical-layer transformation rules for this point.
72    ///
73    /// This is always present. The identity transform means:
74    /// - `datatype = None` (logical type follows wire `data_type`)
75    /// - `scale = None` (treated as 1.0)
76    /// - `offset = None` (treated as 0.0)
77    /// - `negate = false`
78    #[serde(default)]
79    pub transform: Transform,
80    /// Driver configuration
81    pub driver_config: serde_json::Value,
82}
83
84#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
85pub struct ActionModel {
86    pub id: i32,
87    /// Device ID
88    pub device_id: i32,
89    /// Name
90    pub name: String,
91    /// Command
92    pub command: String,
93    /// Inputs
94    pub inputs: Vec<Parameter>,
95}
96
97#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
98pub struct Parameter {
99    /// Name
100    pub name: String,
101    /// Key
102    pub key: String,
103    /// Data type
104    pub data_type: DataType,
105    /// Required
106    pub required: bool,
107    /// Default value
108    pub default_value: Option<serde_json::Value>,
109    /// Max value
110    pub max_value: Option<f64>,
111    /// Min value
112    pub min_value: Option<f64>,
113    /// Logical-layer transformation rules for this parameter.
114    ///
115    /// This is always present; see `PointModel::transform` for identity semantics.
116    #[serde(default)]
117    pub transform: Transform,
118    /// Driver configuration
119    pub driver_config: serde_json::Value,
120}
121
122/// Runtime init context for a southbound driver
123///
124/// Consolidated view of channel topology plus host-injected capabilities for driver initialization.
125/// @author saiki
126#[derive(Clone)]
127pub struct SouthwardInitContext {
128    /// All devices under this channel
129    pub devices: Vec<Arc<dyn RuntimeDevice>>,
130    /// Points grouped by device id
131    pub points_by_device: HashMap<i32, Vec<Arc<dyn RuntimePoint>>>,
132    /// Runtime channel configuration and policies
133    pub runtime_channel: Arc<dyn RuntimeChannel>,
134    /// Northbound publisher injected by the host
135    pub publisher: Arc<dyn NorthwardPublisher>,
136    /// Channel id (fast access; avoid repeated downcasts).
137    pub channel_id: i32,
138    /// Host-injected transport meter (authoritative measured bytes).
139    pub transport_meter: Arc<dyn SouthwardTransportMeter>,
140    /// Host-provided supervision observer factory (low-frequency control plane).
141    pub observer_factory: Arc<dyn ObserverFactory>,
142}
143
144impl SouthwardInitContext {
145    /// Attach a disabled/no-op observability configuration.
146    ///
147    /// This is intended for tests and offline tools that do not run inside the gateway host.
148    #[inline]
149    pub fn with_noop_observability(mut self) -> Self {
150        self.transport_meter = Arc::new(NoopSouthwardTransportMeter);
151        self.observer_factory = Arc::new(NoopObserverFactory);
152        self
153    }
154}
155
156/// Driver metrics
157#[derive(Debug, Clone, Default)]
158pub struct DriverMetrics {
159    pub total_requests: u64,
160    pub successful_requests: u64,
161    pub failed_requests: u64,
162    pub average_response_time: Duration,
163}
164
165#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, FromJsonQueryResult)]
166#[serde(rename_all = "camelCase")]
167pub struct ConnectionPolicy {
168    #[serde(default = "ConnectionPolicy::default_connect_timeout_ms")]
169    pub connect_timeout_ms: u64,
170    #[serde(default = "ConnectionPolicy::default_read_timeout_ms")]
171    pub read_timeout_ms: u64,
172    #[serde(default = "ConnectionPolicy::default_write_timeout_ms")]
173    pub write_timeout_ms: u64,
174    #[serde(default)]
175    pub backoff: RetryPolicy,
176}
177
178impl ConnectionPolicy {
179    fn default_connect_timeout_ms() -> u64 {
180        10000
181    }
182    fn default_read_timeout_ms() -> u64 {
183        10000
184    }
185    fn default_write_timeout_ms() -> u64 {
186        10000
187    }
188}
189
190impl Default for ConnectionPolicy {
191    fn default() -> Self {
192        Self {
193            connect_timeout_ms: ConnectionPolicy::default_connect_timeout_ms(),
194            read_timeout_ms: ConnectionPolicy::default_read_timeout_ms(),
195            write_timeout_ms: ConnectionPolicy::default_write_timeout_ms(),
196            backoff: RetryPolicy::default(),
197        }
198    }
199}
200
201impl sea_orm::IntoActiveValue<ConnectionPolicy> for ConnectionPolicy {
202    fn into_active_value(self) -> sea_orm::ActiveValue<ConnectionPolicy> {
203        sea_orm::ActiveValue::Set(self)
204    }
205}