From e191537bc9b29b2a9e08aab41688326f744c98f4 Mon Sep 17 00:00:00 2001 From: Jason Watkins Date: Fri, 17 Apr 2015 14:59:09 -0700 Subject: [PATCH] Refactored MATLAB client to use the Java client internally. - Still need to implement selectDATA for all languages. --- MATLAB/+XPlaneConnect/XPlaneConnect.jar | Bin 0 -> 6480 bytes MATLAB/+XPlaneConnect/clearUDPBuffer.m | 33 ------- MATLAB/+XPlaneConnect/closeUDP.m | 27 +++--- MATLAB/+XPlaneConnect/getDREFs.m | 37 ++++++++ MATLAB/+XPlaneConnect/openUDP.m | 49 +++++------ MATLAB/+XPlaneConnect/pauseSim.m | 46 ++++------ MATLAB/+XPlaneConnect/readDATA.m | 71 +++------------ MATLAB/+XPlaneConnect/readUDP.m | 83 ------------------ MATLAB/+XPlaneConnect/requestDREF.m | 69 --------------- MATLAB/+XPlaneConnect/sendCTRL.m | 68 ++++++-------- MATLAB/+XPlaneConnect/sendDATA.m | 47 ++++------ MATLAB/+XPlaneConnect/sendDREF.m | 58 ------------ MATLAB/+XPlaneConnect/sendPOSI.m | 66 ++++++-------- MATLAB/+XPlaneConnect/sendSTRU.m | 57 ------------ MATLAB/+XPlaneConnect/sendTEXT.m | 49 +++++------ MATLAB/+XPlaneConnect/sendUDP.m | 49 ----------- MATLAB/+XPlaneConnect/sendWYPT.m | 52 +++++------ MATLAB/+XPlaneConnect/setConn.m | 56 +++++------- MATLAB/+XPlaneConnect/setDREF.m | 37 ++++++++ TestScripts/Java Tests/XPlaneConnectTest.java | 48 +++++----- 20 files changed, 307 insertions(+), 695 deletions(-) create mode 100644 MATLAB/+XPlaneConnect/XPlaneConnect.jar delete mode 100644 MATLAB/+XPlaneConnect/clearUDPBuffer.m create mode 100644 MATLAB/+XPlaneConnect/getDREFs.m delete mode 100644 MATLAB/+XPlaneConnect/readUDP.m delete mode 100644 MATLAB/+XPlaneConnect/requestDREF.m delete mode 100644 MATLAB/+XPlaneConnect/sendDREF.m delete mode 100644 MATLAB/+XPlaneConnect/sendSTRU.m delete mode 100644 MATLAB/+XPlaneConnect/sendUDP.m create mode 100644 MATLAB/+XPlaneConnect/setDREF.m diff --git a/MATLAB/+XPlaneConnect/XPlaneConnect.jar b/MATLAB/+XPlaneConnect/XPlaneConnect.jar new file mode 100644 index 0000000000000000000000000000000000000000..47d7775b36b9662e8fe95448142cc0131ba1407d GIT binary patch literal 6480 zcmZ`;Wl&sOm&G*%4elhtJ-CGsAh6h6fMpL?nPN!2#>a&okBa8q&O0NRB3ic-!r8tAlq2NqLLFAjg0^L%u$(K3iu#pXi}*DRE0HJz)Jt z^u92LHw}jv^|&uv#M5$IjQ9H2-Qy8sppa;+)PM%kbdCG7-E=wHP+k6OK_08mjFRBI z94}-W7&;nH46eHqQ&=2*pN1-dSpB zveYaSUHVy;0iK7TDt`xY0hMK9GAXo_VTGG)_%mNLH#d> zue1vH#V>T+_Z^)w&S<9aI<&6|H^{Ui#B zGHTtQLvCx}v~p)MT3vF6&|zksP>$D~yvYi^SlMD@ow>>r(16qlD&%oXuj=Ykn%f|l z3im!^@OnwTOSWDmMCfeLN4tBFAn;%>Nq5keoN*lq?a?;kA$x zl=*~pM9MDSK7=hPNf~ z6J24PNxdwZs{~E)7JEuZ%W;z3OIA&l&@|^anWhRf@F#9bMTATXl~}YFep?__a>>rz zP|J>(0A$4^1^nIwbc}%&K1M$z1cWq{|7^y8=J=ocL;KG;)={-Hb+C|fba1c$y8UOA zV|9H@G^|pdazx^NtVm4=2uwa8^%Z_HKmUx_~gx4ETo2A;K_ z2F1~cZ0&*`q-j78bQGeMrJ66fSQTFdxvFieTF^YGI&q&fG(1v2yY{=bv?NH}r@1}$ zobc?r$hi=SKUo?Y3AlaW3Ph8;{~CI7&rSAJVJYE+NWzhRlOIZRyVe7Vx^eV>AeB(- zQ+f3D8;d9Pw_IPHshT6Ym1sFw!r8ytiCQB8{Zt_Qa$bn?MT_&x*+%n?3gMUfQ{$+c z)u#0M(T;>kNeT+CW*0N>P`N1Z5b_6&2g@0^Gkhe^ylnq$ErCZ6K&i8lVw9ta2! z`KmZovDrNA74HkF4>0W+L zuk;f`vLOch0CK{Cx{_sEs+S)c#K}fx9iuD@(Rn9x`8yl*en@00zfY>YGBhOXxfBKR zqD#kI{oHPCD&-*(*fU{kXPEWs_jlFQI%B(rX=p2QHNMJ?Q44ykRrGNS2u@y4)v$U~ z%bFPp@eJP`_kjDLZn2{SWcQOMSF9f=-K-vG7H7yP07K?bKskTL&i6O>MMIs1tIH{4 zn(a3q79sZY);nvJlMSvi{>}FKauzA}RC4GCi**^`^B*8tYebad6cX1xKpUV_*J50d z=OHWJ12#1eW|_CeTJ3a5w+D+z_kPpg|oamG!T0>hpQiDV^67Y5!x? z*^95fls93&IK}cc@zFx7P5Zk-&;(i#z6eWt)^*|0uE+gNcCP%;qaXV7e(T!&Ca>v9 zOrS-(kzOS|&KEPw^KUCUQ{pp#R;!RHxV-GWH_-l!x_FRJPfE%3rI8e+w>K`215Yi* zomuC+k_f*5_bd$A8<%A1SsQZjTSU+5Ub6}C11O}wl{s^WYsSzgnfv%X+YkxExa9MT zlTV5Aw$_ZuZJY@+*-N0qRh2Z6*KoiUMVtkY;tj|9!I^nku&6v03zvQNMTRR#^N2n? zVVw)U?P6XzVO{`ly0Vz|({+fH_R-1$fA43WWgyJsw!ldM=qNvvOM;z$cr#gAV@EC# z_|uw0O1Egh-fnfWz^`!cc--!_Fd`k7p~ky2p=rY9pE$} zuqN$WdF>^8=w$EP>Q+ z*xOs&cFHf!&rJ=wU2Y|WMtk54c*{R1BYmvh$L_X)@=Ay{%iQ&C zrX6e%xdrI!Ai_MvkcMs^{U*yr`fU|ao8S2Apr2%H&fOY*$WM6PW33KPhoXMH`F!1} z|JINbeTrzAT|y56r@EE2T zS2WrSDmXfFy{Q$hLVfNVdWrItouFDf)r1-yHrysthFz_GfVWk!PSEZSEfr!b+6m4N z<&Ly#o0Z*L4ZWSqcLnKd5TYd1UQ5Kd**T!lT}{&l5WXOCFk#WYR5_YI-*TaDRXyHDwjMG;_U_Z#`xM) zLuD=Gjp_3@qS}7GYU|A@H|Lipl|>C%fj#mzuENfeO%BSER!0Q_`uOC>+XCI>*t+-o ze1Xvf8#kP%s6PCgO@W#Vj(Ng}QUIf`Ykv z?MtBv6pDR%r+%GOF^||$G@)G#?zp&c^ZRw~JdqbLdCPFy34ZxyXsZe0pVCH*{UEen zOD%y`P52{p%V(l*BAana#^}U zbOC|a&icRTEhlOu1;|POLOMJwjCRZ~3UPdm`E$$WP!r)^B7i;M;&-xiy-d&^%Qrh; zs>67M8P}S#vHZn(sw4-rQ^`-)0Y;59PP;3d+FGo zqtYa1Y_{k>!f4PZak^D2OZ@8|rzfbD@}$L6U&h&Vv9Be)z}LFkp$*}pp34?+x&+-} znG2%XQD4$yYl`2y+#lpTQXhN9E_YO!)H62UV%+7789F88v7{{H8tc~H(D{V#PThhpk;Z`!hI@!wqcl zx&Xj8D?(MRjsuH>#XqZe069C5xa_beT^*Gjl$)zwBZo!p&*_|{>9~$?5vD`S%Jd&O z4?y%|3?o>n@Hgml4;<4eo!aoS)itDLMcKoM8bo&JDt@X)>P2gfH%8DtZ~D?2d2g~6 z-ApNWio7-ndSvA}c%C-u+-hu{`LpZtrP`+{OS};*dM`};(X0k8tEqP#`am(g=xaf} z!-9#FiHDhlb1VzZGaZNn15>l@&%!$dQ_J*|7`so`awuo#FI_6gc8PWwW_L*j z@S;Zf#AH5ryS%FzJ9CSi+EhpfF|IU#@=Jhyk4bKqrCg}-CgjxYP63gHBiv)0(@cr> zZ6ST7Et>X5I_7K885guyR0)Hpc=F8^g&;I;F#>K1Wgx6vYfkro2$h&_lz?YiXd!Ha zEG}aKOme@Fh%MCMGeTNqyV5A% z8C^sq?oO~J&iswo4pRW`08>7MzHe44orsL1H#9t_4o}^J&P*mOzF9=3oJ}j#3Zq^o zhIIsJO>zEW{hBBCp4@WdpoM6)TfU!EE}?MXe%!pN^=ipV&qsh6pBV)7?% z5i^-W$V$CdIP3S>m9^*m&7R<3{Y8`%*u1+L3wV+&@<$ZSs^G1UhKOfT6yB)6wtF@$5MYrB{@Knt3uN z4V;mZke{bT6G5fYLn1!vxpt8~UcI3Lj2LE2OcYoy6kD<$q{gQdxh>GbzTnPklcXa- z6XlDkWqwl_N3mlqKrGB}2grplRaP~=NLV8jR0ZId>zqH^#xe8PR~jI2$gS3yFp-4g zaWESRMo7O1DPyZzH^-Zi4>X&82j7X=6hb#}Iq#L7_#8&rSlKw>{!=ofthzW*lC3KC znJZLx>v?N9g;x0sER+M(*h{+ZNSzDg=$~ zIxr9G7q}aKhD~=;jwrx5m)DaSx85kFQ4INn_NY>ir`c0X#Yvkvw&1AgHQA8 z2{k%AD#3McEr;G^aHgoU&eUnp*Xe=G30Ipwyd9#8TgUxG$;J>*X4j0 zD;}q$2s5eFSkKkX3*}>jixr7vbbHAyqo1(1=Y1FZJ@J<>3F#L&OWfW;DuI#d% z#+rc~@3P&8`uef7b&f&7nTi_d?PI}rQVTyrQJn8R-jF-jy%8(U`6`{;BbN9qTMSiG ziNOU$<-#DOtVKswLZMQlfO_CfUiB_c`fG7U)(WF=*{#a*k@fnb3{nl&_xCC~PPtJz zvdp~AWj9EU3;}dmyTZce>kaGT@t->4y!3JrCzxcuhUcp7-BLQ&@&;r9K#bb5OIDp! zRjArH>vi1P4bafLMjqqX*E=o&bxHRi4>YSGvAgu0BjDynQMvGg+2)9HTlL)haHeV! z1e3xIwPw1ekzaPDY_Ku3*et0aov&}Xv{tvcG>NK8My0$otX3j~d7r!8R$eR`eX_x) zyYKB&Xwn`FVKnE&miHi#(Pt1KVkcn$aexGvqF2^ADg$oWxlC5*-p>)<^Un7CVxEuY*POJ-F^9KP}#<=)FI#Js2 zv$B_`$(KKb-KfaDqix>F zprml3u+UL>lsWZ8v;^|W8~GIr*l6d4?rwwYO)w$FLH76(G_D10Qk0)%rLVuG@rMkT zYemKl{fk6yGh-*SHJ_pk121+GZ0+yG61!B+rzugY<0nDqpB+EW7Fa_odiI77F4rUG zjz$W)dVTSxb#ayxq6R#vY5HfEE4uRs>Gs|_wY$$eS%y}0&wylW^*pv(LiQV58b95( zM`=`{#(n%Gu*trXic42b_|E7By$2KwhYiQtiPGZoXeo1PQOlHz1`C}t0k^nkzmQX}e2 zjxHzysO1hyPiiU?Wia5^_eIhNcu5{v1Nu#F(}zvrsy2g$rXKMq(JsHLS%bGRldanb ziK8B}dd;T9mARRp^c#UBB4#titvEC#q)DnEMHnTJr6QJ|jjsgQ$c>y8lVQzmxdsxi z78sti7?p{d5C>APIE=z`U`R{$2Eq3+p*Kaf81WP-iE|JGk!CmMw0=DfknT^Y+_J-vmo6hWAu6Wuf9uVai3KbLLA@mTx{U=|rKzc)pR2)b{HHZNcQByjsBO zTH^3ncR@2KywbNTUeuF9sb#f=k};MYJY^00?2H-~%i5^oQ3L#77I)0up%X0j@KTMe zDLdg*(;ME$Sw;RFo$dF(q%uQlA>O0iGoR?I2I*gU#Y1+-c9l5KD@h z!79z59#E)Ii0tuiaq^3G!=d3LK~)2wysFX#NVBp)Y-6r(4r z1cPC8A7fCqDVQzw$#GyfqfO8F$^Ax~7-!<72Tz-fxT(i(F@HneQs8rL()nd(J^p;{<)1xb@@R!Y9Dh# zVOQ?x1EOnus5`p?N{lDLl)kF@lKcn9K7$PpD9>@fw>YPOc;FGtuw`5@F8xgMWo-MT zqc4U41r6*7CPqGPi`m2S?hZ>tHpx^hPf}cwvI4BTQ0a}MPqSRXO5{?r8sxaHPySQn z)PDKyV_8!0_t2x{GFlJY2&+C#w;-IjWs`vL`JVS{)&k!PDe?lwAKiYU@4%D3fhFXG zX&ow=SMow?U@|o&hb`10v#}s`Ltu#IQ_FO#$EGax6+|QB0zxDgb4`C0+aiK{%%Vuw zg4^qOdd@9Az;cPf5}Q;eKs~^-F|A`O8uog_xq)28r1b3N#uamaECA(pFW7iWU8q}q z{3L(t@YxGNG(9r6)fwl^r`QI(n3KKCQ_cX?KgMMSF9gq)2m!%~@sDwdh=hgk@7Dis z_wsM}D+u^^)t@NfFTDO;{w)~zciEq4;4disF8^2dpP&E{i3s7ZsNnDB>z}CLFMxlS z|3~`I;NZ_M|4*wwZtdTngZ8gJzpJ;%|7i99c( +% Jason Watkins - import XPlaneConnect.* +import XPlaneConnect.* - %% Read UDP Socket - [ sensor.raw] = readUDP(socket); - - %% Interpret Input - bits = size(sensor.raw); - if sensor.raw ~= -998 %If the signal exists - header = char(sensor.raw(1:4)'); - if strcmp(header,'DATA') %DATA signal type - Values = floor((bits-5)/36); - sensor.d = []; - sensor.h = zeros(Values(1),1); - for i=1:Values(1) - sensor.h(i) = sensor.raw(6+(i-1)*36); - sensor.d = [sensor.d; typecast(uint8(sensor.raw(10+(i-1)*36:5+i*36))','single')]; - end - elseif strcmp(header,'STRU') %STRU signal type - a = 6; - while a % no data - -%% Handle Input -p = inputParser; -addRequired(p,'DREFArray'); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,DREFArray,varargin{:}); - -%% BODY - % Header - message(1:4) = 'GETD'-0; - message(6) = length(p.Results.DREFArray); - - % DREFS - for i=1:length(p.Results.DREFArray) - message(len) = length(p.Results.DREFArray{i}); - message(len+1:len+message(len)) = p.Results.DREFArray{i}; - len = len+1+message(len); - end - - % Send UDP - status = sendUDP(message, p.Results.IP, p.Results.port); - - % Look for response - for i=1:40 - data = readUDP(); - if length(data) > 1 % Received Data - status = 0; - counter = 7; - nArrays = data(6); - result = cell(nArrays,1); - for j=1:nArrays - sizeArray = data(counter); - result{j} = typecast(uint8(data(counter+1:counter+sizeArray*4))','single'); - counter = counter + 1 + sizeArray * 4; - end - break; - else - result = cell(0,1); - end - end -end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/sendCTRL.m b/MATLAB/+XPlaneConnect/sendCTRL.m index 821efd0..85a7b4d 100644 --- a/MATLAB/+XPlaneConnect/sendCTRL.m +++ b/MATLAB/+XPlaneConnect/sendCTRL.m @@ -1,5 +1,5 @@ -function [ status ] = sendCTRL( ctrl, acft, IP, port ) -% sendCTRL Send X-Plane Aircraft Control Commands over UDP +function sendCTRL( ctrl, ac, socket ) +% sendCTRL Sends command to X-Plane setting control surfaces on the specified aircraft. % % Inputs % ctrl: control array where the elements are as follows: @@ -9,56 +9,44 @@ function [ status ] = sendCTRL( ctrl, acft, IP, port ) % 4. Throttle [-1, 1] % 5. Gear (0=up, 1=down) % 6. Flaps [0, 1] -% acft (optional): Aircraft # (default is 0; 0 = own aircraft) -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp +% ac (optional): The aircraft to set. 0 for the player aircraft. +% socket (optional): The client to use when sending the command. % % Outputs % status: If there was an error. Status<0 means there was an error. % % Use % 1. import XPlaneConnect.*; -% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54. -% 3. status = sendCTRL([0, 0, 0, 0.8, 0, 1], 1, '172.0.100.54',49009); +% 2. socket = openUDP(); +% 3. status = sendCTRL([0, 0, 0, 0.8, 0, 1], 0, socket); % Set throttle and flaps on the player aircraft. % -% Note: send the value -998 to not overwrite that parameter. That is, if -998 is sent, the parameter will stay at the current X-Plane value +% Note: send the value -998 to not overwrite that parameter. That is, if +% -998 is sent, the parameter will stay at the current X-Plane value. % % Contributors -% [CT] Christopher Teubert (SGT, Inc.) -% christopher.a.teubert@nasa.gov -% -% To Do -% 1. Verify Input -% -% BEGIN CODE +% Christopher Teubert (SGT, Inc.) +% Jason Watkins import XPlaneConnect.* -%% Handle Input - % Optional parameters - if ~exist('IP','var'), IP = '127.0.0.1'; end - if ~exist('port','var'), port = 49009; end - if ~exist('acft','var'), acft = 0; end - - % Check format of input-TODO - -%%BODY - header = ['CTRL'-0,0]; - dataStream = header; %TODO-ADD ACFT - - % Deal with position update - control = [-998.5, -998.5, -998.5, -998.5, -998.5, -998.5]; - - for i=1:min(length(ctrl),length(control)) - control(i) = ctrl(i); +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); end - dataStream = [dataStream, typecast(single(control(1:4)),'uint8')]; - dataStream = [dataStream, uint8(control(5))]; - dataStream = [dataStream, typecast(single(control(6)),'uint8')]; - dataStream = [dataStream, uint8(acft)]; - - % Send DATA - status = sendUDP(dataStream, IP, port); - + socket = clients(1); end +%% Validate input +ctrl = single(ctrl); +if ~exist('ac', 'var') + ac = 0; +end +ac = logical(ac); + +%% Send command +socket.sendCTRL(ctrl, ac); + +end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/sendDATA.m b/MATLAB/+XPlaneConnect/sendDATA.m index f051fbe..6149205 100644 --- a/MATLAB/+XPlaneConnect/sendDATA.m +++ b/MATLAB/+XPlaneConnect/sendDATA.m @@ -1,15 +1,11 @@ -function [ status ] = sendDATA(data, varargin) +function sendDATA(data, socket) % sendDATA Send X-Plane formatted DATA over UDP % % Inputs % data: X-Plane formatted data. Is a matlab structure with the following fields: % .h: Header array containing header numbers corresponding to values in the X-Plane UDP Data screen. % .d: 2-D Data array. Each row contains eight values corresponding to the header value (.h(1) corresponds to .d(1,:)) -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent . Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp interface. -% -% Outputs -% status: 0: no error, <0: error +% socket (optional): The client to use when sending the command. % % Use % 1. import XPlaneConnect.*; @@ -29,29 +25,22 @@ function [ status ] = sendDATA(data, varargin) import XPlaneConnect.* -%% Handle Input -p = inputParser; -addRequired(p,'data'); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,data,varargin{:}); - -%% BODY - - header = ['DATA'-0,0]; - dataStream = header; - - for i=1:length(p.Results.data.h) - dataStream = [dataStream, p.Results.data.h(i), 0, 0, 0, typecast(single(p.Results.data.d(i,1:8)),'uint8')]; %#ok +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[sendDATA] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); end - - % Send DATA - if length(dataStream) > 5 - status = sendUDP(dataStream, p.Results.IP, p.Results.port); - else - disp('Warning in sendDATA: Sending empty dataStream') - status = -2; - end - + socket = clients(1); end +%% Validate input +javaData = []; +for i = 1:length(data.h); + javaData = [javaData; data.h(i) data.d(i, 1:8)]; +end + +%% Send command +socket.sendDATA(javaData); + diff --git a/MATLAB/+XPlaneConnect/sendDREF.m b/MATLAB/+XPlaneConnect/sendDREF.m deleted file mode 100644 index 4632d67..0000000 --- a/MATLAB/+XPlaneConnect/sendDREF.m +++ /dev/null @@ -1,58 +0,0 @@ -function status = sendDREF( dataRef, Value, varargin ) -% sendDREF Send a command to change any DataRef in X-Plane over UDP. This requires the X-Plane Connect Plugin to be running -% -% Inputs -% dataRef: The X-Plane Dataref that will be chaged -% Value: The value that the above dataref is set to -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp -% -% Outputs -% status: If there was an error. status<0 means there was an error. -% -% Use -% 1. import XPlaneConnect.* -% 2. dataRef = 'sim/aircraft/parts/acf_gear_deploy'; // Landing Gear -% 3. Value = 0; -% 4. status = sendDREF(dataRef, Value); -% -% Contributors -% [CT] Christopher Teubert (SGT, Inc.) -% christopher.a.teubert@nasa.gov -% -% To Do -% 1. Verify Input -% -% BEGIN CODE - -import XPlaneConnect.* - -status = 0; - -%% Handle Input -p = inputParser; -addRequired(p,'dataRef'); -addRequired(p,'Value'); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,dataRef, Value ,varargin{:}); - -%% BODY - dataStream = zeros(1,7+length(p.Results.dataRef)+length(p.Results.Value)*4); - % Build Header - dataStream(1:4) = 'DREF'-0; - - % Add DREF - dataStream(6) = uint8(length(p.Results.dataRef)); - len = 6+length(p.Results.dataRef); - dataStream(7:len)=p.Results.dataRef-0; - - % Add Value - dataStream(len+1) =uint8(length(p.Results.Value)); - dataStream(len+2:end)=typecast(single(p.Results.Value),'uint8'); - - % Send DREF - if length(dataStream) > 5 - status = sendUDP(dataStream, p.Results.IP, p.Results.port); - end -end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/sendPOSI.m b/MATLAB/+XPlaneConnect/sendPOSI.m index 4f85735..4953990 100644 --- a/MATLAB/+XPlaneConnect/sendPOSI.m +++ b/MATLAB/+XPlaneConnect/sendPOSI.m @@ -1,5 +1,5 @@ -function [ status ] = sendPOSI( posi, varargin ) -% sendPOSI Send X-Plane Aircraft Position over UDP +function sendPOSI( posi, ac, socket ) +% sendPOSI Sets the position of the specified aircraft. % % Inputs % posi: Position array where the elements are as follows: @@ -10,52 +10,42 @@ function [ status ] = sendPOSI( posi, varargin ) % 5. Pitch (deg) % 6. True Heading (deg) % 7. Gear (0=up, 1=down) -% acft (optional): Aircraft # (default is 0; 0 = own aircraft) -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp -% -% Outputs -% status: If there was an error. Status<0 means there was an error. +% acft (optional): The aircraft to set. 0 for the player aircraft. +% socket (optional): The client to use when sending the command. % % Use -% 1. import XPlaneConnect.*; -% 2. #Send the data array to port 49009 on the computer at IP address 172.0.100.54. -% 3. status = sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1, '172.0.100.54'); +% 1. import XPlaneConnect.*; +% 2. sendPOSI([37.5242422, -122.06899, 2500, 0, 0, 0, 1], 1); % -% Note: send the value -998 to not overwrite that parameter. That is, if -998 is sent, the parameter will stay at the current X-Plane value +% Note: send the value -998 to not overwrite that parameter. That is, if +% -998 is sent, the parameter will stay at the current X-Plane value. % % Contributors % [CT] Christopher Teubert (SGT, Inc.) % christopher.a.teubert@nasa.gov -% -% To Do -% -% BEGIN CODE +% [JW] Jason Watkins +% jason.w.watkins@nasa.gov import XPlaneConnect.* -%% Handle Input -p = inputParser; -addRequired(p,'posi'); -addOptional(p,'acft',0,@isnumeric); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,posi,varargin{:}); - -%% BODY - header = ['POSI'-0,0]; - dataStream = [header, p.Results.acft]; - - % Deal with position update - position = [37.4185718,-121.935565,500,0,0,0, 0]; - - for i=1:min(length(position),length(p.Results.posi)) - position(i) = p.Results.posi(i); +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[pauseSim] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); end - dataStream = [dataStream, typecast(single(position),'uint8')]; - - % Send POSI - status = sendUDP(dataStream, p.Results.IP, p.Results.port); - + socket = clients(1); end +%% Validate input +posi = single(posi); +if ~exist('ac', 'var') + ac = 0; +end +ac = logical(ac); + +%% Send command +socket.sendCTRL(ctrl, ac); + +end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/sendSTRU.m b/MATLAB/+XPlaneConnect/sendSTRU.m deleted file mode 100644 index e00898a..0000000 --- a/MATLAB/+XPlaneConnect/sendSTRU.m +++ /dev/null @@ -1,57 +0,0 @@ -function [ status ] = sendSTRU( STRU, varargin ) -%sendSTRU Send a MATLAB structure over UDP -% -%Inputs -% stru: A MATLAB structure -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin -% -%Outputs -% status: If there was an error. Status<0 means there was an error. -% -%Use -% 1. import XPlaneConnect.*; -% 2. data = struct('a',[1:20],'b',1.853,'name','Example Structure'); -% 3. #Send the data structure to port 49005 on the computer at IP address 172.0.100.54 -% 4. status = sendUDP( data, '172.0.100.54', 49005 ); -% -% Contributors -% [CT] Christopher Teubert (SGT, Inc.) -% christopher.a.teubert@nasa.gov -% -% To Do -% -%BEGIN CODE - - import XPlaneConnect.* - - %% Handle Input - p = inputParser; - addRequired(p,'STRU'); - addOptional(p,'IP','127.0.0.1',@ischar); - addOptional(p,'port',49009,@isnumeric); - parse(p,STRU,varargin{:}); - - %% Form Data Array representing the structure - DATA = ['STRU'-0,0]; %array header - fieldName = fieldnames(p.Results.STRU); %all Struct fields - for i=1:length(fieldName) %for each field - field = getfield(p.Results.STRU,fieldName{i}); %get field - if ischar(field) %String - dim1 = 0; %Indicates string - dim2 = length(field); %length - data = field-0; %data - else %Numeric - dim1 = size(field,1); %Array Dim1 - dim2 = size(field,2); %Array Dim2 - data = typecast(single(reshape(field',1,dim1*dim2)),'uint8'); %Data - end - - DATA = [DATA,length(fieldName{i}),fieldName{i}-0,dim1,dim2,data]; %add to array - end - - %% Send Array - status = sendUDP(DATA, p.Results.IP, p.Results.port); - -end - diff --git a/MATLAB/+XPlaneConnect/sendTEXT.m b/MATLAB/+XPlaneConnect/sendTEXT.m index 499c12b..6dcd010 100644 --- a/MATLAB/+XPlaneConnect/sendTEXT.m +++ b/MATLAB/+XPlaneConnect/sendTEXT.m @@ -1,4 +1,4 @@ -function [ status ] = sendTEXT( msg, varargin ) +function sendTEXT( msg, x, y, socket ) % sendTEXT Sends a string to be displayed in X-Plane. % % Inputs @@ -13,35 +13,34 @@ function [ status ] = sendTEXT( msg, varargin ) % % Use % 1. import XPlaneConnect.*; -% 2. #Set a message to be displayed near the top middle of the screen. +% 2. % Set a message to be displayed near the top middle of the screen. % 3. status = sendTEXT('Some text', 512, 600); % % Contributors -% Jason Watkins -% jason.w.watkins@nasa.gov -% -% To Do -% -% BEGIN CODE +% Jason Watkins (jason.w.watkins@nasa.gov) import XPlaneConnect.* -%% Handle Input -p = inputParser; -addRequired(p,'msg'); -addOptional(p,'x',-1,@isnumeric); -addOptional(p,'y',-1,@isnumeric); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,msg,varargin{:}); -%% Body - header = ['TEXT'-0,0]; - dataStream = [header,... - typecast(uint32(p.Results.x), 'uint8'),... - typecast(uint32(p.Results.y), 'uint8'),... - uint8(length(msg)), msg-0]; - - % Send TEXT - status = sendUDP(dataStream, p.Results.IP, p.Results.port); +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); + end + socket = clients(1); end +%% Validate input +if ~exist('x', 'var') + x = -1; +end +if ~exist('y', 'var') + y = -1; +end +x = int32(x); +y = int32(y); + +%% Send command +socket.sendTEXT(msg, x, y); +end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/sendUDP.m b/MATLAB/+XPlaneConnect/sendUDP.m deleted file mode 100644 index 6b0b112..0000000 --- a/MATLAB/+XPlaneConnect/sendUDP.m +++ /dev/null @@ -1,49 +0,0 @@ -function [ status ] = sendUDP( data, IP, port ) -%sendUDP Send an one dimensional array of type uint8 data over an UDP connection using a java DatagramSocket -% -%Inputs -% Data: 1-D array of type uint8 data to be sent -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin -% -%Outputs -% status: If there was an error. Status<0 means there was an error. -% -%Use -% 1. import XPlaneConnect.*; -% 2. data = uint8([1:20]); -% 3. #Send the data array to port 49005 on the computer at IP address 172.0.100.54. -% 4. status = sendUDP( data, '172.0.100.54', 49005 ); -% -% Contributors -% [CT] Christopher Teubert (SGT, Inc.) -% christopher.a.teubert@nasa.gov -% -% To Do -% 1. Verify Input -% -%BEGIN CODE - - import java.net.DatagramSocket - import java.net.DatagramPacket - import java.net.InetAddress - - data(5) = length(data); - status = 0; - - %% Send array - persistent socket - if isempty(socket) - try - socket = DatagramSocket; - catch err - status = 1; - disp(err) - end - end - - IP = InetAddress.getByName(IP); - packet = DatagramPacket(data, length(data), IP, port); %create packet - socket.send(packet); -end - diff --git a/MATLAB/+XPlaneConnect/sendWYPT.m b/MATLAB/+XPlaneConnect/sendWYPT.m index ed64b04..c8ebabf 100644 --- a/MATLAB/+XPlaneConnect/sendWYPT.m +++ b/MATLAB/+XPlaneConnect/sendWYPT.m @@ -1,53 +1,43 @@ -function [ status ] = sendWYPT( op, points, varargin ) +function sendWYPT( op, points, socket ) % sendWYPT Adds, removes, or clears a set of waypoints to be rendered in % the simulator. % % Inputs -% msg: The string to be displayed -% x (optional): The distance from the left edge of the screen to display the message. -% y (optional): The distance from the bottom edge of the screen to display the message. -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp -% -% Outputs -% status: 0 if successful, otherwise a negative value. +% op: The operation to perform. 1=add, 2=remove, 3=clear. +% points: An array of values representing points. Each triplet in the +% array will be interpreted as a (Lat, Lon, Alt) point. +% socket (optional): The client to use when sending the command. % % Use % 1. import XPlaneConnect.*; -% 2. #Set a message to be displayed near the top middle of the screen. +% 2. %Set a message to be displayed near the top middle of the screen. % 3. status = sendTEXT('Some text', 512, 600); % % Contributors -% Jason Watkins -% jason.w.watkins@nasa.gov +% Jason Watkins (jason.w.watkins@nasa.gov) % % To Do % % BEGIN CODE import XPlaneConnect.* -%% Handle Input -p = inputParser; -addRequired(p,'op'); -addRequired(p,'points'); -addOptional(p,'IP','127.0.0.1',@ischar); -addOptional(p,'port',49009,@isnumeric); -parse(p,op,points,varargin{:}); -%% Validate Input +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); + end + socket = clients(1); +end + +%% Validate input len = uint32(length(points)); assert(op > 0 && op < 4); assert(mod(len, 3) == 0); -assert(len / 3 < 20); -%% Body -header = ['WYPT'-0,0]; -dataStream = [header,... - uint8(op),... - uint8(len / 3),... - typecast(single(points), 'uint8')]; - -% Send TEXT -status = sendUDP(dataStream, p.Results.IP, p.Results.port); -end +%% Send command +socket.sendCTRL(ctrl, ac); +end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/setConn.m b/MATLAB/+XPlaneConnect/setConn.m index 39c2fbf..4038e68 100644 --- a/MATLAB/+XPlaneConnect/setConn.m +++ b/MATLAB/+XPlaneConnect/setConn.m @@ -1,51 +1,35 @@ -function status = setConn( recvPort, IP, port ) +function setConn(port, socket) % setConn Send a command to set up the port where you will receive data on % this computer. % % Inputs -% Receiving Port: Port that data will be sent to in the future for this connection -% IP Address (optional): IP Address of the machine that will receive the data as a character array. Default is '127.0.0.1' (local machine) -% port (optional): Port on the receiving machine where the data will be sent. Default is 49009 (XPlaneConnect). In general use 49009 to send to the plugin and 49005 to send to the x-plane udp -% -% Outputs -% status: If there was an error. status<0 means there was an error. +% port: Port that data will be sent to in the future for this connection. +% socket (optional): The client to use when sending the command. % % Use % 1. import XPlaneConnect.* % 2. status = setConn(49011); % % Contributors -% [CT] Christopher Teubert (SGT, Inc.) -% christopher.a.teubert@nasa.gov -% -% To Do -% 1. Verify Input -% -% BEGIN CODE - import XPlaneConnect.* +% Christopher Teubert (SGT, Inc.) +% Jason Watkins - status = 0; - message = zeros(1,7); - -%% Handle Input - % Optional parameters - if ~exist('IP','var'), IP = '127.0.0.1'; end - if ~exist('port','var'), port = 49009; end +import XPlaneConnect.* - % Check format of input-TODO +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[sendCTRL] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); + end + socket = clients(1); +end -%% BODY - % Header - message(1:4) = 'CONN'-0; - - % RecvPort - message(6:7) = typecast(uint16(recvPort),'uint8'); - - % Send - sendUDP(message,IP,port); - - global udpReadPort; - udpReadPort = recvPort; - readUDP(); % Read and discard CONF message +%% Validate input +port = int32(port); + +%% Send command +socket.setCONN(port); end \ No newline at end of file diff --git a/MATLAB/+XPlaneConnect/setDREF.m b/MATLAB/+XPlaneConnect/setDREF.m new file mode 100644 index 0000000..9b28bb1 --- /dev/null +++ b/MATLAB/+XPlaneConnect/setDREF.m @@ -0,0 +1,37 @@ +function setDREF( dref, value, socket ) +% sendDREF Sends a command to X-Plane that sets the given DREF. +% +% Inputs +% dref: The name of the X-Plane dataref to set. +% Value: An array of floating point values whose structure depends on the dref specified. +% socket (optional): The client to use when sending the command. +% +% Use +% 1. import XPlaneConnect.* +% 2. dataRef = 'sim/aircraft/parts/acf_gear_deploy'; // Landing Gear +% 3. Value = 0; +% 4. status = setDREF(dataRef, Value); +% +% Contributors +% [CT] Christopher Teubert (SGT, Inc.) +% christopher.a.teubert@nasa.gov +% [JW] Jason Watkins +% jason.w.watkins@nasa.gov + +import XPlaneConnect.* + +%% Get client +global clients; +if ~exist('socket', 'var') + assert(istrue(length(clients) < 2), '[setDREF] ERROR: Multiple clients open. You must specify which client to use.'); + if isempty(clients) + openUDP(); + end + socket = clients(1); +end + +%% Validate input +value = single(value); + +%%Send command +socket.setDREF(dref, value); \ No newline at end of file diff --git a/TestScripts/Java Tests/XPlaneConnectTest.java b/TestScripts/Java Tests/XPlaneConnectTest.java index 5bc3d45..2964a06 100644 --- a/TestScripts/Java Tests/XPlaneConnectTest.java +++ b/TestScripts/Java Tests/XPlaneConnectTest.java @@ -123,7 +123,7 @@ public class XPlaneConnectTest String dref = "sim/cockpit/switches/gear_handle_status"; try(XPlaneConnect xpc = new XPlaneConnect()) { - float[] result = xpc.requestDREF(dref); + float[] result = xpc.getDREF(dref); assertEquals(1, result.length); } } @@ -138,7 +138,7 @@ public class XPlaneConnectTest }; try(XPlaneConnect xpc = new XPlaneConnect()) { - float[][] result = xpc.requestDREFs(drefs); + float[][] result = xpc.getDREFs(drefs); assertEquals(2, result.length); assertEquals(1, result[0].length); assertEquals(4, result[1].length); @@ -150,7 +150,7 @@ public class XPlaneConnectTest { try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.requestDREFs(null); + xpc.getDREFs(null); fail(); } } @@ -161,7 +161,7 @@ public class XPlaneConnectTest String[] drefs = new String[0]; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.requestDREFs(drefs); + xpc.getDREFs(drefs); fail(); } } @@ -172,7 +172,7 @@ public class XPlaneConnectTest String[] drefs = new String[300]; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.requestDREFs(drefs); + xpc.getDREFs(drefs); fail(); } } @@ -184,7 +184,7 @@ public class XPlaneConnectTest String[] drefs = new String[]{longDREF}; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.requestDREFs(drefs); + xpc.getDREFs(drefs); fail(); } } @@ -195,7 +195,7 @@ public class XPlaneConnectTest String dref = ""; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.requestDREF(dref); + xpc.getDREF(dref); fail(); } } @@ -207,12 +207,12 @@ public class XPlaneConnectTest try(XPlaneConnect xpc = new XPlaneConnect()) { xpc.pauseSim(true); - float[] result = xpc.requestDREF(dref); + float[] result = xpc.getDREF(dref); //assertEquals(1, result.length); //TODO: Why is this result 20 elements long in Java? (It's only one in MATLAB) assertEquals(1, result[0], 1e-4); xpc.pauseSim(false); - result = xpc.requestDREF(dref); + result = xpc.getDREF(dref); //assertEquals(1, result.length); assertEquals(0, result[0], 1e-4); } @@ -305,12 +305,12 @@ public class XPlaneConnectTest String dref = "sim/cockpit/switches/gear_handle_status"; try(XPlaneConnect xpc = new XPlaneConnect()) { - float gearHandle = xpc.requestDREF(dref)[0]; + float gearHandle = xpc.getDREF(dref)[0]; float value = gearHandle > 0.5 ? 0 : 1; - xpc.sendDREF(dref, value); + xpc.setDREF(dref, value); - float result = xpc.requestDREF(dref)[0]; + float result = xpc.getDREF(dref)[0]; assertEquals(value, result, 1e-4); } } @@ -320,7 +320,7 @@ public class XPlaneConnectTest { try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(null, 0); + xpc.setDREF(null, 0); fail(); } } @@ -332,7 +332,7 @@ public class XPlaneConnectTest try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(dref, null); + xpc.setDREF(dref, null); fail(); } } @@ -343,7 +343,7 @@ public class XPlaneConnectTest String dref = "sim/cockpit/switches/gear_handle_status"; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(dref, new float[0]); + xpc.setDREF(dref, new float[0]); fail(); } } @@ -354,7 +354,7 @@ public class XPlaneConnectTest String dref = "sim/cockpit/switches/gear_handle_status"; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(dref, new float[200]); + xpc.setDREF(dref, new float[200]); fail(); } } @@ -365,7 +365,7 @@ public class XPlaneConnectTest String dref = "sim/cockpit/switches/i/am/a/very/long/fake/dref/that/is/over/255/characters/./which/means/that/my/length/cant/be/encoded/in/the/single/byte/allocated/by/the/message/format/,/so/i/should/cause/an/exception/instead/./i/am/still/not/long/enough/./almost/there"; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(dref, 0); + xpc.setDREF(dref, 0); fail(); } } @@ -376,7 +376,7 @@ public class XPlaneConnectTest String dref = ""; try(XPlaneConnect xpc = new XPlaneConnect()) { - xpc.sendDREF(dref, 0); + xpc.setDREF(dref, 0); fail(); } } @@ -396,7 +396,7 @@ public class XPlaneConnectTest try(XPlaneConnect xpc = new XPlaneConnect()) { xpc.sendCTRL(ctrl); - float[][] result = xpc.requestDREFs(drefs); + float[][] result = xpc.getDREFs(drefs); if(result.length < ctrl.length) { fail(); @@ -425,8 +425,8 @@ public class XPlaneConnectTest try(XPlaneConnect xpc = new XPlaneConnect()) { xpc.sendCTRL(ctrl, 1); - float[][] result1 = xpc.requestDREFs(drefs1); - float[][] result2 = xpc.requestDREFs(drefs2); + float[][] result1 = xpc.getDREFs(drefs1); + float[][] result2 = xpc.getDREFs(drefs2); if(result1.length != 4 || result2.length != 2) { fail(); @@ -480,7 +480,7 @@ public class XPlaneConnectTest xpc.sendPOSI(posi); //TODO: It seems that these calls are a bit too fast. The dref request often gets stale data, causing the test to fail incorrectly. try {Thread.sleep(100);}catch(InterruptedException ex){} - float[][] result = xpc.requestDREFs(drefs); + float[][] result = xpc.getDREFs(drefs); xpc.pauseSim(false); if(result.length < posi.length) { @@ -543,7 +543,7 @@ public class XPlaneConnectTest try(XPlaneConnect xpc = new XPlaneConnect()) { xpc.sendDATA(data); - float[] result = xpc.requestDREF(dref); + float[] result = xpc.getDREF(dref); assertEquals(data[0][1], result[0], 1e-4); } } @@ -577,7 +577,7 @@ public class XPlaneConnectTest { xpc.setCONN(49055); assertEquals(49055, xpc.getRecvPort()); - float[] result = xpc.requestDREF(dref); + float[] result = xpc.getDREF(dref); assertEquals(1, result.length); } }