Using Perl to communicate with Single Line LED Sign

SVV-ML-80X7-RG

SVV-ML-80X7-RG

I recently inherited a single line LED sign made by SuperViewVision, Model Number SVV-ML-80X7-RG, and my first thought was “Great! I can stream cool stuff to the sign like tweets”. To my dismay the sign came with windows only software and little documentation. On top of that there was no easy method to programmaticly update the display. Each change to the message had to be done manually. I search for several days looking for protocol documentation. In the product description there is a blurb about protocol documentation available upon request. So, I attempted to communicate with the vendor asking for documentation. The vendor’s response was less than helpful. Evidently they sell the sign but allow resellers to re-flash the sign with their own protocols so they wanted to know the date I bought the sign and who I bought it from. This was information  I wasn’t privy to due to my method of acquiring the sign. After searching I started to get the feeling the sign was really old or its simply not used as often as other signs using some of the more main stream LED sign protocols because I couldn’t find anything!

The stage was set, the challenge clear. I was going to map out the protocol for the sign and use a perl script to communicate with it.

To understand how the sign communicated I used a windows serial port sniffer and started logging commands sent to the sign. As it turns out the protocol is a two (or more) step process. A wakeup signal followed by the command(s). Something like this:

PORT_WRITE -> ~128~
PORT_WRITE -> f01A\Y1\Z4\a\sHello World\r\r\r

To help you out, I’ve built a small perl script to help. Click here to download the perl script. I suggest renaming it from .txt to .pl If your running on a linux machine (like me) you will have to make the script executable before trying to run it.

Here is the usage syntax.

usage: perl post_to_sign.pl --port=/dev/ttyS0 --signid='~128~' --info 'info message' --alert 'alert message' --update 'update message' --setDTM
       --port   '/dev/ttyS0'     Define the port the sign is connected to. Defaults to /dev/ttyS0
       --signid '~128~'          Define the sign ID. Defaults to ~128~
       --info   'info message'   Post the string using the default format (bright green default size)
       --alert  'alert message'  Post the string using the alert format (flashing ALERT and scrolling in bright red)
       --update 'update message' Post string using the update format (flashing UPDATE and scrolling in bright yellow)
       --showDTM                 Will add the current date time to the message displayed
       --setDTM                  Updates the sign with the current date and time

The --info, --alert, and --update are all pre configured displays but you can pass any kind of slash command to send any combination of cool things. Here is an example of passing both an --alert and --info with some embedded embellishments.

perl post_to_sign.pl --port=/dev/ttyS0 --signid='~128~' --info 'Conns db1:\c12\h db2:\c12\h \rC\Y1\h\sServers:\c48\h Up:\c39\h Down:\b2\h \rC\Y1\h\scan you can a can as canners can a can' --alert '\djavtableau\b is NOT responding to ping!'

Now that I had a simple command line interface I built a script (not documented here) to pull my environment health and statistics every few minutes and update the sign.

Something else about the script, I havn’t tested it on a windows machine but I bet if you update the USE statement to point to the Win32::SerialPort module it should work.

That’s about it… each of the modes and other effects are further documented inside the perl file.
Enjoy!

Running Perl In Atrium Orchestrator

At work I’ve been transitioning to a new team that closely aligns itself with my goals of developing some sort of autonomous environment. To help us in our quest the company I work for chose BMC’s Atrium Orchestrator. Due to the dynamic nature of automation I needed to make use of the Script Adapter. Here are the quick and easy steps to get the Script Adapter installed and how to make use of it.

  1. Download and install the MSI installer from ActiveState (http://www.activestate.com/activeperl/downloads)
  2. Update the Dumper.pm file
    1. Location on an x64 machine is C:\Perl64\lib\data\Dumper.pm
    2. Make sure the file is not Read Only
    3. Open the file in Notepad
    4. Find and comment out the following line by adding a # (hash) in front of the line
      1. i. sprintf our $refaddr_format, Scalar::Util::refaddr(shift);
      2. ii. # sprintf our $refaddr_format, Scalar::Util::refaddr(shift);
    5. Save your changes
    6. Re-enable Read Only on the file
  3. Open Grid Manager and add the ro-adapter-script adapter
    1. When configuring the adapter make sure to give it a name of ScriptAdapter. Anything else won’t work
    2. In the other required field give the path to the perl.exe file
      1. i. C:\Perl64\bin\perl.exe
    3. Save your updates
  4. Add the ScriptAdapter to the peer(s)

Once you’ve added the script adapter taking advantage of the Perl engine is quite simple.

  1. Add the Script Activity to your process
  2. Double click on the Script object
    1. Add any input parameters
      1. i.      These input parameters are addressed within the perl script by their name: $input1
    2. Add your expected output parameters (similar to a returned result set from queries ect..)
      1. i.      Assign values to these output parameters from within your code like this: $output = “my output value”;
  3. To actually write your script click on the “View/Edit Script” button.
    1. Select the Scripting Language as Perl
    2. Write your script. An example looks like:$strOutput = lc $strInput;
    3. The lc is the lower case function

And there you have it… One of the huge advantages of this is the ability to pass data through regular expressions, validating or searching for matches.

Another simple example using perl with regular expressions to validate an IP is:

if( $strIP =~ m/^(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)\.(\d\d?\d?)$/ ){
  $ strOut =("IP Address $strIP --> VALID FORMAT! \n");
  if($1 <= 255 && $2 <= 255 && $3 <= 255 && $4 <= 255){
    $strOut=("IP address: $1.$2.$3.$4 --> All octets within range\n");
  }else{
    $ strOut =("One of the octets is out of range. All octets must contain a number between 0 and 255 \n");
  }
}else{
  $ strOut =("IP Address $strIP --> NOT IN VALID FORMAT! \n");
}

Hope this helps.