10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

#NervesJPAdvent Calendar 2024

Day 1

ZenohexをNervesでいごかす v0.3.2篇

Last updated at Posted at 2024-12-01

もう師走だなんて信じられない!11月31日はどこにいった!!
なんて言ってても時は戻らないので,雑ネタを投下したいと思います.

2023年は一本もQiita記事をアウトプットしておらず,そして #NervesJP Advent Calendar 2023 も飛ばしてしまったので,その罪滅ぼしも兼ねまして,,,
みなさんれっつじょいなす!!

Zenohexとは??

ZenohのElixir APIライブラリです.
@ShintaroHosoai@pojiro と楽しくつくってます:D

いろんなご縁がありまして7月の daimon.ex にて講演させてもらいました.YouTubeアーカイブも公開してくれていて,Alchemist向け前提ではあるものの,ZenohやZenohexの解説内容としては一番まとまっているのではと思っています.

このへんの記事も参考になるかと思います,というか私も参考にしています:D

ネイティブなElixirで試されている記事も!(Zenohexバージョンが v0.1.3 で古めです)

という感じで Zenohex on Nerves はまだ記事がなさそうなのでセーフセーフ,ということでやっていきます〜

下準備

ホスト環境

ホストは MacBook Pro 2021 / Apple M1 Max でやっていきます.
Elixir/Erlang/Nerves 関係の環境は構築済みであることを前提とします.ちなバージョンはこんな感じ.

% asdf current                  
elixir          1.17.3-otp-27   /Users/takasehideki/.tool-versions
erlang          27.1.2          /Users/takasehideki/.tool-versions

Nerves mix プロジェクトの作成

いつものように Nerves mix プロジェクトを作成して初期ビルドしておきます.

% mix nerves.new zenohex_nerves           
* creating zenohex_nerves/config/config.exs
* creating zenohex_nerves/config/host.exs
* creating zenohex_nerves/config/target.exs
* creating zenohex_nerves/lib/zenohex_nerves.ex
* creating zenohex_nerves/lib/zenohex_nerves/application.ex
* creating zenohex_nerves/test/test_helper.exs
* creating zenohex_nerves/test/zenohex_nerves_test.exs
* creating zenohex_nerves/rel/vm.args.eex
* creating zenohex_nerves/rootfs_overlay/etc/iex.exs
* creating zenohex_nerves/.gitignore
* creating zenohex_nerves/.formatter.exs
* creating zenohex_nerves/mix.exs
* creating zenohex_nerves/README.md

Fetch and install dependencies? [Yn] y
* running mix deps.get
* running mix format
Your Nerves project was created successfully.

You should now pick a target. See https://hexdocs.pm/nerves/supported-targets.html
for supported targets. If your target is on the list, set `MIX_TARGET`
to its tag name:

For example, for the Raspberry Pi 3 you can either
  $ export MIX_TARGET=rpi3
Or prefix `mix` commands like the following:
  $ MIX_TARGET=rpi3 mix firmware

If you will be using a custom system, update the `mix.exs`
dependencies to point to desired system's package.

Now download the dependencies and build a firmware archive:
  $ cd zenohex_nerves
  $ mix deps.get
  $ mix firmware

If your target boots up using an SDCard (like the Raspberry Pi 3),
then insert an SDCard into a reader on your computer and run:
  $ mix burn

Plug the SDCard into the target and power it up. See target documentation
above for more information and other targets.

mix deps.get

これもいつものやつですね.
ターゲットは目の前に転がっていたラズパイ4にしました.

