![]() |
|
pj talk - Printable Version +- LogicMachine Forum (https://forum.logicmachine.net) +-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1) +--- Forum: Gateway (https://forum.logicmachine.net/forumdisplay.php?fid=10) +--- Thread: pj talk (/showthread.php?tid=286) |
pj talk - npinguin - 24.04.2016 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/01/A/man-migrate/MANUAL000015642.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 RE: pj talk - admin - 24.04.2016 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()RE: pj talk - npinguin - 24.04.2016 Super thanks for the Lightning fast reply ! RE: pj talk - npinguin - 24.04.2016 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
endCode: 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: RE: pj talk - Erwin van der Zwart - 24.04.2016 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 commandGood luck! BR, Erwin RE: pj talk - npinguin - 25.04.2016 Thanks Eric Will try, I have been searching on this topic and it seems nobody got this protocol working over ip... Hmmm RE: pj talk - npinguin - 30.11.2017 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))
endRE: pj talk - admin - 30.11.2017 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)RE: pj talk - npinguin - 30.11.2017 Thanks ![]() 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
endadd 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) |