package.path = package.path..";.\\LuaSocket\\?.lua;" package.cpath = package.cpath..";.\\LuaSocket\\?.dll;" package.path = package.path..";.\\LuaSocket\\?.lua" package.cpath = package.cpath..";.\\LuaSocket\\?.dll" local MATRIC = {} local mtrxlog = nil MATRIC.ipaddr = "127.0.0.1" MATRIC.port = 50300 MATRIC.PIN = "9087" MATRIC.appName = "MATRIC4DCS" MATRIC.clientId = "llAcjxdT+iYC6tWNRk76R/D3w6X2uoDw5DvApg/NcoE=" MATRIC.updatePeriod = 0.2 local socket = require("socket") MATRIC.conn = socket.udp() MATRIC.conn:settimeout(0) MATRIC.conn:setpeername(MATRIC.ipaddr, MATRIC.port) JSON = loadfile("Scripts\\JSON.lua")() --returns the data structure that MATRIC expects for SETDECK command MATRIC.cmdSETDECK = function() return { command = "SETDECK", appName = MATRIC.appName, appPin = MATRIC.PIN, clientId = MATRIC.clientId, deckId = "", pageId = "" } end --returns the data structure that MATRIC expects for SETACTIVEPAGE command MATRIC.cmdSETACTIVEPAGE = function() return { command = "SETACTIVEPAGE", appName = MATRIC.appName, appPin = MATRIC.PIN, clientId = MATRIC.clientId, pageId = "" } end --returns the data structure that MATRIC expects for SETBUTTONPROPS command MATRIC.cmdSETBUTTONPROPS = function() return { command = "SETBUTTONPROPS", appName = MATRIC.appName, appPin = MATRIC.PIN, clientId = MATRIC.clientId, buttonId = "", data = { imageOff = nil, imageOn = nil, textcolorOn = nil, textcolorOff = nil, backgroundcolorOn = nil, backgroundcolorOff = nil, fontSize = nil, text = nil, halign = nil, valign = nil, padding = nil, } } end --returns the data structure that MATRIC expects for SETBUTTONPROPSEX command MATRIC.cmdSETBUTTONPROPSEX = function() return { command = "SETBUTTONPROPSEX", appName = MATRIC.appName, appPin = MATRIC.PIN, clientId = MATRIC.clientId, data = {} } end ----returns the data structure containing button props we can modify MATRIC.buttonProps = function() return { buttonId = nil, imageOff = nil, imageOn = nil, textcolorOn = nil, textcolorOff = nil, backgroundcolorOn = nil, backgroundcolorOff = nil, fontSize = nil, text = nil, halign = nil, valign = nil, padding = nil, } end --Here we have button Ids of the buttons that we shall control with our script --In the future we might add an option to add a "name" to the button so that we do not need to address them by this horrible mess but instead by names like "ADI_BANK_INDICATOR" or whatever you call your button --Integration API is still in active development local KA50 = { deckId = "813ccc63-0d08-46f8-a500-dc0e8538b77e", initialPageId = "682b6740-fbad-4893-9954-853e0b215421", bBANK = "d81e2ccf-7c07-40f7-b8bc-a36162a0d887", bPITCH = "a847c207-8d77-43f8-9b0e-b703899eccac", bHEADING = "5103f719-4e52-49b7-a333-88abbd872859", bALT = "64c3dc12-0296-4460-b865-6b8d3fe98a77", bFD = "b7f59734-a19c-4fd4-8ada-631c681cda11", bHOVER = "41a6f7b7-2005-4df1-847e-d976d651922b", bMASTERARM = "707eff6b-a188-4eda-a558-a4b4c648c3b7", bLASER = "ee1e7453-cc2d-4b11-a87f-ce0fd655ed29", AutoHoverLightId = 175, MasterArmStatusId = 167, LaserOnId = 435, UV26DisplayId = 7, bTGTSYS = "0076cd7d-1a49-462d-9da7-eb3133b865cf", bUV26Display = "4fdecf9d-c1e8-4711-ae1b-db99f8f7d65b", TargetingSystemOnId = 433 } local _prevExport = {} _prevExport.LuaExportActivityNextEvent = LuaExportActivityNextEvent _prevExport.LuaExportBeforeNextFrame = LuaExportBeforeNextFrame _prevExport.LuaExportStart = LuaExportStart _prevExport.LuaExportStop = LuaExportStop function LuaExportStart() --initialize mtrxlog = io.open(lfs.writedir().."/Logs/matric_connector_log.txt", "w") mtrxlog:write("-- LOG start --") --ToDo: set deck, page local _status,_result = pcall(function() -- Call original function if it exists if _prevExport.LuaExportStart then _prevExport.LuaExportStart() end end) end function LuaExportStop() if mtrxlog then mtrxlog:write("-- LOG end --") mtrxlog:close() mtrxlog = nil end local _status,_result = pcall(function() -- Call original function if it exists if _prevExport.LuaExportStop then _prevExport.LuaExportStop() end end) end LuaExportActivityNextEvent = function(tCurrent) local tNext = tCurrent + MATRIC.updatePeriod if (LoGetSelfData() ~= nil) then if (LoGetSelfData().Name == "Ka-50") then UpdateMATRICKa50() end end -- call original local _status,_result = pcall(function() -- Call original function if it exists if _prevExport.LuaExportActivityNextEvent then _prevExport.LuaExportActivityNextEvent(tCurrent) end end) return tNext end LuaExportBeforeNextFrame = function() -- call original _status,_result = pcall(function() -- Call original function if it exists if _prevExport.LuaExportBeforeNextFrame then _prevExport.LuaExportBeforeNextFrame() end end) end function SendMATRICCommand(data) mtrxlog:write("sending UDP update") mtrxlog:write(JSON:encode_pretty(data)) socket.try(MATRIC.conn:send(JSON:encode_pretty(data))) end function UpdateMATRICKa50() -- Inspect the state of flight director and update matric buttons AP = GetDevice(33) --33 is the autopilot device local autopilotState = { ch_bank = AP:get_channel_status_Bank(), ch_pitch = AP:get_channel_status_Pitch(), ch_heading = AP:get_channel_status_Yaw(), ch_alt = AP:get_channel_status_Height(), ch_fd_off = AP:get_directional_mode() } --Let's define the appearance of ADI buttons local ADI_ON_IMAGE = "edd50bfc-43ca-40bd-bc97-643bad2fa44c.png" local ADI_OFF_IMAGE = "fdb88a80-6695-4280-a51e-321c0641d477.png" local ADI_TEXT_COL_ON = "white" local ADI_TEXT_COL_OFF = "#999999" local HOVER_INDICATOR_ON = "green_down.png" local HOVER_INDICATOR_OFF = "green_up.png" local MASTER_ARM_ON = "arm_on.png" local MASTER_ARM_OFF = "arm_off.png" local LASER_ON = "red_down.png" local LASER_OFF = "red_up.png" local TGT_ON = "green_sc_down.png" local TGT_OFF = "green_sc_up.png" local cmd = MATRIC:cmdSETBUTTONPROPSEX() cmd.data[1] = MATRIC.buttonProps() --bank ADI channel cmd.data[1].buttonId = KA50.bBANK if (autopilotState.ch_bank == 1) then cmd.data[1].imageOff = ADI_ON_IMAGE cmd.data[1].textcolorOff = ADI_TEXT_COL_ON else cmd.data[1].imageOff = ADI_OFF_IMAGE cmd.data[1].textcolorOff = ADI_TEXT_COL_OFF end --pitch ADI channel cmd.data[2] = MATRIC.buttonProps() cmd.data[2].buttonId = KA50.bPITCH if (autopilotState.ch_pitch == 1) then cmd.data[2].imageOff = ADI_ON_IMAGE cmd.data[2].textcolorOff = ADI_TEXT_COL_ON else cmd.data[2].imageOff = ADI_OFF_IMAGE cmd.data[2].textcolorOff = ADI_TEXT_COL_OFF end --heading ADI channel cmd.data[3] = MATRIC.buttonProps() cmd.data[3].buttonId = KA50.bHEADING if (autopilotState.ch_heading == 1) then cmd.data[3].imageOff = ADI_ON_IMAGE cmd.data[3].textcolorOff = ADI_TEXT_COL_ON else cmd.data[3].imageOff = ADI_OFF_IMAGE cmd.data[3].textcolorOff = ADI_TEXT_COL_OFF end --alt ADI channel cmd.data[4] = MATRIC.buttonProps() cmd.data[4].buttonId = KA50.bALT if (autopilotState.ch_alt == 1) then cmd.data[4].imageOff = ADI_ON_IMAGE cmd.data[4].textcolorOff = ADI_TEXT_COL_ON else cmd.data[4].imageOff = ADI_OFF_IMAGE cmd.data[4].textcolorOff = ADI_TEXT_COL_OFF end --ADI mode cmd.data[5] = MATRIC.buttonProps() cmd.data[5].buttonId = KA50.bFD if (autopilotState.ch_fd_off == false) then cmd.data[5].imageOff = ADI_ON_IMAGE cmd.data[5].textcolorOff = ADI_TEXT_COL_ON else cmd.data[5].imageOff = ADI_OFF_IMAGE cmd.data[5].textcolorOff = ADI_TEXT_COL_OFF end --Hover indicator local mainPanel = GetDevice(0) cmd.data[6] = MATRIC.buttonProps() cmd.data[6].buttonId = KA50.bHOVER if (mainPanel:get_argument_value(KA50.AutoHoverLightId) == 1) then cmd.data[6].imageOff = HOVER_INDICATOR_ON cmd.data[6].textcolorOff = ADI_TEXT_COL_ON else cmd.data[6].imageOff = HOVER_INDICATOR_OFF cmd.data[6].textcolorOff = ADI_TEXT_COL_OFF end --Master arm cmd.data[7] = MATRIC.buttonProps() cmd.data[7].buttonId = KA50.bMASTERARM if (mainPanel:get_argument_value(KA50.MasterArmStatusId) == 1) then cmd.data[7].imageOff = MASTER_ARM_ON cmd.data[7].textcolorOff = "black" else cmd.data[7].imageOff = MASTER_ARM_OFF cmd.data[7].textcolorOff = ADI_TEXT_COL_OFF end --Laser cmd.data[8] = MATRIC.buttonProps() cmd.data[8].buttonId = KA50.bLASER if (mainPanel:get_argument_value(KA50.LaserOnId) == 1) then cmd.data[8].imageOff = LASER_ON cmd.data[8].textcolorOff = "black" else cmd.data[8].imageOff = LASER_OFF cmd.data[8].textcolorOff = ADI_TEXT_COL_OFF end --Targeting system cmd.data[9] = MATRIC.buttonProps() cmd.data[9].buttonId = KA50.bTGTSYS --mtrxlog:write(mainPanel:get_argument_value(KA50.TargetingSystemOnId)) if (mainPanel:get_argument_value(KA50.TargetingSystemOnId) == 1) then cmd.data[9].imageOff = TGT_ON else cmd.data[9].imageOff = TGT_OFF end --UV-26 display cmd.data[10] = MATRIC.buttonProps() cmd.data[10].buttonId = KA50.bUV26Display if (_getListIndicatorValue(KA50.UV26DisplayId) ~= nil) then local uv26text = _getListIndicatorValue(KA50.UV26DisplayId).txt_digits cmd.data[10].text = uv26text end --mtrxlog:write(JSON:encode_pretty(uv26)) SendMATRICCommand(cmd) --mtrxlog:write(JSON:encode_pretty(LoGetSelfData())) --mtrxlog:write( JSON:encode_pretty(autopilotState)) end function _getListIndicatorValue(IndicatorID) local ListIindicator = list_indication(IndicatorID) local TmpReturn = {} if ListIindicator == "" then return nil end local ListindicatorMatch = ListIindicator:gmatch("-----------------------------------------\n([^\n]+)\n([^\n]*)\n") while true do local Key, Value = ListindicatorMatch() if not Key then break end TmpReturn[Key] = Value end return TmpReturn end