Difference between revisions of "Cerealbot/rpi"

From Makers Local 256
Jump to: navigation, search
m (Compiling Stuff: typo)
m (/* Recover SD Filesystem did thing can't see text)
 
(20 intermediate revisions by one user not shown)
Line 5: Line 5:
  
 
== Cerealbot Code ==
 
== Cerealbot Code ==
 
This is the '''most important''' section on this page. Everything below is just config and notes for setting up my RPi server.
 
 
How it works:
 
 
Shell script hooks bound to Octoprint's "printStart" and "printDone" events. These handle setting the flag which indicates a part is being printed/removed. Once a part is being removed, its corresponding gcode is deleted from the queue.
 
 
A cron job checks the printer status and queue for a match of "free printer + file to print" and then kicks off the print job.
 
 
A C program acts as a buffer to the arduino and allows the shell scripts to control hardware in a easy to use but complicated to setup manner.
 
 
=== Prerequisites ===
 
 
* The Gear - [[Cerealbox/Hardware]]
 
* Octoprint - [[Cerealbot/rpi#Octoprint]]
 
* Webcam (if you want it) - [[Cerealbot/rpi#MJPG-Streamer]]
 
* Arduino/ATmel that you can flash code to [[Cerealbot/rpi#Arduino.2FATmega.2FAVR]]
 
* Servo w/ arm to kick parts
 
* The [https://github.com/ctag/cerealbox source code]
 
* Lots of spare time and patience
 
 
=== ATmega Firmware ===
 
 
If you haven't yet, clone the git project from "Prerequisites" section. In the project, go to cerealbox/avr/src. Build the .ino source and flash it to the board.
 
 
Super simple, right?
 
 
=== Set up scripts ===
 
 
The the root of the project are a ton of scripts, they must be tweaked before use. I'll be making them more flexible to a variety of printers soon, hang tight.
 
 
From the git project, make the directory ''../.cerealbox/''. In it create a file ''apis.sh'':
 
<pre>
 
# To be sourced into config
 
# Export Octoprint api key
 
OCTO_API_KEY="abcde"
 
# Placeholder RQ api key
 
RQ_API_KEY="12345"
 
</pre>
 
These api keys are private, and not stored on github :P RQ is our hackerspace bot. Comment that line and it should just fail kinda quietly.
 
 
pop_part = use hotbed to dislodge the part. push_part = use servo and print head to sweep the part off the bed.
 
 
Take a look at config in the project and make sure that it reflects your printer/servo setup. I strongly recommend disabling push_part and tuning the pop_part cycles and temp for a few prints first.
 
 
=== Set Octoprint Hooks ===
 
 
This is the dangerous part. I '''HAVE NOT COMPLETED''' this guide, and you have to check that you're ready for these scripts to run rampant whenever a print starts and finishes.
 
 
Edit ~/.octoprint/config.yaml to have:
 
<pre>
 
events:
 
  enabled: true
 
  subscriptions:
 
  - command: /home/pi/cerealbox/print_start.sh "{__filename}"
 
    event: PrintStarted
 
    type: system
 
  - command: /home/pi/cerealbox/print_done.sh "{__filename}" "{__currentZ}" > /tmp/lastprint.log
 
    event: PrintDone
 
    type: system
 
</pre>
 
 
That's it, the scripts should run upon next print.
 
  
 
=== API ===
 
=== API ===
Line 127: Line 64:
 
=== Setup Byobu ===
 
=== Setup Byobu ===
  
* F1 allows you to set "log into byobu" to save some time while logging in.
+
F1 allows you to set "log into byobu" to save some time while logging in.
  
* 'C-a a' will send C-a to /usr/bin/screen, so you can use screen within byobu to debug serial connections.
+
'C-a a' will send C-a to /usr/bin/screen, so you can use screen within byobu to debug serial connections.
 +
 
 +
Sometimes BYOBU will make life miserable. To [http://superuser.com/questions/387237/how-do-i-stop-byobu-from-launching-at-login disable] it:
 +
 
 +
* byobu-disable
 +
* ssh -t IP bash
 +
* export LC_BYOBU=0
  
 
=== Recover SD Filesystem ===
 
=== Recover SD Filesystem ===
Line 141: Line 84:
 
Test recovery:
 
Test recovery:
 
<pre>
 
<pre>
sudo dd if=/dev/sdX2 of=pi_bkup.img
+
sudo dd if=/dev/sdX2 of=pi_bkup.img status=progress
 
cp pi_bkup.img pi_bkup_recv.img
 
cp pi_bkup.img pi_bkup_recv.img
 
sudo e2fsck -fy pi_bkup_recv.img
 
sudo e2fsck -fy pi_bkup_recv.img
Line 154: Line 97:
  
 
<pre>
 
<pre>
sudo e2fsck -ft /dev/sdX2
+
sudo e2fsck -fyt /dev/sdX2
 
</pre>
 
</pre>
  
Line 160: Line 103:
  
 
Good luck!
 
Good luck!
 +
 +
''' Raspberry Pi PWN Count: 3 ''' (Why the hell does the Raspberry Pi foundation ship a board capable of ejecting its own hard drive?!)
 +
 +
=== Migrate to Jessie ===
 +
 +
Ugh, next time we use Archlinux-Arm, OK?
 +
 +
Update just the mirror source in /etc/sources.list from wheezy to jessie.
 +
 +
<pre>
 +
# apt-get update
 +
# apt-get upgrade
 +
# apt-get dist-upgrade
 +
# rpi-update
 +
</pre>
 +
 +
==== Set graphical/tty login ====
 +
 +
Jessie won't be set to tty login by the raspi-config tool. You have to do it [https://www.raspberrypi.org/forums/viewtopic.php?f=66&t=95724 manually]:
 +
 +
<pre>
 +
# systemctl set-default multi-user.target # No Graphics
 +
## OR ##
 +
# systemctl set-default graphical.target # GUI
 +
</pre>
  
 
== Octoprint ==
 
== Octoprint ==
Line 234: Line 202:
 
There are general instructions for installing mjpg-streamer on [https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian#webcam octoprint's wiki]. I've detailed some changes to incorporate a different version and setup a daemon.  
 
There are general instructions for installing mjpg-streamer on [https://github.com/foosel/OctoPrint/wiki/Setup-on-a-Raspberry-Pi-running-Raspbian#webcam octoprint's wiki]. I've detailed some changes to incorporate a different version and setup a daemon.  
  
[https://github.com/jacksonliam/mjpg-streamer mjpg-streamer] is by far my favorite solution for webcam streaming from the RPi. A recent update brought immense relief for CPU overhead.
+
[https://github.com/jacksonliam/mjpg-streamer mjpg-streamer-experimental] is by far my favorite solution for webcam streaming from the RPi. A recent update brought immense relief for CPU overhead.
  
Install some dependancies:
+
Follow the Apt/Pacman directions below, and then continue from here.
<pre>
+
sudo apt-get install libjpeg62-dev cmake subversion imagemagick libav-tools
+
</pre>
+
  
 
Git the project:
 
Git the project:
Line 256: Line 221:
 
Previously I've used the -y flag for compatibility, which totally crushed the little CPU, but the most recent build of mjpg-streamer-experimental appears to work quite well with my Logitech webcam using the default MJPG codec.
 
Previously I've used the -y flag for compatibility, which totally crushed the little CPU, but the most recent build of mjpg-streamer-experimental appears to work quite well with my Logitech webcam using the default MJPG codec.
  
=== Setup Init Script ===
+
==== Apt ====
 +
 
 +
Install some dependancies:
 +
<pre>
 +
sudo apt-get install libjpeg62-dev cmake subversion imagemagick libav-tools
 +
</pre>
 +
 
 +
==== Pacman ====
 +
 
 +
I don't remember what prereqs are needed..
 +
 
 +
=== Systemd Init Script ===
 +
 
 +
If you're using mjpg-streamer-experimental, then you can make the start.sh file like so.
 +
~/mjpg-streamer/mjpg-streamer-experimental/start.sh:
 +
<pre>
 +
#!/bin/bash
 +
 
 +
#/******************************************************************************
 +
#                                                                              #
 +
#      MJPG-streamer allows to stream JPG frames from an input-plugin          #
 +
#      to several output plugins                                              #
 +
#                                                                              #
 +
#      Copyright (C) 2007 Tom St<C3><B6>veken                                        #
 +
#                                                                              #
 +
# This program is free software; you can redistribute it and/or modify        #
 +
# it under the terms of the GNU General Public License as published by        #
 +
# the Free Software Foundation; version 2 of the License.                      #
 +
#                                                                              #
 +
# This program is distributed in the hope that it will be useful,              #
 +
# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
 +
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
 +
# GNU General Public License for more details.                                #
 +
#                                                                              #
 +
# You should have received a copy of the GNU General Public License            #
 +
# along with this program; if not, write to the Free Software                  #
 +
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    #
 +
#                                                                              #
 +
#******************************************************************************/
 +
 
 +
export LD_LIBRARY_PATH=`dirname $0`
 +
DIR=`dirname $0`
 +
$DIR/mjpg_streamer -i "input_uvc.so -d /dev/video0 -n -f 5 -r 1280x720" -o "output_http.so -p 8080 -w $DIR/www"
 +
</pre>
 +
 
 +
Create /etc/systemd/system/mjpg-streamer.service:
 +
<pre>
 +
[Unit]
 +
Description=mjpg-streamer daemon
 +
 
 +
[Service]
 +
Type=simple
 +
ExecStart=/home/berocs/mjpg-streamer/mjpg-streamer-experimental/start.sh
 +
 
 +
[Install]
 +
WantedBy=multi-user.target
 +
</pre>
 +
 
 +
=== SysV Init Script ===
  
 
Go to [https://gist.github.com/foosel/8185988#file-mjpg-streamer-default foosel's mjpg init page] and copy-pasta the two files into ''/etc/init.d/mjpg-streamer'' and ''/etc/default/mjpg-streamer'' respectively.
 
Go to [https://gist.github.com/foosel/8185988#file-mjpg-streamer-default foosel's mjpg init page] and copy-pasta the two files into ''/etc/init.d/mjpg-streamer'' and ''/etc/default/mjpg-streamer'' respectively.
Line 455: Line 478:
 
Here the trailing slash lands the GET variable. It took Hunter Fuller to figure all that out.
 
Here the trailing slash lands the GET variable. It took Hunter Fuller to figure all that out.
  
== UV4L ==
+
=== Streaming over RTMP ===
 
+
uv4l is a promising tool to replace mjpg-streamer with faster performance on the RPi 2. Right now it just crashes my pi though.
+
 
+
[http://raspberrypi.stackexchange.com/questions/7446/how-can-i-stream-h-264-video-from-the-raspberry-pi-camera-module-via-a-web-serve http://raspberrypi.stackexchange.com/questions/7446/how-can-i-stream-h-264-video-from-the-raspberry-pi-camera-module-via-a-web-serve]
+
 
+
[http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14 http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14]
+
 
+
== Arduino/ATmega/AVR ==
+
 
+
To make the Cerealbot code work, you have to have some sort of AVR microcontroller. This can range anywhere from a full-fledge Arduino, to a somewhat cheaper Diavolino, to a bare breadboarded ATmega328.
+
 
+
I'm using a Diavolino wired to the RPi via GPIO headers. Again, there are good resources out there, no need to copy me exactly.
+
 
+
=== Wiring to GPIO ===
+
 
+
On the Pi's headers, there's a default serial Rx/Tx associated with TTY. We're going to yank it away from the OS and use it to speak with and program the ATmega on our Diavolino.
+
 
+
I'm using a high-low logic level converter to protect the Pi. This is crucial; the arduino is capable of burning out the headers on the Pi without some sort of voltage divider.
+
 
+
The following table uses the HARDWARE (aka "Board") GPIO mappings! You can reference [http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/ this image], and use the numbers in the circles, not by the labels!
+
{| class="wikitable"
+
|-
+
! Arduino Pin || RPi GPIO
+
|-
+
| Rx (0) || UART0_TXD (8)
+
|-
+
| Tx (1) || UART0_RXD (10)
+
|-
+
| GND || GND (6)
+
|-
+
| RST/RTS || GPIO (11)
+
|}
+
Connect Vcc and GND pins from the Arduino to an external source, I don't suggest wiring them to the GPIO pins even though seemingly appropriate pins exist.
+
  
=== Free UART0 from TTY ===
+
I don't want to give up mjpg-streamer, not when its working so well. But mjpg-streamer also can't export FLV, which is required for RTMP :(
  
We need to [http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/ kick Rasbian] off of the header GPIO:
+
Solution: Export mjpg-streamer normally, capture and convert, and re-export as FLV alongside. This '''does not work with Debian Wheeze''', which is the standard for Rasbian! The version of avconv is too old, and will report errors. To get a newer version, I upgraded to Debian Jessie (which was awful). I now have avconv version:
  
At the end of /etc/inittab, change
 
 
<pre>
 
<pre>
#Spawn a getty on Raspberry Pi Serial line
+
avconv version 11.4-6:11.4-1~deb8u1+rpi1, Copyright (c) 2000-2014 the Libav developers
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
+
  built on Jun 16 2015 05:32:34 with gcc 4.9.2 (Raspbian 4.9.2-10)
</pre>
+
avconv 11.4-6:11.4-1~deb8u1+rpi1
To:
+
libavutil    54.  3. 0 / 54.  3. 0
<pre>
+
libavcodec    56.  1. 0 / 56.  1. 0
#Spawn a getty on Raspberry Pi Serial line
+
libavformat  56.  1. 0 / 56.  1. 0
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
+
libavdevice  55.  0. 0 / 55.  0. 0
 +
libavfilter    5.  0. 0 / 5.  0. 0
 +
libavresample  2.  1. 0 / 2.  1. 0
 +
libswscale    3.  0. 0 /  3.  0. 0
 
</pre>
 
</pre>
  
In /boot/cmdline.txt, remove any of ''console=ttyAMA0,115200'' or ''kgdboc=ttyAMA0,115200''
+
To run the conversion:
  
Create /etc/udev/rules.d/80-gpio.rules, and add:
 
 
<pre>
 
<pre>
KERNEL=="ttyAMA0", SYMLINK+="ttyS0",GROUP="dialout",MODE:=0666
+
$ avconv -f mjpeg -i http://localhost:8080/?action=stream -f flv rtmp://friends-webserver.com/ctag
 
</pre>
 
</pre>
  
=== Set up a Toolchain ===
+
== Node JS ==
  
Since I'm making use of the Arduino Bootloader to flash programs to the ATmega without ICSP, we're going to stick with regular "sketches" for now, not real microcontroller firmware. I do intend to mess with that later though.
+
=== Archlinuxarm ===
  
Compiling sketches without a graphical X server has apparently been an [https://github.com/arduino/Arduino/issues/3054 issue for some time] with Arduino folk. Even though the official IDE touts CLI building, it fails without a X screen for me.
+
From [http://stackoverflow.com/questions/20454199/how-to-use-a-different-version-of-python-during-npm-install StackOverflow]. I found it a requirement for node-gyp.
 
+
Install packages:
+
 
<pre>
 
<pre>
sudo apt-get install arduino-mk arduino-core avrdude avr-libc gcc-avr
+
npm config set python python2.7
 
</pre>
 
</pre>
  
Setup the GPIO reset workaround:
+
=== Wheezy ===
<pre>
+
git clone https://github.com/deanmao/avrdude-rpi
+
cd avrdude-rpi
+
sudo mv /usr/bin/avrdude /usr/bin/avrdude-original
+
sudo ln -s /home/pi/avrdude-rpi/avrdude-autoreset /usr/bin/avrdude
+
sudo ln -s /home/pi/avrdude-rpi/autoreset /usr/bin/autoreset
+
</pre>
+
  
That should do it! Pretty straightforward really.
+
'''Don't do this.''' Building modules manually is just a waste of time once Node is installed.
  
=== Compiling Stuff ===
+
[http://elinux.org/Node.js_on_RPi http://elinux.org/Node.js_on_RPi] - EEwiki page on downloading / building from source.
  
Go into a source folder with a .ino file:
+
[https://nodejs.org/dist/latest/ https://nodejs.org/dist/latest/] - Latest source release.
<pre>
+
cd ~/cerealbox/avr/src
+
make clean
+
make
+
sudo make raw_upload
+
</pre>
+
  
Output from ''make raw_upload'' should be like:
+
Building:
 
<pre>
 
<pre>
pi@bns-daedalus ~/cerealbox/avr/src $ sudo make raw_upload                                                                                           
+
wget https://nodejs.org/dist/latest/node-v0.12.7.tar.gz
/usr/bin/avrdude -q -V -p atmega328p -C /etc/avrdude.conf -c arduino -b 57600 -P /dev/ttyAMA0  \
+
tar xzf node*.tar.gz
                -U flash:w:build-cli/printr_avr.hex:i
+
cd node-v0.12.7/
done with autoreset
+
./configure
 
+
make -j 3
avrdude-original: AVR device initialized and ready to accept instructions
+
sudo make install
avrdude-original: Device signature = 0x1e950f
+
avrdude-original: NOTE: FLASH memory has been specified, an erase cycle will be performed
+
                  To disable this feature, specify the -D option.
+
avrdude-original: erasing chip
+
avrdude-original: reading input file "build-cli/printr_avr.hex"
+
avrdude-original: writing flash (4902 bytes):
+
avrdude-original: 4902 bytes of flash written
+
 
+
avrdude-original: safemode: Fuses OK
+
 
</pre>
 
</pre>
  
=== Links ===
+
=== Jessie ===
  
'''AMT1001'''
+
Well, if you're willing to break nearly every other part of this ecosystem in order to get node working, just upgrade the system to Jessie and then install Node/Mongodb/etc with apt-get.
  
[http://davidegironi.blogspot.com/2013/07/amt1001-humidity-and-temperature-sensor.html#.VXOzO5Tve00 http://davidegironi.blogspot.com/2013/07/amt1001-humidity-and-temperature-sensor.html#.VXOzO5Tve00]
+
Nearly the worst idea I've had this summer. Next time we use ArchlinuxArm.
  
'''SURE Electronics 3208'''
+
== UV4L ==
  
[http://store.sure-electronics.com/led/de-dp13119 http://store.sure-electronics.com/led/de-dp13119]
+
uv4l is a promising tool to replace mjpg-streamer with faster performance on the RPi 2. Right now it just crashes my pi though.
  
[http://forum.arduino.cc/index.php?topic=167753.0 http://forum.arduino.cc/index.php?topic=167753.0]
+
[http://raspberrypi.stackexchange.com/questions/7446/how-can-i-stream-h-264-video-from-the-raspberry-pi-camera-module-via-a-web-serve http://raspberrypi.stackexchange.com/questions/7446/how-can-i-stream-h-264-video-from-the-raspberry-pi-camera-module-via-a-web-serve]
  
[http://playground.arduino.cc/Main/HT1632C http://playground.arduino.cc/Main/HT1632C]
+
[http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14 http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14]
 
+
[https://github.com/gauravmm/HT1632-for-Arduino https://github.com/gauravmm/HT1632-for-Arduino] <- Awesome
+
 
+
[http://bailey.st/blog/2011/07/12/how-to-connect-sure-electronics-8x32-led-matrix-display-to-arduino/ http://bailey.st/blog/2011/07/12/how-to-connect-sure-electronics-8x32-led-matrix-display-to-arduino/] <- Wiring
+
 
+
'''GPIO To Arduino'''
+
 
+
[http://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control http://stackoverflow.com/questions/957337/what-is-the-difference-between-dtr-dsr-and-rts-cts-flow-control]
+
 
+
[http://www.evilmadscientist.com/2010/diavolino/ http://www.evilmadscientist.com/2010/diavolino/]
+
 
+
[http://www.atmel.com/Images/doc8161.pdf http://www.atmel.com/Images/doc8161.pdf]
+
 
+
[http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/ http://www.raspberrypi-spy.co.uk/2014/07/raspberry-pi-b-gpio-header-details-and-pinout/]
+
 
+
[https://github.com/deanmao/avrdude-rpi https://github.com/deanmao/avrdude-rpi]
+
 
+
[http://www.deanmao.com/2012/08/10/uploading-sketches-to-the-arduino-on-the-pi/ http://www.deanmao.com/2012/08/10/uploading-sketches-to-the-arduino-on-the-pi/]
+
 
+
[http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/ http://spellfoundry.com/sleepy-pi/setting-arduino-ide-raspbian/]
+

Latest revision as of 22:23, 13 April 2016

I'm using an RPi 2 model B for this project. Here are my notes.

Pi <-> RPi <-> Raspberry Pi

Cerealbot Code

API

Curl is great for testing around with both Octoprint and RedQueen's api, but I've switched the shell scripts to use resty for ease of maintenance.

Curl Examples
To RedQueen:
curl --data "{\"message\":\"${MSG}\", \"channel\":\"##rqtest\", \"isaction\":false, \"key\":\"${APIKEY}\"}" https://crump.space/rq/relay -H "Content-Type:application/json"
To Octoprint:
curl -H "X-Api-Key:$OCTO_API_KEY" http://bns-daedalus.256.makerslocal.org/api/printer -o /tmp/printr_status.json

OS

Install

I'm just using Rasbian from the foundation's download page. I find Debian derivatives to be comfortable for projects such as this. You're welcome to use whatever distro you like.

I strongly recommend you follow some official guide for installing the OS if you're at all uncertain. The notes here are sparse and meant to make it faster for me to recover from a broken system.

Get the archive, extract the file. Should be along the lines of '2015-05-05-rasbian-wheezy.img'.

Flash it to the SD card: 'sudo dd if=2015...img of=/dev/sdX bs=4M'.

Configure things with the raspi tool that loads on first boot, then install your favorite packages. Mine are:

htop vim emacs byobu tmux build-essential bash-completion haproxy authbind

Set the time/zone

http://aryo.lecture.ub.ac.id/configure-timezone-settings-on-raspberry-pi-raspbian-wheezy/

By default, Rasbian has an ntp daemon running, but you may still need to select a timezone. Use tzselect to set the timezone, then echo the returned line into .profile.

for me, this means:

echo "TZ='America/Chicago'; export TZ" >> ~/.profile

Setup SSH

I really recommend setting up SSH keys. There are many good guides for this elsewhere.

Setup Git

There's really no need to do this, but I like having git handle passwords for me.

https://help.github.com/articles/caching-your-github-password-in-git/

git config --global credential.helper 'cache --timeout=3600'

Setup Byobu

F1 allows you to set "log into byobu" to save some time while logging in.

'C-a a' will send C-a to /usr/bin/screen, so you can use screen within byobu to debug serial connections.

Sometimes BYOBU will make life miserable. To disable it:

  • byobu-disable
  • ssh -t IP bash
  • export LC_BYOBU=0

Recover SD Filesystem

Hypothetically, in a strictly theoretical sense, with no basis whatsoever to the real world and real people:

Say someone at your hackerspace is horsing around and trips the breaker that your Pi is powered from. Well if you're lucky, then you just walk over and reboot the sucker. Sometimes that doesn't work though, and the computer's little SD card has become corrupt. Rather than break out the backup that you totally have, let's try a quick recovery first.

First, remove the SD card and insert it into your computer. Make sure it is unmounted.

Test recovery:

sudo dd if=/dev/sdX2 of=pi_bkup.img status=progress
cp pi_bkup.img pi_bkup_recv.img
sudo e2fsck -fy pi_bkup_recv.img

You may have to run that last command twice, idk why. If the program successfully recovers the test image, you have two options:

  • Flash this cured image file back to the partition it came from
  • Try to directly recover the SD card, since you know it has a chance of working.

The second option is faster:

sudo e2fsck -fyt /dev/sdX2

Reference thread

Good luck!

Raspberry Pi PWN Count: 3 (Why the hell does the Raspberry Pi foundation ship a board capable of ejecting its own hard drive?!)

Migrate to Jessie

Ugh, next time we use Archlinux-Arm, OK?

Update just the mirror source in /etc/sources.list from wheezy to jessie.

# apt-get update
# apt-get upgrade
# apt-get dist-upgrade
# rpi-update

Set graphical/tty login

Jessie won't be set to tty login by the raspi-config tool. You have to do it manually:

# systemctl set-default multi-user.target # No Graphics
## OR ##
# systemctl set-default graphical.target # GUI

Octoprint

Install

There are good guides elsewhere for installing Octoprint. I really don't see a need for repeating the instructions.

  • Install Octoprint
  • Have it start on boot
  • Configure your account
  • Generate an API key

Authbind to Port 80

If your network supports it, go ahead and use HAProxy. Ours didn't work initially, so I gave up and instead used Authbind.

https://mutelight.org/authbind

sudo apt-get install authbind
sudo touch /etc/authbind/byport/80
sudo chown pi /etc/authbind/byport/80
sudo chmod 500 /etc/authbind/byport/80

Adjust a few lines in /etc/default/octoprint to match:

...
PORT=80
...
DAEMON_ARGS="--port=$PORT"
...

In /etc/init.d/octoprint you need to add a line for authbind in the variable declaration area:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="Octoprint Daemon"
NAME="Octoprint"
DAEMON=/usr/local/bin/octoprint
AUTHBIND=/usr/bin/authbind
...

In the same file, you then need to find the line which starts octoprint and insert authbind:

start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \
       --exec $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- $DAEMON_ARGS

To:

start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \
       --exec $AUTHBIND $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- $DAEMON_ARGS

MJPG-Streamer

This is the current go-to tool for webcam streaming with octoprint. If you have a webcam set up, then you can totes ignore this section. It's also worth browsing around to see if you find a process you like better than mine.

First, you may want to collect some information on your webcam:

To list available formats:

v4l2-ctl --list-formats

or

v4l2-ctl -d /dev/videoX --list-formats-ext | less

Install

There are general instructions for installing mjpg-streamer on octoprint's wiki. I've detailed some changes to incorporate a different version and setup a daemon.

mjpg-streamer-experimental is by far my favorite solution for webcam streaming from the RPi. A recent update brought immense relief for CPU overhead.

Follow the Apt/Pacman directions below, and then continue from here.

Git the project:

git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental/
make clean
make all

The base command to run mjpg-streamer. Don't worry about this, its handled by an init.d script.

mjpg_streamer -b -i "./input_uvc.so -d /dev/video0 -n -f 5 -r 1280x720" -o "./output_http.so -p 8080 -w ./www"

Previously I've used the -y flag for compatibility, which totally crushed the little CPU, but the most recent build of mjpg-streamer-experimental appears to work quite well with my Logitech webcam using the default MJPG codec.

Apt

Install some dependancies:

sudo apt-get install libjpeg62-dev cmake subversion imagemagick libav-tools

Pacman

I don't remember what prereqs are needed..

Systemd Init Script

If you're using mjpg-streamer-experimental, then you can make the start.sh file like so. ~/mjpg-streamer/mjpg-streamer-experimental/start.sh:

#!/bin/bash

#/******************************************************************************
#                                                                              #
#      MJPG-streamer allows to stream JPG frames from an input-plugin          #
#      to several output plugins                                               #
#                                                                              #
#      Copyright (C) 2007 Tom St<C3><B6>veken                                         #
#                                                                              #
# This program is free software; you can redistribute it and/or modify         #
# it under the terms of the GNU General Public License as published by         #
# the Free Software Foundation; version 2 of the License.                      #
#                                                                              #
# This program is distributed in the hope that it will be useful,              #
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
# GNU General Public License for more details.                                 #
#                                                                              #
# You should have received a copy of the GNU General Public License            #
# along with this program; if not, write to the Free Software                  #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    #
#                                                                              #
#******************************************************************************/

export LD_LIBRARY_PATH=`dirname $0`
DIR=`dirname $0`
$DIR/mjpg_streamer -i "input_uvc.so -d /dev/video0 -n -f 5 -r 1280x720" -o "output_http.so -p 8080 -w $DIR/www"

Create /etc/systemd/system/mjpg-streamer.service:

[Unit]
Description=mjpg-streamer daemon

[Service]
Type=simple
ExecStart=/home/berocs/mjpg-streamer/mjpg-streamer-experimental/start.sh

[Install]
WantedBy=multi-user.target

SysV Init Script

Go to foosel's mjpg init page and copy-pasta the two files into /etc/init.d/mjpg-streamer and /etc/default/mjpg-streamer respectively.

Don't forget to edit /etc/default/mjpg-streamer to your liking, and make /etc/init.d/mjpg-streamer executable!

sudo chmod +x /etc/init.d/mjpg-streamer
sudo update-rc.d mjpg-streamer defaults

If you have troubles, make sure to sudo update-rc.d mjpg-streamer remove and then reboot each time while working on it manually.

I've modified the init scripts while facerolling to try and get this junk working.

/etc/init.d/mjpg-streamer:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          mjpg-streamer
# Required-Start:    $local_fs networking
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: mjpg-streamer daemon
# Description:       Starts the mjpg-streamer daemon with the user specified in
#                    /etc/default/mjpg-streamer.
### END INIT INFO
 
# Author: Sami Olmari
 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="mjpg-streamer Daemon"
NAME="mjpg-streamer"
DAEMON=mjpg-streamer
PIDFILE=/var/run/$NAME.pid
PKGNAME=mjpg-streamer
SCRIPTNAME=/etc/init.d/$PKGNAME
 
# Read configuration variable file if it is present
[ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME
 
# Exit if the mjpg-streamer is not installed
[ -x "$DAEMON_HOME/$DAEMON" ] || exit 0
 
# Load the VERBOSE setting and other rcS variables
[ -f /etc/default/rcS ] && . /etc/default/rcS
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
 
if [ -z "$RUN_AT_STARTUP" -o "$RUN_AT_STARTUP" != "YES" ]
then
   log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it."
   exit 0
fi
 
if [ -z "$MJPG_STREAMER_USER" ]
then
    log_warning_msg "Not starting $PKGNAME, MJPG_STREAMER_USER not set in /etc/default/$PKGNAME."
    exit 0
fi
 
#
# Function to verify if a pid is alive
#
is_alive()
{
   pid=`cat $1` > /dev/null 2>&1
   kill -0 $pid > /dev/null 2>&1
   return $?
}
 
#
# Function that starts the daemon/service
#
do_start()
{
   # Return
   #   0 if daemon has been started
   #   1 if daemon was already running
   #   2 if daemon could not be started
 
   is_alive $PIDFILE
   RETVAL="$?"
 
   if [ $RETVAL != 0 ]; then
       start-stop-daemon --start --pidfile $PIDFILE --make-pidfile --chuid $MJPG_STREAMER_USER --user $MJPG_STREAMER_USER --umask $UMASK \
--exec $DAEMON_HOME/$DAEMON
       RETVAL="$?"
	echo "\nRetval: $RETVAL"
   fi
}
 
#
# Function that stops the daemon/service
#
do_stop()
{
   # Return
   #   0 if daemon has been stopped
   #   1 if daemon was already stopped
   #   2 if daemon could not be stopped
   #   other if a failure occurred
 
   start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $MJPG_STREAMER_USER --pidfile $PIDFILE
   RETVAL="$?"
   [ "$RETVAL" = "2" ] && return 2
 
   rm -f $PIDFILE
 
   [ "$RETVAL" = "0"  ] && return 0 || return 1
}
 
case "$1" in
  start)
   [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
   do_start
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  stop)
   [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
   do_stop
   case "$?" in
      0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
      2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
   esac
   ;;
  restart)
   log_daemon_msg "Restarting $DESC" "$NAME"
   do_stop
   case "$?" in
     0|1)
      do_start
      case "$?" in
         0) log_end_msg 0 ;;
         1) log_end_msg 1 ;; # Old process is still running
         *) log_end_msg 1 ;; # Failed to start
      esac
      ;;
     *)
        # Failed to stop
      log_end_msg 1
      ;;
   esac
   ;;
  *)
   echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2
   exit 3
   ;;
esac
:

/etc/default/mjpg-streamer:

# Configuration for /etc/init.d/mjpg-streamer
 
# The init.d script will only run if this variable non-empty.
MJPG_STREAMER_USER="pi"
 
# Where mjpg-streamer is installed, this is important!
DAEMON_HOME=/home/pi/mjpg-streamer/mjpg-streamer-experimental
DAEMON=start.sh
 
# What arguments to pass to mjpg-streamer, here is few examples; You can change them by commenting one and
# uncommenting another:
 
export LD_LIBRARY_PATH=$DAEMON_HOME

#DAEMON_ARGS='-i "$DAEMON_HOME/input_uvc.so -r SXGA -f 15" -o "$DAEMON_HOME/output_http.so"'   # UVC-mode
#DAEMON_ARGS='-i "$DAEMON_HOME/input_uvc.so -y" -o "$DAEMON_HOME/output_http.so"'              # YUV-mode

# Umask of files mjpg-streamer generates, Change this to 000 if running mjpg-streamer as its own, separate user
UMASK=022
 
# Should we run at startup?
RUN_AT_STARTUP="YES"

Octoprint Protip

To use an http stream with octoprint, the URL has to be formatted correctly.

At first glance, I tried: cerealbox.256.makerslocal.org:8081, which didn't work.

Turns out Octoprint blindly appends a GET variable to the URL, which turns the above into: cerealbox.256.makerslocal.org:8081?2354jk345 which isn't a valid URL anymore.

So, you have to set up the webcam URL like: http://cerealbox.256.makerslocal.org:8081/

Here the trailing slash lands the GET variable. It took Hunter Fuller to figure all that out.

Streaming over RTMP

I don't want to give up mjpg-streamer, not when its working so well. But mjpg-streamer also can't export FLV, which is required for RTMP :(

Solution: Export mjpg-streamer normally, capture and convert, and re-export as FLV alongside. This does not work with Debian Wheeze, which is the standard for Rasbian! The version of avconv is too old, and will report errors. To get a newer version, I upgraded to Debian Jessie (which was awful). I now have avconv version:

avconv version 11.4-6:11.4-1~deb8u1+rpi1, Copyright (c) 2000-2014 the Libav developers
  built on Jun 16 2015 05:32:34 with gcc 4.9.2 (Raspbian 4.9.2-10)
avconv 11.4-6:11.4-1~deb8u1+rpi1
libavutil     54.  3. 0 / 54.  3. 0
libavcodec    56.  1. 0 / 56.  1. 0
libavformat   56.  1. 0 / 56.  1. 0
libavdevice   55.  0. 0 / 55.  0. 0
libavfilter    5.  0. 0 /  5.  0. 0
libavresample  2.  1. 0 /  2.  1. 0
libswscale     3.  0. 0 /  3.  0. 0

To run the conversion:

$ avconv -f mjpeg -i http://localhost:8080/?action=stream -f flv rtmp://friends-webserver.com/ctag

Node JS

Archlinuxarm

From StackOverflow. I found it a requirement for node-gyp.

npm config set python python2.7

Wheezy

Don't do this. Building modules manually is just a waste of time once Node is installed.

http://elinux.org/Node.js_on_RPi - EEwiki page on downloading / building from source.

https://nodejs.org/dist/latest/ - Latest source release.

Building:

wget https://nodejs.org/dist/latest/node-v0.12.7.tar.gz
tar xzf node*.tar.gz
cd node-v0.12.7/
./configure
make -j 3
sudo make install

Jessie

Well, if you're willing to break nearly every other part of this ecosystem in order to get node working, just upgrade the system to Jessie and then install Node/Mongodb/etc with apt-get.

Nearly the worst idea I've had this summer. Next time we use ArchlinuxArm.

UV4L

uv4l is a promising tool to replace mjpg-streamer with faster performance on the RPi 2. Right now it just crashes my pi though.

http://raspberrypi.stackexchange.com/questions/7446/how-can-i-stream-h-264-video-from-the-raspberry-pi-camera-module-via-a-web-serve

http://www.linux-projects.org/modules/sections/index.php?op=viewarticle&artid=14