External data sources: A bitcoin ticker
Posted Nov 02 2014 by Florian WeschOften you have external dynamic information that you want to show in an info-beamer visualization. Since info-beamer itself doesn't provide an API to (for example) use HTTP you might wonder how to do this. info-beamer makes this very easy. It's also language agnostic. So you can use the language of your choice to fetch information and then make it available to info-beamer. Here's a pretty basic bitcoin ticker that shows how to do this.
info-beamer was designed with external scripting in mind. Lua, the programming language that info-beamer uses for its scripting interface, is surprisingly powerful once you get used to it. It's also one of the fastest scripting languages available right now. So it's a perfect match for info-beamer.
But that doesn't mean you have to use Lua for everything when using info-beamer. You probably already have a favourite language that you are familiar with. And it probably has libraries to access all kind of APIs. info-beamer embraces this fact by allowing you to send data to a running info-beamer visualization from another program written in the language of your choice. In fact there's multiple ways to get data into a visualization:
- You can write into files in the directory of a running visualization: info-beamer instantly detects changed files and allows you to react to those changes. So you might write a JSON file in your program which info-beamer then instantly notices and loads. See the function util.file_watch to learn more about this.
- You can connect using TCP to info-beamer and send data to a running visualization. This way of communicating with info-beamer also allows a running visualization to export data to an external program. There's going to be a blog post about this in the future.
- You can send data using UDP. This way of communicating is recommended if you have lots of small updates that you want to send to your visualization.
This blog post will use UDP to send the current bitcoin exchange rates in multiple currencies to a visualization that displays those values on screen. First let's have a look at the code for the visualization (save this code in the file node.lua):
gl.setup(1024, 768) local json = require "json" local font = resource.load_font "font.ttf" local currencies = {} node.alias "bitcoin" util.data_mapper{ update = function(data) currencies = json.decode(data) end } function node.render() gl.clear(1, 1, 1, 1) font:write(30, 10, "Bitcoin", 100, .5,.5,.5,1) local y = 120 for idx, currency in ipairs(currencies) do local line = string.format("%.2f %s", currency.val, currency.sym) font:write(30, y, line, 160, .3,.3,.3,1) y = y + 160 end end
In the first line the visualization resolution is set to 1024x768 and the bundled json parser as well as the font file font.ttf is loaded. Just download any Truetype font file and place it in the current directory. I used Arial.ttf and renamed it to font.ttf.
The currencies variable contains a list of exchange rates for different currencies. Since we don't know these values yet we'll initialize it to an empty list for now. This list will later be updated by an external program.
The node.alias function sets the node alias name to bitcoin. Normally the name of a node is its directory name. Using node.alias allows you to set an alias that is independant of the directory name. External programs can address nodes using either of those names. By setting the alias bitcoin, external programs can now be sure that they reach this node when sending data to bitcoin.
Setting up data handlers
The util.data_mapper is where the magic happens. It defines Lua functions that can be called by external programs. To do that these programs send UDP messages to info-beamer. Here's what a messages has to look like:
bitcoin/update:[{"value": 123, "symbol": ":-)"}]
The part before the colon specifies the name of the info-beamer node (bitcoin) and the handler (update) that you want to send data to. The part after the first colon is the data that will be delivered to this handler. Now when you have another look at the usage of util.data_mapper, you'll see that there is a single handler called update defined:
util.data_mapper{ update = function(data) currencies = json.decode(data) end }
This handler will be called with the data as first argument. In this example the handler just parses this data as JSON and updates the variable currencies.
The remaining code in node.render is doing the visualization: It clears the screen, writes Bitcoin in large friendly letters and then iterates over the list of currencies and displays their value.
Let's run this info-beamer visualization:
pi@raspberry ~/bitcoin-example$ info-beamer .
Sending data to your visualization
Well. That's boring. The currencies variable is empty so there's nothing to display right now. Let's send some data to the running info-beamer visualization. So open another terminal and type this command:
pi@raspberry ~$ echo 'bitcoin/update:[{"val": 123, "sym": ":-)"}]' > /dev/udp/localhost/4444
This instructs your command shell (bash) to send data using UDP to the local machine (that's your PI!) on port 4444. info-beamer listens to port 4444 so the data you send ends up being handled by info-beamer. This is what the screen looks like:
Using an external program
Let's use an external program to fetch the current bitcoin value using HTTP and send it to info-beamer. I'll use Python in this example but you can use the programming language of your choice to do that. The important thing is that you send data to info-beamer. Here's what the python program looks like:
#!/usr/bin/python2.7 import socket, json, time, requests sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) DISPLAY_CURRENCIES = ['USD', 'EUR', 'GBP'] while True: ticker = requests.get("https://blockchain.info/ticker").json currencies = [] for currency_name in DISPLAY_CURRENCIES: currencies.append(dict( val = ticker[currency_name]['last'], sym = ticker[currency_name]['symbol'], )) data = json.dumps(currencies, ensure_ascii=False).encode("utf8") print data sock.sendto("bitcoin/update:%s" % data, ('127.0.0.1', 4444)) time.sleep(60)
This program uses the awesome requests library for python to do HTTP requests. It gets the current bitcoin exchange rates from the bitcoin.info API.
It gets the currencies to display (as defined in DISPLAY_CURRENCIES) from the returned value of the bitcoin.info API and creates the list that the info-beamer visualization needs.
It then encodes this list as JSON and sends it to the running info-beamer on localhost. It's using an UDP socket for that. Finally it sleeps 60 seconds so it doesn't overload the bitcoin.info API. Here's what info-beamer was showing on Nov 2, 2014:
Summary
I hope that this posting explained the basics of sending data to a running info-beamer visualization. Using external programs is the proper way to get dynamic data into your visualizations. Use the programming language you like the most to fetch and enrich data and send it to info-beamer.
Not only can you use any library and language you're already familiar with - it also decouples the visualization part from the potentially more complex data enrichment part.
To see more examples on how to use external data, have a look at this visualization from a conference, a remote controlled slideshow or an example on how to synchronize two info-beamer nodes.
Read more...
Recent blog posts
info-beamer hosted 14 releasedinfo-beamer hosted 13 released
info-beamer hosted 12 released
info-beamer hosted 11 released
More blog posts...
Learn more about info-beamer.com
The info-beamer hosted digital signage platformThe info-beamer pi software
Sign up to info-beamer hosted
info-beamer.com offers the most advanced digital signage platform for the Raspberry Pi. Fully hosted, programmable and easy to use. Learn more...
Get started for free!
Trying out the best digital signage solution for the Raspberry Pi is totally free: Use one device and 1GB of storage completely free of charge. No credit card required.
Follow @infobeamer on twitter to get notified of new blog posts and other related info-beamer news. It's very low traffic so just give it a try.
You can also subscribe to the RSS feed.
Share this post:
Questions or comments?
Get in contact!