昨日の調査結果を踏まえて、ちょっとした Perl スクリプトを書いてみた。usbhidctl の出力を受け取って解釈し、センサ値を表示する。
$ usbhidctl -f /dev/uhid0 -la | perl jmbadge.pl
3D Accelerometer: X:-0.023, Y:-0.235, Z:-1.108
Ambient Light Sensor: 1888.968
Touch Sensor(L): 0 0 0 0
Touch Sensor(R): 0 0 0 0
こんな感じでセンサ値を繰り返し表示する。$ cat jmbadge.pl
#!/usr/pkg/bin/perl
# jmbadge.pl - show sensor values
# 2011.03.09
# masato at bird.email.ne.jp
use strict;
use Parse::Binary::FixedFormat;
use Data::Dumper;
local $Data::Dumper::Tarse = 1;
local $Data::Dumper::Indent = 1;
local $Data::Dumper::Sortkeys = 1;
#
use constant REPORT_LENGTH => 64;
use constant COMMON_PART =>
qw(
DEVICE_ID:C1
SENSOR_ID:C1
COMMAND_OR_INDEX:C1
STATUS:C1
GUID:C:16
PROP_VARIANT:L1
);
use constant COMMON_PART_LENGTH => 24;
my $tar = new Parse::Binary::FixedFormat [ COMMON_PART ];
my $stop = 0;
#
$SIG{ INT } = sub { $stop = 1 };
main();
exit 0;
#
sub clear {
print "\e[2J";
}
sub print_at {
my ($x,$y,$s) = @_;
print "\e[${y};${x}H",$s,"\n";
}
sub parse {
my $d = shift;
my $hr = $tar->unformat($d);
# check SENSOR_ID only. ignore GUID
if ($hr->{'SENSOR_ID'} == 1) {
# 3D Accelerometer
my @a = unpack("fff", substr($d, COMMON_PART_LENGTH));
$hr->{'XYZ'} = \@a;
} elsif ($hr->{'SENSOR_ID'} == 2) {
# Ambient Light Sensor
($hr->{'LIGHT'}) = unpack("f", substr($d, COMMON_PART_LENGTH));
} elsif (($hr->{'SENSOR_ID'} == 3) or ($hr->{'SENSOR_ID'} == 4)) {
# Touch sensor
my $d = unpack("c", substr($d, COMMON_PART_LENGTH));
my @a;
for (0..3) {
push(@a, $d & 0x01);
$d >>= 1;
}
if ($hr->{'SENSOR_ID'} == 3) {
$hr->{'LPAD'} = \@a;
} else {
$hr->{'RPAD'} = \@a;
}
} else {
# unkown sensor
}
return $hr;
}
sub disp {
my $hr = shift;
# print Dumper $hr;
if ($hr->{'SENSOR_ID'} == 1) {
print_at(2, 1, sprintf(" 3D Accelerometer: X:%6.3f, Y:%6.3f, Z:%6.3f", @{$hr->{'XYZ'}}));
} elsif ($hr->{'SENSOR_ID'} == 2) {
print_at(2, 2, sprintf("Ambient Light Sensor: %6.3f", $hr->{'LIGHT'}));
} elsif ($hr->{'SENSOR_ID'} == 3) {
print_at(2, 3, sprintf(" Touch Sensor(L): %d %d %d %d", @{$hr->{'LPAD'}}));
} elsif ($hr->{'SENSOR_ID'} == 4) {
print_at(2, 4, sprintf(" Touch Sensor(R): %d %d %d %d", @{$hr->{'RPAD'}}));
} else {
print_at(2, 5, "unknown sensor_id:". $hr->{'SENSOR_ID'});
}
}
sub main {
my $i = 0;
my $buf = '';
clear();
while (<STDIN>) {
chomp;
my $s = $_;
if (length($s)) {
$buf .= chr(int($1)) if $s =~ /^0x0001\.Counted_Buffer=(\d+)$/;
# $buf .= chr(int($1)) if $s =~ /=(\d+)$/; # これでも十分
} else {
if (length($buf) == REPORT_LENGTH) {
my $hr = parse($buf);
disp($hr);
}
$i = 0;
$buf = '';
}
last if $stop;
}
print_at(1, 6, "end");
}
1;
# EOF
$
加速度は数値表示にしているが、バーグラフ的な表示も簡単にできる。Perl/Tk などでの GUI 表示も試してみようか。処理速度を求めるなら、usbhidctl のコードをベースに C で書けば良いだろう。
おそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。