Squeezebox and Smarthings


(Lee Charlton) #28

Hi again Mike

I'm still not quite there.

Here is what I did:
squeezeSwitch:
Created a squeezeSwitch device handler and pulished it for me.
I had edited line 68 (getNID method) to my SBS IP and CLI port - I checked this agreed with the SBS settings, advanced tab Command Line Interface port.
From the squeezeSwitch device handler I created a squeezeSwitch device with a network ID = to the SBS MAC
I then edited the preferences of the new squeezeSwitch device with three Squeezebox player MACs
sqVS:
I Created a sqVS device handler and pulished it for me.
From the sqVS device handler I created three sqVS devices. I set the Nework ID to a unique string (e.g. sqVSBedroom)
I did not edit the the prefereces of the new sqVS devices
squeezeController:
I created the smart app squeezeController and Published if for me.
SmartThings App:
Finally I added the smart app 'squeezeController' using the SmartThings mobile App by selecting: Automation, SmartApp, Add a Smart App.
In the squeezeController I specified the three sqVS devices and then then the SqueezeSwitch and saved the settings.

I now have all 4 devices and a smart App set up in my SmartThings, but when I toggle the sqVS switches nothing occurs at any of the squeezeboxes .

What have I done wrong?

I'm using Squeezebox radios and a Squeezebox Touch as my players and a SBS installed on a Raspi


(Lee Charlton) #29

Hi

Thought I was going mad, but I finally got it working, I missed that the Network ID for the squeezeSwitch device has to be the HEX IP:port of the SBS in the device defintion not just at line 68.

I had the network ID set to the MAC of my SBS as I have a couple of other devices that have their network ID encoded from their MAC.

So to get it to work In my case IP:port =192:168.01.85:9090 = C0A80155:2382 and has to be set in the device netwok ID.

To be fair it is highlighted in one of the images in post 5, I just didn't understand the significance.


(Hendre) #30

Hi to all the people who managed to get their SB devices working with Smartthings.
I have been trying for more than 6 hours to get this working without any success. I am convinced that I have followed the steps to the letter (where they are clear), but I can’t get this to work.
Lee’s description was especially useful in this regard.
Everything shows up in the Smartthings Android App as it should, but the SB Devices do not respond.
My SBS server IP is 192.168.0.9 and the CLI port is 9090. I made sure that this is the correct IP and Port – I can Telnet into the SBS PC from my laptop to that IP and Port and successfully execute commands like “info total albums?”.
After installation, I changed the IP of the SqueezeSwitch to the Hex value. I entered the MAC addresses of the 3 SB Devices.
Whereas Lee indicated that he/she did not make any changes to the Virtual Switches, I edited the Virtual Switches by adding the MAC address of each SB device to its Virtual Switches to see if I can’t get it to work.
I have now given up since I believe I’ve tried every possible permutation I can think of as far as the way the IP is entered; whether the Mac address of the SB Device should be added to the virtual switch or not; tried adding the HEX values of the IP instead of the MAC addresses in the virtual switches and many other things. Even deleted all handlers; switches and the App and started afresh.
Things I’m not sure of:
Is the only change one must make in the Device Handler code of SqueezeSwitch to set the IP address and Port to that of the SBS?
Should the IP be in the format ("192.168.0.9", 9000) or (“0xC0A80009”, 2382)?
Should the Device Mac be added to its Virtual Switch or not (it appears logical that it should be done, else how would the switch know where to find the SB device?)
Should the MAC Address of the SB device be added to both the SqueezeSwitch as well as the Virtual switches (if the latter is used), or only to the virtual switches?
I don’t suppose it is important, but just in case – I have more than 3 SB devices on my network, but for starters I only tried to set up 3 of them, since the Device Handler is configured for 3 devices.
I'll appreciate any assistance immensely.


(Lee Charlton) #31

Hi Hendre

Sorry to hear you are struggling, it took me some time to make it work with Mike's help, but it was worth doing.

You are correct I did not modify the SqVS switchs except the name.

I have pasted a copy of My Devices in the image below, maybe that will help you out .
The device Network Id for the sqVS is just any unique number.
For the squeezeSwitch I have used my IP and port Hex encoded, notice there is no 0x leader as hinted in your post

