NanoPi NEOのボタン入力をRustで検知してみる(tokio1.x系)
2022-11-02gpio-cdevクレートがバージョンアップしてtokio 1.x系で扱えるようになった。
本記事で以前の記事のコードを書き直す。 環境と準備は同様なので割愛する。
コード
Cargo.toml
[dependencies]
futures = "0.3.25"
tokio = {version = "1", features = ["time", "sync", "rt", "macros"]}
gpio-cdev = {version = "0.5", features=["async-tokio"]}
tokioクレートとgpio-cdevクレートのバージョン修正のみ。
main.rs
use futures::stream::StreamExt;
use gpio_cdev::{AsyncLineEventHandle, Chip, EventRequestFlags, LineRequestFlags};
use std::error::Error;
async fn async_main() -> Result<(), Box<dyn Error>> {
//使用するGPIOキャラクターデバイスを指定する
let mut chip = Chip::new("/dev/gpiochip0")?;
//使用するピン番号のハンドルを取得する
let lines = [chip.get_line(0)?, chip.get_line(2)?, chip.get_line(3)?];
//対応するピン番号のイベントハンドルを取得する
//どの状態変化を検出するかを引数で指定する
let events = lines
.iter()
.map(|line| {
line.events(
LineRequestFlags::INPUT, //入力として使用する
EventRequestFlags::BOTH_EDGES, //ボタンが押されたときと、ボタンから手を離したときを検知する
"gpioevents",
)
})
.collect::<Result<Vec<_>, _>>()?;
//イベントを非同期で受け取れるようにする
let handles = events
.into_iter()
.map(AsyncLineEventHandle::new)
.collect::<Result<Vec<_>, _>>()?;
let (mut handle1, mut handle2, mut handle3) = {
let mut iter = handles.into_iter();
(
iter.next().unwrap(),
iter.next().unwrap(),
iter.next().unwrap(),
)
};
loop {
//どれか1つのボタンが押されたときに標準出力へ出力する
let (name, event) = tokio::select! {
Some(Ok(e)) = handle1.next() => {
("F1", e.event_type())
},
Some(Ok(e)) = handle2.next() => {
("F2", e.event_type())
},
Some(Ok(e)) = handle3.next() => {
("F3", e.event_type())
},
else => break,
};
println!("{}: {:?}", name, event);
}
Ok(())
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async_main().await
}
特記事項
- 基本は以前の記事と同じ
- tokio::mainアトリビュートはflavorの指定が必要