Présentation de l'architecture du BSIM.CCU

  1. Présentation des fonctionnalités demandées

  2. Solutions proposées

  3. Développement futur

Plan

  1. Présentation des fonctionnalités demandées

  2. Solutions proposées

  3. Développement futur

Plan

Présentation des fonctionnalités demandées

  • Être stable sur le long terme (> 1 mois)
  • Être résilient des erreurs du côté PyramIDS
  • Envoyer les messages dans leurs formats corrects
  • Avoir les fonctions nécessaires pour la science (?)

 

Présentation des fonctionnalités demandées

  • Être stable sur le long terme (> 1 mois)
  • Être résilient des erreurs du côté PyramIDS
  • Envoyer les messages dans leurs formats corrects
  • Avoir les fonctions nécessaires pour la science (?)

 

Présentation des fonctionnalités demandées

  • Être stable sur le long terme (> 1 mois)

      ⇒ Rust

  • Être résilient des erreurs du côté PyramIDS
  • Envoyer les messages dans leurs formats corrects
  • Avoir les fonctions nécessaires pour la science (?)

 

Présentation des fonctionnalités demandées

  • Être stable sur le long terme (> 1 mois)
  • Être résilient des erreurs du côté PyramIDS
  • Envoyer les messages dans leurs formats corrects
  • Avoir les fonctions nécessaires pour la science (?)

 

Présentation des fonctionnalités demandées

  • Être stable sur le long terme (> 1 mois)
  • Être résilient des erreurs du côté PyramIDS

      ⇒ Spécifications des messages en JSON Schema

  • Envoyer les messages dans leurs formats corrects

      ⇒ Spécifications des messages en JSON Schema

  • Avoir les fonctions nécessaires pour la science (?)

 

JSON Schema

JSON Schema

  1. Présentation des fonctionnalités demandées

  2. Solutions proposées

  3. Développement futur

Plan

Solutions proposées

/// This trait centralizes all the interaction with PyramIDS
pub trait Pyramids {
    /// Associated type for the initialization
    type Initialization;
    /// Associated type for the incoming messages
    type Incoming;
    /// Associated type for the outgoing messages
    type Outgoing;
    /// Associated Result type from the crate
    type Result<T>;

    /// Initialization step sending back the `JoinHandle` given by `tokio::spawn`
    async fn initialize(&mut self) -> Self::Result<Self::Initialization>;

    fn subscriptions<Topic, Message>(
    	&mut self, 
        m: IncomingMessages<Topic, Message>
    )
    where
        Topic: Into<String>,
        Message: Into<String>;

    /// Helper to send all the messages that we can to the broker
    async fn send<Topic, Message>(
        &self,
        message: OutgoingPayload<Topic, Message>,
    ) -> Self::Result<Self::Outgoing>
    where
        Topic: Into<String>,
        Message: Into<String>;

    /// Helper to receive all the messages that we subscribed to
    async fn recv(&mut self) -> Self::Result<Self::Incoming>;
}

Trait

Comportement partagé en Rust ⇒ Trait

Exemple - TAS

## Topics

### Pyramids -> TAS

`lisa/{prod_or_simu}/devices/bsim/tas/<cmd>`

used to start scan, stop scan, sync datalogger time.

### TAS -> Pyramids

`lisa/{prod_or_simu}/devices/bsim/tas/housekeeping`

used to send if tas is scanning or not. 

`lisa/{prod_or_simu}/devices/bsim/tas/measures` 

used to send temperatures measurements.

## Payloads

### cmd

Action has to be one of the following : 

Start   // Start scan
Stop    // Stop scan
Sync    // Sync datalogger clock with clock from PC
pub struct Tas {
    pyramids_client: Pyramids_Client,
    instrument_client: Instrument_Client,
    settings: TasSettings,
    subscriptions: Vec<Payload>,
	// ... Internal fields
}

impl Pyramids for Tas {
    type Initialization = ();
    type Incoming = Event;
    type Outgoing = ();
    type Result<T> = Result<T>;

    async fn initialize(&mut self) -> Result<()> {
        self.init().await?;
        Ok(())
    }

    async fn send<S: Into<String>, M: Into<String>>(
        &self,
        message: OutgoingPayload<S, M>,
    ) -> Result<()> {
        self.pyramids_client
            .publish(
                message.topic.into(),
                QoS::ExactlyOnce,
                false,
                message.message.into().clone(),
            )
            .await?;
        Ok(())
    }

    async fn recv(&mut self) -> Result<Event> {
        Ok(self.pyramids_client.poll().await?)
    }
}

Exemple - TAS

And in the binary definition

