2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてね AtomVM(5) GenServer が AtomVM でもいごいた

2
Posted at

はじめに

直近の記事 はじめてね AtomVM(4) ESP32でLチカ v0.7.0-alpha.1 版 でアルファ版の AtomVM をインストールしてみました。
普段なら v0.7.1 になるぐらいじゃないと手を出さないのですが、今回は新しい機能を試してみたくて珍しく手を出しました。

気になる新しい機能

Releases v0.7.0-alpha.0Elixir improvements には Native GenServer and Supervisor support とあるじゃありませんか。これこれ。Elixir で楽しくプロセスごっこするにはこれが必要です。ということで今回は AtomVM での GenServer を試してみます。

なお AtomVM v0.7 系の新機能の詳細については Releases v0.7.0-alpha.0Releases v0.7.0-alpha.1Added 欄に書いてあります。

GenServer を用いたLチカ

デフォルトのサンプルプログラムでのLチカ Blinky は、単純なループで構成されています。これをタイマーをしかけて自分自身にメッセージを送る形のプログラムで構成してみます。

defmodule Blinky do
  @compile {:no_warn_undefined, [GPIO, :atomvm]}
  @gpio_pin 2 # for GPIO of ESP32

  use GenServer

  def start() do
    IO.puts("LED Blink starts")
    GenServer.start_link(__MODULE__, {@gpio_pin, :low})
    Process.sleep(:infinity)
  end

  def init({pin, level}) do
    GPIO.set_pin_mode(pin, :output)
    GPIO.digital_write(pin, level)
    set_interval(1000)
    IO.puts("GenServer init finished")
    {:ok, {pin, level}}
  end

  def handle_info(:toggle, {pin, :low}) do
    {:noreply, {pin, :high, 100}, {:continue, :toggle_common}}
  end
  
  def handle_info(:toggle, {pin, :high}) do
    {:noreply, {pin, :low, 700}, {:continue, :toggle_common}}
  end

  def handle_continue(:toggle_common, {pin, level, interval}) do
    GPIO.digital_write(pin, level)
    IO.puts("led level: #{level}")
    set_interval(interval)
    {:noreply, {pin, level}}
  end

  def set_interval(ms), do: Process.send_after(self(), :toggle, ms)
end

GenServer の状態の型が途中で変わる(handle_continue に渡すところだけ3要素のタプルで、ほかは2要素のタプル)という、ちょっと変則的な模範的でなさそうなプログラムを書いちゃいました。ま、いごいてます。

うまく行ってないこと

Lチカを出来るには出来ましたが、いくつかうまくいかなかったことや不便なことがあります。これ、書き方や使い方が悪いのか、そもそも出来ないのかがわからないものもあります。

不要な Warning メッセージが出る

上のプログラムで mix compile し、その後 mix atomvm.packbeam すると以下の Warning が出ます。

Warning: following modules or functions are not available on AtomVM:
* Elixir.GenServer:start_link/2
* Elixir.Supervisor:child_spec/2
* erlang:phash2/2

最初の Elixir.GenServer:start_link/2Elixir.GenServer:start_link/3 の第3引数を省略した形でプログラム中で使っています。実のところ使えているので、この Warning はよろしくないです。
あと Elixir.Supervisor:child_spec/2erlang:phash2/2 は明示的に使ってなくて、どっかで勝手に呼ばれてるのかなと思ったりもしますが、心当たりがないので困ります。

Logger はいごかない

require Logger を使ってもコンパイルはできます。が Logger.info/1 とかの関数を使うとクラッシュしちゃいます。
API Reference Documentation / Module logger には記載があるのですが、コンソールに Warning: module Elixir.Logger cannot be resolved. と出てくるので Erlang logger でOKでも Elixir Logger にはまだ対応してないということのようです。

まとめ

AtomVM v0.7.0-a.1 で GenServer が使えるのを確認しました。まだちょっとわからないこともありますので続けて調べていきたいです。
あとSupervisorBinary のパターンマッチなど、IoT で使ういろいろな機能が実装されてきていますので、それも試していきたいと思います。

参考文献

2
0
0

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?