Monoprice 6-zone Audio amp items, sitemap & rules

@jroffey

I modified @bartus great work to adapt to using a GlobalCache iTach Flex. I also modified the script to use group persistence, which greatly reduced the repetitive code for each zone.

Setup notes:

  • You must set up mapDB persistence

  • Refer to Design Pattern: Working with Groups in a Rule for more information
    Design Pattern: Working with Groups in Rules

  • Set up your Monoprice GlobalCache iTach Flex Thing for “Direct” serial communication (no .map file required)

  • Enable 2-way communication for the iTach thing using “%0D%0A” as the End-of-message Delimiter

Item file:

Group gZonePowerSwitch (all)
Group gZoneVolume (all)
Group gZoneMuteSwitch (all)
Group gZoneTone (all)
Group gZoneBalance (all)
Group gZoneSource (all)
Group gMonoPriceStatus (all)

String AudioMTX             "Audio Matrix"           { channel="globalcache:itachFlex:audiomtx:sl-m1#c1-direct" }
String AudioMTX_Receive     "Audio Matrix Receive"   { channel="globalcache:itachFlex:audiomtx:sl-m1#c1-receive" }
Switch MonoPrice_Refresh    "Refresh String"
//String MonoPrice_Receive_String "Received Response"
String MonoPrice_Status     "MonoPrice Status [%s]"
String MonoPrice_Status_G1  "MP G1 (Zone) [%s]"             (gMonoPriceStatus)
String MonoPrice_Status_G2  "MP G2 (PA Status) [%s]"        (gMonoPriceStatus)
String MonoPrice_Status_G3  "MP G3 (Pwr Status) [%s]"       (gMonoPriceStatus)
String MonoPrice_Status_G4  "MP G4 (Mute Status) [%s]"      (gMonoPriceStatus)
String MonoPrice_Status_G5  "MP G5 (DT Status) [%s]"        (gMonoPriceStatus)
Number MonoPrice_Status_G6  "MP G6 (Volume Status) [%.0f]"  (gMonoPriceStatus)
Number MonoPrice_Status_G7  "MP G7 (Treble Status) [%.0f]"  (gMonoPriceStatus)
Number MonoPrice_Status_G8  "MP G8 (Bass Status) [%.0f]"    (gMonoPriceStatus)
Number MonoPrice_Status_G9  "MP G9 (Balance) [%.0f]"        (gMonoPriceStatus)
Number MonoPrice_Status_G10 "MP G10 (Src Status) [%.0f]"    (gMonoPriceStatus)
String MonoPrice_Status_G11 "MP G11 (Keypad Status) [%s]"   (gMonoPriceStatus)
String MonoPrice_Z11         "Zone 1 Status [%s]"
String MonoPrice_Z12         "Zone 2 Status [%s]"
String MonoPrice_Z13         "Zone 3 Status [%s]"
String MonoPrice_Z14         "Zone 4 Status [%s]"
String MonoPrice_Z15         "Zone 5 Status [%s]"
String MonoPrice_Z16         "Zone 6 Status [%s]"
Switch MonoPrice_Z11_Power   "Zone 1 Power [%s]"        <switch>		 (gZonePowerSwitch)
Switch MonoPrice_Z12_Power   "Zone 2 Power [%s]"        <switch>		 (gZonePowerSwitch)
Switch MonoPrice_Z13_Power   "Zone 3 Power [%s]"        <switch>		 (gZonePowerSwitch)
Switch MonoPrice_Z14_Power   "Zone 4 Power [%s]"        <switch>		 (gZonePowerSwitch)
Switch MonoPrice_Z15_Power   "Zone 5 Power [%s]"        <switch>		 (gZonePowerSwitch)
Switch MonoPrice_Z16_Power   "Zone 6 Power [%s]"        <switch> 	 (gZonePowerSwitch)
Switch MonoPrice_Z11_Mute    "Zone 1 Mute [%s]"   	   <mute> 		 (gZoneMuteSwitch)
Switch MonoPrice_Z12_Mute    "Zone 2 Mute [%s]"    	   <mute> 		 (gZoneMuteSwitch)
Switch MonoPrice_Z13_Mute    "Zone 3 Mute [%s]"    	   <mute> 		 (gZoneMuteSwitch)
Switch MonoPrice_Z14_Mute    "Zone 4 Mute [%s]"    	   <mute> 		 (gZoneMuteSwitch)
Switch MonoPrice_Z15_Mute    "Zone 5 Mute [%s]"     	   <mute> 		 (gZoneMuteSwitch)
Switch MonoPrice_Z16_Mute    "Zone 6 Mute [%s]"    	   <mute> 		 (gZoneMuteSwitch)
Dimmer MonoPrice_Z11_Volume  "Zone 1 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z12_Volume  "Zone 2 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z13_Volume  "Zone 3 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z14_Volume  "Zone 4 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z15_Volume  "Zone 5 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z16_Volume  "Zone 6 Volume [%02d %%]"  <soundvolume> (gZoneVolume)
Dimmer MonoPrice_Z11_Treble  "Zone 1 Treble [%02d %%]"  <treble>      (gZoneTone)
Dimmer MonoPrice_Z12_Treble  "Zone 2 Treble [%02d %%]"  <treble>      (gZoneTone)
Dimmer MonoPrice_Z13_Treble  "Zone 3 Treble [%02d %%]"  <treble>      (gZoneTone)
Dimmer MonoPrice_Z14_Treble  "Zone 4 Treble [%02d %%]"  <treble>      (gZoneTone)
Dimmer MonoPrice_Z15_Treble  "Zone 5 Treble [%02d %%]"  <treble>      (gZoneTone) 
Dimmer MonoPrice_Z16_Treble  "Zone 6 Treble [%02d %%]"  <treble>	     (gZoneTone)
Dimmer MonoPrice_Z11_Bass    "Zone 1 Bass [%02d %%]"  	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z12_Bass    "Zone 2 Bass [%02d %%]"  	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z13_Bass    "Zone 3 Bass [%02d %%]"   	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z14_Bass    "Zone 4 Bass [%02d %%]"   	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z15_Bass    "Zone 5 Bass [%02d %%]"    	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z16_Bass    "Zone 6 Bass [%02d %%]"    	<bass>		 (gZoneTone)
Dimmer MonoPrice_Z11_Balance "Zone 1 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Dimmer MonoPrice_Z12_Balance "Zone 2 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Dimmer MonoPrice_Z13_Balance "Zone 3 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Dimmer MonoPrice_Z14_Balance "Zone 4 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Dimmer MonoPrice_Z15_Balance "Zone 5 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Dimmer MonoPrice_Z16_Balance "Zone 6 Balance [%02d %%]" 	<control>	 (gZoneBalance)
Number MonoPrice_Z11_Source  "Zone 1 Source [%.0f]" 	<control>		 (gZoneSource)
Number MonoPrice_Z12_Source  "Zone 2 Source [%.0f]" 	<control>		 (gZoneSource)
Number MonoPrice_Z13_Source  "Zone 3 Source [%.0f]"	<control>		 (gZoneSource)
Number MonoPrice_Z14_Source  "Zone 4 Source [%.0f]"	<control>		 (gZoneSource)
Number MonoPrice_Z15_Source  "Zone 5 Source [%.0f]"	<control>		 (gZoneSource)
Number MonoPrice_Z16_Source  "Zone 6 Source [%.0f]"	<control>		 (gZoneSource)
//Not using the following items but here for complete reference
//String MonoPrice_Z1_PA      "Zone 1 PA Status [%s]"
//String MonoPrice_Z2_PA      "Zone 2 PA Status [%s]"
//String MonoPrice_Z3_PA      "Zone 3 PA Status [%s]"
//String MonoPrice_Z4_PA      "Zone 4 PA Status [%s]"
//String MonoPrice_Z5_PA      "Zone 5 PA Status [%s]"
//String MonoPrice_Z6_PA      "Zone 6 PA Status [%s]"
//String MonoPrice_Z1_KeyPad  "Zone 1 Key Pad Status [%s]"
//String MonoPrice_Z2_KeyPad  "Zone 2 Key Pad Status [%s]"
//String MonoPrice_Z3_KeyPad  "Zone 3 Key Pad Status [%s]"
//String MonoPrice_Z4_KeyPad  "Zone 4 Key Pad Status [%s]"
//String MonoPrice_Z5_KeyPad  "Zone 5 Key Pad Status [%s]"
//String MonoPrice_Z6_KeyPad  "Zone 6 Key Pad Status [%s]"
//Switch MonoPrice_Z1_DT      "Zone 1 Do Not Disturb [%s]"
//Switch MonoPrice_Z2_DT      "Zone 2 Do Not Disturb [%s]"
//Switch MonoPrice_Z3_DT      "Zone 3 Do Not Disturb [%s]"
//Switch MonoPrice_Z4_DT      "Zone 4 Do Not Disturb [%s]"
//Switch MonoPrice_Z5_DT      "Zone 5 Do Not Disturb [%s]"
//Switch MonoPrice_Z6_DT      "Zone 6 Do Not Disturb [%s]"

Rule:

import java.util.regex.Matcher
import java.util.regex.Pattern

var String zone
   
rule "MonoPrice Status on command change"
when      
        Item MonoPrice_Status changed or
        System started
then                      
        var String MonoPrice_ResponseExpr = "%23%3E(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)%0D%0D%0A"
        var Pattern pattern = null 
        var Matcher matcher = null
        pattern = Pattern::compile(MonoPrice_ResponseExpr)
        matcher = pattern.matcher(AudioMTX_Receive.toString)
        matcher.find()
        Thread::sleep(300)
        for(var int i = 1; i <= gMonoPriceStatus.members.size; i=i+1){
        postUpdate("MonoPrice_Status_G"+i, matcher.group(i))
    }        
end

rule "Power (G3) Update"
when
	Item MonoPrice_Status_G3 received update 
then	
	if(MonoPrice_Status_G3.state == "01"){
        val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Power", "ON")
    }
	else {	
  	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Power", "OFF")
    }        
end

rule "Mute (G4) Update"
when
	Item MonoPrice_Status_G4 received update 
then	
	if(MonoPrice_Status_G4.state == "01"){
	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Mute", "ON")
    }
	else {	
  	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Mute", "OFF")
    }  
end

rule "Volume (G6) Update"
when
	Item MonoPrice_Status_G6 received update 
