Control Roon using OpenHab

(Ludovic Boyer) #1

Hi All,

I unsuccessfully tried to control Roon via OpenHab by directly executing an app.js API.
Then, thanks to the suggestion of @St0g1e and @Matthew_Clegg, I am now able to control Roon from OpenHab.

Here is how I did it. Hopefully, it will help someone.

Each time I want to send a command to Roon, I use an HTTP request to an app.js which is listening on my Raspebbry pi’s port n° 3000. When the app.js receives a request, it interprets it then send the appropriate command to Roon. The app.js and the package.json files can be found in the first post of the topic Control Roon from the iOS Notification Center as a widget.

When the app.js and the package.json files are properly installed, OpenHab can be configured as follow.
I wanted to be able to select the Roon’s zone and command prior to sending the control command to Roon. Thus, I needed a list pointing to the different zones and a list pointing to the different commands.

Items

Code is below

/*Roon*/
Number Roon_cmd "Commands to be sent to Roon" (Multimedia, gRoon)
Number Roon_zone "Zone selection of Roon" (Multimedia, gRoon)
Switch Roon_valid "valid selection" (Multimedia, gRoon)

Roon_cmd and Roon_zone will be a list of numbers in the SiteMap. The numbers will then be interpreted within a Rule.
The switch Roon_valid will allow me to send the control to Roon.

SiteMap

Code is below

Frame
{
	Text label="Hifi Salon" icon="musical-note"
	{
		Selection item=Roon_zone label="Roon zone" icon="Audio-settings" mappings=[1="Salon", 2="Mezzanine", 3="Chambre"]
		Selection item=Roon_cmd label="Roon cmd" icon="Audio-settings" mappings=[1="play/pause", 2="next", 3="previous"]
		Switch item=Roon_valid label="envoi cmd a Roon" icon="volume"
	}
}

The 2 Selections are drop down menus pointing to the items Roon_zone and Roon_cmd. Both menus map names to numbers. For instance, if I select Salon from the menu, the value 1 will be mapped to the item Roon_zone.

Once the zone and the command are selected, I switch on the item Roon_valid.

Now, a rule is needed to interpret the zone and command selection and to control Roon once the item Roon_valid is switched on.

##Rule

Code is below

rule "Roon simple cmd"
	when Item Roon_valid changed
then
	if(Roon_valid.state == ON)
	{
		var String cmd="nonedshjhdjs";
		var String zone="none";
		switch Roon_cmd.state{
			case 1: cmd="playpause"
			case 2: cmd="next"
			case 3: cmd="previous"
		}
		switch Roon_zone.state{
			case 1: zone="HQPlayer"
			case 2: zone="Mezzanine"
			case 3: zone="Chambre"
		}
		
		postUpdate(Roon_valid, OFF)
		val resluts = sendHttpGetRequest("http://192.168.xxx.xxx:3000/api?command=" + cmd + "&zone=" + zone, 3000)
	}
end

The rule does the following:
When the state of the switch Roon_valid change, the rule starts. If the state of Roon_valid is OFF, it does nothing and rule ends. If the state of Roon_valid is ON, then the rule looks at the values of Roon_cmd and Roon_zone. For instance, if Roon_cmd has the value 1 (this happens if I select play/pause from the drop down menu of OpenHab site), the text playpause is attributed to the variable cmd. The same goes for Roon_zone where a text mapped to a defined number is attributed to the variable zone.
Once this is done, the rule has two more actions. The first one is to switch back Roon_valid to an OFF state and the second one is to send the HTTP request through the command sendHttpGetRequest. The argument of this command contains the necessary code and the texts attributed to the variables cmd and zone.
For this command to be successful, you need to provide the IP address of the device running the app.js.

##Automatically start the app.js with the Raspberry pi

Now that OpenHab is configured, I had to find a way to launch the app.js on my headless Raspberry pi. If I did so through ssh, the app.js would be killed as soon as I stopped the ssh. If I ran the app.js in the background, using the command node app.js &. The app would be killed sometime after the ssh was stopped. I cannot explained why. The only solution I came up with was to start the app.js during the boot sequence of the Raspberry pi. This will be show below, after the next paragraph.

Then, I tried to find a way to restart the app.js after it had been killed, just in case. I found the answer in this forum. I adapted the given script and I stored it under the name Roon_API_Monitor.sh at the location /usr/local/bin/. It is shown below:

#!/bin/bash

cd "/home/pi/roon/roon-extension-webserver/";

until node app.js; do
    echo "Server 'myserver' crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

This is how I understood how it works. first it starts the app.js. Then, it watches for the output of the process corresponding to app.js, which is 1 if it is stopped normally. In this case the script is done and stops. Now, if app.js crashes, the output of the process corresponding to it will be a number different from 1. In this case, it will restart app.js.

This script has to start when the Raspberry pi starts. This is done by editing the rc.local file located at /etc/ with the following line:

Roon_API_Monitor.sh &

I found the instructions for the modification of rc.local here.

Now the Raspberry pi needs to be rebooted and voilà!

Hope this helps.

Cheers,

Ludovic