Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions PJLink-TCP-Network-Command/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Overview
------------

This plugin allows a BrightSign to operate and control a projector using the [PJLink](http://pjlink.jbmia.or.jp/english/) standard. PJLink commands are sent as hexadecimal-formatted messages over the local network using a TCP connection.

## Installation

In BrightAuthor, while editing a presentation, open the Autorun presentation properties at **File > Presentation Properties > Autorun**.

1. Add a new *Script Plugin*:

* **Name**: _pjlink_ (in all lowercase letters)
* **Path**: Select `pjlink.brs` as the path.

2. Set the PJLink IP Address and optionally the TCP port number. Create two **User Variables** by going to **File > Presentation Properties > Variables** and adding the following:
* **pjlink_projector_ip** - set the default to your projector's IP Address
* **pjlink_projector_port** - (optional) set to the TCP port number to address the projector. If this variable is not set the plugin will use port **4352**.


## Usage

This plugin includes two named commands: "poweron" and "poweroff". Otherwise actual raw PJLink commands can be sent as well.

There are two methods of usage for this plugin:

1. Using Send Plugin Message in an interactive presentation:
* **Advanced > Send > Send Plugin Message**. Select the "pjlink" plugin. In the parameters block, enter one of the following:
* **poweron**
* **poweroff**
* **input-to-dvi**
* **input-to-hdmi**
* **shutter-open**
* **shutter-closed**
* Any raw PJLink command, such as **INPT 32** to switch to the digital input.

2. Direct messaging with UDP datagrams. Commands must be prefixed with "pjlink!":

' Named commands from this plugin:
' power the projector on and off
pjlink!poweron
pjlink!poweroff

' "Raw" PJLink commands. Format: pjlink!<command>
' power the projector on and off:
pjlink!POWR 1
' power the projector off:
pjlink!POWR 0
' switch inputs:
pjlink!INPT 11
pjlink!INPT 32

## Testing

The [PJLink Test software](http://pjlink.jbmia.or.jp/english/dl.html) can be used to confirm commands are being sent/processed on the projector end. (Configure the Network under the Set up menu of the PJLinkTest4PJ exe.)

With telnet enabled on the BrightSign unit you can see messages from the pjlink plugin printed to the screen. Connection details (IP and port) as well as hex-encoded commands are printed.

To generate the required hex string for additional pre-baked commands, try this in csharp:

string cmd = "INPT 31"
BitConverter.ToString(System.Text.Encoding.ASCII.GetBytes("%1" + cmd + "\r\n")).Replace("-", "")
163 changes: 163 additions & 0 deletions PJLink-TCP-Network-Command/pjlink.brs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
' Based on PJLinkOn BrightSign Plugin by Tweaklab
' v1.00

Function pjlink_Initialize(msgPort As Object, userVariables As Object, bsp as Object)
print "pjlink_Initialize - entry"

pjlink = newpjlink(msgPort, userVariables, bsp)

return pjlink
End Function

Function newpjlink(msgPort As Object, userVariables As Object, bsp As Object)
print "newpjlink"
s = {}
s.msgPort = msgPort
s.userVariables = userVariables
s.bsp = bsp
s.ProcessEvent = pjlink_ProcessEvent

s.projector_ip$ = ""
s.projector_port = 4352
s.debug = true
' s.dlog = pjlink_dlog

' SetParamsFromUserVariables(s, userVariables)
' set IP address from user variables
if userVariables.DoesExist("pjlink_projector_ip") then
myvariable = userVariables.Lookup("pjlink_projector_ip")
if myvariable <> invalid then
s.projector_ip$ = myvariable.GetCurrentValue()
s.bsp.diagnostics.printdebug("set pjlink ip address: " + s.projector_ip$)
endif
endif

' set projector port
if userVariables.DoesExist("pjlink_projector_port") then
myvariable = userVariables.Lookup("pjlink_projector_port")
if myvariable <> invalid then
s.projector_port = myvariable.GetCurrentValue()
s.bsp.diagnostics.printdebug("set pjlink port: "+s.projector_port)
endif
endif

return s
End Function

Function pjlink_ProcessEvent(event As Object) as boolean
print "pjlink_ProcessEvent"
print " type of message is: ";type(m)
print " type of event is: ";type(event)
retval = false

' define the message "%1POWR 1" in HEX to power ON the projector
' %1POWR 1 = Power On
' projector_message$="2531504F575220310D0A"

if type(event) = "roAssociativeArray" then
if type(event["EventType"]) = "roString" then
if event["EventType"] = "SEND_PLUGIN_MESSAGE" then
if event["PluginName"] = "pjlink" then
pluginMessage$ = event["PluginMessage"]
print "SEND_PLUGIN/EVENT_MESSAGE:";pluginMessage$
messageToParse$ = event["PluginName"]+"!"+pluginMessage$
retval = pjlink_ParsePluginMsg(messageToParse$, m)
endif
endif
endif
elseif type(event) = "roDatagramEvent" then
' UDP Datagrams for pjlink!<command>
msg$ = event
if (left(msg$,6) = "pjlink") then
retval = pjlink_ParsePluginMsg(msg$, m)
endif
endif

return retval
End Function

Function pjlink_ParsePluginMsg(msg As string, s As Object) as boolean
print "pjlink_ParsePluginMsg"
retval = false

r = CreateObject("roRegex", "^pjlink", "i")
match = r.IsMatch(msg)
if match then
retval = true
command = ""

r2 = CreateObject("roRegex", "!", "i")
fields = r2.split(msg)
numFields = fields.count()
if (numFields < 2) or (numFields > 2) then
s.bsp.diagnostics.printdebug("pjlink Incorrect number of fields for command:"+msg)
return retval
else
' numFields = 2
' To generate additional pre-baked commands, try this in csharp:
' string cmd = "INPT 31"
' BitConverter.ToString(System.Text.Encoding.ASCII.GetBytes("%1" + cmd + "\r\n")).Replace("-", "")
if fields[1] = "poweron" then
' %1POWR 1\r\n
command = "2531504F575220310D0A"
elseif fields[1] = "poweroff" then
' %1POWR 0\r\n
command = "2531504F575220300D0A"
elseif fields[1] = "input-to-dvi" then
' %1INPT 31\r\n
command = "2531494E50542033310D0A"
elseif fields[1] = "input-to-hdmi" then
' %1INPT 32\r\n
command = "2531494E50542033320D0A"
elseif fields[1] = "shutter-open" then
' %1AVMT 30\r\n
command = "253141564D542033300D0A"
elseif fields[1] = "shutter-closed" then
' %1AVMT 31\r\n
command = "253141564D542033310D0A"
else
' append %1 and \r\n to the command
ba = CreateObject("roByteArray")
ba.FromAsciiString("%1" + fields[1] + Chr(13) + Chr(10))
command = ba.ToHexString()
endif
endif
' s.bsp.diagnostics.printdebug("pjlink command found: " +command)
print "pjlink command assigned: ";command
retval = pjlink_SendProjectorMessage(command, s)
endif

return retval
End Function

Function pjlink_SendProjectorMessage(hex_msg as string, s As Object) as boolean
print "Connecting to projector at ";s.projector_ip$; ":";s.projector_port

sock=CreateObject("roTCPStream")
if sock=invalid then
print "Failed to create roTCPClient object"
stop
endif
if sock.ConnectTo(s.projector_ip$, StrToI(s.projector_port)) then
' print "Connected"
bytes = CreateObject("roByteArray")
sleep(500)
bytes.FromHexString(hex_msg)
print "Sending PJLink message: ";hex_msg
sock.SendBlock(bytes)
return true
else
print "Failed to connect to projector"
sock = invalid
endif

return false
End Function

' Sub pjlink_dlog (error$ as String)
' m.bsp.logging.WriteDiagnosticLogEntry("99plgn", error$)
' 'm.bsp.diagnostics.printdebug(error$)
' print error$
' slog = createobject("roSystemLog")
' slog.sendline(error$)
' End Sub