Monday, December 5, 2016

Retrofitting a LED Display into the IoT

I have a LED panel. I have an ESP8266. Annhmm! LED - ESP!
Kinda works well if you spell it: L E D - E S P! Or maybe not...

Viral pun aside, I had an old LED panel laying around my workshop. It once had uses in one of my old companies, spitting out Forex prices and news. It was pretty cool back then.
I knew it had a RS-232 interface which I have hacked before, but I managed to lost all code for it long time ago. The remote control had batteries inside for years, which is usually not a very good idea. Battery fluids spilled out  everywhere and it was basically useless.
I could fix the remote, replace the rusted contacts, clean up the board and so on...
But why fix when you can retrofit? And why a physical remote when you have a bunch of ESP8266 around?
Let's put this old dog into the IosT.

(Yes, IosT, as in Internet of Shitty Things since I'll not be worrying about security. I can, because I'm just an hobbyist messing around with stuff. And because I work with security for a living. And because I'm lazy. And just because. But if you are a toaster/fridge/door/camera/ manufacturer, please do worry about security... Last thing I need is to be cut offline for a day because a botnet of lawn mowers screws up my ISP)

Anyway, I had lost all documentation on the LED panel and the casing had no brand or any indication of manufacturer. Luckily for me, the panel prints out its model as soon as it boots: AM03127
This made it easier to find some documentation about it.

So I pop open the LED panel and behold two nice contacts on the board marked as TX / RX. Great, I'll just solder some pins to it and use that as an entry point.

But we can't just connect the serial pins on the ESP8266 to the RS-232 port, since RS-232 physical interface works with different voltages.
There are several articles written on how to connect an Arduino to the RS-232 port. I used this excellent article on  ArduinoDIY blog, based on the MAX232, to build my own interface.
I used it since I had all parts that I need to built one in my workshop. If you have a ton of old stuff laying around, you will most likely find a MAX232 or similar IC in one of your old boards.

Since the power plug is also close to the TX/RX location and I had more than enough space to put the ESP-12E and all the support hardware.

In a nutshell, the retrofit involves a power converter to get the 3.3V for the ESP-12 (marked orange), the ESP itself (marked green), the MAX232 interface board (marked blue) and finally the LED Display itself:

Lots of wires going around but it's actually quite simple. It's ugly but out of sight.

As for the software, on the ESP side, I just cannibalized the WiFiTelnetToSerial Example, a transparent UART to Telnet Server made by Hristo Gochkov.
On the client side, not wanting to go through the specs all over again, I used Christian Sullivan toledo, which has most of the stuff implemented for my needs.
I just needed to patch the code so it prints to stdout instead of a serial connection.

(UPDATE: you can now fetch the working code at github without the need for patching, thanks Christian)

Here's the patch for version which adds a --stdout flag:

--- orig/    2008-04-14 11:57:12.000000000 +0100
+++    2016-10-26 15:15:38.920431334 +0100
@@ -59,6 +59,7 @@
     global _version
     global _output
     global _debug
+    global _stdout
     _port       = "COM7"
     _message    = "snicklfritz982342"
@@ -79,9 +80,10 @@
     _version    = ""
     _output     = 0
     _debug      = 0
+    _stdout        = 0
-        opts, args = getopt.getopt(argv, "hvof:s:l:m:p:c:", ["help", "raw=", "version", "output", "font=", "sid=", "line=", "message=", "port=", "intro=", "exit=", "speed=", "bell=", "color=", "date", "time", "link=", "page=", "runpage=", "debug"])
+        opts, args = getopt.getopt(argv, "hnsvof:s:l:m:p:c:", ["help","stdout", "raw=", "version", "output", "font=", "sid=", "line=", "message=", "port=", "intro=", "exit=", "speed=", "bell=", "color=", "date", "time", "link=", "page=", "runpage=", "debug"])
     except getopt.GetoptError:
@@ -90,6 +92,8 @@
         if opt in ("-h", "--help"):
+        if opt in ("-n", "--stdout"):
+            _stdout = 1
         if opt in ("--raw"):
             _raw = arg
@@ -369,6 +373,7 @@
     print "                    and XOR checksum"
     print "-m (--message=)   Set the desired message (call this flag before output)"
     print "-o (--output)     Output to sign (call this flag last)"
+    print "-n (--stdout)     Only print command, no serial connection"
     print ""
     print "-------------------------------------------------------------------------"
     print 'example: ./ --link="ABACAB" --output'
@@ -379,6 +384,9 @@

 def serout(finalMessage):
    # set up serial port
+    if (_stdout == 1):
+        print finalMessage
+        return
     ser = serial.Serial(_port, 9600, timeout=3)
     # clear out the buffer 

After making sure the ESP-12E is working and has an IP address (in this case , just pipe the output to the telnet port:

./ --stdout -f 2 --message='I can haz ESP' -c rainbow --page=A --output | nc 23

All in all, it's not a complicated hack and it's pretty much generic, you could control any other RS-232 based hardware you have using a similar setup.

Sorry for the long post, here's a potato:

Wait, that's not a potato. It's one of the first messages someone left on the board. A news feed.
No, its a live snapshot of my LED - ESP board. And the live video is here:
Also, at lives the direct serial interface to the board.
If you reached this far in the post and you want to test it out, you can send serial commands to serial interface and watch the results in the live feed.
Go ahead, send me a message (I'll probably regret this...). You can patch and use and pipe it via netcat as the example bellow:

./ --stdout -f 2 --message='I HaXoR L33T' -c rainbow --page=A --output | nc 8023