mise à jours des handlers d'actions
This commit is contained in:
@@ -113,25 +113,27 @@ pub type ActionFuture = Pin<Box<dyn Future<Output = Result<(), crate::actions::A
|
|||||||
/// # Signature
|
/// # Signature
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// Fn(Arc<ActionInstance>, ActionData) -> ActionFuture
|
/// Fn(Arc<ActionInstance>) -> ActionFuture
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Prend :
|
/// Prend :
|
||||||
/// - [`Arc<ActionInstance>`](crate::actions::ActionInstance) : L'instance de l'action avec accès aux variables liées
|
/// - [`Arc<ActionInstance>`](crate::actions::ActionInstance) : L'instance de l'action avec accès aux variables liées
|
||||||
/// - [`ActionData`] : Les données d'entrée (arguments IN)
|
/// qui contiennent déjà les valeurs des arguments IN
|
||||||
///
|
///
|
||||||
/// Retourne un [`ActionFuture`] qui se résout en `Result<(), ActionError>`.
|
/// Retourne un [`ActionFuture`] qui se résout en `Result<(), ActionError>`.
|
||||||
///
|
///
|
||||||
/// # Responsabilités
|
/// # Responsabilités
|
||||||
///
|
///
|
||||||
/// Le handler est responsable de :
|
/// Le handler est responsable de :
|
||||||
/// - Lire les arguments d'entrée depuis `data`
|
/// - Lire les arguments d'entrée depuis les variables liées à l'instance
|
||||||
/// - Exécuter la logique métier
|
/// - Exécuter la logique métier
|
||||||
/// - Modifier les variables d'instance selon les besoins
|
/// - Modifier les variables d'instance selon les besoins
|
||||||
/// - Retourner `Ok(())` en cas de succès ou `Err(ActionError)` en cas d'erreur
|
/// - Retourner `Ok(())` en cas de succès ou `Err(ActionError)` en cas d'erreur
|
||||||
///
|
///
|
||||||
/// La méthode [`ActionInstance::run()`](crate::actions::ActionInstance::run) s'occupe
|
/// La méthode [`ActionInstance::run()`](crate::actions::ActionInstance::run) s'occupe
|
||||||
/// automatiquement de collecter les valeurs OUT si le handler retourne `Ok(())`.
|
/// automatiquement de :
|
||||||
|
/// 1. Stocker les valeurs IN dans les variables liées avant d'appeler le handler
|
||||||
|
/// 2. Collecter les valeurs OUT si le handler retourne `Ok(())`
|
||||||
///
|
///
|
||||||
/// # Traits requis
|
/// # Traits requis
|
||||||
///
|
///
|
||||||
@@ -147,8 +149,8 @@ pub type ActionFuture = Pin<Box<dyn Future<Output = Result<(), crate::actions::A
|
|||||||
/// use pmoupnp::action_handler;
|
/// use pmoupnp::action_handler;
|
||||||
/// use pmoupnp::actions::ActionError;
|
/// use pmoupnp::actions::ActionError;
|
||||||
///
|
///
|
||||||
/// let handler = action_handler!(|instance, data| {
|
/// let handler = action_handler!(|instance| {
|
||||||
/// // Logique métier
|
/// // Logique métier - les valeurs IN sont déjà dans les variables
|
||||||
/// Ok::<(), ActionError>(())
|
/// Ok::<(), ActionError>(())
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
@@ -156,10 +158,10 @@ pub type ActionFuture = Pin<Box<dyn Future<Output = Result<(), crate::actions::A
|
|||||||
/// ## Manuellement
|
/// ## Manuellement
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use pmoupnp::actions::{ActionData, ActionHandler, ActionInstance, ActionError};
|
/// use pmoupnp::actions::{ActionHandler, ActionInstance, ActionError};
|
||||||
/// use std::sync::Arc;
|
/// use std::sync::Arc;
|
||||||
///
|
///
|
||||||
/// let handler: ActionHandler = Arc::new(|instance, data| {
|
/// let handler: ActionHandler = Arc::new(|instance| {
|
||||||
/// Box::pin(async move {
|
/// Box::pin(async move {
|
||||||
/// // Votre logique async
|
/// // Votre logique async
|
||||||
/// Ok::<(), ActionError>(())
|
/// Ok::<(), ActionError>(())
|
||||||
@@ -174,7 +176,7 @@ pub type ActionFuture = Pin<Box<dyn Future<Output = Result<(), crate::actions::A
|
|||||||
/// - Le handler capture les variables par `move`
|
/// - Le handler capture les variables par `move`
|
||||||
/// - Le future est automatiquement `Send` si les captures le sont
|
/// - Le future est automatiquement `Send` si les captures le sont
|
||||||
/// - Utilisez la macro `action_handler!` pour simplifier la création
|
/// - Utilisez la macro `action_handler!` pour simplifier la création
|
||||||
pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>, ActionData) -> ActionFuture + Send + Sync>;
|
pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>) -> ActionFuture + Send + Sync>;
|
||||||
|
|
||||||
/// Macro pour créer facilement un ActionHandler.
|
/// Macro pour créer facilement un ActionHandler.
|
||||||
///
|
///
|
||||||
@@ -184,16 +186,16 @@ pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>, ActionD
|
|||||||
/// # Syntaxe
|
/// # Syntaxe
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// action_handler!(|instance, data| {
|
/// action_handler!(|instance| {
|
||||||
/// // votre logique async (automatiquement dans un bloc async move)
|
/// // votre logique async (automatiquement dans un bloc async move)
|
||||||
/// data
|
/// // Les valeurs IN sont déjà disponibles dans les variables liées
|
||||||
/// })
|
/// })
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// - `instance` : Paramètre de type `Arc<`[`ActionInstance`](crate::actions::ActionInstance)`>` - L'instance de l'action
|
/// - `instance` : Paramètre de type `Arc<`[`ActionInstance`](crate::actions::ActionInstance)`>` - L'instance de l'action
|
||||||
/// - `data` : Paramètre de type [`ActionData`] (Arc<HashMap<String, StateValue>>) - Les données d'entrée
|
/// avec les valeurs IN déjà stockées dans les variables liées
|
||||||
/// - Le corps du bloc peut contenir du code asynchrone (`.await`)
|
/// - Le corps du bloc peut contenir du code asynchrone (`.await`)
|
||||||
///
|
///
|
||||||
/// # Type de retour
|
/// # Type de retour
|
||||||
@@ -208,56 +210,61 @@ pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>, ActionD
|
|||||||
/// use pmoupnp::action_handler;
|
/// use pmoupnp::action_handler;
|
||||||
///
|
///
|
||||||
/// // Handler minimal - run() collectera automatiquement les OUT
|
/// // Handler minimal - run() collectera automatiquement les OUT
|
||||||
/// let handler = action_handler!(|instance, data| {
|
/// let handler = action_handler!(|instance| {
|
||||||
/// Ok(()) // Succès, pas d'erreur
|
/// Ok(()) // Succès, pas d'erreur
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Exemple 2 : Handler qui modifie une variable avec gestion d'erreur
|
/// ## Exemple 2 : Handler qui lit et modifie des variables
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// use pmoupnp::action_handler;
|
/// use pmoupnp::action_handler;
|
||||||
/// use pmoupnp::actions::ActionError;
|
/// use pmoupnp::actions::ActionError;
|
||||||
///
|
///
|
||||||
/// let handler = action_handler!(|instance, data| {
|
/// let handler = action_handler!(|instance| {
|
||||||
/// // Lire un argument d'entrée
|
/// // Lire un argument d'entrée depuis la variable liée
|
||||||
/// let volume = data.get("DesiredVolume")
|
/// let arg = instance.argument("DesiredVolume")
|
||||||
/// .ok_or_else(|| ActionError::MissingArgument("DesiredVolume".to_string()))?;
|
/// .ok_or_else(|| ActionError::ArgumentNotFound("DesiredVolume".to_string()))?;
|
||||||
///
|
|
||||||
/// // Modifier la variable d'instance
|
|
||||||
/// let arg = instance.argument("CurrentVolume")
|
|
||||||
/// .ok_or_else(|| ActionError::ArgumentNotFound("CurrentVolume".to_string()))?;
|
|
||||||
///
|
///
|
||||||
/// let var = arg.get_variable_instance()
|
/// let var = arg.get_variable_instance()
|
||||||
/// .ok_or_else(|| ActionError::VariableNotBound)?;
|
/// .ok_or_else(|| ActionError::VariableNotBound)?;
|
||||||
///
|
///
|
||||||
/// var.set_value(volume.clone());
|
/// let volume = var.value();
|
||||||
|
///
|
||||||
|
/// // Modifier une autre variable d'instance
|
||||||
|
/// let current_volume = instance.argument("CurrentVolume")
|
||||||
|
/// .ok_or_else(|| ActionError::ArgumentNotFound("CurrentVolume".to_string()))?
|
||||||
|
/// .get_variable_instance()
|
||||||
|
/// .ok_or_else(|| ActionError::VariableNotBound)?;
|
||||||
|
///
|
||||||
|
/// current_volume.set_value(volume);
|
||||||
///
|
///
|
||||||
/// Ok(()) // Succès - run() collectera CurrentVolume dans les OUT
|
/// Ok(()) // Succès - run() collectera CurrentVolume dans les OUT
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ## Exemple 3 : Handler avec logique métier asynchrone et gestion d'erreur
|
/// ## Exemple 3 : Handler avec logique métier asynchrone
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// use pmoupnp::action_handler;
|
/// use pmoupnp::action_handler;
|
||||||
/// use pmoupnp::actions::ActionError;
|
/// use pmoupnp::actions::ActionError;
|
||||||
///
|
///
|
||||||
/// let handler = action_handler!(|instance, data| {
|
/// let handler = action_handler!(|instance| {
|
||||||
|
/// // Lire les paramètres depuis les variables liées
|
||||||
|
/// let uri_var = instance.argument("CurrentURI")
|
||||||
|
/// .and_then(|a| a.get_variable_instance())
|
||||||
|
/// .ok_or_else(|| ActionError::VariableNotBound)?;
|
||||||
|
///
|
||||||
|
/// let uri = uri_var.value();
|
||||||
|
///
|
||||||
/// // Appel asynchrone à un service externe
|
/// // Appel asynchrone à un service externe
|
||||||
/// let response = external_service::fetch_data().await
|
/// let response = external_service::fetch_metadata(&uri).await
|
||||||
/// .map_err(|e| ActionError::ExternalError(e.to_string()))?;
|
/// .map_err(|e| ActionError::ExternalError(e.to_string()))?;
|
||||||
///
|
///
|
||||||
/// // Mettre à jour les variables selon la réponse
|
/// // Mettre à jour les variables selon la réponse
|
||||||
/// if let Some(arg) = instance.argument("Status") {
|
/// if let Some(arg) = instance.argument("Metadata") {
|
||||||
/// if let Some(var) = arg.get_variable_instance() {
|
/// if let Some(var) = arg.get_variable_instance() {
|
||||||
/// var.set_value(StateValue::String(response.status));
|
/// var.set_value(StateValue::String(response.metadata));
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// if let Some(arg) = instance.argument("Message") {
|
|
||||||
/// if let Some(var) = arg.get_variable_instance() {
|
|
||||||
/// var.set_value(StateValue::String(response.message));
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
@@ -276,7 +283,7 @@ pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>, ActionD
|
|||||||
/// // Contexte partagé (ex: état d'un lecteur média)
|
/// // Contexte partagé (ex: état d'un lecteur média)
|
||||||
/// let player_state = Arc::new(Mutex::new(PlayerState::Stopped));
|
/// let player_state = Arc::new(Mutex::new(PlayerState::Stopped));
|
||||||
///
|
///
|
||||||
/// let handler = action_handler!(|instance, data| {
|
/// let handler = action_handler!(|instance| {
|
||||||
/// // Vérifier l'état actuel
|
/// // Vérifier l'état actuel
|
||||||
/// {
|
/// {
|
||||||
/// let state = player_state.lock().await;
|
/// let state = player_state.lock().await;
|
||||||
@@ -309,8 +316,8 @@ pub type ActionHandler = Arc<dyn Fn(Arc<crate::actions::ActionInstance>, ActionD
|
|||||||
/// - Le résultat est automatiquement boxé et arcé
|
/// - Le résultat est automatiquement boxé et arcé
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! action_handler {
|
macro_rules! action_handler {
|
||||||
(|$instance:ident, $data:ident| $body:block) => {
|
(|$instance:ident| $body:block) => {
|
||||||
std::sync::Arc::new(|$instance: std::sync::Arc<$crate::actions::ActionInstance>, $data: $crate::actions::ActionData| {
|
std::sync::Arc::new(|$instance: std::sync::Arc<$crate::actions::ActionInstance>| {
|
||||||
Box::pin(async move $body)
|
Box::pin(async move $body)
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use tracing::debug;
|
use tracing::{debug, trace};
|
||||||
use xmltree::{Element, XMLNode};
|
use xmltree::{Element, XMLNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -165,9 +165,10 @@ impl ActionInstance {
|
|||||||
/// Exécute l'action avec les données fournies.
|
/// Exécute l'action avec les données fournies.
|
||||||
///
|
///
|
||||||
/// Cette méthode :
|
/// Cette méthode :
|
||||||
/// 1. Exécute le handler avec les données d'entrée
|
/// 1. Stocke les valeurs IN dans les variables liées
|
||||||
/// 2. Collecte automatiquement les valeurs OUT via [`get_out_values()`](Self::get_out_values)
|
/// 2. Exécute le handler (qui peut accéder aux valeurs IN via les variables)
|
||||||
/// 3. Retourne les résultats
|
/// 3. Collecte automatiquement les valeurs OUT via [`get_out_values()`](Self::get_out_values)
|
||||||
|
/// 4. Retourne les résultats
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
@@ -185,9 +186,13 @@ impl ActionInstance {
|
|||||||
///
|
///
|
||||||
/// # Fonctionnement
|
/// # Fonctionnement
|
||||||
///
|
///
|
||||||
/// Le handler n'a pas besoin de retourner les valeurs OUT - il modifie simplement
|
/// 1. Pour chaque argument IN, la valeur fournie dans `data` est stockée dans la
|
||||||
/// les variables d'instance et retourne `Ok(())`. La méthode `run()` collecte automatiquement
|
/// variable d'état liée à cet argument
|
||||||
/// toutes les valeurs des arguments marqués comme OUT si le handler réussit.
|
/// 2. Le handler est appelé avec l'instance (il peut lire les valeurs IN via
|
||||||
|
/// `argument.get_variable_instance().value()`)
|
||||||
|
/// 3. Le handler modifie les variables selon ses besoins et retourne `Ok(())` ou `Err(...)`
|
||||||
|
/// 4. Si le handler réussit, `run()` collecte automatiquement toutes les valeurs
|
||||||
|
/// des arguments marqués comme OUT
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@@ -206,8 +211,10 @@ impl ActionInstance {
|
|||||||
/// pmoupnp::variable_types::StateValue::UI2(50));
|
/// pmoupnp::variable_types::StateValue::UI2(50));
|
||||||
/// let input_data = Arc::new(input);
|
/// let input_data = Arc::new(input);
|
||||||
///
|
///
|
||||||
/// // Exécuter l'action - le handler modifie CurrentVolume
|
/// // Exécuter l'action
|
||||||
/// // run() retourne automatiquement CurrentVolume dans les OUT
|
/// // 1. run() stocke DesiredVolume=50 dans la variable liée
|
||||||
|
/// // 2. Le handler lit la valeur et fait son travail
|
||||||
|
/// // 3. run() retourne automatiquement les valeurs OUT
|
||||||
/// match instance.run(input_data).await {
|
/// match instance.run(input_data).await {
|
||||||
/// Ok(output_data) => {
|
/// Ok(output_data) => {
|
||||||
/// // Traiter les résultats
|
/// // Traiter les résultats
|
||||||
@@ -224,15 +231,30 @@ impl ActionInstance {
|
|||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
|
/// - Les valeurs IN sont automatiquement stockées avant l'appel du handler
|
||||||
|
/// - Le handler n'a plus besoin de recevoir les données en paramètre
|
||||||
/// - Le handler modifie les variables et retourne `Ok(())` ou `Err(ActionError)`
|
/// - Le handler modifie les variables et retourne `Ok(())` ou `Err(ActionError)`
|
||||||
/// - `run()` collecte automatiquement les OUT si le handler retourne `Ok(())`
|
/// - `run()` collecte automatiquement les OUT si le handler retourne `Ok(())`
|
||||||
/// - L'instance doit être wrappée dans un `Arc` pour être passée au handler
|
/// - L'instance doit être wrappée dans un `Arc` pour être passée au handler
|
||||||
pub async fn run(self: Arc<Self>, data: ActionData) -> Result<ActionData, crate::actions::ActionError> {
|
pub async fn run(self: Arc<Self>, data: ActionData) -> Result<ActionData, crate::actions::ActionError> {
|
||||||
|
// Stocker les valeurs IN dans les variables liées
|
||||||
|
for arg_inst in self.arguments.all() {
|
||||||
|
let arg_model = arg_inst.as_ref().get_model();
|
||||||
|
if arg_model.is_in() {
|
||||||
|
if let Some(value) = data.get(arg_inst.get_name()) {
|
||||||
|
if let Some(var_inst) = arg_inst.get_variable_instance() {
|
||||||
|
var_inst.set_value(value.clone());
|
||||||
|
trace!(" IN {} = {:?}", arg_inst.get_name(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let handler = self.model.handler().clone();
|
let handler = self.model.handler().clone();
|
||||||
let instance_clone = self.clone();
|
let instance_clone = self.clone();
|
||||||
|
|
||||||
// Exécuter le handler
|
// Exécuter le handler (il peut maintenant lire les valeurs IN depuis les variables)
|
||||||
handler(instance_clone, data).await?;
|
handler(instance_clone).await?;
|
||||||
|
|
||||||
// Collecter automatiquement les valeurs OUT si succès
|
// Collecter automatiquement les valeurs OUT si succès
|
||||||
debug!("✅ Action '{}' completed successfully, collecting outputs", self.get_name());
|
debug!("✅ Action '{}' completed successfully, collecting outputs", self.get_name());
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
@@ -11,11 +10,9 @@ use crate::{
|
|||||||
UpnpObjectSetError,
|
UpnpObjectSetError,
|
||||||
UpnpObjectType,
|
UpnpObjectType,
|
||||||
UpnpTyped,
|
UpnpTyped,
|
||||||
UpnpTypedInstance,
|
|
||||||
};
|
};
|
||||||
use crate::actions::{
|
use crate::actions::{
|
||||||
Action,
|
Action,
|
||||||
ActionData,
|
|
||||||
ActionHandler,
|
ActionHandler,
|
||||||
ActionInstance,
|
ActionInstance,
|
||||||
Argument,
|
Argument,
|
||||||
@@ -56,7 +53,9 @@ impl Action {
|
|||||||
///
|
///
|
||||||
/// Ce handler logge simplement l'appel et les arguments d'entrée.
|
/// Ce handler logge simplement l'appel et les arguments d'entrée.
|
||||||
/// La méthode [`ActionInstance::run()`](crate::actions::ActionInstance::run) s'occupe
|
/// La méthode [`ActionInstance::run()`](crate::actions::ActionInstance::run) s'occupe
|
||||||
/// automatiquement de collecter les valeurs OUT après l'exécution.
|
/// automatiquement de :
|
||||||
|
/// 1. Stocker les valeurs IN dans les variables liées avant d'appeler le handler
|
||||||
|
/// 2. Collecter les valeurs OUT après l'exécution
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
@@ -65,7 +64,7 @@ impl Action {
|
|||||||
/// # Comportement
|
/// # Comportement
|
||||||
///
|
///
|
||||||
/// - Logge le nom de l'action
|
/// - Logge le nom de l'action
|
||||||
/// - Logge les arguments IN avec leurs valeurs
|
/// - Logge les arguments IN avec leurs valeurs (lues depuis les variables liées)
|
||||||
/// - Ne fait aucune modification (handler passif)
|
/// - Ne fait aucune modification (handler passif)
|
||||||
///
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
@@ -73,17 +72,17 @@ impl Action {
|
|||||||
/// Ce handler est automatiquement assigné lors de la création d'une action.
|
/// Ce handler est automatiquement assigné lors de la création d'une action.
|
||||||
/// Il peut être remplacé via [`set_handler`](Self::set_handler).
|
/// Il peut être remplacé via [`set_handler`](Self::set_handler).
|
||||||
fn default_handler() -> ActionHandler {
|
fn default_handler() -> ActionHandler {
|
||||||
action_handler!(|instance, data| {
|
action_handler!(|instance| {
|
||||||
use crate::UpnpTypedInstance;
|
use crate::UpnpTypedInstance;
|
||||||
|
|
||||||
debug!("🎬 Action '{}' called", instance.get_name());
|
debug!("🎬 Action '{}' called", instance.get_name());
|
||||||
|
|
||||||
// Logger les arguments d'entrée
|
// Logger les arguments d'entrée (déjà stockés dans les variables par run())
|
||||||
for arg_inst in instance.arguments_set().all() {
|
for arg_inst in instance.arguments_set().all() {
|
||||||
let arg_model = arg_inst.as_ref().get_model();
|
let arg_model = arg_inst.as_ref().get_model();
|
||||||
if arg_model.is_in() {
|
if arg_model.is_in() {
|
||||||
if let Some(value) = data.get(arg_inst.get_name()) {
|
if let Some(var_inst) = arg_inst.get_variable_instance() {
|
||||||
trace!(" IN {} = {:?}", arg_inst.get_name(), value);
|
trace!(" IN {} = {:?}", arg_inst.get_name(), var_inst.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,10 +137,10 @@ impl UpnpInstance for ArgumentInstance {
|
|||||||
name: from.get_name().clone(),
|
name: from.get_name().clone(),
|
||||||
object_type: "ArgumentInstance".to_string(),
|
object_type: "ArgumentInstance".to_string(),
|
||||||
},
|
},
|
||||||
|
|
||||||
// Clone du modèle pour référence future
|
// Clone du modèle pour référence future
|
||||||
model: from.clone(),
|
model: from.clone(),
|
||||||
|
|
||||||
// Initialisation à None - sera lié plus tard via bind_variable()
|
// Initialisation à None - sera lié plus tard via bind_variable()
|
||||||
// Arc<RwLock<...>> permet la modification thread-safe post-construction
|
// Arc<RwLock<...>> permet la modification thread-safe post-construction
|
||||||
variable_instance: Arc::new(RwLock::new(None)),
|
variable_instance: Arc::new(RwLock::new(None)),
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ pub type ArgumentSet = UpnpObjectSet<Argument>;
|
|||||||
/// 1. **Création** : Instanciation via [`UpnpInstance::new`] avec `variable_instance = None`
|
/// 1. **Création** : Instanciation via [`UpnpInstance::new`] avec `variable_instance = None`
|
||||||
/// 2. **Liaison** : Association à une [`StateVarInstance`] via [`bind_variable`](Self::bind_variable)
|
/// 2. **Liaison** : Association à une [`StateVarInstance`] via [`bind_variable`](Self::bind_variable)
|
||||||
/// 3. **Utilisation** : Accès à la valeur runtime via [`get_variable_instance`](Self::get_variable_instance)
|
/// 3. **Utilisation** : Accès à la valeur runtime via [`get_variable_instance`](Self::get_variable_instance)
|
||||||
|
/// 4. **Exécution** : Les valeurs IN sont stockées dans les variables liées lors de l'appel à `run()`
|
||||||
///
|
///
|
||||||
/// # Pourquoi `variable_instance` est optionnel ?
|
/// # Pourquoi `variable_instance` est optionnel ?
|
||||||
///
|
///
|
||||||
@@ -114,6 +115,13 @@ pub type ArgumentSet = UpnpObjectSet<Argument>;
|
|||||||
/// - Les `ActionInstance` sont créées **avant** que toutes les variables soient disponibles
|
/// - Les `ActionInstance` sont créées **avant** que toutes les variables soient disponibles
|
||||||
/// - La validation des dépendances se fait en deux phases
|
/// - La validation des dépendances se fait en deux phases
|
||||||
///
|
///
|
||||||
|
/// # Stockage des valeurs IN
|
||||||
|
///
|
||||||
|
/// Lors de l'exécution d'une action, les valeurs des arguments IN sont automatiquement
|
||||||
|
/// stockées dans les `StateVarInstance` liées. Les handlers peuvent ensuite y accéder
|
||||||
|
/// via `argument.get_variable_instance().value()` sans avoir besoin de recevoir les
|
||||||
|
/// valeurs en paramètre.
|
||||||
|
///
|
||||||
/// # Thread-safety
|
/// # Thread-safety
|
||||||
///
|
///
|
||||||
/// Le champ `variable_instance` est protégé par un `RwLock` pour permettre :
|
/// Le champ `variable_instance` est protégé par un `RwLock` pour permettre :
|
||||||
|
|||||||
Reference in New Issue
Block a user