----------------------------------------------------------------------------
-- FSX Pulg-in for OzRunways "FSXOzplug.lua"
-- Author: Jason Beringer jason.beringer@monash.edu
-- 20/6/2012  Version 1.1
-- FSUIPC  (http://www.schiratti.com/dowson.html) Lua Plug-In
-- OzRunways EFB App for iPhone and Ipad (http://www.ozrunways.com/site/)
--(For FSUIPC4/ESPIPC version 4.60 and later, or FSUIPC3 version 3.98 and later)
-- Place in Modules folder
-- Code reads FSUIPC offsets and writes to UDP port 49002 in format of Xplane data packets
-- this makes OzRunways think it is connected to XPlane but really its FSX
--
--INSTALLATION
-- Download and install FSUIPC (http://www.schiratti.com/dowson.html) - version 4.60 and later, or FSUIPC3 version 3.98 and later
-- To install extract this file (FSX_OzRunways_plugin.lua) into directory ..... /Microsoft Games/Microsoft Flight Simulator X/Modules/
-- Requires vstruct in ..... /Microsoft Games/Microsoft Flight Simulator X/Modules/vstruct
-- Enter the IPad / IPhone IP address into the "host" below in the code
-- Edit the "FSUIPC.ini".  Add the following lines to the end (no dashes)
--[Auto]
--1=Lua FSXOzplug

--
--History
-- v1.0 First release June 2012
-- v1.1 Added current weather (wind speed and direction) as data output.  Added a few print statements to tack in FSUIPC log. Added comments

-----------------------------------------------------------------------------

--Required LUA Modules
local socket = require("socket")
local vstruct = require ("vstruct")

-- Define update rate here in mS
local update_rate=100	--0.1 seconds

print ("Loading FSXOzPlug")
-- Define IP and port
-- Enter the IP address of the IPad or Iphone that OzRunways is running on. 
-- Port 49002 is UDP port that XPlane communicates on and OzRunways expects
host = host or "192.168.0.6"  -- USER EDIT THIS FOR YOUR IPDA/IPHONE RUNNING OZRUNWAYS
port = port or 49002

-- Set options for UDP socket
print ("Setting up socket")
udp2 = socket.udp()
udp2:settimeout(0)
udp2:setoption('broadcast',true)
udp2:setoption('dontroute',true)

--Loop forever
print ("FSXOzplug running .....")
while 1 do

	-- These are the variables OzRunways cares about
	--For code 20  - lat,lon,altitude - index 0 = lat, 1=lon, 2=alt (units - lat/lon degrees, altitude is in feet)
	--For code 21 - vx,vz (if that makes sense)-  index 3=vx  index 5=vz (units kts)
	--For code 18 - heading (maybe more correctly, track, direction aircraft is pointing) - index 2=track (units degrees)

	--Get data from FSUIPC
	local gs_FSUIPC_raw, tas_FSUIPC_raw, ias_FSUIPC_raw,
	lat_FSUIPC_raw, lon_FSUIPC_raw, alt_FSUIPC_raw, pitch_FSUIPC_raw, bank_FSUIPC_raw, hdgT_FSUIPC_raw,
	mach_FSUIPC_raw,vs_FSUIPC_raw, Vz_ft_s_FSUIPC_raw, Vx_ft_s_FSUIPC_raw, Vy_ft_s_FSUIPC_raw, 
	Mag_var_FSUIPC_raw, ambt_WS_knt_FSUIPC_raw,ambt_WD_T_FSUIPC_raw  = ipc.readStruct(	0x02B4, "3UD",
			0x0560, "3DD", "2SD", "1UD",
			0x11C6, "1UW",
			0x0842, "1SW",
			0x3190, "3DBL",
			0x02A0, "1UW",
			0x0E90, "2UW")

	-- and convert it from FS units to units we like
	local gs_FSUIPC = (gs_FSUIPC_raw * 3600) / (65536 * 1852)
	local tas_FSUIPC = tas_FSUIPC_raw / 128
	local ias_FSUIPC = ias_FSUIPC_raw / 128
	local mach_FSUIPC = mach_FSUIPC_raw / 20480
	local vs_FSUIPC = vs_FSUIPC_raw * -3.28084
	local lat_FSUIPC = lat_FSUIPC_raw * 90 / (10001750 * 65536 * 65536)
	local lon_FSUIPC = lon_FSUIPC_raw * 360 /  (65536 * 65536 * 65536 * 65536)
	local alt_ft_FSUIPC = alt_FSUIPC_raw * 3.28084 / (65536 * 65536)
	local alt_m_FSUIPC = alt_FSUIPC_raw / (65536 * 65536)
	local pitch_FSUIPC = pitch_FSUIPC_raw * 360 / (65536 * 65536)
	local bank_FSUIPC = bank_FSUIPC_raw * 360 / (65536 * 65536)
	local hdgT_FSUIPC = hdgT_FSUIPC_raw * 360 / (65536 * 65536)
	local Mag_var_FSUIPC = Mag_var_FSUIPC_raw * 360 / 65536
	local hdgM_FSUIPC = hdgT_FSUIPC - Mag_var_FSUIPC
	local Vz_m_s_FSUIPC=Vz_ft_s_FSUIPC_raw/3.28084
	local Vx_m_s_FSUIPC=Vx_ft_s_FSUIPC_raw/3.28084
	local Vy_m_s_FSUIPC=Vy_ft_s_FSUIPC_raw/3.28084
	local ambt_WD_T_FSUIPC = ambt_WD_T_FSUIPC_raw * 360 / 65536
	local ambt_WS_knt_FSUIPC = ambt_WS_knt_FSUIPC_raw 
	
	-- Now produce the datagram for Xplane UDP packet
	-- First part the "DATA" phrase
	local data1=68
	local data2=65
	local data3=84
	local data4=65
	local data5=64
	
	-- Then index 17 for xpplane pitch, roll, hdg
	-- Note in Xplane ten this is 17 but we output 18 because that is what OzRunways expects
	local index1=18
	local index1a=0	
	local index1b=0
	local index1c=0
	
	local pitch=pitch_FSUIPC
	local roll=bank_FSUIPC
	local hdg_true=hdgT_FSUIPC
	local hdg_mag=hdgM_FSUIPC
	local blank1=ambt_WD_T_FSUIPC -- This was previously blank for Xplane but I have added weather info here
	local blank2=ambt_WS_knt_FSUIPC	-- This was previously blank for Xplane but I have added weather info here	
	local blank3=-999
	local blank4=-999			
				
	-- Then index 20 for x-plane lat,lon,alt,etc.
	local index2=20
	local index2a=0
	local index2b=0
	local index2c=0	
	local lat_D=lat_FSUIPC
	local lon_D=lon_FSUIPC
	local alt_m=alt_m_FSUIPC
	local alt_ft=alt_ft_FSUIPC
	local onrwy=0
	local alt_ind=alt_ft_FSUIPC
	local lat_S=100
	local lon_W=100
		
	-- Then index 21 for x-plane position info X,Y,Z,Vx,Vy,Vz, dist
	local index3=21
	local index3a=0		
	local index3b=0
	local index3c=0
		
	-- Add dummy values for some variables that FSUIPC doesnt have
	local posX=-999
	local posY=-999
	local posZ=-999
	local vX=Vx_m_s_FSUIPC
	local vY=Vy_m_s_FSUIPC
	local vZ=Vz_m_s_FSUIPC
	local dist_ft=-999
	local dist_m=-999

	
	local newtable={data1, data2, data3, data4, data5, index1, index1a, index1b, index1c, pitch, roll, hdg_true, hdg_mag, blank1, blank2, blank3, blank4, index2, index2a, index2b, index2c, lat_D, lon_D, alt_ft, alt_m, onrwy, alt_ind, lat_S, lon_W, index3, index3a, index3b, index3c, posX, posY, posZ, vX, vY, vZ, dist_ft, dist_m}

	newdgram = (vstruct.pack("9*u1 8*f4 4*u1 8*f4 4*u1 8*f4", newtable))	
	-- Leave this as we may later want to divide the data packet up in bits and send seperately
	-- newtable1 ={data1, data2, data3, data4, data5, index1, index1a, index1b, index1c, pitch, roll, hdg_true, hdg_mag, blank1, blank2, blank3, blank4}
	-- newtable2 ={data1, data2, data3, data4, data5, index2, index2a, index2b, index2c, lat_D, lon_D, alt_m, alt_ft, onrwy, alt_ind, lat_S, lon_W}
	-- newtable3 ={data1, data2, data3, data4, data5, index3, index3a, index3b, index3c, posX, posY, posZ, vX, vY, vZ, dist_ft, dist_m}

	-- newdgram1 = (vstruct.pack("9*u1 8*f4 ", newtable1))	
	-- newdgram2 = (vstruct.pack("9*u1 8*f4 ", newtable2))		
	-- newdgram3 = (vstruct.pack("9*u1 8*f4 ", newtable3))	

	--Send Data to HOST on PORT
	udp2:sendto(newdgram, host, port)

	-- -- udp2:sendto(newdgram1, host, port)
	-- -- udp2:sendto(newdgram2, host, port)
	-- -- udp2:sendto(newdgram3, host, port)

	-- -- Sleep for 500 mSecs so the update gets done roughly 2 times per second
	ipc.sleep(update_rate)

end



