Using DataStore to save aircraft state

Hi All

I just happened across a post on MFSF SDK platform/forum (linked below) about local storage; specifically about DataStore. Looking at the WT NXi code they have a set of code which sets and gets variables sent into the DataStore and it got me thinking about whether we may be able to use the DataStore to save aircraft persistence?

Is there anyone in the forum who is able to shed some light on best practice / or whether this is possible? @evanburnsdev @Dakfly0219 Did I see you guys adding something similar into the F22?

1 Like

If you’re referring to javascript/html gauges then you should take a look at /JS/dataStorage.js. You can use the GetStoredData(_key) and SetStoredData(_key, _data) functions to read and write persistent variables. It essentially writes the variables to a database that is saved to the aircraft’s working directory.

WebAssembly has the ability to directly save/read files to the working directory and is outlined in the sdk documentation Here. You can use the fstream library to read and write the files.

1 Like

@evanburnsdev thanks so much for your reply.

Do you know where /JS/dataStorage.js lives in the file structure? I can’t find it in the official folder anywhere.

I’d love to use this to record the fuel tank levels and switches on our G36 Improvement Project in between flights; a little steep learning curve for me.

For Steam:
C:\Program Files (x86)\SteamLibrary\steamapps\common\MicrosoftFlightSimulator\Packages\fs-base-ui\html_ui\JS

For Windows Store:
It’s in your WindowsApps directory. You’ll need to change the directory ownership to gain access to it. Make sure you know what you’re doing before you attempt it.
C:\Program Files\WindowsApps\Microsoft.FlightSimulator_1.19.9.0_x64__8wekyb3d8bbwe\Packages\fs-base-ui\html_ui\JS

1 Like

Awesome thank you!

Ok, for anyone following my convoluted brain


This is where I am in making aircraft save their states:

I believe I can use DataStore.js to create L:Vars which I can save in between sessions? If that’s the case I can then read SimVars for switches, tank levels etc. and write them to my custom variables and read back on aircraft loading :question:

So as I understand so far, to use the DataStore.js I need to use this in a glass cockpit gauge. The only gauges available in the G36 are the NXi.

I have added the following folder structure to the G36 Improvement Project

image

