Monoprice 6-zone Audio amp items, sitemap & rules

@rlkoshak, VERY COOL!! Thanks for the heads up, that Member Of group handler will do wonders for my rules, especially the metric crap-ton of JSON rules in my MQTT LED strip implementation ( NodeMCU MQTT LED Strip Controller Build & Config How-To Videos ). I could already improve that code tenfold with triggeringItem, but I’ll wait until 2.3 is officially out and then do it all in one shot.

BTW, the post you replied to is ~2.5 years old, back when I was just starting my adventure with OH :slight_smile:

1 Like

Somehow I got mixed up.

At least pointing out the group triggers was useful.

This amp is currently on sale. I’m wondering if this is truly a sale or if it’s just been marked down as it’s a few years old; has anyone been keeping track?

For those who own it: are you overall happy? I’m thinking about picking one up for my new house, though I haven’t purchased the home yet. I’m wary to pick up yet another piece of equipment to move, but the sale price is compelling.

That is a great price for it (I paid $550 for mine in 2014). They may be lowering the price since it’s an older product now, so I don’t know if this is the lowest it’s been or not.

Overall, I’m very happy with it - I use it with a Chromecast Audio as pretty much the only input. Combined it with their in wall speakers and I get quality audio al over the house (using 4 of the 6 zones).

Btw, hopefully their QA got better, but first two amps they sent me didn’t even turn on - third one is solid. Monoprice customer support was top notch though, expedited shipping on the two replacement amps. They let me keep one of the bad ones, so I have spare parts I guess :slight_smile:)

I’ve had mine for about 4 years and it’s been working great. I am controlling 6 zones and have 4 different sources. The only issue I had in the past was integration with my automation system and general control over my network and OH (along with Global Cache iTach Flex) solved that problem for me.

Also note this amp is also sold as a Factor Electronics V-66.

https://www.mcssl.com/store/factorelectronics/001v-66

I have found the Factor Electronics manual was better in some areas than the Monoprice version.

Another helpful app I found:

The app works great but doesnt always play nice with my OH rules.

1 Like

@swamiller @bartus

Thanks for the feedback and tips! I ordered one and am looking forward to putting it to use!

Thanks for sharing this wonderful information.

First, thank you all for sharing!
It sure saved me a day or two when trying to get my two Dayton DAX66 up and running with openHAB.
The communication is done with a cheap RS232<->USB adapter on a Linux system.
At first glance everything seemed to work with a single unit but further testing showed issues especially with all the sleeps in the rules. After a few tries I understood that a quick fix wasn’t going to work. So I ended up rewriting all the rules with the previous posted contribution as a base.

First of all. This version will not be my final, just a good enough version for now. There is for sure some more tweaks I would like to do but time is up for now :).

Here is a list of the main issue fix:

  1. To keep the user UI feedback experience at an acceptable level the zone states will not be updated until no input has been given during 1 second.
  2. Issues with the math and integer rounding at dimmer value calculation caused some item values getting stuck.
  3. The rules would grow way too much if support for slaves would be added.

Except for improving timing/sleep issues I also added some new features:

  1. The rules can now fully handle both the Master and any Slaves that may be connected.
  2. openHAB can now detect when master unit is powered ON and will automatically start to update all states.
  3. Three new status items that shows which units that is alive (answering)
  4. The stereo balance gauge is made of two dimmers that is synchronized. (Note: You can still use only one if you want to. It just felt a bit awkward for me with a single gauge for this setting.)

And a TODO list:

  1. The Dimmer calculation rule is quite intact. That part can surely be improved.
  2. Sorry @rlkoshak, I didn’t add a Gate Keeper as sophisticated as your one in your super pattern article.
  3. In order to make the rules significantly shorter I had to fiddle with the Item names to fit a get-item-by-name solution. Don’t know right now if this is a really terrible solution.

It’s been years since I did anything with openHAB so some of my ideas are probably quite terrible but I haven’t noticed anything and it is working smoothly except for an issue with the Google Home binding that is mentioned here https://community.openhab.org/t/help-with-a-few-item-warnings-oh-2-3/45832

My units are of the type Dayton Audio DAX66 but other identical brands are:

  • Monoprice 10761/MPR-SG6Z
  • Factor Electronics V66
  • McLelland MAP-1200HD
  • Omnitronic MCS-1250

Items (with Master + Slave 1)
Note: All “Audio_Zones_Dax66Amp” strings can be replaced. I think the last underscore in each item name must be kept due to dependency in a rule.

Group       gDax66AliveCheck (All)
Group       gDax66PowerSwitch (All)
Group       gDax66Volume (All)
Group       gDax66Mute (All)
Group       gDax66Tone (All)
Group       gDax66Balance (All)
Group       gDax66Source (All)
Group       gDax66CommandReceiver (All)
Group       gDax66DoNotDisturb (All)
Group       gDax66KeypadPower (All)
Group       gDax66PublicAddress (All)

/*============================================= Master unit ==============================================*/

String      Audio_Zones_Dax66Amp_RS232_Buffer    "Dax66 Send/Receive RS232 data buffer"      { serial="/dev/ttyUSB0@9600" }
String      Audio_Zones_Dax66Amp_Send            "Dax66 Send RS232 data"
String      Audio_Zones_Dax66Amp_Receive         "Dax66 Last Received RS232 data"

Switch      Audio_Zones_Dax66Amp_Alive_Check_10  "Master unit is [%s]"                  (gDax66AliveCheck)
Switch      Audio_Zones_Dax66Amp_Alive_Check_20  "Slave 1 unit is [%s]"                 (gDax66AliveCheck)
Switch      Audio_Zones_Dax66Amp_Alive_Check_30  "Slave 2 unit is [%s]"                 (gDax66AliveCheck)

Switch      Audio_Zones_Dax66Amp_Refresh         "Alive check and complete status refresh"

