//implementation following this protocol : https://www.epiphan.com/userguides/LUMiO12x/Content/UserGuides/PTZ/3-operation/VISCAcommands.htm#InquiryCommands // var parameterPath = local.parameters; // var valuesPath = local.values; var ZoomPos = script.addFloatParameter("Zoom Position", "", 0., 0., 1.); var ZoomPosLastUpdate = script.addFloatParameter("Zoom update", "", 0.); // var state = var inquiry = ['CAM_ZoomPosInq', 'CAM_FocusModeInq', 'CAM_FocusPosInq', 'CAM_ReplyIntervalTimeInq']; var camID = 1; var waitTaskComplete = 0 ; var currentInquiry = ''; var ZoomAuto = false ; var ZoomPos_target ; var ZoomTime_target ; //////////////////////// HELPERS FUNCTIONS //////////////////////////// function printArray(name, array){ var printHeader = ' '+name+' : '; if (array.length){for(var i=0; i<array.length; i++){printHeader+=array[i] + ' ';}} script.log(printHeader); } //////////////////////// VISCA FUNCTIONS //////////////////////////////// function setZoomPos(ID, position){ var header = [1, 4, 71]; var posCmd = []; var pos = Math.round(Math.floor(16384 * position)); // script.log(pos); posCmd[3]=pos%16; pos = Math.round(Math.floor(pos/16)); posCmd[2]=pos%16; pos=Math.round(Math.floor(pos/16)); posCmd[1]=pos%16; posCmd[0]=Math.round(Math.floor(pos/16)); // local.sendBytes(idHex, 1, 4, 71, posCommand, 255); sendHeaderCommand(camID, header, posCmd); } function setZoomSpeed(ID, speed){ var header = [1, 4, 7]; var speedCmd = speed < 0 ? 48 : 32; speedCmd += Math.abs(speed)-1; speedCmd = speed == 0 ? 0 : speedCmd ; sendHeaderCommand(camID, header, speedCmd); } function sendInquiry(id, inquiryName){ var command ; if (currentInquiry == ''){ //no inquiry running; currentInquiry = inquiryName ; if(inquiryName == 'CAM_ZoomPosInq'){ command = [9, 4, 71];} if(inquiryName == 'CAM_ReplyIntervalTimeInq'){ command = [9, 4, 106];} sendCommand(camID, command); } else{script.log("inquiry running");} } function sendCommand(id, command){ var idHex = (parseInt("0x80") + id); // printArray('command', command); local.sendBytes(idHex, command, 255); } function sendHeaderCommand(id, header, command){ if (!waitTaskComplete){ var idHex = (parseInt("0x80") + id); // printArray('header', header); // printArray('command', command); local.sendBytes(idHex, header, command, 255); waitTaskComplete = 1; } else { script.log('task not complete');} } //////////////////////// ZOOM AUTOMATION //////////////////////////////// function setZoomPositionInTime(ID, position, time){ //update zoom position and time targets ZoomPos_target = position ; ZoomTime_target = util.getTime()+time; //activate callback ZoomAuto = true ; //deduce appropriate speed // var speedCmd = speed < 0 ? 48 : 32; // speedCmd = speed == 0 ? 0 : speedCmd ; // speedCmd += Math.abs(speed); // sendHeaderCommand(camID, header, speedCmd); } function setZoomPositionInTime_TL(ID, position, time){ var tl_time = root.sequences.keys.currentTime.get(); //update zoom position and time targets ZoomPos_target = root.sequences.keys.zoom.automation.getValueAtPosition(tl_time+time) ; ZoomTime_target = util.getTime()+time; //activate callback ZoomAuto = true ; //deduce appropriate speed // var speedCmd = speed < 0 ? 48 : 32; // speedCmd = speed == 0 ? 0 : speedCmd ; // speedCmd += Math.abs(speed); // sendHeaderCommand(camID, header, speedCmd); } function updateZoomPosition() { if (ZoomAuto){ //update position sendInquiry(1, 'CAM_ZoomPosInq'); //update speed if needed var lastUpdated = util.getTime()-ZoomPosLastUpdate.get(); // script.log(lastUpdated); if(lastUpdated<0.5){ //compute remaining time var remainTime = ZoomTime_target - util.getTime(); if(remainTime > 0){ var remainLength = (ZoomPos_target - ZoomPos.get()) * 100; var rawSpeed = remainLength / remainTime ; var absSpeed = Math.abs(rawSpeed); var realSpeed = -0.00221 * Math.pow(absSpeed,2) + 0.30898 * absSpeed ; var direction = rawSpeed > 0 ? 1 : -1; realSpeed *= direction ; realSpeed = Math.floor(realSpeed); script.log(remainLength + '% in ' + remainTime + ' s : ' + realSpeed + ' / ' +rawSpeed ); setZoomSpeed(1, realSpeed); } else { ZoomAuto = false; script.log('automation timeout'); //go to position setZoomPos(1, ZoomPos_target); sendInquiry(1, 'CAM_ZoomPosInq'); } } } } function computeSpeed(){ // 0,151*PUISSANCE((A18+1);2) +3,0001717*(A18+1)+0,007557 } /////////////////////// SCRIPT FUNCTIONS /////////////////////////////// function init() { //loadFixtures(); script.log("VISCA module loaded"); script.setUpdateRate(2); } function update(deltaTime){ updateZoomPosition(); computeSpeed(); // script.log('update'); } var buffer=[]; var bufferIndex = 0 ; function dataReceived(data) { //If mode is "Lines", you can expect data to be a single line String // script.log("Data received : " +data); //If mode is anything else, you can expect data to be an array of bytes // script.log(" Bytes received : "+data.length); // for(var i=0; i < data.length; i++) // { // script.log(" > " + parseInt((""+data[i]),16)); // } //fill buffer with bytes until you find a 255 for (var i = 0 ; i<data.length ; i++){ if (data[i]!=255){ buffer[bufferIndex]=data[i]; bufferIndex += 1; } else{ if(buffer[0]==144){ //0x90, you've got a message if (buffer[1]==65){script.log("received command");} //0x41 else if (buffer[1]==81){script.log("complete command");waitTaskComplete=0;} //0x51 else if (buffer[1]==96){script.log("syntax error");} //0x60 else if (buffer[1]==97){//0x61 var msg = "error :"; if(buffer[2]==1){msg=msg+"message length";} else if(buffer[2]==2){msg=msg+"syntax";} else if(buffer[2]==3){msg=msg+"command buffer full";} else if(buffer[2]==4){msg=msg+"command cancelled";} else if(buffer[2]==5){msg=msg+"no socket";} else if(buffer[2]==65){msg=msg+"command not executable";} else{ msg=msg+"unknow error"; for(var j=2; j < buffer.length; j++) { script.log(" > " +data[i]); } } script.log(msg); } //inquiry answers else if (buffer[1]==80){//0x50 if(currentInquiry == 'CAM_ZoomPosInq'){ var position = buffer[2]*4096 + buffer[3]*256 + buffer[4]*16 + buffer[5]; // printArray("zoom position :", buffer); // script.log(position); ZoomPos.set(position/16384.); ZoomPosLastUpdate.set(util.getTime()); } if(currentInquiry == 'CAM_ReplyIntervalTimeInq'){ var position = buffer[4]*16 + buffer[5]; // printArray("zoom position :", buffer); // script.log(position); ZoomPos.set(position/16384.); ZoomPosLastUpdate.set(util.getTime()); } //free inquiry slot currentInquiry = ''; } else if(buffer[1] == 7 && buffer[2] == 4 && buffer[3]==105){ var position = buffer[6]*4096 + buffer[7]*256 + buffer[8]*16 + buffer[9]; // printArray("zoom position :", buffer); // script.log(position); ZoomPos.set(position/16384.); ZoomPosLastUpdate.set(util.getTime()); } else{printArray("unknown answer :", buffer);} } bufferIndex = 0; buffer=[]; } } //then process buffer }