Minivizとは?
IoTのデータや画像を簡単にデータ格納・可視化・通知が行えるサービスです。
PoCや学習用途に向いています。
今回はラズパイとカメラをつかってお手軽な監視カメラっぽいものをつくります。
作った経緯など
#1はこちら(ESP32で温度・湿度のモニタリング)
ここで行うこと
Raspberry PiとUSBカメラを接続してMinivizに画像を送信します。
画像送信機能はProプランのみです。無料プランでは利用できません。
(お試しもできますのでご気軽にお問い合わせください)
用意するもの・環境
- Raspberry Pi
- sshはvscodeのリモートアクセスを利用すると便利です
- USBカメラ
- MinivizのプロジェクトIDとトークン
Raspberry PiとUSBカメラの接続
USBカメラを接続して lsusb コマンドを実行します。
pi@raspberrypi:~ $ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 003: ID 0424:2514 Microchip Technology, Inc. (formerly SMSC) USB 2.0 Hub
Bus 001 Device 004: ID 0424:7800 Microchip Technology, Inc. (formerly SMSC)
Bus 001 Device 007: ID 0411:02da BUFFALO INC. (formerly MelCo., Inc.) USB 2.0 Camera // これがUSBカメラ
USBカメラのデバイスファイルが確認できます。
$ ls /dev/video*
/dev/video0 /dev/video10 /dev/video12 /dev/video14 /dev/video16 /dev/video20 /dev/video22 /dev/video31
/dev/video1 /dev/video11 /dev/video13 /dev/video15 /dev/video18 /dev/video21 /dev/video23
カメラで撮った画像を確認
$ sudo apt-get install fswebcam
$ fswebcam -r 640x480 --no-banner image.jpg
画質はイマイチですがとれています。(画像はGUIで開くか、scp等でローカルに落としてください)
(((そうなんです、私の部屋寒いです....)))
カメラの画像をMinivizに送信
大まかな手順
- プロジェクトIDとトークンを取得
- 画像APIを呼び出してサンプル画像を送信してみる
- 問題がなければ、画像APIを呼び出してカメラの画像を送信
1. プロジェクトIDとトークンを取得
プロジェクトIDとトークンを取得します。
プロジェクト作成 -> プロジェクトIDとトークンを取得
2. 画像APIを呼び出してサンプル画像を送信
まずは先ほどのサンプルキャプチャ
API: リクエストボディに画像を送信
POST https://api.miniviz.net/api/project/{project_id}/image?token={token}
リクエストボディ
{
"timestamp": 1717587812345,
"label_key": "raspberry_pi_cam",
"image_name": "camera.jpg",
"image_base64": "base64_encoded_image_data"
}
サンプル画像を送信(Python)
#!/usr/bin/env python3
"""
figure image to miniviz
"""
import requests
import base64
import os
from datetime import datetime, timezone
# 設定
PROJECT_ID = "PROJECT_ID"
TOKEN = "TOKEN"
API_URL = "https://api.miniviz.net"
IMAGE_PATH = "image.jpg" # 先ほどの画像。もしくはサンプル画像
LABEL_KEY = "raspberry_pi_cam"
# 画像をbase64エンコード
with open(IMAGE_PATH, "rb") as f:
image_data = f.read()
image_base64 = base64.b64encode(image_data).decode('utf-8')
# リクエスト送信
url = f"{API_URL}/api/project/{PROJECT_ID}/image"
payload = {
"timestamp": int(datetime.now(timezone.utc).timestamp() * 1000),
"label_key": LABEL_KEY,
"image_name": os.path.basename(IMAGE_PATH),
"image_base64": image_base64
}
try:
response = requests.post(url, json=payload, params={"token": TOKEN})
response.raise_for_status()
print("✅ Send successful")
print(response.json())
except requests.exceptions.HTTPError as e:
print(f"❌ Error: HTTP {e.response.status_code}")
print(e.response.text)
except Exception as e:
print(f"❌ Error: {e}")
Miniviz上で確認
プレビューを実行すると・・・
3. カメラの画像を定期送信させる
サンプルコードに問題なければ、カメラの画像を定期送信します。
コード
コードは巻末に記載しましたので参照してください。
画像をデータベースで表示
データベースメニューからデータを確認します。
送信されたデータはデータベースに保存されます。
※ここに表示されない場合はデータ送信が失敗しています。再度デバイス側のログなどを確認してください。※
画像をVisualizeで表示
Visualizeメニューからグラフを作成します。
グラフの種類やデータの表示形式などを設定できます。
サンプルコード(定期送信)
#!/usr/bin/env python3
"""
Raspberry Pi USB Camera to Miniviz
"""
import requests
import base64
import os
import subprocess
import time
from datetime import datetime, timezone
# Miniviz configuration
PROJECT_ID = "PROJECT_ID"
TOKEN = "TOKEN"
API_URL = "https://api.miniviz.net"
LABEL_KEY = "raspberry_pi_cam"
# USB Camera configuration
DEVICE = "/dev/video0"
RESOLUTION = "640x480"
IMAGE_PATH = "image.jpg"
# Send interval (seconds)
SEND_INTERVAL = 60 # 1 minute
def capture_image():
"""Capture image with USB camera"""
cmd = [
"fswebcam",
"-d", DEVICE,
"-r", RESOLUTION,
"--no-banner",
"-S", "5",
IMAGE_PATH
]
print("[Info] Capturing image...")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"[Error] Capture failed: {result.stderr}")
return False
print("[Info] Image captured successfully")
return True
def encode_image_to_base64(image_path):
"""Encode image file to base64"""
with open(image_path, "rb") as f:
image_data = f.read()
return base64.b64encode(image_data).decode('utf-8')
def send_image_to_miniviz(image_path):
"""Send image to Miniviz API"""
url = f"{API_URL}/api/project/{PROJECT_ID}/image"
# Encode image to base64
image_base64 = encode_image_to_base64(image_path)
# Request payload
payload = {
"timestamp": int(datetime.now(timezone.utc).timestamp() * 1000),
"label_key": LABEL_KEY,
"image_name": os.path.basename(image_path),
"image_base64": image_base64
}
try:
response = requests.post(url, json=payload, params={"token": TOKEN})
response.raise_for_status()
print("[Info] Send successful")
print(response.json())
return True
except requests.exceptions.HTTPError as e:
print(f"[Error] HTTP {e.response.status_code}")
print(e.response.text)
return False
except Exception as e:
print(f"[Error] {e}")
return False
def cleanup_image(image_path):
"""Delete sent image file (to save disk space)"""
try:
if os.path.exists(image_path):
os.remove(image_path)
print(f"[Info] Cleaned up: {image_path}")
except Exception as e:
print(f"[Warning] Failed to delete {image_path}: {e}")
def main():
"""Main process"""
# Capture image with USB camera
if not capture_image():
print("[Error] Failed to capture image")
return
# Send to Miniviz
success = send_image_to_miniviz(IMAGE_PATH)
# Delete image file only on success (to save disk space)
if success:
cleanup_image(IMAGE_PATH)
if __name__ == "__main__":
print("Starting miniviz image send test (press Ctrl+C to stop)")
try:
while True:
main()
time.sleep(SEND_INTERVAL)
except KeyboardInterrupt:
print("\n[Info] Stopped by user")
最後に
動画はローカルに残しておいて、キャプチャを送るだけでも実用性がありそうです。
発展系として画像をAIと組み合わせて、通知させるような仕組みも面白そう。