Switch      Audio_Zones_Dax66Amp_10PA            "All zones PA [%s]"                    <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_11PA            "Zone 1 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_12PA            "Zone 2 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_13PA            "Zone 3 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_14PA            "Zone 4 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_15PA            "Zone 5 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_16PA            "Zone 6 PA [%s]"                       <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_10PR            "All zones power [%s]"                 <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_11PR            "Zone 1 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_12PR            "Zone 2 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_13PR            "Zone 3 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_14PR            "Zone 4 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_15PR            "Zone 5 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_16PR            "Zone 6 power [%s]"                    <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_10MU            "All zones mute [%s]"   	            <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_11MU            "Zone 1 mute [%s]"   	                <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_12MU            "Zone 2 mute [%s]"    	                <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_13MU            "Zone 3 mute [%s]"    	                <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_14MU            "Zone 4 mute [%s]"    	                <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_15MU            "Zone 5 mute [%s]"     	            <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_16MU            "Zone 6 mute [%s]"    	                <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_10DT            "All zones do not disturb [%s]"        <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_11DT            "Zone 1 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_12DT            "Zone 2 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_13DT            "Zone 3 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_14DT            "Zone 4 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_15DT            "Zone 5 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_16DT            "Zone 6 do not disturb [%s]"           <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_10VO            "All zones volume [%d %%]"             <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_11VO            "Zone 1 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_12VO            "Zone 2 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_13VO            "Zone 3 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_14VO            "Zone 4 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_15VO            "Zone 5 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_16VO            "Zone 6 volume [%d %%]"                <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_10TR            "All zones treble [%d %%]"             <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_11TR            "Zone 1 treble [%d %%]"                <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_12TR            "Zone 2 treble [%d %%]"                <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_13TR            "Zone 3 treble [%d %%]"                <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_14TR            "Zone 4 treble [%d %%]"                <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_15TR            "Zone 5 treble [%d %%]"                <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_16TR            "Zone 6 treble [%d %%]"                <treble>	        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_10BS            "All zones bass [%d %%]"  	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_11BS            "Zone 1 bass [%d %%]"  	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_12BS            "Zone 2 bass [%d %%]"  	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_13BS            "Zone 3 bass [%d %%]"   	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_14BS            "Zone 4 bass [%d %%]"   	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_15BS            "Zone 5 bass [%d %%]"    	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_16BS            "Zone 6 bass [%d %%]"    	            <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_10BLL           "All zones balance Left [%d %%]"       <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_11BLL           "Zone 1 balance Left [%d %%]"          <control>           (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_12BLL           "Zone 2 balance Left [%d %%]" 	        <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_13BLL           "Zone 3 balance Left [%d %%]" 	        <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_14BLL           "Zone 4 balance Left [%d %%]" 	        <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_15BLL           "Zone 5 balance Left [%d %%]" 	        <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_16BLL           "Zone 6 balance Left [%d %%]" 	        <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_10BLR           "All zones balance Right [%d %%]"      <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_11BLR           "Zone 1 balance Right [%d %%]"         <control>           (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_12BLR           "Zone 2 balance Right [%d %%]"         <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_13BLR           "Zone 3 balance Right [%d %%]"         <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_14BLR           "Zone 4 balance Right [%d %%]"         <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_15BLR           "Zone 5 balance Right [%d %%]"         <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_16BLR           "Zone 6 balance Right [%d %%]"         <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]

Number      Audio_Zones_Dax66Amp_10CH            "All zones source [%.0f]" 	            <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_11CH            "Zone 1 source [%.0f]" 	            <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_12CH            "Zone 2 source [%.0f]" 	            <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_13CH            "Zone 3 source [%.0f]"	                <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_14CH            "Zone 4 source [%.0f]"	                <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_15CH            "Zone 5 source [%.0f]"	                <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_16CH            "Zone 6 source [%.0f]"	                <control>		    (gDax66Source)

String      Audio_Zones_Dax66Amp_11LS            "Zone 1 keypad power [%s]"             <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_12LS            "Zone 2 keypad power [%s]"             <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_13LS            "Zone 3 keypad power [%s]"             <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_14LS            "Zone 4 keypad power [%s]"             <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_15LS            "Zone 5 keypad power [%s]"             <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_16LS            "Zone 6 keypad power [%s]"             <switch>		    (gDax66KeypadPower)


/*============================================= Slave 1 ==============================================*/


Switch      Audio_Zones_Dax66Amp_20PA            "All slave 1 zones PA [%s]"            <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_21PA            "Slave 1 Zone 1 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_22PA            "Slave 1 Zone 2 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_23PA            "Slave 1 Zone 3 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_24PA            "Slave 1 Zone 4 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_25PA            "Slave 1 Zone 5 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_26PA            "Slave 1 Zone 6 PA [%s]"               <switch>		    (gDax66PublicAddress, gDax66CommandReceiver)  [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_20PR            "All slave 1 zones power [%s]"         <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_21PR            "Slave 1 Zone 1 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_22PR            "Slave 1 Zone 2 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_23PR            "Slave 1 Zone 3 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_24PR            "Slave 1 Zone 4 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_25PR            "Slave 1 Zone 5 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_26PR            "Slave 1 Zone 6 power [%s]"            <switch>		    (gDax66PowerSwitch, gDax66CommandReceiver)     [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_20MU            "All slave 1 zones mute [%s]"   	    <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_21MU            "Slave 1 Zone 1 mute [%s]"   	        <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_22MU            "Slave 1 Zone 2 mute [%s]"    	        <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_23MU            "Slave 1 Zone 3 mute [%s]"    	        <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_24MU            "Slave 1 Zone 4 mute [%s]"    	        <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_25MU            "Slave 1 Zone 5 mute [%s]"     	    <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_26MU            "Slave 1 Zone 6 mute [%s]"    	        <mute> 		        (gDax66Mute, gDax66CommandReceiver)      [ "Switchable" ]

Switch      Audio_Zones_Dax66Amp_20DT            "All slave 1 zones do not disturb [%s]"  <mute> 		    (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_21DT            "Slave 1 Zone 1 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_22DT            "Slave 1 Zone 2 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_23DT            "Slave 1 Zone 3 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_24DT            "Slave 1 Zone 4 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_25DT            "Slave 1 Zone 5 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]
Switch      Audio_Zones_Dax66Amp_26DT            "Slave 1 Zone 6 do not disturb [%s]"   <mute> 		        (gDax66DoNotDisturb, gDax66CommandReceiver)  [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_20VO            "All slave 1 zones volume [%d %%]"     <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_21VO            "Slave 1 Zone 1 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_22VO            "Slave 1 Zone 2 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_23VO            "Slave 1 Zone 3 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_24VO            "Slave 1 Zone 4 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_25VO            "Slave 1 Zone 5 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_26VO            "Slave 1 Zone 6 volume [%d %%]"        <soundvolume>       (gDax66Volume, gDax66CommandReceiver)          [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_20TR            "All slave 1 zones treble [%d %%]"     <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_21TR            "Slave 1 Zone 1 treble [%d %%]"        <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_22TR            "Slave 1 Zone 2 treble [%d %%]"        <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_23TR            "Slave 1 Zone 3 treble [%d %%]"        <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_24TR            "Slave 1 Zone 4 treble [%d %%]"        <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_25TR            "Slave 1 Zone 5 treble [%d %%]"        <treble>            (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_26TR            "Slave 1 Zone 6 treble [%d %%]"        <treble>	        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_20BS            "All slave 1 zones bass [%d %%]"  	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_21BS            "Slave 1 Zone 1 bass [%d %%]"  	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_22BS            "Slave 1 Zone 2 bass [%d %%]"  	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_23BS            "Slave 1 Zone 3 bass [%d %%]"   	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_24BS            "Slave 1 Zone 4 bass [%d %%]"   	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_25BS            "Slave 1 Zone 5 bass [%d %%]"    	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_26BS            "Slave 1 Zone 6 bass [%d %%]"    	    <bass>		        (gDax66Tone, gDax66CommandReceiver)            [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_20BLL           "All slave 1 zones balance Left [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_21BLL           "Slave 1 Zone 1 balance Left [%d %%]"  <control>           (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_22BLL           "Slave 1 Zone 2 balance Left [%d %%]" 	<control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_23BLL           "Slave 1 Zone 3 balance Left [%d %%]" 	<control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_24BLL           "Slave 1 Zone 4 balance Left [%d %%]" 	<control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_25BLL           "Slave 1 Zone 5 balance Left [%d %%]" 	<control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_26BLL           "Slave 1 Zone 6 balance Left [%d %%]" 	<control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]

Dimmer      Audio_Zones_Dax66Amp_20BLR           "All slave 1 zones balance Right [%d %%]" <control>	    (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_21BLR           "Slave 1 Zone 1 balance Right [%d %%]" <control>           (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_22BLR           "Slave 1 Zone 2 balance Right [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_23BLR           "Slave 1 Zone 3 balance Right [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_24BLR           "Slave 1 Zone 4 balance Right [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_25BLR           "Slave 1 Zone 5 balance Right [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]
Dimmer      Audio_Zones_Dax66Amp_26BLR           "Slave 1 Zone 6 balance Right [%d %%]" <control>	        (gDax66Balance, gDax66CommandReceiver)         [ "Switchable" ]

Number      Audio_Zones_Dax66Amp_20CH            "All slave 1 zones source [%.0f]" 	    <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_21CH            "Slave 1 Zone 1 source [%.0f]" 	    <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_22CH            "Slave 1 Zone 2 source [%.0f]" 	    <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_23CH            "Slave 1 Zone 3 source [%.0f]"	        <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_24CH            "Slave 1 Zone 4 source [%.0f]"	        <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_25CH            "Slave 1 Zone 5 source [%.0f]"	        <control>		    (gDax66Source)
Number      Audio_Zones_Dax66Amp_26CH            "Slave 1 Zone 6 source [%.0f]"	        <control>		    (gDax66Source)

String      Audio_Zones_Dax66Amp_21LS            "Slave 1 Zone 1 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_22LS            "Slave 1 Zone 2 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_23LS            "Slave 1 Zone 3 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_24LS            "Slave 1 Zone 4 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_25LS            "Slave 1 Zone 5 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
String      Audio_Zones_Dax66Amp_26LS            "Slave 1 Zone 6 keypad power [%s]"     <switch>		    (gDax66KeypadPower)
2 Likes

…and here are the rules that didn’t fit in the previous message :wink:

import java.util.regex.Matcher
import java.util.regex.Pattern
import org.apache.commons.lang.StringUtils

var Timer aliveCheckTimeoutTimer = null
val java.util.Map<String, Timer> inputZoneTimers = newHashMap

val updateAmpValue = [ String zoneId, String actionCode, String value, Functions.Function4<String, String, String, Functions.Function1<String, Integer>, Integer> getAmpValueAsPercentage, Functions.Function1<String, Integer> getMaxAmpValue | 
    logDebug("dax66.rules", "func updateAmpValue: On zoneId " + zoneId + ", set ampValue(" + actionCode + ") = " + value)
    switch actionCode {
        case "PA": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, if(value == "01") "ON" else "OFF") }//Public Address
        case "PR": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, if(value == "01") "ON" else "OFF") }//Power
        case "MU": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, if(value == "01") "ON" else "OFF") }//Mute
        case "DT": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, if(value == "01") "ON" else "OFF") }//Do Not Disturb 
        case "VO": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, getAmpValueAsPercentage.apply(zoneId, actionCode, value, getMaxAmpValue).toString) }//Volume
        case "TR": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, getAmpValueAsPercentage.apply(zoneId, actionCode, value, getMaxAmpValue).toString) }//Treble
        case "BS": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, getAmpValueAsPercentage.apply(zoneId, actionCode, value, getMaxAmpValue).toString) }//Bass
        case "BL": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode + "R", getAmpValueAsPercentage.apply(zoneId, actionCode, value,getMaxAmpValue).toString) }//Balance
        case "CH": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, value.right(1)) }//Source
        case "LS": { postUpdate("Audio_Zones_Dax66Amp_" + zoneId + actionCode, if(value == "01") "ON" else "OFF") }//Keypad connected
    }
]

