たくさんの自由帳

どうもこんばんわ。
ハジラブ -Making*Lovers- 攻略しました。
桜子ちゃんが可愛かったです。無印版もやりたいと思います。
Imgur  

あと別にこのゲームに限った話じゃないけど他のヒロイン攻略するのしんどくなるやつわかる人いますかね?

Imgur

好きな娘からやればいいと思いますがおすすめは初穂さんを最後にやるといいかも?

本題

なんかBLU出来るらしいから買ったXiaomi Mi 11 Lite 5G、この子Mi Remoteっていうプリインアプリで赤外線を送信して家電操作ができるんですね。
でもこのアプリ、シーリングライトが何故か用意されてません。

赤外線通信、懐かしい響きなんですかね?。スマホ世代だからわからん
(iモード?、着せ替えツール?、フルブラウザ?、ネットワーク暗証番号?、センター問い合わせ?、富士通のプライバシーモード?、パケ・ホーダイ?)

MIUI初体験

なんかUSBデバッグとは別にUSB経由のアプリインストールの設定があって、これSIMカード刺さないとONに出来ないので注意。

赤外線送信するためには

  • 赤外線送信ができて、ConsumerIrManager#hasIrEmitter()trueを返す端末
    • 今回はXiaomi Mi 11 Lite 5Gを利用。33W充電めっちゃ早くて怖いまである。
  • 赤外線のパターンを取得出来る環境
    • 今回はラズパイと赤外線受信モジュールで取得
    • Nature Remo(エアコンや照明を外出先からONに出来るやつ)を持っている場合はいらないかもしれない
      • 後述。なお私は持っていない。誰か確かめてみてくれ。

環境

なまえあたい
端末Xiaomi Mi 11 Lite 5G
言語Kotlin
UIJetpack Compose
Raspberry Pi2 Model B
赤外線受信モジュールOSRB38C9AA (秋月で買えた)

UI作るのだるいので、Jetpack Composeを使います。

赤外線のパターン取得編

今回はNECのシーリングライトの赤外線パターンを取得したいと思います。NECって昔ゲーム作ってたってマジ?
Raspberry Piと赤外線受信モジュールをGPIOで接続して取得するんですが、残念ながらこの辺は詳しくないので先人に乗っかります。この辺詳しくなくても出来るので先人GJ

どんなデータ?

こんな感じの配列。本当はもっと長い。

[
    8925, 4540, 514, 626, 514,
]

ラズパイとか持ってないよ

赤外線のパターンが手に入ればいいので、Nature Remoをお持ちの方は、Nature Remo 赤外線データとかで調べるとそれっぽいパターンを取得できるそうですよ(そもそも持ってたらこんな事する必要すらないけどな)

Raspberry Pi に 赤外線受信モジュール を接続する

先人に乗っかります。ラズパイのセットアップは各自。ディスプレイつないで初期設定終わらせておいてね。

https://qiita.com/takjg/items/e6b8af53421be54b62c9#%E8%B5%A4%E5%A4%96%E7%B7%9A%E3%82%92%E5%8F%97%E4%BF%A1%E3%81%99%E3%82%8B%E5%9B%9E%E8%B7%AF

受光部を正面にした場合、右から「3.3V」「グラウンド」「データ」線をつなぎます。

+-+
|●|
+-+
|||

321
3. データ線     GPIO 18 (ピン番号12)
2. グラウンド   ピン番号 9 (GNDならどこでもおk)
1. 3.3V        ピン番号 1 (3.3Vならどこでもおk)

以下結線例です。

Imgur

Raspberry PiにSSH接続する

SSH接続ってのはラズパイにあるターミナル(Windowsでいうコマンドプロンプト)を他PCから操作するときに使うやつです。リモートデスクトップでコマンドプロンプト操作してるみたいな感じだと思う。

Raspberry Piにリモートで入ります。別にラズパイにつないだディスプレイとキーボードで操作してもいいんだけど、赤外線のパターンを母艦(開発環境があるPC)にコピーするのが面倒なのでリモートで入ります。
ところで母艦って死語?

なんか最近はディスプレイなしでもファイル作ってラズパイと有線LANで繋げば初回起動からSSHに入れるそうですね?

SSHの有効化は省略させてもらいます。ごめんね。TeraTermPowerShellのsshでラズパイのターミナル画面が出るところまで用意しておいてください。

Wi-Fiの場合もLANの場合もmDNS?のおかげでホストの欄にpi@raspberrypi.localって入れれば接続できます。固定IPにしていない場合でもわざわざ調べに行かなくていいのでとても便利。

ちなみに以下の画像は関係ないです。

Imgur

赤外線パターンを手に入れる

必要なパッケージをラズパイへインストール

黒い画面に入れていきます

sudo apt install pigpio python3-pigpio
sudo systemctl enable pigpiod.service
sudo systemctl start pigpiod

GPIOの設定

赤外線モジュールのデータ線をGPIO 18に繋いだのでその旨を教えてあげます。

