Mercurial > templog
annotate rust/src/main.rs @ 607:282fae1c12e4 rust
NotTooOften
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 17 Feb 2017 22:27:44 +0800 |
parents | 278f1002b5c7 |
children | 7bda01659426 |
rev | line source |
---|---|
588
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
1 extern crate tokio_core; |
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
2 extern crate futures; |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
3 #[macro_use] |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
4 extern crate log; |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
5 extern crate env_logger; |
597 | 6 extern crate rustc_serialize; |
7 extern crate time; | |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
8 |
604
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
9 #[macro_use] |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
10 extern crate lazy_static; |
278f1002b5c7
sensor regex, custom error type
Matt Johnston <matt@ucc.asn.au>
parents:
603
diff
changeset
|
11 |
595 | 12 #[macro_use] |
13 extern crate serde_derive; | |
14 extern crate serde; | |
15 | |
16 extern crate toml; | |
17 | |
597 | 18 extern crate docopt; |
19 | |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
20 use std::io; |
607 | 21 use std::time::{Duration,Instant}; |
22 use std::ops::Not; | |
23 use std::cell::Cell; | |
588
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
24 |
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
25 use tokio_core::reactor::Core; |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
26 use futures::{Stream,Sink,Future}; |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
27 use futures::sync::{mpsc}; |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
28 use sensor::Sensor; |
589
f2508125adf1
Try using traits for periodic stream
Matt Johnston <matt@ucc.asn.au>
parents:
588
diff
changeset
|
29 |
595 | 30 mod config; |
590 | 31 mod sensor; |
597 | 32 pub mod fridge; |
592
03b48ec0bb03
fridge, types, configwaiter
Matt Johnston <matt@ucc.asn.au>
parents:
591
diff
changeset
|
33 mod types; |
593
bf138339d20a
fiddling with timeouts and closures
Matt Johnston <matt@ucc.asn.au>
parents:
592
diff
changeset
|
34 mod paramwaiter; |
591 | 35 |
592
03b48ec0bb03
fridge, types, configwaiter
Matt Johnston <matt@ucc.asn.au>
parents:
591
diff
changeset
|
36 use types::*; |
597 | 37 use config::Config; |
588
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
38 |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
39 fn run(config: &Config, nowait: bool, testmode: bool) { |
595 | 40 |
588
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
41 let mut core = Core::new().unwrap(); |
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
42 let handle = core.handle(); |
587 | 43 |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
44 let mut paramh = ParamHolder::new(); |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
45 let mut fridge = fridge::Fridge::new(&config, nowait, paramh.p, &handle); |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
46 |
597 | 47 let (fridge_reading_s, fridge_reading_r) = mpsc::channel(1); |
48 let fridge_reading_r = fridge_reading_r.map_err(|_| io::Error::new(io::ErrorKind::Other, "Problem with fridge_reading_r channel")); | |
587 | 49 |
597 | 50 let sensor_stream = if testmode { |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
51 sensor::TestSensor::new(config).stream(&handle) |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
52 } else { |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
53 sensor::OneWireSensor::new(config).stream(&handle) |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
54 }; |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
55 |
597 | 56 // Send the sensors of interest to the fridge (fridge_reading_s), |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
57 // while streaming them all to the web sender. |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
58 let s = sensor_stream.map(|r| { |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
59 debug!("sensors {:?}", r); |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
60 let msg = fridge::Message::Sensor { |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
61 wort: r.get_temp(&config.WORT_NAME), |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
62 fridge: r.get_temp(&config.FRIDGE_NAME) |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
63 }; |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
64 let t = fridge_reading_s.clone().send(msg) |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
65 .map(|_| ()) |
595 | 66 .map_err(|e| { |
597 | 67 warn!("Send error in fridge_reading_s: {}", e.to_string()); |
595 | 68 () |
69 }); | |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
70 handle.spawn(t); |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
71 r |
588
038734052b20
fiddling with futures-rs instead
Matt Johnston <matt@ucc.asn.au>
parents:
587
diff
changeset
|
72 }); |
587 | 73 |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
74 let param_stream = paramwaiter::ParamWaiter::stream(&handle); |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
75 let p = param_stream.map(|p| { |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
76 fridge::Message::Params(p) |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
77 }); |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
78 |
597 | 79 let timeouts = fridge.wakeups(); |
591 | 80 |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
81 let all_readings = s.for_each(|_| Ok(())); |
597 | 82 let all_fridge = p.select(timeouts).select(fridge_reading_r).forward(fridge) |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
83 .map(|_| () ); |
592
03b48ec0bb03
fridge, types, configwaiter
Matt Johnston <matt@ucc.asn.au>
parents:
591
diff
changeset
|
84 |
594
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
85 let all = all_fridge.select(all_readings); |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
86 |
aff50ee77252
rust working better now with streams and sinks.
Matt Johnston <matt@ucc.asn.au>
parents:
593
diff
changeset
|
87 core.run(all).ok(); |
587 | 88 } |
89 | |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
90 const USAGE: &'static str = "\ |
597 | 91 Wort Temperature |
92 Matt Johnston 2017 [email protected] | |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
93 Usage: wort-templog [--help] [--new] [--daemon] [--debug] [--test] [--defconf] [--thisconf] [--nowait] |
597 | 94 |
95 Options: | |
96 -h, --help | |
97 --new Replace existing running instance | |
98 -D, --daemon Run in background | |
99 -d, --debug | |
100 -t, --test Use fake sensors etc | |
101 --nowait Skip initial fridge wait | |
102 --defconf Print default config (customise in tempserver.conf) | |
103 --thisconf Print used config | |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
104 "; |
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
105 |
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
106 #[derive(RustcDecodable)] |
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
107 struct Args { |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
108 flag_new: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
109 flag_daemon: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
110 flag_debug: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
111 flag_test: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
112 flag_defconf: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
113 flag_thisconf: bool, |
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
114 flag_nowait: bool, |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
115 } |
597 | 116 |
117 fn setup_log(debug: bool) { | |
118 let loglevel = if debug { | |
119 log::LogLevelFilter::Debug | |
120 } else { | |
121 log::LogLevelFilter::Info | |
122 }; | |
123 | |
124 let format = |record: &log::LogRecord| { | |
125 let datefmt = "%Y-%m-%d %I:%M:%S %p"; | |
126 let ts = time::strftime(datefmt, &time::now()).unwrap(); | |
127 format!("{}: {} - {}", ts, record.level(), record.args()) | |
128 }; | |
129 | |
130 | |
131 let mut builder = env_logger::LogBuilder::new(); | |
132 builder.format(format).filter(Some("wort_templog"), loglevel); | |
133 builder.init().unwrap(); | |
134 } | |
135 | |
136 fn handle_args() -> Args { | |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
137 let args: Args = docopt::Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit()); |
597 | 138 |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
139 if args.flag_defconf { |
597 | 140 println!("Default configuration:\n{}\n\n{}", |
141 "(custom options go in tempserver.conf)", | |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
142 config::Config::default().to_toml_string()); |
597 | 143 std::process::exit(0); |
144 } | |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
145 args |
597 | 146 } |
147 | |
601 | 148 fn load_config() -> Config { |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
149 let nconfig = config::Config::default(); |
601 | 150 |
151 let conf_filename = "tempserver.conf"; | |
152 nconfig.merge_file(conf_filename) | |
153 .unwrap_or_else(|e| { | |
154 println!("Couldn't parse {}: {}", conf_filename, e); | |
155 std::process::exit(1); | |
156 }) | |
157 } | |
158 | |
597 | 159 fn main() { |
160 | |
161 let args = handle_args(); | |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
162 setup_log(args.flag_debug); |
597 | 163 //env_logger::init().unwrap(); |
164 | |
165 info!("wort-templog"); | |
166 debug!("debug mode"); | |
167 | |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
168 let config = load_config(); |
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
169 |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
170 if args.flag_thisconf { |
598
d4fbfb5c46ff
broken update of versions of things
Matt Johnston <matt@ucc.asn.au>
parents:
597
diff
changeset
|
171 println!("Current configuration:\n\n{}", |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
172 config.to_toml_string()); |
599
f71cf1ad745f
updated toml serde works OK
Matt Johnston <matt@ucc.asn.au>
parents:
598
diff
changeset
|
173 std::process::exit(0); |
597 | 174 } |
175 | |
603
b45b8b4cf0f5
get rid of lazy_static, config is passed around
Matt Johnston <matt@ucc.asn.au>
parents:
601
diff
changeset
|
176 run(&config, args.flag_nowait, args.flag_test); |
597 | 177 } |
178 | |
607 | 179 /// Call closures with a rate limit. Useful for log message ratelimiting |
180 pub struct NotTooOften { | |
181 last: Cell<Instant>, | |
182 limit: Duration, | |
183 } | |
184 | |
185 impl NotTooOften { | |
186 pub fn new(limit_secs: u64) -> Self { | |
187 NotTooOften { | |
188 limit: Duration::new(limit_secs, 0), | |
189 last: Cell::new(Instant::now() - Duration::new(limit_secs+1, 0)), | |
190 } | |
191 } | |
192 | |
193 pub fn and_then<F>(&self, op: F) | |
194 where F: Fn() { | |
195 let now = Instant::now(); | |
196 if now - self.last.get() > self.limit { | |
197 self.last.set(now); | |
198 op(); | |
199 } | |
200 } | |
201 } | |
202 |