The No.1 Website for Pro Audio
Dante routing without Dante Controller is possible
Old 3rd July 2018
  #1
Here for the gear
Dante routing without Dante Controller is possible

I'm doing this on Arch Linux with a virtual machine running Windows 10 and Dante Controller. My goal is to have fully scriptable channel routing from Linux clients. It was trivial to capture some network traffic with wireshark and replay it with netcat to send commands to my Audinate AVIO adapters to route channels between devices.

For example, with 192.168.1.15 as the avio-output adapter:

# avio-input ch1 -> avio-output ch1 off
echo '2729001001da30140000000100000001' | xxd -r -p | nc -c -w1 -u 192.168.1.15 4440

# avio-input ch1 -> avio-output ch1 on
echo '2729002f02923010000001010001002000240000000000000000000000000000434831006176696f2d696e70757400' | xxd -r -p | nc -c -w1 -u 192.168.1.15 4440
Old 20th November 2018
  #2
Here for the gear
 
I am extremely interested in this. Do you have some additional example code available?
Old 3rd February 2019 | Show parent
  #3
Here for the gear
Quote:
Originally Posted by dpzmick ➡️
I am extremely interested in this. Do you have some additional example code available?
I haven't done much more than make this enable/disable connections. I'll keep this thread updated if I expand on this (I do plan on doing that). The basic idea is to capture the packets and resend them; I always found that there was a prefix in the request that could be removed. The device name is used in the request too.

edit: I received a new Dante device, so I made a video demo while I was collecting packets for the commands to it. The avio input and output adapters have level controls within Dante Controller; I've scripted these now too.

Here is a list of the features I have working so far.

Port 8700:
  • Sample rate
  • Level control
  • Preferred Encoding

Port 4440:
  • Get/set subscriptions
  • Device latency
  • Set/reset channel name
  • Rename device

MDNS:
  • Read device encoding
  • Read device sample rate
  • Read device latency
  • Enumerate channel count
  • Device discovery
  • Device model
  • MAC address
  • Device manufacturer
  • Device version

TODO:
  • Read events
  • Set device IP
  • Signal active/inactive state
  • Device reboot / clear config
  • Pull-up/down setting
  • Unicast Delay Requests setting
  • Enable/disable AES67 mode
  • Read latency tab info

video: Scripting Dante — Routing commands
code: Scripting Dante — Routing commands

video: Scripting Dante — Level controls
code: Scripting Dante — Level controls

I used wireshark with a filter to capture packets sent from Dante Controller. The packet destination is always going to be the receiver (rows in Dante Controller), and the source is whatever computer you are using to click on the buttons in Dante Controller. In this example, my Windows VM is 192.168.1.138 and the avio output adapter is 192.168.1.30.

Code:
ip.dst == 192.168.1.30 && ip.src == 192.168.1.138
Once you do this, restart the capture (clear the screen of logged packets) and click the button to enable the connection anywhere in Dante Controller.
Right click the first packet logged and select copy -> bytes -> hex stream. You'll get a string like this:
Code:
001dc1501ec0525400c5c27108004500004b6
d8c00008011491dc0a8018ac0a8011ed96111
58003784412729002f0809301000000101000
1002000240000000000000000000000000000
434831006176696f2d696e70757400
I've added line-breaks so this isn't too long, but when you send this later it shouldn't have those. After all of the irrelevant confirmation packets are sent and settled, clear the packet log again and then click on the same connection in Dante Controller to remove the route you just added. Again, you want the first packet logged, and it will look something like this when the hex stream is copied:
Code:
001dc1501ec0525400c5c27108004500002c6
ca6000080114a22c0a8018ac0a8011ed96111
5800188422272900100800301400000001000
00001
Strip the packet header (in this example the data always starts with "272900" for every request).
Code:
2729002f08093010000001010001002000240
0000000000000000000000000004348310061
76696f2d696e70757400
Code:
27290010080030140000000100000001
Now you can send this data back yourself without Dante Controller. I'm using BSD netcat and xxd here for these examples. UDP port 4440. Don't use any line-breaks or spaces in the echo command.

On:
Code:
echo '001dc1501ec0525400c5c27108004500002c6ca6
000080114a22c0a8018ac0a8011ed961115800188
42227290010080030140000000100000001' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
Off:
Code:
echo '2729002f0809301000000101000100200024
0000000000000000000000000000434831006176696f
2d696e70757400' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
You can use the same payload for different receivers by changing only the IP address.

For the level controls, the requests needed to be sent on port 8700. Each of the devices had a unique prefix for all requests, while only the channel number and setting would change.
Code:
  bytes='ffff003403440000525400c5c2710000417564696e61746507271
00a0000000000010001000c001001020000000000
0100000002'
  echo "${bytes}" | xxd -r -p | nc -w0 -u $host 8700
In this example, 0100000002 is the only unique part of the request to this device. The first 01 is the channel number; so 01 or 02 in my case. The last number was the setting; 01 was the first selection and 05 was the last.

MDNS is used for device/service discovery and can be used to read the device config:
Code:
{
  "name": "avio-output._netaudio-arc._udp.local",
  "type": "TXT",
  "class": "IN",
  "flash": true,
  "ttl": 4500,
  "rdata": {
    "arcp_vers": "2.7.41",
    "arcp_min": "0.2.4",
    "router_vers": "4.0.1",
    "router_info": "DAO2",
    "mf": "Audinate",
    "model": "DAO2"
  }
},
{
  "name": "avio-input._netaudio-cmc._udp.local",
  "type": "TXT",
  "class": "IN",
  "flash": true,
  "ttl": 4500,
  "rdata": {
    "id": "001dc1fffe502b0a",
    "process": "0",
    "cmcp_vers": "1.2.0",
    "cmcp_min": "1.0.0",
    "server_vers": "4.0.2",
    "channels": "0x6000004d",
    "mf": "Audinate",
    "model": "DAI2"
  }
},
{
  "name": "[email protected]_netaudio-chan._udp.local",
  "type": "TXT",
  "class": "IN",
  "flash": true,
  "ttl": 3600,
  "rdata": {
    "txtvers": "2",
    "dbcp1": "0x1102",
    "dbcp": "0x1004",
    "id": "1",
    "rate": "48000",
    "en": "24",
    "pcm": "3 4",
    "enc": "24",
    "latency_ns": "1000000",
    "fpp": "16,16",
    "nchan": "2"
  }
}

