MAIN ON/OFF Volume&Mute (HDMI1-5 AV1-6 AUDIO1-2, NET, USB, V-AUX)
Code: Select all
# Basic Python Plugin
#
# Author: thomas-villagers
#
"""
<plugin key="YamahaPlug" name="Yamaha AV Receiver" author="thomasvillagers" version="1.0.0" wikilink="http://www.domoticz.com/wiki/plugins/plugin.html" externallink="https://yamaha.com/products/audio_visual/av_receivers_amps/">
<params>
<param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
<param field="Port" label="Port" width="50px" required="true" default="50000"/>
<param field="Mode6" label="Debug" width="75px">
<options>
<option label="True" value="Debug"/>
<option label="False" value="Normal" default="true" />
</options>
</param>
</params>
</plugin>
"""
import Domoticz
import base64
class BasePlugin:
enabled = False
isConnected = True
outstandingPings = 0
nextConnect = 0
commandArray = ["@MAIN:SOUNDPRG=?", "@MAIN:PWR=?", "@MAIN:VOL=?", "@MAIN:INP=?", "@MAIN:MUTE=?", "@ZONE2:PWR=?", "@ZONE2:VOL=?", "@ZONE2:MUTE=?", "@ZONE2:INP=?"]
#commandArray = ["@MAIN:VOL=?", "@MAIN:INP=?", "@MAIN:MUTE=?", "@MAIN:SOUNDPRG=?"]
commandIndex = 0
def __init__(self):
#self.var = 123
return
def onStart(self):
if Parameters["Mode6"] == "Debug":
Domoticz.Debugging(1)
Domoticz.Debug("onStart called")
if 1 not in Devices:
Domoticz.Debug("Create Status Device")
Domoticz.Device(Name="Status", Unit=1, Type=17, Switchtype=17, Used=1).Create()
if 2 not in Devices:
Domoticz.Debug("Create Volume Device")
Domoticz.Device(Name="Volume", Unit=2, Type=244, Subtype=73, Switchtype=7, Image=8, Used=1).Create()
if 3 not in Devices:
Domoticz.Debug("Create HDMI Device")
Options = { "LevelActions" : "|||||||",
"LevelNames" : "Off|HDMI1|HDMI2|HDMI3|HDMI4|HDMI5",
"LevelOffHidden" : "true",
"SelectorStyle" : "0"
}
Domoticz.Device(Name="Source", Unit=3, TypeName="Selector Switch", Switchtype=18, Options=Options, Used=1).Create()
if 4 not in Devices:
Domoticz.Debug("Create AV Device")
Options = { "LevelActions" : "||||||",
"LevelNames" : "Off|AV1|AV2|AV3|AV4|AV5|AV6",
"LevelOffHidden" : "true",
"SelectorStyle" : "0"
}
Domoticz.Device(Name="AV Source", Unit=4, TypeName="Selector Switch", Switchtype=18, Options=Options, Used=1).Create()
if 5 not in Devices:
Domoticz.Debug("Create AUDIO Device")
Options = { "LevelActions" : "||||||",
"LevelNames" : "Off|AUDIO 1|AUDIO 2|NET|USB|V-AUX",
"LevelOffHidden" : "true",
"SelectorStyle" : "0"
}
Domoticz.Device(Name="AUDIO Source", Unit=5, TypeName="Selector Switch", Switchtype=18, Options=Options, Used=1).Create()
if 6 not in Devices:
Domoticz.Debug("Create Status Z2 Device")
Domoticz.Device(Name="Status Zone2", Unit=6, Type=17, Switchtype=17, Used=1).Create()
if 7 not in Devices:
Domoticz.Debug("Create Volume Zone 2 Device")
Domoticz.Device(Name="Volume Zone2", Unit=7, Type=244, Subtype=73, Switchtype=7, Image=8, Used=1).Create()
if 8 not in Devices:
Domoticz.Debug("Create AUDIO Z2 Device")
Options = { "LevelActions" : "||||||",
"LevelNames" : "Off|AUDIO 1|AUDIO 2|NET|USB",
"LevelOffHidden" : "true",
"SelectorStyle" : "0"
}
Domoticz.Device(Name="AUDIO Source Zone2", Unit=8, TypeName="Selector Switch", Switchtype=18, Options=Options, Used=1).Create()
self.connection = Domoticz.Connection(Name="Yamaha connection", Transport="TCP/IP", Protocol="Line", Address=Parameters["Address"], Port=Parameters["Port"])
self.connection.Connect()
Domoticz.Heartbeat(20)
def onStop(self):
Domoticz.Log("onStop called")
def onConnect(self, Connection, Status, Description):
Domoticz.Debug("onConnect called. Status: " + str(Status))
if (Status == 0):
self.isConnected = True
UpdateDevice(1,1,"")
self.onHeartbeat()
else:
self.isConnected = False
def onMessage(self, Connection, Data):
Domoticz.Debug("onMessage called")
self.outstandingPings = self.outstandingPings - 1
strData = Data.decode("utf-8", "ignore")
arrData = strData.split('=')
for x in arrData:
Domoticz.Debug(x)
if (arrData[0] == "@MAIN:VOL"):
vol = float(arrData[1])
sliderValue = int(vol*5/4 + 100)
UpdateDevice(2, Devices[2].nValue, str(sliderValue))
elif (arrData[0] == "@MAIN:MUTE"):
if (arrData[1] == "Off"):
UpdateDevice(2, 2, Devices[2].sValue)
elif (arrData[1] == "On"):
UpdateDevice(2, 0, Devices[2].sValue)
elif (arrData[0] == "@MAIN:INP"):
s = arrData[1]
if (s.startswith("HDMI")) or (s.startswith("AV")) or (s.startswith("AUDIO")) :
inp = int(s[-1:])
if (s.startswith("HDMI")):
UpdateDevice(3,2,str(inp*10))
UpdateDevice(4,2,"0")
UpdateDevice(5,2,"0")
elif (s.startswith("AV")):
UpdateDevice(4,2,str(inp*10))
UpdateDevice(5,2,"0")
UpdateDevice(3,2,"0")
elif (s.startswith("AUDIO")):
UpdateDevice(5,2,str(inp*10))
UpdateDevice(4,2,"0")
UpdateDevice(3,2,"0")
elif (s.startswith("NET")):
UpdateDevice(5,2,str(30))
UpdateDevice(4,2,"0")
UpdateDevice(3,2,"0")
elif (s.startswith("USB")):
UpdateDevice(5,2,str(40))
UpdateDevice(4,2,"0")
UpdateDevice(3,2,"0")
elif (s.startswith("V-AUX")):
UpdateDevice(5,2,str(50))
UpdateDevice(4,2,"0")
UpdateDevice(3,2,"0")
elif (arrData[0] == "@MAIN:SOUNDPRG"):
UpdateDevice(1,1, arrData[1])
elif (arrData[0] == "@MAIN:PWR"):
if (arrData[1] != "On"):
UpdateDevice(1, 2, "Off")
#elif (arrData[1] == "Standby"):
#UpdateDevice(6, 2, "Off")
#elif (arrData[1] == "On"):
#UpdateDevice(1, 2, "On")
if (arrData[0] == "@ZONE2:VOL"):
vol = float(arrData[1])
sliderValue = int(vol*5/4 + 100)
UpdateDevice(7, Devices[7].nValue, str(sliderValue))
elif (arrData[0] == "@ZONE2:MUTE"):
if (arrData[1] == "Off"):
UpdateDevice(7, 2, Devices[7].sValue)
elif (arrData[1] == "On"):
UpdateDevice(7, 0, Devices[7].sValue)
elif (arrData[0] == "@ZONE2:INP"):
s = arrData[1]
if (s.startswith("HDMI")) or (s.startswith("AV")) or (s.startswith("AUDIO")) :
inp = int(s[-1:])
elif (s.startswith("AUDIO")):
UpdateDevice(8,2,str(inp*10))
elif (s.startswith("NET")):
UpdateDevice(8,2,str(30))
elif (s.startswith("USB")):
UpdateDevice(8,2,str(40))
elif (arrData[0] == "@ZONE2:PWR"):
if (arrData[1] != "On"):
UpdateDevice(6, 0, "Off")
#elif (arrData[1] == "Standby"):
#UpdateDevice(6, 2, "Off")
elif (arrData[1] == "On"):
UpdateDevice(6, 2, "On")
def onCommand(self, Unit, Command, Level, Hue):
Domoticz.Debug("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
if (self.isConnected == False):
self.connection.Connect()
return
if (Unit == 1):
if (Command == "Off"):
UpdateDevice(1,0,Devices[1].sValue) # TODO remove
self.connection.Send("@MAIN:PWR=Standby\r\n")
elif (Command == "On"):
self.connection.Send("@MAIN:PWR=On\r\n")
elif (Unit == 2):
if (Command == "Set Level"):
volume = int(Level)*4/5 - 80
volumeToSend = round(2*volume)/2
self.connection.Send("@MAIN:VOL="+str(volumeToSend)+"\r\n")
elif (Command == "Off"):
self.connection.Send("@MAIN:MUTE=On\r\n")
elif (Command == "On"):
self.connection.Send("@MAIN:MUTE=Off\r\n")
elif (Unit == 3):
input = str(int(int(Level)/10))
self.connection.Send("@MAIN:INP=HDMI" + input + "\r\n")
elif (Unit == 4):
input = str(int(int(Level)/10))
self.connection.Send("@MAIN:INP=AV" + input + "\r\n")
elif (Unit == 5):
input = str(int(int(Level)/10))
if (input == "1" or input == "2"):
self.connection.Send("@MAIN:INP=AUDIO" + input + "\r\n")
elif (input == "3"):
self.connection.Send("@MAIN:INP=NET RADIO" + "\r\n")
elif (input == "4"):
self.connection.Send("@MAIN:INP=USB" + "\r\n")
elif (input == "5"):
self.connection.Send("@MAIN:INP=V-AUX" + "\r\n")
if (Unit == 6):
if (Command == "Off"):
UpdateDevice(6,0,Devices[6].sValue) # TODO remove
self.connection.Send("@ZONE2:PWR=Standby\r\n")
elif (Command == "On"):
self.connection.Send("@ZONE2:PWR=On\r\n")
elif (Unit == 7):
if (Command == "Set Level"):
volume = int(Level)*4/5 - 80
volumeToSend = round(2*volume)/2
self.connection.Send("@ZONE2:VOL="+str(volumeToSend)+"\r\n")
elif (Command == "Off"):
self.connection.Send("@ZONE2:MUTE=On\r\n")
elif (Command == "On"):
self.connection.Send("@ZONE2:MUTE=Off\r\n")
elif (Unit == 8):
input = str(int(int(Level)/10))
if (input == "1" or input == "2"):
self.connection.Send("@ZONE2:INP=AUDIO" + input + "\r\n")
elif (input == "3"):
self.connection.Send("@ZONE2:INP=NET RADIO" + "\r\n")
elif (input == "4"):
self.connection.Send("@ZONE2:INP=USB" + "\r\n")
elif (input == "5"):
self.connection.Send("@ZONE2:INP=V-AUX" + "\r\n")
def onNotification(self, Data):
Domoticz.Debug("onNotification: " + str(Data))
def onDisconnect(self, Connection):
Domoticz.Debug("onDisconnect called")
self.isConnected = False
UpdateDevice(1,0,"")
UpdateDevice(2,0,Devices[2].sValue)
UpdateDevice(3,0,Devices[3].sValue)
UpdateDevice(4,0,Devices[4].sValue)
UpdateDevice(5,0,Devices[5].sValue)
UpdateDevice(6,0,Devices[6].sValue)
UpdateDevice(7,0,Devices[7].sValue)
UpdateDevice(8,0,Devices[8].sValue)
def onHeartbeat(self):
Domoticz.Debug("onHeartbeat called. Connected: " + str(self.isConnected))
if (self.isConnected == True):
if (self.outstandingPings > 6):
Domoticz.Debug("Missed more than 6 pings - disconnect")
self.connection.Disconnect() # obsolete
self.nextConnect = 0
else:
self.connection.Send(self.commandArray[self.commandIndex] + "\r\n")
self.commandIndex = (self.commandIndex + 1 ) % len(self.commandArray)
self.outstandingPings = self.outstandingPings + 1
else:
self.outstandingPings = 0
self.nextConnect = self.nextConnect - 1
if (self.nextConnect <= 0):
self.nextConnect = 3
self.connection.Connect() # obsolete
global _plugin
_plugin = BasePlugin()
def onStart():
global _plugin
_plugin.onStart()
def onStop():
global _plugin
_plugin.onStop()
def onConnect(Connection, Status, Description):
global _plugin
_plugin.onConnect(Connection, Status, Description)
def onMessage(Connection, Data):
global _plugin
_plugin.onMessage(Connection, Data)
def onCommand(Unit, Command, Level, Hue):
global _plugin
_plugin.onCommand(Unit, Command, Level, Hue)
def onNotification(Data):
global _plugin
_plugin.onNotification(Data)
def onDisconnect(Connection):
global _plugin
_plugin.onDisconnect(Connection)
def onHeartbeat():
global _plugin
_plugin.onHeartbeat()
def UpdateDevice(Unit, nValue, sValue):
# Make sure that the Domoticz device still exists (they can be deleted) before updating it
if (Unit in Devices):
if (Devices[Unit].nValue != nValue) or (Devices[Unit].sValue != sValue):
Devices[Unit].Update(nValue, str(sValue))
Domoticz.Log("Update "+str(nValue)+":'"+str(sValue)+"' ("+Devices[Unit].Name+")")
return
# Generic helper functions
def DumpConfigToLog():
for x in Parameters:
if Parameters[x] != "":
Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
Domoticz.Debug("Device count: " + str(len(Devices)))
for x in Devices:
Domoticz.Debug("Device: " + str(x) + " - " + str(Devices[x]))
Domoticz.Debug("Device ID: '" + str(Devices[x].ID) + "'")
Domoticz.Debug("Device Name: '" + Devices[x].Name + "'")
Domoticz.Debug("Device nValue: " + str(Devices[x].nValue))
Domoticz.Debug("Device sValue: '" + Devices[x].sValue + "'")
Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
return
def stringToBase64(s):
return base64.b64encode(s.encode('utf-8')).decode("utf-8")
def base64ToString(b):
return base64.b64decode(b).decode('utf-8')
As i am not a coder at all I am sure my code is not the most beautifull thing, but it works for me at the moment.
The only thing i am not getting the way it should, is the ON/OFF on the status device :
-On Off action works but the status of the receiver is not 100% clear. --> it appears in the text in the sensor it self
-On Off action works but in some condiftions you need to click a couple of time to cyclus on/off on the device duo to the above.
-Off is displayed as pause, but switches to on while the receiver remains off (due to status update)
I have no idea how to solve this.
- is it possible to retieve the device status in python plugin ? (If i use device.svalue i get errors :S) --> The goal is to stop the commands issued by @MAIN:SOUNDPRG what currently overwrites the status of on/off
Any hints tips to solve this last issue are welcome.