To address your questions:
I only made one change to the squeezeSwitch
Line 68 for me looks like this:
log.debug makeNetworkId("192.168.1.85", 9090) //your squeeze server CLI interface ip address and port
Notice the port is 9090, your post was 9000. - I missed this the first time or two around. You should use whatever worked for the Telnet you tried.
I didn't add MAC addresses or change anything on the SqVS. The SmartApp ties things together.
You do need to add the MAC address of your SB players to the squeezeSwitch, you can do this through the ST mobile APP once you have added the device. See mine below (obviously I have obscured the MACs)

These settings will show up on the squeezeSwitch device settings on the My Device tab of the SDE.

There was no metion of the Smart App in your post I assume you are using this. See Mikes post about 6 from the top. A screen shot of the settings I used for the smart App are shown below.


The selected devices are the three sqVs then the squeezeSwitch.

I hope that helps.


(Hendre) #32

Hi again Lee
I got it to work, thank you so much. Don't know where I went wrong with my previous attempts. I had deleted the devices so I could not compare, but from memory, I suspect this was the problem "notice there is no 0x".
My Squeezeboxes are currently on a schedule controlled by Tasker (running on a tablet), so I was wondering, what are the chances of sending commands like the following with the app:
"Player Study: sync -" to "unsync" a player
"Player Study: sync 00:00:00:00:00:00 to sync players
"favorites playlist play item_id:13" to play favorite 13.
The ultimate goal would be to be able to send these commands from an app plike webCore to start the player and to play a specific playlist or internet radio station saved as a favorite depending on the time of day.
While you clever guys work that one out for us, I'm going to attempt to edit the Device Handler so that I can add my other 3 Squeezeboxes as well. (I'm a total Squeezebox junkie - even more after I bought a few Samsung Multiroom speakers - can't do half of what we can to with the Squeezebox, with them. As has been asked a million times, one would never understand why Logitech discontinues the series - I suppose they were just too far ahead of their time.)


(Lee Charlton) #33

Hendre great to hear you got it going.

I too am a Squezzebox Junkie, I have five of things plus a controller and Raspberry Pi SBS.
If you extend the App to include additional players do share the code.

You may also be intrested in RELEASE Generic Media Renderer (DLNA Speakers). Cheap Sonos Alternative (Update V2)
Some people have had sucess with this any squeezebox.


(Mike Maxwell) #34

For those interested, I have 4 squeeze players and 2 duet controllers up for grabs.
One of the players has bad analog out, optical is fine.
Both duets are fully functional, both have one row of vertical pixels that are dead.
Make me a reasonable offer, pay for the shipping and they are yours.


(Hendre) #35

I know absolutely nothing about programming, so bear that in mind when considering using these, but I managed to add 2 more players. I had to change the Smart app and squeezeSwitch code:

First the squeezeSwitch:

/**
* squeezeSwitch
*
* Copyright 2014 Mike Maxwell
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
//player mac adddresses, for each required player
preferences {
input("confp1", "string", title:"Enter Player 1 MAC",defaultValue:"00:00:00:00:00:00", required:true, displayDuringSetup:true)
input("confp2", "string", title:"Enter Player 2 MAC",defaultValue:"00:00:00:00:00:00", required:true, displayDuringSetup:true)
input("confp3", "string", title:"Enter Player 3 MAC",defaultValue:"00:00:00:00:00:00", required:true, displayDuringSetup:true)
input("confp4", "string", title:"Enter Player 4 MAC",defaultValue:"00:00:00:00:00:00", required:true, displayDuringSetup:true)
input("confp5", "string", title:"Enter Player 5 MAC",defaultValue:"00:00:00:00:00:00", required:true, displayDuringSetup:true)
}

metadata {
definition (name: "squeezeSwitch", namespace: "mmaxwell", author: "Mike Maxwell") {
capability "Switch"
//custom commands for multiple players
//use the standard (built in on/off) if you only have one player
command "p1On"
command "p1Off"
command "p2On"
command "p2Off"
command "p3On"
command "p3Off"
command "p4On"
command "p4Off"
command "p5On"
command "p5Off"
//enable and use to create the hex version of your squeeze servers CLI interface
//ip address and port, this will need to be assigned to the "Device Network Id" field
//after the device is added to your system
//command "getNid"

}

simulator {
	// TODO: define status and reply messages here
}

tiles {
	standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
    state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
    state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
    }
}
main "switch"
details(["switch"])

}

// parse events into attributes
def parse(String description) {
log.debug "Parsing '${description}'"

}

private String makeNetworkId(ipaddr, port) {
String hexIp = ipaddr.tokenize('.').collect {
String.format('%02X', it.toInteger())
}.join()
String hexPort = String.format('%04X', port())
return "${hexIp}:${hexPort}"
}
def getNID() {
log.debug makeNetworkId("192.168.0.9", 9090) //your squeeze server CLI interface ip address and port
}

// handle commands for multiple players
def p1On() {
//log.debug settings.confp1
def ha = new physicalgraph.device.HubAction("${settings.confp1} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p1Off() {
//log.debug settings.confp1
def ha = new physicalgraph.device.HubAction("${settings.confp1} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p2On() {
//log.debug settings.confp2
def ha = new physicalgraph.device.HubAction("${settings.confp2} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p2Off() {
//log.debug settings.confp2
def ha = new physicalgraph.device.HubAction("${settings.confp2} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p3On() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp3} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p3Off() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp3} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p4On() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp4} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p4Off() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp4} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p5On() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp5} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def p5Off() {
//log.debug settings.confp3
def ha = new physicalgraph.device.HubAction("${settings.confp5} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}

// command for one player only
def on() {
//log.debug "Executing 'on'"
def ha = new physicalgraph.device.HubAction("${settings.confp1} play\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}
def off() {
//log.debug "Executing 'off'"
def ha = new physicalgraph.device.HubAction("${settings.confp1} power 0\r\n\r\n",physicalgraph.device.Protocol.LAN, "${device.deviceNetworkId}")
return ha
}

And the app:

/**
* squeezeController
*
* Copyright 2014 Mike Maxwell
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "squeezeController",
namespace: "mmaxwell",
author: "Mike Maxwell",
description: "SqueezeBox virtual supervisor.",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")

/**
* VirtualSwitchParent
*
* Author: badgermanus@gmail.com
* Date: 2014-03-26
*/
preferences {
section("Connect these virtual switches to the squeeze players") {
input "switch1", title: "Study", "capability.switch", required: true
input "switch2", title: "Kitchen", "capability.switch", required: true
input "switch3", title: "Dining Area", "capability.switch", required: true
input "switch4", title: "Master Bedroom", "capability.switch", required: true
input "switch5", title: "Bar", "capability.switch", required: true

}
section("Which squeeze server?") {
	input "squeeze", "capability.switch"
}

}

def installed() {
log.debug "Installed with settings: ${settings}"
subscribe()
}

def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
subscribe()
}

def subscribe() {
subscribe(switch1, "switch.on", p1On)
subscribe(switch1, "switch.off", p1Off)
subscribe(switch2, "switch.on", p2On)
subscribe(switch2, "switch.off", p2Off)
subscribe(switch3, "switch.on", p3On)
subscribe(switch3, "switch.off", p3Off)
subscribe(switch4, "switch.on", p4On)
subscribe(switch4, "switch.off", p4Off)
subscribe(switch5, "switch.on", p5On)
subscribe(switch5, "switch.off", p5Off)
}

def p1On(evt)
{
log.debug "switchOn1($evt.name: $evt.value: $evt.deviceId)"
squeeze.p1On()
}
def p1Off(evt)
{
log.debug "switchOff1($evt.name: $evt.value: $evt.deviceId)"
squeeze.p1Off()
}
def p2On(evt)
{
log.debug "switchOn2($evt.name: $evt.value: $evt.deviceId)"
squeeze.p2On()
}
def p2Off(evt)
{
log.debug "switchOff2($evt.name: $evt.value: $evt.deviceId)"
squeeze.p2Off()
}
def p3On(evt)
{
log.debug "switchOn3($evt.name: $evt.value: $evt.deviceId)"
squeeze.p3On()
}
def p3Off(evt)
{
log.debug "switchOff3($evt.name: $evt.value: $evt.deviceId)"
squeeze.p3Off()
}
def p4On(evt)
{
log.debug "switchOn4($evt.name: $evt.value: $evt.deviceId)"
squeeze.p4On()
}
def p4Off(evt)
{
log.debug "switchOff4($evt.name: $evt.value: $evt.deviceId)"
squeeze.p4Off()
}
def p5On(evt)
{
log.debug "switchOn4($evt.name: $evt.value: $evt.deviceId)"
squeeze.p5On()
}
def p5Off(evt)
{
log.debug "switchOff5($evt.name: $evt.value: $evt.deviceId)"
squeeze.p5Off()
}

Hmmm, can't figure out how one is supposed to post code like this.


(Lee Charlton) #36

