-
Notifications
You must be signed in to change notification settings - Fork 87
BBIOServer
BBIOServer is a dynamic web interface library for PyBBIO. It offers a quick and simple way to create custom GUIs for your BeagleBone.
There are two example programs for BBIOServer; one using the default layout, and the other using the mobile device layout. First make sure you've updated to the most recent version of PyBBIO, then run the example programs:
# cd PyBBIO/examples
# python BBIOServer_test.py
or
# python BBIOServer_mobile_test.py
Now open your web browser and navigate to http://your_beaglebone_ip_address:8000
. Pressing ctrl-c
will stop the server.
Check out the video demo of BBIOServer_mobile_test.py here.
##API
Each page of the web interface is created by making a new instance of the Page class:
####Page(title, stylesheet="style.css")
title will be the title of the page and the optional stylesheet argument should point to a CSS stylesheet in the BBIOServer/src/
directory. The default stylesheet is a very basic layout, and is not very mobile device friendly. Also included with the library is a similar stylesheet that gets along nicely with mobile browsers, which may be used by passing in stylesheet="mobile.css" when initializing each page.
The content of the page is then created sequentially using these methods:
####Page.add_heading(text)
Creates a large header with the given text at the current location on the page.
####Page.add_text(text, newline=False)
Adds the given text to the current location on the page. If newline = True it will be forced to the next line, otherwise it will stack to the right of the previous object if there is room on the page.
####Page.add_button(function, label, newline=False)
Creates a button with the given label at the current location on the page. function must be a callable object, and will be called when the button is pressed. If newline = True it will be forced to the next line, otherwise it will stack to the right of the previous object if there is room on the page.
####Page.add_entry(function, submit_label, newline=False)
Creates a text entry and a submit button with the given label at the current location on the page. function must be a callable object which takes one argument, and will be called when the button is pressed and will be passed the contents of the entry. If newline = True it will be forced to the next line, otherwise it will stack to the right of the previous object if there is room on the page.
####Page.add_monitor(function, label, units='' newline=False)
Adds a label to the current position on the page in the form: "label value units" where value is the return value of the callable object function which will be repeatedly called. If newline = True it will be forced to the next line, otherwise it will stack to the right of the previous object if there is room on the page.
####Page.add_video(ipaddress,port,newline=False) Add a video with controls to the current position in the page. It plays the video that is streamed from http://ipaddress:port. If newline=True the text will be put on a new line, otherwise it will be stacked on the current line.
The web server is created using the BBIOServer class:
####BBIOServer(port=8000, verbose=False, blocking=True)
The port argument may be used to run the server on a port other than the default of 8000. If verbose = True a log of every request will be printed. If blocking = False the server will run in non-blocking mode, meaning the main loop() routine will be executed as normal while the server runs in the background.
The server is then controlled with the following methods:
####BBIOServer.start(*pages)
starts the server with the given pages. The navigation bar is created with the pages in the same order as they are passed in, and the first page acts as a home page. Once this is called, no new pages can be added.
####BBIOServer.stop()
This method may be used to stop the server when running in non-blocking mode.
##Tutorial The example programs are a bit complicated, so I'll walk through a simpler one:
The first step is to import bbio, then the BBIOServer library:
from bbio import *
from BBIOServer import *
Then we create an instance of the BBIOServer class:
server = BBIOServer()
Next, in our setup routine, we need to create a Page object; we'll give it the name "Home":
def setup():
home = Page("Home")
At this point we could start the server with our empty page, but to make it a bit more interesting let's add some text:
home.add_text("This is a test of the BBIOServer library.")
Now we start the server with our home page:
server.start(home)
The server is blocking, so our program will hang at this point until the server is stopped with ctrl-c
, at which point it will continue on, so if we want our program to stop completely we need to use the PyBBIO stop()
function. Since we have nothing in our loop()
function, we need to use the pass statement to keep Python happy. Then all that's left to do is to call run()
. Putting it all together we have:
from bbio import *
from BBIOServer import *
server = BBIOServer()
def setup():
home = Page("Home")
home.add_text("This is a test of the BBIOServer library.")
server.start(home)
stop()
def loop():
pass
run(setup, loop)
If you run this and navigate to http://your_beaglebone_ip_address:8000
in your web browser, you should see something like this:
Note that port 8000 is the default, but any port number can be specified when creating the server, e.g. server = BBIOServer(1234)
.
OK, now we know how to set up a server, but it would be nice if it actually did something. Let's create a second page called 'LED Control' and add some text to it:
led = Page("LED Control")
led.add_text("This page allows control of the on-board LEDs")
Next we'll make sure the USR3 LED is configured as an output, then we'll add a button to our led page to toggle it:
pinMode(USR3, OUTPUT)
led.add_button(lambda: toggle(USR3), "Toggle USR3 LED", newline=True)
We use a lambda expression here so we can pass the USR3 variable to toggle()
.
The only thing we need to change to use our second page is to pass it to the server.start()
function along with our home page. Putting it all together we get:
from bbio import *
from BBIOServer import *
server = BBIOServer()
def setup():
home = Page("Home")
home.add_text("This is a test of the BBIOServer library.")
led = Page("LED Control")
led.add_text("This page allows control of the on-board LEDs")
pinMode(USR3, OUTPUT)
led.add_button(lambda: toggle(USR3), "Toggle USR3 LED", newline=True)
server.start(home, led)
stop()
def loop():
pass
run(setup, loop)
When we run this and refresh the web page, we should see our original home page with a new a link in the sidebar to our led control page. If you follow the link you should see this:
At this point clicking the button will toggle the LED as expected, but it would be nice to have some feedback. To do this we only need one more line of code:
led.add_monitor(lambda: pinState(USR3), "Current state:")
Again using a lambda expression so we can pass the USR3 variable to the pinState()
function.
So now our program looks something like this:
from bbio import *
from BBIOServer import *
server = BBIOServer()
def setup():
home = Page("Home")
home.add_text("This is a test of the BBIOServer library.")
led = Page("LED Control")
led.add_text("This page allows control of the on-board LEDs")
pinMode(USR3, OUTPUT)
led.add_button(lambda: toggle(USR3), "Toggle USR3 LED", newline=True)
led.add_monitor(lambda: pinState(USR3), "Current state:")
server.start(home, led)
stop()
def loop():
pass
run(setup, loop)
Which results in this page:
This gets the job done, but it sure would look nicer if it said 'on' and 'off' instead of '1' and '0'. To do this we're going to have to define our own function, something like this:
def ledState(led):
if (pinState(led)):
return 'on'
return 'off'
And we simply have our lambda function call our ledState()
instead of PyBBIO's pinState()
.
So now we have this:
from bbio import *
from BBIOServer import *
server = BBIOServer()
def ledState(led):
if (pinState(led)):
return 'on'
return 'off'
def setup():
home = Page("Home")
home.add_text("This is a test of the BBIOServer library.")
led = Page("LED Control")
led.add_text("This page allows control of the on-board LEDs")
pinMode(USR3, OUTPUT)
led.add_button(lambda: toggle(USR3), "Toggle USR3 LED", newline=True)
led.add_monitor(lambda: ledState(USR3), "Current state:")
server.start(home, led)
stop()
def loop():
pass
run(setup, loop)
Which looks a bit nicer:
There's one more page element that we haven't used, which is the text entry. To use an entry, we're going to need to define a new function to handle the text entered. To keep it simple we'll just print the submitted text to the terminal:
def printEntry(text):
print "Text entered:\n '%s'" % text
We'll add the entry to our home page:
home.add_entry(lambda entry_text: printEntry(entry_text), "Submit", newline=True)
So the whole program should look like this:
from bbio import *
from BBIOServer import *
server = BBIOServer()
def printEntry(text):
print "Text entered:\n '%s'" % text
def ledState(led):
if (pinState(led)):
return 'on'
return 'off'
def setup():
home = Page("Home")
home.add_text("This is a test of the BBIOServer library.")
home.add_entry(lambda entry_text: printEntry(entry_text), "Submit", newline=True)
led = Page("LED Control")
led.add_text("This page allows control of the on-board LEDs")
pinMode(USR3, OUTPUT)
led.add_button(lambda: toggle(USR3), "Toggle USR3 LED", newline=True)
led.add_monitor(lambda: ledState(USR3), "Current state:")
server.start(home, led)
stop()
def loop():
pass
run(setup, loop)
When we refresh and head back to the home page, we should see something like this:
And when we enter some text and hit submit we should see the text appear in our terminal: