Software apps and online services
After trying Resin.io briefly with a SomaFM Streaming Application, I was eager to experiment more with their cloud deployment platform. Maybe some new hardware, maybe some more complex project... In the end, it became a little bit of both: here's MrEdison, and portable IRC chat display based on Intel Edison.
The idea came from the fact that we have an IRC channel for the Taipei Hackerspace, #taipeihack on Freenode, just it is not very well (or rather: at all) frequented by people. I wanted to break that channel out of the computer, and put a physical window to it in the 'space, so people can see what's going on, and hopefully want to get on too!
Here's how the result looks like:
For this I've used parts that were pretty much lying around in the Hackerspace:
- an Intel Edison, then added...
- the Arduino Breakout Board,
- a Grove Base Shield
- a Grove RGB-LCD (that is controlled over the I2C lines)
- a Grove LED (on one of the digital pins)
I've started a new project in the Resin.io interface based on Edison. Downloaded their image (and checked out getting started guide), flashed it onto the board through the Android breakout board, and it was ready to get some code on (well, kinda).
In the docs I've found that there's a specific docker starter container made by the Resin team for Python code, and that looked like a good point to start off from.
First I was thinking using the default mraa library that Intel provides for the low level I/O, but fortunately also found UPM, a higher level library that already supports a lot of sensors and I/O - including the RGB-LCD! That saves a lot of time indeed, and has both Python and Node.js API for quicker code (besides the base C++).
Mraa is already installed on the base image, but UPM had to be added manually to the Dockerfile.
The base function of the code is crystallized out as:
- connect to a specified IRC server and join a specific channel
- listen to the messages there
- on the LCD display the messages as:
- first line shows the user that posted
- second line is the message posted, if longer than the width of the LCD then scroll it
- to quickly distinguish between people, assign different colours to the different users
- blink the LED on new messages
- keep doing this...
I've used the irc library in Python to create a simple IRC bot that listens to the channel and does the required I/O. Needed some code digging (because it's not too -- khm -- well documented), for example to enable SSL connection for the bot part of the code (for usingport 7070 on Freenode). In the end indeed "use the source, Luke!", as they write and it worked out.
The I/O part needed to be parallelized too, there used some part of the multiprocessing library that I haven't used before (Process), and some data sharing: the display can run and scroll the text, while the bot can notify the display's process when it needs to show something new. Same for notifying the LED, when it needs to blink.
For doing different colours for the different usernames I use hashing: run the username through SHA256, and use the 1st, 2nd, 3rd bytes of the resulting has as Red/Green/Blue for the backlight colour.
Here's the code in Python (2.x):
username = "MrEdison"
h = hashlib.sha256()
r, g, b = int(h.hexdigest()[0:2], 16), int(h.hexdigest()[2:4], 16), int(h.hexdigest()[4:6], 16)
# (115, 126, 15) or #737EF
Works pretty well!
The bot's settings (server name, port, channel, nickname) are all set through the Resin.io control panel as environment variables.
Environmental variables used at the moment:
- SERVER: the IRC server used, defaults to irc.freenet.net
- PORT: port used, has to be SSL-enabled, defaults to 6697
- CHANNEL: which channel to connect to, together with all the hashes, defaults to #mredison
- NICK: nick to choose, no authentication yet, defaults to mredison
- TIMEZONE: what timezone to display updates in standard tz database notation, defaults to UTC
This makes it quite flexible, can let the bot/setup monitor any channel on any network, though at the moment needs SSL-enabled server, but that's easy enough to change if someone wants to run the code and don't care about security... :P
For testing I was using mostly the #ubuntu and ##linux channels, as they seems to be pretty chatty!
It was a bit bumpy process, like most experimental works.
I2C: First I've run into some Edison/Docker related strangeness that messed with the I/O. Solved by Shaun from Resin, the trick being needing to mount the debugfs before running my code, so the kernel can configure things correctly:
mount -t debugfs nodev /sys/kernel/debug
Edit (8/1): This in the end wasn't enough, had to go back to the Edison GPIO Pin Muxing Guide, and turned their Example 4: Configure IO18/IO19 for I2C connectivity guide into a pretty hard core, but probably well commented bash script to set up I2C, which is called on start. Seems to work out!
Connectivity: There was also some issue with the bot timing out in a strange way and losing connection. I was about to rewrite the whole code in Node.js, but tried a quick client test first. Turns out that I was testing on port 6697 (which is I read the default SSL port), and that has some connection issues. After I've switched to 7070, all of that disappeared, and the connection seems pretty solid (looks like much fewer connection drops now).
There are some bugs that remain, though:
- Unicode handling is non-existent, so those posts can pretty much mess up the display
- There can be race conditions using the display, not the best threading code probably...
- At bootup, the LCD display is borked, but after adjusting the environment variables (without reboot), things sort themselves out! Maybe need to tweak the startup script and add some delay between the steps?
Otherwise it's working pretty well, the colour changes are fun, the text is readable, so I guess mission is accomplished!
The source code is on Github, and to set up your own version of this, just create a new Edison project, flash the system, clone the source code and push it to your application, finally define the environment variables SERVER, PORT, CHANNEL, NICK as they are suitable for you, and enjoy!
It would be probably good to create an enclosure for this setup, to hold the parts together more securely. Then drop it in the Hackerspace and set it up to listen to our IRC channel - and get chatting.
It's probably unlikely that I'll change much on it in the future, most I can think of is adding some more bells & whistles (or rather, literally a buzzer:), but that might be too much. The code works well enough, but pull requests are accepted!
I'm mostly just glad that the idea worked out, and the project is done. Now I can actually move onto another one (there are way too many projects on the waiting list, driving me nuts)....
What's your take on IRC? Do you use it? Would this project be useful for you somehow?
The original of this this writeup is from my blog: A window to IRC with Edison and Resin.
Drew down in the comment below asked to add the GTA III pager sound to this project. Well, challenge accepted!
Fortunately the UPM library I used has a buzzer function that do tones! So now the steps become:
- reverse engineer the tune
- code the tunes in with appropriate time and delays
The first step was done using Sonic Visualizer, by adding a spectrum layer, pulling the window down a bit (512 seems to work), and go through the file picking out the lower frequency peaks (not the harmonics!!). Also add the relative lengths, and pauses.
The result is not too bad, but I'm not a musical guy, pull requests are welcome to that section in the code!
The buzzer has to be attached to a PWM-capable GPIO pin: pin 5 seems to be working well.
I can't seem to really control the buzzer volume, so it's pretty annoying pretty soon. So use this as an optional add-on, I guess!