arete-sdk 0.1.6

The Project Arete SDK for smart buildings
Documentation
use super::{Client, Context, Error};
use crate::consumer::ChangeEvent;
use regex::Regex;
use serde_json::Value;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;

pub struct Provider {
    client: Client,
    context: Context,
    pub profile: String,
}

impl Provider {
    pub(crate) fn new(client: Client, context: Context, profile: String) -> Self {
        Self {
            client,
            context,
            profile,
        }
    }

    fn profile_key_prefix(&self) -> String {
        let system_id = self.context.node.system.id.to_string();
        let node_id = &self.context.node.id;
        let context_id = &self.context.id;
        let profile = &self.profile;
        format!("cns/{system_id}/nodes/{node_id}/contexts/{context_id}/provider/{profile}/")
    }

    fn property_key(&self, property: &str) -> String {
        let profile_key_prefix = self.profile_key_prefix();
        format!("{profile_key_prefix}properties/{property}")
    }

    pub fn get(&self, property: &str, default_value: Option<Value>) -> Result<Option<Value>, Error> {
        let key = self.property_key(property);
        self.client.get(&key, default_value)
    }

    pub fn put(&self, property: &str, value: &str) -> Result<(), Error> {
        let key = self.property_key(property);
        let mut client = self.client.clone();
        client.put(&key, value)
    }

    pub fn watch(&self) -> Result<Receiver<ChangeEvent>, Error> {
        let key_prefix = self.profile_key_prefix();
        let mut client = self.client.clone();
        let upstream_rx = client.on_update()?;
        let (tx, rx) = mpsc::channel();
        let re = Regex::new(r"connections/(\w+)/properties/(\w+)$")?;

        let keys = client.keys()?;
        std::thread::spawn(move || {
            // Start by notifying of existing cached properties
            for (k, v) in keys.iter() {
                if !k.starts_with(&key_prefix) {
                    continue;
                }
                if let Some(captures) = re.captures(k) {
                    let connection = captures[1].to_string();
                    let property = captures[2].to_string();
                    let value = v.clone();
                    let change_event = ChangeEvent {
                        connection,
                        property,
                        value,
                    };
                    tx.send(change_event).unwrap();
                };
            }

            // Watch for future property changes
            for event in upstream_rx {
                for (k, v) in event.keys.iter() {
                    if !k.starts_with(&key_prefix) {
                        continue;
                    }
                    if let Some(captures) = re.captures(k) {
                        let connection = captures[1].to_string();
                        let property = captures[2].to_string();
                        let value = v.clone();
                        let change_event = ChangeEvent {
                            connection,
                            property,
                            value,
                        };
                        tx.send(change_event).unwrap();
                    };
                }
            }
        });
        Ok(rx)
    }
}