From 4e4eed84bbcb1fe234ff9f5bdc1c4caf90e904b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 3 Jan 2013 00:39:17 +0100 Subject: [PATCH] Removed python based webcam support (didn't work well with the raspi), switched instead to external stream (mjpg-streamer being the preferred webcam server) --- README.md | 59 +++++++++++++++++++++++++++ printer_webui/server.py | 20 +--------- printer_webui/settings.py | 3 ++ printer_webui/static/css/ui.css | 8 ---- printer_webui/static/js/ui.js | 27 ------------- printer_webui/templates/index.html | 10 ++--- printer_webui/webcam.py | 64 ------------------------------ 7 files changed, 67 insertions(+), 124 deletions(-) delete mode 100644 printer_webui/webcam.py diff --git a/README.md b/README.md index 6efecc3e..ba9e4ee2 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ allows * reading the communication log and send arbitrary codes to be executed by the printer * moving the X, Y and Z axis (jog controls, although very ugly ones right now) * changing the speed modifiers for inner & outer wall, fill and support +* optional: visual monitoring of the printer via webcam stream integrated into the UI (using MJPG-Streamer) The intended usecase is to run the Printer WebUI on a single-board computer like the Raspberry Pi and a WiFi module, connect the printer to the server and therefore create a WiFi-enabled 3D printer. @@ -61,6 +62,60 @@ The following example config should explain the available options: # use this option to define the port to which to bind the server, defaults to 5000 port = 5000 + [webcam] + # use this option to enable display of a webcam stream in the UI, e.g. via MJPG-Streamer + stream = http://10.0.0.2:8080/?action=stream + +Setup on a Raspberry Pi running Raspbian +---------------------------------------- + +I currently run the Printer WebUI on a Raspberry Pi running Raspbian (http://www.raspbian.org/). For the basic +package you'll need Python 2.7 (should be installed by default), pip and flask: + + cd ~ + sudo apt-get install python-pip git + git clone https://github.com/foosel/PrinterWebUI.git + cd PrinterWebUI + pip install -r requirements.txt + +You should then be able to start the WebUI server: + + pi@raspberrypi ~/PrinterWebUI $ python -m printer_webui.server + * Running on http://0.0.0.0:5000/ + +If you also want webcam support, you'll need to download and compile MJPG-Streamer: + + cd ~ + sudo apt-get install libjpeg8-dev imagemagick + wget -Omjpg-streamer.tar.gz http://mjpg-streamer.svn.sourceforge.net/viewvc/mjpg-streamer/mjpg-streamer/?view=tar + tar xfz mjpg-streamer.tar.gz + cd mjpg-streamer + make + +This should hopefully run through without any compilation errors. You should then be able to start the webcam server: + + pi@raspberrypi ~/mjpg-streamer $ ./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so" + MJPG Streamer Version: svn rev: + i: Using V4L2 device.: /dev/video0 + i: Desired Resolution: 640 x 480 + i: Frames Per Second.: 5 + i: Format............: MJPEG + [...] + o: www-folder-path...: disabled + o: HTTP TCP port.....: 8080 + o: username:password.: disabled + o: commands..........: enabled + +If you now point your browser to http://:8080/?action=stream, you should see a moving picture at 5fps. +Open `~/.printerwebui/config.ini` and add the following lines to it: + + [webcam] + stream = http://:8080/?action=stream + +Restart the WebUI server and reload its frontend. You should now see a Webcam tab with content. + +If everything works, add the startup commands to `/etc/rc.local`. + Credits ------- @@ -76,3 +131,7 @@ It also uses the following libraries and frameworks for backend and frontend: * Knockout.js: http://knockoutjs.com/ * Flot: http://www.flotcharts.org/ * jQuery File Upload: http://blueimp.github.com/jQuery-File-Upload/ + +And this for Webcam support: + +* MJPG-Streamer: http://sourceforge.net/apps/mediawiki/mjpg-streamer/index.php?title=Main_Page diff --git a/printer_webui/server.py b/printer_webui/server.py index b8c36955..fada932b 100644 --- a/printer_webui/server.py +++ b/printer_webui/server.py @@ -7,7 +7,6 @@ from werkzeug import secure_filename from printer_webui.printer import Printer, getConnectionOptions from printer_webui.settings import settings -from printer_webui.webcam import hasWebcamSupport, Webcam import sys import os @@ -28,14 +27,10 @@ if not os.path.isdir(WEBCAM_FOLDER): app = Flask("printer_webui") printer = Printer() -if hasWebcamSupport(): - webcam = Webcam() -else: - webcam = None @app.route("/") def index(): - return render_template("index.html") + return render_template("index.html", webcamStream = settings().get("webcam", "stream")) #~~ Printer state @@ -261,19 +256,6 @@ def setSettings(): s.save() return getSettings() -#~~ webcam - -@app.route(BASEURL + "webcam/image", methods=["GET"]) -def getImage(): - if webcam is None: - abort(404) - - image = webcam.get() - strIO = StringIO.StringIO() - image.save(strIO, "JPEG", quality=80) - strIO.seek(0) - return send_file(strIO, mimetype="image/jpeg") - #~~ helper functions def sizeof_fmt(num): diff --git a/printer_webui/settings.py b/printer_webui/settings.py index 47a53c9c..7f3a278b 100644 --- a/printer_webui/settings.py +++ b/printer_webui/settings.py @@ -24,6 +24,9 @@ default_settings = { "server": { "host": "0.0.0.0", "port": 5000 + }, + "webcam": { + "stream": None } } diff --git a/printer_webui/static/css/ui.css b/printer_webui/static/css/ui.css index b2088360..148869ca 100644 --- a/printer_webui/static/css/ui.css +++ b/printer_webui/static/css/ui.css @@ -97,12 +97,4 @@ table th.gcode_files_action, table td.gcode_files_action { #webcam_container { height: 440px; background-color: #000000; -} - -#webcam_placeholder { - height: 440px; - line-height: 440px; - text-align: center; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); } \ No newline at end of file diff --git a/printer_webui/static/js/ui.js b/printer_webui/static/js/ui.js index a30a86b1..bfef9eb6 100644 --- a/printer_webui/static/js/ui.js +++ b/printer_webui/static/js/ui.js @@ -438,32 +438,6 @@ function DataUpdater(connectionViewModel, printerStateViewModel, temperatureView } var dataUpdater = new DataUpdater(connectionViewModel, printerStateViewModel, temperatureViewModel, speedViewModel, terminalViewModel); -function WebcamViewModel() { - var self = this; - - self.webcamUpdateInterval = 5000; - self.offlineUrl = "/static/img/webcam-offline.png"; - - self.url = ko.observable(undefined); - self.enabled = ko.observable(undefined); - - self.enabled.subscribe(function(newValue) { - if (newValue) { - self.requestData(); - } else { - $("#webcam_image") - } - }); - - self.requestData = function() { - if (!self.enabled()) - return; - self.url(AJAX_BASEURL + "webcam/image?" + (new Date()).getTime()); - setTimeout(self.requestData, self.webcamUpdateInterval); - } -} -var webcamViewModel = new WebcamViewModel(); - $(function() { //~~ Print job control @@ -603,7 +577,6 @@ $(function() { ko.applyBindings(printerStateViewModel, document.getElementById("jog")); ko.applyBindings(terminalViewModel, document.getElementById("term")); ko.applyBindings(speedViewModel, document.getElementById("speed")); - ko.applyBindings(webcamViewModel, document.getElementById("webcam")); //~~ startup commands diff --git a/printer_webui/templates/index.html b/printer_webui/templates/index.html index 5248a813..877e3b66 100644 --- a/printer_webui/templates/index.html +++ b/printer_webui/templates/index.html @@ -115,7 +115,7 @@
  • Jog
  • Speed
  • Term
  • -
  • Webcam
  • + {% if webcamStream %}
  • Webcam
  • {% endif %}
    @@ -216,15 +216,13 @@
    + {% if webcamStream %}
    -
    - -
    Offline
    +
    + {% endif %} diff --git a/printer_webui/webcam.py b/printer_webui/webcam.py deleted file mode 100644 index 79a111ed..00000000 --- a/printer_webui/webcam.py +++ /dev/null @@ -1,64 +0,0 @@ -# coding=utf-8 -__author__ = "Gina Häußge " -__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' - -try: - #Try to find the OpenCV library for video capture. - import cv -except: - cv = None - -try: - import VideoCapture as win32vidcap -except: - win32vidcap = None - -import PIL - -def hasWebcamSupport(): - if cv == None and win32vidcap == None: - return False - return True - -class Webcam(object): - def __init__(self): - self._cam = None - if cv != None: - self._cam = cv.CreateCameraCapture(-1) - elif win32vidcap != None: - try: - self._cam = win32vidcap.Device() - self._cam.setResolution(640, 480) - except: - pass - - def get(self): - if self._cam is None: - return None - - if cv is not None: - frame = cv.QueryFrame(self._cam) - image = PIL.Image.fromstring("L", frame.GetSize(), frame.tostring()) - return image - elif win32vidcap is not None: - image = self._cam.getImage() - return image - else: - return None - - def save(self, filename): - if self._cam is None: - return - - if cv is not None: - frame = cv.QueryFrame(self._cam) - cv.SaveImage(filename, frame) - elif win32vidcap is not None: - self._cam.saveSnapshot(filename) - -if __name__ == "__main__": - from printer_webui.settings import settings - import os - - webcam = Webcam() - webcam.save(os.path.join(settings().settings_dir, "image.png"))