then
	val Number vol = ((MonoPrice_Status_G6.state as DecimalType) / 38 * 100).intValue
	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Volume", vol.toString)
	logInfo("MonoPrice", "G6 Volume updated to zone " + num + " Volume level " + vol)      
end

rule "Treble (G7) Update"
when
	Item MonoPrice_Status_G7 received update 
then
	val Number tre = ((MonoPrice_Status_G7.state as DecimalType) / 14 * 100).intValue
	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Treble", tre.toString)
	logInfo("MonoPrice", "G7 Treble updated to zone " + num + " Treble level " + tre)     
end

rule "Bass (G8) Update"
when
	Item MonoPrice_Status_G8 received update 
then
	val Number bas = ((MonoPrice_Status_G8.state as DecimalType) / 14 * 100).intValue 
	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Bass", bas.toString)
	logInfo("MonoPrice", "G8 Bass updated to zone " + num + " Bass level " + bas)     
end

rule "Balance (G9) Update"
when
	Item MonoPrice_Status_G9 received update 
then
	val Number bal = ((MonoPrice_Status_G9.state as DecimalType) / 20 * 100).intValue
	val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Balance", bal.toString)
	logInfo("MonoPrice", "G9 Balance updated to zone " + num + " Balance " + bal)     
end

rule "Source (G10) Update"
when
	Item MonoPrice_Status_G10 received update 
then
	val sor = MonoPrice_Status_G10.state
        val int num = Integer::parseInt(MonoPrice_Status_G1.state.toString)
        postUpdate("MonoPrice_Z"+num+"_Source", sor.toString)
	logInfo("MonoPrice", "G10 Source updated to zone "+ num + " Source Number " + sor)         
end

rule "Refresh Switch" //used during system startup, cycle through each zone
when
        Item MonoPrice_Refresh received command ON or
        System started
then 
       for(var int i=11; i <= 16; i = i+1){
        AudioMTX.sendCommand("%3f"+i+"%0D%0A")
        Thread::sleep(600)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
    }
        logInfo("Monoprice", "Monoprice Amp items refreshed")
end 

rule "MonoPrice Zone Power"
when
        Item MonoPrice_Z11_Power received command or
        Item MonoPrice_Z12_Power received command or
        Item MonoPrice_Z13_Power received command or
        Item MonoPrice_Z14_Power received command or
        Item MonoPrice_Z15_Power received command or
        Item MonoPrice_Z16_Power received command
then
        Thread::sleep(100)
        val power = gZonePowerSwitch.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as SwitchItem
        val source = gZoneSource.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as NumberItem
        switch power {	
        	case MonoPrice_Z11_Power: zone ="1"
        	case MonoPrice_Z12_Power: zone ="2"
        	case MonoPrice_Z13_Power: zone ="3"
        	case MonoPrice_Z14_Power: zone ="4"
        	case MonoPrice_Z15_Power: zone ="5"
        	case MonoPrice_Z16_Power: zone ="6"
        }	        	
        if(receivedCommand==ON){
                AudioMTX.sendCommand("%3C1" + zone + "PR01%0D%0A")
                logInfo("MonoPrice", "Zone "+ zone + " Power ON")
                
                if (source.state.toString == "2") {
                zone2Power.sendCommand(ON)
                }
        }
        else if(receivedCommand==OFF){
                AudioMTX.sendCommand("%3C1" + zone + "PR00%0D%0A")
                logInfo("MonoPrice", "Zone " + zone + " Power OFF")
        }
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
end

rule "MonoPrice Zone Volume"
when
        Item MonoPrice_Z11_Volume received command or
        Item MonoPrice_Z12_Volume received command or
        Item MonoPrice_Z13_Volume received command or
        Item MonoPrice_Z14_Volume received command or
        Item MonoPrice_Z15_Volume received command or
        Item MonoPrice_Z16_Volume received command
then
	Thread::sleep(100)
        val volume = gZoneVolume.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as DimmerItem
        var Number volume_z
        switch volume {	
        	case MonoPrice_Z11_Volume: zone ="1"
        	case MonoPrice_Z12_Volume: zone ="2"
        	case MonoPrice_Z13_Volume: zone ="3"
        	case MonoPrice_Z14_Volume: zone ="4"
        	case MonoPrice_Z15_Volume: zone ="5"
        	case MonoPrice_Z16_Volume: zone ="6"
        }       
        if(receivedCommand instanceof PercentType) {           
                volume_z = receivedCommand
                volume_z = (volume_z * 38 / 100).intValue             
        } else {
                        if(receivedCommand==INCREASE)                   
                        {
                                volume_z = volume_z + 1
                        }
                        if(receivedCommand==DECREASE)
                        {
                                volume_z = volume_z - 1
                        }
                }
        if (volume_z>9) {AudioMTX.sendCommand("%3C1" + zone + "VO" + volume_z.toString + "%0D%0A") }    
        else {AudioMTX.sendCommand("%3C1" + zone + "VO0" + volume_z.toString + "%0D%0A") }
        volume.postUpdate((volume_z / 38 * 100).intValue) 
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)                             
end

rule "MonoPrice Zone Mute"
when
        Item MonoPrice_Z11_Mute received command or
        Item MonoPrice_Z12_Mute received command or
        Item MonoPrice_Z13_Mute received command or
        Item MonoPrice_Z14_Mute received command or
        Item MonoPrice_Z15_Mute received command or
        Item MonoPrice_Z16_Mute received command
