Jump to content

HowTo: Get contents of CMSP, CMCP and some other indicators as a string


FSFIan

Recommended Posts

This morning, I hooked up the lua console of DCS Witchcraft to the export environment and looked around.

 

What I found blew my mind:

there is a function that can return the contents of the CMSP (and some other indicators) as text, so you could easily display it on a character LCD.

 

exportconsole.png

 

The function is even mentioned in the DCS User Manual on page 94:

To obtain an element name, run a mission with the desired element string displayed in the cockpit, open the game console and execute the “console.out(list_indication(n))” command (where ‘n’ is the desired indicator’s ID). The game console can be accessed by pressing the “`” command in-game. The console.out(list_indication(n)) console command will list all currently displayed elements with their associated strings for the set indicator

 

So why is this not common knowledge? Why have people gone through the trouble of using OCR or scanning the memory of the DCS process to get the contents of this display?

Page 93 has the answer:

Although cockpit triggers are considered a developer's tool, most of their functionality is open to the player. There are some examples, however, which require the use of the ingame console, which is disabled in public builds.

 

ED, for some reason, disabled their lua console in public builds, and so far no one bothered to poke around because without the proper tools it would have been too annoying to do given that you are not guaranteed to find anything at all.

 

For those who want to poke around for themselves, I have made a video that shows how to use the lua console with the export.lua environment.

 

If you are looking to export a specific value to your custom panel, this is a great way to quickly iterate until you get it right.

 

I am actually a little angry that no one at ED ever mentioned the existence of this function while people were putting a lot of effort into solutions based on character recognition or scanning the memory of the DCS process.

  • Like 11
Link to comment
Share on other sites

Just lost my socks (jumping with joy:) knowing this isn't magic but it's as close as it comes. Just amazing. Just got a mission for upcomming autumn to grasp the consept to grab the data.

Thanks for posting :notworthy::notworthy:

- - - -

Link to comment
Share on other sites

....and one line of export.lua added and three lines of C# code later...BAM! Mr. Ian if I could add rep to you I would!

<insert picture here of my one line of export.lua code and a MessageBox showing pretty much the same thing you show above. I just picked a random property number (2091 seemed to come next :)).

 

SendData(2091, list_indication(7))

  • Like 1
Link to comment
Share on other sites

I should be doing other things right now, but given this discovery I couldn't resist playing with the contents of my parts drawers again.

 

Here's an Arduino sketch and accompanying Export.lua file that will display the CMSP contents on a 20x2 character LCD connected to the Arduino. It will also turn a push button on pin 10 and the built-in LED on pin 13 into a Master Caution button/light.

 

20140716_001.jpg

(That picture was taken before I added the push button.)


Edited by [FSF]Ian
Link to comment
Share on other sites

Awesome to see, if anyone finds the radio displays can they also post to this thread?

 

You can ask the radio devices:

local uhf = string.format("%.03f", GetDevice(54):get_frequency()/1000000)
local vhf_am = string.format("%.03f", GetDevice(55):get_frequency()/1000000)
local vhf_fm = string.format("%.03f", GetDevice(56):get_frequency()/1000000)

However, DCS seems to model that the radios are not always tuned exactly, so the frequencies you get here are always slightly off.

 

 

The UHF frequencies are displayed as text in the cockpit, so we can grab them as strings (the following functions will return the empty string if the cockpit displays are off because of no power or broken UHF radio):

local function get_uhf_preset()
   local ind = parse_indication(10)
   if ind == nil then return "" end
   return ind["txtPresetChannel"]
end

local function get_uhf_freq()
   local ind = parse_indication(11)
   if ind == nil then return "" end
   local freqStatus = ind["txtFreqStatus"] -- e.g. "251000"
   return freqStatus:sub(0,3) .. "." .. freqStatus:sub(4,6)
end

 

For the VHF radio, the mainpanel_init.lua file indicates which argument numbers may be interesting:

elements["PTR-ANARC186-VHFAM-FREQ-1"] = radio_wheel(_("Frequency Selector the 1nd"), devices.VHF_AM_RADIO, device_commands.Button_9, device_commands.Button_10, 139,{-0.1, 0.1}, {143,{0.125,0.775},0.5})
elements["PTR-ANARC186-VHFAM-FREQ-2"] = radio_wheel(_("Frequency Selector the 2nd"), devices.VHF_AM_RADIO, device_commands.Button_11, device_commands.Button_12, 140,{-0.1, 0.1}, {144,{0.0,1.0},1.0})
elements["PTR-ANARC186-VHFAM-FREQ-3"] = radio_wheel(_("Frequency Selector the 3rd"), devices.VHF_AM_RADIO, device_commands.Button_13, device_commands.Button_14, 141,{-0.1, 0.1}, {145,{0.0,1.0},1.0})
elements["PTR-ANARC186-VHFAM-FREQ-4"] = radio_wheel(_("Frequency Selector the 4th"), devices.VHF_AM_RADIO, device_commands.Button_15, device_commands.Button_16, 142,{-0.25, 0.25}, {146,{0.0,1.0},1.0})

elements["PTR-ANARC186-VHFFM-FREQ-1"] = radio_wheel(_("Frequency Selector the 1nd"), devices.VHF_FM_RADIO, device_commands.Button_9, device_commands.Button_10, 153,{-0.1, 0.1}, {157,{0.125,0.775},0.5})
elements["PTR-ANARC186-VHFFM-FREQ-2"] = radio_wheel(_("Frequency Selector the 2nd"), devices.VHF_FM_RADIO, device_commands.Button_11, device_commands.Button_12, 154,{-0.1, 0.1}, {158,{0.0,1.0},1.0})
elements["PTR-ANARC186-VHFFM-FREQ-3"] = radio_wheel(_("Frequency Selector the 3rd"), devices.VHF_FM_RADIO, device_commands.Button_13, device_commands.Button_14, 155,{-0.1, 0.1}, {159,{0.0,1.0},1.0})
elements["PTR-ANARC186-VHFFM-FREQ-4"] = radio_wheel(_("Frequency Selector the 4th"), devices.VHF_FM_RADIO, device_commands.Button_15, device_commands.Button_16, 156,{-0.25, 0.25}, {160,{0.0,1.0},1.0})

 

After some experimentation with the lua console, the following seems to work:

local vhf_lut1 = {
   ["0.15"] = " 3",
   ["0.20"] = "4",
   ["0.25"] = "5",
   ["0.30"] = "6",
   ["0.35"] = "7",
   ["0.40"] = "8",
   ["0.45"] = "9",
   ["0.50"] = "10",
   ["0.55"] = "11",
   ["0.60"] = "12",
   ["0.65"] = "13",
   ["0.70"] = "14",
   ["0.75"] = "15"
}

function get_vhf_am_freq()
   local freq1 = vhf_lut1[string.format("%.2f",GetDevice(0):get_argument_value(143))]
   local freq2 = string.format("%1.1f", GetDevice(0):get_argument_value(144)):sub(3)
   local freq3 = string.format("%1.1f", GetDevice(0):get_argument_value(145)):sub(3)
   local freq4 = string.format("%1.2f", GetDevice(0):get_argument_value(146)):sub(3)

   return freq1 .. freq2 .. "." .. freq3 .. freq4
end

function get_vhf_fm_freq()
   local freq1 = vhf_lut1[string.format("%.2f",GetDevice(0):get_argument_value(157))]
   local freq2 = string.format("%1.1f", GetDevice(0):get_argument_value(158)):sub(3)
   local freq3 = string.format("%1.1f", GetDevice(0):get_argument_value(159)):sub(3)
   local freq4 = string.format("%1.2f", GetDevice(0):get_argument_value(160)):sub(3)

   return freq1 .. freq2 .. "." .. freq3 .. freq4
end

function get_vhf_am_preset()
   return tostring(tonumber(string.format("%.2f", GetDevice(0):get_argument_value(137)):sub(3))+1)
end

function get_vhf_fm_preset()
return tostring(tonumber(string.format("%.2f", GetDevice(0):get_argument_value(151)):sub(3))+1)
end

 

 

ILS and TACAN frequency / channel:

local function get_tcn_channel()
   local tcn_2 = ""
   if GetDevice(0):get_argument_value(263) == 1 then
       tcn_2 = " "
   else
   	tcn_2 = "1"    
   end
   local tcn_1 = string.format("%.1f", GetDevice(0):get_argument_value(264)):sub(3)
   local tcn_0 = string.format("%.1f", GetDevice(0):get_argument_value(265)):sub(3)

   local tcn_xy_lut = {"X", "Y"}
   local tcn_xy = tcn_xy_lut[GetDevice(0):get_argument_value(266)+1]

   return tcn_2 .. tcn_1 .. tcn_0 .. tcn_xy
end

local function get_ils_freq()
   local ils_mhz_lut = {
       ["0.0"] = "108",
       ["0.1"] = "109",
       ["0.2"] = "110",
       ["0.3"] = "111"
   }
   local ils_khz_lut = {["0.0"] = 0.10,
       ["0.1"] = ".15",
       ["0.2"] = ".30",
       ["0.3"] = ".35",
       ["0.4"] = ".50",
       ["0.5"] = ".55",
       ["0.6"] = ".70",
       ["0.7"] = ".75",
       ["0.8"] = ".90",
       ["0.9"] = ".95"
   }
   local mhz = ils_mhz_lut[string.format("%.1f", GetDevice(0):get_argument_value(251))]
   local khz = ils_khz_lut[string.format("%.01f", GetDevice(0):get_argument_value(252))]
   return mhz .. khz
end

Link to comment
Share on other sites

Are the HSI values also included in this?

 

Potential values and inputs are -

 

- Power OFF Flag

- Compass Card

- Range Indicator

- Bearing Pointer 1

- Bearing Pointer 2

- Heading Set Knob

- Heading Marker

- Bearing Validity Flag

- Course Set Knob

- Course Selector Window

- Course Arrow

- Course Deviation Indicator (CDI)

- To-From Indicator

 

Thanks in advance!

 

Smirks

Cheers,

 

Smirkza

Link to comment
Share on other sites

Are the HSI values also included in this?

 

Potential values and inputs are -

 

- Power OFF Flag

- Compass Card

- Range Indicator

- Bearing Pointer 1

- Bearing Pointer 2

- Heading Set Knob

- Heading Marker

- Bearing Validity Flag

- Course Set Knob

- Course Selector Window

- Course Arrow

- Course Deviation Indicator (CDI)

- To-From Indicator

 

Thanks in advance!

 

Smirks

 

After going through Helios properly for the first time I think all of these are available for extraction.

 

Now I just need to figure out how to communicate with an arduino. All of the guides assume a level of knowledge I don't yet have (not got a programming background and never extracted data from DCS before).

Cheers,

 

Smirkza

Link to comment
Share on other sites

:( trying to use list_indication and it seems i don't have it!

here is what i have

 

 

"tostring",

"gLastGunStatus",

"LoGetObjectById",

"LoGetCameraPosition",

"LoGetMachNumber",

"LoGetRadioBeaconsStatus",

"LoGetControlPanel_HSI",

"list_cockpit_params",

"debug",

"assert",

"tonumber",

"COMExportStart",

"FlapsServoCalTable",

"LoRemoveSharedTexture",

"load",

"socket",

"LoGetF15_TWS_Contacts",

"LoGetVerticalVelocity",

"LoGeoCoordinatesToLoCoordinates",

"coroutine",

"LoGetVersionInfo",

"LoGetRadarAltimeter",

"siocConfig",

"loadstring",

"LoGetMechInfo",

"LoGetAngularVelocity",

"SimpleRadioPre",

"string",

"Servo",

"LoEnableExternalFlightModelSock",

"print",

"a_cockpit_perform_clickable_action",

"a_cockpit_highlight_position",

"COMExportBeforeNextFrame",

"table",

"round",

"_ARCHITECTURE",

"LoGetMCPState",

"ProcessIndicators",

"_ED_VERSION",

"LoSetCameraPosition",

"ipairs",

"LoSetCommand",

"collectgarbage",

"c_cockpit_param_in_range",

"FuelQuantityL",

"c_start_wait_for_user",

"LoGetMagneticYaw",

"LoGetBasicAtmospherePressure",

"math",

"LoGetSnares",

"pcall",

"Flaps",

"type",

"a_cockpit_remove_highlight",

"lfs",

"LoGetHelicopterFMData",

"AmmoCountersAndType",

"LoLoCoordinatesToGeoCoordinates",

"LoEnableExternalFlightModel",

"LoGetAltitude",

"loadfile",

"log",

"gOxyGaugeSIOCParam",

"LoGetAccelerationUnits",

"gcinfo",

"msg",

"COMExportStop",

"gVVISIOCParam",

"LoGetNavigationInfo",

"SiocExportStop",

"ThreePositionSwitch",

"LoGetSlipBallPosition",

"OxyGaugeServoCalTable",

"SiocExportBeforeNextFrame",

"SiocExportStart",

"inputsTable",

"HYDSsysRServoCalTable",

"gHYDSsysRSIOCParam",

"LoGetADIPitchBankYaw",

"LoGetEngineInfo",

"dbg_print",

"io",

"VVI",

"LoUpdateSharedTexture",

"HYDSsysLServoCalTable",

"LoGetAngleOfSideSlip",

"gHYDSsysLSIOCParam",

"gIndicatorTables",

"module",

"SiocExportActivityNextEvent",

"LoGetWindAtPoint",

"LoGetSelfData",

"LoGetWingInfo",

"_G",

"FuelQuantityLServoCalTable",

"gFuelQuantityLSIOCParam",

"VVIServoCalTable",

"gFuelQuantityRSIOCParam",

"list_indication",

"SAIPitchServoCalTable",

"LoSetSharedTexture",

"Simple_radio_1_wheel",

"gSAIPitchSIOCParam",

"SAIPitch",

"gFlapsSIOCParam",

"LoGetWingTargets",

"FuelQuantityRServoCalTable",

"LoGetTargetInformation",

"myIndicators",

"LoGetTWSInfo",

"LoGetVectorWindVelocity",

"SiocExportAfterNextFrame",

"c_argument_in_range",

"Simple_radio_4_wheel",

"Simple_radio_wheel",

"HYDSsysL",

"Simple_radio_Pre",

"SimplePotentiometer",

"LoGetSightingSystemInfo",

"c_cockpit_highlight_visible",

"LoCreateCoroutineActivity",

"SIOC_Parse",

"xpcall",

"LoGetSideDeviation",

"package",

"SimpleRotary",

"_VERSION",

"FuelQuantityR",

"HYDSsysR",

"LoGetGlideDeviation",

"OxyGauge",

"unpack",

"gLastWeaponType",

"LoGetIndicatedAirSpeed",

"require",

"weaponsTypeIndicator",

"LuaExportAfterNextFrame",

"LoGetAltitudeAboveGroundLevel",

"setmetatable",

"next",

"os",

"a_cockpit_param_save_as",

"LoGetLockedTargetInformation",

"rawequal",

"LuaExportStart",

"LoUpdateExternalFlightModel",

"LoGetAltitudeAboveSeaLevel",

"LoGetHeightWithObjects",

"log_G_effect",

"c_cockpit_param_is_equal_to_another",

"getmetatable",

"getfenv",

"a_cockpit_highlight_indication",

"LoGetPlayerPlaneId",

"LoGetTrueAirSpeed",

"pairs",

"LoGetAngleOfAttack",

"rawset",

"LoGetModelTime",

"GetIndicator",

"c_indication_txt_equal_to",

"a_start_listen_event",

"LoGetFMData",

"LoGetPilotName",

"c_stop_wait_for_user",

"c_cockpit_param_equal_to",

"LoGetPayloadInfo",

"LoGetMissionStartTime",

"ResetIndicators",

"LoGetWorldObjects",

"LoGetNameByType",

"a_cockpit_highlight",

"select",

"LoGetRoute",

"dofile",

"rawget",

"TwoPositionSwitch",

"a_start_listen_command",

"LoGetVectorVelocity",

"setfenv",

"newproxy",

"GetDevice",

"error",

"LuaExportStop"

 

 

Someone else has tested it?

Link to comment
Share on other sites

 

 

"tostring",

"gLastGunStatus",

"LoGetObjectById",

"LoGetCameraPosition",

"LoGetMachNumber",

"LoGetRadioBeaconsStatus",

"LoGetControlPanel_HSI",

"list_cockpit_params",

"debug",

"assert",

"tonumber",

"COMExportStart",

"FlapsServoCalTable",

"LoRemoveSharedTexture",

"load",

"socket",

"LoGetF15_TWS_Contacts",

"LoGetVerticalVelocity",

"LoGeoCoordinatesToLoCoordinates",

"coroutine",

"LoGetVersionInfo",

"LoGetRadarAltimeter",

"siocConfig",

"loadstring",

"LoGetMechInfo",

"LoGetAngularVelocity",

"SimpleRadioPre",

"string",

"Servo",

"LoEnableExternalFlightModelSock",

"print",

"a_cockpit_perform_clickable_action",

"a_cockpit_highlight_position",

"COMExportBeforeNextFrame",

"table",

"round",

"_ARCHITECTURE",

"LoGetMCPState",

"ProcessIndicators",

"_ED_VERSION",

"LoSetCameraPosition",

"ipairs",

"LoSetCommand",

"collectgarbage",

"c_cockpit_param_in_range",

"FuelQuantityL",

"c_start_wait_for_user",

"LoGetMagneticYaw",

"LoGetBasicAtmospherePressure",

"math",

"LoGetSnares",

"pcall",

"Flaps",

"type",

"a_cockpit_remove_highlight",

"lfs",

"LoGetHelicopterFMData",

"AmmoCountersAndType",

"LoLoCoordinatesToGeoCoordinates",

"LoEnableExternalFlightModel",

"LoGetAltitude",

"loadfile",

"log",

"gOxyGaugeSIOCParam",

"LoGetAccelerationUnits",

"gcinfo",

"msg",

"COMExportStop",

"gVVISIOCParam",

"LoGetNavigationInfo",

"SiocExportStop",

"ThreePositionSwitch",

"LoGetSlipBallPosition",

"OxyGaugeServoCalTable",

"SiocExportBeforeNextFrame",

"SiocExportStart",

"inputsTable",

"HYDSsysRServoCalTable",

"gHYDSsysRSIOCParam",

"LoGetADIPitchBankYaw",

"LoGetEngineInfo",

"dbg_print",

"io",

"VVI",

"LoUpdateSharedTexture",

"HYDSsysLServoCalTable",

"LoGetAngleOfSideSlip",

"gHYDSsysLSIOCParam",

"gIndicatorTables",

"module",

"SiocExportActivityNextEvent",

"LoGetWindAtPoint",

"LoGetSelfData",

"LoGetWingInfo",

"_G",

"FuelQuantityLServoCalTable",

"gFuelQuantityLSIOCParam",

"VVIServoCalTable",

"gFuelQuantityRSIOCParam",

"list_indication",

"SAIPitchServoCalTable",

"LoSetSharedTexture",

"Simple_radio_1_wheel",

"gSAIPitchSIOCParam",

"SAIPitch",

"gFlapsSIOCParam",

"LoGetWingTargets",

"FuelQuantityRServoCalTable",

"LoGetTargetInformation",

"myIndicators",

"LoGetTWSInfo",

"LoGetVectorWindVelocity",

"SiocExportAfterNextFrame",

"c_argument_in_range",

"Simple_radio_4_wheel",

"Simple_radio_wheel",

"HYDSsysL",

"Simple_radio_Pre",

"SimplePotentiometer",

"LoGetSightingSystemInfo",

"c_cockpit_highlight_visible",

"LoCreateCoroutineActivity",

"SIOC_Parse",

"xpcall",

"LoGetSideDeviation",

"package",

"SimpleRotary",

"_VERSION",

"FuelQuantityR",

"HYDSsysR",

"LoGetGlideDeviation",

"OxyGauge",

"unpack",

"gLastWeaponType",

"LoGetIndicatedAirSpeed",

"require",

"weaponsTypeIndicator",

"LuaExportAfterNextFrame",

"LoGetAltitudeAboveGroundLevel",

"setmetatable",

"next",

"os",

"a_cockpit_param_save_as",

"LoGetLockedTargetInformation",

"rawequal",

"LuaExportStart",

"LoUpdateExternalFlightModel",

"LoGetAltitudeAboveSeaLevel",

"LoGetHeightWithObjects",

"log_G_effect",

"c_cockpit_param_is_equal_to_another",

"getmetatable",

"getfenv",

"a_cockpit_highlight_indication",

"LoGetPlayerPlaneId",

"LoGetTrueAirSpeed",

"pairs",

"LoGetAngleOfAttack",

"rawset",

"LoGetModelTime",

"GetIndicator",

"c_indication_txt_equal_to",

"a_start_listen_event",

"LoGetFMData",

"LoGetPilotName",

"c_stop_wait_for_user",

"c_cockpit_param_equal_to",

"LoGetPayloadInfo",

"LoGetMissionStartTime",

"ResetIndicators",

"LoGetWorldObjects",

"LoGetNameByType",

"a_cockpit_highlight",

"select",

"LoGetRoute",

"dofile",

"rawget",

"TwoPositionSwitch",

"a_start_listen_command",

"LoGetVectorVelocity",

"setfenv",

"newproxy",

"GetDevice",

"error",

"LuaExportStop"

 

 

Someone else has tested it?

 

But it's right there in your list... (emphasis mine)

What exactly did you try that did not work?

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...