Errors when using library files

Help creating logic scripts for Air Manager Instruments

Moderators: Ralph, russ

Post Reply
Message
Author
floatingcub
Posts: 10
Joined: Fri Apr 03, 2020 4:09 am

Errors when using library files

#1 Post by floatingcub » Thu Apr 01, 2021 11:33 pm

Hello,

Hoping someone can help unlock a mystery for me.

I've got an annunciator instrument I built which 100% works as expected. In an effort to better organize it, and in preparation to transition to LEDs instead of images, I split related functions out of the main script and created library files. For instance, there are functions specific to alerts for the engine/fuel system; they have all been moved to the engine.lua script.

My mystery revolves around when functions in the library scripts are executed, and how they utilize global variables. Prior to initializing a library file, I fill a variable called plane, which holds various reference data. When I run the instrument, I'm getting errors (attempt to index a nil value, attempt to compare number with nil). The location of the errors are where the library scripts refer to the plane variable. I am also getting errors when I try to reference an image variable that I set prior to initializing the library file. In this latter case, I tried moving the _init statements to the end of the function that loads images, but I still get the error.

Key parts of the logic.lua script:
  1. -- Define dimensions and location of each light area
  2.  
  3. dx =
  4.  
  5. {5,5,5,5,5,5,5,136,136,136,136,136,136,136,270,270,270,270,270,270,270,400,400,400,400,400,400,400,530,530,530,530,530,530,530,660,660,660,660,660,660,660,790,790,790,790,790,790,790}
  6.  
  7. dy = {14,74,141,207,274,339,405,14,74,141,207,274,339,405,14,74,141,207,274,339,405,14,74,141,207,274,339,405,14,74,141,207,274,339,405,14,74,141,207,274,339,405}
  8.  
  9. dw = {132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132}
  10.  
  11. dh = {67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67}
  12.  
  13.  
  14.  
  15. aircraft = {
  16.  
  17.     ["M20T"] = {
  18.  
  19.         ["vac_press"]  = {4.3, 5.2},
  20.  
  21.         ["fuel_press"] = {25, 550},
  22.  
  23.         ["oil_press"]  = {3400, 550},
  24.  
  25.         ["throttle"]   = 10,
  26.  
  27.         ["flap"]       = 55,
  28.  
  29.         ["alerts"]     = {1,2,3,5,6,7,10,11,12,13,14,15,16,17,19,21,24,26,27,28,29,30,31,34,35,38,40,41,42},
  30.  
  31.         ["retract"]    = true,
  32.  
  33.     }
  34.  
  35.     -- other aircraft omitted for brevity
  36.  
  37. }
  38.  
  39.  
  40.  
  41. -- To facilitate value access, prepare a variable that will be filled with the appropriate aircraft values
  42.  
  43. plane = {}
  44.  
  45.  
  46.  
  47. function load_images()
  48.  
  49.     -- Load the lights, but keep them off
  50.  
  51.  
  52.  
  53.     if plane.engines == 1 then
  54.  
  55.         img_anun_off = img_add("exp_annun_single_off.png", 0, 0, 800, 480, "stretch")
  56.  
  57.     else
  58.  
  59.         img_anun_off = img_add("exp_annun_multi_off.png", 0, 0, 800, 480, "stretch")
  60.  
  61.     end
  62.  
  63.     img_lit = {}
  64.  
  65.     img_dis = {}
  66.  
  67.  
  68.  
  69.     -- Prepare the lighted alerts
  70.  
  71.     for i = 1, 42 do
  72.  
  73.         if plane.engines == 1 then
  74.  
  75.             img_lit[i] = img_add("exp_annun_single.png", 0, 0, 800, 480)
  76.  
  77.         else
  78.  
  79.             img_lit[i] = img_add("exp_annun_multi.png", 0, 0, 800, 480)
  80.  
  81.         end
  82.  
  83.         viewport_rect(img_lit[i], dx[i], dy[i], dw[i], dh[i])
  84.  
  85.         visible(img_lit[i], false)
  86.  
  87.  
  88.  
  89.         -- Load the blocking image for alerts that don't apply to the aircraft
  90.  
  91.         if not has_value(i) then
  92.  
  93.             img_dis[i] = img_add("exp_annun_disabled.png", 0, 0, 800, 480)
  94.  
  95.             viewport_rect(img_dis[i], dx[i], dy[i], dw[i], dh[i])
  96.  
  97.             visible(img_dis[i], true)
  98.  
  99.         end
  100.  
  101.     end
  102.  
  103. end
  104.  
  105.  
  106.  
  107. function has_value(value)
  108.  
  109.     -- Facilitates loading of working vs. disabled annunciator alert images
  110.  
  111.     for i, val in ipairs(plane.alerts) do
  112.  
  113.         if val == value then
  114.  
  115.             return true
  116.  
  117.         end
  118.  
  119.     end
  120.  
  121.     return false
  122.  
  123. end
  124.  
  125.  
  126.  
  127. function set_aircraft(atc_model, engines, type, center_cap)
  128.  
  129.  
  130.  
  131.     model = atc_model
  132.  
  133.     plane = aircraft[model]
  134.  
  135.  
  136.  
  137.     if plane == nil then
  138.  
  139.         plane = aircraft["Undefined"]
  140.  
  141.     end
  142.  
  143.     if type == 0 then
  144.  
  145.         plane.type = "piston"
  146.  
  147.     elseif type == 1 then
  148.  
  149.         plane.type = "jet"
  150.  
  151.     elseif type == 5 then
  152.  
  153.         plane.type = "turboprop"
  154.  
  155.     else
  156.  
  157.         plane.type = "unsupported"
  158.  
  159.     end
  160.  
  161.     plane.engines = math.floor(engines)
  162.  
  163.     plane.c_fuel_cap = center_cap
  164.  
  165.  
  166.  
  167.     -- Prepare display
  168.  
  169.     load_images()
  170.  
  171.     -- Initialize all systems
  172.  
  173.     electric_init()
  174.  
  175.     engine_init()
  176.  
  177.     switch_init()
  178.  
  179.     mechanical_init()
  180.  
  181.     gear_init()
  182.  
  183.     light_init()
  184.  
  185. end
  186.  
  187.  
  188.  
  189. fsx_variable_subscribe("ATC MODEL", "String",
  190.  
  191.                     "NUMBER OF ENGINES", "Number",
  192.  
  193.                     "ENGINE TYPE", "Enum",
  194.  
  195.                     "FUEL TANK CENTER CAPACITY", "Gallons", set_aircraft)
