This is a tutorial on how to setup up your Raspberry Pi to track SABnzbd download progress and output it to an LCD (brought to you by Adafruit)
- Raspberry Pi
- Enclosure for Pi (optional)
- Adafruit LCD
- A configuration of SABnzbd
Here is a list of compatible LCDs from Adafruit’s website. For this tutorial I am using the RGB Negative screen, but the rest should work just fine. Note however that I set the backlight color of the screen to yellow, which the Blue&White display is not be capable of doing. If you’re going to use an enclosure, might I suggest the Adafruit Pi Box ($14.95)?
If you are having any problems setting it up let me know and I will try to help out.
Once you have your screen built and configured let’s start preparing our script! We’ll need some information about our SABnzbd configuration that the script will use to pull updates. Make a note of the HOST your configuration is hosted on and the PORT as well. Lastly, we’ll need our API key which can be found under Config -> General -> SABnzbd Web Server
Copy the long string of characters next to API key (yours won’t be blank) and save it for later. Next, let’s create a folder for our script and the LCD modules it will be dependent on. Fire up terminal (or your ssh client that you use to connect to your Raspberry Pi):
sudo mkdir ~/sablcd
You should have gone through the tutorial on Adafruit’s website that goes through the usage of the LCD and sets you up with the example code. From the example code you’ll need to copy Adafruit_I2C.py, Adafruit_MCP230xx.py, and Adafruit_CharLCDPlate.py to our new directory. Navigate to Adafruit-Raspberry-Pi-Python-Code and copy the files we need like so:
sudo cp Adafruit_I2C.py Adafruit_MCP230xx.py Adafruit_CharLCDPlate.py ~/sablcd/
Finally to end the boilerplate section, we need to install the requests module for python via pip:
pip install requests
If you get an error it’s probably because you don’t have the pip installer, which in that case run the following command and then try the one above again:
sudo apt-get install python-pip
Woot. Fire up your favorite editor and let’s code (“Or you can just shut up and give me the script”)
First you’ll need the following import statements at the top of your script
import requests from time import sleep from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
Requests is an awesome module that allows us to make HTTP requests. It’s how we’ll pull information about our queue. The sleep function from the time module will be handy for displaying our welcome message, updating our information at a specific interval, and switching the information that is being displayed on screen.
Next, this is where you will fill in the information about your SABnzbd configuration. Replace YOURHOST, YOURPORT and YOURAPIKEY with your settings.
host = 'YOURHOST' port = 'YOURPORT' key = 'YOURAPIKEY' url = 'http://%s:%s/api?mode=queue&output=json&apikey=%s' % (host, port, key)
Initialize our lcd screen and set the backlight color to yellow (because colors are great and yellow is the SAB logo color.) and display the welcome message for 3 seconds. If you have the blue&white display remove
lcd.backlight(lcd.YELLOW). No yellow for you.
lcd = Adafruit_CharLCDPlate() lcd.backlight(lcd.YELLOW) lcd.message("SABnzbd\n Tracker") sleep(3)
Our script will have two functions:
getStatus() which will be responsible for requesting information about our queue and
showStatus() to display it to the screen. Let’s start with
def getStatus(): r = requests.get(url) info = r.json()['queue'] slots = info['noofslots'] state = info['status'] speed = str(int(float(info['kbpersec']))) + ' kb/s' try: job = info['slots'] job_name = job['filename'][:16] job_mbtotal = int(float(job['mb'])) job_mb = job_mbtotal - int(float(job['mbleft'])) job_mbstatus = str(job_mb) + '/' + str(job_mbtotal) + 'MB' job_timeleft = job['timeleft'] job_percent = job['percentage'] + '%' except IndexError: job_name = "No Active Slots" job_mbstatus = "0/0 MB" job_timeleft = "0:00:0" job_percent = "0%" return [slots, state, speed, job_name, job_mbstatus, job_timeleft, job_percent]
Break it down. This first part makes a request to SABnzbd and decodes the json data about our queue to dictionary format so we can pick stats out of it easily.
r = requests.get(url) info = r.json()['queue']
The next block starts extracting information from our dictionary and putting it into variables. This section is dedicated to stats about the entire queue such as number of active slots, status of queue, and the speed at which it is running.
slots = info['noofslots'] state = info['status'] speed = str(int(float(info['kbpersec']))) + ' kb/s'
The big block in the function is for extracting information about the first download slot. The reason it’s surrounded in a try/except statement is because if there are no slots in our queue, python will throw an IndexError exception. We handle that by saying under the circumstances there is an IndexError (no slots), set our variables to “0”. Then return the data in list format.
try: job = info['slots'] job_name = job['filename'][:16] job_mbtotal = int(float(job['mb'])) job_mb = job_mbtotal - int(float(job['mbleft'])) job_mbstatus = str(job_mb) + '/' + str(job_mbtotal) + 'MB' job_timeleft = job['timeleft'] job_percent = job['percentage'] + '%' except IndexError: job_name = "No Active Slots" job_mbstatus = "0/0 MB" job_timeleft = "0:00:0" job_percent = "0%" return [slots, state, speed, job_name, job_mbstatus, job_timeleft, job_percent]
So that’s it for
getStatus(). Now let’s move on to
showStatus(). This guy is a little more simple so I’ll just break it down here. The function has two parameters, info and panel, which respectively consists of the list of information returned from
getStatus() and the panel of information we would like to display. First it clears the display so it can be updated with new information and then depending on which panel we tell it to show (1, 2 or 3) it outputs the data from the list to the screen.
def showStatus(info, panel): lcd.clear() if panel == 1: lcd.message("Queue: %s\n" % info) lcd.message(info) elif panel == 2: lcd.message("%s\n" % info) lcd.message(info) elif panel == 3: lcd.message("Left: %s\n" % info) lcd.message("%s %s" % (info,info))
Last but not least we have a loop that executes the
showStatus() function every second, and every 10 seconds will switch panels. The
counter variable is used to keep track of the seconds and
panel is used to set the panel to display.
counter = 0 panel = 1 while True: sleep(1) counter += 1 if counter == 10: counter = 0; panel += 1 if panel == 4: panel = 1 showStatus(getStatus(), panel)
Done. Now make sure that the script is saved in the folder we made earlier with all of the modules it depends on and fire it up with:
sudo python sablcd.py
If you’re getting compilation/runtime errors double check your code to make sure it’s all correct. Make sure you having the correct indentation and code blocks in the right spots. You can compare your script with mine. Feel free to ask any questions you have or make suggestions, I’ll try my best to help out!