Help with serial binding rule

Okay, have openHAB installed on Ubuntu Server via apt-get.
User open is added to the dialout group.

When I manually enter the command in the terminal it all works fine.

echo -e “SBI01O01” > /dev/ttyUSB0

My Rule looks like this:

rule "Output1"
when
Item Output1 received command
then
switch(receivedCommand) {
case 1 : sendCommand (ShinyBowSerial, “SBI01O01”)
case 2 : sendCommand (ShinyBowSerial, “SBI02O01”)
case 3 : sendCommand (ShinyBowSerial, “SBI03O01”)
}
end

Sitemap:

Selection item=Output1 label=“Kitchen Music” icon=“music” mappings=[1=Squeeze, 2=Radio, 3=Chromecast]

Items:

String ShinyBowSerial “ShinyBow” { serial="/dev/ttyUSB0" }
Switch ShinyBow "ShinyBow Power"
Number Output1

In Debug mode when I execute one of the numbers it shows Executing Rule Output 1
but then nothing.

Is my rule correct?

Thanks josh

I can’t answer your specific question, but I am working on configuring a Shinybow SB8804LCM 8x8 audio matrix switcher. I am using an IP to serial converter (digi portserver TS16), using the TCP/UDP binding.

It looks like Josh’s switcher uses v2 of the code (with 2 digits after the commands, while mine uses v3 (with 3 digits after the commands).

It is slow going because there are so many command combinations. There is probably a better way using a script. I think I might be able to use groups in my items, but I haven’t figured that out yet either. Hopefully, this helps others get started configuring a switcher.

So far, I am able to turn power on and off, and select inputs for three zones. I am still trying to figure out volume settings and parsing the feedback from the unit.

items

    /* Shinybow Matrix Switcher */
Switch MatrixPower	"Power"	{tcp=">[ON:192.168.50.142:2103:'MAP(matrix.map)'], >[OFF:192.168.50.142:2103:'MAP(matrix.map)']"}
String Z1 "Zone1"	{tcp=">[O1I0:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I1:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I2:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I3:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I4:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I5:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I6:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I7:192.168.50.142:2103:'MAP(matrix.map)'], >[O1I8:192.168.50.142:2103:'MAP(matrix.map)']"}
String Z2 "Zone2"	{tcp=">[O2I0:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I1:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I2:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I3:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I4:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I5:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I6:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I7:192.168.50.142:2103:'MAP(matrix.map)'], >[O2I8:192.168.50.142:2103:'MAP(matrix.map)']"}
String Z3 "Zone3"	{tcp=">[O3I0:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I1:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I2:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I3:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I4:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I5:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I6:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I7:192.168.50.142:2103:'MAP(matrix.map)'], >[O3I8:192.168.50.142:2103:'MAP(matrix.map)']"}
String Z1Input           "Z1 Input [%s]"            {tcp=">[192.168.50.142:2103:'REGEX((.*))']" }

sitemap

		Text label="Matrix" icon="firstfloor" {
			Switch item=MatrixPower
			Text item=Z1Input
			Text item=Z2Input
			Text item=Z3Input
			Selection label="Zone 1 Input" item=Z1 mappings=[O1I0="Off", O1I1="Input 1", O1I2="Input 2", O1I3="Input 3", O1I4="Input 4", O1I5"Input 5", O1I6="Input 6", O1I7="Input 7", O1I8="Input 8"]
			Selection label="Zone 2 Input" item=Z2 icon="music" mappings=[O2I0="Off", O2I1="Input 1", O2I2="Input 2", O2I3="Input 3", O2I4="Input 4", O2I5"Input 5", O2I6="Input 6", O2I7="Input 7", O2I8="Input 8"]
			Selection label="Zone 3 Input" item=Z3 icon="music" mappings=[O3I0="Off", O3I1="Input 1", O3I2="Input 2", O3I3="Input 3", O3I4="Input 4", O3I5"Input 5", O2I6="Input 6", O3I7="Input 7", O3I8="Input 8"]
			Slider item=Z1Volume

map file

ON=Power\ 001;
OFF=Power\ 000;
O1I0=OUTPUT001\ 000;
O1I1=OUTPUT001\ 001;
O1I2=OUTPUT001\ 002;
O1I3=OUTPUT001\ 003;
O1I4=OUTPUT001\ 004;
O1I5=OUTPUT001\ 005;
O1I6=OUTPUT001\ 006;
O1I7=OUTPUT001\ 007;
O1I8=OUTPUT001\ 008;
O2I0=OUTPUT002\ 000;
O2I1=OUTPUT002\ 001;
O2I2=OUTPUT002\ 002;
O2I3=OUTPUT002\ 003;
O2I4=OUTPUT002\ 004;
O2I5=OUTPUT002\ 005;
O2I6=OUTPUT002\ 006;
O2I7=OUTPUT002\ 007;
O2I8=OUTPUT002\ 008;
O3I1=OUTPUT003\ 000;
O3I1=OUTPUT003\ 001;
O3I2=OUTPUT003\ 002;
O3I3=OUTPUT003\ 003;
O3I4=OUTPUT003\ 004;
O3I5=OUTPUT003\ 005;
O3I6=OUTPUT003\ 006;
O3I7=OUTPUT003\ 007;
O3I8=OUTPUT003\ 008;
O1=OUTPUT001\ ?;

I’ve moved to CBus audio switcher at the moment so the Shinybow is on the back burner but I might come back to it if I need more inputs (which I doubt).

Josh

I rewrote my configuration for the Shinybow 8804LCM, using this as a template https://community.openhab.org/t/monoprice-6-zone-audio-amp-items-sitemap-rules/1693 Thank you @bartus

This still needs some work with parsing the feedback.

Items:

/* ShinyBow */
String ShinyBow "ShinyBow Matrix [%s]"  { tcp=">[192.168.50.142:2103:'REGEX((.*))']" }
String ShinyBow_Status "ShinyBow Status [%s]" 
Switch ShinyBow_PWR "Master Power"
Number Shinybow_Z1_Input "Bonus Room Input"
Dimmer Shinybow_Z1_Volume "Bonus Room Volume [%03d %%]"
Switch Shinybow_Z1_Mute "Bonus Room Mute"
Number Shinybow_Z2_Input "Living Room Input"
Dimmer Shinybow_Z2_Volume "Living Room Volume [%03d %%]"
Switch Shinybow_Z2_Mute "Living Room Mute"
Number Shinybow_Z3_Input "Hall Input"
Dimmer Shinybow_Z3_Volume "Hall Volume [%03d %%]"
Switch Shinybow_Z3_Mute "Hall Room Mute"
Number Shinybow_Z4_Input "Office Input"
Dimmer Shinybow_Z4_Volume "Office Volume [%03d %%]"
Switch Shinybow_Z4_Mute "Office Mute"
Number Shinybow_Z5_Input "Kitchen Input"
Dimmer Shinybow_Z5_Volume "Kitchen Volume [%03d %%]"
Switch Shinybow_Z5_Mute "Kitchen Mute"
Number Shinybow_Z6_Input "Master Bed Input"
Dimmer Shinybow_Z6_Volume "Master Bed Volume [%03d %%]"
Switch Shinybow_Z6_Mute "Master Bed Mute"
Number Shinybow_Z7_Input "Master Bath Input"
Dimmer Shinybow_Z7_Volume "Master Bath Volume [%03d %%]"
Switch Shinybow_Z7_Mute "Master Bath Room Mute"
Number Shinybow_Z8_Input "Backyard Input"
Dimmer Shinybow_Z8_Volume "Backyard Volume [%03d %%]"
Switch Shinybow_Z8_Mute "Backyard Mute"

Sitemap

		Text label="Matrix" icon="firstfloor" {
			Text item=ShinyBow
			Text item=ShinyBow_Status
			Switch item=ShinyBow_PWR
			Selection item=Shinybow_Z1_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z1_Mute
			Slider item=Shinybow_Z1_Volume
			Selection item=Shinybow_Z2_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z2_Mute
			Slider item=Shinybow_Z2_Volume
			Selection item=Shinybow_Z3_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z3_Mute
			Slider item=Shinybow_Z3_Volume
			Selection item=Shinybow_Z4_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z4_Mute
			Slider item=Shinybow_Z4_Volume
			Selection item=Shinybow_Z5_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z5_Mute
			Slider item=Shinybow_Z5_Volume
			Selection item=Shinybow_Z6_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z6_Mute
			Slider item=Shinybow_Z6_Volume
			Selection item=Shinybow_Z7_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z7_Mute
			Slider item=Shinybow_Z7_Volume
			Selection item=Shinybow_Z8_Input mappings=[0=Off, 1=Input1, 2=Input2, 3=Input3]
			Switch item=Shinybow_Z8_Mute
			Slider item=Shinybow_Z8_Volume
    		}

Rules:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import java.util.regex.Matcher
import java.util.regex.Pattern

var Number volume_z1 = 0
var Number volume_z2 = 0
var Number volume_z3 = 0
var Number volume_z4 = 0
var Number volume_z5 = 0
var Number volume_z6 = 0
var Number volume_z7 = 0
var Number volume_z8 = 0

rule "ShinyBow Power"
when
        Item ShinyBow_PWR received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "Power 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "Power 000;")
        }   
end

rule "Select Zone 1 Input"
when
		Item Shinybow_Z1_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT001 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT001 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT001 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT001 003;")
		}
end

rule "Shinybow_Z1_Volume control"
	when
		Item Shinybow_Z1_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z1=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z1=volume_z1 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z1=volume_z1 - 1
			}
		}
		if (volume_z1>9) {sendCommand(ShinyBow, "VOLUME001 0" + volume_z1.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME001 00" + volume_z1.toString("%02d") + ";")}
		postUpdate(Shinybow_Z1_Volume)
end

rule "ShinyBow Shinybow_Z1_Mute"
when
        Item Shinybow_Z1_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE001 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE001 000;")
        }   
end

rule "Select Zone 2 Input"
when
		Item Shinybow_Z2_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT002 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT002 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT002 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT002 003;")
		}
end

rule "Shinybow_Z2_Volume control"
	when
		Item Shinybow_Z2_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z2=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z2=volume_z2 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z2=volume_z2 - 1
			}
		}
		if (volume_z2>9) {sendCommand(ShinyBow, "VOLUME002 0" + volume_z2.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME002 00" + volume_z2.toString("%02d") + ";")}
		postUpdate(Shinybow_Z2_Volume)
end

rule "ShinyBow Shinybow_Z2_Mute"
when
        Item Shinybow_Z2_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE002 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE002 000;")
        }   
end

rule "Select Zone 3 Input"
when
		Item Shinybow_Z3_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT003 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT003 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT003 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT003 003;")
		}
