Wed 03/09, 2011

JM Badge Board (2) [Electronics ]

JMBADGE昨日の調査結果を踏まえて、ちょっとした 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
こんな感じでセンサ値を繰り返し表示する。

スクリプト(jmabadge.pl)は下記の通り。
$ 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 で書けば良いだろう。
Posted by masato at 09:47 PM
このエントリーのトラックバックURL: http://bird.dip.jp/cgi-bin/mt/mt-tb.cgi/1796
コメントする

おそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。










名前、アドレスを登録しますか?