(この記事は、「#NervesJP Advent Calendar 2019」の2日目です)
昨日はtakasehideki先生の「ElixirでIoT#4.1:Nerves開発環境の準備(2019年12月版)」です!こちらもぜひぜひ!
What is Nerves ?
- 神経
-
ElixirでIoT#2.1:Nervesって何者?ラズパイでLチカできんの!?
- こちらの@TAKASEhideki 先生の記事がわかりやすいです
- IoTボード上で動作する最小構成のLinuxブートローダ+Elixir実行環境+各種デバドラのパッケージセット
- とにかく、ElixirがRaspberry Pi2で動きます、動かしてみましょう
- 以下、Getting Startedの内容を日本語で少しだけ詳しくかいているつもりです
使うもの
- MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
- Raspberry Pi2
つくったもの
- hello_nerves
- 記事執筆時点のリビジョン: 76443c5e4a16c35b0fbc88c2dd89b9fa424a4c61
Elixirのインストール
- Host(今回の記事ではMacBook Pro)にインストールします
- macOS Catalina(10.15.1)にasdfでElixirをインストールする
- Elixirをインストールできたら、公式に従って以下を行います
$ mix local.hex
$ mix local.rebar
$ mix archive.install hex nerves_bootstrap
まずは nerves_examples で練習
1. microSDカードにfirmware.burnするまで
- Raspberry Pi2でNervesを動かしてネットワークに接続してみます
- 以下、Host(今回の記事ではMacBook Pro)での作業です
-
MIX_TARGET
はTargetsでお持ちのガジェットを指定してください- 私はRaspberry Pi2しかもっていないのでこれでしか試せていません
-
NERVES_NETWORK_SSID
とNERVES_NETWORK_PSK
の値は適切な値をセットしてください - これを読んでいるような人はたいていもっているとおもうのですが、
~/.ssh
に秘密鍵と公開鍵のペアがおいてある必要があります- デフォルトは以下の3種類のうちいずれかを期待しているようです
-
id_rsa
/id_rsa.pub
-
id_ecdsa
/id_ecdsa.pub
-
id_ed25519
/id_ed25519.pub
-
- ソースコードはここなので、ファイル名が違うとかあればここを書き換えればうまくいくとおもいます
- 私は、
~/.ssh/id_rsa
と~/.ssh/id_rsa.pub
がありましたので特に変更はしていないです
- 私は、
- デフォルトは以下の3種類のうちいずれかを期待しているようです
$ git clone https://github.com/nerves-project/nerves_examples.git
$ cd nerves_examples/hello_network/
$ export MIX_TARGET=rpi2
$ export NERVES_NETWORK_SSID=ssid
$ export NERVES_NETWORK_PSK=secret
$ mix deps.get
$ mix firmware
- microSDカードをHost(今回の記事ではMacBook Pro)に挿入!
$ mix firmware.burn
- microSDカードを自動検出してくれるのですが、「本当にburnしていいの?」って、ここはじめてだと緊張します
- 慣れると
Y
をすぐおします - Macのパスワード聞かれるので、本当に大丈夫なことを確認して、burnしてください
- microSDカードのデータ容量くらいで、エイッとやっています
- 正しい確認方法ありましたら、コメントください
2. できあがったmicroSDカードをRaspberry Pi2に差し込んで電源ON
- ディスプレイとキーボードを接続しておくといいかもしれません
- iexが起動しています
- 適当にエンターでもおして
-
HelloNetwork.test_dns
を実行してみてください -
:ok
が返ってくれば、Nerves on Raspberry Pi2はインターネットにつながっています - 私は特に失敗などありませんでした
- もしうまくつながらない場合は、RPi3B/B+ wired and wireless Ethernet connections あたりが解決のヒントになるのではないかとおもいます(カンです)
- Nerves on Raspberry Pi2のIPアドレスをどうにかして調べてください
- 私は192.168.1.1にアクセスして、ルーターの管理画面みたいなやつにいって、「DHCPv4サーバ払い出し状況」みたいなやつから特定しました
-
@TAKASEhideki 先生から、Raspberry Pi2とTV(ディスプレイ)、キーボードをつないでおいて、iexに
ifconfig
コマンドを打ち込む方法を教えてもらいました
-
@TAKASEhideki 先生から、Raspberry Pi2とTV(ディスプレイ)、キーボードをつないでおいて、iexに
- 私は192.168.1.1にアクセスして、ルーターの管理画面みたいなやつにいって、「DHCPv4サーバ払い出し状況」みたいなやつから特定しました
- Host(今回の記事ではMacBook Pro)からNerves on Raspberry Pi2にssh接続しましょう!
- 例:
ssh 192.168.1.10
- 例:
- ここまで順調にいきましたら、続いて自分のプロダクトを作ってみましょう
おまけ
- どうでもよい話ですが、Host(今回の記事ではMacBook Pro)からNerves on Raspberry Pi2にssh接続ができることをNervesを始めた当初は知りませんでした
- TVとRaspberry Pi2をつないで、日本語配列のキーボードで記号をうつときに、パズルのようにしてキーを探していました
- Nervesをはじめた当初はこんな感じで、@zacky1972 先生のcpu_infoのデバッグに参加していました
- 文字起こしとかしてました
- 解決したときはこちらに名前を載せてもらいました!
-
hd
とかそれまで私は知らなかった関数の存在を知ることができてよかったです - いい思い出です
-
アプリの作成
1. ひながたの作成
$ mix nerves.new hello_nerves
2. WiFi接続
config/target.exs
config :nerves_network,
regulatory_domain: "JP"
key_mgmt = System.get_env("NERVES_NETWORK_KEY_MGMT") || "WPA-PSK"
config :nerves_network, :default,
wlan0: [
networks: [
[
ssid: System.get_env("NERVES_NETWORK_SSID"),
psk: System.get_env("NERVES_NETWORK_PSK"),
key_mgmt: String.to_atom(key_mgmt)
]
]
]
- https://github.com/TORIFUKUKaiou/hello_nerves/commit/10a9d08e9edbe12a94ab67183c94d05a083911dc
- 上記を書き足したあと、とりあえずWiFi接続できるかどうか試してみましょう
$ export MIX_TARGET=rpi2
$ export NERVES_NETWORK_SSID=ssid
$ export NERVES_NETWORK_PSK=secret
$ mix deps.get
$ mix firmware
$ mix firmware.burn
- 練習のところでやったように、Host(今回の記事ではMacBook Pro)からNerves on Raspberry Pi2にssh接続できることを確かめましょう
3. 天気予報取得、Twitter投稿のためのソースコード変更
- Livedoor Weather Web Serviceは、■サービス終了のお知らせとなっております。
- いままでありがとうございました
- 2020/12/2現在、天気予報の取得はは下記をご参考にしてください。
- 天気予報はお天気Webサービスを使わせていただいて、HTTP Get |> parse をします
- 取得した結果をTwitterに投稿(HTTP POST)します
- 普通のElixirプログラムを作る感覚でつくれば良いです
- 変更箇所は、こちらをご参照ください
- 以下はうまく書けたとおもうところを抜粋しています
lib/weather/forecast.ex
defmodule Weather.Forecast do
def run do
city = cities() |> Enum.random()
description =
"http://weather.livedoor.com/forecast/webservice/json/v1?city=#{city}"
|> HTTPoison.get!()
|> Map.get(:body)
|> Poison.decode!()
|> Map.get("description")
|> Map.get("text")
|> String.split()
|> Enum.reduce_while("", fn s, acc ->
if String.length(acc <> "#{s}\n") < 140 - String.length(i_use_nerves()),
do: {:cont, acc <> "#{s}\n"},
else: {:halt, acc}
end)
if String.length(description) == 0, do: exit("oh no")
description |> Kernel.<>(i_use_nerves())
end
defp i_use_nerves do
if Application.get_env(:hello_nerves, :target) != :host do
"I use Nerves. I like it!"
else
""
end
end
- その後、なんどかリファクタをして現在の姿はこちら です
- 大筋はかわっていません
4. イメージの作成、microSDカードへの書き込み
- Twitterの認証情報の取得方法はわすれました
- いつ取得したのかすら忘れましたがもっていたものを使いました
$ export MIX_TARGET=rpi2
$ export NERVES_NETWORK_SSID=ssid
$ export NERVES_NETWORK_PSK=secret
$ export TWITTER_CONSUMER_KEY=xxx
$ export TWITTER_CONSUMER_SECRET=yyy
$ export TWITTER_ACCESS_TOKEN=zzz
$ export TWITTER_ACCESS_TOKEN_SECRET=aaa
$ mix deps.get
$ mix firmware
$ mix firmware.burn
5. Nerves on Raspberry Pi2の起動
- こんがりやきあがったmicroSDカードをRaspberry Pi2に挿し込んで電源を投入しましょう
- Host(今回の記事ではMacBook Pro)からNerves on Raspberry Pi2にssh接続して、
HelloNerves.update
を実行してみましょう
Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
Toolshed imported. Run h(Toolshed) for more info
RingLogger is collecting log messages from Elixir and Linux. To see the
messages, either attach the current IEx session to the logger:
RingLogger.attach
or print the next messages in the log:
RingLogger.next
iex(1)> HelloNerves.update
%ExTwitter.Model.Tweet{
in_reply_to_user_id: nil,
truncated: false,
withheld_in_countries: nil,
quoted_status_id_str: nil,
favorite_count: 0,
scopes: nil,
lang: "ja",
favorited: false,
geo: nil,
- うまく投稿できましたでしょうか!
- ラズパイ4でも動くそうです!
まとめ
-
Nervesだからと身構える必要はなく、ふつうのElixirプログラムを書けばうごきます
- 私の郷里の言葉では、「いごきます」
- Getting Startedは英語が不得手な私でも読みやすいです
- cron的なことができていないので、手動でiexから実行しています
- 課題といえば課題ですが
- 朝、早起きする意味でこのままでもいいかも
最後に
- IoTつくるよ!2 2019/11/30(土)のNervesJPのブースにて、TAKASEhideki先生に使っていただきました!
- ありがとうございます!
次回
次回も引き続き私が担当しまして、「Nervesでcron的なことをする」です!こちらも是非どうぞ~