shorthauler Posted September 18, 2023 Report Posted September 18, 2023 Hi folks, I am trying to extract numbers from a string. The string corresponds to the full FCU message, for example SPD240 or MACH 0,78. Let's call the offset where the string can be found 0xABCD. The result shall be written to offset 066C1. As the MACH number is not an integer, I think I should be working with floats. As SPD and MACH have different lengths, I cannot extract from specific positions of the string. spdstate = ipc.readSTR(0xABCD) local speed = string.match(spdstate, "%d+") ipc.writeFLT(0x66C1, speed) end I would like to show the resulting value in a window in FSX, I think I shoud use U32 as a type for logging. But I only receive a 0. Any input is much appreciated. I am reluctant to use the tonumber function as I am afraid I will mess up. Best regards -shorthauler
John Dowson Posted September 19, 2023 Report Posted September 19, 2023 string.match will return a string, not a number, so you need to convert the results to a number (using tonumber). Also, the match will stop after the first non-digit character is found (after a digit), so "Mach 0,78" will return 0 (due to the comma). If you want to extract decimals, see https://stackoverflow.com/questions/38140434/lua-how-to-retrieve-a-decimal-number-from-string. Otherwise, maybe take a look here: https://stackoverflow.com/questions/46794989/extracting-number-from-string-using-lua But it would be better to just read the offsets holding the values you want to extract. For example, if its the mach speed, that will be in offset 0x11C6 (or 0x35A0 or maybe 0x07E8 for AP mach value).
shorthauler Posted September 20, 2023 Author Report Posted September 20, 2023 Thsnk you for directing me to these links. This now works: spdstate = ipc.readSTR(0xABCD, 9) speed = string.match(spdstate, "%d+") ipc.writeSW(0x66C1, speed) It was essential to define the lenght of the string (the ", 9" in the first line). Best regards, -shorthauler
John Dowson Posted September 21, 2023 Report Posted September 21, 2023 11 hours ago, shorthauler said: It was essential to define the lenght of the string (the ", 9" in the first line). Yes, sorry, missed that... 11 hours ago, shorthauler said: This now works: spdstate = ipc.readSTR(0xABCD, 9) speed = string.match(spdstate, "%d+") ipc.writeSW(0x66C1, speed) That surprises me though, for the reasons previously mentioned...
shorthauler Posted September 21, 2023 Author Report Posted September 21, 2023 Yes, I was also surprised, but it only works in SPD mode, not in MACH. SPD is an integer, MACH a rational number < 1. For MACH I only get a zero. This may be the zero in front of the decimal, and the value after the decimal is cut off. I have tried to make use of the tonumber function - did I do this correctly? For the value after the decimal, I tried this "[%d.,]". But it does not do the trick. I have used "ipc.writeSW" (signed word value). -- dashes C2, dot C3 spdstate = ipc.readSTR(0xABCD, 9) if (string.find(spdstate, "---") and string.find(spdstate, "*")) then ipc.writeUB(0x66C2,1) ipc.writeUB(0x66C3,1) elseif (string.find(spdstate, "---") and not string.find(spdstate, "*")) then ipc.writeUB(0x66C2,1) ipc.writeUB(0x66C3,0) elseif (string.find(spdstate, "*") and not string.find(spdstate, "---")) then ipc.writeUB(0x66C2,0) ipc.writeUB(0x66C3,1) else ipc.writeUB(0x66C2,0) ipc.writeUB(0x66C3,0) end speed_str = string.match(spdstate, "%d%d[%d.,]") -- speed as string speed =tonumber(speed_str) -- converting speed from string to number ipc.writeSW(0x66C1, speed)
John Dowson Posted September 21, 2023 Report Posted September 21, 2023 1 hour ago, shorthauler said: MACH a rational number < 1. For MACH I only get a zero. This is because it contains a comma not a full stop - MACH 0,78 not MACH 0.78 - or was that a typo? If it is a comma, you could try replacing that with a full stop first.... And as with your other post, try adding some logging statements to determine what is happening.... John
shorthauler Posted September 21, 2023 Author Report Posted September 21, 2023 The Mach number in the string is seperated with a full stop, not with a comma. - shorthauler
John Dowson Posted September 22, 2023 Report Posted September 22, 2023 See the following: Quote function getnumbersfromtext(txt) local str = "" string.gsub(txt,"([%d.]+)",function(e) str = str .. e end) return tonumber(str); end n = getnumbersfromtext("SPD240") ipc.log("SPD240: " .. n) n = getnumbersfromtext("MACH 0.78") ipc.log("MACH 0.78: " .. n) n = getnumbersfromtext("MACH 1.78") ipc.log("MACH 1.78: " .. n) Output: 1734078 LUA.15: SPD240: 240 1734094 LUA.15: MACH 0.78: 0.78 1734110 LUA.15: MACH 1.78: 1.78
shorthauler Posted September 22, 2023 Author Report Posted September 22, 2023 Thank you, so adapted to my variables, this would look like this? spdstate = ipc.readSTR(0xABCD, 9) function getnumbersfromtext(spdstate) local str = "" string.gsub(txt,"([%d.]+)",function(e) str = str .. e end) return tonumber(str); end speed = getnumbersfromtext ipc.writeSW(0x66C1, speed)
John Dowson Posted September 22, 2023 Report Posted September 22, 2023 55 minutes ago, shorthauler said: speed = getnumbersfromtext Should be: speed = getnumbersfromtext(spdstate) You have to pass the text into the function... And you would normally define your functions at the top of the script.
shorthauler Posted September 24, 2023 Author Report Posted September 24, 2023 I think I may have the correct code now: spdstate = ipc.readSTR(0xABCD, 9) function getnumbersfromtext(spdstate) return tonumber(spdstate:match"%d+[%d.,]*") end speed = getnumbersfromtext(spdstate) -- everything works until here, I get a correct Mach number such as 0.59 ipc.writeFLT(0x66C1, speed) -- I get 0.590000000000... as an output value that I read via the logging window or in Mobiflight As per the log below, I am getting the correct results for "speed". But how do I write them best to the offset? If I use "writeFLT" for writing and "FLT32" for monitoring, I get a number with a seemingly infinite number of zeroes after the Mach value. I only need the two digits after the decimal, just like in the log. Am I using the wrong format to write to the offset? Best regards, - shorthauler ********* LUA: "A320 SPD split" Log [from FSUIPC version 4.977] ********* 529704 System time = 24/09/2023 09:09:22, Simulator time = 13:20:07 (12:20Z) 529704 LUA: beginning "E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua" 529719 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:1 529719 LUA: Global: ipcPARAM = 0 529719 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:11 529719 LUA: Global: spdstate = MACH 0.56 529719 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:3 529735 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:13 529735 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:6 fn: getnumbersfromtext 529735 LUA: Local: spdstate = MACH 0.56 529735 LUA: E:\FSX\Flight Simulator X\Modules\A320 SPD split.lua:14 529735 LUA: Global: speed = 0.56 529766 >>> Thread forced exit (ipc.exit or os.exit) <<< 529766 System time = 24/09/2023 09:09:22, Simulator time = 13:20:09 (12:20Z) ********* LUA execution terminated: Log Closed *********
shorthauler Posted September 24, 2023 Author Report Posted September 24, 2023 Update: I was able to solve this with the "transform" function in Mobiflight using "Round($*100, 0)". "Truncate" did not work for some reason, but "Round" did the trick. I will now do a few flights to see if everything really works and then report back.
John Dowson Posted September 24, 2023 Report Posted September 24, 2023 1 hour ago, shorthauler said: ipc.writeFLT(0x66C1, speed) -- I get 0.590000000000... as an output value that I read via the logging window or in Mobiflight But you should not do his... a float is 4 bytes/32-bits, and so you should write on a 4-byte boundary. This will also overwrite offsets 66C2, CC63 & 66C4 1 hour ago, shorthauler said: If I use "writeFLT" for writing and "FLT32" for monitoring, I get a number with a seemingly infinite number of zeroes after the Mach value. This is how floating point numbers work - they are not exact. If you only want to store to 2 decimal places, store the value * 100 as an int, and just remember to divide by 100 when you read it. The size of the offset that you need to store the number depends on the range - you can use 2-bytes if its always between -32,768 to 32,767 (signed) or 0-65,535 (signed), and 4-bytes for the full int range (-2,147,483,648 to 2,147,483,647 signed, 0 to 4,294,967,295 unsigned). And 1-byte if its between 0-255 (unsigned) or -128 - + 127 (signed). Remember to always read the same size as writing, don't overlap your offsets (i.e. make sure you leave enough space for the offset to hold the data before assigning the next offset value), and respect offset boundaries depending on the size of the data the offset holds (as I explained in the other post!). John
shorthauler Posted September 24, 2023 Author Report Posted September 24, 2023 Thanks a lot, *100 and then /100 in MobiFlight works great! I am using free offset 66C1 for the speed and it occupies 66C2 as well, but not 66C3 and beyond. For "speed100" I am logging U16 in the simulator and a 2 byte integer in MobiFlight. This is the final script. It works well. There is, however, a noticeable delay between the digit changes in the simulator and the digit changes in my FCU. I am using "repeat ... until condition" to have the script constantly run over the string and check for changes. Maybe this can be done more efficiently. - shorthauler repeat spdstate = ipc.readSTR(0xABCD, 9) function getnumbersfromtext(spdstate) return tonumber(spdstate:match"%d+[%d.,]*") end if (string.find(spdstate, "%-") and string.find(spdstate, "%*")) then ipc.writeUB(0x66C5,1) ipc.writeUB(0x66C6,1) elseif string.find(spdstate, "%-") then ipc.writeUB(0x66C5,1) ipc.writeUB(0x66C6,0) elseif string.find(spdstate, "%*") then ipc.writeUB(0x66C5,0) ipc.writeUB(0x66C6,1) else ipc.writeUB(0x66C5,0) ipc.writeUB(0x66C6,0) end if string.find(spdstate, "SPD") then ipc.writeUB(0x66C7,1) else ipc.writeUB(0x66C7,0) end if string.find(spdstate, "MACH") then ipc.writeUB(0x66C8,1) else ipc.writeUB(0x66C8,0) end if string.find(spdstate, "%-") then ipc.writeSW(0x66C1, 0) -- speed hast to be forced to 0, when the dashes appear in managed mode, otherwise there will be interferences with the dashes else speed = getnumbersfromtext(spdstate) speed100 = speed*100 ipc.writeUW(0x66C1, speed100) -- logging "speed100" with U16 in the simulator and a 2 byte integer in MobiFlight end until condition
John Dowson Posted September 25, 2023 Report Posted September 25, 2023 14 hours ago, shorthauler said: I am using free offset 66C1 for the speed and it occupies 66C2 as well, but not 66C3 and beyond. For "speed100" I am logging U16 in the simulator and a 2 byte integer in MobiFlight. But, as I keep saying, ypu shouldn't do this.... If you are storing a number in an offset as a 2-byte word, you should store it starting on a 2-byte offset, e.g. at 66C0 or 66C2. It way seem to work, but you can get problems if you don't do this, depending on how the offset is accessed... 14 hours ago, shorthauler said: I am using "repeat ... until condition" to have the script constantly run over the string and check for changes. Maybe this can be done more efficiently. Rather than have it run in an endless loop, you can use the event.offset function, using offset 0xABCD, so that you update each time that offset changes value - this would be more efficient.
shorthauler Posted September 25, 2023 Author Report Posted September 25, 2023 Thank you, I was not aware of this. I replaced offset 66C1 by 66C0. The values stored in 66C0 still "leak" into 66C1. I am not sure how I should apply "event.offset" to 0xABCD here. I made a line event.offset (0x54C4, "STR", 9, "getnumbersfromtext") and put it in front of everything else as first line. But this does not work. If the format is event.offset(offset, "STR", length, "function-name") what should I use as function name? Best - shorthauler
John Dowson Posted September 26, 2023 Report Posted September 26, 2023 11 hours ago, shorthauler said: The values stored in 66C0 still "leak" into 66C1. No they don't, as I have explained several times. Offsets will be written starting from the offset specified and to the number of offsets required by the type and size of the data you are writing, and when you read from an offset it will read that offset and the consecutive ones up to the size if the data type you are reading. Everything works as it should, and nothing "leaks". You just need to understand how memory addresses work. 11 hours ago, shorthauler said: I made a line event.offset (0x54C4, "STR", 9, "getnumbersfromtext") and put it in front of everything else as first line. But this does not work. Of course not, as that would just call the getnumbersfromtext function each time the offset changed - that is obviously not what you want.... 11 hours ago, shorthauler said: If the format is event.offset(offset, "STR", length, "function-name") what should I use as function name? Whatever you like - you have to wrap your script in a function, e.g. based upon the last script you posted function getnumbersfromtext(spdstate) return tonumber(spdstate:match"%d+[%d.,]*") end funcyion decodeString(offset, spdstate) if (string.find(spdstate, "%-") and string.find(spdstate, "%*")) then ipc.writeUB(0x66C5,1) ipc.writeUB(0x66C6,1) elseif string.find(spdstate, "%-") then ipc.writeUB(0x66C5,1) ipc.writeUB(0x66C6,0) elseif string.find(spdstate, "%*") then ipc.writeUB(0x66C5,0) ipc.writeUB(0x66C6,1) else ipc.writeUB(0x66C5,0) ipc.writeUB(0x66C6,0) end if string.find(spdstate, "SPD") then ipc.writeUB(0x66C7,1) else ipc.writeUB(0x66C7,0) end if string.find(spdstate, "MACH") then ipc.writeUB(0x66C8,1) else ipc.writeUB(0x66C8,0) end if string.find(spdstate, "%-") then ipc.writeSW(0x66C1, 0) -- speed hast to be forced to 0, when the dashes appear in managed mode, otherwise there will be interferences with the dashes else speed = getnumbersfromtext(spdstate) speed100 = speed*100 ipc.writeUW(0x66C1, speed100) -- logging "speed100" with U16 in the simulator and a 2 byte integer in MobiFlight end end -- of function decodeString event.offset (0xABCD, "STR", 9, "decodeString") If you are planning to use lua, you should look at some on-line lua tutorials. Also take a look at the example lua scripts provided, which are located in your FSUIPC documents folders. There are also plenty of examples in these forums. John
shorthauler Posted September 26, 2023 Author Report Posted September 26, 2023 Thank you, now everything works. I am consulting lua fora, but I was under the impression that event.offset was specific to FSUIPC. I misread the lua library document - the term offset is not between quotation marks, so it should indeed be written offset. I wrote the actual offset, silly me. Thank you so much again -shorthauler
John Dowson Posted September 27, 2023 Report Posted September 27, 2023 11 hours ago, shorthauler said: I was under the impression that event.offset was specific to FSUIPC. Yes it is - everything in the FSUIPC lua library document is specific to FSUIPC. - it is the FSUIPC lua library after all!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now