Mercurial > templog
annotate rust/src/types.rs @ 610:af0dac00d40b rust
untested step integrator
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 23 Feb 2017 23:27:09 +0800 |
parents | 7bda01659426 |
children | f3e39e2107fd |
rev | line source |
---|---|
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
1 use std::collections::HashMap; |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
2 use std::time::{Duration,Instant}; |
604
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
3 use std::error::Error; |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
4 use std::fmt; |
610 | 5 use std::cmp; |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
6 use std::cell::Cell; |
610 | 7 use std::iter::FromIterator; |
604
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
8 |
595 | 9 use serde::{Deserialize,Serialize}; |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
10 |
596
ca8102feaca6
sensor takes config parameter
Matt Johnston <matt@ucc.asn.au>
parents:
595
diff
changeset
|
11 #[derive(Deserialize, Serialize, Debug)] |
592 | 12 pub struct Params { |
13 pub fridge_setpoint: f32, | |
14 pub fridge_difference: f32, | |
15 pub overshoot_delay: u32, | |
16 pub overshoot_factor: f32, | |
17 pub disabled: bool, | |
18 pub nowort: bool, | |
19 pub fridge_range_lower: f32, | |
20 pub fridge_range_upper: f32, | |
21 } | |
22 | |
23 impl Params { | |
24 pub fn defaults() -> Params { | |
25 Params { | |
26 fridge_setpoint: 16.0, | |
27 fridge_difference: 0.2, | |
28 overshoot_delay: 720, // 12 minutes | |
29 overshoot_factor: 1.0, | |
30 disabled: false, | |
31 nowort: false, | |
32 fridge_range_lower: 3.0, | |
33 fridge_range_upper: 3.0, | |
34 } | |
35 } | |
36 } | |
37 | |
38 #[derive(Debug)] | |
39 pub struct ParamHolder { | |
40 pub p: Params, | |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
41 epoch: String, |
592 | 42 } |
43 | |
44 impl ParamHolder { | |
45 pub fn new() -> ParamHolder { | |
46 ParamHolder { | |
47 p: Params::defaults(), | |
48 epoch: String::new(), | |
49 } | |
50 } | |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
51 |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
52 pub fn receive(&mut self, p: &Params, epoch: &String) |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
53 { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
54 |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
55 } |
592 | 56 } |
57 | |
58 #[derive(Debug)] | |
59 pub struct Readings { | |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
596
diff
changeset
|
60 pub temps: HashMap<String, f32>, |
592 | 61 } |
62 | |
63 impl Readings { | |
64 pub fn new() -> Readings { | |
65 Readings { | |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
66 temps: HashMap::new(), |
592 | 67 } |
68 } | |
593
bf138339d20a
fiddling with timeouts and closures
Matt Johnston <matt@ucc.asn.au>
parents:
592
diff
changeset
|
69 |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
596
diff
changeset
|
70 pub fn add(&mut self, name: &str, v: f32) { |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
596
diff
changeset
|
71 self.temps.insert(name.to_string(), v); |
593
bf138339d20a
fiddling with timeouts and closures
Matt Johnston <matt@ucc.asn.au>
parents:
592
diff
changeset
|
72 } |
bf138339d20a
fiddling with timeouts and closures
Matt Johnston <matt@ucc.asn.au>
parents:
592
diff
changeset
|
73 |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
596
diff
changeset
|
74 pub fn get_temp(&self, name: &str) -> Option<f32> { |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
596
diff
changeset
|
75 self.temps.get(name).map(|f| *f) |
592 | 76 } |
77 } | |
78 | |
604
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
79 #[derive(Debug)] |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
80 pub struct TemplogError { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
81 desc: String, |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
82 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
83 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
84 impl Error for TemplogError { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
85 fn description(&self) -> &str { &self.desc } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
86 fn cause(&self) -> Option<&Error> { None } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
87 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
88 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
89 impl fmt::Display for TemplogError { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
91 write!(f, "TemplogError: {}", self.desc); |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
92 Ok(()) |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
93 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
94 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
95 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
96 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
97 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
98 impl TemplogError { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
99 pub fn new(desc: &str) -> Self { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
100 TemplogError { |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
101 desc: desc.to_string(), |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
102 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
103 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
104 } |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
105 |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
106 |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
107 /// Call closures with a rate limit. Useful for log message ratelimiting |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
108 pub struct NotTooOften { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
109 last: Cell<Instant>, |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
110 limit: Duration, |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
111 } |
604
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
112 |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
113 impl NotTooOften { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
114 pub fn new(limit_secs: u64) -> Self { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
115 NotTooOften { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
116 limit: Duration::new(limit_secs, 0), |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
117 last: Cell::new(Instant::now() - Duration::new(limit_secs+1, 0)), |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
118 } |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
119 } |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
120 |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
121 pub fn and_then<F>(&self, op: F) |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
122 where F: Fn() { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
123 let now = Instant::now(); |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
124 if now - self.last.get() > self.limit { |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
125 self.last.set(now); |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
126 op(); |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
127 } |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
128 } |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
129 } |
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
130 |
610 | 131 struct Period { |
132 start: Instant, | |
133 end: Option<Instant>, | |
134 } | |
609
7bda01659426
not building, paramwaiter work
Matt Johnston <matt@ucc.asn.au>
parents:
604
diff
changeset
|
135 |
610 | 136 pub struct StepIntegrator { |
137 on_periods: Vec<Period>, | |
138 limit: Duration, | |
139 } | |
140 | |
141 impl StepIntegrator { | |
142 pub fn new(limit: Duration) -> Self { | |
143 StepIntegrator { | |
144 on_periods: Vec::new(), | |
145 limit: limit, | |
146 } | |
147 } | |
148 | |
149 pub fn turn(&mut self, on: bool) { | |
150 self.trim(); | |
151 | |
152 if self.on_periods.is_empty() { | |
153 self.on_periods.push( Period { start: Instant::now(), end: None }); | |
154 return; | |
155 } | |
156 | |
157 let current_on = self.on_periods.last().unwrap().end.is_none(); | |
158 if on == current_on { | |
159 // state is unchanged | |
160 return; | |
161 } | |
162 | |
163 if on { | |
164 self.on_periods.push( Period { start: Instant::now(), end: None }); | |
165 } else { | |
166 self.on_periods.last_mut().unwrap().end = Some(Instant::now()); | |
167 } | |
168 } | |
169 | |
170 pub fn set_limit(&mut self, limit: Duration) { | |
171 self.limit = limit; | |
172 self.trim(); | |
173 } | |
174 | |
175 fn integrate(&self) -> Duration { | |
176 let durs = self.on_periods.iter().map(|p| { | |
177 let end = p.end.unwrap_or_else(|| Instant::now()); | |
178 end - p.start | |
179 }); | |
180 // TODO rust 1.16: impl Sum for Duration | |
181 // durs.sum() | |
182 durs.fold(Duration::new(0,0), |acc, d| acc + d) | |
183 } | |
184 | |
185 fn trim(&mut self) { | |
186 let begin = Instant::now() - self.limit; | |
187 | |
188 self.on_periods.retain(|p| { | |
189 // remove expired endtimes | |
190 if let Some(e) = p.end { | |
191 e >= begin && e != p.start | |
192 } else { | |
193 true | |
194 } | |
195 }); | |
196 | |
197 for p in &mut self.on_periods { | |
198 p.start = cmp::max(p.start, begin); | |
199 } | |
200 } | |
201 } | |
202 |