Pine64 & OctoPrint (Part 2)

Picking up where Part 1 left off, it's not time to look at how to install and configure OctoPrint on the Pine 64, setup webcam streaming to OctoPrint, and make our first print!

Important Notes

Before proceeding, it's important to understand how Linux permissions work. When following these instructions, make note as to where commands are run as sudo and when they're not. Do not simply run all of these commands as sudo or do a sudo su before starting, or these instructions will not work. Also make note of character case. OctoPrint and octoprint are not interchangeable, and must be used specifically with the case noted.

Installing OctoPrint

I've derived my install process from the Raspberry Pi Raspbian install instructions for OctoPrint, with just a few subtle changes. One big one being the installation directory, which I've changed to /usr/local/etc/ instead of the user's home directory.

  • Run cd /usr/local/etc to switch to the local etc directory
  • Install all of the required OctoPrint prerequisites by running sudo apt-get install python-pip python-dev python-setuptools python-virtualenv git libyaml-dev build-essential
  • Copy OctoPrint from the GitHub repository by running git clone
  • Navigate into the new OctoPrint folder with cd OctoPrint
  • Configure the virtual environment by running virtualenv venv
  • Perform the PIP install by running ./venv/bin/pip install pip -–upgrade
  • Run the OctoPrint setup script with ./venv/bin/python install

OctoPrint will by default look at ~/.octoprint/config.yaml for the configuration file, so before we run OctoPrint for the first time, we need to make sure that folder exists and has appropriate security so that OctoPrint can create config.yaml during first run.

  • First, create a folder called .octoprint in your local directory with mkdir ~/.octoprint
  • Ensure that folder is readable by running chmod 755 ~/.octoprint

Before we run OctoPrint for the first time, we want to ensure that our user has access to the Pine64's USB ports by running the following commands, where ubuntu is your username.

  • sudo usermod -a -G tty ubuntu
  • sudo usermod -a -G dialout ubuntu

Now we can start OctoPrint for the first time by running /usr/local/etc/OctoPrint/venv/bin/octoprint. If all goes well, you should see the scripts executing, and you should be able to go to http://{pine64-ip}:5000 from another machine on your network and see OctoPrint.

