Controlling A Cruise Ship’s Massive Video Display with Python
Time to read: 6 minutes
In this article you will learn how to control an NEC display via RS232 or UTP connection with the official nec-pd-sdk Python package from NEC. Reasons for controlling NEC displays programmatically vary from automatic turning them on and off, scheduling, monitoring, and more.
I became interested in controlling NEC displays programmatically when I was building a virtual waterfall system and had issues with one of the displays. I needed to restart one manually every few days when it entered an error state and displayed only a black picture.
Next, I will explain where and how this NEC display was used and then we’ll dive straight into the code.
General Overview of a Virtual Waterfall System
I was responsible for the maintenance of a 17 meter tall virtual waterfall on a cruise ship:
There are 34 NEC X551UN displays in the setup. Each display has a dedicated Linux PC for playback. Playback is delivered from the Linux PC to the NEC display via SDI, and each display has a DVI to HDMI active converter. An active converter means that the converter also supplies power.
Each Linux PC plays video for only one display. One additional Windows PC is responsible for synchronizing playout of all of the Linux PCs.
Installing the nec-pd-sdk Python Package
I recommended always using a virtual environment when developing with Python.
To install nec-pd-sdk with pip, run:
Let’s Write Some Code
The entire display program is around 100 lines. Let’s go over it step by step.
We begin by importing the libraries we’ll need:
The code is compatible with Python version 2.7 and later. We add print syntax compatibility by importing print_function
from the __future__
package.
The next lines import modules from the standard library and the last 3 lines import from the nec-pd-sdk
package.
We have three custom functions to make code more readable:
touch
is similar to the touch
unix command; it will make an empty file. We are using files with specific names as notifications.
The IP addresses of the NEC displays are stored in a JSON file with the name display_config.json
. So if we want to add or remove some displays we do not need to change source code, just one JSON configuration file.
In our current directory, let’s create a sample display_config.json
:
The get_display_list
function reads display_config.json
and returns the content of display_list
as a Python
list.
The get_screen_state
function takes an established connection to a display and returns a Python dictionary state and diagnostics. The state, or status
is either on or off. The diagnostic message, or diagnosis
is normal or an error description (eg. No signal;
)
displays_with_error
is a
list of all displays that had an error. In that function, we loop through all displays and if a display is in error state it is added to this list (and turned off).
With the
for loop we access each display from the get_display_list
function.
Inside try we open a connection to a display with NECPD.open(display). If there is some exception, we use except PDError as msg to display the error.
After that we have try with final for closing the connection to the display.
Inside of
try with
monitor_id = 1; pd.helper_set_destination_monitor_id(monitor_id) we are accessing the first display in pd
. In our setup we have one network UTP Cat5e cable connected to each individual display so each monitor_id
is always 1. A NEC display setup can also be done as a daisy chain, and then each display will have a different id. In our setup we do not use daisy-chaining, so we know display id is always 1.
In the loop we are getting displays and testing them for errors. If an error is detected, we add the display to the displays_with_error
list and turn off the display with
pd.command_power_status_set(PD_POWER_STATES['Off']). Visually, if a display is showing only a black screen the display is in an error state.
If at least one display had errors, then we will wait for 5 minutes with time.sleep(), calling time.sleep(FIVE_MINUTES).
As you recall, we already turned off all displays with errors. From my experience, 5 minutes of having a display off is enough to clear all the errors, so from the next ‘on’ command display will work well.
After that, we have similar code for connecting to each display with monitor_id = 1. The major difference is now we are sending the command to turn a display on with pd.command_power_status_set(PD_POWER_STATES['On'])
This code appears in the same ‘if’ block and so we can include some code for notifications.
This code is executed every hour on the computer in the server room. We needed some system of notifications to know when and which displays had errors. Because this computer is not connected to internet or rest of office network, we can not send an email or use Twilio’s SMS service.
One practical solution was to use files as error notifications. Our file names have the date, time and number of displays that had an error. E.g.: 20171109-111512_display_52_had_error.txt
So, every few days when we checked for errors we’d know when and which displays had errors that required a restart.
Testing the Code
For all the current code to be executed, the NEC display must be in No Signal;
state.
In order to test turning a display ON
and OFF
, add the line
displays_with_error = [‘192.168.1.52’] before the
if len(displays_with_error) > 0: line (where 192.168.1.52
is the IP address of an NEC display).
Controlling NEC Displays with Python
This is just one example of how the nec-pd-sdk package can be used.
Everything that can be done manually with an NEC display can also be done programmatically with Python and nec-pd-sdk.
If you’ve automated an installation with NEC displays in the past, please share your examples.
Sasa Buklijas can be contacted via email through his website at http://buklijas.info/blog/.
Editor: Want to see more of the incredible waterfall in action? Sasa sent over three videos of the installation. Enjoy!
- Looking at the span of the waterfall: python_nec_waterfall_height
- View from the top of the waterfall: python_nec_waterfall_look_down
- Looking from the bottom of the falls up: python_nec_waterfall_ground
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.