end

rule "Shinybow_Z3_Volume control"
	when
		Item Shinybow_Z3_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z3=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z3=volume_z3 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z3=volume_z3 - 1
			}
		}
		if (volume_z3>9) {sendCommand(ShinyBow, "VOLUME003 0" + volume_z3.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME003 00" + volume_z3.toString("%02d") + ";")}
		postUpdate(Shinybow_Z3_Volume)
end

rule "ShinyBow Shinybow_Z3_Mute"
when
        Item Shinybow_Z3_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE003 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE003 000;")
        }   
end

rule "Select Shinybow_Zone 4 Input"
when
		Item Shinybow_Z4_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT004 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT004 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT004 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT004 003;")
		}
end

rule "Shinybow_Z4_Volume control"
	when
		Item Shinybow_Z4_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z4=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z4=volume_z4 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z4=volume_z4 - 1
			}
		}
		if (volume_z4>9) {sendCommand(ShinyBow, "VOLUME004 0" + volume_z4.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME004 00" + volume_z4.toString("%02d") + ";")}
		postUpdate(Shinybow_Z4_Volume)
end

rule "ShinyBow Shinybow_Z4_Mute"
when
        Item Shinybow_Z4_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE004 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE004 000;")
        }   
end

rule "Select Zone 5 Input"
when
		Item Shinybow_Z5_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT005 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT005 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT005 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT005 003;")
		}
