Jump to content
The simFlight Network Forums

Vb.Net, FSUIPC and writing to the payload offset


Recommended Posts

Hi all,

(FSUIPC 4.40, FSX) I'm trying to write payload information to FS in VB.net using the .Net client DLL, but I'm having problems - I'm almost sure it's due to the way I'm handling byte arrays and conversion from doubles - I'm not 100% up to speed on that. Anyway:

I've declared an array of payload offsets with:

Public myPayload(60) As FSUIPC.Offset(Of Byte())
For n = 0 To 60
     myPayload(n) = New FSUIPC.Offset(Of Byte())(&H1400 + (&H30 * (n - 1)), 8)
Next

Any after an FSUIPC.Process, I can read the payload values for a given number of stations using

For n = 0 To stations - 1
     myArray(n) = BitConverter.ToDouble(myPayload(n + 1).Value, 0)
Next

And that works perfectly. Now, once I've changed the values, I try and write them back with (cargoArray() holds the station weight values as doubles)

Dim dblarr() As Double = {0}
Dim test() As Byte = Array.CreateInstance(GetType(Byte), Buffer.ByteLength(dblarr))

For n = 0 To stations - 1
     dblarr(0) = cargoArray(n)
     Buffer.BlockCopy(BitConverter.GetBytes(CDbl(cargoArray(n))), 0, test, 0, Buffer.ByteLength(BitConverter.GetBytes(CDbl(cargoArray(n)))))
     myPayload(n).Value = test
Next

FSUIPCConnection.Process()

When I run this code, all the payload stations get set to the value in the last station I set. If I run an FSUIPCConnection.Process after setting each myPayload(x) element, I get varying results as if it's using certain values to set multiple payload stations - for example, if I populate cargoArray with an incrementing value from 1 to 10 and set that to the appropriate payload station (so I should see 1 to 10 assigned per payload station in FS), the first 3 are 1, the next 5 are 7 and the last 2 are 10.

Does anyone have any thoughts? Am I converting the double to a byte value in the appropriate manner? Have I missed something obvious?

Many thanks,

Slopey.

Link to comment
Share on other sites

Have I missed something obvious?

In your example you are setting 10 stations. Does the aircraft you are using have 10 defined stations? I have the feeling, from what I've seen, that the numbering can wrap around somewhat and give misleading results. ALWAYS limit the number you use to the number declared -- you can read this from offset 13FC at the start.

Incidentally, in FS9 these changes don't appear to affect the overall weights, flight characteristics, and so on. I don't know if they do in FSX. Since you are using FSX, can you confirm or not whether these changes work correctly, so I can update the documentation?

Regards

Pete

Link to comment
Share on other sites

Hi Pete,

I'll check that for you (off the top of my head, unless I pop up the Payload dialog in FS and get them to Ok it, it doesn't). (In answer to a previous query btw, the fs date reported by FS9 does appear to be Zulu).

I have the correct number of payload stations. I've worked out a way to get it to work but I'm not sure why it is - I'm sure you'll know ;)

If I write each value with an FSUIPC.Process after I assign it, then "sleep" for 3 seconds, it works perfectly. But if I write them all first, then do a Process. It doesn't work.

i.e. if I want to load 1,2,3,4,5,6 into the first 6 payload stations, then set - sleep - process in a loop works ok and I get 1,2,3,4,5,6 in FS. If I set them to the values first, then do a process at the end of the loop, I get 1,6,6,6,6,6 in FS.

So - I've found a workaround, so not too much of a problem - my user will just need to wait a little minute while the handling agents load up the plane :)

Link to comment
Share on other sites

(In answer to a previous query btw, the fs date reported by FS9 does appear to be Zulu).

Ah, good. So FS9 and FSX match. Thanks. I'll update to dox to make it clearer.

I have the correct number of payload stations. I've worked out a way to get it to work but I'm not sure why it is - I'm sure you'll know ;)

If I write each value with an FSUIPC.Process after I assign it, then "sleep" for 3 seconds, it works perfectly. But if I write them all first, then do a Process. It doesn't work.

And this is with FSX, right, as per your original message in this thread? 3 seconds is one helluva long time!

i.e. if I want to load 1,2,3,4,5,6 into the first 6 payload stations, then set - sleep - process in a loop works ok and I get 1,2,3,4,5,6 in FS.

Set - Process - Sleep, you mean? There's no point in waiting between set and process.

If I set them to the values first, then do a process at the end of the loop, I get 1,6,6,6,6,6 in FS.

This most certainly sounds like a SimConnect bug! SimConnect runs asynchronously to both FSUIPC and the rest of FSX. It sounds like after SimConnect is asked to write one value it instigates the appropriate processes to re-compute things (overall weights, changed flight characteristics -- meaning re-populating tables -- and so on), and when it then immediately processes the next station it instigates the same processing which turns out to be non-re-entrant. The final value gets used by the non-reentrant code because it loses the previous by the re-entry.

I've seen code like that before (probably written some myself before now! ;-) ).

Could you report this, with the gory details, via tell_fs@microsoft.com please. You can quote my "analysis" above too, as it should help. There's no chance of a fix in FSX, but we should try to stop it promulgating to ESP2 and FSXI.

Regards

Pete

Link to comment
Share on other sites

Slopey,

If there any reason you're using a Byte array and then converting the bytes to doubles yourself?

The DLL supports reading and writing of Doubles directly. It would save you a lot of trouble in the code if you just made an array of Offset(Of Double). It may fix your problem. It sounds like the DLL is having a hard time tracking which data have been changed and therefore which to write back to FS.

Paul

Link to comment
Share on other sites

I think I've just seen the problem...

For n = 0 To stations - 1
     dblarr(0) = cargoArray(n)
     Buffer.BlockCopy(BitConverter.GetBytes(CDbl(cargoArray(n))), 0, test, 0, Buffer.ByteLength(BitConverter.GetBytes(CDbl(cargoArray(n)))))
     myPayload(n).Value = test
Next

You're always copying new values into the 'test' byte array and then setting that object as the value of the offset. However, all your offsets are getting set to the same byte array. You just keep changing its value with every loop. You need to make a new byte array for each one:

For n = 0 To stations - 1
     dblarr(0) = cargoArray(n)
     test = New .... (Whatever you declared it as)
     Buffer.BlockCopy(BitConverter.GetBytes(CDbl(cargoArray(n))), 0, test, 0, Buffer.ByteLength(BitConverter.GetBytes(CDbl(cargoArray(n)))))
     myPayload(n).Value = test
Next

This wouldn't be a problem with doubles as they are Value types in VB.net and not Reference types like Byte Arrays(). You always get a new copy of value types automatically.

Paul

Link to comment
Share on other sites

If there any reason you're using a Byte array and then converting the bytes to doubles yourself?

Is that what it is doing? Sorry, I only read the words, not the code. Don't know anything about this new-fangled managed stuff! ;-)

The DLL supports reading and writing of Doubles directly. It would save you a lot of trouble in the code if you just made an array of Offset(Of Double). It may fix your problem. It sounds like the DLL is having a hard time tracking which data have been changed and therefore which to write back to FS.

If this might be happening it would certainly be best to check BEFORE reporting any SimConnect problem to MS.

I could tell from an FSUIPC log file. Slopey, could you enable IPC write logging in the Logging tab and show me what you get for a non-working sequence?

Pete

Link to comment
Share on other sites

  • 2 years later...

Ah ha!!!

Perfect - works like a charm!! Many thanks phenty - I didn't realise I could use the double directly!

Works perfectly now!

Many thanks to both!! :D :D :D

