reactive_graph_std_state/behaviour/component/state/
mod.rs1use std::sync::Arc;
2use std::sync::LazyLock;
3
4use reactive_graph_behaviour_model_api::behaviour_validator;
5use reactive_graph_behaviour_model_api::prelude::*;
6use reactive_graph_behaviour_model_impl::entity::EntityBehaviourFactories;
7use reactive_graph_behaviour_model_impl::entity_behaviour;
8use reactive_graph_graph::prelude::*;
9use reactive_graph_reactive_model_api::ReactiveInstanceContainer;
10use reactive_graph_reactive_model_impl::ReactiveEntity;
11use serde_json::Value;
12use uuid::Uuid;
13
14use reactive_graph_std_state_model::NAMESPACE_STATE;
15
16use crate::model_state::StateProperties;
17use crate::model_value::*;
18
19pub static STATE_BEHAVIOURS: LazyLock<BehaviourTypeIds> = LazyLock::new(|| {
20 BehaviourTypeIds::with_namespace(NAMESPACE_STATE)
21 .ty("state_array")
22 .ty("state_boolean")
23 .ty("state_number")
24 .ty("state_object")
25 .ty("state_string")
26 .into()
27});
28
29pub static STATE_FACTORIES: LazyLock<EntityBehaviourFactories> = LazyLock::new(|| {
30 STATE_BEHAVIOURS.iter().fold(EntityBehaviourFactories::new(), |factories, behaviour_ty| {
31 factories.factory(Arc::new(StateFactory::new(behaviour_ty.clone())))
32 })
33});
34
35entity_behaviour!(State, StateFactory, StateFsm, StateBehaviourTransitions, StateValidator);
36
37behaviour_validator!(
38 StateValidator,
39 Uuid,
40 ReactiveEntity,
41 StateProperties::STATE.as_ref(),
42 StateProperties::SET_STATE.as_ref(),
43 ValueProperties::VALUE.as_ref()
44);
45
46impl BehaviourInit<Uuid, ReactiveEntity> for StateBehaviourTransitions {
47 fn init(&self) -> Result<(), BehaviourInitializationFailed> {
48 let state = self.get(StateProperties::STATE.as_ref()).ok_or(BehaviourInitializationFailed {})?;
50 let value = self.get(ValueProperties::VALUE.as_ref()).ok_or(BehaviourInitializationFailed {})?;
51 if state != value {
52 self.set(ValueProperties::VALUE.as_ref(), state);
53 }
54 Ok(())
55 }
56}
57
58impl BehaviourShutdown<Uuid, ReactiveEntity> for StateBehaviourTransitions {}
59
60impl BehaviourConnect<Uuid, ReactiveEntity> for StateBehaviourTransitions {
61 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
62 let reactive_instance = self.property_observers.reactive_instance.clone();
63 self.property_observers
64 .observe_with_handle(StateProperties::SET_STATE.as_ref(), move |new_value: &Value| {
65 if let Some(old_value) = reactive_instance.get(StateProperties::STATE.as_ref()) {
66 let new_value = new_value.clone();
67 if old_value != new_value {
68 reactive_instance.set(StateProperties::STATE.as_ref(), new_value);
69 }
70 }
71 });
72 let reactive_instance = self.property_observers.reactive_instance.clone();
74 self.property_observers.observe_with_handle(StateProperties::STATE.as_ref(), move |v: &Value| {
75 reactive_instance.set(ValueProperties::VALUE.as_ref(), v.clone());
76 });
77 Ok(())
78 }
79}
80
81impl BehaviourTransitions<Uuid, ReactiveEntity> for StateBehaviourTransitions {}