4. 黒豆, IRKit, KURO-RS によるリモコン信号の解析

黒豆や IRKit, KURO-RS, クロッサム2+ などのプログラマブルな学習リモコン (スマートリモコン) の信号データを、リモコン同士ツノつき合わせて学習させるのではなく、PC 上で理想的な波形に合成するためのノウハウです。

  1. 赤外線リモコンの信号定義データの合成 [表紙]
  2. 家製協フォーマットの信号データ合成
  3. NEC フォーマットの信号データ合成
  4. ソニーフォーマットの信号データ合成
  5. 黒豆, IRKit, KURO-RS によるリモコン信号の解析 (このページ)
  6. 機器付属リモコンのコード

このページでは、IRKit や KURO-RS を利用して簡便に機器付属のリモコン信号を解析するサンプルコードを紹介します。

4.1. 黒豆によるリモコンコードの解析

黒豆で「学習」した16進数列形式のデータから、リモコン信号のフォーマット (家製協/NEC/ソニー) を判別し、デコードするための perl スクリプトです。アドホックな作りですが、そこそこの精度で解析できています。

  • 入力は、1行に16進数列データ一つの形式のテキストファイル。読めない行は黙って捨てる。
  • 出力は、各データを解析した結果が標準出力に書き出される。

サンプルコード

#! /usr/bin/perl

while (<>) {
    # 信号フォーマット/コードの解析
    chop;
    next if (length ($_) < 16);
    next if (/[^0-9a-fA-F]/);
    @run = ($_ =~ /(..)/g);
    @run = @run[4..$#run];                      # ヘッダ4バイト捨てる
    @run = map { hex ($_); } @run;

    @run1 = ();
    while (@run > 0) {                          # マルチバイトの処理
        if ($run[0] == 0) {
            push (@run1, $run[1] * 256 + $run[2]);
            shift (@run); shift (@run); shift (@run);
        } else {
            push (@run1, shift (@run));
        }
    }
    @run = map { $_ * 1000.0 * 269 / 8192; } @run1;     # μsec単位に揃える

    print &analyze (@run), "\n";
}

sub analyze {
    my (@run) = @_;
    my ($code) = "";

    # -- ヘッダ部の「1」の長さでフォーマット判別
    if ($run[0] <= 2600) {              # ソニーフォーマット (仕様上は2400μsec)
        shift (@run); shift (@run);
        $t = 600;
        while (@run) {
            $d1 = int (shift (@run) / $t + 0.25);
            $d0 = int (shift (@run) / $t + 0.25);
            $code .= ($d1 == 1) ? "0" : "1";
            last if ($d0 > 1);
        }
        $len = length ($code);
        goto unknown if ($len != 12 && $len != 15 && $len != 20);
        ($cmd, $id) = ($code =~ /(.{7})(.*)/);
        $result = sprintf ("sony(%d): %x %02x", $len, unpack ("SS", pack ("b16b16", $id, $cmd)));

    } elsif ($run[0] <= 4800) {         # 家製協フォーマット (仕様上は2800~4000μsec)
        shift (@run); shift (@run);
        $t = 425.0;
        while (@run) {
            $d1 = int (shift (@run) / $t + 0.25);
            $d0 = int (shift (@run) / $t + 0.25);
            last if ($d0 >= 10);
            $code .= ($d0 == 1) ? "0" : "1";
        }
        $len = length ($code);
        goto unknown if ($len % 8 != 0);
        $result = sprintf ("aeha(%d): ", $len / 8);
        $result .= join (" ", unpack ("H2"x ($len / 8), pack ("b$len", $code)));

    } elsif ($run[0] <= 15000) {        # NECフォーマット (仕様上は9000μsec)
        shift (@run); shift (@run);
        $t = 9000 / 16;
        while (@run) {
            $d1 = int (shift (@run) / $t + 0.25);
            $d0 = int (shift (@run) / $t + 0.25);
            last if ($d0 > 5);
            $code .= ($d0 == 1) ? "0" : "1";
        }
        $len = length ($code);
        goto unknown if ($len != 32);
        $result = sprintf ("nec(%d): ", $len);
        $result .= join (" ", unpack ("H2"x 4, pack ("b32", $code)));

    } else {                            # 未知フォーマット
      unknown:
        $result = "unknown";
    }

    return $result;
}

4.2. IRKit によるリモコンコードの解析

IRKit で「学習」した JSON 形式のデータを解析する場合は、黒豆のサンプルコードの入力ファイル読み込み部分を以下のように書き換えれば、解析ロジック部分はそのまま利用できる。

#! /usr/bin/perl

while (<>) {
    # 信号フォーマット/コードの解析
    next unless /"data":\[(.*?)\]/;
    @run = split (",", $1);
    $raw = join (" ", @run);
    @run = map { $_ /= 2; } @run;       # μsec単位に揃える

    print &analyze (@run), "\n";
}

4.3. KURO-RS によるリモコンコードの解析

KURO-RS で「学習」した1920ビットのバイナリデータを解析する場合は、黒豆のサンプルコードの入力ファイル読み込み部分を以下のように書き換えれば、解析ロジック部分はそのまま利用できる。

#! /usr/bin/perl

while (<>) {
    # 信号フォーマット/コードの解析
    chop;
    $data = pack ("H*", $_);
    $data = unpack ("b1920", $data);
    @run = map (length, $data =~ /(0+|1+)/g);
    @run = map { $_ *= 100; } @run;     # μsec単位に揃える

    print &analyze (@run), "\n";
}