(I'll let you know if FSX uses the values correctly Pete!).

Hello, can help-me with this, a have a same problem with c#, how to get and convert this values of double ?

Link to comment
Share on other sites

Hello, can help-me with this, a have a same problem with c#, how to get and convert this values of double ?

Hi,

Assuming you just want the weights from the payload stations like the original poster and not the distances and names, you just need to create an array of Offset<double>, then calculate and set the offset address for each one.

1. At your form or class level declare the array for all the payload offsets:

private Offset&lt;double&gt;[] payloadStations = new Offset&lt;double&gt;[60];

2. Somewhere at the start of your program, create the actual offsets for each payload station and add them to the array:

for (int i = 0; i &lt; 60; i++)
{
    payloadStations[i] = new Offset&lt;double&gt;("Payload", 0x1400 + (0x30 * i));
}  

Note that these are in a separate offset group called 'Payload' so we can control when this data gets read.

3. When you need to refresh this data call Process on the Payload group:

FSUIPCConnection.Process("Payload");

4. Read the payload information: Examples below show reading a single payload station and adding up the weights of all stations:

// Get the weight from the Third (#3) payload station.
double weight = payloadStations[2].Value;

// Gets total wieght of all payload stations
double totalWeight = 0d;
for (int i = 0; i &lt; 60; i++)
{
    totalWeight += payloadStations[i].Value;
}

Note that I've hard-coded the number of stations to 60. You can use offset 13FC to get actual number of payload stations for the current aircraft.

Paul

Link to comment
Share on other sites

Hi,

Assuming you just want the weights from the payload stations like the original poster and not the distances and names, you just need to create an array of Offset<double>, then calculate and set the offset address for each one.

1. At your form or class level declare the array for all the payload offsets:

private Offset&lt;double&gt;[] payloadStations = new Offset&lt;double&gt;[60];

2. Somewhere at the start of your program, create the actual offsets for each payload station and add them to the array:

for (int i = 0; i &lt; 60; i++)
{
    payloadStations[i] = new Offset&lt;double&gt;("Payload", 0x1400 + (0x30 * i));
}  

Note that these are in a separate offset group called 'Payload' so we can control when this data gets read.

3. When you need to refresh this data call Process on the Payload group:

FSUIPCConnection.Process("Payload");

4. Read the payload information: Examples below show reading a single payload station and adding up the weights of all stations:

// Get the weight from the Third (#3) payload station.
double weight = payloadStations[2].Value;

// Gets total wieght of all payload stations
double totalWeight = 0d;
for (int i = 0; i &lt; 60; i++)
{
    totalWeight += payloadStations[i].Value;
}

Note that I've hard-coded the number of stations to 60. You can use offset 13FC to get actual number of payload stations for the current aircraft.

Paul

Paul, sorry but another question came up when trying to use the reading of the exact number of stations with the offset 13FC. In my attempt, the offset 13FC returns six seasons. But the suggested code aprenseta an error "index out of range". I believe that this is due to the sum 0x30. How did you get this constant 0x30?

Again, sorry for my poor performance programming.

Link to comment
Share on other sites

But the suggested code aprenseta an error "index out of range". I believe that this is due to the sum 0x30. How did you get this constant 0x30?

0x30 is the length in hex of each payload station block. It's 48 in decimal, as described in the FSUIPC documentation - There are 4 doubles (4*8 bytes) plus a 16 byte string for the name = 48.

The "index out of range" is probably because you're trying to using the count as the highest index. If you have 6 stations then your array will only have indexes 0-5. 0 is the 1st element, 5 is the last (6th) element. Therefore if you ask for MyArray[6] you'll get an "index out of range" error.

You've probably done something like this:

for (int i = 0; i&lt;= NumberOfStations; i++)

What you actually need is this:

for (int i = 0; i&lt; NumberOfStations; i++)

If that's not the problem then maybe you can post the block of code that's causing the problem.

[EDITED: Sorry I thought you were using VB. Changed to C#!]

Paul

Link to comment
Share on other sites

0x30 is the length in hex of each payload station block. It's 42 in decimal, as described in the FSUIPC documentation - There are 4 doubles (4*8 bytes) plus a 16 byte string for the name = 42.

Just to correct what must be a typo, 0x30 = 3 x 16 = 48, not 42 (4*8 + 16 = 32 + 16 = 48).

Regards

Pete

Link to comment
Share on other sites

Indeed. Thanks Pete. I'll edit my post again. Not doing too well with this one!

Paul

Paul, thanks for the attention that is me dismissively. I'm getting the same error below is the code I typed. If I put the type as int in the statement returns an error if put to double and try to convert Retona always 0. You can indicate where is my mistake?

   public static double calculaPayload()
    	{
        	int index = Convert.ToInt32(FSUIPCData.PayloadstationcountFS2004.Value); //Here I tried two things, convert to integer (Retona always 0), and declare as int offset (in error as above).

        	for (int i = 0; i &lt; index; i++)
        	{
            	FSUIPCData.PayloadweightlbsFS2004[i] = new Offset&lt;double&gt;(0x1400 + (0x30 * i));
        	}

        	FSUIPCData.FSUIPCProcess();

        	// Pegar peso total
        	double totalWeight = 0;
        	for (int i = 0; i &lt; index; i++)
        	{
            	totalWeight += FSUIPCData.PayloadweightlbsFS2004[i].Value;
        	}


        	return totalWeight;
    	}

Link to comment
Share on other sites

Firstly, you are right by declaring the PayloadstationcountFS2004 as <int>. There is no need for conversion, just use the .Value directly.

About the "index out of range" - I cannot see anything in the code that will cause that. However, you have not shown the code where you declare and initialise your array FSUIPCData.PayloadweightlbsFS2004[]. Is this set to be large enough? Have you checked the value coming back from PayloadstationcountFS2004 to see if it within the bounds of your array?

There is also a larger problem here I can see. Is this method calculaPayload() only ever called once? If so then it's OK. But if you call it more than once during the running of your application then you will have problems.

Each time you do this:

FSUIPCData.PayloadweightlbsFS2004[i] = new Offset&lt;double&gt;(0x1400 + (0x30 * i));

you are creating new Offsets, but the old ones are still there. So if your plane has 20 payload stations and you call calculaPayload() 10 times, you'll have 200 offsets being read during Process().

You need to put the payload offsets in their own group then use FSUIPCConnection.DeleteGroup() to get rid of them before calculaPayload() ends. You could also reset the PayloadweightlbsFS2004 in this method. I've made all those changes in the code below. This might work. If not, please tell me which line the error occurs on.

        public static double calculaPayload()
        {
            int index = FSUIPCData.PayloadstationcountFS2004.Value; // Declare as Offset&lt;int&gt;

            // Setup a new array with the correct dimensions
            FSUIPCData.PayloadweightlbsFS2004 = new Offset&lt;double&gt;[index];

            for (int i = 0; i &lt; index; i++)
            {
                FSUIPCData.PayloadweightlbsFS2004[i] = new Offset&lt;double&gt;("Payload", 0x1400 + (0x30 * i));
            }

            FSUIPCConnection.Process("Payload");

            // Pegar peso total
            double totalWeight = 0;
            for (int i = 0; i &lt; index; i++)
            {
                totalWeight += FSUIPCData.PayloadweightlbsFS2004[i].Value;
            }

            FSUIPCConnection.DeleteGroup("Payload");

            return totalWeight;
        }

Paul

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.