Visca.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. //implementation following this protocol : https://www.epiphan.com/userguides/LUMiO12x/Content/UserGuides/PTZ/3-operation/VISCAcommands.htm#InquiryCommands
  2. // var parameterPath = local.parameters;
  3. // var valuesPath = local.values;
  4. var ZoomPos = script.addFloatParameter("Zoom Position", "", 0., 0., 1.);
  5. var ZoomPosLastUpdate = script.addFloatParameter("Zoom update", "", 0.);
  6. // var state =
  7. var inquiry = ['CAM_ZoomPosInq', 'CAM_FocusModeInq', 'CAM_FocusPosInq', 'CAM_ReplyIntervalTimeInq'];
  8. var camID = 1;
  9. var waitTaskComplete = 0 ;
  10. var currentInquiry = '';
  11. var ZoomAuto = false ;
  12. var ZoomPos_target ;
  13. var ZoomTime_target ;
  14. var ZoomCurrentSpeed;
  15. var ZoomAuto_Remain = script.addFloatParameter("Zoom remain", "", 0.);
  16. var ZoomAuto_Speed = script.addFloatParameter("Zoom speed", "", 0., -7, 7);
  17. var autoZoomPos = false;
  18. //////////////////////// HELPERS FUNCTIONS ////////////////////////////
  19. function printArray(name, array){
  20. var printHeader = ' '+name+' : ';
  21. if (array.length){for(var i=0; i<array.length; i++){printHeader+=array[i] + ' ';}}
  22. script.log(printHeader);
  23. }
  24. //////////////////////// VISCA FUNCTIONS ////////////////////////////////
  25. function setZoomPos(ID, position){
  26. ZoomAuto = false ;
  27. var header = [1, 4, 71];
  28. var posCmd = [];
  29. var pos = Math.round(Math.floor(16384 * position));
  30. // script.log(pos);
  31. posCmd[3]=pos%16;
  32. pos = Math.round(Math.floor(pos/16));
  33. posCmd[2]=pos%16;
  34. pos=Math.round(Math.floor(pos/16));
  35. posCmd[1]=pos%16;
  36. posCmd[0]=Math.round(Math.floor(pos/16));
  37. // local.sendBytes(idHex, 1, 4, 71, posCommand, 255);
  38. sendHeaderCommand(camID, header, posCmd);
  39. }
  40. function setZoomSpeed(ID, speed){
  41. ZoomAuto = false ;
  42. var header = [1, 4, 7];
  43. var speedCmd = speed < 0 ? 48 : 32;
  44. speedCmd += Math.abs(speed)-1;
  45. speedCmd = speed == 0 ? 0 : speedCmd ;
  46. sendHeaderCommand(camID, header, speedCmd);
  47. }
  48. function sendInquiry(id, inquiryName){
  49. var command ;
  50. if (currentInquiry == ''){ //no inquiry running;
  51. currentInquiry = inquiryName ;
  52. if(inquiryName == 'CAM_ZoomPosInq'){ command = [9, 4, 71];}
  53. if(inquiryName == 'CAM_ReplyIntervalTimeInq'){ command = [9, 4, 106];}
  54. sendCommand(camID, command);
  55. }
  56. else{script.log("inquiry running");}
  57. }
  58. function sendCommand(id, command){
  59. var idHex = (parseInt("0x80") + id);
  60. // printArray('command', command);
  61. local.sendBytes(idHex, command, 255);
  62. }
  63. function sendHeaderCommand(id, header, command){
  64. if (!waitTaskComplete){
  65. var idHex = (parseInt("0x80") + id);
  66. // printArray('header', header);
  67. // printArray('command', command);
  68. local.sendBytes(idHex, header, command, 255);
  69. waitTaskComplete = 0;
  70. }
  71. else { script.log('task not complete');}
  72. }
  73. function continuousZoomPos(state){
  74. if (autoZoomPos != state ){
  75. autoZoomPos = state;
  76. var header = [1, 4, 105];
  77. var stateCmd = state ? 2 : 3;
  78. // stateCmd = speed == 0 ? 0 : speedCmd ;
  79. sendHeaderCommand(camID, header, stateCmd);
  80. }
  81. }
  82. //////////////////////// ZOOM AUTOMATION ////////////////////////////////
  83. function setZoomPositionInTime(ID, position, time){
  84. //update zoom position and time targets
  85. ZoomPos_target = position ;
  86. ZoomTime_target = util.getTime()+time;
  87. //activate callback
  88. ZoomAuto = true ;
  89. continuousZoomPos(true);
  90. //deduce appropriate speed
  91. // var speedCmd = speed < 0 ? 48 : 32;
  92. // speedCmd = speed == 0 ? 0 : speedCmd ;
  93. // speedCmd += Math.abs(speed);
  94. // sendHeaderCommand(camID, header, speedCmd);
  95. }
  96. function setZoomPositionInTime_TL(ID, position, time){
  97. var tl_time = root.sequences.keys.currentTime.get();
  98. //update zoom position and time targets
  99. ZoomPos_target = root.sequences.keys.zoom.automation.getValueAtPosition(tl_time+time) ;
  100. ZoomTime_target = util.getTime()+time;
  101. //activate callback
  102. ZoomAuto = true ;
  103. //deduce appropriate speed
  104. // var speedCmd = speed < 0 ? 48 : 32;
  105. // speedCmd = speed == 0 ? 0 : speedCmd ;
  106. // speedCmd += Math.abs(speed);
  107. // sendHeaderCommand(camID, header, speedCmd);
  108. }
  109. function updateZoomPosition() {
  110. if (ZoomAuto){
  111. var lastUpdated = util.getTime()-ZoomPosLastUpdate.get();
  112. //update position if was updated long ago
  113. // sendInquiry(1, 'CAM_ZoomPosInq');
  114. if (lastUpdated>0.5){
  115. // sendInquiry(1, 'CAM_ZoomPosInq');
  116. continuousZoomPos(true);
  117. }
  118. //update speed if needed
  119. var lastUpdated = util.getTime()-ZoomPosLastUpdate.get();
  120. // script.log(lastUpdated);
  121. if(lastUpdated<0.5){
  122. //compute remaining time
  123. var remainTime = ZoomTime_target - util.getTime();
  124. if(remainTime > 0.5){
  125. var remainLength = (ZoomPos_target - ZoomPos.get()) * 100;
  126. var rawSpeed = remainLength / remainTime ;
  127. var absSpeed = Math.abs(rawSpeed);
  128. var realSpeed = -0.00221 * Math.pow(absSpeed,2) + 0.30898 * absSpeed ;
  129. var direction = rawSpeed > 0 ? 1 : -1;
  130. realSpeed *= direction ;
  131. realSpeed = Math.floor(realSpeed);
  132. ZoomAuto_Remain.set(remainTime);
  133. ZoomAuto_Speed.set(realSpeed);
  134. // script.log(remainLength + '% in ' + remainTime + ' s : ' + realSpeed + ' / ' +rawSpeed );
  135. if (realSpeed != ZoomCurrentSpeed){
  136. script.log("change speed");
  137. ZoomCurrentSpeed = realSpeed ;
  138. setZoomSpeed(1, ZoomCurrentSpeed);
  139. }
  140. ZoomAuto=true;
  141. break;
  142. }
  143. else {
  144. ZoomAuto = false;
  145. script.log('automation timeout');
  146. //go to position
  147. setZoomPos(1, ZoomPos_target);
  148. continuousZoomPos(false);
  149. // sendInquiry(1, 'CAM_ZoomPosInq');
  150. }
  151. }
  152. }
  153. }
  154. function computeSpeed(){
  155. // 0,151*PUISSANCE((A18+1);2) +3,0001717*(A18+1)+0,007557
  156. }
  157. /////////////////////// SCRIPT FUNCTIONS ///////////////////////////////
  158. function init() {
  159. //loadFixtures();
  160. script.log("VISCA module loaded");
  161. script.setUpdateRate(10);
  162. continuousZoomPos(false);
  163. }
  164. function update(deltaTime){
  165. updateZoomPosition();
  166. // script.log('update');
  167. }
  168. var buffer=[];
  169. var bufferIndex = 0 ;
  170. function dataReceived(data)
  171. {
  172. //If mode is "Lines", you can expect data to be a single line String
  173. // script.log("Data received : " +data);
  174. //If mode is anything else, you can expect data to be an array of bytes
  175. // script.log(" Bytes received : "+data.length);
  176. // for(var i=0; i < data.length; i++)
  177. // {
  178. // script.log(" > " + parseInt((""+data[i]),16));
  179. // }
  180. //fill buffer with bytes until you find a 255
  181. for (var i = 0 ; i<data.length ; i++){
  182. if (data[i]!=255){
  183. buffer[bufferIndex]=data[i];
  184. bufferIndex += 1;
  185. }
  186. else{
  187. if(buffer[0]==144){ //0x90, you've got a message
  188. if (buffer[1]==65){script.log("received command");} //0x41
  189. else if (buffer[1]==81){script.log("complete command");waitTaskComplete=0;} //0x51
  190. else if (buffer[1]==96){script.log("syntax error");} //0x60
  191. else if (buffer[1]==97){//0x61
  192. var msg = "error :";
  193. if(buffer[2]==1){msg=msg+"message length";}
  194. else if(buffer[2]==2){msg=msg+"syntax";}
  195. else if(buffer[2]==3){msg=msg+"command buffer full";}
  196. else if(buffer[2]==4){msg=msg+"command cancelled";}
  197. else if(buffer[2]==5){msg=msg+"no socket";}
  198. else if(buffer[2]==65){msg=msg+"command not executable";}
  199. else{
  200. msg=msg+"unknow error";
  201. for(var j=2; j < buffer.length; j++)
  202. {
  203. script.log(" > " +data[i]);
  204. }
  205. }
  206. script.log(msg);
  207. }
  208. //inquiry answers
  209. else if (buffer[1]==80){//0x50
  210. if(currentInquiry == 'CAM_ZoomPosInq'){
  211. var position = buffer[2]*4096 + buffer[3]*256 + buffer[4]*16 + buffer[5];
  212. // printArray("zoom position :", buffer);
  213. // script.log(position);
  214. ZoomPos.set(position/16384.);
  215. ZoomPosLastUpdate.set(util.getTime());
  216. }
  217. if(currentInquiry == 'CAM_ReplyIntervalTimeInq'){
  218. var position = buffer[4]*16 + buffer[5];
  219. // printArray("zoom position :", buffer);
  220. // script.log(position);
  221. ZoomPos.set(position/16384.);
  222. ZoomPosLastUpdate.set(util.getTime());
  223. }
  224. //free inquiry slot
  225. currentInquiry = '';
  226. }
  227. else if(buffer[1] == 7 && buffer[2] == 4 && buffer[3]==105){
  228. var position = buffer[6]*4096 + buffer[7]*256 + buffer[8]*16 + buffer[9];
  229. // printArray("zoom position :", buffer);
  230. // script.log(position);
  231. ZoomPos.set(position/16384.);
  232. ZoomPosLastUpdate.set(util.getTime());
  233. }
  234. else{printArray("unknown answer :", buffer);}
  235. }
  236. bufferIndex = 0;
  237. buffer=[];
  238. }
  239. }
  240. //then process buffer
  241. }