pjlink communication videoprojector panasonic tcp

simon.ben@free.fr's icon

Hi,

I'm wondering if anyone had already tried to communicate via ethernet with a panasonic projector. It works fine on a web browser but I'd like to do it in max.
It uses the "pjlink" protocol. (http://pjlink.jbmia.or.jp/english/index.html)
It's uses TCP on port 4352.
After several tried with the mxj net.tcp.send object, I didn't succeed. Each time I'm sending something in it, it returns the message via the failure outlet.
Can anyone help me?

Regards.

Benoit SIMON.

topher lafata's icon

I dont think you can send raw data with net.tcp.send. It probably
sends atoms, which of course the projector will not understand. You
would need to make a custom mxj object that communicates with the
projector using whatever protocol it expects. There is a lot of stuff
about java client/server socket programming on the internet so it
shouldnt be too difficult.
t

On Sep 20, 2008, at 06:05 AM, benoit simon wrote:

>
> Hi,
>
> I'm wondering if anyone had already tried to communicate via
> ethernet with a panasonic projector. It works fine on a web browser
> but I'd like to do it in max.
> It uses the "pjlink" protocol. (http://pjlink.jbmia.or.jp/english/
> index.html)
> It's uses TCP on port 4352.
> After several tried with the mxj net.tcp.send object, I didn't
> succeed. Each time I'm sending something in it, it returns the
> message via the failure outlet.
> Can anyone help me?
>
> Regards.
>
> Benoit SIMON.

nicolai's icon

Here is what I just made in JAVA at the Danish National Gallery.

I made a java package called pjLink. Within this package i made following 2 classes. When execute as compiled it tells how to use it.

* Remember to update line "pjLinkSocket = new Socket("172.20.X.X", 4352);" with the correct IP-Address
* Only works on Projector without Password. Haven't implemented the md5 authentication.

CLASS PjLinkCom

package pjLink;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

import pjLink.Projector.*;

/**
 * @author Nicolai Bob Zachariassen
 * @year 2009
 * Application to turn power on / off of a projector using PJLink protocol
 */
public class PjLinkCom {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Projector projector = new Projector();

        for (String s: args) {
            // Turn power on
            if (s.equals("on") && projector.POWR == PowerState.undefined){
                projector.POWR = PowerState.on;
                System.out.println("Turning Power On");
            }

            // Turn power off
            if (s.equals("off") && projector.POWR == PowerState.undefined){
                projector.POWR = PowerState.off;
                System.out.println("Turning Power Off");
            }

            // Switch Input to: rgb1
            if (s.equals("rgb1") && projector.INPT == InputState.undefined){
                projector.INPT = InputState.rgb1;
                System.out.println("Switching Input to RGB1");
            }
            // Switch Input to: rgb2
            if (s.equals("rgb2") && projector.INPT == InputState.undefined){
                projector.INPT = InputState.rgb1;
                System.out.println("Switching Input to RGB2");
            }
            // Switch Input to: video
            if (s.equals("video") && projector.INPT == InputState.undefined){
                projector.INPT = InputState.rgb1;
                System.out.println("Switching Input to VIDEO");
            }
            // Switch Input to: svideo
            if (s.equals("svideo") && projector.INPT == InputState.undefined){
                projector.INPT = InputState.rgb1;
                System.out.println("Switching Input to S-VIDEO");
            }
            // Switch Input to: dvi
            if (s.equals("dvi") && projector.INPT == InputState.undefined){
                projector.INPT = InputState.rgb1;
                System.out.println("Switching Input to DVI-D");
            }
        }

        Socket pjLinkSocket;
        try {
            System.out.println("Opening connection");
            pjLinkSocket = new Socket("172.20.X.X", 4352);

            DataOutputStream ostream = new DataOutputStream(pjLinkSocket.getOutputStream());
            BufferedReader istream = new BufferedReader(new InputStreamReader(pjLinkSocket.getInputStream()));            

            System.out.println(istream.readLine());

            if (projector.INPT == InputState.undefined && projector.POWR == PowerState.undefined){
                System.out.println("nnSyntax:n");
                System.out.println("tTurn on/off projector: java pjLink.PjLinkCom on|off");
                System.out.println("tSwitch input on projector: java pjLink.PjLinkCom rgb1|rgb2|video|svideo|dvi");
                System.out.println("ntExample: java pjLink.PjLinkCom on rgb2");
            }

            if (projector.INPT == InputState.undefined){
                ostream.writeBytes("%1INPT ?r");
                System.out.println(istream.readLine());
            }else if (projector.INPT == InputState.rgb1){
                ostream.writeBytes("%1INPT 11r");
            }else if (projector.INPT == InputState.rgb2){
                ostream.writeBytes("%1INPT 12r");
            }else if (projector.INPT == InputState.video){
                ostream.writeBytes("%1INPT 21r");
            }else if (projector.INPT == InputState.svideo){
                ostream.writeBytes("%1INPT 22r");
            }else if (projector.INPT == InputState.dvi){
                ostream.writeBytes("%1INPT 31r");
            }

            if (projector.POWR == PowerState.undefined){
                ostream.writeBytes("%1POWR ?r");
                System.out.println(istream.readLine());
            }else if (projector.POWR == PowerState.on){
                ostream.writeBytes("%1POWR 1r");
            }else if (projector.POWR == PowerState.off){
                ostream.writeBytes("%1POWR 0r");
            }

            ostream.close();
            istream.close();
            pjLinkSocket.close();

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

CLASS Projector

package pjLink;

public class Projector {
    protected enum PowerState{
        on, off, undefined
    }
    protected enum InputState{
        rgb1, rgb2, video, svideo, dvi, undefined
    }
    protected PowerState POWR;
    protected InputState INPT;

    Projector(){
        POWR = PowerState.undefined;
        INPT = InputState.undefined;
    }

}

simon.ben@free.fr's icon

Hi Nicolai,

Sorry for the late reply, but I just took the time to look at your job.
Have you already try your classes in max?
I haven't succeed to work with.
There are missing lines before compiling:

import com.cycling74.max.*;

or

public class PjLinkCom extends MaxObject{

The compiling was successful after adding these but the "mxj pjLink.PjLinkCom" object doesn't understand rgb1 or another strings...

If you will have few time to give me some advices, I would appreciate.

Regards,

Benoit.

Owen Green's icon

Nicolai's code will additional need some small changes to run under mxj as well as extending MaxObject:

main() needs to be changed to a method that will take input from the max environment. Given the way the code is written, the quickest way to do this would be to change it to a handler for a list of symbol atoms.

deKam's icon

Hi

I searched the forums today for PJ LINK, since I am also wanting to control a Panasonic projector from Max… this thread is a year old, but I was wondering if anyone had any further success, using the java code or otherwise? The command structure itself is more like a serial string then anything else. I just wish the serial object had an option to send over a tcp connection :)

any help appreciated

Johnny DeKam

deKam's icon

PS I'm fairly java illiterate -- could someone take a whack at converting the javacode earlier in the thread to mxj?

I am all setup to test it here with the projector on the network. The only functionality I am really after is turning the power on and off.

many thanks

Johnny

deKam's icon

More on this saga, I put this on the back burner some time ago, using an rs-232 implementation instead for that particular project, but now I am about to add more projectors for a new project, and need to revisit PJLINK.

Today I found some new GPL java pjlink code, haven't had a chance to try it yet in max... but anyone care to take a look at compatibility / portability?

/**
*
*/
package pjlinkApp;

import java.net.*;
import java.security.*;
//import java.util.*;
import java.io.*;
//import java.lang.*;

/**
* @author sebastiaan
*
*/

public class PjlinkApp {
    private String IP;
    private String Password;

    public void PjlinkSetting(String projectorIp,String ProjectorPw){
        IP=projectorIp;
        Password=ProjectorPw;
    }

    public void projectorOn(){
        this.sendRecvData(new JLinkDataSend("POWR","1"));
    }

    public void projectorOff(){
        this.sendRecvData(new JLinkDataSend("POWR","0"));
    }

    public String projectorHours(){
        JLinkDataRecv recv=this.sendRecvData(new JLinkDataSend("LAMP","?"));
        if(recv==null){System.out.println("recv null");return null;}
        if(recv.arg==null){System.out.println("arg null");return null;}
        String[] lamphours=recv.arg.split(" ");

        System.out.println("lamp testing");
        return "Total lamp hours: "+ lamphours[0];
    }

    public String projectorName(){
        JLinkDataRecv recv=this.sendRecvData(new JLinkDataSend("NAME","?"));
        if(recv==null)return null;
        return recv.arg;
    }

    private String readSocketData(BufferedReader in){
        try{
            return in.readLine();
        } catch (IOException e){
            System.out.println("Read failed");
         System.exit(1);
        }
        return null;
    }

    private JLinkDataRecv sendRecvData(JLinkDataSend dataOut){
        PrintWriter out=null;
        BufferedReader in=null;
        Socket PJsock = null;
        JLinkDataRecv recvd=null;
        String[] Data=null;

        try{
            PJsock=new Socket();
            PJsock.bind(null);
            PJsock.connect(new InetSocketAddress(IP,4352), 2000);
            out = new PrintWriter(PJsock.getOutputStream(),true);
         in = new BufferedReader(new InputStreamReader(PJsock.getInputStream()));
        } catch (UnknownHostException e) {
     System.out.println("Unknown host: "+IP);
     return null;
     } catch (IOException e) {
     System.out.println("Cannot connect to ip: "+IP);
     return null;
     }

     Data=readSocketData(in).split(" ");
     if(!Data[0].equals("PJLINK")){
         System.out.println("projector did not send out magic PJLINK");
     }else{
         if(Data[1].equals("1")){
             System.out.println("projector uses secured link");
             String secureComp= new String(Data[2]+this.Password);
             try{
                 MessageDigest md5 = MessageDigest.getInstance("MD5");
                 md5.reset();
                 md5.update(secureComp.getBytes());
                 byte[] digested=md5.digest();
                 String tmp = "";
                 String res = "";

                 for (int i = 0; i < digested.length; i++) {
                     tmp = (Integer.toHexString(0xFF & digested[i]));
                     if (tmp.length() == 1) {
                         res += "0" + tmp;
                     } else {
                         res += tmp;
                     }
                 }
                    System.out.println("adding secured MD5 digest: "+res);
                    dataOut.AddSecurityData(res);
             }catch(NoSuchAlgorithmException nsae){
                 System.out.println("could not find MD5 digest");
             }

         }
         System.out.println("sending to beamer: "+dataOut.outData);
         out.write(dataOut.outData.toCharArray());
         out.write(0x0d);
         out.flush();
            //Receive text from server
         String dataIn=readSocketData(in);
         System.out.println("received from beamer: "+dataIn);
         if(dataIn!=null){
             recvd=new JLinkDataRecv(dataIn);
         }else{
             System.out.println("received a NULL string from beamer!");
         }

     }
        System.out.println("closing socket");
        try {
            PJsock.close();
        } catch (IOException e) {
            System.out.println("failure on socket close");
            e.printStackTrace();
        }
        return recvd;
    }        

    class JLinkDataRecv{
        public String cmd;
        public String arg;
        public JLinkDataRecv(String data){
            cmd=data.substring(2,4);
            arg=data.substring(7);
        }
    }
    class JLinkDataSend{
        public String outData;
        public JLinkDataSend(String cmd,String arg){
            outData="%1"+cmd+" "+arg;
        }
        public void AddSecurityData(String addData){
            outData=addData+outData;
        }
    }

}

reno-'s icon

You can use standard mxj net.tcp.send object to remote Panasonic Videoprojectors with PJLink protocol.

Here is a simple patch which open and close the shutter…

I hope it will help…

Max Patch
Copy patch and select New From Clipboard in Max.

admant's icon

Hello,

the thread is old, but it is exactly about what I am looking for help for. Did anybody succeed in controlling a projector with PJLink and max? Anybody can confirm Reno's method does work? I tried with it, but with no luck.

cheers