val getAmpValueAsPercentage = [ String zoneId, String actionCode, String value, Functions.Function1<String, Integer> getMaxAmpValue | 
    val int maxAmpValue = getMaxAmpValue.apply(actionCode)
    val result = Math::round((Double::parseDouble(value) / maxAmpValue) * 100).intValue
    result
]

val getMaxAmpValue = [ String actionCode | 
    var int maxAmpValue
    switch actionCode {
        case "VO": maxAmpValue = 38
        case "TR": maxAmpValue = 14
        case "BS": maxAmpValue = 14
        case "BL": maxAmpValue = 20
    }
    maxAmpValue
]
rule "Dax66 Sending RS232"
when
    Item Audio_Zones_Dax66Amp_Send received update
then
    var String sendData = Audio_Zones_Dax66Amp_Send.state.toString
    Audio_Zones_Dax66Amp_RS232_Buffer.sendCommand(sendData)

    //This code will take care of race-conditions between frequent user input and zone update requests.
    //The idea is to wait until no user input has been done during last second in a zone before requesting an update from the amp.
    if(sendData.startsWith("<")) {
        val String zoneId = sendData.substring(1, 3)
        if(inputZoneTimers.containsKey(zoneId) && inputZoneTimers.get(zoneId) !== null) {
            inputZoneTimers.get(zoneId).reschedule(now.plusMillis(1000))
        } else {
            inputZoneTimers.put(zoneId, createTimer(now.plusMillis(1000)) [|
                Audio_Zones_Dax66Amp_Send.sendCommand("?" + zoneId + "\r")//Request an update for current zone or amp unit, just to be sure everything is up to date.
                inputZoneTimers.get(zoneId).cancel
                inputZoneTimers.remove(zoneId)
            ])
        }
    }
