Tuesday 13 October 2020

More Jongo Music

Objective

It is nearly two months since my last post.  Mostly tech time over that period has been spent looking at Jongo music.  The multiroom music server MuSe and album player aMuSe control what music is played on an mpd music server.  The sound is sent to a Jongo using bluetooth and distributed amongst other Jongos using caskeid - a bespoke Jongo program which shares and synchronises sound.

For some reason the bluetooth connection is not very reliable.  It could be that the RPi bluetooth device or configuration has issues or the Jongo firmware/hardware is not good enough.  For whatever reason it is not always possible to use our web applications to play music and sometimes the system cannot be restarted, evening by rebooting the Jongo and RPI.

There isn't much you can do to monitor control bluetooth devices.  On RPi bluetoothctl allows you to check the status of connections, but it doesn't always allow you to see, diagnose or correct problems.  There is a python bluetooth module (pybluez) but only has similar capabilities.  Jongos can tell you very little about their bluetooth connections.  

Consequently I decided to look again at setting up Jongos using the wireless interface.  If using the Pure app Pure Connect to control Jongos you are using wireless and can play multiple Jongos in synchronisation.  We don't have any specific documentation telling us how Pure Connect controls Jongos but we would like to achieve something similar.

Jongo Access

Our first task is to be able to access Jongos reliably.    Jongos setup a random port for wireless communication and keep the same number until rebooted.  The only way to find this port number is to use ssdp.discovery but an ssdp.discovery dialog takes about 30s and it is inconvenient to wait that long for each access.  Ellis Percival has provided a python upnp library which provides ssdp / upnp functions. His github page also provides a great tutorial on using the library to interrogate / control devices interactively with ipython. I wrote a simple program jongoPorts.py which runs a discover once a minute and stores results in a file.  All other programs just need to read the file contents to be able to access each jongo.  I also wrote a program jongocheck.py which looks out for any port changes or devices appearing / disappearing so that if testing goes wrong I can check whether device or network access issue occured.

I have been unhappy with VirginMedia wireless coverage for some time (in particular interference from the microwave) and recently purchased a cheap and cheerful router with, hopefully, a better wifi range.  Jongos only work at 2.4GHz so I setup a new 2.4GHz network and made sure that all Jongos are on that segment with DHCP allocated fixed IP addresses.  We now have our hardware and network configured and monitored to increase reliability.

Packet Capture for Reverse Engineering

Pure have discontinued their Jongo range and it never really caught on (Sonos captured the market) so there is very limited information available on how Jongos work.  The Pure Connect (PC) app does a pretty good job at allowing you to play albums or stream radio stations.  We have previously been able to instruct a Jongo to play a URL (song, album or radio stream).  However I wasn't able to work out how PC controls multiple Jongos in synchronisation.

I wrote a short python program which interrogates Jongos to find what they are doing.  This can be set up to run  and  provide frequent upates with the Bash watch command.  It shows us that we add an extra Jongo to PC, it synchronises to the first one using an RTSP stream as shown in the picture below where device Jon was running and Job was added as a second synchronised device.


It is difficult to guess the commands which PC issued to set this up so we need to capture them.  I used wireshark to monitor the wireless network 192.168.0.0/24 but it only shows ssdp multicast packets.  It  doesn't show any http packets, possibly because the packets are WPA encrypted when they circulate the network.   The subject appears to get quite complicated.  Firstly, the interface has to be in "monitor" mode not "promiscuous" mode.  Secondly, Windows does not support monitor mode and nor does the RPi built in wireless adapter.  Eventually I found that my WiPi wireless adapter does support monitor mode.  A utility airmon-ng allows you to set the adapter into monitor mode and it does show lots of information - for example you can see all devices attached to the neighbours wifi networks.  However it still didn't allow wireshark-linux to show me http dialogs.  

Close to despair, I made a breakthrough when I found fiddler which does http packet capture and allows you to look at packets in a variety of formats.   Much more significantly it allows you to set up a proxy for wireless devices on the network.  I set up my Windows computer on the wireless 2.4GHz network and setup Fiddler with port 8888 as a proxy.  I then told fiddler to configure itself for Windows and to decode https traffic.  I setup an old ipad on the 2.4GHz network and setup Windows port 8888 as a manual proxy.  Fiddle now showed all traffic through my windows computer including all ipad http traffic.

I captured Jongo related packets using fiddler, they are all xml formatted and they work with the upnp protocol.  It was very easy to see how Jongos achieve synchronisation.  The original Jongo (Jon in our example above) starts music with a SyncPlay command, it also creates a unique session id with CreateSession.  When you add another Jongo in the PureConnect client it issues a GetSession command to determine the session id.  It then tells Jon to AddUnitToSession for the second Jongo (Job).  Command RemoveUnitFromSession is used to stop playing on the second Jongo. Fiddler organises the output so it is simple to understand as shown below.


Once we know the commands to issue it is simple to implement the play/stop add/remove functions in python.

Using Synchronised Wifi


We can setup mpd to output icecast2 or http streaming and then load the stream URL to Jongo and can share it on multiple devices.   This allows us to play whatever we decide on the MuSe or aMuSe web pages on synchronised Jongos throughout the house.  There is a catch - streaming introduces an inherent delay so if you start or stop aMuSe you must wait 8s before it takes effect.  This makes it irritating using the apps interactively.  However when we want to listen to the radio or an album streaming is generally fine and we should be able to expand functionality and usefulness of JongoPanel.  MuSe and aMuSe will be targetted at playing on a single Jongo in the study.