Increase Speaker Volume with Alexa command


#1

1) Give a description of the problem
Trying to increase the speaker volume of a set of speakers in my house (not Sonos) with an Alexa command “Alexa increase the kitchen volume”

2) What is the expected behavior?
Not able to correctly capture the current volume setting and thus the resulting volume is not correct

3) What is happening/not happening?
Volume actually being reduced

4) Post a Green Snapshot of the pistonimage

5) Attach any logs (From ST IDE and by turning logging level to Full)
12/15/2018, 11:39:25 PM +323ms
+1ms ╔Received event [Vir Sp Volume Up].switch = on with a delay of 67ms
+10055ms ║RunTime Analysis CS > 15ms > PS > 9995ms > PE > 45ms > CE
+10056ms ║Piston waited at a semaphore for 9773ms
+10058ms ║Runtime (40797 bytes) successfully initialized in 9995ms (v0.3.109.20181207) (10056ms)
+10059ms ║╔Execution stage started
+10070ms ║║Comparison (enum) on changes_to (string) on = true (1ms)
+10072ms ║║Cancelling condition #12’s schedules…
+10073ms ║║Condition #12 evaluated true (7ms)
+10074ms ║║Cancelling condition #11’s schedules…
+10076ms ║║Condition group #11 evaluated true (state changed) (10ms)
+10116ms ║║Comparison (enum) off is (string) on = false (2ms)
+10119ms ║║Comparison (enum) off is (string) on = false (2ms)
+10123ms ║║Comparison (enum) off is (string) on = false (3ms)
+10127ms ║║Comparison (enum) off is (string) on = false (2ms)
+10131ms ║║Comparison (enum) on is (string) on = true (2ms)
+10135ms ║║Comparison (enum) off is (string) on = false (2ms)
+10141ms ║║Condition #2 evaluated true (63ms)
+10142ms ║║Condition group #1 evaluated true (state did not change) (64ms)
+10150ms ║║Cancelling statement #18’s schedules…
+10157ms ║║Executed virtual command setVariable (3ms)
+10161ms ║║Cancelling statement #14’s schedules…
+10171ms ║║Calculating (dynamic) on + (integer) 10 >> (dynamic) on10
+10176ms ║║Calculating (dynamic) on = (dynamic) on10 >> (dynamic) onon10
+10207ms ║║Executed physical command [Porch].setLevel([10]) (28ms)
+10208ms ║║Executed [Porch].setLevel (30ms)
+10214ms ║║Cancelling statement #16’s schedules…
+10275ms ║║Executed physical command [Vir Sp Volume Up].off() (55ms)
+10277ms ║║Executed virtual command [Vir Sp Volume Up].setSwitch (58ms)
+10280ms ║╚Execution stage complete. (221ms)
+10283ms ╚Event processed successfully (10282ms)


#2

This is entirely dependant on the Device Handler controlling your speakers.
(If your DH does not process that data, then neither ST nor webCoRE can access it either)

A good place to start would be the forum for your speaker’s Device Handler.


#3

Yes, I thought your original code was working. But further testing proved fatal. I’ll check the DH and see if I can glean some information. Thanks.

I can control the volume with commands like “Alexa, set the kitchen to 50 percent” and that works.


#4

What “original code”…? This is my first post here…


#5

Sorry, not exactly “your code”.
I tried to modify a piece of your code thinking it might work here. I was incorrect.

image


#6

Oh right… That concept works if your DH is able to report the current level…

For light bulbs, it is built-in, but for speakers, it would rely on the DH to gather that information.


#7

Here is the DH. Any ideas?

