This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

pj talk
#1
Hi

I am trying to create a library for PJ talk communication with a Sony VPL-HW65ES Projector

I am experiencing some difficulties

protocol description is very limited, so far I found the following info
http://forum.coolux.de/viewtopic.php?t=2004&p=6623
http://ec1.images-amazon.com/media/i3d/0...015642.pdf


From what I figure out I need to send the following hex values

projector on
h01 h00 hA9 h17 h2F h00 h00 h00 h3F h9A

project off
h01 h00 hA9 h17 h2E h00 h00 h00 h3F h9A

My LUA knowledge is still limited

How can I setup a socket and communicate the above hex values ?
- how to setup the socket ?
- how to send hex values ?

Thanks
Nicky
Reply
#2
Try this example, just change ip variable to your projector IP address:

Code:
require('socket') ip = '192.168.1.23' port = 53484 cmd = string.char(0x01, 0x00, 0xA9, 0x17, 0x2F, 0x00, 0x00, 0x00, 0x3F, 0x9A) sock = socket.tcp() sock:settimeout(3) res, err = sock:connect(ip, port) if res then   res, err = sock:send(cmd)   if res then     alert('send OK')   else     alert('send failed: ' .. tostring(err))   end else   alert('connect failed: ' .. tostring(err)) end sock:close()
Reply
#3
Super

thanks for the Lightning fast reply !
Reply
#4
I am one step further, but not there yet

- communication works, but command is probably not correct because I get a weird response

my user script
Code:
-------------------------------------- -- Author:         Nicky Wessels -- Last Modified:     24/04/2016 -- -- Change Log: -- 24/04/2016        Intial Version -------------------------------------- -- IP of the projector PROJECTOR_IP = '192.168.0.20' PROJECTOR_PORT = '53484' -- Power ON -- 'h01 h00 hA9 h17 h2F h00 h00 h00 h3F h9A' SONYPJ_CMD_ON = string.char(0x01, 0x00, 0xA9, 0x17, 0x2F, 0x00, 0x00, 0x00, 0x3F, 0x9A) -- Power Off -- 'h01 h00 hA9 h17 h2E h00 h00 h00 h3F h9A' SONYPJ_CMD_OFF = string.char(0x01, 0x00, 0xA9, 0x17, 0x2E, 0x00, 0x00, 0x00, 0x3F, 0x9A) -- change input s-video -- 'h01 h00 ha9 h00 h01 h00 h00 h01 h01 h9a' SONYPJ_SET_SVIDEO = string.char(0x01, 0x00, 0xA9, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x9A) -- funtion to send basic commands to the receiver function sonypj_send_cmd(cmd, ip, port)     require 'socket.http'  response_tbl = { }  -- fill up optional parameters  if (ip == nil) then    ip = PROJECTOR_IP  end  if (port == nil) then    port = PROJECTOR_PORT  end  response_tbl['ip']=ip  response_tbl['port']=port  response_tbl['cmd']=cmd  -- Send command to projector     sock = socket.tcp()     sock:settimeout(3)     result, err = sock:connect(ip, port)  response_tbl['result']=result     if result then      result, err = sock:send(cmd)       response_tbl['result']=result    response_tbl['error']=error    -- Check response from projector         if result then        alert('send OK')      else        alert('send failed: ' .. tostring(err), response_tbl)      end     else      alert('connect failed: ' .. tostring(err), response_tbl)     end     sock:close()    return response_tbl end
my trigger script
Code:
require 'user.sony_pjtalk' -- object mapped to this event must have its data type set bStatus = event.getvalue() -- get the status of the projector if (bStatus) then  status_tbl = sonypj_send_cmd(SONYPJ_CMD_ON) else     status_tbl = sonypj_send_cmd(SONYPJ_CMD_OFF) end   log('status',status_tbl)

the response that I get for all commands

Code:
* arg: 2  * table:   [error]    * function: builtin#19   [ip]    * string: 192.168.0.20   [result]    * number: 10   [cmd]    * string: 
Reply
#5
Hi,


Try this to see the HEX values from cmd after string.char(0x01, 0x00, 0xA9, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x9A):

Code:
response_tbl['cmd']=lmcore.strtohex(cmd)


Are your commands processed? Sometimes you need to end a command like this:

Code:
res, err = sock:send(cmd .. '\r')


If you expect an answer from the socket after sending a command you need to switch to receive mode like this:


Code:
s, status, partial = sock:receive(1024) -- 1024 is expected response length and be sure to set socket timeout like this sock:settimeout(2) before sending a command


Good luck!

BR,

Erwin
Reply
#6
Thanks Eric

Will try,

I have been searching on this topic and it seems nobody got this protocol working over ip...

Hmmm
Reply
#7
I got it working, but I am unable to convert a string into a hex array to compute the code

These codes work

Code:
-- Power ON -- HEX: 02 0A 53 4F 4E 59 00 01 30 02 00 01 SONYSDCP_CMD_ON = string.char(0x02, 0x0A, 0x53, 0x4F, 0x4E, 0x59, 0x00, 0x01, 0x30, 0x02, 0x00, 0x01) -- Power Off -- HEX: 02 0A 53 4F 4E 59 00 01 30 02 00 00 SONYSDCP_CMD_OFF =string.char(0x02, 0x0A, 0x53, 0x4F, 0x4E, 0x59, 0x00, 0x01, 0x30, 0x02, 0x00, 0x00)

I use the following strings after computation

Code:
-- Power ON -- HEX: 02 0A 53 4F 4E 59 00 01 30 02 00 01 SONYSDCP_CMD_ON = "020A534F4E59000130020001" -- Power Off -- HEX: 02 0A 53 4F 4E 59 00 01 30 02 00 00 SONYSDCP_CMD_OFF = "020A534F4E59000130020000"

The following helpers do not convert correctly, but I am unable to determine why 

Code:
-- convert hex char array to string function string.fromhex(str)    return (str:gsub('..', function (cc)        return string.char(tonumber(cc, 16))    end)) end -- convert string to hex char array function string.tohex(str)    return (str:gsub('.', function (c)        return string.format('%02X', string.byte(c))    end)) end
Reply
#8
You can convert hex to binary string like this (second argument is needed, otherwise NULL bytes will be removed). You can also use loghex function which logs binary strings in readable hex format.
Code:
SONYSDCP_CMD_ON = lmcore.hextostr('020A534F4E59000130020001', true) loghex(SONYSDCP_CMD_ON)
Reply
#9
Smile 
Thanks  Smile

I found an alternative in the mean time

Hereby the full script for anyone looking for a PJ Talk solution

Code:
-------------------------------------- -- Author:         Nicky Wessels -- Last Modified:     30/11/2017 -- -- Change Log: -- 24/04/2016        Intial Version -- 30/11/2017        Update Based on SDCP-Com - By Vokkim on JSDelivr -- 30/11/2017        Javascript code https://github.com/vokkim/sony-sdcp-com -- 30/11/2017        Protocol https://www.digis.ru/upload/iblock/f5a/VPL-VW320,%20VW520_ProtocolManual.pdf -------------------------------------- ------------------------- -- CONFIG ------------------------- -- IP of the projector BASEMENT_PROJECTOR_IP = '192.168.0.21' BASEMENT_PROJECTOR_PORT = '53484' ------------------------- -- CONSTANTS ------------------------- -- CONSTANTS VERSION = '02' CATEGORY = '0A' -- Default to 'SONY' COMMUNITY = '534F4E59'                              actions = {  GET= '01',  SET= '00' } commands = {  SET_POWER= '0130',  CALIBRATION_PRESET= '0002',  ASPECT_RATIO= '0020',  INPUT= '0001',  GET_STATUS_ERROR= '0101',  GET_STATUS_POWER= '0102',  GET_STATUS_LAMP_TIMER= '0113' } input = {  HDMI1 = '0002',  HDMI2 = '0003', } aspectRatio = {  NORMAL= '0001',  V_STRETCH= '000B',  ZOOM_1_85= '000C',  ZOOM_2_35= '000D',  STRETCH= '000E',  SQUEEZE= '000F' } powerStatus = {  STANDBY= '0000',  START_UP= '0001',  START_UP_LAMP= '0002',  POWER_ON= '0003',  COOLING= '0004',  COOLING2= '0005' } -- set projector input function setInput(input, ip, port, debug)  if (debug) then    log (string.format("setInput:%s projector:%s:%s", input, ip, port))  end  frame = createMessageAsHex(actions.SET, commands.INPUT, input, debug)  result = sony_sdcp_send_frame(frame, ip, port, debug)  return result end -- get projector input status function getInputStatus(ip, port, debug)  if (debug) then    log (string.format("getInputStatus projector:%s:%s", ip, port))  end  frame = createMessageAsHex(actions.GET, commands.INPUT, nil, debug)  result = sony_sdcp_send_frame(frame, ip, port, debug)  inputStatus = nil  if (result and result.reply and result.reply.data) then    inputStatus = result.reply.data  end  return inputStatus end -- power projector on function setPower(powerOn, ip, port, debug)  if (debug) then    log (string.format("powerOn:%s projector:%s:%s", tostring(powerOn), ip, port))  end  if (powerOn) then    frame = createMessageAsHex(actions.SET, commands.SET_POWER, powerStatus.START_UP, debug)  else      frame = createMessageAsHex(actions.SET, commands.SET_POWER, powerStatus.STANDBY, debug)  end  result = sony_sdcp_send_frame(frame, ip, port, debug)  return result end -- get projector power status function getPowerStatus(ip, port, debug)  if (debug) then    log (string.format("getPowerStatus projector:%s:%s", ip, port))  end  frame = createMessageAsHex(actions.GET, commands.GET_STATUS_POWER, nil, debug)  result = sony_sdcp_send_frame(frame, ip, port, debug)  powerstatus = false  if (result and result.reply and result.reply.data) then    powerstatus = result.reply.data  end  return powerstatus end -- get projector power status as a boolean function getPowerStatusAsBool(ip, port, debug)  if (debug) then    log (string.format("getPowerStatusAsBool projector:%s:%s", ip, port))  end  result = false  powerstatus = getPowerStatus(ip, port, debug)  if (powerstatus) then    result = powerstatus == powerStatus.POWER_ON or powerstatus == powerStatus.START_UP or powerstatus == powerStatus.START_UP_LAMP  end  return result end -- convert hex char array to string function string.fromhex(str)  result =''     for c in str:gmatch"." do    result = result .. string.format("%02x", string.byte(c))  end  return string.upper(result) end -- convert string to hex char array function string.tohex(str)  result =''     for cc in str:gmatch".." do    result = result .. string.char(tonumber(cc, 16))  end  return string.upper(result) end -- create a sdcp message function createMessageAsHex(action, command, data, debug)  if (command and type(command) ~= "string") then    alert(string.format("Accepts command only as String (HEX) for now, was %s", type(command)))     end      if (string.len(command) ~= 4) then         alert(string.format("Command must be 4 bytes long"))  end  if (data and type(data) ~= "string") then      alert(string.format("Accepts data only as String (HEX) for now, was %s", type(data)))  end  if (not data) then    data = ""  end      dataLength = string.format('%02x', string.len(data)/2)  if (debug) then --    log ("dataLength:" .. dataLength)  end  frame = VERSION .. CATEGORY.. COMMUNITY.. action.. command.. dataLength.. data  if (debug) then --    log ("frame:" .. frame)  end     return string.tohex(frame) end -- parse a sdcp message function parseResponse(value, debug)  if (not value) then    alert(string.format("Empty value passed"))    assert(not value, string.format("Empty value passed"))  end  frame = string.fromhex(value)  if (string.len(frame) < 20) then    alert(string.format("Unknown response %s, length %d",frame,string.len(frame)))    assert(string.len(frame) < 20, string.format("Unknown response %s",frame))  end     version = string.sub(frame, 1, 2)     category = string.sub(frame, 3, 4)     community = string.sub(frame, 5, 12)     success = string.sub(frame, 13, 14)     command = string.sub(frame, 15, 18)     dataLength = string.sub(frame, 19, 20)  if (tonumber(dataLength, 16) > 0) then         data = string.sub(frame,21, 21 + tonumber(dataLength, 16) * 2)  end     result = {    version=version,         category=category,         community=community,         command=command,         dataLength=dataLength,    data=data,         success=success ~= '00',    raw = frame  }  return result end -- funtion to send basic commands to the projector function sony_sdcp_send_frame(frame, ip, port, debug)     require 'socket.http'  response_tbl = { }  -- fill up optional parameters  if (ip == nil) then    ip = BASEMENT_PROJECTOR_IP  end  if (port == nil) then    port = BASEMENT_PROJECTOR_PORT  end  response_tbl['ip']=ip  response_tbl['port']=port  response_tbl['frame']=frame  if (debug) then    log("ip:" .. ip)    log("port:" .. port)    log("transmit frame char:" .. string.fromhex(frame))    log("transmit frame hex:" .. frame)    log("transmit frame length:" .. string.len(frame))  end    -- Send command to projector     sock = socket.tcp()     sock:settimeout(3)     result, err = sock:connect(ip, port)  response_tbl['result']=result  response_tbl['error']=err     if result then      result, err = sock:send(frame .. "\r")           response_tbl['result']=result    response_tbl['error']=error    -- Check response from projector         if result then           if (debug) then        log ('transmit succesfully send')      end      -- read the response      resframe = ''      while true do          resp, err, part = sock:receive(1)        if resp ~= nil then            resframe = resframe .. resp        else          break        end      end      resstring = string.fromhex(resframe)      resdecoded = parseResponse(resframe)      response_tbl['reply']=resdecoded      if (debug and resframe) then        log("response frame char:" .. resstring)        log("response frame hex:" .. resframe)        log("response frame length:" .. string.len(resframe))        log("response frame decoded", resdecoded)              end            else        alert('send failed: ' .. tostring(err), response_tbl)      end     else      alert('connect failed: ' .. tostring(err), response_tbl)     end     sock:close()    return response_tbl end


add trigger scripts to call the functions in the user lib

Code:
-- activate projector setPower(bStatus, BASEMENT_PROJECTOR_IP, BASEMENT_PROJECTOR_PORT) -- check if it is active or starting up -- warning takes a few seconds before projector boots up bPowerStatus = getPowerStatusAsBool(BASEMENT_PROJECTOR_IP, BASEMENT_PROJECTOR_PORT) -- set the input setInput(input.HDMI1, BASEMENT_PROJECTOR_IP, BASEMENT_PROJECTOR_PORT, true) -- check the input state sInputStatus = getInputStatus(BASEMENT_PROJECTOR_IP, BASEMENT_PROJECTOR_PORT)
Reply


Forum Jump: