組み込み屋も楽がしたい 〜Github Actionsに恋して〜

## はじめに
　どうも。都内で一人細々とソフト開発業を経営しているZETABLACKと申します。名前から分かる通り、Zガンダムが好きです。特に量産したくてもできなかったZプラスにときめいております。地味なグレーで性能も中途半端。そこに痺れる憧れるぅ。

## ハードウェア屋から見た開発環境のもどかしさ
　まあ、ESP32に代表されるマイコンを使ったガジェットを作ったり、Pythonのコードを書いたりして貴重な人生の時間を消費しているわけです。
　PythonとかWebで使用される言語だと色々ありますよね、GithubにプッシュしたらGithub Actionsでテストが勝手に走って、パスしたらmainブランチにマージされてECSにデプロイされてエレガントに運用環境へ。何なら、コードすらClineのAIで書いてもらって。スカウト即デビューのようなシンデレラストーリー。
(※: 開発している方々がエレガントなメンタル状況だとは思っておりません。裏側にありがちな、無茶な要求に必死に応えるためのコーディング…。涙なしでは語れません。)

　これがESP32やArduinoとかの組み込みになると、途端に20世紀へ戻るわけですわ。
　基本ローカル環境での作業。ArduinoのプロジェクトをGithubに上げてレビューでOKもらっても、書き込みは実機でやらないとアカンわけです。これが手元にある実機だけだったらいいですが、LEDの点滅動作確認のためだけに会社へ行くのって無茶苦茶辛いんです。電車から見える空に語りかけたくもなるわけです。

「俺は、休日に何をしているんだろうか…。今日も、空が青いなあ…。」

 ウェブの恩恵を組み込みへ。AIの恩恵も組み込みへ。プロジェクトXには絶対に取り上げられないであろう格闘記録を、ここに記していきたいと思います。

