Jump to content

DCS BIOS decode Export using c#.net


Recommended Posts

Hi,

 

 

Im fiddling around with DCS-BIOS and visual studio. Currently I am listening to the export broadcast address on 239.255.50.10, port 5010. I am receiving data ok but I don't know how to decode it.

 

 

Does anybody have a quick code snippet preferably in c# on how to decode the received data from the export?

 

 

Thanks

 

 

Here is my test program

 

 

       public void StartListener()
       {
           try
           {
               UdpClient client = new UdpClient();

               client.ExclusiveAddressUse = false;
               IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 5010);

               client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
               client.ExclusiveAddressUse = false;

               client.Client.Bind(localEp);

               IPAddress multicastaddress = IPAddress.Parse("239.255.50.10");
               client.JoinMulticastGroup(multicastaddress);

               Console.WriteLine("Listening this will never quit so you will need to ctrl-c it");

               while (true)
               {
                   Byte[] data = client.Receive(ref localEp);
                   Console.WriteLine(Encoding.ASCII.GetString(data, 0, data.Length));
               }
           }
           catch (SocketException e)
           {
               Console.WriteLine(e);
           }
           finally
           {

           }
       }

Link to comment
Share on other sites

I'm decode DCS-BIOS data using this

https://github.com/emcek/dcspy/blob/master/dcspy/dcsbios.py

Original code done by jboecker

If you want details PM me we can chat somewhere, code is in Python, I can show up how I'm using it... Or you can look around thru code

 

Nokia 6.1 with Tapatalk

Take a look my mods :joystick: 

dcs_footer500.jpg

CPU: i7 7700 | GPU: GeForce GTX 1080 8GB DDR5 | Motherboard: ASUSTeK PRIME B250M-A | RAM: 2x16GB DDR4-2400 | Output: Kingston HyperX Cloud II | Edifier C2XD 2.1 | Controlls: Saitek X-56 Rhino | Saitek Flight Rudder Pedals | Saitek Multi/Radio/Switch Panels | Thrustmaster MFD Cougar | Elgato Stream Deck XL | OpenTrack with LaserClip | VoiceAttack with VAICOM Pro plugin

 

Link to comment
Share on other sites

I wrote a Node/JS library to decode the data here:

 

https://github.com/danieltian/dcs-bios-api/blob/master/lib/dcs-bios-export-parser.js

 

I wrote comments that hopefully should help with figuring out how the decoding works, but to give an overview, you need to look at the .json files in the %APPDATA%\DCS-BIOS\Plugins folder. They will contain information on the address of a control, which I'll refer to as a control definition. When you receive incoming data, the first 2 bytes is the control's address, the next 2 bytes is the number of bytes to update starting from that address, and the remaining is the new data that you need to set. All integers are little endian. For example, let's assume the aircraft name is at address 5412. You'll receive the following message:

 

12 54 05 00 65 45 49 48 67

 

Broken up it will be:

 

[12 54] [05 00] [65 45 65 45 49 48 67]

 

Converted to decimal, that becomes:

 

[5412] [5] [65 45 65 45 49 48 67]

 

Or in other words, for the address 5412, update 5 bytes, and [65 45 65 45 49 48 67] is the data to update with. Since the aircraft name is a string, we can assume it's ASCII text, which translates to "A-10C".

 

If you're interested in strings, it's a bit involved. You need to create an array with a length of 65536 to hold all the incoming data because updates can be partial updates. For example, if the aircraft name changes, you might not get the entire string at once; the first update can be for address 5412, 2 bytes, with the characters "A-", and the second update for address 5414, 3 bytes, with the characters "10C". Because 5414 might not match up with any of the addresses in the control definition .json files, you will also need to keep track of all the control addresses:

 

https://github.com/danieltian/dcs-bios-api/blob/master/lib/dcs-bios-json-parser.js#L49

 

Then if the message has an address that doesn't match up with a control address, it's a partial update and you need to count down from the update address until you find the control:

 

https://github.com/danieltian/dcs-bios-api/blob/master/lib/dcs-bios-export-parser.js#L172-L174

 

In picture form:

 

                           
Address: [5411] [5412] [5413] [5414] [5415] [5416] [5417] ...
                 ^                                  ^
           Aircraft name                   Some other control

Address 5414 is in between two controls, so we have to count down to find
the control at 5412 to know which control 5414 is a partial update for.

 

If you're interested in integers, it seems like the updates will always be full updates and you probably don't need to create an array to hold the incoming data. To parse an analog value like a knob position, you can just read the two bytes as an Int16 and use that value (analog numbers in DCS BIOS will always be 0 to 65535). To parse a boolean value like a light on/off, you'll have to look at the control definition and use the mask and shift_by properties to get the value. This is because a byte can represent up to 8 on/off lights where each bit is the state of an individual light. For example:

 

01101011
  ^
  you only want this light

 

The mask will be 32 and the shift_by will be 5. To get the value of the light, you simply logical AND the byte, then shift right by the shift_by value:

 

   01101011 // our byte
AND 00100000 // mask value of 32
   --------
   00100000

 

00100000 shifted right 5 times becomes 001 = 1 = on

 

Another thing to look out for is if the address and count are both 0x5555. This is a "sync command" that lets you know that all the updates for this particular frame are done and it's safe to process the data. Using the earlier example, we might get one update that gives us "A-" and a second update that gives us "10C", but if we processed the aircraft name after the first frame, we'll have the wrong string. So we wait until the we get the sync command, then we know it's safe to read the aircraft string at that point.

 

One last thing to be aware of is that some aircraft have overlapping addresses. For example, the F-14 addresses overlap with the A-10C addresses, so if you're trying to write something generic that applies across multiple aircraft, you might also need to check the currently-active aircraft in MetadataStart json to ensure that you're not processing the wrong aircraft's controls. Here's an example of how to do that:

 

https://github.com/danieltian/dcs-bios-stream-deck-plugin/blob/master/src/server/dcs-bios-api/index.js#L111-L116


Edited by Ranma13
  • Like 3
Link to comment
Share on other sites

Wow awesome work Renma13. Thats complicated lol. I dont wanna re-invent the wheel especially when looking at your API it looks great and covers the planes I am looking at as well (Hornet and the Harrier), in particular I just want to get the ufc display for a start.

 

I wonder if I can use your API in my c#.net project somehow.

Link to comment
Share on other sites

Ok ive made some progress, basically what I am doing is running Ranma13 node.js and relaying that through tcp for which I am listening in my c#.net application. Obviously would like to decode it myself but this will do in the meantime.

Link to comment
Share on other sites

Hi Ranma13

I‘m really interested in your Nodejs code. I tried to get it running, but with the delivered code samples I can't get it to work probertly.. I get info messages for the airplanes, but after that the code did not keep on going, for example to listen an receive messages.. you have any idea why this could be the case? Or maybe what I‘m doing wrong? I tried just to run your code along with decks-bios and DCs.. I tried a up connection to DCs-bios and get the encoded stream.. but when I tried to set up your code, it didn‘t do what I was expecting..

Sorry for my bad english, not my native language

Link to comment
Share on other sites

Hi MudzNZ

 

Thank you for your help. It works now.

 

Here is the code that i needed to get it running:

const DcsBiosApi = require('dcs-bios-api');

 

var api = new DcsBiosApi({ logLevel: 'INFO' });

api.startListening();

api.on('update', (value) => {

 

value.forEach(element => {

if(element.output != undefined){

if(element.control.identifier == 'AHCP_MASTER_ARM'){

console.log(element);

}

}

});

});

 

it was just the ".startListening();" that wasn't in the description.

Link to comment
Share on other sites

  • 1 year later...

i work some times white a javascript decode script,it's can work.

//0-255 to hex
function i2h(i){
    
    var h = (i).toString(16);
    
            if (h.length==1){
                 h="0"+h;
                }
                return h;
}

var fbiosarr=new Array();       //所有未处理数据
var tmphex=new Array();         //正在处理数据
var da = new Array(65536);       //数据存放缓冲区
var sync=0;//同步标识

function decodebios(hex) {
    //ka50雷达高度0-65525
    console.log("get:1858|59>",da[0x1859]*256+da[0x1858])
    
    // 把HEX数据放到fbiosarr数组,Uint16Array操作不便
    var x1 = new Uint16Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    x1.forEach(e => {
        fbiosarr.push(e)
    });

    // 开始处理fbiosarr数据
    while (fbiosarr.length>5){

        //如果是同步指令
        if (fbiosarr[0]==0x55 && fbiosarr[1]==0x55 && fbiosarr[2]==0x55 && fbiosarr[3]==0x55){
            sync=1;

            //删除0x55555555
            fbiosarr.splice(0,4)
        }else{
            //如果不同步,
            tmphex.push(fbiosarr.shift())
        }
        
        if (sync==1){
            //同步开始,处理之前收到的数据
            while (tmphex.length>5){
                var address = tmphex.splice(0,2);
                address.reverse();
                address = eval("0x"+i2h(address[0])+i2h(address[1]))

                var count = tmphex.splice(0,2);
                count.reverse()
                count = eval("0x"+i2h(count[0])+i2h(count[1]))

                var data = tmphex.splice(0,count)
                //循环写入da数组
                for (let i = 0; i < data.length; i++) {
                    const h = data[i];
                    da[address+i]=h
                }
            }          
            //复位同步记号
            sync=0;
            tmphex.splice(0);
        }
    }
}

 


Edited by qq515616480
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...