end

rule "Dax66 Check for received data from RS232 send/receive"
when
    Item Audio_Zones_Dax66Amp_RS232_Buffer received update
then
    //All data (send AND receive) is concatenated.
    //Each data block is terminated with at least one '\r' then a '\n' and then finally a '#' char.
    //Note: Double CR chars, '\r\r\n#' probably means the end of a RECEIVED block.
    var String rawBuffer = Audio_Zones_Dax66Amp_RS232_Buffer.state.toString
    logDebug("dax66.rules", "------>   RS232 Send/Receive: Audio_Zones_Dax66Amp_RS232_Buffer = [" + rawBuffer.replace('\r','\\r').replace('\n','\\n') + "]")
    if(rawBuffer.equals("\r\n#")) {//Master unit is powered on...
        Audio_Zones_Dax66Amp_Refresh.sendCommand(ON)//...start alive check
        return
    }
    var String[] receivedDataBlocks = StringUtils.substringsBetween(rawBuffer, ">", "#")
    if(receivedDataBlocks !== null) {
        for(String receivedData: receivedDataBlocks) {
            Audio_Zones_Dax66Amp_Receive.postUpdate(receivedData.remove("\r").remove("\n"))
            //Need this sleep here or else doubles of same data is posted to Audio_Zones_Dax66Amp_Receive
            Thread::sleep(50)
        }
    }