Key parts of engine.lua:
  1. function engine_init()
  2.  
  3. end
  4.  
  5.  
  6.  
  7. function engine_liteup(fuelpress, oilpress, fuel_level, suction, feathered, autofeather, fire, xfeed)
  8.  
  9.     visible(img_lit[1], fuelpress[1] == 1 or fuelpress[1] == nil)
  10.  
  11.     visible(img_lit[2], oilpress[1] == 1 or oilpress[1] == nil)
  12.  
  13.     visible(img_lit[4], fire == 1)
  14.  
  15.     visible(img_lit[8], fuelpress[2] == 1 or fuelpress[2] == nil)
  16.  
  17.     visible(img_lit[9], oilpress[2] == 1 or oilpress[2] == nil)
  18.  
  19.     visible(img_lit[10], suction == 1)
  20.  
  21.     visible(img_lit[15], fuel_level[1] == 1)
  22.  
  23.     visible(img_lit[22], fuel_level[2] == 1)
  24.  
  25.     visible(img_lit[18], autofeather == 1)
  26.  
  27.     visible(img_lit[29], fuel_level[3] == 1)
  28.  
  29.     visible(img_lit[32], feathered[1] == 1)
  30.  
  31.     visible(img_lit[36], xfeed == 1)
  32.  
  33.     visible(img_lit[39], feathered[2] == 1)
  34.  
  35. end
  36.  
  37.  
  38.  
  39. function fuel_oil_pressure(type, pressure1, pressure2, rpm1, rpm2)
  40.  
  41. -- omitted for brevity
  42.  
  43. end
  44.  
  45.  
  46.  
  47. function annunciate_engine(fuelpress1, fuelpress2, oilpress1, oilpress2,
  48.  
  49.     prop_rpm1, prop_rpm2, n1_rpm1, n1_rpm2,
  50.  
  51.     c_percent, l_percent, r_percent,
  52.  
  53.     fire1, fire2, xfeed, fuel_flow,
  54.  
  55.     suction, feather1, feather2, autofeather1, autofeather2)
  56.  
  57.  
  58.  
  59.     if plane.type == "piston" or plane.type == "turboprop" then
  60.  
  61.         rpm1 = prop_rpm1
  62.  
  63.         rpm2 = prop_rpm2
  64.  
  65.     elseif plane.type == "jet" then
  66.  
  67.         rpm1 = n1_rpm1
  68.  
  69.         rpm2 = n1_rpm2
  70.  
  71.     end
  72.  
  73.      
  74.  
  75.     -- Fuel Pressure
  76.  
  77.     fuelpress = fuel_oil_pressure("fuel", fuelpress1, fuelpress2, rpm1, rpm2)
  78.  
  79.  
  80.  
  81.     -- Oil Pressure
  82.  
  83.     oilpress = fuel_oil_pressure("oil", oilpress1, oilpress2, rpm1, rpm2)
  84.  
  85.  
  86.  
  87.     -- Fuel Quantity
  88.  
  89.     -- Alarm at <10%
  90.  
  91.     fuel_level = {0, 0, 0}
  92.  
  93.     fuel_level[1] = fif(l_percent < 10, 1, 0)
  94.  
  95.     fuel_level[3] = fif(r_percent < 10, 1, 0)
  96.  
  97.     if plane.c_fuel_cap > 0 then
  98.  
  99.         fuel_level[2] = fif(c_percent < 10, 1, 0)
  100.  
  101.     end
  102.  
  103.  
  104.  
  105. -- filling other variables here, omitted for brevity --
  106.  
  107. --[...]
  108.  
  109. -- using the variables next --
  110.  
  111.     if power() and startup == false then engine_liteup(fuelpress, oilpress, fuel_level, suction, {pitch1, pitch2}, autofeather, fire, xfeed) end
  112.  
  113. end
  114.  
  115.  
  116.  
  117. fsx_variable_subscribe(
  118.  
  119.     "GENERAL ENG FUEL PRESSURE:1", "Psi",
  120.  
  121.     "GENERAL ENG FUEL PRESSURE:2", "Psi",
  122.  
  123.     "GENERAL ENG OIL PRESSURE:1", "Psf",
  124.  
  125.     "GENERAL ENG OIL PRESSURE:2", "Psf",
  126.  
  127.     "PROP RPM:1", "Rpm",
  128.  
  129.     "PROP RPM:2", "Rpm",
  130.  
  131.     "ENG N1 RPM:1", "Rpm",
  132.  
  133.     "ENG N1 RPM:2", "Rpm",
  134.  
  135.     "FUEL TANK CENTER LEVEL", "Percent",
  136.  
  137.     "FUEL TANK LEFT MAIN LEVEL", "Percent",
  138.  
  139.     "FUEL TANK RIGHT MAIN LEVEL", "Percent",
  140.  
  141.     "ENGINE ON FIRE:1", "Bool",
  142.  
  143.     "ENGINE ON FIRE:2", "Bool",
  144.  
  145.     "FUEL CROSS FEED", "Enum",
  146.  
  147.     "RECIP ENG FUEL TANK SELECTOR:1", "Enum",
  148.  
  149.     "SUCTION PRESSURE", "inHg",
  150.  
  151.     "PROP BETA:1", "Radians",
  152.  
  153.     "PROP BETA:2", "Radians",
  154.  
  155.     "PROP AUTO FEATHER ARMED:1", "Bool",
  156.  
  157.     "PROP AUTO FEATHER ARMED:2", "Bool",
  158.  
  159.     annunciate_engine
  160.  
  161. )
I simply don't understand why Air Manager is executing a function inside a script that I have not yet initialized (if that is what is happening), or why variables which are set before initialization don't appear to be visible.

Any guidance here would be appreciated.

-Bryan

floatingcub
Posts: 10
Joined: Fri Apr 03, 2020 4:09 am

Re: Errors when using library files

#2 Post by floatingcub » Thu Apr 01, 2021 11:59 pm

Nevermind, I just found this on the wiki (http://siminnovations.com/wiki/index.ph ... _libraries):
When the instrument is started, your library lua files will be executed first, followed by the logic.lua.
Given this, I will have to think hard about how the use of libraries is beneficial or even possible in this case, since I can't access variables in any consistent, desirable way. Or maybe there is just something that I'm missing here.

-Bryan

User avatar
Sling
Posts: 4419
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Errors when using library files

#3 Post by Sling » Fri Apr 02, 2021 12:05 am

Hi Bryan,

It’s not a mystery I can assure. Let me explain.

First some facts to take into account.

The library file run order is random.
The logic.lua file will always be run last. i.e. always after the library files.
This is stated on the libraries wiki page.

So with this information in mind and looking at your code we can see that the lib file runs first and the subscribe callback triggers. The callback references variables that are not yet declared because you declare them in the logic.lua. This is why they are nil. There are a few ways to solve this but in my experience it’s always best to hold off doing your subscribes until last when working with more complex instruments that use lib files. The subscribes can stay in lib files but wrap them in a function and call it once at the end of logic.lua. A tiny change to your code.

I hope that helps. Let us know how you go.

Tony

User avatar
Sling
Posts: 4419
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Errors when using library files

#4 Post by Sling » Fri Apr 02, 2021 12:06 am

Oops looks like we cross posted. I see you found the wiki info. Read my other post for an easy solution.

floatingcub
Posts: 10
Joined: Fri Apr 03, 2020 4:09 am

Re: Errors when using library files

#5 Post by floatingcub » Fri Apr 02, 2021 12:41 am

Thanks Tony. A quick change, as you suggested, and I see that it works now.

On a related note, what is the trick to posting code here so the interpreter doesn't add a space between each line? In my initial post I chose LUA from the 'Select code' dropdown in the editor.

-Bryan

User avatar
Sling
Posts: 4419
Joined: Mon Sep 11, 2017 2:37 pm
Contact:

Re: Errors when using library files

#6 Post by Sling » Fri Apr 02, 2021 3:15 am

Glad you got it going and learnt something to boot.

I think the code posting method you used tends to do that unfortunately. I tend not to use it, but the alternative. Don't use the 'select code' drop down but instead hit the </> button and paste your code between the inserted tags.

It looks like this.

Code: Select all

--code line 1
--code line 2
--code line 3

floatingcub
Posts: 10
Joined: Fri Apr 03, 2020 4:09 am

Re: Errors when using library files

#7 Post by floatingcub » Fri Apr 02, 2021 4:31 am

Code: Select all

Perfect, thanks!
;)

-Bryan

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests