Rust serialport ③

e-tipsmemo.hatenablog.com
以前このようなプログラムを書いて、
ワットチェッカーからシリアルポート(over Bluetooth)経由で電力のログを取っていたが、
まともにエラーハンドリングしていなかったので、
不具合が起きており、その修正を行った。

問題の処理

pub fn communicate_command(&mut self, cmd:Vec<u8>, rcount:usize)->Result<Vec<u8>, std::io::Error>
{
	let mut resp : Vec<u8> = vec![];

	match self.port.write(&cmd) {
		Ok(_) => (),
		Err(e) => eprintln!("{:?}", e),
	}

	let mut buffer : [u8; 1] = unsafe{mem::uninitialized()};

	loop{
		match self.port.read(&mut buffer)
		{
			Ok(bytes) => if bytes == 1
			{
				resp.push(buffer[0]);
				if resp.len() == rcount 
				{
					break;
				}
			},
			Err(ref e) if e.kind() == io::ErrorKind::TimedOut => (),
			Err(e) => return Err(e),
		}
	}
	
	Ok(resp)
}

指定したバイト数を受信するまでループするが、何らかの理由で受信バイト数が来ずにずっとループが回っていた。

Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {
	eprintln!("{:?}", e);
	timeoutbreak = timeoutbreak + 1;
	
	if timeoutbreak == 200 {
		return Err(Error::new(ErrorKind::Other, "timeout 200 times"));
	}
	
	()
},

一回ごとのタイムアウトの時間は10ミリ秒
連続して、200回タイムアウトしたら、Errでループを抜けることにした。
(計測の間隔が2秒であることと、RTCを設定するのに1300ミリ秒ぐらいかかるので)

f:id:katakanan:20191017061210p:plain
処理を継続させる代わりにstd::process::exitで止めたところ。

止めずに再び新しい測定値を得るようにしたところどうやら動き続けているのでこれでとりあえず放置。

あと、mem::uninitialized()が非推奨になっていた。

実践Rust入門[言語仕様から開発手法まで]

実践Rust入門[言語仕様から開発手法まで]