|
1 | | -#[cfg(feature = "async-tokio")] |
2 | | -extern crate futures; |
3 | | -#[cfg(feature = "async-tokio")] |
4 | | -extern crate sysfs_gpio; |
5 | | -#[cfg(feature = "async-tokio")] |
6 | | -extern crate tokio; |
| 1 | +// Copyright (c) 2020. The sysfs-gpio Authors. |
7 | 2 |
|
8 | | -#[cfg(feature = "async-tokio")] |
| 3 | +use futures::future::join_all; |
| 4 | +use futures::StreamExt; |
9 | 5 | use std::env; |
10 | | - |
11 | | -#[cfg(feature = "async-tokio")] |
12 | | -use futures::{lazy, Future, Stream}; |
13 | | - |
14 | | -#[cfg(feature = "async-tokio")] |
15 | 6 | use sysfs_gpio::{Direction, Edge, Pin}; |
16 | 7 |
|
17 | | -#[cfg(feature = "async-tokio")] |
18 | | -fn stream(pin_nums: Vec<u64>) -> sysfs_gpio::Result<()> { |
| 8 | +async fn monitor_pin(pin: Pin) -> Result<(), sysfs_gpio::Error> { |
| 9 | + pin.export()?; |
| 10 | + pin.set_direction(Direction::In)?; |
| 11 | + pin.set_edge(Edge::BothEdges)?; |
| 12 | + let mut gpio_events = pin.get_value_stream()?; |
| 13 | + while let Some(evt) = gpio_events.next().await { |
| 14 | + let val = evt.unwrap(); |
| 15 | + println!("Pin {} changed value to {}", pin.get_pin_num(), val); |
| 16 | + } |
| 17 | + Ok(()) |
| 18 | +} |
| 19 | + |
| 20 | +async fn stream(pin_nums: Vec<u64>) { |
19 | 21 | // NOTE: this currently runs forever and as such if |
20 | 22 | // the app is stopped (Ctrl-C), no cleanup will happen |
21 | 23 | // and the GPIO will be left exported. Not much |
22 | 24 | // can be done about this as Rust signal handling isn't |
23 | 25 | // really present at the moment. Revisit later. |
24 | | - let pins: Vec<_> = pin_nums.iter().map(|&p| (p, Pin::new(p))).collect(); |
25 | | - let task = lazy(move || { |
26 | | - for &(i, ref pin) in pins.iter() { |
27 | | - pin.export().unwrap(); |
28 | | - pin.set_direction(Direction::In).unwrap(); |
29 | | - pin.set_edge(Edge::BothEdges).unwrap(); |
30 | | - tokio::spawn( |
31 | | - pin.get_value_stream() |
32 | | - .unwrap() |
33 | | - .for_each(move |val| { |
34 | | - println!("Pin {} changed value to {}", i, val); |
35 | | - Ok(()) |
36 | | - }) |
37 | | - .map_err(|_| ()), |
38 | | - ); |
39 | | - } |
40 | | - Ok(()) |
41 | | - }); |
42 | | - tokio::run(task); |
43 | | - |
44 | | - Ok(()) |
| 26 | + join_all(pin_nums.into_iter().map(|p| { |
| 27 | + let pin = Pin::new(p); |
| 28 | + tokio::task::spawn(monitor_pin(pin)) |
| 29 | + })) |
| 30 | + .await; |
45 | 31 | } |
46 | 32 |
|
47 | | -#[cfg(feature = "async-tokio")] |
48 | | -fn main() { |
| 33 | +#[tokio::main] |
| 34 | +async fn main() { |
49 | 35 | let pins: Vec<u64> = env::args() |
50 | 36 | .skip(1) |
51 | 37 | .map(|a| a.parse().expect("Pins must be specified as integers")) |
52 | 38 | .collect(); |
53 | 39 | if pins.is_empty() { |
54 | 40 | println!("Usage: ./tokio <pin> [pin ...]"); |
55 | 41 | } else { |
56 | | - stream(pins).unwrap(); |
| 42 | + stream(pins).await; |
57 | 43 | } |
58 | 44 | } |
59 | | - |
60 | | -#[cfg(not(feature = "async-tokio"))] |
61 | | -fn main() { |
62 | | - println!("This example requires the `tokio` feature to be enabled."); |
63 | | -} |
0 commit comments