end

rule "Z5_Volume control"
	when
		Item Shinybow_Z5_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z5=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z5=volume_z5 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z5=volume_z5 - 1
			}
		}
		if (volume_z5>9) {sendCommand(ShinyBow, "VOLUME005 0" + volume_z5.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME005 00" + volume_z5.toString("%02d") + ";")}
		postUpdate(Shinybow_Z5_Volume)
end

rule "ShinyBow Z5_Mute"
when
        Item Shinybow_Z5_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE005 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE005 000;")
        }   
end

rule "Select Zone 6 Input"
when
		Item Shinybow_Z6_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT006 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT006 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT006 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT006 003;")
		}
end

rule "Shinybow_Z6_Volume control"
	when
		Item Shinybow_Z6_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z6=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z6=volume_z6 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z6=volume_z6 - 1
			}
		}
		if (volume_z6>9) {sendCommand(ShinyBow, "VOLUME006 0" + volume_z6.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME006 00" + volume_z6.toString("%02d") + ";")}
		postUpdate(Shinybow_Z6_Volume)
end

rule "ShinyBow Z6_Mute"
when
        Item Shinybow_Z6_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE006 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE006 000;")
        }   
end

rule "Select Zone 7 Input"
when
		Item Shinybow_Z7_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT007 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT007 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT007 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT007 003;")
		}
end

rule "Z7_Volume control"
	when
		Item Shinybow_Z7_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z7=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z7=volume_z7 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z7=volume_z7 - 1
			}
		}
		if (volume_z7>9) {sendCommand(ShinyBow, "VOLUME007 0" + volume_z7.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME007 00" + volume_z7.toString("%02d") + ";")}
		postUpdate(Shinybow_Z7_Volume)
end

rule "ShinyBow Z7_Mute"
when
        Item Shinybow_Z7_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE007 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE007 000;")
        }   
end

rule "Select Zone 8 Input"
when
		Item Shinybow_Z8_Input received command
then
		switch(receivedCommand) {
			case 0 : sendCommand(ShinyBow, "OUTPUT008 000;")
			case 1 : sendCommand(ShinyBow, "OUTPUT008 001;")
			case 2 : sendCommand(ShinyBow, "OUTPUT008 002;")
			case 3 : sendCommand(ShinyBow, "OUTPUT008 003;")
		}
end

rule "Z8_Volume control"
	when
		Item Shinybow_Z8_Volume received command
	then
		if(receivedCommand instanceof PercentType) {
			volume_z8=receivedCommand
		} else {
			if(receivedCommand==INCREASE) 
				{
				volume_z8=volume_z8 + 1
				}
			if(receivedCommand==DECREASE) 
			{
				volume_z8=volume_z8 - 1
			}
		}
		if (volume_z8>9) {sendCommand(ShinyBow, "VOLUME008 0" + volume_z8.toString("%02d") + ";")}
		else {sendCommand(ShinyBow, "VOLUME008 00" + volume_z8.toString("%02d") + ";")}
		postUpdate(Shinybow_Z8_Volume)
end

rule "ShinyBow Z8_Mute"
when
        Item Shinybow_Z8_Mute received command
then
        if(receivedCommand==ON){
                sendCommand(ShinyBow, "MUTE008 001;")
        }
        else if(receivedCommand==OFF){
                sendCommand(ShinyBow, "MUTE008 000;")
        }   
end
1 Like

@jacksteraz, that’s awesome, I’m glad my post helped you with your setup!

If I may add a suggestion, I noticed you removed the Thread::sleep(1000) statements from your rules. I had to add those to my rules, to allow the serial binding to send all of its outputs to the amp, including the status query, and then allow it some time to fully receive the status message from the amp, before parsing using RegEx. I’m not sure if the device you’re interfacing with has similar timing issues, but keep the delay in mind if you come across any issues with parsing status.

Good luck!