Skip to content

Commit

Permalink
Adding Zenoh-Flow Examples Target (#167)
Browse files Browse the repository at this point in the history
Move `getting-started` and `period-miss-detector` examples inside Zenoh-Flow.

Co-authored-by: J-Loudet <julien.loudet@zettascale.tech>
  • Loading branch information
PhilipTamb and J-Loudet authored Oct 9, 2023
1 parent 380fe6a commit 66b4231
Show file tree
Hide file tree
Showing 11 changed files with 472 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"zenoh-flow-derive",
"zenoh-flow-plugin",
"zfctl",
"examples",
]

[workspace.package]
Expand Down
34 changes: 34 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "zenoh-flow-examples"
version.workspace = true
edition.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
categories.workspace = true
description.workspace = true
license.workspace = true
readme = "README.md"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-std = { workspace = true }
async-trait = { workspace = true }
prost = "0.11"
zenoh-flow = { path = "../zenoh-flow/" }

[[example]]
name = "greetings-maker"
path = "examples/greetings-maker/src/lib.rs"
crate-type = ["cdylib"]

[[example]]
name = "file-writer"
path = "examples/file-writer/src/lib.rs"
crate-type = ["cdylib"]

[[example]]
name = "period-miss-detector"
path = "examples/period-miss-detector/src/lib.rs"
crate-type = ["cdylib"]
51 changes: 51 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Zenoh-Flow examples

## How to run

### Build

We can create all the zenoh-flow node libraries used in the examples with the following command:
```bash
cargo build --examples
```

Alternatively, we can create a single library of a zenoh-flow node with the following command:
```bash
cargo build --example <node>
```

### Configure and run the examples

We first have to update all the occurrences of `{{ BASE_DIR }}` in the YAML descriptors to match our system.

#### Launch the flow

```shell
./target/debug/zfctl launch ~/dev/zenoh-flow/examples/data-flow.yaml
```

If you have enabled the REST plugin of Zenoh
```shell
curl -X PUT -d 'world' http://localhost:8000/zf/getting-started/hello
```

For the "period-miss-detector" example:

```shell
curl -X PUT -d '2340' http://localhost:8000/zf/period-miss-detector
```
#### Show the result:

The Sink node used in both examples creates a text file where the node writes the strings it receives.
We can see the "getting-started" test file with:

```
tail -f /tmp/greetings.txt
```
For the "period-miss-detector" example:
```
tail -f /tmp/period-log.txt
```
14 changes: 14 additions & 0 deletions examples/examples/file-writer/file-writer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
id: file-writer

vars:
BASE_DIR: "/path/to/zenoh-flow"

# Do not forget to change the extension depending on your operating system!
# Linux -> .so
# Windows -> .dll (and remove the "lib" in front)
# MacOS -> .dylib
uri: "file://{{ BASE_DIR }}/target/debug/examples/libfile_writer.dylib"
# If the compilation is in release:
# uri: file:///absolute/path/to/target/release/libfile_writer.so

inputs: [in]
71 changes: 71 additions & 0 deletions examples/examples/file-writer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright (c) 2022 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
//

use async_std::{fs::File, io::WriteExt, sync::Mutex};
use prost::Message as pMessage;
use zenoh_flow::{anyhow, prelude::*};

#[export_sink]
pub struct FileWriter {
input: Input<String>,
file: Mutex<File>,
}

#[async_trait::async_trait]
impl Node for FileWriter {
async fn iteration(&self) -> Result<()> {
let (message, _) = self.input.recv().await?;

if let Message::Data(greeting) = message {
let mut file = self.file.lock().await;
file.write_all(greeting.as_bytes())
.await
.map_err(|e| zferror!(ErrorKind::IOError, "{:?}", e))?;
return file
.flush()
.await
.map_err(|e| zferror!(ErrorKind::IOError, "{:?}", e).into());
}

Ok(())
}
}

#[async_trait::async_trait]
impl Sink for FileWriter {
async fn new(
_context: Context,
configuration: Option<Configuration>,
mut inputs: Inputs,
) -> Result<Self> {
let file_path = match &configuration {
Some(conf) => conf["file"]
.as_str()
.ok_or_else(|| zferror!(ErrorKind::ConfigurationError))?,
None => "/tmp/greetings.txt",
};

Ok(FileWriter {
file: Mutex::new(
File::create(file_path)
.await
.unwrap_or_else(|e| panic!("Could not create '{}'", e)),
),
input: inputs
.take("in")
.expect("No Input called 'in' found")
.typed(|bytes| String::decode(bytes).map_err(|e| anyhow!(e))),
})
}
}
15 changes: 15 additions & 0 deletions examples/examples/greetings-maker/greetings-maker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
id: greetings-maker

vars:
BASE_DIR: "/path/to/zenoh-flow"

# Do not forget to change the extension depending on your operating system!
# Linux -> .so
# Windows -> .dll (and remove the "lib" in front)
# MacOS -> .dylib
uri: "file://{{ BASE_DIR }}/target/debug/examples/libgreetings_maker.dylib"
# If the compilation is in release:
# uri: file:///absolute/path/to/target/release/libgreetings_maker.so

inputs: [name]
outputs: [greeting]
64 changes: 64 additions & 0 deletions examples/examples/greetings-maker/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// Copyright (c) 2022 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <zenoh@zettascale.tech>
//

use prost::Message as pMessage;
use zenoh_flow::{anyhow, prelude::*};

#[export_operator]
pub struct GreetingsMaker {
input: Input<String>,
output: Output<String>,
}

#[async_trait::async_trait]
impl Operator for GreetingsMaker {
async fn new(
_context: Context,
_configuration: Option<Configuration>,
mut inputs: Inputs,
mut outputs: Outputs,
) -> Result<Self> {
Ok(GreetingsMaker {
input: inputs
.take("name")
.expect("No input 'name' found")
.typed(|bytes| String::from_utf8(bytes.into()).map_err(|e| anyhow!(e))),
output: outputs
.take("greeting")
.expect("No output 'greeting' found")
.typed(|buffer, data: &String| data.encode(buffer).map_err(|e| anyhow!(e))),
})
}
}

#[async_trait::async_trait]
impl Node for GreetingsMaker {
async fn iteration(&self) -> Result<()> {
let (message, _) = self.input.recv().await?;
if let Message::Data(characters) = message {
let name = characters.trim_end();

let greetings = match name {
"Sofia" | "Leonardo" => format!("Ciao, {}!\n", name),
"Lucia" | "Martin" => format!("¡Hola, {}!\n", name),
"Jade" | "Gabriel" => format!("Bonjour, {} !\n", name),
_ => format!("Hello, {}!\n", name),
};

return self.output.send(greetings, None).await;
}

Ok(())
}
}
15 changes: 15 additions & 0 deletions examples/examples/period-miss-detector/period-miss-detector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
id: period-miss-detector

vars:
BASE_DIR: "/path/to/zenoh-flow"

# Do not forget to change the extension depending on your operating system!
# Linux -> .so
# Windows -> .dll (and remove the "lib" in front)
# MacOS -> .dylib
uri: "file://{{ BASE_DIR }}/target/debug/examples/libperiod_miss_detector.dylib"
# If the compilation is in release:
# uri: file:///absolute/path/to/target/release/libperiod_miss_detector.dylib

inputs: [in]
outputs: [out]
Loading

0 comments on commit 66b4231

Please sign in to comment.