【第1回】Geminiで温度計を読み取ってみよう ― reCameraではじめる計器デジタル化入門

製造業や農業などにおいて、温度管理は多くの現場で行われています。温度ロガーなどの自動化ソリューションはたくさんありますが、まだまだ多くの現場では、担当者が1日に何度も温度計を目視で確認し、紙の記録簿に手書きする業務が残っています。

「IoTセンサーを後付けすれば解決する」と思われるかもしれませんが、既存の温度計にネットワーク対応の温度センサーを導入するにはコストも手間もかかります。そして何より、既に設置されている温度計が無駄になってしまいます。

この連載では、Seeed Studio社のエッジAIカメラ reCameraを使って、既存の温度計をそのままカメラで撮影し、GoogleのマルチモーダルAI Geminiで読み取る方法を紹介します。

第1回となる今回は、カメラで撮影した温度計の画像から値を読み取って、メールで通知するNode-REDフローを作ります。

連載の全体像

テーマキーワード
第1回(本記事)reCamera単体でフロー開発Node-RED、Gemini、メール通知
第2回複数台reCameraとゲートウェイ連携reTerminal、Google Sheets連携、スケールの課題
第3回enebularによるセキュアなクラウド連携実行環境間の接続、クレデンシャル管理

reCameraとは

reCameraはSeeed Studio社が開発したオープンソースの小型AIカメラです。手のひらに収まるサイズでありながら、RISC-VベースのSoC(SG2002)を搭載し、エッジで1 TOPSのAI処理能力を持っています。

以前の記事で紹介しておりますが、本記事で特に重要な特徴は以下の3点です。

  • Node-REDが内蔵されており、撮影・録画・保存をフローから制御できる
  • USB接続(Type-C)でホストPCから給電とネットワーク接続が同時に行える
  • カメラ用三脚のネジやマグネットがケースに組み込まれ、設置が簡単に行える

2026年3月時点で、1万円以下で購入できるので産業用カメラとしては非常に手頃です。

reCamera
各辺4cmの立方体よりも小さい

今回のゴール

reCamera1台でNode-REDフローを開発し、以下を実現します。

  • reCameraのカメラで温度計の表示部分を定期的に撮影する
  • 撮影画像をGemini APIに送信し、温度・湿度などの値を構造化JSONとして取得する
  • メールノードで結果を確認する

まずは「reCameraだけで、ここまでできる」を体感してみましょう。

reCameraでデジタル温度計を撮影している様子(Gemini generated)

準備するもの

機材・サービス備考
reCamera 2002w または 2002どちらのモデルでもOK
USBケーブル(Type-C)PCからの給電と接続
Ethernetアダプタ+LANケーブルネットワーク接続(Wi-Fiモデルは不要)
PC(Webブラウザ)Node-REDフローエディタへのアクセス用
Gemini APIキーGoogle AI Studio(https://aistudio.google.com/)から無料で取得可能
読み取り対象の温度計デジタル温度計、温湿度計など

ステップ1:reCameraでの準備

reCameraをUSBケーブルでPCに接続します。reCameraはUSB接続時にネットワークデバイスとして認識され、IPアドレス 192.168.42.1 が割り当てられます。接続方法については、前回記事を参照してください。

Node-REDが動くカメラ reCamera | enebular blog

Workspaceを開いたら、ノードをパレットの管理からインストールします。

  • base64ノード: node-red-node-base64
  • image-toolノード: node-red-contrib-image-output
  • emailノード: node-red-node-email

ステップ2:フローの全体像を理解する

これから作るフローは、大きく4つのパートに分かれます。

【撮影】
  [inject] → [capture image]

【画像取得】
  [complete] → [delay 5秒] → [対象ファイル名取得] → [fileの読み出し] → 

【API連携】
  → [指示(プロンプト作成)] → [base64変換] → [推論(APIリクエスト生成)]
      → [http request] →

【メール通知】
   → [move] → [json] → [email]

順を追って各パートを説明します。


ステップ3:撮影

injectノード(定期トリガー)

温度計を定期的に撮影するためのトリガーです。

  • パレットから「inject」ノードをワークスペースに配置します
  • ダブルクリックして設定を開き、「繰り返し」を「指定した時間間隔」に設定します
  • 間隔はデモなら30秒〜1分程度、本番運用を想定するなら15分程度です。

capture imageノード(画像キャプチャ)

node-red-contrib-sscmaのcapture imageノードを使って、カメラから静止画を取得し保存します。

  • パレットから「capture image」ノードを配置します
  • デフォルト設定のままで動作します
  • captureノードには次の出力のポッチがありません。ファイルが保存されるだけとなります。

ステップ4:画像取得

撮影した画像をSDカードまたはローカルストレージから読み出して、プレビュー表示します。Linkノードでステップ5のフローに接続しています。

[complete: inject] → [delay 5秒] → [exec] → [read file] → [image preview]

completeノードは基本的にずっと稼働しているので、画像が確実に保存されるであろう5秒後にinjectノードからの完了を受け取って、フォルダにある一番新しい画像を取得します。execノードでは、Linuxのコマンドを実行できます。

ls -t /userdata/Images/*.jpg /userdata/Images/*.png 2>/dev/null | head -n 1

image previewノードは画像を表示するためのノードです。撮影がうまくいっているか、温度計の表示が判読できるかを目視確認できます。


ステップ5:API連携

撮影した画像をGemini APIに送り、温度計の値を構造化されたJSONとして受け取ります。

templateノード「指示」(プロンプト生成)

Gemini APIに渡すプロンプト(指示文)を生成するtemplateノードです。

# 指示
添付された画像から、デジタル測定器に表示されている「温度」「湿度」「日付」「時刻」の情報を読み取り、指定のJSON形式で出力してください。

# 抽出ルール
1. 数値のみを抽出してください(単位の "°C" や "%" は含めない)。
2. 日付は、画像から読み取ったら、MM/DDの形式にしてください。
3. 時刻は、画像から読み取れる形式で抽出してください。
4. もし画像から特定の項目が読み取れない場合は、値を null にしてください。
5. 推測ではなく、画像に表示されている文字に忠実に読み取ってください。
6. 出力はJSON形式のみとし、jsonなどの表記、解説や前置き、囲む記号は不要です。
# 注意
- Markdownのコードブロック(```json ... ```)は絶対に使用しないでください。
- 出力は { から始まり } で終わる純粋なJSON文字列のみにしてください。
- 文末に余計な改行やテキストを含めないでください。

# 出力フォーマット (JSON)
{
  "measurement": {
    "temperature": float,
    "humidity": int,
    "date": "string",
    "time": "string"
  },
  "confidence": "high/medium/low"
}

base64ノード(要確認)

撮影画像をBase64エンコードする処理です。captureノードからの出力画像をBase64文字列に変換します。

functionノードでも代替可能です。

msg.payload = msg.payload.toString('base64');
return msg;

functionノード「推論」(APIリクエスト生成)

Gemini APIのリクエストボディを組み立てるfunctionノードです。

const API_KEY = "YOUR_GEMINI_API_KEY";  // ← 取得したAPIキーに置き換える

// APIのリクエストボディを作成
msg.payload = {
    "contents": [{
        "parts": [
            { "text": msg.prompt },
            {
                "inline_data": {
                    "mime_type": "image/jpeg", // 画像形式に合わせて変更 (pngなら image/png)
                    "data": msg.payload
                }
            }
        ]
    }]
};

// 最新モデルのURLを設定 (gemini-2.5-flash を使用)
msg.url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=${API_KEY}`;

return msg;

http requestノード

Gemini APIにPOSTリクエストを送信するノードです。

  • パレットから「http request」ノードを配置します
  • メソッドを「POST」に設定します
  • URLは空欄のままにします(functionノードの msg.url が使われます)
  • ヘッダーはContent-Typeを選択して、値をapplication/jsonに設定します。
  • 戻り値は「JSONオブジェクト」に設定します

email通知

changeノード「move」(レスポンス整形)

Gemini APIのレスポンスから、生成されたテキスト部分を取り出すfunctionノードです。

msg.payload.candidates[0].content.parts[0].text

msg.headersを削除します。理由はコラムを参照してください。

jsonノード

文字列をJSONオブジェクトにパースする標準ノードです。

  • パレットから「json」ノードを配置します
  • デフォルト設定のままで動作します

templateノード

メールの本文を作るためのノードです。出力は平文です。msg.topicの内容が件名になります。

{{{payload.measurement.date}}} {{payload.measurement.time}}、現在の温湿度は以下です。

温度:{{payload.measurement.temperature}}
湿度:{{payload.measurement.humidity}}

emailノード

メールを送信します。Gmailの場合の設定はこちらの過去記事を参考にしてください。

メールノードを使おう | enebular blog


コラム:メールが添付ファイルになる? msgオブジェクトの落とし穴

Node-REDではノード間をmsgオブジェクトが流れていきますが、このmsgには自分が設定したプロパティだけでなく、前のノードが自動的に追加したプロパティも含まれています。

例えばHTTP requestノードでGemini APIを呼び出すと、APIのレスポンスヘッダーがmsg.headersとしてmsgに残ります。このmsgをそのままemailノードに渡すと、msg.headers内のcontent-typeが「application/json」になっているため、emailノードはpayloadをメール本文ではなく添付ファイルとして扱ってしまいます。結果として、本文が空で「noname」という謎の添付ファイルだけが届くことになります。

対策はシンプルで、emailノードの手前にchangeノードを置いてmsg.headersを削除するだけです。

この例に限らず、Node-REDではmsgオブジェクトが下流に進むほど不要なプロパティが蓄積していきます。意図しない動作に出会ったら、まずdebugノードでmsgの中身を確認してみてください。思わぬプロパティが悪さをしているかもしれません。


ステップ7:デプロイして動かす

フローが完成したら、右上の「デプロイ」ボタンをクリックします。

injectノードの左側にあるボタンをクリックするか、設定した間隔で自動的にフローが実行されます。

デバッグタブを開くと、以下のような出力が確認できるはずです。

{
  "temperature": 26.2,
  "humidity": 53,
  "date": "2/25",
  "time": "16:39",
  "confidence": "high"
}

温度だけでなく、湿度、温度計に表示されている日付や時刻、そして読み取りの確信度まで、1回のAPIコールで構造化データとして取得できています。

メールボックスを確認するとメールが届いています。


なぜGemini 汎用的なLLMを使った理由

当初はエッジAIでの読み取りを検討していました。しかし実際に試してみると、数字を検出できるものの、意外と手間がかかることがわかりました。

エッジAIでは、数字を検出できるものの、意味のまとまりは考慮されません。それぞれのコンテキストも踏まえて意味のある数字にするためのロジックも書かなければなりません。

Gemini APIを使うと、これらの処理がすべて不要になります。画像をそのまま送って「読み取ってJSONで返して」と頼むだけ。前処理なし、パース処理なし。しかも温度以外の情報もまとめて取得できます。


レガシー計器のデジタル化

このアプローチの面白いところは、温度計に限らないということです。工場にはネットワーク化されていない計器が数多く存在します。圧力計、流量計、電力メーター、水位計……これらすべてに対して、reCameraとGemini APIの組み合わせで同じアプローチが適用できそうです。

既存設備に手を加えず、カメラを前に置くだけでデータのデジタル化ができる。IoT化のハードルが最も低いアプローチになるのではないでしょうか。


設置のコツ

実際に温度計の前にreCameraを設置する際のポイントをいくつか紹介します。

距離は5〜15cmが目安です。Gemini APIはマルチモーダルAIなので厳密なフレーミングは不要ですが、温度計の表示が画角内で十分に判読できるサイズであることが前提です。

冷蔵庫のように結露が発生しやすい環境では、カメラを扉の外側に設置し、ガラス窓越しに読み取る構成をお勧めします。

LED補助光の直接反射を避けるため、カメラをやや斜め(5〜10°)に設置すると良いでしょう。


まとめと次回予告

今回はreCamera1台で、温度計の値をGemini APIで読み取り、メールで受け取るフローを開発しました。reCameraのNode-REDだけで完結する、とてもシンプルな構成です。

ポイントは以下の通りです。

  • reCameraはNode-REDとカメラ機能が内蔵されており、USB接続でPCからすぐに開発を始められる
  • Gemini APIを使うことで、画像前処理なしに温度・湿度を構造化データとして取得できる
  • まずは1台で「動くもの」をすぐに作れる

ただし、ここで得られたデータはメールで通知されるだけです。活用しやすいデータの保管方法が欲しいところです。また、温度計が1台ならこれで良いのですが、冷蔵庫が5台、10台と増えたらどうなるでしょうか。

次回は、複数のreCameraをゲートウェイ(reTerminal)に接続し、読み取ったデータをGoogle Spreadsheetに自動記録する構成をやってみたいと思います。