LoginSignup
12
0

More than 3 years have passed since last update.

「kentaro/mix_tasks_upload_hotswap」を試してみる! ご本人が参加していらっしゃるカレンダーにて

Last updated at Posted at 2020-12-11

この記事は、#NervesJP Advent Calendar 2020 12日目です。
前日は、 @mnishiguchi さんの「Elixir/Nervesでパルス幅変調 (PWM) Lチカ」でした。
こちらもお楽しみください。


はじめに

では、さっそくためしていきます :rocket::rocket::rocket:

$ git clone https://github.com/kentaro/mix_tasks_upload_hotswap.git
$ cd mix_tasks_upload_hotswap/example
$ export MIX_TARGET=rpi4
$ export MY_NETWORK_SSID=your_ssid
$ export MY_NETWORK_PSK=your_psk
$ mix deps.get
$ mix firmware
  • MIX_TARGETはお使いのハードウェアにあわせてください
    • 他に使用できるものは、Targetsをご参照ください
  • MY_NETWORK_SSIDMY_NETWORK_PSKはWi-FiでRaspberry Piを接続する場合に指定してください
    • 2.4GHz(G)と5GHz(A)が使える場合は、2.4GHz(G)の方を使っておいたほうが無難という噂があります
    • LANケーブルでネットワークに接続する場合は必要ありません
  • Firmwareがビルドできたら、開発用マシンにmicroSDカードを挿して
$ mix burn
  • :point_up::point_up_tone1::point_up_tone2::point_up_tone3::point_up_tone4::point_up_tone5: このコマンドで焼き込みます
  • こんがり焼き上がったmicroSDカードをRaspberry Pi 4にさして電源ON !!!

シナリオ1

REDAMEに書いてある通り、Example.hello/0のAtomをかえてみる(:world -> :"new world")

$ ssh nerves.local

iex(example@nerves.local)> Example.hello
:world
  • Example.hello/0の結果は:worldであることを確認したらソースコードを書き換えます
example/lib/example.ex
--- a/example/lib/example.ex
+++ b/example/lib/example.ex
@@ -13,7 +13,7 @@ defmodule Example do

   """
   def hello do
-    :world
+    :"new world"
   end
  • ふつうはここでmix firmware && mix uploadとやるわけですが、今回はそうではありません
  • 開発マシンから以下のコマンドを打ち込みます
$ mix upload.hotswap
  • mix firmware && mix uploadをやるのと比較するとほぼ一瞬でおわります
  • もう一度、Example.hello/0の結果を確認してみます
iex(example@nerves.local)> Example.hello
:"new world"
  • :world -> :"new world"に変わっている!
  • まじNervesアプリ書き換わっているよ! → 成功

シナリオ2

Awesomeモジュール追加(Awesome.hello/0)

  • これはさすがに対応していないんじゃないかな?
example/lib/awesome.ex
defmodule Awesome do
  def hello do
    "NervesはElixirのIoTでナウでヤングなcoolなすごいヤツです🚀 (https://twitter.com/torifukukaiou/status/1201266889990623233)"
  end
end
  • モジュールを追加したらおもむろに、開発マシンから
$ mix upload.hotswap

Successfully connected to example@nerves.local
Successfully deployed Elixir.Awesome to example@nerves.local
Successfully deployed Elixir.Example to example@nerves.local
Successfully deployed Elixir.Example.Application to example@nerves.local
Successfully deployed Elixir.Example.Counter to example@nerves.local
  • Elixir.Awesomeがdeployされた!?
  • Nervesで動作を確認してみましょう
iex(example@nerves.local)> Awesome.hello
"NervesはElixirのIoTでナウでヤングなcoolなすごいヤツです🚀 (https://twitter.com/torifukukaiou/status/1201266889990623233)"
  • これすげーよ、対応しちょるよ!

このHexどんな複雑なことをやっているのだろう?

シナリオ3

  • 今度こそこれはどうだろう?

Timexmix.exsに追加して、Timex.now/0を呼び出してみる

example/mix.exs
--- a/example/mix.exs
+++ b/example/mix.exs
@@ -52,7 +52,8 @@ defmodule Example.MixProject do
       {:nerves_system_x86_64, "~> 1.13", runtime: false, targets: :x86_64},

       # Local dependencies
-      {:mix_tasks_upload_hotswap, path: "../", only: :dev}
+      {:mix_tasks_upload_hotswap, path: "../", only: :dev},
+      {:timex, "~> 3.5"}
     ]
   end
example/lib/example.ex
@@ -19,4 +19,8 @@ defmodule Example do
   def increment do
     GenServer.call(Example.Counter, :increment)
   end
+
+  def now do
+    Timex.now()
+  end
 end
  • この状態で、mix upload.hotswapしてもTimexNervesアプリに入りません
    • この時点でmix upload.hotswapを実行してしまうと以下の変更をしても反映されないのでまだ待ってください
    • Timexなぞ知らぬといわれる のです
    • これはさすがにだめか
    • けれど歌うアルケミストと呼ばれる、自称アルケミストのはしくれ、名乗るほどのものでもないが、解決しろと血がさわぐ
  • 以下の変更をすると、(本当に)とりあえずイゴきました ザマス
lib/mix/tasks/mix/tasks/upload/hotswap.ex
-    {:ok, modules} = :application.get_key(app_name, :modules)
+    # {:ok, modules} = :application.get_key(app_name, :modules)
+    IO.puts :awesome
+    modules = :code.all_loaded() |> Enum.map(&elem(&1, 0))

     for module <- modules do
       for node <- nodes do
@@ -57,6 +59,10 @@ defmodule Mix.Tasks.Upload.Hotswap do
     IO.puts("Successfully deployed #{module} to #{node}")
   end

  defp handle_load_module({:ok, [{_, :loaded, _}]}, module, node) do
    IO.puts("Successfully deployed #{module} to #{node}")
  end

+  defp handle_load_module({:ok, [{_, hoge, fuga}]}, module, node) do
+    IO.puts("#{hoge} #{fuga} #{module} to #{node}")
+  end
  • :application.get_key(app_name, :modules)だと自分が追加したモジュール情報しか取れないようなので全部とっちゃえばいいのじゃなかろうか(そんな発想です)
  • :code.all_loadedなんて、なんのことだかさっぱりわからないけれど、天が教えてくれた(たぶん ↓↓↓)
$ mix upload.hotswap
  • すごくだーっと流れます
  • ヒヤヒヤします
  • スピード・スリル・サスペンス 飯塚オートです
  • 変数名、とりあえずhogeとかfugaです
  • 一応、(本当に一応)これ動きました!!!
  • mix firmware && mix burn よりは断然速いです!(体感)
iex(example@nerves.local)2> Example.now  
~U[2020-12-09 12:55:24.790199Z]

ただし

  • Timexは上の手順で入りましたが、HTTPoisonはうまく動きませんでした(依存ライブラリが完全に入り切らず足りない)
  • シナリオ3の私のホットフィックスはいろいろあやしいです
    • 気づいたことを披露しておきます
  • 上記の通りを一気にやるとTimex.now/0を呼び出せることは確認したのですが、なにか変更をさらに加えてmix upload.hotswapしたときのNervesアプリの動作がさらにあやしさ満点です
    • ssh nerves.localの接続が切れている
    • Example.now/0を呼び出したときにまたふたたびTimexなぞ知らぬと言われる:sob:
  • mix deps.getして、mix upload.hotswapをしたときにTimexおよびその依存モジュールがビルドされるのですがその最初のときだけ私のホットフィックスでTimexNervesアプリに入るようです
iex(example@nerves.local)2> Example.now  
** (UndefinedFunctionError) function Timex.now/0 is undefined (module Timex is not available)
    Timex.now()

シナリオ4

  • パソコン側でiex -S mix
$ iex -S mix
Erlang/OTP 23 [erts-11.0.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]


iex> :application.get_key(:example, :modules)
{:ok, [Example, Example.Application, Example.Counter]}

Wrapping Up :lgtm::santa::santa_tone1::santa_tone2::santa_tone3::santa_tone4::santa_tone5::lgtm:

  • kentaro/mix_tasks_upload_hotswapは、とにかくすごい! :rocket::rocket::rocket:
  • mix deps.getするようなときは一回mix firmware && mix uploadをしてmicroSDカードを落ち着けてから、自分の追加モジュールをイジイジしてmix upload.hotswapで効率よく開発して、コードが固まったらまたそこでmix firmware && mix uploadするというような使い方でだいぶ開発効率はあがるようにおもいます
  • さっそく私のごった煮プロジェクトTORIFUKUKaiou/hello_nervesには追加していきたいとおもいます
    • ついでにNervesのバージョンあげよう! とおもぉう〜 :microphone:
    • Pelemay
    • CpuInfo
    • もいれておこう!
    • (まだできてはいない :relaxed:)
  • Enjoy Elixir !!! :rocket::rocket::rocket::rocket::rocket::rocket::rocket::rocket::rocket:

明日は@kentaro さんご本人がkentaro/mix_tasks_upload_hotswapを語ってくださいます。「mix upload.hotswap (kentaro/mix_tasks_upload_hotswap)の裏側」もぜひお楽しみください。
I can’t wait until tomorrow.

mix upload.hotswap (kentaro/mix_tasks_upload_hotswap)の裏側

:point_up::point_up_tone1::point_up_tone2::point_up_tone3::point_up_tone4::point_up_tone5:

12
0
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
0