シェルスクリプトマガジン

特集1 ESP32とラズパイで作る本格IoT(Vol.78記載)

筆者:魔法少女

マイコン「ESP32」と小型コンピュータボード「Raspberry Pi」を使って本格的なIoT(Internet of Things、モノのインターネット)環境を構築してみましょう。本企画では、3軸の加速度センサーを用いて簡易地震計を作成し、リアルタイムに揺れをグラフで表示します。

シェルスクリプトマガジン Vol.78は以下のリンク先でご購入できます。

図4 Eclipse Mosquittoの設定スクリプト(mosquitto_setting.sh)

#!/bin/sh

sudo tee /etc/mosquitto/conf.d/confer.conf << EOF >dev/null
listener 1883
allow_anonymous true
listener 8081
protocol websockets
sudo systemctl reload mosquitto

図18 ESP32搭載ボートの起動時に無線LANに接続するプログラム(boot.py)

import network

SSID = 'SSID'
PASSWORD = 'パスワード'

wlan_if = network.WLAN(network.STA_IF)
wlan_if.active(True)
wlan_if.connect(SSID, PASSWORD)

図19 パブリッシャのプログラム(main.py)

import time
from machine import Pin, SoftI2C
import mpu6050
from umqtt.simple import MQTTClient
import json

mqtt_topic = "home/seismometer1"
publisher_id = "place_esp32"
broker_address = "192.168.1.100"
interval_time = "1"

i2c = SoftI2C(scl=Pin(22), sda=Pin(21))
accelerometer = mpu6050.accel(i2c)

time.sleep(5)

while True:
  iot_value = accelerometer.get_values()
  iot_value_json = json.dumps(iot_value)
  print(iot_value_json)
  publisher = MQTTClient(publisher_id,broker_address)
  publisher.connect()
  publisher.publish(mqtt_topic, msg=str(iot_value_json))
  publisher.disconnect()
  time.sleep(int(interval_time))

図24 ブスクライバとなるJavaScriptプログラムを含んだHTMLファイル(seismometer.html)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>簡易地震計</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-streaming@1.9.0"></script>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
</head>
<body>
  <canvas id="myChart"></canvas>
  <script>
    const client = mqtt.connect('ws://raspibroker.local:8081');
    const ctx = document.getElementById('myChart').getContext('2d');
    var chart = new Chart(ctx, {
      type: 'line',
      data: {
        datasets: [{
          data: [],
          label: 'X軸',
          borderColor: 'rgb(255, 0, 255)',
          backgroundColor: 'rgba(255, 255, 255, 0)',
          lineTension: 0,
        }, {
          data: [],
          label: 'Y軸',
          borderColor: 'rgb(0, 255, 0)',
          backgroundColor: 'rgba(255, 255, 255, 0)',
          lineTension: 0,
        }, {
          data: [],
          label: 'Z軸',
          borderColor: 'rgb(0, 0, 255)',
          backgroundColor: 'rgba(255, 255, 255, 0)',
          lineTension: 0,
        }]
      },
      options: {
        scales: {
          xAxes: [{
            type: 'realtime',
            realtime: {
              delay: 2000,
            },
          }],
          yAxes: [{
            ticks: {
              min: -32767,
              max: 32767
            }
          }]
        }
      }
    });
    client.on('connect', () => {
      console.log('connected');
      client.subscribe('home/seismometer1');
    });
    client.on('message', (topic, message) => {
      console.log(message.toString());
      acc_json = JSON.parse(message.toString());
      chart.data.datasets[0].data.push({
        x: Date.now(),
        y: acc_json.AcX
      });
      chart.data.datasets[1].data.push({
        x: Date.now(),
        y: acc_json.AcY
      });
      chart.data.datasets[2].data.push({
        x: Date.now(),
        y: acc_json.AcZ - 16384
      });
      chart.update();
    });
  </script>
</body>
</html>