Fantastic, I'll give it a go when I get a chance. For someone with no coding skills you have have made a great start.
I have been looking at your sync and timed play list problem. It looks doable. I don't know when I will get round to it, but I'll post here if I do.


#37

Willing to take trades? I have two brand new Wink Relay units I opened and rooted for the purposes of documentation in the Wink Relay thread. I lost the receipt, hence the reason I'm still sitting on them.


(Mike Maxwell) #38

devices, almost any zwave/zigbee devices, yea, sure trade would be fine, but I don't use any HID in my HA setup...
Seriously, at this point I'll basically give them away, I just can't chuck the lot in the bin..., but If I don't find a home for them, that's where they're headed...


#39

Let's take this private. :slight_smile:


(Brian Spranger) #40

Mike, where you located or willing to ship? I love my squeezebox boom.


(Mike Maxwell) #41

I've already made a deal on them.


(John) #42

Not me unfortunately. The default version of the Media Render Connect doesn't support more than one DNLA player on the same IP:PORT combination. The beta version does I think. However all the devices (I've got 5 Squeezebox devices of various types) whilst they start as being marked as present, all soon get marked as INACTIVE and NOT PRESENT due to a bug of some kind.


(Brian Spranger) #43

I had the same problem with only one squeeze box.


(smboards@gmail.com) #44

OK guys, first I have to thank all the previous posters for their effort, has been really inspirational. Brought me back to my long-lingering idea of controlling the Squeezebox (I have a Duet setup). I doubt anybody will really benefit from it but I have thrown together a quick device handler for just playing and pausing the SqueezeBox. This is definitely rudimentary but is my first stepping stone towards the goal of having a device handler for switching between different di.fm channels. I think I should touch the capability.mediaController but not sure yet how.

    /*
 *  squeezeServer On/Off Control
 *
 *  Copyright 2017 SMBoards
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */

//Server IP address
preferences {
    input("setting_server", "string", title:"Enter Logitech Media Server IP address",defaultValue:"192.168.1.1", required:true, displayDuringSetup:true)
    input("setting_port", "string", title:"Enter server port",defaultValue:"9000", required:false, displayDuringSetup:true)
}

metadata {
    definition (name: "squeezeServer", namespace: "smboards", author: "SMBoards") {
        capability "Switch"
        command "on"
        command "off"
    }

    tiles {
        standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
        state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
        state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
        }
    }
    main "switch"
    details(["switch"])
}
// parse events into attributes
def parse(String description) {
    log.debug "Parsing '${description}'"

}

// command handlers
def on()	{
    def ha = new physicalgraph.device.HubAction
    (
        method: "GET",
        path: "/status.html?p0=play",
        headers: [HOST: "${setting_server}:${setting_port}"],
     )
    return ha
}
def off()	{
    def ha = new physicalgraph.device.HubAction
    (
        method: "GET",
        path: "/status.html?p0=pause",
        headers: [HOST: "${setting_server}:${setting_port}"],
     )
    return ha
}

(smboards@gmail.com) #45

OK now I have something that is actually quite close to my original goal. So, if anybody is still running a SqeezeBox/SqueezeServer, then check this out:

Once again, not even close to perfect but does the stuff I need :slight_smile:


(Tyler Britten) #46

This looks pretty good- good starting point for me. I think i’d like to make a smartapp that lets you configure those ‘slots’ on the player with LMS urls of your choosing- to include spotify, etc.

And actually now that they’ve added a Music Player capability…time to look at using that.
http://docs.smartthings.com/en/latest/capabilities-reference.html#music-player


(Lee Charlton) #47

Hi

Well I got round to modifying Mike’s code as requested by HENDRE so now it’s all a bit more usable. Still with the 5 player update.

If it is off use to anybody please consider donating to my favourite charity: https://www.nowdonate.com/checkout/pv0j03m4s1o1x60o6bh2

New functions are:

  • sqVS: volume control and on/off status refresh.
  • sqeezeSwitch: 3 player sync groups, 5 playlist slots, playlist and player select and on/off status refresh.

The Smart App has been updated also.

To support the status refresh I have added a bridge program that runs on the Linux box you run your SBS and a JSON Slurper device handler to receive commands back from the bridge.

Its not a simple install so there are some instructions and all the files on GitHub:
https://github.com/LeeC77/SmartThings-and-Squeezebox-Controller
sqVS:


squeezeSwitch:

Hope this works for you