Last edited by s00pcan; 3rd February 2019 at 09:05 PM.. Reason: added videos
Old 3rd October 2019
  #4
Gear Addict
 
UnDeFiNeD's Avatar
 
🎧 15 years
Amazing stuff! I bet there isn't an official API for Dante controller available?
Old 9th October 2019 | Show parent
  #5
Here for the gear
Quote:
Originally Posted by UnDeFiNeD ➡️
I bet there isn't an official API for Dante controller available?
I asked Audinate about this directly; they do not create any licenses for individuals to use their API or access the documentation on it. You'd have to create some kind of Dante-enabled product to get access to that. I've seen leaked documentation on it, but it's meant for embedded device commands and driver programming and is very outdated. I have more Dante devices now and am still planning on doing more to script them when I have time.
Old 27th November 2019
  #6
Here for the gear
 
Great work!

Congratullations s00pcan!
It is very interesting for me too. Year ago I tried investigate Dante network (I would like in the future to sync of crosses in some other - GPIO matrix with crosses in audio matrix of Dante). I can't continued my experiments because of absence of free time. Fortunatelly I see you are much more experienced in code writting So please share with us any news from your investigation. Thanks a lot!
Puchatek.
Old 2nd December 2019
  #7
Here for the gear
 
Thanks s00pcan,
this is great stuff - I managed to do some routing with this info myself - thanks for sharing!
Do you know if there is a possibility to control volume/ a volume command for the Dante Avio Adapters?
Old 3rd December 2019
  #8
Here for the gear
 
AFAIK Avio, and most of Dante interfaces have no volume control.
Old 4th December 2019 | Show parent
  #9
