What is Miniviz?
Miniviz is a service that allows you to easily store, visualize, and receive alerts for IoT data and images.
It is well-suited for PoC projects and learning purposes.
In this guide, we’ll build a simple surveillance-camera-like system using a Raspberry Pi and a USB camera.
Part #1 (Monitoring temperature and humidity with ESP32):
https://dev.to/yoshidataisei/how-to-send-esp32-sensor-data-to-miniviz-for-real-time-visualizationminiviz-1-59na
What we will do
We will connect a Raspberry Pi to a USB camera and send images to Miniviz.
:::note info
Image upload is available only with the Pro plan.
:::
What you need
- Raspberry Pi
- Using VS Code Remote SSH is convenient
- USB camera
- Miniviz Project ID and Token
Connecting the Raspberry Pi and USB Camera
Connect the USB camera and run the lsusb command.
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カメラ
You can check the USB camera device file.
$ 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
Checking the image captured by the camera
$ sudo apt-get install fswebcam
$ fswebcam -r 640x480 --no-banner image.jpg
The image quality isn’t great, but it works.
(Open the image via GUI or download it locally using scp, etc.)
(((Yes… my room is really cold…)))
Sending camera images to Miniviz
Overall steps:
- Obtain your Project ID and Token
- Call the Image API and try sending a sample image
- If it works, send actual camera images using the API
1. Obtain your Project ID and Token
Get your Project ID and Token from the Miniviz dashboard.
Create a project → then retrieve the Project ID and Token.
2. Call the Image API to send a sample image
First, try sending the sample image you captured earlier.
API: Send an image in the request body
POST https://api.miniviz.net/api/project/{project_id}/image?token={token}
Request body
{
"timestamp": 1717587812345,
"label_key": "raspberry_pi_cam",
"image_name": "camera.jpg",
"image_base64": "base64_encoded_image_data"
}
Sending a sample image (Python)
#!/usr/bin/env python3
"""
figure image to miniviz
"""
import requests
import base64
import os
from datetime import datetime, timezone
# Settings
PROJECT_ID = "PROJECT_ID"
TOKEN = "TOKEN"
API_URL = "https://api.miniviz.net"
IMAGE_PATH = "image.jpg" # The captured image, or any sample image
LABEL_KEY = "raspberry_pi_cam"
# Encode image as base64
with open(IMAGE_PATH, "rb") as f:
image_data = f.read()
image_base64 = base64.b64encode(image_data).decode('utf-8')
# Send request
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}")
Checking on Miniviz
When you run Preview…
3. Sending camera images periodically
Once the sample code works, you can start sending camera images at regular intervals.
Code
The full code is provided at the end of this document.
Viewing images in the Database
You can check the uploaded data from the Database menu.
All sent images are stored in the database.
If nothing appears here, the data transmission failed.
Please check the logs on your device.
Displaying images in Visualize
You can create graphs from the Visualize menu.
You can customize the graph type and how the data is displayed.
Sample Code (Periodic Sending)
#!/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")
Lastly
You can also keep the video locally and send only snapshots, which can still be quite practical.
As a more advanced use case, combining images with AI to trigger notifications could be an interesting approach.







Top comments (0)