Raspi3B+とLIRCでリモコン学習（irrecord）に困った話

`irrecord` でリモコンのボタンを学習させたけれども「`-f`」が必要で、
リピートも認識されなかったのでその対処をメモメモ。

## 結論
`irrecord -n -f -d /dev/lirc0` したら、
**自分でビット変換**すれば正しく認識させることができる。（難しくない！）

## 登場人物
- Raspberry Pi3 B+ with Raspbian stretch
- 赤外線受信器 VS1838B
- リモコン（出自不明）
- LIRC 0.9.4c-9

## サマリー
1. Raspbian セットアップ（ディスプレイ不要！）
2. 赤外線受信器 VS1838B 接続
3. LIRC インストール ～ 基本設定
4. 受信テスト
5. 受信内容学習（生データ版）
6. **自分でビット変換**
7. `irexec` でコマンド実行（おまけ）

## 1. Raspbian セットアップ（ディスプレイ不要！）
(1) [Raspbian stretch ダウンロード](https://www.raspberrypi.org/downloads/raspbian/)
(2) 7zip か何かで解凍した img ファイルをフォーマット済みの SD カードへ書き込み
(3) SD カードのルートに空ファイル「ssh」作成
(4) 同じ階層に「wpa_supplicant.conf」作成

```shell:wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
country=JP
network={
	ssid="YOUR_SSID"
	psk="YOUR_PASSWORD"
	key_mgmt=WPA-PSK
	proto=WPA WPA2
	pairwise=CCMP TKIP
	group=CCMP TKIP WEP104 WEP40
}
```
(5) SD カード挿入して電源入れて ssh で接続（ Wi-Fi ルータの DHCP 払出状態から IP/MAC を確認できる）
(6) `sudo raspi-config` で「7 Advanced Options」の「A1 Expand Filesystem」からファイルシステム拡張
(7) 再起動して `sudo apt-get update` で準備OK！

## 2. 赤外線受信器 VS1838B 接続
(1) 正面（丸い方）向かって右の足を 3.3V へ、真ん中の足を GND へ、左の足を GPIO18 へ！

## 3. LIRC インストール ～ 基本設定
(1) `sudo apt-get install lirc`
(2) `sudo vi /boot/config.txt`

```ini:/boot/config.txt
# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi:gpio_out_pin=17,gpio_in_pin=18,gpio_in_pull=up,invert=on
```
(3) `sudo vi /etc/lirc/lirc_options.conf`

```ini:/etc/lirc/lirc_options.conf
[lircd]
nodaemon        = False
driver          = default
device          = /dev/lirc0
```
(4) 再起動して `sudo systemctl restart lircd.service` 後に以下のようになることを確認して完了

```console:console
pi@raspberrypi:~ $ sudo ls -la /dev/lirc*
crw-rw---- 1 root video 243, 0 Jan 1 12:34 /dev/lirc0

pi@raspberrypi:~ $ sudo lsmod | grep lirc*
lirc_rpi               16384  2
lirc_dev               16384  1 lirc_rpi

pi@raspberrypi:~ $ sudo dmesg | grep lirc
[    4.047087] lirc_dev: IR Remote Control driver registered, major 243
[    4.092308] lirc_rpi: module is from the staging directory, the quality is unknown, you have been warned.
[    5.171567] lirc_rpi: auto-detected active low receiver on GPIO pin 18
[    5.171856] lirc_rpi lirc_rpi: lirc_dev: driver lirc_rpi registered at minor = 0
[    5.171863] lirc_rpi: driver registered!
[   10.628930] input: lircd-uinput as /devices/virtual/input/input0
```
## 4. 受信テスト
(1) `sudo mode2 --driver default --device /dev/lirc0` を実行してリモコンのボタンを押すと・・・

```console:console
pi@raspberrypi:~ $ sudo mode2 --driver default --device /dev/lirc0
Using driver default on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
Running as regular user pi　←　ここでボタンを押す！
space 16777215
pulse 9366
space 4648
pulse 511
space 648
pulse 521
space 647
pulse 478
space 675
pulse 510
space 647
pulse 484
...
```
(2) `sudo hexdump /dev/lirc0` を実行してリモコンのボタンを押すと・・・

```console:console
pi@raspberrypi:~ $ sudo hexdump /dev/lirc0
0000000 ffff 00ff 245a 0100 11cd 0000 0258 0100
0000010 022d 0000 0256 0100 0245 0000 023e 0100
0000020 0230 0000 023d 0100 025d 0000 0240 0100
0000030 0243 0000 0241 0100 022e 0000 0255 0100
0000040 0245 0000 023d 0100 0246 0000 023c 0100
0000050 0691 0000 0256 0100 068d 0000 0255 0100
0000060 0690 0000 0254 0100 06a5 0000 023f 0100
0000070 06a4 0000 023f 0100 06a4 0000 023f 0100
0000080 06a5 0000 023d 0100 068f 0000 0256 0100
0000090 0244 0000 0243 0100 068a 0000 0254 0100
00000a0 0699 0000 0249 0100 0231 0000 0252 0100
00000b0 068f 0000 0259 0100 022b 0000 0255 0100
00000c0 0245 0000 021d 0100 0266 0000 023c 0100
00000d0 06b5 0000 022d 0100 0232 0000 0250 0100
00000e0 024a 0000 0248 0100 0685 0000 0253 0100
00000f0 0231 0000 0254 0100 06a6 0000 023a 0100
0000100 0691 0000 0250 0100 06a9 0000 0239 0100
```
## 5. 受信内容学習（生データ版）
(1) `irrecord -n -f -d /dev/lirc0` で受信内容学習（カレントに「リモコン名.lircd.conf」ができる）

```shell:./リモコン名.lircd.conf
begin remote

  name  リモコン名
  flags RAW_CODES|CONST_LENGTH
  eps            30
  aeps          100

  gap          109377

      begin raw_codes

          name KEY_1
             9226    4584     570     608     545     586
              568     607     601     529     570     607
              546     586     567     607     547     606
              547    1705     569    1705     569    1727
              547    1727     547    1727     546    1705
              569    1704     570    1727     547    1705
              578    1718     546    1706     569     607
              546     583     571     607     548     582
              570     582     571     607     546     607
              546     608     547    1729     545    1727
              547    1704     572    1701     570    1704
              569
```
(2) `sudo cp リモコン名.lircd.conf /etc/lirc/lircd.conf.d/` で学習させた設定ファイルを設定フォルダへ
(3) `sudo systemctl restart lircd.service` で設定ファイル反映
(4) `irw` で受信確認・・・できるけど押しっぱなしにしても反応しないし、設定ファイル汚いし。。。

```shell:irw
pi@raspberrypi:~ $ irw
0000000000000001 00 KEY_1 リモコン名
0000000000000001 00 KEY_1 リモコン名
0000000000000001 00 KEY_1 リモコン名
0000000000000001 00 KEY_1 リモコン名
...
```

## 6. **自分でビット変換**（やっと本題）
(1) `irrecord -n -d /dev/lirc0` で「`-f`」無し（動作しない）を見てみる

★印を読み解くと、**生データを 0 と 1 に置き換えられそうだ**ということが分かった！
⇒ 先頭の「9262 4575」あたりは固定、以降は「565 1709」あたりなら 1 、
　「565 591」あたりなら 0 、末尾は「568」あたりで固定。

```shell:./リモコン名.lircd.conf
begin remote

  name  リモコン名
  bits           32　　　　　　　　★生データは 0 と 1 が 32個 のはず
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9262  4575        ★生データの先頭には「9226 4584」あたりが毎回あった（平均値？）
  one           565  1709        ★生データには「547 1727」あたりの組み合わせがあった（平均値？）
  zero          565   591        ★生データには「548 582」あたりの組み合わせがあった（平均値？）
  ptrail        568              ★生データの末尾には「569」あたりが毎回あった（平均値？）
  repeat       9259  2283        ★受信テストで押しっぱなしにするとこのあたりが毎回あった（平均値？）
  gap          109533
  toggle_bit_mask 0x0
  frequency    38000

      begin codes
          KEY_1      0x00FFE01F 0x7EEE6DBC  ★仮説：「0x00FF」は決め事、「0x7EEE6DBC」は余分！
          ...
      end codes

end remote
```

(2) このルールで「5. 受信内容学習（生データ版）」のデータを変換
![raw_data.png](https://qiita-image-store.s3.amazonaws.com/0/64591/6ffab34b-db0f-f684-1c7b-8c6206b1db03.png)
**0000000011111111 1110000000011111　32bit！
＝ 0x00FF 0xE01F ⇒ 仮説のとおりの結果となった！**

(3) ググった成功例では 「[pre_data_bits と pre_data](http://www.lirc.org/html/lircd.conf.html)」 が使われている！
⇒ 最初の 16bits （0x00FF）を固定として、データ本体は 16bits とした。

(4) **完成版「リモコン名.lircd.conf」！**

```shell:./リモコン名.lircd.conf
begin remote

  name  リモコン名
  bits           16
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9262  4575
  one           565  1709
  zero          565   591
  ptrail        568
  repeat       9259  2283
  pre_data_bits  16
  pre_data     0xFF
  gap          109533
  toggle_bit_mask 0x0
  frequency    38000

      begin codes
          KEY_1      0xE01F
          ...
      end codes

end remote
```
(5) `sudo cp リモコン名.lircd.conf /etc/lirc/lircd.conf.d/` で学習させた設定ファイルを設定フォルダへ
(6) `sudo systemctl restart lircd.service` で設定ファイル反映
(7) `irw` で受信確認・・・押しっぱなしがきちんと認識されている！！！

```shell:irw
pi@raspberrypi:~ $ irw
0000000000ffe01f 00 KEY_1 リモコン名 ← 押す
0000000000ffe01f 01 KEY_1 リモコン名
0000000000ffe01f 02 KEY_1 リモコン名
0000000000ffe01f 03 KEY_1 リモコン名 ← 離す
0000000000ffe01f 00 KEY_1 リモコン名 ← 押す
0000000000ffe01f 01 KEY_1 リモコン名
0000000000ffe01f 02 KEY_1 リモコン名
...
```
## 7. `irexec` でコマンド実行（おまけ）
(1) `sudo vi /etc/lirc/irexec.lircrc` でボタン押下時のコマンドを指定（ここでは `date +%S.%3N` ）

```shell:/etc/lirc/irexec.lircrc

begin
    remote = リモコン名
    prog   = irexec
    button = KEY_1
    config = date +%S.%3N
    repeat = 1
end
```
(2) `sudo systemctl restart lircd.service` / `sudo systemctl restart irexec.service` で設定反映
(3) `sudo  ps -ef | grep irexec` で `irexec` 起動確認、無ければ再起動

```console:console
pi@raspberrypi:~ $ sudo  ps -ef | grep irexec
root      4253     1  0 01:23 ?        00:00:00 /usr/bin/irexec /etc/lirc/irexec.lircrc
pi        4260   818  0 12:34 pts/0    00:00:00 grep --color=auto irexec    ⇒これは今打ったコマンドね。
```
(4) `sudo journalctl -u irexec.service -f` でコマンド実行結果の確認

```console:console
pi@raspberrypi:~ $ sudo journalctl -u irexec.service -f
-- Logs begin at Sun 2018-01-01 01:23:45 JST. --
Jan 01 01:23:45 raspberrypi systemd[1]: Started Handle events from IR remotes decoded by lircd(8).
Jan 01 12:34:03 raspberrypi irexec[4339]: 03.547
Jan 01 12:34:03 raspberrypi irexec[4339]: 03.686
Jan 01 12:34:05 raspberrypi irexec[4339]: 05.055
Jan 01 12:34:05 raspberrypi irexec[4339]: 05.194
Jan 01 12:34:06 raspberrypi irexec[4339]: 06.182
Jan 01 12:34:06 raspberrypi irexec[4339]: 06.291
Jan 01 12:34:06 raspberrypi irexec[4339]: 06.400
Jan 01 12:34:06 raspberrypi irexec[4339]: 06.510
Jan 01 12:34:06 raspberrypi irexec[4339]: 06.619
```

おつかれさまでした！