OctoPrint will present you with a first run Wizard, asking you to setup a username/password to use when interacting with the system via your browser, and configuring basic parameters of your 3D printer. Create the username and password; OctoPrint will tell you it's optional, but it's just smart system security to do so. You can set basic properties for your printer if you want, or you can do that later (we'll be back), then finish the wizard. We'll come back to OctoPrint later, but for now, go back to your terminal and hit Ctrl + C to kill the OctoPrint script.

If you want to change the port that you use to access OctoPrint, open the config.yaml file by running nano ~/.octoprint/config.yaml. Move down to the server: section, and add/change the port node. In my case, I added port: 8080 to the server node.

Installing Webcam Capabilities

One of the nice features of OctoPrint is the ability to stream a webcam to the browser for remote monitoring of your prints. Additionally, OctoPrint also gives you the opportunity to use this webcam to create timelapse videos of your prints, all configured and delivered through the OctoPrint UI.

  • Make sure you have a webcam that's supported by mjpg-streamer. I'm using a Logitech C920, which works great.
  • Navigate back to /usr/local/etc by running cd /usr/local/etc
  • Install the prerequisites for mjpg-streamer by running sudo apt-get install libv4l-0 fswebcam subversion libjpeg8-dev imagemagick libav-tools ffmpeg cmake
  • Copy mjpg-streamer from the GitHub repository by running git clone
  • Navigate into the copied directory with cd mjpg-streamer/mjpg-streamer-experimental
  • Run export LD_LIBRARY_PATH=.
  • Compile the code by running make

We've now installed mjpg-streamer, but need to set it up to start automatically at boot. There's a few mechanisms to start it, and OctoPrint's native instructions have you setup custom actions inside the OctoPrint UI to start and stop the service, but for my purposes it's easier to just have it automatically start when my Pine64 boots up. To achieve this, we need to create a couple scripts.

  • Run nano /usr/local/etc/OctoPrint/scripts/webcam
  • Paste in the following script and save the file
# Start / stop streamer daemon
  case "$1" in
    /usr/local/etc/OctoPrint/scripts/webcamDaemon >/dev/null 2>&1 &
    echo "$0: started"
    pkill -x webcamDaemon
    pkill -x mjpg_streamer
    echo "$0: stopped"
    echo "Usage: $0 {start|stop}" >&2
  • Run nano /usr/local/etc/OctoPrint/scripts/webcamDaemon
  • Paste in the following script and save the file; note that if you're using a different camera than the Logitech C920, you'll have to change the camera_usb_options to reflect the config for your webcam. Note that I've set the output port for the webcam stream to 8088. This means that OctoPrint will run on 8080 and the webcam will be available on 8088.


# init configuration
camera_usb_options="-n -r 1920x1080 -f 30"
camera_raspi_options="-fps 10"

if [ -e "/boot/octopi.txt" ]; then
    source "/boot/octopi.txt"

# runs MJPG Streamer, using the provided input plugin + configuration
function runMjpgStreamer {
    echo Running ./mjpg_streamer -o " -p 8088 -w ./www" -i "$inpu$
    LD_LIBRARY_PATH=. ./mjpg_streamer -o " -p 8088 -w ./www" -i "$

# starts up the RasPiCam
function startRaspi {
    logger "Starting Raspberry Pi camera"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_RASPICAM $camera_raspi_options"

# starts up the USB webcam
function startUsb {
    logger "Starting USB webcam"
    runMjpgStreamer "$MJPGSTREAMER_INPUT_USB $camera_usb_options"

# we need this to prevent the later calls to vcgencmd from blocking
# I have no idea why, but that's how it is...
vcgencmd version

# echo configuration
echo camera: $camera
echo usb options: $camera_usb_options
echo raspi options: $camera_raspi_options

# keep mjpg streamer running if some camera is attached
while true; do
    if [ -e "/dev/video0" ] && { [ "$camera" = "auto" ] || [ "$camera" = "usb" $
    elif [ "`vcgencmd get_camera`" = "supported=1 detected=1" ] && { [ "$camera$

    sleep 120
  • Next we need to make both of these scripts executable, by running the following commands:
  • chmod +x /usr/local/etc/OctoPrint/scripts/webcam
  • chmod +x /usr/local/etc/OctoPrint/scripts/webcamDaemon
  • And add the webcam daemon to rc.local by running sudo nano /etc/rc.local, and inserting the following before exit 0:
echo before-mjpg
/usr/local/etc/OctoPrint/scripts/webcam start
echo after-mjpg

Making OctoPrint Start Automatically

In addition to automatically starting mjpg-streamer and the webcam services, I also want OctoPrint to start automatically.

  • Edit the octoprint.init file by running sudo nano /usr/local/etc/OctoPrint/scripts/octoprint.init
  • Add new paths the PATH variable by appending to the end:
  • Copy octoprint.init by running sudo cp /usr/local/etc/OctoPrint/scripts/octoprint.init /etc/init.d/octoprint
  • Make /etc/init.d/octoprint executable by running sudo chmod +x /etc/init.d/octoprint
  • Edit the octoprint.default file by running sudo nano /usr/local/etc/OctoPrint/scripts/octoprint.default
  • Make changes noted below. Be sure to uncomment (remove the # at the start of the line) if you set a value:
# Configuration for /etc/init.d/octoprint

# The init.d script will only run if this variable non-empty.

# base directory to use

# configuration file to use

# On what port to run daemon, default is 5000

# Path to the OctoPrint executable, you need to set this to match your installation!

# What arguments to pass to octoprint, usually no need to touch this

# Umask of files octoprint generates, Change this to 000 if running octoprint as its own, separate user

# Process priority, 0 here will result in a priority 20 process.
# -2 ensures Octoprint has a slight priority over user processes.

# Should we run at startup?
  • Copy octoprint.default by running sudo cp /usr/local/etc/OctoPrint/scripts/octoprint.default /etc/default/octoprint
  • Ensure that OctoPrint is added to rc.d for startup by running sudo update-rc.d octoprint defaults

First Reboot

Now that all the services are setup, we can reboot for the first time and validate that all of our services start.

  • Issue a sudo reboot from the terminal to reboot your Pine64.
  • Once the OS boots, wait 30 seconds or so for the services to all spin up, then try hitting OctoPrint in a browser, on the port we defined (in my case 8080): http://{pine64-ip}:8080
  • In another browser tab, attempt to view your webcam stream, on the port we defined (in my case 8088): http://{pine64-ip}:8088/?action=stream

Shutdowns & Reboots

Ideally, we never want to have to SSH into our Pine64 in the future, so we need to configure a way to shutdown the Pine64 or reboot it from inside the OctoPrint UI. Thankfully, OctoPrint gives us the ability to define custom actions, which can call scripts that you define.

First things first, we need our user (in this case ubuntu) to be able to issue shutdown commands without entering a password. To do this, perform the following steps:

  • Run sudo -s
  • Run cat > /etc/sudoers.d/octoprint-shutdown
  • Type ubuntu ALL=NOPASSWD: /sbin/shutdown and hit Enter
  • Press Ctrl + D twice

Now we'll create the actions inside of OctoPrint.

  • Open the OctoPrint config file by running nano ~/.octoprint/config.yaml
  • Scroll down to the system section, or create it if it doesn't exist
  • Define the actions section inside of system, and enter the following actions. Note that spaces and correct indentations here are critical, or they will not work.
    - name: Shutdown
      command: sudo shutdown -h now
      action: shutdown
      confirm: You are about to shutdown the system.
    - name: Reboot
      command: sudo shutdown -r now
      action: reboot
      confirm: You are about to reboot the system.
  • Save the file, and reboot by issuing a sudo reboot

When the system comes back up, navigate to OctoPrint in your browser, and login. You should now see a System menu at the top right of your screen with options to shutdown and reboot the system.

Final Updates & Package Installs

At this point, it's a good idea to run a sudo apt-getupdate && sudo apt-get upgrade to make sure there's no updates available for your system before we put it into production. I also took this opportunity to install the Arduino core just in case I need it in the future (by running sudo apt-get install arduino arduino-core).

Final Configuration

From here on out we'll do everything in the UI and no longer need our SSH session. Complete the final OctoPrint configuration by hitting the Settings button in the top bar of OctoPrint. Many of these settings will be specific to your 3D printer (including those on the Serial Connection, Printer Profiles, and Temperatures tabs), but some need to match things we've already setup, such as the webcam settings.

On the Webcam & Timelapse tab, set the Stream URL to http://{pine64-ip}:8088/?action=stream and set the Snapshot URL to http://{pine64-ip}:8088/?action=snapshot. Set the FFMPEG path to /usr/bin/ffmpeg. Decide if you want the OctoPrint watermark on your timelapse videos, and set a bitrate for your output videos.

On the API tab, set whether you want the API enabled or not. If you wish to use the Octo app on your phone to monitor your prints, this will need to be enabled, and the API key set inside the app.

On the Folders tab, remember back in Part 1, we created some specific network shares to store our files and timelapse output in. Configure those here, in my case:

  • Upload Folder: /media/RigidBot/Uploads
  • Timelapse Folder: /media/RigidBot/Timelapse
  • Timelapse Temp Fodler: /home/ubuntu/.octoprint/timelapse/tmp
  • Logs Folder: /media/RigidBot/Logs
  • Watched Folder: /media/RigidBot/Watched
  • Actively poll watched folder: Yes

Note that I'm not storing the timelapse temp files on the network share. Those will live on the Pine64 so that FFMPEG can process them more efficiently. Only the final videos will be set to the network share.

Lastly, click on the Software Update tab, then click the little wrench icon at the top right, and set the OctoPrint checkout folder to /usr/local/etc/OctoPrint. This allows OctoPrint to alert you when new versions of the software are available.

Your First Print

That's it. OctoPrint is now installed, configured, and ready to run. Maybe you should consider printing a new case for your OctoPrint Pine64 to test everything out!

Pine64 & OctoPrint (Part 1)

I had a couple Pine64 boards sitting in a drawer, and decided it was finally time to replace that old Raspberry Pi running OctoPrint (err, OctoPi) for my 3D printer. The Raspberry Pi has served admirably, but it was definitely time for an upgrade, and a chance to improve a lot of my overall printing workflow.

The Pine64

If you're unfamiliar, the Pine64 is a 64-bit, single board computer. I'm using the A64+ 2GB board, which comes with a quad core ARM Cortex A53 processor operating at 1.2 Ghz, 2Gb of DDR3 memory, dual core graphics, and gigabit ethernet. With double the memory of the Raspberry Pi 3, plus gigabit ethernet, the Pine64 is a steal at just $29.

Downloading an Image

If you're used to a Raspberry Pi, the initial configuration of the Pine64 is going to feel nice and familiar. Start off by grabbing the image of your choice from the Pine64 Wiki. I didn't want a desktop environment, so I'm using the July 16, 2016 Longsleep image. It has to be said that the downloads from the Pine64 Wiki are painfully slow, so even at just ~170Mb, plan ahead a little. Some of the images listed in the wiki are available via torrent, so if go that route, you'll likely see much better download performance.

Creating the SD Card

Identical to the Raspberry Pi process, you'll want to use something like SD Card Formatter to prep your card, then "burn" the image to it using Win32 Disk Imager. If you happen to be using a Pine64 for another project, you'll notice that the Android images are "burned" using PhoenixCard. Note that these processes are not interchangeable; you cannot make a Linux SD card using PhoenixCard.

Powering Up

Once you've got your SD card ready to go, insert it into the Pine64. For my initial setup, I plugged in a local keyboard and mouse, monitor (via HDMI port), and a network cable. The Pine64 is a bit more power hungry than a Raspberry Pi, and consequently you must use a decent quality USB power adapter that puts out a nice clean 2A. I'm using a Power-over-Ethernet splitter for mine, which splits apart a POE network cable into standard gigabit ethernet and a micro-USB for power. Whatever method you choose will work, don't just grab an old mid-2000s USB adapter from a drawer and expect to be successful.

Logging In

Once you've seen a clean boot, login with the default password for the image you've chosen (credentials will be listed on the Wiki with the download). Any time you've downloaded an image from the community, step 1 should always be to run passwd and change the password! Once you've done that, be sure to expand the root partition to use your full SD card. For my image, a script was included to perform this, so it was as simple as running sudo /usr/local/sbin/ and just watch it do its thing. Now is also a great time to grab and install any updates, since your image may be out of date. Simply run sudo apt-get update && sudo apt-get upgrade.

Mounting Shares

One of the things I always wanted to do with my Raspberry Pi, was point OctoPrint at a network share for logs, timelapse videos and uploads. This gets these files off of my OctoPrint machine, allows me to back them up easier, and makes transferring those files between OctoPrint and my Windows machines much easier. With the limited processing and network bandwidth of the Raspberry Pi, this never really worked well, but it works just fine on a Pine64! I went ahead and created a new user on my Windows network, a network share for my "RigidBot" 3D Printer, and gave that user full control over the share, now we just have to mount it.

  • Start by installing the CIFS utilities by running sudo apt-get install cifs-utils.
  • Create a new file to store your network credentials. It's important that you use a credential file to avoid storing plain text credentials in our mount definition later. Create this file by running sudo nano ~/.smbcredentials.
  • Enter your credentials in this file. It is important that your file is structured the same way as the example below (username on one line, password on the next, etc.). If your user is affiliated with a domain, include the domain line.
  • Once you've created your file, we need to set the appropriate permissions on it by running chmod 600 ~/.smbcredentials
  • Before we define our mount point, run id and make note of the output. This is likely something like 1000, but we'll need this number to ensure OctoPrint can correctly read and write to our share.
  • Now we're ready to define our mount point and tell the system how to connect. To do this, open up /etc/fstab by running sudo nano /etc/fstab. Here we'll enter a new row that defines the path to our share, the path to our local mount point, the file system type, and our credentials. Be sure to replace SERVERIP, SHARE, USERNAME and ID with your own values. Note that for this step, USERNAME is your Linux logon username, not the network credential. //SERVERIP/SHARE /media/SHARE cifs credentials=/home/USERNAME/.smbcredentials,sec=ntlm,uid=ID 0 0
  • Now, run sudo mount -a to tell the OS to process the changes to our fstab file. If all goes well, you'll now be able to cd /media/SHARE and see any content from your Windows share.

More to Come

In Part 2 we'll look at how to install and configure OctoPrint on the Pine64, setup webcam streaming to OctoPrint, and make our first print!

Anatomy of an Intranet (Triangle SharePoint User Group)

Presented at the Triangle SharePoint User Group ( on January 5, 2016.

While many people see the intranet as a pretty (hopefully) homepage, in reality the modern enterprise intranet is a complex animal of many moving parts. Structuring of the information within the intranet, how that information is presented to the user, how the user interacts with it, how the organization manages it, and the physical branding that sits on top of all of it are all critical conversations to have if an intranet is going to be effective. In this session we’ll explore the building blocks of a successful intranet and discuss common intranet pitfalls to avoid on your next intranet roll-out.

Why I Gave Up On Windows Phone

I've been a Microsoft supporter (dare I say fan boy) since... well... as long as I can remember, and an equally strong critic of Apple for just as long, but last week I did something I never thought I would. I ordered an iPhone.

Why a fruit phone? Don't you hate Apple?

Hate is a strong word, but I have been extremely vocal and critical of Apple over the years. Apple hardware is simply beautiful, it's stable, and for the most part, everything just works (right?). What I dislike about Apple is the culture - something that has been rooted in every business decision they've made in the last 20 years... the idea that people will flock to buy something just because it's brand new and it has a fruit logo on it. I can't tell you how many people I've met that have every version of the iPad. This is completely unnecessary... nobody needs 5 iPads; you're gullible. I refuse to be proxy to that culture. I bought an iPhone 6 out of need, and any future purchases will also be based on need... will I run to the nearest Apple store to get the next phone as soon as it comes out? No.

The other frustration that I suppose I'll learn to deal with is the abundance of proprietary everything. What do you mean I have to carry around a proprietary charging cable to charge something that everyone else in the industry uses a Micro-USB for? What do you mean every licensed accessory is overpriced because of the Apple royalty? But that said, at the end of the day the big selling point of the iPhone is the ecosystem - and it's this ecosystem that helps me look beyond cultural and hardware inconveniences.

Why not Windows Phone? Wasn't it Amazing?

The Platform

Before I say anything bad, let me say that I've given Windows Phone 4 years to become what it could be. I've proudly recruited family, friends and peers to the Windows Phone platform. The operating system is beautiful. It's simple to use, it's clean, in short it works. The integration with OneDrive is great, and I've long said that any of the critical apps I need to get through the day are available on Windows Phone. What took me a long time to realize is that all those things that I just praised... are all available on other platforms as well.


Need banking and travel apps? For the most part they're all available on Windows Phone. Want to be part of anything new and exciting? You're out of luck; it really is quite that simple.

As anyone that follows me knows that I'm a huge supporter of Kickstarter. I love what it represents and the innovation that's derived from empowering people to try something new. Sadly, not a single one of my backed projects has plans for Windows Phone, and virtually every new product develops for Apple first, Android second, and Windows Phone third (if at all). This dilemma isn't limited to startups though.

Major companies develop for Windows Phone last. United Airlines as an example, released updated iOS and Android apps earlier this year, while the Windows Phone app still hasn't had the matching refresh launched. I can't fault them for that... if the user pool is so small that they would be better off spending their money elsewhere then that makes complete business sense. I've personally encountered dozens of "apps" that are just basically the company's mobile website packaged in an iFrame and tossed into the store... just to say they support Windows Phone. For the longest time, the Redbox app was like this. It took Fitbit ages to finally support Windows Phone... citing a lack of support for Bluetooth 4, which many (if not all) of the Nokia/Lumia phones support... and those are just three examples of hundreds and hundreds of companies that have placed little to no emphasis on the Windows Phone platform.

In my opinion, this is where Microsoft has failed. Microsoft has provided zero incentive to develop apps for their platform. It has taken us almost 4 years to get to the point where every day apps we need to survive are largely available. I fear it'll take another 10 years to get to the maturity of iOS or Android. Thinking back to my original Windows Phone purchase, I practically had to argue with the salesman in my local wireless carrier's store to get him to sell me a Windows Phone. That story is largely the same today... go to your wireless carrier and they'll likely recommend you an iPhone or an Android phone way before a Windows Phone. If you don't specifically ask about Windows Phone, or be pulled that way due to a sale or promotion, chances are you're going to leave with an iPhone or Android phone.

So now we're stuck in this chicken vs. the egg dilemma. Windows Phone can't build and retain market share without a mature ecosystem, and that mature ecosystem won't happen as long as the market share is too small for developers to invest in it.

I spent a lot of time pondering creating apps for Windows. There's such a gap in the ecosystem that there must be a good business opportunity there, right? I'm not so sure. With such a small slice of market share, any sort of niche app is going to have too small of a user pool to make it worth my time to develop.

Brand Recognition?

Everyone knows the name Microsoft. Anyone who had been using a cell phone since the mid-90s knew the name Nokia. I've had numerous Nokia phones over the years, and they were some of the best built handsets I've ever owned. When Microsoft announced the acquisition of the Nokia devices group I was thrilled. This was our chance to get out there, connect with customers, build great hardware, and steal market share. Sadly, this hasn't happened.

Microsoft and Nokia created some great phones together. My Nokia Lumia 1020 is fabulous. But now it has been announced that the Nokia name is being dropped and Microsoft's mobile devices will be branded with just the Lumia name. Well that's great if you're a Microsoft fan boy that knows the story, and knows where Lumia came from, but if you're a layman... what the hell is "Lumia"? The few sales people that were actually pushing Microsoft and Nokia phones in the past had the benefit of brand recognition... now they're trying to sell something nobody has ever heard of.

My Dilemma

This leads me to my ultimate dilemma. Microsoft has been my life for years, privately and professionally, but I also consider myself an innovative individual that wants to be on the cusp of new technology. Waiting months or potentially years, for a hardware or service to create a Windows Phone app just isn't for me.

Microsoft is going to have to spend oodles of money on brand recognition, educating users on the Lumia name, if they're going to have any chance at building the brand. I think it's too late for that. I feel like we're at a now or never crossroads for Windows Phone. The sad thing is that the Operating System is fabulous. It doesn't crash and hang constantly like my previous Android phones did (the primary reason Android was off the table this time around). It's clean, and simple to use. The live tiles make complete sense, and when properly used by an app are incredibly powerful. In short, it's a great platform that has been completely misguided and poorly released to the market.

If things change, then I'll certainly be back. But for now, it's off to greener pastures... and all sorts of cool home automation and hardware projects on Kickstarter.

Anatomy of an Intranet (Triangle SharePoint User Group)

Presented at the Triangle SharePoint User Group ( on October 7, 2014.

While many people see the intranet as a pretty (hopefully) homepage, in reality the modern enterprise intranet is a complex animal of many moving parts. Structuring of the information within the intranet, how that information is presented to the user, how the user interacts with it, how the organization manages it, and the physical branding that sits on top of all of it are all critical conversations to have if an intranet is going to be effective. In this session we’ll explore the building blocks of a successful intranet and discuss common intranet pitfalls to avoid on your next intranet roll-out.