14.3.3 Make a web capture with camera

In the previous section, we used the GPIO extension to use the I2C sensor. The BMP180 senses ambient temperature, air pressure, and altitude data. In this section, we add a camera and make a simple web camera that collection of environmental images and data.

Connect the RPi-Spark and BMP180 modules together as shown below.

I2C BMP180 + Camera

First, we explain the composition of the application: first build a SensorDataPool class for getting sensor data, it will automatically get data from sensors and cameras at specified intervals. The data obtained last time can be obtained through its property sensorData. Then we set up an http web server to wait for the user's data request, using port 8080. When a client request this server using a browser, we obtain the most recently collected data through the SensorDataPool.sensorData property, and overlay the environment data on the captured image then sent to the client.

This a simple webcam application and process is shown in the figure:

I2C BMP180

The use of SensorDataPool is responsible for data collection to avoid hardware resource conflicts caused by multi-user requests.

Create a file named: SensorDataPool.py and type the content:

import time
import threading

from picamera import PiCamera
from picamera import Color

FILENAME_CAPTURE_IMG = "foo.jpg"

class SensorDataPool:
    _interval = None
    _imagePath = None
    _timer = None
    _bmp085 = None
    _camera = None

    count = 0
    sensorData = None

    def __init__(self, interval = 2, imagePath = "./", enableBMP=True):
        self.sensorData = {}

        self._interval = interval
        self._imagePath = imagePath + FILENAME_CAPTURE_IMG

        if enableBMP: self._initBMPSensor()

        self._camera = PiCamera()
        self._camera.rotation = 90
        self._camera.preview_fullscreen=False
        # camera.preview_window=(0, 0, 800, 1066)
        self._camera.resolution = (640, 480)
        self._camera.annotate_text_size = 12
        self._camera.annotate_foreground = Color('white')
        #self._camera.annotate_background = Color('white')
        self._camera.start_preview()

    def _initBMPSensor(self):
        import Adafruit_BMP.BMP085 as BMP085 # Imports the BMP library
        self._bmp085 = BMP085.BMP085()

    def _callbackTimer(self):
        self.count = self.count + 1
        self._readSensorData()
        self._timer = threading.Timer(self._interval, self._callbackTimer)
        self._timer.start()

    def _captureImage(self):
        if self._bmp085!=None: 
            annotateText = u"{} | Temp: {:.1f} *C | Baro: {:.0f} hPa | Alt: {:.2f} m".format(
                self.sensorData["date"],
                self.sensorData["temp"],
                self.sensorData["baro"] / 100, 
                self.sensorData["alt"])
        else:
            annotateText = u"{}".format(self.sensorData["date"])

        self._camera.annotate_text = annotateText
        # Camera warm-up time
        self._camera.capture(self._imagePath)

    def _readSensorData(self):
        self.sensorData["date"] = time.strftime("%Y-%m-%d %a %H:%M:%S")
        if self._bmp085!=None:
            self.sensorData["temp"] = self._bmp085.read_temperature()
            self.sensorData["baro"] = self._bmp085.read_pressure()
            self.sensorData["alt"] = self._bmp085.read_altitude()

        self._captureImage();
        self.sensorData["image"] = self._imagePath

        print(self.sensorData)

    def start(self):
        self._timer = threading.Timer( 1, self._callbackTimer )
        self._timer.start()

    def stop(self):
        self._timer.cancel()

Next we use the build http server WebRequestHandler and RPi-Spark application:

from JMRPiFoundations.Skeleton.RPiSparkModule import RPiSparkModule
from os import curdir, sep, path
import sys

from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from SensorDataPool import SensorDataPool 

SENSOR_DATA_POOL = SensorDataPool( interval = 4, imagePath = "./" )

PORT_NUMBER = 8080
FILENAME_INDEX_HTML = "index.html"

class WebRequestHandler(BaseHTTPRequestHandler):

    def sendData(self):
        outputPage = None
        if self.path=="/":
            self.path= FILENAME_INDEX_HTML
            template = open( curdir + sep + self.path ).read()
            outputData = SENSOR_DATA_POOL.sensorData
            outputPage = template.format(
                outputData["image"],
                outputData["date"],
                outputData["temp"], 
                outputData["baro"], 
                outputData["alt"])

        try:
            print(FILENAME_INDEX_HTML)
            print(curdir + self.path, "index.html")
            print("load file: ",self.path)

            self.send_response(200)
            self.send_header('Content-type','text/html')
            self.end_headers()

            if outputPage != None:
                self.wfile.write(outputPage)
            else:
                # Send the html message
                f = open( curdir + sep + self.path )
                self.wfile.write(f.read())
                f.close()

        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)

    def do_GET(self):
        """
            Handler for the GET requests
        """
        self.sendData()
        return

class WebCamera(RPiSparkModule):
    WebServer = None

    def onKeyButtonUp(self, channel):
        if channel == self.RPiSparkConfig.BUTTON_ACT_A:
            self.stopWebCamera()
            sys.exit()

    def stopWebCamera(self):
        print('\nShutting down the WebCamera server')
        self.releaseKeyButtons()
        SENSOR_DATA_POOL.stop()
        self.WebServer.socket.close()

    def setup(self):
        # setup all key buttons to INT mode, same time query work fine
        self.initKeyButtons("INT")

    def run(self):
        SENSOR_DATA_POOL.start()

        # Drawing the ball on the screen
        self.RPiSpark.Screen.clear()
        tip = "RPi-Spark WebCapture\nPORT: {}\nQuit: Ctrl + C  or\n      Button A".format(PORT_NUMBER)
        self.RPiSpark.Screen.write(tip, xy=(4,4), spacing=2)
        self.RPiSpark.Screen.refresh()

        try:
            #Create a web server and define the handler to manage the
            #incoming request
            self.WebServer = HTTPServer(('', PORT_NUMBER), WebRequestHandler)
            print('Started WebCamera httpserver on port: ', PORT_NUMBER)
            print('------------------------------------------------------------')
            print('Quit: Ctrl + C  or  Button A')

            #Wait forever for incoming htto requests
            self.WebServer.serve_forever()

        except KeyboardInterrupt:
            self.stopWebCamera()

Save as 14_3_3_webcamera.py and enter the command:

rspk 14_3_3_webcamera -f

At this time, RPi-Spark's OLED display should display the following information:

RPi-Spark WebCapture

Then use any browser to access the address: 192.168.2.18:8080 (the IP address set by our tree) You can see the remote image and data:


 

Was this article helpful?

YES     |     NO

 

Enjoying the project? Spotted a mistake? Any opinions on the website? Let us know!