echo 'm 18 r    pud 18 u' > /dev/pigpio

赤外線パターン入手プログラムをダウンロード

curl http://abyz.me.uk/rpi/pigpio/code/irrp_py.zip | zcat > irrp.py

赤外線パターンを取得

先程ダウンロードしたプログラムを実行すると赤外線パターンを入手出来ます。
以下のコマンドを実行した後、リモコンを赤外線受信モジュールへ向けてボタンを押します。

python3 irrp.py -r -g18 -f codes light_on --no-confirm --post 130

成功するとOkeyまで出ます。

Recording
Press key for 'light_on'
Okay

赤外線パターンはcodesというファイルに保存されます。

赤外線パターンを見る

以下のコマンドを打ち込むと赤外線パターンを記載したファイルを見ることが出来ます。

cat codes

Imgur

[から]で囲われてる数値を控えておきます。
画像の例では8953から]の前まで。以下例

8953, 4544, 463, 730, 463, 1730, 463, 1730, 463, 586, 549, 586, 549, 586, 463, 586, 463, 586, 463, 1730, 463, 1730, 549, 586, 463, 586, 463, 586, 549, 1730, 463, 730, 463, 1730, 549, 586, 463, 586, 463, 730, 463, 586, 463, 1730, 549, 1730, 463, 1730, 463, 586, 549, 586, 463, 586, 463, 586, 463, 586, 463, 730, 463, 1730, 463, 1730, 463, 1730, 463, 41143, 8953, 2224, 463

赤外線パターンの中身知りたい方はNECフォーマットだけですが適当にまとめたのでどうぞ:赤外線のNECフォーマットまとめ?
別に見なくても分からなくても作れます。

Xiaomi Mi 11 Lite 5G で送信

テスト用アプリ用意しておきました。

赤外線のパターンを入れて送信できるか試せるアプリです。

Imgur

ソースコード:https://github.com/takusan23/IrSenDroid

APKダウンロード:https://github.com/takusan23/IrSenDroid/releases/tag/1.0

AndroidManifest

適当にComposeプロジェクトを作成します。
できたら、赤外線を使うので権限をManifestに書き足します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="io.github.takusan23.irsendroid">

    <uses-permission android:name="android.permission.TRANSMIT_IR"/>

送信用関数の用意

IrSendTool.ktを作成して、以下をコピペ

LIGHT_OFF_DATALIGHT_ON_DATAの配列は各自取得したパターンを入れてください。

object IrSendTool {

    /** NECのシーリングライトの 消灯ボタン を押したときに送信される赤外線のパターン */
    val LIGHT_OFF_DATA = listOf(
        8925, 4540, 514, 626, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 626, 514
    )

    /** NECのシーリングライトの 全灯ボタン を押したときに送信される赤外線のパターン */
    val LIGHT_ON_DATA = listOf(
        8925, 4540, 514, 626, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 1730, 514, 626, 514, 1730, 514, 1730, 514, 626, 514, 626, 514, 626, 514, 626, 514, 626, 514, 1730, 514, 626, 514
    )

    /**
     * 赤外線送信
     * @param context Context
     * @param pattern 赤外線パターン
     * */
    fun sendIr(context: Context, pattern: List<Int>) {
        val consumerIrManager = context.getSystemService(Context.CONSUMER_IR_SERVICE) as ConsumerIrManager
        // 赤外線利用可能かどうか
        if (consumerIrManager.hasIrEmitter()) {
            // 利用可能なら送信
            consumerIrManager.transmit(38_000, pattern.toIntArray())
        }
    }

}

使うときはこんな風に

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        IrSendTool.sendIr(this, IrSendTool.LIGHT_ON_DATA)

    }
}

ComposeでちゃちゃっとUIを作る

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            IrSenDroidTheme {
                Surface(color = MaterialTheme.colors.background) {
                    HomeScreen()
                }
            }
        }
    }
}

@Preview(backgroundColor = 0xFFFFFF, showBackground = true)
@Composable
fun HomeScreenPrev() {
    HomeScreen()
}

@Composable
fun HomeScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        RoomLightOnButton()
        RoomLightOffButton()
    }
}

@Composable
fun RoomLightOnButton() {
    val context = LocalContext.current

    Button(
        modifier = Modifier.padding(10.dp),
        onClick = { IrSendTool.sendIr(context, IrSendTool.LIGHT_ON_DATA) }
    ) {
        Text(text = "照明ON")
    }
}

@Composable
fun RoomLightOffButton() {
    val context = LocalContext.current

    Button(
        modifier = Modifier.padding(10.dp),
        onClick = { IrSendTool.sendIr(context, IrSendTool.LIGHT_OFF_DATA) }
    ) {
        Text(text = "照明OFF")
    }
}

これでXiaomi Mi 11 Lite 5Gがあればシーリングライト操作し放題です。やったね。

終わりに

赤外線送信付いてるのおもろいな。
休日終わるの早すぎな~~~