/**

  • SmartThings Device Handler: Russound Zone

  • Author: redloro@gmail.com

  • 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.
    */
    metadata {
    definition (name: “Russound Zone”, namespace: “redloro-smartthings”, author: "redloro@gmail.com") {

    /**

    • List our capabilties. Doing so adds predefined command(s) which
    • belong to the capability.
      */
      capability “Music Player”
      capability “Switch”
      capability “Switch Level”
      capability “Refresh”
      capability “Polling”
      capability “Sensor”
      capability “Actuator”

    /**

    • Define all commands, ie, if you have a custom action not
    • covered by a capability, you NEED to define it here or
    • the call will not be made.
    • To call a capability function, just prefix it with the name
    • of the capability, for example, refresh would be “refresh.refresh”
      */
      command “source0”
      command “source1”
      command “source2”
      command “source3”
      command “source4”
      command “source5”
      command “loudnessOn”
      command “loudnessOff”
      command “bassLevel”
      command “trebleLevel”
      command “partyModeOn”
      command “partyModeOff”
      command “allOff”
      command “zone”
      }

/**

  • Define the various tiles and the states that they can be in.
  • The 2nd parameter defines an event which the tile listens to,
  • if received, it tries to map it to a state.
  • You can also use ${currentValue} for the value of the event
  • or ${name} for the name of the event. Just make SURE to use
  • single quotes, otherwise it will only be interpreted at time of
  • launch, instead of every time the event triggers.
    */
    tiles(scale: 2) {
    multiAttributeTile(name:“state”, type:“generic”, width:6, height:4) {
    tileAttribute (“device.switch”, key: “PRIMARY_CONTROL”) {
    attributeState “on”, label:‘On’, action:“switch.off”, icon:“st.Electronics.electronics16”, backgroundColor:"#79b821", nextState:“off”
    attributeState “off”, label:‘Off’, action:“switch.on”, icon:“st.Electronics.electronics16”, backgroundColor:"#ffffff", nextState:“on”
    }
    tileAttribute (“source”, key: “SECONDARY_CONTROL”) {
    attributeState “source”, label:’${currentValue}’
    }
    }
// Row 1
controlTile("volume", "device.volume", "slider", height: 1, width: 6, range:"(0..100)") {
  state "volume", label: "Volume", action:"music Player.setLevel", backgroundColor:"#00a0dc"
}

// Row 2-3
standardTile("0", "device.source0", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Radio Air1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Radio Air1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("1", "device.source1", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Kodi", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Kodi", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("2", "device.source2", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Great Box", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Great Box", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("3", "device.source3", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Master Box", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Master Box", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("4", "device.source4", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Porch Box", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Porch Box", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("5", "device.source5", decoration: "flat", width: 2, height: 2) {
  state("off", label:"Bluetooth", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
  state("on", label:"Bluetooth", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}


// Row 4
standardTile("loudness", "device.loudness", decoration: "flat", width: 2, height: 2) {
  state "off", label:'Loudness', action:"loudnessOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff"
  state "on", label:'Loudness', action:"loudnessOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-loudness.png", backgroundColor:"#ffffff"
}
standardTile("partyMode", "device.partyMode", decoration: "flat", width: 2, height: 2, inactiveLabel: false) {
  state "off", label:'Party Mode', action:"partyModeOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff"
  state "on", label:'Party Mode', action:"partyModeOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-party.png", backgroundColor:"#ffffff"
}
standardTile("alloff", "device.status", decoration: "flat", width: 2, height: 2, inactiveLabel: false) {
  state "default", label:"All Off", action:"allOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-power.png", backgroundColor:"#ffffff"
}

// Row 5-6
standardTile("bassLevelLabel", "default", decoration: "flat", height: 1, width: 1) {
  state "default", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/bass.png"
}
controlTile("bassLevel", "device.bassLevel", "slider", height: 1, width: 3, range:"(-10..10)") {
  state "default", action:"bassLevel", backgroundColor:"#00a0dc"
}
standardTile("trebleLevelLabel", "default", decoration: "flat", height: 1, width: 1) {
  state "default", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/treble.png"
}
controlTile("trebleLevel", "device.trebleLevel", "slider", height: 1, width: 3, range:"(-10..10)") {
  state "default", action:"trebleLevel", backgroundColor:"#00a0dc"
}

standardTile("refresh", "device.status", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
  state "default", label:"Refresh", action:"refresh.refresh", icon:"st.secondary.refresh-icon", backgroundColor:"#ffffff"
}

// Defines which tile to show in the overview
main "state"

// Defines which tile(s) to show when user opens the detailed view
details([
  "state",
  "volume",
  "0","1","2","3","4","5",
  "loudness", "partyMode", "alloff",
  "bassLevelLabel", "bassLevel",
  "refresh",
  "trebleLevelLabel", "trebleLevel"
])

}
}

/**************************************************************************

  • The following section simply maps the actions as defined in
  • the metadata into onAction() calls.
  • This is preferred since some actions can be dealt with more
  • efficiently this way. Also keeps all user interaction code in
  • one place.

*/
def on() { sendCommand([“state”: 1], false) }
def off() { sendCommand([“state”: 0], false) }
def source0() { sendCommand([“source”: 0], true) }
def source1() { sendCommand([“source”: 1], true) }
def source2() { sendCommand([“source”: 2], true) }
def source3() { sendCommand([“source”: 3], true) }
def source4() { sendCommand([“source”: 4], true) }
def source5() { sendCommand([“source”: 5], true) }
def setLevel(value) { sendCommand([“volume”: (value/2).intValue()], true) }
def loudnessOn() { sendCommand([“loudness”: 1], false) }
def loudnessOff() { sendCommand([“loudness”: 0], false) }
def partyModeOn() { parent.partyMode([“state”: 1, “master”: getZone(), “source”: getSource(), “volume”: getVolume()]) }
def partyModeOff() { partyMode([“state”: 0]) }
def bassLevel(value) { sendCommand([“bass”: value+10], false) }
def trebleLevel(value) { sendCommand([“treble”: value+10], false) }
def allOff() { sendCommand([“all”: 0], false) }
def refresh() { sendCommand([], false) }
/**************************************************************************/

/**

  • Called every so often (every 5 minutes actually) to refresh the
  • tiles so the user gets the correct information.
    */
    def poll() {
    refresh()
    }

def zone(evt) {
//log.debug “ZONE${getZone()} zone(${evt})”

/*

  • Zone On/Off state (0x00 = OFF or 0x01 = ON)
    */
    if (evt.containsKey(“state”)) {
    //log.debug “setting state to ${result.state}”
    sendEvent(name: “switch”, value: (evt.state == 1) ? “on” : “off”)

    //turn off party mode
    if (evt.state == 0 || !device.currentState(“partyMode”)) {
    partyMode([“state”: 0])
    }
    }

/*

  • Zone Volume level (0x00 - 0x32, 0x00 = 0 … 0x32 = 100 Displayed)
    */
    if (evt.containsKey(“volume”)) {
    //log.debug “setting volume to ${result.volume * 2}”
    sendEvent(name: “volume”, value: evt.volume * 2)
    }

/*

  • Zone Loudness (0x00 = OFF, 0x01 = ON )
    */
    if (evt.containsKey(“loudness”)) {
    //log.debug “setting loudness to ${result.loudness}”
    sendEvent(name: “loudness”, value: (evt.loudness == 1) ? “on” : “off”)
    }

/*

  • Zone Bass level (0x00 = -10 … 0x0A = Flat … 0x14 = +10)
    */
    if (evt.containsKey(“bass”)) {
    //log.debug “setting bass to ${result.bass - 10}”
    sendEvent(name: “bassLevel”, value: evt.bass - 10)
    }

/*

  • Zone Treble level (0x00 = -10 … 0x0A = Flat … 0x14 = +10)
    */
    if (evt.containsKey(“treble”)) {
    //log.debug “setting treble to ${result.treble - 10}”
    sendEvent(name: “trebleLevel”, value: evt.treble - 10)
    }

/*

  • Zone Source selected (0-5)
    */
    if (evt.containsKey(“source”)) {
    //log.debug “setting source to ${result.source}”
    for (def i = 0; i < 6; i++) {
    if (i == evt.source) {
    state.source = i
    sendEvent(name: “source${i}”, value: “on”)
    sendEvent(name: “source”, value: “Source ${i+1}: ${evt.sourceName}”)
    }
    else {
    sendEvent(name: “source${i}”, value: “off”)
    }
    }
    }
    }

def partyMode(evt) {
// [“state”: “”, “master”: “”, “source”: “”, “volume”: “”]
//log.debug “ZONE${getZone()} partyMode(${evt})”
if (evt.containsKey(“state”)) {
sendEvent(name: “partyMode”, value: (evt.state == 1) ? “on” : “off”)
if (evt.state == 1) {
sendCommand([“state”: 1], false)
}
} else {
// exit if partyMode is off
if (getPartyMode() == 0) {
return
}
}

if (evt.containsKey(“volume”)) {
sendCommand([“volume”: evt.volume], false)
}

if (evt.containsKey(“source”)) {
sendCommand([“source”: evt.source], false)
}
}

private sendCommand(evt, broadcast) {
//log.debug “ZONE${getZone()} sendCommand(${evt}, ${broadcast})”

// send command to partyMode
if (broadcast && getPartyMode()) {
parent.partyMode(evt)
return
}

// send command to Russound
def part = “”
if (evt.size() == 1) {
part = “/${evt.keySet()[0]}/${evt.values()[0]}”
}

//log.debug “ZONE${getZone()} calling parent.sendCommand”
parent.sendCommand("/plugins/rnet/controllers/${getController()}/zones/${getZone()}${part}")
}

private getTrebelLevel() {
return device.currentState(“trebleLevel”).getValue().toInteger()
}

private getBassLevel() {
return device.currentState(“bassLevel”).getValue().toInteger()
}

private getPartyMode() {
return (device.currentState(“partyMode”).getValue() == “on”) ? 1 : 0;
}

private getVolume() {
return (device.currentState(“volume”).getValue().toInteger())/2
}

private getSource() {
for (def i = 0; i < 6; i++) {
if (device.currentState(“source${i}”).getValue() == “on”) {
return i
}
}
}

private getController() {
return new String(device.deviceNetworkId).tokenize(’|’)[1]
}

private getZone() {
return new String(device.deviceNetworkId).tokenize(’|’)[2]
}


#8

Sorry, I am booked thru the holidays… Hopefully someone else can chime in.

(although I still think the info will be easiest to gather at the forum for your Device Handler… since that is where the conversations are focused on that particular DH)


#9

SOLVED


#10

Now if I can just figure out how to determine which Alexa unit I am speaking to so that I can increase/decrease the volume of the speakers in that room ONLY.