end

rule "Dax66 Process received data"
when
    Item Audio_Zones_Dax66Amp_Receive received update
then
    val String receivedData = Audio_Zones_Dax66Amp_Receive.state.toString
    if(receivedData !== null) {
        logInfo("dax66.rules", "Process received data: Data = [" + receivedData + "]")

        //The two rows below updates unit alive awareness for the unit that sent the received data.
        val targetSyncItem = gDax66AliveCheck.members.findFirst[ name.equals("Audio_Zones_Dax66Amp_Alive_Check_" + receivedData.left(1) + "0")]
        if(targetSyncItem.state == OFF) { targetSyncItem.sendCommand(ON) }

        var Pattern pattern = null 
        var Matcher matcher = null
        val bigResponseValueCount = 11
        if(receivedData.length == (bigResponseValueCount * 2)) {
            pattern = Pattern::compile("(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)")
            matcher = pattern.matcher(receivedData)
            if(matcher.find()) {
                for(var int i = 2; i <= bigResponseValueCount; i=i+1)
                {
                    var String actionCode = "N/A"
                    switch i {
                        case 2: { actionCode = "PA" }//Public Address
                        case 3: { actionCode = "PR" }//Power
                        case 4: { actionCode = "MU" }//Mute
                        case 5: { actionCode = "DT" }//Do Not Disturb 
                        case 6: { actionCode = "VO" }//Volume
                        case 7: { actionCode = "TR" }//Treble
                        case 8: { actionCode = "BS" }//Bass
                        case 9: { actionCode = "BL" }//Balance
                        case 10: { actionCode = "CH" }//Source
                        case 11: { actionCode = "LS" }//Keypad connected
                    }
                    logDebug("dax66.rules", "Process received data: zoneId " + matcher.group(1) + ", ampValue(" + actionCode + ") = " + matcher.group(i))
                    updateAmpValue.apply(matcher.group(1), actionCode, matcher.group(i), getAmpValueAsPercentage, getMaxAmpValue)
                }
            } else {
                logError("dax66.rules", "Process received data: matcher.find() = FAIL")
            }
        } else if(receivedData.length == 6) {
            pattern = Pattern::compile("(\\d\\d)(\\s\\s)(\\d\\d)")
            matcher = pattern.matcher(receivedData)
            if(matcher.find()) {
                logDebug("dax66.rules", "Process received data: zoneId " + matcher.group(1) + ", ampValue(" + matcher.group(2) + ") = " + matcher.group(3))
                updateAmpValue.apply(matcher.group(1), matcher.group(2), matcher.group(3), getAmpValueAsPercentage, getMaxAmpValue)
            }
        } else {
            logError("dax66.rules", "Process received data: FAILED! receivedData.length = " + receivedData.length)
        }
    }
end

rule "Refresh values from Dax66 at alive confirm"
when
    Member of gDax66AliveCheck received command
then
    if(receivedCommand == ON) {
        val aliveUnitId = triggeringItem.name.right(2)
        Audio_Zones_Dax66Amp_Send.sendCommand("?" + aliveUnitId + "\r")
    }
end

//Can't trust openHAB persistence because Dax66 values may have changed during openHAB offline time.
rule "Check if Dax66 is alive at openHAB startup"
when
    Item Audio_Zones_Dax66Amp_Refresh received command or
    System started
then 
    //Reset alive check status
    Audio_Zones_Dax66Amp_Alive_Check_10.postUpdate(OFF)
    Audio_Zones_Dax66Amp_Alive_Check_20.postUpdate(OFF)
    Audio_Zones_Dax66Amp_Alive_Check_30.postUpdate(OFF)

    //Send refresh requests and wait 5 seconds for everything to process
    aliveCheckTimeoutTimer = createTimer(now.plusSeconds(5)) [|
        aliveCheckTimeoutTimer.cancel
        aliveCheckTimeoutTimer = null
        logInfo("dax66.rules", "Alive check: Master = " + Audio_Zones_Dax66Amp_Alive_Check_10.state + "   Slave 1 = " + Audio_Zones_Dax66Amp_Alive_Check_20.state + "   Slave 2 = " + Audio_Zones_Dax66Amp_Alive_Check_30.state)
    ]

    for(var int i = 1; i <= 3; i++) {
        Thread::sleep(1000)
        Audio_Zones_Dax66Amp_Send.sendCommand("?" + i + "1PR\r")
    }
