-
Notifications
You must be signed in to change notification settings - Fork 4
/
eapi.rs
106 lines (98 loc) · 3.09 KB
/
eapi.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// EVA ICS example
use roboplc::{
io::eapi::{EAPIConfig, EAPI, OID},
prelude::*,
time::interval,
};
use serde::Deserialize;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use tracing::info;
#[derive(Clone, Debug)]
#[binrw]
struct Env {
temp: f64,
hum: f64,
pressure: f64,
}
#[derive(Default)]
struct Variables {
fan: AtomicBool,
}
#[derive(DataPolicy, Clone)]
enum Message {}
#[derive(WorkerOpts)]
#[worker_opts(name = "worker1")]
struct Worker1 {
eapi: EAPI<Message, Variables>,
}
#[allow(clippy::cast_lossless)]
impl Worker<Message, Variables> for Worker1 {
fn run(&mut self, context: &Context<Message, Variables>) -> WResult {
let mut temp = 25;
let oid: Arc<OID> = "unit:tests/fan".parse::<OID>().unwrap().into();
let dobj_name: Arc<String> = "Env".to_owned().into();
for _ in interval(Duration::from_millis(200)) {
if temp == 25 {
temp = 10;
} else {
temp = 25;
}
info!(temp);
self.eapi.dobj_push(
dobj_name.clone(),
Env {
temp: temp as f64,
hum: temp as f64 / 2.0,
pressure: temp as f64 / 3.0,
},
)?;
self.eapi.state_push(
oid.clone(),
u8::from(context.variables().fan.load(Ordering::Acquire)),
)?;
//self.eapi.dobj_error(dobj_name.clone())?;
if !context.is_online() {
break;
}
}
Ok(())
}
}
// EAPI requires a separate connector worker to run with
#[derive(WorkerOpts)]
#[worker_opts(name = "eapi", blocking = true)]
struct EAPIConnector {
eapi: EAPI<Message, Variables>,
}
impl Worker<Message, Variables> for EAPIConnector {
fn run(&mut self, context: &Context<Message, Variables>) -> WResult {
self.eapi.run(self.worker_name(), context);
Ok(())
}
}
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
// This macro call copies AUTHOR, VERSION and DESCRIPTION from program's Cargo.toml to the EAPI
// I/O module.
roboplc::init_eapi!();
roboplc::setup_panic();
roboplc::configure_logger(roboplc::LevelFilter::Info);
let eapi_config: EAPIConfig<Message, Variables> = EAPIConfig::new("/opt/eva4/var/bus.ipc")
.action_handler("unit:tests/fan".parse().unwrap(), |action, context| {
let params = action.take_unit_params()?;
let val = u8::deserialize(params.value)?;
context.variables().fan.store(val != 0, Ordering::Release);
Ok(())
});
// this creates a connector instance with the name `fieldbus.HOSTNAME.plc`. To use a custom
// name, use `EAPI::new` instead.
let eapi = EAPI::new_program(eapi_config);
let mut controller = Controller::<Message, Variables>::new();
controller.register_signals(Duration::from_secs(5))?;
controller.spawn_worker(Worker1 { eapi: eapi.clone() })?;
controller.spawn_worker(EAPIConnector { eapi })?;
controller.block();
Ok(())
}