// main
let settings = Settings::new()
        .map_err(|e| e.to_string())
        .expect("Can not read settings");

    let tas_settings = settings
        .tas
        .into_iter()
        .next()
        .expect("Did not find the dataloggers settings");

    let addr = tas_settings.address.clone();
    let instrument_client = tas::Client::connect(addr)
        .await
        .expect("cant connect to datalogger");
    let pyramids_client = mqtt_Client::connect(["localhost:1883", "localhost:1883"])
        .await
        .expect("Could not reach the MQTT broker");

    let mut tas = Pyramids_Client::from_settings(instrument_client, pyramids_client, tas_settings);
    tas.initialize().await?;

  // Continue right
// Continued
    loop {
        let message = tas.recv().await?;
        // XXX: Match in trait ?
        match message {
            // We receive communication on the client
            Event::Incoming(packet) => {
                // Someone published (most likely on a topic we subscribe to)
                if let Packet::Publish(p) = packet {
                    // We grab the topic and the payload
                    let Publish { topic, payload, .. } = p;

                    match topic.as_str() {
                        "lisa/prod/devices/bsim/tas/start" => tas.start(),
                        "lisa/prod/devices/bsim/tas/stop" => tas.stop(),
                        "lisa/prod/devices/bsim/tas/sync" => tas.sync(),
                        _ => {
                            // XXX: Unknown topic, what do we do ?
                            todo!();
                        }
                    }
                } else {
                    match packet {
                        Packet::Subscribe(subscribe) => todo!(),
                        Packet::Unsubscribe(unsubscribe) => todo!(),
                        Packet::PingReq => todo!(),
                        Packet::PingResp => todo!(),
                        Packet::Disconnect => todo!(),
                        _ => continue,
                    }
                }
            }
            // XXX: Log outgoing requests?
            _ => continue,
        }
    }
}

Exemple - TAS

And in the binary definition

// main

/* Initialization */
let settings = Settings::new()
        .map_err(|e| e.to_string())
        .expect("Can not read settings");

    let tas_settings = settings
        .tas
        .into_iter()
        .next()
        .expect("Did not find the dataloggers settings");

    let addr = tas_settings.address.clone();
    let instrument_client = tas::Client::connect(addr)
        .await
        .expect("cant connect to datalogger");
    let pyramids_client = mqtt_Client::connect(["localhost:1883", "localhost:1883"])
        .await
        .expect("Could not reach the MQTT broker");

    let mut tas = Pyramids_Client::from_settings(instrument_client, pyramids_client, tas_settings);
    tas.initialize().await?;

/* Main control loop */
  // Continue right ↗
// Continued
    loop {
        let message = tas.recv().await?;
        // XXX: Match in trait ?
        match message {
            // We receive communication on the client
            Event::Incoming(packet) => {
                // Someone published (most likely on a topic we subscribe to)
                if let Packet::Publish(p) = packet {
                    // We grab the topic and the payload
                    let Publish { topic, payload, .. } = p;

                    match topic.as_str() {
                        "lisa/prod/devices/bsim/tas/start" => tas.start(),
                        "lisa/prod/devices/bsim/tas/stop" => tas.stop(),
                        "lisa/prod/devices/bsim/tas/sync" => tas.sync(),
                        _ => {
                            // XXX: Unknown topic, what do we do ?
                            todo!();
                        }
                    }
                } else {
                    match packet {
                        Packet::Subscribe(subscribe) => todo!(),
                        Packet::Unsubscribe(unsubscribe) => todo!(),
                        Packet::PingReq => todo!(),
                        Packet::PingResp => todo!(),
                        Packet::Disconnect => todo!(),
                        _ => continue,
                    }
                }
            }
            // XXX: Log outgoing requests?
            _ => continue,
        }
    }
}
  1. Présentation des fonctionnalités demandées

  2. Solutions proposées

  3. Développement futur

Plan

Les casseroles

  1. IHM
  2. Mock Pyramids
  3. Amélioration de l’encapsulation
  4. Création d'une variable d'état (automate fini ?)
// Continued
    loop {
        let message = tas.recv().await?;
        // XXX: Match in trait ?
        match message {
            // We receive communication on the client
            Event::Incoming(packet) => {
                // Same ol' same
                } else {
                // XXX: Useful ?
                    match packet {
                        Packet::Subscribe(subscribe) => todo!(),
                        Packet::Unsubscribe(unsubscribe) => todo!(),
                        Packet::PingReq => todo!(),
                        Packet::PingResp => todo!(),
                        Packet::Disconnect => todo!(),
                        _ => continue,
                    }
                }
            }
            // XXX: Log outgoing requests?
            _ => continue,
        }
    }
}

Présentation de l'avancement de l'architecture du BSIM.CCU

By Claude-Alban RANÉLY-VERGÉ-DÉPRÉ

Présentation de l'avancement de l'architecture du BSIM.CCU

  • 13