end

rule "Dax66 command handler"
when
    Member of gDax66CommandReceiver received command
then
    if(triggeringItem.state == NULL) { return }
    val String target = triggeringItem.name.substringAfterLast('_')
    val String zoneId = target.substring(0, 2)
    val String actionCode = target.substring(2, 4)
    logDebug("Dax66", "Command handler: triggeringItem.getType = " + triggeringItem.getType + "   zoneId = " + zoneId + "   actionCode = " + actionCode)

    switch triggeringItem.getType {
        case "Switch":  Audio_Zones_Dax66Amp_Send.sendCommand("<" + zoneId + actionCode + if(receivedCommand == ON) "01\r" else "00\r")
        case "Dimmer":  {
            var int maxAmpValue = getMaxAmpValue.apply(actionCode)
            var Number currentValue
            var Number newValue
            logDebug("Dax66", "Dimmer item: triggeringItem.state.getClass = " + triggeringItem.state.getClass.toString)
            if(receivedCommand instanceof PercentType) {           
                currentValue = receivedCommand
                newValue = Math::round(currentValue.doubleValue * (maxAmpValue.doubleValue / 100))             
                logDebug("Dax66", "Dimmer item (PercentType): newValue = " + currentValue + " -> " + newValue)
            } else if(receivedCommand instanceof IncreaseDecreaseType) {
                currentValue = Math::round(Double::parseDouble(triggeringItem.state.toString) * (maxAmpValue.doubleValue / 100))
                if(receivedCommand==INCREASE && currentValue < maxAmpValue) {
                    newValue = currentValue + 1
                    logDebug("Dax66", "Dimmer item (IncreaseDecreaseType/INCREASE): newValue = " + currentValue + " -> " + newValue)
                } else if(receivedCommand==DECREASE && currentValue > 0) {
                    newValue = currentValue - 1
                    logDebug("Dax66", "Dimmer item (IncreaseDecreaseType/DECREASE): newValue = " + currentValue + " -> " + newValue)
                } else { return }
            } else { 
                logWarn("Dax66", "Dimmer item: Unsupported receivedCommand type = " + receivedCommand.getClass.toString)
                triggeringItem.postUpdate(Math::round(((maxAmpValue.doubleValue / 2) / maxAmpValue) * 100) as Number) 
            }

            logDebug("Dax66", "Dimmer item: " + Math::round((currentValue.doubleValue / maxAmpValue) * 100) + "% -> " + Math::round((newValue.doubleValue / maxAmpValue) * 100) + "%")
            triggeringItem.postUpdate(Math::round((newValue.doubleValue / maxAmpValue) * 100) as Number)

            if(actionCode.equals("BL") && target.substring(4, 5).equals("L")) {
                newValue = 20 - newValue// Do some reverse calculation if LEFT balance is the triggering item. 
            }
            Audio_Zones_Dax66Amp_Send.sendCommand("<" + zoneId + actionCode + (if (newValue < 10) "0" else "") + newValue.toString + "\r")
        }
    }
end

rule "Dax66 sync left and right balance dimmers"
when
    Member of gDax66Balance received update
then
    val String targetSyncSide = if(triggeringItem.name.endsWith("L")) "R" else "L"
    val targetSyncItem = gDax66Balance.members.findFirst[ name.equals(triggeringItem.name.left(triggeringItem.name.length - 1) + targetSyncSide)]
    if(targetSyncItem.state == NULL || Integer::parseInt(triggeringItem.state.toString) + Integer::parseInt(targetSyncItem.state.toString) != 100)
        targetSyncItem.postUpdate(100 - Integer::parseInt(triggeringItem.state.toString))
    logDebug("Dax66", "Balance dimmers: " + triggeringItem.name + " = " + triggeringItem.state + "  ==>  " + targetSyncItem.name + " = " + (100 - Integer::parseInt(triggeringItem.state.toString)))
end

rule "Dax66 Zone Source"
when
        Member of gDax66Source received command
then
        val zoneIdAndActionCode = triggeringItem.name.right(4)
        Audio_Zones_Dax66Amp_Send.sendCommand("<" + zoneIdAndActionCode + "0" + receivedCommand.toString + "\r")
end

3 Likes

Hey. I am hoping you guys might be able to give me some guidance. I am new to openHAB, coming from Home Assistant.

I am having issues with my Monoprice Amp. I am still learning how to configure everything but I got my Ecobee items, sitemap, and rules working correctly.

I am using a usb to serial device that previously working with Home Assistant. I know the OS see’s the device but not sure how I know if openHAB is seeing it correctly.
“Bus 001 Device 004: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port”

I copied the items, rules, and sitemap from the 1st post here. The rules isn’t working for me but the other load just fine. Maybe it is seeing it and my only problem is I need to fix my rules?

“2019-01-09 18:52:27.435 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model ‘monoprice.items’”
“2019-01-09 18:52:46.845 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model ‘monoprice.sitemap’”

then I get errors with he rules.
“Error during the execution of startup rule ‘MonoPrice Status on command change’: No match found”
“Rule ‘MonoPrice Status on command change’: No match found” and so on.

Thanks.

What you’re seeing is just poor error-handling on my part :slight_smile: - not an actual error with your rules. Basically, when you created all the items, the String item that contains the message going to/coming from the amp is empty, and the rule that parses it errors out on the Regex pattern match. I haven’t had a chance to try @tony_alpskog 's rewrite above yet, but his rules do a better job of error-checking.

Do any of the switches on your sitemap work to control the amp zones? If not, you’ll need to make sure that the String AudioMTX is actually being populated with your commands, and it’s getting responses from the amp (basically, troubleshoot the serial connection to the amp).

Thanks for the reply!

No, so far I haven’t gotten the switches to do anything with the sitemap. I wasn’t sure if it was because the error in the rules (Like I said, I’m new and still learning everything.)

I will take a deeper look. thanks!

I’ve adapted your streamlined version of the rule to use my Globalcache iTach Flex (serial over network) adapter.

I must say it was a bit of a learning curve for me since OH and coding is a hobby for me. I learned a lot about how your (and any) lambda works, although it’s still a little mysterious to me.

Have made any updates to what you posted?

No updates. The reason for the improvement was that I had bought one unit on discount and I wanted to know the limits of the interface before buying a second one. So I just made the whole thing on a “good enough level” to fulfill my requirements. Got the units but they are not installed yet. I will probably continue the work when I’ve got the whole thing installed. No date so far for that :). The test sitemap is a quite crappy hack but I could add it if someone wants it.

Thanks, Tony! I appreciate your contribution. I bought a second unit over the holidays and your code performed well detecting both. The only “issue” i’ve had is the refresh doesn’t seem to work on my system, but all the other functions work.

FYI https://github.com/ccutrer/openhab2-addons/tree/monoprice10761

It’s still my first stab, and it does work. I need to do some work to make it more robust though.

1 Like

Woohoo, love it! I was actually going to suggest to @swamiller and @tony_alpskog if we should convert this to a dedicated binding, given that it seems to be gaining users (and supports other amps, as well)…Looking forward to trying it out!

While I want you to get excited that it is coming, don’t get too excited. Getting my whole home audio system fully running is pretty far down my list. I’ve been focusing on improving the HomeKit service first (adding support for lots more accessory types, and being more reliable), but I need to get a big jump on it - right now it has an (Apple) limitation of 150 accessories, and I’m already at 130, with lots more smart devices coming soon. So I gotta get that fixed. And then I need basic connections with several more device types. Then I can circle back around to this.

Ah, but the important thing is you got it started! I haven’t had time to even consider writing a dedicated binding for it. The rules I originally wrote have worked just fine for 4+ years, improved by the folks here over time, but I’ve always thought this was a large enough interface to warrant its own binding, especially after @tony_alpskog mentioned that it works for about 5 different manufacturers’ models (and also because a binding should do a better job of refreshing/holding the amp zone states). Maybe we can all collaborate to get it to a point where it’s included in the OH2 snapshots, even if your focus will be elsewhere for the time being. So, thanks for kicking it off (the hard part, I think)!

I fixed the major communications issues. Once I get it running, it seems to work just fine now.

2 Likes