Ajoute une reference dans les VariableInstance vers leur ServiceInstance
This commit is contained in:
@@ -129,6 +129,10 @@ impl UpnpModel for Device {
|
||||
// Créer les instances de services depuis le modèle
|
||||
for service_model in self.services() {
|
||||
let service_instance = service_model.create_instance();
|
||||
|
||||
// Enregistrer le service auprès de ses variables
|
||||
service_instance.register_with_variables();
|
||||
|
||||
service_instance.set_device(Arc::clone(&instance));
|
||||
if let Err(e) = instance.add_service(service_instance) {
|
||||
tracing::error!("Failed to add service instance: {:?}", e);
|
||||
|
||||
@@ -252,6 +252,32 @@ impl UpnpObject for ServiceInstance {
|
||||
}
|
||||
|
||||
impl ServiceInstance {
|
||||
/// Enregistre cette instance de service auprès de toutes ses variables.
|
||||
///
|
||||
/// Cette méthode doit être appelée APRÈS la création de l'Arc<ServiceInstance>
|
||||
/// pour permettre aux variables de notifier le service lors de leurs changements.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `self_arc` - Arc pointant vers cette instance
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # use pmoupnp::services::Service;
|
||||
/// # use pmoupnp::UpnpModel;
|
||||
/// # use std::sync::Arc;
|
||||
/// let service = Service::new("AVTransport".to_string());
|
||||
/// let instance = Arc::new(service.create_instance());
|
||||
/// instance.register_with_variables(&instance);
|
||||
/// ```
|
||||
pub fn register_with_variables(self: &Arc<Self>) {
|
||||
let weak_self = Arc::downgrade(self);
|
||||
for var in self.statevariables.all() {
|
||||
var.register_service(weak_self.clone());
|
||||
}
|
||||
}
|
||||
|
||||
/// Retourne l'identifiant du service.
|
||||
///
|
||||
/// # Examples
|
||||
|
||||
@@ -43,6 +43,7 @@ impl UpnpInstance for StateVarInstance {
|
||||
old_value: RwLock::new(from.get_default()),
|
||||
last_modified: RwLock::new(Utc::now()),
|
||||
last_notification: RwLock::new(Utc::now()),
|
||||
service: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,11 +84,36 @@ impl Clone for StateVarInstance {
|
||||
old_value: RwLock::new(self.old_value.read().unwrap().clone()),
|
||||
last_modified: RwLock::new(self.last_modified.read().unwrap().clone()),
|
||||
last_notification: RwLock::new(self.last_notification.read().unwrap().clone()),
|
||||
service: RwLock::new(self.service.read().unwrap().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StateVarInstance {
|
||||
/// Enregistre le service parent pour cette variable.
|
||||
///
|
||||
/// Cette méthode doit être appelée depuis `ServiceInstance::new()` pour
|
||||
/// permettre à la variable de notifier le service lorsqu'elle change.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `service` - Arc vers le ServiceInstance parent
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # use pmoupnp::services::ServiceInstance;
|
||||
/// # use pmoupnp::state_variables::StateVarInstance;
|
||||
/// # use std::sync::Arc;
|
||||
/// let service_instance = Arc::new(ServiceInstance::new(&service));
|
||||
/// let var_instance = Arc::new(StateVarInstance::new(&variable));
|
||||
/// var_instance.register_service(Arc::downgrade(&service_instance));
|
||||
/// ```
|
||||
pub fn register_service(&self, service: std::sync::Weak<crate::services::ServiceInstance>) {
|
||||
let mut svc = self.service.write().unwrap();
|
||||
*svc = Some(service);
|
||||
}
|
||||
|
||||
pub async fn set_value(&self, new_value: StateValue) -> Result<(), StateValueError> {
|
||||
// Validation du type
|
||||
if self.as_state_var_type() != new_value.as_state_var_type() {
|
||||
@@ -102,9 +128,23 @@ impl StateVarInstance {
|
||||
let mut modified = self.last_modified.write().unwrap();
|
||||
|
||||
*old_val = val.clone();
|
||||
*val = new_value;
|
||||
*val = new_value.clone();
|
||||
*modified = Utc::now();
|
||||
|
||||
// Notifier le service parent si la variable envoie des événements
|
||||
if self.is_sending_notification() {
|
||||
// Relâcher les locks avant d'appeler le service
|
||||
drop(val);
|
||||
drop(old_val);
|
||||
drop(modified);
|
||||
|
||||
if let Some(weak_service) = self.service.read().unwrap().as_ref() {
|
||||
if let Some(service) = weak_service.upgrade() {
|
||||
service.event_to_be_sent(self.get_name().to_string(), new_value.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
/// Accès à la valeur
|
||||
|
||||
@@ -58,6 +58,8 @@ pub struct StateVarInstance {
|
||||
old_value: RwLock<StateValue>,
|
||||
last_modified: RwLock<DateTime<Utc>>,
|
||||
last_notification: RwLock<DateTime<Utc>>,
|
||||
/// Pointeur vers le service parent (interior mutability)
|
||||
service: RwLock<Option<std::sync::Weak<crate::services::ServiceInstance>>>,
|
||||
}
|
||||
|
||||
pub type StateVarInstanceSet = UpnpObjectSet<StateVarInstance>;
|
||||
|
||||
Reference in New Issue
Block a user