Python version of the Roon SDK/API


(Marcel van der Veldt) #1

So, I got bored of using the nodejs implementation and decided to write a python version of the SDK.
Documentation is not yet ready but the examples should get you up and running.

It’s available on pypi as package: https://pypi.org/project/roonapi/


(Ged) #2

As the last thing I developed in was VB for Windows V1.0 reading this post is similar to my reading of A Brief History of Time; I read it but don’t ask me to explain it afterwards :grin:


(Joe Gratz) #3

This looks amazing and I cannot WAIT to play with it. Thank you!


#4

Now that’s what I call an understatement posting.
Big kudos from me, being alienated by nodejs.
Maybe it paves the way to a plain C implementation. :wink:

Today I’m fresh into the Roon API, after some succesful first tests with nodejs I found this. However, I fail to run it. Where’s the token supposed to come from? “Stealing” a uid (as a plain hex string with dashes) from nodejs config.json didn’t work out, maybe some format is required? Is it supposed to be discovered in the Roon extension settings?


(Ben) #5

I am not particularly familiar with this library specifically, but I’ve looked at the code a little. My understanding is that the token is the one assigned to the extension by the Roon Core when it is approved in settings -> extensions by the user.

If I understand this Python library correctly, you should be able to run the extension once with no token, then approve it in the Roon settings, and save the value returned.


(Joe Gratz) #6

Right! The example code on the PyPI page shows how to do this, but it assumes the token file already exists. In my code, I do this:

   token = None
   if os.path.isfile("mytokenfile"):
    	with open("mytokenfile") as f:
    		token = f.read()
   roonapi = RoonApi(appinfo, token, host=ROON_HOST)`

If there wasn’t a token, it’ll tell you to authenticate in the Roon app, and get a token. So then at the end, to clean up, you can save the token in a file for next time:

	roonapi.stop()
	token = roonapi.token
	if token:
		with open("mytokenfile", "w") as f:
			f.write(token)

#7

When I try, the RoonApi constructor just hangs. Roon doesn’t show a new extension waiting to be authenticated. The Node.js examples work, on the same machine, so I guess it’s not a firewall issue etc.


(Joe Gratz) #8

Try passing in the literal IP address (or even 127.0.0.1) as the host attribute to the RoonApi() constructor. I couldn’t get it to autodetect either.


#9

Ah! Thanks, now I’m getting somewhere.


#10

Thanks, that was my missing key too :slight_smile:


(Marcel van der Veldt) #11

Good catch about the autodetect. It’s working on my setup but I have never tested it on another setup. The whole thing is undocumented on Roon’s side and I got it working by trial and error and reverse engineering the nodeJS implementation. The whole thing is kind of a mystery but I’ll take another look at it this weekend.


#12

Got it working on my setup.

I have an idea of extension to feed my Digital Audio Player based on tags inside the database, and something clever enough to smart synchronize. Note sure all API are there, but this is a good hobby for the next few weeks/months :slight_smile:


(Rune Lausen) #13

First of all: Thank you so much for your work on this!

The autodetect also hangs in my setup. I found out it’s because the format of the data returned from my version of Roon Core is different from what the code in discovery.py expects. I’m working on a stable fix, and will make a pull request as soon as I’m done.


(Rune Lausen) #14

@Marcel_van_der_Veldt Is it important for you to keep Python 2 compatibility?


(Marcel van der Veldt) #15

no, not at all


(Rune Lausen) #16

Great. I have made a pull request. Hope you find it useful :slight_smile: