My brother had the awesome idea to stay organized this school year with a scrolling LED display that would read the next five tasks off a Google Calendar. This is the exciting end result! The LED display we used unfortunately ran only proprietary software called PowerLed, giving me no way to programmatically set the text the screen was displaying and instead requiring each line be manually entered (like some kind of neanderthal). Fortunately Python has tools for automating actions in even the gnarliest GUI programs, so I wrote up this guide about how I managed to make this dumb device smart!
THE PROBLEM
It’s <current year> and manufacturers are still shipping hardware with awful proprietary software and no way for the end user to tinker with it. Additionally it is not web-friendly and all information has to be edited by hand.
The specific sign I worked with was this one although many signs originating in Asia ship with the same PowerLed software, so this guide should help you out! I made use of the WiFi interface, so if your sign does not have one you should check if it has a serial interface instead and make a few modifications to my program (remove the Wifi stuff, have the program click the button to send the configuration over USB for example).
THE SOLUTION
(TL;DR here is the code!)
There are a number of tools that let you click through GUI programs and automate tasks with Python, but today I am going to focus on pywinauto, a popular set of modules for automating tasks in Windows GUI programs. This is appropriate because as far as I can tell my sign only came with a Windows version of the software (although there are mobile apps that work with it supposedly). Pywinauto works by opening a program at a specified path and then navigating down menus it can see. For example, I can tell it to send my configuration by telling it to click a certain member of the Tools menu at the top of the screen: ‘window.menu_select(“Tools(T)->Send All”)’. It’s that easy! Those names were copied directly from the GUI itself.
I made use of the Google Calendar API which lets me programmatically pull down information from a Google Calendar. At the time of writing Google gives a generous one million queries per day which I cannot imagine one person would ever be able to exceed. To be safe though, my code updates the sign’s text every three minutes (although this can be changed at the top of main.py). The program I wrote pulls down the next five events on your calendar and processes them to be displayed by the sign.
How does this all work?
- PowerLed uses ledprj files which are essentially just XML files. I made my own template with placeholder text (‘REPLACE1’, ‘REPLACE2’, etc.) and saved this template alongside my Python script. This template let me play with scroll speed, font size, and other settings using the PowerLed software and trial and error with my display. To automate updating the template with Python, I simply read in this template file and do a find/replace for ‘REPLACE1’ and so forth with the five events I pulled from Google Calendar. When PowerLed reads this file, these strings are sent instead!
- The LED sign broadcasts its own WiFI network that I must connect to in order to update the device. I use subprocess calls to netsh to drop off my WiFi and then connect to the display.
- I use pywinauto to open PowerLed, which I have already pointed at my LEDprj file, and connect to the device. I then automated the process of pressing the ‘send’ button to update the display. Once updated, pywinauto automatically closes PowerLed.
- The project then waits three minutes and pulls down the next five events again, updates the sign, and so on until the program is stopped.
By noticing that the LEDPrj files were really just XML files I saved a great deal of time reverse engineering how I can get Python to update this sign. While there is no API or command line interface for the software, pywinauto let me quickly get the computer updating the sign itself.
Now I am sure you’re thinking ‘This is all fine and good, but do I need to let this program run forever, popping open this PowerLed thing every three minutes?’ – the answer is yes. But there is a solution! Upcycle an old laptop (68% of Americans have an unwanted computer in their home) or make use of a cheap Intel Compute Stick or similar device (make sure it runs Windows, the cheapest ones run Linux). I used an inexpensive Windows compute stick with an Intel Atom processor inside that more than handily can run this program on loop forever.
How do you get this set up for yourself? Head on over to the Git repo and check out my README, it’ll fill you in! The gist is to clone the repository, follow Google’s procedure to enable the Calendar API and get a credentials file, change the values in the program so that it knows what time zone you are in and what networks it needs to connect to (I don’t pass credentials, the program expects you to have connected to your sign and your home network before) and then give it a try!
TROUBLESHOOTING
- I assume you have PowerLed installed and you made sure the path in the program is pointed at where you installed it
- I assume you have connected to your sign and your home network before
- I assume that you have loaded display.ledprj in PowerLed and then exited the program so that it will load next time you open PowerLed
- I assume you are running Windows and that you have installed Python 3
SHARING THE SOLUTION
My code and instructions can be found here.
Here are the exact products I used: