TECH PLAY

Raspberry Pi

イベント

該当するコンテンツが見つかりませんでした

マガジン

技術ブログ

SCSK いわいです。 前回はRaspberry Pi 5で気温/気圧/湿度センサーを使って測定し、 Webで表示、DBに取得データを検索するシステムを構築しました。 今回は測定したデータからAIを使って気温/気圧/湿度をリアルタイム予測してみます。 今回は前回セットアップした環境をそのまま流用します。 Raspberry Piで気温/気圧/湿度計測 結果をWebサーバで見てみよう Raspberry Pi 5で気温/気圧/湿度センサーを使って測定し、Webで表示するシステムを構築したいと思います。DBに取得データを格納し、あとから検索できるといろいろ便利です。 blog.usize-tech.com 2025.12.08   過去データから現在値を予測す る 過去データから現在値を予測します。これには機械学習結果からの推論(教師あり学習)を使用します。 温度/湿度/気圧の予測のために「線形回帰」「非線形回帰」「LSTM(Long Short Term Memory)」の3つを試してみます。 「線形回帰」はデータの関係性が直線(線形)の場合で表せる場合に使われます。 ⇒グラフにした時にだいたいまっすぐな線で表せる 例えば商品の売上と広告費用などが該当します。 「非線形回帰」は「データの関係性が曲線(非線形)」で表せる場合に使われます。 ⇒グラフにした時に曲がった線で表せる 例えば投げたボールの高さと時間の関係が該当します。 「LSTM」は時系列データや文章など、時間の流れや順番が大事なデータをうまく使える機械学習のモデルです。 ⇒過去と今の情報を組み合わせて考えられる仕組み 例えば株価の予測、文章の意味理解が該当します。 普通の再帰型ニューラルネットワークは「昔のこと」をすぐ忘れてしまいますが、LSTMは 「長い・短い記憶をうまく使い分けできる」ので、長い文章や長期的な傾向も扱えるようです。 なんだか今回のテーマに合致しそうな気配です。 ざっくりまとめると以下になります。 方式 得意なデータ 値の関係 過去の情報との関係 例 線形回帰 数値 & シンプル 直線 考慮しない 商品の売上と広告費用 非線形回帰 (RF予測) 数値 & 複雑 曲線 考慮しない 投げたボールの高さと経過時間 LSTM 時系列・文章・音声等 複雑 + 順番 重視する 株価予測、文書生成 これらの3つの方式を実装してどの予測値が実測値に近いか確認してみます。   システムのイメージ 前回作成したFlaskアプリケーションに機能を追加します。今回はWeb画面に測定結果と予測値を表示します。 蓄積した測定結果から予測モデルを作成して、予測モデルを使ってリアルタイムで現在の温度/湿度/気圧を予測してみます。 イメージはこんなカンジで。 今回のシステムで導入する機能と各ライブラリの説明は以下のとおりです。 機能 ライブラリ 説明 Webサーバ Flask 軽量なWebフレームワーク。センサー値や予測結果をWebアプリとしてブラウザに表示。 センサー通信 Smbus2 ラズパイとI2C通信する。BME280と通信するために利用。   bme280 Bosch製の温湿度・気圧センサー BME280用のPythonライブラリ。データ取得する。 データ保存 sqlite3 軽量な組み込み型データベースSQLiteを操作するためのライブラリ。計測データをローカルDBに保存・検索するために利用。 時刻処理 datetime 計測時刻の記録に利用。ローカルDBに保存するtimestampを生成。 ファイル管理 (new) os OSレベルの操作。LSTMモデル/Scalerファイル(ディープラーニング結果ファイル)の存在確認に利用。   joblib Pythonオブジェクトを高速に保存・読み込みするためのライブラリ。学習済みScalerを保存・読み込みするために利用。 数値処理 (new) numpy 数値計算ライブラリ。線形回帰やLSTMに渡すデータを配列に整形するために利用。 機械学習 (new) scikit-learn 線形回帰、非線形回帰をつかった予測のために利用。   tensorflow LSTM予測のために利用。 前回導入済みのライブラリに加え、ファイル管理用ライブラリ(joblib)、数値処理ライブラリ(numpy)、機械学習用ライブラリ(scikit-learn、tensorflow)を追加します。ファイル管理用ライブラリであるosはデフォルトでインストールされています。   過去のデータからLSTMモデルを作成する LSTMモデルを作成するために高速演算用ライブラリのnumpy、機械学習ライブラリのscikit-learnとtensorflow、ファイル生成用ライブラリjoblibをインストールします。 sudo pip install numpy –break-system-packages  sudo pip install tensorflow –break-system-packages sudo pip install scikit-learn –break-system-packages sudo pip install joblib –break-system-packages ローカルに測定結果を蓄積しているDBファイルを元にLSTMモデルとScalerファイルを生成します。 Scalerファイルとは学習時のデータの最大値/最小値、標準偏差等を求めて、それぞれのデータをを0~1の数値に 置き換えるための定義ファイルとのこと。 この定義ファイルがないとそもそもどんな情報を元に学習した結果なのかわからず、 予測もできないため、学習時と予測時には同じ定義ファイルを使う必要があります。 import sqlite3 import numpy as np import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense from sklearn.preprocessing import MinMaxScaler import joblib # スケーラー保存用 # ====== 設定 ====== DB_FILE = "bme280_data.db" TREND_WINDOW = 10 # LSTM の timesteps MODEL_FILE = "bme280_lstm_model.keras" SCALER_FILE = "bme280_scaler.save" # ====== SQLite からデータ取得 ====== def load_data(): with sqlite3.connect(DB_FILE) as conn: c = conn.cursor() c.execute(""" SELECT temperature, humidity, pressure FROM measurements ORDER BY timestamp ASC """) rows = c.fetchall() data = np.array(rows, dtype=np.float32) return data # shape = (n_samples, 3) # ====== LSTM 用系列データ作成 ====== def create_sequences(data, window_size): X, y = [], [] for i in range(len(data) - window_size): X.append(data[i:i + window_size]) y.append(data[i + window_size]) return np.array(X), np.array(y) # ====== メイン処理 ====== def main(): # --- データロード --- data = load_data() if len(data) <= TREND_WINDOW: raise ValueError("データ数が TREND_WINDOW 以下です") # --- 正規化 --- scaler = MinMaxScaler() data_scaled = scaler.fit_transform(data) # --- 系列化 --- X, y = create_sequences(data_scaled, TREND_WINDOW) print("X shape:", X.shape) # (samples, timesteps, features) print("y shape:", y.shape) # (samples, features) # --- LSTM モデル --- model = Sequential([ LSTM(32, input_shape=(X.shape[1], X.shape[2])), Dense(X.shape[2]) # temperature, humidity, pressure ]) model.compile( optimizer="adam", loss="mse" ) model.summary() # --- 学習 --- model.fit( X, y, epochs=100, batch_size=16, verbose=1 ) # --- 保存(.keras 形式) --- model.save(MODEL_FILE) joblib.dump(scaler, SCALER_FILE) print("✅ モデル保存:", MODEL_FILE) print("✅ スケーラー保存:", SCALER_FILE) # ====== 実行 ====== if __name__ == "__main__": main() 予測用に直近10件のデータを測定し、学習結果から次の1件のデータを予測するLSTMモデルを作成しています。 これで温度/湿度/気圧予測の準備ができました。   Pythonスクリプト作成/実行 今回もChatGPTを利用してPythonスクリプトを作りました。 前回の構成に過去のデータから現在の気温/湿度/気圧を線形予測、RF予測、LSTM予測した結果を 表示する機能を追加しています。 線形予測は直近5000件のデータから現在の各値を予測、RF予測は過去の測定値からランダムな特徴やデータの一部を選定、 50パターンの決定木 = forestを生成して、その平均値から各値を予測するように設計しています。 Raspberry PiでWebサーバを起動します。   実行結果 上から「実測値」、「線形予測値」、「RF予測値」、「LSTM予測値」を表示しています。 線形予測はだいぶ外れた値、RF予測は実測値にかなり近い値、LSTM予測は若干ずれた値となりました。 現実では温度/湿度/気温には以下の傾向があります。 温度:平坦⇒微増/微減⇒平坦 湿度:ジグザグ 気圧:ほぼ一定+揺れ この現象に対してそれぞれのリアルタイム予測はざっくりと以下のように動きます。 線形予測:微増/微減したら次も微増/微減するはず ⇒そもそも現実と合致してないが傾向はわかる RF予測:大体前と同じぐらいの値では? ⇒ほぼ正解 LSTM予測:過去の値からみてちょっと変えたほうがそれっぽい? ⇒賢すぎてノイズが発生することもあるがクセは覚えられる 今回のケースではそれぞれの予測は得意な分野があることがわかりました。 線形予測は「傾向予測、急激な変化を検出する」、RF予測は「リアルタイム予測、直近予測をする」、 LSTM予測は「周期的な予測、1時間後の予測をする」が得意なようです。 勉強になりました。
前回記事からの続きです。 IoTに高可用性はなぜ必要?信頼性を確保するための第一歩 – TechHarmony   アーキテクチャ概要 まず、クラスタ構成については、以下の通りです。 Pacemaker :リソース管理(仮想IPやサービスの制御) Corosync :クラスタ通信(ノード間の状態同期) Raspberry Pi 5[2台] :クラスタノード 仮想IP(VIP) :サービス提供用IP クラスタ全体構成の構成図   今回は、HUBを用いて、1号機と2号機を接続し、同じネットワークアドレスの設定をしていきます。 仮想IPリソースを作成し、1号機と2号機にインストールしたPacemakerでリソース監視を行い、 Corosyncでノード間の状態を同期し、クラスタ通信を行います。   実際の画像です(赤枠で囲っているものがケースで覆われていますが、Raspberry Piです)   実装手順 1. 環境準備 Raspberry Pi OS ネットワーク設定(今回は固定IPにて設定) Pacemaker、Corosync、pcsインストール Raspberry Piのセットアップを2台ともに設定を入れていきます。 環境の用意ができましたら、まずは、Raspberry Pi にPacemakerとCorosyncをインストールしていきます。 1. OSアップデート  :まずRaspberry Pi のターミナルを開き、最新パッケージに更新します。 #sudo apt update #sudo apt upgrade -y  2. 必要パッケージのインストール  :PacemakerとCorosyncをインストールします。 #sudo apt install pacemaker corosync pcs -y 3. pcsdサービスの起動・自動起動設定 #sudo systemctl enable pcsd #sudo systemctl start pcsd 4. 設定完了確認 #pcs –version #pacemakerd –version #corosync -v 対象のバージョンが表示されるとOKとなります。 続いてクラスタ設定をしていきます。   2. Corosync設定 Corosyncの設定は、 /etc/corosync/corosync.conf  にて行っていきます。 以下、今回設定した内容となります。 totem {     version: 2     cluster_name: クラスタ名     transport: knet     crypto_cipher: aes256     crypto_hash: sha256     cluster_uuid:00000000-0000-0000-0000-000000000000 (※実際にはユニークなUUIDが表示されます) } nodelist {     node {         ring0_addr: 192.168.179.1         name: ラズパイ1号機         nodeid: 1     }     node {         ring0_addr: 192.168.179.2         name: ラズパイ2号機         nodeid: 2     } } quorum {     provider: corosync_votequorum     two_node: 1 } logging {     to_logfile: yes     logfile: /var/log/corosync/corosync.log     to_syslog: yes     timestamp: on } quorumセクションはクラスタノードのどちらをアクティブとするかを判定する設定がされています。 今回は2ノードのみのため、2ノードで動作できる設定を入れております。 loggingセクションは、Corosync動作時のエラーログやイベント履歴を、指定したファイルとシステムログ双方に、日時付きで詳細に残す設定が入っております。   3. クラスタ認証設定 クラスタを起動していきます。 #sudo systemctl start corosync #sudo systemctl start pacemaker 1号機と2号機のノード認証を行い、クラスタ構成を作成します。 #pcs cluster auth ラズパイ1号機 ラズパイ2号機 #pcs cluster setup –name iot-cluster ラズパイ1号機 ラズパイ2号機 #pcs cluster start –all   4. リソース設定(仮想IPリソース) 続いて、仮想IPリソースの作成をしていきます。 ここで注意点があるのですが、仮想IPリソースを作成するのは1号機のみで実施します。 実は、1号機2号機ともに作成を最初しており、上手く動作しないなーということに陥っておりましたので、 皆様はお気を付けください。 ■設定値 – 仮想IPにしたいIPアドレス :  192.168.179.100 – サブネット(netmask) : /24(255.255.255.0の場合) – リソース名 :  my-vip ■実行コマンド #pcs resource create my-vip  ocf:heartbeat:IPaddr2 ip= 192.168.179.100 cidr_netmask=24 op monitor interval=30s   ■作成後の状態確認 #pcs status 仮想IP( my-vip )が「Started on <ノード名>」のように表示されていれば成功です。 これで、ノード障害が発生したとしても、仮想IPが自動で生きているノードに引き継がれます。   これにてクラスタ設定は完了となります。   動作確認 1. スイッチオーバー(手動) クラスタの動作確認をしていきたいと思います。 まずはスイッチオーバーと呼ばれる手動にて行うリソース移動を確認していきます。 コマンドを実行して、1号機⇒2号機へ仮想IPリソースが移動するか見ていきましょう。 事前確認でリソースがどちらのノードにあるか確認します。 ■事前確認 #pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 16:53:16 +09:00) Cluster Summary: * Stack: corosync * Last updated: Wed Oct 29 16:53:17 2025 * 2 nodes configured * 1 resource instance configured Node List: * Online: [ ラズパイ1号機  ラズパイ2号機 ] Full List of Resources: * my-vip (ocf:heartbeat:IPaddr2): Started ラズパイ1号機 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled 仮想IPリソース(my-vip) の箇所に記載のあるノードが、現在、仮想IPリソースを所持しているノードになります。 そのため、現時点では ラズパイ1号機 に仮想IPリソースがあること確認できました。 それでは、1号機から2号機へリソースを移動させたいと思います。 実施方法としては、以下コマンドを実行します。 ■リソース移動コマンド実行 #pcs resource move  my-vip  ラズパイ2号機   ■スイッチオーバー後の確認 #sudo pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 16:55:19 +09:00) Cluster Summary: * Stack: corosync * Last updated: Wed Oct 29 16:55:20 2025 * 2 nodes configured * 1 resource instance configured Node List: * Online: [ ラズパイ2号機    ラズパイ1号機 ] Full List of Resources: * my-vip (ocf:heartbeat:IPaddr2): Started ラズパイ2号機 Daemon Status: corosync: active/enabled pacemaker: active/enabled pcsd: active/enabled 仮想IPリソース(my-vip) の箇所を確認すると、 ラズパイ2号機 の表記があり、1号機から2号機へ変更されていましたので、無事スイッチオーバーが出来たことを確認しました。   2. スイッチバック(手動) 続いて、2号機⇒1号機へコマンドを実行して、仮想IPリソースを戻せるか確認します。 ■事前確認 # pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 17:07:59 +09:00) Cluster Summary:   * Stack: corosync   * Last updated: Wed Oct 29 17:08:00 2025   * Last change:  Wed Oct 29 17:07:28 2025 by root via cibadmin on ラズパイ2号機   * 2 nodes configured   * 1 resource instance configured Node List:   * Online: [ ラズパイ2号機 ラズパイ1号機  ] Full List of Resources:   * my-vip    (ocf:heartbeat:IPaddr2):    Started  ラズパイ2号機 Daemon Status:   corosync: active/enabled   pacemaker: active/enabled   pcsd: active/enabled ■リソース移動コマンド実行 #pcs resource move my-vip ラズパイ1号機   ■スイッチバック後の確認 sudo pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 17:13:58 +09:00) Cluster Summary:   * Stack: corosync   * Last updated: Wed Oct 29 17:13:59 2025   * Last change:  Wed Oct 29 17:13:44 2025 by root via cibadmin on  ラズパイ1号機   * 2 nodes configured   * 1 resource instance configured Node List:   * Online: [ ラズパイ1号機 ラズパイ2号機  ] Full List of Resources:   * my-vip    (ocf:heartbeat:IPaddr2):     Started ラズパイ1号機 Daemon Status:   corosync: active/enabled   pacemaker: active/enabled   pcsd: active/enabled   3. フェイルオーバー(自動) 最後の動作確認として、フェイルオーバーと呼ばれる、リソースが自動で移動されるかを確認します。 1号機で疑似障害を起こし、2号機へ仮想IPリソースが自動で移動するか確認します。 疑似障害としては、1号機-HUB間のLANケーブルを抜線し、疎通ができない状態にします。 抜線後、2号機にて確認コマンドを実行し、仮想IPリソースが移動していましたら、フェイルオーバーされていると判断します。 ■フェイルオーバー動作イメージ ■事前確認 #pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 17:23:32 +09:00) Cluster Summary:   * Stack: corosync   * Last updated: Wed Oct 29 17:23:33 2025   * Last change:  Wed Oct 29 17:13:44 2025 by root via cibadmin on  ラズパイ1号機   * 2 nodes configured   * 1 resource instance configured Node List:   * Online: [ ラズパイ2号機  ラズパイ1号機  ] Full List of Resources:   * my-vip    (ocf:heartbeat:IPaddr2):     Started  ラズパイ2号機 Daemon Status:   corosync: active/enabled   pacemaker: active/enabled   pcsd: active/enabled ■1号機-HUB間のLANケーブルを抜線   ■フェイルオーバーされたか、仮想IPリソースの確認 # pcs status Cluster name: クラスタ名 Status of pacemakerd: ‘Pacemaker is running’ (last updated 2025-10-29 17:37:32 +09:00) Cluster Summary:   * Stack: corosync   * Last updated: Wed Oct 29 17:37:33 2025   * Last change:  Wed Oct 29 17:23:33 2025 by root via cibadmin on ラズパイ1号機   * 2 nodes configured   * 1 resource instance configured Node List:   * Online: [ ラズパイ2号機 ]   * Offline: [ ラズパイ1号機 ] Full List of Resources:   * my-vip    (ocf:heartbeat:IPaddr2):     Started  ラズパイ2号機 Daemon Status:   corosync: active/enabled   pacemaker: active/enabled   pcsd: active/enabled my-vip の箇所に無事2号機のノード名があり、フェイルオーバーの確認ができました。 また、Node Listの1号機の表示がOflineとなっており、2号機のみOnline(稼働の確認が取れている状態)となりました。   最後に Pacemaker + Corosyncを使えば、IoT環境でも高可用性を実現できることが確認できました。 LifeKeeper製品を取り扱う、LifeKeeperチームとして、今回IoT環境での冗長化や障害対応の仕組みを実際に検証していき、普段とは違う試みが出来たと感じました。 今後も色んな活用方法を実践していきたいと思います。
当部では「LifeKeeper」というHAクラスタ製品を取り扱っています。 HAクラスタ製品の市場として、クラウドでの需要の高まりはよく話題になりますが、 IoT分野でのHA(高可用性)やクラスタ技術の需要・役割も近年、ニーズの高まりを見せています。 今後のLifeKeeperビジネスにおける新たな機会創出を見据え、 今回、IoTクラスタ化の普及について探るべく、オープンソースの Pacemaker と Corosync を活用し、Raspberry Piを用いて、IoT環境でのクラスタ構築をLifeKeeperチームが検証してきたいと思います。   なぜ、IoTに高可用性が必要なのか? そもそも、IoTにおけるクラスタ化のニーズについてですが、 技術的・ビジネス的な観点から高まっている背景として、以下の要因があります。 1. デバイス数の爆発的増加 世界中でIoTデバイスが指数関数的に増加し、2030年には約290億台に達すると予測されています。 この膨大なデバイスを効率的に管理し、障害時にサービスを継続する仕組みが求められています。 2. 高可用性(HA)の要求 製造業などの分野では、システム停止が直接的な損失や安全リスクにつながります。 クラスタ化をすることで、障害発生時に自動フェイルオーバーを実現し、ダウンタイムを最小化できます。 3. スケーラビリティと負荷分散 クラスタ単位で処理を分散することで、クラウドへの依存を減らし、ネットワーク負荷を軽減します。   IoT分野においてデバイスが集める大量データや制御システムは「止められない」ものが多く、サーバやゲートウェイのHAクラスタ化が求められており、現場からクラウド中継、分析基盤まで広くHAのニーズが高まっています。 特に、IoTゲートウェイやエッジサーバが停止すると、サービス全体が中断し、ビジネスに深刻な影響を与える可能性があります。 こうしたリスクを回避するために注目されているのが「 クラスタ化による高可用性(HA)構成 」となります。     IoTのクラスタ構築を検証するにあたって IoTのクラスタ化の必要性・ニーズが高まっていることを理解したところで、 今回、IoT環境でクラスタ構築を実現するためにはどうすればいいかを考えました。 そうです、低コストで手に入る機器とツールを使えば良いのです。 そこで今回選ばれたのは、 「Raspberry Pi 5」さんです👏 選定理由としては、手の届く範囲の値段、かつLinuxベースで動作する機器となるためです。 Raspberry Piは、コストパフォーマンスが高く、IoTや産業用途に適したコンパクトなコンピュータとして、 商用利用が広がっているため、今後の活用も見据え、こちらで検証をしていこうと思います。   備考として、Raspberry Piについてあまり知らないといった方向けに特徴や利点を記載しておきます。 コストパフォーマンス Raspberry Piはお手頃な価格帯であり、特に小規模なプロジェクトやスタートアップにとって、初期投資を抑えることができます。 豊富なインターフェース 多くのI/Oポートを持ち、センサーやカメラなどの周辺機器の接続が可能となります。 オープンソースソフトウェアの利用 LinuxベースのOSを使用しており、Pythonなどのプログラミング言語をサポートしています。AIやデータ処理の開発環境をスムーズに構築できます。 豊富な情報 多くのユーザーが情報を共有しているため、トラブルシューティングの際は参考となる記事が多くスムーズに解決へ向かうことがあります。     Pacemakerとは? 今回、Raspberry Piに導入するクラスタツールとしては、「Pacemaker」を選定しました。 選定理由については、IoTに導入できるクラスタ製品であること、そして無料で利用できる点です。 そもそもPacemakerとはなんぞや、という方向けに説明をすると、 Pacemakerは、クラスタ内のリソース(サービス、IPアドレス、ストレージなど)を監視・制御し、障害発生時に自動的に別ノードへ切り替える(フェイルオーバー)仕組みを提供しているクラスタソフトウェアです。 Pacemakerの役割としては、クラスタ内のリソース(サービス、IPアドレス、ストレージなど)を監視・制御し、障害発生時に自動的に別ノードへ切り替える(フェイルオーバー)仕組みを提供します。   動作についてですが、Pacemaker単体では動作せず、 クラスタ通信レイヤー(CorosyncやHeartbeat)と連携してノード間の状態を共有します。 サービスの起動・停止・監視を実行する際は、スクリプトを使用して制御します。     Corosyncとは? Pacemakerを利用するにあたり、クラスタ通信レイヤーである「Corosync」を今回利用していきます。 Corosyncは、オープンソースのクラスタ通信エンジンで、Linux環境で高可用性クラスタを構築する際に、 ノード間の状態同期やメッセージ交換を担うコンポーネントとなります。 主な役割として、クラスタ通信の基盤として複数ノード間で「誰が生きているか(ノードの稼働状態)」を共有してくれます。 クラスタ動作のフェイルオーバーについてはトリガーとして、ノード障害を検知し、Pacemakerに通知することでリソース移動を行い、冗長性を確保しております。   PacemakerとCorosyncの役割をおさらいしておきましょう。 Pacemaker :リソース管理(サービス、IP、ストレージ) Corosync :クラスタ通信(ノード間の状態同期) PacemakerはCorosyncから「ノード障害」や「クラスタ状態」の情報を受け取り、リソースをどのノードで稼働させるかを判断します。 つまり、PacemakerとCorosyncを用いることで、IoT環境に「高可用性クラスタ」を構築できるということです。 前段について記載してきましたが、 次回は実際に、Raspberry PiにPacemakerとCorosyncの設定を行い、クラスタ構築手順とスイッチオーバー、スイッチバック、フェイルオーバーといった動作確認を通じて、IoTでの高可用性を実践していきます。

動画

書籍