Hardware bill of materials and setup instructions
Link to the Ubuntu 18.04 image for the Raspberry Pi 3
The application will be coded in python 3. The associated pip version needs to be installed:
$ sudo apt install python3-pip
Picamera can be installed directly via pip:
$ sudo pip3 install picamera
To configure the Raspberry Pi to enable the camera module, open up the board configuration file with a text editor:
$ sudo nano /boot/firmware/config.txt
Add the following line to enable the camera:
start_x=1
While the official image includes compatible firmware, bootloader and kernel, there are a few packages available in an unofficial PPA (ppa:ubuntu-raspi2/ppa) which are useful on the Raspberry Pi, including:
libraspberrypi-bin - VideoCore utilities from https://github.com/raspberrypi/userland such as vcgencmd, raspistill, etc.
To install required but the missing libraries:
$ sudo add-apt-repository ppa:ubuntu-raspi2/ppa
$ sudo apt-get update
$ sudo apt-get install libraspberrypi-bin
Create a project directory. In the project directory, create a python file with a text editor:
$ sudo nano ipcamera.py
Then enter the following script that will stream the camera input to a web server:
#!/usr/bin/env python3
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server
PAGE="""\
<html>
<head>
<title>Your Ubuntu IP Camera Appliance</title>
</head>
<body>
<h1>Ubuntu IP Camera Appliance</h1>
<img src="stream.mjpg" width="1280" height="720" />
</body>
</html>
"""
class StreamingOutput(object):
def __init__(self):
self.frame = None
self.buffer = io.BytesIO()
self.condition = Condition()
def write(self, buf):
if buf.startswith(b'\xff\xd8'):
# New frame, copy the existing buffer's content and notify all
# clients it's available
self.buffer.truncate()
with self.condition:
self.frame = self.buffer.getvalue()
self.condition.notify_all()
self.buffer.seek(0)
return self.buffer.write(buf)
class StreamingHandler(server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.send_response(301)
self.send_header('Location', '/index.html')
self.end_headers()
elif self.path == '/index.html':
content = PAGE.encode('utf-8')
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.send_header('Content-Length', len(content))
self.end_headers()
self.wfile.write(content)
elif self.path == '/stream.mjpg':
self.send_response(200)
self.send_header('Age', 0)
self.send_header('Cache-Control', 'no-cache, private')
self.send_header('Pragma', 'no-cache')
self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
self.end_headers()
try:
while True:
with output.condition:
output.condition.wait()
frame = output.frame
self.wfile.write(b'--FRAME\r\n')
self.send_header('Content-Type', 'image/jpeg')
self.send_header('Content-Length', len(frame))
self.end_headers()
self.wfile.write(frame)
self.wfile.write(b'\r\n')
except Exception as e:
logging.warning(
'Removed streaming client %s: %s',
self.client_address, str(e))
else:
self.send_error(404)
self.end_headers()
class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
allow_reuse_address = True
daemon_threads = True
with picamera.PiCamera(resolution='1280x720', framerate=24) as camera:
output = StreamingOutput()
camera.start_recording(output, format='mjpeg')
try:
address = ('', 8000)
server = StreamingServer(address, StreamingHandler)
server.serve_forever()
finally:
camera.stop_recording()
Run $ python ipcamera.py
to launch the application.
The video stream is accessible through any browser from any computer in the local network.
http://<board IP address>:8000/
The network IP address of the board can be obtained via command: hostname -I
.
The firewall can be configured to allow access to the video stream from any computer connected to the web.
In the same project directory, create the snapcraft.yaml file for the application:
$ sudo nano snapcraft.yaml
The content of the snapcraft.yaml file is below:
name: rpi-ipcamera
version: '0.1'
summary: demo IP camera app on Ubuntu for the Raspberry Pi 3
description: |
A demo IP camera appliance on Ubuntu. Video from a camera attached to the
Raspberry Pi CSI interface is streamed to the web on port 8000.
To watch the video stream go to http://<IP address of your Board>:8000/
grade: stable
confinement: strict
base: core18
architectures:
- build-on: armhf
run-on: armhf
apps:
ipcamera:
command: ipcamera
daemon: simple
plugs:
- mount-observe
- network
- network-bind
- opengl
parts:
picamera:
plugin: python
python-version: python3
python-packages:
- picamera
build-environment:
- READTHEDOCS: 'True'
pilibs:
plugin: nil
override-pull: |
sudo add-apt-repository ppa:ubuntu-raspi2/ppa
sudo apt-get update
build-packages:
- software-properties-common
after: [ picamera ]
ipcamera:
source: .
plugin: nil
override-build: |
mkdir -p $SNAPCRAFT_PART_INSTALL/bin
cp ipcamera $SNAPCRAFT_PART_INSTALL/bin/
stage-packages:
- libraspberrypi-bin
after: [ pilibs ]
The application snap will be built in a lightweight virtual machine on the Raspberry Pi. To this end, LXD needs to be installed and initialised.
$ sudo snap install lxd
$ sudo lxd init
After the installation, a VM instance of Ubuntu 18.04 will be created to build the snap.
$ sudo lxd launch bionic
The snap can be built by simply executing the snapcraft command in the project directory:
$ sudo lxc exec xenial — bash
$ mkdir ipcamera && cd ipcamera
$ wget https://raw.githubusercontent.com/xxl007/ipcamera-snap/master/snapcraft.yaml
$ wget https://raw.githubusercontent.com/xxl007/ipcamera-snap/master/ipcamera
$ snapcraft
To share your snaps you need to publish them in the Snap Store. First, create an account on the dashboard. Here you can customise how your snaps are presented, review your uploads and control publishing.
You’ll need to choose a unique “developer namespace” as part of the account creation process. This name will be visible by users and associated with your published snaps.
Make sure the snapcraft command is authenticated using the email address attached to your Snap Store account:
$ snapcraft login
Use snapcraft to push the snap to the Snap Store.
$ snapcraft push --release=edge ipcamera_*.snap
If you’re happy with the result, you can commit the snapcraft.yaml to your GitHub repo and turn on automatic builds so any further commits automatically get released to edge, without requiring you to manually build locally.
Follow the instructions to download Ubuntu Core 18 for the Raspberry Pi 3
Install your snap from the global snap store on your board running Ubuntu Core.
snap install ipcamera
Upon installation, the video stream is accessible through any browser from any computer in the local network. (Do not forget to connect and enable the camera in the configuration file as described above).
http://<board IP address>:8000/
$ snapcraft release ipcamera 1 candidate
$ snap refresh