zbmtwo Posted October 13, 2016 Share Posted October 13, 2016 I'm interested in writing a LUA script to send NMEA data over TCP/IP or as UDP broadcast. I understand that the DCS coordinate system doesn't necessarily match the real world 100% of the time (it's a flat plane instead of a spheroid?), but I'm still interested in trying as at least AHRS data would be accurate. I would like to receive the data with a Glass Cockpit app on my iOS devices. In particular, I'm interested in Air Navigation Pro as it already has FSX and X Plane integration. It should be a matter of taking ownship information from DCS, converting it into the relevant formats for the appropriate NMEA sentences, then open a socket and send the data as NMEA sentences to the client. I've emailed the company that makes Air Navigation Pro asking for more info about the protocol they use, but in the meantime I want to get started writing the export script (I'll post their response when I receive it). I understand that I would have to do something like this from the example in the default export.lua: function LuaExportAfterNextFrame() -- get the variables local t = LoGetModelTime() local name = LoGetPilotName() local altBar = LoGetAltitudeAboveSeaLevel() local altRad = LoGetAltitudeAboveGroundLevel() local pitch, bank, yaw = LoGetADIPitchBankYaw() local engine = LoGetEngineInfo() local HSI = LoGetControlPanel_HSI() -- format the data and send it over the network socket.try(c:send(string.format("t = %.2f, name = %s, altBar = %.2f, alrRad = %.2f, pitch = %.2f, bank = %.2f, yaw = %.2f\n", t, name, altRad, altBar, pitch, bank, yaw))) end Outside of having a basic understanding of what is required, I'm stuck as to execution. I want to send the following NMEA sentences to start with: $PAHR - AHRS info; pitch, roll, heading $GPGLL - Geographic position; latitude / longitude So I'd need to convert: angles from Radians to Degrees in the format of DDD.DD (radian * 57.296; +ve values for roll to port/pitch up, -ve values for roll to starboard/pitch down) LAT/LON to the format DDMM.MM,N/S / DDDMM.MM,E/W time to the format HHMMSS.SS speed from m/s to knots in the format KKK.KK (speed * 1.943844) height from meters to feet (alt * 3.048, as an integer) Is someone able to point me in the direction of some resources or otherwise provide me an example of how to format NMEA strings and send them via TCP/IP using LUA? I don't want to reinvent the wheel if someone has already made something for this purpose. I had a look at the TacView export script, a script for exporting UH-1 telemetry to Android, and at LotATC but the info in this post is as far as I've got on my own for now. I'm going to have a go at writing a LUA script based on that UH-1 script (I see that it uses the ID of specific instruments, but I'm thinking I can get the values I need using LoGet functions?) Thanks for your help! Here's some greater detail on what I want to accomplish... Background It is possible to export ownship data from DCS via LUA There are a number of Glass Cockpit apps for iOS and Android that accept NMEA data over TCP/IP Goal Create code for export.lua that extracts relevant ownship data, formats it as NMEA sentences, and sends it over TCP/IP to a Glass Cockpit app on a mobile device Requirements Exctract ownship data from DCS Format ownship data as NMEA sentences for AHRS and GPS Transmit data over TCP/IP to a mobile device running client software Alternatively/additionally: transmit data via UDP Resources 1. AHRS Devices Levil have AHRS devices that sends data to iOS and Android devices via TCP/IP over WLAN: Wireless Transmission Some mobile devices that do not have a USB or serial port, require wireless communication to the AHRS (i.e iPad/iPhones). The iLevil and AHRS-G mini series have an embedded wireless transmitter that works as the router at home and creates a WiFi access point to which your tablet will link to. Once connected, navigation programs can then telnet to the transmitter using either TCP or UDP transmission: - TCP/IP connection is very robust and requires the remote device to confirm receipt of data every time the AHRS sends a package. Although TCP connection guarantees no data is lost on the way, it may cause some latency on the transmission if either the sender or the receiver is not properly responding in a timely manner. For example, iPad devices have shown latency when you move the device around because it is trying to figure out the screen rotation. You can also expect some latency if you are inside a building with multiple Wi-Fi access points or if you are accidentally blocking the iPad transmitter with your hand. The best way to test the AHRS transmission is to fly with it. TCP can only be used by one application at a time. - UDP transmission is not as robust as TCP, but allows multiple devices to access the same data simultaneously. If you’d like to use two iPads, for example, you might want to use the device in UDP mode. UDP is the default mode and is recommended for in-flight use. InertialLabs make and AHRS that does the same, and we can see via their AHRS documentation (pp. 21-22) that NMEA has a proprietry sentence for AHRS data ($PAHR): At the “NMEA Output” the AHRS output data are transmitted in the form of sentences with printable ASCII characters like the NMEA 0183 format. Each sentence starts with a "$" sign and ends with <CR><LF> (carriage return 0xD and line feed 0xA symbols). All data fields are separated by commas. The general form of the “NMEA Output” sentence is the text PAHR,RRRR.rr,PPP.pp,HHH.hh,TTT.t,V.vv,SSSS*CC<CR><LF> where PAHR is identifier and other fields are listed in the Table 6.7. Тable 6.7.The AHRS message in NMEA format (at NMEAcont or NMEAreq command) Field RRRR.rr PPP.pp HHH.hh TTT.t V.vv SSSS CC Parameter Roll Pitch Heading Temperature Vdd USW Checksum Note deg deg deg ºC VDC Hex* *Hex written in ASCII; AHRS state information (Ready/Sleeping, Errors, BIT, etc) Notes: 1. USW is unit status word (see section 6.5 pp. 43-44 for details). 2. Temperature is averaged value for 3 accelerometers. 3. Vdd is input voltage of the AHRS. 4. Check sum consists of a "*" and two hex digits representing XOR of all characters between, but not including "$" and "*". Important note: The AHRS maximum data rate is limited to 50 Hz in the NMEA output format 2. NMEA Sentences Although the NMEA standard costs $$$ to obtain, there are a number of resources that explain some of the sentences For example: http://aprs.gids.nl/nmea/ $GPBOD - Bearing, origin to destination $GPBWC - Bearing and distance to waypoint, great circle $GPGGA - Global Positioning System Fix Data $GPGLL - Geographic position, latitude / longitude $GPGSA - GPS DOP and active satellites $GPGSV - GPS Satellites in view $GPHDT - Heading, True $GPR00 - List of waypoints in currently active route $GPRMA - Recommended minimum specific Loran-C data $GPRMB - Recommended minimum navigation info $GPRMC - Recommended minimum specific GPS/Transit data $GPRTE - Routes $GPTRF - Transit Fix Data $GPSTN - Multiple Data ID $GPVBW - Dual Ground / Water Speed $GPVTG - Track made good and ground speed $GPWPL - Waypoint location $GPXTE - Cross-track error, Measured $GPZDA - Date & Time 3. Client Applications Air Navigation Pro Air Navigation is a flight planning and real-time aircraft navigation application with 2D moving map and 3D synthetic vision for iPhone, iPad and Android devices. A Desktop version for Mac OS X is also available. Air Navigation Apps support free charts of almost the entire world as well as commercial aviation VFR charts for many countries. The application costs a fraction of the price of a dedicated portable aviation GPS and will help you to plan your flight, saving you time and money. Air Navigation can be connected to the X-Plane or FSX flight simulators by installing a plugin on your favorite simulator. This is a great feature for training at home when bad weather prevents real flying! Also, simulator enthusiasts can add a full moving map system to their Sim setup. Currently we have an X-Plane 9/10 plugin for Windows and Mac OS X and and FSX plugin for Windows. List of Other Client Apps: http://aviation.levil.com/compatible-apps.html 4. DCS export.lua Variables Get the relevant paramaters: LoGetAltitudeAboveSeaLevel() LoGetADIPitchBankYaw() LoGetVerticalVelocity() LoGetTrueAirSpeed() MyPlane.LatLongAlt.Lat MyPlane.LatLongAlt.Long Format them for NMEA: local t = LoGetModelTime() local altBar = LoGetAltitudeAboveSeaLevel() local pitch, bank, yaw = LoGetADIPitchBankYaw() local vertvel = LoGetVerticalVelocity() local trueairspeed = LoGetTrueAirSpeed() local LatPos = MyPlane.LatLongAlt.Lat local LongPos = MyPlane.LatLongAlt.Long local av = LoGetAngularVelocity() Send as NMEA sentences: $PAHR - AHRS info $GPGLL - Geographic position, latitude / longitude I have also found this script that is used to export UH-1 telemetry to an Android app. It looks like I could use this code as the bones of an NMEA export script over UDP: --------------------------------------------------------------------------------------------------- -- Export UH-1H instruments --------------------------------------------------------------------------------------------------- f_uh1h = { Start=function(self) package.path = package.path..";.\\LuaSocket\\?.lua" package.cpath = package.cpath..";.\\LuaSocket\\?.dll" socket = require("socket") my_init = socket.protect(function() -- export telemetry to instrumeny panel on android host2, port2 = "10.0.0.3", 6000 -- replace IP with android device ip udp = socket.try(socket.udp()) end) my_init() end, AfterNextFrame=function(self) --local player = LoGetObjectById(LoGetPlayerPlaneId()) --print(player.Name) --if (player and player.Name == "UH-1H") then -- read from UH-1H main panel instruments local MainPanel = GetDevice(0) local AirspeedNeedle = MainPanel:get_argument_value(117)*150 local Altimeter_10000_footPtr = MainPanel:get_argument_value(178)*100000 local Altimeter_1000_footPtr = MainPanel:get_argument_value(179)*10000 local Altimeter_100_footPtr = MainPanel:get_argument_value(180)*1000 local Variometer = MainPanel:get_argument_value(134)*4000 local TurnNeedle = MainPanel:get_argument_value(132)*math.rad(1.5) local Slipball = MainPanel:get_argument_value(133) local CoursePointer1 = MainPanel:get_argument_value(159) * 2.0 * math.pi local CoursePointer2 = MainPanel:get_argument_value(160) * 2.0 * math.pi local CompassHeading = MainPanel:get_argument_value(165) * 2.0 * math.pi local Torque = MainPanel:get_argument_value(124) * 103 + -3 local Engine_RPM = MainPanel:get_argument_value(122)*7200 local AHorizon_Pitch = MainPanel:get_argument_value(143) * math.pi / 2.0 local AHorizon_Bank = MainPanel:get_argument_value(142) * math.pi local AHorizon_PitchShift = 0 local GyroHeading = MainPanel:get_argument_value(165) * 2.0 * math.pi local Oil_Temperature = MainPanel:get_argument_value(114) * 150 local Oil_Pressure = MainPanel:get_argument_value(113) * 100 local Fuel_Pressure = MainPanel:get_argument_value(126) * 50 local Fuel_Tank = MainPanel:get_argument_value(239) * 1580.0 / 100.0 local VerticalBar = MainPanel:get_argument_value(151) * -2.0 local HorisontalBar = MainPanel:get_argument_value(152) * -2.0 local ToMarker = MainPanel:get_argument_value(153) local FromMarker = MainPanel:get_argument_value(154) local RotCourseCard = MainPanel:get_argument_value(156) * 2.0 * math.pi my_send = socket.protect(function() local json = string.format("{ 'AirspeedNeedle':%.2f, 'Altimeter_10000_footPtr':%.2f, 'Altimeter_1000_footPtr':%.2f, 'Altimeter_100_footPtr':%.2f, 'Variometer':%.2f, 'TurnNeedle':%.2f, 'Slipball':%.2f, 'CoursePointer1':%.2f, 'CoursePointer2':%.2f, 'CompassHeading':%.2f, 'Torque':%.2f, 'Engine_RPM':%.2f, 'AHorizon_Pitch':%.2f, 'AHorizon_Bank':%.2f, 'GyroHeading':%.2f, 'Oil_Temperature':%.2f, 'Oil_Pressure':%.2f, 'Fuel_Pressure':%.2f, 'Fuel_Tank':%.2f,'VerticalBar':%.2f,'HorisontalBar':%.2f,'ToMarker':%.2f,'FromMarker':%.2f,'RotCourseCard':%.2f}\n", AirspeedNeedle, Altimeter_10000_footPtr, Altimeter_1000_footPtr, Altimeter_100_footPtr, Variometer, TurnNeedle, Slipball, CoursePointer1, CoursePointer2, CompassHeading, Torque, Engine_RPM, AHorizon_Pitch, AHorizon_Bank, GyroHeading, Oil_Temperature, Oil_Pressure, Fuel_Pressure, Fuel_Tank, VerticalBar, HorisontalBar, ToMarker, FromMarker, RotCourseCard ) --print(json) socket.try(udp:sendto(json, host2, port2)) end) -- my_send my_send() --end -- if UH-1H end, Stop=function(self) my_close = socket.protect(function() socket.try(udp:close()) end) my_close() end } -- ============= -- Overload -- ============= do local PrevLuaExportStart=LuaExportStart LuaExportStart=function() f_uh1h:Start() if PrevLuaExportStart then PrevLuaExportStart() end end end do local PrevLuaExportAfterNextFrame=LuaExportAfterNextFrame LuaExportAfterNextFrame=function() f_uh1h:AfterNextFrame() if PrevLuaExportAfterNextFrame then PrevLuaExportAfterNextFrame() end end end do local PrevLuaExportStop=LuaExportStop LuaExportStop=function() f_uh1h:Stop() if PrevLuaExportStop then PrevLuaExportStop() end end end Link to comment Share on other sites More sharing options...
BR55Sevas Posted October 15, 2016 Share Posted October 15, 2016 (edited) So, what the problem? Just read and use "LatLongAlt" function for coordinates extraction Edited October 15, 2016 by BR=55=Sevas МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted October 20, 2016 Share Posted October 20, 2016 (edited) @zbmtwo I've done what you are trying to do, with the same "template", the TacView export script. But I used the GPGGA and GPRMC sentence. But I'm using true airspeed instead of groundspeed so far, haven't bother to do the calculations yet. You will be off a few 100m depending on where you are flying. I'm not a regular programmer my self so my code is ugly. I might share the code if you like, but no support guarantee. @BR=55=Sevas What is that for and application you have there? Homemade? Edit: Sorry, I didn't use the TacView export script, but the exporting UH-1 telemetry to Android one. Edited January 27, 2019 by Holton181 Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
gavilan_cl Posted January 4, 2019 Share Posted January 4, 2019 Hi guys. Nice idea! Is there a public code? I will like to integrate DCS World with ForeFlight Salute Gavilan Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 6, 2019 Share Posted January 6, 2019 HEre is my app with MFD and GPS map https://forums.eagle.ru/showthread.php?t=80496 МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 7, 2019 Share Posted January 7, 2019 HEre is my app with MFD and GPS map https://forums.eagle.ru/showthread.php?t=80496 Better late than never :smilewink: Seriously, thanks :thumbup:, always interesting to see how others solve problems. But both OP an I want to send NMEA sentences to whatever application/device that can handle them. You sends the coordinates straight to a self made app. And you also get the same location error as me, since we both uses the in game coordinates without any adjustments for the real world. All is working good for me except I cant get the ground speed and track direction (not heading or LoGetMagneticYaw you are using). Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 8, 2019 Share Posted January 8, 2019 (edited) You can send NMEA sentence in your app, all you need is correct string format according to NMEA standart $GPRMC...and so on The reason for localtion error on map is DCS itself. DCS uses flat earth projection, but gps map uses spherical. To get ground speed and track direction use Speed vector LoGetVectorVelocity = {x,y,z} -- vector of self velocity (world axis) Just calculate derivative between frames and you`ll get real world speed, using arctan you can calculate true direction. Edited January 8, 2019 by BR=55=Sevas МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 8, 2019 Share Posted January 8, 2019 You can send NMEA sentence in your app, all you need is correct string format according to NMEA standart $GPRMC...and so on The reason for localtion error on map is DCS itself. DCS uses flat earth projection, but gps map uses spherical. To get ground speed and track direction use Speed vector LoGetVectorVelocity = {x,y,z} -- vector of self velocity (world axis) Just calculate derivative between frames and you`ll get real world speed, using arctan you can calculate true direction. Thanks, I do use RMC and GGA sentences and I know about the flat earth in DCS. But I didn't think of using LoGetVectorVelocity, will try it out. It's in meters right? I figure it out. Thanks again! Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 8, 2019 Share Posted January 8, 2019 Yes, Dcs uses metric SI units. Also z axis directed up, but you know about I think. МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 8, 2019 Share Posted January 8, 2019 Also z axis directed up, but you know about I think. Wasn't sure though, though I read something a while ago they had some strange configuration with Y as up, but most likely my memory fail on me. Thanks again. Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 8, 2019 Share Posted January 8, 2019 I believe you are correct, Y is up. МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 9, 2019 Share Posted January 9, 2019 (edited) To get ground speed and track direction use Speed vector LoGetVectorVelocity = {x,y,z} -- vector of self velocity (world axis) Just calculate derivative between frames and you`ll get real world speed, using arctan you can calculate true direction. This works like a charm! :thumbup: But no need to calculate derivative between frames, it's a velocity vector so all information needed is there for each point. Just to use some Pythagoras and arctan to get the resultant lateral vector. Just gonna clean up the code and then I might share it. One can connect with either UDP or Bluetooth virtual serial port. I have a small annoying issue with the Bluetooth port though. When there is no one listening on it DCS freeze until something start to. Would like to find a way to handle that situation. Thanks again! Edited January 9, 2019 by Holton181 Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 10, 2019 Share Posted January 10, 2019 Thats weird. As I remember DCS freeze only if you try to send data from your app to DCS, and DCS waits data, if there are no data its freeze. Functions like socket.receive or similar. Try this advise, maybe it fix freeze А почему нельзя к этому: c:setoption("tcp-nodelay",true) -- set immediate transmission mode добавить это: c:settimeout(.001) -- set the timeout for reading the socket МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 10, 2019 Share Posted January 10, 2019 (edited) It's only when using the Bluetooth virtual port, not UDP. It freeze the second I hit "Fly" on the briefing window at mission start, and it unfreeze the second any application start listening to the port. If I stop listening the app DCS freeze again, start and it unfreeze. These are the three blocks used for it: at start --Bluetooth ---[[ sPort = "COM3" com = io.open(sPort,"w+b") --]]sending --Bluetooth ---[[ com:write(string.format("$%s*%x\r\n$%s*%x\r\n", GGA,csGGA,RMC,csRMC)) -- fills the serial buffer com:flush() -- send the serial buffer --]]stop --Bluetooth ---[[ com:close(sPort) --]]COM3 is the Bluetooth VP configured as "incoming" in Windows 7 Pro. I basically know nothing about these things but have used examples around the web to get it working. I assume I should do some sort of test on the port before sending. Searched the web how to but could not find anything. Checking the io.open in the beginning for errors should not help, since that is only done at start and the issue is strictly related to if anything is listening on the port: If it is, all good. If not, freeze. Also, it can be a Bluetooth issue, and since DCS and the script isn't really aware of that, only seeing the serial port, it might not be possible to do anything about it? Edited January 10, 2019 by Holton181 Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
BR55Sevas Posted January 11, 2019 Share Posted January 11, 2019 (edited) Show full export.lua code Edited January 11, 2019 by BR=55=Sevas МиГ-29 Fly by wire СДУ Su-27SM second display panel https://www.youtube.com/embed/videoseries?list=PL_2GGwNpWNp_fKXfRtDhIk8s5Jf4a9XHS http://berkuts.ru Пилотажный сервер с роботом | Aerobatic server with PhantomControl Link to comment Share on other sites More sharing options...
Holton181 Posted January 29, 2019 Share Posted January 29, 2019 Here it is: https://www.digitalcombatsimulator.com/en/files/3303310/ Helicopters and Viggen DCS 1.5.7 and OpenBeta Win7 Pro 64bit i7-3820 3.60GHz P9X79 Pro 32GB GTX 670 2GB VG278H + a Dell PFT Lynx TrackIR 5 Link to comment Share on other sites More sharing options...
Recommended Posts