8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Azure IoT Hub + Time Series Insight + Nerves Livebookで温度・湿度のグラフを書く

Last updated at Posted at 2021-09-04

はじめに

  • Elixirを楽しんでいますか:bangbang::bangbang::bangbang:
  • Nerves Livebookを用いて、AHT20というモジュールを用いて温度・湿度を測ってAzureでグラフ表示したいとおもいます
    • もしAHT20 もしくは代替のものがご用意いただけない場合にはランダムな値でも送ってみましょう

必要なもの

参考

Nerves Livebook

output.gif1

Azure IoT Hub

  • ポータル画面 https://portal.azure.com/#home から、リソースの作成 > IoT Hubと進んで作成してみましょう
  • 必須入力項目を入力して、選択するところは基本はデフォルトのままにしておいて、価格とスケールティアF1を選びました

スクリーンショット 2021-09-04 10.42.29.png

  • :coffee: でも飲んで待ちましょう

IoTデバイス

  • Azure IoT Hubができあがったら、IoTデバイスを追加します

スクリーンショット 2021-09-04 11.42.44.png

  • デバイスの追加

スクリーンショット 2021-09-04 11.43.10.png

  • デバイスIDはlivebookと名付けました

SASトークンをつくる

  • このあとHTTPSでIoT Hubにデータを送ります
  • その際に必要となるのがSASトークンです

注意喚起

参考

Dockerを使ってSASトークンをつくってみました

$ docker run -it mcr.microsoft.com/azure-cli

bash-5.1# az login
  • 指示通りにブラウザでURLを開いて
    スクリーンショット 2021-09-04 14.36.49.png

  • az login実行時に書いてあるcodeを打ち込みます

  • あとは画面の指示通りに進んでいくとサインインが成功してまたターミナルにコマンドを打ち込めるようになります

bash-5.1# az iot hub generate-sas-token --hub-name {IOT_HUB_NAME}
  • 私の場合は以下のようになります
bash-5.1# az iot hub generate-sas-token --hub-name iot-hub-awesome
  • 実行結果をメモしておきます
  • "SharedAccessSignature sr=xxxx"を使います

Run!!!

  • Nerves Livebookで操作をします
  • http://nerves.local にアクセスして、Authenticationはnervesを入力
  • あとは右上のNew notebookからElixirのプログラミングを楽しみましょう

AHT20から温度・湿度を取得するプログラム

defmodule Aht20.Reader do
  alias Circuits.I2C

  @i2c_bus "i2c-1"
  @i2c_addr 0x38
  @initialization_command <<0xBE, 0x08, 0x00>>
  @trigger_measurement_command <<0xAC, 0x33, 0x00>>
  @two_pow_20 :math.pow(2, 20)

  def read do
    {:ok, ref} = I2C.open(@i2c_bus)

    I2C.write(ref, @i2c_addr, @initialization_command)
    Process.sleep(10)

    I2C.write(ref, @i2c_addr, @trigger_measurement_command)
    Process.sleep(80)

    ret = I2C.read(ref, @i2c_addr, 7)

    I2C.close(ref)

    value(ret)
  end

  defp value({:ok, val}), do: {:ok, convert(val)}

  defp value(_), do: :error

  defp convert(<<_, raw_humi::20, raw_temp::20, _>>) do
    humi = Float.round(raw_humi * 100 / @two_pow_20, 1)
    temp = Float.round(raw_temp * 200 / @two_pow_20 - 50.0, 1)

    {temp, humi}
  end
end
  • AHT20もしくは代替のセンサーのご用意がない場合はランダムな値を返すようにしてみましょう
defmodule Aht20.Reader do
  def read do
    {:ok, {Enum.random(250..300) / 10, Enum.random(600..800) / 10}}
  end
end

IoT Hubへデータを送り込むプログラム

f = fn -> 
  url = 'https://iot-hub-awesome.azure-devices.net/devices/livebook/messages/events?api-version=2020-03-13'

  :inets.start
  :ssl.start

  {:ok, {temp, humi}} = Aht20.Reader.read()
  {:ok, datetime} = DateTime.now("Etc/UTC")
  time = datetime |> DateTime.to_unix()

  json = Jason.encode!(%{value: %{temperature: temp, humidity: humi, time: time}}) |> String.to_charlist()
  request = {url, [{'Authorization', 'SharedAccessSignature sr=xxx'}], 'application/json', json}
  IO.inspect(request)

  :httpc.request(:post, request, [], [])
end

f.()
{:ok,
 {{'HTTP/1.1', 204, 'No Content'},
  [
    {'date', 'Sat, 04 Sep 2021 05:56:41 GMT'},
    {'server', 'Microsoft-HTTPAPI/2.0'},
    {'vary', 'Origin'},
    {'content-length', '0'},
    {'x-ms-request-id', '1f8cfa57-c449-446d-bca0-0d11c02965f4'}
  ], []}}
  • こんな応答が返ってきたら成功です

定期的にIoT Hubへデータを送り込むプログラム

defmodule Ticker do
  use GenServer

  def start_link(state) do
    GenServer.start_link(__MODULE__, state, name: __MODULE__)
  end

  def init(state) do
    :timer.send_interval(1000 * 20, self(), :tick)
    {:ok, state}
  end

  def handle_info(:tick, state) do
    send()
    {:noreply, state}
  end

  defp send do
    url = 'https://iot-hub-awesome.azure-devices.net/devices/livebook/messages/events?api-version=2020-03-13'

    :inets.start
    :ssl.start

    {:ok, {temp, humi}} = Aht20.Reader.read()
    {:ok, datetime} = DateTime.now("Etc/UTC")
    time = datetime |> DateTime.to_unix()

    json = Jason.encode!(%{value: %{temperature: temp, humidity: humi, time: time}}) |> String.to_charlist()
    request = {url, [{'Authorization', 'SharedAccessSignature sr=iot-hub-awesome.azure-devices.net&sig=XSUR%2BX3tP9Em%2FVqQx5Q%2FwSIeq5qUiYGyD8BG3Bog51g%3D&se=1630737793&skn=iothubowner'}], 'application/json', json}
    IO.inspect(request)

    :httpc.request(:post, request, [], [])
  end
end

Ticker.start_link([])
  • 20秒ごとにセンサーからの値取得、IoT Hubへの送信を行っています
  • このまましばらく放置しておきます
  • :coffee: でも飲んで待っていると、デバイスからのデータが届いていることがわかります
    • 図はIoT Hubの概要

スクリーンショット 2021-09-04 15.13.55.png

Time Series Insight

  • Time Series Insightでグラフ表示をしてみます

スクリーンショット 2021-09-04 15.07.59.png

  • 「作成」を迷わず押して
  • あとはカンで値を入力して、Time Series Insightをデプロイしましょう

スクリーンショット 2021-09-04 15.11.35.png

  • :coffee:でも飲んでデプロイが終わって、「リソースに移動」
  • さらに「TSIエクスプローラーに移動」
  • そうするとこんな画面になります

スクリーンショット 2021-09-04 15.19.58.png

  • nullのところを触って、あとは雰囲気でvalue.humidityvalue.temperatureにチェックをいれましょう
  • そうすると以下のようなグラフが表示されます :tada::tada::tada:

スクリーンショット 2021-09-04 15.23.01.png

  • ランダム値を送り込むプログラムでの結果です
  • 温度・湿度なのでそれほど激しくはうごきません

Wrapping Up :lgtm::lgtm::lgtm::lgtm:

最後の最後に

https___qiita-user-contents.imgix.net_https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F240349%2F5ef22bb9-f357-778c-1bff-b018cce54948.png_ixlib=rb-1.2.png

  1. ブレッドボードとLチカは今回の記事とはなんら関係ありません

8
5
3

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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?