then
        Thread::sleep(100)
        val mute = gZoneMuteSwitch.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as SwitchItem       
        switch mute {	
        	case MonoPrice_Z11_Mute: zone ="1"
        	case MonoPrice_Z12_Mute: zone ="2"
        	case MonoPrice_Z13_Mute: zone ="3"
        	case MonoPrice_Z14_Mute: zone ="4"
        	case MonoPrice_Z15_Mute: zone ="5"
        	case MonoPrice_Z16_Mute: zone ="6"
        }	       	
        if(receivedCommand==ON){
                AudioMTX.sendCommand("%3C1" + zone + "MU01%0D%0A")
                logInfo("MonoPrice", "Zone "+ zone + " Mute ON")
        }
        else if(receivedCommand==OFF){
                AudioMTX.sendCommand("%3C1" + zone + "MU00%0D%0A")
                logInfo("MonoPrice", "Zone " + zone + " Mute OFF")
        }                                  
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
end

rule "MonoPrice Zone Source"
when
        Item MonoPrice_Z11_Source received command or
        Item MonoPrice_Z12_Source received command or
        Item MonoPrice_Z13_Source received command or
        Item MonoPrice_Z14_Source received command or
        Item MonoPrice_Z15_Source received command or
        Item MonoPrice_Z16_Source received command
then
        Thread::sleep(100)
        val source = gZoneSource.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as NumberItem        
        switch source {	
        	case MonoPrice_Z11_Source: zone ="1"
        	case MonoPrice_Z12_Source: zone ="2"
        	case MonoPrice_Z13_Source: zone ="3"
        	case MonoPrice_Z14_Source: zone ="4"
        	case MonoPrice_Z15_Source: zone ="5"
        	case MonoPrice_Z16_Source: zone ="6"
        }	
        AudioMTX.sendCommand("%3C1" + zone + "CH0" + source.state.toString + "%0D%0A")
        if (source.state.toString == "2") {
        zone2Power.sendCommand(ON)
        }
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
end

rule "MonoPrice Zone Tone"
when
        Item MonoPrice_Z11_Treble received command or
        Item MonoPrice_Z12_Treble received command or
        Item MonoPrice_Z13_Treble received command or
        Item MonoPrice_Z14_Treble received command or
        Item MonoPrice_Z15_Treble received command or
        Item MonoPrice_Z16_Treble received command or
        Item MonoPrice_Z11_Bass received command or
        Item MonoPrice_Z12_Bass received command or
        Item MonoPrice_Z13_Bass received command or
        Item MonoPrice_Z14_Bass received command or
        Item MonoPrice_Z15_Bass received command or
        Item MonoPrice_Z16_Bass received command
then
        var Number toneslider_z
        var String tone_z
        Thread::sleep(100)
        val tone = gZoneTone.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as DimmerItem       
        switch tone {	
        	case MonoPrice_Z11_Treble: {
        	zone ="1" 
        	tone_z = "1TR" 
        	}
        	case MonoPrice_Z12_Treble: {
        	zone ="2" 
        	tone_z = "2TR"
        	}
        	case MonoPrice_Z13_Treble: {
        	zone ="3" 
        	tone_z = "3TR"
        	}
        	case MonoPrice_Z14_Treble: {
        	zone ="4"
        	tone_z = "4TR"
        	}
        	case MonoPrice_Z15_Treble: {
        	zone ="5"
        	tone_z = "5TR"
        	}
        	case MonoPrice_Z16_Treble: {
        	zone ="6"
        	tone_z = "6TR"
        	}
        	case MonoPrice_Z11_Bass: {
        	zone ="1"
        	tone_z = "1BS"
        	}
        	case MonoPrice_Z12_Bass: {
        	zone ="2"
        	tone_z = "2BS"
        	}
        	case MonoPrice_Z13_Bass: {
        	zone ="3"
        	tone_z = "3BS"
        	}
        	case MonoPrice_Z14_Bass: {
        	zone ="4"
        	tone_z = "4BS"
        	}
        	case MonoPrice_Z15_Bass:{ 
        	zone ="5"
        	tone_z = "5BS"
        	}
        	case MonoPrice_Z16_Bass: {
        	zone ="6"
        	tone_z = "6BS"
        	}
        }	
        if(receivedCommand instanceof PercentType) {                    
                toneslider_z = receivedCommand
                toneslider_z = (toneslider_z * 14 / 100).intValue             
        } else {
                        if(receivedCommand==INCREASE)                   
                        {
                                toneslider_z = toneslider_z + 1
                        }
                        if(receivedCommand==DECREASE)
                        {
                                toneslider_z = toneslider_z - 1
                        }
                }
        if (toneslider_z>9) {AudioMTX.sendCommand("%3C1" + tone_z + toneslider_z.toString + "%0D%0A") }    
        else {AudioMTX.sendCommand("%3C1" + tone_z + "0" + toneslider_z + "%0D%0A") }
        tone.postUpdate((toneslider_z / 14 * 100).intValue)                              
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
end