## 教えて、偉い人
　ところで、Github Actionsから組み込み系の書き込みをできるようにするのはいいのですが、果たしてそんなことってできるのでしょうか。よくよく考えてみると、Github Actionsが動作する環境はインターネット上のここではない何処か。Githubへプッシュされたデータを、手元の何かにそのデータを持ってきて書き込み準備ぐらいはできるようにする必要があると思います。
「世の中の誰かが似たようなことをしているような気がする…。」
と思って調べてみたら、[ここ](https://www.techlife-hacking.com/?p=2892)と[ここ](https://qiita.com/BonyChops/items/a617e0f6129056de98f7)にありました。Github Actions self-hosted runnerというやつです。あと、[この情報](https://zenn.dev/komeko_step/articles/57bd1b52a8d234)も使えそうです。この世はデッカイ宝島ですな。
　要するに、Raspberry Piでも動くローカル用ランナーがあるのでそいつを使うということですな。知見を公開していただいた方、ありがとうございます。

## とりあえずパスワードを聞かれないようにする
　家に転がっているRaspberry Pi3を使おうかとも思いましたが、いい機会だと思ってRaspberry Pi5を買ってみました。USB Type-Cが付いてたり映像出力がmicro HDMIに変わってたりしたので、スターターキットを買って正解だった気がします。安くしようと最小限の物だけ買って、色々足らなくて動かないという経験が今まで何度もあったので、今回は素直にスターターキットを買いました。僕も大人になった…。

 マニュアルに従って、OSをインストール。まず最初に、sudoで実行した時にパスワードを聞かれないようにしました。順調に処理が進んでいると思っていたら、パスワード入力の画面で止まっていた経験ってありませんか? 僕はあります。

　とりあえずターミナルで
 ```
 sudo visudo
 ```

 を入力して、

 ```
 # Allow members of group sudo to execute any command
 # %sudo  ALL=(ALL:ALL) ALL
 %sudo  ALL=(ALL) NOPASSWD: ALL
 ```
 
という感じに修正すると、sudoで実行した際でもパスワードを聞かれなくなります。インターネットに直接晒されているわけではないので、とりあえず大丈夫…だと思います。怖い人多いよね、インターネットって。

## arduino-cliのインストール
　はい、これがないとarduinoに書き込めないです。以下のコマンドでインストールします。
 
 ```
 cd ~
 curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
 mv ./bin/arduino-cli /bin/arduino-cli
 ```

　インストールしたら、動作確認。
  ```
  pi@raspberrypi:~ $ arduino-cli
Arduino Command Line Interface (arduino-cli).

Usage:
  arduino-cli [command]

Examples:
  arduino-cli <command> [flags...]

Available Commands:
  board           Arduino board commands.
  burn-bootloader Upload the bootloader.
  cache           Arduino cache commands.
  compile         Compiles Arduino sketches.
  completion      Generates completion scripts
  config          Arduino configuration commands.
  core            Arduino core operations.
  daemon          Run the Arduino CLI as a gRPC daemon.
  debug           Debug Arduino sketches.
  help            Help about any command
  lib             Arduino commands about libraries.
  monitor         Open a communication port with a board.
  outdated        Lists cores and libraries that can be upgraded
  sketch          Arduino CLI sketch commands.
  update          Updates the index of cores and libraries
  upgrade         Upgrades installed cores and libraries.
  upload          Upload Arduino sketches.
  version         Shows version number of Arduino CLI.

Flags:
      --additional-urls strings   Comma-separated list of additional URLs for the Boards Manager.
      --config-dir string         Sets the default data directory (Arduino CLI will look for configuration file in this directory).
      --config-file string        The custom config file (if not specified the default will be used).
  -h, --help                      help for arduino-cli
      --json                      Print the output in JSON format.
      --log                       Print the logs on the standard output.
      --log-file string           Path to the file where logs will be written.
      --log-format string         The output format for the logs, can be: text, json (default "text")
      --log-level string          Messages with this level and above will be logged. Valid levels are: trace, debug, info, warn, error, fatal, panic (default "info")
      --no-color                  Disable colored output.

Use "arduino-cli [command] --help" for more information about a command.
```

インストールできてるっぽいですね。

　今回は **XIAO ESP32C3** というモジュールに書き込みを行うので、その下準備を行います。以下のコマンドでESP32C3用の諸々を入れます。

 ```
 arduino-cli core install esp32:esp32
 ```

　これで、ESP32C3への書き込み準備ができました。

## Github Actions self-hosted runner のインストール
　いきなり出てきました、Webな香りがするツールの筆頭、「Github Actions」。でも、「self-hosted runner」というのは今回初めて知りました。要するに、Github Actionsの実行環境を手元のPCに構成するやつのようです。Raspberry Pi5でも動作します。スゲエ。

　で、どうやって設定するのって話ですが…とりあえず、Raspberry Pi5側は
```
cd ~
```
でホームに移動しておきます。その後はGithubのページで「使用するリポジトリに移動」→「Setting」→「Actions」→「Runners」と移動して、「New self-hosted runner」というボタンを押すと、以下のような画面が出てきます。「Linux」「ARM64」を選択するとコマンドが表示されて、それをRaspberry Pi5上で打ち込むだけ。

 ![スクリーンショット_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636077/e9f7cfed-7964-4738-a1fd-835da8e2967c.png)

　いやあ、ほんとにこれだけしか書くことないんですわ、インストールに関しては。

## Github Actions self-hosted runnerに.envファイルを使用する方法
　Github Actionsとかでも.envファイルを使いたくなったりしますよね。なりますよね?
意外に迷ったので、誰かの助けになれば。

　まずはこんな感じの.envファイルを作ります。
  ```.env
  local_fqbn_model=esp32:esp32:XIAO_ESP32C3
  local_arduino_cli_port=/dev/ttyACM0
  local_firmware_input_dir=./build/esp32.esp32.XIAO_ESP32C3/
  ```

  **local_firmware_input_dir**ですが、arduino ideでバイナリデータをエクスポートするとこんな感じのディレクトリにバイナリファイル系が入ってきます。

  で、このファイルをアクションランナーのディレクトリに保存します。 **actions-runner/.env** のパスになります。最初、置き場所がよくわからなかった…。.envを保存したらようやく
  ```
  ./run.sh
  ```
  を実行させてRaspberry Pi5側は準備できました。
  
  ちなみに、こいつを修正するたびに**actions-runner/run.sh**を起動し直す必要があります。環境変数が反映されないなあと思ったら、run.shを再スタートさせると良いです。

## Github Actions用ランナー
　やっと来ましたアクションランナー。とりあえずシンプルに、ESP32C3に書き込む機能だけのアクションランナーを書いてみました。

 ```.github/workflows/self-hosted-runner.yml
 name: CI on the Self-Hosted Runner
 
 on:
   push:
     branches: [ "main" ]
    
 jobs:
   build:
     runs-on: [ self-hosted, Linux, ARM64 ]
     
   steps:
     - name: Checkout repository
       uses: actions/checkout@v3
       
     - name: Upload firmware
       run: |
         echo "Start"
         arduino-cli upload --fqbn ${local_fqbn_model} --port ${local_arduino_cli_port} --input-dir ${local_firmware_input_dir}
         echo "Finish"
 ```

　Raspberry Pi5にESP32C3を接続した状態で、上記のアクションランナーを含めてmainブランチにプッシュすると、 **./build/esp32.esp32.XIAO_ESP32C3/** に保存されたバイナリファイルがESP32C3に書き込まれます。arduino-cliって、HEXファイルじゃなくてもうまいこと書き込んでくれます。

## 終わりに
　Webを通して組み込み系ファームウェアをいじる情報って、あるようでなかなかない気がします。特に一貫したものは。今回はArduino IDEでサンプルコードを書いてみましたが、VSCodeでもArduino IDEと同じことはできるので可能性は広がると思っています。VSCodeって、やたらプラグインが多いし。

　というわけで、俺たちの戦いはこれからだ！