Skip to content

Commit

Permalink
add rem actiobn to sim
Browse files Browse the repository at this point in the history
  • Loading branch information
Boris Zhguchev committed Aug 28, 2023
1 parent 994cd0e commit 38a0460
Show file tree
Hide file tree
Showing 16 changed files with 2,405 additions and 174 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@
* **`0.2.3`**
* Add built in actions for bb
* fix bugs
* **`0.2.4`**
* add remote action to simulation

2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description = "Workflow framework based on the behavior trees"
authors = ["BorisZhguchev <[email protected]>"]
homepage = "https://github.com/besok/forester"
repository = "https://github.com/besok/forester"
version = "0.2.3"
version = "0.2.4"
edition = "2021"
license-file = "LICENSE"

Expand Down
2 changes: 1 addition & 1 deletion docs/src/actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and mix-in on the execution stage.
The actions have 2 keywords to mark:

- `impl` means some job or action that can take time and be asynchronous
- `cond` means some activity to check some conditions and swiftly returns result
- `cond` means some activity to check some conditions and immediately returns result

*In practice, the engine does not see difference*

Expand Down
1 change: 0 additions & 1 deletion docs/src/builtin.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,4 @@ impl http_get(url:string, bb_key:string);

# Http server (sync | async)
# Curl
# lock | unlock key

36 changes: 22 additions & 14 deletions docs/src/sim.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,27 @@ actions:
Config section:
| Setting | Description | Default | Example |
|---------------|--------------------------------------------------|------------------------------------------|-------------------|
| tracer.file | the tracer settings to write to a file | if it is absent, there will be no action | gen/main.trace |
| tracer.dt_fmt | the tracer settings to given data format | if it is absent, there will be no action | "%d %H:%M:%S%.3f" |
| graph | the visualization file | if it is absent, there will be no action | gen/main.svg |
| bb.dump | the dump of the bb at the end | if it is absent, there will be no action | gen/bb.json |
| bb.load | the dump that will be used to init bb before sim | if it is absent, there will be no action | gen/init_bb.json |
| max_ticks | the maximum amount of ticks to work. | 0 by default | 10 |
| Setting | Description | Default | Example |
|---------------|-------------------------------------------------------------------|------------------------------------------|-------------------|
| tracer.file | the tracer settings to write to a file | if it is absent, there will be no action | gen/main.trace |
| tracer.dt_fmt | the tracer settings to given data format | if it is absent, there will be no action | "%d %H:%M:%S%.3f" |
| graph | the visualization file | if it is absent, there will be no action | gen/main.svg |
| bb.dump | the dump of the bb at the end | if it is absent, there will be no action | gen/bb.json |
| bb.load | the dump that will be used to init bb before sim | if it is absent, there will be no action | gen/init_bb.json |
| max_ticks | the maximum amount of ticks to work. | 0 by default | 10 |
| http.port | The port for http server to communicate with the remote actions . | if it is absent, there will be no action | 8080 |
Actions sections:
The actions sections is an array to stub the actions
| Setting | Description | Default | Example |
|--------------|------------------------------------------|---------------------|---------|
| name | the name of the stubbed action | should be presented | name |
| stub | the stubbed implementation | should be presented | success |
| params.delay | denotes the pause before start in millis | 0 | 100 |
| Setting | Description | Default | Example |
|---------------|-----------------------------------------------------------------|---------------------|-------------------------------|
| name | the name of the stubbed action | should be presented | name |
| stub | the stubbed implementation | should be presented | success |
| params.delay | denotes the pause before start in millis | 0 | 100 |
| params.url | (For remote stub) the url to connect | should be presented | http://localhost:10000/action |
| params.server | (For remote stub) the url to provide to action to connect to bb | http://localhost | http://localhost:8080 |
#### Default profile
Expand All @@ -67,10 +70,15 @@ Other artifacts will not be generated.
- success: returns a success
- failure: returns a failure
- random: returns either a failure or a success randomly
- remote: connects to the remote server and returns the result of the action. The details can be found in the [Remote action](./r_actions.md#remote-actions).
All stubs have the following params:
The stubs success, failure, random have the following param:
- delay: in millis, the time to delay the stub.
The remote stub has the following params:
- url: the url to connect to the remote server
- server: the url to provide to the remote server to connect to the blackboard
## Process
The simulation can be performed in on of two ways:
Expand Down
57 changes: 50 additions & 7 deletions src/simulator/actions.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,72 @@
use crate::runtime::action::{Impl, Tick};
use crate::runtime::action::builtin::remote::RemoteHttpAction;
use crate::runtime::action::{Impl, ImplRemote, Tick};
use crate::runtime::args::RtArgs;
use crate::runtime::context::TreeContextRef;
use crate::runtime::context::{TreeContextRef, TreeRemoteContextRef};
use crate::runtime::{RtResult, RuntimeError, TickResult};
use std::collections::HashMap;
use std::time::{Duration, SystemTime};

/// The action that represent the stubs fro the real actions.
pub enum SimAction {
/// usize here is a miilisecond for delay
/// usize here is a millisecond for delay
Success(usize),
/// usize here is a miilisecond for delay
/// usize here is a millisecond for delay
Random(usize),
/// usize here is a miilisecond for delay
/// usize here is a millisecond for delay
Failure(usize),
/// The remote action wrapper
Remote(RemoteHttpAction),
}

impl SimAction {
pub fn create(key: &str, delay: usize) -> RtResult<SimAction> {
pub fn is_remote(&self) -> bool {
match self {
SimAction::Remote(_) => true,
_ => false,
}
}

pub fn create(key: &str, params: HashMap<String, String>) -> RtResult<SimAction> {
let delay = params
.get("delay")
.map(|s| s.parse::<usize>().unwrap_or_default())
.unwrap_or_default();

match key {
"success" => Ok(SimAction::Success(delay)),
"random" => Ok(SimAction::Random(delay)),
"failure" => Ok(SimAction::Failure(delay)),
"remote" => {
let url = params.get("url").cloned().ok_or_else(|| {
RuntimeError::WrongArgument("the url is not specified".to_string())
})?;

let action = if let Some(serv) = params.get("server").cloned() {
RemoteHttpAction::new_with(url, serv)
} else {
RemoteHttpAction::new(url)
};

Ok(SimAction::Remote(action))
}
e => Err(RuntimeError::WrongArgument(format!(
"the {e} is not recognized as simulation stub."
"the {e} is not recognized as a simulation stub."
))),
}
}
}

impl ImplRemote for SimAction {
fn tick(&self, args: RtArgs, ctx: TreeRemoteContextRef) -> Tick {
match self {
SimAction::Remote(delegate) => delegate.tick(args, ctx),
_ => Err(RuntimeError::uex(
"the remote action is expected here".to_string(),
)),
}
}
}

impl Impl for SimAction {
fn tick(&self, _args: RtArgs, _ctx: TreeContextRef) -> Tick {
match self {
Expand All @@ -51,6 +91,9 @@ impl Impl for SimAction {
Ok(TickResult::failure_empty())
}
}
SimAction::Remote(_) => Ok(TickResult::Failure(
"The remote action should execute another contract namely ImplRemote".to_string(),
)),
}
}
}
23 changes: 12 additions & 11 deletions src/simulator/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,19 @@ impl SimulatorBuilder {
fb.bb_load(bb_load_path);
}

if let Some(http) = profile.config.http {
fb.http_serv(http.port);
}

for action in profile.actions.iter() {
fb.register_sync_action(
action.name.as_str(),
SimAction::create(
action.stub.as_str(),
action
.params
.get("delay")
.map(|s| s.parse::<usize>().unwrap_or_default())
.unwrap_or_default(),
)?,
)
let sim_action = SimAction::create(action.stub.as_str(), action.params.clone())?;
let name = action.name.as_str();

if sim_action.is_remote() {
fb.register_remote_action(name, sim_action);
} else {
fb.register_sync_action(name, sim_action);
}
}

let forester =
Expand Down
10 changes: 9 additions & 1 deletion src/simulator/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ pub struct SimProfileConfig {

/// The port where needs to deploy the server to communicate with the remote actions.
#[serde(default)]
pub port: Option<u16>,
pub http: Option<HttpServ>,
}

/// The http server configuration
/// It is used to communicate with the remote actions.
/// The server is used to receive the requests from the remote actions and to send the responses.
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
pub struct HttpServ {
pub port: u16,
}

#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
Expand Down
68 changes: 65 additions & 3 deletions src/tests/simulator.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::runtime::builder::ForesterBuilder;
use crate::simulator::builder::SimulatorBuilder;
use crate::simulator::config::{Action, BbConfig, SimProfile, SimProfileConfig, TracerSimConfig};
use crate::simulator::config::{
Action, BbConfig, HttpServ, SimProfile, SimProfileConfig, TracerSimConfig,
};
use crate::simulator::Simulator;
use crate::tests::test_folder;
use crate::tests::{test_folder, turn_on_logs};
use graphviz_rust::attributes::quadtree::fast;
use std::collections::HashMap;
use std::path::PathBuf;
Expand All @@ -25,7 +27,7 @@ fn file() {
dump: Some(String::from("bb.dump")),
load: Some(String::from("bb.json")),
},
port: None,
http: None,
},
actions: vec![
Action {
Expand Down Expand Up @@ -90,6 +92,40 @@ fn file() {
},
profile
);

let buf = test_folder("simulator/example5.yaml");
let profile = SimProfile::parse_file(&buf).unwrap();

assert_eq!(
SimProfile {
config: SimProfileConfig {
tracer: Default::default(),
bb: Default::default(),
graph: None,
max_ticks: None,
http: Some(HttpServ { port: 8080 }),
},
actions: vec![
Action {
name: "name1".to_string(),
stub: "remote".to_string(),
params: HashMap::from_iter(vec![
("url".to_string(), "localhost:10000".to_string()),
("server".to_string(), "http://localhost:8080".to_string()),
])
},
Action {
name: "name2".to_string(),
stub: "remote".to_string(),
params: HashMap::from_iter(vec![(
"url".to_string(),
"localhost:10001".to_string()
),])
}
]
},
profile
);
}

#[test]
Expand All @@ -111,6 +147,32 @@ fn smoke() {
let tracer = &sim.forester.tracer;
sim.run().unwrap();
}
#[test]
fn smoke_remote() {
turn_on_logs();
let mut sb = SimulatorBuilder::new();

let root = test_folder("simulator/smoke_rem");

sb.root(root.clone());
sb.profile(PathBuf::from("sim.yaml"));

let mut fb = ForesterBuilder::from_fs();
fb.main_file("main.tree".to_string());
fb.root(root);

sb.forester_builder(fb);

let mut sim = sb.build().unwrap();
sim.run().unwrap();

let bb = sim.forester.bb.lock().unwrap();
let option = bb.get("tt".to_string()).unwrap();
assert_eq!(
option.and_then(|v| v.clone().as_string()),
Some("OK".to_string())
);
}

// #[test]
fn text() {
Expand Down
Loading

0 comments on commit 38a0460

Please sign in to comment.