In AS1000_PFD.html I have the following code (this loads the NXi PFD and then my own on top?

Code:

<script type="text/html" import-script="/Pages/VCockpit/Instruments/NavSystems/WTG1000/PFD/WTG1000_PFD.html"></script>
<script type="text/html" import-script="/Pages/VCockpit/Instruments/NavSystems/G36XG1000/PFD/G36XG1000_PFD.html"></script>

In G36XG1000_PFD.html I have the following code - which I am assuming loads before the NXi?

Code:

<script type="text/html" import-script="/JS/dataStorage.js"></script>
<script type="text/html" import-script="/JS/coherent.js"></script>
<script type="text/html" import-script="/Pages/VCockpit/Instruments/NavSystems/G36XG1000/PFD/G36X_Utils.js"></script>

G36X_Utils.js I have:

Code:

console.log('Hello World');
1 (&gt;L:XMLVAR_TEST_FUEL)

I can see the hello world console log which is a real win! (well for me anyway!) When I try and set a simple L: var I get errors in the console. When I use an arbitrary L: Var from somewhere else like:

Code:

console.log('Hello World');
1 (&gt;L:XMLVAR_GPS_Approach)

it doesn’t error, so I’m obviously missing something here.

What I need to do now, is understand the best way to write in G36X_Utils.js and create a simple L: variable that I can display in the NXi; i’m obviously not initiating the L: Var correctly in my mind.

If I can get it to work, from there that gives me a foundation to build on for using DataStore in the JS file.

As ever, many thanks for any pointers or thoughts from anyone.

@kaosfere4829 & @Bishop398 Realise you guys extremely busy but if you have any thoughts I’d really value them!

You’re setting variables like you would in an xml file. In javascript, you have to use the SimVar class:
SimVar.SetSimVarValue("L:XMLVAR_TEST_FUEL", "number", 1);

You might want to do some research on javascript/html before diving into creating custom gauges. The lack of documentation and the way the default aircraft gauges are built requires a fair bit of reverse engineering.

But to answer some of your questions above, the order in which scripts are imported should be done to satisfy the dependencies of the other scripts. There are multiple ways an html element can be created, a few ways are within the javascript file, and some directly in the html file. So you can’t be sure which elements are created first unless you look at the files in their entirety to see how they’re created. But you’d not want to create elements directly on top of other elements. That’ll really start to hurt performance considering these gauges are read in a single thread.

One thing with the order pops out to me is dataStorage.js depends on coherent.js, so you’ll want to import coherent.js first.

1 Like

Hey, thanks

I think I follow what your saying - although at the end of a very long work day and brain slightly frazzled.

After doing some digging I had changed to the js method of creating a L:Var

console.log('Hello World');
SimVar.SetSimVarValue("L:XMLVAR_MJB_FUEL", "number", 1);
test = SimVar.GetSimVarValue("L:XMLVAR_MJB_FUEL", "number");
console.log(test);

But as I think you point out I’m loading the dependencies incorrectly and out of order?

I’m not really trying to create a gauge, what I’m trying to do is on aircraft load read the data store for variables set at the end of the last flight. For example fuel tank level.

I could well be completely going out there and trying to make something work that isn’t designed to work in the way I want it.

All the code you posted is doing is setting a local simvar then reading it into a separate variable. You haven’t used any functions from the dataStorage.js file yet.

To store, you’ll have to generate a key, then call the set function.
var test = SimVar.GetSimVarValue("L:XMLVAR_MJB_FUEL", "number");
var key = `${SimVar.GetSimVarValue("ATC MODEL", "string")}.${"key_name"}`;
SetStoredData(key, test.toString());

Then on load, you’ll be able to read the stored value to a variable:

var key = `${SimVar.GetSimVarValue("ATC MODEL", "string")}.${"key_name"}`;
var storedValue = GetStoredData(key);

As long as the key is unique, it should work. I use the ATC Model as a way of guaranteeing uniqueness, but you could probably do whatever you wanted for that.

Hey thanks so much, getting there I think with your example. That makes sense.

With regard the local variable; I was just trialling whether the code setting a local variable was working, but sadly the output of ‘test’ in my code returns 0 instead of what I expected as 1.

I must have a loading issue still.

Put either var or let in front of test and try again.

Thanks so much for your help.

That didn’t work with either the let or var

console.log('Hello World');
let setTest = SimVar.SetSimVarValue("L:XMLVAR_MJB_FUEL", "number", 5);
let test = SimVar.GetSimVarValue("L:XMLVAR_MJB_FUEL", "number");
console.log(test);
console.log(setTest);

I must have a file issue I think, as setTest returns in the console. I have something wrong here definitely.
image

It looks like you’re trying to call this in the constructor. You should only be defining and initializing variables there. Try calling it in a different function. If there is a connectedCallback() function, try it in there.

My G36X_Utils.js is just an empty .js file at the moment - with the test code we’ve been discussing.

I think I need to do some more digging and working out where and how connectedCallback is called etc.

Thanks so much for your help!!!

Ok So I am kinda getting somewhere. (https://github.com/TheFrett/msfs_g36_project/tree/development)

I have managed to get the aircraft to save its fuel data to the datastore and then to read it on loading the aircraft.

I have also managed to get the sim to write the values to the datastore when the bat 1 & engine is running therefore keeping up to date with fuel usage.

//load the left fuel tank from the dataStore or set full and record in dataStore
  var initLeftFuel = GetStoredData('G36XIP_LEFT_FUEL');
  if (initLeftFuel) {
    SimVar.SetSimVarValue("FUEL TANK LEFT MAIN QUANTITY", "number", Number(initLeftFuel));
  } else {
    SimVar.SetSimVarValue("FUEL TANK LEFT MAIN QUANTITY", "number", 40);
    SetStoredData('G36XIP_LEFT_FUEL', '40');
  }

//load the right fuel tank from the dataStore or set full and record in dataStore
  var initRightFuel = GetStoredData('G36XIP_RIGHT_FUEL');
  if (initRightFuel) {
    SimVar.SetSimVarValue("FUEL TANK RIGHT MAIN QUANTITY", "number", Number(initRightFuel));
  } else {
    SimVar.SetSimVarValue("FUEL TANK RIGHT MAIN QUANTITY", "number", 40);
    SetStoredData('G36XIP_RIGHT_FUEL', '40');
  }



// - - - - - - - - - - - - - - - - - - - WHEN SIM RUNNING - - - - - - - - - - - - - - - - - - - - -

var timerMilSecs = 30000;
var timer = window.setInterval(checkG36State, timerMilSecs);

function checkG36State() {
  if (SimVar.GetSimVarValue("ELECTRICAL MASTER BATTERY:1", "bool") && SimVar.GetSimVarValue("ENG COMBUSTION:1", "bool")) {
    let lefttank = SimVar.GetSimVarValue("FUEL TANK LEFT MAIN QUANTITY", "gallons");
    let righttank = SimVar.GetSimVarValue("FUEL TANK RIGHT MAIN QUANTITY", "gallons");
    SetStoredData('G36XIP_LEFT_FUEL', lefttank.toString());
    SetStoredData('G36XIP_RIGHT_FUEL', righttank.toString());
  }
}

I then moved on to setting & reading the Battery 1 switch but this doesn’t set.

I think this is due to the fact that I am not using a class and function. e.g. connectedCallback.
I’m not quite there with how the best way is to create the class and call the function, I think I need to extend baseInstrument but not sure