Here for the gear
Quote:
Originally Posted by cvxdev ➡️
Thanks s00pcan,
this is great stuff - I managed to do some routing with this info myself - thanks for sharing!
Do you know if there is a possibility to control volume/ a volume command for the Dante Avio Adapters?
Yes, this is possible, somewhat. You don't have many steps to choose from with these adapters, but they're the only ones I've seen with any built-in gain adjustment available. I don't use the AVIO adapters as much since getting a Ferrofish A32 Dante (which handles gain levels over MIDI/USB but I haven't scripted that yet).

Here is a script you can modify and use for the AVIO adapters. Handles both the input and output 2ch adapters.

http://dpaste.com/22DB7JF.txt

Code:
function dante_level_control() {

  local channel=$3
  local host=$1
  local label=$5
  local setting=$4
  local target=$2
  local udp_port=8700

  bytes="${target}${channel}000000${setting}"
  echo "$host $channel $setting $label"
  echo "${bytes}" | xxd -r -p | nc -w0 -u $host $udp_port

}

function dante_test_output_level() {

  local avio_input_1='192.168.1.31'
  local avio_output_1='192.168.1.30'
  local avio_output_2='192.168.1.33'
  local host=''

  # crashes the device
  # bytes='120000140015100100000000525400c5c2710000'
  # host=$avio_output_1
  # udp_port=4440

  # start avio-input
  
  host=$avio_input_1
  target='ffff003403440000525400c5c2710000417564696e6174650727100a0000000000010001000c001001020000000000'
  
  # start channel 1

  channel='01'
  
  dante_level_control $host $target $channel '01' '+24 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '02' '+4dBu'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'
  
  # end channel 1
  
  sleep 2
  
  # start channel 2

  channel='02'
  
  dante_level_control $host $target $channel '01' '+24 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '02' '+4dBu'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'
  
  # end channel 2
  # end avio-input

  sleep 4

  # start avio-output
  
  host=$avio_output_1
  target='ffff003403260000525400c5c2710000417564696e6174650727100a0000000000010001000c001002010000000000'
  
  # start channel 1

  channel='01'

  dante_level_control $host $target $channel '01' '+18 dBu'
  sleep 2
  dante_level_control $host $target $channel '02' '+4 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'
  
  # end channel 1

  sleep 2
  
  # start channel 2

  channel='02'

  dante_level_control $host $target $channel '01' '+18 dBu'
  sleep 2
  dante_level_control $host $target $channel '02' '+4 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'

  # end channel 2
  # end avio-output

  sleep 4

  # start avio-output-2
  
  host=$avio_output_2
  target='ffff003403470000525400c5c2710000417564696e6174650727100a0000000000010001000c001002010000000000'
  
  # start channel 1

  channel='01'

  dante_level_control $host $target $channel '01' '+18 dBu'
  sleep 2
  dante_level_control $host $target $channel '02' '+4 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'
  
  # end channel 1

  sleep 2
  
  # start channel 2

  channel='02'

  dante_level_control $host $target $channel '01' '+18 dBu'
  sleep 2
  dante_level_control $host $target $channel '02' '+4 dBu (default)'
  sleep 2
  dante_level_control $host $target $channel '03' '+0 dBu'
  sleep 2
  dante_level_control $host $target $channel '04' '0 dBV'
  sleep 2
  dante_level_control $host $target $channel '05' '-10 dBV'

  # end channel 2
  # end avio-output-2

}

function dante_mic_output_level() {

  local avio_output_1='192.168.1.30'
  local host=''

  host=$avio_output_1
  target='ffff003403260000525400c5c2710000417564696e6174650727100a0000000000010001000c001002010000000000'

  channel='01'

  # dante_level_control $host $target $channel '01' '+18 dBu'
  # dante_level_control $host $target $channel '02' '+4 dBu (default)'
  # dante_level_control $host $target $channel '03' '+0 dBu'
  # dante_level_control $host $target $channel '04' '0 dBV'
  # dante_level_control $host $target $channel '05' '-10 dBV'
  
  # Two channels, summed
  # Five settings; four effective levels
  # Two inputs: 0dB and -6dB
  # Twenty possible levels plus two with the channels off, total of 22

  if [[ $1 == '1' ]]; then
    dante_level_control $host $target '01' '01' 
    dante_level_control $host $target '02' '01'
  elif [[ $1 == '2' ]]; then
    dante_level_control $host $target '01' '05'
    dante_level_control $host $target '02' '05'
  fi
}
Old 10th December 2019
  #10
Here for the gear
 
Awesome - thanks a lot!
Will try and let you guys know if it worked!
Old 18th December 2019
  #11
Here for the gear
 
Hi,
thanks again @ s00pcan for sharing the code.
I was able to make it work with my Avio-Analog adapters.
I guess this method is not possible with the Avio-USB adapter, or?
Is anyone aware of any other method to regulate their volume by a command?
Thanks.
Old 15th May 2020
  #12
Here for the gear
 
Thanks for all the hard work s00pcan, has this progressed any further?
I am looking to implement Dante cross point recall from a Q-SYS core using lua as they still don’t have anything like a Linux client.
Old 2nd October 2021
  #13
Old 3rd November 2021
  #14
Here for the gear
 
Not sure if anyone is still checking this thread. I'm struggling to follow along with the above example. Where it says:

Strip the packet header (in this example the data always starts with "272900" for every request).

I don't understand how you've got from:

Code:
2729002f08093010000001010001002000240
0000000000000000000000000004348310061
76696f2d696e70757400
To this:

Code:
27290010080030140000000100000001
If anyone understands I'd be grateful for your help.

Thanks!
Old 7th November 2021 | Show parent
  #15
Here for the gear
 
Hey wearethehive!

I just spent some time refreshing myself on this process to hopefully better answer your question.

These are 2 different strings.

This is the data needed to turn the connection on:

Code:
2729002f08093010000001010001002000240
0000000000000000000000000004348310061
76696f2d696e70757400
And this is the data needed to turn the the connection off:

Code:
27290010080030140000000100000001
Both of these are what he got after stripping the packet header from the two packets he copied from wireshark. I would love to know how s00pcan determined what part of the packet was the header cause I'm not an expert in that.
Old 7th November 2021
  #16
Here for the gear
 
What I remember originally getting hung up on was the next step where it shows you this:

On:
Code:
echo '001dc1501ec0525400c5c27108004500002c6ca6
000080114a22c0a8018ac0a8011ed961115800188
42227290010080030140000000100000001' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
Off:
Code:
echo '2729002f0809301000000101000100200024
0000000000000000000000000000434831006176696f
2d696e70757400' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
I believe what happened here is that the on and off commands somehow got flip flopped. Also the "Off" data (which is listed as the "On") still has the header in it.

Instead I think those should read as follows:

On:
Code:
echo '2729002f0809301000000101000100200024
0000000000000000000000000000434831006176696f
2d696e70757400' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
Off:
Code:
echo '27290010080030140000000100000001' | xxd -r -p | nc -w0 -u 192.168.1.30 4440
Old 21st January 2022
  #17
Here for the gear
I signed up for a trial key but didn't end up using it at all. It was limited to 30 days, and I went on vacation right after getting it.
Quote:
Originally Posted by wearethehive ➡️
Not sure if anyone is still checking this thread.
I'm still checking it. As to your question, the part I stripped off was information about the source/destination on my local network. It's not part of the payload that does anything. I was completely unfamiliar with using wireshark when I originally started doing this, so I didn't know which parts were useful at first.

I'm going to work on this some more this week and see what I can discover. I've made some progress on identifying requests that respond with the name of device, existing connections and all available channels. The data for connections is in a format like "transmitter channel name | transmitter device name | receiver channel name". Subsequent connections between the same two devices save a few bytes by omitting the transmitter device name. Self-connections use a period as the device name. The goal is still to replace Dante Controller with something that can be automated, and I'm getting close to that.

27ff000affff10000000 - contains tx and rx channel counts. For one of my devices the transmitter count was given as 64 instead of 2.

27ff000affff10030000 - device info (model name, dante model, default name, current name)

27ff0010ffff20000000000100010000 - receiver tab of device info. Increment the digit before the final 1 to get more pages of data.
27ff0010000020000000000100110000
In a 128 channel device, you'd go up to 100710

Dante Controller skips some pages because they contain data that was already included in other requests. I guessed at making requests for the other pages and worked, but you won't need them.

27ff0010000030000000000100010000 - transmit tab of device info, showing active connections. Increment the same digit for additional pages.
27ff0010000030000000000100110000
...
27ff0010000030000000000100710000

If you ask for values that are out of the supported range for the target device, you will get very short error responses.

The "ff" and "ffff" is something I've know about for a while. Replace it with whatever you want. Each request allows you to specify values that are returned in the corresponding response to uniquely and positively identify it. Dante Controller just increments this every time it sends a new request, but you can specify anything. Given a source port number (nc -p xxxxx) and this identifier, you can always know which response goes with which request.
Old 26th January 2022
  #18
Here for the gear
https://github.com/chris-ritsen/netw...dio-controller

I'm working on making a python CLI program that anyone could use. So far, it discovers devices, gets the address/name/make/model, tx/rx channels, active subscriptions, changes channel/device names, device latency, sample rate, subscribe/unsubscribe, and JSON output. Virtual devices using VIA work too. Next I'm going to add everything I've discussed here already.

It took me a few hours to analyze the receiver responses to determine what was going on. It's mostly pointing to offsets of where to find channel/device labels and a few fields to represent the current state of the connection.

Code:
00000000: 27ff 0281 ffff 3000 8112 1010 0001 000e  '.....0.........
00000010: 0158 014c 0156 0168 0000 0004 0000 0000  .X.L.V.h........
00000020: 0002 000e 0158 0171 0156 017b 0000 0004  .....X.q.V.{....
00000030: 0000 0000 0003 000e 0158 0184 0156 018e  .........X...V..
00000040: 0000 0004 0000 0000 0004 000e 0158 0197  .............X..
00000050: 0156 01a1 0000 0004 0000 0000 0005 000e  .V..............
00000060: 0158 01aa 0156 01b4 0000 0004 0000 0000  .X...V..........
00000070: 0006 000e 0158 01bd 0156 01c7 0000 0004  .....X...V......
00000080: 0000 0000 0007 000e 0158 01d0 0156 01da  .........X...V..
00000090: 0000 0004 0000 0000 0008 000e 0158 01e3  .............X..
000000a0: 01e6 01eb 0000 0001 0000 0000 0009 000e  ................
000000b0: 0158 01f4 0156 01fe 0000 0004 0000 0000  .X...V..........
000000c0: 000a 000e 0158 0207 0156 0211 0000 0004  .....X...V......
000000d0: 0000 0000 000b 000e 0158 021a 0156 0224  .........X...V.$
000000e0: 0000 0004 0000 0000 000c 000e 0158 022d  .............X.-
000000f0: 0156 0237 0000 0004 0000 0000 000d 000e  .V.7............
00000100: 0158 0000 0000 0240 0000 0000 0000 0000  .X............
00000110: 000e 000e 0158 0000 0000 0249 0000 0000  .....X.....I....
00000120: 0000 0000 000f 000e 0158 0252 0156 025c  .........X.R.V.\
00000130: 0000 0004 0000 0000 0010 000e 0158 0265  .............X.e
00000140: 0156 026f 0000 0004 0000 0000 4f75 7470  .V.o........Outp
00000150: 7574 2033 3300 2e00 0000 bb80 0101 0018  ut 33...........
00000160: 0400 0018 0018 000e 496e 7075 7420 3031  ........Input 01
00000170: 004f 7574 7075 7420 3334 0049 6e70 7574  .Output 34.Input
00000180: 2030 3200 4f75 7470 7574 2033 3500 496e   02.Output 35.In
00000190: 7075 7420 3033 004f 7574 7075 7420 3336  put 03.Output 36
000001a0: 0049 6e70 7574 2030 3400 4f75 7470 7574  .Input 04.Output
000001b0: 2033 3700 496e 7075 7420 3035 004f 7574   37.Input 05.Out
000001c0: 7075 7420 3338 0049 6e70 7574 2030 3600  put 38.Input 06.
000001d0: 4f75 7470 7574 2031 3700 496e 7075 7420  Output 17.Input
000001e0: 3037 0030 3200 6164 3464 0049 6e70 7574  07.02.ad4d.Input
000001f0: 2030 3800 4f75 7470 7574 2031 3700 496e   08.Output 17.In
00000200: 7075 7420 3039 004f 7574 7075 7420 3537  put 09.Output 57
00000210: 0049 6e70 7574 2031 3000 4f75 7470 7574  .Input 10.Output
00000220: 2035 3800 496e 7075 7420 3131 004f 7574   58.Input 11.Out
00000230: 7075 7420 3336 0049 6e70 7574 2031 3200  put 36.Input 12.
00000240: 496e 7075 7420 3133 0049 6e70 7574 2031  Input 13.Input 1
00000250: 3400 4f75 7470 7574 2034 3700 496e 7075  4.Output 47.Inpu
00000260: 7420 3135 004f 7574 7075 7420 3438 0049  t 15.Output 48.I
00000270: 6e70 7574 2031 3600 496e 7075 7420 3137  nput 16.Input 17
00000280: 00

                 conn     conn    dev    status  status
index  ?    ?    to chan  to dev  chan   1       2       ?    ?
0001   000e 0158 014c     0156    0168   0000    0004    0000 0000
0002   000e 0158 0171     0156    017b   0000    0004    0000 0000
0003   000e 0158 0184     0156    018e   0000    0004    0000 0000
0004   000e 0158 0197     0156    01a1   0000    0004    0000 0000
0005   000e 0158 01aa     0156    01b4   0000    0004    0000 0000
0006   000e 0158 01bd     0156    01c7   0000    0004    0000 0000
0007   000e 0158 01d0     0156    01da   0000    0004    0000 0000
0008   000e 0158 01e3     01e6    01eb   0000    0001    0000 0000
0009   000e 0158 01f4     0156    01fe   0000    0004    0000 0000
000a   000e 0158 0207     0156    0211   0000    0004    0000 0000
000b   000e 0158 021a     0156    0224   0000    0004    0000 0000
000c   000e 0158 022d     0156    0237   0000    0004    0000 0000
000d   000e 0158 0000     0000    0240   0000    0000    0000 0000
000e   000e 0158 0000     0000    0249   0000    0000    0000 0000
000f   000e 0158 0252     0156    025c   0000    0004    0000 0000
0010   000e 0158 0265     0156    026f   0000    0004    0000 0000

status 1 values:
0000 not connected or connected and self-connected
0101 connected and not self-connected

status 2 values:
0000 means Not connected (not subscribed)
0001 means Not connected (subscription unresolved)
0009 means Connected (Unicast)
0004 means Connected (subscribed to own signal)
Old 5th February 2022 | Show parent
  #19
Here for the gear
 
Hi, I pulled out wireshark to look at Dante Controller packets last night, tweeted about it, and someone on Twitter pointed me to the work you've been doing. This is great! Found the Github repo with the Python scripts too.

I'm thinking about building a box with knobs or physical buttons to control routing of audio on my network. I have a bunch of junk Grass Valley video routing aux panels with buttons and displays. I've already given those a USB device interface. I'm thinking of using an ESP32 or RPi to handle the Dante UDP packets just because there's a semiconductor shortage and I have lots of those sitting around the house not doing anything. This likely means my development will be in C rather than Python though.

Anyway, hi and if there's anything you want me to try or test on my network, I can give it a shot.

-Glen
Old 9th February 2022 | Show parent
  #20
Here for the gear
 
Quote:
Originally Posted by bikerglen ➡️
Hi, I pulled out wireshark to look at Dante Controller packets last night, tweeted about it, and someone on Twitter pointed me to the work you've been doing. This is great! Found the Github repo with the Python scripts too.

I'm thinking about building a box with knobs or physical buttons to control routing of audio on my network. I have a bunch of junk Grass Valley video routing aux panels with buttons and displays. I've already given those a USB device interface. I'm thinking of using an ESP32 or RPi to handle the Dante UDP packets just because there's a semiconductor shortage and I have lots of those sitting around the house not doing anything. This likely means my development will be in C rather than Python though.

Anyway, hi and if there's anything you want me to try or test on my network, I can give it a shot.

-Glen
I'd like to use a bank of LEDs to indicate which receivers are connected to which transmitters in my application but I don't want to continually poll all the Dante devices for their current connections. This wastes bandwidth and would not scale to say a dozen wall switches each controlling the routing in their rooms.

I decided it was time to try to see if there were any network messages that indicated a change in settings. I set up two laptops each running an instance of Dante Controller. Whenever I made a change in DC on one laptop, it was almost immediately reflected in DC on the other laptop. It was much faster than I thought it would be.

I grabbed Wireshark, toggled a few subscriptions off and on, and noticed that whenever a receiver is disconnected from its current transmitter or connected to a new transmitter, the receiver sends a multicast UDP packet to address 224.0.0.231 from port 8700 to port 8702. The packet is 35 bytes long, has the usual sequence counters, and then a few other values that can change.

In response to receiving the 35 byte multicast UDP packet, the Dante Controller app on the laptop sends a few UDP packets to port 4440 on the receiver asking what it's current subscribed to and the receiver replies with the subscribed channels.

Anybody else see this or use this successfully to rapidly update a list of subscriptions without continually polling on the devices on the network?
Old 9th February 2022 | Show parent
  #21
Here for the gear
Quote:
Originally Posted by bikerglen ➡️
I'd like to use a bank of LEDs to indicate which receivers are connected to which transmitters in my application but I don't want to continually poll all the Dante devices for their current connections. This wastes bandwidth and would not scale to say a dozen wall switches each controlling the routing in their rooms.

I decided it was time to try to see if there were any network messages that indicated a change in settings. I set up two laptops each running an instance of Dante Controller. Whenever I made a change in DC on one laptop, it was almost immediately reflected in DC on the other laptop. It was much faster than I thought it would be.

I grabbed Wireshark, toggled a few subscriptions off and on, and noticed that whenever a receiver is disconnected from its current transmitter or connected to a new transmitter, the receiver sends a multicast UDP packet to address 224.0.0.231 from port 8700 to port 8702. The packet is 35 bytes long, has the usual sequence counters, and then a few other values that can change.

In response to receiving the 35 byte multicast UDP packet, the Dante Controller app on the laptop sends a few UDP packets to port 4440 on the receiver asking what it's current subscribed to and the receiver replies with the subscribed channels. On one of my devices I get two of these responses on that port, one short and one long.

Anybody else see this or use this successfully to rapidly update a list of subscriptions without continually polling on the devices on the network?
I've looked at the multicast traffic before but couldn't make much sense of it. For me, I see the data I think you're describing on 224.0.0.233 on port 8700->8708. I don't have any clue what it's for. I don't see any meaningful differences in the response data when I change subscriptions. It seems to be sent at regular intervals.

I can now get the channel volume levels. I see this being sent to the host with Dante Controller on port 8751 about twice a second. The data is mostly "fe" for channels that aren't transmitting any data and some other value like "1c" for any that are. The lower the value, the higher the volume. The first set is the Tx channels and the second set is the Rx channels.

This data stops when the device info window closes, so of course there is an argument to the command which asks the device to stop sending that data to a client. I looked and found my computer's IP and MAC addresses in the request, so all I needed to do was change those values and it can send the data to any computer I want. 222f here is the port (8751) and appears twice in the arguments.

Code:
Request to device UDP 8800 -> 8800 sent when the device info panel is opened:
1200003efbbc30100000000090e2ba610ce
000000004001400010016000a6c782d64616e7465
000100160001001a0001222f00010000c0a80171222f0000
0000   12 00 00 3e fb bc 30 10 00 00 00 00 90 e2 ba 61   ...>..0........a
0010   0c e0 00 00 00 04 00 14 00 01 00 16 00 0a 6c 78   ..............lx
0020   2d 64 61 6e 74 65 00 01 00 16 00 01 00 1a 00 01   -dante..........
0030   22 2f 00 01 00 00 c0 a8 01 71 22 2f 00 00         "/.......q"/..

Response:
1200003efbbc301000010000001dc1081258
00000004001400010016000a6c782d64616e7465
000000000001001a0001222f00010000c0a80171222f0000
0000   90 e2 ba 61 0c e0 00 1d c1 08 12 58 08 00 45 00   ...a.......X..E.
0010   00 5a 00 00 40 00 40 11 b6 aa c0 a8 01 27 c0 a8   [email protected]                                 @
....
..'..
0020   01 71 22 60 22 60 00 46 ae b0 12 00 00 3e fb bc   .q"`"`.F.....>..
0030   30 10 00 01 00 00 00 1d c1 08 12 58 00 00 00 04   0..........X....
0040   00 14 00 01 00 16 00 0a 6c 78 2d 64 61 6e 74 65   ........lx-dante
0050   00 00 00 00 00 01 00 1a 00 01 22 2f 00 01 00 00   .........."/....
0060   c0 a8 01 71 22 2f 00 00                           ...q"/..

Response for channel volumes on port 8751:
0000   ff ff 01 1e f5 f5 00 00 00 1d c1 08 12 58 00 00   .............X..
0010   41 75 64 69 6e 61 74 65 03 00 00 80 00 80 fe fe   Audinate........
0020   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0030   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0040   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0050   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0060   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0070   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0080   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0090   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
00a0   fe fe fe fe fe fe 7a 96 fe fe fe fe fe fe fe fe   ......z.........
00b0   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
00c0   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
00d0   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
00e0   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
00f0   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0100   fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe   ................
0110   fe fe fe fe fe fe fe fe fe fe fe fe fe fe         ..............

Another request made automatically:
1200003efbbe30100000000090e2ba610ce
000000004001400010016000a6c782d64616e7465
000100160001001a0001222f00010000c0a80171222f0000
0000   12 00 00 3e fb be 30 10 00 00 00 00 90 e2 ba 61   ...>..0........a
0010   0c e0 00 00 00 04 00 14 00 01 00 16 00 0a 6c 78   ..............lx
0020   2d 64 61 6e 74 65 00 01 00 16 00 01 00 1a 00 01   -dante..........
0030   22 2f 00 01 00 00 c0 a8 01 71 22 2f 00 00         "/.......q"/..

Response:
1200003efbbe301000010000001dc1081258
00000004001400010016000a6c782d64616e7465
000000000001001a0001222f00010000c0a80171222f0000
0000   12 00 00 3e fb be 30 10 00 01 00 00 00 1d c1 08   ...>..0.........
0010   12 58 00 00 00 04 00 14 00 01 00 16 00 0a 6c 78   .X............lx
0020   2d 64 61 6e 74 65 00 00 00 00 00 01 00 1a 00 01   -dante..........
0030   22 2f 00 01 00 00 c0 a8 01 71 22 2f 00 00         "/.......q"/..

Request sent when the device info window is closed:
8800->8800
1200003efbbf30100000000090e2ba610ce
000000004001400010016000a6c782d64616e7465
000100160001001a0001222f000100000000000000000000
0000   00 1d c1 08 12 58 90 e2 ba 61 0c e0 08 00 45 00   .....X...a....E.
0010   00 5a 26 fe 00 00 80 11 00 00 c0 a8 01 71 c0 a8   .Z&..........q..
0020   01 27 22 60 22 60 00 46 84 40 12 00 00 3e fb bf   .'"`"`.F                                 @
...
>..
0030   30 10 00 00 00 00 90 e2 ba 61 0c e0 00 00 00 04   0........a......
0040   00 14 00 01 00 16 00 0a 6c 78 2d 64 61 6e 74 65   ........lx-dante
0050   00 01 00 16 00 01 00 1a 00 01 22 2f 00 01 00 00   .........."/....
0060   00 00 00 00 00 00 00 00                           ........

Response:
1200003efbbf301000010000001dc1081258
00000004001400010016000a6c782d64616e7465
000000000001001a0001222f000100000000000000000000
0000   12 00 00 3e fb bf 30 10 00 01 00 00 00 1d c1 08   ...>..0.........
0010   12 58 00 00 00 04 00 14 00 01 00 16 00 0a 6c 78   .X............lx
0020   2d 64 61 6e 74 65 00 00 00 00 00 01 00 1a 00 01   -dante..........
0030   22 2f 00 01 00 00 00 00 00 00 00 00 00 00         "/............
The modified request to start:
Code:
ip='c0a8016b' # 192.168.1.107, address to receive the data
mac='0c9d92c512f9' # mac address to receive the data
device_name='6c782d64616e7465' # lx-dante
port='222f' # 8751
bytes="1200003effff301000000000${mac}000000040014
00010016000a${device_name}
000100160001001a0001${port}00010000${ip}${port}0000"

1200003effff3010000000000c9d92c512f9000000040014
00010016000a6c782d64616e7465
000100160001001a0001222f00010000c0a8016b222f0000
And to stop:
Code:
mac='0c9d92c512f9' # mac address to receive the data
device_name='6c782d64616e7465' # lx-dante
port='222f' # 8751
bytes="1200003effff301000000000${mac}000000040014
00010016000a${device_name}
000100160001001a0001${port}000100000000000000000000"

1200003effff3010000000000c9d92c512f9000000040014
00010016000a6c782d64616e7465
000100160001001a0001222f000100000000000000000000
To identify a device (flash the red LED on the network port), send the following request on port 8700:
Code:
ffff00200a4a000090e2ba610ce00000417564696e6174650731006300000064
Old 10th February 2022
  #22
Here for the gear
 
Thanks for the additional information. I think this is something different. It's 8700->8702 on multicast address 224.0.0.231 and the packets are quite a bit shorter than the per-second status packets sent 8700->8708 on address 224.0.0.233 (I see those too).

The receiver that has the new subscription sends two packets from its IP address to multicast address 224.0.0.231 from port 8700 to port 8702 with a data length of 35. The packets look like this:

Code:
                        |- MAC ADDRESS OF RX -|  A  u  d  i  n  a  t  e
ff ff 00 23 d5 05 00 00 00 1d c1 ff fe -- -- -- 41 75 64 69 6e 61 74 65 07 31 01 02 00 00 00 00 00 01 01

ff ff 00 23 d5 06 00 00 00 1d c1 ff fe -- -- -- 41 75 64 69 6e 61 74 65 07 31 01 05 00 00 00 00 00 01 01
These are only sent when a subscription changes. The Danta Controller app then sends two unicast 16 byte packets to the receiver (ephemeral port to port 4440):

Code:
27 29 00 10 00 33 30 00 00 00 00 01 00 01 00 00 <= get subscriptions command!!!

27 29 00 10 00 34 32 00 00 00 00 01 00 01 00 00 <== unknown command
The receiver then responds with two unicast packets to the Dante Controller app (port 4440 back to the ephemeral port):

Code:
27 29 00 66 00 3d 30 00 00 01 02 02 00 01 00 06 00 48 00 34 00 39 00 58 01 01 00 0a 00 00 00 00 00 02
00 06 00 48 00 5c 00 39 00 62 01 01 00 0a 00 00 00 00 ... (subscription info redacted)

27 29 00 48 00 3e 32 00 00 01 02 01 00 10 00 00 00 02 00 01 00 00 bb 80 00 00 00 18 00 01 00 02 00 01 00 30 00
2a 00 2c 00 38 00 01 00 02 00 0a 08 02 10 e1 ef ff 7c 07 00 0a 00 01 08 00 00 00 00 0f 42 40 00 00 00 00
I don't know what the 2nd of the two packets is in each set. Anyway, I think the 35 byte packets at the start of this post are sent out to alert any controllers that the device's subscription status changed and that the controller should ask the receivers what their new subscriptions are.
Old 10th February 2022 | Show parent
  #23
Here for the gear
Quote:
Originally Posted by bikerglen ➡️
Thanks for the additional information. I think this is something different. It's 8700->8702 on multicast address 224.0.0.231 and the packets are quite a bit shorter than the per-second status packets sent 8700->8708 on address 224.0.0.233 (I see those too).
I looked at it again and you're right; it's on 8702 and definitely correlates to subscriptions.

I figured out the channel volume start/stop requests. The way it pads out the device name made it difficult for me to see the pattern to calculate the lengths needed in the requests. Once I did this and looped it I was disappointed to see this command is only supported on a few of my devices, so however the signal presence/clipping indicator on the device info window works, this isn't it. You get 253 levels of volume per channel instead of the three that I expected, so it should be good for something. By default the command causes the device to send this data for 10 seconds, but I found an argument that makes it send it forever.

I've updated my program to list channel volumes, if supported on the device. It's nice that I'm finding features that are completely unused and unknown (at least on the devices I have to test).
Old 11th February 2022 | Show parent
  #24
Here for the gear
 
Quote:
Originally Posted by s00pcan ➡️
I looked at it again and you're right; it's on 8702 and definitely correlates to subscriptions.

I figured out the channel volume start/stop requests. The way it pads out the device name made it difficult for me to see the pattern to calculate the lengths needed in the requests. Once I did this and looped it I was disappointed to see this command is only supported on a few of my devices, so however the signal presence/clipping indicator on the device info window works, this isn't it. You get 253 levels of volume per channel instead of the three that I expected, so it should be good for something. By default the command causes the device to send this data for 10 seconds, but I found an argument that makes it send it forever.
Sounds good. My ESP32 code is doing device discovery using mDNS, querying device names and channel counts, and at least receiving the subscription change notification packets. The plan for tomorrow night is to query subscriptions after power up and when the change notification packets are received. That should be enough to light up some LEDs to indicate which transmitter the receiver is currently subscribed to. Then I can work on changing subscriptions when the user presses a button and turning this into a box I can set on top of my amp to pick the source without needing a laptop or the Dante Controller app.

If I have time, I'll look at the signal presence indicator tomorrow in wireshark to see if I can gain any insights.
Old 11th February 2022
  #25
Here for the gear
I started looking into the multicast traffic and commands to ask the devices to send some specific data. By clicking on everything in Dante Controller, I found 21 types of responses so far. One of my devices seems to be hardcoded to spam my network every five seconds with seven responses.
Code:
224.0.0.129 319
224.0.0.231 8702
224.0.0.233 8708
224.0.0.251 5353
Code:
Multicast replies are dev_ip:1030 -> 224.0.0.231:8702
     len  seq  type         [mac       ]
1200 0014 5d00 1001 0000000090e2ba610ce00000 192.168.1.37:8800
1200 0014 5d01 1001 0000000090e2ba610ce00000 192.168.1.41:8800
1200 0014 5d02 1001 0000000090e2ba610ce00000 192.168.1.42:8800
1200 0014 5d07 1001 0000000090e2ba610ce00000 192.168.1.39:8800
Code:
192 ('192.168.1.37', 1036) 000eddfd4e13
Shure Inc. AD4D
96 ('192.168.1.37', 1036) 000eddfd4e13
Bklyn2 Brooklyn II
192 ('192.168.1.39', 1030) 001dc1081258
Digigram LX-DANTE
96 ('192.168.1.39', 1030) 001dc1081258
PCIe Dante PCIe IF
The response type here is 1001 in hex, so 4097 in dec. Here's the full list:
[17, 20, 32, 96, 98, 112, 120, 128, 130, 132, 146, 192, 256, 258, 260, 261, 262, 288, 4097, 4103, 4105, 4107]

Some of them I've identified and a few had obvious strings that could be parsed.
96 dante model
98 identify device
112 firmware version related
146 device reboot notice
192 make/model info
258,261 both are related to sub/unsub
4105 device lock/unlock status

Code:
Send to 8700 on the device and wait for a reply on 224.0.0.231:8702
mac='90e2ba610ce0'    

cmd_args='00c100000000' # type 192, make/model
cmd_args='006100000000' # type 92, dante model
cmd_args='100800000064' # type 4105 lock/unlock status

bytes="ffff00200fdb0000${mac}0000417564696e6174650731${cmd_args}"
ffff00200fdb00000c9d92c512f90000417564696e617465073100c100000000
Here, 00c1 is the command to run, 193. So this is going to give a response with 192 (make/model info). The response isn't always the lower number; the device lock status request is made on 4104 and responds on 4105.

Quote:
Originally Posted by bikerglen ➡️
27 29 00 48 00 3e 32 00 00 01 02 01 00 10 00 00 00 02 00 01 00 00 bb 80 00 00 00 18 00 01 00 02 00 01 00 30 00
2a 00 2c 00 38 00 01 00 02 00 0a 08 02 10 e1 ef ff 7c 07 00 0a 00 01 08 00 00 00 00 0f 42 40 00 00 00 00
One thing I see in there is the sample rate, 00bb80 (48kHz).
Old 13th February 2022 | Show parent
  #26
Here for the gear
 
Quote:
Originally Posted by s00pcan ➡️
I started looking into the multicast traffic and commands to ask the devices to send some specific data. By clicking on everything in Dante Controller, I found 21 types of responses so far. One of my devices seems to be hardcoded to spam my network every five seconds with seven responses.
Code:
224.0.0.129 319
224.0.0.231 8702
224.0.0.233 8708
224.0.0.251 5353
Code:
Multicast replies are dev_ip:1030 -> 224.0.0.231:8702
     len  seq  type         [mac       ]
1200 0014 5d00 1001 0000000090e2ba610ce00000 192.168.1.37:8800
1200 0014 5d01 1001 0000000090e2ba610ce00000 192.168.1.41:8800
1200 0014 5d02 1001 0000000090e2ba610ce00000 192.168.1.42:8800
1200 0014 5d07 1001 0000000090e2ba610ce00000 192.168.1.39:8800
Code:
192 ('192.168.1.37', 1036) 000eddfd4e13
Shure Inc. AD4D
96 ('192.168.1.37', 1036) 000eddfd4e13
Bklyn2 Brooklyn II
192 ('192.168.1.39', 1030) 001dc1081258
Digigram LX-DANTE
96 ('192.168.1.39', 1030) 001dc1081258
PCIe Dante PCIe IF
The response type here is 1001 in hex, so 4097 in dec. Here's the full list:
[17, 20, 32, 96, 98, 112, 120, 128, 130, 132, 146, 192, 256, 258, 260, 261, 262, 288, 4097, 4103, 4105, 4107]

Some of them I've identified and a few had obvious strings that could be parsed.
96 dante model
98 identify device
112 firmware version related
146 device reboot notice
192 make/model info
258,261 both are related to sub/unsub
4105 device lock/unlock status

Code:
Send to 8700 on the device and wait for a reply on 224.0.0.231:8702
mac='90e2ba610ce0'    

cmd_args='00c100000000' # type 192, make/model
cmd_args='006100000000' # type 92, dante model
cmd_args='100800000064' # type 4105 lock/unlock status

bytes="ffff00200fdb0000${mac}0000417564696e6174650731${cmd_args}"
ffff00200fdb00000c9d92c512f90000417564696e617465073100c100000000
Here, 00c1 is the command to run, 193. So this is going to give a response with 192 (make/model info). The response isn't always the lower number; the device lock status request is made on 4105 and responds on 4105.



One thing I see in there is the sample rate, 00bb80 (48kHz).
I have different LEDs lighting up to indicate which transmitters one of my receivers is connected to now. When I change a subscription in Dante Controller, the LEDs indicate the change pretty much immediately. Next step is to add the ability to push a button to change subscriptions. I'll have a make a short video once that's done. The Arduino code for what I have so far is posted at https://github.com/bikerglen/esp32-dante-test

Now I'm thinking about scalability. Having a dozen of these little controllers all pinging all the Dante devices all the time might not be scalable. It might be better to have one central controller (maybe your python code running on an RPi or Intel NUC) that communicates with all the Dante devices then a bunch of smaller controllers with buttons and LEDs that communicate with the central controller using MQTT. MQTT would also fit in very well with Home Assistant and other DIY home automation projects.

I might write a Dante routing control to MQTT bridge once I get the real hardware built for my current application and installed next to the amp in my garage.
Old 13th February 2022 | Show parent
  #27
Here for the gear
Quote:
Originally Posted by bikerglen ➡️
Now I'm thinking about scalability. Having a dozen of these little controllers all pinging all the Dante devices all the time might not be scalable. It might be better to have one central controller (maybe your python code running on an RPi or Intel NUC) that communicates with all the Dante devices then a bunch of smaller controllers with buttons and LEDs that communicate with the central controller using MQTT. MQTT would also fit in very well with Home Assistant and other DIY home automation projects.
Of course, some kind of client/server model is ideal, as waiting on these network requests takes time. I initially made my program as a one-shot CLI tool to list information about Dante devices on the network or to control a device. As of now my program is finding all of the device names and then continuing on to make commands to those devices sequentially to get the channels and other info, but this isn't as good as doing them async for each device. Once I have this done, I could make a client that takes a script to do dozens of operations in seconds, such as applying a preset file exported from Dante Controller or some kind of custom script syntax from a file. At that point, the program would be useful for scripting devices fully.

The server should get a list of mDNS devices and watch them for changes. Most devices have 2-4 netaudio type services. After some reasonable timeout, gather the services related to one host and see what controls it offers. The chain would be something like this: find services, group by host, make requests on control ports (4440, 8700, 8800, etc.) for any known information (skipping those that are known to be unsupported on the device model), parse responses as they come in and add the information to a device object. Then, wait for the mDNS TTL and add/remove/update events to update the device list. Another loop would check for changes to device settings like subscription changes or control requests from a client program.

I found that one of my devices was terrible at responding to requests for device info on 224.0.0.231:8702. To figure out how to improve this, I made a program that requests the device make/model and then the dante board model/model id. If I send both requests right after one another, I never see the second response. The absolute minimum time I have to wait to get a second response is two seconds. Most devices aren't like this and can respond to both requests without a problem.

Example python script showing slow responses: https://gist.github.com/chris-ritsen...ea2da80ca4f3b1

Code:
./network_audio_controller.py -la
dinet-tx-1 192.168.1.41
lx-dante 192.168.1.39

./dante_device_info.py 192.168.1.41
Radial Engineering DiNET-TX UltimoX2
Time taken: 0.2023000717163086

./dante_device_info.py 192.168.1.39
Digigram LX-DANTE PCIe Dante PCIe IF
Time taken: 2.1070830821990967
When I started using the sequence ID I was surprised to see faster responses from the device I was having trouble with:
https://gist.github.com/chris-ritsen...a506d707c07677

Code:
./dante_device_info.py 192.168.1.41
Radial Engineering DiNET-TX UltimoX2
Time taken: 0.02202773094177246

./dante_device_info.py 192.168.1.39
Digigram LX-DANTE PCIe Dante PCIe IF
Time taken: 0.11317229270935059
The device still takes multiple attempts to get a response and isn't as fast as the others, but all response times are improved. Therefore, the sequence ID is critical to making this work properly for even one client.
Old 23rd February 2022
  #28
Here for the gear
Instead of adding features this past week, I did the boring work on my tool to change the CLI library to simplify commands and options as well as making it into easily installable packages. If you're on Arch Linux like I am, use aur/python-netaudio. Otherwise, install from PyPI with pip or pipx like this:
Code:
pipx install netautio
pip install netaudio
Code:
$ netaudio device list
avio-input-2
avio-output-2
avio-usb
avio-usb-2
avio-usb-3
dinet-tx-1
lx-dante
Code:
$ netaudio subscription list
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- [email protected] [Subscription unresolved]
[email protected] <- [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- Output [email protected] [Subscription unresolved]
[email protected] <- [email protected] [Connected (Unicast)]
[email protected] <- [email protected] [Connected (Unicast)]
More usage examples

I'm currently working on a server that sends requests for information to devices and parses all known types of messages and dumps the information into redis (a cache on the network).
Old 9th March 2022
  #29
Here for the gear
 
Javascript NPM Package

Hi there, I've been following this thread for a while and have been trying to control Dante devices in javascript. s00pcan's work identifying the sequence number got me through the final hurdle! The python library looks great

Here's where I've got to so far -

https://github.com/ryanmccartney/dante-control


Hopefully, it's of some use - I've got to do some more work to parse channel names.
Old 9th March 2022 | Show parent
  #30
Here for the gear
Eventually I hope we're going to have client libraries in every language for this. Node was one of my top choices, but I wanted to learn more about python instead.

Quote:
Originally Posted by ryan.mccartney ➡️
I've got to do some more work to parse channel names.
The channel names are weird. For RX, you always get the same channel names (user renamed or defaults). For TX, you have two different requests with a flag changed to get the default names or another request to get any changed names. You'll always want to use the changed names when targeting a TX channel when creating a subscription (crosspoint in your program), so doing the request to get the original names is almost pointless. When exporting a preset from Dante Controller, these renamed channels are called "friendly names" in the XML file. I haven't explored how high sample rates affect data in the responses for channel count or channel names yet; I've been assuming 48kHz everywhere.
📝 Reply

Similar Threads

Thread / Thread Starter Replies / Views Last Post
replies: 128 views: 28179
Avatar for mudseason
mudseason 28th October 2016
replies: 52676 views: 3973428
Avatar for St Thomas
St Thomas 2 hours ago
replies: 29 views: 3378
Avatar for Mat@Ferrofish
[email protected] 4 days ago
Post Reply

Welcome to the Gearspace Pro Audio Community!

Registration benefits include:
  • The ability to reply to and create new discussions
  • Access to members-only giveaways & competitions
  • Interact with VIP industry experts in our guest Q&As
  • Access to members-only sub forum discussions
  • Access to members-only Chat Room
  • Get INSTANT ACCESS to the world's best private pro audio Classifieds for only USD $20/year
  • Promote your eBay auctions and Reverb.com listings for free
  • Remove this message!
You need an account to post a reply. Create a username and password below and an account will be created and your post entered.


 
 
Slide to join now Processing…

Forum Jump
Forum Jump