% cd zenohex_nerves
% export MIX_TARGET=rpi4
% mix deps.get
Resolving Hex dependencies...
Resolution completed in 0.09s
Unchanged:
  beam_notify 1.1.1
  castore 1.0.10
  circular_buffer 0.4.1
  elixir_make 0.9.0
  gen_state_machine 3.0.0
  jason 1.4.4
  mdns_lite 0.8.11
  muontrap 1.5.0
  nerves 1.11.2
  nerves_logging 0.2.2
  nerves_motd 0.1.15
  nerves_pack 0.7.1
  nerves_runtime 0.13.7
  nerves_ssh 1.0.0
  nerves_system_bbb 2.25.0
  nerves_system_br 1.29.1
  nerves_system_grisp2 0.13.0
  nerves_system_mangopi_mq_pro 0.11.0
  nerves_system_osd32mp1 0.20.0
  nerves_system_rpi 1.29.0
  nerves_system_rpi0 1.29.0
  nerves_system_rpi2 1.29.0
  nerves_system_rpi3 1.29.0
  nerves_system_rpi3a 1.29.0
  nerves_system_rpi4 1.29.0
  nerves_system_rpi5 0.4.0
  nerves_system_x86_64 1.29.0
  nerves_time 0.4.8
  nerves_toolchain_aarch64_nerves_linux_gnu 13.2.0
  nerves_toolchain_armv6_nerves_linux_gnueabihf 13.2.0
  nerves_toolchain_armv7_nerves_linux_gnueabihf 13.2.0
  nerves_toolchain_ctng 1.10.0
  nerves_toolchain_riscv64_nerves_linux_gnu 13.2.0
  nerves_toolchain_x86_64_nerves_linux_musl 13.2.0
  nerves_uevent 0.1.0
  one_dhcpd 2.0.3
  property_table 0.2.5
  ring_logger 0.11.3
  shoehorn 0.9.2
  ssh_subsystem_fwup 0.6.2
  toolshed 0.4.1
  uboot_env 1.0.1
  vintage_net 0.13.5
  vintage_net_direct 0.10.7
  vintage_net_ethernet 0.11.2
  vintage_net_wifi 0.12.5
All dependencies are up to date
==> jason
Compiling 10 files (.ex)
Generated jason app
==> elixir_make
Compiling 8 files (.ex)
Generated elixir_make app
==> castore
Compiling 1 file (.ex)
Generated castore app
==> nerves
HOST_CC port.o
HOST_LD port
Compiling 51 files (.ex)
Generated nerves app
==> zenohex_nerves

Nerves environment
  MIX_TARGET:   rpi4
  MIX_ENV:      dev

Checking for prebuilt Nerves artifacts...
  Checking nerves_system_rpi4...
  [GitHub] nerves_system_rpi4-portable-1.29.0-FB67112.tar.gz
|==================================================| 100% (274 / 274) MB
  => Success
  Found nerves_toolchain_aarch64_nerves_linux_gnu in cache
    /Users/takasehideki/.nerves/artifacts/nerves_toolchain_aarch64_nerves_linux_gnu-darwin_arm-13.2.0

Zenohex のインストール

いつものように mix.exs を編集します.

mix.exs
  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
<snipped...>
      {:nerves_system_mangopi_mq_pro, "~> 0.6", runtime: false, targets: :mangopi_mq_pro},

      # Add zenohex hex package
      {:zenohex, "~> 0.3.2"}
    ]
  end

改めて mix deps.get しておきます.

% mix deps.get
Resolving Hex dependencies...
Resolution completed in 0.109s
New:
  rustler_precompiled 0.8.2
  toml 0.7.0
  zenohex 0.3.2
Unchanged:
<snipped...>
* Getting zenohex (Hex package)
* Getting rustler_precompiled (Hex package)
* Getting toml (Hex package)
==> nerves
==> zenohex_nerves

Nerves environment
  MIX_TARGET:   rpi4
  MIX_ENV:      dev

Checking for prebuilt Nerves artifacts...
  Found nerves_toolchain_aarch64_nerves_linux_gnu in cache
    /Users/takasehideki/.nerves/artifacts/nerves_toolchain_aarch64_nerves_linux_gnu-darwin_arm-13.2.0
  Found nerves_system_rpi4 in cache
    /Users/takasehideki/.nerves/artifacts/nerves_system_rpi4-portable-1.29.0

さてビルド

Zenoh は Rust 実装されていますが,NIF的な RustlerRustler Precompiled のおかげでユーザはそこをあんまり気にする必要ありません.ビルド時に prebuild binary をよしなにダウンロードしてきてくれます.

% mix firmware
==> nerves
<snipped...>
==> rustler_precompiled
Compiling 4 files (.ex)
Generated rustler_precompiled app
==> zenohex
Compiling 13 files (.ex)

18:13:10.932 [debug] Copying NIF from cache and extracting to /Users/takasehideki/research/zenoh/zenohex_nerves/_build/rpi4_dev/lib/zenohex/priv/native/libzenohex_nif-v0.3.2-nif-2.15-aarch64-unknown-linux-gnu.so.tar.gz
Generated zenohex app
<snipped...>
==> zenohex_nerves
Compiling 2 files (.ex)
Generated zenohex_nerves app
|nerves| Building OTP Release...

* [Nerves] validating vm.args
* skipping runtime configuration (config/runtime.exs not found)
* creating _build/rpi4_dev/rel/zenohex_nerves/releases/0.1.0/vm.args
Updating base firmware image with Erlang release...
Copying rootfs_overlay: /Users/takasehideki/research/zenoh/zenohex_nerves/_build/rpi4_dev/nerves/rootfs_overlay
Copying rootfs_overlay: /Users/takasehideki/research/zenoh/zenohex_nerves/rootfs_overlay
Building /Users/takasehideki/research/zenoh/zenohex_nerves/_build/rpi4_dev/nerves/images/zenohex_nerves.fw...
Firmware built successfully! 🎉

Now you may install it to a MicroSD card using `mix burn` or upload it
to a device with `mix upload` or `mix firmware.gen.script`+`./upload.sh`.

burn:fire:

これもいつものやつですね.
microSDカードにNervesファームウェアを焼きます.

% mix burn
==> nerves
==> zenohex_nerves

Nerves environment
  MIX_TARGET:   rpi4
  MIX_ENV:      dev

Use 14.65 GiB memory card found at /dev/rdisk4? [Yn] y
100% [====================================] 45.06 MB in / 54.37 MB out       
Success!
Elapsed time: 5.560 s

実行

SSHアクセス

microSDカードを Raspberry Pi 4 に挿入し,Ethernetでよしなに接続しておきます.

これもいつものやつですね.電源を入れてちょっと待ってから ssh nerves.local で Nerves 上の IEx に入ります.

% ssh nerves.local
Warning: Permanently added 'nerves.local' (ED25519) to the list of known hosts.
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
████▄▄    ▐███
█▌  ▀▀██▄▄  ▐█
█▌  ▄▄  ▀▀  ▐█   N  E  R  V  E  S
█▌  ▀▀██▄▄  ▐█
███▌    ▀▀████
zenohex_nerves 0.1.0 (22c33f4a-52b4-56c7-1d3e-159ed97caaa2) arm rpi4
  Serial       : 10000000b39a11d8
  Uptime       : 23.652 seconds
  Clock        : 2024-11-26 20:49:47 UTC (unsynchronized)
  Temperature  : 47.2°C

  Firmware     : Valid (A)               Applications : 41 started
  Memory usage : 152 MB (4%)             Part usage   : 288 MB (2%)
  Hostname     : nerves-11d8             Load average : 0.80 0.19 0.06

  eth0         : 192.168.11.100/24, fe80::e65f:1ff:fe65:8172/64
  usb0         : 172.31.166.73/30

Nerves CLI help: https://hexdocs.pm/nerves/iex-with-nerves.html

Toolshed imported. Run h(Toolshed) for more info.
iex(1)> 

とりま Pub/Sub してみる

Zenohex リポジトリの README にある Getting Started を :muishiki: にやってみます.

iex(1)> {:ok, session} = Zenohex.open()
{:ok, #Reference<0.1198495918.1163788306.186120>}
iex(2)> {:ok, publisher} = Zenohex.Session.declare_publisher(session, "demo/example/test")
{:ok, #Reference<0.1198495918.1163788290.187264>}
iex(3)> {:ok, subscriber} = Zenohex.Session.declare_subscriber(session, "demo/**")
{:ok, #Reference<0.1198495918.1163788290.187298>}
iex(4)> Zenohex.Publisher.put(publisher, "Hello Zenoh Dragon")
:ok
iex(5)> Zenohex.Subscriber.recv_timeout(subscriber, 1000)
{:ok,
 %Zenohex.Sample{
   key_expr: "demo/example/test",
   value: "Hello Zenoh Dragon",
   kind: :put,
   reference: #Reference<0.1198495918.1163788306.186121>
 }}

やったぜいごいたぜっ!!

ちなリポジトリには,より Elixir 成分の感じられる practical な Examples もご用意しております.

注意点というかお誘いというか

本稿執筆時点での Zenohex の最新版は v0.3.2 となります.

Zenoh への対応は v0.11.0 になります.
Zenoh は割りとバージョン番号にセンシティブ a.k.a 絶賛成長中で,異なるバージョン間では通信できないことが多いです.なので他ライブラリや言語モジュールと疎通させたい場合はご注意ください.

もちろん v1.0 対応は進行中でっす!

ですが,,, たいへん辛みがツラく,,, v0.11.0 to v1.0 はけっこう内部構造から変わってるんですよねぇ,,,
Elixir と Rust と Rustler を完全に理解されている方がいましたら,ぜひとも手伝ってください!!

まとめ

Zenoh の Elixir API である Zenohex を用いて Nerves で Pub/Sub をしてみました。簡単に Pub/Sub できました。

今回は NAT越えやネットワーク間通信をするための Zenoh ルータを用いていません。また Zenoh 独自の機能である pull や get も使っていません。今後、試していきたいと思います。

という既視感たっぷりな締めにて筆を置きたいと思います〜

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?