Using the Camera Widget with a Raspberry Pi

May 23, 2024

The Camera Widget in ioCtrlMQ allows you to display a live video feed directly on your dashboard. This is incredibly useful for visual monitoring, from keeping an eye on a 3D printer to checking on a remote location. A Raspberry Pi with a camera module is a popular and cost-effective way to create such a feed.

This guide will walk you through a common method to get your Raspberry Pi's camera stream working with the ioCtrlMQ Camera Widget.

What You'll Need

  1. A Raspberry Pi (Model 3B+ or newer recommended).
  2. A Raspberry Pi Camera Module.
  3. A power supply for the Pi.
  4. An SD card with Raspberry Pi OS installed.
  5. Access to your ioCtrlMQ dashboard.

The Core Concept: From Pi to Dashboard

The ioCtrlMQ Camera Widget works by pulling a video stream from a URL. Therefore, the main task is to make the Raspberry Pi's camera feed available at a stable URL. While there are many ways to achieve this (like WebRTC, HLS, etc.), one common and straightforward method for prototyping is to use a simple Python web server.

Raspberry Pi with camera module attached connected to a network

Step 1: Set Up Your Raspberry Pi

First, ensure your Raspberry Pi is set up, connected to your network (Wi-Fi or Ethernet), and you have access to the command line (via SSH or with a keyboard/monitor).

  1. Enable the Camera: Open the terminal and run sudo raspi-config. Navigate to Interface Options -> Legacy Camera and enable it. Reboot when prompted.

  2. Install Dependencies: We will use picamera2 and Flask to create the web server. Install them using pip:

    pip3 install picamera2 "flask[async]"
    

Step 2: The Python Streaming Script

Create a Python file on your Raspberry Pi, for example, app.py, and paste the following code into it. This script uses the picamera2 library to capture frames and Flask to serve them as a multi-part JPEG stream.

#!/usr/bin/env python3
import io
import time
from flask import Flask, Response
from picamera2 import Picamera2
from picamera2.encoders import JpegEncoder
from picamera2.outputs import FileOutput

app = Flask(__name__)

picam2 = Picamera2()
video_config = picam2.create_video_configuration(main={"size": (1280, 720)})
picam2.configure(video_config)

class StreamingOutput(io.BufferedIOBase):
    def __init__(self):
        self.frame = None
        self.condition = Condition()

    def write(self, buf):
        with self.condition:
            self.frame = buf
            self.condition.notify_all()

output = StreamingOutput()
picam2.start_recording(JpegEncoder(), FileOutput(output))

def generate():
    while True:
        with output.condition:
            output.condition.wait()
            frame = output.frame
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/stream')
def stream():
    return Response(generate(),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000, threaded=True)

Step 3: Run the Stream

In your Raspberry Pi's terminal, run the script:

python3 app.py

Your Raspberry Pi is now serving the camera feed. You can test this by opening a web browser on another computer on the same network and navigating to http://<YOUR_PI_IP_ADDRESS>:8000/stream. You should see the live video.

Step 4: Configure the ioCtrlMQ Widget

  1. Add a Camera Widget to your dashboard.
  2. Open the configuration sheet for the widget.
  3. Under API Configuration, set the URL to your Raspberry Pi's stream URL: http://<YOUR_PI_IP_ADDRESS>:8000/stream.
  4. Since the stream is the direct response, you do not need a "Data Path". You can leave this field blank.
  5. Set the polling interval to 0. This is important because the connection is a persistent stream, not something that needs to be polled.
  6. Save the configuration.

Your Camera Widget should now display the live feed from your Raspberry Pi. This setup is great for local networks. For accessing the stream over the internet, you would need to configure port forwarding on your router or use a tunneling service like ngrok, but be mindful of security implications.