rule "MonoPrice Zone Balance"
when
        Item MonoPrice_Z11_Balance received command or
        Item MonoPrice_Z12_Balance received command or
        Item MonoPrice_Z13_Balance received command or
        Item MonoPrice_Z14_Balance received command or
        Item MonoPrice_Z15_Balance received command or
        Item MonoPrice_Z16_Balance received command
then
        var Number balance_z
        val balance = gZoneBalance.members.filter[t|t.lastUpdate("mapdb") !== null].sortBy[lastUpdate("mapdb")].last as DimmerItem
        Thread::sleep(100)
        switch balance {	
        	case MonoPrice_Z11_Balance: zone ="1"
        	case MonoPrice_Z12_Balance: zone ="2"
        	case MonoPrice_Z13_Balance: zone ="3"
        	case MonoPrice_Z14_Balance: zone ="4"
        	case MonoPrice_Z15_Balance: zone ="5"
        	case MonoPrice_Z16_Balance: zone ="6"
        }
        
        if(receivedCommand instanceof PercentType) {                    
                balance_z = receivedCommand
                balance_z = (balance_z * 20 / 100).intValue             
        } else {
                        if(receivedCommand==INCREASE)                  
                        {
                                balance_z = balance_z + 1
                        }
                        if(receivedCommand==DECREASE)
                        {
                                balance_z = balance_z - 1
                        }
                }
        if (balance_z>9) {AudioMTX.sendCommand("%3C1" + zone + "BL" + balance_z.toString + "%0D%0A") }   
        else {AudioMTX.sendCommand("%3C1" + zone + "BL0" + balance_z.toString + "%0D%0A") }
        balance.postUpdate((balance_z / 20 * 100).intValue)                              
        AudioMTX.sendCommand("%3f1" + zone + "%0D%0A")                                            
        Thread::sleep(300)
        MonoPrice_Status.postUpdate(AudioMTX_Receive.state.toString.trim)
end

Sitemap:

Frame label="MonoPrice" {
		Switch item=MonoPrice_Refresh
		//Text item=AudioMTX_Receive
		//Text item=MonoPrice_Status
		//Text item=MonoPrice_Status_G1
		// Text item=MonoPrice_Status_G2
		// Text item=MonoPrice_Status_G3
		// Text item=MonoPrice_Status_G4
		// Text item=MonoPrice_Status_G5
		// Text item=MonoPrice_Status_G6
		// Text item=MonoPrice_Status_G7
	    // Text item=MonoPrice_Status_G8
		// Text item=MonoPrice_Status_G9
		// Text item=MonoPrice_Status_G10
		// Text item=MonoPrice_Status_G11
		Text item=MonoPrice_Z11
		Switch item=MonoPrice_Z11_Power
		Selection item=MonoPrice_Z11_Source label="Zone 1 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z11_Power==ON]
		Slider item=MonoPrice_Z11_Volume visibility=[MonoPrice_Z11_Power==ON]
		Switch item=MonoPrice_Z11_Mute visibility=[MonoPrice_Z11_Power==ON]
		Slider item=MonoPrice_Z11_Treble visibility=[MonoPrice_Z11_Power==ON]
		Slider item=MonoPrice_Z11_Bass visibility=[MonoPrice_Z11_Power==ON]
		Slider item=MonoPrice_Z11_Balance visibility=[MonoPrice_Z11_Power==ON]
		Text item=MonoPrice_Z12
		Switch item=MonoPrice_Z12_Power
		Selection item=MonoPrice_Z12_Source label="Zone 2 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z12_Power==ON]
		Slider item=MonoPrice_Z12_Volume visibility=[MonoPrice_Z12_Power==ON]
		Switch item=MonoPrice_Z12_Mute visibility=[MonoPrice_Z12_Power==ON]
		Slider item=MonoPrice_Z12_Treble visibility=[MonoPrice_Z12_Power==ON]
		Slider item=MonoPrice_Z12_Bass visibility=[MonoPrice_Z12_Power==ON]
		Slider item=MonoPrice_Z12_Balance visibility=[MonoPrice_Z12_Power==ON]
		Text item=MonoPrice_Z13
		Switch item=MonoPrice_Z13_Power
		Selection item=MonoPrice_Z13_Source label="Zone 3 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z13_Power==ON]
		Slider item=MonoPrice_Z13_Volume visibility=[MonoPrice_Z13_Power==ON]
		Switch item=MonoPrice_Z13_Mute visibility=[MonoPrice_Z13_Power==ON]
		Slider item=MonoPrice_Z13_Treble visibility=[MonoPrice_Z13_Power==ON]
		Slider item=MonoPrice_Z13_Bass visibility=[MonoPrice_Z13_Power==ON]
		Slider item=MonoPrice_Z13_Balance visibility=[MonoPrice_Z13_Power==ON]
		Text item=MonoPrice_Z14
		Switch item=MonoPrice_Z14_Power
		Selection item=MonoPrice_Z14_Source label="Zone 4 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z14_Power==ON]
		Slider item=MonoPrice_Z14_Volume visibility=[MonoPrice_Z14_Power==ON]
		Switch item=MonoPrice_Z14_Mute visibility=[MonoPrice_Z14_Power==ON]
		Slider item=MonoPrice_Z14_Treble visibility=[MonoPrice_Z14_Power==ON]
		Slider item=MonoPrice_Z14_Bass visibility=[MonoPrice_Z14_Power==ON]
		Slider item=MonoPrice_Z14_Balance visibility=[MonoPrice_Z14_Power==ON]
		Text item=MonoPrice_Z15
		Switch item=MonoPrice_Z15_Power
		Selection item=MonoPrice_Z15_Source label="Zone 5 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z15_Power==ON]
		Slider item=MonoPrice_Z15_Volume visibility=[MonoPrice_Z15_Power==ON]
		Switch item=MonoPrice_Z15_Mute visibility=[MonoPrice_Z15_Power==ON]
		Slider item=MonoPrice_Z15_Treble visibility=[MonoPrice_Z15_Power==ON]
		Slider item=MonoPrice_Z15_Bass visibility=[MonoPrice_Z15_Power==ON]
		Slider item=MonoPrice_Z15_Balance visibility=[MonoPrice_Z15_Power==ON]
		Text item=MonoPrice_Z16
		Switch item=MonoPrice_Z16_Power
		Selection item=MonoPrice_Z16_Source label="Zone 6 Source" mappings=[1=CH1,2=CH2,3=CH3,4=CH4,5=CH5,6=CH6] visibility=[MonoPrice_Z16_Power==ON]
		Slider item=MonoPrice_Z16_Volume visibility=[MonoPrice_Z16_Power==ON]
		Switch item=MonoPrice_Z16_Mute visibility=[MonoPrice_Z16_Power==ON]
		Slider item=MonoPrice_Z16_Treble visibility=[MonoPrice_Z16_Power==ON]
		Slider item=MonoPrice_Z16_Bass visibility=[MonoPrice_Z16_Power==ON]
		Slider item=MonoPrice_Z16_Balance visibility=[MonoPrice_Z16_Power==ON]
   }

Some of the lines may be excessive. I have a 3rd party iPhone app that can control my amp and I have been working on getting the refresh code in OH to read when the 3rd party app changes settings on the amp. For the record, it doesn’t refresh consistently yet but it works well if you only control using OH.

Also, note that several of the lines are commented out. I will often uncomment these line for troubleshooting purposes to see that the serial commands are being sent/received.

Hope this helps.

UPDATED 02/25/2018: Incorporated most of the suggestions from @rikoshak
Also removed much of the delay time from within the rules to speed up responsiveness.

1 Like