MudzNZ Posted April 16, 2020 Posted April 16, 2020 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 { } }
emc Posted April 16, 2020 Posted April 16, 2020 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 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
Ranma13 Posted April 19, 2020 Posted April 19, 2020 (edited) 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 April 19, 2020 by Ranma13 3
MudzNZ Posted April 20, 2020 Author Posted April 20, 2020 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.
MudzNZ Posted April 21, 2020 Author Posted April 21, 2020 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.
donoli Posted April 22, 2020 Posted April 22, 2020 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
MudzNZ Posted April 23, 2020 Author Posted April 23, 2020 try run the index.js file not the one in git hub home screen code I found that worked for me
donoli Posted April 23, 2020 Posted April 23, 2020 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.
qq515616480 Posted December 12, 2021 Posted December 12, 2021 (edited) 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 December 25, 2021 by qq515616480
Recommended Posts