Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
1
tools/EVerest-main/modules/Examples/RustExamples/.gitignore
vendored
Normal file
1
tools/EVerest-main/modules/Examples/RustExamples/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
target
|
||||
@@ -0,0 +1,2 @@
|
||||
ev_add_module(RsExample)
|
||||
ev_add_module(RsExampleUser)
|
||||
@@ -0,0 +1,37 @@
|
||||
load("@rules_rust//rust:defs.bzl", "rust_binary")
|
||||
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
|
||||
load("@everest_crate_index//:defs.bzl", "all_crate_deps")
|
||||
|
||||
cargo_build_script(
|
||||
name = "build_script",
|
||||
srcs = ["build.rs"],
|
||||
edition="2021",
|
||||
build_script_env = {
|
||||
# This is a path to the folder where interfaces and types are placed.
|
||||
# We are guessing it here since bazel doesn't provide a good way
|
||||
# to resolve a directoryname of filegroup.
|
||||
"EVEREST_CORE_ROOT": "../../../../",
|
||||
},
|
||||
deps = all_crate_deps(build=True) + [
|
||||
"//lib/everest/framework/everestrs/everestrs-build",
|
||||
],
|
||||
data= [
|
||||
"//types:types",
|
||||
"//interfaces:interfaces",
|
||||
"manifest.yaml",
|
||||
],
|
||||
)
|
||||
|
||||
rust_binary(
|
||||
name = "RsExample",
|
||||
srcs = glob(["src/**/*.rs"]),
|
||||
visibility = ["//visibility:public"],
|
||||
edition = "2021",
|
||||
deps = all_crate_deps() + [
|
||||
"//lib/everest/framework/everestrs/everestrs",
|
||||
"//lib/everest/framework/everestrs/everestrs:everestrs_sys",
|
||||
"//lib/everest/framework/everestrs/everestrs:everestrs_bridge",
|
||||
":build_script",
|
||||
],
|
||||
proc_macro_deps = all_crate_deps(proc_macro=True),
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "RsExample"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
everestrs = { workspace = true }
|
||||
serde = { version = "1.0.200", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
[build-dependencies]
|
||||
everestrs-build = { workspace = true }
|
||||
@@ -0,0 +1,34 @@
|
||||
description: Simple example module written in Rust
|
||||
config:
|
||||
some_string_config:
|
||||
description: A module level string config.
|
||||
type: string
|
||||
default: Hello world
|
||||
some_number_config:
|
||||
description: A module level number config.
|
||||
type: number
|
||||
default: 42
|
||||
provides:
|
||||
foobar:
|
||||
interface: example
|
||||
description: This implements an example interface that uses multiple framework features
|
||||
config:
|
||||
some_bool_config:
|
||||
description: An interface level bool config
|
||||
type: boolean
|
||||
default: true
|
||||
some_integer_config:
|
||||
description: An interface level integer config.
|
||||
type: integer
|
||||
default: 1234
|
||||
my_store:
|
||||
interface: kvs
|
||||
description: This implements the kvs interface, mostly for testing multiple interfaces in one manifest
|
||||
requires:
|
||||
their_store:
|
||||
interface: kvs
|
||||
metadata:
|
||||
license: https://opensource.org/licenses/Apache-2.0
|
||||
authors:
|
||||
- Holger Rapp
|
||||
enable_external_mqtt: false
|
||||
@@ -0,0 +1,89 @@
|
||||
// EVerest expects binaries to be CamelCased, and Rust wants them to be snake_case. We yield to
|
||||
// EVerest and shut up the compiler warning.
|
||||
#![allow(non_snake_case)]
|
||||
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
|
||||
|
||||
use generated::{
|
||||
Context, ExampleServiceSubscriber, KvsClientSubscriber, KvsServiceSubscriber, Module,
|
||||
ModulePublisher, OnReadySubscriber,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use std::{thread, time};
|
||||
use everestrs::serde_json;
|
||||
|
||||
pub struct OneClass {}
|
||||
|
||||
impl KvsServiceSubscriber for OneClass {
|
||||
fn store(
|
||||
&self,
|
||||
context: &Context,
|
||||
key: String,
|
||||
value: serde_json::Value,
|
||||
) -> ::everestrs::Result<()> {
|
||||
context.publisher.their_store.store(key, value)
|
||||
}
|
||||
|
||||
fn load(&self, context: &Context, key: String) -> ::everestrs::Result<serde_json::Value> {
|
||||
context.publisher.their_store.load(key)
|
||||
}
|
||||
|
||||
fn delete(&self, context: &Context, key: String) -> ::everestrs::Result<()> {
|
||||
context.publisher.their_store.delete(key)
|
||||
}
|
||||
|
||||
fn exists(&self, context: &Context, key: String) -> ::everestrs::Result<bool> {
|
||||
context.publisher.their_store.exists(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExampleServiceSubscriber for OneClass {
|
||||
fn uses_something(&self, context: &Context, key: String) -> ::everestrs::Result<bool> {
|
||||
if !context.publisher.their_store.exists(key.clone())? {
|
||||
println!("IT SHOULD NOT AND DOES NOT EXIST");
|
||||
}
|
||||
|
||||
let test_array = vec![1, 2, 3];
|
||||
context
|
||||
.publisher
|
||||
.their_store
|
||||
.store(key.clone(), test_array.clone().into())?;
|
||||
|
||||
let exi = context.publisher.their_store.exists(key.clone())?;
|
||||
if exi {
|
||||
println!("IT ACTUALLY EXISTS");
|
||||
}
|
||||
|
||||
let ret: Vec<i32> = serde_json::from_value(context.publisher.their_store.load(key)?)
|
||||
.expect("Wanted an array as return value");
|
||||
|
||||
println!("loaded array: {ret:?}, original array: {test_array:?}");
|
||||
Ok(exi)
|
||||
}
|
||||
}
|
||||
|
||||
impl KvsClientSubscriber for OneClass {}
|
||||
|
||||
impl OnReadySubscriber for OneClass {
|
||||
fn on_ready(&self, publishers: &ModulePublisher) {
|
||||
// Ignore errors here.
|
||||
let _ = publishers.foobar.max_current(125.);
|
||||
}
|
||||
}
|
||||
|
||||
#[everestrs::main]
|
||||
fn main(module: &Module) {
|
||||
let config = module.get_config();
|
||||
println!("Received the config {config:?}");
|
||||
let one_class = Arc::new(OneClass {});
|
||||
let _publishers = module.start(
|
||||
one_class.clone(),
|
||||
one_class.clone(),
|
||||
one_class.clone(),
|
||||
one_class.clone(),
|
||||
);
|
||||
// Everest is driving execution in the background for us, nothing to do.
|
||||
loop {
|
||||
let dt = time::Duration::from_millis(250);
|
||||
thread::sleep(dt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
load("@rules_rust//rust:defs.bzl", "rust_binary")
|
||||
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
|
||||
load("@everest_crate_index//:defs.bzl", "all_crate_deps")
|
||||
|
||||
cargo_build_script(
|
||||
name = "build_script",
|
||||
srcs = ["build.rs"],
|
||||
edition="2021",
|
||||
build_script_env = {
|
||||
"EVEREST_CORE_ROOT": "../../../../",
|
||||
},
|
||||
deps = all_crate_deps(build=True) + [
|
||||
"//lib/everest/framework/everestrs/everestrs-build",
|
||||
],
|
||||
data= [
|
||||
"//types:types",
|
||||
"//interfaces:interfaces",
|
||||
"manifest.yaml",
|
||||
],
|
||||
)
|
||||
|
||||
rust_binary(
|
||||
name = "RsExampleUser",
|
||||
srcs = glob(["src/**/*.rs"]),
|
||||
visibility = ["//visibility:public"],
|
||||
edition = "2021",
|
||||
deps = all_crate_deps() + [
|
||||
"//lib/everest/framework/everestrs/everestrs",
|
||||
"//lib/everest/framework/everestrs/everestrs:everestrs_sys",
|
||||
"//lib/everest/framework/everestrs/everestrs:everestrs_bridge",
|
||||
":build_script",
|
||||
],
|
||||
proc_macro_deps = all_crate_deps(proc_macro=True),
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "RsExampleUser"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
everestrs = { workspace = true }
|
||||
serde = { version = "1.0.200", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
[build-dependencies]
|
||||
everestrs-build = { workspace = true }
|
||||
@@ -0,0 +1,15 @@
|
||||
description: Simple example module written in Rust and using the other example module
|
||||
provides:
|
||||
main:
|
||||
interface: example_user
|
||||
description: This implements the example_user interface
|
||||
requires:
|
||||
their_example:
|
||||
interface: example
|
||||
another_example:
|
||||
interface: example
|
||||
metadata:
|
||||
license: https://opensource.org/licenses/Apache-2.0
|
||||
authors:
|
||||
- Holger Rapp
|
||||
enable_external_mqtt: false
|
||||
@@ -0,0 +1,88 @@
|
||||
// EVerest expects binaries to be CamelCased, and Rust wants them to be snake_case. We yield to
|
||||
// EVerest and shut up the compiler warning.
|
||||
#![allow(non_snake_case)]
|
||||
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{thread, time};
|
||||
|
||||
use generated::{
|
||||
Context, ExampleClientSubscriber, ExampleUserServiceSubscriber, Module, ModulePublisher,
|
||||
OnReadySubscriber,
|
||||
};
|
||||
|
||||
struct ExampleClient {
|
||||
max_current: Mutex<Option<f64>>,
|
||||
thread: Mutex<Option<thread::JoinHandle<()>>>,
|
||||
}
|
||||
|
||||
impl ExampleClient {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
max_current: Mutex::new(None),
|
||||
thread: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExampleClientSubscriber for ExampleClient {
|
||||
fn on_max_current(&self, context: &Context, value: f64) {
|
||||
println!("Received the value {value}");
|
||||
let _ = context
|
||||
.publisher
|
||||
.their_example
|
||||
.uses_something("hello_there".to_string());
|
||||
*self.max_current.lock().unwrap() = Some(value);
|
||||
|
||||
// Example where we start a thread with the publisher. The cloning is
|
||||
// only done if the user wants to offload the publisher into a thread.
|
||||
let clone = context.publisher.clone();
|
||||
*self.thread.lock().unwrap() = Some(thread::spawn(move || {
|
||||
let _ = clone.another_example.uses_something("foo".to_string());
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
struct MainService {}
|
||||
impl ExampleUserServiceSubscriber for MainService {}
|
||||
|
||||
struct OurModule {
|
||||
their_example: Arc<ExampleClient>,
|
||||
another_example: Arc<ExampleClient>,
|
||||
min_current: Mutex<Option<f64>>,
|
||||
}
|
||||
|
||||
impl OnReadySubscriber for OurModule {
|
||||
fn on_ready(&self, _pub_impl: &ModulePublisher) {
|
||||
let mut their_current = self.their_example.max_current.lock().unwrap();
|
||||
let mut another_current = self.another_example.max_current.lock().unwrap();
|
||||
*their_current = Some(1.);
|
||||
*another_current = Some(2.);
|
||||
// uses somehow both...
|
||||
*self.min_current.lock().unwrap() = Some(1.);
|
||||
}
|
||||
}
|
||||
|
||||
#[everestrs::main]
|
||||
fn main(module: &Module) {
|
||||
let their_example = Arc::new(ExampleClient::new());
|
||||
let another_example = Arc::new(ExampleClient::new());
|
||||
let main_service = Arc::new(MainService {});
|
||||
let our_module = Arc::new(OurModule {
|
||||
their_example: their_example.clone(),
|
||||
another_example: another_example.clone(),
|
||||
min_current: Mutex::new(None),
|
||||
});
|
||||
let _publishers = module.start(
|
||||
our_module.clone(),
|
||||
main_service.clone(),
|
||||
their_example.clone(),
|
||||
another_example.clone(),
|
||||
);
|
||||
|
||||
// Everest is driving execution in the background for us, nothing to do.
|
||||
loop {
|
||||
let dt = time::Duration::from_millis(250);
|
||||
thread::sleep(dt);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user